Help needed

Hi everyone,

I'm a complete novice with Arduino programing and have a project that I have to get done ASAP for our family business.

I have a Arduino Mega with a 8 way relay board, 3.2 inch tft screen and a 4x4 membrane keypad.

What I need,

  1. 8 relays to fire in sequence with one on and off time for all.
  2. Screen to display various outputs regarding the process of the unit
  3. Use the keypad to change the values of offTime and onTime.

What I've done so far,

  1. Relays are working with the offTime and onTime manually set in the global variables
  2. Screen displaying all needed info and also with three different "menus"
  3. I have the keypad setup with input working onto the Serial monitor
  4. The "A", "B" and "C" buttons select the relevant menus.

What I'm struggling with,

  1. I need to use the keypad to change the maximum 4 digit offTime/onTime by going into menu "B" or "C", and then saving that value, but pressing "#", into the global variable so that it changes the delays for the relays.
  2. I need to be able to cancel the input of the value in case it was done incorrectly, or even delete the previously pushed values.
  3. The changed value needs to be saved to the EEPROM in case there's a power outage for any reason.

My code so far is as follows,

// Code
#include <UTFT.h>
#include <Keypad.h>

// TFT
UTFT myGLCD(CTE32HR, 38, 39, 40, 41);
extern uint8_t BigFont[];
extern uint8_t Grotesk32x64[];

// Serial Number, change for each new unit
int serialNum = 0001;

// Blowers
const byte Machine1 = A0; // I/O pin connected by the first relay
const byte Machine2 = A1;
const byte Machine3 = A2;
const byte Machine4 = A3;
const byte Machine5 = A4;
const byte Machine6 = A5;
const byte Machine7 = A6;
const byte Machine8 = A7;
unsigned long BlowerStartTime;
unsigned long BlowerStopTime;
bool BlowerIsRunning = false;
byte CurrentBlower = Machine1;
int onTime = 1 ; // seconds on
int offTime = 30 ; // seconds off
unsigned long blows = 0;
unsigned long activeDays = 0;
unsigned long activeHours = 0;
unsigned long powderUsed = 0;

// Keypad
const byte ROWS = 4; // Four rows
const byte COLS = 4; // Four columns
char keys[ROWS][COLS] =
{
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {9, 8, 7, 6};
byte colPins[COLS] = {5, 4, 3, 2};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS );

void setup()
{
  for (int i = Machine1; i <= Machine8; i += 1)
  {
    pinMode(i, OUTPUT); //set digital I/O pin as output
  }

  Serial.begin(9600);
  keypad.addEventListener(keypadEvent);
  keypad.setDebounceTime(100);

  // Intro screen
  myGLCD.InitLCD();
  myGLCD.setFont(Grotesk32x64);
  myGLCD.clrScr();
  myGLCD.setColor(VGA_BLUE);
  myGLCD.print("CHINCO FIRESIDE", CENTER, 100);
  myGLCD.print("TREATMENT", CENTER, 164);
  delay (3000);
  myGLCD.clrScr();
  Splash();
}

void Splash() {
  myGLCD.setColor(VGA_BLUE);
  myGLCD.drawRect(0, 0, 479, 305);
  myGLCD.setFont(BigFont);
  myGLCD.print("CHINCO FIRESIDE TREATMENT", CENTER, 2);
  myGLCD.setColor(VGA_WHITE);
  myGLCD.print("'Press 'A' - Statistics'", 1, 100);
  myGLCD.print("'Press 'B' - Delay Setup'", 1, 116);
  myGLCD.print("'Press 'C' - Blow Setup'", 1, 132);
  myGLCD.setColor(VGA_WHITE);
  myGLCD.print("Serial #", 270, 286);
  myGLCD.printNumI(serialNum, 398, 286);
}

