3d archery pop up system computer replacement

i am working on a 3d archery pop-up system. i am using twelve relays in pins 2-13 and a button in pin 1 they are supposed to run in random cycles of six where when the button is pressed all the relays should be off for ten seconds then one random relay should turn on for between 5-10 seconds then off for 20 seconds this should happen with six relays in random order once six have turned on the other six run in random order and when that's done and the button is pressed again it all starts over. i have done all the wiring and know it works I just cant figure out the programming side and need some help

Welcome to the forum

Your topic has been moved to the Project Guidance category of the forum

What code have you written so far ?

Please post it here and describe the problems that you have

nothing even remotely helpful just turning them on and off i dont know how to generate random numbers and make sure none of them repeat and only go off in sequences of six

There is plenty of discussion on this topic. Use the forum search box to find it.

i have tried this but the problem is the numbers can repeat and i want it to be 1-6 in a random cycle of six without any of the numbers repeating

Again, random numbers without repeats has been discussed many times on this forum, with code examples.

What you really want is an array of all the permutations of 6 possible relays and then a random picking of the array entry.

1 Like

how would i do that

Begin with pencil and paper. Write down all the permutations possible with 6 relays. You can make a two dimension array of 6 bytes times the number of permutations you want. Or you can use a single byte with the bits set to indicate the relay is turned on or off.
Convert your paper list to C code.
If you have not worked with arrays, now is a good time to learn.

Another approach is to generate the permutations on the fly. Start with a six element array initialized 1 to 6, then use the random number generator to pick two random elements to swap, 20 or 30 or 100 times in a row.

As already discussed in several previous Arduino forum posts on this exact topic.

this is what i have come up with, my problem is its still repeating. keep in mind i have only been learning for a few weeks, so try not to be too mean.Use code tags to format code for the forum

#include <Arduino.h>
#include <stdlib.h> 

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 = 1;

const int targetsPerCycle = 6;

const int targetDelay = 3000;

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},  
};

void setup() {
 
  for (int i = 0; i < numRelays; i++) {
    pinMode(relayPins[i], OUTPUT);
    digitalWrite(relayPins[i], LOW); 
  }

  
  pinMode(buttonPin, INPUT_PULLUP);

  randomSeed(analogRead(A0));
}

