Using matrix keypad input as time variable

Hello everyone. I have been a lurker for some time. I have frustrated myself quite enough with the current project I am on, and would be grateful for any guidance.

Here’s a quick overview of the project: I am adding 10 LEDs, a 12v fan, and a 3 by 4 matrix keypad to my 3D printer. I want to start a print, go over and punch 3 keys on the keypad that will indicate the duration (in minutes) of the print, and then after three keys are pressed (‘049’ = 49 minutes; ‘143’ = 143 minutes) I want the fan to kick on and stay on for 10 minutes beyond the print duration, and the LEDs to all light up and sequentially turn off in a row to indicate the progress of the print. All 10 lit means it just started, 5 lit means halfway done, etc…

I have successfully programmed the fan (w/ a transistor and diode to reach the Vin 12v) and LEDs (take minutes_entered and multiply by 6000, and then delay by this amount between each LED pulling to LOW).

The issue is with the keypad input. Alone, this section of the code outputs the right 3-digit number:

int time_in = 0;
void loop(){
  if (isdigit(ch)){
      uint8_t time_in   = ch - '0';
      time_in          = ((time_in * 10) + time_in); 
      Serial.println(ch);
      Serial.println(time_in);}}

When I attempt to integrate it into the rest, I get nonsensical outputs or no outputs, and the LEDs never turn on (although the fan does…).

If anyone spots my error, I will love you forever.

Full code:

#include <Keypad.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] = {39, 41, 43, 45}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {47, 49, 51}; //connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

int L1 = 52;
int L2 = 50;
int L3 = 48;
int L4 = 46;
int L5 = 44;
int L6 = 42;
int L7 = 40;
int L8 = 38;
int L9 = 36;
int L10 = 34;

int fan = 22;

int time_in = 0;
float Tbit;

void setup()
{
  Serial.begin(9600);
  pinMode(L1, OUTPUT);
  pinMode(L2, OUTPUT);
  pinMode(L3, OUTPUT);
  pinMode(L4, OUTPUT);
  pinMode(L5, OUTPUT);
  pinMode(L6, OUTPUT);
  pinMode(L7, OUTPUT);
  pinMode(L8, OUTPUT);
  pinMode(L9, OUTPUT);
  pinMode(L10, OUTPUT);

  pinMode(fan, OUTPUT);
}

int i;

void loop()
{
  
char ch = keypad.getKey();

while (i < 3){
  if (isdigit(ch)){
      uint8_t time_in   = ch - '0';
      time_in          = ((time_in * 10) + time_in); 
      Serial.println(ch);
      Serial.println(time_in);

      i = i++;}

      Serial.print("i is");
      Serial.println(i);
      
  Tbit = time_in*6000;

  digitalWrite(fan, HIGH);

  digitalWrite(L1, HIGH);
  digitalWrite(L2, HIGH);
  digitalWrite(L3, HIGH);
  digitalWrite(L4, HIGH);
  digitalWrite(L5, HIGH);
  digitalWrite(L6, HIGH);
  digitalWrite(L7, HIGH);
  digitalWrite(L8, HIGH);
  digitalWrite(L9, HIGH);
  digitalWrite(L10, HIGH);
  
  delay(Tbit);
  digitalWrite(L10, LOW);
  delay(Tbit);
  digitalWrite(L9, LOW);
  delay(Tbit);
  digitalWrite(L8, LOW);
  delay(Tbit);
  digitalWrite(L7, LOW);
  delay(Tbit);
  digitalWrite(L6, LOW);
  delay(Tbit);
  digitalWrite(L5, LOW);
  delay(Tbit);
  digitalWrite(L4, LOW);
  delay(Tbit);
  digitalWrite(L3, LOW);
  delay(Tbit);
  digitalWrite(L2, LOW);
  delay(Tbit);
  digitalWrite(L1, LOW);

  delay(600000);
  digitalWrite(fan, LOW);
}}
}}

Don’t put two closing braces on one line. Use the auto-format tool to fix this. It will indent your code to show what code is part of which block.

Then look again. I think you will see the issue.

Is this an independent processor that’s not controlled as part of the printer? I’d first attempt to do this in the printer controller. Use an un-used digital output. Then find the G-code commands which will turn that output on and off. Put that code into the additional codes that your G-code processor adds into every print.

