diff --git a/Pictures/photo_2017-07-29_19-06-50.jpg b/Pictures/photo_2017-07-29_19-06-50.jpg new file mode 100644 index 0000000..653ae44 Binary files /dev/null and b/Pictures/photo_2017-07-29_19-06-50.jpg differ diff --git a/speedclock.h b/speedclock.h index 171d64c..9b95c3e 100644 --- a/speedclock.h +++ b/speedclock.h @@ -71,6 +71,7 @@ const float LEDStates[][3] = #define MAX_DIFFERENCE_OFFSET_MS 100 // 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 MAX_ALLOWED_FAILED_OFFSETS 3 // if more than this number of offsets are out of the specified MAX_DIFFERENCE_OFFSET_MS value, offset calcultion will be restarted #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 @@ -88,6 +89,7 @@ const float LEDStates[][3] = #define TIMER_TIMEOUT 20000 //--------------------------------------- function declarations ---------------------------------------------- +void receive_values(void); void false_start_isr(void); void update_screen(timer_state_e state); void set_state_LEDs(timer_state_e state, boolean warn); diff --git a/speedclock.ino b/speedclock.ino index 2472717..32d826e 100644 --- a/speedclock.ino +++ b/speedclock.ino @@ -30,7 +30,8 @@ unsigned long runner_start_time = 0; // this is the time the runner lef 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 -unsigned long connection_established = 0; +unsigned long connection_established = 0; // time the last active connection was established +uint8_t failed_offsets = MAX_ALLOWED_FAILED_OFFSETS; // number of offset values that did not fullfill the MAX_DIFFERENCE_OFFSET_MS criterion boolean topbuttonwaspressed = false; @@ -164,62 +165,12 @@ void loop(void) { } - /****************** Code for the BASESTATION is here - the display and the start button is connected here. All caclulation will be done here ***************************/ if ( stationNumber == BASESTATION ) { - byte pipeNo; - // read data from TOP_STATION ... - if( radio.available()){ - // check if radio data is available - if so read the data - while( radio.available(&pipeNo)){ // Read all available payloads - connection_established = millis(); - radio.read( &radio_data, sizeof(radio_data) ); // Read the data the TOPSTATION sent - } - current_time_offset = radio_data.topstationtime - millis(); // the offset between TOP_STATION and BASESTATION - Serial.print("Current time on host in millis:"); - Serial.print(millis()); - Serial.print(F(" Current time on client in millis: ")); - Serial.println(radio_data.topstationtime); - Serial.print("Offset is: "); - Serial.println(current_time_offset); - Serial.print(F(" Button was pressed last time on client in millis: ")); - Serial.println(radio_data.topbuttonpressedtime); - } - // offset calculation ... only needed if the variation is bigger than allowed or not enough values available already ... - // check current offset of the TOP_STATIOn and the BASESTATION if more than allowed ... - if(counter_time_offset == 0){ - mean_time_offset = current_time_offset; - } - 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){ - //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(" of ")); - Serial.print(REQUIRED_NUMBER_MEANVALS); - Serial.print(F(" values used for offset calculation. Mean value of offset based on that is: ")); - Serial.println(mean_time_offset); - } - } else { - // the current offset is out of range so we need to restart the mean calculation and set the timer to unready state ... - Serial.print("Difference current offset is "); - Serial.println( abs(current_time_offset - mean_time_offset) ); - Serial.print(F("Will restart offset calculation because the variation of the current offset: ")); - Serial.print(current_time_offset); - Serial.print(F(" is more than the allowed: ")); - Serial.print(MAX_DIFFERENCE_OFFSET_MS); - Serial.print(F(" compared to the mean offset: ")); - Serial.println(mean_time_offset); - counter_time_offset = 0; - sum_time_offset = 0; - mean_time_offset = 0; - } + // receive data from top_station, calculate offset and set 'last connection' time stamp + receive_values(); // set state to new_state if(timer_state != timer_new_state){ @@ -347,6 +298,75 @@ void loop(void) { //####################### HELPER FUNCTIONS ########################### +void receive_values(void){ + byte pipeNo; + // check if radio data is available - if so read the data + if( radio.available()){ + while( radio.available(&pipeNo)){ // Read all available payloads + // read data from TOP_STATION ... + connection_established = millis(); + radio.read( &radio_data, sizeof(radio_data) ); // Read the data the TOPSTATION sent + } + current_time_offset = radio_data.topstationtime - millis(); // the offset between TOP_STATION and BASESTATION + Serial.print("Current time on host in millis:"); + Serial.print(millis()); + Serial.print(F(" Current time on client in millis: ")); + Serial.println(radio_data.topstationtime); + Serial.print("Offset is: "); + Serial.println(current_time_offset); + Serial.print(F(" Button was pressed last time on client in millis: ")); + Serial.println(radio_data.topbuttonpressedtime); + + // offset calculation ... only needed if the variation is bigger than allowed or not enough values available already ... + if(counter_time_offset == 0){ + // this is the initial setup to start with something - in this case the last offset value that was received + mean_time_offset = current_time_offset; + } + // 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){ + // if the current value is in range - decrease the fail counter by 1 if it was not zero already + if(failed_offsets > 0){ + failed_offsets--; + } + // 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){ + //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 have ")); + Serial.print(counter_time_offset); + Serial.print(F("/")); + Serial.print(REQUIRED_NUMBER_MEANVALS); + Serial.print(F(" values. Mean offset value based on that is: ")); + Serial.println(mean_time_offset); + } + } else { + // the current offset is out of range ... + // if the values before also already failed the criterion but the max allowed number of such fails is not reached ... just increase the counter. + if(failed_offsets < MAX_ALLOWED_FAILED_OFFSETS){ + failed_offsets++; + } + else{ + // if the values before also already failed the criterion AND the max allowed number of such fails is reached ... we need to restart the mean calculation and set the timer to unready state ... + Serial.print(F("TopStation BaseStation are out off sync. Offset calculation will be restarted. Last ")); + Serial.print(MAX_ALLOWED_FAILED_OFFSETS); + //offset ")); + Serial.print(current_time_offset); + Serial.print("is to far from the mean offset "); + Serial.println( abs(current_time_offset - mean_time_offset) ); + Serial.print(F(" is more than the allowed: ")); + Serial.print(MAX_DIFFERENCE_OFFSET_MS); + Serial.print(F(" compared to the mean offset: ")); + Serial.println(mean_time_offset); + counter_time_offset = 0; + sum_time_offset = 0; + mean_time_offset = 0; + failed_offsets = 0; + } + } + } +} void update_statemessage(timer_state_e timer_state){ switch(timer_state){ @@ -506,8 +526,7 @@ void update_screen(timer_state_e state){ } } -void set_state_LEDs(timer_state_e state, boolean warn) -{ +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]); @@ -524,8 +543,7 @@ void set_state_LEDs(timer_state_e state, boolean warn) } } -void startSequence(void) -{ +void startSequence(void){ // set the startime - this is the current time plus the length of this sequence running_time_offset = mean_time_offset; start_time = millis() + STARTSEQ_LENGTH_MS; @@ -556,8 +574,7 @@ void startSequence(void) } } -void failSequence(void) -{ +void failSequence(void){ // first tone tone(PIEZO_PIN, FAILSEQ_TON_FREQUENCY,FAILSEQ_TON_LENGTH_MS ); delay(FAILSEQ_TONEPAUSE_MS); @@ -567,8 +584,7 @@ void failSequence(void) noTone(PIEZO_PIN); } -void false_start_isr(void) -{ +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 **");