void title() {
  myGLCD.clrScr();
  myGLCD.setColor(VGA_BLUE);
  myGLCD.drawRect(0, 0, 479, 305);
  myGLCD.setFont(BigFont);
  myGLCD.print("CHINCO FIRESIDE TREATMENT", CENTER, 2);
  myGLCD.setColor(VGA_WHITE);
  myGLCD.print("Delay Between Blows :", 2, 48); // Delay time
  myGLCD.printNumI(offTime, 337, 48);
  myGLCD.print("s", 403, 48);
  myGLCD.print("Duration of Each Blow :", 2, 64); // Blow time
  myGLCD.printNumI(onTime, 368, 64);
  myGLCD.print("s", 402, 64);
  myGLCD.print("System Active For :", 2, 80); //Active Days
  myGLCD.printNumI(activeDays, 305, 80);
  myGLCD.print("Days", 355, 80);
  myGLCD.print("System Active For :", 2, 96); //Active Hours
  myGLCD.printNumI(activeHours, 305, 96);
  myGLCD.print("Hours", 355, 96);
  myGLCD.print("Number of Blows :", 2, 112); //Blows
  myGLCD.printNumI(blows, 274 , 112);
  myGLCD.print("KGs powder used :", 2, 128); //KGs used
  myGLCD.printNumF(powderUsed, 3, 274, 128);
  myGLCD.setColor(VGA_RED);
  myGLCD.print("'Press 'A' - Update Stats'", 1, 150);
  myGLCD.print("'Press 'B' - Delay Setup'", 1, 166);
  myGLCD.print("'Press 'C' - Blow Setup'", 1, 182);
  myGLCD.setColor(VGA_GRAY);
  myGLCD.print("Serial #", 270, 286);
  myGLCD.printNumI(serialNum, 398, 286);
}

void offTimeChange() {
  myGLCD.clrScr();
  myGLCD.setColor(VGA_BLUE);
  myGLCD.drawRect(0, 0, 479, 305);
  myGLCD.setFont(BigFont);
  myGLCD.print("CHINCO FIRESIDE TREATMENT", CENTER, 2);
  myGLCD.setColor(VGA_WHITE);
  myGLCD.print("CHANGE BLOW DELAY TIME", CENTER, 50);
  myGLCD.print("ENTER VALUE", CENTER, 66);
  myGLCD.print("PRESS # TO SAVE", CENTER, 100);
  myGLCD.setColor(VGA_RED);
  myGLCD.print("'Press 'A' - Statistics'", 1, 146);
  myGLCD.print("'Press 'C' - Blow Setup'", 1, 162);
  myGLCD.setColor(VGA_GRAY);
  myGLCD.print("Serial #", 270, 286);
  myGLCD.printNumI(serialNum, 398, 286);
  }

void onTimeChange() {
  myGLCD.clrScr();
  myGLCD.setColor(VGA_BLUE);
  myGLCD.drawRect(0, 0, 479, 305);
  myGLCD.setFont(BigFont);
  myGLCD.print("CHINCO FIRESIDE TREATMENT", CENTER, 2);
  myGLCD.setColor(VGA_WHITE);
  myGLCD.print("CHANGE LENGTH OF BLOW TIME", CENTER, 50);
  myGLCD.print("ENTER VALUE", CENTER, 66);
  myGLCD.print("PRESS # TO SAVE", CENTER, 100);
  myGLCD.setColor(VGA_RED);
  myGLCD.print("'Press 'A' - Statistics'", 1, 146);
  myGLCD.print("'Press 'B' - Delay Setup'", 1, 162);
  myGLCD.setColor(VGA_GRAY);
  myGLCD.print("Serial #", 270, 286);
  myGLCD.printNumI(serialNum, 398, 286);
  }

