Lastest changes ... this versions seems to work again
This commit is contained in:
parent
dfb75de303
commit
6fa6c2c909
4 changed files with 92 additions and 81 deletions
Binary file not shown.
BIN
p14756.db
Normal file
BIN
p14756.db
Normal file
Binary file not shown.
17
speedclock.h
17
speedclock.h
|
@ -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
|
||||
}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_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_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_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 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_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_TON_LENGTH_MS 300
|
||||
|
@ -100,4 +100,5 @@ void startSequence(void);
|
|||
void update_statemessage(timer_state_e timer_state);
|
||||
void failSequence(void);
|
||||
void wait(unsigned long ms);
|
||||
void start_isr(void);
|
||||
#endif
|
||||
|
|
140
speedclock.ino
140
speedclock.ino
|
@ -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 "SSD1306Ascii.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.
|
||||
|
||||
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
|
||||
signed long sum_time_offset = 0; // sum of offset values
|
||||
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 ...
|
||||
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
|
||||
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)
|
||||
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 ...
|
||||
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
|
||||
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
|
||||
boolean false_start = false;
|
||||
boolean topbuttonwaspressed = false;
|
||||
volatile boolean false_start = false; // set to true if a false start occurs (use volatile for all shared variables that deals with hardware)
|
||||
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_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;
|
||||
}
|
||||
else{
|
||||
// if the offset is claculated switch to IDLE mode ...
|
||||
if(counter_time_offset > REQUIRED_NUMBER_MEANVALS){
|
||||
// if the offset is claculated, cancel not pressed and failstart not pressed switch to IDLE mode ...
|
||||
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
|
||||
timer_new_state = TIMER_IDLE;
|
||||
}
|
||||
|
@ -185,15 +193,17 @@ void loop(void) {
|
|||
timer_new_state = TIMER_NOCONNECTION;
|
||||
}
|
||||
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
|
||||
timer_new_state = TIMER_INIT;
|
||||
}
|
||||
else{
|
||||
// check if the FALSESTATE button is pressed - somebody is ready to run ...
|
||||
if(digitalRead(FAILSTARTBUTTON_IN) == FAILSTARTBUTTON_PRESSED){
|
||||
// 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) || (timer_mode == MODE_TRAINING)) &&
|
||||
(digitalRead(STARTBUTTON_IN) != STARTBUTTON_PRESSED))
|
||||
{
|
||||
//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 ...
|
||||
if(digitalRead(FAILSTARTBUTTON_IN) == FAILSTARTBUTTON_PRESSED){
|
||||
timer_new_state = TIMER_READY;
|
||||
|
@ -203,37 +213,43 @@ void loop(void) {
|
|||
}
|
||||
break;
|
||||
case TIMER_READY:
|
||||
if(connection_available == false){
|
||||
// if the connection was lost ... switch to noconnection state
|
||||
timer_new_state = TIMER_NOCONNECTION;
|
||||
}
|
||||
else{
|
||||
if(digitalRead(FAILSTARTBUTTON_IN) == FAILSTARTBUTTON_PRESSED){
|
||||
if((digitalRead(FAILSTARTBUTTON_IN) != FAILSTARTBUTTON_PRESSED) &&
|
||||
(timer_mode != MODE_TRAINING))
|
||||
{
|
||||
// false start was released again - go back to INIT ... so far this is not a false start - run was not started yet
|
||||
timer_new_state = TIMER_INIT;
|
||||
} else {
|
||||
// check if the start button was pressed ... there is at least still someone waiting for the run .
|
||||
if(digitalRead(STARTBUTTON_IN) == STARTBUTTON_PRESSED){
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
else{
|
||||
timer_new_state = TIMER_IDLE;
|
||||
// call the start sequence interrupt routine ...
|
||||
start_isr();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TIMER_STARTED:
|
||||
//initialize the start countdown
|
||||
startSequence();
|
||||
if(false_start == false){
|
||||
//initialize the start ISR and the timer interrupt ...
|
||||
//----> to be removed : startSequence();
|
||||
if( false_start == true) {
|
||||
timer_new_state = TIMER_FAIL;
|
||||
} else {
|
||||
if(startsequence_done == true){
|
||||
timer_new_state = TIMER_RUNNING;
|
||||
}
|
||||
else{
|
||||
timer_new_state = TIMER_FAIL;
|
||||
}
|
||||
break;
|
||||
case TIMER_RUNNING:
|
||||
noTone(PIEZO_PIN);
|
||||
if(counter_time_offset < REQUIRED_NUMBER_MEANVALS){
|
||||
// check if offset is still OK - if not .. set state to TIMER_RUNNING
|
||||
if(time_offset_ok != true){
|
||||
// check if offset is still OK - if not .. set warning
|
||||
warn_during_run = true;
|
||||
}
|
||||
if(millis() - start_time > TIMER_TIMEOUT){
|
||||
|
@ -242,7 +258,6 @@ void loop(void) {
|
|||
if(digitalRead(CANCELBUTTON_IN) == CANCELBUTTON_PRESSED){
|
||||
timer_new_state = TIMER_CANCELLED;
|
||||
}
|
||||
Serial.println(radio_data.topbuttonpressedtime);
|
||||
if(radio_data.topbuttonpressedtime > running_time_offset){
|
||||
if((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;
|
||||
case TIMER_STOPPED:
|
||||
//calculate the run_time and switch to WAIT
|
||||
delay(10);
|
||||
delay(KEY_BOUNCE_MS);
|
||||
if(digitalRead(CANCELBUTTON_IN) != CANCELBUTTON_PRESSED){
|
||||
timer_new_state = TIMER_WAIT;
|
||||
}
|
||||
|
@ -261,7 +276,7 @@ void loop(void) {
|
|||
//fail start case ....
|
||||
failSequence();
|
||||
run_time = 99999;
|
||||
delay(10);
|
||||
delay(KEY_BOUNCE_MS);
|
||||
if(digitalRead(CANCELBUTTON_IN) != CANCELBUTTON_PRESSED){
|
||||
timer_new_state = TIMER_WAIT;
|
||||
}
|
||||
|
@ -269,7 +284,7 @@ void loop(void) {
|
|||
case TIMER_CANCELLED:
|
||||
// what to do in chancel mode ?
|
||||
run_time = 99999;
|
||||
delay(10);
|
||||
delay(KEY_BOUNCE_MS);
|
||||
if(digitalRead(CANCELBUTTON_IN) != CANCELBUTTON_PRESSED){
|
||||
timer_new_state = TIMER_WAIT;
|
||||
}
|
||||
|
@ -277,7 +292,7 @@ void loop(void) {
|
|||
case TIMER_TIMEDOUT:
|
||||
// time out
|
||||
run_time = millis() - start_time;
|
||||
delay(10);
|
||||
delay(KEY_BOUNCE_MS);
|
||||
if(digitalRead(CANCELBUTTON_IN) != CANCELBUTTON_PRESSED){
|
||||
timer_new_state = TIMER_WAIT;
|
||||
}
|
||||
|
@ -286,7 +301,10 @@ void loop(void) {
|
|||
// 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){
|
||||
if((digitalRead(CANCELBUTTON_IN) == CANCELBUTTON_PRESSED) &&
|
||||
(digitalRead(STOPBUTTON_IN) == STOPBUTTON_PRESSED) &&
|
||||
(digitalRead(FAILSTARTBUTTON_IN) == FAILSTARTBUTTON_PRESSED))
|
||||
{
|
||||
timer_new_state = TIMER_IDLE;
|
||||
}
|
||||
break;
|
||||
|
@ -340,7 +358,10 @@ void receive_values(void){
|
|||
Serial.print(REQUIRED_NUMBER_MEANVALS);
|
||||
Serial.print(F(" values. Mean offset value based on that is: "));
|
||||
Serial.println(mean_time_offset);
|
||||
} else {
|
||||
time_offset_ok = true;
|
||||
}
|
||||
|
||||
} 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.
|
||||
|
@ -360,6 +381,7 @@ void receive_values(void){
|
|||
Serial.print(MAX_DIFFERENCE_OFFSET_MS);
|
||||
Serial.print(F(" compared to the mean offset: "));
|
||||
Serial.println(mean_time_offset);
|
||||
time_offset_ok = false;
|
||||
counter_time_offset = 0;
|
||||
sum_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){
|
||||
// first tone
|
||||
tone(PIEZO_PIN, FAILSEQ_TON_FREQUENCY,FAILSEQ_TON_LENGTH_MS );
|
||||
|
@ -570,16 +563,33 @@ void false_start_isr(void){
|
|||
runner_start_time = millis();
|
||||
if(millis() - start_time <= 0){
|
||||
false_start = true;
|
||||
noTone(PIEZO_PIN);
|
||||
Serial.println("** Interrupt service routine detected false_start. Set new state to TIMER_FAIL **");
|
||||
detachInterrupt(digitalPinToInterrupt(FAILSTARTBUTTON_IN));
|
||||
} else {
|
||||
if((timer_state == TIMER_RUNNING) | (timer_new_state == TIMER_RUNNING) ){
|
||||
// disable this interrupt;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
Reference in a new issue