Fade and Chase some lights in ONE system

So, shortly after you become a professional in this railroad hobby, you start getting good at this, build a Fading LED here and a chaser on a movie theater over there, and then you realize, I have enough pins on one Arduino to maybe combine the two.

After you waited for the coffee machine to finish, you move over to the microwave to wait for the bacon to cook and after that you push the bread into the toaster, and stand there and wait to get the jolt when the toast pops out and then you realize that your coffee is cold. Well, that is not how we make breakfast, you get it all started and tend to it as each task completes and have a full tummy in a third of the time.

With the Arduino's single thread, you can't really schedule them like your microwave, because you still need to make the 'waves'. If you simply use 'delay()' to wait for time to go by, everything else has to wait too, so what we do here is use 'millis()' to tell use how much time has gone by since the chip started running, compare that to a value we stored, and when 2 minutes went by, we pop the bread from the toaster, when 3 minutes has gone by since we started the microwave, we take the bacon out of the microwave, and every 5 minute mark, we make the next cup of coffee.

This is a lot easier when we use Object Orientated Programming (OOP), since all the data and code stays together and we can reuse it over and over, without raking 50 lines of code from an older program. You simply copy the Class over, make the object you need (instantiate, sorry) with the pins and timeouts required, and then call the Update() function when you want to, so it can figure out if enough time as gone by to do the next thing. So in the end you have:

void loop() { chaser1.Update();

fader1.Update();

fader2.Update();

} // and that is the end of your loop!

So here is the code we combined for Vance's Haunted House (fading in and out the lights of the top and bottom floor, one after the other) and the Chasing lights on or around his movie theater sign (notice no delay() anywhere!!!):

