Using Arduino to light LED's randomly

I have a model railroad building that I fitted with a load of LED's, and can make each of them turn on and off sequentially, and can specify a time each stays on.

What I want to do is to get them to turn on and off randomly for between a couple of minutes and half an hour. Looking here /https://docs.arduino.cc/language-reference/en/functions/random-numbers/random/I think I can use the " random(min, max)" function to do this by defining 120000ms and 1800000ms as the min and max values.

I believe that would be easy to do sequentially but I want the lights to come on randomly simultaneously, if you see what I mean - sorry guys, I'm not finding the right words to explain so hope you get what I want to do.

Is what I am asking possible?

Do you mean that sets of or all the leds should get the same timing?
You could define an array of led numbers to get the same random on/off times instead of individual leds. If the first number in the array (arry[0]) held the array length then one function could handle different arrays when passed a pointer to the array to handle. The name of the array is a pointer to the start of the array.

void func( unsigned long *arr,  unsigned long interval ) 
{ 
  for ( int i = 1; i < arr[0]; i++ )
  { 
    arr[ i ] = interval;
  }
}

maybe even put the random inside of func() instead of passing interval.

1 Like

Remember to calculate the total current needed for the number of LEDs turned on,

1 Like

Take a look here: LED lighting and sound effects for modelers and miniaturists, under the "House and Building Lighting" section.

Edit: and I picked up a non mbed version that I'll be darned if I can remember where it came from. It's included below.

//LED House Lighting effect with flickering TV and room lights randomly changing

#define tvPin 9
#define roomPin 8
#define room2Pin 7
#define porchPin 6
#define firePin 5
#define welderPin 3
#define fireRedPin 10
#define fireGreenPin 11

// analogWrite is available on  pins 3, 5, 6, 9, 10, and 11
class Flame {
 public:
   void setup(int pin, int alpha = 20, int update = 100);
   void flicker(void);

 private:
   int _pin;
   int _brightness = 0;  // soft start
   int _oldBrightness = 0;
   int _updateDelay;
   unsigned long _nextUpdate;
   int _alpha;  // filter coefficient (0..100). Low means slow changes
};

void Flame::setup(int pin, int alpha, int update) {
   constrain(alpha, 0, 100);
   _pin = pin;
   _alpha = alpha;
   _updateDelay = update;
   // random first upate to prevent multiple flames looking synchronous
   _nextUpdate = millis() + random(_updateDelay);
}

void Flame::flicker(void) {
   if( millis() >= _nextUpdate ) {
      _nextUpdate += _updateDelay;
      _brightness = random(0, 255);
      // low pass filter the brightness changes
      _brightness = (_alpha * _brightness + (100 - _alpha) * _oldBrightness) / 100;
      _oldBrightness = _brightness;
      analogWrite(_pin, _brightness);
   }
}

class BicolourFlame {
 public:
   void setup(int redPin, int greenPin, int alpha = 20, int update = 100);
   void flicker(void);

 private:
   int _redPin;
   int _greenPin;
   int _redBrightness = 0;    // soft start
   int _greenBrightness = 0;  // soft start
   int _oldRedBrightness = 0;
   int _oldGreenBrightness = 0;
   int _updateDelay;
   unsigned long _nextUpdate;
   int _alpha;  // filter coefficient (0..100). Low means slow changes
};

void BicolourFlame::setup(int redPin, int greenPin, int alpha, int update) {
   constrain(alpha, 0, 100);
   _redPin = redPin;
   _greenPin = greenPin;
   _alpha = alpha;
   _updateDelay = update;
   // random first upate to prevent multiple flames looking synchronous
   _nextUpdate = millis() + random(_updateDelay);
}

