Trains.com

Subscriber & Member Login

Login, or register today to interact in our online community, comment on articles, receive our newsletter, manage your account online and more!

Analise this sketch please

3806 views
23 replies
1 rating 2 rating 3 rating 4 rating 5 rating
  • Member since
    June 2016
  • 81 posts
Analise this sketch please
Posted by Ron Hume on Friday, February 3, 2017 3:13 AM

 

Willsome kind person tell me what sequence I can expect from the following Arduino Uno sketch, that is, how many lights on at one time, duration of sequence and so on, as I need to test the circuits before turning the layout upright. (82 years old, can't crawl around the nether regions). Any help appreciated.

Ron from down under.

 

#define numleds  12                                                      

 

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

 

void setup( )  {                  

 

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

     pinMode ( ledpins [ i ], OUTPUT) ;

     digitalWrite ( ledpins [ i ] , HIGH) ;

    }

    pinMode (2,INPUT);      // Pin 2 will be the control pin for this lighting group

    digitalWrite (2,HIGH);    //This turns the Pull up ON

 }

 void loop ( )  {  

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

                 delay ( 4000 ) ;                  

 }

 boolean lightsw ( )  {

  if (digitalRead(2)  == LOW) return LOW;  //If the group control pin is LOW ALL lights

                                                              // will eventually turn OFF

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

    else return HIGH ;

 }

 

  • Member since
    July 2007
  • From: Yorkton, Sk, Cnd
  • 441 posts
Posted by wvg_ca on Friday, February 3, 2017 4:20 AM

Did you try it on a breadboard first??

  • Member since
    February 2002
  • From: Reading, PA
  • 30,002 posts
Posted by rrinker on Friday, February 3, 2017 6:47 AM

 It depends on Pin 2. If Pin 2 is high, there is about a 60% chance any given pin will turn on. It's possible that ALL of them could end up on, it's also possible that ALL of them could end up off, regardless of the state of Pin 2. If Pin 2 is low, then whatever random pin is selected in the loop will be turned off.

 Many times through the loop, nothing will happen - a pin that is already on will be selected at random and set to on, or a pin that is already off will get set off again. The loop pauses 4 seconds each time through.

                             --Randy

 


Modeling the Reading Railroad in the 1950's

 

Visit my web site at www.readingeastpenn.com for construction updates, DCC Info, and more.

  • Member since
    July 2009
  • From: lavale, md
  • 4,678 posts
Posted by gregc on Friday, February 3, 2017 7:42 AM

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

the ledpins[]   starts at index 0 and ends at 1 less than the size (i.e. 11).    The for loop in setup() should be

for ( int  i=0; i < numleds;  i++ )

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

likewise in loop(), the range of random should be limited to numleds-1 not numleds+1

Ron Hume
pinMode (2,INPUT);

digitalWrite (2,HIGH);

i'm not sure about the need for digitalWrite(2, HIGH).    Instead of pinMode(2,INPUT), i think pinMode(2, INPUT_PULLUP) is what you want.  (see pinMode)

 

if pin-2 is made low, it will take loop() 48 sec = 12 * 4 to possibly affect each LED.   But since loop() picks the LED randomly, it may take much longer for all the LEDs to turn off have turned on just once.    Likewise,  it may take just as long for any one LED to come on and much longer for all of the LEDs to have come on just once turn off.

only one LED has a chance of changing state every 4 sec.    No two LEDs can change state at the same time.

 

I can see how this might be used to simulate building lights at night (pin-2 on) and day (pin-2 off).    But there's only a chance of any one light turning on or off every 4 seconds.   But the delays when pin-2 changes would make sense for dusk and dawn.

 

 

greg - Philadelphia & Reading / Reading

  • Member since
    December 2004
  • From: Pa.
  • 3,361 posts
Posted by DigitalGriffin on Friday, February 3, 2017 8:38 AM

What they said.  I know that's not very helpful from my end.  But their reverse analysis is correct.

Don - Specializing in layout DC->DCC conversions

Modeling C&O transition era and steel industries There's Nothing Like Big Steam!

  • Member since
    January 2009
  • From: Bakersfield, CA 93308
  • 6,526 posts
Posted by RR_Mel on Friday, February 3, 2017 8:38 AM

Ron that sketch looks like my original 12 LED random sketch, it is totally random, never the same.  Changing the two delays will change the duration of the random pick as well as the on-off delay.
 
I have a 14 port sketch that is slightly modified, at the time I didn’t know I could use the TX RX pins (1 & 2) for outputs.
 
