Go Down

Topic: In need of code for 32 relay switching randomly (Read 463 times) previous topic - next topic

josharoymans

Sep 19, 2018, 11:25 am Last Edit: Sep 19, 2018, 11:28 am by josharoymans
I am in need for a code to make my 2x16 relay board randomly switch.

It is for an exhibition in which there will be 32 ceiling lamps suspended from the ceiling in different sizes. In the middle there is a chandelier made of 7 lamps. In the middle (on the floor) there will be a pedestal with a big button.

I want the lamps to be on all the time and when the button is pressed the sequence starts. The following needs to happen:

- lamps are on all the time (relays should be off, passing the current)
- button is pressed; all lamps turn off for 2 seconds
- they start to randomly flash (relays randomly turn on, 0,5 or 1 second on, then off)
- sequence takes 20 seconds, within these 20 seconds the sequence should gradually slow down to 2 seconds a lamp
-  the sequence ends by turning the 7 lamps of the chandelier on till button is pressed again
- after the button is pressed, all relays should turn off again, switching all lights on
- ...etc

I have tried to make the code myself, but I am to noob to make it happen. I have managed to make the relays randomly switch, but only by copying code and altering somethings. Making a button on the timing is to complicated for me. So you will have to start from scratch I guess..

Let me know if you are interested, I will pay (paypall, or a free lampshade) for the code.  

See the attached pictures for the design sketch of the exhibition and the relay boards.

Josha
Studio Josha
josharoymans@gmail.com

wvmarle

So you got all relays act individually? That's a good start.
Are you using a Mega for this? Or port expanders? The Uno doesn't have that many outputs.

Relay off: does that mean the output signal is LOW or HIGH? Normally when you say a relay is "off" I'd assume that the contacts are open and the lights are off.

Basic layout of this sketch is a finite state machine, started by the button press. Time a lamp is on can increase based on the time it's in the sequence - start at 0.5 second on time at 0 seconds, increasing steadily to 2 seconds when the 20 seconds is reached. Or any other form of progress of course, but you have to define it accurately. Also that on time can be randomised, with the limits (min/max) changing over time.

How many lamps may be on at the same time - minimum/maximum? How long should a lamp remain off before it can be switched on again?
Quality of answers is related to the quality of questions. Good questions will get good answers. Useless answers are a sign of a poor question.

josharoymans

So you got all relays act individually? That's a good start.
Are you using a Mega for this? Or port expanders? The Uno doesn't have that many outputs.

Relay off: does that mean the output signal is LOW or HIGH? Normally when you say a relay is "off" I'd assume that the contacts are open and the lights are off.

Basic layout of this sketch is a finite state machine, started by the button press. Time a lamp is on can increase based on the time it's in the sequence - start at 0.5 second on time at 0 seconds, increasing steadily to 2 seconds when the 20 seconds is reached. Or any other form of progress of course, but you have to define it accurately. Also that on time can be randomised, with the limits (min/max) changing over time.

How many lamps may be on at the same time - minimum/maximum? How long should a lamp remain off before it can be switched on again?
Hello MVmarle,

Thanks for you reply.

I am using a Mega.

With relays off I mean that the relay is "signal low", meaning the relay is not activated. Otherwise they have to be on for most of the time (to have my installation with all lights on). I only want the relays on when the sequence is starting, ie; the random flashing.

I think it would be nice that during the sequence the lights switch randomly with a maximum of 4 lights on at the same time.

Reading about "random" I understand that in theory it might flash the same light a few times after each other. So preferably the code would "spread" the randomness.

wvmarle

Hello MVmarle,
That's a new one :)

Quote
I think it would be nice that during the sequence the lights switch randomly with a maximum of 4 lights on at the same time.

Reading about "random" I understand that in theory it might flash the same light a few times after each other. So preferably the code would "spread" the randomness.
Or enforce lights can not go on again for 1 second after they were off. That's easier.

Furthermore I'd rather talk about "light on" or "light off", and know which one relates to a logic HIGH and which one LOW. How the relays are wired is actually irrelevant to the code.

