Notifications
Clear all

A New Building Lighting for My HO Layout

23 Posts
5 Users
17 Likes
2,432 Views
Photo Bud
(@photo-bud)
Estimable Member
Joined: 4 years ago
Posts: 111
Topic starter  

So, a year ago I posted a test for a non-existent building. Tonight, I modified the code for an actual building that I am still working on. The momentous thing about this is that after modifying it, it compiled on the first try! Then I prepared a breadboard test and it worked on the first try! I should quit while I'm ahead! lol

Eventually hard coded "times" will be replaced with randomized start/stop within constraints. Also hoping to have a centralized Mega with RTC broadcasting the fast clock times to all Arduino Nanos on the layout. But in the meantime, this will work. There are seven locations within this building, each with two LEDs. A freight room, a priority freight/office (1st floor), an office (2nd floor), attic, external lights on the back, and on the dock.

Here is a picture of the building under construction.

 

IMG 20210112 170451152

Here is the breadboard circuit. Each pin is controlling two LEDs.

IMG 20210113 220256833

And here is the code.

 

/*
  Large_Frt_House_Lighting
  Want to set up time spans for lights on by hour/minute format (24hr clock)
  Want fast clock capability both as testing function and normal running. Usually 4:1 or 5:1
  Include start of sequence flash of all lights 5 times
  Watch push button to restart sequence
  Initial lights to include
    Freight Room (x2)
    1st Floor (x2)
    2nd Floor (x2)
    Attic
    Outside Back Door (x2)
    Outside Freight Dock Main (x2)
    Outside Freight Dock Office (x2)
    
*/
// Time Variables
  unsigned long currtime;
  unsigned long starttime;
  unsigned long elapsetime;
  float floatelapse;
  float hourconv;
  float hourmsecs = 3600000;
  float minmsecs  =   60000;
  float daymsecs  = hourmsecs * 24;
  float elapseoffset = 16.95 * hourmsecs;   // On startup, start the clock at approx 16:47 
  float flmin;
  float fastratio = 12;
  int ihour;
  int imin;
  int iprevmin = 99;                        // integer dummy value of previous minute for proper start up
  
// LED Info
  int frtroom = 9;            //red
  int firstfloor = 3;         //yellow
  int secondfloor = 5;        //green
  int attic = 6;              //blue
  int outbackdoor = 7;        //yellow
  int outdockfreight = 2;     //white
  int outdockoffice = 4;      //white
  
// Room Arrays
  int onhrArray[] = {17, 17, 17, 17, 17, 17, 17};       // Time on hour
  int onmiArray[] = {00, 05, 10, 25, 00, 12, 12};       // Time on minute  
  int offhArray[] = {19, 19, 18, 17, 19, 19, 19};       // Time off hour  
  int offmArray[] = {29, 28, 20, 40, 29, 28, 28};       // Time off minute  
  int statArray[] = {false, false, false, false, false, false, false}; //Current on/off status of LED
  int ledArray[]  = {frtroom, firstfloor, secondfloor, attic, outbackdoor, outdockfreight, outdockoffice}; //Pin numbers of corresponding rooms
  int allarraysize = sizeof(ledArray)/sizeof(ledArray[0]);
  int outdockfreightIdx = 5;
  int justRoomLEDs[] = {frtroom, firstfloor, secondfloor, attic, outbackdoor, outdockfreight, outdockoffice};
  int justroomLEDsize = sizeof(justRoomLEDs)/sizeof(justRoomLEDs[0]);

// Misc Variables
  int i = 0;
  int j = 0;
  int longdelay = 300;
  int shortdelay = 200;

