inconsistent loop outputs

Good afternoon. Thanks to all who have answered my earlier post on the FADE loop. I applied the suggestions to a few other projects and they appeared to work! I also tried to apply those suggestions to a bit more complicated project and am now stuck. The intent is to lock the car doors when the lock button is pressed or if the car is taken out of Park by checking the status of the 2 door lock switches and if the gear shift is in Park. If the door unlock button is pressed while the car is in gear, then the doors will unlock for 10 seconds then recheck for gear position or door lock. I don't know how to get the momentary door lock/unlock switch to latch LOW when pressed. Nor can I figure out how to get the unlock loop to function. So far the output is:

Pin 5 LOW: serial output is "doors are locked" x3 and lockPin goes HIGH for each momentary press Pin 2 LOW: serial output is "doors are locked" x3 and lockPin goes HIGH for the first press and then serial output is "doors are locked" x4 and lockPin remains HIGH for each following press Pin 3 LOW: nothing happens.

I have to reset between each button press/event

const int doorlockPin = 2;   // input from door lock switch
const int doorunlockPin = 3; // input from door unlock switch
const int parkPin = 5;       // input from gear indicator
const int lockPin = 10;      // output to door lock


int previousParkState;
int previousLockState;
int previousUnlockState;
unsigned long startTimeL;
const unsigned long durationL = 10000; // 10 seconds

void setup() {
  Serial.begin(9600);
  while( !Serial );
  
  pinMode(doorlockPin, INPUT_PULLUP);      // initialize input from door lock switch set HIGH (unlocked)
  pinMode(doorunlockPin, INPUT_PULLUP);    // initializes input from door unlock switch set HIGH (lock)
  pinMode(parkPin, INPUT_PULLUP);          // initialize input from gear shift indicator set HIGH (in Park)
  pinMode(lockPin, OUTPUT);                // output to door lock relay
  previousLockState = digitalRead(doorlockPin);      // reads doorlockPin as HIGH
  previousUnlockState = digitalRead(doorunlockPin);  // reads doorunlockPin as HIGH
  previousParkState = digitalRead(parkPin);          // reads parkPin as HIGH
}

void loop()  //DOOR LOCK block. Doors will be unlocked if in Park or 10 seconds if NOT in Park and unlock has been pressed.
  {
    int currentLockState = digitalRead(doorlockPin);  // reads doorlockPin for comparison
    int currentUnlockState = digitalRead(doorunlockPin);  // reads doorunlockPin for comparison
    int currentParkState = digitalRead(parkPin);    // reads parkPin for comparison

  if (( currentParkState != previousParkState ) ||  ( currentLockState != previousLockState ))      // compares the two pin states if not in Park or door lock has been pressed --> lock doors
   {
   Serial.println( "Doors are locked." );
   digitalWrite(lockPin, HIGH);       // output to lock doors
   }
      if (( doorlockPin == HIGH) && ( currentUnlockState == LOW))         // door was locked and unlock has been pressed --> unlock doors for 10 seconds
        {
      startTimeL = millis();
      Serial.println( "door was locked and unlock has been pressed." );
      digitalWrite(lockPin, LOW);         // output to unlock doors
      digitalWrite(doorlockPin, HIGH);    // resets door lock pin HIGH (unlock)
      digitalWrite(doorunlockPin, HIGH);  // resets door unlock pin HIGH (lock)
        }
   
    delay(50);  // debounce

//  previousLockState = currentLockState; // remember for next time through loop

  if ( startTimeL > 0 && millis() - startTimeL >= durationL ) {       // doors are unlocked for 10 seconds
    digitalWrite (lockPin, LOW);  // unlocks doors
  
  }  // End DOOR LOCK block
  
} // End all code

You are using the wrong variable in your second if() statement. doorlockPin should be currentLockState.

You might want to introduce a new variable to keep track of what state you are in

  1. Lock button changed to pressed? locked = true
  2. Gear moved out of park? locked = true
  3. unlock button changed to pressed? unlock and start timer
  4. timer running and expired? locked = true

There are probably a few more cases you need to worry about like should the doors unlock when the gear moves into park?

So, your sketch at any time can be in one of these states:

Doors locked, car in park/stationary Doors unlocked, car in park/stationary Doors locked, car moving Doors locked for 10 seconds, car moving