+++++++++++++++++++++++++++++++++++++
  
#define numleds  14                                                     
byte ledpins [ ] =  { 0,1,2,3,4,5,6,7,8,9,10,11,12,13 } ;
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 ( 4000 ) ;                  
}
boolean lightsw ( )  {
 if (digitalRead(2)  == LOW) return LOW;  //If the group control pin is LOW ALL lights
                                                             // will eventually turn OFF
 if  ( random (0,100) > 60 ) return LOW ;
   else return HIGH ;
}
 
++++++++++++++++++++++++++++++++++++++++
 
EDIT:
 
Pin 2, control wasn't needed on my original sketch so the new sketch uses pin 2 as an output.
 
EDIT:
 
I used 7 channel 500ma driver chips (ULN2003 for inverted & TD62304 for non inverted) for my outputs.  Maybe some of the Arduino Gurus can advise the max LED current of the UNO with all LEDs on.
 
My structure lighting is made up of 12 volt 40 to 100ma bulbs operating at 8½ volts.   
 
 
Mel
 
Modeling the early to mid 1950s SP in HO scale since 1951
 
My Model Railroad   
 
Bakersfield, California
 
I'm beginning to realize that aging is not for wimps.
 
  • Member since
    June 2016
  • 81 posts
Posted by Ron Hume on Saturday, February 4, 2017 12:56 AM

Hey Mel, it looks like I had better start this from scratch. I have nine pins connected to outputs because I was advised that the Arduino couldn't cope with twelve. No LED's are connected yet. #1 to #9 pins. I have a switch to turn chip power on during the evening. All I need is a sketch to randomely switch these LEDs say five or six at a time. I have a completely separate circuit for "constantly on" street lights and so on. Just something realistic would do. But I don't understand sketches at all so all the replies are lost on me.

Ron from down under. 

  • Member since
    February 2002
  • From: Reading, PA
  • 30,002 posts
Posted by rrinker on Saturday, February 4, 2017 10:28 AM

 More detail (it may help if you look at the initial tutorials which will walk you through the basics required in every sketch and introduce just one concept at a time instead of diving into a more complex program). Also, this sketch as shown takes advantage of some language features that make it more efficient, which has the downside of being slightly less readable for a newcomer. I'm not saying the sketch is wrong, what I saying is this is not how someone knew to the whole thing would write it, the way it is indicates a greater experience level with the language.

Anyway.. (basing off your initial post version of the code)

First line - that means any time the word 'numleds' appears in the program, the value 12 is substituted.

Next line - ledpins is an array listing the Arduino pin numbers that are being used. Because of the way the code works later, there needs to be at LEAST 12 items listed - matching the previous line.

3rd line - all Arduino Sketches need a setup function. For the purposes of sketches like this, just do it as shown. It's a more advanced topic to know what the 'void' means.

4th line - a FOR loop simply counts, the three parameters inside the () tell it how to count. In this case, variable i is used for a counter. It starts at 1. It keeps counting as lon as i is less than or equal to numleds (12), and after each loop it adds 1 to the value of i. So first time, it is 1, then 2, then 3, up until 12. Then it adds 1 to i and makes it 13, and since 13 is not less than or equal to 12, the loop ends.

Inside the loop are two lines. The first one is pinMode, this is the command to tell the Arduino what you are going to use a specific pin for - input or output. In our case, we want to make the pins for the LEDs outputs. Note the reference to the ledpins defined back at the beginning. This returns the i'th item in the ledpins array - when i is 1, it returns the fiurst value, which is 0, when i is 2, it returns the second value, which is 3, etc.

The second line inside the loop is digitalWrite. This is the Arduino command to turn an output on or off. Again we reference what pin we want, and then set it to HIGH, which is on, it would read +5 volts on the typical Arduino Uno or Nano if measured with a voltmeter. LOW would set it to 0 volts.

That's it for the loop (contained within the {} curly braces, but there are 2 more lines that are part of the setup.

In the first, we set Arduino pin 2 to be an input. That means you will, later in the code, be able to check the status of this pin and if it's HIGH or LOW, do something.

The next and last line in the setup may look strange, we are doing a digitalWrite to the pin we just made an INPUT. However, this is an Arduino method to enable what are called pullup resistors. This ties Pin 2 to +5 volts via a resistor (to limit current - just like with an LED). That resistor is inside the chip. What this does is unless you connect pin 2 to ground with a wire or switch or whatever, it will always read in the HIGH state. No connection, pin 2 'sees' +5V and would report that it is HIGH.

