Making smart home temperature sensors for under $15

In order to monitor the temperature of some of the rooms in my house, I wanted to make a few cheap temperature sensor nodes to toss around. I started reading about what other people had accomplished online and decided to use the popular ESP8266 wifi board and a DS18B20 temperature sensor. I did try using the ESP8266 with a DHT11 and a DHT22 but neither one was very successful. In the end, the DS18B20 worked perfectly and I happened to have a few them that I wasn’t using.

I’m also planning on using a protocol called MQTT (Message Queuing Telemetry Transport) to publish the information to all the subscribed clients. The link above is worth a quick read but the way MQTT works in my system is that my home hub Raspberry Pi hosts an MQTT broker and the temperature sensor node will act as a MQTT client that can publish its latest reading to it. Home Assistant will then be able to read the latest temperature reading and will display and treat it as a sensor.

This is everything you need in order to make one temperature sensor node:

  • An ESP8266
  • A DS18B20
  • An FT232 FTDI adapter (a 3.3V variant or one of those that can offer both)
  • A 1K resistor
  • A 4.7K resistor
  • Dupont cables or wire to connect it all up

It should be possible to make one of these with a Li-Po cell and make it a wireless temperature sensor node, but I haven’t found a great source for Li-Pos and would love to avoid a Note 7 level disaster in my living room. I’ll make an updated guide in the future if I ever source any reliable and cheap power cells.

Wiring it up

The ESP8266 is a great little board but it does have a few annoyances. It requires a 3-3.6V power source but unlike other 3.3V sensor components, the ESP8266 requires a lot of power for such a little chip and cannot be powered off the 3.3V pin of an Arduino and I had no luck using a voltage divider circuit to power it either. I opted to use a few 3.3V power bricks off of ebay to power the nodes.

Here is a quick schematic drawing I made in fritzing to show how to wire the whole thing together.

I’ve never used fritzing before so this is as good as I could make it. The ESP8266 chips that I buy usually look like this:

And have this standard pinout:

Feed the VCC and GND pins from a power source of your choice and you should be in business. There’s an extra step for whenever you want to program the ESP8266 and that’s to make sure you connect the GPIO0 pin to GND.

Programming the ESP8266

In order to program the ESP8266, you have first have to download and install the required componenets from the Arduino IDE board manager. From board manager, search for esp8266 and download and install the esp8266 community package.

Once that’s done, you need to connect:

  • ESP RX >> FTDI TX
  • ESP TX >> FTDI RX
  • ESP GND >> FTDI GND
  • ESP VCC >> FTDI 3.3V
  • ESP GPIO0 >> FTDI GND

Then you should be able to flash the following code:

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <OneWire.h>
#include <DallasTemperature.h>

#define wifi_ssid “wifi_ssid”
#define wifi_password “wifi_password”

#define mqtt_server “mqtt_broker_ip”
#define mqtt_user “your_username”
#define mqtt_password “your_password”

#define temperature_topic “livingroom/temperature”

#define ONE_WIRE_BUS 6

WiFiClient espClient;
PubSubClient client(espClient);
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

void setup() {
Serial.begin(115200);
setup_wifi();
client.setServer(mqtt_server, 1883);

}

void setup_wifi() {
delay(10);
// We start by connecting to a WiFi network
Serial.println();
Serial.print(“Connecting to “);
Serial.println(wifi_ssid);

WiFi.begin(wifi_ssid, wifi_password);

while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(“.”);
}

Serial.println(“”);
Serial.println(“WiFi connected”);
Serial.println(“IP address: “);
Serial.println(WiFi.localIP());
}

void reconnect() {
// Loop until we’re reconnected
while (!client.connected()) {
Serial.print(“Attempting MQTT connection…”);
if (client.connect(“ESP8266Client”)) {
Serial.println(“connected”);
} else {
Serial.print(“failed, rc=”);
Serial.print(client.state());
Serial.println(” try again in 5 seconds”);
// Wait 5 seconds before retrying
delay(5000);
}
}
}

bool checkBound(float newValue, float prevValue, float maxDiff) {
return !isnan(newValue) &&
(newValue < prevValue – maxDiff || newValue > prevValue + maxDiff);
}

long lastMsg = 0;
float temp = 0.0;
float diff = 0.01;

void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();

long now = millis();
if (now – lastMsg > 10000) {
lastMsg = now;
sensors.requestTemperatures();

float newTemp = sensors.getTempCByIndex(0);

if (checkBound(newTemp, temp, diff)) {
temp = newTemp;
Serial.print(“New temperature:”);
Serial.println(String(temp).c_str());
client.publish(temperature_topic, String(temp).c_str(), true);
}
else {
Serial.println(“No temperature change”);
}
}
}

Which is a modification of the code found here; the original code didn’t work with the DS18B20 and I didn’t have any use for reporting the humidity since the DS18B20 didn’t support it so I removed it. Obviously fill in the wifi details for your network as well as the ip address of your MQTT broker and the topic that you want the temperature published to. I also used boiling water to calibrate my temperature sensor and found that it was reading .94 degrees cooler so I added a factor to correct for that.

That’s all you need to set up the temperature sensor. Now all you need to do is add it to your smart home controller using whatever bridging platform you like. Homebridge for homekit devices and siri, or Home Assistant or OpenHAB for something a little more powerful and customizable. I’m currently using them with homebridge but since I’m making the switch to Home Assistant, I’ll be writing more about integrating these sensors with that smart home platform.

Leave a Reply