Arduino Uno - Start/Stop Time Delayed Relays With Momentary Negative Pulse

Hello,

I'm new here and also to arduino so maybe my question is stupid or something, sorry for that.

I have bought an Arduino Uno + a 4 channnel Relay Module

Now here is the problem...

In my car I have a remote central locking system, on the remote I have an extra button for accessories (trunk release) so if I press that button there is 1 wire that will give the option to ground a power circuit for 2/3 seconds. It is kind of a momentary negative pulse to ground something on, like the 5v port of the arduino. If I look at the "Button" example from this site and then invert that and leave the button out, I could make a closed circuit.

So connecting 5V with 10K resistor in between to port 2 and from port 2 a wire to my remote central locking.

In this 2/3 seconds the arduino has to start a sequence:

Start relay 1 Delay 500 Start relay 2 Delay 100 Start relay 3 Delay 1000 Start relay 4 Delay 1200 Stop relay 4

And the relays have to stay in this position until the button is pressed again and there is another pulse of 2/3 seconds, the relays have to turn of all together.

I have absolutely no idea how to write this code, could someone help me with this?

Big thanks in advance!

Regards, Stijn

It is kind of a momentary negative pulse to ground something on, like the 5v port of the arduino.

The 5V pin of the Arduino is about the last thing you want to ground.

Forget about the car and its remote for now. Look at the example sketches in the IDE, The Button example that you mention would be a good start. Do you understand how the button input is being read ? Do you understand how the output to the LED is being done ?

How much current do your relays take ?

What would happen if you substituted a relay for the LED, assuming that the Arduino can supply enough current ? If you don't have a switch to test it with then use a wire between the button pin and the 5V pin. Once that works think about how you would test for the button pin going LOW (to GND) instead of HIGH and change the code. Once you can turn one relay on make a second, third, forth one come on when you press the button/connect the switch wire. Insert a delay() between each relay coming on and/or off.

Test that until it works reliably then post the program here for more help towards using something like it in your car.

Thanks for your help !!

This is the code I have made, what happens is;

The relays will go on with the delay in between but when i press the button, only relay 4 will turn on and off and the other ones stay on.

//radioPin is relay1
//accPin is relay2
//onPin is relay3
//startPin is relay4
//purplePin is the button input


const int radioPin = 4;
const int accPin = 7;
const int onPin = 8;
const int startPin = 12;
const int purplePin = 3;

int radioState = HIGH;
int accState = HIGH;
int onState = HIGH;
int startState = HIGH;
int purpleState = HIGH;
int lastPurpleState = LOW;
int reading;

long lastDebounceTime = 0;
long debounceDelay = 50;

void setup() {
  pinMode(radioPin, OUTPUT);
  pinMode(accPin, OUTPUT);
  pinMode(onPin, OUTPUT);
  pinMode(startPin, OUTPUT);
  pinMode(purplePin, INPUT);

  digitalWrite(radioPin, HIGH);
  digitalWrite(accPin, HIGH);
  digitalWrite(onPin, HIGH);
  digitalWrite(startPin, HIGH); 
}

void loop() {
  reading = digitalRead(purplePin);
    if (reading != lastPurpleState) {
      lastDebounceTime = millis();
      lastPurpleState = reading;
    }

    if ((millis() - lastDebounceTime) > debounceDelay) {
        if (purpleState != lastPurpleState) {
            purpleState = lastPurpleState;
            if (purpleState == HIGH) { 
                radioState = !radioState;
                digitalWrite(radioPin, LOW);
                delay(1000); 
                accState = !accState;
                digitalWrite(accPin, LOW);
                delay(200);
                onState = !onState;
                digitalWrite(onPin, LOW);
                delay(1300);
                startState = !startState;
                digitalWrite(startPin, LOW);
                delay(1750);
                startState = !startState;
                digitalWrite(startPin, HIGH);
            }
        }
    }
}

Maybe you could help me, and tell me exactly what I have to change ...

only relay 4 will turn on and off and the other ones stay on.

relay4 is being turned on and off with this code

digitalWrite(startPin, LOW);
                delay(1750);
                startState = !startState;
                digitalWrite(startPin, HIGH);

but once the others are on they are never turned off. If you want them all off at the end of the sequence then add digitalWrite()s to do it immediately after the last one for startPin in the code above. You are not using any of the State variables in the code. Are you planning on using them later ?

Incidentally, your program would be better structured if you turned it into a State Machine. Oh, and please use Auto Format in the IDE to make it more readable.

