[SOLVED] 18B20 timing problem

I modified your code a bit:

  • added two lines in setup() for a proper start

  • moved the serial.print(temp) into the conditional part (so only print after a new reading, to not get flooded with values)

  • commented out this same serial.println(temp) as that causes the tx led to blink

  • LED 13 blinks after every read (just to see that the code still works)

==> I have no blinking tx LED at my Arduino 2009 (no UNO nearby)

Please try this code..

#include <DallasTemperature.h>
#include <OneWire.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);

float temp;
long previousMillis = 0; 

void setup(void)
{
  pinMode(13, OUTPUT);
  sensors.begin();
  sensors.setResolution(12);
  sensors.setWaitForConversion(false);  // makes it async asincrono=non blocca il programma durante la lettura
  Serial.begin(9600);

  sensors.requestTemperatures(); // Send the command to get temperatures
  previousMillis = millis();
}

void loop(void)
{ 
  if (millis() - previousMillis > 750)   // mette la temperatura nella variabile temp dopo 750ms
  {
    temp = sensors.getTempCByIndex(0);
    sensors.requestTemperatures(); // Send the command to get temperatures
    previousMillis = millis(); // riparte il temporizzatore
    digitalWrite(13, !digitalRead(13));
    // Serial.println(temp); 
  }
}

Did some poking & tweaking in the Dallas Library to optimize fetching the temperature only. To be applied as previous specified. The comments give the hard coded delays of the wire class.

// EXPERIMENTAL
void DallasTemperature::readScratchPadFast(uint8_t* deviceAddress, uint8_t* scratchPad) 
{
  // send the command                       
  _wire->reset();                                //  1.5 millis 
  if (devices > 1) _wire->select(deviceAddress);  // command + 8 bytes == 9 * 0.6 = 5.4 millis.
  else _wire->skip();                          // 1 Byte = 0.6 millis.  // needed for 1 device 

  _wire->write(READSCRATCH);          // 1 BYTE = 0.6 millis
  scratchPad[0] = _wire->read();         // read only the temperature bytes 
  scratchPad[1] = _wire->read();         // 2 * 0.6 = 1.2 millis
}

Results sofar one sensor:

  1. readScratchPad() sensors.getTempCByIndex(0); takes 28 millis()
  2. readScratchPadFast() sensors.getTempCByIndex(0); takes 18 millis()

Results sofar two sensors:

  1. readScratchPad() sensors.getTempCByIndex(0); takes 28 millis()
  2. readScratchPadFast() sensors.getTempCByIndex(0); takes 23 millis()

Conclusion:
There is time to be gained, however to get more one probably need to dive into the wire lib.

disclaimer - code still experimental

i updated the .ccp but have always 28ms with 1 sensor
may send me your library ?

i used this code (sensor on pin16 (A2))

#include <DallasTemperature.h>
#include <OneWire.h>

// Data wire is plugged into port 2 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);

// temp variable
float temp;

void setup(void)
{
  sensors.begin();
  sensors.setResolution(12);
  sensors.setWaitForConversion(false);  // makes it async asincrono=non blocca il programma durante la lettur
  Serial.begin(9600);
}


void loop(void)
{ 
 unsigned long before = millis();
 temp = sensors.getTempCByIndex(0);
 Serial.println(millis() - before);
}

i updated the .ccp but have always 28ms with 1 sensor
may send me your library ?

sorry but no, too much (other) experimental code in it. As soon as it is stable I'll get it incorporated in the official library.

I went through my previous post and found this bug (sorry)

// EXPERIMENTAL
bool DallasTemperature::isConnected(uint8_t* deviceAddress, uint8_t* scratchPad)
{
  readScratchPad(deviceAddress, scratchPad);  <<<<<<<<<<< should be readScratchPadFast(deviceAddress, scratchPad); of course
  return true;
}

