#include #define ENCODER_SW 2 #define ENCODER_CLK 3 #define ENCODER_DT 4 #define SWITCH 7 #define LED_RED 10 #define LED_GREEN 11 #define LED_BLUE 12 #define VIBRATION_SWITCH 6 #define LCD_ANIMATION_SPEED 250 LiquidCrystal_I2C lcd(0x27, 20, 4); int openCodes[] = { 5703, 6219 }; int adminCode = 3497; enum modes { day, night } mode = night; enum states { closed, open, alarm } state = closed; const char stateNames[][9] = { "Zavreno", "Otevreno", "Alarm" }; int digits[4]; byte digitsEntered = 255; bool digitsDirty = false; byte strikes=0; states nextState = 255; long lastLCDTick = 0; byte LCDAnimationFrame = 0; long lastButtonPress = 0; long buttonPressStart = 0; bool buttonPressActive = false; bool lastSwitchState; void setup() { lcd.init(); lcd.backlight(); Serial.begin(9600); Serial.println("System pro ovladani trezoru byl aktivovan"); pinMode(ENCODER_SW, INPUT_PULLUP); pinMode(ENCODER_CLK, INPUT); pinMode(ENCODER_DT, INPUT); attachInterrupt(digitalPinToInterrupt(ENCODER_SW), buttonPress, CHANGE); attachInterrupt(digitalPinToInterrupt(ENCODER_CLK), encoderClock, CHANGE); pinMode(SWITCH, INPUT_PULLUP); lastSwitchState=digitalRead(SWITCH); pinMode(VIBRATION_SWITCH, INPUT_PULLUP); setMode(night); } void loop() { if ((millis() - lastLCDTick) > LCD_ANIMATION_SPEED) { tickLCD(); lastLCDTick = millis(); } if (digitsDirty) { displayCode(); digitsDirty = false; } if (nextState!=255) { setState(nextState); nextState=255; } if (lastSwitchState!=digitalRead(SWITCH)) { lastSwitchState=digitalRead(SWITCH); if (mode==day) { setMode(night); } else { setMode(day); } } if (Serial.available()) { switch (Serial.read()) { case 'Q': if (state == alarm) { strikes=0; setState(closed); Serial.println("Alarm vypnut"); } break; case 'S': if (mode==day) { Serial.print("Den"); } else { Serial.print("Noc"); } Serial.print(", "); if (state==open) { Serial.println("Otevreno"); } else if (state==closed) { Serial.println("Zavreno"); } else { Serial.println("Alarm"); } break; case 'R': if (mode==day) { setMode(night); } else { setMode(day); } break; } } if (state==closed) { if (digitalRead(VIBRATION_SWITCH)) { Serial.println("Podezdrele otresy!"); setState(alarm); } } setLED(); } void setMode(modes newMode) { if (newMode == night) { if (state == open) { return; } Serial.println("Rezim NOC"); lcd.clear(); lcd.noBlink(); clearCode(); LCDAnimationFrame = 254; // tickLCD will print the text on next tick } if (newMode == day) { Serial.println("Rezim DEN"); lcd.clear(); setState(state); } mode = newMode; } void setState(states newState) { if (mode==day) { lcd.clear(); if (mode==day) { lcd.setCursor(8 - strlen(stateNames[state])/2, 0); // Calculates position for text to be centered lcd.print(stateNames[state]); } lcd.setCursor(16 + 8 - strlen(stateNames[newState])/2, 0); // The Display has a buffer off screen for scrolling lcd.print(stateNames[newState]); LCDAnimationFrame = 0; } state = newState; } void tickLCD() { if (mode == night) { lcd.scrollDisplayRight(); LCDAnimationFrame++; if (LCDAnimationFrame >= 11 + 16 + 2) { lcd.clear(); lcd.setCursor(40 - 12, 0); lcd.print("Nocni rezim"); LCDAnimationFrame = 0; } } if (mode == day) { if (LCDAnimationFrame < 16) { lcd.scrollDisplayLeft(); // Scrolls entire screen, the entered code is moved manualy in the opposite direction LCDAnimationFrame++; displayCode(); } } } void displayCode() { if (mode==day && digitsEntered!=255) { lcd.setCursor(5 + LCDAnimationFrame, 1); // Counteract scrolling lcd.print(" "); for (byte i=0;i<=4;i++) { if (i= 3000)) { nextState = closed; } buttonPressActive = false; } } } void encoderClock() { if (mode==day && state!=open && digitsEntered!=255) { if (digitalRead(ENCODER_CLK) == digitalRead(ENCODER_DT)) { digits[digitsEntered]--; } else { digits[digitsEntered]++; } digits[digitsEntered]+=10; digits[digitsEntered]%=10; digitsDirty = true; } } void setLED() { bool phase = millis()%1000 > 500; if (mode==day) { if (state==closed) { digitalWrite(LED_RED, LOW); digitalWrite(LED_GREEN, HIGH); digitalWrite(LED_BLUE, LOW); } if (state==open) { digitalWrite(LED_RED, LOW); digitalWrite(LED_GREEN, phase); digitalWrite(LED_BLUE, LOW); } if (state==alarm) { digitalWrite(LED_RED, phase); digitalWrite(LED_GREEN, LOW); digitalWrite(LED_BLUE, LOW); } } else { if (state == alarm) { digitalWrite(LED_RED, phase); digitalWrite(LED_GREEN, phase); digitalWrite(LED_BLUE, LOW); } else { digitalWrite(LED_RED, LOW); digitalWrite(LED_GREEN, LOW); digitalWrite(LED_BLUE, HIGH); } } }