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!

Arduino Curiosity

4792 views
23 replies
1 rating 2 rating 3 rating 4 rating 5 rating
  • Member since
    January 2009
  • From: Bakersfield, CA 93308
  • 6,526 posts
Arduino Curiosity
Posted by RR_Mel on Wednesday, September 27, 2017 1:45 PM

Question for the programming experts.
 
I have five Arduino UNOs all programmed as a random lighting controller with the same sketch.  All five Arduinos start with port #9 active, every time.  My curiosity is why #9 every time.  I don’t have a problem with it being #9, just curious.
 
 
This is my Sketch:
 ==================================
#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  ( random (0,100) > 60 ) return LOW ;
   else return HIGH ;
}

 

==================================

The sketch works great.
 
 
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
    February 2002
  • From: Reading, PA
  • 30,002 posts
Posted by rrinker on Wednesday, September 27, 2017 2:50 PM

 That's because the random() function is not random, it's psuedorandom. If you watch carefully, you should be seeing the exact same sequence every time you run the program. There is also the randomseed() function which generates a new seed number for the random() function. This is from the Arduino site:

If it is important for a sequence of values generated by random() to differ, on subsequent executions of a sketch, use randomSeed() to initialize the random number generator with a fairly random input, such as analogRead() on an unconnected 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
    June 2009
  • From: QLD, Australia
  • 1,111 posts
Posted by tbdanny on Wednesday, September 27, 2017 2:58 PM

Mel,

One thing I've noticed is that your setup routine is a little off.  You've got the LED pins defined as 0-13, but the for loop goes from 1-14 (i = 1, numleds = 14).  As such, when you run it, pin 0 will be undefined, and pin 14 will be set up as an output even though it's not in use.

As for why pin #9, I suspect it's because the Arduino random function is really pseudo-random.  Namely, it returns the next member in a sequence of numbers, and this sequence is actually set, not generated.  As such, it'll return the same numbers for each execution.  It would appear that the output of the random function is triggering the conditions to activate pin 9 each time the sketch is run.

The randomseed function (https://www.arduino.cc/en/Reference/RandomSeed) initiates the random number generator to a different point in the sequence.  I would suggest putting this in your startup routine, to initiate the random number generator.  There are two approaches you could take:

1) Put a different number in the randomseed function for each Arduino.

2) Perform an analogread() on an undefined & unused analog pin, and feed this into the randomseed function on startup.  Given that the analog pin isn't in use, the value of the read from it will be random.

I've used approach no. 2 in my own programming.

The Location: Forests of the Pacific Northwest, Oregon
The Year: 1948
The Scale: On30
The Blog: http://bvlcorr.tumblr.com

  • Member since
    January 2009
  • From: Bakersfield, CA 93308
  • 6,526 posts
Posted by RR_Mel on Wednesday, September 27, 2017 3:25 PM

Thanks for your input guys!
 
I’m not a programmer!  I’m an old electronics guy, a very old electronics guy!
 
All 14 ports in my sketch work as is.  I didn’t notice that all the Arduinos had the same sequence, I seldom turn them on at the same time so I guess that puts them out of sync and not noticeable.
 
I don’t believe in fixing something that isn’t broke so I don’t think I’ll attempt to change my sketch.  It took some doings just to get it to work and I’m afraid if I attempt to change it I’ll screw it up.
 
Edit:
 
This is the light placement in my current build, all lights work.
 
 
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
    April 2012
  • From: Huron, SD
  • 1,016 posts
Posted by Bayfield Transfer Railway on Wednesday, September 27, 2017 3:25 PM

"sketch?"

Why not, oh, say... "program?"

 

Disclaimer:  This post may contain humor, sarcasm, and/or flatulence.

Michael Mornard

Bringing the North Woods to South Dakota!

  • Member since
    December 2016
  • 168 posts
Posted by speedybee on Wednesday, September 27, 2017 3:51 PM

RR_Mel

Thanks for your input guys!
 
I’m not a programmer!  I’m an old electronics guy, a very old electronics guy!
 
All 14 ports in my sketch work as is.  I didn’t notice that all the Arduinos had the same sequence, I seldom turn them on at the same time so I guess that puts them out of sync and not noticeable.
 
