Timer problem - why this output?

Hello,
I don't understand why this sketch generates a (to me) not understandable output. But first the part of the sketch. All variables connected with the timing are defined as unsigned long. This part resides in the loop()-section.

   /* running timer */
   Start = digitalRead(ButtStart);
   timerM = timer*60000;                  // ms to min
   if (Start == HIGH){
      time_start = millis();
      Start = LOW;
   }
   time_end = time_start + timerM;
   time_rem = (time_end - millis())/60000;
   if (time_rem < 10){lcd.print("  "); lcd.print(time_rem + 1);}
   else if (timer < 100){lcd.print(" "); lcd.print(time_rem + 1);}
   else {lcd.print(time_rem - 1);}

   if (time_end < millis()) {
   Serial.println("END");
   }

When I press the start button, the timer should start. The display should show the remaning time in minutes, at the end of the period it should show "0" and an action is triggered (here for testing a text on the serial monitor).

The timer works, it counts down as desired, it triggers the output "END" in the moment the timer has reached the target time. So far everything is is OK. But why the heck the display reads 71564 (or a similiar ununderstandable number) at the end?

Any ideas?

Thank you,

-richard

There are multiple possible causes. The most probable is that you declared a different baudrate as the one used by the serial monitor. Check that the value in the Serial.begin() is the same as the one in the monitor

Or maybe you connected something to digital pins 0 and/or 1?

Hi,
Please post your entire code.
How have you got your variables declared, int, float, long, double etc.

Tom... :slight_smile:

lesept:
The most probable is that you declared a different baudrate as the one used by the serial monitor. Check that the value in the Serial.begin() is the same as the one in the monitor

Same baudrate. 9600 in Serial.begin and the monitor.

lesept:
Or maybe you connected something to digital pins 0 and/or 1?

No.

TomGeorge:
Please post your entire code.

I thought it would be better to post only the relevant parts. But of course I can do it:

#include <LiquidCrystal.h> 

#include <EEPROM.h>                      

const int rs = 12, en = 11, d4 = 10, d5 = 9, d6 = 8, d7 = 7;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
const int ButtGoDown = 6;  //button pins
const int ButtGoUp = 5;
const int ButtChTemp = 4;
const int ButtChTime = 3;
const int ButtStart = 2;
int cal_Tempadr=0, cal_Timeadr = 2, save_Temp=0, save_Time = 0;
int GoDown = 0;   //variables for reading the buttons (button states)
int GoUp = 0;
int ChTemp = 0;
int ChTime = 0;
int Start = 0;
int temp_nom = 130;
int save_temp = 0;
int cal_Temp=0, cal_Time=0;
int ThermistorPin = 2;
int Vo, temp_act;
float R1 = 20000;
float logR2, R2;
float c1 = 0.001026189, c2 = 0.000223186, c3 = 1.20877360e-7; //NTC Type 203

unsigned long  timer = 30UL;
unsigned long timerM, time_start, time_rem,  time_end; //will be manipulated with millis(), therefore unsigned long 



void setup() {

  /* definition of buttons */
  pinMode(ButtGoDown, INPUT);       // decrement value
  pinMode(ButtGoUp, INPUT);         // increment value
  pinMode(ButtChTemp, INPUT);       // change nominal temperature
  pinMode(ButtChTime, INPUT);       // change timer
  pinMode(ButtStart, INPUT);        // start timer
  time_rem = constrain(time_rem, 0, 300);

  temp_nom=EEPROMReadInt(cal_Tempadr); // initial values from eeprom
  timer=EEPROMReadInt(cal_Timeadr); 
  lcd.begin(20,4);
  lcd.setCursor(0,0);
  lcd.print("Solltemp. (\337C):");  //nominal temperature
  lcd.setCursor(0,1);
  lcd.print("Isttemp.  (\337C):");  //measured temperature
  lcd.setCursor(0,2);
  lcd.print("Sollzeit (min):");     // timer
  lcd.setCursor(0,3);
  lcd.print("Restzeit (min):");     // remaining time
  Serial.begin(9600);
}

