DHT22 an ESP8622 + MQTT

Der DHT22 ist ein günstiger Sensor zur Messung der Temperatur und der Luftfeuchte. Dieser ist baugleich zum AM2302.
Der Sensor kann sowohl mit 3.3V als auch mit 5V betrieben werden. Also Ideal für gängige Microcontrollerplattformen wie Arduino, Rapsberry Pi, STM32 und weitere.
Der Anschluss ist wirklich simpel, Spannung, Masse und Signal. Der Datenaustausch erfolgt über einen Single-Bus, als seriell.

Technische Daten:

  • Digital Temperatur und Luftfeuchtigkeit ermitteln
  • DHT22 / AM2302
  • Betriebsspannung: DC 3.3-5.5V
  • Luftfeuchtigkeitsmessbereich : 0 bis 100% relative Luftfeuchte
  • Feuchtemessgenauigkeit: ±2% RH
  • Temperaturbereich: -40 bis +80 C
  • Temperaturmessgenauigkeit ±0.5
  • Single-Bus – Digitalsignalausgang, bidirektionale serielle Daten
  • Maße: 28mm x 12mm x 10mm

In meinem Beispiel habe ich den DHT22 an den ESP3266 angeschlossen. Dazu habe ich VCC and 3.3V angeschlossen, GND an GND und Data an den Pin D6 des Microcontrollers.

Im Endeffekt wird der DHT22 ausgelesen und die Werte an das Display geschrieben. Zusätzlich werden die Informationen per MQTT übertragen.
Das passende Codesnippet sieht wie folgt aus

/***************************************************
  This code uses the ESP8266 Kit8 with the following functionality
  @li [in] DHT22
  @li [out] some information at the display by I2C
  @li [out] MQTT
  @author Andreas Amann (quick and dirty)
 ****************************************************/
#include <ESP8266WiFi.h>
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"

/*************************  Display stuff *********************************/
#include <Arduino.h>
#include <U8g2lib.h>

#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif

U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ 16, /* clock=*/ 5, /* data=*/ 4);

/*************************  DHT22 *********************************/
#include "DHT.h"

#define DHTPIN 12     // Digital pin connected to the DHT sensor
// Feather HUZZAH ESP8266 note: use pins 3, 4, 5, 12, 13 or 14 --
// Pin 15 can work but DHT must be disconnected during program upload.

//#define DHTTYPE DHT11   // DHT 11
#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321
//#define DHTTYPE DHT21   // DHT 21 (AM2301)

// Initialize DHT sensor.
// Note that older versions of this library took an optional third parameter to
// tweak the timings for faster processors.  This parameter is no longer needed
// as the current DHT reading algorithm adjusts itself to work on faster procs.
DHT dht(DHTPIN, DHTTYPE);

char strTmp[8]; // Buffer big enough for 7-character float

/************************* WiFi Access Point *********************************/
#define WLAN_SSID       "MYSSID"
#define WLAN_PASS       "123412341234"

/************************* Adafruit.io Setup *********************************/
#define AIO_SERVER      "192.168.180.101"
#define AIO_SERVERPORT  1883                   // use 8883 for SSL
#define AIO_USERNAME ""
#define AIO_KEY ""
//#define AIO_USERNAME    "...your AIO username (see https://accounts.adafruit.com)..."
//#define AIO_KEY         "...your AIO key..."

/************ Global State (you don't need to change this!) ******************/
// Create an ESP8266 WiFiClient class to connect to the MQTT server.
WiFiClient client;
// or... use WiFiFlientSecure for SSL
//WiFiClientSecure client;

// Setup the MQTT client class by passing in the WiFi client and MQTT server and login details.
// Notice MQTT paths for AIO follow the form: <username>/feeds/<feedname>
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);
Adafruit_MQTT_Publish pub_humidity = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/uc/humidity");
Adafruit_MQTT_Publish pub_temperature = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/uc/temp");

