Tutorial: IoT Datalogger with ESP8266 WiFi Module and FRDM-KL25Z

In my earlier post “Tutorial: Web Server with the ESP8266 WiFi Module” I  used the ESP8266 WiFi module to run a local web server. This is a cool way to control devices inside my network. But to use that web page from the internet, I would need to open up my router which I don’t want to do for obvious reasons. Why not going the other way: host the web page in the internet, and have my board communicating with that internet page? This is exactly what this hype around IoT (Internet of Things) is all about :-).

ThingSpeak Channel for ESP8266

ThingSpeak Channel for ESP8266

Outline

In this article I continue to use the foundation I have made in my earlier “Tutorial: Web Server with the ESP8266 WiFi Module“: The FRDM-KL25Z board with the ESP8266 WiFi module.

ThingSpeak

I stumbled over ThingSpeak (https://thingspeak.com/) while searching for an IoT cloud platform where I could store my data. There are many ones available, but the this one really stand out in my view: open, free and good infrastructure, including visualization tools.

💡 There is another IoT data server which I recommend to look at: https://data.sparkfun.com/. This one is simple and easy to use, but does not come with visualization out of the box.

Before using ThingSpeak, you need to set up an account:

  1. Sign up for a free account at https://thingspeak.com/
  2. Go to Channels and create New Channel. It will assign a Channel ID (we will use later). Provide a name and description. You can leave the other fields with the defaults for now. Press Save at the bottom of the Channel Settings page.

    New ThingSpeak Channel

    New ThingSpeak Channel

  3. Go to API Keys: it has generated an API key we will use in the communication.

    new API Key

    new API Key

  4. Now I can test the connection by putting this in my browser
    http://api.thingspeak.com/update?key=API_KEY&field1=0
    after replacing API_KEY with the API key from above:
    http://api.thingspeak.com/update?key=J4P1LICZI6ZF0YWG&field1=0
    This will add the data ‘0’ to ‘field1’. The browser responds with the number of data points:

    Testing Channel

    Testing Channel

  5. I can check the result with
    http://api.thingspeak.com/channels/CHANNEL_ID/feed.json?key=API_KEY
    where now again use my API key plus the channel ID I have been assigned from above:
    http://api.thingspeak.com/channels/20696/feed.json?key=J4P1LICZI6ZF0YWG

    Data Added to System

    Data Added to System

  6. This way I can add multiple data points, and I can view the data in a graphical view:

    Visualized Data

    Visualized Data

Now all what is needed to get the ESP8266 to connect to the ThingSpeak server and send the data :-).

Manual ESP8266 Command Sequence

First, let me show the command sequence using the command line shell.

At this point, I assume the ESP8266 module is connected to the access point. Then I set it up to allow multiple connections with CIPMUX:

AT+CIPMUX=1

Then, start a TCP connection to the ThingSpeak server (184.106.153.149), using http port 80. Because I’m allowing multiple connections with CIPMUX, I pass a channel (4):

AT+CIPSTART=4,"TCP","184.106.153.149",80

The ESP8286 should respond with:

OK
Linked

Next, I’m using the CIPSEND to send my data. The first value is the channel id from above (4), followed by the size of the string I’m going to send (44 characters in my case):

AT+CIPSEND=4,44

❗ The size needs to include/count the “\r\n” at the end of the string!

Then the module should respond with

>

to show it is ready to receive the data. The data is sent directly, in my case with

GET /update?key=J4P1LICZI6ZF0YWG&field1=60

The GET command sends the data. ‘/update’ is the command to the data site to update the data points, followed by the API key, the field name and the value (60 in my case).

Finally, I close the TCP connection at the end with

AT+CIPCLOSE

And the new data point shows up in ThingSpeak 🙂 :

Sent Data with ESP8266

Sent Data with ESP8266

And here the full command line log:

ESP8266 Data Sending to ThingSpeak

ESP8266 Data Sending to ThingSpeak

Sending Data from Program

Because sending the data with the command line shell takes time, it makes sense to automate it in a function.

#define THING_SPEAK_IP_STR      "184.106.153.149" /* thingspeak.com IP Address */
#define THINK_SPEAK_IP_PORT     80 /* port number */
#define THING_SPEAK_KEY_STR     "J4P1LICZI6ZF0YWG" /* API key */
#define THING_SPEAK_CHANNEL     20696 /* channel ID */
#define THING_SPEAK_LABEL_STR   "field1"

