First fixes o state conditions
This commit is contained in:
parent
8961d7b24e
commit
cdd094d191
3 changed files with 364 additions and 146 deletions
95
pitch.h
Normal file
95
pitch.h
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*************************************************
|
||||
* Public Constants
|
||||
*************************************************/
|
||||
|
||||
#define NOTE_B0 31
|
||||
#define NOTE_C1 33
|
||||
#define NOTE_CS1 35
|
||||
#define NOTE_D1 37
|
||||
#define NOTE_DS1 39
|
||||
#define NOTE_E1 41
|
||||
#define NOTE_F1 44
|
||||
#define NOTE_FS1 46
|
||||
#define NOTE_G1 49
|
||||
#define NOTE_GS1 52
|
||||
#define NOTE_A1 55
|
||||
#define NOTE_AS1 58
|
||||
#define NOTE_B1 62
|
||||
#define NOTE_C2 65
|
||||
#define NOTE_CS2 69
|
||||
#define NOTE_D2 73
|
||||
#define NOTE_DS2 78
|
||||
#define NOTE_E2 82
|
||||
#define NOTE_F2 87
|
||||
#define NOTE_FS2 93
|
||||
#define NOTE_G2 98
|
||||
#define NOTE_GS2 104
|
||||
#define NOTE_A2 110
|
||||
#define NOTE_AS2 117
|
||||
#define NOTE_B2 123
|
||||
#define NOTE_C3 131
|
||||
#define NOTE_CS3 139
|
||||
#define NOTE_D3 147
|
||||
#define NOTE_DS3 156
|
||||
#define NOTE_E3 165
|
||||
#define NOTE_F3 175
|
||||
#define NOTE_FS3 185
|
||||
#define NOTE_G3 196
|
||||
#define NOTE_GS3 208
|
||||
#define NOTE_A3 220
|
||||
#define NOTE_AS3 233
|
||||
#define NOTE_B3 247
|
||||
#define NOTE_C4 262
|
||||
#define NOTE_CS4 277
|
||||
#define NOTE_D4 294
|
||||
#define NOTE_DS4 311
|
||||
#define NOTE_E4 330
|
||||
#define NOTE_F4 349
|
||||
#define NOTE_FS4 370
|
||||
#define NOTE_G4 392
|
||||
#define NOTE_GS4 415
|
||||
#define NOTE_A4 440
|
||||
#define NOTE_AS4 466
|
||||
#define NOTE_B4 494
|
||||
#define NOTE_C5 523
|
||||
#define NOTE_CS5 554
|
||||
#define NOTE_D5 587
|
||||
#define NOTE_DS5 622
|
||||
#define NOTE_E5 659
|
||||
#define NOTE_F5 698
|
||||
#define NOTE_FS5 740
|
||||
#define NOTE_G5 784
|
||||
#define NOTE_GS5 831
|
||||
#define NOTE_A5 880
|
||||
#define NOTE_AS5 932
|
||||
#define NOTE_B5 988
|
||||
#define NOTE_C6 1047
|
||||
#define NOTE_CS6 1109
|
||||
#define NOTE_D6 1175
|
||||
#define NOTE_DS6 1245
|
||||
#define NOTE_E6 1319
|
||||
#define NOTE_F6 1397
|
||||
#define NOTE_FS6 1480
|
||||
#define NOTE_G6 1568
|
||||
#define NOTE_GS6 1661
|
||||
#define NOTE_A6 1760
|
||||
#define NOTE_AS6 1865
|
||||
#define NOTE_B6 1976
|
||||
#define NOTE_C7 2093
|
||||
#define NOTE_CS7 2217
|
||||
#define NOTE_D7 2349
|
||||
#define NOTE_DS7 2489
|
||||
#define NOTE_E7 2637
|
||||
#define NOTE_F7 2794
|
||||
#define NOTE_FS7 2960
|
||||
#define NOTE_G7 3136
|
||||
#define NOTE_GS7 3322
|
||||
#define NOTE_A7 3520
|
||||
#define NOTE_AS7 3729
|
||||
#define NOTE_B7 3951
|
||||
#define NOTE_C8 4186
|
||||
#define NOTE_CS8 4435
|
||||
#define NOTE_D8 4699
|
||||
#define NOTE_DS8 4978
|
||||
|
||||
|
71
speedclock.h
71
speedclock.h
|
@ -2,13 +2,19 @@
|
|||
#ifndef Remote_Control_transceiver_H
|
||||
#define Remote_Control_transceiver_H
|
||||
|
||||
//-------------- defines fpr the radio devices NRF24 ---------------------------------------------------------
|
||||
//-------------- defines for the radio devices NRF24 ---------------------------------------------------------
|
||||
|
||||
#define STATION_SEL0 9 // this 9 for Nano
|
||||
#define STATION_SEL1 10 // this 10 for Nano
|
||||
|
||||
#define STATION_SEL 4 // this 4 for Nano
|
||||
typedef enum {BASESTATION = 0, TOPSTATION} radio_type_e;
|
||||
#define RF24_CNS 7 // this is 7 for the Nano, D4 for the ESP
|
||||
#define RF24_CE 8 // this is 8 for the Nano, D3 for the ESP
|
||||
|
||||
//--------------- defines for the I2C
|
||||
//#define SCL A5 // I2C clock pin
|
||||
//#define SDA A4 // I2C data pin
|
||||
|
||||
//--------------- define the structure and type of data that sender and receiver will exchange ----------------
|
||||
|
||||
typedef struct transcv_struct{
|
||||
|
@ -17,18 +23,20 @@ typedef struct transcv_struct{
|
|||
}transcv_s;
|
||||
|
||||
|
||||
#define STOPBUTTON_IN D2 // this is the input for the button
|
||||
#define STOPBUTTON_IN 2 // this is the input for the button
|
||||
#define STOPBUTTON_PRESSED HIGH // this the signal level the top button will be at as soon as pressed
|
||||
#define MIN_DELAY_BETWEEN_PRESSED_MS 1000 // this defines the time in milliseconds before the button is expected to be pressed again. We do this to avaoid keybouncing
|
||||
#define MIN_DELAY_BETWEEN_SEND_MS 1000 // this defines the time in milliseconds before the next set of data will be send to the base station - except the button was pressed.
|
||||
|
||||
#define STARTBUTTON_IN D4 // start button
|
||||
#define STARTBUTTON_IN 4 // start button
|
||||
#define STARTBUTTON_PRESSED LOW
|
||||
#define CHANCELBUTTON_IN D2 // chancle button
|
||||
#define CHANCELBUTTON_PRESSED LOW
|
||||
#define FAILSTARTBUTTON_IN D3 // fail start button
|
||||
#define CANCELBUTTON_IN 2 // chancle button
|
||||
#define CANCELBUTTON_PRESSED LOW
|
||||
#define FAILSTARTBUTTON_IN 3 // fail start button
|
||||
#define FAILSTARTBUTTON_PRESSED LOW
|
||||
|
||||
#define PIEZO_PIN 6 // piezo speaker
|
||||
|
||||
#define WARN_LED A1 // yellow warn LED
|
||||
#define WARN_LED_ON HIGH
|
||||
#define WARN_LED_OFF LOW
|
||||
|
@ -43,29 +51,46 @@ typedef struct transcv_struct{
|
|||
#define RUN_LED_OFF LOW
|
||||
|
||||
|
||||
typedef enum {TIMER_INIT = 0, TIMER_READY, TIMER_STARTED, TIMER_RUNNING , TIMER_CHANCELED, TIMER_STOPPED, TIMER_TIMEDOUT, TIMER_FAIL, TIMER_WAIT} timer_state_e;
|
||||
typedef enum {TIMER_INIT = 0, TIMER_READY, TIMER_STARTED, TIMER_RUNNING , TIMER_CANCELLED, TIMER_STOPPED, TIMER_TIMEDOUT, TIMER_FAIL, TIMER_WAIT} timer_state_e;
|
||||
|
||||
// READY_LED, WARN_LED, RUN_LED, FAIL_LED
|
||||
const float LEDStates[][3] =
|
||||
{
|
||||
TIMER_INIT = {READY_LED_OFF, RUN_LED_OFF, FAIL_LED_OFF},
|
||||
TIMER_READY = {READY_LED_ON, RUN_LED_OFF, FAIL_LED_OFF},
|
||||
TIMER_STARTED = {READY_LED_ON, RUN_LED_ON, FAIL_LED_OFF},
|
||||
TIMER_RUNNING = {READY_LED_OFF, RUN_LED_ON, FAIL_LED_OFF},
|
||||
TIMER_CHANCELED = {READY_LED_OFF, RUN_LED_OFF, FAIL_LED_ON},
|
||||
TIMER_STOPPED = {READY_LED_ON, RUN_LED_ON, FAIL_LED_OFF},
|
||||
TIMER_TIMEDOUT = {READY_LED_OFF, RUN_LED_ON, FAIL_LED_ON},
|
||||
TIMER_FAIL = {READY_LED_OFF, RUN_LED_OFF, FAIL_LED_ON}
|
||||
}
|
||||
[TIMER_INIT] = {READY_LED_OFF, RUN_LED_OFF, FAIL_LED_OFF},
|
||||
[TIMER_READY] = {READY_LED_ON, RUN_LED_OFF, FAIL_LED_OFF},
|
||||
[TIMER_STARTED] = {READY_LED_ON, RUN_LED_ON, FAIL_LED_OFF},
|
||||
[TIMER_RUNNING] = {READY_LED_OFF, RUN_LED_ON, FAIL_LED_OFF},
|
||||
[TIMER_CANCELLED] = {READY_LED_OFF, RUN_LED_OFF, FAIL_LED_ON},
|
||||
[TIMER_STOPPED] = {READY_LED_ON, RUN_LED_ON, FAIL_LED_OFF},
|
||||
[TIMER_TIMEDOUT] = {READY_LED_OFF, RUN_LED_ON, FAIL_LED_ON},
|
||||
[TIMER_FAIL] = {READY_LED_OFF, RUN_LED_OFF, FAIL_LED_ON}
|
||||
};
|
||||
|
||||
#define MAX_DIFFERENCE_OFFSET_MS 10 // 0,001sec is the maximum offset we allow between the current offset and the mean offset. if it is more - restart offset calculation
|
||||
#define REQUIRED_NUMBER_MEANVALS 100 // we need at least this number of meanvalues to be ready to start a run
|
||||
#define REQUIRED_NUMBER_MEANVALS 10 // we need at least this number of meanvalues to be ready to start a run
|
||||
|
||||
#define STARTSEQ_LENGTH_MS = 3100 // the length of the start sequence from the time the button was pressed ... includes the 3 tones
|
||||
#define STARTSEQ_STARTPAUSE_MS = 1000
|
||||
#define STARTSEQ_TONEPAUSE_MS = 800
|
||||
#define STARTSEQ_TON_1_2_LENGTH_MS = 200
|
||||
#define STARTSEQ_TON_3_LENGTH_MS = 100
|
||||
#define STARTSEQ_LENGTH_MS 3100 // the length of the start sequence from the time the button was pressed ... includes the 3 tones
|
||||
#define STARTSEQ_STARTPAUSE_MS 1000
|
||||
#define STARTSEQ_TONEPAUSE_MS 800
|
||||
#define STARTSEQ_TON_1_2_LENGTH_MS 200
|
||||
#define STARTSEQ_TON_1_2_FREQUENCY NOTE_G4
|
||||
#define STARTSEQ_TON_3_LENGTH_MS 100
|
||||
#define STARTSEQ_TON_3_FREQUENCY NOTE_C6
|
||||
|
||||
#define FAILSEQ_TONEPAUSE_MS 400
|
||||
#define FAILSEQ_TON_LENGTH_MS 300
|
||||
#define FAILSEQ_TON_FREQUENCY NOTE_G1
|
||||
|
||||
#define TIMER_MAX_TIME 99999
|
||||
#define TIMER_TIMEOUT 20000
|
||||
|
||||
//--------------------------------------- function declarations ----------------------------------------------
|
||||
void false_start_isr(void);
|
||||
void update_screen(timer_state_e timer_state);
|
||||
void set_state_LEDs(timer_state_e state, boolean warn);
|
||||
void startSequence(void);
|
||||
void update_statemassage(timer_state_e timer_state);
|
||||
void failSequence(void);
|
||||
#endif
|
||||
|
||||
|
||||
|
|
332
speedclock.ino
332
speedclock.ino
|
@ -4,14 +4,17 @@
|
|||
#include <SPI.h>
|
||||
#include "RF24.h"
|
||||
#include "speedclock.h"
|
||||
#include "pitch.h"
|
||||
|
||||
// internal defines for the OLED display ...
|
||||
U8G2_SSD1306_128X64_NONAME_1_SW_I2C display(U8G2_R0, /* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE); // All Boards without Reset of the Display
|
||||
//U8G2_SSD1306_128X64_NONAME_1_HW_I2C display(U8G2_R0,/* reset=*/ U8X8_PIN_NONE); // All Boards without Reset of the Display
|
||||
|
||||
|
||||
/****************** User Config for NRF24***************************/
|
||||
/*** Set this radio as radio number RADIO0 or RADIO1 ***/
|
||||
radio_type_e radioNumber = BASESTATION; //---> TOPSTATION has the button connected
|
||||
radio_type_e stationNumber = BASESTATION; //---> TOPSTATION has the button connected, BASESTATION is the default ...
|
||||
uint8_t radio_sel0, radio_sel1; // code of type of station
|
||||
|
||||
/* Hardware configuration: Set up nRF24L01 radio on SPI bus plus pins 7 & 8 */
|
||||
RF24 radio(RF24_CNS,RF24_CE);
|
||||
|
@ -24,15 +27,13 @@ unsigned long mean_time_offset = 0; // mean value for the offset
|
|||
unsigned long current_time_offset = 0; // current offset ...
|
||||
unsigned long running_time_offset = 0; // offset that will be used for this run ...
|
||||
unsigned long start_time = 0; // if the timer is running this is that start time ...
|
||||
unsigned long runner_start_time = 0; // this is the time the runner left the pad - so the status of the falsetstart pin goes to high again - but this is OK and a real start
|
||||
signed long runner_run_time = 0; // this is the time the runner really needed or the time started to early - depending on sign ...
|
||||
unsigned long run_time = 0; // if the timer is running this is that start time ...
|
||||
boolean warn_during_run = false; // will be set to true if there is a warning during the run - usually an offset sync error
|
||||
|
||||
timer_state_e timer_state = TIMER_INIT; // timer needs to be initialized ...
|
||||
// timer is ready to be started ...
|
||||
// will be true if the timer was started
|
||||
// will be true if the timer is running and the stopbutton was pressed at the TOPSTATION
|
||||
// will be true if the timeout of the timer is reached
|
||||
// will be true if the chancel button was pressed - e.g. in case of a early start
|
||||
timer_state_e timer_state = TIMER_WAIT; // timer needs to be initialized ...
|
||||
timer_state_e timer_new_state = TIMER_INIT; // timer needs to be initialized ...
|
||||
|
||||
|
||||
transcv_s radio_data;
|
||||
|
@ -42,10 +43,10 @@ void setup(){
|
|||
Serial.begin(115200);
|
||||
|
||||
// this is the top button - will be pressed by the speed climber as soon she/he reaches the top ...
|
||||
pinMode(STOPBUTTON_IN, INPUT);
|
||||
pinMode(STARTBUTTON_IN, INPUT);
|
||||
pinMode(CHANCELBUTTON_IN, INPUT);
|
||||
pinMode(FAILSTARTBUTTON_IN, INPUT);
|
||||
pinMode(STOPBUTTON_IN, INPUT_PULLUP);
|
||||
pinMode(STARTBUTTON_IN, INPUT_PULLUP);
|
||||
pinMode(CANCELBUTTON_IN, INPUT_PULLUP);
|
||||
pinMode(FAILSTARTBUTTON_IN, INPUT_PULLUP);
|
||||
|
||||
pinMode(WARN_LED, OUTPUT);
|
||||
pinMode(FAIL_LED, OUTPUT);
|
||||
|
@ -53,12 +54,20 @@ void setup(){
|
|||
|
||||
// Get the station type (base or top) as set by the station select pin - BASESTATION is default
|
||||
|
||||
pinMode(STATION_SEL, INPUT);
|
||||
Serial.print(F(" The station select pin (pin "));
|
||||
Serial.print(STATION_SEL);
|
||||
Serial.print(F(") is set to level: "));
|
||||
Serial.println(RADIO_SEL);
|
||||
if(digitalRead(RADIO_SEL) == HIGH){
|
||||
pinMode(STATION_SEL0, INPUT);
|
||||
pinMode(STATION_SEL0, INPUT);
|
||||
radio_sel0 = digitalRead(STATION_SEL0);
|
||||
radio_sel1 = digitalRead(STATION_SEL1);
|
||||
Serial.print(F(" The station select[1,0] pins (pin "));
|
||||
Serial.print(STATION_SEL0);
|
||||
Serial.print(F(","));
|
||||
Serial.print(STATION_SEL1);
|
||||
Serial.print(F(") are set to level: '"));
|
||||
Serial.print(radio_sel0);
|
||||
Serial.print(radio_sel1);
|
||||
Serial.println("'");
|
||||
|
||||
if((radio_sel0 == 1) & (radio_sel1 == 0)){
|
||||
stationNumber = TOPSTATION;
|
||||
Serial.print(F("The level of the station select pin makes the current node set to the TOPSTATION."));
|
||||
}
|
||||
|
@ -98,7 +107,7 @@ void loop(void) {
|
|||
// check for pressed button ...
|
||||
if( (millis() - radio_data.topbuttonpressedtime) > MIN_DELAY_BETWEEN_PRESSED_MS){
|
||||
// ignore if the button was "pressed" a few millis before - this is keybouncing and would give a false result and if the button is pressed for a longer time that would effect the time as well
|
||||
if(digitalRead(STOPBUTTON_IN, STOPBUTTON_PRESSED)){
|
||||
if(digitalRead(STOPBUTTON_IN) == STOPBUTTON_PRESSED){
|
||||
// button was pressed - store the time
|
||||
radio_data.topbuttonpressedtime = millis();
|
||||
topbuttonwaspressed = true;
|
||||
|
@ -138,13 +147,13 @@ void loop(void) {
|
|||
// check current offset of the TOP_STATIOn and the BASESTATION if more than allowed ...
|
||||
if(abs(current_time_offset - mean_time_offset) < MAX_DIFFERENCE_OFFSET_MS){
|
||||
// the offset is in range - check if we have already enough values of if we need to add more ...
|
||||
if(counter_time_offset < REQUIRED_NUMBER_MEANVALS){
|
||||
if(counter_time_offset <= REQUIRED_NUMBER_MEANVALS){
|
||||
//add the next value to meanvalue calculation ...
|
||||
sum_time_offset = sum_time_offset + current_time_offset;
|
||||
counter_time_offset++;
|
||||
mean_time_offset = sum_time_offset/counter_time_offset;
|
||||
Serial.print(F("Offset calulation. We already have "))
|
||||
Serial.print(counter_time_offset)
|
||||
Serial.print(F("Offset calulation. We already have "));
|
||||
Serial.print(counter_time_offset);
|
||||
Serial.print(F(" of "));
|
||||
Serial.print(REQUIRED_NUMBER_MEANVALS);
|
||||
Serial.print(F(" values used for offset calculation. Mean value of offset based on that is: "));
|
||||
|
@ -163,141 +172,108 @@ void loop(void) {
|
|||
mean_time_offset = 0;
|
||||
}
|
||||
|
||||
// set state to new_state
|
||||
if(timer_state != timer_new_state){
|
||||
update_statemassage(timer_new_state);
|
||||
}
|
||||
timer_state = timer_new_state;
|
||||
|
||||
// set LEDs
|
||||
set_state_LEDs(timer_state, warn_during_run );
|
||||
|
||||
switch(timer_state){
|
||||
case TIMER_INIT:
|
||||
update_screen(timer_state);
|
||||
// check if we are ready ...
|
||||
if(counter_time_offset > REQUIRED_NUMBER_MEANVALS){
|
||||
// check if offset is OK - if not .. set state back to INIT
|
||||
timer_state = TIMER_READY;
|
||||
timer_new_state = TIMER_READY;
|
||||
}
|
||||
break;
|
||||
case TIMER_READY:
|
||||
update_screen(timer_state);
|
||||
warn_during_run = false;
|
||||
if(counter_time_offset < REQUIRED_NUMBER_MEANVALS){
|
||||
// check if offset is OK - if not .. set state back to INIT
|
||||
timer_state = TIMER_INIT;
|
||||
timer_new_state = TIMER_INIT;
|
||||
}
|
||||
else{
|
||||
// check if the FALSESTATE button is pressed - somebody is ready to run ...
|
||||
if(digitalRead(FAILSTARTBUTTON_IN, FAILSTARTBUTTON_PRESSED)){
|
||||
if(digitalRead(FAILSTARTBUTTON_IN) == FAILSTARTBUTTON_PRESSED){
|
||||
//wait a few milliseconds to prevent keybouncing - this is a very simplistic method here
|
||||
delay(300);
|
||||
//read again and check if still active ...
|
||||
if(digitalRead(FAILSTARTBUTTON_IN, FAILSTARTBUTTON_PRESSED)){
|
||||
if(digitalRead(FAILSTARTBUTTON_IN) == FAILSTARTBUTTON_PRESSED){
|
||||
// check if the start button was pressed ... there is at least still someone waiting for the run .
|
||||
if(digitalRead(STARTBUTTON_IN, STARTBUTTON_PRESSED)){
|
||||
timer_state = TIMER_STARTED;
|
||||
if(digitalRead(STARTBUTTON_IN) == STARTBUTTON_PRESSED){
|
||||
// now enable the interrupt for the FALSESTART button
|
||||
attachInterrupt(digitalPinToInterrupt(FAILSTARTBUTTON_IN), false_start_isr, CHANGE);
|
||||
timer_new_state = TIMER_STARTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TIMER_STARTED:
|
||||
//enable the interrupt for the FALSESTART button and start the StartSequence - no interruption possible here anymore, except the FALSESTART button was released to early
|
||||
|
||||
//initialize the start countdown here ... if done set to RUNNING ... maybe check fail start already here ... ?? or in running state ... or extra state ...
|
||||
update_screen(timer_state);
|
||||
//initialize the start countdown
|
||||
timer_new_state = TIMER_RUNNING;
|
||||
startSequence();
|
||||
|
||||
case TIMER_FAILCHECK:
|
||||
//check for fail start in this phase - interrupt is active, this state can only be reached from STARTED state ...
|
||||
if(start_time - millis() >= STARTOK_TOLERANCETIME_MS)
|
||||
{
|
||||
timer_state = TIMER_RUNNING;
|
||||
}
|
||||
break;
|
||||
case TIMER_RUNNING:
|
||||
noTone(PIEZO_PIN);
|
||||
update_screen(timer_state);
|
||||
if(counter_time_offset < REQUIRED_NUMBER_MEANVALS){
|
||||
// check if offset is still OK - if not .. set state to TIMER_RUNNING
|
||||
warn_during_run = true;
|
||||
}
|
||||
if(digitalRead(CHANCELBUTTON_IN, CHANCELBUTTON_PRESSED)){
|
||||
timer_state = TIMER_CHANCELED;
|
||||
if(millis() - start_time > TIMER_TIMEOUT){
|
||||
timer_new_state = TIMER_TIMEDOUT;
|
||||
}
|
||||
if(digitalRead(CANCELBUTTON_IN) == CANCELBUTTON_PRESSED){
|
||||
timer_new_state = TIMER_CANCELLED;
|
||||
}
|
||||
if((radio_data.topbuttonpressedtime - running_time_offset) > millis()){
|
||||
timer_state = TIMER_STOPPED;
|
||||
timer_new_state = TIMER_STOPPED;
|
||||
}
|
||||
break;
|
||||
case TIMER_STOPPED:
|
||||
//calculate the run_time and switch to WAIT
|
||||
|
||||
timer_state = TIMER_WAIT;
|
||||
run_time = (radio_data.topbuttonpressedtime - running_time_offset) - start_time;
|
||||
runner_run_time = runner_start_time - run_time;
|
||||
update_screen(timer_state);
|
||||
timer_new_state = TIMER_WAIT;
|
||||
break;
|
||||
case TIMER_FAIL:
|
||||
//fail start case ....
|
||||
|
||||
timer_state = TIMER_WAIT;
|
||||
failSequence();
|
||||
run_time = 99999;
|
||||
runner_run_time = runner_start_time - start_time;
|
||||
update_screen(timer_state);
|
||||
timer_new_state = TIMER_WAIT;
|
||||
break;
|
||||
case TIMER_CHANCELED:
|
||||
case TIMER_CANCELLED:
|
||||
// what to do in chancel mode ?
|
||||
|
||||
timer_state = TIMER_WAIT;
|
||||
run_time = 99999;
|
||||
runner_run_time = runner_start_time - start_time;
|
||||
update_screen(timer_state);
|
||||
timer_new_state = TIMER_WAIT;
|
||||
break;
|
||||
case TIMER_TIMEDOUT:
|
||||
//
|
||||
|
||||
timer_state = TIMER_WAIT;
|
||||
// time out
|
||||
run_time = millis() - start_time;
|
||||
runner_run_time = runner_start_time - start_time;
|
||||
update_screen(timer_state);
|
||||
timer_new_state = TIMER_WAIT;
|
||||
break;
|
||||
case TIMER_WAIT:
|
||||
// wait until the start button was pressed to go ahead
|
||||
if(digitalRead(STARTBUTTON_IN, STARTBUTTON_PRESSED)){
|
||||
timer_state = TIMER_READY;
|
||||
// disable interrupt if not already done
|
||||
detachInterrupt(digitalPinToInterrupt(FAILSTARTBUTTON_IN));
|
||||
// wait until the chancel button was pressed to go ahead
|
||||
if(digitalRead(CANCELBUTTON_IN) == CANCELBUTTON_PRESSED){
|
||||
timer_new_state = TIMER_READY;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
int ypos = 64-42/2;
|
||||
snprintf ( temp_string, sizeof(temp_string),"%d.%1d", int(client_data.temperature), int(abs(client_data.temperature - int(client_data.temperature))*10 + 0.5));
|
||||
Serial.println(temp_string);
|
||||
|
||||
display.setFontPosCenter();
|
||||
display.setFont(u8g2_font_logisoso34_tn);
|
||||
int xpos = (128-display.getStrWidth(temp_string))/2 - 10;
|
||||
|
||||
display.firstPage();
|
||||
do {
|
||||
display.setFont(u8g2_font_logisoso34_tn);
|
||||
display.setCursor(xpos,ypos);
|
||||
display.print(temp_string);
|
||||
display.setCursor(xpos + display.getStrWidth(temp_string)+ 5,ypos-15);
|
||||
display.setFont(u8g2_font_ncenB12_tr);
|
||||
display.print(F("°C"));
|
||||
} while ( display.nextPage() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
if( radio.available(&pipeNo)){
|
||||
while( radio.available(&pipeNo)){ // Read all available payloads
|
||||
radio.read( &control_data, sizeof(control_data) );
|
||||
}
|
||||
|
||||
radio.stopListening(); // First, stop listening so we can talk
|
||||
|
||||
Serial.print(F("Got remote data counter: "));
|
||||
Serial.print(control_data.counter);
|
||||
Serial.print(F(" time: "));
|
||||
Serial.println(control_data.time);
|
||||
radio_data.counter = control_data.counter + 1; // Ack payloads are much more efficient than switching to transmit mode to respond to a call
|
||||
radio_data.time = control_data.time;
|
||||
Serial.print(F("Loaded next response "));
|
||||
Serial.println(radio_data.counter);
|
||||
|
||||
if( radio.write(&radio_data, sizeof(radio_data) )){
|
||||
Serial.println(F("Sending failed.")); // If no ack response, sending failed
|
||||
//add error handling here if remote does not recieve the data anymore
|
||||
}
|
||||
|
||||
radio.startListening();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -305,42 +281,164 @@ void loop(void) {
|
|||
|
||||
//####################### HELPER FUNCTIONS ###########################
|
||||
|
||||
void update_statemassage(timer_state_e timer_state){
|
||||
switch(timer_state){
|
||||
case TIMER_INIT:
|
||||
Serial.println("*** TIMER_INIT ***");
|
||||
break;
|
||||
case TIMER_READY:
|
||||
Serial.println("*** TIMER_READY ***");
|
||||
break;
|
||||
case TIMER_STARTED:
|
||||
Serial.println("*** TIMER_STARTED ***");
|
||||
break;
|
||||
case TIMER_RUNNING:
|
||||
Serial.println("*** TIMER_RUNNING ***");
|
||||
break;
|
||||
case TIMER_CANCELLED:
|
||||
Serial.println("*** TIMER_CANCELLED ***");
|
||||
break;
|
||||
case TIMER_STOPPED:
|
||||
Serial.println("*** TIMER_STOPPED ***");
|
||||
break;
|
||||
case TIMER_TIMEDOUT:
|
||||
Serial.println("*** TIMER_TIMEDOUT ***");
|
||||
break;
|
||||
case TIMER_FAIL:
|
||||
Serial.println("*** TIMER_FAIL ***");
|
||||
break;
|
||||
case TIMER_WAIT:
|
||||
Serial.println("*** TIMER_WAIT ***");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void update_screen(timer_state_e timer_state){
|
||||
bool scr_update = true;
|
||||
int ypos = 64-42/2;
|
||||
String top_line = "no state";
|
||||
char string_to_char[50];
|
||||
|
||||
switch(timer_state){
|
||||
case TIMER_INIT:
|
||||
top_line = "Init";
|
||||
break;
|
||||
case TIMER_READY:
|
||||
top_line = "Ready!";
|
||||
break;
|
||||
case TIMER_STARTED:
|
||||
top_line = "Started ...";
|
||||
break;
|
||||
case TIMER_RUNNING:
|
||||
top_line = "Running ...";
|
||||
break;
|
||||
case TIMER_CANCELLED:
|
||||
top_line = "Cancelled!";
|
||||
break;
|
||||
case TIMER_STOPPED:
|
||||
top_line = "Stopped!";
|
||||
break;
|
||||
case TIMER_TIMEDOUT:
|
||||
top_line = "Time out!";
|
||||
break;
|
||||
case TIMER_FAIL:
|
||||
top_line = "False start!";
|
||||
break;
|
||||
default:
|
||||
scr_update = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if(scr_update == true){
|
||||
//snprintf( string_to_char, sizeof(string_to_char),"%s", top_line);
|
||||
top_line.toCharArray(string_to_char, sizeof(string_to_char));
|
||||
//Serial.print("DISPLAY: ");
|
||||
//Serial.println(string_to_char);
|
||||
display.setFontPosCenter();
|
||||
display.setFont(u8g2_font_ncenB08_tr);
|
||||
int xpos = (128 - (display.getStrWidth(string_to_char)))/2 - 10;
|
||||
|
||||
display.firstPage();
|
||||
do {
|
||||
display.setFont(u8g2_font_ncenB08_tr);
|
||||
display.setCursor(xpos,ypos);
|
||||
display.print(string_to_char);
|
||||
} while ( display.nextPage() );
|
||||
}
|
||||
}
|
||||
|
||||
void set_state_LEDs(timer_state_e state, boolean warn)
|
||||
{
|
||||
// set the LEDS corresponding to the state of the timer ... as long as the system is not waiting for input ...
|
||||
if(TIMER_WAIT != state){
|
||||
digitalWrite(READY_LED, LEDStates[state][0]};
|
||||
digitalWrite(RUN_LED, LEDStates[state][1]};
|
||||
digitalWrite(FAIL_LED, LEDStates[state][2]};
|
||||
digitalWrite(READY_LED, LEDStates[state][0]);
|
||||
digitalWrite(RUN_LED, LEDStates[state][1]);
|
||||
digitalWrite(FAIL_LED, LEDStates[state][2]);
|
||||
|
||||
if(warn == true){
|
||||
digitalWrite(WARN_LED, WARN_LED_ON};
|
||||
digitalWrite(WARN_LED, WARN_LED_ON);
|
||||
}
|
||||
else
|
||||
{
|
||||
digitalWrite(WARN_LED, WARN_LED_OFF};
|
||||
digitalWrite(WARN_LED, WARN_LED_OFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void startSequence(void)
|
||||
{
|
||||
// first - enable the interrupt
|
||||
|
||||
// set the startime - this is the current time plus the length of this sequence
|
||||
start_time = millis() + STARTSEQ_LENGTH_MS;
|
||||
running_time_offset = mean_time_offset;
|
||||
|
||||
start_time = millis() + STARTSEQ_LENGTH_MS;
|
||||
Serial.print("Start time is: ");
|
||||
Serial.println(start_time);
|
||||
// this is sequence of usually three tones after a wait time 1sec , in between the tones there is also a delay of 1 sec. Each tone is 200ms seconds long, except the last
|
||||
if(timer_new_state == TIMER_RUNNING){
|
||||
delay(STARTSEQ_STARTPAUSE_MS);
|
||||
}
|
||||
// first tone
|
||||
|
||||
if(timer_new_state == TIMER_RUNNING){
|
||||
tone(PIEZO_PIN, STARTSEQ_TON_1_2_FREQUENCY,STARTSEQ_TON_1_2_LENGTH_MS );
|
||||
delay(STARTSEQ_TONEPAUSE_MS);
|
||||
}
|
||||
//second tone
|
||||
|
||||
if(timer_new_state == TIMER_RUNNING){
|
||||
tone(PIEZO_PIN, STARTSEQ_TON_1_2_FREQUENCY,STARTSEQ_TON_1_2_LENGTH_MS );
|
||||
delay(STARTSEQ_TONEPAUSE_MS);
|
||||
}
|
||||
//third tone
|
||||
if(timer_new_state == TIMER_RUNNING){
|
||||
tone(PIEZO_PIN, STARTSEQ_TON_3_FREQUENCY,STARTSEQ_TON_3_LENGTH_MS );
|
||||
}
|
||||
}
|
||||
|
||||
// disable the interrupt and than
|
||||
|
||||
void failSequence(void)
|
||||
{
|
||||
// first tone
|
||||
tone(PIEZO_PIN, FAILSEQ_TON_FREQUENCY,FAILSEQ_TON_LENGTH_MS );
|
||||
delay(FAILSEQ_TONEPAUSE_MS);
|
||||
//second tone
|
||||
tone(PIEZO_PIN, FAILSEQ_TON_FREQUENCY,FAILSEQ_TON_LENGTH_MS );
|
||||
delay(FAILSEQ_TONEPAUSE_MS);
|
||||
noTone(PIEZO_PIN);
|
||||
}
|
||||
|
||||
void false_start_isr(void)
|
||||
{
|
||||
// this is the interrupt routine for the FALSESTART button
|
||||
// this will save the time when the runner is really started
|
||||
Serial.println("** Interrupt service routine started: false_start_ISR **");
|
||||
runner_start_time = millis();
|
||||
if(timer_state == TIMER_STARTED & timer_new_state == TIMER_STARTED){
|
||||
timer_new_state = TIMER_FAIL;
|
||||
detachInterrupt(digitalPinToInterrupt(FAILSTARTBUTTON_IN));
|
||||
noTone(PIEZO_PIN);
|
||||
} else {
|
||||
if(timer_state == TIMER_RUNNING | timer_new_state == TIMER_RUNNING ){
|
||||
// disable this interrupt;
|
||||
detachInterrupt(digitalPinToInterrupt(FAILSTARTBUTTON_IN));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Reference in a new issue