Lastest changes ... this versions seems to work again

This commit is contained in:
Fenoglio 2018-07-17 13:12:58 +02:00
parent dfb75de303
commit 6fa6c2c909
4 changed files with 92 additions and 81 deletions

Binary file not shown.

BIN
p14756.db Normal file

Binary file not shown.

View file

@ -23,12 +23,14 @@ typedef struct transcv_struct{
unsigned long topbuttonpressedtime; // the top station sends the time in millis() when the button was pressed - this is already the calculated time unsigned long topbuttonpressedtime; // the top station sends the time in millis() when the button was pressed - this is already the calculated time
}transcv_s; }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.
#define CONN_TIMEOUT 10000 // if there was no data received from the TOPSTATION for that amount of time - the connection is flagged as lost
#define KEY_BOUNCE_MS 10 // the time we use to avoid keybouncing ...
#define STOPBUTTON_IN 2 // this is the input for the button #define STOPBUTTON_IN 2 // this is the input for the button
#define STOPBUTTON_PRESSED LOW // this the signal level the top button will be at as soon as pressed #define STOPBUTTON_PRESSED LOW // 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_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 CONN_TIMEOUT 10000 // if there was no data received from the TOPSTATION for that amount of time - the connection is flagged as lost
#define STARTBUTTON_IN 4 // start button #define STARTBUTTON_IN 4 // start button
#define STARTBUTTON_PRESSED LOW #define STARTBUTTON_PRESSED LOW
@ -76,13 +78,11 @@ const float LEDStates[][3] =
#define REQUIRED_NUMBER_MEANVALS 100 // we need at least this number of meanvalues to be ready to start a run #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 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_STEPS 4
const uint8_t STARTSEQ_NOTES[] = {0,392,392,1047}; // tone frequence
const uint16_t STARTSEQ_DURATION[] = {0,200,200,100}; // tone duration in milliseconds
const unsigned long STARTSEQ_PAUSE[] = {1000000,1000000,1000000,100000}; // pause between tones in microseconds
#define STARTSEQ_LENGTH_MS 3100 // the length of the start sequence from the time the button was pressed ... includes the 3 tones #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 1000
#define STARTSEQ_TON_1_2_LENGTH_MS 200
#define STARTSEQ_TON_1_2_FREQUENCY 392 //NOTE_G4
#define STARTSEQ_TON_3_LENGTH_MS 100
#define STARTSEQ_TON_3_FREQUENCY 1047 //NOTE_C6
#define FAILSEQ_TONEPAUSE_MS 400 #define FAILSEQ_TONEPAUSE_MS 400
#define FAILSEQ_TON_LENGTH_MS 300 #define FAILSEQ_TON_LENGTH_MS 300
@ -100,4 +100,5 @@ void startSequence(void);
void update_statemessage(timer_state_e timer_state); void update_statemessage(timer_state_e timer_state);
void failSequence(void); void failSequence(void);
void wait(unsigned long ms); void wait(unsigned long ms);
void start_isr(void);
#endif #endif

View file