void BicolourFlame::flicker(void) {
   if( millis() >= _nextUpdate ) {
      _nextUpdate += _updateDelay;
      _redBrightness = random(0, 255);
      // low pass filter the brightness changes
      _redBrightness = (_alpha * _redBrightness + (100 - _alpha) * _oldRedBrightness) / 100;
      _oldRedBrightness = _redBrightness;
      _greenBrightness = random(0, _redBrightness);
      // low pass filter the brightness changes
      _greenBrightness = (_alpha * _greenBrightness + (100 - _alpha) * _oldGreenBrightness) / 100;
      _oldGreenBrightness = _greenBrightness;
      analogWrite(_redPin, _redBrightness);
      analogWrite(_greenPin, _greenBrightness);
   }
}

class TV {
 public:
   void setup(int pin, int update = 50);
   void update(void);

 private:
   int _pin;
   int _brightness = 0;
   int _updateDelay;
   unsigned long _nextUpdate;
};

void TV::setup(int pin, int update) {
   _pin = pin;
   _updateDelay = update;
   _nextUpdate = millis() + random(_updateDelay);
}

void TV::update(void) {
   if( millis() >= _nextUpdate ) {
      _nextUpdate += _updateDelay;
      _brightness += random(128) - 64;
      if( _brightness < 0 || _brightness > 255 ) {
         _brightness = random(256);
      }
      analogWrite(_pin, _brightness);
   }
}
class Welder {
 public:
   void setup(int pin, int update = 20);
   void update(void);

 private:
   int _pin;
   int _brightness = 0;
   int _updateDelay;
   unsigned long _nextUpdate;
};

void Welder::setup(int pin, int update) {
   _pin = pin;
   _updateDelay = update;
   _nextUpdate = millis() + random(_updateDelay);
}

void Welder::update(void) {
   if( millis() >= _nextUpdate ) {
      // random pause between welds
      if( random(10000) > 9925 ) {
         _nextUpdate += 1000 + random(5000);
         analogWrite(_pin, 0);
      } else {
         _nextUpdate += _updateDelay;
         float x = random(1000) / 1000.0;
         // some exponential brightness scaling
         // for more of a fast flash effect
         analogWrite(_pin, (int)(256 * x * x * x));
      }
   }
}

class Room {
 public:
   void setup(int pin, int pct = 1, int update = 300);
   void update(void);

 private:
   bool isDark(void);
   int _pin;
   int _pct;
   int _updateDelay;
   unsigned long _nextUpdate;
};

void Room::setup(int pin, int pct, int update) {
   _pin = pin;
   pinMode(_pin, OUTPUT);
   constrain(pct, 0, 100);
   _pct = pct;
   if( _pct == 0 ) {
      digitalWrite(_pin, HIGH);
   }
   _updateDelay = update;
   _nextUpdate = millis() + random(_updateDelay);
}

void Room::update(void) {
   if( millis() >= _nextUpdate ) {
      _nextUpdate += _updateDelay;
      if( isDark() ) {
         if( random(100) < _pct ) {
            digitalWrite(_pin, !digitalRead(_pin));
         } else if( _pct == 0 ) {
            digitalWrite(_pin, HIGH);
         }
      } else {
         digitalWrite(_pin, LOW);
      }
   }
}

bool Room::isDark(void) {
   return analogRead(A0) > 768;
}

Flame flame;
BicolourFlame bicolourFlame;
TV tv;
Welder welder;
Room room;
Room room2;
Room porch;

void setup(void) {
   flame.setup(firePin, 66);
   bicolourFlame.setup(fireRedPin, fireGreenPin, 50);
   tv.setup(tvPin);
   welder.setup(welderPin);
   room.setup(roomPin, 2);
   room2.setup(room2Pin, 1);
   porch.setup(porchPin, 0);
}

void loop(void) {
   flame.flicker();
   bicolourFlame.flicker();
   tv.update();
   welder.update();
   room.update();
   room2.update();
   porch.update();
}
1 Like

Nice link, thanks!

Let me take a look at it all and see if it does what I was thinking of

Hello shauntherailroadguy

Take a view to this small and simple LED timer switch.
The configuration is made here:

//------snip

