diff --git a/speedclock.h b/speedclock.h index 55e173e..682aca2 100644 --- a/speedclock.h +++ b/speedclock.h @@ -20,7 +20,7 @@ typedef enum {BASESTATION = 0, TOPSTATION} radio_type_e; typedef struct transcv_struct{ unsigned long topstationtime; // the top station sends its time (millis()) continously to the base station - unsigned long topbuttonpressedtime; // the top station sends the time in millis() when the button was pressed - this is already the calculated time + volatile unsigned long topbuttonpressedtime; // the top station sends the time in millis() when the button was pressed - this is already the calculated time }transcv_s; #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. @@ -38,7 +38,7 @@ const uint8_t BUTTONPins[NO_LAST_BUTTON] = { [BUTTON_FAIL] = 3, // stop button input pin }; -#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_PRESSED_MS 500 // this defines the time in milliseconds before the button is expected to be pressed again. We do this to avaoid keybouncing #define PIEZO_PIN 6 // piezo speaker @@ -102,7 +102,7 @@ void failSequence(void); void wait(unsigned long ms); void start_isr(void); void update_buttons(void); - - +void send_values(void); +void stop_isr(void); #endif diff --git a/speedclock.ino b/speedclock.ino index 6a5089d..0fa2c05 100644 --- a/speedclock.ino +++ b/speedclock.ino @@ -91,6 +91,8 @@ void setup(){ radio.begin(); radio.setRetries(15, 15); //the first is the time between reties in multiple of 250ms, the second is the numer of attempts if(stationNumber == TOPSTATION){ + // Attach the STOP button interrupt + attachInterrupt(digitalPinToInterrupt(BUTTONPins[BUTTON_STOPCANCEL]), stop_isr, FALLING ); // Set the PA Level of the sendin TOP_STATION radio.setPALevel(RF24_PA_LEVEL); radio.openWritingPipe(addresses[1]); // Both radios listen on the same pipes by default, but opposite addresses @@ -120,113 +122,83 @@ void loop(void) { blink_on_swiched_at = millis(); blink_on = !blink_on; } + + // set state to new_state + if(timer_state != timer_new_state){ + Serial.print(millis()); + Serial.print("ms : current state:"); + Serial.print(timer_state); + Serial.print(" new state:"); + Serial.println(timer_new_state); + } + + // update button states ... + update_buttons(); + /****************** Code for the TOPSTATION is here - the stop button is connected to the top station ***************************/ - if (stationNumber == TOPSTATION){ // Radio is the top station and sends continously its time and the time the stop button was pressed. - + // send data to base_station + send_values(); - if(false == offset_sync_sequence){ - // check for pressed button ... - if(topbuttonwaspressed == false){ - 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(BUTTONPins[BUTTON_STOPCANCEL]) != BUTTON_NOTPRESSED){ - // button was pressed - store the time - radio_data.topbuttonpressedtime = millis(); - topbuttonwaspressed = true; - digitalWrite(LEDPins[RUN_LED], LED_ON); - } - } - } else { - if(digitalRead(BUTTONPins[BUTTON_STOPCANCEL]) == BUTTON_NOTPRESSED){ - topbuttonwaspressed = false; - digitalWrite(LEDPins[RUN_LED], LED_OFF); - } - } - } else { - topbuttonwaspressed = false; - digitalWrite(LEDPins[RUN_LED], LED_OFF); - } - - // if the button was not pressed only each few second data will be send to BASESTATION ... - if(offset_sync_sequence || topbuttonwaspressed || ((millis()-radio_data.topstationtime) >= MIN_DELAY_BETWEEN_SEND_MS)){ - // store current millis to be send as reference ... - radio_data.topstationtime = millis(); // set the current milli second count - //Serial.print("senddate_to_base at:"); - //Serial.println(millis()); - //Serial.print(" -> topstationtime:"); - //Serial.print(radio_data.topstationtime); - //Serial.print("ms stoppressedtime:"); - //Serial.print(radio_data.topbuttonpressedtime); - //Serial.print("ms offset counter value :"); - //Serial.println(counter_time_offset); + timer_state = timer_new_state; - // send data ... - if (!radio.write(&radio_data,sizeof(radio_data))){ // Send the counter variable to the other radio - if(((millis() - connection_last_established_at_ms) >= (CONN_TIMEOUT-100)) || (connection_last_established_at_ms == 0)){ - connection_available = false; - //Serial.println("Failed to send data to BASESSTATION ... will retry"); - digitalWrite(LEDPins[FAIL_LED], LED_ON); - digitalWrite(LEDPins[READY_LED], LED_OFF); - offset_sync_sequence = true; - counter_time_offset = 0; + // set LEDs + set_state_LEDs(timer_state, false ); + + switch(timer_state){ + case TIMER_NOCONNECTION: + // as long as there is no connection to BASE_STATION we will end up here + if(true == connection_available){ + timer_new_state = TIMER_INIT; + } + offset_sync_sequence = true; + counter_time_offset = 0; + break; + case TIMER_INIT: + if(false == connection_available){ + timer_new_state = TIMER_NOCONNECTION; } else { - if(offset_sync_sequence){ - if(counter_time_offset > 0){ - counter_time_offset--; + if(false == offset_sync_sequence){ + if(button_state[BUTTON_STOPCANCEL] == BUTTON_NOTPRESSED){ + topbuttonwaspressed = false; + timer_new_state = TIMER_IDLE; } } } - } - else - { - //Serial.print("Data sent to BASESSTATION"); - digitalWrite(LEDPins[FAIL_LED], LED_OFF); - if(offset_sync_sequence){ - digitalWrite(LEDPins[FAIL_LED], blink_on); + break; + case TIMER_IDLE: + //check for the pressed button - or better enable the interrupt to handle that + if(false == connection_available){ + timer_new_state = TIMER_NOCONNECTION; } else { - digitalWrite(LEDPins[READY_LED], LED_ON); + if(true == topbuttonwaspressed){ + timer_new_state = TIMER_STOPPED; + } } - connection_last_established_at_ms = millis(); - connection_available = true; - // check offset sync counter ... - if(counter_time_offset < (4*REQUIRED_NUMBER_MEANVALS)){ - counter_time_offset++; - } else { - // offset sync done - offset_sync_sequence = false; + break; + case TIMER_STOPPED: + // wait a few millis and ... after that go back to idle ... + if((signed long)(millis() - radio_data.topbuttonpressedtime) > MIN_DELAY_BETWEEN_PRESSED_MS){ + if(button_state[BUTTON_STOPCANCEL] == BUTTON_NOTPRESSED){ + timer_new_state = TIMER_IDLE; + topbuttonwaspressed = false; + } } - - } - + break; } - //Serial.print("looptime_top "); - //Serial.println(millis()); } /****************** Code for the BASESTATION is here - the display and the start button is connected here. All caclulation will be done here ***************************/ - if ( stationNumber == BASESTATION ) { - // update button states ... - update_buttons(); - // receive data from top_station, calculate offset and set 'last connection' time stamp receive_values(); // update the OLED screen update_screen(timer_new_state); - // set state to new_state - if(timer_state != timer_new_state){ - //Serial.print(millis()); - //Serial.print("ms : current state:"); - //Serial.print(timer_state); - //Serial.print(" new state:"); - //Serial.println(timer_new_state); - } timer_state = timer_new_state; // set LEDs @@ -238,6 +210,7 @@ void loop(void) { if(connection_available == true){ timer_new_state = TIMER_INIT; } + break; case TIMER_INIT: // init the system offset ... if(connection_available == false){ @@ -382,13 +355,16 @@ void loop(void) { } break; } - - //Serial.print("looptime_base "); - //Serial.println(millis()); - } -} + //Serial.print("mean_time_offset "); + //Serial.println(mean_time_offset); + //Serial.print("current_time_offset "); + //Serial.println(current_time_offset); + //Serial.print("looptime "); + //Serial.println(millis()); + +} //####################### HELPER FUNCTIONS ########################### void update_buttons(void){ @@ -453,14 +429,16 @@ void receive_values(void){ connection_last_established_at_ms = millis(); connection_available = true; 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(" Current time on client in millis: "); - //Serial.println(radio_data.topstationtime); - //Serial.print("Offset is: "); - //Serial.println(current_time_offset); - //Serial.print(" Button was pressed last time on client in millis: "); - //Serial.println(radio_data.topbuttonpressedtime); + /* + Serial.print("Current time on host in millis:"); + Serial.print(millis()); + Serial.print(" Current time on client in millis: "); + Serial.println(radio_data.topstationtime); + Serial.print("Offset is: "); + Serial.println(current_time_offset); + Serial.print(" 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){ @@ -697,7 +675,18 @@ void failSequence(void){ } } -void false_start_isr(void){ +void stop_isr(void){ + // this is the interrupt routine for the topstation STOP button + // this will save the time when the runner has pushed the button + if(timer_state == TIMER_IDLE){ + radio_data.topbuttonpressedtime = millis(); + //Serial.print(radio_data.topbuttonpressedtime); + //Serial.println(" ms <- current time ** stop_ISR ** stop button pushed: "); + topbuttonwaspressed = true; + } +} + +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 if(timer_new_state != TIMER_READY){ @@ -741,3 +730,47 @@ void start_isr(void){ } } +void send_values(void){ + if(offset_sync_sequence || topbuttonwaspressed || ((millis()-radio_data.topstationtime) >= MIN_DELAY_BETWEEN_SEND_MS)){ + // store current millis to be send as reference ... + radio_data.topstationtime = millis(); // set the current milli second count + //Serial.print("senddate_to_base at:"); + //Serial.println(millis()); + //Serial.print(" -> topstationtime:"); + //Serial.print(radio_data.topstationtime); + //Serial.print("ms stoppressedtime:"); + //Serial.print(radio_data.topbuttonpressedtime); + //Serial.print("ms offset counter value :"); + //Serial.println(counter_time_offset); + + // send data ... + if (!radio.write(&radio_data,sizeof(radio_data))){ // Send the counter variable to the other radio + if(((millis() - connection_last_established_at_ms) >= (CONN_TIMEOUT-100))){ + connection_available = false; + //Serial.println("Failed to send data to BASESSTATION ... will retry"); + } else { + if(offset_sync_sequence){ + if(counter_time_offset > 0){ + counter_time_offset--; + } + } + } + } + else + { + //Serial.print("Data sent to BASESSTATION"); + connection_last_established_at_ms = millis(); + connection_available = true; + // check offset sync counter ... + if(counter_time_offset < (4*REQUIRED_NUMBER_MEANVALS)){ + counter_time_offset++; + } else { + // offset sync done + offset_sync_sequence = false; + } + + } + } +} + +