void loop()
{
  ManageBlowers();
  int activeDs = millis() / 864000000UL;
  int activeHrs = millis() / 3600000UL;
  activeDays = activeDs;
  activeHours = activeHrs;
  unsigned long int powderUse = (blows * 50) / 1000;
  powderUsed = powderUse;
  Serial.print(powderUsed);

  char key = keypad.getKey();
  if (key) {
    Serial.print(key);
  }
}
void ManageBlowers() {
  if (BlowerIsRunning)
  {
    if (millis() - BlowerStartTime > onTime * 1000UL)
    {
      StopBlower(CurrentBlower);
      CurrentBlower += 1;
      if (CurrentBlower > Machine8)
        CurrentBlower = Machine1;
    }
  }
  else
  {
    if (millis() - BlowerStopTime > offTime * 1000UL)
    {
      StartBlower(CurrentBlower);
    }
  }
}

void StopBlower(int BlowerPin)
{
  digitalWrite(BlowerPin, LOW);
  BlowerIsRunning = false;
  BlowerStopTime = millis();
}

void StartBlower(int BlowerPin)
{
  digitalWrite(BlowerPin, HIGH);
  blows ++;
  BlowerIsRunning = true;
  BlowerStartTime = millis();
  myGLCD.setColor(VGA_WHITE);
  myGLCD.print("LAST APPLICATOR TO BLOW", CENTER, 216);
  myGLCD.setColor(VGA_RED);
  myGLCD.printNumI((BlowerPin - Machine1) / 1 + 1, CENTER, 234);
}
void keypadEvent (KeypadEvent key) {

  {
    switch (keypad.getState())
    {
      case PRESSED:
        if (key == 'A') {
          title();
        }
        else if (key == 'B') {
          offTimeChange();
          offT();
        }
        else if (key == 'C') {
          onTimeChange();
          onT();
        }
        break;
    }
  }


}
void offT() {

}
void onT() {
  
}

Any advise would be greatly appreciated!

  char key = keypad.getKey();
  if (key) {
    Serial.print(key);
  }

Having defined a callback function to deal with key presses, what is the purpose of this code?

