The ESP8266 is a great low cost platform that is easily programmed using the Arduino IDE.
The temperature sensor consists of four DS18B20 sensors wired in parallel (sharing the same digital serial data bus) to digital pin 4 on the ESP8266. I used the NodeMCU form factor for easy wiring and setup.
The sensors are used for monitoring water temperatures including a pool and spa, so the sensors needed to be water and chlorine proof. To achieve this, I embedded the sensors in plastic tubes and filled the tubes with chlorine-tolerant silicone. The sensors have been working perfectly for almost two years now.
I housed the ESP8266 in a small enclosure and installed it in a dry area under my deck. I ran the cables to a junction box and used cat6 cable to extend the connection back to the enclosure. The DS18B20 chips are quite accurate and reliable and work well over extended wiring distances.
/*
Publish DS18B20 readings via MQTT
- connects to an MQTT server and reconnects if needed
- publishes digital temp values
*/
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 4
// Update these with values suitable for your network.
IPAddress server(192, 168, 2, 40);
WiFiClient wclient;
PubSubClient client(wclient, server);
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature DS18B20(&oneWire);
char strTD[6];
const char* ssid = "MyNetwork";
const char* pass = "MyPassword";
float oldTemp_pond;
float oldTemp_pool;
float oldTemp_spa;
float oldTemp_out;
char* deblank(char* input)
{
char *output = input;
int j;
int i;
for (i = 0, j = 0; i < strlen(input); i++, j++)
{
if (input[i] != ' ')
output[j] = input[i];
else
j--;
}
output[j] = 0;
return output;
}
void setup() {
oldTemp_pond = -1;
oldTemp_pool = -1;
oldTemp_spa = -1;
oldTemp_out = -1;
}
void loop() {
float temp_pond;
float temp_pool;
float temp_spa;
float temp_out;
DS18B20.requestTemperatures();
temp_pond = DS18B20.getTempCByIndex(0); //sensor 1
if (temp_pond == (85.0) || temp_pond == (-127.0)) { //failed to read
return;
}
delay(5000);
if (WiFi.status() != WL_CONNECTED) {
WiFi.begin(ssid, pass);
delay(100);
}
if (WiFi.waitForConnectResult() != WL_CONNECTED) {
return;
}
if (WiFi.status() == WL_CONNECTED)
{
if (!client.connected())
{
if (client.connect("esp8266DS18B20"))
{
client.publish(MQTT::Publish("esp8266/DS18B20/status", "mqtt reconnected").set_retain()); }
}
else
{
if (temp_pond != oldTemp_pond) {
dtostrf(temp_pond, 6, 2, strTD);
client.publish(MQTT::Publish("esp8266/DS18B20/pond", deblank(strTD)).set_retain());
oldTemp_pond = temp_pond;
}
temp_spa = DS18B20.getTempCByIndex(1); //sensor 1
if (temp_spa != oldTemp_spa && temp_spa != (85.0) && temp_spa != (-127.0)) {
dtostrf(temp_spa, 6, 2, strTD);
client.publish(MQTT::Publish("esp8266/DS18B20/spa", deblank(strTD)).set_retain());
oldTemp_spa = temp_spa;
}
temp_pool = DS18B20.getTempCByIndex(2); //sensor 2
if (temp_pool != oldTemp_pool && temp_pool != (85.0) && temp_pool != (-127.0)) {
dtostrf(temp_pool, 6, 2, strTD);
client.publish(MQTT::Publish("esp8266/DS18B20/pool", deblank(strTD)).set_retain());
oldTemp_pool = temp_pool;
}
temp_out = DS18B20.getTempCByIndex(3); //sensor 3
if (temp_out != oldTemp_out && temp_out != (85.0) && temp_out != (-127.0)) {
dtostrf(temp_out, 6, 2, strTD);
client.publish(MQTT::Publish("esp8266/DS18B20/outside", deblank(strTD)).set_retain());
oldTemp_out = temp_out;
}
}
}
}