/*!
 * \brief Sends a value to the ThingSpeak server
 * \param value Value to be sent
 * \param io Shell I/O handler or NULL if not used
 * \return Error code, ERR_OK for no failure
 */
uint8_t THINK_SendValue(int32_t value, const CLS1_StdIOType *io) {
  /* Does the same as the following shell commands:
   ESP send AT+CIPMUX=1
   ESP send AT+CIPSTART=4,"TCP","184.106.153.149",80  // 4 is the channel ID
   ESP send AT+CIPSEND=4,44                           // size with \r\n!
   ESP send GET /update?key=J4P1LICZI6ZF0YWG&field1=60
   ESP send AT+CIPCLOSE
   */
  uint8_t res = ERR_OK;
  uint8_t buf[64];
  uint8_t ch_id = 4;

  res = ESP_SetNumberOfConnections(1, io, ESP_DEFAULT_TIMEOUT_MS);
  if (res==ERR_OK) {
    res = ESP_OpenConnection(ch_id, TRUE, THING_SPEAK_IP_STR, THINK_SPEAK_IP_PORT, 5000, io);
    if (res==ERR_OK) {
      UTIL1_strcpy(buf, sizeof(buf), "GET /update?key=");
      UTIL1_strcat(buf, sizeof(buf), THING_SPEAK_KEY_STR);
      UTIL1_chcat(buf, sizeof(buf), '&');
      UTIL1_strcat(buf, sizeof(buf), THING_SPEAK_LABEL_STR);
      UTIL1_chcat(buf, sizeof(buf), '=');
      UTIL1_strcatNum32s(buf, sizeof(buf), value);
      UTIL1_strcat(buf, sizeof(buf), "\r\n");
      res = ESP_PrepareMsgSend(ch_id, UTIL1_strlen(buf), 3000, io);
      if (res==ERR_OK) {
        /* sending data */
        res = ESP_SendATCommand(buf, NULL, 0, NULL, ESP_DEFAULT_TIMEOUT_MS, io);
        if (res!=ERR_OK) {
          CLS1_SendStr("Sending page failed!\r\n", io->stdErr); /* copy on console */
        } else {
          for(;;) { /* breaks */
            res = ESP_ReadCharsUntil(buf, sizeof(buf), '\n', 1000);
            if (res==ERR_OK) { /* line read */
              if (io!=NULL) {
                CLS1_SendStr(buf, io->stdOut); /* copy on console */
              }
            }
            if (UTIL1_strncmp(buf, "SEND OK\r\n", sizeof("SEND OK\r\n")-1)==0) { /* ok from module */
              break;
            }
          }
        }
      }
    }
    (void)ESP_CloseConnection(ch_id, io, ESP_DEFAULT_TIMEOUT_MS);
  }
  return res;
}

All the other ESP8266 functions are in the ESP8266.c driver file. And a ‘send’ command have been implemented to automate sending data:

Command line Interface

Command line Interface

With this, I can send data interactively or automatically in given interval:

ThingSpeak Channel for ESP8266

ThingSpeak Channel for ESP8266

Summary

With the right steps and know-how, it is really easy to send data to the internet and host it on an IoT server. I this example I used ThingSpeak to post data points and visualize them, but any other IoT host can be used. ThingSpeak has other API’s, plugins and apps which can be used for different applications, e.g. tweeting messages to Twitter, line up requests at predetermined times or execute queued commands. I guess I have to explore all this in the next days and weeks :-).

The project and sources for this tutorial are available on GitHub: https://github.com/ErichStyger/mcuoneclipse/tree/master/Examples/KDS/FRDM-KL25Z/FRDM-KL25Z_ESP8266_ThingSpeak.

Happy Logging 🙂

Links:

