Using an Arduino + Ethernet Shield to Update a ThingSpeak Channel

This tutorial demonstrates how to use the Arduino to read in the analog input and update a ThingSpeak Channel by sending an HTTP POST via the Arduino Ethernet Shield or the Arduino Ethernet (all-in-one). The analog input can be the output of a sensor, like a light sensor or temperature sensor.

ThingSpeak Client Arduino Sketch

This Arduino sketch takes the value of Analog Pin 0 and updates Field 1 of a ThingSpeak Channel using the ThingSpeak API.

Arduino_to_ThingSpeak.ino [Arduino 1.0+]

ThingSpeakClient.pde [Arduino 0023 or less]

Getting Started with ThingSpeak

  • Sign Up for New User Account – https://www.thingspeak.com/users/new
  • Create a New Channel by selecting Channels and then Create New Channel
  • Enter the Write API Key in this sketch under “ThingSpeak Settings”

ThingSpeak API IP Address

The Arduino + Ethernet Shield does not have DNS by default, so you need to send data using an IP address. ThingSpeak has an API address dedicated for its API.

byte server[]  = { 184, 106, 153, 149 }; // ThingSpeak IP Address: 184.106.153.149

HTTP POST to ThingSpeak

One option to update a ThingSpeak Channel is to use HTTP POST. You can specify any number of fields, location, or status in one message.

Here is an example HTTP POST to ThingSpeak:

POST /update HTTP/1.1
Host: api.thingspeak.com
Connection: close
X-THINGSPEAKAPIKEY: (Write API Key)
Content-Type: application/x-www-form-urlencoded
Content-Length: (number of characters in message)

field1=(Field 1 Data)&field2=(Field 2 Data)&field3=(Field 3 Data)&field4=(Field 4 Data)&field5=(Field 5 Data)&field6=(Field 6 Data)&field7=(Field 7 Data)&field8=(Field 8 Data)&lat=(Latitude in Decimal Degrees)&long=(Longitude in Decimal Degrees)&elevation=(Elevation in meters)&status=(140 Character Message)

Watchdog Timer

Included in the sketch is a watchdog timer for the Ethernet Shield. When 5 failed transactions are detected in a row, the Arduino re-initializes the Ethernet Shield (soft-reset). This will not solve every lockup, but it will make the setup more stable.

Update Multiple Fields

You can update multiple fields inside of a ThingSpeak Channel by adding on more fields in the update request. Here’s an example:

updateThingSpeak("field1="+analogPin0+"&field2="+analogPin1);

Use Short Field Names to Save Space

If you want to save space when making a ThingSpeak update, you can use short field names. “field1″ is “1″ and field2= “2″ and so on. Here’s an example of how the short field names would look in an Arduino update request for a ThingSpeak Channel:

updateThingSpeak("1="+analogPin0+"&2="+analogPin1);

Common Issues

The function “updateThingSpeak” is expecting a “String” as its input. So, if you use a “long” variable type, you need to convert the “long” into a “String” before passing it into “updateThingSpeak”.

long sensorValue = 6;
updateThingSpeak("field1="+String(sensorValue, DEC));

