Dallas Temperature libary non blocking question

Hi,

Just a quick question on using the DallasTemperature libary.

It has the command, sensors.setWaitForConversion(true); // or this can be false

Obviously if I set it to true it will block for 750ms as per the data sheet.
If i set this to false, it is no longer waits for a conversion and is not blocking.

The library states that 'The programmer is responsible to wait long enough before reading the temperature values'

I can set a timer to wait until 750ms has passed then get temperature reading, but I am wondering is there a 'flag'
that I can test in the libary, that informs me that the conversion is complete and therefore I can now read the temperature ?

Thanks

Regards

Gary

If in a big hurry to get the results, then there is a way to poll the sensor to see when it's done. Check the datasheet, but I think you just keep doing a MATCH ROM until you get an ACK and then you can transfer the converted temperature. Of course you can't really do that when using parasite power mode.

(FYI - I wrote the async extension to the dallas lib)

The idea is simple, when you want to read the DS18B20 in a "normal" way it blocks your code for up to 750 millisec depending on the bitresolution (9..12)
Because 750 milliseconds is a long time in UProc I added functions to split the normal call in two.

  1. start a new reading. (requestTemperatures)
  2. read the new reading. (getTempCByIndex)

By splitting the normal read in two I could use the waiting time to do something more meaningful. This is shown in the demo code at the end where the "blink without delay" trick is used to wait until the conversion in the temp-sensor is ready and can be read by the Arduino. Because you know the resolution you set, you can calculate the time when the conversion is ready ==> // conversionTime = 750 / (1 << (12 - resolution)); So if you know the time when you started a new reading you know when it is ready!

The nice part of this splitting is that you request a new reading directly after reading a value. That way you can process the temperature reading in the time you normally used to wait!

in simplified code

void setup()
{
  conversiontime = 750 / (1 << (12 - resolution));  // res in {9,10,11,12}
  sensors.requestTemperatures(); 
  lastTime = millis();
}

void loop()
{
  if ( millis() - lastTime > conversiontime)
  {
    temperature = sensors.getTempCByIndex(0);
    sensors.requestTemperatures();                    // ask for next reading 
    lastTime = millis();

    // process temperature here
    
  }
  // do other stuff here
}

You can expand this principle to support multiple sensors.

WRT programmatic checking if the conversion is ready.
One can check if a conversion is ready by checking if the PIN goes up/down IIRC but that only works efficiently if there is only one sensor on the pin.
If there are more you need (at least in theory) check them all.

I have considered to do the timekeeping per sensor inside the class and expose a function e.g. conversionReady(int sensor)
but the code for that is not trivial to make reliable as it seems at first sight without "exploding the code".
One could poll the sensor if conversion is ready but that is also quite time consuming.

Hope this helps a bit

more elaborate example.

//
// Sample of using Async reading of Dallas Temperature Sensors
// 
#include <OneWire.h>
#include <DallasTemperature.h>

// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2

// 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);

DeviceAddress tempDeviceAddress;

int  resolution = 12;
unsigned long lastTempRequest = 0;
int  delayInMillis = 0;
float temperature = 0.0;
int  idle = 0;
//
// SETUP
//
void setup(void)
{
  Serial.begin(115200);
  Serial.println("Dallas Temperature Control Library - Async Demo");
  Serial.print("Library Version: ");
  Serial.println(DALLASTEMPLIBVERSION);
  Serial.println("\n");

  sensors.begin();
  sensors.getAddress(tempDeviceAddress, 0);
  sensors.setResolution(tempDeviceAddress, resolution);
  
  sensors.setWaitForConversion(false);
  sensors.requestTemperatures();
  delayInMillis = 750 / (1 << (12 - resolution)); 
  lastTempRequest = millis(); 
  
  pinMode(13, OUTPUT); 
}

void loop(void)
{ 
  
  if (millis() - lastTempRequest >= delayInMillis) // waited long enough??
  {
    digitalWrite(13, LOW);
    Serial.print(" Temperature: ");
    temperature = sensors.getTempCByIndex(0);
    Serial.println(temperature, resolution - 8); 
    Serial.print("  Resolution: ");
    Serial.println(resolution); 
    Serial.print("Idle counter: ");
    Serial.println(idle);     
    Serial.println(); 
    
    idle = 0; 
        
    // immediately after fetching the temperature we request a new sample 
    // in the async modus
    // for the demo we let the resolution change to show differences
    resolution++;
    if (resolution > 12) resolution = 9;
    
    sensors.setResolution(tempDeviceAddress, resolution);
    sensors.requestTemperatures(); 
    delayInMillis = 750 / (1 << (12 - resolution));
    lastTempRequest = millis(); 
  }
  
  digitalWrite(13, HIGH);
  // we can do usefull things here 
  // for the demo we just count the idle time in millis
  delay(1);
  idle++;
}

Recently I used this async mode in a project to read 4 DS18B20's 2 x per second in 11 bits resolution, taking in total about 60 milliseconds (IIRC) in blocking calls,
These 8 calls would normally take 8x375 blocking milliseconds = 3000 milliseconds.

You might already know this, but you can issue a SKIP ROM command and then a temp convert command to initiate conversion on all the devices simultaneously. As long as you can supply the power on the bus, it speeds things up nicely.

robtillaart:
Recently I used this async mode in a project to read 4 DS18B20's 2 x per second in 11 bits resolution, taking in total about 60 milliseconds (IIRC) in blocking calls,
These 8 calls would normally take 8x375 blocking milliseconds = 3000 milliseconds.

Thank you, this is awesome!