ESP32 Publish Sensor Readings to ThingSpeak (easiest way)

In this guide, you’ll learn how to send sensor readings with the ESP32 to ThingSpeak. For demonstration purposes, we’ll use a BME280 sensor, but you can easily modify the examples to use any other sensor. The ESP32 board will be programmed using the Arduino core.

ESP32 Publish Sensor Readings to ThingSpeak easiest way Arduino

ThingSpeak allows you to publish your sensor readings to their website and plot them in charts with timestamps. Then, you can access your readings from anywhere in the world.

We have a similar tutorial for the ESP8266 board: ESP8266 NodeMCU Publish Sensor Readings to ThingSpeak (easiest way)

Project Overview

There are many ways to send sensor readings to ThingSpeak. In this tutorial, we’ll use one of the easiest ways—using the thingspeak-arduino library. This library provides methods to easily publish sensor readings to single fields or multiple fields. You can check the library examples on its GitHub page.

To exemplify, we’ll use the BME280 sensor, but you can use any other sensor (you need to modify the code).

Recommended reading: ESP32 with BME280 Sensor using Arduino IDE (Pressure, Temperature, Humidity).

We’ll cover how to publish to a single field and how to publish to multiple fields.

Preparing Arduino IDE

For this tutorial we’ll program the ESP32 using the Arduino core. So, make sure you have the ESP32 add-on installed in your Arduino IDE:

If you want to program the ESP32 using VS Code with the PlatformIO extension, follow the next tutorial instead:

Installing the ThingSpeak Library

To send sensor readings to ThingSpeak, we’ll use the thingspeak-arduino library. You can install this library through the Arduino Library Manager. Go to Sketch > Include Library > Manage Libraries… and search for “ThingSpeak” in the Library Manager. Install the ThingSpeak library by MathWorks.

Install ThingSpeak Library Arduino IDE

Installing BME280 Libraries

As mentioned previously, we’ll publish sensor readings from a BME280 sensor. So, you also need to install the libraries to interface with the BME280 sensor.

You can install the libraries using the Arduino Library Manager. Go to Sketch Include Library > Manage Libraries and search for the library name.

Installing Libraries (VS Code + PlatformIO)

If you’re using VS Code with the PlatformIO extension, copy the following to the platformio.ini file to include the libraries.

lib_deps = mathworks/ThingSpeak@^2.0.0
            adafruit/Adafruit Unified Sensor @ ^1.1.4
            adafruit/Adafruit BME280 Library @ ^2.1.2  

Building the Circuit

To exemplify how to send data to ThingSpeak, we’ll send sensor readings from a BME280 sensor. So, you need to wire a BME280 sensor to your ESP32.

Parts Required

To complete this tutorial you need the following parts:

You can use the preceding links or go directly to MakerAdvisor.com/tools to find all the parts for your projects at the best price!

Schematic Diagram

We’re going to use I2C communication with the BME280 sensor module. For that, wire the sensor to the default ESP32 SCL (GPIO 22) and SDA (GPIO 21) pins, as shown in the following schematic diagram.

ESP32 Wiring Circuit to BME280 Schematic Diagram

Recommended reading: ESP32 Pinout Reference: Which GPIO pins should you use?

ThingSpeak – Getting Started

Go to ThingSpeak an click the “Get Started For Free” button to create a new account. This account is linked to a Mathworks account. So, if you already have a Mathworks account, you should log in with that account.

Creating New Channel

After your account is ready, sign in, open the “Channels” tab and select “My Channels“.

ThingSpeak Getting Started my channels tab

Press the “New Channel” button to create a new channel.

ESP32 ESP8266 NodeMCU ThingSpeak Create New Channel

Type a name for your channel and add a description. In this example, we’ll just publish temperature. If you want to publish multiple readings (like humidity and pressure), you can enable more fields as you’ll see later in this tutorial.

ThingSpeak Edit Add New Channel Settings Configuration

Click the Save Channel button to create and save your channel.

ESP32 ESP8266 NodeMCU ThingSpeak Save New Channel

Customizing Chart

