DS18S20 temperature sensor , delay problem

I found this code that is great,but it does not match to what I wrote, in the rest of the code because it has delay of 700 ms help to convert to milis

#include <OneWire.h>

// OneWire DS18S20, DS18B20, DS1822 Temperature Example
//
// http://www.pjrc.com/teensy/td_libs_OneWire.html
//
// The DallasTemperature library can do all this work for you!
// http://milesburton.com/Dallas_Temperature_Control_Library

OneWire  ds(10);  // on pin 10 (a 4.7K resistor is necessary)

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

void loop(void) {
  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius, fahrenheit;
  
  if ( !ds.search(addr)) {
    Serial.println("No more addresses.");
    Serial.println();
    ds.reset_search();
    
    return;
  }
  
  Serial.print("ROM =");
  for( i = 0; i < 8; i++) {
    Serial.write(' ');
    Serial.print(addr[i], HEX);
  }

  if (OneWire::crc8(addr, 7) != addr[7]) {
      Serial.println("CRC is not valid!");
      return;
  }
  Serial.println();
 
  switch (addr[0]) {
    case 0x10:
      Serial.println("  Chip = DS18S20");  // or old DS1820
      type_s = 1;
      break;
    case 0x28:
      Serial.println("  Chip = DS18B20");
      type_s = 0;
      break;
    case 0x22:
      Serial.println("  Chip = DS1822");
      type_s = 0;
      break;
    default:
      Serial.println("Device is not a DS18x20 family device.");
      return;
  } 

  ds.reset();
  ds.select(addr);
  ds.write(0x44, 1);        // start conversion, with parasite power on at the end
  





  delay(700);     // maybe 750ms is enough, maybe not
  // we might do a ds.depower() here, but the reset will take care of it.
  






  present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE);         // Read Scratchpad

  Serial.print("  Data = ");
  Serial.print(present, HEX);
  Serial.print(" ");
  for ( i = 0; i < 9; i++) {           // we need 9 bytes
    data[i] = ds.read();
    Serial.print(data[i], HEX);
    Serial.print(" ");
  }
  Serial.print(" CRC=");
  Serial.print(OneWire::crc8(data, 8), HEX);
  Serial.println();

  int16_t raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3;
    if (data[7] == 0x10) {
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    
    if (cfg == 0x00) raw = raw & ~7;  
    else if (cfg == 0x20) raw = raw & ~3; 
    else if (cfg == 0x40) raw = raw & ~1; 
  }
  celsius = (float)raw / 16.0;
  fahrenheit = celsius * 1.8 + 32.0;
  Serial.print("  Temperature = ");
  Serial.print(celsius);
  Serial.print(" Celsius, ");


}

700 ms is 700 millis - i'm quite sure you knew before. Learn to explain better what you want to know. And try to find out what the 700ms is for - maybe the sensor needs it? what does the datasheet say?

damir27:
delay(700); // maybe 750ms is enough, maybe not
// we might do a ds.depower() here, but the reset will take care of it.

700 millisecond is nearly three-quarters of 1 second. They reckon this device takes around 0.75 seconds to take a reading, and some pieces of code has put a 1 second (ie 1000 millisecond) delay. Other code puts 750 millisecond.

But in your code, you have '700'. Did you choose this value? Or somebody else chose it?

Also.....

.... click here ....

Check out the Dallas Temperature Library and the examples that come with it:

It does a lot of the grunt work for you.

The code is junk. The only useful line in it is// The DallasTemperature library can do all this work for you!and it isn't even code, it is a comment. The sensor takes 750ms to make the conversion at the highest resolution, which is also the default resolution. Using a delay of 700 is just asking for trouble, but seeing it in the code is no surprise. In the unlikely event that you really need faster readings you can reduce the resolution and get much faster conversion times.
The DS128B20 data sheet has all you need on this. Some sensible software is here

There are other methods.

The DallasTemperature library also allows you to kick off a non-blocking conversion request and then return immediately so you can still do useful stuff in your code while the measurement is taking place. Then go back later (determined by millis() timer) and get the results.

gfvalvo:
The DallasTemperature library also allows you to kick off a non-blocking conversion request

