Counting and Timing a shock sensor

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