That was my original thinking. How do you do that in Arduino-land ? I was worried the “no_interrupts” (you see commented out) would prohibit other stuff from running.
detachInterrupt
Right now I am just spitting out code into the Arduino editor making sure it compiles. I don’t think storing split times is a bad idea. I’ll see if I can work it in.
Right now I have defined 5 states. INIT, READY, ARMING, RUNNING and REVIEW. I am currently coding the review state where you can set number of shooters. I’ll post that up if there is a desire to test early code. Might be good because I can’t assemble this hardware at home.
Edit: preliminary code. Won’t do anything after a long press of start
#include <LiquidCrystal.h>
// Enable debugging code
#define DEBUG
LiquidCrystal *lcd;
// set pin numbers
const int StartPin = 7; // the number of the Start pushbutton pin
const int TargetAPin = 2; // the number of the A targets input pin
const int TargetBPin = 3; // the number of the B targets input pin
const int BuzzerPin = 10; // the number of the buzzer output pin
const int LEDPin = 13; // the number of the LED output pin
const int ScrollPin = 6; // the number of the scroll button input pin
//const int ButtonInPin = A0; // the pin used for the analog buttons
// initialize the constants
const unsigned long MaxTime = 30000; // the max time the timer can run for = 30 secs
const unsigned long WaitTime = 2000; // wait time btw start and timer running = 2 secs plus debounce
const unsigned long DB_delay = 1000; // set a debounce wait time of 1000 msecs
const unsigned long BuzzTime5 = 500; // set the on time for the buzzer, 500 msecs
const unsigned long BuzzTime2 = 200; // set the on time for the buzzer, 200 msecs
const unsigned long BuzzTime10 = 1000; // set the on time for the buzzer, 1000 msecs
const unsigned int FreqHi = 2000; // High frequency of buzzer tone
const unsigned int FreqLo = 1000; // Low frequency of buzzer tone
const byte MaxHits = 10; // Maximum number if hits allowed
const unsigned long LCDtime = 100; // Set min time btw writes to LCD to 100 msecs
// initialize global variables
volatile byte TimerState = 0; // variable for state of timer, running or not running
volatile byte AupDtFlag = 0; // variable indication an A hit has occurred
volatile byte BupDtFlag = 0; // variable indication a B hit has occurred
byte DisplayIndex = 0; // variable for controlling what's displayed
unsigned long StartTime = 0; // variable to hold the start time
unsigned long BuzzTime = 500; // variable to hold the buzzer on time
unsigned int Freq = 2000; // variable for high or low buzzer tone
volatile byte A_count = 0; // variable to hold the number of A hits
volatile byte B_count = 0; // variable to hold the number of B hits
volatile long A_Times[MaxHits]; // array to hold up to MaxHits hit times for target A
volatile long B_Times[MaxHits]; // array to hold up to MaxHits hit times for target B
unsigned long A_splits[MaxHits];
unsigned long B_splits[MaxHits];
long AB_splits[MaxHits];
unsigned long LastTime = 0; // initialize last LCD display time to zero for 1st pass
float A_Hit_Factor = 0;
float B_Hit_Factor = 0;
byte S1 = 0; // Switch 1 init to zero
byte S2 = 0; // Switch 2 init to zero
unsigned int diMin = 0; // Display index mininmim
unsigned int diMax = 99; // Display index maximum
unsigned int TimerMode = 0; // initialize the mode to be single shooter
volatile int secs = 0;
volatile int frac = 0;
// char time[ ] = " ";
// char buffer[7]; // save 7 empty spaces
// Strings for formatting
char *hitCount = "^: #hits = ^";
char *hitTime = "Hit time = ^";
char *hitSplit = "Split time = ^";
// Mode enumeration
enum state { INIT, READY, ARMING, RUNNING, REVIEW };
enum mode { ONEPLAYER, TWOPLAYER };
enum readyState { MAIN_MENU, PLAYER_SELECT};
enum state currentState;
enum readyState readyState = MAIN_MENU;
int numShooters = 1;
void setup()
{
// Initialization state
currentState = INIT;
// The LCD display and associated pins
lcd = new LiquidCrystal(12, 11, 5, 4, 9, 8);
// Initialize the LCD
// 20 columns and 4 rows
lcd->begin(20, 4);
// Display a start up message while unit is initialized
// Wait 5 seconds at the end to make sure the message is visible
lcd->clear();
lcd->print(" Shot Timer 1 ");
lcd->setCursor(0, 1);
lcd->print(" Initializing ");
delay(5000);
// Set the data direction of output pins
// Initialize the values to low
pinMode(BuzzerPin, OUTPUT);
pinMode(LEDPin, OUTPUT);
digitalWrite(BuzzerPin, LOW);
digitalWrite(LEDPin, LOW);
// Set the input pins and turn on pull-up resistors
pinMode(StartPin, INPUT);
pinMode(TargetAPin, INPUT);
pinMode(TargetBPin, INPUT);
digitalWrite(StartPin, HIGH);
digitalWrite(TargetAPin, HIGH);
digitalWrite(TargetBPin, HIGH);
#ifdef DEBUG
// Diagnostic information to be sent to PC over Serial
Serial.begin(9600);
Serial.print("Shot Timer v1 Ready...");
#endif
// Set display to ready
lcd->setCursor(0, 1);
lcd->print(" Ready ");
delay(5000);
// All initialization finished, set state to ready
currentState = READY;
}
void loop()
{
int startCycles = 0;
switch(currentState)
{
case INIT: // Do nothing in this state, we should never be here
break;
case READY: // Wait for the start button to be pressed and the mode selected
// Check if the button is down, if so increment the counter
if( digitalRead(StartPin) )
{
startCycles++;
} else {
startCycles = 0;
}
delay(100);
readyMenu();
if(startCycles >= 10) // Button was held 1+ seconds, move to arming
{
startCycles = 0;
currentState = ARMING;
tone(BuzzerPin, 1000, 100);
lcd->noBlink();
break;
}
if(startCycles >= 2)
{
if( digitalRead(StartPin) ) // Don't do anything if the button is still down
break;
if(numShooters == 1) // Toggle number of shooters
numShooters = 2;
else
numShooters = 1;
tone(BuzzerPin, 2000, 100);
startCycles = 0;
}
break;
case ARMING: // Enable interrupts, set random start time, turn LED on, when countdown expires sound buzzer
break;
case RUNNING: // Update display on a hit
break;
case REVIEW: // Disable interrupts, change to review mode
break;
}
}
void readyMenu()
{
switch(readyState)
{
case MAIN_MENU: // Select number of shooters, short press toggles between 1 and 2
lcd->setCursor(0, 1);
lcd->print("To start,hold 1 sec");
lcd->setCursor(0, 2);
lcd->print("Number of shooters:");
lcd->setCursor(0, 3);
lcd->print(numShooters);
lcd->blink();
}
}
Dan