Go Down

Topic: DS18B20 750ms delay bypass? (Read 8 times) previous topic - next topic

robtillaart

The DS18S20 has a fixed resolution of 9 bits, so setting the resolution won't help. The B series can be set from 9-12 bit.

In  WaitingForConversion2.pde first a conversion request is send to the DS18B20, the sketch continues while the temp sensor does the conversion.
In the sketch a timeflag is set when thelast Request was done and the needed delay is calculated.

Code: [Select]

  sensors.setWaitForConversion(false);
  sensors.requestTemperatures();
  delayInMillis = 750 / (1 << (12 - resolution));
  lastTempRequest = millis();


In loop() it is checked if this delayInMillis miliseconds has passed before the temperature is fetched from the sensors. In the meanwhile one can do other things. In the example it increases just a counter. You could check if your Button is pressed and hold that in a state variable.

Quote
I'd still be interested if there was less codely way of using the scratchpad to effectively elimination the delay/lag, but for now I'm happy.

The DS18 series need conversion time (There is an ADC within the sensor that need to stabilize) and the asynchronuous method gives you most degrees of freedom.

The sketch below fetches the temperature continuously in the async way so it takes relatively little time. When the button is pressed there is allways an actual temperature available.
Code: [Select]

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

// button
#define BUTTONPIN 4


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

  // initialization
  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)
{
  // this part keeps the var temperature up to date as possible.
  if (millis() - lastTempRequest >= delayInMillis) // waited long enough??
  {
    digitalWrite(13, LOW);
    temperature = sensors.getTempCByIndex(0);
    sensors.requestTemperatures();
    lastTempRequest = millis();
  }
  digitalWrite(13, HIGH);
 
  if (digitalRead(BUTTONPIN) == LOW)
  {
    Serial.println(temperature);
  }
}
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Molehs

My mistake I have DS18B20s. I basically drag and dropped your code in and it does seem to work very well, short of it is only pulling the first temp. The parasitic temps are not returning proper values.

My sketch is constantly displaying the current temps and the buttons change the pages of the menu. Previously the menu buttons would fail to do anything, assuming due to the conversion time, but now buttons work every time. So that is really good, just need to tweak it so that the other temps are displayed properly.

robtillaart


make temperature an array with 5 elements and fetch all 5 of them in a for loop()

Code: [Select]

  // this part keeps the var temperature up to date as possible.
  if (millis() - lastTempRequest >= delayInMillis) // waited long enough??
  {
    digitalWrite(13, LOW);
    for (int i=0; i< 5; i++)  temperature[i] = sensors.getTempCByIndex(i);  // <<<<<<<<<<<<<<<<<<<<
    sensors.requestTemperatures();
    lastTempRequest = millis();
  }
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Molehs

Why, originally did I only need have this "sensors.requestTemperatures();" once in the loop and the all the temps were pulled just fine. But now that it's part of the IF statement it only pulls the first one? Placing the values in an array doesn't really work for me because all of my code is based on each address already having a specific variable name.

If I comment out the getTempCByIndex line, either with the for loop or not, it still only populates the first probes temp. It's almost as if the way it's running it ignores all the parasites. It knows if they are plugged in because I get 185 F if they are in and -196.9 F if they are not...

Jack Christensen

#9
May 22, 2011, 09:04 pm Last Edit: May 22, 2011, 09:13 pm by Jack Christensen Reason: 1

Would you mind sharing your code for that section? If I had a 2nd example of how to code that it would be easier for me to decipher.


I've copied-and-pasted the pertinent code from a much larger sketch, so this is not guaranteed to run verbatim, but should give the general idea. Note that I am using the DS18B20, not DS18S20. (Too easy to miss that!) HTH.

Code: [Select]

#include <OneWire.h>           //http://www.pjrc.com/teensy/td_libs_OneWire.html
#include <Wire.h>              //http://arduino.cc/en/Reference/Libraries
#include <Time.h>              //http://www.arduino.cc/playground/Code/Time
#include "DS1307RTC.h"         //http://www.arduino.cc/playground/Code/Time (declares the RTC variable)

time_t utcNow, utcLast;   //RTC is set to UTC
int utcH, utcM, utcS;   //utc time parts
OneWire  ds(dsPin);            //DS18B20 temperature sensor
int tF10;                      //temperature from DS18B20    

...

void loop(void) {
   utcNow = now();
   if (utcNow != utcLast) {           //once through here per second ought to be enough
       utcLast = utcNow;
       utcH = hour(utcNow);
       utcM = minute(utcNow);
       utcS = second(utcNow);
       readTemperature();
}

/*-------------------------------------------------------------*
* Start the temperature conversion at second 55, read it back *
* at second 56.                                               *
*-------------------------------------------------------------*/
int readTemperature() {
   byte dsData[12];

   if (utcS == 55) {
       ds.reset();
       ds.skip();
       ds.write(0x44);        //start temperature conversion
   }

   if (utcS == 56) {
       ds.reset();
       ds.skip();
       ds.write(0xBE);        //read scratchpad

       for ( int i=0; i<9; i++) {    //read 9 bytes
           dsData[i] = ds.read();
       }
       if (OneWire::crc8( dsData, 8) == dsData[8]) {
           tF10 = tempF_DS18B20(dsData[1], dsData[0]);
           haveTemperature = true;
       }
       else {
           Serial.print(" CRC ERR");
       }
   }
}

int tempF_DS18B20(byte tempMSB, byte tempLSB) {
   /* Convert 12-bit °C temp from DS18B20 to an integer which is °F * 10    *
    * Jack Christensen 30Jan2011                                            */

   int tC16;        //16 times the temperature in deg C (DS18B20 resolution is 1/16 °C)
   int tF160;       //160 times the temp in deg F (but without the 32 deg offset)
   int tF10;        //10 times the temp in deg F

   tC16 = (tempMSB << 8) + tempLSB;
   tF160 = tC16 * 18;
   tF10 = tF160 / 16;
   if (tF160 % 16 >= 8) tF10++;        //round up to the next tenth if needed
   tF10 = tF10 + 320;                  //add in the offset (*10)
   return tF10;
}
MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

Go Up