@ -1,3 +1,5 @@
#include <TimerOne.h> // this will enable us to simply use the Timer1. The Timer1 is NOT used by any Arduino internal functions we are using in thsi sketch (the Servo lib is usually using the Timer1) - so we are free to use it for our needs as we like :-)
#include <Wire.h> #include <Wire.h>
#include "SSD1306Ascii.h" #include "SSD1306Ascii.h"
#include "SSD1306AsciiWire.h" #include "SSD1306AsciiWire.h"
@ -16,19 +18,22 @@ RF24 radio(RF24_CNS,RF24_CE);
/**********************************************************/ /**********************************************************/
byte addresses[][12] = {"top_station","basestation"}; // Radio pipe addresses for the 2 nodes to communicate. byte addresses[][12] = {"top_station","basestation"}; // Radio pipe addresses for the 2 nodes to communicate.
boolean time_offset_ok = false; // true as long as the offset is correctly calculated
uint8_t counter_time_offset = 0; // number of used values for the mean value calculation uint8_t counter_time_offset = 0; // number of used values for the mean value calculation
signed long sum_time_offset = 0; // sum of offset values signed long sum_time_offset = 0; // sum of offset values
signed long mean_time_offset = 0; // mean value for the offset signed long mean_time_offset = 0; // mean value for the offset
signed long running_time_offset = 0; // offset that will be used for this run ... signed 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 ... volatile unsigned long start_time = 0; // if the timer is running this is that start time ... (use volatile for all shared variables that deals with hardware)
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 volatile 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 (use volatile for all shared variables that deals with hardware)
unsigned long run_time = 0; // if the timer is running this is that start time ... 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 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_last_established_at_ms = 0; // time the last active connection was established unsigned long connection_last_established_at_ms = 0; // time the last active connection was established
boolean connection_available = false; // if there were no data for longer then CONN_TIMEOUT the connection will be flaged as lost ... boolean connection_available = false; // if there were no data for longer then CONN_TIMEOUT the connection will be flaged as lost ...
uint8_t failed_offsets = MAX_ALLOWED_FAILED_OFFSETS; // number of offset values that did not fullfill the MAX_DIFFERENCE_OFFSET_MS criterion uint8_t failed_offsets = MAX_ALLOWED_FAILED_OFFSETS; // number of offset values that did not fullfill the MAX_DIFFERENCE_OFFSET_MS criterion
boolean false_start = false; volatile boolean false_start = false; // set to true if a false start occurs (use volatile for all shared variables that deals with hardware)
boolean topbuttonwaspressed = false; volatile uint8_t startsequence_count = 0; // shows thze actual step in the startsquence. Number of steps is defined in STARTSEQ_STEPS (use volatile for all shared variables that deals with hardware)
volatile boolean startsequence_done = false;
boolean topbuttonwaspressed = false; // set to true if the stop button was pressed
timer_state_e timer_state = TIMER_IDLE; // current state needs to be initialized to somethin different then new_state due to the fact that some pieces of the code check for differnt values of state and _new_state to detect an update... timer_state_e timer_state = TIMER_IDLE; // current state needs to be initialized to somethin different then new_state due to the fact that some pieces of the code check for differnt values of state and _new_state to detect an update...
timer_state_e timer_new_state = TIMER_NOCONNECTION; // next state - in the startup phase the first state - will be TIMER_NOCONNECTION ... checking if a connection to TOPSTATION is established timer_state_e timer_new_state = TIMER_NOCONNECTION; // next state - in the startup phase the first state - will be TIMER_NOCONNECTION ... checking if a connection to TOPSTATION is established
@ -171,8 +176,11 @@ void loop(void) {
timer_new_state = TIMER_NOCONNECTION; timer_new_state = TIMER_NOCONNECTION;
} }
else{ else{
// if the offset is claculated switch to IDLE mode ... // if the offset is claculated, cancel not pressed and failstart not pressed switch to IDLE mode ...
if(counter_time_offset > REQUIRED_NUMBER_MEANVALS){ if((time_offset_ok == true) &&
(digitalRead(CANCELBUTTON_IN != CANCELBUTTON_PRESSED)) &&
(digitalRead(FAILSTARTBUTTON_IN != FAILSTARTBUTTON_PRESSED)) )
{
// check if offset is OK - if not .. set state back to INIT // check if offset is OK - if not .. set state back to INIT
timer_new_state = TIMER_IDLE; timer_new_state = TIMER_IDLE;
} }
@ -185,15 +193,17 @@ void loop(void) {
timer_new_state = TIMER_NOCONNECTION; timer_new_state = TIMER_NOCONNECTION;
} }
else{ else{
if(counter_time_offset < REQUIRED_NUMBER_MEANVALS){ if(time_offset_ok == true){
// check if offset is OK - if not .. set state back to INIT // check if offset is OK - if not .. set state back to INIT
timer_new_state = TIMER_INIT; timer_new_state = TIMER_INIT;
} }
else{ else{
// check if the FALSESTATE button is pressed - somebody is ready to run ... // check if the FALSESTATE button is pressed OR we are in trainingsmode - somebody is ready to run, but STARTBUTTON is NOT pressed ...
if(digitalRead(FAILSTARTBUTTON_IN) == FAILSTARTBUTTON_PRESSED){ if(((digitalRead(FAILSTARTBUTTON_IN) == FAILSTARTBUTTON_PRESSED) || (timer_mode == MODE_TRAINING)) &&
(digitalRead(STARTBUTTON_IN) != STARTBUTTON_PRESSED))
{
//wait a few milliseconds to prevent keybouncing - this is a very simplistic method here //wait a few milliseconds to prevent keybouncing - this is a very simplistic method here
delay(10); delay(KEY_BOUNCE_MS);
//read again and check if still active ... //read again and check if still active ...
if(digitalRead(FAILSTARTBUTTON_IN) == FAILSTARTBUTTON_PRESSED){ if(digitalRead(FAILSTARTBUTTON_IN) == FAILSTARTBUTTON_PRESSED){
timer_new_state = TIMER_READY; timer_new_state = TIMER_READY;
@ -203,37 +213,43 @@ void loop(void) {
} }
break; break;
case TIMER_READY: case TIMER_READY:
if(connection_available == false){ if((digitalRead(FAILSTARTBUTTON_IN) != FAILSTARTBUTTON_PRESSED) &&
// if the connection was lost ... switch to noconnection state (timer_mode != MODE_TRAINING))
timer_new_state = TIMER_NOCONNECTION; {
} // false start was released again - go back to INIT ... so far this is not a false start - run was not started yet
else{ timer_new_state = TIMER_INIT;
if(digitalRead(FAILSTARTBUTTON_IN) == FAILSTARTBUTTON_PRESSED){ } else {
// check if the start button was pressed ... there is at least still someone waiting for the run . // check if the start button was pressed ... there is at least still someone waiting for the run .
if(digitalRead(STARTBUTTON_IN) == STARTBUTTON_PRESSED){ if(digitalRead(STARTBUTTON_IN) == STARTBUTTON_PRESSED){
// now enable the interrupt for the FALSESTART button // now enable the interrupt for the FALSESTART button
startsequence_count = 0;
startsequence_done = false;
running_time_offset = mean_time_offset;
false_start = false;
attachInterrupt(digitalPinToInterrupt(FAILSTARTBUTTON_IN), false_start_isr, CHANGE);
// set the startime - this is the current time plus the length of this sequence
start_time = millis() + STARTSEQ_LENGTH_MS;
timer_new_state = TIMER_STARTED; timer_new_state = TIMER_STARTED;
} // call the start sequence interrupt routine ...
} start_isr();
else{
timer_new_state = TIMER_IDLE;
} }
} }
break; break;
case TIMER_STARTED: case TIMER_STARTED:
//initialize the start countdown //initialize the start ISR and the timer interrupt ...
startSequence(); //----> to be removed : startSequence();
if(false_start == false){ if( false_start == true) {
timer_new_state = TIMER_FAIL;
} else {
if(startsequence_done == true){
timer_new_state = TIMER_RUNNING; timer_new_state = TIMER_RUNNING;
} }
else{
timer_new_state = TIMER_FAIL;
} }
break; break;
case TIMER_RUNNING: case TIMER_RUNNING:
noTone(PIEZO_PIN); noTone(PIEZO_PIN);
if(counter_time_offset < REQUIRED_NUMBER_MEANVALS){ if(time_offset_ok != true){
// check if offset is still OK - if not .. set state to TIMER_RUNNING // check if offset is still OK - if not .. set warning
warn_during_run = true; warn_during_run = true;
} }
if(millis() - start_time > TIMER_TIMEOUT){ if(millis() - start_time > TIMER_TIMEOUT){
@ -242,7 +258,6 @@ void loop(void) {
if(digitalRead(CANCELBUTTON_IN) == CANCELBUTTON_PRESSED){ if(digitalRead(CANCELBUTTON_IN) == CANCELBUTTON_PRESSED){
timer_new_state = TIMER_CANCELLED; timer_new_state = TIMER_CANCELLED;
} }
Serial.println(radio_data.topbuttonpressedtime);
if(radio_data.topbuttonpressedtime > running_time_offset){ if(radio_data.topbuttonpressedtime > running_time_offset){
if((radio_data.topbuttonpressedtime - running_time_offset) > start_time){ if((radio_data.topbuttonpressedtime - running_time_offset) > start_time){
run_time = (radio_data.topbuttonpressedtime - running_time_offset) - start_time; run_time = (radio_data.topbuttonpressedtime - running_time_offset) - start_time;
@ -252,7 +267,7 @@ void loop(void) {
break; break;
case TIMER_STOPPED: case TIMER_STOPPED:
//calculate the run_time and switch to WAIT //calculate the run_time and switch to WAIT
delay(10); delay(KEY_BOUNCE_MS);
if(digitalRead(CANCELBUTTON_IN) != CANCELBUTTON_PRESSED){ if(digitalRead(CANCELBUTTON_IN) != CANCELBUTTON_PRESSED){
timer_new_state = TIMER_WAIT; timer_new_state = TIMER_WAIT;
} }
@ -261,7 +276,7 @@ void loop(void) {
//fail start case .... //fail start case ....
failSequence(); failSequence();
run_time = 99999; run_time = 99999;
delay(10); delay(KEY_BOUNCE_MS);
if(digitalRead(CANCELBUTTON_IN) != CANCELBUTTON_PRESSED){ if(digitalRead(CANCELBUTTON_IN) != CANCELBUTTON_PRESSED){
timer_new_state = TIMER_WAIT; timer_new_state = TIMER_WAIT;
} }
@ -269,7 +284,7 @@ void loop(void) {
case TIMER_CANCELLED: case TIMER_CANCELLED:
// what to do in chancel mode ? // what to do in chancel mode ?
run_time = 99999; run_time = 99999;
delay(10); delay(KEY_BOUNCE_MS);
if(digitalRead(CANCELBUTTON_IN) != CANCELBUTTON_PRESSED){ if(digitalRead(CANCELBUTTON_IN) != CANCELBUTTON_PRESSED){
timer_new_state = TIMER_WAIT; timer_new_state = TIMER_WAIT;
} }
@ -277,7 +292,7 @@ void loop(void) {
case TIMER_TIMEDOUT: case TIMER_TIMEDOUT:
// time out // time out
run_time = millis() - start_time; run_time = millis() - start_time;
delay(10); delay(KEY_BOUNCE_MS);
if(digitalRead(CANCELBUTTON_IN) != CANCELBUTTON_PRESSED){ if(digitalRead(CANCELBUTTON_IN) != CANCELBUTTON_PRESSED){
timer_new_state = TIMER_WAIT; timer_new_state = TIMER_WAIT;
} }
@ -286,7 +301,10 @@ void loop(void) {
// disable interrupt if not already done // disable interrupt if not already done
detachInterrupt(digitalPinToInterrupt(FAILSTARTBUTTON_IN)); detachInterrupt(digitalPinToInterrupt(FAILSTARTBUTTON_IN));
// wait until the chancel button was pressed to go ahead // wait until the chancel button was pressed to go ahead
if(digitalRead(CANCELBUTTON_IN) == CANCELBUTTON_PRESSED){ if((digitalRead(CANCELBUTTON_IN) == CANCELBUTTON_PRESSED) &&
(digitalRead(STOPBUTTON_IN) == STOPBUTTON_PRESSED) &&
(digitalRead(FAILSTARTBUTTON_IN) == FAILSTARTBUTTON_PRESSED))
{
timer_new_state = TIMER_IDLE; timer_new_state = TIMER_IDLE;
} }
break; break;
@ -340,7 +358,10 @@ void receive_values(void){
Serial.print(REQUIRED_NUMBER_MEANVALS); Serial.print(REQUIRED_NUMBER_MEANVALS);
Serial.print(F(" values. Mean offset value based on that is: ")); Serial.print(F(" values. Mean offset value based on that is: "));
Serial.println(mean_time_offset); Serial.println(mean_time_offset);
} else {
time_offset_ok = true;
} }
} else { } else {
// the current offset is out of range ... // 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 the values before also already failed the criterion but the max allowed number of such fails is not reached ... just increase the counter.
@ -360,6 +381,7 @@ void receive_values(void){
Serial.print(MAX_DIFFERENCE_OFFSET_MS); Serial.print(MAX_DIFFERENCE_OFFSET_MS);
Serial.print(F(" compared to the mean offset: ")); Serial.print(F(" compared to the mean offset: "));
Serial.println(mean_time_offset); Serial.println(mean_time_offset);
time_offset_ok = false;
counter_time_offset = 0; counter_time_offset = 0;
sum_time_offset = 0; sum_time_offset = 0;
mean_time_offset = 0; mean_time_offset = 0;
@ -524,35 +546,6 @@ void set_state_LEDs(timer_state_e state, boolean warn){
} }
} }
void startSequence(void){
// set the startime - this is the current time plus the length of this sequence
running_time_offset = mean_time_offset;
false_start = false;
attachInterrupt(digitalPinToInterrupt(FAILSTARTBUTTON_IN), false_start_isr, CHANGE);
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(false_start == false){
delay(STARTSEQ_STARTPAUSE_MS);
}
// first tone
if(false_start == false){
tone(PIEZO_PIN, STARTSEQ_TON_1_2_FREQUENCY,STARTSEQ_TON_1_2_LENGTH_MS );
delay(STARTSEQ_TONEPAUSE_MS);
}
//second tone
if(false_start == false){
tone(PIEZO_PIN, STARTSEQ_TON_1_2_FREQUENCY,STARTSEQ_TON_1_2_LENGTH_MS );
delay(STARTSEQ_TONEPAUSE_MS);
}
//third tone
if(false_start == false){
tone(PIEZO_PIN, STARTSEQ_TON_3_FREQUENCY,STARTSEQ_TON_3_LENGTH_MS );
delay(STARTSEQ_TON_3_LENGTH_MS);
}
}
void failSequence(void){ void failSequence(void){
// first tone // first tone
tone(PIEZO_PIN, FAILSEQ_TON_FREQUENCY,FAILSEQ_TON_LENGTH_MS ); tone(PIEZO_PIN, FAILSEQ_TON_FREQUENCY,FAILSEQ_TON_LENGTH_MS );
@ -570,16 +563,33 @@ void false_start_isr(void){
runner_start_time = millis(); runner_start_time = millis();
if(millis() - start_time <= 0){ if(millis() - start_time <= 0){
false_start = true; false_start = true;
noTone(PIEZO_PIN);
Serial.println("** Interrupt service routine detected false_start. Set new state to TIMER_FAIL **"); Serial.println("** Interrupt service routine detected false_start. Set new state to TIMER_FAIL **");
detachInterrupt(digitalPinToInterrupt(FAILSTARTBUTTON_IN)); detachInterrupt(digitalPinToInterrupt(FAILSTARTBUTTON_IN));
} else { } else {
if((timer_state == TIMER_RUNNING) | (timer_new_state == TIMER_RUNNING) ){
// disable this interrupt; // disable this interrupt;
detachInterrupt(digitalPinToInterrupt(FAILSTARTBUTTON_IN)); detachInterrupt(digitalPinToInterrupt(FAILSTARTBUTTON_IN));
} }
} }
void start_isr(void){
// this is the timer interrupt routine that is called during the startsequence
if(startsequence_count < STARTSEQ_STEPS){
// (re)init the interrupt timer ...
Timer1.initialize(STARTSEQ_PAUSE[startsequence_count]);
Timer1.attachInterrupt(start_isr); // startISR to run every given microseconds
// play the tone ...
if(STARTSEQ_NOTES[startsequence_count] > 0 ){
tone( PIEZO_PIN, STARTSEQ_NOTES[startsequence_count],STARTSEQ_DURATION[startsequence_count] );
}
// increase the counter
startsequence_count++;
} else {
// set the done bit and stop and detache the timer1
Timer1.detachInterrupt();
startsequence_done = true;
}
} }