The chart can be customized, go to your Private View tab and click on the edit icon.

ThingSpeak Customize Chart Private View ThingSpeak

You can give a title to your chart, customize the background color, x and y axis, and much more.

ThingSpeak field 1 chart options save settings

When you’re done, press the “Save” button.

API Key

To send values from the ESP32 to ThingSpeak, you need the Write API Key. Open the “API Keys
tab and copy the Write API Key to a safe place because you’ll need it in a moment.

Thingspeak Write API Key generate new key

ESP32 Publish Sensor Readings to ThingSpeak – Code

Copy the following code to your Arduino IDE (or to the main.cpp file if you’re using PlatformIO).

/*
  Adapted from WriteSingleField Example from ThingSpeak Library (Mathworks)
  
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com/esp32-thingspeak-publish-arduino/
  
  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files.
  
  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
*/

#include <WiFi.h>
#include "ThingSpeak.h"
#include <Adafruit_BME280.h>
#include <Adafruit_Sensor.h>

const char* ssid = "REPLACE_WITH_YOUR_SSID";   // your network SSID (name) 
const char* password = "REPLACE_WITH_YOUR_PASSWORD";   // your network password

WiFiClient  client;

unsigned long myChannelNumber = X;
const char * myWriteAPIKey = "XXXXXXXXXXXXXXXX";

// Timer variables
unsigned long lastTime = 0;
unsigned long timerDelay = 30000;

// Variable to hold temperature readings
float temperatureC;
//uncomment if you want to get temperature in Fahrenheit
//float temperatureF;

// Create a sensor object
Adafruit_BME280 bme; //BME280 connect to ESP32 I2C (GPIO 21 = SDA, GPIO 22 = SCL)

void initBME(){
  if (!bme.begin(0x76)) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  }
}

void setup() {
  Serial.begin(115200);  //Initialize serial
  initBME();
  
  WiFi.mode(WIFI_STA);   
  
  ThingSpeak.begin(client);  // Initialize ThingSpeak
}

void loop() {
  if ((millis() - lastTime) > timerDelay) {
    
    // Connect or reconnect to WiFi
    if(WiFi.status() != WL_CONNECTED){
      Serial.print("Attempting to connect");
      while(WiFi.status() != WL_CONNECTED){
        WiFi.begin(ssid, password); 
        delay(5000);     
      } 
      Serial.println("\nConnected.");
    }

    // Get a new temperature reading
    temperatureC = bme.readTemperature();
    Serial.print("Temperature (ºC): ");
    Serial.println(temperatureC);
    
    //uncomment if you want to get temperature in Fahrenheit
    /*temperatureF = 1.8 * bme.readTemperature() + 32;
    Serial.print("Temperature (ºC): ");
    Serial.println(temperatureF);*/
    
    
    // Write to ThingSpeak. There are up to 8 fields in a channel, allowing you to store up to 8 different
    // pieces of information in a channel.  Here, we write to field 1.
    int x = ThingSpeak.writeField(myChannelNumber, 1, temperatureC, myWriteAPIKey);
    //uncomment if you want to get temperature in Fahrenheit
    //int x = ThingSpeak.writeField(myChannelNumber, 1, temperatureF, myWriteAPIKey);

    if(x == 200){
      Serial.println("Channel update successful.");
    }
    else{
      Serial.println("Problem updating channel. HTTP error code " + String(x));
    }
    lastTime = millis();
  }
}

View raw code

To make the code work, you need to insert your network credentials in the following variables:

const char* ssid = "REPLACE_WITH_YOUR_SSID";   
const char* password = "REPLACE_WITH_YOUR_PASSWORD";  

You need to insert the number of the channel that you’re publishing to. If you only have one channel created in ThingSpeak, the channel number is 1. Otherwise, you can see the number of the channel on the Private View tab.

unsigned long myChannelNumber = 1;

Finally, you need to insert the Write API key you’ve gotten from the previous steps:

const char * myWriteAPIKey = "XXXXXXXXXXXXXXXX";

How the Code Works

First, you need to include the necessary libraries.

