WeMos D1 R1 Temperature/Humidity measure with DHT11 sensor

Here I propose two different programs how to handle sensors and more specific the DHT11-sensor for measuring Temperature/Humidity.

  • Temperature/Humidity with the DHT11 Sketch based on the Arduino Uno
  • Same but now for Asynchronous Webserver – OTA based on the WeMos D1 R1

Temperature/Humidity with the DHT11
A nice sensor has been developed for measuring the temperature and relative humidity – the DHT11. The protocoll that the DHT11 sensor uses is weird. It sends, after a very short pulse, very rapidly a serie of bits. That means after a short LOW pulse it will sends a 5-byte packet.
As each byte is 8 bits the packet is 5B * 8bit/B = 40 bits long.
To show how it works I present here a Arduino Uno program based on the program published in the book “Make Sensors”, Maker Media, ISBN: 987-1-449-36810-4, a very fine book to use. For this experiment I used the program “DHT11 Code and Connection for Arduino” It shows how to handle the weird protocoll of the DHT11 sensor.
Be aware! On internet you will find some wrong connection examples for the DHT11. For sure the connections show above works fine.

DHT11 Three and Four pin type

For more information about the DHT sensors family look here.

/**********************************************************************************
*                                   PA3BYB
*                 temperature/humidity with the DHT11 versie 0.1
*                          Based on the Arduino Uno
* 
* Based on Book "Make Sensors" by Tero Karvinnen, Kimmo Karvinnen, Ville Valtokari
***********************************************************************************/

const int dataPin = 8;    // GPIO connection Arduino with the DHT11 data pin

int temperature = -0;     // 
int humidity = -1;        //

int readDHT11(){
uint8_t recvBuffer[5]; // The packet from DHT11 is 5 bytes (40 bits) lenght
uint8_t cnt = 7;
uint8_t idx = 0;
for(int i = 0; i < 5; i++) recvBuffer[i] = 0; // Init the buffer with zero's

/////////////////////// Start communication with LOW pulse  //////////////////////
pinMode(dataPin, OUTPUT);
digitalWrite(dataPin, LOW);
delay(10);                    // Need time to switch
digitalWrite(dataPin, HIGH);  

delayMicroseconds(40); // Receive the DHT11 response Signal
pinMode(dataPin, INPUT);
pulseIn(dataPin, HIGH); // Receive the DHT11 response Signal

//////////////////////// Read data packet /////////////////////////////
unsigned int timeout = 10000;     // loop iteration
for (int i=0; i<40; i++){         // For each of the 40 bits, perform the operation
                                  // inside curly btaces
timeout = 10000;
while(digitalRead(dataPin) == LOW) {
if (timeout == 0) return -1;
timeout--; 
}

unsigned long t = micros();       // Uptme in microsec.; stored to mesure the 
                                  //duration of the pulse
timeout = 10000;
while(digitalRead(dataPin) == HIGH) {       // Measure the pulse with a loop
if (timeout == 0) return -1;
timeout--;
}

if ((micros() - t) > 40) recvBuffer[idx] |= (1 << cnt); 
  /* If the pulse was longer then 40 micro sec. it was a 1. Otherwise, that bit 
  * is left as its initialized value, 0. To toggle the corresponding bit in the
  * corresponding byte, a new number is created with bit shifting (eg 1<<2 ==
  * 0b100). This bit is then combined with the previousbyte value using a 
  * bitwise inplace OR. So if the value was already a 1, it's says set at 1.
  * If it was zero, but the new number (0b00) was 1, then this sets it to 1.
  * See bitwise operation on page 221 from the book for more details */

if (cnt == 0) {                      // next byte?
cnt = 7; // restart at MSB
idx++; // next byte!
}
else cnt--;
}

humidity = recvBuffer[0];           // % Hunidity is the first byte of the 
                                    // recieved package
temperature = recvBuffer[2];        // C
uint8_t sum = recvBuffer[0] + recvBuffer[2];
if(recvBuffer[4] != sum) return -2; // The checksum (byte 4) is the sum of 
                                    // humidity and temperature
return 0;
}

void setup() {
Serial.begin(115200);
}

void loop() {
int ret = readDHT11();
if(ret != 0) Serial.println(ret);
Serial.print("Humidity: "); Serial.print(humidity); Serial.println(" %");
Serial.print("Temperature: "); Serial.print(temperature); Serial.println(" C");
delay(2000);                         // mSec.
}

Asynchronous Webserver – OTA based
Do you ever struggle to present real-time data on a website, for example the measured value of a sensor? Then this project may be an idea for you.
I present a sketch that is written on the WeMos board family, but it will work on every ESP8266 based board. This experiment is based on an example Sketch of Rui Santos, namely measuring temperature and humidity.

The Advantage of the project:

  • Over The Air (OTA) programmable. It means no usb-connection needed for reprogramming the board.
  • Two different files incorporated : wifisecrets.h and index_html.h It makes the program more well-arranged. The wifisecrets.h file contain the WiFi-ID and WiFi-Password. It make the OTA connection more save for intercepting over the air data.
  • The website works asynchrone with means no man’s handle is necessary for new result presented on the website. The website take of itselfs for this. It was for me the main goal for this project, to study how asynchrone website works.

There is a another interesting part of the WeMos boards, and more specific the GPIO pins.
Above you wil find the differents between the models R1 and R2 form the WeMoS D1 boards. As you can see the most important port been switch.

 

