#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
#include<Keypad.h>
char customKey=0;
const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
char hexaKeys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte rowPins[ROWS] = {A15, A14, A13, A12}; //row pinouts of the keypad
byte colPins[COLS] = {A11, A10, A9, A8}; //column pinouts of the keypad
Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS); //initialize an instance of class NewKeypad
const byte IN4 = 4;
const byte IN5 = 5;
const byte IN6 = 6;
const byte LockInd = 13;
const unsigned long shortWaitTime = 75;
const unsigned long longWaitTime = 150;
struct pressButtonType
{
byte Pin;
unsigned long lastChange;
int lastState;
int state;
boolean pressed();
};
boolean pressButtonType::pressed()
{
int state = digitalRead(pressButtonType::Pin);
if (state != pressButtonType::lastState) {
pressButtonType::lastChange = millis();
pressButtonType::lastState = state;
}
if (state != pressButtonType::state && millis() - pressButtonType::lastChange > 50) {
pressButtonType::state = state;
};
return !pressButtonType::state;
}
enum CountStates {idle, COUNTUP, COUNTDOWN, COUNTUPDEC, COUNTDOWNDEC};
CountStates actState = idle;
CountStates lastState = idle;
signed long count = 0; // Changed to 0 so that COUNTUP starts with 1
signed long StartCountUpDec = 1; // Used by COUNTUPDEC when the counting limit has been reached
signed long StartCountDownDec = 444; // Used by COUNTDOWNDEC when the counting limit has been reached
pressButtonType but4 = {IN4, 0, HIGH};
pressButtonType but5 = {IN5, 0, HIGH};
pressButtonType but6 = {IN6, 0, HIGH};
void setup()
{
lcd.init();
lcd.backlight();
Serial.begin(9600);
Serial.println("Start");
pinMode(but4.Pin, INPUT_PULLUP);
pinMode(but5.Pin, INPUT_PULLUP);
pinMode(but6.Pin, INPUT_PULLUP);
actState = idle;
lcd.setCursor(0,0);
lcd.print("Start ... ");
delay(1000); // Just to allow to read the "Start" on LCD ..
}
String ActStartNo = String(count);
boolean Error = false;
void loop()
{
StateMachine();
static String StartNo = "";
char key = customKeypad.getKey();
if (key != NO_KEY) {
// lcd.setCursor(0,1); // Displaying the key pressed value
// lcd.print(StartNo+key);
switch(key) {
case '*' : // As we limit the no of digits already in default now
// we do not need the if here anymore
count = StartNo.toInt(); // Press * to apply and clear StartNo
// Note that here is NO break; so
// the next lines until the break; below
// case 'C' will also be executed
if (count > StartCountDownDec) count = StartCountDownDec; // Check for the given maximum!!
lcd.setCursor(0,1);
lcd.print(" ");
//StartNo = "";
//break;
case '#' : StartNo = ""; // Press # to clear StartNo
lcd.setCursor(0,1);
//lcd.print("Res");
//delay(444);
lcd.print(" ");
break; // break required, otherwise it runs into next "case"
case 'A' : StartCountDownDec = StartNo.toInt(); // Press A to set new StartCountDownDec
break; // break required, otherwise it runs into next "case"
case 'B' : if (StartNo.length() >= 1) {
StartNo.remove(StartNo.length()-1);
}
break;
case 'C' : // As long as A is not separately handled, it must be here!
case 'D' : // because these all be ignored now!!!
break;
default : if (StartNo.length() < 3)
{
StartNo = StartNo+key; // All keys except those mentioned above appended to StartNo
}
else if(key>=445)
{
Error = true;
}
// else
// {
// Error = true;
// }
// if (key>444)
// {
// StartNo="";
// }
break;
}
ActStartNo = StartNo; // Set the global to the actual state of StartNo so that it can be printed in loop)()
}
//void PrintData()//
static signed long OldCount = 0;
static String OldStartNo = "";
static signed long OldStartCountDownDec = 0;
static unsigned long lastError = 0;
static boolean RemoveError = false;
static boolean RefreshMax = true;
if (OldCount != count) {
Serial.println(count);
OldCount = count;
lcd.setCursor(0,0);
lcd.print("Counting");
lcd.setCursor(11,1);
lcd.print(" "); // Deleting previous data in row 2 on the left side only!
lcd.setCursor(11,1);
lcd.print(count);
}
if (OldStartNo != ActStartNo){
OldStartNo = ActStartNo;
Serial.println(StartNo);
lcd.setCursor(0,1);
lcd.print(" "); // Deleting previous data in row 2 on the left side only!
lcd.setCursor(0,1); // Displaying the key pressed value
lcd.print(StartNo);
}
// if (Error) {
// Serial.println("Maximum Digits reached ... Apply, Remove or Clear!");
// //lcd.setCursor(11,0);
// //lcd.print("Error");
// Error = false;
// RemoveError = true;
// RefreshMax = false;
// lastError = millis();
// }
// if (RemoveError && millis() - lastError > 1000) {
// RemoveError = false;
// RefreshMax = true;
// OldStartCountDownDec = 0; // To force an update!
// }
if (RefreshMax && OldStartCountDownDec != StartCountDownDec) {
OldStartCountDownDec = StartCountDownDec;
lcd.setCursor(11,0);
lcd.print(" ");
//lcd.setCursor(11,0);
//lcd.print(StartCountDownDec);
}
if (Error)
{
lcd.setCursor(2,1);
lcd.print(" ");
}
} // void loop ends here
void StateMachine()
{
static unsigned long lastActionTime = 0;
static unsigned long WaitTime = longWaitTime;
switch (actState)
{
case idle : if (but4.pressed())
{
actState = COUNTUP;
};
if (but5.pressed())
{
actState = COUNTDOWN;
};
if (but6.pressed() && but4.pressed())
{
actState = COUNTUPDEC;
StartCountUpDec = (count % 10); // Sets the COUNTUPDEC start value to actual (count modulo 10)
}; // Which is the last decimal of count (e.g. 8 for 18)
if (but6.pressed() && but5.pressed())
{
actState = COUNTDOWNDEC;
StartCountDownDec = 444 + (count % 20);
if (count - 10 <= 1)// && count >= 444)
count = StartCountDownDec;
};
WaitTime = longWaitTime;
break;
case COUNTUP :
if (but5.pressed()) WaitTime = shortWaitTime;
else WaitTime = longWaitTime;
if (but4.pressed() && millis()-lastActionTime >= WaitTime)// || case 'C')
{
lastActionTime = millis();
if(count<444)
{
count=count+1;
}
else
{
count=1;
}
//Serial.println(count);
}
if (!but4.pressed() && !but5.pressed()) actState = idle;
break;
case COUNTDOWN :
if (but4.pressed()) WaitTime = shortWaitTime;
else WaitTime = longWaitTime;
if (but5.pressed() && millis()-lastActionTime >= WaitTime)
{
lastActionTime = millis();
if(count>1)
{
count=count-1;
}
else
{
count=444;
}
//Serial.println(count);
}
if (!but4.pressed() && !but5.pressed()) actState = idle;
break;
//*
case COUNTUPDEC :
if (but5.pressed()) WaitTime = shortWaitTime;
else WaitTime = longWaitTime;
if (but4.pressed() && millis()-lastActionTime >= WaitTime)
{
lastActionTime = millis();
//if(count+10<100) // Added (+10) do avoid counting over 100
if(count+10<=444)
{
count=count+10;
}
else
{
count=StartCountUpDec; // Reset count
}
//Serial.println(count);
}
if (!but4.pressed() && !but5.pressed()) actState = idle;
break;
case COUNTDOWNDEC :
if (but4.pressed()) WaitTime = shortWaitTime;
else WaitTime = longWaitTime;
if (but5.pressed() && millis()-lastActionTime >= WaitTime)
{
lastActionTime = millis();
if(count>=1 && count<=444)
{
count=count-10;
}
else
{
//count=StartCountDownDec;
count=444; // Reset count
}
//Serial.println(count);
}
if (!but4.pressed() && !but5.pressed()) actState = idle;
break;
default : actState = idle;
break;
}
//}
//PrintCounter();
//HandleKeyPad();
}