I don’t believe in fixing something that isn’t broke so I don’t think I’ll attempt to change my sketch.  It took some doings just to get it to work and I’m afraid if I attempt to change it I’ll screw it up.

As others have noted, your "for" loop doesn't include port 0. The Arduino pins default to inputs, and writing "high" to an input enables its internal resistor, which will dim your LED, though as you have observed it still works.

 

I get that if you don't want to change your code that's fine, but it just takes a few seconds, so I've copied your code here with the appropriate changes others have already mentioned in case you change your mind:

#define numleds  14                                                      
byte ledpins [ ] =  { 0,1,2,3,4,5,6,7,8,9,10,11,12,13 } ;
void setup( )  { 
 
  randomSeed(analogRead(A0));     // as long as analog pin 0 is unattached            
    for ( int  i=0; 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  ( random (0,100) > 60 ) return LOW ;
   else return HIGH ;
}
 
 -------------------------
edit: also, if you need more pins, FYI you can use the analog input pins as digital outputs as well, though if you attach anything to the analog pin 0, the randomizing won't work as well
 
another edit: while you're randomizing things, perhaps consider randomizing the 4 second lighting interval as well, for an added sense of realism? Could change the " delay(4000) " to something like " delay(random(3000,30000)); " for an interval anywhere between 3 and 30 seconds
 
Bayfield Transfer Railway
  "sketch?"  Why not, oh, say... "program?" 
    Because in the Arduino IDE, a program is called a sketch. 
  • Member since
    January 2009
  • From: Bakersfield, CA 93308
  • 6,526 posts
Posted by RR_Mel on Wednesday, September 27, 2017 4:13 PM

Speedy
I gave your Sketch a shot and I like the operation better than mine.  It seems that the change screwed up the timing.  I changed the delay to 8 seconds and that seems to work better.
 
More later, I’m dinking with the sketch.
 
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 Wednesday, September 27, 2017 4:24 PM

Randy and Danny after I made the changes you suggested I couldn’t get it to compile.  That’s pretty much normal for me.
 
Speedy, the 8 second delay looks pretty good.
 
There is one change, now it starts every time at 14, that’s understandable.
 
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
    April 2012
  • From: Huron, SD
  • 1,016 posts
Posted by Bayfield Transfer Railway on Wednesday, September 27, 2017 4:27 PM

I figured that Arduino uses "sketch" for "program."

It annoys me.  It annoys me when neologims are used for concepts we already have words for.  It's one of the things that pissed me off so much about Java.  Enough with the "cute" coffee puns already, those things all have names.

 

Disclaimer:  This post may contain humor, sarcasm, and/or flatulence.

Michael Mornard

Bringing the North Woods to South Dakota!

  • Member since
    February 2002
  • From: Reading, PA
  • 30,002 posts
Posted by rrinker on Wednesday, September 27, 2017 7:00 PM

 Arduino was originally designed for artists. The word 'program' scares artists. So they called it a 'sketch'. I am not an artist (the mess in front of me as I try to draw out even a simple schematic for a Tortoise controlling signals in a good example - but none of the electronic CAD programs I have contain a Tortoise as a component. LEDs, sure. Diodes, Sure. Turtles? Nope). I write programs for my Arduinos - actually I only use the Arduinos for development, my finished project will have just the ATMegas 328P microcontroller and supporting components. In fact, half the time I use Visual Studio to develop my programs rather than the Arduino IDE.

                               --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 Wednesday, September 27, 2017 8:01 PM

I’ve dinked around with the timing for three hours and while I like some of the changes there are some that I don’t like.  I placed the new house on my layout close to a house with my original sketch and the RandomSeed change looks strange compared to just Random but maybe that’s good.
 
At this point I’m using 5 seconds for delay and (5,150) >60) for the if statement with RandomSeed.
 
A plus for the RandomSeed is the bulbs randomly stay on longer.  Before the change the average current draw (bulb on time) was 200ma, after the change the average current is 400ma+.  All lights on max draw is 550ma.
 
