DS18B20 DS18X20 Intermittent Readings errors

I have noticed a few posts regarding errors reading the DS18B20 Dallas Temperature sensor, such as reading high or low intermittently. I had similar problems when I first obtained one and thought that it might be that the user code gets routinely interrupted to do the particle housekeeping for cloud functions etc. I found that if I set to Manual Mode with no WiFi connection, the errors stopped.

My actual fix for this, which seems quite stable now, was to enable the system threading in the initialisation: -

SYSTEM_THREAD(ENABLED)

Then put a block around the temperature conversion in the main loop using the ATOMIC_BLOCK function.

void getTemp () { //get data from the DS18B20
    ATOMIC_BLOCK() { //block calls while reading the sensor
        sensors.requestTemperatures();
        tempC = sensors.getTempCByIndex(0);
    } //end of atomic block

This seemed to work for me so I hope this may be of help to others who may have similar problems.

UPDATE: Using SINGLE_THREADED_BLOCK() instead of ATOMIC_BLOCK() seems to work just as well as is probably a bit safer. Thanks to tommy_boy for the tip.

5 Likes

Legend! Thank you, will be trying that tomorrow.

Thanks for sharing, very much appreciated

I do a similar thing with my DS18B20’s. I use SINGLE_THREADED_BLOCK() for the time-sensitive portions. Mine have been stable over 6 months now. :slight_smile:
I have a lot of error correction that I use as well to validate temperature readings. If readings trigger an error, then I re-read the sensors, all while not allowing the whole process to take too long - that would disconnect the device from the cloud.

I did wonder if the SINGLE_THREADED_BLOCK() would have worked as well. It is probably safer to use than the ATOMIC_BLOCK() in most cases.

Agree, will be trying SINGLE_THREADED_BLOCK() too. Hopefully gets rid of that -127 degree error

Hi,
I’m also having issues with intermittent readings on the waterproof DS18B20 probe. I take a reading every minute, and about 10% of the time, it returns -127 as the value.

I’m using the “spark-dallas-temperature.h” and <OneWire.h> libraries. I’m not clear how I would implement the proposed solution above using SINGLE_THREADED_BLOCK().

I’m powering the probe directly from the particle Electron D1 pin. The data wire is D0, and the ground is connected directly to the ground of the Electron. (a 4.7 kOhm resistor is connected between D0 and D1)

Here’s the relevant portion of my code:

#include "spark-dallas-temperature.h"
#include <OneWire.h>

#include <Ubidots.h>
#define TOKEN "mytoken"  
Ubidots ubidots(TOKEN);


//************ Temp Probe
#define ONE_WIRE_BUS D0          // Data wire For Temp Probe is plugged into this pin.  A 4.7kohm pullup resistor is also needed between this pin and positive.
const int TempProbePositive =D1;  //Temp Probe power connected to pin 

 
OneWire oneWire(ONE_WIRE_BUS);// Setup a oneWire instance to communicate with any OneWire devices, like the temp probe.
DallasTemperature sensors(&oneWire);// Pass our oneWire reference to the Dallas Temperature library.
 
 
float Temperature=10; //base temperature measurement from Onewire probe
double tempF=0.0;


//*********************************Setup - runs Once and sets pins etc ******************************************************//
void setup()
{

  pinMode(TempProbePositive , OUTPUT ); //Set the positive power pin to the temp sensor as an output
  digitalWrite(TempProbePositive , HIGH ); // turn on the power pin
   
  delay(100);  // gives sensor time to settle
  sensors.begin();
  delay(100);
   
 
 
//************************************* Main Loop ****************************************************//
    
void loop()
    {
     
    sensors.requestTemperatures();  // Send the command to get temperatures
    Temperature=sensors.getTempCByIndex(0);  //Stores value in variable called Temperature
    tempF=Temperature*1.8+32;
     
    PrintReadings();  // Calls Print routine [below main loop]
     
     
    delay(60000); //delay between readings in milliseconds.  60000 milliseconds = 60 seconds
     
    }

//************************************** End Of Main Loop ***********************************************************//

 

void PrintReadings(){
    ubidots.add("Temperature_°C", Temperature);  // Add variables to the Ubidots list
    ubidots.add("Temperature_°F", tempF);
    ubidots.sendAll();      //send the variables to Ubidots
    } 

Thanks in advance for any help.

Hi,

Try adding the line…

SYSTEM_THREAD(ENABLED);

to the your definitions, for example just after ‘Ubidots ubidots(TOKEN);’ but should also work at the end of the definitions just before the setup().

Next you need to place your first two lines of your loop() within a single threaded blocking statement as follows…

void loop()
{
SINGLE_THREADED_BLOCK() { //block calls while reading the sensor
sensors.requestTemperatures();
Temperature = sensors.getTempCByIndex(0);
} //end of block
tempF=Temperature*1.8+32;

....rest of your code....

This worked for me by stopping interrupts out of the temperature sensor read routine. Hope it works OK for you as well.

2 Likes