Now we start the second part of every Arduino sketch - the loop. Anything inside the loop is automatically executed over and over again as long as the Arduino is turned on. Compared to setup, which only runs once. Again, ignore the technicalities of what 'void' means at this time.

There are really only 2 lines here, but that's because of what I said above, the first line in the loop joins together several lines in one.

The main command is digitalWrite, again this is how you set one of the output on or off. digitalWrite needs two parameters - what pin you want to control, and what state you want to make it - HIGH or on, or LOW or off. So for what pin, it again refers to our array of pin numbers, ledpins. But instead of a specific item in the list, the code implements the random function which generates a random number between the specified limits. Between, not inclusive, that's why it says 0 to numleds=1 - remember where numleds appears it is replaced by 12. So what you get is a random number between 0 and 13 - and the endpoints aren't included, so your possible values are 1 through 12 - exactly matching the number of pins we are using.

 To make it further random, the second parameter of the digitalWrite isn't simply HIGH or LOW as seen before, but instead calls another function named lightsw. So here we step outside the loop and jump down to the code at the bottom which will return a HIGH or LOW depending on some other factors. So we randomly pick one of the outputs and then we randomly set it to be either on or off.

Then the next line, delay is a command that makes the Arduino pause and do nothing for some number of milliseconds. In this case, 4000, or 4 seconds. We now hit the } ending the loop function so it goes back to the digitalWrite line and does it all over again with a new random pin number.

The function lightsw is defined next. Notice is says boolean instead of void - this is because lightsw() needs to return a binary value - 1 or 0, on or off, HIGH or LOW.