This is what I ended up with:
=======================================
#define numleds  14                                                      
byte ledpins [ ] =  { 0,1,2,3,4,5,6,7,8,9,10,11,12,13 } ;
void setup( )  {
    randomSeed(analogRead(0));                
    for ( int  i=0; i <= numleds;  i++ )  {     
    pinMode ( ledpins [ i ], OUTPUT) ;
    digitalWrite ( ledpins [ i ] , HIGH) ;
   }
  
}
void loop ( )  { 
                digitalWrite ( ledpins [ random ( 0, numleds+1 ) ], lightsw ( ) ) ;
                delay ( 5000 ) ;                  
}
boolean lightsw ( )  {
 
 if  ( random (5,150) > 60 ) return LOW ;
   else return HIGH ;
}
=======================================
 
Thanks for the input guys, I have ended up learning more goodies and a better operating controller.
 
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
    September 2015
  • 34 posts
Posted by Pukka on Thursday, September 28, 2017 12:27 PM

The sketch/programming language used in the Arduino is a version of the 'c' programming language. If interested, obtain a book on the Arduino 'c' as that 'c' is not a full 'c' or 'c++'. Confusing!Surprise

Tags: c language
  • Member since
    July 2009
  • From: lavale, md
  • 4,677 posts
Posted by gregc on Thursday, September 28, 2017 4:20 PM

Pukka
Arduino 'c' as that 'c' is not a full 'c' or 'c++'.

can you give an example of something you can do in c/c++ that you can't do on an Arduino?

greg - Philadelphia & Reading / Reading

  • Member since
    February 2002
  • From: Reading, PA
  • 30,002 posts
Posted by rrinker on Thursday, September 28, 2017 9:14 PM

 Well, Arduino isn't directly based on C or C++, it's actually based on Wiring. It's very close to C++ but not exactly the same. Unless you're a hardcore C++ programmer, it doesn't really matter much.

 You can of course directly access the micro's control registers in Arduino, or program an Arduino using Atmel Studio and use 'pure' C. To do so, you directly manipulate the control registers and port registers in the Atmega chip. It's WAY faster than pinMode, digitalWrite, and digitalRead. But you need to keep track of each bit of the port register yourself and use bitmasking to turn a given pin on and off. If you need ultimate performance, direct control in Arduino is the first step. If that's STILL not fast enough, then direct programming with Atmel Studio is the way to go. They may only be 8 bit, and run at 16MHz, but the ATMega 328 used in the Uno and Nano are actually pretty fast. Most of the things we need for model railroads, the speed you get using the Arduino IDE to code is plenty fast enough.

                                --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,677 posts
Posted by gregc on Friday, September 29, 2017 5:13 AM

i see gcc tools under ther hardware/.  Looks like it's using the GNU compiler which is standard c/c++ which we use on our small-cell project.

rrinker
You can of course directly access the micro's control registers in Arduino, or program an Arduino using Atmel Studio and use 'pure' C.

don't understand how accessing HW registers is relavent to the question.

There are various ways of accessing HW registers affecting multiple I/O pins with different features and performance.  This is an age old problem.   Can't you write your own version versions of digitalWrite/Read that are faster, if needed?

 

still looking for an example

 

greg - Philadelphia & Reading / Reading

  • Member since
    February 2002
  • From: Reading, PA
  • 30,002 posts
Posted by rrinker on Friday, September 29, 2017 11:41 AM

 You should be able to use an C/C++ construct, so long as you observe the limits of the microcontroller - there are differences around floating point support since the ATMega series used in common Arduinos is only an 8 bit processor and doesn't have the scratch register space to to high precision math. This affects double and float types - it's pretty well documented on the Arduino site. 

 The reverse is not true though, since Arduino's flavor has extensions from Wiring as part of the language which will not be in standard C/C++. This is where the HW register access is relevent. Unless you write your own routines and call them the same name, an Arduino program won't compile in stock C. 

 Does any of it matter? You can program these things with anything you are comfortable with. The Arduino IDE is a bit simplistic and doesn't do much more than I can do with Notepad++ but you can always use the Visual Studio add-in that I do and leverage VS (free edition even) as a superior IDE yet still have the convenience of a button to upload the program to the Arduino like in the Arduino IDE. Or you can go whole hog and use Atmel Studio (which is VS with Atmel's add ins) and write directly to the hardware. There's a lot of animosity on the aprt of 'professional' embedded programmers towards the Arduino IDE. True it is lacking compared to high end professional development systems, but it does get the job done and allows people who might not be able to do so to write working code. I think it's a good thing, as it hides the complexity of working with the HW registers and lets you focus on just learning the C syntax and program flow. Once you've got that down you can take the next step and replace all the digitalWrite, digitalRead, and pinMode stuff with direct register access. One step at a time.

                             --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
    September 2015
  • 34 posts
