DallasTemperature library function too slow (nano v3.0)

Hello.
I have a problem with DallasTemperature library. The function .getTempCByIndex(0) takes apr. 29 millis. Is there any way how to get the Temperature value during max 5 millis? For me is good fill unsigned int by 12 bit number from sensor. My loop is divided to blocks and each block start in another INT0 (Comes each 10 millis, 4 millis I need and 5 is for block of code). In example is function requestTemperatures() OK - is only 3 millis. But I need divide the getTempCByIndex(0) to more step.
Maybe I only bad set up the library. I use powered sensors. (means no parasite mode need)-
Please not damn me. Thanks for help.
timing example:

//Temerature senzor test

//Libraries
#include <OneWire.h>
#include <DallasTemperature.h>
#include <LiquidCrystal.h>


//Declare 1-wire bus on pin 12
OneWire oneWire(12);

//Declare dallas senzors bus
DallasTemperature Dallas(&oneWire);
byte Senzor1[8]; //Senzor address

// Declare LCD
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

//Declare variables
float Temperature = 0;
long Start = 0;
long End = 0;

void setup() {
  Dallas.begin();
   Dallas.getAddress(Senzor1, 0);
   Dallas.setResolution(Senzor1, 12);
   
   Dallas.setWaitForConversion(false); //expected - I wait for conversion, not the library
   
   //LCD init
 lcd.begin(16, 2);
}

void loop() {
  
  Dallas.requestTemperatures(); //? Start convert
  
  delay(750); //Wait for conversion
  
  Start = millis();
  Temperature = Dallas.getTempCByIndex(0);
  End = millis();
  
  lcd.setCursor(0,0);
  lcd.print(Temperature);
  lcd.setCursor(0,1);
  lcd.print(End-Start);
  
}

The problem is the speed of the actual sensor when doing a temperature "conversion". That can take up to 750mS for a 12 bit precision answer according to the datasheet (and personal experience). The only thing you could do is start the conversions earlier and then read the converted value from the sensor when you need it. That should only take way less than 1mS. If you need an actual temperature reading every 10mS, then you won't be able to use a 1-wire sensor. You'll need to use something fast.

Azersen:
Hello.
I have a problem with DallasTemperature library. The function .getTempCByIndex(0) takes apr. 29 millis. Is there any way how to get the Temperature value during max 5 millis? For me is good fill unsigned int by 12 bit number from sensor. My loop is divided to blocks and each block start in

Like you, I use 12 bit resolution. I have been derided for not using 10 bit, and 12 bit is an unwarranted waste of time. Since I use a one second read interval, I don't care, but you may get some advantage with 10 bit resolution.

Hello.
My problem is not get temperature once per second or waiting for conversion, but tje reading time.
afremont wrote:
That should only take way less than 1mS.
But the function getTempCByIndex(0) after a 750 ms waiting for conversion takes 29 ms.
Maybe is possible call directly oneWire library and read only the first two bytes with temperature. Unfortunately all my experiments don't work. Could somebody post here the right sequence of commands for oneWire to solve this?
Thanks.

Can you post some code that you thought would work but didn't ? (would save me a lot of typing :wink:

According to my figures here:

It took 12.5 mS to read one temperature.

That should only take way less than 1mS.

Why? As I read it, you need to send/receive at least 18 bytes (plus possibly a 480 uS "reset"). Even without the reset, as each bit takes 60 uS, at the very least you would have:

60e-6 * 8 * 18 = 0.00864

So that's 8.64 mS at the very minimum.

the function getTempCByIndex(0) first needs to resolve the index zero to an address,

see lib code

bool DallasTemperature::requestTemperaturesByIndex(uint8_t deviceIndex)
{
  DeviceAddress deviceAddress;
  getAddress(deviceAddress, deviceIndex);
  return requestTemperaturesByAddress(deviceAddress);
}

