(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.
- start a new reading. (requestTemperatures)
- 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.