commit 70a9eb0be6d8305500e5ae88c955d9948e9e3f3f Author: Piotr Dobrowolski Date: Sat Sep 9 19:44:05 2017 +0200 Initial commit diff --git a/arduino/.gitignore b/arduino/.gitignore new file mode 100644 index 0000000..6c69f4c --- /dev/null +++ b/arduino/.gitignore @@ -0,0 +1,2 @@ +.pioenvs +.piolibdeps diff --git a/arduino/platformio.ini b/arduino/platformio.ini new file mode 100644 index 0000000..34243b6 --- /dev/null +++ b/arduino/platformio.ini @@ -0,0 +1,18 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; http://docs.platformio.org/page/projectconf.html + +[env:megaatmega2560] +platform = atmelavr +board = megaatmega2560 +framework = arduino +lib_deps = + EnableInterrupt + Keypad + LiquidCrystal_I2C diff --git a/arduino/src/main.ino b/arduino/src/main.ino new file mode 100644 index 0000000..8cf208a --- /dev/null +++ b/arduino/src/main.ino @@ -0,0 +1,543 @@ +#include +#include //http://www.arduino.cc/playground/uploads/Code/Keypad.zip +#include +#include + +#define CommandSerial Serial +#define LogSerial Serial + +//##########################RUNTIME########################## +//ilosc zadan: +#define N_TASKS 10 +//dlugosc sekundy w ms: +#define TICK 1000 +//czas odswiezania potencjometru w ms: +#define TICK2 200 + +//obecne czasy zycia LEDow na panelu +int taskLifetimes[N_TASKS] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +//tekst ostatnio wpisany na keypadzie +String keypadInput = ""; + +//liczniki klikniec +int foambtn_clicks = 0; +int dynamo1_clicks = 0; +int dynamo2_clicks = 0; +int dynamo3_clicks = 0; + +unsigned long previousMillis = 0; +unsigned long previousMillis2 = 0; + +//liczniki i teksty z potencjometru +int prevKnobInput = 0; +bool added = false; +String knobInputTotal = ""; + +//czas zwolnienia zamka szuflady +#define DRAWER_OPEN_DELAY 2000 +//##########################GAMEPLAY########################## +//ile razy trzeba wcisnac piankowy guzik? +#define FOAM_MAXSCORE 10 +//ile razy trzeba przekrecic korba w kazdym gniezdzie? +#define DYNAMO_MAXSCORE1 50 +#define DYNAMO_MAXSCORE2 20 +#define DYNAMO_MAXSCORE3 30 +//ile czasu zyje kazda dioda po zapaleniu? (w sekundach) +int taskMaxLifetimes[N_TASKS] = {600, 180, 180, 180, 180, 180, 180, 180, 180, 180}; +//haslo do otwarcia szuflady +String pass1 = "1234"; +//haslo do zagadki z mp3 +String pass2 = "ABCD"; +//kod do sejfu +String knob_pass = "354"; + +//wiadomosc poczatkowa na LCD +#define LCD_PROMPT "Podaj haslo:" + +//wiadomosc na LCD po dobrym kodzie +#define LCD_CORRECT "DOBRZE" + +//wiadomosc na LCD po zlym kodzie +#define LCD_INCORRECT "ZLE" + +//##########################PINY########################## +//piny do RPi + +int pin_rpi_neg = 45; // +int pin_rpi_pos = 47; // +//gpio +int pin_rpi_slide1 = 37; //RPi GPIO25 +int pin_rpi_slide2 = 39; //RPi GPIO8 +int pin_rpi_slide3 = 41; //RPi GPIO7 +int pin_rpi_slide5 = 43; //RPi GPIO12 +int pin_rpi_slide6 = 49; //RPi GPIO16 +//pin slajdu zwyciestwa +int pin_rpi_slide_win = 51; //RPi GPIO20 + +//piny od RPi +int pin_rpi_win9 = 11; //RPi GPIO3 +int pin_rpi_win4 = 12; //RPi GPIO2 +int pin_rpi_win10 = 10; //RPi GPIO4 +//piny kontrolerow zagadek +int pin_key = 14; +int pin_foambtn = 15; +int pin_maze = A8; +int pin_dynamo1 = A11; +int pin_dynamo2 = A9; +int pin_dynamo3 = A10; + +//piny ledow do korby +int pin_dyna_led1 = A2; +int pin_dyna_led2 = A6; +int pin_dyna_led3 = A4; +int pin_dyna_led4 = A3; +int pin_dyna_led5 = A1; +int pin_dyna_led6 = A5; + +//piny ledow na panelu - w kolejnosci zagadek +int taskPins[N_TASKS] = {34, 36, 38, 40, 42, 44, 46, 48, 50, 52}; + +//pin pokretla sejfu +int pin_knob = A0; + +//pin otwarcia szuflady +int pin_drawer_relay = A7; +//piny klawiatury +const byte ROWS = 4; // Four rows +const byte COLS = 4; // columns +// Define the Keymap +char keys[ROWS][COLS] = { + {'1', '2', '3', 'A'}, + {'4', '5', '6', 'B'}, + {'7', '8', '9', 'C'}, + {'*', '0', '#', 'D'} +}; +byte rowPins[ROWS] = {A12, A13, A14, A15}; +byte colPins[COLS] = {2, 3, 4, 5}; +Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS); + +LiquidCrystal_I2C lcd(0x3F,16,2); + +void log(String in){ + LogSerial.println(in); +} + +void taskDone(int n){ + taskLifetimes[n] = taskMaxLifetimes[n]; + LogSerial.print("task done: "); + LogSerial.println(n+1); +} + +void taskUnDone(int n){ + taskLifetimes[n] = 0; + //wylaczanie ledow korby + if(n == 4){ + dynamo1_clicks = 0; + dynamo2_clicks = 0; + dynamo3_clicks = 0; + digitalWrite(pin_dyna_led1, LOW); + digitalWrite(pin_dyna_led2, LOW); + digitalWrite(pin_dyna_led3, LOW); + digitalWrite(pin_dyna_led4, LOW); + digitalWrite(pin_dyna_led5, LOW); + digitalWrite(pin_dyna_led6, LOW); + log("turning off dynamo leds."); + } + LogSerial.print("task undone: "); + LogSerial.println(n+1); +} + +void updateDynamo(){ + if(dynamo1_clicks > DYNAMO_MAXSCORE1 && dynamo2_clicks > DYNAMO_MAXSCORE2 && dynamo3_clicks > DYNAMO_MAXSCORE3 && taskLifetimes[4] == 0){ + taskDone(4); + } + + if (taskLifetimes[4] == 1){ + dynamo1_clicks = 0; + dynamo2_clicks = 0; + dynamo3_clicks = 0; + + digitalWrite(pin_dyna_led1, LOW); + digitalWrite(pin_dyna_led2, LOW); + digitalWrite(pin_dyna_led3, LOW); + digitalWrite(pin_dyna_led4, LOW); + digitalWrite(pin_dyna_led5, LOW); + digitalWrite(pin_dyna_led6, LOW); + log("turning off dynamo leds."); + } +} + +void updateTasks(){ + bool win = true; + updateDynamo(); + for(int i=0; i 0){ + digitalWrite(taskPins[i], HIGH); + taskLifetimes[i]--; + } + else{ + digitalWrite(taskPins[i], LOW); + win = false; + } + } +if (win){ + setSlide(9); + log("GAME OVER - YOU WIN."); +} +} + +void logTasks(){ + LogSerial.print("tasks: "); + for(int i=0; i FOAM_MAXSCORE){ + taskDone(2); + foambtn_clicks = 0; + } +} + +void pin_dynamo1ISR() { + if(digitalRead(pin_dynamo1) == LOW){ + dynamo1_clicks++; + log("dynamo 1 up."); + + if(dynamo1_clicks > DYNAMO_MAXSCORE1){ + digitalWrite(pin_dyna_led1, HIGH); + log("dynamo 1 done."); + } + else if(dynamo1_clicks > DYNAMO_MAXSCORE1/2){ + digitalWrite(pin_dyna_led2, HIGH); + log("dynamo 1 half done."); + } + + } +} + +void pin_dynamo2ISR() { + if(digitalRead(pin_dynamo2) == LOW){ + dynamo2_clicks++; + log("dynamo 2 up."); + + if(dynamo2_clicks > DYNAMO_MAXSCORE2){ + digitalWrite(pin_dyna_led3, HIGH); + log("dynamo 2 done."); + } + else if(dynamo2_clicks > DYNAMO_MAXSCORE2/2){ + digitalWrite(pin_dyna_led4, HIGH); + log("dynamo 2 half done."); + } + + } + +} + +void pin_dynamo3ISR() { + if(digitalRead(pin_dynamo3) == LOW){ + dynamo3_clicks++; + log("dynamo 3 up."); + + if(dynamo3_clicks > DYNAMO_MAXSCORE3){ + digitalWrite(pin_dyna_led5, HIGH); + log("dynamo 3 done."); + } + else if(dynamo3_clicks > DYNAMO_MAXSCORE3/2){ + digitalWrite(pin_dyna_led6, HIGH); + log("dynamo 3 half done."); + } + + } + +} + +void pin_mazeISR() { + if(digitalRead(pin_maze) == LOW) taskDone(6); +} + +void openDrawer(){ + log("The drawer is open."); + digitalWrite(pin_drawer_relay, HIGH); + delay(DRAWER_OPEN_DELAY); + digitalWrite(pin_drawer_relay, LOW); +} + +void checkPassword(){ + if(keypadInput == pass1){ + taskDone(5); + openDrawer(); + log("Password 1 ok."); + } + if(keypadInput == pass2){ + taskDone(7); + log("Password 2 ok."); + } + keypadInput = ""; +} + +void clearPassword(){ + keypadInput = ""; +} + +void keypadEvent(KeypadEvent event){ + if (keypad.getState() == PRESSED){ + switch (event){ + case '*': checkPassword(); break; + case '#': clearPassword(); break; + default: keypadInput += event; + } + LogSerial.print("Key pressed: "); + LogSerial.print(event); + LogSerial.print(" password now: "); + LogSerial.println(keypadInput); + setSlide(6); + } +} + +void lcdPrint(String in){ + lcd.setCursor(0,1); + lcd.print(" "); + lcd.setCursor(0,1); + lcd.print(in); +} + +void updateKnob(){ + int knobInput = 0; + knobInput = map(analogRead(pin_knob), 0, 1024, 10, 0)-1; + + if (knobInput != prevKnobInput) { + LogSerial.print("Knob input: "); + LogSerial.println(knobInputTotal); + setSlide(2); + //LogSerial.print("Analog: "); + //LogSerial.println(analogRead(pin_knob)); + + added = false; + prevKnobInput = knobInput; + } + else if (!added){ + knobInputTotal += String(knobInput); + lcdPrint(knobInputTotal); + added = true; + //LogSerial.print("Knob current: "); + //LogSerial.println(knobInput); + } + if(knobInputTotal == knob_pass){ + knobInputTotal = ""; + taskDone(1); + lcdPrint(LCD_CORRECT); + log("knob password ok."); + } + else if(knobInputTotal.length() == knob_pass.length()){ + knobInputTotal = ""; + lcdPrint(LCD_INCORRECT); + } +} + +void setupPins(){ + + //inicjalizacja pinow idacych do RPi + //piny do konwertera poziomow + pinMode(pin_rpi_neg, OUTPUT); + digitalWrite(pin_rpi_neg, LOW); + pinMode(pin_rpi_pos, OUTPUT); + digitalWrite(pin_rpi_pos, HIGH); + + //inicjalizacja przerwan PCINT idacych od RPi + pinMode(pin_rpi_win4, INPUT); //nie moze byc pullup, bo podciagalby do 5V - te piny trzyma w stanie wysokim RPi + enableInterrupt(pin_rpi_win4, win4ISR, CHANGE); + pinMode(pin_rpi_win9, INPUT); + enableInterrupt(pin_rpi_win9, win9ISR, CHANGE); + pinMode(pin_rpi_win10, INPUT); + enableInterrupt(pin_rpi_win10, win10ISR, CHANGE); + + //piny slajdow + pinMode(pin_rpi_slide1, OUTPUT); + digitalWrite(pin_rpi_slide1, HIGH); //tu moze byc wysoki, bo jestesmy za konwerterem poziomow + pinMode(pin_rpi_slide2, OUTPUT); + digitalWrite(pin_rpi_slide2, HIGH); + pinMode(pin_rpi_slide3, OUTPUT); + digitalWrite(pin_rpi_slide3, HIGH); + pinMode(pin_rpi_slide5, OUTPUT); + digitalWrite(pin_rpi_slide5, HIGH); + pinMode(pin_rpi_slide6, OUTPUT); + digitalWrite(pin_rpi_slide6, HIGH); + pinMode(pin_rpi_slide_win, INPUT); + //pinMode(pin_rpi_slide_win, OUTPUT); + //digitalWrite(pin_rpi_slide_win, HIGH); //zostawiamy plywajacy, zeby pullup robilo RPi, ale tylko to na scianie A + + //inicjalizacja przerwan PCINT podlaczonych do kontrolerow zagadek + pinMode(pin_key, INPUT_PULLUP); + enableInterrupt(pin_key, pin_keyISR, CHANGE); + pinMode(pin_foambtn, INPUT_PULLUP); + enableInterrupt(pin_foambtn, pin_foambtnISR, CHANGE); + pinMode(pin_maze, INPUT_PULLUP); + enableInterrupt(pin_maze, pin_mazeISR, CHANGE); + + //inicjalizacja PCINT wejsc korby + pinMode(pin_dynamo1, INPUT_PULLUP); + enableInterrupt(pin_dynamo1, pin_dynamo1ISR, CHANGE); + pinMode(pin_dynamo2, INPUT_PULLUP); + enableInterrupt(pin_dynamo2, pin_dynamo2ISR, CHANGE); + pinMode(pin_dynamo3, INPUT_PULLUP); + enableInterrupt(pin_dynamo3, pin_dynamo3ISR, CHANGE); + + pinMode(pin_drawer_relay, OUTPUT); + digitalWrite(pin_drawer_relay, LOW); + + + //inicjalizacja pinow LEDow korby + for(int i=0; i<6; i++){ + pinMode(A1+i, OUTPUT); + digitalWrite(A1+i, LOW); + } + + + //inicjalizacja pinow LEDów na panelu + for(int i=0; i 0) { + // read the oldest byte in the serial buffer: + incomingByte = CommandSerial.read(); + /* if (incomingByte == 'A') { + taskDone(0); + } + if (incomingByte == 'a') { + taskUnDone(0); + }*/ + //komunikacja po UART z arduwifi + if (incomingByte > 64 && incomingByte < 75){ + taskDone(incomingByte-65); + }else if(incomingByte > 96 && incomingByte < 107){ + taskUnDone(incomingByte-97); + }else if(incomingByte == 'X'){ + for(int i=0; i= TICK) { + // save the last time you blinked the LED + previousMillis = currentMillis; + logTasks(); + updateTasks(); + } + //aktualizowanie kodu z potencjometru + if (currentMillis - previousMillis2 >= TICK2) { + // save the last time you blinked the LED + previousMillis2 = currentMillis; + updateKnob(); + } + keypad.getKey(); + +}