#include <WiFi.h>
#include "ThingSpeak.h"
#include <Adafruit_BME280.h>
#include <Adafruit_Sensor.h>

Insert your network credentials in the following variables:

const char* ssid = "REPLACE_WITH_YOUR_SSID";   
const char* password = "REPLACE_WITH_YOUR_PASSWORD"; 

Create a Wi-Fi client to connect to ThingSpeak.

WiFiClient  client;

Insert your channel number as well as your write API key:

unsigned long myChannelNumber = 1;
const char * myWriteAPIKey = "XXXXXXXXXXXXXXXX";

In the timerDelay variable insert how frequently you want to publish readings. In this case, we’re publishing readings every 30 seconds (30000 milliseconds). You can change this delay time if you want.

unsigned long lastTime = 0;
unsigned long timerDelay = 30000;

The temperatureC variable holds the temperature value in Celsius degrees.

float temperatureC;

If you want to get the temperature in Fahrenheit degrees, uncomment the following line.

//float temperatureF;

Create an Adafruit_BME280 object called bme on the default ESP32 pins.

Adafruit_BME280 bme; //BME280 connect to ESP32 I2C (GPIO 21 = SDA, GPIO 22 = SCL)

The initBME() function initializes the BME280 sensor.

void initBME(){
  if (!bme.begin(0x76)) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  }
}

In the setup(), initialize the Serial Monitor:

Serial.begin(115200);  //Initialize serial

Initialize the BME280 sensor.

initBME();

Set the ESP32 as a Wi-Fi station:

WiFi.mode(WIFI_STA);

Initialize ThingSpeak:

ThingSpeak.begin(client);  // Initialize ThingSpeak

In the loop(), connect or reconnect to Wi-Fi in case the connection was lost:

// Connect or reconnect to WiFi
if(WiFi.status() != WL_CONNECTED){
  Serial.print("Attempting to connect");
  while(WiFi.status() != WL_CONNECTED){
    WiFi.begin(ssid, password); 
    delay(5000);     
  } 
  Serial.println("\nConnected.");
}

Get a new temperature reading and print it in the Serial Monitor:

temperatureC = bme.readTemperature();

Uncomment the following lines if you want to get the temperature in Fahrenheit degrees.

/*temperatureF = 1.8 * bme.readTemperature() + 32;
Serial.print("Temperature (ºC): ");
Serial.println(temperatureF);*/

Finally, write to ThingSpeak. You can use the writeField() method that accepts as arguments:

  • the channel number;
  • the field number (in our case, we just have one field);
  • the value you want to publish (temperatureC or temperatureF);
  • your write API key.

This function returns the code 200 if it has succeeded in publishing the readings.

int x = ThingSpeak.writeField(myChannelNumber, 1, temperatureC, myWriteAPIKey);
if(x == 200){
  Serial.println("Channel update successful.");
}
else{
  Serial.println("Problem updating channel. HTTP error code " + String(x));
}

If you want to publish your readings in Fahrenheit degrees, uncomment the following line in the code:

//int x = ThingSpeak.writeField(myChannelNumber, 1, temperatureF, myWriteAPIKey);

Demonstration

After inserting your network credentials, channel number and API key, upload the code to your board.

Open the Serial Monitor at a baud rate of 115200, and press the on-board RST button. After 30 seconds, it should connect to Wi-Fi and start publishing the readings to ThingSpeak.

Publish Temperature Readings ThingSpeak ESP32 Serial Monitor

Go to your ThingSpeak account to the channel you’ve just created, and you’ll see the temperature readings being published and plotted on the chart.

ThingSpeak Chart BME280 Readings ESP32

Now, you can get access to those readings from anywhere in the world by accessing your ThingSpeak account.

Sending Multiple Fields (Temperature, Humidity, and Pressure)

In this section, you’ll learn how to send multiple fields—this is sending more than one value at a time—we’ll send temperature, humidity, and pressure readings.

Enable Multiple Fields – ThingSpeak

First, you need to create more fields in your ThingSpeak account. This is simple. You need to go to your Channel Settings and add as many fields as you want. In this case, we’ve added two more fields, one for the humidity and another for the pressure.

