Stand with Ukraine flag
Try it now Pricing
Community Edition
ESP32 Pico Kit GPIO control and DHT22 sensor monitor using ThingsBoard Arduino SDK
Getting Started Documentation Devices Library Guides Installation Architecture API FAQ
On this page

ESP32 Pico Kit GPIO control and DHT22 sensor monitor using ThingsBoard Arduino SDK

Introduction

ThingsBoard is an open-source server-side platform that allows you to monitor and control IoT devices. It is free for both personal and commercial usage and you can deploy it anywhere. If this is your first experience with the platform we recommend to review what-is-thingsboard page and getting-started guide.

ESP32 is a series of low-cost, low-power system-on-a-chip microcontrollers with integrated self-contained Wi-Fi and dual-mode Bluetooth. ESP32 is a successor of ESP8266 chip.

This sample application will allow you to control GPIO of your ESP32 device using ThingsBoard web UI and display humidity/temperature data from DHT22 sensor. We will observe GPIO control using LEDs connected to the pins. The purpose of this application is to demonstrate ThingsBoard RPC capabilities and ThingsBoard Telemetry.

The application that is running on ESP32 is written using ThingsBoard Arduino SDK which is quite simple and easy to understand.

Current GPIO state and GPIO control widget is visualized using built-in customizable dashboard.

Once you complete this sample/tutorial, you will see your sensor data on the following dashboard.

image

List of hardware

image

image

  • 6 LEDs
  • 6 Resistors in range between 68Ω and 100Ω
  • Breadboard
  • Micro-USB cable

Wiring

DHT22 connection

Pin Connect to
DHT22 VCC Pico 5V
DHT22 DATA Pico 33

LEDs connection

Pin Connect to
LED1 Anode Pico 32 trough resistor (68Ω - 100Ω)
LED2 Anode Pico 26 trough resistor (68Ω - 100Ω)
LED3 Anode Pico 25 trough resistor (68Ω - 100Ω)
LED4 Anode Pico 19 trough resistor (68Ω - 100Ω)
LED5 Anode Pico 22 trough resistor (68Ω - 100Ω)
LED6 Anode Pico 21 trough resistor (68Ω - 100Ω)
All LEDs cathodes Pico Ground

Connection diagram

The following picture summarizes the connections for this project:

image

Device provisioning

This step contains instructions that are necessary to connect your device to ThingsBoard.