58 thoughts on “Tutorial: IoT Datalogger with ESP8266 WiFi Module and FRDM-KL25Z

  1. Very nice and useful post Erich ( as usual ) !!!

    Just a little point to add : the thingspeak server ip address address ( today it is 184.106.153.149 ) could change in future , so it would be great to add dsn client capability to the project in order to automatically resolve the “thingspeak.com” address to the correct ip address ( whatever it will become ).

    Like

  2. Hello Erich,

    I am trying to send 3-axis data from the FRDM accelerometer to 3 fields in my ThingSpeak channel. For a start, I am sending only X axis to one field. It seems to be necessary to close TCP connection after every GET command, is that true? Also, if I want to send data to multiple fields, do I need to use multiple channels, with multiple CIPSTART commands to different channels, and also several CIPSEND commands?

    Like

    • Yes, I had to close the connections with my hardware/firmware too. I believe this is a bug in the firmware, so this might change we newer firmware (I have not tried that yet). I have not tried multiple channels yet, but if you do, you will need a CIPSEND for each channel.

      Like

      • Hello,

        Instead of using multiple channels, I found out that I can use a single GET command to send multiple data fields. I just need to add “&field2=xx&field3=yy” after the original GET command. Now I can send all accelerometer axes for my 3 channel fields in one command. Anyway, it is a pain in the neck to have to close and re-open TCP connection every time I want to send new data. It would be interesting to make a programmer for the module using the FRDM board, so when new firmware versions come, we can be able to update the module with the hardware we have at hand.

        Like

        • Ah, I thought you wanted to use multiple channels. But yes, you can use a single GET for multiple fields too 🙂
          As for updating the firmware on the ESP8266: I was considering as well to setup a FRDM board to do that job too, but had no time to work on that yet.

          Like

  3. Pingback: Hello Internet! I have a Thing! | MWH Projects Blog

  4. The major problem now in using ESP8266 for WiFi router routed application, is the IP address that is got to be written in the program ( say for Arduino) so it cannot be changed by a lame user.We have successfully overcome this by writing the vales of SSID & Password every time it faces a new wifi router on a serial terminal like (most user friendly is from Hackaday.–http://hackaday.io/project/3568-esp8266-test-program) .Run all the AT commands till you complete the SSID & Password and then remove the ESP and use it with any Arduino interface with program running from thereafter..

    Like

  5. Hello. Can you help me? I cant find any way to get data from thingspeak.com. i try many way but it not work. (sory because my english)

    Like

  6. Hello.

    I tried your esp8266 tutorial on sending data to thinkspeak. I get all the way to the end but after I post the data following the CIPSEND I get an error and the data never shows up? I can’t get past the 400 error. Obvioulsy a bad GET request.

    at+CIPSTART=4,”TCP”,”184.106.153.149″,80
    4,CONNECT

    OK
    at+CIPSEND=4,37
    > /update?key=80TH1Y8SLZ3XXXXX&field1=1
    SEND OK

    +IPD,4,323:HTTP/1.1 400 Bad Request
    Server: nginx/1.7.5
    Date: Mon, 26 Jan 2015 00:16:38 GMT
    Content-Type: text/html
    Content-Length: 172
    Connection: close

    OK
    4,CLOSED

    Thank you,
    Rich

    Like

    • Yes we also faced the same problem. write like this Tx_String(“AT+CIPSEND=50”);

      Tx_String(“GET /update?key=****************&field1=”);

      As you see the above characters inside the bracket, are 40 But write little more as seen above for AT+CIPSEND = 50 (and not 40)

      On Mon, Jan 26, 2015 at 12:55 PM, MCU on Eclipse wrote:

      > Rich commented: “Hello. I tried your esp8266 tutorial on sending data > to thinkspeak. I get all the way to the end but after I post the data > following the CIPSEND I get an error and the data never shows up? I can’t > get past the 400 error. Obvioulsy a bad GET request.” Respond to this > comment by replying above this line > New comment on *MCU on Eclipse * > > > *Rich* commented > > on Tutorial: IoT Datalogger with ESP8266 WiFi Module and FRDM-KL25Z > . > > > in response to *Erich Styger*: > > In my earlier post “Tutorial: Web Server with the ESP8266 WiFi Module” I > used the ESP8266 WiFi module to run a local web server. This is a cool way > to control devices inside my network. But to use that web page from the > internet, I would need to open up my router which I don’t […] > > Hello. > > I tried your esp8266 tutorial on sending data to thinkspeak. I get all the > way to the end but after I post the data following the CIPSEND I get an > error and the data never shows up? I can’t get past the 400 error. > Obvioulsy a bad GET request. > > at+CIPSTART=4,”TCP”,”184.106.153.149″,80 > 4,CONNECT > > OK > at+CIPSEND=4,37 > > /update?key=80TH1Y8SLZ3XXXXX&field1=1 > SEND OK > > +IPD,4,323:HTTP/1.1 400 Bad Request > Server: nginx/1.7.5

      Like

  7. Thanks for the post – it was helpful.
    I’m getting an “ERROR” response from thingspeak after issuing my GET command.
    My AT commands are almost exactly like yours, except for the API Key of course.
    The command works from the terminal (updates my thingspeak graph), but when it’s run from my Arduino sketch, I get the error and my data is not sent.
    Any clues?

    Like

    • Hi James,
      is there a special reason why you have to run an Arduino sketch? Can you not use normal C/C++ instead? My guess is that there is a bug in that sketch, so you would have to debug it to find out what is going wrong.
      The other thing is: check if doing things slower (with a delay) is helping. That might be a synchronization issue. I assume you are using interrupts?

      Like

      • Erich, Thanks for your prompt reply. I’m using Arduino because that is my preferred platform for this project, and I have other elements already implemented in Aduino sketch. In other words, C/C++ is not “normal” for me. In any event, I agree that there is probably an error in the sketch, and when I insert 2s delays between the important bits, but I still get the “ERROR” response on the GET command. Do you know of any additional details behind the “ERROR” message that I can use to troubleshoot my sketch?

        Like

        • Hi James,
          I don’t know what is behind this error. The inability of really debugging Arduino sketches other then with printf() messages was the major reason why I stopped using ‘the Arduino way’ years back. So I recommend that you start adding printing information in your program flow to find out what is going on. Good luck!

          Like

  8. hello,
    I have send my data to thingspeak. can i go for sending data from one esp8266 to another one.?
    If yes then how it would be??
    Please leave reply.

    Like

  9. Hello every body
    I have a question that I want to ask
    It is that i want to send a sensor data with ESP
    the sensor output is serial with RX and TX pins
    so I have decided to connect it directly to ESP
    the question is how to read this data with the simulinkUDP receive?
    thank you so much

    Like

    • Hello,
      I’m not familiar with the simulinkUDP connection. My understanding is that you want to read that data over the wire? You could use the FRDM board translating the data over UART/USB CDC to the host, if this is your use case.

      Like

  10. Hi, could you help me out a bit? My Esp seem to be sending out data perfectly while connected to my home router. However, the connection closes most of the time when I use a wifi hotspot instead, and most of the values dont send. This is really weird because it works beautifully with my home wifi. My wifi hotspot works fine by the way

    Like

      • I have tried using my phone as a hotspot as well to no avail. Some values do get sent out but these are far and few. The connection closes after every attempt at sending a value, and I think its because of an error after the At+CIPSEND command.

        Like

        • I’m not clear what the problem could be, but I suspect it might be a problem that the hotspot too frequently closes the connection?

          Like

  11. Hello, i am working on ESP8266 access point and i want to have internet on my phone when i connect to my ESP8266 but it said that don’t have internet connection, but i have i don’t know what is wrong? can someone help me with that please.

    Like

  12. hi i’m using esp8266 module.i have already uploaded lua firmware by nodemcu. now i want to send adc value from one esp module to another esp module they are connected through UART.now plz help how i can send adc value. plz give the two programmes code.

    Like

    • I’m affraid that I cannot do the work for you, but I can give you some hints what you have to do: I recommend that you either configure one ESP module as AP the other in Device mode. Then connect from the Device node to the AP node. The other (easier) way is that you configure both in Device mode, then connect to a third node (e.g. HTTP/FTP server) and store the values there. So one node sends the ADC value to the server, while the other module is retrieving the values from there.

      Like

  13. Hi Erich,
    I have a system where I am using HiFly HF-LPB100 wifi module. It supports HTTP protocol but it does not have FTP implemented on it.

    My system has 2 components.
    1. SD card (where i store the csv files).
    2. wifi module.

    I am using FRDM-K22F board.

    I want to send files from SDCard to the server. I am thinking of 2 options.
    1. Use HTTP POST command to attach the file.
    2. Use FTP for file transfers.

    Which is better among these two.
    Also I know HTTP POST with file attachment works on my laptop. But I have no clue how to attach a file from my MCU. On my laptop, I give the path of file. How do I do it on my embedded device?

    Thanks in advance.

    Like

  14. Hi,

    I’m looking to transmit short bursts of data as fast as possible. My adc is capturing at 10M Samples per second, so the bottleneck will most likely be on the networking side.

    Do you know what kind of data rates are generally achievable with the esp8266 (or cc3100, etc)? For example, a host using a spi clock of 5mhz, doing nothing but transmitting the alphabet, how many characters per second before characters start dropping (udp or tcp)?

    What type of application layer is best suited for high bandwidth bursts?

    Thanks!
    Ben

    Like

    • Hi Ben,
      I have no idea, I have not used that module that way. One limitation factor will be as well the serial interface to the module. So 10M (Mega?) samples per second are a *lot*.
      Using SPI with 5 MHz clock will require at least 8 clocks to transmit one byte (8 bits), plus overhead. So with a 5 MHz clock you will not be able to send more than 5/8 MBytes. Realistically you need to count in an overhead (idle time, communication overhead) of 10-20%.

      I hope this helps,
      Erich

      Like

  15. Pingback: PIC na IoT com ESP8266 e ThingSpeak - Embarcados

  16. Thank you very mush.
    There is a slight problem which is occuring before the final execution.ON giving the GET command to fetch the page details a ‘busys….’ is returned. Can please let me know how to overcome this problem?

    Like

  17. how to mysql to php databases send the thingspeak ?

    i am using gas sensor mq135 to data send the Node MCU .the node mcu Crete the esp8266 host post to send data bases storage of MYSQL php ..

    mysql tohow to post the data on web server thinkspeak.how?

    Like

    • I have not used it in that way, but this is certainly possible. Search the internet for tutorials which guide you how to send data to a mysql server using http or any other TCP/IP based protocol. The ESP8266 is not any differnt from that.

      Like

  18. Hi, Erich!

    I am trying to create a project that is using 2 Serial_LDD components: one for sending debug messages on UART0 and the second one to communicate with an ESP8266-12F WiFi module on UART2. I am trying to set the baud for UART2 to 115200 bps, but I get an error saying that is impossible to set the selected value. I tried to set the baud to 38400, but this doesn’t help because the module is communicating on 115200. Is it impossible to use UART2 with 115200 as a baud value?

    Thank you,
    Elena

    Like

        • Hi Elena,
          if you are using the KL25Z, then the default would be only around 20 MHz which is too slow for high baud rates. So yes, you can (and should) set it to the maximum value which is 48 MHz.

          Erich

          Like

  19. Pingback: WiFi OLED Mini Weather Station with ESP8266 | MCU on Eclipse

  20. This is a post from 4 years ago, but am using esp8266 in a project, I figured it would be super simple to hook it up to a FRDM-K64F board and get it working. Sure enough even without a webserver implementation, I have written a simple firmware that connects to the esp8266 board in AP mode and sends a value to thingspeak.com. My issue is that it is not consistent in sending values. First of all I have to use longer timeout values than yours (typically 10 to 12 seconds) in order to read the entire response and even then is not always consistent. In your testing I see you were uploading a value to thingspeak every 30 seconds. That is what I am trying to achieve here, too often it fails. Sometimes it reports failed to send and the value appears on the chart. How comes you were able to get consistent results? I am using some 4G wifi dongle for internet and it works pretty well.

    Like

    • It is amazing to realize how fast time goes by, 4 years already!
      I would have to dig out that project hardware (not sure if I still have a esp8266 around), but it was working very well that way for several months. I used an normal wireless access point, so no 4G. Maybe the issue is on thingspeak that they slow down things now? I pretty much moved over to use MQTT instead for such kind of things.

      Like

      • Thanks man. I will check out MQTT. I figured out that the 4g network is troublesome over here, I am in Lahore Pakistan. I however figured out how to update the firmware to the latest version using esptools, in Linux. I am writing a blog post about that. I will test again the performance tomorrow before ruling it out.

        Like

  21. Pingback: Eclipse JTAG Debugging the ESP32 with a SEGGER J-Link | MCU on Eclipse

What do you think?

This site uses Akismet to reduce spam. Learn how your comment data is processed.