i work on a termometer with 18b20, i read the temp by a variable and send it to the display.
but during the Temperature Reading Time (750ms on 12bit) the display is empty because the variable with the temp readed waiting the 750ms time for new reading.
Is there a way for using Arduino in parallel ?
1 process: reading temp
2 process: repeat for 750ms the last temp on the display
Yes. Use the Blink Without Delay example for how to schedule things. Send out the command to start a temperature conversion. 750 milliseconds later, send the command to read the scratchpad. Store the temperature in a global variable. Go back to sending out the command to start a new conversion. When you want to update the display just take the temperature from the global variable. It won't be very old.
thanks for the answer,
please look if i understand tips, this is the code that i used but do not work, the result is the same, my display are off during the 750ms conv getting.
temp is my global variable
void loop(void)
{
sensors.requestTemperatures(); // Send the command to get temperatures
// blink without delay technique
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > interval) {
previousMillis = currentMillis;
temp=sensors.getTempCByIndex(0);
}
Problem is the code will start a conversion every time through loop(). You want to start a new conversion AFTER you fetch the results of the last conversion:
void setup()
{
previousMillis = 0;
sensors.requestTemperatures(); // Send the command to get temperatures
}
void loop(void)
{
// blink without delay technique
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > 750)
{
previousMillis = currentMillis;
temp=sensors.getTempCByIndex(0);
sensors.requestTemperatures(); // Send the command to get temperatures
}
}
this is complete code, visualizzazione is subroutine for display the value, it is correct because i use it in other code with other sensor.
#include <OneWire.h>
#include <DallasTemperature.h>
// Data wire is plugged into port 16 (A2) on the Arduino
#define ONE_WIRE_BUS 16
// 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);
// variabili temp
int t1,t2,t3;
float temp;
long previousMillis = 0;
void setup()
{
sensors.begin();
sensors.setResolution(12);
sensors.requestTemperatures(); // Send the command to get temperatures
}
void loop(void)
{
// blink without delay technique
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > 750)
{
previousMillis = currentMillis;
temp=sensors.getTempCByIndex(0); // current temperature to temp variables
sensors.requestTemperatures(); // Send the command to get temperatures
}
t1=(int)(temp/10);
t2=(int)(temp-t1*10);
t3=(int)(temp*10)%10;
visualizzazione ();
}
Ah, found some of my code for driving this chip - you should be able to use start_conversion() and read_conversion_result() separately to drive the DS18B20 asynchronously. You might want to suggest to the DallasTemperature library maintainer to add asynchronous conversion...
#include "Wire.h"
#include "OneWire.h"
#define DS18B20_PIN 8
OneWire ds(DS18B20_PIN) ;
byte addr[8];
void setup_tempsense ()
{
if (!ds.search (addr))
{
Serial.println("No more addresses.") ;
ds.reset_search () ;
delay (250) ;
return ;
}
Serial.print ("R=") ;
for (byte i = 0 ; i < 8 ; i++)
{
Serial.print (addr[i], HEX) ;
Serial.print (" ") ;
}
Serial.println () ;
long unique = 0L ;
for (byte i = 6 ; i >= 1 ; i--)
{
unique = (unique << 8) | addr [i] ;
}
Serial.print ("Unique=") ; Serial.println (unique, HEX) ;
if (OneWire::crc8 (addr, 7) != addr[7])
{
Serial.println ("CRC is not valid!") ;
return ;
}
if (addr[0] != 0x28)
{
Serial.println ("Device is not a DS18B20 family device.") ;
return ;
}
int temp = read_temp () ;
Serial.print (((float) temp) * 0.0625) ;
Serial.println ("C") ;
}
int start_conversion ()
{
// The DallasTemperature library can do all this work for you!
ds.reset () ;
ds.select (addr) ;
ds.write (0x44) ; // start conversion, with parasite power on at the end
}
int read_conversion_result ()
{
byte present = ds.reset () ;
ds.select (addr) ;
ds.write (0xBE) ; // Read Scratchpad
byte data[12];
for (byte i = 0 ; i < 9 ; i++) // we need 9 bytes
{
data[i] = ds.read();
}
int temp = (data [1] << 8) | data[0] ;
return temp ;
}
int read_temp ()
{
start_conversion () ;
delay (800) ; // maybe 750ms is enough, play safe
return read_conversion_result () ;
}
void setup ()
{
Serial.begin (57600) ;
setup_tempsense () ;
}
void loop ()
{
float degC = (float) read_temp () ;
degC *= 0.0625 ;
Serial.println (degC) ;
delay (2000) ;
}
I still don't really understand the problem, partly because I can't see the code. Since it takes 750ms to read the temperature, it's only going to change every 750ms, so why do you need to keep updating the display more rapidly? Is it a device that needs continuous refresh? If so, MarkT appears to have your solution.
MarkT the code do not work, i tried it with serial monitor, changing only the #define DS18B20_PIN 8 to 16, there is other changing to do ? I receive a fixed 85 degree every 2sec.
the last Dallas Library added async, if I understand, the link is here, but there is no example to use it MilesBurton.com
If the Dallas library doesn't support asynchronous starting of the conversion, just don't use it. The chips are easy enough to talk to:
#include <OneWire.h>
// how many milliseconds between grabbing data and logging it. 1000 ms is once a second
#define LOG_INTERVAL 10000 // mills between entries (reduce to take more/faster data)
unsigned long LastLogTime = 0;
// Fault flags
extern const unsigned int ITemp_fault;
extern const unsigned int ETemp_fault;
extern unsigned int Faults;
// DS18S20 Temperature chip I/O
const int ONEWIRE_PIN = 9;
OneWire DS18S20(ONEWIRE_PIN);
// Can't make them const because the OneWire library doesn't take const. :(
byte InteriorThermometer[8] = {
0x28, 0x95, 0xB9, 0x1D, 0x03, 0x00, 0x00, 0xB9};
byte ExteriorThermometer[8] = {
0x28, 0xA9, 0x9E, 0x1D, 0x03, 0x00, 0x00, 0x80};
unsigned long lastTempConversionTime = 0;
void setup(void)
{
Serial.begin(9600);
Thermometers_setup();
}
void loop(void)
{
unsigned long currentTime = millis();
Thermometers_loop(LastLogTime, LOG_INTERVAL);
if (currentTime - LastLogTime < LOG_INTERVAL)
return;
/// Data Logging Starts Here
LastLogTime = currentTime;
Thermometers_log(Serial);
Serial.println();
}
void Thermometers_setup(void)
{
}
void Thermometers_loop(unsigned long lastLogTime, unsigned long logInterval)
{
unsigned long currentTime = millis();
// One second before logging, start the thermometers converting,
// as long as it has been more then two seconds since the last conversion
if ((currentTime - lastLogTime >= (logInterval - 1000)) &&
(currentTime - lastTempConversionTime > 2000))
startThermometers();
}
void Thermometers_log(Print &dest)
{
// Now read the temperatures
float i_temperatureC = readThermometer(InteriorThermometer);
float e_temperatureC = readThermometer(ExteriorThermometer);
dest.print(i_temperatureC, 3);
dest.print(", ");
dest.print(e_temperatureC, 3);
}
void startThermometers()
{
lastTempConversionTime = millis();
DS18S20.reset();
DS18S20.write(0xCC); // Address all thermometers
DS18S20.write(0x44); // start conversion, no parasite power on at the end
}
float readThermometer(byte addr[8])
{
byte data[9];
float temperature_C;
DS18S20.reset();
DS18S20.select(addr);
DS18S20.write(0xBE); // Read Scratchpad
for (int i = 0; i < 9; i++)
data[i] = DS18S20.read();
if (data[5] != 0xFF || data[7] != 0x10)
{
return 999.999;
}
if ( OneWire::crc8( data, 8) == data[8])
{ // CRC is valid
int temperature = (data[1] << 8) + data[0]; // Two byte binary temperature in °C/16
// Serial.println(temperature, HEX);
temperature_C = temperature / 16.0;
}
else
{
return 999.999;
}
return temperature_C;
}
//
// 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)); // resolution = {9,10,11,12} // delayInMIllis = 94 << (resolution-9); // gives 94, 188, 376, 752 faster but a bit less exact
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);
// this part will print it at the push of a button
if (digitalRead(BUTTONPIN) == LOW)
{
Serial.println(temperature);
}
}
now i'm very close to the solution,
mix the two tip by john and markt i'm now have only little bit of display off problem,
befoure i had 750ms of black, now i think only 20ms.
what do you think, where are it from ? conversion time ?
this is actual loop
void loop(void)
{
// blink without delay technique
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > 750)
{
previousMillis = currentMillis;
temp=sensors.getTempCByIndex(0); // mette la temperatura nella variabile temp
sensors.setWaitForConversion(false); // makes it async
sensors.requestTemperatures(); // Send the command to get temperatures
}
unsigned long previousMillis = 0; // must be outside loop
float temp = 0.0;
// UPDATED
int timeout = 94 << (resolution - 9); // calc the timeout for every resolution between 9..12 automatically
void loop(void)
{
if (millis() - previousMillis > timeout)
{
temp = sensors.getTempCByIndex(0);
sensors.setWaitForConversion(false); <<<<<<<< strictly not needed every time
sensors.requestTemperatures();
previousMillis = millis(); <<<<<<<<<<<<<<< moved
}
Serial.println(temp, 2);
}
I tried normal power supply mode but the problem remain the same
this is the actual code
#include <OneWire.h>
#include <DallasTemperature.h>
// Data wire is plugged into port 16 (A2) on the Arduino
#define ONE_WIRE_BUS 16
// 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);
// variabili temp
float temp;
long previousMillis = 0;
void setup()
{
sensors.begin();
sensors.setResolution(12);
sensors.setWaitForConversion(false); // makes it async asincrono=non blocca il programma durante la lettura
sensors.requestTemperatures(); // Send the command to get temperatures
}
void loop(void)
{
// blink without delay technique. Il delay normale blocca il processore, questo no
if (millis() - previousMillis > 750) // mette la temperatura nella variabile temp dopo 750ms
{
temp=sensors.getTempCByIndex(0);
sensors.requestTemperatures(); // riparte una nuova richiesta, ma solo dopo, e non prima come facevo all'inizio
previousMillis = millis(); // riparte il temporizzatore
}