23 comments

  1. How do you update multiple fields, I tried adding another updateThinkSpeak() right after the first, but it didn’t work. Only the first field gets updated. I tried putting a delay between the two, but that didn’t work either.

    if(!client.connected() && (millis() – lastConnectionTime > updateThingSpeakInterval))
    {
    updateThingSpeak(“field1=”+analogPin0);
    updateThingSpeak(“field2=”+analogPin1);

    }

    • @scott

      Here’s what you want to do… You want to combine the fields into one request. This way you can send all of the data at once instead of trying to send two requests with a delay.

      updateThingSpeak(“field1=”+analogPin0+”&field2=”+analogPin1);

      I hope that helps you out.

      PS. Sorry for the delay – your comment made it into the SPAM folder.

      • When I used short field names as described above:

        updateThingSpeak(“1=”+analogPin0+”&2=”+analogPin1);

        The program only ran twice, i’m assuming because of the &2? Anyway, I reverted to using full field names and it works again. Just thought I’d post in case anyone has that problem, took me ages to work out.

  2. Thanks for the excellent Arduino Sketch. It served as a great starting point for my project and ensured I began with a well constructed foundation to which I only needed to add the specifics of the live IO I was gathering.

  3. By the way, I added a check to see if millis() is less than lastConnectionTime to address the instance in which millis() wraps after about 50 days. If this were to happen, it will never be greater than updateThingSpeakInterval and the code will never send another update. I simply reset lastConnectionTime to zero, which isn’t the most sophisticated, but only introduces a briefer update period roughly once every 50 days.

  4. Is there a way in the POST to tell the ThingSpeak server to be less verbose? Once I disconnected the USB cable, the Arduino seemed to stall after a few hours and seemingly cleared up once I reconnected the cable. I’m guessing (and it’s really a guess) there’s an output buffer on the Arduino that’s getting full and stopping the Serial.print commands from being processed. In the meantime, I’ve added a conditional before each Serial.print to check and see if a troubleshoot flag is set. If not, the Serial.print command is not executed.

    • Tom,

      The Arduino doesn’t have a dynamic serial buffer. That’s not the cause. I’ve had sketches run for months, pumping out serial data with the USB disconnected for months and I don’t lose a byte of memory.

      Hard to say what your problem is, but you might be dynamically creating strings that aren’t being properly deleted.

  5. Ladies and gentlemen,

    Maybe this is the wrong place to ask but this is my question:

    I have a ThingSpeak server running at 94.212.224.139:3000

    So thingSpeakAddress = 94.212.224.139 and the 80 has to replaced with 3000.

    But in the arduinocode do i put in: client.print(“Host: api.thingspeak.com\n”);
    to replace api.thingspeak.com?

    Please help.

    if (client.connect(thingSpeakAddress, 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: “+writeAPIKey+”\n”);
    client.print(“Content-Type: application/x-www-form-urlencoded\n”);
    client.print(“Content-Length: “);
    client.print(tsData.length());
    client.print(“\n\n”);

    • Sorry for the delay… questions are easier to track in the forum.

      You need to change this line:

      if (client.connect(thingSpeakAddress, 80))

      to

      if (client.connect(thingSpeakAddress, 3000))

      Does that work?

  6. Hi again,
    now i would like to plot my float temperature values…i saw that “updateThingSpeak”expects a “String” as input, therefore i did a cast:
    String temp = String(temper());

    temper() returns a float but it doesn’t work; if i change the return of function temper() in int, it works, obviously.
    How can i do to fix it?

    • Francesco. you want to turn a float into a string. but you are not using the proper function.
      suppose ‘t’ is the temperature value coming from yr sensor and it is a float.
      Do like this:
      char t_buffer[10];
      t=(ReadSensor);
      String temp=dtostrf(t,0,5,t_buffer);

  7. The last question!
    now the update is every fifteen minutes.
    How can i change it?

    thanks

    Francesco

  8. I am trying to send data with an arduino and an ethernet shield, but it refuses work.
    At first attempt, many commands of the sketch had to be rewritten, because the API reports them as invalid or renamed – maybe different versions of the arduino API. Mine is updated, freshly instaled and downloades from the official arduino site.
    I added several commands to trace the program via serial monitor – it is running, the data was aquired, but it can’t send the data to the servers.
    The server side seens to be unavaible.
    Any idea?

    • Have you tried updating the channel manually from your web browser first to make sure it’s working as intended? http://community.thingspeak.com/documentation/api/#send_data

      • I’m new here.

        Also to me it refuses to work. I changed some coding according to EthernetClient class,

        and I used for parameter IP number, mnemonic, char[], String and so on.

        The point is that client.connect(server,80) never returns true! (see the folowing)

        void updateThingSpeak(String tsData)
        {
        Serial.println(“Connecting to ThingSpeak…”);

        if (client.connect(server,80))
        {
        Serial.println(“Connected to ThingSpeak…”);
        Serial.println();

        alway seen “Connecting to ThingSpeak…” and
        never seen “Connected to ThingSpeak…”!!!!!

        I tried a schema and it does work.

        I know it seems not a problem of ThingsSpeak….

        Thanks for help.
        Michele

        • Sorry …

          “I tried a schema and it does work.” STANDS FOR

          I tried a “client.connect(server,80)” schema with google server (“www.google.com”,80) and it does work.

          Thanks
          Michele

          • Solved. Just trying without any logic!! Why?

            Ethernet.begin(mac, ip, gateway, subnet);

            CHANGED TO

            Ethernet.begin(mac, ip);

            Ciao

          • Hello,

            I think I am having a very similar problem. Can you post the version of code you have working? or the changes you made to the ethernet class?

            Thanks!

  9. I am using wifi shield instead of ethernet.
    I can connect it to ThingSpeak but after some data sent I get a message “No socket available”. This make Thingspeak connection fail.

    Here the code
    https://docs.google.com/file/d/0B6Yw5tJf9DQ2cmg0VXExZDlQTDQ/edit

    Message
    Connecting to ThingSpeak…

    4958ºC
    SSID: GuiFi
    BSSID: 0:27:22:E6:55:25
    signal strength (RSSI):-72
    Encryption Type:4

    HTTP/1.1 200 OK
    X-Frame-Options: ALLOWALL
    Access-Control-Allow-Origin: *
    Access-Control-Allow-Methods: GET, POST, PUT, OPTIONS, DELETE, PATCH
    Access-Control-Allow-Headers: origin, content-type, X- Requested-With
    Access-Control-Max-Age: 1800
    Content-Type: text/html; charset=utf-8
    Etag: “289dff07669d7a23de0ef88d2f7129e7″
    Cache-Control: max-age=0, private, must-revalidate
    X-Request-Id: 172e8293-f68c-4217-ae88-11087f06dbb8
    X-Runtime: 0.016702
    Server: WEBrick/1.3.1 (Ruby/2.1.0/2013-12-25)
    Date: Fri, 23 May 2014 08:11:26 GMT
    Content-Length: 3
    Connection: close

    234No Socket available
    Connection to ThingSpeak Failed (1)

    I also can not send more than one field, even using:
    updateThingSpeak(“field1=”+analogPin0+”&field2=”+analogPin1);

    Thanks, Rodri

  10. Hey!
    The above all discussion is about arduino to thingspeak. I am using STM32F4 Discovery Board instead of arduino and trying to send sensor data to thingspeak. Can any one help me how can I send? I am using simple socket programming.

  11. Hi i want a complete solution for turn on or off pins of arduino from the internet. board also connects to the internet wirelessly (using GPRS internet). Is it possible ? or any other solution for complete wireless arduino remote. please send me reply to uma5b3@gmail.com

  12. I am using the adafruit CC3000 Wi Fi chip. What changes do I have do make to upload my data ?

Leave a comment