Please Note: Xively no longer has free developer access to their system, so this tutorial is only for historical research. Please check out our other IoT tutorials for alternative services!
The Arduino sketch for this project consists in initializing the DHT 11 sensor & the CC3000 WiFi chip, and then in running a loop that measures the temperature & humidity, send data to the Xively server, and repeat itself every 10 seconds. It starts by importing the right libraries.
The DHT library is at https://github.com/adafruit/DHT-sensor-library and CC3000 is at https://github.com/adafruit/Adafruit_CC3000_Library but be sure to follow the tutorials for both of those products first!
The DHT library is at https://github.com/adafruit/DHT-sensor-library and CC3000 is at https://github.com/adafruit/Adafruit_CC3000_Library but be sure to follow the tutorials for both of those products first!
#include <Adafruit_CC3000.h> #include <SPI.h> #include "DHT.h" #include <avr/wdt.h>
We can then define the correct pins for the CC3000 breakout board:
#define ADAFRUIT_CC3000_IRQ 3 #define ADAFRUIT_CC3000_VBAT 5 #define ADAFRUIT_CC3000_CS 10
And the correct pin for the DHT sensor, as well as the sensor type:
#define DHTPIN 7 #define DHTTYPE DHT11
We can then create the CC3000 instance:
Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT, SPI_CLOCK_DIV2);
And the DHT sensor instance:
DHT dht(DHTPIN, DHTTYPE);
The next set of parameters is something your have to modify with your parameters: your WiFi network name, your password, and the type of security.
#define WLAN_SSID "yourNetwork" #define WLAN_PASS "yourPass" #define WLAN_SECURITY WLAN_SEC_WPA2
The next set of parameters concerns Xively. If you remember, I asked you to write down some parameters of your Xively account: your API key and your feedID. Just enter them in these fields, it will be used to make the request to the Xively server.
#define WEBSITE "api.xively.com" #define API_key "yourAPIKey" #define feedID "yourFeedID"
Now, we enter the setup() part of the sketch. As we will connect and disconnect from the Xively server every time we want to send data, the setup() we will only include the initialization of the CC3000 chip, and the connection to the WiFi network:
Serial.println(F("\nInitializing...")); if (!cc3000.begin()) { Serial.println(F("Couldn't begin()! Check your wiring?")); while(1); } // Connect to WiFi network Serial.print(F("Connecting to WiFi network ...")); cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY); Serial.println(F("done!")); // Wait for DHCP to complete Serial.println(F("Request DHCP")); while (!cc3000.checkDHCP()) { delay(100); }
Then, in the loop() part of the sketch, we need to get the IP of the Xively server:
uint32_t ip = 0; Serial.print(F("api.xively.com -> ")); while (ip == 0) { if (! cc3000.getHostByName("api.xively.com", &ip)) { Serial.println(F("Couldn't resolve!")); while(1){} } delay(500); } cc3000.printIPdotsRev(ip); Serial.println(F(""));
We also need to keep in mind that we want the project to run continuously day after day, whatever happens. For example, we want to deploy this project in a remote location and have it run for months without any human intervention. So if the Arduino cannot connect to the Xively server or crashes when sending the data, we don't want it to freeze and do nothing anymore.
This is why we need to use the Arduino watchdog. This will basically reset the Arduino if no reset signal is received after a given delay. Here, we will initialise the watchdog with the maximum delay of 8 seconds:
This is why we need to use the Arduino watchdog. This will basically reset the Arduino if no reset signal is received after a given delay. Here, we will initialise the watchdog with the maximum delay of 8 seconds:
wdt_enable(WDTO_8S);
We can now measure the temperature & humidity using the dht instance, and convert these values into integers:
float h = dht.readHumidity(); float t = dht.readTemperature(); int temperature = (int) t; int humidity = (int) h;
This is now the time to format the data for the Xively website in the JSON format. It might seem complicated, but the Xively website has many tutorials to format your data correctly. We also need to know the total length (in number of characters) of the data so we can put it in the HTTP request:
// JSON data String data = ""; data = data + "\n" + "{\"version\":\"1.0.0\",\"datastreams\" : [ " + "{\"id\" : \"Temperature\",\"current_value\" : \"" + String(temperature) + "\"}," + "{\"id\" : \"Humidity\",\"current_value\" : \"" + String(humidity) + "\"}]}"; // Get length length = data.length();
We can now connect to the Xively server with the following piece of code. If it is successful, we print a message on the Serial monitor:
Adafruit_CC3000_Client client = cc3000.connectTCP(ip, 80); if (client.connected()) { Serial.println(F("Connected to Xively server."));
When the client is connected, we can send the request to the server. This is a typical HTTP PUT request, where we specify the feedID, the API key, and send the data at the end of the request. We first send the headers, and we reset the watchdog after this step:
Serial.print(F("Sending headers")); client.fastrprint(F("PUT /v2/feeds/")); client.fastrprint(feedID); client.fastrprintln(F(".json HTTP/1.0")); Serial.print(F(".")); client.fastrprintln(F("Host: api.xively.com")); Serial.print(F(".")); client.fastrprint(F("X-ApiKey: ")); client.fastrprintln(API_key); Serial.print(F(".")); client.fastrprint(F("Content-Length: ")); client.println(length); Serial.print(F(".")); client.fastrprint(F("Connection: close")); Serial.println(F(" done.")); // Reset watchdog wdt_reset();
We can now transmit the core of the data itself. We transmit the JSON data in several chunks using a dedicated function called sendData. This function cuts the data into small pieces, send these pieces one by one, and reset the watchdog after each chunk is sent. This way, we are protected in case the transmission doesn't work and makes the Arduino freeze.
The size of a chunk is defined in the buffer_size variable. Depending on your connection speed, you might have to change this variable so the watchdog doesn't reset the sketch every time.
The size of a chunk is defined in the buffer_size variable. Depending on your connection speed, you might have to change this variable so the watchdog doesn't reset the sketch every time.
Serial.print(F("Sending data ...")); client.fastrprintln(F("")); sendData(client,data,buffer_size); client.fastrprintln(F("")); Serial.println(F("done."));
After the request is sent, we read the answer from the server to be sure that everything is ok, and we print it on the Serial monitor. This is be useful when trying to debug the project.
while (client.connected()) { while (client.available()) { char c = client.read(); Serial.print(c); } }
After the answer has been received from the server, we close the connection, and disable the watchdog until the next loop():
client.close(); Serial.println(F("Closing connection")); // Reset watchdog & disable wdt_reset(); wdt_disable();
Because the temperature & humidity are slow-changing values, we can read these values & send them over to Xively only a few number of times every hour. For this guide, I used a delay of 10 seconds to make sure that the sketch is working, but you can use any value you want. This part is done by using a dedicated function called wait, which is also protected by the watchdog in case the Arduino sketch crashes:
wait(10000)
Finally, the complete code can be found in the GitHub repository of this project.
Text editor powered by tinymce.