help with multiple digital inputs for a car lighting circuit

hi everyone.

i'm trying to design a circuit to to the interior light of a car on when door is open and then turn the light of after 10 seconds when the door is shut. i can make it do this but i also want it turn on but if the gear selector is in drive there will be no delay.

This is my code so far

unsigned long elapsedTime;
unsigned long onTime;

// constants won't change
const int interior = 11; // interior lamps O/P pin 11
const int doorOpen = 13; // door open I/P pin 13
const int pn = 12; // park/neutral I/P pin 12

// variables will change
int doorOpenState = 0; // current  state of the door open
int lastDoorOpenState = 0; // previous state of the door ope

void setup()
{
  onTime = millis();
  onTime = elapsedTime; 
  pinMode (interior, OUTPUT);  
  pinMode (doorOpen, INPUT);     
  pinMode (pn, INPUT_PULLUP);
}

void dooropen()
{
  if (digitalRead(doorOpen) == LOW)   // Switch is closed to start LED timer
         {
          digitalWrite(interior, HIGH);  // LED comes On  
          onTime = millis();  
          }
          if (digitalRead(pn) == LOW) {
            digitalWrite(interior,LOW);
          }
      if(onTime > 0 && millis() - onTime > 5000)  
            {      
            digitalWrite(interior, LOW);  // LED goes off
             onTime = 0;
            }
}

void loop() {
  
  dooropen();
}

Hi, welcome to the forum.

Is this for school ? It is something that seems simple, but it needs careful thinking how to translate the conditions into code. It is a good example how to learn to code.

You have to be sure what OnTime is used for, before you start writing code.
In setup(), OnTime is set to millis(), I don't know why. After that it is set to elapsedTime, I also don't understand that.

I think it is easier to make a new variable: bool lightOn ;
It is the state of the light, so it can also be called "lightState" or so.
Whenever the interior light is switched on, make it true, and false when interior light is switched off.
Use a variable to remember the time at which the lights are switched on : unsigned long lightOnMillis ;
Remember the time of course with : lightOnMillis = millis();

With those two variables, you know if the lights are switched on, and how long ago it was.

I think you don't want to turn on the lights as long as the door is open. Turn the lights on just once, at the moment the door is opened.

Please name the pin number with the term 'pin', like pinInteriror, or interirorPin. Do that also for the other pins.

Hi.

it is for a small project i am doing for work but im not very fluent with programming.

How would them changes work with the second input from the gear selector pin

That depends on the moment you check that condition.
I think at the moment the door is closed, you check the gear selector.

I would rather not rewrite your code, because if you don't understand it, you can't alter it.

You use the onTime for the moment the lights are turned on, but you use also onTime to check if the value is above zero. I would like to split that into two variables, one for the time and one for a flag to indicate that the lights are on. And elapsedTime is not used at all.

Could you do a little cleanup of your code, and add comment how exactly the timing variables are used ?

i've changed a few things round and put in the comments

unsigned long lightOnTime; // to store current time

// constants won't change
const int interiorPin = 11; // interior lamps O/P pin 11
const int doorOpenPin = 13; // door open I/P pin 13
const int parkPin = 12; // park/neutral I/P pin 12

void setup()
{
  pinMode (interiorPin, OUTPUT);  // O/P pin to turn on the interior lamps
  pinMode (doorOpenPin, INPUT);   // I/P from the door switch  
  pinMode (parkPin, INPUT_PULLUP); // I/P from the park/neutral switch
}

void dooropen()
{
  if (digitalRead(doorOpen) == LOW)   // test if the door has been openned
         {
          digitalWrite(interiorPin, HIGH);  // if door is open then turn on the interior lamp 
          lightOnTime = millis();  // store the current time in variable lightOnTime
          }
      if(lightOnTime > 0 && millis() - lightOnTime > 5000) // test to seee if 5 seconds has passed 
            {      
            digitalWrite(interiorPin, LOW);  // if 5 seconds has passed then turn of the interior lamp
             lightOnTime = 0; // rest the time back to 0
            }
}

void loop() {
  
  dooropen();
}

When the door is open, the "if (digitalRead(doorOpen) == LOW)" is always executed, as long as the door is open. It is okay, if you want that to happen.

You could add another if-statement.
If lightOnTime is not zero (or above zero) and the door is closed and the gear shift is in park, turn off the lights and set lightOnTime to zero.

That won't make pretty code, and you will run intro trouble when adding debouncing or other extra things.

Could you also make a nice text layout of the sketch ? There is an auto-text-format tool in the menu.

When an Arduino board is used in a car, extra safety should be added against voltage peaks via the power input and via the Arduino pins.

every time the door is open i want the light to turn on. just what happens when the door is shut will change depending on if the park switch is low. if it is low then there will be no delay on the light. if it is high then there will be a 5 second delay.