// Fading FADE1 and FADE2 LEDs in and out, one after the other, like the // top and bottom floor of a haunted house;// while also running CHASING LEDs,// 1 thru 6 (max 10), like on top of a movie theater.//// Two classes, FadeLite to fade a light from off to on and from on to off when needed.// ChaseLites for turning LEDs on in a sequence.//// Author Vance Nurmi, under very tight supervision of Speed// Version 1.2 on 2016/07/08//// Chaser LED pin numbers #define CHASE6 7 #define CHASE5 6 #define CHASE4 5#define CHASE3 4#define CHASE2 3#define CHASE1 2// Fading LED pins#define FADE1 9#define FADE2 10 int analog0Pin = A0; // button to start waveint val0 = 0; // variable to store the value read// time in milliseconds, better values for a demo#define FADETIME 1000#define UPDATETIME 50#define CHASERTIME 150#define MAXCHASELITES 10class FadeLite { // Class Member Variables // These are initialized at startup int ledPin; // the number of the LED pin long int fadeTime; // how long to spend fading long int stepSize; // size of steps to take to fade long int updateTime; // how often to update // These maintain the current state int ledState; // ledState used to set the LED, 0 off, 1 on, 2 fading to on, 3 fading to off int ledValue; // 0 thru 255 for full off thru full on unsigned long previousMillis; // will store last time LED was updated void Output() { analogWrite( ledPin, ledValue ); } // Outout public: // Constructor - creates a Flasher // and initializes the member variables and state FadeLite( int pin, long int fTime ) { ledPin = pin; pinMode( ledPin, OUTPUT ); updateTime = UPDATETIME; fadeTime = fTime; stepSize = int( 256 * ( (1.0 * UPDATETIME ) / ( 1.0 * fadeTime ) ) ); if ( stepSize < 1 ) { stepSize = 1; updateTime = fadeTime / 255; } // if FullOff(); previousMillis = millis(); } // FadeLite constructor // I used this to send some serial data to the PC. Nice to use when you need // to see what the math looks like when you want to increase the updatetime since // your steps are already 255 and you want the fading to take longer than UPDATETIME * 255! void FullOn() { ledValue = 255; ledState = 1; Output(); } // FullOn void FullOff() { ledValue = 0; ledState = 0; Output(); } // FullOff void Reset() { FullOff(); previousMillis = millis(); } // Reset bool IsOn() { return ledState == 1; } // IsOn() bool IsOff() { return ledState == 0; } // IsOff() void Toggle() { if ( ledState == 0 ) { //FullOn();// TurnOn(); } else { if ( ledState == 1 ) { //FullOff(); // TurnOff(); } // if } // if } // Toggle() void TurnOn() { ledState = 2; } // TurnOn() void TurnOff() { ledState = 3; } // TurnOff() void Update() { // check to see if it's time to change the state of the LED unsigned long now = millis(); if ( now - previousMillis >= updateTime ) { previousMillis = now; switch ( ledState ) { case 0: break; case 1: break; case 2: ledValue += stepSize; if ( ledValue >= 255 ) { ledValue = 255; ledState = 1; } // if on break; case 3: ledValue -= stepSize; if ( ledValue <= 0 ) { ledValue = 0; ledState = 0; } // if of break; }; // switch Output(); // Update the actual LED } // if, time for change yet? } // Update}; // FadeLiteclass ChaseLites { // Class Member Variables // These are initialized at startup int led[MAXCHASELITES]; // array storing LED pins int numLEDs; long int updateTime; // how often to update // These maintain the current state int whichLedOn = 4; // 0 is none int ledState; // 0 off, 1 running unsigned long previousMillis; // will store last time LED was updated public: // Constructor - creates a Flasher // and initializes the member variables and state ChaseLites( long int fTime, int numPins, int pins[] ) { numLEDs = numPins; ledState = 0; // off for ( int i = 0; i < numLEDs; i++ ) { led[i] = pins[i]; pinMode( led[i], OUTPUT ); //digitalWrite( led[i], LOW ); } // for updateTime = fTime; FullOff(); previousMillis = millis(); } // FadeLite constructor void Output() { if ( ledState == 1 ) { for ( int i = 0; i < numLEDs; i++ ) { // run through all the LEDs digitalWrite( led[i], whichLedOn == i?HIGH:LOW ); // and only turn the selected one on } // for } else { for ( int i = 0; i < numLEDs; i++ ) { // run through all the LEDs digitalWrite( led[i], LOW ); // and turn them off } // for } // if ledState on } // Outout void FullOff() { ledState = 0; Output(); } // FullOff void Reset() { FullOff(); // turn all off previousMillis = millis(); // and reset the previousTime } // Reset bool IsAnyOn() { return ledState != 0; } // IsOn() bool IsOff() { return ledState == 0; } // IsOff() void TurnOff() { ledState = 0; Output(); } // TurnOff() void Update() { // check to see if it's time to change to the next LED unsigned long now = millis(); // the time now if ( now - previousMillis >= updateTime ) { // if it is time for the next one previousMillis = now; // save the time whichLedOn++; // and increase to the next LED if ( whichLedOn >= numLEDs ) whichLedOn = 0; // if at max, go back to zero Output(); // Update the actual LED } // if, time for change yet? } // Update}; // ChaseUpTo10LEDs// creating the objectsFadeLite fader1( FADE1, FADETIME );FadeLite fader2( FADE2, FADETIME );boolean leftOn; // we are using a variable to keep track of which FadeLite to fade.int chaserPins[] = { CHASE1, CHASE2, CHASE3, CHASE4, CHASE5, CHASE6 }; // simply add or remove a pin hereChaseLites chaser1( CHASERTIME, sizeof( chaserPins) / sizeof( chaserPins[0] ), chaserPins ); // this will figure out how many pins in usevoid setup() { pinMode( analog0Pin, INPUT ); Serial.begin( 115200 ); // setup serial for 115200 baud Serial.println( "Fade_and_Chase version 2016.07.08_1.2" ); // print the version, use Ctrl-M to see leftOn = true; // starting with the left LED fader1.TurnOn(); // need to turn it on to get it out of state 0 // and tell it we are turning it on} // setupvoid loop() { chaser1.Update(); // chaser is ready, update it! // the next if code will cycle between fader1 and fader2, fading it in and and out, one after the other // could have created a Class that uses two pins and deal with this internally, and then you only need fadeTwo.Update() if ( leftOn ) { // do fader1 this round fader1.Update(); // update the first one if ( fader1.IsOn() ) // if it is fully on, turn it off now fader1.TurnOff(); if ( fader1.IsOff() ) { // when it is fully off, lets go back to the other lite fader2.TurnOn(); // need to turn it on to get it out of state 0 leftOn = false; } // if } else { // do fader2 now fader2.Update(); // update the second one, if it is its turn if ( fader2.IsOn() ) // if it is fully on, turn it off now fader2.TurnOff(); if ( fader2.IsOff() ) { // when it is fully off, lets go back to the other lite fader1.TurnOn(); // need to turn it on to get it out of state 0 leftOn = true; } // if } // else} // loop