Can't get two ds18b20 sensors read on different pins

...I guess the trick here would be keeping it from continuously restarting once 60C is hit. Damn, I forgot about that part.

I wish I could code code like that, maybe one day...!
I keep going back and trying to make sure I understand your posts, and there is one particular line that clicks now that I sort of get how time is handled. It's where you said " The startup to 60 degrees could be done in setup (), just a loop waiting on the sensor(s)". I would like to try doing that, even if it's just for the sake of learning how to do that. Am I understanding it correctly that you can make the program stop in the setup until certain conditions are met? If so, do you mind showing me what that would look like in my case? I'm going to do some googling on that, but I would appreciate any help you can give!

It is not usually necessary to reset a running sketch as part of its normal operation.

The solution in # too lazy to look right now showed one way. I beleive I suggested that such a method could in fact just be moved into setup() - just loop there continuously testing if the temperature was high enough to begin. At that point, grab the value of millis(); in subsequent caculations use the difference between now, the current value of millis(), and that start time, that is to say the elapsed time since 60 was hit.

a7

Haha, typing at the same instant.

You can't stop a charging elephant running sketch, but you sure as hope can make it spin its little wheels until something becomes true or some condition has changed. Last line in setup()

// all set to go but... it's too cold yet

  do {
      sensor = dallas stuff that gets the temperature
   } while (sensor < 60.0);

  startTime = millis();
}

It might be nice to do more than nothing, like post a spinning message saying "waiting for whatever" so ppl woukd know the sketch hadn't just died.

The sketch I posted code and a link to the simulation of which handles temperature differently throughout the process. I don't see how you can track Pasteurisation without integrating the net effect of temperature over time.

I offer again the example of having the process be at 60.00001 degree for a long time, then 90 degrees for the last minute… your simple monitoring woukd assert that 13 minutes at 90 degrees had been performed.

Unless this process just runs at or within narrow range. But monitoring should mean just that - watching time and temperature and adding bit by bit to a growing account of PUs.

I stress and admit I am making all this up. It's just how I hope a real process monitor woukd function. Call a fault if the temperature goes below 60.0. Account for minutes at higher or lower but still valid effective temperatures.

a7

...I'm having trouble using "while" in the setup() now. Keep getting following error: Compilation error: request for member 'readObjectTempC' in 'sensor2', which is of non-class type 'float' Maybe someone can show me what I'm missing in my code below please?
What I'm trying to do is have the program stop and wait in setup until the temperature on sensor2 reads 60 or more C. While the program is waiting I want it to actively display the read temperatures from both sensors just like further along in the program. The whole point of this is to have the elapsed time measured starting from after temp is =>60C which is done in the loop() code.



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

#define ONE_WIRE_BUS_A 2  // Define the input pin for the DS18B20 sensor1
#define ONE_WIRE_BUS_B 4 // Define the input pin for the DS18B20 sensor2
#define BUTTON_PIN 7

OneWire oneWireA(ONE_WIRE_BUS_A); // Setup a oneWire instance to communicate with the sensor
OneWire oneWireB(ONE_WIRE_BUS_B); // Setup a oneWire instance to communicate with the sensor

DallasTemperature sensorA(&oneWireA); // Pass the oneWire instance to DallasTemperature library
DallasTemperature sensorB(&oneWireB); // Pass the oneWire instance to DallasTemperature library

LiquidCrystal_I2C lcd(0x27, 20, 4); //First parameter is the I2C address. Second parameter is how many rows on the screen, 3rd parameter is how many columns on the screen.


int button1 = 7; //variable name "button1", value assigned is "7".
int buzzer = 9; //variable name "buzzer", value assigned is "9"
int timer = 0;
int buttonState = 0; // Define a variable to store the button state
float t = 0; //float is used to store a variable, in this case time in minutes as "t" since 60C< was reached
float T = 0; //Here float is used to store the temperature value from sensorB as "T"

float sensor1, sensor2; //Store value from sensor1, and sensor2
float PU = 0; //Store calculated PU value

