Overflow?

I done a little countdown.
Here the picture:

All go right, but after abouts 3 minutes display strange caracters and the software hangs.

May be an overflow?

Here the code.

May you help me?

#include <LiquidCrystal.h>;
#include <Button.h>

LiquidCrystal lcd(2, 3, 5,6,7,4);

int running = 0;
Button bottone_down = Button (10,PULLDOWN);
Button bottone_up = Button (9,PULLDOWN);
Button bottone_start_stop= Button(8,PULLUP);
int pinRele=13;

long millis_start=0;
long tempo=0;
long debounce = 200;
long cron=0;

void setup() {
  
  lcd.begin(16, 2);
  lcd.print("Rele");
  lcd.setCursor(0, 1);
  lcd.print("off");
 


pinMode(pinRele, OUTPUT); 
digitalWrite(pinRele, LOW); 

tempo=0;
}

void loop() {

 
buttonstate();
delay(debounce);

if (running==1) {
  cron=(millis()-millis_start)/1000;


  lcd.setCursor(0,0);
  lcd.print("Accensione tra: ");
  lcd.setCursor(0,1);
  lcd.print(convertTime(tempo-cron));

    lcd.print("         ");
  if (cron>=tempo) {
    digitalWrite(pinRele, HIGH); 
    lcd.setCursor(0,0);
    lcd.print("Rele   ");
    lcd.setCursor(0,1);
    lcd.print("on   ");
    tempo=cron;
  } else {
    pinMode(pinRele, OUTPUT); 
digitalWrite(pinRele, LOW); 
  }
} else {
  
    lcd.setCursor(0,0);
    lcd.print("Setting time:  ");
    lcd.setCursor(0,1);
    lcd.print(convertTime(tempo));
    lcd.print("      ");
  
  
}

}

void buttonstate() {
 
if (bottone_up.isPressed()) {
  tempo=tempo+180;
}
if (bottone_down.isPressed()) {
  tempo=tempo-180;
}
if (tempo<0) {
  tempo=0;
}

if (bottone_start_stop.isPressed()) { 
 if (running==1) {
     running=0; 
     tempo=tempo-cron;
   } else {
       running=1;
millis_start=millis();


     }
delay(debounce);
}

}


char* convertTime(long time) {
static char hh[32] = {0}; 
static char mm[3] = {0};
static char ss[3] = {0};
static char t[3] = {0};
long hhI;
long mmI;
long ssI;
hhI=time/3600;
mmI=(time-hhI*3600)/60;
ssI=time-hhI*3600-mmI*60;
itoa(hhI,hh,10);
itoa(mmI,mm,10);
itoa(ssI,ss,10);
strcat(hh,":");
strcat(hh,mm);
strcat(hh,":");
strcat(hh,ss);
return hh;
}

My guess is convertTime() is overflowing some of the 3-character strings you declared. Try using Serial.println() to print out the values of hhI, mmI, and ssI prior to converting them to strings to make sure they fit into 2 characters.

Also, itoa() takes an int parameter and you are passing a long. You can use ltoa() (though I doubt it will make a difference as your numbers should be small).

-- Check out our new shield: http://www.ruggedcircuits.com/html/gadget_shield.html

I believe itoa() takes a pointer to the char array you want to store the resulting string, and your code indicates your trying to pass the entire char array. http://www.cplusplus.com/reference/clibrary/cstdlib/itoa/

Although it may pass through the compiler, you want to use &hh, &mm, etc and pass in the address of the char. Also, typecast your longs into ints, as RuggedCircuts suggested I think that may also be a problem.

As a workaround, try using sprintf instead of itoa(). Something like

unsigned long longData = 250; // an 8 bit number

void setup(){
Serial.begin(9600);
}

void loop(){

char buffer[75];

while(longData++ <= 270){ //Jumps the from 8 bit to 16 bit number

sprintf(buffer, “longData = %.lX in hex, and %.lu in decimal”, longData, longData);
Serial.println(buffer);

}

longData = 4294967295; //Highest value unsigned long can store

sprintf(buffer, “longData = %.lX in hex, and %.lu in decimal”, longData, longData);
Serial.println(buffer); //Prints with no problem

while(true){
continue;
}

}

http://www.cplusplus.com/reference/clibrary/cstdio/sprintf/

Good Luck

EDIT: I modified it slightly since you’re using long and not unsigned long, but I would advise unsigned long unless you expect a negative time :wink:

long longData = 250; // an 8 bit number

void setup(){
Serial.begin(9600);
}

void loop(){

char buffer[75];

while(longData++ <= 270){ //Jumps the from 8 bit to 16 bit number

sprintf(buffer, “longData = %.lX in hex, and %.ld in decimal”, longData, longData);
Serial.println(buffer);

}

longData = 4294967295; //Highest value unsigned long can store

sprintf(buffer, “longData = %.lX in hex, and %.lu in decimal”, longData, longData);
Serial.println(buffer); //Prints with no problem

while(true){
continue;
}

}

