/* Komentare pro porotu soutez v programovani 2019, ustredni kolo Ondrej Mach, cislo 415 Zarizeni by melo byt plne funkcni podle zadani, implementovany jsou vsechny funkce krome posouvani textu na displayi. Zarizeni je napajeno ze zasuvky nabijeckou na telefon. kabel k arduino vede pouze pro datovou komunikaci. Program je konstruovan tak, aby co nejrychleji probihal cyklus loop, k casovani udalosti vyuziva funkce millis(). Pro rotacni enkoder jsou zde pouzita preruseni, protoze pulzy probehnou velmi rychle. Poznamka: V zadani nebylo explicitne receno, jestli muze kod pro otevreni trezoru fungovat, kdyz je alarm. Ridil jsem se podle sve predstavy treyoru, takze u tohoto trezoru je treba nejprve vypnout alarm, pote jde teprve otevrit Senzor vibraci je pridelan napevno k desce, pro aktivaci staci silneji tuknout do desky Omluvete prosim spatne odsazeni, Arduino IDE nedovoli lepsi */ #include //jedina pouzita knihovna je pro LCD display pres royhrani i2c // piny vsech periferii jsou urceny zde a lze je jednoduse prepsat #define rgbRed 9 //RGB led #define rgbGreen 10 #define rgbBlue 11 #define sw 5 //prepinac #define encData 2 //enkoder #define encClk 3 #define encSw 4 #define sensorMove A6 //senzor pohybu #define sensorTilt A7 //senzor vibraci a sklonu int turn; bool clicked; bool lastSw; int fill; int number = 0; int wrong = 0; bool prevMove = 0; bool dayTime = 0; //denni cas - 1:den , 0:noc int state = 1; //stav - 0:Otevreno, 1:Zavreno, 2:Alarm bool lastDayTime = dayTime; int lastState = state; long t[5]; int incomingByte; LiquidCrystal_I2C lcd(0x27, 20, 4); void setup() { pinMode(rgbRed, OUTPUT); //Nastaveni vstupu a vystupu pinMode(rgbGreen, OUTPUT); pinMode(rgbBlue, OUTPUT); pinMode(sw, INPUT_PULLUP); pinMode(encData, INPUT); pinMode(encClk, INPUT); pinMode(encSw, INPUT); Serial.begin(9600); lcd.init(); //inicializace LCD lcd.backlight(); attachInterrupt(digitalPinToInterrupt(encData), turnData, FALLING); //nastaveeni preruseni pro enkoder attachInterrupt(digitalPinToInterrupt(encClk), turnClock, FALLING); lastSw = digitalRead(sw); Serial.println("System pro ovladani trezoru byl aktivovan"); } void loop() { lcdShow(); //Ukaze na display data a zpracovava zadavani kodu movement(); //Ziskava data ze senzoru pohybu tilt(); //Ziska data o vibracich checkClick(); //Zkontroluje tlacitko enkoderu a vypinac led(); //Podle dat rozsviti LED checkSerial(); //Zkontroluje vstup na seriovy port, oznamuje zmeny modu nebo casu pocitaci } void checkSerial(){ if (Serial.available() > 0) { incomingByte = Serial.read(); if (incomingByte == 'Q') { state = 1; } if (incomingByte == 'S') { printDayTime(); printState(); } if (incomingByte == 'R') { dayTime = !dayTime; } } if(state != lastState){ lastState = state; printState(); } if(dayTime != lastDayTime){ lastDayTime = dayTime; printDayTime(); } } void checkClick(){ if(lastSw != digitalRead(sw)){ dayTime = !dayTime; lastSw = digitalRead(sw); } if((digitalRead(encSw) == LOW) and !clicked and (millis() - t[3] > 500)){ t[3] = millis(); clicked = 1; } } void tilt(){ if(state != 0 and tiltDetected() and state != 2){ Serial.println("Podezrele otresy!"); state = 2; } } void movement(){ if(!dayTime and state != 2){ if(moveDetected() and !prevMove){ t[1] = millis(); prevMove = 1; Serial.println("Podezrely pohyb"); } if(prevMove and (millis() - t[1] > 3000)){ if(moveDetected()){ state = 2; prevMove = 0; }else{ prevMove = 0; } } } } void lcdShow(){ if(millis() > t[0] + 400){ lcd.clear(); if(dayTime){ lcd.setCursor(6, 0); switch(state){ case 0: lcd.print("Otevreno"); break; case 1: lcd.print("Zavreno"); break; case 2: lcd.print("Alarm"); break; } if((state == 0) and clicked and (millis() - t[3] > 3000)){ state = 1; clicked = 0; } if((state != 0) and clicked and (fill == 0)){ fill = 1; number = 0; clicked = 0; turn = 0; } if(fill != 0){ lcd.blink(); lcd.setCursor(7,1); for(int i = 1; i < fill; i++){ lcd.print("*"); } int a = (turn + 100) % 10; lcd.print(a); if(clicked){ clicked = 0; turn = 0; number += a * pow(10, 4 - fill); fill++; } if(fill > 4){ checkNum(number); fill = 0; } }else{ lcd.noBlink(); } }else{ lcd.noBlink(); clicked = 0; lcd.setCursor(5, 0); lcd.print("Nocni rezim"); fill = 0; } t[0] = millis(); } } void led(){ if(dayTime){ if(state == 0){ if(millis() - t[2] > 500){ digitalWrite(rgbRed, LOW); digitalWrite(rgbGreen, !digitalRead(rgbGreen)); digitalWrite(rgbBlue, LOW); t[2] = millis(); } }else{ if(state == 1){ digitalWrite(rgbRed, LOW); digitalWrite(rgbGreen, HIGH); digitalWrite(rgbBlue, LOW); }else{ if(millis() - t[2] > 500){ digitalWrite(rgbRed, !digitalRead(rgbRed)); digitalWrite(rgbGreen, LOW); digitalWrite(rgbBlue, LOW); t[2] = millis(); } } } }else{ if(state == 2){ if(millis() - t[2] > 500){ digitalWrite(rgbRed, !digitalRead(rgbGreen)); digitalWrite(rgbGreen, !digitalRead(rgbGreen)); digitalWrite(rgbBlue, LOW); t[2] = millis(); } }else{ if(prevMove){ digitalWrite(rgbRed, HIGH); digitalWrite(rgbGreen, HIGH); digitalWrite(rgbBlue, LOW); }else{ digitalWrite(rgbRed, LOW); digitalWrite(rgbGreen, LOW); digitalWrite(rgbBlue, HIGH); } } } } void checkNum(int number){ number += 1; if((number == 5703) or (number == 6219)){ if(state == 1){ state = 0; wrong = 0; } }else{ if(number == 3497){ state = 1; wrong = 0; }else{ wrong++; Serial.println("Chybny kod"); } } if(wrong >= 3) state = 2; } void printDayTime(){ if(dayTime){ Serial.println("Rezim DEN"); }else{ Serial.println("Rezim NOC"); } } void printState(){ switch(state){ case 0: Serial.println("Otevreno"); break; case 1: Serial.println("Zavreno"); break; case 2: Serial.println("Alarm"); break; } } boolean moveDetected(){ return(analogRead(sensorMove) > 300); } boolean tiltDetected(){ return(analogRead(sensorTilt) > 500); } void turnData(){ if(!digitalRead(encClk)) turn++; } void turnClock(){ if(!digitalRead(encData)) turn--; }