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();
}
52 Comments

Leave a Reply to Anonymous Cancel reply

Your email address will not be published. Required fields are marked *