// Start of Code
void setup() {
  starttime = millis();
  Serial.begin(9600);
  pinMode(frtroom, OUTPUT);
  pinMode(firstfloor, OUTPUT);
  pinMode(secondfloor, OUTPUT);
  pinMode(attic, OUTPUT);
  pinMode(outbackdoor, OUTPUT);
  pinMode(outdockfreight, OUTPUT);
  pinMode(outdockoffice, OUTPUT);

  for (i=0; i<5; i = i + 1) {            // Flash all LEDs 5 times
    for (j=0; j<justroomLEDsize; j = j + 1) {
      digitalWrite(justRoomLEDs[j], HIGH);   // turn the LED on (HIGH is the voltage level)
    }
    delay(longdelay);                   // wait for long delay
    for (j=0; j<justroomLEDsize; j = j + 1) {
      digitalWrite(justRoomLEDs[j], LOW);    // turn the LED off by making the voltage LOW
    }
    delay(shortdelay);                   // wait for short delay
  }
}

void print2digits(int number) {          // Print with leading zero
  if (number >=0 && number < 10) {
    Serial.print('0');
  }
  Serial.print(number);
}

void loop() {                            // Main Loop
  currtime = millis();
  elapsetime = currtime - starttime;
  elapsetime = (elapsetime * fastratio) + elapseoffset;
  floatelapse = float (elapsetime);
  hourconv = floatelapse / hourmsecs;
  ihour = int(hourconv);
  flmin = hourconv - ihour;
  imin  = 60 * flmin;
  if (imin != iprevmin) {
    Serial.print("           Time: ");
    if (ihour > 23) {
      ihour = 0;
      starttime = currtime;
      elapseoffset = 0;
    }
    print2digits(ihour);
    Serial.print (":");
    print2digits(imin);    
    Serial.println();
    iprevmin = imin;
    
    for (j=0; j<allarraysize; j = j + 1) {
      if (statArray[j] == false && ihour == onhrArray[j] && imin == onmiArray[j]) {
        statArray[j] = true;
        digitalWrite (ledArray[j], HIGH);
      }
      else if (statArray[j] == true && ihour == offhArray[j] && imin == offmArray[j]) {
        statArray[j] = false;
        digitalWrite (ledArray[j], LOW);
      }
    }
  }
  
  delay (75);
}

Photo Bud (aka John)
The Old Curmudgeon!


   
hayttom reacted
Quote
Photo Bud
(@photo-bud)
Estimable Member
Joined: 4 years ago
Posts: 111
Topic starter  

Need some help. As can be seen from code and description, 14 LEDs will be used, with two on each of seven pins. Assuming 18-20 mA each with a 470 ohm resistor per pair, this would exceed the 200 mA total for board. As I am anything but an electronic whiz, what would be the minimum resistor I would need to drop total amperage below that total?

AND would using PWM to reduce brightness also reduce the amperage or do I need to use higher ohm resistors anyway?

Photo Bud (aka John)
The Old Curmudgeon!


   
ReplyQuote
Photo Bud
(@photo-bud)
Estimable Member
Joined: 4 years ago
Posts: 111
Topic starter  

Here is Fritzing view of test breadboard.

Lrg Frt House Lighting bb

Photo Bud (aka John)
The Old Curmudgeon!


   
ReplyQuote
frogandtoad
(@frogandtoad)
Noble Member
Joined: 4 years ago
Posts: 1506
 

@photo-bud

Posted by: @photo-bud

Need some help. As can be seen from code and description, 14 LEDs will be used, with two on each of seven pins. Assuming 18-20 mA each with a 470 ohm resistor per pair, this would exceed the 200 mA total for board. As I am anything but an electronic whiz, what would be the minimum resistor I would need to drop total amperage below that total?

AND would using PWM to reduce brightness also reduce the amperage or do I need to use higher ohm resistors anyway?

It's not recommended to use LED's in parallel with a single resistor, as due to inconsistencies in current draw, they won't all get the same current and will start to burn out, as one will hog more of the current - I have read about this in the past, and that is my recollection of it.

Wiring them up in series is recommended, that way they'll all get the same current going through them, but this also presents another problem... the voltage drop across the two LED's (the LED forward voltage * 2) may be greater than the 5V supply - You'll need to check the datasheet for your LED's.

