Combine lights fading on while displaying text

All of this is in regards to a little free library that has internal lights and landscape lights. The door is opened, lights fade on, and text is displayed.

I have read a couple of different forums where people have run into similar trouble having the arduino appear to perform multiple functions simultaneously. I haven't been able to manipulate the language to work with my circumstance.

It took a very long time to get all this code to perform its basic function reliably. Though I realize it's excessively wordy, and could likely be trimmed down significantly and still perform its basic function. I just haven't had the confidence to mess with something that's already functional.

My problem is, currently, when the door is opened, there is a significant delay before any text starts scrolling. I am hoping to set this up so that the lights fade on, and text begins scrolling, all apparently at the same time.

Anybody have input on if/how this is possible? (I'll include the code in my next post)

/*
*/

// include the library code:
#include <LiquidCrystal.h>
#include <DHT.h>
//#include <Button.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(2, 4, 7, 8, 12, 13);
#define DHTPIN 16     // Pin 16(A2) to temp sensor middle pin
#define DHTTYPE DHT22   // DHT 22  (AM2302)
DHT dht(DHTPIN, DHTTYPE);


void fade_on_lights();
void fade_off_lights();
void fade_on_lcd_backlight();
void fade_off_lcd_backlight();
void door_open_lcd_cycle();
void display_current_temp();
void display_batteryVoltage();
void display_low_battery();
void turn_on_LowBattLED();
void turn_off_LowBattLED();
void LibraryTimedOut();
void CheckVoltageButton();
void Make_Sure_Lights_Are_Off();

// this constant won't change:
const int ButtonPin = 15;     // the pin that the pushbutton is attached to (15(A1) to gnd)
const int SwitchPin = 17;     // the pin that the reed switch is attached to (17(A3) to gnd)
const int voltpin = A0;       // analog input for voltage sense 
const int ledPin1 = 3;        // interior light the pin that the LED is attached to  (5 to gnd)
const int ledPin2 = 5;        // landscape light pin that the LED is attached to  (6 to gnd)
const int ledPin3 = 6;        // landscape light
const int ledPin4 = 9;        // landscape light
const int ledPin5 = 10;       // landscape light
const int LowBattLED = 19;    //low battery lighting
const int WarningLEDPin = 18; //door left open LED
//attached, not active.  const int ledpin6 = 20;
const int lcdledPin = 11;

// Variables will change:
int SwitchCounter = 646;  //current as of 07/09/16     // counter for the number of times Door has been opened
int SwitchState = 0;         // current state of the Door Switch
int lastSwitchState = 0;     // previous state of the Door Switch
int ButtonState = 0;    //current state of the button
int lastButtonState = 0;  //previous state of the button


//door switch initialize
#define TIMEOUT_THRESHOLD 600000               // Timeout set to maximum of 10 minutes of continuous light.
#define DEBOUNCE_DELAY    50                 // Debounce for 50ms.


//battery voltmeter initialize
float vout = 0;
float batteryVoltage = 0;
float R1 = 996000.0;  //993000.0;           //prototype board resistor 998000.0;
float R2 = 281200.0;  //267700.0;           //prototype board resistor 267500.0;
int value = 0;


bool          debouncing       = false;      // Start with no debouncing until the door opens.
bool          DoorState        = true;       // Start with the door closed.
bool          lastDoorState    = true;       // Start with the previous door state closed.
bool          timeoutRunning   = false;      // Start with no timeout running.
unsigned long timeout          = millis();   // Initialize the timeout timer.
unsigned long lastDebounceTime = millis();   // Initialize the timeout timer.




void setup()
{ //begining of void setup
  lcd.begin(16, 2);
  dht.begin();

  pinMode(SwitchPin, INPUT_PULLUP); // initialize the switch pin as an input
  pinMode(ButtonPin, INPUT_PULLUP); // initialize the button pin as an input
  pinMode(DHTPIN, INPUT_PULLUP);  //initialize the temp sensor pin as input pulled up
  pinMode(ledPin1, OUTPUT);   // initialize the LED as an output:
  pinMode(ledPin2, OUTPUT);  //initialize LED as an output
  pinMode(ledPin3, OUTPUT);
  pinMode(ledPin4, OUTPUT);
  pinMode(ledPin5, OUTPUT);
  pinMode(LowBattLED, OUTPUT);
  pinMode(WarningLEDPin, OUTPUT);
  pinMode(lcdledPin, OUTPUT);
} //end of void setup



void loop()

{ // Begin Loop check battery voltage
  value          = analogRead(voltpin);
  vout           = (value * 4.985) / 1024.0;
  batteryVoltage = vout / (R2 / (R1 + R2));
  if( batteryVoltage < 11.0 )  //If voltage is less than 11v, charger has failed and running on batteries


  { // Battery is NOT OK. Run the low voltage code.

  digitalWrite(WarningLEDPin, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(750);                       // wait for a second
  digitalWrite(WarningLEDPin, LOW);    // turn the LED off by making the voltage LOW
  delay(750);                       // wait for a second
    
    DoorState = digitalRead(SwitchPin);  // compare the SwitchState to its previous state  LATEST ADD
    if( debouncing )
    { // Debouncing the button. See if it's done. If not then do nothing at all, just let the loop repeat and check again next time.
      if( (millis() -lastDebounceTime) >= DEBOUNCE_DELAY)
      { // Should be debounced by now so read and process the damn thing.
        DoorState  = digitalRead( SwitchPin );
        debouncing = false;                                     // done with debouncing.
       
        if( DoorState != lastDoorState )                        // only do something when the door state changed.
        { // Debounced button has changed state.
          lastDoorState = DoorState;                            // Remember the new state.
         
          if( DoorState )
          { // Door was just closed
            turn_off_LowBattLED();
            fade_off_lcd_backlight();
            Make_Sure_Lights_Are_Off();
            timeoutRunning = false;                             // Stop timeout timer when lights turn off.
          }
          else
          { // Door was just opened
            ++SwitchCounter;
            turn_on_LowBattLED();
            fade_on_lcd_backlight(); 
            display_low_battery();
            CheckVoltageButton();          
            timeoutRunning = true;                              // Start up the timeout timer.
            timeout        = millis();                          // Reset the timer for a new period.
          }
        }
      }
    }
    else
    { // Not debouncing. Check for a state change in the switch. If it hasn't changed, do nothing more.
      if( DoorState != lastDoorState )
      { // Button has changed state. Start debouncing the button.
        debouncing       = true;
        lastDebounceTime = millis();
      }
    }
  }
  

 
  else
  { // Battery is OK. Run the library normally.
    DoorState = digitalRead(SwitchPin);  // compare the SwitchState to its previous state
    if( debouncing )
    { // Debouncing the button. See if it's done. If not then do nothing at all, just let the loop repeat and check again next time.
      if( (millis() -lastDebounceTime) >= DEBOUNCE_DELAY)
      { // Should be debounced by now so read and process the damn thing.
        DoorState  = digitalRead( SwitchPin );
        debouncing = false;                                     // done with debouncing.
       
        if( DoorState != lastDoorState )                        // only do something when the door state changed.
        { // Debounced button has changed state.
          lastDoorState = DoorState;                            // Remember the new state.
         
          if( DoorState )
          { // Door was just closed
            fade_off_lights();
            Make_Sure_Lights_Are_Off();
            timeoutRunning = false;                             // Stop timeout timer when lights turn off.
          }
          else
          { // Door was just opened
            ++SwitchCounter;
            fade_on_lights();                                   // Turn on the lights.
            //fade_on_lcd_backlight(); //REMOVE WHEN FINAL
            door_open_lcd_cycle();
            display_current_temp();
            CheckVoltageButton();                               // Check to see if voltage button is pressed
            timeoutRunning = true;                              // Start up the timeout timer.
            timeout        = millis();                          // Reset the timer for a new period.
          }
        }
      }
    }
    else
    { // Not debouncing. Check for a state change in the switch. If it hasn't changed, do nothing more.
      if( DoorState != lastDoorState )
      { // Button has changed state. Start debouncing the button.
        debouncing       = true;
        lastDebounceTime = millis();
      }
    }
  }
 
  // Deal with turning off the lights when they've been on too long.
  if( timeoutRunning && ((millis() -timeout) >= TIMEOUT_THRESHOLD))
  { // Lights have been on too long. Turn them all off.
    LibraryTimedOut();
    timeoutRunning = false;                                     // Turn off the timeout timer.
  }
}

//END OF LOOP

Continued Code In Next Post

//begin defining all actions


void fade_on_lights()
{ // begin fade_on_lights
  digitalWrite(WarningLEDPin, LOW);  
  int pins[6]   = { ledPin1, ledPin2, ledPin3, ledPin4, ledPin5, lcdledPin };
  int delays[6] = { 60, 25, 20, 13, 8, 30 };

  for( int p = 0; p < 7; p++ )
    for( int fadeValue = 0; fadeValue <= 255; fadeValue += 5)  // fade in from min to max in increments of 5 points:
    { // Sets the value (range from 0 to 255)
      if( p != 6 )                                             // skip pin6
      { analogWrite( pins[p], fadeValue );
        delay( delays[p] );                                    // wait to see the dimming effect.
      }
    }
}



void fade_off_lights()
{ // begin fade_on_lights
  lcd.clear();
digitalWrite(WarningLEDPin, LOW);
  int pins[6]   = { lcdledPin, ledPin5, ledPin4, ledPin3, ledPin2, ledPin1 };
  int delays[6] = { 15, 15, 15, 20, 25, 35 };

  for( int p = 0; p < 7; p++ )
    for( int fadeValue = 255; fadeValue >= 5; fadeValue -= 5)  // fade in from min to max in increments of 5 points:
    { // Sets the value (range from 0 to 255)
      if( p != 6 )                                             // skip pin6
      { analogWrite( pins[p], fadeValue );
        delay( delays[p] );                                    // wait to see the dimming effect.
      }
    }
}



void turn_on_LowBattLED()
{
  digitalWrite(LowBattLED, HIGH);
}


void turn_off_LowBattLED()
{
  digitalWrite(LowBattLED, LOW);
}



void Make_Sure_Lights_Are_Off()
{
  analogWrite(ledPin1, 2);
  analogWrite(ledPin2, 2);
  analogWrite(ledPin3, 2);
  analogWrite(ledPin4, 2);
  analogWrite(ledPin5, 2);
  digitalWrite(lcdledPin, LOW);
  digitalWrite(LowBattLED, LOW);
}


void fade_on_lcd_backlight()
{ //begin fading on LCD backlight
  digitalWrite(WarningLEDPin, LOW);
  for (int fadeValue = 10 ; fadeValue <= 255; fadeValue += 5)
  {
    // sets the value (range from 0 to 255):
    analogWrite(lcdledPin, fadeValue);
    // wait for 30 milliseconds to see the dimming effect        // sets the value (range from 0 to 255)
    delay(30);
  }
}   //end fading on LCD backlight



void fade_off_lcd_backlight()
{ //begin fading off lcd backlight
  lcd.clear();
  digitalWrite(WarningLEDPin, LOW);
  for (int fadeValue = 255 ; fadeValue >= 0; fadeValue -= 5)
  {
    // sets the value (range from 0 to 255):
    analogWrite(lcdledPin, fadeValue);
    // wait for 30 milliseconds to see the dimming effect
    delay(35);
  }
}   //end fading off lcd backlight



void door_open_lcd_cycle()
{ //begin printing welcome messages to LCD
  lcd.clear();
  lcd.print("   Welcome To");
  delay(2800);
  lcd.clear();
  lcd.print("   Our Little");
  lcd.setCursor(0, 2);
  lcd.print("  Free Library!");
  delay(2800);

  for (int positionCounter = 0; positionCounter < 16; positionCounter++)
  {
    // scroll one position left:
    lcd.scrollDisplayLeft();
    // wait a bit:
    delay(150);
  }

  // scroll 13 positions (string length) to the left
  // to move it offscreen left:

  lcd.clear();
  lcd.print("   ");
  lcd.print(SwitchCounter);
  lcd.print(" Visitors");
  lcd.setCursor(0, 2);
  lcd.print("  and counting!");
  delay(2800);

  // scroll 29 positions (string length + display length) to the right
  // to move it offscreen right:
  for (int positionCounter = 0; positionCounter < 16; positionCounter++)
  {
    // scroll one position right:
    lcd.scrollDisplayRight();
    // wait a bit:
    delay(150);
  }

    lcd.clear();
  lcd.print("  Take A Book,");
  lcd.setCursor(0, 2);
  lcd.print("  Leave A Book,");
  delay(2800);

  lcd.clear();
  lcd.print("      Or ");
  lcd.setCursor(0,2);
  lcd.print("     Both!");
  delay(2800);

//  lcd.clear();
//  lcd.createChar(0, smiley);
//  lcd.write(byte(0));
//  delay(2800);

}   //end printing welcome messages to LCD




void display_current_temp()

{ //begin reading from temp sensor and display value
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();
  float t = dht.readTemperature();
  t = t * 9 / 5 + 30;      //32;   (calibrate as necessary)

  // check if returns are valid, if they are NaN (not a number) then something went wrong!
  if (isnan(t) || isnan(h))
  { //if sensor is failed
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Failed to read");
    lcd.setCursor(0, 1);
    lcd.print("from DHT");
    //Serial.println("Failed to read from DHT");
  }   //if sensor is failed
  else
  { //if sensor is not failed
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Temp: ");
    lcd.print(t);
    lcd.print("F");

    lcd.setCursor(0, 1);
    lcd.print("Humidity: ");
    lcd.print(h);
    lcd.print("%");

    //Serial.print("Humidity: ");
    //Serial.print(h);
    //Serial.print(" %\t");
    //Serial.print("Temperature: ");
    //Serial.print(t);
    //Serial.println(" *C");


  }  //if sensor is not failed
}   //end of displaying temp value



void display_batteryVoltage()
{ //begin displaying batteryVoltage
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Charge Status");
  lcd.setCursor(0, 1);
  lcd.print(batteryVoltage);
  lcd.print("v");

  Serial.print(batteryVoltage);
  Serial.println (" V");
}   //end displaying batteryVoltage



void display_low_battery()
{ //begin displaying low battery message
  lcd.clear();
  lcd.setCursor(6, 0);
  lcd.print("LOW");
  lcd.setCursor(4, 2);
  lcd.print("BATTERY");
  delay(3000);
}   //end displaying low battery message



void LibraryTimedOut()
{
  lcd.clear();
  lcd.print("LIBRARY TIME OUT");
  lcd.setCursor(0,2);
  lcd.print("Cycle Door Reset");
  delay(8000);
  lcd.clear();
  digitalWrite(ledPin1, LOW);
  digitalWrite(ledPin2, LOW);
  digitalWrite(ledPin3, LOW);
  digitalWrite(ledPin4, LOW);
  digitalWrite(ledPin5, LOW);
  digitalWrite(lcdledPin, LOW);
  digitalWrite(WarningLEDPin, HIGH);
}


void CheckVoltageButton()
{ 
   if( digitalRead( ButtonPin) == LOW )
   display_batteryVoltage();
   delay(2500);
}

To get multiple things happenning at the same time, you have to turn code like this inside-out. It's a fairly big job.

Instead of having a function that fades the light, you have a function that checks a current 'light fade state' set of variables, looks at the current millis() time, and works out if it is now time to fade the light another notch. Most of the time, this function returns without doing anything. Your loop() calls that function every time it executes, unconditionally. To make the light fade, you set a variable like "fade_light_3" to true, and you set a variable "fade_light_3_start_ms" to the current millis(). That function which is called every time unconditionally wlll commence fading the light.

enum LightState {
  OFF = 0,
  FADING_ON = 1,
  ON = 2,
  FADING_OFF = 3
};

LightState lightState;

uint32_t fadeStartMs;

void loop() {
  manageLightFading();
  // rest of your code goes here :)
}

void startFadingOn() {
  lightState = FADING_ON;
  fadeStartMs = millis();
  / *if you want to manage the case where a fade on can happen in the middle
   of a fade off, you would do that by performing some arithmetic on fadeStartMs */
}

void startFadingOf() {
  lightState = FADING_OFF;
  fadeStartMs = millis();
  / *if you want to manage the case where a fade off can happen in the middle
   of a fade on, you would do that by performing some arithmetic on fadeStartMs */
}

void manageLightFading() {
  switch(lightState) {
    case FADING_ON:
      if the fade time is complete {
        set the output to full on
        lightState = ON;
      }
      else {
        work out what the brighness of the light should be right now
        set the output
      }
      break;

    case FADING_OFF:
      if the fade time is complete {
        set the output to full off
        lightState = OFF;
      }
      else {
        work out what the brighness of the light should be right now
        set the output
      }
      break;

    // default: do nothing
  }
}

There's additional complexity in your case because you have different fade rates for the different lights, and they appear to fade in sequence. If that's what you want, the fade state would also include an index into the array to indicate which light is currently being faded. When a given light's fade time is complete, the code would set the state on to the next light.

If you haven’t already, check out: http://forum.arduino.cc/index.php?topic=223286.0
Also, if you want to edit your code without losing the original go to on the IDE menu bar, go down to and enter a new name (something like myProgram_New) then edit the new program, your original will still be there untouched if you crash.