So the sequence as I understand it now (read your OP carefully: it's contradictory in what you want with lights all on or all off or just a group!):
- when idle: a specific set of 7 lights on (your chandelier).
- upon button press: all lights switch off for two seconds.
- random pattern of lights switching on and off for a period of 20 seconds:
  - maximum 4 lights on at the same time (any minimum? or when one switches off, another switches on, so always 4?)
  - lights remain on for a randomised time of 0.5-1 seconds, that time increasing to 2 seconds near the end of the sequence.
- after the 20 seconds: the original 7 get switched on, and we're back to idle state.

Suggestion: increase the number of lights on to 7. Then after the 20 seconds are finished, let the lights that are on complete their 2 seconds, and when done replaced by one of the 7 of the chandelier, until all 7 chandelier lights are on and the sequence is completed. It should look like the lights start to "walk home", preventing an abrupt end.
Or start with 4 lights (I would start by lighting up 1, then after say 0.3 seconds the second, etc - so staggered a bit), increase to 5 at 10 seconds in, 6 at 15 seconds, and add the 7th at 20 seconds, which is when the lights start to "walk home".
Should be a nice little light show.
Quality of answers is related to the quality of questions. Good questions will get good answers. Useless answers are a sign of a poor question.

PieterP

#4
Sep 19, 2018, 04:01 pm Last Edit: Sep 19, 2018, 04:02 pm by PieterP
Here's is my approach. Here's a video of it in action: https://streamable.com/exw07

Code: [Select]
// ------------------------------------------------------------------------------------------------------------- //

constexpr bool ON = HIGH; // define how the pin state relates to the lamp states
constexpr bool OFF = LOW;

// the minimum blink duration in the begining (milliseconds)
constexpr unsigned long minDuration = 1;
// the difference between the minimum and maximum blink duration in the beginning (milliseconds)
constexpr unsigned long variance = 500;
// the blink duration at the end (milliseconds)
constexpr unsigned long maxDuration = 2000;

// ------------------------------------------------------------------------------------------------------------- //

using pin_t = uint8_t;

class RandomlyBlinkingLamp {
  public:
    RandomlyBlinkingLamp() : pin(0) {}
    RandomlyBlinkingLamp(pin_t pin) : pin(pin) {}
   
    void setup() {
      pinMode(pin, OUTPUT);
    }

    void on() {
      digitalWrite(pin, ON);
      interval = 0;
    }

    void off() {
      digitalWrite(pin, OFF);
      interval = 0;
    }

    void startRandomlyBlinking(bool endState) {
      interval = newRandomInterval();
      previousMillis = millis();
      // digitalWrite(pin, interval & 1); // random initial state instead of fade-in from current state
      this->endState = endState;
    }
   
    void loop() {
      if (interval && (millis() - previousMillis >= interval)) {
        previousMillis += interval;
        interval = newRandomInterval();
        if (!interval)
          digitalWrite(pin, endState); // fade out to end state
        else
          toggle();
      }
    }

  private:
    pin_t pin;
    unsigned long interval = 0;
    unsigned long previousMillis = 0;
    bool endState;

    void toggle() {
      digitalWrite(pin, !digitalRead(pin));
    }

    static unsigned long newRandomInterval() {
      unsigned long elapsed = millis() - timerStart;
      if (elapsed >= (timerDuration - maxDuration))
        return 0;
      unsigned long minDelay = map(elapsed, 0, timerDuration - maxDuration, minDuration, maxDuration);
      unsigned long maxDelay = map(elapsed, 0, timerDuration - maxDuration, minDuration + variance, maxDuration);
      unsigned long interval = random(minDelay, maxDelay + 1);
      return interval;
    }

    static unsigned long timerDuration;
    static unsigned long timerStart;

  public:
    static void startTimer(unsigned long duration) {
      timerDuration = duration;
      timerStart = millis();
    }

    static bool timerFinished() {
      return millis() - timerStart >= timerDuration;
    }
};

unsigned long RandomlyBlinkingLamp::timerDuration;
unsigned long RandomlyBlinkingLamp::timerStart;

// ------------------------------------------------------------------------------------------------------------- //

// Change Lamp pin numbers according to your connections
RandomlyBlinkingLamp ceilingLamps[32] = {  3,  4,  5,  6,    7,  8,  9, 10,
                                          11, 12, 13, 14,   15, 16, 17, 18,
                                          19, 20, 21, 22,   23, 24, 25, 26,
                                          27, 28, 29, 30,   31, 32, 33, 34 };
RandomlyBlinkingLamp chandelierLamps[7] = {   35, 36, 37,   38, 39, 40, 41 };

constexpr pin_t buttonPin = 2;

// ------------------------------------------------------------------------------------------------------------- //

void setup() {
  for (RandomlyBlinkingLamp &lamp : ceilingLamps)
    lamp.setup();
  for (RandomlyBlinkingLamp &lamp : chandelierLamps)
    lamp.setup();
  pinMode(buttonPin, INPUT_PULLUP);
}

// ------------------------------------------------------------------------------------------------------------- //

void loop() {
 
  // All lamps on
  for (RandomlyBlinkingLamp &lamp : ceilingLamps)
    lamp.on();
  for (RandomlyBlinkingLamp &lamp : chandelierLamps)
    lamp.on();

  // wait for button press
  while(digitalRead(buttonPin) == LOW); 
  while(digitalRead(buttonPin) == HIGH);

  // All lamps off for 2 seconds
  for (RandomlyBlinkingLamp &lamp : ceilingLamps)
    lamp.off();
  for (RandomlyBlinkingLamp &lamp : chandelierLamps)
    lamp.off();
   
  delay(2000);
 
  // Randomly blink all lamps for 20 seconds, slowing down to 2 seconds interval at the end
  RandomlyBlinkingLamp::startTimer(20000); // milliseconds
  for (RandomlyBlinkingLamp &lamp : ceilingLamps)
    lamp.startRandomlyBlinking(OFF);
  for (RandomlyBlinkingLamp &lamp : chandelierLamps)
    lamp.startRandomlyBlinking(ON);
  while (!RandomlyBlinkingLamp::timerFinished()) {
    for (RandomlyBlinkingLamp &lamp : ceilingLamps)
      lamp.loop();
    for (RandomlyBlinkingLamp &lamp : chandelierLamps)
      lamp.loop();
  }

  // wait for button press
  while(digitalRead(buttonPin) == HIGH);
  while(digitalRead(buttonPin) == LOW); 
  delay(50); // debounce

}


The on/off time of the lights evolves as follows: starting fast, then slowing down to 2 seconds between transitions:


Pieter

josharoymans

Hello Pieter,

Thanks! I am chekking it now. I cant seem to find the button, or where to connect it to my Mega.

Also the code includes 39 lamps correct? In total it should be 32, of which 7 is the chandelier.

On which nr should I connect the button?


PieterP

#6
Sep 19, 2018, 04:48 pm Last Edit: Sep 19, 2018, 04:49 pm by PieterP
I cant seem to find the button, or where to connect it to my Mega.

On which nr should I connect the button?
Edit this line to select the pin of the button:
Code: [Select]
constexpr pin_t buttonPin = 2;

Also the code includes 39 lamps correct? In total it should be 32, of which 7 is the chandelier.
You can just change the pin numbers in the arrays as well, and change the number of elements from 32 to 25.
Code: [Select]
// Change Lamp pin numbers according to your connections
RandomlyBlinkingLamp ceilingLamps[32] = {  3,  4,  5,  6,    7,  8,  9, 10,
                                          11, 12, 13, 14,   15, 16, 17, 18,
                                          19, 20, 21, 22,   23, 24, 25, 26,
                                          27, 28, 29, 30,   31, 32, 33, 34 };
RandomlyBlinkingLamp chandelierLamps[7] = {   35, 36, 37,   38, 39, 40, 41 };

josharoymans

Thank you so much! I play arround with it and got it to work. I will tweek the numbers a bit. I will let you know and post a video soon!

josharoymans

Hi Pieter,

I hooked everything up the right way and it works! The random switching with the 20 seconds slowing down is perfect.

One thing seems wrong: after the sequence the Chandelier is burning (7 lights), when I press the button it turns all the relays off (so all the lamps go on), but when I release the button it restarts the sequence immediately.

I have tried different buttons, but still the same problem.

PieterP

I see. It would be a good idea to use proper debouncing. See attachment.

josharoymans


josharoymans

In the link you will see the end result.

Thank you so much for your help!

Bad Ideas Are Golden

Go Up