You could do this with two booleans and a timer, but I like to use a enum named 'state'

enum State {
  PARKED_LOCKED,
  PARKED_UNLOCKED,
  MOVING_LOCKED,
  MOVING_UNLOCKED
};

State state; // initial value of this will be set in setup()

The main loop will have a switch statement with a block for each state:

void loop() {
  // read the sketch inputs - the door locks, the gear lever, the lock button - here

  switch(state) {
    PARKED_LOCKED:
      break;
    PARKED_UNLOCKED:
      break;
    MOVING_LOCKED:
      break;
    MOVING_UNLOCKED:
      break;
  }
}

Then work out what to do in each state.

    PARKED_LOCKED:
      if the car has been put into gear {
        state = MOVING_LOCKED;
      }
      else if the beeper has been beeped {
        unlock everything;
        state = PARKED_UNLOCKED;
      }
      break;
    PARKED_UNLOCKED:
      if the car has been put into gear {
        tensecondtimerstart = millis();
        state = MOVING_UNLOCKED;
      }
      else if the beeper has been beeped {
        lock everything;
        state = PARKED_LOCKED;
      }
      break;
    MOVING_LOCKED:
      if the car has been put into park {
        state = PARKED_LOCKED;
      }
      else if the beeper has been beeped {
        tensecondtimerstart = millis();
        state = MOVING_UNLOCKED;
      }
      break;
    MOVING_UNLOCKED:
      if the car has been put into park {
        state = PARKED_UNLOCKED;
      }
      else if the beeper has been pressed, or if (millis()-tensecondtimerstart)>=10000L {
        lock the doors;
        state = MOVING_LOCKED;
      }
      
      break;

something like that. I'm not handling the situation where the car is put in and out of gear simultaneously with the beeper being pressed. Probably will never happen. But if it does ... meh, the next loop() with catch the beep, or failing that they'll need to press the button again.

blh64:
You are using the wrong variable in your second if() statement. doorlockPin should be currentLockState.

You might want to introduce a new variable to keep track of what state you are in

  1. Lock button changed to pressed? locked = true
  2. Gear moved out of park? locked = true
  3. unlock button changed to pressed? unlock and start timer
  4. timer running and expired? locked = true

There are probably a few more cases you need to worry about like should the doors unlock when the gear moves into park?

Sir, once again, thank you for your insights. So some questions:
Second if() statement: I chose doorlockPin vice currentLockState because I thought the HIG/LOW of the output pin would be a better choice but it sounds like they are the same value??
other cases: I plan to include an if() statement to unlock the doors if doorunlockPin is HIGH.
I will have to read up on the 1-4 variable suggestions regarding state.
Luckily(?) I am in quarantine prior to travelling so I have plenty of time to read and practice (hopefully I won’t burn out).
Thanks again!

PaulMurrayCBr - thanks for the response and suggestion but that looks way too much/intense for my rookie level programming skills. Clearly you are a programmer by trade. I understand what you are trying to do/say, but have no idea of how to implement it (at this time) and am afraid that trying to figure it out would be extremely frustrating.

blh64:
You are using the wrong variable in your second if() statement. doorlockPin should be currentLockState.

You might want to introduce a new variable to keep track of what state you are in

  1. Lock button changed to pressed? locked = true
  2. Gear moved out of park? locked = true
  3. unlock button changed to pressed? unlock and start timer
  4. timer running and expired? locked = true

There are probably a few more cases you need to worry about like should the doors unlock when the gear moves into park?

sir - after doing some reading and video watching, I am still confused. Why I would switch from HIGH/LOW to true/false? Aren’t they read as the same values (1/0)?

Do not confuse a pin number with the state of that pin (HIGH/LOW). 'doorlockPin' is the value 2. Reading the value of that pin using digitalRead() returns the HIGH/LOW state of said pin.

It sounds like you might want to look at some C tutorials and the examples in the IDE to learn more about the C language before going to much further on this project.

thanks sir. I don't think I was confusing the pin number with the state, maybe I just typed it wrong in the message. Either way, I will do some more reading on this topic to hopefully help with my understanding.

Thanks again.

This is your code

      if (( doorlockPin == HIGH) && ( currentUnlockState == LOW))         // door was locked and unlock has been pressed --> unlock doors for 10 seconds

which clearly shows a confusion between pin and state of the pin. If you are typing this in directly - don't! Always cut and paste from the actual sketch to avoid errors.

