Adding a DHT22 temperature and humidity sensor to the Sonoff

I want more…

Just a few days ago I replaced the firmware on my Sonoff, and immediately after, I wanted more…

After looking on their website, I found a version which also had a DHT11 sensor attached, and I then wanted to do something similar, just with a DHT22 for higher resolution (0.1C on a DHT22, compared to 1C on a DHT11). After digging a bit more in the schematic for the Sonoff, I found that the last pin on the 1×5 pinheader, was connected to GPIO14, so it should not be that difficult to get up and running.

Let’s do this!

The first thing I did, was to just put the DHT22 on a breadboard, and test it all there, and surprisingly enough, it worked the first time!
2016-05-24 20.30.35

Well, okay… I might have cheated a bit, by using the NodeMCU development board first, and get all the coding done and tested, before uploading it to the ESP8266 in the Sonoff…

Next I mounted the DHT22 to the side of the box, beware, you don’t have much free space on the side where the power supply is. Instead mount it on the side with the relay. Here I have put a screw in just above the relay, so I can drill holes at the other end, and easily have them clear the relay too.

2016-05-24 20.50.52

Here the wires for the DHT22 have been soldered to the pin header, one for 3V3, one for GND, and the last for the data coming from the sensor.

2016-05-24 21.08.16

Don’t make the wires too long, or the case will be difficult to close, and they would be at bigger risk of getting close to things they should not come close of.

When closing the case, make the wires bend out towards the led, to keep them away from the other components inside the box.

2016-05-24 21.08.42

Closing words

After having had a go at replacing the firmware on the Sonoff, and adding a temperature and humidity sensor, I am generally pleased with how the device is put together, and the choice of parts, but… As you probably noticed, I got the mains in and mains out soldered directly to the board. I had to do this because after tightening and losenig the screws in the terminals a few times, the thread simply started to fail, and made it impossible to tighten them. The entire body of the connectors were also twisting quite badly when tightening the screws, which is a problem I have found with quite a lot of products.

In my first projects, I used similar terminals, but after having those fail, I went searching for alternatives, and found some very good ones. They are slightly bigger, and instead of having a screw pressing down on a thin metal plate, they lift a little metal bar up, which holds the wires very firmly in, and will hold up to a lot more use.

But still, for the price of this thing, it is still very good value, with a lot of uses once you made it 100% your own.

2016-05-24 21.13.19

#include <MQTTClient.h>
#include <ESP8266WiFi.h>
#include <DHT.h>


#define WLAN_SSID       "SSID"
#define WLAN_PASS       "WPA-PSK"


const char* server = "192.168.1.69"; // server or URL of MQTT broker
String clientName = "Sonoff-"; // just a name used to talk to MQTT broker


const float avgForce = 10.0;  // Force of which the averaging function is using to affect the reading
const float avgSkip = 0.5; // Skip the averaging function if the reading difference is bigger than this since last reading


char* tempTopic = "/Sonoff/dht/Temperature"; //topic to publish temperatures readings to
char* humiTopic = "/Sonoff/dht/Humidity"; // publish humidity readings


#define DHTTYPE DHT22 // DHT11 or DHT22
#define DHTPIN  14


unsigned long dhtLast = 0;
#define dhtInterval 2000 //(ms) - 2 seconds between reading
DHT dht(DHTPIN, DHTTYPE, 11);
float avgHumidity, mqttPublishHumi, avgTemperature, mqttPublishTemp;

char charVal[10];               //temporarily holds data from vals

unsigned long postLast = 0;
const int postInterval = 60000; // Post every minute


WiFiClient wifiClient;
MQTTClient client;

char message_buff[100];
bool mqttSync = false;

String macToStr(const uint8_t* mac)
{
  String result;
  for (int i = 0; i < 6; ++i)
  {
    result += String(mac[i], 16);
    if (i < 5)
      result += ':';
  }
  return result;
}


void setup()
{
  Serial.begin(9600);
  Serial.println();

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

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

  dht.begin();
  Serial.println("Delaying startup to allow DHT sensor to be started properly...");
  delay(1000);

  uint8_t mac[6];
  WiFi.macAddress(mac);
  clientName += macToStr(mac);
  clientName += "-";
  clientName += String(micros() & 0xff, 16);

  client.begin(server, wifiClient);
  Serial.print("Connecting to ");
  Serial.print(server);
  Serial.print(" as ");
  Serial.println(clientName);

  if (client.connect((char*) clientName.c_str()))
  {
    Serial.println("Connected to MQTT broker");
  }
  else
  {
    Serial.println("MQTT connect failed");
    Serial.println("Will reset and try again...");
    abort();
    while(1); // Let WDT reset
  }
}


void loop()
{
  if (WiFi.status() != WL_CONNECTED)
  {
    while(1); // Let WDT reset
  }
  
  client.loop();

  readDHT();
  publishMessages();
}