You might also point out that the DS18B20 does not prevent you from doing useful stuff while it is doing its conversions.It just needs that time before you ask it for an answer. This goes some way to explain why you can read a swag of them at maximum resolution and in a one second loop. In real-world terms, the conversion time can hardly be a problem anyway and, in the unlikely event that it is, you are almost certainly using the wrong sensor.

Nick_Pyner:
You might also point out that the DS18B20 does not prevent you from doing useful stuff while it is doing its conversions.

I did, see Reply #5. I just went back a highlighted it.

At the risk of being too pedantic, I might suggest you

  1. put a full stop after" immediately"
  2. Delete the word "so"
  3. Use a capital Y in "You"

The red stuff is fine, although adding "so there is not much point using the non-blocking request", also in red might be helpful.

In short, I submit the whole deal is a silly red herring that doesn't solve a real problem, it merely moves a perceived one. I believe there may be some point in non-blocking request if you are using low resolution and parasitic power, but you might consider the justification for the use of parasitic power first before you bother to find out about non-blocking requests.

Hi,
Is this to do with this?

https://forum.arduino.cc/index.php?topic=509030.0

Tom.. :slight_smile:

OP..... you probably should confirm that you have a ds18s20 .... just assuming this is exactly what you have. Not a ds18B20.... right?

/*

  • If you use the examples you will see about 750ms for 12bit precision.
  • This sketch does in 29ms on an Arduino Nano with one probe. Did not test on multiples probes.
  • Note that there are no delay()s which allows other routines to run while waiting for the Request to complete.

*/

// Include the libraries we need
#include <OneWire.h>
#include <DallasTemperature.h>

// Define pin
#define ONE_WIRE_BUS 2

// Set some global variables
long int intervalRequestTemperatures = 1000; // probe sample rate in ms, should be > 750ms
long int timerRequestTemperatures = millis(); // timer for requesting temperature
long int timerGetTempCByIndex = millis(); // timer for reading request results temperature
bool checkingRequestTemperatures = 0; // enable Request or Get Temperature but not both at the same time.
float probeTemperature;

// not needed for your project
long int startRequest; // not needed for your project
long int endRequest; // not needed for your project
long int startGetTemp; // not needed for your project
long int endGetTemp; // not needed for your project
// 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);

void setup() {
// start serial port
Serial.begin(9600);
Serial.println("Demonstrate fast way to pull temp probe readings from DallasTemperature sensors");

// Start up the library
sensors.begin();
sensors.requestTemperatures(); // Send the command to get temperatures
probeTemperature = sensors.getTempFByIndex(0);

}

void loop() {
// Request temperature conversion - non-blocking / async
if (millis() > timerRequestTemperatures && checkingRequestTemperatures == false) {
startRequest = millis(); // not needed for your project

sensors.setWaitForConversion(false); // makes it async
sensors.requestTemperatures(); // Send the command to get temperatures
timerGetTempCByIndex = millis() + 750; // waits 750ms before attempting to read request results. Change at your own risk.
timerRequestTemperatures = millis() + intervalRequestTemperatures; // time to wait before requesting temperature
checkingRequestTemperatures = true; // enable get temperature routine.

endRequest = millis(); // not needed for your project

}
// Get temperature
if (millis() > timerGetTempCByIndex && checkingRequestTemperatures == true) {
startGetTemp = millis(); // not needed for your project

probeTemperature = sensors.getTempFByIndex(0); // read the temperature of the first probe in array.
checkingRequestTemperatures = false; // enable request temperature from probes routine.

endGetTemp = millis(); // not needed for your project
int timeRequest = endRequest - startRequest; // not needed for your project
int timeGetTemp = endGetTemp - startGetTemp; // not needed for your project
int timeTotal = timeRequest + timeGetTemp; // not needed for your project
Serial.println("request + getTemp = Total"); // not needed for your project
Serial.print(" "); // not needed for your project
Serial.print(timeRequest); // not needed for your project
Serial.print("ms + "); // not needed for your project
Serial.print(timeGetTemp); // not needed for your project
Serial.print("ms = "); // not needed for your project
Serial.print(timeTotal); // not needed for your project
Serial.println("ms"); // not needed for your project

Serial.print("Temperature = "); // not needed for your project
Serial.print(probeTemperature); // not needed for your project
Serial.println("F\n"); // not needed for your project
}

}

