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
}