Open ThingsBoard Web UI (http://localhost:8080) in browser and login as tenant administrator. If you loaded the demo data during TB installation, the next credentials can be used:

  • login: tenant@thingsboard.org
  • password: tenant

Go to “Devices” section. Click “+” button and create a device with the name “ESP32 Pico Device”. Set “Device type” to “default”.

image

Once device created, open its details and click “Manage credentials”.

Copy auto-generated access token from the “Access token” field. Please save this device token. It will be referred to later as $ACCESS_TOKEN.

image

Provision your dashboard

Download the dashboard file using this link. Use import/export instructions to import the dashboard to your ThingsBoard instance.

Creating ESP32 firmware

Easiest way to program ESP32 Pico Kit is to use Arduino IDE. Following sections are describing that approach.

ESP32 and Arduino IDE setup

First you will need Arduino IDE and all related software installed.

Download and install Arduino IDE.

The Pico board support must be added to Arduino IDE before any program can be built and flashed into ESP32. To do so, install ESP32 package as described below:

  1. Open Arduino IDE.

  2. Open File -> Preferences menu, and add a board manager URLs

    1
    
    https://dl.espressif.com/dl/package_esp32_index.json,http://arduino.esp8266.com/stable/package_esp8266com_index.json
    

    into Additional Boards Manager URL field, as shown below:

    image

  3. Select Tools -> Board… -> Board manager menu.

  4. Enter ESP32 in the search field. Click Install

    image

Install Arduino ThingsBoard SDK

To simplify application development, install the ThingsBoard Arduino SDK and its dependencies from standard Arduino library repository:

  1. Proceed to Sketch -> Include Library… submenu. Select Manage Libraries.

  2. Find and install ThingsBoard Arduino SDK, PubSubClient by Nick O’Leary and ArduinoHttpClient libraries.

    image image image

  3. Install ArduinoJSON library v6.9.1 or higher. Avoid installing beta releases of the ArduinoJson library.

    image

From now on, you can use ThingsBoard SDK right from Arduino IDE.

Install ESP32 DHT22 driver

DHT22 sensor, connected to the ESP32 requires a special driver. To install it, proceed as follows:

  1. Click on “Sketch” menu. Open “Include Library…” submenu. Select “Manage Libraries”.

  2. Type “ESP DHT22” in the search field.

  3. Click install on “DHT22 Sensor Library for ESPx”, as shown below:

    image

Connect ESP32 Pico to PC

ESP32 Pico Kit does not require a sophisticated connection. Just plug micro-USB cable into PC and Pico, this should be enough.

Prepare and upload sketch

Download and open esp32-dht-gpio.ino sketch.

Note You need to edit following constants and variables in the sketch:

  • WIFI_AP - name of your access point
  • WIFI_PASSWORD - access point password
  • TOKEN - the $ACCESS_TOKEN from ThingsBoard configuration step.
  • THINGSBOARD_SERVER - ThingsBoard HOST/IP address that is accessible within your wifi network. Specify demo.thingsboard.io if you are using live demo server.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
#include <DHTesp.h>         // DHT for ESP32 library
#include <WiFi.h>           // WiFi control for ESP32
#include <ThingsBoard.h>    // ThingsBoard SDK

// Helper macro to calculate array size
#define COUNT_OF(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))

// WiFi access point
#define WIFI_AP_NAME        "WIFI_AP"
// WiFi password
#define WIFI_PASSWORD       "WIFI_PASSWORD"

// See https://thingsboard.io/docs/getting-started-guides/helloworld/ 
// to understand how to obtain an access token
#define TOKEN               "TOKEN"
// ThingsBoard server instance.
#define THINGSBOARD_SERVER  "demo.thingsboard.io"

// Baud rate for debug serial
#define SERIAL_DEBUG_BAUD    115200

// Initialize ThingsBoard client
WiFiClient espClient;
// Initialize ThingsBoard instance
ThingsBoard tb(espClient);
// the Wifi radio's status
int status = WL_IDLE_STATUS;

// Array with LEDs that should be lit up one by one
uint8_t leds_cycling[] = { 25, 26, 32 };
// Array with LEDs that should be controlled from ThingsBoard, one by one
uint8_t leds_control[] = { 19, 22, 21 };

// DHT object
DHTesp dht;
// ESP32 pin used to query DHT22
#define DHT_PIN 33

// Main application loop delay
int quant = 20;

// Initial period of LED cycling.
int led_delay = 1000;
// Period of sending a temperature/humidity data.
int send_delay = 2000;

// Time passed after LED was turned ON, milliseconds.
int led_passed = 0;
// Time passed after temperature/humidity data was sent, milliseconds.
int send_passed = 0;

// Set to true if application is subscribed for the RPC messages.
bool subscribed = false;
// LED number that is currenlty ON.
int current_led = 0;

// Processes function for RPC call "setValue"
// RPC_Data is a JSON variant, that can be queried using operator[]
// See https://arduinojson.org/v5/api/jsonvariant/subscript/ for more details
RPC_Response processDelayChange(const RPC_Data &data)
{
  Serial.println("Received the set delay RPC method");

  // Process data

  led_delay = data;

  Serial.print("Set new delay: ");
  Serial.println(led_delay);

  return RPC_Response(NULL, led_delay);
}

// Processes function for RPC call "getValue"
// RPC_Data is a JSON variant, that can be queried using operator[]
// See https://arduinojson.org/v5/api/jsonvariant/subscript/ for more details
RPC_Response processGetDelay(const RPC_Data &data)
{
  Serial.println("Received the get value method");

  return RPC_Response(NULL, led_delay);
}

// Processes function for RPC call "setGpioStatus"
// RPC_Data is a JSON variant, that can be queried using operator[]
// See https://arduinojson.org/v5/api/jsonvariant/subscript/ for more details
RPC_Response processSetGpioState(const RPC_Data &data)
{
  Serial.println("Received the set GPIO RPC method");

  int pin = data["pin"];
  bool enabled = data["enabled"];

  if (pin < COUNT_OF(leds_control)) {
    Serial.print("Setting LED ");
    Serial.print(pin);
    Serial.print(" to state ");
    Serial.println(enabled);

    digitalWrite(leds_control[pin], enabled);
  }

  return RPC_Response(data["pin"], (bool)data["enabled"]);
}

// RPC handlers
RPC_Callback callbacks[] = {
  { "setValue",         processDelayChange },
  { "getValue",         processGetDelay },
  { "setGpioStatus",    processSetGpioState },
};

// Setup an application
void setup() {
  // Initialize serial for debugging
  Serial.begin(SERIAL_DEBUG_BAUD);
  WiFi.begin(WIFI_AP_NAME, WIFI_PASSWORD);
  InitWiFi();

  // Pinconfig

  for (size_t i = 0; i < COUNT_OF(leds_cycling); ++i) {
    pinMode(leds_cycling[i], OUTPUT);
  }

  for (size_t i = 0; i < COUNT_OF(leds_control); ++i) {
    pinMode(leds_control[i], OUTPUT);
  }

  // Initialize temperature sensor
  dht.setup(DHT_PIN, DHTesp::DHT22);
}

// Main application loop
void loop() {
  delay(quant);

  led_passed += quant;
  send_passed += quant;

  // Check if next LED should be lit up
  if (led_passed > led_delay) {
    // Turn off current LED
    digitalWrite(leds_cycling[current_led], LOW);
    led_passed = 0;
    current_led = current_led >= 2 ? 0 : (current_led + 1);
    // Turn on next LED in a row
    digitalWrite(leds_cycling[current_led], HIGH);
  }

  // Reconnect to WiFi, if needed
  if (WiFi.status() != WL_CONNECTED) {
    reconnect();
    return;
  }

  // Reconnect to ThingsBoard, if needed
  if (!tb.connected()) {
    subscribed = false;

    // Connect to the ThingsBoard
    Serial.print("Connecting to: ");
    Serial.print(THINGSBOARD_SERVER);
    Serial.print(" with token ");
    Serial.println(TOKEN);
    if (!tb.connect(THINGSBOARD_SERVER, TOKEN)) {
      Serial.println("Failed to connect");
      return;
    }
  }

  // Subscribe for RPC, if needed
  if (!subscribed) {
    Serial.println("Subscribing for RPC...");

    // Perform a subscription. All consequent data processing will happen in
    // callbacks as denoted by callbacks[] array.
    if (!tb.RPC_Subscribe(callbacks, COUNT_OF(callbacks))) {
      Serial.println("Failed to subscribe for RPC");
      return;
    }

    Serial.println("Subscribe done");
    subscribed = true;
  }

  // Check if it is a time to send DHT22 temperature and humidity
  if (send_passed > send_delay) {
    Serial.println("Sending data...");

    // Uploads new telemetry to ThingsBoard using MQTT. 
    // See https://thingsboard.io/docs/reference/mqtt-api/#telemetry-upload-api 
    // for more details

    TempAndHumidity lastValues = dht.getTempAndHumidity();    
    if (isnan(lastValues.humidity) || isnan(lastValues.temperature)) {
      Serial.println("Failed to read from DHT sensor!");
    } else {
      tb.sendTelemetryFloat("temperature", lastValues.temperature);
      tb.sendTelemetryFloat("humidity", lastValues.humidity);
    }

    send_passed = 0;
  }

  // Process messages
  tb.loop();
}

void InitWiFi()
{
  Serial.println("Connecting to AP ...");
  // attempt to connect to WiFi network

  WiFi.begin(WIFI_AP_NAME, WIFI_PASSWORD);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("Connected to AP");
}

void reconnect() {
  // Loop until we're reconnected
  status = WiFi.status();
  if ( status != WL_CONNECTED) {
    WiFi.begin(WIFI_AP_NAME, WIFI_PASSWORD);
    while (WiFi.status() != WL_CONNECTED) {
      delay(500);
      Serial.print(".");
    }
    Serial.println("Connected to AP");
  }
}

Troubleshooting

In order to to perform troubleshooting, you must check ESP32 Pico logs. For that, simply open Serial Monitor in the Arduino IDE.

Data visualization and GPIO control

Finally, open ThingsBoard Web UI. You can access this dashboard by logging in as a tenant administrator.

In case of local installation (if the demo data was added during TB installation):

  • login: tenant@thingsboard.org
  • password: tenant

In case of live-demo server:

  • login: your live-demo username (email)
  • password: your live-demo password

See live-demo page for more details how to get your account.

Go to “Devices” section and locate “ESP32 Pico Device”, open device details and switch to “Latest telemetry” tab. If all is configured correctly you should be able to see latest values of “temperature” and “humidity” in the table.

image

After, open “Dashboards” section then locate and open “ESP32 Pico Dashboard”. As a result, you will see a time-series chart displaying temperature and humidity level (similar to dashboard image in the introduction).

You should also observe a GPIO control for your device. It consists of two widgets: one is for controlling LED blink speed (in milliseconds) and second for turning individual LEDs on and off.

You can switch status of GPIOs using control panel. As a result, you will see LEDs status change on the device. To control LED blink speed, simply turn a knob and observe a speed change.

See also

Browse other samples or explore guides related to main ThingsBoard features:

Your feedback

Don’t hesitate to star ThingsBoard on github to help us spread the word. If you have any questions about this sample - post it on the issues.

Next steps