void setup() {  //Setup Code goes here, to run once. void means that the actions contained will return no information to the larger program.
  
  lcd.init(); //Initialize the lcd screen
  lcd.backlight(); //Turn on lcd backlighting
  
  pinMode(9, OUTPUT); //set the mode of pin 9
  pinMode(7, INPUT_PULLUP); //set the mode of pin 7, and activate pullup resistor
  
  sensorA.begin(); //Begin reading sensor value
  sensorB.begin(); //begin reading sensor value
  
  sensor1 = sensorA.getTempCByIndex(0); //read the temp from sensor1
  sensor2 = sensorB.getTempCByIndex(0); //read the temp from sensor2

  lcd.setCursor(0, 0); //Where to start writing the following information
  lcd.print("Tank: "); //write "Tank:" to lcd screen
  lcd.print(sensor1); //write value from sensor1 to screen after "Tank"
  lcd.print(" C"); //write " C" to screen after sensor1 value

  lcd.setCursor(0, 1);  //Where to start writing the following information
  lcd.print("Can: "); //write "Can:" to lcd screen
  lcd.print(sensor2); //write value from sensor2 to screen after "Tank"
  lcd.print(" C"); //write " C" to screen after sensor2 value

  while (sensor2.readObjectTempC() < 60) { // wait until temperature is equal to or more than 60 degrees Celsius
  delay(100); // delay for 100 milliseconds
}

void loop() {  //main code goes here, to run repeatedly. void is used again because no information is returned to the larger program.
  
  //   request temperatures each bus
  sensorA.requestTemperatures(); // Request temperature readings from sensor1
  sensorB.requestTemperatures(); // Request temperature readings from sensor2
  sensor1 = sensorA.getTempCByIndex(0); //read the temp from sensor1
  sensor2 = sensorB.getTempCByIndex(0); //read the temp from sensor2

  buttonState = digitalRead(BUTTON_PIN);  //read the value from Button_PIN and save as value named "buttonstate"

  lcd.setCursor(0, 0); //Where to start writing the following information
  lcd.print("Tank: "); //write "Tank:" to lcd screen
  lcd.print(sensor1); //write value from sensor1 to screen after "Tank"
  lcd.print(" C"); //write " C" to screen after sensor1 value

  lcd.setCursor(0, 1);  //Where to start writing the following information
  lcd.print("Can: "); //write "Can:" to lcd screen
  lcd.print(sensor2); //write value from sensor2 to screen after "Tank"
  lcd.print(" C"); //write " C" to screen after sensor2 value

  if (buttonState == LOW) { // Check if read and saved buttonState is LOW (button pressed)
    
    noTone(buzzer); // Actions(s) to take if buttonState condition is true (LOW): Stop tone and reset PU value to 0
    PU = 0;
  
  

  // Check if temperature from sensor2 is less than 60 C
  if (sensor2 < 60) {
    // Display "PU=0" on line 3 of LCD
    lcd.setCursor(0, 2);
    lcd.print("PU 0");
  }
  else {
    // Calculate PU value using formula1
    t = millis() / 60000.0; // Convert milliseconds to minutes
    T = sensor2;
    PU = t * pow(1.393, ((T - 60) / T));

    // Display "PU" and calculated PU value on line 3 of LCD
    lcd.setCursor(0, 2);
    lcd.print("PU: ");
    lcd.print(PU);


    // Check if PU is 15 or more
    if (PU >= 15) {
      // Make beep tone on pin 9
      tone(buzzer, 300);
      delay(500);        // ...for 1 sec
      noTone(buzzer);     // Stop sound...
      delay(500);        // ...for 1sec
    }
  }

  
  }
}


// Code for reading DS18B20 sensors and displaying on LCD adapted from: https://create.arduino.cc/projecthub/TheGadgetBoy/ds18b20-digital-temperature-sensor-and-arduino-9cc806
// Code for calculating PU value adapted from: https://www.thermexcel.com/english/tables/thermophysical_properties/calculation_of_the_viscosity_of_water.htm

Just saw this post after I posted the other stuff. I agree on the things you are saying, and still trying to get my head wrapped around some of it. In my mind we need to keep taking snapshots of time and temperature at brief intervals, calculating PU accumulated in that snapshot, and adding that value to the previous snapshots resulting value until we get to 15 PU... and I think that's sort of what you're getting at as well, right? Because the way the formula is applied right now, the value generated by the equation is only based on the current data at any given moment vs. an accumulation of what has transpired.

Yes. That is exactly what the sketch I posted does.

Have you played with it in the simulation I linked?

a7

Sry, I just saw this

  while (sensor2.readObjectTempC() < 60) { // wait until temperature is equal to or more than 60 degrees Celsius
  delay(100); // delay for 100 milliseconds
} 

I don't know why you are getting the temperature with a different method. I can't test this just now, but it is simply what you got working before - request then get:

  do {
    sensorB.requestTemperatures(); 
    sensor2 = sensorB.getTempCByIndex(0); 
  } while (sensor2 < 60.0);

You could use a while loop. 1, the condition, is always true and we use the break statement as an alternate way to end the looping. Key obvsly in either is getting the temperature over end over until, viz:

  while (1) {
    sensorB.requestTemperatures(); 
    sensor2 = sensorB.getTempCByIndex(0); 

    if (sensor2 >= 60.0) break;
  }

and again, I've just noticed that you have some missing or wrong { braces }. I think. Use the IDE Autoformat tool, it can make seeing errors of this type easier to spot.

Note how the loop function is indented and tries to be part of setup() because you dropped a closing brace:

    lcd.print(sensor2);
    lcd.print(" C");

    while (sensor2.readObjectTempC() < 60) {
        delay(100); 
    }

    void loop() { 
        sensorA.requestTemperatures(); 

BTW comments are fine, I use them myself sometimes. But comments like
  delay(100); // delay for 100 milliseconds

and

      delay(500);        // ...for 1 sec
      noTone(buzzer);     // Stop sound...
      delay(500);        // ...for 1sec

aren't helpful even if they were accurate.

HTH

a7

Yes, I checked it out, ran it, now I'm working on understanding the mechanics of it and trying to apply it!

Okay, I see. "break" is another statement I haven't come across yet in my readings, thanks for that. I'm going to put that in my setup code and then try to apply what I learn from your other sketch. Fingers crossed I get it! I'm down to the last minute, lol!

With all the fiddling around and tweaking I've done in there it doesn't surprise me that things are a little screwy. Looks like I forgot to update the comments after I made changes in a few spots too!

So I managed to pick up a bit of your sketch, but truthfully some of it is over my head (damn ADhD). "const byte" is new to me. From what I understand its a newer form of # define and doesn't work with negative numbers. I'm not clear why you used it.

A thing I noticed in the simulation is that the PU's accumulate pretty fast. But I also didn't see the PU formula I'm using in my sketch.

Long story short, until I've had a chance to do more extensive learning, I'm going to struggle with understanding and implementing some of the elements.

As part of working through this all step by step, and at a pace that works for me, I want to play some more with what we're doing in the setup() portion. Obviously by stalling the program with:
`while (1) {
sensorB.requestTemperatures();
sensor2 = sensorB.getTempCByIndex(0);

if (sensor2 >= 60.0) break;

}`
...the program appears to have hung up to the onlooker. as part of showing some life, I'd like it to continue updating the two temperature readings while we wait for our wonderful 60C on sensor2. To do that, I think I would need some looping to happen in the setup (), which as we all know is only "do once". So what to do? Can I somehow put all that read temp and display stuff in with the "while" thingy?

You know the answer to this one! You have a spinning while loop in setup(), there are no restrictions on what you do in its body.

Request and get the temp (already did).
Print a nice message including the temperature and why nothing else is happening.

And maybe print a counter that you increment in the loop, so we see signs of life if the temp is unchanged.

Here a delay is harmless and appropriate, 100 milliseconds, whatever.

You could turn on an off an indicator LED and on exiting the loop leave it on.

This was drafted earlier:

Everyone does. Forget. That's one of the problems with comments! I usually strip them from code presented on these fora.

Comments are too often gratuitous, misleading, out of date or just obvsly wrong. There's an extreme view that suggests code should not need comments, I agree at least that line by line commentary is rarely helpful. For some of us more ink means a harder time to see the code - even without comments, code style can make code inviting to read or intimidating.

"Real" professional code by programmers can be just plain ugly. Some must think that it has to be that way.

A good description of what a function expects for inputs and what it produces for outputs or side effects and how it does that if it is not trivial can be useful.

a7

I actually went ahead and tried that earlier, and it worked! The other thing I did was just wire my lone pushbutton to the reset pin on the arduino, because trying to get the thing to work the way I want was ticking me off.

Anyways, the other thing I did was test the device with some hot water. I found that the speed at which PU's are accumulated is the same at 60C as at 90C, with the formula applied simply in it's native form. That led me to conclude that it's probably going to work good enough for now as is, and I've put it to work in the brewhouse. However, I did get a second UNO R3 board, and am going to continue trying to make it work with code from your sketch example. I think that is key to absolute accuracy. I'm also going to keep fiddling with that damn button until I've beat it into submission! I don't know why I'm having such a difficult time getting it to just clear the stored values and start over from scratch, and turn off the buzzer at the same time. I think I was pretty close earlier, but I ran out of time and had to go with what I had.

I don't see how that is possible. If you'd like, post the code that works well enough to brew with.

And assure me I am in no way going to be drinking any of that. :expressionless:

a7

Lol, I don't understand it either! I was certain that if I cranked the heat the PU's would accumulate faster! Anyways, here's the code:



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

#define ONE_WIRE_BUS_A 2  // Define the input pin for the DS18B20 sensor1
#define ONE_WIRE_BUS_B 4  // Define the input pin for the DS18B20 sensor2
#define BUTTON_PIN 7

OneWire oneWireA(ONE_WIRE_BUS_A);  // Setup a oneWire instance to communicate with the sensor
OneWire oneWireB(ONE_WIRE_BUS_B);  // Setup a oneWire instance to communicate with the sensor

DallasTemperature sensorA(&oneWireA);  // Pass the oneWire instance to DallasTemperature library
DallasTemperature sensorB(&oneWireB);  // Pass the oneWire instance to DallasTemperature library

LiquidCrystal_I2C lcd(0x27, 20, 4);  //First parameter is the I2C address. Second parameter is how many rows on the screen, 3rd parameter is how many columns on the screen.


int button1 = 7;  //variable name "button1", value assigned is "7".
int buzzer = 9;   //variable name "buzzer", value assigned is "9"
int timer = 0;
int buttonState = 0;  // Define a variable to store the button state
float t = 0;          //float is used to store a variable, in this case time in minutes as "t" since 60C< was reached
float T = 0;          //Here float is used to store the temperature value from sensorB as "T"

float sensor1, sensor2;  //Store value from sensor1, and sensor2
float PU = 0;            //Store calculated PU value

void setup() {  //Setup Code goes here, to run once. void means that the actions contained will return no information to the larger program.

  lcd.init();       //Initialize the lcd screen
  lcd.backlight();  //Turn on lcd backlighting

  pinMode(9, OUTPUT);        //set the mode of pin 9
  pinMode(7, INPUT_PULLUP);  //set the mode of pin 7, and activate pullup resistor

  sensorA.begin();  //Begin reading sensor value
  sensorB.begin();  //begin reading sensor value

  sensor1 = sensorA.getTempCByIndex(0);  //read the temp from sensor1
  sensor2 = sensorB.getTempCByIndex(0);  //read the temp from sensor2

  

  while (1) {
    sensorA.requestTemperatures();
    sensorB.requestTemperatures();
    sensor1 = sensorA.getTempCByIndex(0);
    sensor2 = sensorB.getTempCByIndex(0);
    lcd.setCursor(0, 0);  //Where to start writing the following information
    lcd.print("Tank: ");  //write "Tank:" to lcd screen
    lcd.print(sensor1);   //write value from sensor1 to screen after "Tank"
    lcd.print(" C");      //write " C" to screen after sensor1 value

    lcd.setCursor(0, 1);  //Where to start writing the following information
    lcd.print("Can: ");   //write "Can:" to lcd screen
    lcd.print(sensor2);   //write value from sensor2 to screen after "Tank"
    lcd.print(" C");      //write " C" to screen after sensor2 value
    lcd.setCursor(0, 2);
    lcd.print("PU 0");
    if (sensor2 >= 60.0) break;
  }
}
void loop() {  //main code goes here, to run repeatedly. void is used again because no information is returned to the larger program.

  //   request temperatures each bus
  sensorA.requestTemperatures();         // Request temperature readings from sensor1
  sensorB.requestTemperatures();         // Request temperature readings from sensor2
  sensor1 = sensorA.getTempCByIndex(0);  //read the temp from sensor1
  sensor2 = sensorB.getTempCByIndex(0);  //read the temp from sensor2

  buttonState = digitalRead(BUTTON_PIN);  //read the value from Button_PIN and save as value named "buttonstate"

  lcd.setCursor(0, 0);  //Where to start writing the following information
  lcd.print("Tank: ");  //write "Tank:" to lcd screen
  lcd.print(sensor1);   //write value from sensor1 to screen after "Tank"
  lcd.print(" C");      //write " C" to screen after sensor1 value

  lcd.setCursor(0, 1);  //Where to start writing the following information
  lcd.print("Can: ");   //write "Can:" to lcd screen
  lcd.print(sensor2);   //write value from sensor2 to screen after "Tank"
  lcd.print(" C");      //write " C" to screen after sensor2 value

  
  


  // Check if temperature from sensor2 is less than 60 C
  if (sensor2 < 60) {
  // Display "PU=0" on line 3 of LCD
    lcd.setCursor(0, 2);
    lcd.print("PU 0");
  }
  else {
    // Calculate PU value using formula1
    t = millis() / 60000.0;  // Convert milliseconds to minutes
    T = sensor2;
    PU = t * pow(1.393, ((T - 60) / T));

     // Display "PU" and calculated PU value on line 3 of LCD
      lcd.setCursor(0, 2);
      lcd.print("PU: ");
      lcd.print(PU);
    }

   // Check if PU is 15 or more
  if (PU >= 15) {
    // Make beep tone on pin 9
    tone(buzzer, 300);
   delay(500);
  }     
       
  
  }



// Code for reading DS18B20 sensors and displaying on LCD adapted from: https://create.arduino.cc/projecthub/TheGadgetBoy/ds18b20-digital-temperature-sensor-and-arduino-9cc806
// Code for calculating PU value adapted from: https://www.thermexcel.com/english/tables/thermophysical_properties/calculation_of_the_viscosity_of_water.htm

The code is not actually accumulating PUs.

This, when the temperature is greater than or equal to 60

        t = millis() / 60000.0;  // Convert milliseconds to minutes
        T = sensor2;
        PU = t * pow(1.393, ((T - 60) / T));

calculates t, minutes since reset or reboot - including the warmup time elapsed spinning in setup().

Then it calculates PU as if the temperature had been sensor2 all that time.

So the PU at any instant will depend on the temperature at that instant and how long it has been until that time. There is no way that holding 62 is going to produce the same result as holding 67.

Meanwhile, Some sites use your formula, but I find sites that use the equation

PU = t * 1.393 ^ (T−60)

So I am confused. You might want to check your sources. You should account for the warmup time. Try some values in a spreadsheet and if your code is making different numbers we needa find out why.

Lastly, I can't help but repeat the idea that you really want to measure over small periods, each of which will add some PUs to the growing total.

I did place both formulae into a spreadsheet. Notice how your PU for one minute barely changes as the temp goes from 60 to 90 (formula 2) while the other one I found shows a distinct and frankly wild increase (formula 1):

base formula 1 formula 2
1.393 60
temperature T - 60 (T - 60) / T
60 1 1
63 2.703 1.016
66 7.306 1.031
69 19.750 1.044
72 53.384 1.057
75 144.300 1.069
78 390.050 1.079
81 1054.322 1.090
84 2849.881 1.099
87 7703.359 1.108
90 20822.530 1.117

So unless you are looking very carefully, you could miss the small effect of temperature on the process using 1.393 ^ ((T - 60) / T) PU per minute.

10 minutes at 60 would be 10 PU, 10 minutes at 90 would be 11.2 PU. And of course 9 minutes at 60 and 1 minute at 90 would also be 11.2 PU, because you only look at the temperature at the end of the interval , the interval growing at the rate of time.

I repeat that thing about not knowing what I am doing. But this does not make any sense, and your monitoring makes me want to know what brand of beer this is for.

a7

1 Like

Indeed. Line by line seems to come from school teachers who have drunk the wrong kool-aid and require their students to continue the foolish practice.

I like comments for any magic numbers I've used (hopefully defined as const) and then for anywhere I've done something counterintuitive to explain why. Generally, it seems that why rather than what makes sense and any comment that just echoes the code is frankly silly.

I like a comment on a library include line so you can click through to its documentation.

#include <DallasTemperature.h> // https://github.com/milesburton/Arduino-Temperature-Control-Library
1 Like

Especially when

      delay(500);        // ...for 1 sec

they don't. Quite.

@hardym78 don't mind us, not picking on you. Comments is a hole thing.

If you don't know Robert C. "Uncle Bob" Martin now you know:

a7