user66421: I am trying to build a unlocker on my hardlid for my ute. I have replaced the manual unlocking mechanism with 2 of these https://www.jaycar.com.au/slave-door-lock-actuator/p/LR8813.
Now my code below works sometimes and I cannot work out why. The way the code should work is 

Press Unlock Button (Count increments)
Press Unlock Button again 
When count = 2 turn relay on for 4 seconds then turn off
reset count to 0
If time between presses is longer than 10 seconds reset count to 0

Basic diagram below. Please note the push button is actually wired to a relay which is triggered by the car unlock remote and the LED is the actuators.

This is my code
int switchPin = 2; // choose the input pin (for a pushbutton)
int relayPin = 4; // choose the input pin (for a pushbutton)
int val = 0; // variable for reading the pin status
int counter = 0;
int currentState = 0;
int previousState = 0;
bool lockOn = false;

unsigned long currentMillis = 0;
unsigned long previousMillis = 0;

unsigned long LockcurrentMillis = 0;
unsigned long LockpreviousMillis = 0;


const long interval = 10000;
const long Lockinterval = 4000;

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

  pinMode(switchPin, INPUT); // declare pushbutton as input
  pinMode(relayPin, OUTPUT); // declare pushbutton as input


  Serial.println("Ready");
  Serial.print("IP address: ");

}

void loop() {



  currentMillis = millis();
  LockcurrentMillis = millis();
/*
  Serial.print("Current ");
  Serial.print(currentMillis);
  Serial.print(" | Previous ");
  Serial.println(previousMillis);
    //Serial.println(lockOn); 


  Serial.print("Lock Current ");
  Serial.print(LockcurrentMillis);
  Serial.print(" | Lock Previous ");
  Serial.println(LockpreviousMillis);
  */
  if (lockOn == true){

    if (LockcurrentMillis - LockpreviousMillis >= Lockinterval) {
      // save the last time you blinked the LED
      LockpreviousMillis = LockcurrentMillis;
      digitalWrite(relayPin, LOW); // turn relayPin off
      lockOn = false;
      Serial.println("relay off");
    }
  }

  val = digitalRead(switchPin); // read input value
  if (val == HIGH) { // check if the input is HIGH (button released)
    currentState = 1;
  }
  else {
    currentState = 0;
  }
  if (currentState != previousState) {
    if (currentState == 1) {
      counter = counter + 1;
      previousMillis = currentMillis;   //reset timer
      Serial.println(counter);
    }
  }
  if (counter == 2) {
    counter = 0;
    digitalWrite(relayPin, HIGH); // turn relayPin on
    //delay(4000);
    //digitalWrite(relayPin, LOW); // turn relayPin off
    lockOn = true;
          LockpreviousMillis = LockcurrentMillis;

    Serial.println("relay on");
  }

  previousState = currentState;
  //delay(250);
  if (currentMillis - previousMillis >= interval) {
    // save the last time you presse the button
    previousMillis = currentMillis;
    //LockpreviousMillis = LockcurrentMillis;
    //if (counter >= 1) {
    Serial.println("Took too long reset count");
    counter = 0;
    lockOn = false;
    //}
  }
}

Any Help would be highly appreciated
Thanks

user7508: Your circuit drawing seems very wrong, but it is not helpful since, as
you say, it doesn't represent the real circuit. Please, add a proper
diagram of the actual circuit.
As for your reliability problem, I did not dig into the logic of the
code you posted, but I suspect it may be caused by the lack of
debouncing. You could add you own debouncing code but, for the sake
of simplicity, I suggest you instead use a ready-made library, like
Bounce2.
For the kind of program you are trying to write, I find that the logic
becomes way easier to grasp if you think think of it as a finite state
machine. This is program construct based on the idea that the
system can be in any of a predefined set of possible states, and that
its behavior and the possible state transitions depend on what
particular state it is in. In this specific case, I would use three
states:

In the LOCKED state, the lid is locked and you need to press the
button twice in order to unlock it. Once you press the button once,
it transitions to the WAITING state.
In the WAITING state, the lid is still locked, but the first
button press has already been registered. If you press the button
again, the system transitions to the UNLOCKED state. If not,
after a timeout it transitions back to LOCKED.
In the UNLOCKED state the lid is unlocked. After another timeout it
transitions back to the LOCKED state.