void loop() {
   ChTemp = digitalRead(ButtChTemp);
   ChTime = digitalRead(ButtChTime);

   /* setting nominal temperature */
  temp_nom = constrain(temp_nom, 20, 150);
      lcd.setCursor(16,0);
  if (temp_nom < 100){lcd.print(" ");lcd.print(temp_nom);}
    else {lcd.print(temp_nom);}
  if (ChTemp == HIGH) {
    GoUp = digitalRead(ButtGoUp);
    if (GoUp == HIGH) {++temp_nom;}
    GoDown = digitalRead(ButtGoDown);
    if (GoDown == HIGH) {--temp_nom;}
    save_Temp = 1;
  }
    if(save_Temp==1) {            // save nominal temperature to eeprom
    EEPROMUpdateIntTemp(cal_Tempadr, temp_nom);
    save_Temp=0;                  // temp_nom is saved
  }
 
    delay(150);                   // delay to get in-/decrements of 1 while pressing button up/down
  

   /*actual temperature*/
  Vo = analogRead(ThermistorPin);
  R2 = R1 * (1023.0 / (float)Vo - 1.0);
  logR2 = log(R2);
  temp_act = (1.0 / (c1 + c2*logR2 + c3*logR2*logR2*logR2)); //c1: a0, c2: a1, c3: a3
  //(cf. https://de.wikipedia.org/wiki/Steinhart-Hart-Gleichung)
  temp_act = (temp_act - 273.15);
  lcd.setCursor(16,1);
 if (temp_act < 100) {lcd.print(" "); lcd.print(temp_act);}
    else {lcd.print(temp_act);}



   /* setting timer */
  timer = constrain(timer, 1, 300);
      lcd.setCursor(16,2);
  if (timer < 10){lcd.print("  ");lcd.print(timer);}
  else if (timer < 100){lcd.print(" ");lcd.print(timer);}
    else {lcd.print(timer);}
   if (ChTime == HIGH) {
    GoUp = digitalRead(ButtGoUp);
    if (GoUp == HIGH) {++timer;}
    GoDown = digitalRead(ButtGoDown);
    if (GoDown == HIGH) {--timer;}
    save_Time=1;
    }
  if (save_Time==1){
    EEPROMUpdateIntTime(cal_Timeadr, timer);
    save_Time=0;
//    cal_Time=!cal_Time;
  }

   /* running timer */
   Start = digitalRead(ButtStart);
   timerM = timer*60000;                  // ms to min
   if (Start == HIGH){
    time_start = millis();
    Start = LOW;
      }
   time_end = time_start + timerM;
   time_rem = (time_end - millis())/60000;
 //  time_rem = constrain(time_rem, 1, 200);
   lcd.setCursor(16,3);
   if (time_rem < 10){lcd.print("  "); lcd.print(time_rem + 1);}
   else if (timer < 100){lcd.print(" "); lcd.print(time_rem + 1);}
   else {lcd.print(time_rem - 1);}

   if (time_end < millis()) {
   Serial.println("EEENNNDDDEEE");
   }
   
      Serial.print("timerM: ");Serial.print(timerM);Serial.print(" time_rem: ");Serial.print(time_rem + 1); Serial.print(" time_start: "); Serial.print(time_start); Serial.print(" time_end: "); Serial.print(time_end); Serial.print(" millis: "); Serial.println(millis());
   
} 

/* update Temp to eeprom */
void EEPROMUpdateIntTemp(int cal_Tempadr, int temp_nom)
  {
  byte lowByte = ((temp_nom >> 0) & 0xFF);
  byte highByte = ((temp_nom >> 8) & 0xFF);

  EEPROM.update(cal_Tempadr, lowByte);
  EEPROM.update(cal_Tempadr + 1, highByte);
  }

/* update timer to eeprom */
void EEPROMUpdateIntTime(int cal_Timeadr, long timer)
  {
  byte lowByte = ((timer >> 0) & 0xFF);
  byte highByte = ((timer >> 8) & 0xFF);

  EEPROM.update(cal_Timeadr, lowByte);
  EEPROM.update(cal_Timeadr + 1, highByte);
  }


  



/* read/write from/to eeprom  */
int EEPROMReadInt(int adr) {  
// Integer aus dem EEPROM lesen
byte low, high;
  low=EEPROM.read(adr);
  high=EEPROM.read(adr+1);
  return (low + ((high << 8)&0xFF00));
} 
 
/*
void eepromWriteInt(int adr, int val) {
// Integer in das EEPROM schreiben
byte low, high;
  low=val&0xFF;
  high=(val >> 8)&0xFF;
  EEPROM.update(adr, low); // dauert 3,3ms
  EEPROM.update(adr+1, high);
  return;
}*/

Be aware that the code is not finished yet. I'm sure not everything is solved smoothly. Many parts could be better. But fine tunig comes afterwards. It shall control a heating unit for test tubes.

   /* running timer */

