#include <Servo.h>
enum states
{
WAITING_FOR_INPUT,
REVEAL_TARGET,
SHOWING_TARGET,
HIDE_TARGET,
HIDING_TARGET,
ALL_UP,
ALL_STOP,
PAUSED // currently not used
};
struct servoData
{
Servo theServo; // Servo object
byte pinNumber; // pin number used by the servo
byte up; // value written to the servo to move the target up
byte down; // value written to the servo to move the target down
};
const byte numberOfServos = 9; // number of servos attached
servoData servos[numberOfServos]; // declare an array of servo data
byte currentState;
const int buttonPin_runPin = A0; // the pins that the pushbuttons are attached to
const int buttonPin_upPin = A1;
const int buttonPin_stopPin = A2;
const int buttonPin_pausedPin = A3; // NOTE- currently not used
unsigned long stateStartTime;
byte randomServoNum;
byte shownCount; // count of targets shown in the session
const byte numberToShow = 10; // number of targets to show in a session
const unsigned long showPeriod = 300; // milliseconds to show target
const unsigned long hidePeriod = 1000; // milliseconds to hide target
unsigned long currentTime;
const int ledPin = 13; // built in led pin number
const int ledPin_active = 11; // target active led indicator
void setup()
{
Serial.begin(115200); // serial print baud rate
pinMode(ledPin, OUTPUT); // pin 13 built in led
pinMode (ledPin_active, OUTPUT); // target running light
pinMode (buttonPin_runPin, INPUT_PULLUP); // RF button inputs
pinMode (buttonPin_upPin, INPUT_PULLUP);
pinMode (buttonPin_stopPin, INPUT_PULLUP);
pinMode (buttonPin_pausedPin, INPUT);
setServoData(); // function to get servo data
initServos(); // function to attach servos and set start positions to target down
currentState = WAITING_FOR_INPUT; // start in this state
Serial.println("in state WAITING_FOR_INPUT");
}
void loop()
{
random(numberOfServos); // make random servo selection later more variable
currentTime = millis(); // time stamp in milliseconds
if (digitalRead(buttonPin_upPin) == LOW)
{
currentState = ALL_UP; // puts all targets in up position
}
else if (digitalRead(buttonPin_stopPin) == LOW)
{
currentState = ALL_STOP; // puts all targets in up position
}
if (digitalRead(buttonPin_runPin) == LOW) // starts target sequence
{
currentState = REVEAL_TARGET;
shownCount = 0; // initialise the number of targets shown in the session
}
switch (currentState) // change state depending on inputs
{
case WAITING_FOR_INPUT:
break;
case REVEAL_TARGET: // choose a target at random and show it
initServos(); // start with all targets down
shownCount++;
digitalWrite(ledPin, !digitalRead(ledPin));
digitalWrite(11, HIGH);
randomServoNum = random(0, numberOfServos); // pick a servo
servos[randomServoNum].theServo.write(servos[randomServoNum].up); // reveal the target
Serial.print("\nrevealing target number ");
Serial.println(randomServoNum);
Serial.print("target will be shown for ");
Serial.println(showPeriod);
Serial.print("shownCount = ");
Serial.println(shownCount);
currentState = SHOWING_TARGET;
Serial.println("moving to SHOWING_TARGET");
stateStartTime = currentTime;
break;
case SHOWING_TARGET: // stay in this state until the show period ends (does not block loop())
if (currentTime - stateStartTime >= showPeriod) // if the show period has ended
{
currentState = HIDE_TARGET; // hide the target
// stateStartTime = currentTime;
Serial.println("moving to HIDE_TARGET");
Serial.print("target will be hidden for ");
Serial.println(hidePeriod);
}
break;
case HIDE_TARGET: // hide the target
digitalWrite(ledPin, !digitalRead(ledPin));
Serial.print("hiding target number ");
Serial.println(randomServoNum);
servos[randomServoNum].theServo.write(servos[randomServoNum].down); // hide the target
Serial.println("moving to HIDING_TARGET");
Serial.print("target will be hidden for ");
Serial.println(hidePeriod);
currentState = HIDING_TARGET;
stateStartTime = currentTime;
break;
case HIDING_TARGET: // stay in this state until the hide period ends (does not block loop())
if (currentTime - stateStartTime >= hidePeriod) // if the hide period has ended
{
if (shownCount >= numberToShow) // if the target session is over
{
Serial.println("Target session ended. Moving to state WAITING_FOR_INPUT");
digitalWrite(11, LOW); // active led indicator on
currentState = WAITING_FOR_INPUT; // go back to waiting for input
}
else // otherwise reveal anothe target
{
currentState = REVEAL_TARGET;
}
}
break;
case ALL_UP: // move all targets up
Serial.println("in state ALL_UP");
for (int servoNum = 0; servoNum < numberOfServos; servoNum++)
{
servos[servoNum].theServo.write(servos[servoNum].up);
Serial.print("\tservo ");
Serial.print(servoNum);
Serial.println(" moved up");
}
currentState = WAITING_FOR_INPUT;
break;
case ALL_STOP:
Serial.println("in state ALL_STOP");
for (int servoNum = 0; servoNum < numberOfServos; servoNum++)
{
servos[servoNum].theServo.write(servos[servoNum].down);
Serial.print("\tservo ");
Serial.print(servoNum);
Serial.println(" moved down");
}
currentState = WAITING_FOR_INPUT;
break;
}
}
void initServos() // attach all servos and move targets down
{
for (int s = 0; s < numberOfServos; s++)
{
servos[s].theServo.write(servos[s].down); // start with all targets down
servos[s].theServo.attach(servos[s].pinNumber);
}
}
void setServoData() // set up data for all servos
{
servos[0].pinNumber = 2;
servos[0].up = 180;
servos[0].down = 0;
servos[1].pinNumber = 3;
servos[1].up = 180;
servos[1].down = 0;
servos[2].pinNumber = 4;
servos[2].up = 180;
servos[2].down = 0;
servos[3].pinNumber = 5;
servos[3].up = 180;
servos[3].down = 0;
servos[4].pinNumber = 6;
servos[4].up = 180;
servos[4].down = 0;
servos[5].pinNumber = 7;
servos[5].up = 180;
servos[5].down = 0;
servos[6].pinNumber = 8;
servos[6].up = 180;
servos[6].down = 0;
servos[7].pinNumber = 9;
servos[7].up = 180;
servos[7].down = 0;
servos[8].pinNumber = 10;
servos[8].up = 180;
servos[8].down = 0;
}