/*************************** Sketch Code ************************************/
void MQTT_connect();

/****************************************************************************/
void setup() 
{
  Serial.begin(115200);
  delay(10);

  Serial.println(F("Adafruit MQTT demo"));

  // Connect to WiFi access point.
  Serial.println(); 
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(WLAN_SSID);

  WiFi.begin(WLAN_SSID, WLAN_PASS);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println();
  Serial.println("WiFi connected");
  Serial.println("IP address: "); Serial.println(WiFi.localIP());

  // init display
  u8g2.begin();
  
  // init sensor
  dht.begin();

  // sendout message
  Serial.println(F("DHTxx test!"));
}

/************ ugly global variable *************************************/
uint32_t x=0;

/************** read out humidity and log messages ********************/
float GetHumidity()
{
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();

  // Check if any reads failed and exit early (to try again).
  if (isnan(h)) 
  {
    Serial.println(F("Failed to read from DHT sensor!"));
  }

  return h;
}

/************ read out temperatur and log messages *********************/
float GetTemperature()
{
  // Read temperature as Celsius (the default)
  float t = dht.readTemperature();

  // Check if any reads failed and exit early (to try again).
  if (isnan(t)) {
    Serial.println(F("Failed to read from DHT sensor!"));
  }

  return t;
}

/************** display provided values ***************************/
void DisplayValues(float t, float h)
{
   // printout to display
  u8g2.clearBuffer();          // clear the internal memory
  u8g2.setFont(u8g2_font_ncenB08_tr); // choose a suitable font
  u8g2.drawStr(0,10,"Humidity [%]: ");  // write something to the internal memory
  dtostrf(h, 6, 2, strTmp); // Leave room for too large numbers!
  u8g2.drawStr(90,10,strTmp);  // write something to the internal memory
  
  u8g2.drawStr(0,25,"Temperature [C°]: ");  // write something to the internal memory
  dtostrf(t, 6, 2, strTmp); // Leave room for too large numbers!
  u8g2.drawStr(90,25,strTmp);  // write something to the internal memory
  //u8g2.drawStr(0,31,"Heat index");  // write something to the internal memory
  u8g2.sendBuffer();          // transfer internal memory to the display
}

/******** send out data by MQTT *********************************/
void PublishTemperature(float t)
{
  if (! pub_temperature.publish(t)) 
  {
    Serial.println(F("Failed(__LINE__)"));
  } 
}

/******** send out data by MQTT *********************************/
void PublishHumidity(float h)
{
  if (! pub_humidity.publish(h)) 
  {
    Serial.println(F("Failed(__LINE__)"));
  } 
}

/************ loop **********************************************/
void loop() 
{
  // Ensure the connection to the MQTT server is alive (this will make the first
  // connection and automatically reconnect when disconnected).  See the MQTT_connect
  // function definition further below.
  MQTT_connect();

 const float t = GetTemperature();
 const float h = GetHumidity();
 PublishTemperature(t);
 PublishHumidity(h);
 DisplayValues(t,h);

  // ping the server to keep the mqtt connection alive
  // NOT required if you are publishing once every KEEPALIVE seconds
  /*
  if(! mqtt.ping()) {
    mqtt.disconnect();
  }
  */
}

// Function to connect and reconnect as necessary to the MQTT server.
// Should be called in the loop function and it will take care if connecting.
void MQTT_connect() 
{
  int8_t ret;

  // Stop if already connected.
  if (mqtt.connected()) 
  {
    return;
  }

  Serial.print("Connecting to MQTT... ");

  uint8_t retries = 3;
  while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected
       Serial.println(mqtt.connectErrorString(ret));
       Serial.println("Retrying MQTT connection in 5 seconds...");
       mqtt.disconnect();
       delay(5000);  // wait 5 seconds
       retries--;
       if (retries == 0) {
         // basically die and wait for WDT to reset me
         while (1);
       }
  }
  Serial.println("MQTT Connected!");
}