Hi,
I'm trying to hook up a bunch of DS18B20s to an ESP8266 to monitor temperatures around my house.
I've had great success with up to appx. 6 sensors at around 2m max cable length, as I'm adding more and more sensors, I've started to get dropouts (sensors reading "-127C").
I tried coding a loop to re-read sensors if an out-of-range value was received, though this ended up behaving very strangely, with some readings being applied to the wrong sensor (hopefully this is a simple coding problem - the loop can be seen in the code below, commented out). This persisted even when I reduced the number of sensors to a known-good configuration.
From research, it seems there's a way to verify by CRC if the data is ok - though I think in my case it's a straight up failure to read (gives -127C from the Dallas library).
The DS18B20s are the pre-wired waterproof type, hooked up with a 4.4k pull-up to 3v3, and Vcc connected to 5v (all on the ESP8266). I've got a single 1m "extension" (4-wire phone cable) out to a "hub", which has a bunch of sensors (up to 8) hooked up, then I plan to also have another extension from there to another hub (this is where I started to see problems, even with only 1 sensor hooked into the furthest "hub").
My theories are:
5V (Vcc) sagging - though it measures OK at the far end during use, as far as I can tell - could be sagging for a fraction of a second during communications. I was originally using 3v3 for Vcc, bumped up to 5v to test.
Signal reflections/noise - what can I do to mitigate this?
Not enough loop delay to read all sensors correctly (I beleive it's roughly 750ms per sensor, though perhaps that was for parasite mode, which I'm not using). I've tried various delays, to no avail, though they may not have been in the right places.
Broader project info:
The readings are posted to an MQTT server as a float value, the topic is "TempSensor/" and the device address - this way I can manipulate the data elsewhere.
I'm also curious as to why my "loop" for re-reads introduced the overlap bug (i.e., 2 or more "addresses" getting one sensor's actual "reading" - is this a memory issure? I'm not particularly well versed in deeper C++ memory allocation, and had all manner of strange behaviour in my previous iterations of this project due to (I'm assuming) memory overlapping/being re-used because of accidental pointer/variable/reference/dereferece misunderstandings.
Here's the full code - mostly irrelevant I expect, but perhaps the issue stems from something outside the main guts!
Thanks in advance,
Moley
#include <Arduino.h>
#include <PubSubClient.h>
#include <ESP8266WiFi.h>
#include <OneWire.h>
#include <DallasTemperature.h>
// Data wire is plugged TO GPIO 4
#define ONE_WIRE_BUS 4
// Setup a oneWire instance to communicate with OneWire devices
OneWire oneWire(ONE_WIRE_BUS);
// Pass the oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
// Number of temperature devices found
int numberOfDevices;
// Use this variable to store a found device address
DeviceAddress tempDeviceAddress;
char ssid[] = "My_SSID";
char pass[] = "My_Password";
const char* mqtt_server = "192.168.1.177";
// Initializes the espClient. You should change the espClient name if you have multiple ESPs running in your home automation system
WiFiClient myTempMeasuringEsp;
PubSubClient client(myTempMeasuringEsp);
const char *ID = "My_Device_ID"; // Name of our device, must be unique
char tempC_char[8];
float tempC;
// Connect to WiFi network
void setup_wifi() {
Serial.print("\nConnecting to ");
Serial.println(ssid);
WiFi.begin(ssid, pass); // Connect to network
while (WiFi.status() != WL_CONNECTED) { // Wait for connection
delay(500);
Serial.print(".");
}
Serial.println();
Serial.println("WiFi connected");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
// Reconnect to client
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
if (client.connect(ID, "scott", "thisismylongMQTTpassword")) {
Serial.println("connected");
Serial.print("Publishing to server");
Serial.println('\n');
} else {
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
// function to print a device address
void printAddress(DeviceAddress deviceAddress) {
for (uint8_t i = 0; i < 8; i++){
if (deviceAddress[i] < 16) Serial.print("0");
Serial.print(deviceAddress[i], HEX);
}
}
// funtion to convert deviceAdress to hex char array
void charAddress(DeviceAddress deviceAddress, char* hexAddress) {
char hexString[17];
for (uint8_t i = 0; i < 8; i++){
sprintf(hexString+i*2, "%02X", deviceAddress[i]);
}
for (uint8_t i = 0; i < 17; i++){
hexAddress[i] = hexString[i]; //possibly not needed, could be wrapped in the sprintf
}
}
void setup() {
Serial.begin(115200);
setup_wifi();
client.setServer(mqtt_server, 1883);
// Start up the library
sensors.begin();
// Grab a count of devices on the wire
numberOfDevices = sensors.getDeviceCount();
// locate devices on the bus
Serial.print("Locating devices...");
Serial.print("Found ");
Serial.print(numberOfDevices, DEC);
Serial.println(" devices.");
// Loop through each device, print out address
for(int i=0;i<numberOfDevices; i++){
// Search the wire for address
if(sensors.getAddress(tempDeviceAddress, i)){
Serial.print("Found device ");
Serial.print(i, DEC);
Serial.print(" with address: ");
printAddress(tempDeviceAddress);
Serial.println();
} else {
Serial.print("Found ghost device at ");
Serial.print(i, DEC);
Serial.print(" but could not detect address. Check power and cabling");
}
}
}
void loop() {
if (!client.connected()) // Reconnect if connection is lost
{
reconnect();
}
client.loop();
sensors.requestTemperatures(); // Send the command to get temperatures
delay(1000); //delay to see if waiting after requestT aids stability
char tempDeviceAddressHex[17];
// Loop through each device, print out temperature data
for(int i=0;i<numberOfDevices; i++){
// Search the wire for address
if(sensors.getAddress(tempDeviceAddress, i)){
char topic[28] = "TempSensors/"; //note this behaved unexpectedly when no size was defined
charAddress(tempDeviceAddress, tempDeviceAddressHex);
strcat(topic, (char*) tempDeviceAddressHex);
tempC = sensors.getTempC(tempDeviceAddress);
/* Tried this to filter bad responses - ended up with overlaps (tempC getting reported against the wrong device address)
for(int retries=0; i<5; retries++){
tempC = sensors.getTempC(tempDeviceAddress);
if(tempC > 3){
break;
// delay(751); // also tried this to stop overlap
}
}
tempC = (tempC > 3) ? tempC : -2; //force a bad (consistent) number if no good after the retries
*/
sprintf(tempC_char, "%.3f", tempC); //print to string, 3 decimal places, float input/format
client.publish(topic, tempC_char);
}
}
delay(4000); //decreased this delay while testing the 1000ms delay after requestT
//delay(5000); //standard loop delay for normal operation purposes
}