// configure the Led Timer System here
constexpr uint8_t OutputPins[] {9, 10, 11, 12};
constexpr uint32_t RandomsTimes[sizeof(OutputPins)][2]
{
  {1000, 2000}, // min/max random time @ led 1
  {2000, 3000}, // min/max random time @ led 2
  {3000, 4000}, // min/max random time @ led 3
  {4000, 5000}, // min/max random time @ led 4
};
//-----------------------------------------

// -- snip

and the complete sketch:

//https://forum.arduino.cc/t/using-arduino-to-light-leds-randomly/1357654/1
//https://europe1.discourse-cdn.com/arduino/original/4X/7/e/0/7e0ee1e51f1df32e30893550c85f0dd33244fb0e.jpeg
#define ProjectName "Using Arduino to light LED's randomly"
#define NotesOnRelease "Arduino MEGA tested"
// make names
enum TimerEvent {NotExpired, Expired};
enum TimerControl {Halt, Run};
enum OnOff {Off, On};
enum MinMax {Min, Max};
// make variables
uint32_t currentMillis = millis();
//-----------------------------------------
// configure the Led Timer System here
constexpr uint8_t OutputPins[] {9, 10, 11, 12};
constexpr uint32_t RandomsTimes[sizeof(OutputPins)][2]
{
  {1000, 2000}, // min/max random time @ led 1
  {2000, 3000}, // min/max random time @ led 2
  {3000, 4000}, // min/max random time @ led 3
  {4000, 5000}, // min/max random time @ led 4
};
//-----------------------------------------
// make structures
//-----------------------------------------
struct TIMER
{
  uint32_t interval;
  uint16_t control;
  uint32_t now;
  uint8_t expired(uint32_t currentMillis)
  {
    uint8_t timerEvent = currentMillis - now >= interval and control;
    if (timerEvent == Expired) now = currentMillis;
    return timerEvent;
  }
};
//-----------------------------------------
struct LEDTIMERSWITCH
{
  uint8_t pin;
  uint32_t tMin;
  uint32_t tMax;
  TIMER dimmer;
  void make(uint8_t pin_, uint32_t tMin_, uint32_t tMax_)
  {
    pin = pin_;
    tMin = tMin_;
    tMax = tMax_;
    Serial.print("LED test @ pin "), Serial.print(pin);
    pinMode (pin, OUTPUT);
    digitalWrite(pin, On);
    delay(1000);
    digitalWrite(pin, Off);
    delay(1000);
    Serial.println(" done");
    dimmer.control = Run;
    dimmer.interval = random(tMin, tMax);

  }
  void run ( uint32_t currentMillis)
  {
    if (dimmer.expired(currentMillis) == Expired)
    {
      dimmer.interval = random(tMin, tMax);
      digitalWrite(pin, digitalRead(pin) ? Off : On);
    }
  }
};
LEDTIMERSWITCH ledTimerSwitches[sizeof(OutputPins)];
//-----------------------------------------
// make support
void heartBeat(const uint8_t LedPin, uint32_t currentMillis)
{
  static bool setUp = false;
  if (setUp == false) pinMode (LedPin, OUTPUT), setUp = true;
  digitalWrite(LedPin, (currentMillis / 500) % 2);
}
// make application
void setup()
{
  Serial.begin(115200);
  for (uint8_t n = 0; n < 32; n++) Serial.println("");
  Serial.print("Source: "), Serial.println(__FILE__);
  Serial.print(ProjectName), Serial.print(" - "), Serial.println(NotesOnRelease);
  uint8_t index = 0;
  for (auto &ledTimerSwitch : ledTimerSwitches)
  {
    ledTimerSwitch.make(OutputPins[index], RandomsTimes[index][Min], RandomsTimes[index][Max]);
    index++;
  }
  delay(2000);
  Serial.println(" =-> and off we go\n");
}
void loop()
{
  currentMillis = millis();
  heartBeat(LED_BUILTIN, currentMillis);
  for (auto &ledTimerSwitch : ledTimerSwitches) ledTimerSwitch.run(currentMillis);

}

Have a nice day and enjoy coding in C++.

1 Like

Great, thanks a lot!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.