Explains why you still get 28 millis, it is experimental code (no guarantees :wink:

(I'll fix the code in the prev post too) done

always 28ms

i have dallas 3.7.1 on onewire2 whit no other change, if you want i may send you the two library for check ?

i think this work is important because 18ms off is not interpretable by human eyes and this mean using 18B20 in realtime temp reading

i think this work is important because 18ms off is not interpretable by human eyes and this mean using 18B20 in realtime temp reading

The reading of the sensor took 18 ms, but I had to wait 750ms before conversion was ready ....

You can attach your library as a zip file (See additional options), if time permits I can have a look

I attached the files,

i know the 750ms delay, but my idea of "real time temp" derived from display used.
My display work on BCD, so arduino pick the TEMP variable from gettempbyindex, convert in bcd, and send this to display.

So during 750ms conversion time arduino convert always the same value to bcd (no problem), but during the GetTempByIndex we need 28ms, and during this 28ms the TEMP variable is empy, so NO BCD CONVERSION, so display off.

DallasTemperature_371Beta.zip (23.3 KB)

So during 750ms conversion time arduino convert always the same value to bcd (no problem), but during the GetTempByIndex we need 28ms, and during this 28ms the TEMP variable is empy, so NO BCD CONVERSION, so display off.

I don't understand your code logic from what you write. You should just keep on displaying the last temperature until the GetTemperatureByINdex is ready

Can you post the latest code of your sketch?

Your patched library looks OK.

all my code derived from arduinix project, the code is very long if you want go to the official site.

it is a clock that need BCD , the BCD value need to bo always present, example if i use a delay of 1000ms, it block the BCD routine, and the display is off.

My idea is, but no people explain me if it is true or not, that during our famous 28ms the TEMP variable is Empty or Not Accessible. It is true ?

It is a basic question, but hard for me because I came from the electronic world, not sw.

Don't know the Arduinix project, if you want people to look there you might provide an URL or so.

it is a clock that need BCD

What is BCD ? Binary Coded Decimal?

My idea is, but no people explain me if it is true or not, that during our famous 28ms the TEMP variable is Empty or Not Accessible. It is true ?

not true. (not seen the code so all disclaimers apply :wink:

A variable will keep its value until it is changed OR goes out of scope. A variable can't be empty, technically speaking there is allways content, defined or undefined.

Software takes time to execute, every single statement takes time.
The Arduino can only do one thread at the time (and IRQ's )

So the statement
TEMP = getTempCByIndex(0);
will take 28 ms, but only in the last microsecond the value of TEMP will change.
When the processor is executing getTempCByINdex(), the variable TEMP can not be accessed by other routines except for interrupt routines as the Arduino is single threaded.

Hope this explanation is clear to you.

Q: How often do you refresh your display?
You only need to refresh the parts that have changed!
So the whole 28ms the "old" value of TEMP should be left unchanged on the display, just like in the other 750 ms.

this is the arduinix code that i used, http://arduinix.com/Main/Code/Arduinix-6bulb-clock-demo.txt

the display is updated every milliseconds by bcd (yes binary coded decimal)

in your explanation:
"executing getTempCByINdex(), the variable TEMP can not be accessed by other routines"

-- this means that it is not possible access TEMP for 28ms or for 1 microsecond ?

thanks

in your explanation:
"executing getTempCByINdex(), the variable TEMP can not be accessed by other routines"

-- this means that it is not possible access TEMP for 28ms or for 1 microsecond ?

28 milliseconds.

I ran the Arduinix code (don't have nixies ) and the display is written approx every 10 milliseconds, so to calculate and display the time 10 millis is needed, That means that the display does not go off if you are calculating...

Can you add delay(50); before this line DisplayNumberString( NumberArray ); in loop(); // at the end of the sketch

Does that still display time correctly?

If so the delay for getTempCByIndex() should work.

Rob

NO
the time is blocked, blinking.

so this demonstrate that my diagnosis is good ? Is the 28ms the problem because during this 28ms the variable TEMP it is not accessible, are you agree ?

option 1: decrease the gettemo needed time (no other sw solution is possible because the 28ms block the bcd calculation)
option 2: hardware solution, external latch ?
option 3: change the sensor, with one analogic like lm35 ? (analogic sensor do not have long calculating time right ? the value it is always present)

so this demonstrate that my diagnosis is good ?

No, it shows that the Arduinix sketch need to refresh very often to keep the nixies displaying constantly, that is the cause. By lowering the value of the inserted delay() from 50 to 0 in a few steps you can find out how much time you have to do calculations for TEMP.

Try the following values for delay 50,40,30,25,20,15,10,5 and report what delay is acceptable and what not.

Current the math for the time is approx 10 millis which shows no dimming. I have not investigated WHY nixies in this Arduinix sketch behave that way, maybe due to multiplexing? Don't know. There is a delay(3) in the code that must be executed otherwise they will not light up. (change this to 5? 10? what happens)

Is the 28ms the problem because during this 28ms the variable TEMP it is not accessible, are you agree ?

No I do not agree. The main cause is the Arduinix code

Again: The variable TEMP is perfectly accessible, that is not the point. The point is the Arduino can only do one thing at the time, it is single tasking at best. It can't keep displaying 100(?) times per second a string and do one calculation that takes 28 millisecond.

Solution: Don't use the Dallas Temperature Control Library. Develop code (all needed steps are available in the DTCLib) in which you have split this 28ms function in smaller chunks, chunks of max 10 ms. and execute these smaller chunks between rewrites

do part 1 ; display ;l do part 2 ; display; do p[art 3 ; display; etc.

The way to fix the problem is to make the nixie tube update code interrupt driven. Just set up TimerCounter2 to interrupt every few milliseconds and each interrupt, update a digit. Then you can change the digits any time.

Perfect idea John!!

why didn't I think of that :wink: this also means a serious rewrite.

x rob: i'm agree with you,
when i tell "the problem is 28ms" i know that it is only "one side" of problem.
the very-speedy refresh of display is the "other side".
the important is that now, thanks to you and other, i know which is the problem.
understand that arduino is single task it is very important for me.

if i understand your idea is: the gettempbyindex command is created by more single command, i must use all of them mixed with display visualization subroutine.

x john: your tips is too mutch for me, i need study what means code interrupt driven. do you have a link ? i'm new to the programming side, i came from electronic side of game :slight_smile:

thanks

Startpoint for IRQ's - http://www.arduino.cc/en/Reference/AttachInterrupt -

robtillaart:
Startpoint for IRQ's - http://www.arduino.cc/en/Reference/AttachInterrupt -

Hmmm... That page for attachInterrupt() only talks about EXTERNAL interrupts. Does it not deal with timer/counter interrupts?