Take a look at this as well.

/Send via serial the time in hh:mm:ss format that the arduino has been running this program/ /http://mikestechspot.blogspot.com/

unsigned int ss; unsigned int mm; unsigned int hh; char charTime[13];

void currentTime();

void setup(){ Serial.begin(9600); }

void loop(){

currentTime(); Serial.print(charTime); Serial.print(13, BYTE); //Return to beginning of line

delay(500);

}

void currentTime(){

unsigned long longTime = floor(millis()/1000); //Get time in Seconds since Board started running

mm = (longTime / 60) % 60; //Convert longTime to minutes and store

ss = longTime % 60; //Store remaining seconds after conversion to minutes

hh = floor(longTime / 3600); //Convert minutes to hours and store result;

sprintf(charTime, "%.2hd:%.2hd:%.2hd", hh, mm, ss);

}

I modify code, so it’s more readable and uses unsigned and Moore313 suggest.

But seems crash between point 1 and point 2, not when the timer countdown but after some minutes of starting.

#include <LiquidCrystal.h>;
#include <Button.h>

LiquidCrystal lcd(2, 3, 5,6,7,4);

Button bottone_down = Button (10,PULLDOWN);
Button bottone_up = Button (9,PULLDOWN);
Button bottone_start_stop= Button(8,PULLUP);
int pinRele=13;
unsigned long debounce = 200;

int running = 0;
int started = 0;
unsigned long millis_start=0;
unsigned long tempo=0;
unsigned long cron=0;
char charTime[13];

void setup() {
  Serial.begin(9600); 
  lcd.begin(16, 2);
  lcd.print("Rele");
  lcd.setCursor(0, 1);
  lcd.print("off");
  pinMode(pinRele, OUTPUT); 
  digitalWrite(pinRele, LOW); 
}

void loop() {
  buttonstate();
  delay(debounce);
  if ((started==0) && (running==1)) {
    cron=(millis()-millis_start)/1000;
    lcd.setCursor(0,0);
    lcd.print("Strarting in: ");
    lcd.setCursor(0,1);
    convertTime(tempo-cron);
    lcd.print(charTime);
    lcd.print("         ");
    if (cron>=tempo) {
      tempo=cron;
      running=0;
      started=1;
    }
  }
  if ((running==0) && (started==0)) {
    lcd.setCursor(0,0);
    lcd.print("Setting:  ");
    lcd.setCursor(0,1);
    convertTime(tempo);
    lcd.print(charTime);
    lcd.print("      ");
  }
/* point 1 */
  if (started==1) {
    lcd.setCursor(0,0);
    lcd.print("Rele");
    lcd.setCursor(0,1);
    lcd.print("on");
    digitalWrite(pinRele, HIGH); 
  } else {
    digitalWrite(pinRele, LOW); 
  }
/* point 2 */  
}

void buttonstate() {
  if (bottone_up.isPressed()) {
    tempo=tempo+180;
  }
  if (bottone_down.isPressed()) {
    tempo=tempo-180;
  }
  if (tempo<0) {
    tempo=0;
  }
  if (bottone_start_stop.isPressed()) { 
    if (running==1) {
      running=0;
      started=0; 
      tempo=tempo-cron;
    } else {
      running=1;
      millis_start=millis();
    }
    delay(debounce);
  }
}

void convertTime(unsigned long longTime) {
  unsigned int ss;
  unsigned int mm;
  unsigned int hh;
  mm = (longTime / 60) % 60; //Convert longTime to minutes and store
  ss = longTime % 60; //Store remaining seconds after conversion to minutes
  hh = floor(longTime / 3600); //Convert minutes to hours and store result;
  sprintf(charTime, "%.2hd:%.2hd:%.2hd", hh, mm, ss);
}

How often is that block of code between point 1 and point 2 executed?

From my perspective, running and started should be boolean variables, and should be set to true or false. The code would be much easier to follow that way. Instead of

if(running == 0)

you could have

if(!running)

Instead of

if(running == 1)

you could have

if(running)

You are having to take great pains to set running and started to 0 or 1, and remember there states. It's easier to think true or false. I mean, either something is running or it isn't. When you ask "Is this thing running?", you don't expect a response of 0 or 1, you expect yes or no/true or false.

If you make this change, and recognize that loop() is called in an infinite loop, as many as 16,000,000 times per second, you'll see that the block of code can be executed many, many times per second.

Each time that it is executed, it is writing the same data to the LCD. I wouldn't bother re-writing the data on the LCD unless it changed. I suspect that your issue might be related to writing to the LCD too often. My first step would be to only write when the data changes, to see if that gets rid of the problem.