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.
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
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
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 HumeAs 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
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
Ron Humeit 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); }
Click on "Messages" on the right side of the page below the green bar with your name in it.
Yes Greg, but more like a minute or two would be more realistic.
Ron HumeAll 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)?
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.
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?
Check your IM Ron
Mel
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.
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.
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!
Ron Humefor ( 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 HumedigitalWrite ( ledpins [ random ( 0, numleds+1 ) ], lightsw ( ) ) ;
likewise in loop(), the range of random should be limited to numleds-1 not numleds+1
Ron HumepinMode (2,INPUT); digitalWrite (2,HIGH);
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.
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.
Did you try it on a breadboard first??
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.
#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 ;