Posted by Pukka on Friday, September 29, 2017 12:23 PM

Arduino Wiring Guide as used at a college.

  • Member since
    July 2009
  • From: lavale, md
  • 4,677 posts
Posted by gregc on Friday, September 29, 2017 3:33 PM

are you guys suggesting that Arduino C is not standard C because functions like pinmode() and DigitalWrite() aren't part of any standard C library?

greg - Philadelphia & Reading / Reading

  • Member since
    February 2002
  • From: Reading, PA
  • 30,002 posts
Posted by rrinker on Saturday, September 30, 2017 12:42 PM

 There are some differences in data types as well. boolean and byte aren't standard C types. They do map to bool and unsigned char for the most part but Arduino code with such type declarations won;t just compile in a C compiler.

 It's close enough, but it's not exactly standard C.

                             --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,677 posts
Posted by gregc on Saturday, September 30, 2017 2:12 PM

rrinker
 It's close enough, but it's not exactly standard C.

i'm curious how people understand what a language is.

 

one difference I see is that the IDE must wrap the .ino file within another more standard c/cpp file with additional includes (one reason it's not a .c/cpp file).   One include is Arduino.h (hardware/arduino/avr/cores/arduino/Arduino.h).   I need to explicitly include arduino.h in my .c/cpp files in multi-file projects.

Arduino.h includes several standard includes (e.g. stdlib, string, math), common Arduino #defines (e.g. HIGH, INPUT_PULLUP), typedefs (e.g. boolean, byte), and function declarations (e.g. pinMode, analogWrite, delay).

these things (e.g. HIGH, byte, delay()) are not part of the language, they are conventional customizations for the Arduino environment.

rrinker
There are some differences in data types as well. boolean and byte aren't standard C types.

arduino.h uses typedefs to define new data types from existing ones:

typedef unsigned int word;
typedef bool boolean;
typedef uint8_t byte;

bool is a standard C++ data type and uint8_t is typedef'd in stdint.h as unsigned char.   Unsigned int is standard C which doesn't define the size of an int.

 

rrinker
They do map to bool and unsigned char for the most part but Arduino code with such type declarations won;t just compile in a C compiler.

I have taken Arduino code, added these typedefs and stubs for pinMode(), digitalWrite(), ..., and compiled an Arduino application with the standard GNU compiler (I use cygwin on windows).  This is a good way to simulate and save time during embedded program development.

 

Our small-cell project is required to use stdint.h which defines uint8_t, int16_, uint32_t, ... for variables outside file scope.   They are not defined by the language and this usage is becoming common industry practice.   Our small-cell project has functions similar to pinMode() and digitalWrite() that are unique to our system and application.

we recently upgraded to c++14.   It adds some esoteric features that i'm unlikely to ever use.    It doesn't mean that the code i wrote 20 years ago is not C++.

 

the point is, the Arduino build environment provides all the superfluous coding needed to build an Arduino application using a standard, flexible and mature programing language rather than write their own language (C-51).   This makes it easy for novices to create Arduino programs and use Arduinos for custom and intelligent electronic projects.   Much better than the KIM-1 I started with.

greg - Philadelphia & Reading / Reading

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

 In some wyas it's better than the days of old - the smaller 8 bit micros may be the clooses thing to the old processors that there is, in that the raw machine language is actually learnable. I stopped assembly after the 8088 was done, the further extensions they kept adding made it near impossible to memorize all the opcodes. The instruction set of modern processors - I don't even want to contemplate the number of opcodes.

 My first machine was an RCA CDP1802. It has 91 op codes, most of which I still remember. I still have that computer and it still works - I can fire it up and do some simple demo programs purely from memory. My second foray into machine code was the Z80 on a friend's TRS-80. Don't really remember a whole lot of it but when I see some code I can begin to recall it. Third attempt was 6502, same as the KIM-1, but on an Apple II. My program for the advanced BASIC class in HS was too slow to update the video, so I redid the video routines in assembly. And was that ever a pain in the rear - I was so used to the 1802, with 16x 16 bit registers, any of which could be the program counter, a pointer, or whatever. And even the Z80 had quite a few registers, although not quite as flexible as the 1802 (PC and X were fixed). The 6502 though - almost no registers to speak of. Even the simpliest of tasks required you to build a stack and stack pointer and keep track of it all. I got my project working, but I hated that processor from the get-go.

 There certainly are productivity gains using higher level languages, but the higher you get, there is always some tradeoff. The simplicity of Arduino statements like pinMode and digitalWrite are a good example - they are a fraction of the speed of direct register manipulation, but infinitely easier to understand.

 The rare times I need to write code at work that's more than Powershell scripting, I typically use VB.NET as various BASIC dialects are still the languages I have the moost experience with. For simple Powershell scripts I just type them in a text editor, but for more complex needs (and you can do a LOT with Powershell) I usually use the Quest PowerGUI IDE (free). The microcontroller stuff is all personal/hobby stuff and the simplicity of Arduino wins out. I haven't yet hit a level where the program runs too slowly and I need to resort to direct register manipulation, but even if I do, Atmel's designs seem MUCH easier to use than Microchip's (and I really hope Microchip doesn't ruin the Atmega series). I have a few development systems for smaller PICs, but never went very far with them as they seem extremely complicated. I've also seen some of the examples for the newer 32 bit micros and if the amount of code required to simply blink an LED is any indications - no thanks. I am firmly of the opinion that if an 8 bit device can fully meet the requirements, there is zero point in throwing a 32 bit device at the problem just because 32 > 8. There are so many applications where 16MHz and 8 bits are PLENTY to accomplish the task with a more than satisfactory response time. There is a tendency today to throw more hardware at problems that don;t need more hardware, just for marketing purposes. I recently got a new iPad, only because I finally managed to drop my old one and smashed the screen. The new one has a processor that is much faster and has more cores than the old one. But it doesn't read books or read my email any faster (my two main uses of it). I never would have gotten a new one had I not smashed the old one.

 Anyway this has gotten way off the original topic which really was imply the difference between random and psuedorandom number generators and how to seed the random function in an Arduino (a similar function is available in most programming languages to keep each 'random' pattern from being the same).

 I will close by saying it is far from just me who calls these dialect differences new 'languages'. It seems like ever other dya there is an article on the 'latest and greatest' programming language which are often given cute names but when you look are really just c/c++ varients, or Java derivatives. It's like the latest trend is to write (or modify) a compiler to 'invent' your own language that solves some (but never all) shortcomings in the original language. There are very few truly NEW languages coming out.

                                  --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,677 posts
Posted by gregc on Saturday, September 30, 2017 6:53 PM

rrinker
If it is important for a sequence of values generated by random() to differ, on subsequent executions of a sketch, use randomSeed() to initialize the random number generator with a fairly random input, such as analogRead() on an unconnected pin.

won't an unconnected analog input be pulled high or low?   The inputs are multi-function and there's lots of circuitry hanging on the pin (datasheet pg 73)

for this purpose, wouldn't it better to tie it to a noisy signal or a sinusoid so that it's value is constantly changing, maybe even an RC?

greg - Philadelphia & Reading / Reading

  • Member since
    February 2002
  • From: Reading, PA
  • 30,002 posts
Posted by rrinker on Sunday, October 1, 2017 10:44 AM

 The analog pins have input pullup disabled by default - would cause a bit of a problem if the analog pins were pulled high. Unless otherwise definied, the analog pins are floating, so they will return various values depending on the surrounding environment - like leaving a scope probe flapping in the breeze and not grounded. The majority input will likely be picking up the 60Hz AC sine.

                        --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 Thursday, October 5, 2017 1:33 AM

I want to thank you guys for your help.  I have a much better RANDOM light controller now with your help.  I also experimented a bit using A0 to A5 analog input ports as outputs as suggested.  I built up a three chip high current driver board and have a 20 port truly random lighting controller.
 
I overhauled my Winter’s Mansion lighting to light up all 18 rooms and both front and rear porch lights, looks great.
 
 
EDIT:
 
I ended up with my sketch compiling first try and worked great on my first attempt, all 20 bulbs worked.  That too is a first.
 
 
Thanks again guys!
 
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!