Uploading sensor data to Thingspeak

[Repost from my blog]

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();
}
4 Likes

@ccrumpacker, the delay() function only “blocks” the user code but it does call SPARK_WLAN_Loop() during the wait. :smile:

2 Likes

Ahhhh ok i found a few reference to it messing up if used for an always on project. Thanks for the heads up.

I am running this code but I am not seeing regular connections. I check millis() to see if I am ready to send (every 60 seconds) but I don’t see the ThingSpeak update on a minute basis and yet I see the message on the LED display that it is sending every 60 seconds or at least trying to. I don’t get any timeouts or failures that I can see.

Can I see your code?

Apart from the following in loop(), the rest is as posted above.

//
//See if time to send next update to ThingSpeak
//
currentTime = millis();

if(currentTime > thingTime)
{
    thingTime = currentTime + 60000;    // Every minute
    
    if(Spark.connected())
    {
        sprintf(info, "field1=%0.1f&field2=%0.1f", celsiusU,celsiusL);

        ThingSpeakUpdate(info);
    }
}

thingTime and currentTime are declared as unsigned long.

1 Like

Can you serial print the “tsData” and tsData.length() to verify the string is correct and the length is fine. Also if the field data is too long you can have issues. I kept my floats to 2 decimal places like this. String(floatVar, 2)

The string is fine. It’s the same one I send on UDP as my device is located away from the computer. It’ appears fine over UDP.

That’s why I Iike this system as I can update without dragging my laptop around.

It’s only 2 sets of data and as you can see I limit it to 1 decimal place.

Here’s a link to the ThingSpeak data. It should be every 60 seconds but seems to vary but is always some multiple of 60 seconds or there abouts.

https://thingspeak.com/channels/14333

Oh ic. I thought you meant it never updated. Yeah I reported that same issue, I think there is some issue with the spark loop when using this sort of timer. I was hoping someone has an idea here;