// include the library code: #include "rgb_lcd.h" #include // Delay when button is pressed #define BUTTON_DELAY 200 // --- DISPLAYS AND COLORS //LCD initialisation rgb_lcd lcd; // Structure LCD color values struct lcdcolor { //Red color int colorR; //Green color int colorG; //Blue color int colorB; }; // LCD display normal state struct lcdcolor baselcd = {50, 50, 50}; // LCD display when script is HIGH struct lcdcolor actionlcd = {150, 150, 50}; struct lcdcolor action2lcd = {50, 100, 50}; struct lcdcolor timerlcd = {50, 150, 50}; // LED for buttons variable definition using adafruit //variable for KeyCaps leds #define PIXEL_COUNT 60 // instanciate led key object // usage : Adafruit_NeoPixel "objectname" = Adafruit_NeoPixel(PIXEL_COUNT, "LED PIN", NEO_GRB + NEO_KHZ800); Adafruit_NeoPixel action = Adafruit_NeoPixel(PIXEL_COUNT, 11, NEO_GRB + NEO_KHZ800); Adafruit_NeoPixel action2 = Adafruit_NeoPixel(PIXEL_COUNT, 13, NEO_GRB + NEO_KHZ800); Adafruit_NeoPixel ledstop = Adafruit_NeoPixel(PIXEL_COUNT, 7, NEO_GRB + NEO_KHZ800); Adafruit_NeoPixel ledtimer = Adafruit_NeoPixel(PIXEL_COUNT, 5, NEO_GRB + NEO_KHZ800); // Structure for led color change struct keyledcolor { //init number int pixelnum; //Red color int ledR; //Green color int ledG; //Blue color int ledB; }; //color definitions struct keyledcolor brightblue ={0, 0, 255, 255}; struct keyledcolor green ={0, 0, 255, 0}; struct keyledcolor yellowish ={0, 255, 255, 0}; struct keyledcolor brightred ={0, 255, 0, 0}; struct keyledcolor brightmix ={0, 200, 70, 200}; struct keyledcolor uncolored ={0, 0, 0, 0}; // --- TIME GESTION initialisation // time variables init for timer LCD unsigned long startMillis; unsigned long currentMillis; unsigned long elapsedMillis; // time variables for step actionscript unsigned long stepcheckMillis; unsigned long step2checkMillis; unsigned long startcheckMillis; #define persistanceMillis 30000 #define motorwaitMillis 5000 #define secondmotorwaitMillis 3000 #define timers_showtime 10000 long inDataSec[10]; long inDataMs[10]; long maxtime = 0; int maxms; int maxsec; long sumtime = 0; int sumsec; int summs; long totaltime = 0; int totalsec; int totalms; float v; float vit = 250000; float datasec; float datams; // Steps for actionscript variable const int actionsteps = 31; int runningstep = 0; int stepstate = LOW; int burningstate = LOW; // Will keep track of burner for actionscript int stopState = LOW; // Will keep track of stopwatch button pushed int waitTime = LOW; // Will tell if there is to wait // --- GLOBAL STRUCTS --- // Represent a pin and associated state struct pin_state { int pin; int state; }; // --- COMMANDS and INPUTS --- // Struct definition // Struct containing all commands buttons, inputs and states struct commands { // home button pin_state home; // burner move pin pin_state burner; // action script pin pin_state actionscript; // action script 2 pin pin_state actionscript2; // Stopwatch pin pin_state stopwatch; // timer pin pin_state timer; // buzzer pin; pin_state buzzer; }; // Create command struct struct commands cmd = {{2, 0}, {8, 0}, {10, 0}, {12, 0}, {6, 0}, {4, 0}, {53, 0}}; // --- MOTORS --- // Structs definitions // Struct containing input pullups attached to motor struct pullups { // home pullup pin_state home; // end pullup pin_state end; }; // Struct containing all pins and delay associated with a motor struct motor { // pins51 int dir; int step; int enable; // delay int delay; // pullups associated pullups pups; // in position or not (mainly used by burner motor) bool in_pos; }; // Structs creation // Create struct containing burner motor stuff struct motor burner_motor = {31, 35, 33, 100, {43, 0, 45, 0}, false}; // Array containing signals instructions // forward move int forward[4] = {HIGH, HIGH, HIGH, LOW}; // backward move int backward[4] = {LOW, HIGH, HIGH, LOW}; // move_motor is used to move motor forward or backward // arg motor: motor to activate is passed a parameter // arg signals: array of int used to specify backward or forward mode void move_motor(motor motor, int *signals) { digitalWrite(motor.dir, signals[0]); digitalWrite(motor.enable, signals[1]); digitalWrite(motor.step, signals[2]); delayMicroseconds(motor.delay); digitalWrite(motor.step, signals[3]); delayMicroseconds(motor.delay); } // home_motors is used to get all motors to home position void home_motors() { // ensure a delay when button is pressed delay(BUTTON_DELAY); while (burner_motor.pups.home.state == LOW) { move_motor(burner_motor, backward); refresh_motors_states(); } burner_motor.in_pos = true; refresh_motors_states(); // resetFunc(); } // refresh all motors pullups states void refresh_motors_states() { burner_motor.pups.home.state = digitalRead(burner_motor.pups.home.pin); burner_motor.pups.end.state = digitalRead(burner_motor.pups.end.pin); } void set_position() { burner_motor.pups.home.state = digitalRead(burner_motor.pups.home.pin); if (burner_motor.pups.home.state == HIGH) { burner_motor.in_pos = true; } } // move_motor_quarter will move burner motor 1 quarter void move_motor_quarter() { set_position(); // if not in position turn if (burner_motor.in_pos == true) { while (burner_motor.pups.end.state == LOW) { move_motor(burner_motor, forward); refresh_motors_states(); } // inverse motor position burner_motor.in_pos = false; } // else turn the other way else { home_motors(); // inverse motor position burner_motor.in_pos = true; } } void lcd_set_color(lcdcolor lcdcolor) { lcd.setRGB(lcdcolor.colorR, lcdcolor.colorG, lcdcolor.colorB); } // --- SETUP --- // setup LCD display void setup_lcd() { lcd.begin(16, 2); lcd.setRGB(baselcd.colorR, baselcd.colorG, baselcd.colorB); lcd.clear(); lcd.setCursor(0, 0); lcd.print("Bienvenue"); } // setup_motors assign all pin to output and input for motors void setup_motors() { // burner motor setup pinMode(burner_motor.step, OUTPUT); pinMode(burner_motor.dir, OUTPUT); pinMode(burner_motor.enable, OUTPUT); pinMode(burner_motor.pups.home.pin, INPUT_PULLUP); pinMode(burner_motor.pups.end.pin, INPUT_PULLUP); } // setup_commands assign all pin to output and input for commands void setup_commands() { pinMode(cmd.home.pin, INPUT_PULLUP); pinMode(cmd.burner.pin, INPUT_PULLUP); pinMode(cmd.actionscript.pin, INPUT_PULLUP); pinMode(cmd.actionscript2.pin, INPUT_PULLUP); pinMode(cmd.stopwatch.pin, INPUT_PULLUP); pinMode(cmd.timer.pin, INPUT_PULLUP); pinMode(cmd.buzzer.pin, OUTPUT); } // setup all keyleds to off void setoff(Adafruit_NeoPixel& ledsetup) { ledsetup.begin(); // Initialize all pixels to 'off' ledsetup.clear(); ledsetup.show(); } // setup the leds void setup_leds() { setoff(action); setoff(action2); setoff(ledstop); setoff(ledtimer); } void arduino_led_start() { led_bright(ledtimer, green); led_bright(action, brightblue); led_bright(action2, brightred); } // -- Setup function, needed by Arduino void setup() { setup_lcd(); setup_leds(); setup_motors(); setup_commands(); // start leds init arduino_led_start(); home_motors(); set_position(); } // --- MAIN --- // refresh_commands_states will refresh all commands related inputs void refresh_commands_states() { cmd.home.state = digitalRead(cmd.home.pin); cmd.burner.state = digitalRead(cmd.burner.pin); cmd.actionscript.state = digitalRead(cmd.actionscript.pin); cmd.actionscript2.state = digitalRead(cmd.actionscript2.pin); cmd.stopwatch.state = digitalRead(cmd.stopwatch.pin); cmd.timer.state = digitalRead(cmd.timer.pin); } // refresh_state is a wrapup off all refresh function void refresh_state() { // commands states refresh_commands_states(); // motors states refresh_motors_states(); } // buzzer void beep() { digitalWrite(cmd.buzzer.pin, HIGH); delay(50); digitalWrite(cmd.buzzer.pin, LOW); } // lcd print parameters or Strings void lcd_print_string(int col, int line, String argument) { lcd.setCursor(col, line); lcd.print(argument); } void lcd_print_long(int col, int line, long argument) { lcd.setCursor(col, line); lcd.print(argument); } void lcd_print_float(int col, int line, float argument) { lcd.setCursor(col, line); lcd.print(argument); } // reset all timers variables void reset_millis() { v = 0; startMillis = 0; currentMillis = 0; elapsedMillis = 0; stepcheckMillis = 0; step2checkMillis = 0; startcheckMillis = 0; totaltime = 0; sumtime = 0; maxtime = 0; memset(inDataSec,0,sizeof(inDataSec)); memset(inDataMs,0,sizeof(inDataMs)); } // Check if you print action2 timers or action1 void timer_show_select() { lcd.clear(); if (v > 0) show_action2_timers(); else { cycle_through_timers(); } } // Timers recollection void cycle_through_timers() { lcd.clear(); led_bright(ledtimer, yellowish); if (totaltime > 0) { delay(2000); for (int timers = 0; timers < 10; timers++) { sumtime = (inDataSec[timers]*1000) + inDataMs[timers]; if (maxtime <= sumtime) maxtime = sumtime; } lcd.clear(); maxms = (maxtime%1000); maxsec = (maxtime/1000)%60; lcd_print_string(0, 0, "Tps maximum "); lcd_print_long(0, 1, maxsec); lcd_print_string(5,1, "S"); lcd_print_long(9, 1, maxms); lcd_print_string(12,1, "Ms"); delay(4000); sumtime = 0; for (int timers = 0; timers < 10; timers++) { lcd.clear(); lcd_print_string(0, 0, "Tps N"); lcd_print_long(6, 0, (timers + 1)); lcd_print_long(0, 1, inDataSec[timers]); lcd_print_string(5,1, "S"); lcd_print_long(9, 1, inDataMs[timers]); lcd_print_string(12,1, "Ms"); if ((inDataMs[timers] > 0) || (inDataSec[timers] > 0)) delay(4000); sumtime = sumtime + (inDataSec[timers]*1000) + inDataMs[timers]; } lcd.clear(); summs = (sumtime%1000); sumsec = (sumtime/1000)%60; lcd_print_string(0, 0, "Temps total"); lcd_print_long(0, 1, sumsec); lcd_print_string(4,1, "S"); lcd_print_long(6, 1, summs); lcd_print_string(12,1, "Ms"); delay(timers_showtime); arduino_led_start(); } else { lcd_print_string(0, 0, "Pas de timer "); delay(2000); } led_bright(ledtimer, uncolored); lcd_set_color(baselcd); setup_lcd(); arduino_led_start(); } // Timer actionscript 2 recollection void show_action2_timers() { led_bright(ledtimer, yellowish); lcd.clear(); datasec = (inDataSec[1]*1000); datams = inDataMs[1]; datasec = datasec+datams; v = (float)(vit / datasec); lcd_print_string(0, 0, "V="); lcd_print_float(4, 0, v); lcd_print_string(12,0, "mm/s"); lcd_print_string(0, 1, "T2"); lcd_print_long(4, 1, inDataSec[1]); lcd_print_string(6, 1, "S"); lcd_print_long(8, 1, inDataMs[1]); lcd_print_string(11, 1, "Ms"); delay(timers_showtime); led_bright(ledtimer, uncolored); setup_lcd(); arduino_led_start(); } // Display stopwatch and store timer void lcdshow() { currentMillis = millis(); elapsedMillis = (currentMillis - startMillis); lcd.clear(); lcd_print_string(0, 0, "Temps mesure"); lcd_print_string(0, 1, " "); unsigned long durMS = (elapsedMillis%1000); //Milliseconds unsigned long durSS = (elapsedMillis/1000)%60; //Seconds unsigned long durMM = (elapsedMillis/(60000))%60; //Minutes unsigned long durHH = (elapsedMillis/(3600000)); //Hours durHH = durHH % 24; String durMilliSec = timeMillis(durHH, durMM, durSS,durMS); totaltime = totaltime + elapsedMillis; inDataSec[(runningstep -1)] = durSS; inDataMs[(runningstep -1)] = durMS; lcd_print_string(0, 1, durMilliSec); delay(50); } //Led color change void led_bright(Adafruit_NeoPixel& led_display, keyledcolor keyledcolor) { led_display.setPixelColor(keyledcolor.pixelnum, keyledcolor.ledR, keyledcolor.ledG, keyledcolor.ledB); led_display.show(); } // -- ACTIONSCRIPT 1 // Stop current actionscript void stop_action() { delay(BUTTON_DELAY); stepstate = LOW; lcd.clear(); lcd_print_string(0, 0, "Stop fonction"); home_motors(); runningstep = actionsteps; waitTime = LOW; burningstate = LOW; cycle_through_timers(); led_bright(action, uncolored); led_bright(ledstop, green); refresh_commands_states(); } // action script key is pushed, initialize the 10 steps void actionscript() { home_motors(); delay(BUTTON_DELAY); reset_millis(); lcd_set_color(actionlcd); led_bright(ledtimer, brightred); lcd.clear(); for (runningstep = 0; runningstep < actionsteps; runningstep++) { stepstate = HIGH; while ((stepstate == HIGH) && (runningstep < actionsteps)) { timed_motor(); if (cmd.timer.state == HIGH) { stop_action(); break; } refresh_commands_states(); } } led_bright(action, uncolored); led_bright(ledstop, uncolored); lcd_set_color(baselcd); cycle_through_timers(); } // -- ACTIONSCRIPT 1 timing the motor void timed_motor() { stepcheckMillis = millis(); led_bright(action, brightblue); move_motor_quarter(); burningstate = HIGH; while (burningstate == HIGH) { if (cmd.timer.state == HIGH) { stop_action(); break; } startcheckMillis = millis(); lcd_print_string(0, 0, "Flamme 5 sec"); lcd_print_long(14, 0, runningstep); if ((unsigned long)(startcheckMillis - stepcheckMillis) >= motorwaitMillis) { beep(); home_motors(); lcd.clear(); startMillis = millis(); led_bright(action, uncolored); timer_time(); burningstate = LOW; stepcheckMillis = millis(); } refresh_commands_states(); } } // -- ACTIONSCRIPT 1 Waiting timer key push or countdown to next step void timer_time() { led_bright(ledstop, green); step2checkMillis = millis(); waitTime = HIGH; lcd.clear(); while ((waitTime) && (runningstep < actionsteps)) { if (cmd.timer.state == HIGH) { stop_action(); break; } lcd_print_string(0, 0, "Etape "); lcd_print_long(14, 0, runningstep); startcheckMillis = millis(); stopState = LOW; refresh_commands_states(); timer_push(); if ((unsigned long)(startcheckMillis - step2checkMillis) >= secondmotorwaitMillis) { lcd.clear(); lcd_print_string(0, 0, "3 sec"); beep(); stopState = LOW; led_bright(action, uncolored); led_bright(ledstop, green); refresh_commands_states(); stepstate = LOW; waitTime = LOW; step2checkMillis = millis(); } } } // -- ACTIONSCRIPT 1 Check the timer key push void timer_push() { while (cmd.stopwatch.state == HIGH) { // check if button was previously pushed if (stopState == LOW) { startMillis = millis(); runningstep++; } step2checkMillis = millis(); startcheckMillis = millis(); led_bright(action, brightblue); led_bright(ledstop, brightmix); stopState = HIGH; lcdshow(); led_bright(action, uncolored); led_bright(ledstop, green); refresh_commands_states(); } } // -- ACTIONSCRIPT 2 // action script key is pushed, initialize the burner void actionscript2() { home_motors(); delay(BUTTON_DELAY); lcd_set_color(action2lcd); led_bright(action2, yellowish); led_bright(ledstop, green); reset_millis(); startcheckMillis = millis(); move_motor_quarter(); runningstep = 1; burningstate = LOW; stepstate = HIGH; startMillis = millis(); while(stepstate == HIGH) { if (cmd.timer.state == HIGH) { stop_action(); break; } refresh_commands_states(); lcdshow(); if ((cmd.stopwatch.state == HIGH) || (unsigned long)(currentMillis - startcheckMillis) >= persistanceMillis ) { move_motor_quarter(); runningstep++; beep(); startMillis = millis(); refresh_state(); flame_persistance(); stepstate = LOW; } } led_bright(action2, uncolored); show_action2_timers(); lcd_set_color(baselcd); } // -- ACTIONSCRIPT 2 check time of flame persistance void flame_persistance() { burningstate = HIGH; delay(BUTTON_DELAY); while (burningstate == HIGH) { if (cmd.timer.state == HIGH) { stop_action(); break; } refresh_state(); led_bright(ledstop, brightblue); lcdshow(); if(cmd.stopwatch.state == HIGH) { led_bright(ledstop, uncolored); burningstate = LOW; } } } // --- MAIN LOOP --- void loop() { // refresh states from all inputs refresh_state(); // if home button is pressed, trigger home_motors // get all motors to home position if (cmd.home.state == HIGH) home_motors(); // if burner button is pressed, trigger move_motor_quarter // set burner to burn position if (cmd.burner.state == HIGH) move_motor_quarter(); // if actionscript button is pressed, go in actionscript mode // TODO: hanlde action script if (cmd.actionscript.state == HIGH) { setup_leds(); actionscript(); } if (cmd.actionscript2.state == HIGH) { setup_leds(); actionscript2(); } if (cmd.timer.state == HIGH) { setup_leds(); lcd_set_color(timerlcd); timer_show_select(); } } // time variables init for LCD Display // ROTTEN CODE... String timeMillis(unsigned long Hourtime,unsigned long Mintime,unsigned long Sectime,unsigned long MStime) { String dataTemp = ""; if (Hourtime < 10) { dataTemp = dataTemp + "0" + String(Hourtime)+ "h:"; } else{ dataTemp = dataTemp + String(Hourtime)+ "h:"; } if (Mintime < 10) { dataTemp = dataTemp + "0" + String(Mintime)+ "m:"; } else{ dataTemp = dataTemp + String(Mintime)+ "m:"; } if (Sectime < 10) { dataTemp = dataTemp + "0" + String(Sectime)+ "s:"; } else{ dataTemp = dataTemp + String(Sectime)+ "s:"; } dataTemp = dataTemp + String(MStime); return dataTemp; }