Above gives they differens between GPIO pin-numbers, as used in the sketch, and the pin-number you will find on the boards. This is the result of the placement of the ESP8266 module on the different boards, such as the WEMOS. Because you are programming the ESP8266, you also have to use the GPIO-pins of the module in your sketch and not the names from the board such as those arranged on the board.

 

/**********************************************************************************
*                                   PA3BYB
*                       temperature/humidity versie 0.1
***********************************************************************************
* Asynchronous Webserver - OTA based - HTML page
* 
* DATA 2022 04 07 version 0.1 - Mesure Temperature/Humidity presented in WebPage
*
* Based on idea of Rui Santos
*********************************************************************************** 
* Don't use from the ESP8266 GPIO 6,7,8,9,10 & 11. These ports are used for flasing
* the EEprom. 
* 
* Don't use USB-UART in same time as RX-D0 en TX-D1 / Level conflict
* 
* Not all port can be used in this program. Only the ports D2, D4 and D12 are
* useable.
* 
**********************************************************************************
* Sketch uses 332053 bytes (31%) of program storage space. Maximum is 1044464 bytes.
* Global variables use 31068 bytes (37% of dynamic memory. Maximum is 81920 bytes.
*
**********************************************************************************/

#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#include <Hash.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <secretswifi.h>
#include "index_html.h"

#define OTA_Host_Name "WeMosD1-OTA-DSMRa-"

#define DHTPIN 3        // Define the GPIO3 (WeMos D1 R1 pin D0) the DHT-data pin 
                        // connected to

// Uncomment the type of sensor in use:
#define DHTTYPE DHT11 // DHT 11
//#define DHTTYPE DHT22 // DHT 22 (AM2302)
//#define DHTTYPE DHT21 // DHT 21 (AM2301)

DHT dht(DHTPIN, DHTTYPE);        // Instantiate a DHTobject with the type and pin 
                                 // defined earlier

// current temperature & humidity, updated in loop()
float t = 0.0;
float h = 0.0;

AsyncWebServer server (80);

unsigned long previousMillis = 0;    // will store last time DHT was updated

const long interval = 5000;          // Updates DHT readings every 10 seconds

const int ledPin = LED_BUILTIN;

// create the processor() function, that will replace the placeholders in our 
// HTML text with the actual temperature and humidity values.
String processor(const String& var){      // Replaces placeholder with DHT values
Serial.println(var);
if(var == "TEMPERATURE"){
return String(t);
}
else if(var == "HUMIDITY"){
return String(h);
}
return String();
}


/************************ Start WIFI Connect *************************************/
void StartWifiConnect(){
if(WiFi.getMode() != WIFI_STA){ // Check WiFi mode
WiFi.mode(WIFI_STA);
delay(500);
}

Serial.println("\n Start connection WiFi: ");
WiFi.begin(ssidsta,passwordsta);
while(WiFi.status()!= WL_CONNECTED){ // Connect to WiFi
delay(500);
Serial.print(".");
}

Serial.println("\n WiFi connect");

if(WiFi.status() == WL_CONNECTED) {
Serial.print("IP adress : "); // Connect to IP-adress
Serial.println(WiFi.localIP());
} else {
Serial.println("Cannot connect WiFi...");
}

if (MDNS.begin("esp8266")) { // StarUp mDNS responder
Serial.println("MDNS responder started");
} else {
Serial.println("Error setting up MDNS responder!");
}
}

/**************************** WebPage Not Found *********************************/
void notFound(AsyncWebServerRequest *request) {
request->send(404, "text/plain", "Page Not found");
}

/*******************************Blinck Led ***************************************/
void Blinck(){
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, HIGH);
delay(1000);
digitalWrite(ledPin, LOW);
}

/********************************* SetUp *****************************************/
void setup() {
Serial.begin(115200);
delay(500);                            // Wait for startup serial monitor

Blinck();

StartWifiConnect();

ArduinoOTA.setHostname(OTA_Host_Name); // OTA Hostname
ArduinoOTA.begin();                    // Start OTA

Serial.println(WiFi.localIP());        // Print ESP8266 Local IP Address

// When we make a request on the root URL, we send the HTML text that is stored 
// on the index_html variable. We also need to pass the processorfunction, that 
// will replace all the placeholders with the right values.
// Route for root / web page
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", index_html, processor);
});
server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", String(t).c_str());
});
server.on("/humidity", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", String(h).c_str());
});

server.begin(); // Start server
}

/********************************* LOOP ******************************************/
void loop() {
ArduinoOTA.handle();

unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
     // save the last time you updated the DHT values
previousMillis = currentMillis;
     // Read temperature as Celsius (the default)
float newT = dht.readTemperature();
Serial.println("readTemperature");
    // Read temperature as Fahrenheit (isFahrenheit = true)
    // float newT = dht.readTemperature(true);
    // if temperature read failed, don't change t value
if (isnan(newT)) {
Serial.println("Failed to read from DHT sensor!");
}
else {
t = newT;
Serial.println(t);
}
    // Read Humidity
float newH = dht.readHumidity();
Serial.println("readHumidity");
    // if humidity read failed, don't change h value 
if (isnan(newH)) {
Serial.println("Failed to read from DHT sensor!");
}
else {
h = newH;
Serial.println(h);
}
}
}

 

The file secretswifi.h

#indef STASSID
#define STASSID = "your ID"
#define STAPSK = "Your password"
#endif

const char* ssidsta = STASSID;
const char* passwordsta = STAPS;

File index_html.h
This sketch build the website and have small java-servlet for updating the website with new information if avialable. It is given as a .zip file – index_html.zip