I have a strange problem that I’m hoping someone can help me with.
I’ve had a Photon reading from a BMP180, DS18B20 and DHT22 with a problem for about 3 months now. Until a few days ago that is.
The Photon stopped grabbing temperature data from the DS18B20. All three sensors were reporting to a web server via Publish. The other two sensors continue to work without any problems. I have the Photon connected via USB to my PC for serial troubleshooting. It appears that the Photon sees the DS18B20 but only ever returns a value of -127. It stopped working once my outdoor temperature hit roughly 15.7C (3.74f) and I’m wondering if there might be a variable conversion issue somewhere in the libraries I’m using. I’m not sure where to begin with the libraries. To rule out the sensor as being defective I hooked it up to an Arduino and found it reporting temperature accurately.
// This #include statement was automatically added by the Particle IDE.
#include "spark-dallas-temperature/spark-dallas-temperature.h"
// This #include statement was automatically added by the Particle IDE.
#include "OneWire/OneWire.h"
// This #include statement was automatically added by the Particle IDE.
#include "Adafruit_BMP085/Adafruit_BMP085.h"
// This #include statement was automatically added by the Particle IDE.
#include "PietteTech_DHT/PietteTech_DHT.h"
// System Definitions
#define DHTPIN 3 // what pin we're connected to
#define DHTTYPE DHT22 // DHT 22 (AM2302)
#define DHT_SAMPLE_INTERVAL 60000 // Sample every minute
#define ONE_WIRE_BUS D5
Adafruit_BMP085 bmp;
//declaration
void dht_wrapper(); // must be declared before the lib initialization
// Setup DHT instance
PietteTech_DHT DHT(DHTPIN, DHTTYPE, dht_wrapper);
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
// Global Variables
bool bDHTstarted; // flag to indicate we started acquisition
char myStr[40], dhtStr1[40], dhtStr2[40];
DeviceAddress outsideThermometer = { 0x28, 0xFF, 0x63, 0x93, 0x60, 0x14, 0x2, 0xB0 };
// function to print a device address
void printAddress(DeviceAddress deviceAddress);
void printAddress(DeviceAddress deviceAddress)
{
for (uint8_t i = 0; i < 8; i++)
{
if (deviceAddress[i] < 16) Serial.print("0");
Serial1.print(deviceAddress[i], HEX);
}
}
void setup(void)
{
InitializeApplication();
InitializeBMP085();
// Startup the sensors
//dht.begin();
sensors.begin();
delay(2000);
// Locate devices on the bus
Serial1.print("Locating devices...");
Serial1.print("Found ");
Serial1.print(sensors.getDeviceCount(), DEC);
Serial1.println(" devices.");
// Show the addresses we found on the bus
Serial1.print("Device 0 Address: ");
printAddress(outsideThermometer);
Serial1.println();
// Set the resolution to 11 bit (Each Dallas/Maxim device is capable of several different resolutions)
sensors.setResolution(outsideThermometer, 9);
Serial1.print("Device 0 Resolution: ");
Serial1.print(sensors.getResolution(outsideThermometer), DEC);
Serial1.println();
Serial1.print("Current IP: ");
Serial1.println(WiFi.localIP());
delay(2000); // let everything power up for a bit
DHTnextSampleTime = 0; // Start the first sample immediately
}
// This wrapper is in charge of calling
// mus be defined like this for the lib work
void dht_wrapper() {
DHT.isrCallback();
}
void loop(void)
{
float humidity = 0;
float dhttempc = 0;
float dewptc = 0;
// Check if we need to start the next sample
if (millis() > DHTnextSampleTime)
{
if (!bDHTstarted) { // start the sample
Serial.println(": Retrieving information from sensor: ");
DHT.acquire();
bDHTstarted = true;
}
if (!DHT.acquiring()) { // has sample completed?
// get DHT status
int result = DHT.getStatus();
Serial.print("Read sensor: ");
switch (result) {
case DHTLIB_OK:
Serial.println("OK");
break;
case DHTLIB_ERROR_CHECKSUM:
Serial.println("Error\n\r\tChecksum error");
break;
case DHTLIB_ERROR_ISR_TIMEOUT:
Serial.println("Error\n\r\tISR time out error");
break;
case DHTLIB_ERROR_RESPONSE_TIMEOUT:
Serial.println("Error\n\r\tResponse time out error");
break;
case DHTLIB_ERROR_DATA_TIMEOUT:
Serial.println("Error\n\r\tData time out error");
break;
case DHTLIB_ERROR_ACQUIRING:
Serial.println("Error\n\r\tAcquiring");
break;
case DHTLIB_ERROR_DELTA:
Serial.println("Error\n\r\tDelta time to small");
break;
case DHTLIB_ERROR_NOTSTARTED:
Serial.println("Error\n\r\tNot started");
break;
default:
Serial.println("Unknown error");
break;
}
// grab some data from the dht22
humidity = DHT.getHumidity();
dhttempc = DHT.getCelsius();
dewptc = DHT.getDewPoint();
bDHTstarted = false; // reset the sample flag so we can take another
}
// Cast the float into a string - limit to 3 decimals
String dhtStr1(dhttempc, 3);
String dhtStr2(humidity, 3);
Serial.print("Humidity (%): ");
Serial.println(dhtStr2);
Serial.print("Temperature (oC): ");
Serial.println(dhtStr1);
Serial.print("Dew Point (oC): ");
Serial.println(dewptc);
if (dhttempc> 0) {
Spark.publish("baseTemp", dhtStr1);
Spark.publish("baseHumid", dhtStr2);
}
getTemps();
// Publish events. Wait for 2 second between publishes
PublishBMP085Info();
BlinkLED();
DHTnextSampleTime = millis() + DHT_SAMPLE_INTERVAL; // set the time for next sample
//If you want to power down between sends to save power (ie batteries).
//Serial1.println("System sleeping for 45 seconds . . .");
//delay(1000); //Without the delay it jumps to sleep too fast
//System.sleep(SLEEP_MODE_DEEP,44); //sleep measured in seconds
}
}
void getTemps(){
// call sensors.requestTemperatures() to issue a global temperature
// request to all devices on the bus
Serial1.print("Requesting temperatures...");
sensors.requestTemperatures(); // Send the command to get temperatures
Serial1.println("DONE");
float tempC = sensors.getTempC(outsideThermometer);
Serial1.print("Outdoor Temperature C: ");
Serial1.println(tempC);
//Serial1.print("Basement Temperature C: ");
//Serial1.print(dhttempc);
//Serial1.print(" / Basement Humidity : ");
//Serial1.print(humidity);
//Serial1.print("%");
// Cast the float into a string
String myStr(tempC, 3);
//String dhtStr1(dhttempc, 3);
//String dhtStr2(humidity, 3);
// Publish the temperature online
Spark.publish("tmpInfo", myStr);
//Spark.publish("baseTemp", dhtStr1);
//Spark.publish("baseHumid", dhtStr2);
}
// Initialize applicaiton
void InitializeApplication(){
// Start serial port
Serial1.begin(9600);
pinMode(D7, OUTPUT);
}
// Blink LED and wait for some time
void BlinkLED(){
digitalWrite(D7, HIGH);
delay(500);
digitalWrite(D7, LOW);
delay(500);
}
// Initialize BMP085
void InitializeBMP085(){
if (!bmp.begin()) {
Serial.println("Could not find a valid BMP085 sensor, check wiring!");
while (1) {}
}
}
// Publish Pressure
void PublishBMP085Info(){
Serial.print("Temperature = ");
Serial.print(bmp.readTemperature());
Serial.println(" *C");
Serial.print("Pressure = ");
Serial.print(bmp.readPressure());
Serial.println(" Pa");
char szEventInfo[64];
sprintf(szEventInfo, "{\"Temperature\": %.2f, \"Pressure\": %.2f}", bmp.readTemperature(), bmp.readPressure()/100.0);
Spark.publish("bmpo85info", szEventInfo);
}
If you restart/reflash the device, is it still not functioning? How about a demo version of the sensor library, reading only that sensor? Also, there’s a DS18B20 library available in the IDE, would you be willing to give that a try, even just the demo?
I had tried restarting and reflashing the Photon several times but that didn’t make a difference. I also tried the demo example included in the Onewire library and that didn’t work either. As a last ditch effort I tried the demo example in the DS18B20 library and guess what? It worked! I was getting a ton of CRC errors until I switched back to a 4.7K pullup resistor. I had tried a 1K just for troubleshooting.
After switching the resistor it was still giving me a few intermittent CRC errors which made me think to check and my wiring for the millionth time. It looked like this got rid of the rest of the CRC errors. Then I reflashed my original program and everything appears to be working normally now.
It must have been a loose connection somewhere or maybe even a bad USB power supply which I also replaced. I was hearing some faint whistling from the original. This also goes to show you that breadboards don’t make good long term solutions.
Now I’m baffled. It’s stuck/stopped reporting temperatures again. This has happened again at the exact same negative temperature (-15c or approx. 59-60f). That can’t be a coincidence. =)
I use the lib below (includes CRC checks) and get the occasional CRC error but it has proven to be pretty reliable. Most libs have defined failure values so you can determine it was a failed read. Getting 59-60 is probably a product of your C to F conversion formula. I have the waterproof probe style sensors and soldered the wires to jumpers with male pins so I could easily use them with a breadboard. If every read of the sensor is failing I would suggest looking at your OneWire comms which the DS18B20 is reliant on so if there is a problem there, you will never get a good read at the Dallas/DS layer. Hope that helps!
So here’s the deal. I found that the problem lies with the port of the dallas temperature library that I was using (“spark-dallas-temperature”). The issue is with the -2032 value defined for DEVICE_DISCONNECTED_RAW constant in the header file which should read -7040.
This was reported by RobTillaart who opened this issue on GitHub. These changes have already been made to the original Miles Burton Arduino library. I’ve tested out the change on my own Photon and everything seems to be working now, reporting temperatures below the -15 mark. I’ve created a new Pull request to have the fix updated in the library that’s referenced in the Particle IDE.