here is the auto format code

unsigned long lightOnTime; // to store current time

// constants won't change
const int interiorPin = 11; // interior lamps O/P pin 11
const int doorOpenPin = 13; // door open I/P pin 13
const int parkPin = 12; // park/neutral I/P pin 12

void setup()
{
  pinMode (interiorPin, OUTPUT);  // O/P pin to turn on the interior lamps
  pinMode (doorOpenPin, INPUT);   // I/P from the door switch  
  pinMode (parkPin, INPUT_PULLUP); // I/P from the park/neutral switch
}

void dooropen()
{
  if (digitalRead(doorOpen) == LOW)   // test if the door has been openned
  {
    digitalWrite(interiorPin, HIGH);  // if door is open then turn on the interior lamp 
    lightOnTime = millis();  // store the current time in variable lightOnTime
  }
  if(lightOnTime > 0 && millis() - lightOnTime > 5000) // test to seee if 5 seconds has passed 
  {      
    digitalWrite(interiorPin, LOW);  // if 5 seconds has passed then turn of the interior lamp
    lightOnTime = 0; // rest the time back to 0
  }
}

void loop() {

  dooropen();
}

You can add the other if-statement I wrote about.

Testing if the door is open is something different than using the event when a door is opened.
You can remember in a variable if the door was open or closed and a change in that is the event.

It is also possible to make state-machine with a single variable that keeps the state.
For example a variable "myState", and it can be "DOOR_CLOSED", "DOOR_OPEN", "DOOR_CLOSED_LIGHTS_ON" and so on.
It makes the code easier to read, and a switch-statement can be used for the states.
For example here : http://hacking.majenko.co.uk/finite-state-machine
The green-on-black text shows the switch-statement and things are done according to the state, and the state is set to a new value.
If you like that, it is easy to rewrite the sketch, if you don't like it then a few if-statements can do the same.

the switch statement does look a bit easier to follow and understand.

is the code for this easy to write.

I've never tried using switch statements.

there would not need to be any debounce for the switches as this is taken care of in the circuit and the power supply to the circuit is 5 volts from a dc-dc charge pump circuit

Okay, state machine it is.
I have to warn you, I like to set things up in a broad and big way.
To test the sketch on my Uno, I have added a few things.

The "enum" is just some extra in the c-language. It creates a bunch of numbers, that's all.

I use boolean variables for the door and park.
If ( doorOpen ) means a test if the door is open.
if ( !doorOpen ) reads as "if door not open", it is true if the door is closed.

The state machine makes it easy to detect if the door has just been opened. When the state tells that the door is closed, and the inputs say that the door is open, then the door has just been opened at that very moment.

Do you see how the sketch is divided into two parts ? One part collects all the data (and for example sensors), the other part is the state machine.

// 
// Arduino forum topic : http://forum.arduino.cc/index.php?topic=290915.0
//
// WARNING : when DEBUG is enabled, there is a delay at the end of loop().
// I have added _PULLUP to doorOpenPin.
// Is the park true when the input is LOW ?
//


#define DEBUG
// #define ENABLE_TEST_ON_MY_UNO

#ifdef ENABLE_TEST_ON_MY_UNO
const int interiorPin = 13;     // use system led at pin 13
const int doorOpenPin = 2;      // door open I/P pin
const int parkPin = 8;          // park/neutral I/P pin
#else
// constants won't change
const int interiorPin = 11;     // interior lamps O/P pin 11
const int doorOpenPin = 13;     // door open I/P pin 13
const int parkPin = 12;         // park/neutral I/P pin 12
#endif

enum
{
  STATE_UNKNOWN,                // 0: unknown or idle
  STATE_DOOR_CLOSED_NO_LIGHT,   // 1: door closed and everything okay
  STATE_DOOR_OPEN_NO_LIGHT,     // 2: extra state
  STATE_DOOR_OPEN_LIGHT,        // 3: the door is open and light is on
  STATE_DOOR_CLOSED_TIMER,      // 4: the lights are on with a timer
} state;

unsigned long lightOnTime;      // to store current time in millis

void setup()
{
#ifdef DEBUG 
  Serial.begin (9600);
  Serial.println ("\n-------------------------");
  Serial.println ("Door test");
  Serial.println ("-------------------------");
#endif

  state = STATE_UNKNOWN;           // Not known, the Arduino has just powered on.
  
  pinMode (interiorPin, OUTPUT);   // O/P pin to turn on the interior lamps
  pinMode (doorOpenPin, INPUT_PULLUP);  // I/P from the door switch  PULLUP ?
  pinMode (parkPin, INPUT_PULLUP); // I/P from the park/neutral switch
}

