Random on/off lights model railroad

I am probably posting this wrong. The code below was copied and pasted. I have not uploaded the code but understand it works. The code randomly turns 16 leds on and off, which I want. However, I would like to activate this code by an LDR sensor. Essentially when it is dark the random light effects would be activated/on. Conversely when it is bright the random light effects would be deactivated/off.

I have limited programming skills and would appreciate help in terms of additional coding that is required. Plus I am an old man…so take it easy on me. Thanks in advance.

#define numleds 16

byte ledpins = { 0,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17 } ;

void setup( ) {

for ( int i=1; i <= numleds; i++ ) {

pinMode ( ledpins [ i ], OUTPUT) ;

digitalWrite ( ledpins [ i ] , HIGH) ;

}

}

void loop ( ) {

digitalWrite ( ledpins [ random ( 0, numleds+1 ) ], lightsw ( ) ) ;

delay ( 900 ) ;

}

boolean lightsw ( ) {

if ( random (0,100) > 40 ) return LOW ;

else return HIGH ;

}

Do you know how to wire a 10k resistor and a LDR to an analog input ? Can you print the analog value to the serial monitor ?

Using an LDR ? Then you need hysteresis.
Without hysteresis, the leds could turn on at light level 50% and turn off at 50%.
With hysteresis, the leds could turn on at light level 40% (darker) and turn off at 60% (lighter). That prevents the leds going on and off all the time, which would be annoying.

Are there 16 leds ? Then please declare 16 leds.
A for loop for an array with 16 leds is always like this:

for (int i=0; i<numleds; i++)
{      
  pinMode(ledpins[i], OUTPUT);
  digitalWrite(ledpins[i], HIGH);
}

When ‘numleds’ is 16, then the for-loop above runs from 0 up to 15 (inclusive). In that case, you have to get rid off the dummy ‘0’ in the array.

Where did you find that sketch ? It is not good to start with. Someone who has no experience with arrays wrote it.

In the loop() is a delay of 900 milliseconds. That is not random. That is a fixed delay. How random would you like to turn the leds on and off ?

At tinkercad.com it is possible to simulate your project. Make a autodesk account, select ‘Circuits’, move an Arduino board in the workfield, select “text” for the code.

#define numleds 16

Since numleds is a constant, it should be written in all caps, like so: NUMLEDS.

byte ledpins [ ] =  { 0,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17 } ;

There are 17 elements in that array, not 16. And the name should be ledPins.

for ( int  i=1; i <= numleds;  i++ )  {

The first element of an array is number 0, so the for loop should start at i=0.

boolean lightsw ( )  {
  if  ( random (0,100) > 40 ) return LOW ;
   else return HIGH ;
}

Since this function returns HIGH or LOW, the correct data type is byte, not boolean.

I think you should build this sketch and test it, before adding an LDR.

PS.: What type of Arduino do you have? If it’s an UNO, you can’t use pins 0, 14, 15, 16 or 17 as an output! Use some of A0 … A5 instead.

And you mostly do not even need the 10k resistor.

Connect the LDR between an analog input and ground, set pinMode to INPUT_PULLUP and you have an effective 47k pullup. If that is too weak, then add a 10k or lesser pullup.

I will rewrite the code. As mentioned in my first note I have not attempted to upload this sketch. The sketch itself was previously posted on this forum and it was indicated that it ran.....obviously not.

I will have to get a better understanding of “byte” vs “Boolean” as to data type.

I am using a UNO and will change the sketch to only 7 LEDs, thus limiting the usage of output pins. I have used an LDR sensor in other sketches but limited only to turn on/off specific LEDs. I would like to use an LDR to activate this sketch but perhaps this is beyond my limited programming skills.

It should be simple enough to take the LDR code from one of your other examples to control how the LEDs are lit.

Post your best effort and we'll help you fix it if you're having trouble.

Erik_Baas:
].

