// LIBRARIES
#include <Keypad.h>
#include <LiquidCrystal_I2C.h>
#include <Adafruit_NeoPixel.h>
// DEFINES
#define ROWS 4
#define COLS 3
#define I2C_ADDR 0x27
#define LCD_COLUMNS 20
#define LCD_LINES 2
#define NUM_LEDS 16 // Aantal leds op de ring
#define PIN_NEO 6 // Pin waarop de ring is aangesloten
#define BRIGHTNESS 255 // Intensteit waarop de Leds branden
// STATES SYSTEM
#define WAIT_4_INPUT 0
#define CHECK_CODE 1
#define OPENDOOR 2
#define WAIT_4_CLEAR 3
#define CLOSE_DOOR 4
#define CODE_FOUT 5
// keyboard
char keys[ROWS][COLS] = {
{ '1', '2', '3'},
{ '4', '5', '6'},
{ '7', '8', '9'},
{ 'C', '0', '#'}
};
byte rowPins[ROWS] = {5, 4, 3, 2};
byte colPins[COLS] = {A3, A2, A1};
byte pos = 0;
unsigned long timerCode;
unsigned long timerInterval = 10000;
byte oldState = WAIT_4_INPUT;
byte systemState = WAIT_4_INPUT;
String code = "";
String systemStates[] = {"WAIT_4_INPUT", "CHECK_CODE", "OPENDOOR", "WAIT_4_CLEAR", "CLOSE_DOOR","CODE_FOUT"};
// OBJECTS
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
LiquidCrystal_I2C lcd(I2C_ADDR, LCD_COLUMNS, LCD_LINES);
// NEO_GRB + NEO_KHZ800 zijn component-eigenschappen.
Adafruit_NeoPixel ring(NUM_LEDS, PIN_NEO, NEO_GRB + NEO_KHZ800);
// FUNCTIONS
void pinModes();
void initLCD();
void initNeoPixel();
void changeRingColor(byte R, byte G, byte B);
void handleKey(char key);
void updateSystem();
void checkTimeOutCode();
void checkCode();
void tekstOpLCD(byte start0, String boodschap0, byte start1, String boodschap1);
void setup() {
Serial.begin(9600);
pinModes();
initLCD();
initNeoPixel();
timerCode = millis();
}
void loop() {
char key = keypad.getKey(); // lokaal
if (key != NO_KEY) {
Serial.println(key);
handleKey(key); // geef mee als parameter
}
if (oldState != systemState) {
Serial.println(systemStates[systemState]);
oldState = systemState;
updateSystem();
}
checkTimeOutCode();
}
void changeRingColor(byte R, byte G, byte B) {
for (int i = 0; i < NUM_LEDS; i++) {
ring.setPixelColor(i, ring.Color(R, G, B));
}
ring.show();
}
void handleKey(char key) {
switch (key) {
case 'C': // Is de CLEAR-knop dus reset de code en display
reset();
break;
case '#': // Is de OK-knop dus controleer of de code juist is
systemState = CHECK_CODE;
Serial.println("Enter");
break;
default: // Dit zijn alle andere knoppen
byte lenCode = pos % 4;
lcd.setCursor(3 + (lenCode), 0); // 3 is de startpositie die ik koos op de LCD
lcd.print(key);
lcd.setCursor(3 + (lenCode), 1);
lcd.print('*');
// Controle of de code langer is dan 4 cijfers
if ((lenCode) == 0) {
code = key;
} else {
code = code + key;
}
Serial.print("Deze toetsen werden reeds ingedrukt: ");
Serial.println(code);
pos++; // We schuiven de cursor 1 positie op
// Na elke toets die je indrukt moet je de gebruiker opnieuw 10
// seconden geven om de volgende toets in te drukken.
// Lukt dit niet, dan moet deze opnieuw beginnen en reset het
// systeem (de code) zich. Dus de timer moet opnieuw ingesteld worden
// na elke toets.
timerCode = millis();
break;
}
}
void updateSystem() {
switch (systemState) {
case WAIT_4_INPUT: // 0
break;
case CHECK_CODE: // 1
checkCode();
break;
case CODE_FOUT:
if (millis() - timerCode > 2000) {
lcd.clear();
timerCode = millis();
systemState = WAIT_4_INPUT;
}
break;
case OPENDOOR: // 2
break;
case WAIT_4_CLEAR: // 3
break;
case CLOSE_DOOR: // 4
break;
default:
break;
}
}
void checkTimeOutCode() {
if (millis() - timerCode > timerInterval) {
reset();
timerCode = millis();
}
}
void checkCode() {
if (code == "1234") {
changeRingColor(0, 255, 0);
systemState = OPENDOOR;
} else {
tekstOpLCD(3, "Foute code", 1, "Probeer opnieuw");
timerCode = millis();
systemState = CODE_FOUT;
}
}
void reset() {
Serial.println("Reset");
lcd.clear();
code = "";
pos = 0;
changeRingColor(255, 0, 0);
}
void initNeoPixel() {
ring.begin();
ring.setBrightness(BRIGHTNESS);
changeRingColor(255, 0, 0); // Initialiseer alle led op zwart (geen licht)
ring.show();
}
void initLCD() {
// Init LCD
lcd.init();
lcd.backlight();
}
void pinModes() {
// De pins voor de touchPad, NeoPixel en de LCD worden in de bibliotheken ingesteld
}
void tekstOpLCD(byte start0, String boodschap0, byte start1, String boodschap1) {
lcd.clear();
lcd.setCursor(start0, 0); // 3 is de startpositie die ik koos op de LCD
lcd.print(boodschap0);
lcd.setCursor(start1, 1);
lcd.print(boodschap1);
}COLS
ROWS