Once you have this logic written down, it can be translated into code in
a very straightforward way:
#include <Bounce2.h>

const uint8_t  switch_pin = 2;
const uint8_t  relay_pin  = 4;
const uint32_t wait_interval = 10000;  // 10 s
const uint32_t lock_interval =  4000;  //  4 s

Bounce button;

void setup() {
    button.attach(switch_pin, INPUT_PULLUP);
    pinMode(relay_pin, OUTPUT);
    Serial.begin(9600);
    Serial.println("Ready.");
}

void loop() {
    static enum { LOCKED, WAITING, UNLOCKED } state = LOCKED;
    static uint32_t last_change;  // not used in the LOCKED state

    button.update();
    uint32_t now = millis();
    switch (state) {
    case LOCKED:
        if (button.fell()) {
            Serial.println(F("Waiting for second button press."));
            state = WAITING;
            last_change = now;
        }
        break;
    case WAITING:
        if (button.fell()) {
            Serial.println(F("Unlocking."));
            digitalWrite(relay_pin, HIGH);
            state = UNLOCKED;
            last_change = now;
        } else if (now - last_change >= wait_interval) {
            Serial.println(F("Wait time out."));
            state = LOCKED;
        }
        break;
    case UNLOCKED:
        if (now - last_change >= lock_interval) {
            Serial.println(F("Locking."));
            digitalWrite(relay_pin, LOW);
            state = LOCKED;
        }
        break;
    }
}


66421: <p>I am trying to build a unlocker on my hardlid for my ute. I have replaced the manual unlocking mechanism with 2 of these <a href="https://www.jaycar.com.au/slave-door-lock-actuator/p/LR8813" rel="nofollow noreferrer">https://www.jaycar.com.au/slave-door-lock-actuator/p/LR8813</a>.</p>

<p>Now my code below works sometimes and I cannot work out why. The way the code should work is </p>

<ol>
<li>Press Unlock Button (Count increments)</li>
<li>Press Unlock Button again </li>
<li>When count = 2 turn relay on for 4 seconds then turn off</li>
<li>reset count to 0</li>
<li>If time between presses is longer than 10 seconds reset count to 0</li>
</ol>

<p>Basic diagram below. Please note the push button is actually wired to a relay which is triggered by the car unlock remote and the LED is the actuators.</p>

<p><a href="https://i.stack.imgur.com/zwrEY.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/zwrEY.png" alt="enter image description here"></a></p>

<p>This is my code</p>

<pre><code>int switchPin = 2; // choose the input pin (for a pushbutton)
int relayPin = 4; // choose the input pin (for a pushbutton)
int val = 0; // variable for reading the pin status
int counter = 0;
int currentState = 0;
int previousState = 0;
bool lockOn = false;

unsigned long currentMillis = 0;
unsigned long previousMillis = 0;

unsigned long LockcurrentMillis = 0;
unsigned long LockpreviousMillis = 0;


const long interval = 10000;
const long Lockinterval = 4000;

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

  pinMode(switchPin, INPUT); // declare pushbutton as input
  pinMode(relayPin, OUTPUT); // declare pushbutton as input


  Serial.println("Ready");
  Serial.print("IP address: ");

}

void loop() {



  currentMillis = millis();
  LockcurrentMillis = millis();
/*
  Serial.print("Current ");
  Serial.print(currentMillis);
  Serial.print(" | Previous ");
  Serial.println(previousMillis);
    //Serial.println(lockOn); 


  Serial.print("Lock Current ");
  Serial.print(LockcurrentMillis);
  Serial.print(" | Lock Previous ");
  Serial.println(LockpreviousMillis);
  */
  if (lockOn == true){

    if (LockcurrentMillis - LockpreviousMillis &gt;= Lockinterval) {
      // save the last time you blinked the LED
      LockpreviousMillis = LockcurrentMillis;
      digitalWrite(relayPin, LOW); // turn relayPin off
      lockOn = false;
      Serial.println("relay off");
    }
  }

  val = digitalRead(switchPin); // read input value
  if (val == HIGH) { // check if the input is HIGH (button released)
    currentState = 1;
  }
  else {
    currentState = 0;
  }
  if (currentState != previousState) {
    if (currentState == 1) {
      counter = counter + 1;
      previousMillis = currentMillis;   //reset timer
      Serial.println(counter);
    }
  }
  if (counter == 2) {
    counter = 0;
    digitalWrite(relayPin, HIGH); // turn relayPin on
    //delay(4000);
    //digitalWrite(relayPin, LOW); // turn relayPin off
    lockOn = true;
          LockpreviousMillis = LockcurrentMillis;

    Serial.println("relay on");
  }

  previousState = currentState;
  //delay(250);
  if (currentMillis - previousMillis &gt;= interval) {
    // save the last time you presse the button
    previousMillis = currentMillis;
    //LockpreviousMillis = LockcurrentMillis;
    //if (counter &gt;= 1) {
    Serial.println("Took too long reset count");
    counter = 0;
    lockOn = false;
    //}
  }
}
</code></pre>