Thingspeak add new fields channel settings change

Finally, save the channel—click the Save Channel button.

ESP32 ESP8266 NodeMCU ThingSpeak Save New Channel

Now, if you go to the Private View tab, you should have three charts. Edit the newly created charts with a title and axis labels.

ESP32 Write Multiple Fields to ThingSpeak – Code

The following code sends multiple fields to ThingSpeak (temperature, humidity, and pressure from the BME280 sensor).

/*
  Adapted from Example from ThingSpeak Library (Mathworks)
  
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com/esp32-thingspeak-publish-arduino/
  
  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files.
  
  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
*/

#include <WiFi.h>
#include "ThingSpeak.h"
#include <Adafruit_BME280.h>
#include <Adafruit_Sensor.h>

const char* ssid = "REPLACE_WITH_YOUR_SSID";   // your network SSID (name) 
const char* password = "REPLACE_WITH_YOUR_PASSWORD";   // your network password

WiFiClient  client;

unsigned long myChannelNumber = X;
const char * myWriteAPIKey = "XXXXXXXXXXXXXXXX";

// Timer variables
unsigned long lastTime = 0;
unsigned long timerDelay = 30000;

// Variable to hold temperature readings
float temperatureC;
float humidity;
float pressure;
//uncomment if you want to get temperature in Fahrenheit
//float temperatureF;

// Create a sensor object
Adafruit_BME280 bme; //BME280 connect to ESP32 I2C (GPIO 21 = SDA, GPIO 22 = SCL)

void initBME(){
  if (!bme.begin(0x76)) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  }
}

void setup() {
  Serial.begin(115200);  //Initialize serial
  initBME();
  
  WiFi.mode(WIFI_STA);   
  
  ThingSpeak.begin(client);  // Initialize ThingSpeak
}

void loop() {
  if ((millis() - lastTime) > timerDelay) {
    
    // Connect or reconnect to WiFi
    if(WiFi.status() != WL_CONNECTED){
      Serial.print("Attempting to connect");
      while(WiFi.status() != WL_CONNECTED){
        WiFi.begin(ssid, password); 
        delay(5000);     
      } 
      Serial.println("\nConnected.");
    }

    // Get a new temperature reading
    temperatureC = bme.readTemperature();
    Serial.print("Temperature (ºC): ");
    Serial.println(temperatureC);
    humidity = bme.readHumidity();
    Serial.print("Humidity (%): ");
    Serial.println(humidity);
    pressure = bme.readPressure() / 100.0F;
    Serial.print("Pressure (hPa): ");
    Serial.println(pressure);
    
    //uncomment if you want to get temperature in Fahrenheit
    /*temperatureF = 1.8 * bme.readTemperature() + 32;
    Serial.print("Temperature (ºC): ");
    Serial.println(temperatureF);*/

    // set the fields with the values
    ThingSpeak.setField(1, temperatureC);
    //ThingSpeak.setField(1, temperatureF);
    ThingSpeak.setField(2, humidity);
    ThingSpeak.setField(3, pressure);
    
    // Write to ThingSpeak. There are up to 8 fields in a channel, allowing you to store up to 8 different
    // pieces of information in a channel.  Here, we write to field 1.
    int x = ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);

    if(x == 200){
      Serial.println("Channel update successful.");
    }
    else{
      Serial.println("Problem updating channel. HTTP error code " + String(x));
    }
    lastTime = millis();
  }
}

View raw code

This code is very similar to the previous one, but sends multiple fields. Let’s take a look at the relevant parts for this example.

Frist, create variables to hold the sensor readings:

float temperatureC;
float humidity;
float pressure;

In the loop(), get new temperature, humidity and pressure readings:

// Get a new temperature reading
temperatureC = bme.readTemperature();
Serial.print("Temperature (ºC): ");
Serial.println(temperatureC);
humidity = bme.readHumidity();
Serial.print("Humidity (%): ");
Serial.println(humidity);
pressure = bme.readPressure() / 100.0F;
Serial.print("Pressure (hPa): ");
Serial.println(pressure);