int L1 = 52;
int L2 = 50;
int L3 = 48;
int L4 = 46;
int L5 = 44;
int L6 = 42;
int L7 = 40;
int L8 = 38;
int L9 = 36;
int L10 = 34;

An order of magnitude less code if you used an array.

char ch = keypad.getKey();

while (i < 3){
  if (isdigit(ch)){

While? What were you smoking?

Why aren’t you checking that you got a key FIRST?

Thank you for the reply. I am still very new to coding in general. I have never had any formal education for it…i’ve only ever learned what I had to to complete projects I’m working on. Excuse my newbiness.

I’ve worked out a few kinks, and am not facing a less bewildering (although still puzzling) issue.

Full code:

#include <Keypad.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] = {39, 41, 43, 45}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {47, 49, 51}; //connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

int L1 = 52;
int L2 = 50;
int L3 = 48;
int L4 = 46;
int L5 = 44;
int L6 = 42;
int L7 = 40;
int L8 = 38;
int L9 = 36;
int L10 = 34;

int fan = 22;

void setup()
{
  Serial.begin(9600);
  pinMode(L1, OUTPUT);
  pinMode(L2, OUTPUT);
  pinMode(L3, OUTPUT);
  pinMode(L4, OUTPUT);
  pinMode(L5, OUTPUT);
  pinMode(L6, OUTPUT);
  pinMode(L7, OUTPUT);
  pinMode(L8, OUTPUT);
  pinMode(L9, OUTPUT);
  pinMode(L10, OUTPUT);

  pinMode(fan, OUTPUT);
}

int i;
int time_in;
int Tbit;

void loop()
{

  char ch = keypad.getKey();

  if (isdigit(ch)) {
    uint8_t time_in   = ch - '0';
    time_in          = ((time_in * 10) + time_in);
    i = ++i;
    Serial.println(i);


    if (i == 3) {
      Serial.println(time_in);

      Tbit = time_in * 6000;

      Serial.println(Tbit);

      digitalWrite(fan, HIGH);

      digitalWrite(L1, HIGH);
      digitalWrite(L2, HIGH);
      digitalWrite(L3, HIGH);
      digitalWrite(L4, HIGH);
      digitalWrite(L5, HIGH);
      digitalWrite(L6, HIGH);
      digitalWrite(L7, HIGH);
      digitalWrite(L8, HIGH);
      digitalWrite(L9, HIGH);
      digitalWrite(L10, HIGH);

      delay(Tbit);
      digitalWrite(L10, LOW);
      delay(Tbit);
      digitalWrite(L9, LOW);
      delay(Tbit);
      digitalWrite(L8, LOW);
      delay(Tbit);
      digitalWrite(L7, LOW);
      delay(Tbit);
      digitalWrite(L6, LOW);
      delay(Tbit);
      digitalWrite(L5, LOW);
      delay(Tbit);
      digitalWrite(L4, LOW);
      delay(Tbit);
      digitalWrite(L3, LOW);
      delay(Tbit);
      digitalWrite(L2, LOW);
      delay(Tbit);
      digitalWrite(L1, LOW);

      delay(600000);
      digitalWrite(fan, LOW);
    }
  }
}

Now the program waits for 3 keys to be pressed before attaching a value to time_in and crunching the Tbit calculation.

Here’s the odd bit: no matter which three keys I press, I always get a two-digit number as “time_in” that is the third key pressed as both the ‘tens’ and ‘ones’ value.

If I press ‘439’ – time_in equals 99
If I press ‘001’ – time_in equals 11
If I press ‘823’ – time_in equals 33

Furthermore, Tbit is being assigned the value of time_in multiplied by 42.1818181818 every single time (instead of 6000).

If time_in equals 99 – Tbit equals 4176
If time_in equals 11 – tbit equals 464
etc…

The fan and LEDs are behaving as expected given these incorrect time-in and Tbit values.

Does anyone see why these two variables are not being handled as I intend by this program?

    i = ++i;

That is undefined behavior, and a sign that you do not understand what the ++ operator does. Read the reference page, where it is discussed.

      Tbit = time_in * 6000;

What range of values can Tbit hold? If time_in is greater than 5, the result of the multiplication will overflow an int.

Does anyone see why these two variables are not being handled as I intend by this program?

It was seen in Post#2.

Why aren’t you checking that you got a key FIRST?

Now, see below:

void loop()
{
char ch = keypad.getKey();
if (ch != 0)
{

//your codes are here

}

}