// https://wokwi.com/projects/369512449443396609
// https://forum.arduino.cc/t/3d-archery-pop-up-system-computer-replacement/1144336
// updated from the posted version here all functions functioning in a way
# include <Adafruit_NeoPixel.h>
# define PIN A2 // the pin
# define NPIXELS 12 // number of LEDs on strip
Adafruit_NeoPixel relayRing(NPIXELS, PIN, NEO_GRB + NEO_KHZ800);
const int relayPins[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
const int numRelays = sizeof(relayPins) / sizeof(relayPins[0]);
const int buttonPin = A0;
const int targetsPerCycle = 6;
unsigned char targetList[targetsPerCycle] = {0, 1, 2, 3, 4, 5};
//const int targetDelay = 3000; // life too short
const int targetDelay = 777; // life too short
int currentCycle = 0;
int currentTarget = 0;
bool systemRunning = false;
bool relayStates[numRelays][targetsPerCycle] = {
// {1, 0, 1, 0, 1, 0},
// {0, 1, 0, 1, 0, 1},
// every target for now
{1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1},
};
void digitalWrite(unsigned char pin, unsigned char val, char *msg)
{
Serial.print(msg);
Serial.print(pin);
Serial.print(" goes ");
Serial.println(val ? "HIGH" : "LOW");
digitalWrite(pin, val);
relayRing.setPixelColor(pin - 2, val ? 0xff0000 : 0x008080);
relayRing.show();
}
void setup() {
Serial.begin(115200);
Serial.println("Jello Whirled!\n");
// Serial.println("now rasing only five targets, premature COLLECT");
relayRing.begin();
relayRing.clear();
relayRing.show();
for (int i = 0; i < numRelays; i++) {
pinMode(relayPins[i], OUTPUT);
digitalWrite(relayPins[i], LOW);
}
pinMode(buttonPin, INPUT_PULLUP);
// randomSeed(analogRead(A1)); // later - for now it is good to have the same sequence
// shuffleTargetList(); // or don't. first six would be 0..5 then
}
# define PRESST LOW
unsigned long now; // time for all time for everyone
void loop() {
now = millis();
doButton();
if (systemRunning)
moveTargetAlong();
}
// return; when testing the button logic
// otherwise, it's show time:
enum {IDLE = 0, UP, PAUSE, UP2, PAUSE2, COLLECT};
char *tags[6] = {"_idle", "_up", "_pause", "_up2", "_pause2", "_collect"};
unsigned char tState = IDLE;
unsigned long gTimer;
unsigned int dwell;
bool *currentPermutation;
bool targetState = currentPermutation[currentTarget];
unsigned char pinIndex;
# define UPFOR targetDelay // ms target is up, from before right?
# define TWEEN 997 // ms between target lifts
# define GRAB 3456 // ms to grab arrows
# define NEXT6 4567 // ms until next 6 targets
# define ARROWP 4900 // ms delay after round of 6
void moveTargetAlong()
{
// when it goes bad:
// delay(333); Serial.print("state "); Serial.print(tState); Serial.print(" "); Serial.println(tags[tState]);
// IDLE - time to put up a next target
// UP - wait while target is up
// PAUSE - target(s) down and wait
// ALLUP - after 6 targets, raise them and
// WAIT - time out a period for arrow collect
// static unsigned char collectFleg; // see that 6 have gone by and collect the arrows.
static int currentlyUp = -1;
static unsigned long lastFSMTime;
// if (gTimer && (now - gTimer < dwell)) return;
// time to step this along?
// if (gTimer && (now - gTimer < dwell))
if (now - gTimer < dwell)
return;
Serial.print("action @ ");
Serial.print(now); Serial.print(" () ");
Serial.print(now - lastFSMTime);
Serial.print(" "); Serial.println(tags[tState]);
lastFSMTime = now;
switch (tState) {
case IDLE :
currentPermutation = relayStates[currentCycle];
targetState = currentPermutation[currentTarget];
pinIndex = currentCycle * targetsPerCycle + targetList[currentTarget];
if (!targetState) Serial.println(" skipping! ");
digitalWrite(relayPins[pinIndex], targetState, " target up or not ");
currentlyUp = relayPins[pinIndex];
tState = UP;
gTimer = now;
dwell = UPFOR;
// also advance globals for next target
currentTarget++;
if (currentTarget >= targetsPerCycle) {
// collectFleg = 1; // end of siz targets, collect arrows.
tState = UP2;
shuffleArray(currentPermutation, targetsPerCycle);
shuffleTargetList();
currentCycle++;
if (currentCycle >= numRelays / targetsPerCycle) {
currentCycle = 0;
}
currentTarget = 0;
}
break;
case UP :
Serial.println("time to put target down and go to pause");
if (currentlyUp != -1)
digitalWrite(currentlyUp, LOW, " target def down ");
tState = PAUSE;
gTimer = now;
dwell = TWEEN;
break;
case PAUSE :
Serial.println("pause done -> IDLE");
tState = IDLE;
gTimer = now;
dwell = 0; // right away, 'K?
break;
case UP2 :
Serial.println("time to put target down and go to pause");
if (currentlyUp != -1)
digitalWrite(currentlyUp, LOW, " target def down ");
tState = PAUSE2;
gTimer = now;
dwell = ARROWP;
break;
tState = COLLECT;
gTimer = now;
dwell = GRAB;
break;
case PAUSE2 :
tState = COLLECT;
gTimer = now;
dwell = GRAB;
Serial.println(" raise targets that might have an arrow ");
for (int i = 0; i < numRelays; i++) { // or all of them for now
digitalWrite(relayPins[i], HIGH);
relayRing.setPixelColor(i, 0xffff00);
}
relayRing.show();
break;
case COLLECT :
tState = PAUSE;
gTimer = now;
dwell = NEXT6;
// lower the rasied targets, or all of them really why not?
for (int i = 0; i < numRelays; i++) {
digitalWrite(relayPins[i], LOW);
relayRing.setPixelColor(i, 0x008080);
}
relayRing.show();
Serial.println(" hope you got them all");
break;
default : // "can't" happen
Serial.println("Rotten Denmark!"); Serial.flush();
for (; ; );
break;
}
}
// control systemRunning and manage starting and stopping
void doButton()
{
static unsigned long lastButtonTime;
static unsigned char lastButton = PRESST;
unsigned char thisButton = digitalRead(buttonPin);
if (now - lastButtonTime > 25) {
if (thisButton != lastButton) {
lastButton = thisButton;
lastButtonTime = now;
if (thisButton == PRESST) {
if (systemRunning) {
Serial.println(" system not running.");
systemRunning = false;
for (int i = 0; i < numRelays; i++)
digitalWrite(relayPins[i], LOW);
} else {
Serial.println(" system running.");
systemRunning = true;
currentCycle = 0;
currentTarget = 0;
}
}
}
}
}
void shuffleArray(bool* array, int size) {
Serial.println(" s h u f f l e ");
for (int i = size - 1; i > 0; i--) {
int j = random(i + 1);
bool temp = array[i];
array[i] = array[j];
array[j] = temp;
}
for (int i = 0; i < size; i++) {
Serial.print(array[i]);
Serial.print(" ");
}
Serial.println();
}
void shuffleTargetList()
{
int size = 6;
Serial.println(" target list ");
for (int i = size - 1; i > 0; i--) {
int j = random(i + 1);
unsigned char temp = targetList[i];
targetList[i] = targetList[j];
targetList[j] = temp;
}
for (int i = 0; i < size; i++) {
Serial.print(targetList[i]);
Serial.print(" ");
}
Serial.println();
}