Wednesday, July 2, 2014

Uploading sensor data to Thingspeak with the Spark Core

I was able to get the Spark Core to upload data to Thingspeak after looking at some of the examples for using the arduino with the Wifi shield. a few things to note, I needed to put a slight delay after the stream or the spark would close the TCP connection too quickly. 100 ms seemed to do the trick. Also while my example has a delay to keep updates to Thingspeak I suggest using timers because over time the delay (which is blocking) will kill the Spark Cloud connection.

I set up a Sin wav as fake sensor data just to make a cool looking chart. I also setup an inverse of it to demo two streams. Below is the output chart and the example code.



#include "math.h"
// Thinkspeak channel information
String writeAPIKey = "<<Enter your channel's API key here>>";
String channelID = "<<Enter your channel's ID here>>";

// TCP socket initialize
TCPClient client;

float x;
float y;

/*--------------------------------------------------------
Setup
--------------------------------------------------------*/
void setup()
{
    Serial.begin(9600);
    delay(10000);
    Serial.println("===Starting===");
}

/*--------------------------------------------------------
Main loop
--------------------------------------------------------*/
void loop() 
{
    if(Spark.connected())
    {
        for (float z = 4.712; z < 10.995; z = z + .15)      // "z" sets the sin wave to the first zero crossing 4.712 and ends it on the next 10.995.
        {
          x = sin(z) * 127.5 + 127.5;                       // Making the sin wave all positive numbers and setting it to a scale of 0-255 (makes it easy to PWM an LED)
          y = 255 - (sin(z) * 127.5 + 127.5);               // This inverts the sin wave so we have two streams.
          
          // Must convert data to Strings, make sure you use capital "S" in Strings
          ThingSpeakUpdate("field1="+String(x)+"&field2="+String(y));
          
          // I put this delay in place so we don't flood Thingspeak but you should really use a timer, delays screw with the sparkcloud connection some times.
          delay(15000);
        }
    }
}

/*------------------------------------------------
Sends sensor data to Thingspeak
Inputs: String, data to be entered for each field
Returns: 
------------------------------------------------*/
void ThingSpeakUpdate(String tsData)
{
    Serial.println("Date string: " + tsData);
    
    Serial.println("...Connecting to Thingspeak");
    
    // Connecting and sending data to Thingspeak
    if(client.connect("api.thingspeak.com", 80))
    {
        Serial.println("...Connection succesful, updating datastreams");
        
        client.print("POST /update HTTP/1.1\n");
        client.print("Host: api.thingspeak.com\n");
        client.print("Connection: close\n");
        client.print("X-THINGSPEAKAPIKEY: "+writeAPIKey+"\n");
        client.print("Content-Type: application/x-www-form-urlencoded\n");
        client.print("Content-Length: ");
        client.print(tsData.length());
        client.print("\n\n");
        
        client.println(tsData); //the ""ln" is important here.
    
        // This delay is pivitol without it the TCP client will often close before the data is fully sent
        delay(200);
        
        Serial.println("Thingspeak update sent.");
    }
    else{
        // Failed to connect to Thingspeak
        Serial.println("Unable to connect to Thingspeak.");
    }
    
    if(!client.connected()){
        client.stop();
    }
    client.flush();
    client.stop();
}