| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 | #include <Arduino.h>
#include <Keypad/Keypad.h>
#include <LiquidCrystal.h>
#define KP_ROWS 4
#define KP_COLS 4
char keys[KP_ROWS][KP_COLS] = {
        {'1','2','3','A'},
        {'4','5','6','B'},
        {'7','8','9','C'},
        {'*','0','#','.'}
};
byte rowPins[KP_ROWS] = {A3, A2, A0, A1};
byte colPins[KP_COLS] = {8, 9, 10, 11};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, KP_ROWS, KP_COLS);
#define LCD_ROWS 2
#define LCD_COLS 16
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);
#define SELF_TEST_LABEL "Self testing..."
#define SELF_TEST_ERROR_LABEL "Error: "
#define UID_LABEL "UID:"
#define PWD_LABEL "PWD:"
#define UID_MAX_LEN 12
#define PWD_MAX_LEN 12
String uid;
String password;
enum Status {
    Uid,
    Password,
    SelfTest
};
Status status = Uid;
#define MAX_IDLE_TIME 20
unsigned long lastActivity = 0;
#define SELF_TEST_INTERVAL 60
#define SELF_TEST_ERROR_INTERVAL 2
#define MAX_SELF_TEST_TIME 5
unsigned long lastSelfTest = 0;
#define SELF_TEST_NO_ERROR '0'
int lastSelfTestResult = SELF_TEST_NO_ERROR;
void setup() {
    Serial.begin(9600);
    Serial.println("Starting...");
    lcd.begin(LCD_COLS, LCD_ROWS);
    lcd.blink();
    lcd.noAutoscroll();
    selfTest();
}
String makeChars(char c, int count) {
    char str[count + 1];
    memset(str, c, count);
    str[count] = 0;
    return String(str);
}
bool handleUidPassword(String& str, int maxLength, char key) {
    int len = str.length();
    if (key >= '0' && key <= '9') {
        if (len < maxLength) {
            str += key;
            return true;
        }
    }
    else if (key == 'C' || key == '*') {
        if (len > 0) {
            str = str.substring(0, len - 2);
            return true;
        }
    }
    return false;
}
void loop() {
    unsigned long secs = millis() / 1000;
    if (handleKeyPad()) {
        lastActivity = secs;
        updateLcd();
    }
    if ((uid.length() != 0 || password.length() != 0) && secs - lastActivity >= MAX_IDLE_TIME) {
        askUidPassword();
    }
    if (uid.length() == 0 && password.length() == 0 && secs - lastSelfTest >= SELF_TEST_INTERVAL) {
        selfTest();
    }
}
bool handleKeyPad()
{
    char key = keypad.getKey();
    if (key != NO_KEY) {
        if (status == Uid) {
            if (key == '#') {
                if (uid.length() != 0) {
                    status = Password;
                    return true;
                }
            }
            else {
                return handleUidPassword(uid, UID_MAX_LEN, key);
            }
        }
        else if (status == Password) {
            if (key == '#') {
                if (password.length() != 0) {
                    login(uid, password);
                    return true;
                }
            }
            else {
                return handleUidPassword(password, PWD_MAX_LEN, key);
            }
        }
    }
    return false;
}
void updateLcd()
{
    Serial.println("Update LCD");
    lcd.clear();
    if (status ==  Uid || status == Password)
    {
        lcd.setCursor(0, 0);
        lcd.print(UID_LABEL);
        lcd.print(uid);
        lcd.setCursor(0, 1);
        lcd.print(PWD_LABEL);
        lcd.print(makeChars('*', password.length()));
        if (status == Uid) {
            lcd.setCursor(strlen(UID_LABEL) + uid.length(), 0);
        }
        else {
            lcd.setCursor(strlen(PWD_LABEL) + password.length(), 1);
        }
    }
    else if (status == SelfTest) {
        lcd.print(SELF_TEST_LABEL);
        if (lastSelfTestResult != SELF_TEST_NO_ERROR) {
            lcd.setCursor(0, 1);
            lcd.print(SELF_TEST_ERROR_LABEL);
            lcd.print(lastSelfTestResult);
        }
    }
}
void askUidPassword()
{
    status = Uid;
    uid = "";
    password = "";
    updateLcd();
}
void login(String uid, String password)
{
    Serial.println(uid);
    Serial.println(password);
    askUidPassword();
}
void selfTest()
{
    lastSelfTest = SELF_TEST_NO_ERROR;
    status = SelfTest;
    updateLcd();
    bool test = true;
    while (test) {
        unsigned long secs = millis() / 1000;
        Serial.println("Self Testing");
        while (Serial.available() == 0 && (millis() / 1000) - secs < MAX_SELF_TEST_TIME);
        if (Serial.available() > 0) {
            lastSelfTestResult = Serial.read();
            if (lastSelfTestResult == SELF_TEST_NO_ERROR) {
                test = false;
            }
            else {
                updateLcd();
                delay(SELF_TEST_ERROR_INTERVAL * 1000);
            }
        }
    }
    lastSelfTest = millis() / 1000;
    askUidPassword();
}
 |