Calculating the current using OHMS LAW is very simple - For example (2 LED's in series):

Resistance = (Supply Voltage - LED Forward Voltage * 2 LED's) / LED Current (in AMPS)
Resistance = (5 - (1.9 * 2)) / 0.015
Resistance = (5 - 3.8) / 0.015
Resistance = 1.2 / 0.015
Resistance = 80 ohms

Maybe looking at some cheap BJT's and a separate power supply is the way to go?

Cheers.


   
Photo Bud reacted
ReplyQuote
Photo Bud
(@photo-bud)
Estimable Member
Joined: 4 years ago
Posts: 111
Topic starter  

@frogandtoad Thanks, I appreciate the heads up AND Ohms Law info.

Photo Bud (aka John)
The Old Curmudgeon!


   
frogandtoad reacted
ReplyQuote
Photo Bud
(@photo-bud)
Estimable Member
Joined: 4 years ago
Posts: 111
Topic starter  

Have decided to keep two LEDs per pin and have also decided to modify code to use analogWrite so as to be able to dim to the degree desired using software, rather than resistors. It will leave open the possibility of changing programmatically based on "time of day", e.g. dimmer at "night" than during "daytime".

/*
Large_Frt_House_Lighting
Want to set up time spans for lights on by hour/minute format (24hr clock)
Want fast clock capability both as testing function and normal running. Usually 4:1 or 5:1
Include start of sequence flash of all lights 5 times
Watch push button to restart sequence
Initial lights to include
Freight Room (x2)
1st Floor (x2)
2nd Floor (x2)
Attic
Outside Back Door (x2)
Outside Freight Dock Main (x2)
Outside Freight Dock Office (x2)

*/
// Time Variables
unsigned long currtime;
unsigned long starttime;
unsigned long elapsetime;
float floatelapse;
float hourconv;
float hourmsecs = 3600000;
float minmsecs = 60000;
float daymsecs = hourmsecs * 24;
float elapseoffset = 16.95 * hourmsecs; // On startup, start the clock at approx 16:47
float flmin;
float fastratio = 48;
int ihour;
int imin;
int iprevmin = 99; // integer dummy value of previous minute for proper start up

// LED Info
int frtroom = 9; //orange
int firstfloor = 3; //yellow
int secondfloor = 5; //green
int attic = 6; //blue
int outbackdoor = 7; //yellow
int outdockfreight = 2; //brown
int outdockoffice = 4; //red

// Room Arrays
int onhrArray[] = {17, 17, 17, 17, 17, 17, 17}; // Time on hour
int onmiArray[] = {00, 05, 10, 25, 00, 12, 12}; // Time on minute
int offhArray[] = {19, 19, 18, 17, 19, 19, 19}; // Time off hour
int offmArray[] = {30, 28, 20, 40, 31, 29, 27}; // Time off minute
int statArray[] = {false, false, false, false, false, false, false}; //Current on/off status of LED
int ledArray[] = {frtroom, firstfloor, secondfloor, attic, outbackdoor, outdockfreight, outdockoffice}; //Pin numbers of corresponding rooms
int ledDim[] = {64,64,64,64,64, 64, 64}; // PWM values - initial 25% for all
int allarraysize = sizeof(ledArray)/sizeof(ledArray[0]);
int outdockfreightIdx = 5;
int justRoomLEDs[] = {frtroom, firstfloor, secondfloor, attic, outbackdoor, outdockfreight, outdockoffice};
int justroomLEDsize = sizeof(justRoomLEDs)/sizeof(justRoomLEDs[0]);

// Misc Variables
int i = 0;
int j = 0;
int longdelay = 300;
int shortdelay = 200;

// Start of Code
void setup() {
starttime = millis();
Serial.begin(9600);
pinMode(frtroom, OUTPUT);
pinMode(firstfloor, OUTPUT);
pinMode(secondfloor, OUTPUT);
pinMode(attic, OUTPUT);
pinMode(outbackdoor, OUTPUT);
pinMode(outdockfreight, OUTPUT);
pinMode(outdockoffice, OUTPUT);

for (i=0; i<5; i = i + 1) { // Flash all LEDs 5 times
for (j=0; j<justroomLEDsize; j = j + 1) {
digitalWrite(justRoomLEDs[j], HIGH); // turn the LED on (HIGH is the voltage level)
}
delay(longdelay); // wait for long delay
for (j=0; j<justroomLEDsize; j = j + 1) {
digitalWrite(justRoomLEDs[j], LOW); // turn the LED off by making the voltage LOW
}
delay(shortdelay); // wait for short delay
}
}

void print2digits(int number) { // Print with leading zero
if (number >=0 && number < 10) {
Serial.print('0');
}
Serial.print(number);
}

void loop() { // Main Loop
currtime = millis();
elapsetime = currtime - starttime;
elapsetime = (elapsetime * fastratio) + elapseoffset;
floatelapse = float (elapsetime);
hourconv = floatelapse / hourmsecs;
ihour = int(hourconv);
flmin = hourconv - ihour;
imin = 60 * flmin;
if (imin != iprevmin) {
Serial.print(" Time: ");
if (ihour > 23) {
ihour = 0;
starttime = currtime;
elapseoffset = 0;
}
print2digits(ihour);
Serial.print (":");
print2digits(imin);
Serial.println();
iprevmin = imin;

for (j=0; j<allarraysize; j = j + 1) {
if (statArray[j] == false && ihour == onhrArray[j] && imin == onmiArray[j]) {
statArray[j] = true;
analogWrite (ledArray[j], ledDim[j]);
}
else if (statArray[j] == true && ihour == offhArray[j] && imin == offmArray[j]) {
statArray[j] = false;
analogWrite (ledArray[j], LOW);
}
}
}

delay (75);
}

Photo Bud (aka John)
The Old Curmudgeon!


   
ReplyQuote
Photo Bud
(@photo-bud)
Estimable Member
Joined: 4 years ago
Posts: 111
Topic starter  

Except, of course, it doesn't work for pins 7, 2, and 4, since they are not PWM pins.

Photo Bud (aka John)
The Old Curmudgeon!


   
ReplyQuote
Photo Bud
(@photo-bud)
Estimable Member
Joined: 4 years ago
Posts: 111
Topic starter  

Upshot, using pins 10 & 11 and will only have two dock lights, instead of four. Easy mod to code, and now works fine!

/*
Large_Frt_House_Lighting
Want to set up time spans for lights on by hour/minute format (24hr clock)
Want fast clock capability both as testing function and normal running. Usually 4:1 or 5:1
Include start of sequence flash of all lights 5 times
Watch push button to restart sequence
Initial lights to include
Freight Room (x2)
1st Floor (x2)
2nd Floor (x2)
Attic
Outside Back Door (x2)
Outside Freight Dock Main (x2)
Outside Freight Dock Office (x2)

*/
// Time Variables
unsigned long currtime;
unsigned long starttime;
unsigned long elapsetime;
float floatelapse;
float hourconv;
float hourmsecs = 3600000;
float minmsecs = 60000;
float daymsecs = hourmsecs * 24;
float elapseoffset = 16.95 * hourmsecs; // On startup, start the clock at approx 16:47
float flmin;
float fastratio = 48;
int ihour;
int imin;
int iprevmin = 99; // integer dummy value of previous minute for proper start up

// LED Info
int frtroom = 9; //orange
int firstfloor = 3; //yellow
int secondfloor = 5; //green
int attic = 6; //blue
int outbackdoor = 10; //yellow
// int outdockfreight = 10; //brown
int outdock = 11; //red

// Room Arrays
int onhrArray[] = {17, 17, 17, 17, 17, 17}; // Time on hour
int onmiArray[] = {00, 05, 10, 25, 03, 12}; // Time on minute
int offhArray[] = {19, 19, 18, 17, 19, 19}; // Time off hour
int offmArray[] = {30, 28, 20, 40, 31, 29}; // Time off minute
int statArray[] = {false, false, false, false, false, false}; //Current on/off status of LED
int ledArray[] = {frtroom, firstfloor, secondfloor, attic, outbackdoor, outdock}; //Pin numbers of corresponding rooms
int ledDim[] = {64, 64, 64, 64, 64, 64}; // PWM values - initial 25% for all
int allarraysize = sizeof(ledArray)/sizeof(ledArray[0]);
int outdockfreightIdx = 5;
int justRoomLEDs[] = {frtroom, firstfloor, secondfloor, attic, outbackdoor, outdock};
int justroomLEDsize = sizeof(justRoomLEDs)/sizeof(justRoomLEDs[0]);

// Misc Variables
int i = 0;
int j = 0;
int longdelay = 300;
int shortdelay = 200;

// Start of Code
void setup() {
starttime = millis();
Serial.begin(9600);
pinMode(frtroom, OUTPUT);
pinMode(firstfloor, OUTPUT);
pinMode(secondfloor, OUTPUT);
pinMode(attic, OUTPUT);
pinMode(outbackdoor, OUTPUT);
pinMode(outdock, OUTPUT);
// pinMode(outdockoffice, OUTPUT);

for (i=0; i<5; i = i + 1) { // Flash all LEDs 5 times
for (j=0; j<justroomLEDsize; j = j + 1) {
digitalWrite(justRoomLEDs[j], HIGH); // turn the LED on (HIGH is the voltage level)
}
delay(longdelay); // wait for long delay
for (j=0; j<justroomLEDsize; j = j + 1) {
digitalWrite(justRoomLEDs[j], LOW); // turn the LED off by making the voltage LOW
}
delay(shortdelay); // wait for short delay
}
}

void print2digits(int number) { // Print with leading zero
if (number >=0 && number < 10) {
Serial.print('0');
}
Serial.print(number);
}

void loop() { // Main Loop
currtime = millis();
elapsetime = currtime - starttime;
elapsetime = (elapsetime * fastratio) + elapseoffset;
floatelapse = float (elapsetime);
hourconv = floatelapse / hourmsecs;
ihour = int(hourconv);
flmin = hourconv - ihour;
imin = 60 * flmin;
if (imin != iprevmin) {
Serial.print(" Time: ");
if (ihour > 23) {
ihour = 0;
starttime = currtime;
elapseoffset = 0;
}
print2digits(ihour);
Serial.print (":");
print2digits(imin);
Serial.println();
iprevmin = imin;

for (j=0; j<allarraysize; j = j + 1) {
if (statArray[j] == false && ihour == onhrArray[j] && imin == onmiArray[j]) {
statArray[j] = true;
analogWrite (ledArray[j], ledDim[j]);
}
else if (statArray[j] == true && ihour == offhArray[j] && imin == offmArray[j]) {
statArray[j] = false;
analogWrite (ledArray[j], LOW);
}
}
}

delay (75);
}

 

Photo Bud (aka John)
The Old Curmudgeon!


   
ReplyQuote
frogandtoad
(@frogandtoad)
Noble Member
Joined: 4 years ago
Posts: 1506
 

@photo-bud

Posted by: @photo-bud

Have decided to keep two LEDs per pin and have also decided to modify code to use analogWrite so as to be able to dim to the degree desired using software, rather than resistors.

For reasons with respect to our previous discussion, I think this is a risky approach to take, and not something I would recommend.

[edit] - For reference, this might help: is-it-ok-to-put-leds-in-parallel?

By the way (programming tip)... there are some refactoring opportunities in your code, for example your 'for loop' could be implemented in a function, to make the code look a whole lot cleaner, so then you can just focus on program logic rather than traversing through clutter.

Less lines of code makes for a better coding and maintaining experience 🙂

Cheers.


   
Photo Bud reacted
ReplyQuote
frogandtoad
(@frogandtoad)
Noble Member
Joined: 4 years ago
Posts: 1506
 

@photo-bud

Posted by: @frogandtoad

By the way (programming tip)... there are some refactoring opportunities in your code, for example your 'for loop' could be implemented in a function, to make the code look a whole lot cleaner, so then you can just focus on program logic rather than traversing through clutter.

Less lines of code makes for a better coding and maintaining experience 🙂

I had a bit of time today, so thought I'd provide an example of what I meant by refactoring, and how it can help to clarify ones code, such that we can now focus on our design logic!  if we implement the following function:

void flashLEDS(byte numIterations, byte numRooms, unsigned long duration = 250) {
    numIterations *= 2; // 50%/50% on/off

    for(int iterator(0); iterator < numIterations; iterator++) {

      for(int room(0); room < numRooms; room++) {
         digitalWrite(justRoomLEDs[room], (iterator % 2 == 0)); 
        }

      delay(duration);
     }
 }

...then we can simply incorporate it into our code as follows, and call it as many times (and anywhere), as we like:

flashLEDS(5, 6);
// Or..
flashLEDS(5, 6, 500); // Using custom delay

Hope this helps!

Cheers.


   
wells5150 and Photo Bud reacted
ReplyQuote
KIMOSUBBY
(@kimosubby)
Active Member
Joined: 2 years ago
Posts: 14
 

Hi John,

I have encountered this problem before of to0 many LEDs off of one board and reaching the boards power supply limit of 200ma. Even getting close to the limit can effect the boards functioning, a slight spike in power demand can cause a board power supply dip of a few milliseconds which causes the board to re-set. Your set-up would have continuous power from the pins when in use.

My solution was to find cheap suitable relay switches of latching mode. Their operation is from the pins, usually about 50ma or less, using a built in optocoupler, and the relay switches on the power to the LEDS, which can be many more than you are using. Just do not code the ON/OFFs for pins all at the same time. The drive power for the relay is also external, usually the same source as for the LEDs. The Arduino pin only activates to instigate the relay operation so is only live momentarily for a latching action, click ON click OFF for example. 

Your code will need little change as the pins are already assigned to LEDs, and these will be wired to a relay instead.

One final comment, I agree that LEDs should have their own resistor, I put them at the relay end of the positive LED wire so there's only the led at the working end to fit where its required. There are loads of sites  on the web where you can calculate a suitable value resistor for the voltage and LED being used.

Kimosubby

 

 


   
Photo Bud reacted
ReplyQuote
Photo Bud
(@photo-bud)
Estimable Member
Joined: 4 years ago
Posts: 111
Topic starter  

@frogandtoad - Thanks, I understood but the further clarification and example are great. I have gotten a little(?) sloppy over the years since my 40+ years of mainframe programming, analysis, and debugging experience. My only feeble defense is that I often write such code, then go back later to structure properly which is highly frowned upon in the C++ and variants world!

@kimosubby - In response to you and others, I've decided to go with separate resistors for each LED. From some of the other comments I've received, it appears that even with all LEDs on at the same time, I will still be well within power limitations especially if I use the PWM to limit brightness. First tests, not in structure, seem to indicate using PWM to limit power output to 25-50% will achieve the look I'm seeking.

About the worst that can happen is that it will fail sometime in my lifetime, which at 78 (in April), may not be all that long! lol If that happens, given the modularity of the design, it can be rectified by implementing other measures such as suggested by @kimosubby.

Photo Bud (aka John)
The Old Curmudgeon!


   
frogandtoad reacted
ReplyQuote
Photo Bud
(@photo-bud)
Estimable Member
Joined: 4 years ago
Posts: 111
Topic starter  

btw - Here is the modularity to which I referred. All components will have 2 mm JST-PH JST connectors.

 

Here is the multi-floor assembly that will be slide into (and be removable from) the one end of the building.

IMG 20210130 134602761

And here, again, is the building into which it fits.

IMG 20210130 164434984

Photo Bud (aka John)
The Old Curmudgeon!


   
ReplyQuote
wells5150
(@wells5150)
Active Member
Joined: 3 years ago
Posts: 7
 

I am still new to Arduino, but I 'm familiar with c++. I have a related question. I'm not sure if this should be a new topic or for another forum, but my queries concern timing. I am building something very similar. Would his code be more effective with millis? When would you use millis vs. chrono

Thanks in advance 🖖🏾

LAW


   
ReplyQuote
Photo Bud
(@photo-bud)
Estimable Member
Joined: 4 years ago
Posts: 111
Topic starter  

@wells5150 - I'm still a noob with all of this, but from what I just looked up, "chrono" is not found in Arduino programming language. There doesn't seem to be any native time functions, thus the need for using "millis".

Photo Bud (aka John)
The Old Curmudgeon!


   
wells5150 reacted
ReplyQuote
Page 1 / 2