So saving the address in a variable and calling requestTemperaturesByAddress(addr) directly should be faster (factor 2 approx).

You might win some time if you modify the Dallas Temp Lib and read only the first two fields of the scratchpad. However there are several consequences for the library.

A quick hack in a current project showed I could get timing down from 58ms to about 41 ms [for reading 4 sensors, 9 bit, asynchronous mode] by stripping and hard coding the behaviour of the lib. [I will not post this code as it cripples the lib too much]

Rob is right, I think asking by index forces an enumeration of all devices, in itself quite a slow process, as it has to work out device addresses by elimination.

Hello
I rewrite my malfunction test for serial. The reading time for full data1 looks OK but for data2 is nonsense.
The second problem is the data are constant - non reflect temperature change.
But if I can received data1 for 5 ms, maybe this way can solve my problem if you help me found my mistakes in my code.
I use two powered DS18B20 on pin 12.
Thanks

//Temperature semzor test

#include <OneWire.h>

OneWire  Sensors(12);  // Sensors are on pin 12

//address and data variables
byte addr1[8];
byte addr2[8];
byte data1[8];
byte data2[8];

//Sensor found
byte S1_OK = true;
byte S2_OK = true;

//Time measure
long Start = 0;
long End = 0;

byte present = 0; //???


void setup() {
  Serial.begin(9600);

  if ( !Sensors.search(addr1)) {
    S1_OK = false; //Sensor not found
  }
  
  if ( !Sensors.search(addr2)) {
    S2_OK = false; //Sensor not found
  }
  
  Serial.print("Sensor 1 ");
  if(S1_OK) {
    Serial.print("address: ");
    for(byte i=0; i < 9; i++) {
      Serial.print(addr1[i],HEX);
      Serial.print(" ");
    }
    Serial.println(" ");
  }
  else {
    Serial.println("not found");
  }
  
  Serial.print("Sensor 2 ");
  if(S2_OK) {
    Serial.print("address: ");
    for(byte i=0; i < 9; i++) {
      Serial.print(addr2[i],HEX);
      Serial.print(" ");
    }
    Serial.println(" ");
  }
  else {
    Serial.println("not found");
  }
}

void loop() {
  //Sensors reset
  Start = millis();
  Sensors.reset();
  End = millis();
  
  Serial.print("Reset ");
  Serial.print(End - Start);
  Serial.println(" ms");
  
  delay(10); //INT0 simulation
  
  //Start convertion
  Start = millis();
  Sensors.write(0x44);
  End = millis();
  
  Serial.print("Convert ");
  Serial.print(End - Start);
  Serial.println(" ms");

  //Waiting for convertion
  delay(750);
  
  
  if (S1_OK) {
  //Select address
  present = Sensors.reset();
  Start = millis();
  Sensors.select(addr1);
  End = millis();
  
  Serial.print("Select addr1 ");
  Serial.print(End - Start);
  Serial.println(" ms");
  
  delay(10); //INT0 simulation
  
  //data1 request
  Start = millis();
  Sensors.write(0xBE);
  End = millis();
  
  Serial.print("data1 request ");
  Serial.print(End - Start);
  Serial.println(" ms");
  
  delay(10); //INT0 simulation
  
  //data1 read
  Start = millis();
  for (byte i = 0; i < 9; i++) {
  data1[i] = Sensors.read();
  }
  End = millis();
  
  Serial.print("data1 read ");
  Serial.print(End - Start);
  Serial.println(" ms");
  
  }
  
  delay(10); //INT0 simulation
  
   if (S2_OK) {
     present = Sensors.reset();
  //Select address
  Start = millis();
  Sensors.select(addr2);
  End = millis();
  
  Serial.print("Select addr2 ");
  Serial.print(End - Start);
  Serial.println(" ms");
  
  delay(10); //INT0 simulation
  
  //data1 request
  Start = millis();
  Sensors.write(0xBE);
  End = millis();
  
  Serial.print("data2 request ");
  Serial.print(End - Start);
  Serial.println(" ms");
  
  delay(10); //INT0 simulation
  
  //data2 read
  Start = millis();
  for (byte i = 0; i < 9; i++) {
  data2[i] = Sensors.read();
  }
  End = millis();
  
  Serial.print("data2 read ");
  Serial.print(End - Start);
  Serial.println(" ms");
  
  }
  
  Serial.print("Data1 ");
  if (S1_OK) {
    for(byte i = 0; i < 9; i++) {
      Serial.print(data1[i],HEX);
      Serial.print(" ");
    }
    Serial.println(" ");
  }
  else {
    Serial.println("None");
  }
  
  Serial.print("Data2 ");
  if (S2_OK) {
    for(byte i = 0; i < 9; i++) {
      Serial.print(data2[i],HEX);
      Serial.print(" ");
    }
    Serial.println(" ");
  }
  else {
    Serial.println("None");
  }
  
  delay(10); //INT0 simulation
  delay(30000); //Only make loop slow
}