void keypadEvent (KeypadEvent key) {

  {
    switch (keypad.getState())
    {
      case PRESSED:
        if (key == 'A') {

Where do you use the key if it is '0' to '9'? What key means "use this value"? What key means "Oops, discard that crap"?

PaulS:

  char key = keypad.getKey();

if (key) {
    Serial.print(key);
  }



Having defined a callback function to deal with key presses, what is the purpose of this code?



void keypadEvent (KeypadEvent key) {

{
    switch (keypad.getState())
    {
      case PRESSED:
        if (key == 'A') {



Where do you use the key if it is '0' to '9'? What key means "use this value"? What key means "Oops, discard that crap"?

I took all the "keypad" code from a sample on IDE, and thus it probably makes no sense. I used the Serial.print just to see what the output was on the monitor. I've also used the myGLCD.printNumI command to see what it would print on the screen, but it only outputs one character and not 4 digits in a row which I could then write to the offTime value...

As I said, I'm a complete novice and I've been thrown into the deep end to try figure all this out in a very short time, and I've been doing it for almost two weeks now. I spend quite a lot of hours per day on this, and have picked up a lot so far.

Just cant get my head around getting the keypad output to be displayed on the screen, while write it into a variable at the same time and then saving it into offTime.

I'm pretty sure I'm not using the correct terminology either, so I hope this all makes sense.

Just cant get my head around getting the keypad output to be displayed on the screen, while write it into a variable at the same time and then saving it into offTime.

Suppose I asked you to draw the characters that make up 345 on a chalk board. How would you do that? You look at the value to be printed, 345, and see that the value exceeds 10, so you know that more than 1 character is needed. You look at the value and see that it exceeds 100, so you know that more than 2 characters are needed. You look at the value and see that it is not greater than 1000, so you know that three characters are needed. You start with the 100's value, and draw a three, starting on the left of the board. Then, you divide the value by 100, to get 45, and see that the 10's value is 4. So, you draw a 4 in the next position. Then, you divide the value by 10, to get 5, and see that the 1's value is 5. So, you draw a 5 in the next position. Since that is the last character, you are done.

Now, it is not too hard to envision how to got the other direction. You define an array of characters, and create an index into the array. Initialize the index to 0. Each time you read a key, if it is not the "use the data" key, store it in the position in the array whose value is in the index variable, and then increment the index variable, and store a NULL in the new position. If it IS the "use the data" key, use atoi() to convert the array to an integer (or strtol() or strtoul(), for other types), store the result in the appropriate variable, and reset the index variable to 0 (and store a NULL in the array at the index location).

Robin2's tutorial, Serial input basics - updated, shows how to read data from the serial port, but the process is the same regardless of where the one-character-at-a-time data is coming from.

PaulS:
Suppose I asked you to draw the characters that make up 345 on a chalk board. How would you do that? You look at the value to be printed, 345, and see that the value exceeds 10, so you know that more than 1 character is needed. You look at the value and see that it exceeds 100, so you know that more than 2 characters are needed. You look at the value and see that it is not greater than 1000, so you know that three characters are needed. You start with the 100's value, and draw a three, starting on the left of the board. Then, you divide the value by 100, to get 45, and see that the 10's value is 4. So, you draw a 4 in the next position. Then, you divide the value by 10, to get 5, and see that the 1's value is 5. So, you draw a 5 in the next position. Since that is the last character, you are done.

Now, it is not too hard to envision how to got the other direction. You define an array of characters, and create an index into the array. Initialize the index to 0. Each time you read a key, if it is not the "use the data" key, store it in the position in the array whose value is in the index variable, and then increment the index variable, and store a NULL in the new position. If it IS the "use the data" key, use atoi() to convert the array to an integer (or strtol() or strtoul(), for other types), store the result in the appropriate variable, and reset the index variable to 0 (and store a NULL in the array at the index location).

Robin2's tutorial, Serial input basics - updated, shows how to read data from the serial port, but the process is the same regardless of where the one-character-at-a-time data is coming from.

Thanks man, I'll give the tutorial a read and see if I can make sense of it.
Appreciate the help!

Are you looking for debugging help or for someone to write the code for you? If it's the latter, send me a PM and I should be able to help if you can wait a few days: kinda booked up with projects at the moment.

PaulS:
Suppose I asked you to draw the characters that make up 345 on a chalk board. How would you do that? You look at the value to be printed, 345, and see that the value exceeds 10, so you know that more than 1 character is needed. You look at the value and see that it exceeds 100, so you know that more than 2 characters are needed. You look at the value and see that it is not greater than 1000, so you know that three characters are needed. You start with the 100's value, and draw a three, starting on the left of the board. Then, you divide the value by 100, to get 45, and see that the 10's value is 4. So, you draw a 4 in the next position. Then, you divide the value by 10, to get 5, and see that the 1's value is 5. So, you draw a 5 in the next position. Since that is the last character, you are done.

Now, it is not too hard to envision how to got the other direction. You define an array of characters, and create an index into the array. Initialize the index to 0. Each time you read a key, if it is not the "use the data" key, store it in the position in the array whose value is in the index variable, and then increment the index variable, and store a NULL in the new position. If it IS the "use the data" key, use atoi() to convert the array to an integer (or strtol() or strtoul(), for other types), store the result in the appropriate variable, and reset the index variable to 0 (and store a NULL in the array at the index location).

Robin2's tutorial, Serial input basics - updated, shows how to read data from the serial port, but the process is the same regardless of where the one-character-at-a-time data is coming from.

Am I anywhere near the right direction?

// Example 4 - Receive a number as text and convert it to an int
#include <UTFT.h>
#include <Keypad.h>
UTFT myGLCD(CTE32HR, 38, 39, 40, 41);
extern uint8_t BigFont[];
extern uint8_t Grotesk32x64[];
const byte ROWS = 4; // Four rows
const byte COLS = 4; // Four columns
char keys[ROWS][COLS] =
{
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {9, 8, 7, 6};
byte colPins[COLS] = {5, 4, 3, 2};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS );
//Serial code
const byte numChars = 32;
char receivedChars[numChars];   // an array to store the received data

boolean newData = false;

int dataNumber = 0;             // new for this version

void setup() {
  myGLCD.InitLCD();
  myGLCD.clrScr();
  myGLCD.setFont(BigFont);
  myGLCD.setColor(VGA_WHITE);
  myGLCD.print("Hello", CENTER, 100);
  Serial.begin(9600);
//  Serial.println("<Arduino is ready>");
}

void loop() {
  recvWithEndMarker();
  showNewNumber();
  
}

void recvWithEndMarker() {
  static byte ndx = 0;
  char endMarker = '\n';
  char rc;
  char key = keypad.getKey();

  if (key >= 0) {
    rc = key;
Serial.print(rc);

    if (rc != endMarker) {
      receivedChars[ndx] = rc;
      ndx++;
      if (ndx >= numChars) {
        ndx = numChars - 1;        
      }
    }
    else {
      receivedChars[ndx] = '\0'; // terminate the string
      ndx = 0;
      newData = true;
    }
  }
}

void showNewNumber() {
  if (newData == true) {
    dataNumber = 0;             // new for this version
    dataNumber = atoi(receivedChars);   // new for this version
    myGLCD.print("This just in ... ", CENTER, 116);
    Serial.println(receivedChars);
    myGLCD.print("Data as Number ... ", CENTER, 148);    // new for this version
    myGLCD.printNumI(dataNumber, CENTER, 170);     // new for this version
    newData = false;
  }
}

I've changed the Serial entries to try and use the keypad entries instead. I get as far as "rc" taking the numbers, but now I need to be able to use "#" to save the entry so that it goes into the dataNumber...

Am I anywhere near the right direction?

Near? Don't know. Going in the right direction? Sort of.

Which key generates the '\n'? None that I saw, so I don't know how you plan to break out of the loop reading the keys.

Reading your description, I'm getting the individual bits but not the overall package, the overall flow of control. When, for instance, does this sequence fire?

PaulMurrayCbr:
Reading your description, I'm getting the individual bits but not the overall package, the overall flow of control. When, for instance, does this sequence fire?

The device gets put into a factory, with coal boilers, where we have 8 blowers that "fire" in sequence every few seconds, individually and not together. The blows could be up to an hour apart, but not as likely as 30 to 180 seconds apart. The duration of each blow will never change from 10 seconds, but I'd rather put an option in to be able to change it, if necessary, without having plug a USB cable in.

The unit will be running no stop, and the feature to change the offTime is in case there's a fluctuation in coal usage. The amount of blows is directly measured according to coal usage, and needs to be adjustable by the client because we wont always be on site to make the change. So it has to be user friendly too.

The adjustment options need to be available at any time during the running of the unit, which is why I make the menu easily reachable via the "B" and "C" buttons.

Please let me know if this makes more sense?

PaulS:
Near? Don't know. Going in the right direction? Sort of.

Which key generates the '\n'? None that I saw, so I don't know how you plan to break out of the loop reading the keys.

PaulS.
I'm trying one of your examples to get the hang of the input/output function of the keypad. But I'm not having much success. I changed the screen setup to my screen, and the keypad to my setup.

#include <UTFT.h>
#include <Keypad.h>
UTFT myGLCD(CTE32HR, 38, 39, 40, 41);
extern uint8_t BigFont[];
extern uint8_t Grotesk32x64[];
const byte ROWS = 4; // Four rows
const byte COLS = 4; // Four columns
char keys[ROWS][COLS] =
{
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {9, 8, 7, 6};
byte colPins[COLS] = {5, 4, 3, 2};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS );

int v1 = 0;
int v2 = 0;
int v3 = 0;


void setup()
{
  myGLCD.InitLCD();
  myGLCD.clrScr();
  myGLCD.setFont(BigFont);
  myGLCD.setColor(VGA_WHITE);
  myGLCD.print("Hello", CENTER, 100);                            
  Serial.begin(9600);                     
}

void loop()
{
   v1 = GetNumber();
   v2 = GetNumber();
   v3 = GetNumber();

}


int GetNumber()
{
   int num = 0;
   char key = keypad.getKey();
   while(key != '#')
   switch (key)
   {
     case NO_KEY:
      break;

    case '0': case '1': case '2': case '3': case '4':
    case '5': case '6': case '7': case '8': case '9':
      myGLCD.print(key, CENTER, 116);
      num = num * 10 + (key - '0');
      break;

    case '#':
 //       Serial.println ();
       Serial.print (num);
        return num;
        break;

    case '*':
        num = 0;
        myGLCD.clrScr();
   }
}

It's not outputting anything to the lcd or Serial monitor in the num variable.
What am I doing wrong?

LanceRoberts:
PaulS.
I'm trying one of your examples to get the hang of the input/output function of the keypad. But I'm not having much success. I changed the screen setup to my screen, and the keypad to my setup.

#include <UTFT.h>

#include <Keypad.h>
UTFT myGLCD(CTE32HR, 38, 39, 40, 41);
extern uint8_t BigFont[];
extern uint8_t Grotesk32x64[];
const byte ROWS = 4; // Four rows
const byte COLS = 4; // Four columns
char keys[ROWS][COLS] =
{
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {9, 8, 7, 6};
byte colPins[COLS] = {5, 4, 3, 2};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS );

int v1 = 0;
int v2 = 0;
int v3 = 0;

void setup()
{
  myGLCD.InitLCD();
  myGLCD.clrScr();
  myGLCD.setFont(BigFont);
  myGLCD.setColor(VGA_WHITE);
  myGLCD.print("Hello", CENTER, 100);                           
  Serial.begin(9600);                   
}

void loop()
{
  v1 = GetNumber();
  v2 = GetNumber();
  v3 = GetNumber();

}

int GetNumber()
{
  int num = 0;
  char key = keypad.getKey();
  while(key != '#')
  switch (key)
  {
    case NO_KEY:
      break;

case '0': case '1': case '2': case '3': case '4':
    case '5': case '6': case '7': case '8': case '9':
      myGLCD.print(key, CENTER, 116);
      num = num * 10 + (key - '0');
      break;

case '#':
//      Serial.println ();
      Serial.print (num);
        return num;
        break;

case '*':
        num = 0;
        myGLCD.clrScr();
  }
}




It's not outputting anything to the lcd or Serial monitor in the num variable.
What am I doing wrong?

Ok, figured some of it out, it's outputting now.

PaulS:
Near? Don't know. Going in the right direction? Sort of.

Which key generates the '\n'? None that I saw, so I don't know how you plan to break out of the loop reading the keys.

Ok, I'm getting there, I think.
I've got it to output onto the screen, and it's putting the value into num.
Now, how do I get the entry to stop at 4 numbers?
How do I get the '#' to save the value from num into the offTime variable?
How do I get the '*' to cancel everything?

#include <UTFT.h>
#include <Keypad.h>
UTFT myGLCD(CTE32HR, 38, 39, 40, 41);
extern uint8_t BigFont[];
extern uint8_t Grotesk32x64[];
const byte ROWS = 4; // Four rows
const byte COLS = 4; // Four columns
unsigned long offTime = 0;
char keys[ROWS][COLS] =
{
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {9, 8, 7, 6};
byte colPins[COLS] = {5, 4, 3, 2};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS );

int v1 = 0;
int v2 = 0;
int v3 = 0;


void setup()
{
  myGLCD.InitLCD();
  myGLCD.clrScr();
  myGLCD.setFont(BigFont);
  myGLCD.setColor(VGA_WHITE);
  myGLCD.print("Hello", CENTER, 100);
  Serial.begin(9600);
}

void loop()
{
  v1 = GetNumber();
  //Serial.println ();
  //Serial.print (v1);
  v2 = GetNumber();
  v3 = GetNumber();

}


int GetNumber()
{
  int num = 0;
  char key = keypad.getKey();
  while (key != '#')
  {
    switch (key)
    {
      case NO_KEY:
        break;

      case '0': case '1': case '2': case '3': case '4':
      case '5': case '6': case '7': case '8': case '9':
        num = num * 10 + (key - '0');
        Serial.print(num); //Just wanted to see what's happening in the background
        myGLCD.printNumI(num, CENTER, 116);
        offTime = num;
        break;

      case '#':
        //      Serial.println ();
        //      Serial.print (num);
        myGLCD.setColor(VGA_RED);
        myGLCD.printNumI(offTime, CENTER, 300);
        return num;
        break;

      case '*':
        num = 0;
        myGLCD.clrScr();
        break;
    }
    key = keypad.getKey();
  }
  return num;
}

Now, how do I get the entry to stop at 4 numbers?

Count them. Pretend that the enter key was pressed when the 4th digit is entered.

How do I get the '#' to save the value from num into the offTime variable?

Stop doing that in the case '1' ... '9' block (that abbreviation works, by the way). Do it in the case '#' block.

Even better would be to not do it in that case, but do it in loop:

   offTime = GetNumber();

How do I get the '*' to cancel everything?

First, define what "cancel everything" means. That could mean to reset num to 0 (and the count of digits entered to 0) only. Or, it could mean reset num to 0, reset count to 0, and break out of the while loop.

Since you presumably do not want the user to enter negative values, you should probably return -1 if the cancel key means "cancel EVERYTHING" rather than "forget the number I've been entering and let me start over".

PaulS:
Count them. Pretend that the enter key was pressed when the 4th digit is entered.
Stop doing that in the case '1' ... '9' block (that abbreviation works, by the way). Do it in the case '#' block.

Even better would be to not do it in that case, but do it in loop:

   offTime = GetNumber();

First, define what "cancel everything" means. That could mean to reset num to 0 (and the count of digits entered to 0) only. Or, it could mean reset num to 0, reset count to 0, and break out of the while loop.

Since you presumably do not want the user to enter negative values, you should probably return -1 if the cancel key means "cancel EVERYTHING" rather than "forget the number I've been entering and let me start over".

You make it sound so easy. I'll give it a shot, thanks!

PaulS:
Count them. Pretend that the enter key was pressed when the 4th digit is entered.
Stop doing that in the case '1' ... '9' block (that abbreviation works, by the way). Do it in the case '#' block.

Even better would be to not do it in that case, but do it in loop:

   offTime = GetNumber();

First, define what "cancel everything" means. That could mean to reset num to 0 (and the count of digits entered to 0) only. Or, it could mean reset num to 0, reset count to 0, and break out of the while loop.

Since you presumably do not want the user to enter negative values, you should probably return -1 if the cancel key means "cancel EVERYTHING" rather than "forget the number I've been entering and let me start over".

Ok, I think I got the '#' and '*' buttons to do what I need, please can you check if there's anything wrong here?

I just cant get around "count to 4 and press enter"... Please can you explain a little bit more?

void loop()
{
  offTime = GetNumber();
}

int GetNumber()
{
  int num = 0;
  char key = keypad.getKey();
  char endMarker = '\n';
  while (key != '#')
  
    {
      switch (key)
      {
        case NO_KEY:
          break;

        case '0'...'9':
          num = num * 10 + (key - '0');
          Serial.print(num); //Just wanted to see what's happening in the background
          myGLCD.printNumI(num, CENTER, 116);
          break;

        case '#':

          Serial.print (num);
          myGLCD.setColor(VGA_RED);
          myGLCD.print("saved", CENTER, 200);
          return num;
          break;

        case '*':
          num = 0;
          myGLCD.clrScr();
          myGLCD.setFont(BigFont);
          myGLCD.setColor(VGA_WHITE);
          myGLCD.print("Hello", CENTER, 100);
          break;

        case 'A':
          myGLCD.printNumI(offTime, CENTER, 200); // Trying to see if anything fot written to offTime
          break;

      }
      key = keypad.getKey();
    }
    return num;
  
}

The scary part is that I'm going to have to tie this into my full code once I'm done....

int GetNumber()
{
  int num = 0;
  char key = keypad.getKey();
  char endMarker = '\n';
  while (key != '#')
 
    {

When you set num to 0, 0 keys have been pressed. So, create another variable, pressedKeyCount, and initialize it to 0.

      switch (key)
      {
        case NO_KEY:
          break;

        case '0'...'9':
          num = num * 10 + (key - '0');

AHA, a numeric key was pressed. So, increment pressedKeyCount. Is it now 4? That's enough key presses, so pretend that the enter key was pressed.

        case '#':

          Serial.print (num);
          myGLCD.setColor(VGA_RED);
          myGLCD.print("saved", CENTER, 200);
          return num;
          break;

This is what you do when the actual "enter" key is pressed. So, do this if pressedKeyCount equals 4.

PaulS:

int GetNumber()

{
 int num = 0;
 char key = keypad.getKey();
 char endMarker = '\n';
 while (key != '#')

{



When you set num to 0, 0 keys have been pressed. So, create another variable, pressedKeyCount, and initialize it to 0.



switch (key)
     {
       case NO_KEY:
         break;

case '0'...'9':
         num = num * 10 + (key - '0');



AHA, a numeric key was pressed. So, increment pressedKeyCount. Is it now 4? That's enough key presses, so pretend that the enter key was pressed.



case '#':

Serial.print (num);
         myGLCD.setColor(VGA_RED);
         myGLCD.print("saved", CENTER, 200);
         return num;
         break;



This is what you do when the actual "enter" key is pressed. So, do this if pressedKeyCount equals 4.

How do I press the enter key? Is it '\n'? It doesn't stop at 4 on either the Serial monitor or the screen. I'm sucking at this a bit... And we just got our order for a big trial in China, so now the heat is on!! Another late night for me.

I tried the endMarker, but it might be in the wrong place, not sure. Any sugestions?

{
  int num = 0;
  char key = keypad.getKey();
  int pressedKeyCount = 0;
  char endMarker = '\n';
  while (key != '#')

  {
    switch (key)
    {
      case NO_KEY:
        break;

      case '0'...'9':
        num = num * 10 + (key - '0');
        pressedKeyCount ++;
        if (pressedKeyCount != 4)
          endMarker;
        Serial.print(pressedKeyCount);
        //Serial.print(num); //Just wanted to see what's happening in the background
        myGLCD.printNumI(num, CENTER, 116);
        break;

      case '#':
        Serial.print (num);
        myGLCD.setColor(VGA_RED);
        myGLCD.print("saved", CENTER, 200);
        return num;
        break;

      case '*':
        num = 0;
        reset();
        break;

      case 'A':
        myGLCD.printNumI(offTime, CENTER, 200); // Trying to see if anything got written to offTime
        break;

    }
    key = keypad.getKey();
  }
  return num;

}

You're using the '#' key as enter. So when the count reaches four, do the same thing that you have in the '#' case.

Have you made any progress in the last couple of days?

wildbill:
You're using the '#' key as enter. So when the count reaches four, do the same thing that you have in the '#' case.

Have you made any progress in the last couple of days?

I wish I made some progress, been running ragged the last few days, haven't had much time for coding. Will hopefully get back to it tomorrow.

Thanks for the advise, will try it.