Using AT&T's M2X With the CC3000
This Tutorial is Retired!
This tutorial covers concepts or technologies that are no longer current. It's still here for you to read and enjoy, but may not be as useful as our newest tutorials.
Controlling a Device From M2X
Sending information to M2X is great for logging sensor data, but we can also control hardware devices from M2X. This technique requires a bit of trickery, as there is no way to push data to the Arduino (without turning the Arduino into a web server). So, we have the Arduino poll an M2X stream every few seconds looking for data. If it sees a "0" it will turn off the LED. If it sees any other value, it will turn the LED on. Any time the Arduino reads data from the stream, it immediately deletes all data on the stream.
Required Materials
The Circuit
Connect the CC3000 shield to the Arduino, and connect the resistor and LED as shown.
Make M2X Stream
Rather than use our "temperature" stream, we are going to make another stream in the same Blueprint. We will poll this stream from the Arduino, read values, and delete entries as we read them.
Log in to your AT&T M2X account.
Click on your Blueprint (e.g. "CC3000 Test").
Scroll down, and click on "Add Steam." Name the stream something memorable (we'll call ours "control"). Pick any Unit and Symbol (it really does not matter. "Barn" seemed like a silly unit, so we used that).
Click "Add Stream." Don't add any values! We will add some data later.
Adjust Serial Buffer
Sadly, the poor Arduino UNO (i.e. ATmega328P) simply does not have enough RAM to control the CC3000 and process the incoming M2X data. To free up some space in the RAM, we are going to reduce the size of the Serial buffer. Don't forget to change it back for your other projects!
Navigate to \
Note: If you are using a different Arduino with more RAM (e.g. the Arduino Mega), then you don't need to perform this step.
Scroll down and change SERIAL_BUFFER_SIZE from 64 to 32.
Example Code
Open up the Arduino IDE and paste in the following code:
/**************************************************************** M2X_CC3000_LED.ino Control an LED with AT&T's M2X Shawn Hymel @ SparkFun Electronics August 19, 2014 Manually connects to a WiFi network and performs a GET to the provided M2X stream. It reads the last data point available and deletes all data points. This acts as a "producer-consumer" model. IMPORTANT: This WILL cause an Uno to run out of RAM. You need to change SERIAL_BUFFER_SIZE from 64 to 32 in HardwareSerial.cpp, which can be found in: C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino Change AP_SSID, AP_PASSWORD, AP_SECURITY, FEED_ID, STREAM_NAME, and M2X_KEY to match your WiFi and M2X parameters. The security mode is defined by one of the following: WLAN_SEC_UNSEC, WLAN_SEC_WEP, WLAN_SEC_WPA, WLAN_SEC_WPA2 Resources: Include SPI.h, SFE_CC3000.h, SFE_CC3000_Client.h, jsonlite.h, M2XStreamClient.h Development environment specifics: Written in Arduino 1.0.5 Tested with Arduino UNO R3 This code is beerware; if you see me (or any other SparkFun employee) at the local, and you've found our code helpful, please buy us a round! Distributed as-is; no warranty is given. ****************************************************************/ // Parameters // Pins // Connection info data lengths // WiFi Constants // M2X Constants // Global Variables SFE_CC3000 wifi = SFE_CC3000(CC3000_INT, CC3000_EN, CC3000_CS); SFE_CC3000_Client client = SFE_CC3000_Client(wifi); M2XStreamClient m2x_client(&client, M2X_KEY); uint8_t g_new; int g_response; int g_index; char g_time[TIME_LEN]; uint8_t led_state; // M2X fetch callback. This is called for each entry found. void on_data_point_found( const char* at, \ const char* value, \ int index, \ void* context) { // Index 0 is the most recent. Save the timestamp so we can // delete all the entries up to that point. If the value is // exactly 0, turn off the LED. Otherwise, turn it on. if ( index == 0 ) { g_new = 1; strncpy(g_time, at, TIME_LEN); if ( strcmp(value, "0") == 0 ) { led_state = 0; } else { led_state = 1; } } } // Setup. Configure WiFi and M2X connections. void setup() { g_response = 0; g_new = 0; // Initialize LED led_state = 0; pinMode(LED_PIN, OUTPUT); digitalWrite(LED_PIN, LOW); // Initialize UART for debugging Serial.begin(9600); Serial.println(); Serial.println(F("SparkFun CC3000 - M2X LED")); // Initialize CC3000 (configure SPI communications) if ( wifi.init() ) { Serial.println(F("CC3000 initialization complete")); } else { Serial.println(F("Something went wrong during CC3000 init!")); } // Connect using DHCP Serial.print(F("Connecting to SSID: ")); Serial.println(AP_SSID); if(wifi.connect(AP_SSID, AP_SECURITY, AP_PASSWORD, TIMEOUT)) { Serial.println(F("Connected!")); } else { Serial.println(F("Error: Could not connect to AP")); } } // Main loop. Poll M2X stream, update LED, and delete entries. void loop() { // Fetch values from M2X stream g_response = m2x_client.fetchValues(FEED_ID, \ STREAM_NAME, \ on_data_point_found, \ NULL); // If we fail to receive a reponse, stop running Serial.print(F("Fetch response: ")); Serial.println(g_response); if ( g_response == -1 ) { while(1); } // Update LED and delete entries if there was a new value if ( g_new ) { // Update LED state digitalWrite(LED_PIN, led_state); Serial.print(F("LED: ")); Serial.println(led_state); // Fetch drops last 4 chars. Add some so we can delete entries. strncpy(g_time + 20, "999Z", 5); // Delete all entries g_response = m2x_client.deleteValues( FEED_ID, \ STREAM_NAME, \ FROM_TIME, \ g_time); // If we fail to receive a reponse, stop running Serial.print(F("Delete response: ")); Serial.println(g_response); if ( g_response == -1 ) { while(1); } // Reset new flag g_new = 0; } // Wait to poll stream again delay(POLL_DELAY_MS); }
Don't forget to update the WiFi and M2X stream parameters:
- \<SSID> should be changed to your WiFi network name (SSID)
- \<PASSWORD> is your WiFi password
- Make sure AP_SECURITY matches your WiFi security type (e.g. WPA, WEP)
- Change \
and \ to match your M2X information (see the Post Temperature Data example) - Change \
to your new stream name (e.g. "control")
Run Your Program
Upload your program to the Arduino. Open up a Serial Monitor, and you should see the Arduino connect to WiFi and start to poll your M2X stream.
While your Arduino is polling the M2X stream, go back to your M2X Blueprint in your browser and expand our new data stream.
Click the "Edit" button and enter a value (anything other than "0") into the "Log a Value" field.
Click "Save Stream." In a few seconds, your Arduino should see that a value was logged to the stream and turn on the LED as a result.
To turn off the LED, click on "Edit" again for your data stream. This time, set "Log a Value" to 0 and click "Save Stream." Your LED should turn off within a few seconds.
So What?
OK, so blinking an LED might seem a little simplistic. However, being able to control a microcontroller from the Internet is a pretty big thing (and will garner the admiration of all your geek friends).
You could write a phone app to control the lights in your house by posting and reading values in M2X. You could remotely start your car, computer, stereo, etc. as long as there is Internet connectivity. The list goes on.