Storing Keypad entries as time variables

Hello Community,

This community has been a huge help to me. I have been learning to work on Arduino projects since last year and i could get most of my doubts clarified easily through these forums.

Now coming to the current issue,

My aim : To control 5v relays using RTC DS3231, with Arduino Mega 2560, 16x2 LCD, 4x4 Membrane Keypad.

My issue :

  1. How to input values from keypad - as hours and minutes variables - to use if condition so that when RTC value comes between ON & OFF times, the relays get activated.
  2. How to make the LCD print what is being input by the keypad.

P.S. I only know basic coding concepts.

My code :

#include <LiquidCrystal.h>
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(4, 5, 6, 7, 8, 9);//RS,EN,D4,D5,D6,D7

#include <Key.h>
#include <Keypad.h>//header for keypad commands enabling
const byte ROWS = 4; // Four rows
const byte COLS = 4; // Three columns

// Define the Keymap
char keys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};

// Connect keypad ROW0, ROW1, ROW2 and ROW3 to these Arduino pins.
byte rowPins[ROWS] = { 22, 24, 26, 28 };

// Connect keypad COL0, COL1 and COL2 to these Arduino pins.
byte colPins[COLS] = { 30, 32, 34, 36 };

//  Create the Keypad
Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
int letter = 0;
int line = 0;
char entryHour1[2];   // This can hold up to 2 digits
int index1 = 0;

void setup()
{
  for(int k=4;k<10;k++)
  {
    pinMode(k,OUTPUT);//pins 8-14 are enabled as output
  }
  lcd.begin(16, 2);//initializing LCD
  Serial.begin(9600);
  lcd.home();
  lcd.setCursor(letter+4,line);
  lcd.print("Welcome to");
  lcd.setCursor(letter+4,line+1);
  lcd.print("Delta Labs");
  delay(3000);
  lcd.clear();  
}

void loop()
{
  Serial.println("Enter Char: ");
  getChar1();
}
  
char getChar1()
{
 char key = kpd.getKey();
 while(key == NO_KEY) {
  key = kpd.getKey();
  }
 if (key != NO_KEY)
  {
   Serial.print(key);
   entryHour1[index1] = key;
   index1++;
   if (index1 == 2)
    {
      Serial.print(entryHour1);
      index1 = 0;
     return entryHour1;
    }
  return entryHour1;
  }
}

I suggest you immediately convert an ASCII o to 9 into a numeric byte. Then, if doing minutes, multiply minutes X 10 and add the new digit. You can then immediately display the minute on the LCD without worrying about the size of the value. Same for hours. You can then validate minutes and hours for reasonableness.

Paul

Paul_KD7HB:
I suggest you immediately convert an ASCII o to 9 into a numeric byte. Then, if doing minutes, multiply minutes X 10 and add the new digit. You can then immediately display the minute on the LCD without worrying about the size of the value. Same for hours. You can then validate minutes and hours for reasonableness.

Paul

Thanks for the quick reply paul, but i am relatively new to coding stuff. Can u explain again in a rookie friendly manner ?

www.asciitable.com
ASCII '0' to '9' = hex 0x30 to 0x39, or decimal 48 to 57
So you can convert the char you received into a real number by subtracting '0' or 0x30 or 48.
Two digits = tensDigit * 10 + onesDigit = the number you want

Capt.V0rt3x:
Thanks for the quick reply paul, but i am relatively new to coding stuff. Can u explain again in a rookie friendly manner ?

I tried to "quote" your message for a reply, but didn't work at all, so I just did a reply. Got that all done and posted it, only ho have it disappear and the original "quote" message appear. So, again.

This is my code to process minutes for my drying oven. Up to 4 digits may be entered. I don't care which of the 4 digits are being entered.

void process_Time(int time_key) { // up to 4 digits are valid
entered_Time = (10 * entered_Time + time_key);
++ key_count;
if (key_count > 4) {
setting_Time = false;
reset_the_Parameters();
show_Operator_message(0);
entered_Time = 0;
key_count = 0;
}
update_Display_now();
}

The update_Display_now function decides which fields have changed since the last display and blanks that field on the LCD and then displays the new value. Each time a time-digit is entered, the field is displayed. So each digit entered gets shown as part of the whole time field.

The digits entered are from high order to low order, just as you would read them.

Paul

Paul_KD7HB:

void process_Time(int time_key) {            // up to 4 digits are valid

entered_Time = (10 * entered_Time + time_key);
  ++ key_count;
  if (key_count > 4) {
    setting_Time = false;
    reset_the_Parameters();
    show_Operator_message(0);
    entered_Time = 0;
    key_count = 0;
  }
  update_Display_now();
}

Correct me if I am wrong. As far as I understood the code, it seems to only minutes as input (which would be apt for a oven). I understood the conversion part too.

The thing is I need to control the relays in terms of user defined time values.

e.g. if one would want to power up his mobile charger only between 06:00 AM and 08:00 AM, then i want to provide a way to enter those values, via keypad onto the LCD.

Capt.V0rt3x:
Correct me if I am wrong. As far as I understood the code, it seems to only minutes as input (which would be apt for a oven). I understood the conversion part too.

The thing is I need to control the relays in terms of user defined time values.

e.g. if one would want to power up his mobile charger only between 06:00 AM and 08:00 AM, then i want to provide a way to enter those values, via keypad onto the LCD.

I don't think you actually meant what you wrote. You don't enter anything into the LCD. You display something on the LCD. Every time the user enters anything, display everything - if it has changed from the last display.

In your case, you would need to be able to enter a 2 digit time and a two character "AM" or "PM". Don't you wish the whole world used a 24 hour clock? And a 2 digit minute. For both start and end time. So, 6 entered characters for each of the two fields. The numeric values you now know how to handle.

In my keypad, I used ones with removable keycaps and wrote what they were on a small piece of paper to be placed under the keycap. One was labeled "TIME" another "TEMP", another "ENT" for enter, another for "RUN" to start the oven.

Paul

Paul_KD7HB:
I don't think you actually meant what you wrote. You don't enter anything into the LCD. You display something on the LCD. Every time the user enters anything, display everything - if it has changed from the last display.

In your case, you would need to be able to enter a 2 digit time and a two character "AM" or "PM". Don't you wish the whole world used a 24 hour clock? And a 2 digit minute. For both start and end time. So, 6 entered characters for each of the two fields. The numeric values you now know how to handle.

Paul

Hahaha. I didn't think someone would take it literally. I could use the 24 hr format, that would leave me with 4 characters for 2 fields.

Aargh. I was going through some other forum post and it knocked me off.

void process_Time(int time_key) {            // up to 4 digits are valid
  entered_Time = (10 * entered_Time + time_key);
  ++ key_count;
  if (key_count > 2) {
    setting_Time = false;
    reset_the_Parameters();
    show_Operator_message(0);
    entered_Time = 0;
    key_count = 0;
  }
  update_Display_now();
}

if i use the same process for both hours and times, then it should work right ?!

Hours and minutes. Separate functions, only the names are changed! Logic is the same, but for 2 digits.

Paul