void readDHT()
{
  if (millis() - dhtLast < dhtInterval) return;
  dhtLast = millis();

  float tempHumi = dht.readHumidity();
  float tempTemp = dht.readTemperature();

  if (isnan(tempHumi) || isnan(tempTemp))
  {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }

  if (abs(tempTemp - avgTemperature) > avgSkip)
  {
    avgTemperature = tempTemp;
  }
  else
  {
    avgTemperature = (avgTemperature *  (100.0-avgForce)/100.0) + ((avgForce/100.0) * tempTemp);
  }

  if (abs(tempHumi - avgHumidity) > avgSkip)
  {
    avgHumidity = tempHumi;
  }
  else
  {
    avgHumidity = (avgHumidity * ((100.0-avgForce)/100.0)) + ((avgForce/100.0) * tempHumi);
  }

  Serial.print("DHT22:\tHumidity: ");
  Serial.print(avgHumidity);
  Serial.print(" %\t");
  Serial.print("Temperature: ");
  Serial.print(avgTemperature);
  Serial.println(" *C ");
}

void publishMessages()
{
  if ((millis() - postLast < postInterval && postLast > 0) || dhtLast == 0) return;
  postLast = millis();

  Serial.println("MQTT:\tPosting");

  mqttPublishHumi = avgHumidity;
  char* hPayload = dtostrf(avgHumidity, 1, 2, charVal);
  client.publish(humiTopic, hPayload);

  mqttPublishTemp = avgTemperature;
  char* tPayload = dtostrf(avgTemperature, 1, 2, charVal);
  client.publish(tempTopic, tPayload);
}

void messageReceived(String topic, String payload, char * bytes, unsigned int length)
{
  Serial.print("incoming: ");
  Serial.print(topic);
  Serial.print(" - ");
  Serial.print(payload);
  Serial.println();
}

25 comments

  • I have soldered the DHT11 on the other header. The 1st one is GND, 2nd is VCC. All the others are unpopulated.
    So, I put it looking inside, starting from Vcc at 2nd hole, and route the other 2 (data + gnd) to the 5pin header, from the back of the pcb via wire, permanently.

    The DHT11 fits inside and the case can be closed!

    • What do you do about the heat from the electronics inside the case? That is the main reason I didn’t even try to put it in there.

      • It doesn’t look any different than mounting outside…
        Its of course near the transformer, but I doubt it gets any hot.
        An idea is to drill some holes there.

  • Gentlemen,

    I am curious, why combine with a Temp/humidity meter?
    I would think that there are other sensors that would be more useful in connection with a relay?
    Sure, a fan that is controlled by the relay is useful in some situations, but there are a lot of other sensors that seem more obvious to me, like one measuring the ambient light to turn a light on at dusk/dawn, or a flood sensor connected to a pump, or a moisture meter connected to a pump or valve.
    I guess its up to anyone’s needs, and its all good work, just curious why this would be the premier choice. 🙂

    All the best,
    Björn

  • Here is an easier way. Use ESPEasy firmware (use the latest from github) – this allows you to swap the rx/tv pins to standard io giving you an additional 2 pins. It support OTA updates.
    Many sensors are supported out of the box. I use mine to counts pulses from a water meter and are sent to mqtt every minute or so.

    • I know about ESPEasy too, and I use it on some other devices too, but I hope to also inspire some readers to learn a bit of programming, instead of just going through the steps on flashing something already made onto them.

  • How can I wire this to a thermostat to regulate start and stop times, if say I want my cold air to be operational only between 8am – to 5pm, while the thermostat regulates temps. on-off within that time frame?

    • The ESP8266 itself does not know the time, but you can use the api from https://timezonedb.com/api to get the current time, then count up from that and calculate the time, maybe check in regularly to keep the time accurate. With that you can then check if you are within the span of time you want it to be in auto or off mode.

  • Did you use any resistence between the sensor and Sonoff?

  • hey, can you share your code?

  • Still waiting for the code.

  • Have you uploaded the code for this anywhere?

    • I just updated the post with some code, but there isn’t really anything special about it, just the DHT22 example provided by adafruit in the library would work too. 🙂

  • About DS18B20 Temperature Probe Waterproof Sensors, there is 3 cords black, red and yellow how do i connect them 😉

    • I don’t have one, but I assume black would go to gnd, red to 3v3 and yellow to pin 14, like I connected the DHT22. The code for the sensor you want to use, I have no idea about. I don’t have one of those sensors, but you can most likely use most of the example in a library for it.

  • Great job!
    Would it be possible to hook up a current sensor to the sonoff instaed?
    To monitor the state of a TV/fridge/Other dumb device for example.

    http://www.banggood.com/AC-30A-SCT-013-030-Non-invasive-Split-Core-Current-Transformer-p-937111.html

Leave a Reply