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

Alex Stakhanov
Cloud4RPi
Published in
5 min readSep 6, 2019
DHT11, NodeMCU (ESP8266) board

Introduction

In the previous article, I connected my ESP8266-based NodeMCU board to a Cloud4RPi service. Now, it’s time for a real project!

Hardware requirements

Software and services

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 contains several libraries, from which I selected the most popular one.

According to their GitHub repository, 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. My project is called “MyNodeMCU”. The structure is shown below:

PIO project structure
PlatformIO Project Structure

This project is a slightly modified Cloud4RPi example.

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_PASSWORD=\"__YOUR_WIFI_PASS__\"
-D CLOUD4RPI_TOKEN=\"__YOUR_DEVICE_TOKEN__\"

Added libraries will be automatically installed into a project’s subfolder.

PlatformIO Library Dependencies

The main.cpp header looks as follows:

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <Cloud4RPi.h>
#include "DHT.h"

Step 3: Connect a DHT11 sensor

Adafruit provides a DHTtester.ino example of a sensor connection.

This code initializes a sensor and defines a structure to store the measurement result (in case it was successful):

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

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 page describes the library API, which is a set of methods used to:

-create, read and update variables,
-send variable 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 website (refer to the article’s part 1 for details).

#if defined(CLOUD4RPI_TOKEN)
Cloud4RPi c4r(CLOUD4RPI_TOKEN);
#else
Cloud4RPi c4r("!!!_NO_DEVICE_TOKEN_!!!");
#endif

Then, declare variables for DHT11 readings:

c4r.declareNumericVariable("DHT11_Temp");
c4r.declareNumericVariable("DHT11_Hum");

Then, get data from the sensor, save them into variables and publish the data to Cloud4RPi:

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:

c4r.declareDiagVariable("IP_Address");
c4r.declareDiagVariable("RSSI"); // WiFi signal strength
c4r.declareDiagVariable("Uptime");

Note: The millis function I use to obtain uptime resets to zero every ~50 days. Which is more than enough for my project.

The following code sets diagnostic variable values:

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 milliseconds to a convenient form:

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 site and notice the new device online. Open it to see all variable values received from the device: sensor and diagnostics.

Cloud4RPi Device Page

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:

Cloud4RPi Control Panel

The dashboard is shareable, so I instantly share it with my friend.

Conclusion

The full project’s code is available in the gist.

That’s all for now!

Questions and suggestions are welcome in the comments.

Bonus pics:

VSCode + PlatformIO Serial
NodeMCU and Cloud4RPi Control Panel

--

--