UPDATE: I have done some reading (and A LOT of testing) and gotten a little bit further. I am able to get the Park and lock states to change and the result to serial print. I have been doing it in sections and got the lock section to work as expected.

const int parkPin = 3;    // input from Park relay
const int lockPin = 13;   // output to buzzer

int previousParkState;

void doorlock() {        // lock subroutine
    digitalWrite(lockPin, HIGH);
  }
  
void doorunlock() {      // unlock subroutine
    digitalWrite (lockPin, LOW);  
    digitalWrite (parkPin, HIGH);
  }

void setup() {
  Serial.begin(9600);
  while( !Serial );
  
  pinMode(parkPin, INPUT_PULLUP);    // input from Park relay HIGH
  pinMode(lockPin, OUTPUT);          // buzzer output
  digitalWrite(lockPin, LOW);        // initializes the output (unlocked)
  previousParkState = digitalRead(parkPin);

}

void loop() {  
  int currentParkState = digitalRead(parkPin);
  int currentLockState = digitalRead(lockPin);

  if ( currentParkState != previousParkState ) {      
      Serial.println( "Car is in gear, doors are locked." );
      doorlock();  // digitalWrite (lockPin, HIGH);
      }    

    else {
      Serial.println( "Car is in Park, doors are unlocked." );  
      doorunlock(); // digitalWrite (parkPin, HIGH);
                    // digitalWrite (lockPin, LOW);
      }

    delay(50);  // debounce

  delay (1000);  // for COM3 printing
}  // End all code

However, when I add the next section to check the unlock status, the serial print is correct (I even printed the current status during each step to verify) but the output to lockPin is not changing state. I am not sure why????

// Phase 2: incorporating the momentary lock and unlock buttons

const int doorlockPin = 5;   // digital input from door lock switch
const int doorunlockPin = 4; // digital input from door unlock switch
const int parkPin = 3;       // constant input from gear indicator
const int lockPin = 13;      // output to door lock
        
int previousLockState;          
int previousUnlockState;        
int previousParkState;
unsigned long startTimeL;   
const unsigned long durationL = 10000;

  void doorlock() {        // lock subroutine that sets the lockPin HIGH
    digitalWrite(lockPin, HIGH);
    }
  void doorunlock() {      // unlock subroutine that sets the UnlockPin HIGH
    digitalWrite (lockPin, LOW);  
    }

void setup() {
  Serial.begin(9600);
  while( !Serial );

  pinMode(lockPin, OUTPUT);                  // buzzer output
  pinMode(parkPin, INPUT_PULLUP);            // input from Park relay HIGH
  digitalWrite(doorlockPin, INPUT_PULLUP);   // initializes the output (unlocked)
  digitalWrite(doorunlockPin, INPUT_PULLUP); // initializes the output (unlocked)
  previousParkState = digitalRead(parkPin);
  previousLockState = digitalRead(doorlockPin);
  previousUnlockState = digitalRead(doorunlockPin);

}

void loop()  //DOOR LOCK
{
int currentParkState = digitalRead(parkPin);
int currentLockState = digitalRead(doorlockPin);
int currentUnlockState = digitalRead(doorunlockPin);

//Checks to see if transmission is in Park or door lock button has been pressed
  if (( currentParkState != previousParkState )  ||  ( currentLockState != previousLockState ))  {      
      Serial.println( "Doors are locked." );
      doorlock();  
      }    
    else  Serial.println( "Car is in Park, doors are unlocked." );  
// end lock section

// Checks to see if door unlock button has been pressed
   if (( currentUnlockState != previousUnlockState ) &&  ( currentUnlockState == LOW )) {   // Unlock button state has changed (request to unlock)
        if ( currentParkState == LOW );      // compares to see if in Park, if NOT in Park, start timer
      startTimeL = millis();
      Serial.println( "Unlock button has been pressed while in gear." );
      }
    else  startTimeL = 0; // ensure counter is at zero.
        doorunlock();     // Unlock doors because transmission is not in gear.
    
  if ( startTimeL > 0 && millis() - startTimeL >= durationL ) {    // doors are unlocked for 10 seconds
    doorunlock();
   }
// end unlock section   
   delay(50);  // debounce

  delay (1000);  // for COM3 printing
  
// END DOOR LOCK block   
   }