You need to assign a value to each field. If you’ve created the fields as we did, the first field corresponds to the temperature, the second to the humidity, and the third to the pressure. The following lines assign the corresponding values to each field using the setField() method—it accepts as arguments the field number and the value:

// set the fields with the values
ThingSpeak.setField(1, temperatureC);
//ThingSpeak.setField(1, temperatureC);
ThingSpeak.setField(2, humidity);
ThingSpeak.setField(3, pressure);

Finally, use the writeFields() method and set as arguments the channel number and the write API key:

int x = ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);

Demonstration

Upload the previous code to your board—don’t forget to insert your network credentials, Write API Key and channel number. After uploading, it should connect successfully and send the readigns:

ESP32 Write Multiple Fields ThingSpeak Serial Monitor

If you go to your ThingSpeak account, under Private View, you can see three charts with the sensor readings.

ESP32 Publish Send Sensor Readings to ThingSpeak Demonstration easiest way

Wrapping Up

In this tutorial you’ve learned how to publish readings from a BME280 sensor to ThingSpeak using the ESP32 and the thingspeak-arduino library. You can change the examples to send readings from any other sensors or data from any other source. We have tutorials for the most popular sensors:

You can visualize the sensor readings from anywhere by logging in to your ThingSpeak account.

The library used throughout this tutorial provides several examples that may be useful—check the examples here or in your Arduino IDE go to File > Examples > ThingSpeak, and you’ll have several examples.

We hope you’ve found this tutorial useful. Learn more about the ESP32 with our resources:



Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »
Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »

Recommended Resources

Build a Home Automation System from Scratch » With Raspberry Pi, ESP8266, Arduino, and Node-RED.

Home Automation using ESP8266 eBook and video course » Build IoT and home automation projects.

Arduino Step-by-Step Projects » Build 25 Arduino projects with our course, even with no prior experience!

What to Read Next…


Enjoyed this project? Stay updated by subscribing our newsletter!

20 thoughts on “ESP32 Publish Sensor Readings to ThingSpeak (easiest way)”

  1. Hi Rui and Sara, this work is also very interesting. I will try to monitor my car battery voltage. I believe it can be done.

    Reply
  2. Hello Sara and Rui,

    What a great tutorial! As a follow-up, could you please use the read function inThingSpeak to activate an actuator (for example if the temperature is too high automatically activate a Sonoff or a relay).

    Keep going!

    Reply
  3. I can’t believe it!
    I have managed to take this code, mash it together with your code for multiple DS18B20 temperature sensors, and it worked first time! I mean FIRST TIME! That has never happened to me before.
    I guess it is time to buy a lottery ticket.
    Thanks Guys

    Reply
  4. I was having issues using in Arduino with this code. It would return this error:

    ‘class WiFiClass’ has no member named ‘mode’

    Ended up solving it by deleting line:
    WiFi.mode(WIFI_STA)

    And replacing that line with:
    WiFi.begin(ssid,password);

    I also had to import Arduino’s WiFi Nina and the SPI library. So I imported both in the library manager and added these lines at the very top of the code like this:

    #include <SPI.h>
    #include <WiFiNINA.h>

    I hope this helps people, because this error threw me in for quite a ride. Thanks for the tutorial, it seems hard to find ESP32 code with thingspeak.

    Reply
  5. Hi Sara,
    Can you please tell me how to adapt this program to to count and record the pulse from an electricity meter using a photodiod or optical pulse detector or any other pulse counting device?
    I would very much appreciate it if you give me some guidance in achieving this.
    I would like to be able to record this over a 24hr period and longer term to monitor kWh power usage.
    Many thanks
    Norman Gaskell

    Reply
  6. Hello, thank you for the tutorial.
    I want to ask about the lowest time to publish the value. I’m trying to set the timerdelay to 5000 ms but it only send for every 15 s, does the 15 s is the lowest time to publish the value?

    Reply

Leave a Comment

Download Our Free eBooks and Resources

Get instant access to our FREE eBooks, Resources, and Exclusive Electronics Projects by entering your email address below.