Turn a light on then fade off question

Good evening. I am tying to make a sketch that will turn on a car dome light for 20 seconds then fade it off when the key is turned off. I was able to get the timer loop to function but cannot seem to get a Fade off function incorporated. I have read and used the examples but they all seem to center around fading off and on in a forever loop. I also read some forum posts about fading a light on and keeping it on but I could not get it to work the other way around.

// This sketch will keep the dome light on for up 20 seconds after the ACC switch has been turned off

const int accPin = 5;     // input from ACCs
const int domePin = 11;  // output to dome light

int previousACCState;
unsigned long startTimeD;
const unsigned long durationD = 20000; // 20 seconds

void setup() {

  pinMode(accPin, INPUT_PULLUP);  // input from ACC switch
  pinMode(domePin, OUTPUT);       // buzzer output
  digitalWrite(domePin, LOW);
  previousACCState = digitalRead(accPin);
}

void loop() {  //DOME block.
  int currentACCState = digitalRead(accPin);
  
  if ( currentACCState != previousACCState ) {  // Comparing ACC states
    if ( currentACCState == LOW ) {             // ACC turned OFF so record time
      startTimeD = millis();
       }
    else {               // ACC switch on
      startTimeD = 0;

       }
    delay(50);  // debounce
  }
  
  previousACCState = currentACCState; // remember for next time through loop

  if ( startTimeD > 0 && millis() - startTimeD <= durationD ) {       // ACC switch is off and dome light is powered for (durationD)
    digitalWrite (domePin, HIGH);
    } 
    else {
      digitalWrite (domePin, LOW);
    }
} // End all code

Any code suggestions or pointers to topics will be greatly appreciated.

Thank you.

you can fade in a period by using millis(), map() and analogWrite() function.

For example

void loop() {
  unsigned long progress = millis() - startMillis;

  if (progress <= FADE_PEDIOD)
  {
    int brightness = map(progress, 0, FADE_PEDIOD, 255 , 0);
    analogWrite(ledPin, brightness);
  }
}

If your sketch has nothing else to do you can use delays and loops:

// This sketch will keep the dome light on for up 20 seconds 
// after the ACC switch has been turned off


const int accPin = 5;     // input from ACCs
const int domePin = 11;  // output to dome light
const unsigned long durationD = 20000; // 20 seconds


void setup()
{
  pinMode(accPin, INPUT_PULLUP);  // input from ACC switch
  pinMode(domePin, OUTPUT);       // buzzer output
  digitalWrite(domePin, LOW);
}


void loop()    //DOME block.
{
  // Do nothing until the accessories are turned off
  while (digitalRead(accPin) == HIGH) {}


  // Turn on the dome light
  digitalWrite(domePin, HIGH);


  // Keep it on full for 20 seconds
  delay(durationD);


  // Dimout the dome light
  for (int brightness = 255; brightness > 0; brightness--)
  {
    analogWrite(domePin, brightness);
    delay(10);  // about 2.55 seconds fade period
  }


  // Do nothing until the accessories come back on.
  while (digitalRead(accPin) == LOW) {}
}

I'm surprised that you are using INPUT_PULLUP or the accessory input. The Arduino UNO inputs can't stand more than about 5.5V so I would have expected a 1:3 voltage divider going to an INPUT pin.

Sir - thanks for the code fix. I tested it and it almost worked perfectly (but better than what I could do!). The light never faded all the way off so I added an "=" in the loop to ensure the brightness went to zero.

for (int brightness = 255; brightness >= 0; brightness--)

it appears to be working now.

Thanks again.

SIr - a quick update. It appears that the light comes on and fades whenever there is a state change, i.e. when the ACC is off and when it is on.

I will look over the code and see if I can debug it. fingers crossed...

burrism:
SIr - a quick update. It appears that the light comes on and fades whenever there is a state change, i.e. when the ACC is off and when it is on.

I will look over the code and see if I can debug it. fingers crossed...

My guess would be contact bounce. If that is the case, a short delay after the final "while()" loop would help.
Explanation: There is very little time (a few microseconds) between the final "while()" loop detecting that the ACC has turned ON and the top "while()" loop detecting that the ACC has turned OFF. I the contacts bounce they would go from OFF to ON to OFF to ON several times over the course of a few milliseconds. The first OFF to ON will cause the final "while()" loop to exit within a few microseconds. When loop() re-starts the top "while()" loop will start checking the pin every few microseconds. If it checks the input one of the times it bounced OFF it will exit the "while()" loop and turn the lamp on for 20 seconds. Adding a 10 millisecond delay after the final "while()" loop will give the contacts time to settle ON before the top loop starts checking for an OFF signal.

noiasca:
really? How about replacing the Arduino with one diode and a electrolytic capacitor?

My old 1983 Mercedes 300SD did that with the dome lights using a single transistor, a resistor and capacitor. As the capacitor charged through the resistor, it slowly biased the transistor to cut-off voltage and that turned the light down and eventually off.
Paul

Nice idea guys however this sketch is part of a larger project.

Thanks again for checking out my post.