void loop() 
{
  // Boolean variables makes it easy to test them in the state machine.
  boolean doorOpen;
  boolean park;

  // --------------------------------------------------
  // Gather all the information from the inputs/sensors
  // --------------------------------------------------
  if (digitalRead(doorOpenPin) == LOW)   // test if the door is open
    doorOpen = true;
  else
    doorOpen = false;
  
  if (digitalRead(parkPin) == LOW)       // test if shift is in park, HIGH or LOW ?
    park = true;
  else
    park = false;
    
#ifdef DEBUG 
  Serial.print("doorOpen=");
  Serial.print(doorOpen ? "open  " : "closed");
  Serial.print(", park=");
  Serial.print(park ? "active" : "idle  ");
  Serial.print(", state=");
  Serial.print(state);
#endif

  // --------------------------------------------------
  // Run the state machine
  // --------------------------------------------------
  switch (state)
  {
  case STATE_UNKNOWN:
    // Unknown what the situation is.
    // Assuming that the Arduino has powered up, and assuming that the light is off.
    if (doorOpen)
    {
      // If the door is open, don't turn on the lights, wait until door has been closed first.
      state = STATE_DOOR_OPEN_NO_LIGHT;
    }
    else
    {
      // The door is closed, everything is idle and okay.
      state = STATE_DOOR_CLOSED_NO_LIGHT;
    }
    break;
  case STATE_DOOR_CLOSED_NO_LIGHT:
    if (doorOpen)
    {
      // The door has just been opened, turn light on.
      digitalWrite(interiorPin, HIGH);  // if door is open then turn on the interior lamp 
      state = STATE_DOOR_OPEN_LIGHT;
    }
    break;
  case STATE_DOOR_OPEN_NO_LIGHT:
    // This is an extra state, in case the Arduino is powered up with the door open.
    if (!doorOpen)
    {
      // The door has just been closed.
      state = STATE_DOOR_CLOSED_NO_LIGHT;
    }
    break;
  case STATE_DOOR_OPEN_LIGHT:
    if (!doorOpen)
    {
      // The door has just been closed.
      // Start timer or not ? check the park
      if (park)
      {
        digitalWrite(interiorPin, LOW);      // turn off interior light
        state = STATE_DOOR_CLOSED_NO_LIGHT;
      }
      else
      {
        // The door was just closed, the light is still on, and park was not active.
        // This is the moment to start the timer.
        lightOnTime = millis();            // store the current time in variable lightOnTime
        state = STATE_DOOR_CLOSED_TIMER;
      }
    }
    break;
  case STATE_DOOR_CLOSED_TIMER:
    // using unsigned long for lightOnTime with the next if-statement prevents rollover problem.
    if( millis() - lightOnTime > 5000)
    {
      // The timer has ended, turn off the light.
      digitalWrite(interiorPin, LOW);      // turn off interior light
      state = STATE_DOOR_CLOSED_NO_LIGHT;
    }
    break;
  default:
    // Error in the sketch, this should not happen
    break;
  }

#ifdef DEBUG 
  Serial.print(" -> ");
  Serial.print(state);
  Serial.println();
  delay(1000);
#endif

}

Thank you for your help. It is all working apart from on bit when the door has been opened then closed and the timer is started if you press the park switch it don't turn of the light.

So when the "timer" is running, and the park switch is used, the lights must go off immediately ?
During that the state is "STATE_DOOR_CLOSED_TIMER", so that is where you have to add that condition.
You can add another if-statement, or combine it with the current if-statement.

So the lights should turn off when the "timer" has finished or park is active.
An 'or' is a '||'.

if (millis() - lightOnTime > 5000 || park)

You should be able to do that without my help, I'm afraid that you have now code that you don't understand. If there are parts that you don't understand, please ask.

I read the sketch again, to check if it is okay, but it is not.
When the "timer" is running, and the door is opened, the state should change, but it does not.

At the same case STATE_DOOR_CLOSED_TIMER, please add before testing the millis()
If you test it before the millis() is tested, the lights are still on.

if (doorOpen)
{
  // turn on the light (they are on at the moment).

  // go to the sate where the door is open
  state = STATE_DOOR_OPEN_LIGHT;
}

if (millis() - ....

Thanks for the help. Ive made all the changes and everything works fine.

Now the easy part is done I'll try and tackle the next part which is a bit harder but a similar concept.

Let me guess: play the Nyan Cat tune when it is freezing outside and the car battery is below 12V ?

:slight_smile: that would be funny to see that on a car.

i have to write a program to control the headlight for automatic turn on when it is dark

hi. come to the program this morning and a part of it is not working which was when i left it on friday. when in park and the door is opened the light is no longer coming on

ullisees, are you still waiting for an answer ? How is the status of the project ?
I searched for this topic to show it as an example for this : 3 stop motor - Motors, Mechanics, Power and CNC - Arduino Forum
but I noticed that I didn't see your two last posts before.