Make a variable value from keypad presses

I am trying to create a program, where a "delay" time for running something needs to be set upon the beginning of the program. I am planning on implementing the millis function for that.

However, first hurdle is that I need to be able to set the delay time by keypad presses. I want to be be able to enter up to 5 digits, so max will be "99999". Those "99999" should then be converted to seconds in the program. But also if only, for example, 75 is entered... the delay time should be 75 seconds.

I've tried to make a program for this to happen, but without millis implementation so far. However, I have a few problems... the serial monitor doesnt show what I expected from the code (must've missed something somewhere).. and the key presses only blinks on the LCD at the moment they are pressed - I want them to stay on the LCD so the user can see his input, and confirm the set number in the end.

I hope someone can/will help me with this problem and guide me in the right direction. :slight_smile: This is by no means a finished program, but one step at a time..

#include <Keypad.h>
#include <LiquidCrystal.h>
//#include <SPI.h>

const byte ROWS = 4; //four rows
const byte COLS = 3; //three columns
char keys[ROWS][COLS] = {
  {'1', '2', '3'},
  {'4', '5', '6'},
  {'7', '8', '9'},
  {'*', '0', '#'}
};

byte rowPins[ROWS] = {
  11, 12, 2, 3
}; //PINS WHERE THE ROWS OF THE KEYPAD IS CONNECTED
byte colPins[COLS] = {
  4, 5, 6
};  //connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
byte ledPin = 13;
byte currentState = 1;        //MAKE VARIABLE CURRENTSTATE, SET IT TO START IN STATE 1 IN AUTOMODE


//LCD DISPLAY SETUP
LiquidCrystal lcd(19, 18, 7, 8, 9, 10);  //PINS WHERE THE LCD DISPLAY IS CONNECTED

int t1;
int t2;
int t3;
int t4;
int t5;
unsigned long dlyTime = 0;

void setup() {
  Serial.begin(9600);
  lcd.begin(16, 2);   //SETTING UP LCD'S NUMBER OF COLUMNS AND ROWS
}

void loop() {
  char key = keypad.getKey();
  lcd.setCursor(0, 0);
  lcd.print ("Set delay time:");
  delay (50);
  lcd.setCursor(0, 1);
  lcd.print ("      seconds");

  // if (dlyTime == 0);
  // {
  enterDelay();
  //}
  dlyTime = t1 + t2 + t3 + t4 + t5;
  Serial.println(dlyTime);
}

void enterDelay(void) {

  char key = keypad.getKey();
  switch (currentState)
  {

    //***************************
    case 1:
      Serial.println("case1");
      lcd.setCursor(0, 1);
      if (key)
      {

        lcd.print(key);
        lcd.setCursor(1, 1);
        t1 = (key);
        currentState = 2;
      }

      else {
        currentState = 1;
      }


      break;
    //***************************
    case 2:

      lcd.setCursor(1, 1);
      if (key)
      {
        lcd.print(key);
        t2 = (key);
        currentState = 3;
      }
      else {
        currentState = 2;
      }
      break;
    //***************************
    case 3:

      lcd.setCursor(2, 1);
      if (key)
      {
        lcd.print(key);
        t3 = (key);
        currentState = 4;
      }
      else {
        currentState = 3;
      }
      break;
    //***************************
    case 4:

      lcd.setCursor(3, 1);
      if (key)
      {
        lcd.print(key);
        t4 = (key);
        currentState = 5;
      }
      else {
        currentState = 4;
      }
      break;
    //***************************
    case 5:

      lcd.setCursor(4, 1);
      if (key)
      {
        lcd.print(key);
        t5 = (key);
        currentState = 5;
      }
      else {
        currentState = 5;
      }
      break;
    //***************************
    default:
      currentState = 1;              //Back to state 1

      loop();
  } // END SWITCH/CASE===========================================================
}

Hint: on an 8 bit Arduino, you're not going to fit 99999 in an "int", or even an "unsigned int"

AWOL:
Hint: on an 8 bit Arduino, you're not going to fit 99999 in an "int", or even an "unsigned int"

That is why I made an unsigned long, to sum up the 5 integers - but I think maybe I should change the int's to long's instead, to avoid problems with converting the last entered numbers to a time interval - right?

dlyTime = t1 + t2 + t3 + t4 + t5;

Imagine you enter 12345.
dlyTime = 15.

AWOL:

dlyTime = t1 + t2 + t3 + t4 + t5;

Imagine you enter 12345.
dlyTime = 15.

I know that.. I havent tried converting the inputs yet. But what gets me is that the keypress doesn't stay on the LCD after the key is released. Also, if I push '1', my serial monitor comes up with 49, '2', it comes up with 50... so if I press '2' two times in a row, serial monitor says '100' - but I want it to say 4 (for now) - conversion is something I'll wrestle with after this bit works. :slight_smile:

ASCII character '0' has decimal value 48, '1' is 49 etc.

Ahh.. the explains part of my problem. So do I need to take that into consideration in every case, or is there a clever workaround? Well, I guess the easiest way is to just subtract 48 from every (key). Works wonders... lol

The clever work around is to subtract '0' from the key value.

So do I need to take that into consideration in every case, or is there a clever workaround?

Make the array of characters one larger, NULL terminate it, and use atoi().

AWOL:
The clever work around is to subtract '0' from the key value.

Never mind... had a temporary brain tumor. PaulS - I'm taking baby steps here.. never used the atoi() before, so I'm playing it safe for now. Will try to play around and optimize when I get it working. :slight_smile:

Any suggestions on the LCD problem?

Why '0' and not '48'?

See reply #5

AWOL:
See reply #5

Yea, I know.. edited the post above accordingly. :slight_smile: Also, solved my LCD problem... so I will play around a bit and get back when I need more assistance. Thanks for the help so far to both of you!