OK, I'm stuck

I am trying to finish up my first project to control some off road lights on my truck. I have it doing most of what I want which is push the button once and 2 come on, push the button again and all come on. I would like to add push and hold to make the lights flash in various patterns. The problems I am having:

I can't figure out push and hold to do a separate function despite reading several tutorials. I just can't get my head around it and I want to make sure I know HOW it works so I can build on it.

I tried making the flashing light sequence and I ran into having to press the button several times to turn it off. From what I have read this is because of using delay. I read about flashing an LED without delay but again, I just can't figure it our for my setup which has 4 relays.

Lastly, I want to make sure I don't have to cycle through the flashing mode to turn everything back off. These are pretty high powered lights and I don't want to have them flash if I am in traffic or something, mainly that mode is for emergencies and learning some code.

Here is what I have so far, most of it derived from a ladyada tutorial:

/ * Off Road Lights, v 1.0 /

int switchPin = 3; // switch is connected to pin 3

int relay1Pin = 4; //relay one is on pin 4

int relay2Pin = 5; //relay two is on pin 5

int relay3Pin = 6; //relay three is on pin 6

int relay4Pin = 7; //relay four is on pin 7

int led1Pin = 8; //led indicator is pin 8

int val; // variable for reading the pin status

int val2; // variable for reading the delayed status

int buttonState; // variable to hold the button state

int lightMode = 0; // What mode is the light in?

void setup() {

pinMode(switchPin, INPUT); // Set the switch pin as input

pinMode(relay1Pin, OUTPUT);

pinMode(relay2Pin, OUTPUT);

pinMode(relay3Pin, OUTPUT);

pinMode(relay4Pin, OUTPUT);

pinMode(led1Pin, OUTPUT);

buttonState = digitalRead(switchPin); // read the initial state }

void loop(){ val = digitalRead(switchPin); // read input value and store it in val delay(10); // 10 milliseconds is a good amount of time val2 = digitalRead(switchPin); // read the input again to check for bounces if (val == val2) { // make sure consistent readings!

if (val != buttonState) {          // the button state has changed
  if (val == LOW) {                // check if the button is pressed
    if (lightMode == 0) {          // if its off
      lightMode = 1;               // turn relay 1 and 4 on
    } else {
      if (lightMode == 1) {        // if 1 and 4 are on
        lightMode = 2;             // turn 1, 2, 3 and 4 on
      } else {
        if (lightMode == 2) {      // if all relays are on
          lightMode = 3;           // make it flash
        } else {
          if (lightMode == 3) { //  if its flashing, 
            lightMode = 0;           // turn light off!
          }
        }
      }
    }
  }
}
buttonState = val;                 // save the new state in our variable

}

// Now do whatever the lightMode indicates if (lightMode == 0) { // all-off

digitalWrite(relay1Pin, LOW);
digitalWrite(relay2Pin, LOW);
digitalWrite(relay3Pin, LOW);
digitalWrite(relay4Pin, LOW);
digitalWrite(led1Pin, LOW);

}

if (lightMode == 1) { //Relay 1 and 4 on

digitalWrite(relay1Pin, HIGH);
digitalWrite(relay2Pin, LOW);
digitalWrite(relay3Pin, LOW);
digitalWrite(relay4Pin, HIGH);
digitalWrite(led1Pin, HIGH);

}

if (lightMode == 2) { // relay 1, 2, 3, and 4 on

digitalWrite(relay1Pin, HIGH);
digitalWrite(relay2Pin, HIGH);
digitalWrite(relay3Pin, HIGH);
digitalWrite(relay4Pin, HIGH);
digitalWrite(led1Pin, HIGH);

} if (lightMode == 3) { // flash various patterns

digitalWrite(relay4Pin, LOW);
digitalWrite(relay1Pin, HIGH);
delay(300);
digitalWrite(relay1Pin, LOW);
digitalWrite(relay2Pin, HIGH);
delay(300);
digitalWrite(relay2Pin, LOW);
digitalWrite(relay3Pin, HIGH);
delay(300);
digitalWrite(relay3Pin, LOW);
digitalWrite(relay4Pin, HIGH);
delay(300);

Any help would be greatly appreciated. This is the first time I have touched any kind of code in my life and I want to have understanding before moving on. Thanks in advance.

I can't figure out push and hold to do a separate function despite reading several tutorials.

You need to detect when a transition occurs - from pressed to released or from released to pressed. This is done by recording, at the end of loop, the state of the switch. At the beginning of loop, you read the current state. If it is not the same as the previous state, a transition has occurred.

When a transition occurs, you need to record the time, using millis(). You also determine if the transition was to pressed or to released (based on the current state), so that you record the time in the right variable (timePressed or timeReleased, for instance).

When the transition is to released, measure the time (timeReleased - timePressed). If the pressed time is less than some threshold, it was a quick press. Otherwise, it was a press and hold.

I tried making the flashing light sequence and I ran into having to press the button several times to turn it off. From what I have read this is because of using delay. I read about flashing an LED without delay but again, I just can't figure it our for my setup which has 4 relays.

It is not a matter of having to press the switch (buttons are for shirts) multiple times. It is a matter of having to press the switch at the right time. Yes, this is because the switch state is only read now and then.

Flashing the lights using relays or directly connected to the pin or via a transistor makes no difference. All the Arduino is doing is setting some pin HIGH or LOW.

You have to separate the "what needs to be done" from the "when it needs to be done" in order to get rid of delay() calls.

Think about how YOU would flash the lights using a watch, a pad of paper, and a switch. Turn the switch on and write down the time. Periodically, check the time. If enough time has elapsed (now - then), do something. In the case of flashing a light, that means setting the pin to the other state, and recording when you did it.

The millis() function replaces the watch, and some unsigned long variables replace writing the times on a piece of paper.

Lastly, I want to make sure I don't have to cycle through the flashing mode to turn everything back off. These are pretty high powered lights and I don't want to have them flash if I am in traffic or something, mainly that mode is for emergencies and learning some code.

If you are not using delay(), the period of time between pressing a switch and the Arduino noticing that the switch was pressed will be considerably reduced.

Given the critical need to stop flashing, I'd strongly urge you to consider a separate switch to start/stop flashing.