Values displayes wrong on LCD

Hi there forum!

I am trying to build a diasarmable fake bomb, and I have pretty much figured it out, but I have 2 problems I can’t figure out.

Iḿ using a 3x4 matrix keypad to take input from the user, and a 2x16 IC2 LCD display for output.

When the user is asked to enter detonation time I write out "H: MIN: SEC: " on the screen, place the cursor at the correct place and wait for the user to enter a 2 digit string, saves the string to mins, sets the cursor at the correct place to enter MIN, and so on.

If I try to enter a number that start with 0, say 01 hours, that gets printed to the screen as 11, if I enter 02 it’s 22, and so on. But when the time is set and written to screen for confirmation, the right values show.

When the “bomb” is armed a countdown starts and is printed to screen.

I used the timer library that calls a function every seond that subtracts a second, if there are no seconds subtract a minutes and set secs to 59, and so on, and then prints to the LCD. I think I got the math part working!

The problem is that when a value goes below 10, a zero is added to the printout, so 9 becomes 90, 8 becomes 80 and so on.

The countdown is “correct”, it’s just displayes wrong.

If I it’s supposed to print out "H:00MIN:00SEC:09 " it shows as “H:00MIN:00SEC:90”.

If I set the timer to start at 10 or less it works, but if it starts over at 11 or above a get the added zero.

I did a serialprint of the values, and they show up ok without added zerors in the serial monitor.

Help please!

This is the code to set the timer:

lcd.clear();
lcd.setCursor(3,0);
lcd.print("SET TIMER:");
lcd.setCursor (0,1);

while (temp.length() < 2)
{
lcd.setCursor (2,1);
char key = kpd.getKey();
  if(key)  // Check for a valid key.
  {
    switch (key)
    {
      case '*':
        break;
      case '#':
        break;
      default:
        temp=temp+key;
        lcd.print(temp);
        
    }
  }

}




hours = temp.toInt();

if (hours > 24)
{
  hours=24;
}


tempTime = hours*hoursToMilli;
detonationMilli = detonationMilli+tempTime;
temp=("");

lcd.setCursor(0,1);
lcd.print("H:");
lcd.setCursor(2,1);
lcd.print(hours);
lcd.setCursor(4,1);
lcd.print("MIN:  SEC:  ");

while (temp.length() < 2)
{
lcd.setCursor (8,1);
char key = kpd.getKey();
  if(key)  // Check for a valid key.
  {
    switch (key)
    {
      case '*':
        break;
      case '#':
        break;
      default:
        temp=temp+key;
        lcd.print(temp);
        
        
    }
  }

}


mins = temp.toInt();

if (mins > 59)
{
  mins=59;
}

tempTime = mins*minsToMilli;
detonationMilli = detonationMilli+tempTime;
temp=("");

lcd.setCursor(0,1);
lcd.print("H:");
lcd.setCursor(2,1);
lcd.print(hours);
lcd.setCursor(4,1);
lcd.print("MIN:");
lcd.setCursor(8,1);
lcd.print(mins);
lcd.setCursor(10,1);
lcd.print("SEC:  ");


while (temp.length() < 2)
{
lcd.setCursor (14,1);
char key = kpd.getKey();
  if(key)  // Check for a valid key.
  {
    switch (key)
    {
      case '*':
        break;
      case '#':
        break;
      default:
        temp=temp+key;
        lcd.print(temp);
        
        
    }
  }

}

secs = temp.toInt();

if (secs > 59)
{
  secs=59;
}

tempTime = secs*1000;
detonationMilli = detonationMilli+tempTime;
temp=("");

lcd.clear();
lcd.setCursor(3,0);
lcd.print("TIMER SET:");

lcd.setCursor(0,1);
lcd.print("H:");
lcd.setCursor(2,1);
lcd.print(hours);
lcd.setCursor(4,1);
lcd.print("MIN:");
lcd.setCursor(8,1);
lcd.print(mins);
lcd.setCursor(10,1);
lcd.print("SEC:");
lcd.setCursor(14,1);
lcd.print(secs);

and this is the function for the countdown that gets called every 1000 ms by the timer

void SecondsTimer(void *context)
{
  
  if (secs > 0)
  {
    secs=secs-1;
  }
  
  else if (secs <= 0 && mins > 0)
  {
    secs=59;
    mins=mins-1;  
  }
  
  else if (secs <= 0 && mins <= 0 && hours > 0)
  {
    secs=59;
    mins=59;
    hours=hours-1;
  }
  Serial.print("Hours: ");
  Serial.println(hours);
  Serial.print("Minutes: ");
  Serial.println(mins);
  Serial.print("Seconds: ");
  Serial.println(secs);
  lcd.setCursor(0,0);
  lcd.print("H:");
  lcd.setCursor(2,0);
  lcd.print(hours);
  lcd.setCursor(4,0);
  lcd.print("MIN:");
  lcd.setCursor(8,0);
  lcd.print(mins);
  lcd.setCursor(10,0);
  lcd.print("SEC:");
  lcd.setCursor(14,0);
  lcd.print(secs);
  lcd.setCursor(0,1);
}

And I’ll attach the file with my whole 479 lines of bloated ill formated code! I’m a noob, be gentle…

KeypadAndLCDTest.ino (8.29 KB)

First, you can use Ctrl-T with the cursor in the IDE’s source code window to reformat your code into a standard C style. That will make it easier to read.

Second, step back and look at your code, observing the forest, not the trees. You have many sections of the code that are virtual repeats of other code sections. Why not rewrite those duplicate pieces as a function that can be reused? That will cut down on code size, and make it easier to “see” what’s going on.

Third, any time you are trying to fit data into a fixed field with, you need to check the value to be displayed against the field size and act accordingly, perhaps something similar to:

   char temp[5];
   int seconds;
   // Some code that sets the seconds...
   if (seconds < 10) {
      temp[0] = '0';                  // The leading zero
      temp[1] = (char) seconds + '0'; // ASCII equivalent of single digit character
      temp[2] = '\0';                 // Add the null so we can use it as a string
   } else {
      itoa(seconds, temp, 10);
   }

I haven’t tested the code, but something similar to this should work. Note: You can generalize this to any field with a little thought, not just seconds.

Thank you kindly! The Ctrl-T thing was a blessing.

I know, it's a mess, but right know I just wanted to get it working, since people want to use it, and I'm aaaaalmost there!

I am planning to break it up in to functions and make it more effective in general, there is probably a lot of unnecesar stuff in there, and it'll be hell to update, but first I need to learn more about how functions actually work, so the plan is to get it done the messy way first, and then revisit and re-do the whole thing properly when I have a little more knowledge.

This is my first project, but not my last!

I'll have a think on that one! I think I maybe should read up on zero-padding, I just realised that is a thing...

Thanks again!

Solved it!

I sprinkled a few

if (x<10)
{
lcd.print(“0”);
}

before the lcd.prints and that did the trick.

ShatteredDnB:
Solved it!

I sprinkled a few

if (x<10)
{
lcd.print(“0”);
}

before the lcd.prints and that did the trick.

Instead of 5 lines of code EVERY place you need to print a number, create a function that prints the leading 0, if needed, and the number. Then, when you need to print a 2 digit number, use one line of code to call the function, instead of 5 lines.