Could you give my an example how you would change my code into a state machine were the first button press will turn the relays on and the second button press will turn them all off.

Because I'm breaking my head over it all day (and night)...

Try this, although you will probably need to change the logic to match your wiring.
Each state is a stage of the process. It looks complicated and difficult to write but once you have got the principles its easy. Once one state is defined it is just a matter of copy/paste and changing the state actions and exit conditions. Note that as written all the wait times are 1 second, which is easier to test.

const byte buttonPin = A1;
const byte relayPins[] = {10, 11, 12, 13};
const byte NUMBER_OF_RELAYS = sizeof(relayPins);
byte state = 0;
unsigned long startWait = 0;
unsigned long period;
unsigned long currentTime;
byte currentButtonState;
byte previousButtonState;

void setup()
{
  Serial.begin(115200);
  for (int p = 0; p < NUMBER_OF_RELAYS; p++)
  {
    pinMode(relayPins[p], OUTPUT);
  }
  allOff();
  pinMode(buttonPin, INPUT_PULLUP);
}

void loop()
{
  switch (state)
  {
    case 0:  //wait for button press
      currentButtonState = digitalRead(buttonPin);
      if (currentButtonState != previousButtonState && currentButtonState == LOW)
      {
        digitalWrite(relayPins[0], LOW);
        startWait = millis();
        period = 1000;
        state = 1;
      }
      previousButtonState = currentButtonState;
      break;

    case 1:
      currentTime = millis();
      if (currentTime - startWait >= period)
      {
        digitalWrite(relayPins[1], LOW);
        startWait = currentTime;
        period = 1000;
        state = 2;
      }
      break;

    case 2:
      currentTime = millis();
      if (currentTime - startWait >= period)
      {
        digitalWrite(relayPins[2], LOW);
        startWait = currentTime;
        period = 1000;
        state = 3;
      }
      break;

    case 3:
      currentTime = millis();
      if (currentTime - startWait >= period)
      {
        digitalWrite(relayPins[3], LOW);
        startWait = currentTime;
        period = 1000;
        state = 4;
      }
      break;

    case 4:
      currentTime = millis();
      if (currentTime - startWait >= period)
      {
        digitalWrite(relayPins[3], HIGH);
        previousButtonState = HIGH;
        state = 5;
      }
      break;

    case 5:  //wait for button press and release
      currentButtonState = digitalRead(buttonPin);
      if (currentButtonState != previousButtonState && currentButtonState == HIGH)
      {
        allOff();
        state = 0;
      }
      previousButtonState = currentButtonState;
      break;
  }
}

void allOff()
{
  for (int p = 0; p < NUMBER_OF_RELAYS; p++)
  {
    digitalWrite(relayPins[p], HIGH);
  }
}

I tried everything I could… Editing your code, writing my own code… I can get my relays running with the right delays but it seems impossible to turn them all off with a second GND pulse. Every single pulse causes the sequence to start over again. So with the first pulse the sequence starts and the relays are staying on, with the second pulse, all of them are turning off when immediately the sequence starts from the beginning. Could you solve this problem? What am I doing wrong? This is my (your) code:

const byte buttonPin = 2;
const byte relayPins[] = {4, 7, 8, 12};
const byte NUMBER_OF_RELAYS = sizeof(relayPins);
byte state = 0;
unsigned long startWait = 0;
unsigned long period;
unsigned long currentTime;
byte currentButtonState;
byte previousButtonState;

void setup()
{
  Serial.begin(115200);
  for (int p = 0; p < NUMBER_OF_RELAYS; p++)
  {
    pinMode(relayPins[p], OUTPUT);
  }
  allOff();
  pinMode(buttonPin, INPUT_PULLUP);
}

