Initial commit

This commit is contained in:
Piotr Dobrowolski 2017-09-09 19:44:05 +02:00
commit 70a9eb0be6
3 changed files with 563 additions and 0 deletions

2
arduino/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
.pioenvs
.piolibdeps

18
arduino/platformio.ini Normal file
View File

@ -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

543
arduino/src/main.ino Normal file
View File

@ -0,0 +1,543 @@
#include <EnableInterrupt.h>
#include <Keypad.h> //http://www.arduino.cc/playground/uploads/Code/Keypad.zip
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#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<N_TASKS; i++){
if(taskLifetimes[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<N_TASKS; i++){
LogSerial.print(i+1);
LogSerial.print(": ");
LogSerial.print(taskLifetimes[i]);
LogSerial.print("\t\t");
CommandSerial.print(i);
CommandSerial.print(":");
if(taskLifetimes[i]) CommandSerial.print(("y")); else CommandSerial.print(("n"));
CommandSerial.print("#");
}
LogSerial.println();
CommandSerial.println();
}
void setSlide(int n){
switch(n){
case 1:
log("signalling slide 1.");
digitalWrite(pin_rpi_slide1, LOW);
delay(800);
digitalWrite(pin_rpi_slide1, HIGH);
break;
case 2:
log("signalling slide 2.");
digitalWrite(pin_rpi_slide2, LOW);
delay(800);
digitalWrite(pin_rpi_slide2, HIGH);
break;
case 3:
log("signalling slide 3.");
digitalWrite(pin_rpi_slide3, LOW);
delay(800);
digitalWrite(pin_rpi_slide3, HIGH);
break;
case 5:
log("signalling slide 5.");
digitalWrite(pin_rpi_slide5, LOW);
delay(800);
digitalWrite(pin_rpi_slide5, HIGH);
break;
case 6:
log("signalling slide 6.");
digitalWrite(pin_rpi_slide6, LOW);
delay(800);
digitalWrite(pin_rpi_slide6, HIGH);
break;
case 9:
log("signalling win slide.");
pinMode(pin_rpi_slide_win, OUTPUT);
digitalWrite(pin_rpi_slide_win, LOW);
delay(800);
digitalWrite(pin_rpi_slide_win, HIGH);
break;
}
}
void win4ISR() {
if(digitalRead(pin_rpi_win4) == LOW) taskDone(3);
}
void win9ISR() {
if(digitalRead(pin_rpi_win9) == LOW) taskDone(8);
}
void win10ISR() {
if(digitalRead(pin_rpi_win10) == LOW) taskDone(9);
}
void pin_keyISR() {
if(digitalRead(pin_key) == LOW){
taskDone(0);
setSlide(1);
}
}
void pin_foambtnISR() {
if(digitalRead(pin_foambtn) == LOW){
foambtn_clicks++;
setSlide(3);
}
if(foambtn_clicks > 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<N_TASKS; i++){
pinMode(taskPins[i], OUTPUT);
digitalWrite(taskPins[i], LOW);
}
log("pin setup done.");
}
void setup() {
// set the digital pin as output:
pinMode(13, OUTPUT);
LogSerial.begin(115200);
CommandSerial.begin(9600);
setupPins();
keypad.addEventListener(keypadEvent);
prevKnobInput = map(analogRead(pin_knob), 0, 1024, 0, 10);
lcd.init();
// Print a message to the LCD.
lcd.backlight();
lcd.setCursor(0,0);
lcd.print(LCD_PROMPT);
log("program starts.");
/*taskDone(0);
taskDone(3);
taskDone(4);
taskDone(5);*/
}
int incomingByte;
void loop() {
unsigned long currentMillis = millis();
if (CommandSerial.available() > 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<N_TASKS; i++){
taskDone(i);
}
}
}
//aktualizowanie stanu zagadek
if (currentMillis - previousMillis >= 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();
}