<p>Any Help would be highly appreciated</p>

<p>Thanks</p>
 7508: <p>Your circuit drawing seems very wrong, but it is not helpful since, as
you say, it doesn't represent the real circuit. Please, add a proper
diagram of the actual circuit.</p>

<p>As for your reliability problem, I did not dig into the logic of the
code you posted, but I suspect it may be caused by the lack of
<a href="https://www.arduino.cc/en/tutorial/debounce" rel="nofollow noreferrer">debouncing</a>. You could add you own debouncing code but, for the sake
of simplicity, I suggest you instead use a ready-made library, like
<a href="https://github.com/thomasfredericks/Bounce2" rel="nofollow noreferrer">Bounce2</a>.</p>

<p>For the kind of program you are trying to write, I find that the logic
becomes way easier to grasp if you think think of it as a <a href="https://majenko.co.uk/blog/finite-state-machine" rel="nofollow noreferrer">finite state
machine</a>. This is program construct based on the idea that the
system can be in any of a predefined set of possible states, and that
its behavior and the possible state transitions depend on what
particular state it is in. In this specific case, I would use three
states:</p>

<ul>
<li>In the <code>LOCKED</code> state, the lid is locked and you need to press the
button twice in order to unlock it. Once you press the button once,
it transitions to the <code>WAITING</code> state.</li>
<li>In the <code>WAITING</code> state, the lid is still locked, but the first
button press has already been registered. If you press the button
again, the system transitions to the <code>UNLOCKED</code> state. If not,
after a timeout it transitions back to <code>LOCKED</code>.</li>
<li>In the <code>UNLOCKED</code> state the lid is unlocked. After another timeout it
transitions back to the <code>LOCKED</code> state.</li>
</ul>

<p>Once you have this logic written down, it can be translated into code in
a very straightforward way:</p>

<pre class="lang-cpp prettyprint-override"><code>#include &lt;Bounce2.h&gt;

const uint8_t  switch_pin = 2;
const uint8_t  relay_pin  = 4;
const uint32_t wait_interval = 10000;  // 10 s
const uint32_t lock_interval =  4000;  //  4 s

Bounce button;

void setup() {
    button.attach(switch_pin, INPUT_PULLUP);
    pinMode(relay_pin, OUTPUT);
    Serial.begin(9600);
    Serial.println("Ready.");
}

void loop() {
    static enum { LOCKED, WAITING, UNLOCKED } state = LOCKED;
    static uint32_t last_change;  // not used in the LOCKED state

    button.update();
    uint32_t now = millis();
    switch (state) {
    case LOCKED:
        if (button.fell()) {
            Serial.println(F("Waiting for second button press."));
            state = WAITING;
            last_change = now;
        }
        break;
    case WAITING:
        if (button.fell()) {
            Serial.println(F("Unlocking."));
            digitalWrite(relay_pin, HIGH);
            state = UNLOCKED;
            last_change = now;
        } else if (now - last_change &gt;= wait_interval) {
            Serial.println(F("Wait time out."));
            state = LOCKED;
        }
        break;
    case UNLOCKED:
        if (now - last_change &gt;= lock_interval) {
            Serial.println(F("Locking."));
            digitalWrite(relay_pin, LOW);
            state = LOCKED;
        }
        break;
    }
}
</code></pre>