void loop()
{
  switch (state)
  {
    case 0:  //wait for button press
      currentButtonState = digitalRead(buttonPin);
      if (currentButtonState != previousButtonState && currentButtonState == LOW)
      {
        digitalWrite(relayPins[0], LOW);
        startWait = millis();
        period = 1000;
        state = 1;
      }
      previousButtonState = currentButtonState;
      break;

    case 1:
      currentTime = millis();
      if (currentTime - startWait >= period)
      {
        digitalWrite(relayPins[1], LOW);
        startWait = currentTime;
        period = 200;
        state = 2;
      }
      break;

    case 2:
      currentTime = millis();
      if (currentTime - startWait >= period)
      {
        digitalWrite(relayPins[2], LOW);
        startWait = currentTime;
        period = 1000;
        state = 3;
      }
      break;

    case 3:
      currentTime = millis();
      if (currentTime - startWait >= period)
      {
        digitalWrite(relayPins[1], HIGH);
        previousButtonState = LOW;
        state = 4;
      }
      break;

    case 4:
      currentTime = millis();
      if (currentTime - startWait >= period)
      {
        digitalWrite(relayPins[3], LOW);
        startWait = currentTime;
        period = 1580;
        state = 5;
      }
      break;

    case 5:
      currentTime = millis();
      if (currentTime - startWait >= period)
      {
        digitalWrite(relayPins[3], HIGH);
        previousButtonState = LOW;
        state = 6;
      }
      break;

    case 6:
      currentTime = millis();
      if (currentTime - startWait >= period)
      {
        digitalWrite(relayPins[1], LOW);
        startWait = currentTime;
        state = 7;
      }
      break;

    case 7:  //wait for button press and release
      currentButtonState = digitalRead(buttonPin);
      if (currentButtonState != previousButtonState && currentButtonState == HIGH)
      {
        allOff();
        state = 0;
      }
      previousButtonState = currentButtonState;
      break;
  }
}

void allOff()
{
  for (int p = 0; p < NUMBER_OF_RELAYS; p++)
  {
    digitalWrite(relayPins[p], HIGH);
  }
}

Add         previousButtonState = HIGH; to the actions in state 6 before changing to state 7

Does not help..

Stil the same problem

Here is your program modified in the way I suggested and using pin numbers on my test system. I have added comments to each state and it behaves as I expect it to. Do the comments match what you expect it to do ? Note that in state 7 it actually waits until the input goes from LOW to HIGH before leaving that state

const byte buttonPin = A1;
const byte relayPins[] = {10, 11, 12, 13};
const byte NUMBER_OF_RELAYS = sizeof(relayPins);
byte state = 0;
unsigned long startWait = 0;
unsigned long period;
unsigned long currentTime;
byte currentButtonState;
byte previousButtonState;

void setup()
{
  Serial.begin(115200);
  for (int p = 0; p < NUMBER_OF_RELAYS; p++)
  {
    pinMode(relayPins[p], OUTPUT);
  }
  allOff();
  pinMode(buttonPin, INPUT_PULLUP);
}

void loop()
{
  switch (state)
  {
    case 0:  //wait for button press
      currentButtonState = digitalRead(buttonPin);
      if (currentButtonState != previousButtonState && currentButtonState == LOW)
      {
        digitalWrite(relayPins[0], LOW);
        startWait = millis();
        period = 1000;
        state = 1;
      }
      previousButtonState = currentButtonState;
      break;

    case 1:  //led 0 on wait 1000
      currentTime = millis();
      if (currentTime - startWait >= period)
      {
        digitalWrite(relayPins[1], LOW);
        startWait = currentTime;
        period = 200;
        state = 2;
      }
      break;

    case 2: //leds 1 & 2 on wait 200
      currentTime = millis();
      if (currentTime - startWait >= period)
      {
        digitalWrite(relayPins[2], LOW);
        startWait = currentTime;
        period = 1000;
        state = 3;
      }
      break;

    case 3: //leds 1, 2 & 3 on wait 1000
      currentTime = millis();
      if (currentTime - startWait >= period)
      {
        digitalWrite(relayPins[1], HIGH);
        previousButtonState = LOW;
        state = 4;
      }
      break;

    case 4: //leds 1 & 3 on no wait
      currentTime = millis();
      if (currentTime - startWait >= period)
      {
        digitalWrite(relayPins[3], LOW);
        startWait = currentTime;
        period = 1580;
        state = 5;
      }
      break;

    case 5:  //leds 1, 3 & 4 on wait 1500
      currentTime = millis();
      if (currentTime - startWait >= period)
      {
        digitalWrite(relayPins[3], HIGH);
        previousButtonState = LOW;
        state = 6;
      }
      break;

    case 6:  //leds 1 & 3 no wait
      currentTime = millis();
      if (currentTime - startWait >= period)
      {
        digitalWrite(relayPins[1], LOW);
        startWait = currentTime;
        previousButtonState = HIGH; //bbb
        state = 7;
      }
      break;

    case 7:  //wait for button press and release
      currentButtonState = digitalRead(buttonPin);
      if (currentButtonState != previousButtonState && currentButtonState == HIGH)
      {
        allOff();
        state = 0;
      }
      previousButtonState = currentButtonState;
      break;
  }
}

void allOff()
{
  for (int p = 0; p < NUMBER_OF_RELAYS; p++)
  {
    digitalWrite(relayPins[p], HIGH);
  }
}