Search

How to Send ESP32 Sensor Readings to ThingSpeak

This guide will teach you how to send sensor readings from the ESP32 to ThingSpeak. For this demonstration, we’ll use a BME280 sensor, but you can adapt the examples for any other sensor. The ESP32 board will be programmed with the Arduino core.

ThingSpeak lets you publish your sensor data to their website and visualize it in charts with timestamps, allowing you to access your readings from anywhere globally.

Project Overview

There are multiple ways to send sensor data to ThingSpeak. In this tutorial, we’ll use one of the simplest methods—utilizing the thingspeak-arduino library. This library offers functions to easily send sensor data to single or multiple fields. You can find examples on the library’s GitHub page.

For demonstration purposes, we’ll use the BME280 sensor, but you can adapt the code for any sensor.

Preparing Arduino IDE

Installing the ThingSpeak Library

To send sensor data to ThingSpeak, we’ll use the thingspeak-arduino library. Install this library via the Arduino Library Manager by following these steps: navigate to Sketch > Include Library > Manage Libraries…, then search for “ThingSpeak” in the Library Manager and install the ThingSpeak library by MathWorks.

Installing BME280 Libraries

Since we’ll be using a BME280 sensor to publish sensor readings, you also need to install the necessary libraries to interface with this sensor.

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

Installing Libraries (VS Code + PlatformIO)

If you’re using VS Code with the PlatformIO extension, add the following lines 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 demonstrate how to send data to ThingSpeak, we’ll use a BME280 sensor. You need to connect the BME280 sensor to your ESP32.

Parts Required

Component NameBuy Now
ESP32-WROOM-32 DevelopmentAmazon
BME280 3.3V Atmospheric Pressure SensorAmazon
Please Note: These are affiliate links. I may make a commission if you buy the components through these links. I would appreciate your support in this way!

Schematic Diagram

We’ll use I2C communication with the BME280 sensor module. Connect the sensor to the default ESP32 SCL (GPIO 22) and SDA (GPIO 21) pins, as shown in the schematic diagram.

ThingSpeak – Getting Started

Visit ThingSpeak and click the “Get Started For Free” button to create a new account. This account is linked to a MathWorks account. If you already have a MathWorks account, log in with those credentials.

Creating a New Channel

Once your account is set up, sign in, go to the “Channels” tab, and select “My Channels”. Click the “New Channel” button to create a new channel.

Enter a name and description for your channel. For this example, we’ll publish temperature data. If you want to publish multiple readings (like humidity and pressure), you can enable additional fields as explained later in this tutorial.

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

Customizing the Chart

You can customize the chart by going to your “Private View” tab and clicking the edit icon. Here, you can set a title for your chart, change the background color, adjust the x and y axes, and more. When finished, click the “Save” button.

API Key

To send data from the ESP32 to ThingSpeak, you need the Write API Key. Open the “API Keys” tab and copy the Write API Key to a secure location, as you will need it shortly.

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).

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

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";

Code Explanation

First, include the necessary libraries:

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

Enter 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;

Specify your channel number and write API key:

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

Set the frequency for publishing readings. Here, readings are published every 30 seconds (30000 milliseconds), but you can adjust this interval:

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

The temperatureC variable will hold the temperature value in Celsius:

float temperatureC;

To get the temperature in Fahrenheit, uncomment the following line:

//float temperatureF;

Create an Adafruit_BME280 object named bme for the default ESP32 I2C 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() function, initialize the Serial Monitor and the BME280 sensor, set the ESP32 as a Wi-Fi station, and initialize ThingSpeak:

void setup() {
  Serial.begin(115200);  // Initialize serial
  initBME();  // Initialize BME280 sensor
  WiFi.mode(WIFI_STA);  // Set ESP32 as a Wi-Fi station
  ThingSpeak.begin(client);  // Initialize ThingSpeak
}

In the loop(), ensure the ESP32 is connected to Wi-Fi, get a new temperature reading, and print it to the Serial Monitor. Finally, write the data to ThingSpeak:

void loop() {
  // 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 temperature reading in Celsius
  temperatureC = bme.readTemperature();

  // Uncomment for temperature in Fahrenheit
  /*temperatureF = 1.8 * bme.readTemperature() + 32;
  Serial.print("Temperature (ºF): ");
  Serial.println(temperatureF);*/

  // Publish to ThingSpeak
  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));
  }

  // Uncomment to publish in Fahrenheit
  // int x = ThingSpeak.writeField(myChannelNumber, 1, temperatureF, myWriteAPIKey);

  delay(timerDelay);
}

Demonstration

After entering 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.

Visit your ThingSpeak account and navigate to the channel you created to see the temperature readings being published and displayed on the chart. You can now access these readings from anywhere by logging into your ThingSpeak account.

Sending Multiple Fields (Temperature, Humidity, and Pressure)

In this section, you’ll learn how to send multiple values simultaneously: temperature, humidity, and pressure.

Enable Multiple Fields in ThingSpeak

First, you need to add more fields in your ThingSpeak account. To do this, go to your Channel Settings and add additional fields as needed. For this example, we’ll add two more fields: one for humidity and another for pressure.

After adding the fields, save your changes by clicking the Save Channel button.

In the Private View tab, you should now see three charts. You can edit these charts to add titles and label the axes accordingly.

ESP32: Write Multiple Fields to ThingSpeak – Code

The code below demonstrates how to send multiple fields (temperature, humidity, and pressure from the BME280 sensor) to ThingSpeak.

#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;

// Variables to hold sensor 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 connected 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 new sensor readings
    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 (ºF): ");
    // 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
    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();
  }
}

This code closely resembles the previous example but is modified to send multiple fields. Let’s break down the key parts:

Create Variables for Sensor Readings

float temperatureC;
float humidity;
float pressure;

Get New Sensor Readings in the loop()

// 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);

Assign Values to Fields

Assign each value to the appropriate field using the setField() method, specifying the field number and the value:

// 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

Use the writeFields() method with your channel number and write API key:

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

After configuring your network credentials, channel number, and API key, upload the code to your ESP32. Open the Serial Monitor at a baud rate of 115200 and press the on-board RST button. The ESP32 should connect to Wi-Fi and begin publishing sensor readings to ThingSpeak every 30 seconds. Check your ThingSpeak account to see the updated charts for temperature, humidity, and pressure.

Demonstration

Upload the provided code to your board, ensuring you have inserted your network credentials, Write API Key, and channel number. Once uploaded, the board should connect successfully and start sending readings.

Check your ThingSpeak account under the Private View tab to see the three charts displaying the sensor data.

Wrapping Up

In this tutorial, you learned how to publish readings from a BME280 sensor to ThingSpeak using the ESP32 and the thingspeak-arduino library. You can modify these examples to send readings from different sensors or data sources. We have tutorials available for many popular sensors:

Leave a Comment