The first line in the function is an IF statement. IF the condition is true, do the action that follows, otherwise go to the next line. In this case, we are doing a digitalRead of pin 2 - remember our friend pin 2 from the setup, pin 2 will always return HIGH unless you hook it to ground. In this case, we are testing if it is low, ie, hooked to ground. If so, the function immediately returns LOW. This has the effect of setting whichever pin number was randomly generated back in the main loop to LOW, or off.

 If pin 2 is NOT LOW, we go to the next line. There is another IF, but this time we are generating a random number between 0 and 100 (remember this means the value will be anything from 1 to 99), and then comparing it to 60. If the random number is greater than 60 (so 61-99), the function returns LOW and the led pin is turned off. Otherwise (that's the 'else' keyword) the function returns HIGH which turns the led pin on.

All you have to do to make this work with 9 pins instead of 12 is change that top line so that numleds = 9, and in the second line, you list which 9 pins you have LEDs connected to. That's it. What Mel has done, and shows in one of his other posts, is added additional hardware to the basic Arduino in the form of a 'driver' or 'buffer'. Each output of the driver can run many LEDs without overloading, the input of the driver is connected to the Arduino pin so the Arduino only sees the current of a single LED or less, but really that is working as a switch to control a string of 10 or more LEDs. You need to know the specifications of the driver chip to know how many LEDs you can safely connect, just like when you figure out how big a power supply you need to just drive LEDs the usual way. It WILL be more than you can just hook directly to the Arduino.

 Hope this helps.

 

                                   --Randy

 


Modeling the Reading Railroad in the 1950's

 

Visit my web site at www.readingeastpenn.com for construction updates, DCC Info, and more.

  • Member since
    January 2009
  • From: Bakersfield, CA 93308
  • 6,526 posts
Posted by RR_Mel on Saturday, February 4, 2017 10:33 AM

I found a very basic sketch for a random generator online and played around with it until I got it to dowhat I wanted.
 
I changed it over and over to get it to the point it is now.  For my wants it works very well now.  I was using 12 position DIP switches to manually turn on and off lights in two multi level houses and the first 12 light random generator plugged in and filled the bill.  As time went on I added the two final ports to my controller then added another light and a flickering fireplace to the houses.
 
Because of the max current limitations of the Arduinos I ran my test LEDs at 2ma per port and it will at some time have all 14 LEDs on without damage to the UNO.  I’ve had three UNOs operating as random controllers for several months many times running them 10 hours at a time while working on my layout.  Because I use incandescent lighting I went wit high current 7 channel driver chips, not one problem.  
 
I've been working on using an MEGA to replace my Rob Paisley Signal System.  I finally got it to work OK by my self by using a simple truth table sketch for a single signal then did a copy and paste to get 16 blocks from one MEGA.  There is probably a much better way to get the same results but mine works great for me.
 
Hang in there and don’t give up, you’ll figure it out!  I did and when I can do it anyone can.  Kinda proves the old saying is incorrect “Can’t teach an old dog new tricks”.
 
 
Mel
 
Modeling the early to mid 1950s SP in HO scale since 1951
 
My Model Railroad   
 
Bakersfield, California
 
I'm beginning to realize that aging is not for wimps.
 
  • Member since
    January 2009
  • From: Bakersfield, CA 93308
  • 6,526 posts
Posted by RR_Mel on Saturday, February 4, 2017 10:41 AM

Check your IM Ron

 

Mel

  • Member since
    June 2016
  • 81 posts
Posted by Ron Hume on Saturday, February 4, 2017 11:04 AM

Wow! That's amazing guys. Thanks for the great info. One question; I have a LED connected to pin 2, it seems I need to disconnect that. But how do I ground pin 2?

Ron from down under.

  • Member since
    February 2002
  • From: Reading, PA
  • 30,002 posts
Posted by rrinker on Saturday, February 4, 2017 1:10 PM

Hook a wire between pin 2 and the GND on the Arduino. But you probably would want to put a toggle switch in line with that so you can turn the lights off without modifying the circuit each time. Plain SPST toggle, hook one side to pin 2, the other side to a GND pin.

                           --Randy


Modeling the Reading Railroad in the 1950's

 

Visit my web site at www.readingeastpenn.com for construction updates, DCC Info, and more.

  • Member since
    July 2009
  • From: lavale, md
  • 4,678 posts
Posted by gregc on Saturday, February 4, 2017 1:26 PM

Ron Hume
All I need is a sketch to randomely switch these LEDs say five or six at a time.

are you saying that every once in a while (msec?) you want 5 random LEDs to change state (turn on if off and turn off if on)?

greg - Philadelphia & Reading / Reading

  • Member since
    June 2016
  • 81 posts
Posted by Ron Hume on Sunday, February 5, 2017 3:08 AM

Yes Greg, but more like a minute or two would be more realistic.

Ron from down under.

  • Member since
    June 2016
  • 81 posts
Posted by Ron Hume on Sunday, February 5, 2017 8:16 AM
What's my IM Mel?
  • Member since
    April 2003
  • 305,205 posts
Posted by Anonymous on Sunday, February 5, 2017 8:50 AM

Click on "Messages" on the right side of the page below the green bar with your name in it.

  • Member since
    July 2009
  • From: lavale, md
  • 4,678 posts
Posted by gregc on Sunday, February 5, 2017 8:56 AM

Ron Hume
it looks like I had better start this from scratch. I have nine pins connected to outputs because I was advised that the Arduino couldn't cope with twelve. No LED's are connected yet. #1 to #9 pins. I have a switch to turn chip power on during the evening. All I need is a sketch to randomely switch these LEDs say five or six at a time.

I think this is what you're asking for.

list the LEDs you want in ledpins [].   Near the bottom, change N_LED to the number of LEDs you want to change each period.  You mentioned 5 or 6.  Change N_SEC to the number of seconds you want to wait before changing.  You mentioned 2 minutes or 120 sec.   They are at small values so that I could test the code.

I left serial debugging in.  You can remove it.

The setup routine sequences thru the LEDS, turning one on each second until they are all on, and then turns them off one at a time every second.   This allows you to verify the LEDs being controlled and that they work whenever you power up the circuit.

toggleN() repeatedly and sequentially goes thru the list of LEDs until the number requested to change has changed.   ledIdx keeps track of the next LED to check each iteration.   This means each LED has the same probability of being changed, not the ones at the beginning of the list

delay() has a limit of 65535.   So there's a loop to wait as many seconds as you'd like.

yes, i like to code

 

// toggle N_LED LEDs every N_SEC seconds

byte ledpins [] = { 11, 10, 9, 13 };

#define NumLeds sizeof(ledpins)

// -----------------------------------------------------
// configure each LED pin as output
void setup()
{
    unsigned int ledIdx;

    Serial.begin(9600);

    for (ledIdx = 0; ledIdx < NumLeds; ledIdx++)
        pinMode (ledpins[ledIdx], OUTPUT);

    // sequentially turn each LED on and then off
    for (ledIdx = 0; ledIdx < NumLeds; ledIdx++)  {
        digitalWrite (ledpins[ledIdx], HIGH);
        delay (1000);
    }

    for (ledIdx = 0; ledIdx < NumLeds; ledIdx++)  {
        digitalWrite (ledpins[ledIdx], LOW);
        delay (1000);
    }
}

// -----------------------------------------------------
// repeatedly scans ledpins from last LED toggled,
//   randomly determine whether to toggle an LED,
//   toggle the specified number of LEDs

void
toggleN (int n) {
    static unsigned int  ledIdx     = 0;     

    Serial.print   ("toggleN: ");
    Serial.println (n);

    while (n) {
        if (random (0,100) > 95) {
            // read LED state and set to opposite
            digitalWrite (ledpins[ledIdx],
                    ! digitalRead (ledpins[ledIdx]) );

            Serial.print (" pin ");
            Serial.print ( ledpins [ledIdx]);
            Serial.print (" state ");
            Serial.print (
                        digitalRead (ledpins[ledIdx]));
            Serial.println ("");

            // decrement number of LEDs to be changed
            n--;
        }

        // increment the LED pin index and wrap at end
        ledIdx++;
        if (NumLeds <= ledIdx)
            ledIdx = 0;
    }
}

// -----------------------------------------------------
// toggle N_LED LEDs and wait N_SEC seconds

#define N_LED   1       // # LEDs to toggle each time
#define N_SEC   3       // # secs between each update

void loop()
{
    toggleN (N_LED);

    //  delay by seconds to avoid integer overflow
    for (int sec = N_SEC; sec > 0; sec--)
        delay (1000);
}

 

greg - Philadelphia & Reading / Reading

  • Member since
    June 2016
  • 81 posts
Posted by Ron Hume on Sunday, February 5, 2017 8:24 PM

Great code Greg!

This looks like the way to go. Just a matter of removing the chip from the layout and reprogramming it on the computer unless I can find a cable about ten yards long. As to the serial debug, I'd like to use it but it means installing and removing the chip to cut the debug. Decisions, decisions...

Ron from down under

  • Member since
    July 2009
  • From: lavale, md
  • 4,678 posts
Posted by gregc on Monday, February 6, 2017 6:25 AM

Ron Hume
As to the serial debug, I'd like to use it but it means installing and removing the chip to cut the debug.

won't affect operation if there isn't a usb terminal listening.   suggest you leave it

greg - Philadelphia & Reading / Reading

  • Member since
    June 2016
  • 81 posts
Posted by Ron Hume on Friday, February 17, 2017 12:42 AM

Greg,

I've been off line while replacing my hard drive.

I tried ti run your sketch and got an error message:

"A function-definition is not allowed here before '{' token

That's the line after the last 'void'

Can you tell me how to fix it?

Ron from down under.

  • Member since
    December 2016
  • 168 posts
Posted by speedybee on Friday, February 17, 2017 2:25 AM

That sounds like trying to define a function inside another one. Did you paste his code inside an existing function?

The Arduino IDE starts you off with blank setup and loop functions and you have to delete those before you paste in what he's made for you

  • Member since
    July 2009
  • From: lavale, md
  • 4,678 posts
Posted by gregc on Friday, February 17, 2017 5:14 AM

Ron Hume
"A function-definition is not allowed here before '{' token That's the line after the last 'void'

presumably you're referring to

void loop() { toggleN (N_LED);

I copied and pasted the code from the thread and recompiled without any errors. My guess is you lost a closing brace, '}', above the "void loop()".

may be easiest to send me a copy of you're code in an IM

 

greg - Philadelphia & Reading / Reading

  • Member since
    June 2016
  • 81 posts
Posted by Ron Hume on Friday, February 17, 2017 9:20 AM

Hi again Greg,

I found the problem. Although I copied and pasted your sketch, somehow the two '}' s below "ledIdx = 0; were omitted.

I uploaded the sketck to the board after making the changes you advised. The board LEDs seemed to be timed appropriately so I will install it and await the results when I have connected the LEDs for the structures. Thanks for your help and patience.

Ron from down under.

  • Member since
    January 2009
  • From: Bakersfield, CA 93308
  • 6,526 posts
Posted by RR_Mel on Friday, February 17, 2017 10:01 AM

Check your IM Ron
 
 
 
Mel
 
Modeling the early to mid 1950s SP in HO scale since 1951
 
My Model Railroad   
 
Bakersfield, California
 
I'm beginning to realize that aging is not for wimps.
 

Subscriber & Member Login

Login, or register today to interact in our online community, comment on articles, receive our newsletter, manage your account online and more!

Users Online

There are no community member online

Search the Community

ADVERTISEMENT
ADVERTISEMENT
ADVERTISEMENT
Model Railroader Newsletter See all
Sign up for our FREE e-newsletter and get model railroad news in your inbox!