Start = digitalRead(ButtStart);
  timerM = timer*60000;                  // ms to min
  if (Start == HIGH){
     time_start = millis();
     Start = LOW;
  }
  time_end = time_start + timerM;
  time_rem = (time_end - millis())/60000;
  if (time_rem < 10){
    lcd.print("  ");
    lcd.print(time_rem + 1);}
  else
    if (timer < 100){
      lcd.print(" ");
      lcd.print(time_rem + 1);}
    else {
      lcd.print(time_rem - 1);}

if (time_end < millis()) {
    Serial.println("END");
  }




The timer works, it counts down as desired, it triggers the output "END" in the moment the timer has reached the target time. So far everything is is OK. But why the heck the display reads 71564 (or a similiar ununderstandable number) at the end?

Reformatted a bit to make it a little clearer to read, after you reach time_end, you are continuing to calculate time_rem, even when it would result in a negative number (although it is defined as unsigned). As a result, the lcd.print statement is displaying the first few digits of whatever the result of the time_rem calculation is, the last few digits of the number aren't displayed because the number exceeds the width of the display. There doesn't appear to be anything in the code to actually stop the timer countdown when it reaches the end.

You also have an error in the compound IF statement, if (timer < 100) presumably should be if (timer_rem < 100), but that doesn't have any affect on the problem.

I see david_nc's point. Of course that's the problem. But I'm nearly desperate, I don't find a solution, though I assume it beeing a quite simple problem. I tried this:

/* running timer */
   Start = digitalRead(ButtStart);
   timerM = timer*60000;                  // ms to min
   if (Start == HIGH){
    time_start = millis();
   }
   while(Start = HIGH || time_rem > 0)
   {
      Start = LOW; 
      time_end = time_start + timerM;
      time_rem = (time_end - millis())/60000;
      lcd.setCursor(16,3);
      if (time_rem < 10){lcd.print("  "); lcd.print(time_rem);}
        else if (timer < 100){lcd.print(" "); lcd.print(time_rem);}
        else {lcd.print(time_rem);}
   }
   if (time_rem <= 0) 
   {
   Serial.println("END");
   }

Now I don't quit the "while loop", though both conditions are not met: "Start" becomes LOW and after a time "time_rem" becomes 0 (I tested it with Serial.print at the resp. lines). But I stay inside the loop.

Why? Any hints?

Thanks,
-richard

Delta_G:

while(Start = HIGH || time_rem > 0)

This SETS Start equal to HIGH

Oh, I thought, "while" is always followed by a condition and not an instruction. Changing "=" to "==" did the job. Thank you.

Delta_G:
Show us how you have the buttons wired?

+5V----button--------------res. 10k------GND
|
|
digital pin

i think you are going to have problems using "while", because it will stay inside the loop as long as the condition is true, blocking anything outside from executing until the timer runs out.

I just realized that, too. I found that one: Arduino Kitchen Timer - Hackster.io. Tomorrow I'll look at the code.

Been a while since I did much programming, so played around with it a bit to see what I could come up with, partly just to have something to practice on.

   /* running timer */
   time_current = millis();
   Start = digitalRead(ButtStart);
   if ( (Start == HIGH) && (!timer_running) ){
    timerM = timer*60000;                  // ms to min
    time_start = time_current;
    timer_running = true;
   }
   if (timer_running){
     if((time_current - time_start) < timerM){
       time_rem = (timerM - (time_current - time_start))/60000;
       if (time_rem != prev_time_rem){
         prev_time_rem = time_rem;
         lcd.setCursor(16,3);
         if (time_rem < 10){
           lcd.print("  ");
           lcd.print(time_rem + 1);}
         else {
           if (timer < 100){
             lcd.print(" ");
             lcd.print(time_rem + 1);}
           else {
             lcd.print(time_rem + 1);} 
         }
       }
     }
     else {
       timer_running = false;
       Serial.println("End");}
     }
//
//  get current time
//  read start button
//  if (start button pressed) AND (timer not running)
//    set timer duration
//    save timer start time
//    start timer
//  if (timer running) 
//    if (elapsed time < timer duration)
//      get remaining time
//      if remaining time has decreased
//        display remaining time on LCD display
//    else
//      stop timer
//      print "end"     
//

Also added a few new variables at the beginning

unsigned long time_current;
unsigned long prev_time_rem = 0UL;
bool timer_running = false;

Yesterday evening I saw your code, today I implemented it. You saved my day! Everything is working now. The rest of the software is, I hope, more simple.

I think I can close this thread. Thanks for every contribution!

-richard