read_temp_probes_fast.ino (3.71 KB)

As my first attempt at creating a library for “public consumption”, I’ve written a wrapper for the Arduino Temperature Control Library (aka Dallas Temperature).

This wrapper library automatically catalogs all DS18xxx-type devices on the OneWire bus and stores their address. This is so the devices addresses can be used directly when communicating with the sensors rather than their indices (which is slower due to having to scan the OneWire bus every time). But, the user only need supply the index, not remember the address. Temperature sensor indices are always sequential starting at 0 even if there are other types of OneWire devices on the bus with intervening addresses.

Finally, this wrapper library is easy to use in non-block mode, allowing the main application code to continue to do useful things while the temperature measurement / conversion process is taking place simultaneously on multiple devices. This conversion time can be up to 750 ms when 12-bit resolution is used.

An example program is provided.

Here’s the wrapper library:

gfvalvo:
.......... allowing the main application code to continue to do useful things while the temperature measurement / conversion process is taking place simultaneously on multiple devices. This conversion time can be up to 750 ms when 12-bit resolution is used.

OK. You have gone to all this trouble, and I don't see what it is about.
I fear I am missing something, as I understood that the DS18B20 conversion process is independent of the MCU operations. It gives up a reading and immediately gets on with aquiring the next, irrespective of what is going on around it, and makes no demand on the MCU. All that is required is that you don't make any demand on it until it is ready to deliver. In the meantime, Arduino gets on with doing useful things, like storing, displaying, and communicating, without having to worry about what is going on with the DS18B20s.

Nick_Pyner:
OK. You have gone to all this trouble, and I don't see what it is about.
I fear I am missing something, as I understood that the DS18B20 conversion process is independent of the MCU operations. It gives up a reading and immediately gets on with aquiring the next, irrespective of what is going on around it, and makes no demand on the MCU. All that is required is that you don't make any demand on it until it is ready to deliver. In the meantime, Arduino gets on with doing useful things, like storing, displaying, and communicating, without having to worry about what is going on with the DS18B20s.

Firstly, that understanding is somewhat incorrect. The device only starts a temperature measurement / conversion cycle when instructed to do so, not immediately or automatically after the last read. After the cycle is started, the user must wait until it’s completed before reading the results. Determining how long to wait can be done two ways:

  • Wait the number of ms specified in the data sheet (depends on resolution selected).

  • Poll the OneWire bus line watching for the device(s) to release it (not applicable in parasite power mode).

Second, the default operating mode for the Dallas Temperature library is to Block (i.e. not return immediately to the calling code) during the measurement process. As stated, that can take up to 750ms. I’ve seen many posts on this forum with confused people not understanding why their code stops recognizing buttons, blinking LEDs, etc during this blocking time. The wrapper I wrote makes sure things are set up and operate in non-blocking mode. It also stores the most recent temperature reading for each device and returns that immediately if there’s a measurement in progress. The next user request subsequent to the device(s) finishing will read and store fresh value(s).

Third, just about every DS18B20 code example posted on this forum by newbies has used the Dallas Library’s requestTemperaturesByIndex(), getTempCByIndex(), and getTempFByIndex() methods. Sometimes they call getTempCByIndex() and getTempFByIndex() right after each other. That’s a very inefficient way of doing things. The Dallas Library code must scan the OneWire bus every time to determine the address associated with the indexed device. Then, it must issue more OneWire transactions using that address to accomplish the desired actions. These OneWire transactions are relatively slow. So, the wrapper library stores the OneWire addresses when initialized with the begin() method and uses them as needed. The user code doesn’t need to know or store these addresses, so it can continue to use the simpler index method and let the wrapper provide the OneWire address.

Finally, the above issues worsen when newbies try to use multiple temperature sensor on the OneWire bus. I’ve seen some pretty ugly and inefficient code posted here where significant time is spent blocking the main application due to poor use of the Dallas Library’s methods. The problem is even worse when the newbie tries to read the temperature EVERY time through loop(). That's why the example I provided shows how to set the timing using a millis() timer.