Connecting a DHT11 sensor to the cloud with an ESP8266-based board
====

## Introduction
In the [previous article](https://medium.com/cloud4rpi/connecting-an-esp8266-based-module-to-the-cloud-using-arduino-f0f82aee185b), I connected my ESP8266-based [NodeMCU](https://en.wikipedia.org/wiki/NodeMCU) board to a [Cloud4RPi](https://cloud4rpi.io/) service. Now, it's time for a real project!
## Hardware requirements
* Any board based on an [ESP8266 chip](https://en.wikipedia.org/wiki/ESP8266) (for instance, [NodeMCU](https://en.wikipedia.org/wiki/NodeMCU))
* A [DHT11 or DHT22](https://learn.adafruit.com/dht) sensor
## Software and services
* [DHT sensor library by Adafruit](https://platformio.org/lib/show/19/DHT%20sensor%20library) - v1.3.7
* [Adafruit Unified Sensor](https://platformio.org/lib/show/31/Adafruit%20Unified%20Sensor) - v1.0.3
* [cloud4rpi-esp-arduino](https://platformio.org/lib/show/2045/cloud4rpi-esp-arduino/) - v0.1.0
* [Cloud4RPI - Cloud control panel for IoT devices](https://cloud4rpi.io/)
* [PlatformIO IDE for VSCode](https://platformio.org/install/ide?install=vscode)
## Goal: Measure temperature and humidity
I already had a DHT11 sensor, so I decided to use it for temperature and humidity measurements. Let's choose an Arduino library to read sensor data.
[Arduino registry](https://platformio.org/lib/search?query=dht11) contains several libraries, from which I selected [the most popular one](https://platformio.org/lib/show/19/DHT%20sensor%20library).
According to their [GitHub repository](https://github.com/adafruit/DHT-sensor-library), we are also required to add an Adafruit Unified Sensor package.
## Step 1: Create and configure project
I already described how to create a PlatformIO project and install libraries in the [first part](https://medium.com/cloud4rpi/connecting-an-esp8266-based-module-to-the-cloud-using-arduino-f0f82aee185b). My project is called "MyNodeMCU". The structure is shown below:

This project is a slightly modified [Cloud4RPi example](https://platformio.org/lib/show/2045/cloud4rpi-esp-arduino/examples).
I decided to store the device token and Wi-Fi credentials in the configuration file instead of code.
The `platform.io` file looks as follows:
```
[platformio]
default_envs = nodemcuv2
[env:nodemcuv2]
platform = espressif8266
framework = arduino
board = nodemcuv2
```
## Step 2: Install libraries
Libraries installation is quite simple. You can do it from the IDE's graphical interface, or by adding required library names to the `lib_deps` section of the `platform.io` file:
```
; ...
lib_deps =
cloud4rpi-esp-arduino
Adafruit Unified Sensor
DHT sensor library
build_flags =
-D MQTT_MAX_PACKET_SIZE=1024
-D MQTT_MAX_TRANSFER_SIZE=128
-D CLOUD4RPI_DEBUG=0
-D SSID_NAME=\"__YOUR_WIFI__\"
-D SSID_PASWORD=\"__YOUR_WIFI_PASS__\"
-D CLOUD4RPI_TOKEN=\"__YOUR_DEVICE_TOKEN__\"
```
Added libraries will be automatically installed into a project's subfolder.

The `main.cpp` header looks as follows:
```c
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <Cloud4RPi.h>
#include "DHT.h"
```
## Step 3: Connect a DHT11 sensor
Adafruit provides a `DHTtester.ino` [example](https://platformio.org/lib/show/19/DHT%20sensor%20library) of a sensor connection.
This code initializes a sensor and defines a structure to store the measurement result (in case it was successful):
```c
#define DHTPIN 2 // Digital pin connected to the DHT sensor
#define DHTTYPE DHT11 // DHT 11
// ...
DHT dht(DHTPIN, DHTTYPE);
dht.begin();
// ...
struct DHT_Result {
float h;
float t;
};
DHT_Result dhtResult;
```
The next function shows how to read sensor data and store it in the data structure described above.
```c
void readSensors() {
float h = dht.readHumidity();
// Read temperature as Celsius (the default)
float t = dht.readTemperature();
// Check if any reads failed and exit early (to try again).
if (isnan(h) || isnan(t)) {
Serial.println(F("Failed to read from DHT sensor!"));
return;
}
dhtResult.h = h;
dhtResult.t = t;
}
```
## Step 4: Sending data to the cloud
Once we have that data, the next step is to send it to the Cloud4RPi service.
The [Cloud4RPi for Arduino](https://docs.cloud4rpi.io/start/esp-pio/) page describes the library API, which is a set of methods used to:
-create, read and update variables,
-send veriable values into the cloud using the MQTT protocol.
The library supports three variable types: **Bool**, **Numeric**, and **String**.
The library workflow starts with creating an API instance using the Device Token from the [cloud4rpi.io](https://cloud4rpi.io) website (refer to the [article's part 1](https://medium.com/cloud4rpi/connecting-an-esp8266-based-module-to-the-cloud-using-arduino-f0f82aee185b) for details).
```c
#if defined(CLOUD4RPI_TOKEN)
Cloud4RPi c4r(CLOUD4RPI_TOKEN);
#else
Cloud4RPi c4r("!!!_NO_DEVICE_TOKEN_!!!");
#endif
```
Then, declare variables for DHT11 readings:
```c
c4r.declareNumericVariable("DHT11_Temp");
c4r.declareNumericVariable("DHT11_Hum");
```
Then, get data from the sensor, save them into variables and publish the data to Cloud4RPi:
```c
c4r.setVariable("DHT11_Temp", dhtResult.t);
c4r.setVariable("DHT11_Hum", dhtResult.h);
c4r.publishData();
```
Temperature and humidity does not change quickly, so sending more than one value per 5 minutes is not required.
## Step 5: Diagnostics
Cloud4RPi supports diagnostic data along with variable values. I used uptime, Wi-Fi signal strength, and IP address as diagnostic data:
```c
c4r.declareDiagVariable("IP_Address");
c4r.declareDiagVariable("RSSI"); // WiFi signal strength
c4r.declareDiagVariable("Uptime");
```
Note: The `mils` function I use to obtain uptime resets to zero every ~50 days. This is more than enough for my project.
The following code sets diagnostic variable values:
```c
c4r.setDiagVariable("RSSI", (String)WiFi.RSSI() + " dBm");
c4r.setDiagVariable("IP_Address", WiFi.localIP().toString());
c4r.setDiagVariable("Uptime", uptimeHumanReadable(currentMillis));
c4r.publishDiag();
```
The `uptimeHumanReadable` function converts miliseconds to a convenient form:
```c
String uptimeHumanReadable(unsigned long milliseconds) {
static char uptimeStr[32];
unsigned long secs = milliseconds / 1000;
unsigned long mins = secs / 60;
unsigned int hours = mins / 60;
unsigned int days = hours / 24;
secs -= mins * 60;
mins -= hours * 60;
hours -= days * 24;
sprintf(uptimeStr,"%d days %2.2d:%2.2d:%2.2d", (byte)days, (byte)hours, (byte)mins, (byte)secs);
return String(uptimeStr);
}
```
The function outputs a string like this `5 days 10:23:14` instead of a strange big number.
## Step 6: Start and debug the project
After compiling the created code and flashing it into NodeMCU, the device connects to a cloud service and starts sending data.
You can increase logging verbosity by setting the `CLOUD4RPI_DEBUG` preprocessor variable to `1` (add `-D CLOUD4RPI_DEBUG=1` to `build_flags` section in `platform.io` file).
Next, open the [cloud4rpi.io](https://cloud4rpi.io/devices) site and notice the new device online. Open it to see all variable values received from the device: sensor and diagnostics.

## Step 7: Dashboard configuration
At this step, the data connection to the cloud is operational. Now, let's configure the visual representation of the data.
I used the Dashboard configuration UI to create the following dashboard:

The dashboard is sharable, so I instantly share it with my friend.
## Conclusion
The full project's code is available [in gist](https://gist.github.com/sky3d/1264a8f22f7880d9ff471376392e5998)
That's all for now!
Questions and suggestions are welcome in the comments.
## Bonus pics:

VSCode + PlatformIO Serial

Working NodeMCU and Cloud4RPi control panel
{"metaMigratedAt":"2023-06-14T23:39:46.420Z","metaMigratedFrom":"Content","title":"Connecting a DHT11 sensor to the cloud with an ESP8266-based board","breaks":true,"contributors":"[{\"id\":\"5874e258-71fc-40da-8cad-f926475fd9c8\",\"add\":9007,\"del\":889},{\"id\":null,\"add\":212,\"del\":172}]"}