I was wrong on the 1mS for slow devices, but it should take less than 2mS at any rate to read the temperature. I can't help it if the library is slow and transfers the entire register set from the scratchpad. You only need to issue a READ SCRATCHPAD and transfer two more bytes to get the temperature. Allowing 64uS per time slot, this should take just over 1.5mS.

EDIT: I guess you have to issue the MATCH ROM if you want more than one sensor, but if not then it's not necessary to address the entire device, a SKIP ROM will do and only takes another 8 bits bringing the required total (per the datasheet) to about 2mS.

EDIT2: I have spent much of my life being an assembly language programmer so I tend to have a habit of using datasheets to set limits and not library performance. If a library function won't perform as I need, then I reinvent the wheel with higher performance. I apologize if this has led to confusion about the timing constraints.

Think the minimum handshake is:

  1. reset = >1mS (arduino impl.)
  2. skip,
  3. convert
    [omitted, reset + addr ==> 1mS + 8 bytes]
  4. scratchpad
  5. 2 bytes (skip the rest)

to send and retrieve = 5 * 8 * 60 us = 2.4mSec + 1mS = 3.4 mS as abs minimum I think

using the lib one gets 2 resets + 13 bytes = 2+ + 13 860 = ~9 mSec as minimum

  • worth to investigate a FastDallasLib() ==> todolist :wink:

One nice thing is that you can issue the converts by doing a SKIP ROM followed by the convert command. This should let you get them all under way at once. Then later just select the device and copy the first two bytes from the scratchpad. They retain the converted temperatures after a reset obviously.

I did some timing tests using the library and find that copying the scratchpad with the library takes about 6mS, not terrible for reading 9 bytes from the device. On the other hand, ds.select takes about 5 or 6mS also.

OP:
How fast are you expecting the temperature to change? Is that a reasonable expectation?

Hello.
I solved my problem :slight_smile:
In my application I use external INT0 interrupt. The INT0 comes each 10 ms.
So I can't use DallasTemperatue command for reading temperature - takes 29 ms.
If I try use direct OneWire command, my code not work. But now work and I each block takes less then 7 ms.
I use this way:
Wait for INT0 -> Start convert -> 800 ms other code -> INT0 -> Select Sensor1 -> INT0 -> Read Sensor1 -> INT0 -> Select sensor2_
-> INT0 -> Read Sensor2.
I dont know why but using only OneWire.reset() not work properly. I have to use variable = OneWire.reset()

Thanks to all for help and suggestion.

Can you post you final code, I like to see the details.
I've stripped the Dallas Lib [still crappy] and stuck with about 11.2 ms for read and start convert together (single sensor)

How long does the handling of the INT0 takes? (The ISR routine)

ISR timings here:

If you use attachInterrupt (which adds a certain overhead) around 5.125 uS, plus a certain amount of jitter.