void loop() {

  if (digitalRead(buttonPin) == LOW) {
    delay(50); 
    if (digitalRead(buttonPin) == LOW) {
      if (systemRunning) {
        
        systemRunning = false;
        for (int i = 0; i < numRelays; i++) {
          digitalWrite(relayPins[i], LOW);
        
      } else {
        
        systemRunning = true;
        currentCycle = 0;
        currentTarget = 0;
      }
    }
  }

  if (systemRunning) {
    bool* currentPermutation = relayStates[currentCycle];

    int previousTarget = (currentCycle * targetsPerCycle + currentTarget - 1 + numRelays) % numRelays;
    digitalWrite(relayPins[previousTarget], LOW);

    bool targetState = currentPermutation[currentTarget];

    digitalWrite(relayPins[currentCycle * targetsPerCycle + currentTarget], targetState);

    delay(targetDelay);

    digitalWrite(relayPins[currentCycle * targetsPerCycle + currentTarget], LOW);

    currentTarget++;

    if (currentTarget >= targetsPerCycle) {

      digitalWrite(relayPins[previousTarget], HIGH);


      shuffleArray(currentPermutation, targetsPerCycle);

      currentCycle++;
      if (currentCycle >= numRelays / targetsPerCycle) {
        currentCycle = 0;
      }

      currentTarget = 0;
    }
  }
}

void shuffleArray(bool* array, int size) {
  for (int i = size - 1; i > 0; i--) {
    int j = random(i + 1);
    bool temp = array[i];
    array[i] = array[j];
    array[j] = temp;
  }
}

Start with much more basic programing. No relays, no other stuff.
Just do your permutations of 12 possible items taken 6 at a time. That would be 12 X 11 X 10 X 9 X 8 X7 and serial print the product. That will be the universe of the number of possible combinations you can have. Will that be enough?

Now how will you decide which one of that number if items will you use for any one of your target display. You notice that "random" you are using it way too small. But how will you decide what that number actually is unless you have a list of those numbers?

could you at least help teach me the 3d system broke on short notice and i have not long to get it up and running for summer

The point is your design is only suitable for a PC, not an Arduino!

@dorcuthe I'm tuning in late.

The code you posted does not compile. I fixed what I hoped was the obvious error.

Now it seems the code steps through the relays in numerical order. And uses a scrambled shuffled array of "do or don't" 1s and 0s.

    bool* currentPermutation = relayStates[currentCycle];
 //
//...
//   
    shuffleArray(currentPermutation, targetsPerCycle);

I will reread, but I thought the idea was to open at random from the first six for six times, then at random from the second six for six times.

I missed that part about sometimes the target slot is skipped, but that's OK. Shuffling that row of the relayStates array makes sense.

It seems like you need a firing order array holding numbers 0 to 5 which you would then pre-shuffle in the same manner. Nice you wrote a function you can reuse. :wink:

Now I have not looked at your shuffle function, let us assume it works and will work the same to actually shuffle the relays that get turned on (maybe).

BTW you have some complicated expressions around turning off any relay that might have been turned on. This can be handled a bit differently:

  • a variable, relayIsOn, initially -1 negative one. No relay is on.
  • whenever you turn on a relay, store the number of the relay that is on.
  • if (when) you want to turn off the relay, check: if relayIsOn is not -1, it is the number of a relay that is on and should be turned off

Just an idea. Less code to read, fewer places for errors and so forth.

a7

thank you for the feed back i have to be honest the last month or so of watching youtube videos to learn c++ has been the most excrutiating experience and i would love to hear more about how i can get this to work

Don't wait up for me, I'm still at the beach. But it should be straight forward, if I have anything left I'll look closer L8R.

I'll reread your specifications, no doubt I'll have pesky some questions.

a7

I added some changes per @alto777 and placed the code in the simulator.


Wokwi_badge archery pop up system


// https://wokwi.com/projects/369410932236902401
// https://forum.arduino.cc/t/3d-archery-pop-up-system-computer-replacement/1144336

# 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 = 800;  // 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");

  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();
}

void loop() {

  if (digitalRead(buttonPin) == LOW) {
    delay(50); 
    if (digitalRead(buttonPin) == LOW) {
      if (systemRunning) {
        
        systemRunning = false;
        for (int i = 0; i < numRelays; i++)
          digitalWrite(relayPins[i], LOW);
        
      } else {
        
        systemRunning = true;
        currentCycle = 0;
        currentTarget = 0;
      }
    }
  }

  if (systemRunning) {
    bool* currentPermutation = relayStates[currentCycle];

    bool targetState = currentPermutation[currentTarget];

    unsigned char pinIndex = currentCycle * targetsPerCycle + targetList[currentTarget];

    digitalWrite(relayPins[pinIndex], targetState, " on or not ");

    delay(targetDelay);

    digitalWrite(relayPins[pinIndex], LOW,  " off in any case ");

    currentTarget++;

    if (currentTarget >= targetsPerCycle) {

      shuffleArray(currentPermutation, targetsPerCycle);
      shuffleTargetList();

      currentCycle++;
      if (currentCycle >= numRelays / targetsPerCycle) {
        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();
}

It does what I want, I have no idea if it is what you want.

a7

i apreciate the effort but when i uploaded this code to my arduino mega 2560 it did not do anything.

Compiles, uploads and does nothing.

So it did not print "Jello Whirled!"?

I don't see anything that would make it work on an UNO and not work on a Mega.

Does the code do what you want in the simulator? I'm totally willing to give up on this!

a7