for ( int  i=1; i <= numleds;  i++ )  {

The first element of an array is number 0, so the for loop should start at i=0

But that would make pin zero an OUTPUT
.

PS.: What type of Arduino do you have? If it’s an UNO, you can’t use pins 0, 14, 15, 16 or 17 as an output! Use some of A0 … A5 instead.

Yes, you CAN use pins 14, 15, 16 and 17 as outputs. They are also known as A0 to A3.

You can even make pin zero an output, but it is usually best to save it for serial.

Have I been adding 16 leds for nothing :o :wink:

Koepel, I like your last post which shows what I have requested can be done. Would it be possible to see the entire code (sketch) or point me in the direction as to where this code is kept. Thanks…and you are truly brilliant.

You would not learn from it, if you just copy my sketch :angry:
I am not sure what the leds should do. I don't even know if they are connected to GND or to 5V.
I am also not sure how the LDR should control the leds.

The sketch is written around the variable 'ledsRunning'. It is true when the leds are random turned on and off, and false when they are all off. Once I have the 'ledsRunning' variable, then the rest of the code fall into place.

#define NUMLEDS 16
const byte ledpins[NUMLEDS] = { 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, A0, A1, A2, A3};

const int pinLDR = A4;
bool ledsRunning = false;

void setup()
{
  Serial.begin( 9600);
  Serial.println( "The sketch has started");
  
  for( int i=0; i<NUMLEDS; i++)
  {
    pinMode( ledpins[i], OUTPUT);
  }
}


void loop()
{
  int brightness = getBrightness( pinLDR);
  
  if( ledsRunning)
  {
    digitalWrite( ledpins[random(0, NUMLEDS)], lightsw());
  
    if( brightness > 76)
    {
      ledsRunning = false;
    
      for( int i=0; i<NUMLEDS; i++)
      {
        digitalWrite( ledpins[i], LOW);
      }
    }
  }
  else
  {
    if( brightness < 70)
    {
      ledsRunning = true;

      for( int i=0; i<NUMLEDS; i++)
      {
        digitalWrite( ledpins[i], HIGH);
      }
    }
  }
  
  Serial.print( brightness);
  Serial.print( "\%, ");
  Serial.print( ledsRunning ? "true" : "false");
  Serial.println();
  delay( 500);
}


int lightsw()
{
  if( random(0, 100) > 40)
  {
    return LOW;
  }
  else 
  {
    return HIGH;
  }
}

// The function getBrightness returns a percentage.
// This was neede because the Tinkercad LDR simulation
// is weird.
// 0% is dark, 100% is super bright.
// This function needs to be optimized when used in
// a real project.
int getBrightness( int pin)
{
  // Get the brightness in percentage.
  // The LDR is connected to GND.
  // The 10k is connected to +5V.
  int ldrValue = analogRead( pinLDR);
  
  // curve correction for Tinkercad
  ldrValue = int( sqrt( (float) ldrValue) * 32.0);
  
  int percentage = map( ldrValue, 1000, 50, 0, 100);
  percentage = constrain( percentage, 0, 100);
  return( percentage);
}

I am not copying your code but just trying to understand the logic. I am building a very large model railroad layout. Part of the layout is set in an urban environment with many buildings. All my buildings have internal and external LED lights. I built my layout room with ambient lighting controlled by a fast clock that simulates 24hrs compressed to 4 actual hours. Lighting goes from full bright to dark. As mentioned before I want to randomly turn on and off building LEDs during darkness as sensed by an LDR.

I am using a LDR in a similar application elsewhere on the layout, but using very simple coding to turn on/off specific LEDs based on level of light.

Thanks for your help and by no means am I asking you to write code for me.....but you have given me more clues as to how to proceed.

That sketch can be used for a Christmas tree, but it is not a simulation of light behavior of a house.

All you need is a simulation of a single light, using the LDR and with millis(). Then you can put in code a certain behavior and also add random() to it. For example the light off for a long period during the night.

With that, it is easy to extend it for more lights. Because it has random, they all will do that independent of each other. It will be the same code, but with an array for multiple millis-timers.

With a little cheating, I could run 400 different millis-timers on a Arduino Uno: millis_overdone.ino.

I made changes to the following code as suggested. The program works and randomly turns 10 LEDs on and off. I am happy with the results. Now I want to front end this program by triggering the random affect with a LDR sensor turning the random application on when the sensor is dark (HIGH) and conversely off when the sensor is bright (LOW). I will attempt to write this code but will draw upon advice/expertise as needed.

Here is the random light program

[code]

#define NUMLEDS 10

byte ledPins [ ] = {3,4,5,6,7,8,9,10,11,12};

void setup() {
  // put your setup code here, to run once:

for ( int i=0; i <= NUMLEDS; i++ ) {
  pinMode(ledPins [ i ], OUTPUT);
  digitalWrite ( ledPins [ i ], HIGH);
}
}
void loop() {
  // put your main code here, to run repeatedly:

digitalWrite (ledPins [ random (0, NUMLEDS + 1) ], lightsw ( ) );
delay (900);
}

boolean lightsw ( ) {
  if  (random (0,100) > 40 ) return LOW;
  else return HIGH;
}

[/code]

redliteal:
for ( int i=0; i <= NUMLEDS; i++ ) {

Oops…

As mentioned previously, I wanted to start the random light effects when the ambient room light level was low. As such I included an “if” statement in the loop that upon reaching a light level of less than 200, the random light effects are to start. The program works great. The random statement turns the LEDs (on/off) upon the ambient room lights below 200. However, if the ambient light level goes back above 200, the LEDs do not return to their initial state which should be off.

I think I need to add another “if” statement along the lines of…“if (light >=200) digitalWrite(ledPins, LOW)”. I just dont know where to put this code or if additional coding is required. Any suggestions?

[code]

#define NUMLEDS 10

byte ledPins [ ] = {3,4,5,6,7,8,9,10,11,12}; //ledPins associatedvwith specific Pin numbers 
int light = 0; // store the current ambient light value


void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
for ( int i=0; i <= NUMLEDS; i++ ) {
  pinMode(ledPins [ i ], OUTPUT);
  digitalWrite ( ledPins [ i ], LOW);
}
}
void loop() {
  // put your main code here, to run repeatedly:
  
light=analogRead(A0);  // read and save value from LDR
Serial.println(light);
if (light < 200) // ambient light is low, start random light affects

digitalWrite (ledPins [ random (0, NUMLEDS + 1) ], lightsw ( ) );
delay (5000);
}

boolean lightsw ( ) {
  if  (random(0,100) > 40 ) return HIGH;
  else return LOW;
  
}

[/code]

  if (light < 200) // ambient light is low, start random light affects

    digitalWrite (ledPins [ random (0, NUMLEDS + 1) ], lightsw ( ) );

  else {
    // turn lights off
  }

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