#include #define KNOCK_PIN A0 #define BTN_PIN 3 #define BUZZER_PIN 9 #define LED_PIN 8 #define KNOCK_HIGH 300 #define KNOCK_TIMEOUT 1000 #define BTN_SHORT_MIN 100 #define BTN_SHORT_MAX 2000 #define BTN_LONG_MIN 3000 #define BTN_LONG_MAX 10000 #define OPEN 107 #define OPEN2 103 #define CLOSE 85 #define CLOSE2 88 #define CODE_LEN 5 enum State { OPENED, CLOSED, SETPWD, CNFPWD, INIT }; bool code[CODE_LEN] = { 1, 0, 1, 0, 1 }; bool input[CODE_LEN] = { 0, 0, 0, 0, 0 }; unsigned int knockLevel = 0; State state; Servo srv; void setup() { Serial.begin(115200); pinMode(BTN_PIN, INPUT); pinMode(LED_PIN, OUTPUT); digitalWrite(LED_PIN, LOW); state = INIT; Serial.println("Started."); } bool btn(void) { return digitalRead(BTN_PIN); } bool getknk(void) { bool b1, b2; while(1) { b1 = analogRead(KNOCK_PIN) > knockLevel; delay(1); b2 = analogRead(KNOCK_PIN) > knockLevel; if(b1 == b2) return b1; delay(1); } return false; } char getch_knk(void) { unsigned long tm = millis(); while(!getknk() and millis()-tm < KNOCK_TIMEOUT); if(millis()-tm >= KNOCK_TIMEOUT) return -1; tm = millis(); while(getknk()); while(!getknk() and millis()-tm < KNOCK_HIGH); tm = millis()-tm; while(getknk()); if(tm < KNOCK_HIGH) return 0; return 1; } char readCode(void) { int i; char ch; for(i = 0; i < CODE_LEN; i++) { ch = getch_knk(); if(ch < 0) return -1; input[i] = ch; Serial.print((int)ch); } Serial.println(""); for(i = 0; i < CODE_LEN; i++) { if(input[i] != code[i]) return 0; } return 1; } void readPwd(void) { int i; char ch; for(i = 0; i < CODE_LEN; i++) { while((ch = getch_knk()) < 0); input[i] = ch; Serial.print((int)ch); } } void ledOn(void) { digitalWrite(LED_PIN, HIGH); } void ledOff(void) { digitalWrite(LED_PIN, LOW); } void open(void) { srv.attach(5); srv.write(OPEN); delay(500); srv.write(OPEN2); delay(100); srv.detach(); state = OPENED; Serial.println("Opened."); } void close(void) { srv.attach(5); srv.write(CLOSE); delay(500); srv.write(CLOSE2); delay(100); srv.detach(); state = CLOSED; Serial.println("Closed."); } void loop() { int i; char ch; unsigned long tm; knockLevel = analogRead(A1); switch(state) { case OPENED: while(btn()); tm = millis(); while(!btn()); tm = millis()-tm; if(tm > BTN_SHORT_MIN and tm < BTN_SHORT_MAX) close(); else if(tm > BTN_LONG_MIN and tm < BTN_LONG_MAX) state = SETPWD, ledOn(); break; case CLOSED: ch = readCode(); if(ch < 0) { Serial.println("FAIL"); break; } if(ch == 1) open(); else { tone(BUZZER_PIN, 500, 200); delay(200); tone(BUZZER_PIN, 500, 200); delay(200); tone(BUZZER_PIN, 500, 200); delay(200); } break; case SETPWD: Serial.print("Input code:"); readPwd(); for(i = 0; i < CODE_LEN; i++) code[i] = input[i]; Serial.println(""); state = CNFPWD; break; case CNFPWD: Serial.print("Confirm code:"); readPwd(); for(i = 0; i < CODE_LEN; i++) if(code[i] != input[i]) break; Serial.println(""); if(i == CODE_LEN) ledOff(), state = OPENED; else state = SETPWD; break; case INIT: open(); break; } }