Interface for ThingSpeak

Hi, have put together some firmware (definitely a kludge) for sending sensor values to ThingSpeak. I’ve never attempted something like this before, having previously only tinkered with Arduino.

I have drawn on the post on this forum regarding Xively for code, as well as the API documentation for ThingSpeak regarding interfacing from an Arduino. After having put this together yesterday, i found another thread on this forum regarding POST commands and HTTP i think from memory which seemed to be doing something similar.

I uploaded the code to my Core last night and it was certainly able to connect to ThingSpeak, though i haven’t been able to successfully get any data uploaded. One problem i suspect is not having the length() command available to determine the length of the data packet to be uploaded. I had a guess at including the number 4 instead?!

There seem to be quite a few people interested in doing something like this, so no doubt a common method will evolve.

Interested in thoughts.

Chatty

#define writeAPIkey "<API Key here>"
#define CHANNEL_ID "<Channel ID here>"

int LED = D0;
int i = 0;
TCPClient client;
int LDR = A0;
int lastUp = 0;
int status = 0;


void setup() {
    pinMode(LED, OUTPUT);
    pinMode(LDR, INPUT);
}

void loop() {
    if(millis()-lastUp>10000){
        LDR = analogRead(A0);
        lastUp = millis();
        ThingSpeakUpdate(LDR);
    }
}

void ThingSpeakUpdate(int LDR) {
    if(client.connect("api.thingspeak.com", 80)){
        client.print("POST /update HTTP/1.1\n");
        client.print("Host: api.thingspeak.com\n");
        client.print("Connection: close\n");
        client.print("X-THINGSPEAKAPIKEY: ");
        client.print(writeAPIkey);
        client.print("Content-Type: application/x-www-form-urlencoded\n");
        // sheer guess here at how to tell ThingSpeak what length to expect
        client.print("Content-Length: 4\n");
        client.print(LDR);
        client.println();
        // signals that you have successfully connected
        ledStatus(2, 500);
        // check for a response from ThingSpeak. 
        // A successfull connection will return the channel ID (4 digit number),
        // a failure will return 0
        status = client.available();
        if(status >= 1){
            // status is a value greater than the failure
            ledStatus(6, 100);
        }
        else{
            // status is equal to the failure response
            ledStatus(3, 250);
        }
    }
    else{
        //failed to connect
        ledStatus(3, 1000);
    }
    if(!client.connected()){
        client.stop();
    }
    client.flush();
    client.stop();
}

void ledStatus(int x, int t){
    for (int j = 0; j <= x; j++){
        digitalWrite(LED, HIGH);
        delay(t);
        digitalWrite(LED, LOW);
        delay(t);
    }
}
2 Likes

The content length needs to be calculated based on the content that you send.

You need to send the field paramter in the content along with the value. Let’s assume LDR=100 and you want to send it to field1, then the content length would be 10 and would look like this.

client.print(“Content-Length: 10\n”);
client.print(“field1=”+LDR);
client.println();

You need to find a way to calculate length and make it variable based on the value of LDR. For example, what is LDR is 99, then the content length is 9 (7 for the field1= part and 2 for the 99 part.

Let me know if this helps.

1 Like

Have you looked at the new article up on Thingspeak Thingspeak Talkback with Arduino Yun? If I have time this weekend I will see if I can get it ported over to Spark.

2 Likes

I just posted on how I got this working. I made sure to pass the Strings just like the example arduino sketch then I could do a len on them all the same. Also a big part of this is making sure to put the delay in after the stream and before the connection close.

Forum Post

Function call:

ThingSpeakUpdate("field1="+String(x)+"&field2="+String(y));

Function:

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

Hey, for my project I need to analyze a lot more data points than one every 15 second. Is it possible to create a buffer of analog values from one or more pins and send all of them together as once TCP packet? Any ideas on how I could capture 5 values every second and send it to ThingSpeak? I’m guessing there is something to do with a buffer.

Really appreciate any help!