(HARD) Controlling 2 relays with a momentary switch AND a latching switch

Hello, thank you for reading this.
I've been working on this project for 2 months and was hoping to finalize it this weekend. I just need this bit of code to push this through.

Hardware
Arduino Uno
2 High Voltage Relay Connected to LED Flood Lights
1 Rocker Switch Triggers WHEN HIGH & N/O (LOW) .:

  • Rocking up is a latching contact (N/O LOW)
  • Rocking down is a momentary (N/O LOW)

I am a seasoned electrician.
I have two flood lights controlled by two high voltage relays. I am using a rocker switch the one used for ships with a fuse. They run on 12v. I have all the step-down hooked up to feed only 5v. to my Arduino Uno control pins 6 & 7.

Goals:
Momentary Rocker Position Function Pin 7:
1st click -Close Relay 1 ONLY
2nd click -Close Relay 2 ONLY
3rd click -Close Relay 1 & 2
4th click -Open Relay 1 & 2 (both lights off)
2 fast clicks -Open Relay 1 & 2 at any point in the loop (both lights off)

Latching Rocker Position Function Pin 6:

When HIGH -Close Relay 1 & 2 | AND IMPORTANT Reset Pin 7 State Logic
When LOW -Close Relay 1 & 2 | AND IMPORTANT Reset Pin 7 State Logic

HERE IS THE PROBLEM
The code below is for a typical Arduino board momentary push button (Normally HIGH when Closed) only connected to Pin 7

Current Hardware differences:
Rocker Switch (N/O LOW) with the Momentary position connected to Pin 7 and Latching position (N/O LOW) connected to Pin 6.

I call on someone to simplify this code for the above mentioned hardware.
Note: this code was designed for 3 lights with a push button N/C.

Good Luck!

// Pin assignement WORKING FRONT LIGHTS
#define btnPin 7
#define led1Pin 8
#define led2Pin 9
#define led3Pin 10
enum fcnMode { 
OFF, 
LED1, 
LED2, 
ALL,
NBSTATE
}; // OFF = 0 and NBSTATE=4
int ledState1 = LOW,ledState2 = LOW,ledState3 = LOW;             // ledState used to set the LED
unsigned long buttonState = 0;
int funcState=3;
unsigned long currentMillis1,currentMillis2,currentMillis3;        // will store current time
unsigned long previousMillis1,previousMillis2,previousMillis3;        // will store last time LED was updated
const long interval1 = 100;           // interval at which to blink (milliseconds)
const long interval2 = 300;
const long interval3 = 500;
/******************************************************************\
* PRIVATE FUNCTION: setup
*
* PARAMETERS:
* ~ void
*
* RETURN:
* ~ void
*
* DESCRIPTIONS:
* Initiate inputs/outputs
*
\******************************************************************/
void setup(){
Serial.begin(9600); // initialize serial port
pinMode(btnPin,INPUT_PULLUP);
pinMode(led1Pin,OUTPUT);
pinMode(led2Pin,OUTPUT);
pinMode(led3Pin,OUTPUT);
}
/******************************************************************\
* PRIVATE FUNCTION: loop
*
* PARAMETERS:
* ~ void
*
* RETURN:
* ~ void
*
* DESCRIPTIONS:
* Main Function of the code 
\******************************************************************/
void loop(){
buttonPressed();
setMode();
}
/******************************************************************
* SUBFUNCTIONS 
\******************************************************************/
void buttonPressed() {
buttonState = pulseIn(btnPin,HIGH,1000000);
if (buttonState > 50){
funcState += 1;
Serial.print("Button state n: ");
Serial.println(funcState);
}
funcState=funcState%NBSTATE;
}
void setMode() {
// All Off
digitalWrite(led1Pin,LOW);
digitalWrite(led2Pin,LOW);
digitalWrite(led3Pin,LOW);

Serial.print("Function : ");
Serial.println(funcState); 
switch(funcState){

case LED1:
digitalWrite(led1Pin,HIGH);
break;
case LED2:
digitalWrite(led2Pin,HIGH);
break;
case ALL:
digitalWrite(led1Pin,HIGH);
digitalWrite(led2Pin,HIGH);
digitalWrite(led3Pin,HIGH);
break;
case OFF:
break;

}
}

I'm having difficulty understanding the rocker switch. Can you show a diagram of its electrical contact design.
The result of using the latch function is the same is the same in both cases : -Close Relay 1 & 2 | AND IMPORTANT Reset Pin 7 State Logic. Was that intended ?
In principle, the solution is a simple state machine.

arduihome21:
2 fast clicks -Open Relay 1 & 2 at any point in the loop (both lights off)

I call on someone to simplify this code for the above mentioned hardware.
Note: this code was designed for 3 lights with a push button N/C.

consider

#if 0       // my  hardware
const byte butPin  = A1;
byte ledPins [] = { 10, 11, 12 };

#else
const byte butPin  = 7;
byte ledPins [] = { 8, 9, 10 };
#endif

#define N_LED   sizeof(ledPins)
#define MAX_LED_STATE   (1 << N_LED)

enum { OFF = HIGH, ON = LOW };

byte butLst = OFF;
byte state  = 0;        // all OFF

unsigned long msecLst = 0;
unsigned long msec;

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

    for (unsigned n = 0; n < N_LED; n++)  {
        digitalWrite (ledPins [n], OFF);
        pinMode (ledPins [n], OUTPUT);
    }

    pinMode (butPin, INPUT_PULLUP);
}

// -----------------------------------------------------------------------------
void
loop (void)
{
    msec = millis ();
    byte but = digitalRead (butPin);

    if (butLst != but)  {   // check for change
        butLst = but;
        delay (10);   // debounce

        if (ON == but)  {       // process press
            if ((msec - msecLst) < 150)     // 2 fast clicks
                state = 0;
            else
                state = (state+1) % MAX_LED_STATE;      // increment and wrap

            // set LEDS to inverse of corresponding state bits
            byte st = state;
            for (unsigned n = 0; n < N_LED; n++)  {
                digitalWrite (ledPins [n], ! (st & 1)); // set to inverse
                st >>= 1;                               // shift right
            }
        }

        msecLst = msec;
    }
}

When HIGH -Close Relay 1 & 2 | AND IMPORTANT Reset Pin 7 State Logic

amended to recognize latch switch on 2nd pin

#if 0       // my  hardware
const byte momButPin  = A1;
const byte lchButPin  = A2;

byte ledPins [] = { 10, 11, 12 };

#else
const byte momButPin  = 7;
const byte lchButPin  = 6;

byte ledPins [] = { 8, 9, 10 };
#endif

#define N_LED   sizeof(ledPins)
#define MAX_LED_STATE   (1 << N_LED)

enum { OFF = HIGH, ON = LOW };

byte momButLst = OFF;
byte lchButLst = OFF;
byte state  = 0;        // all OFF

unsigned long msecLst = 0;
unsigned long msec;

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

    for (unsigned n = 0; n < N_LED; n++)  {
        digitalWrite (ledPins [n], OFF);
        pinMode (ledPins [n], OUTPUT);
    }

    pinMode (momButPin, INPUT_PULLUP);
    pinMode (lchButPin, INPUT_PULLUP);
}

// -----------------------------------------------------------------------------
void
loop (void)
{
    msec = millis ();
    byte momBut = digitalRead (momButPin);
    byte lchBut = digitalRead (lchButPin);

    // check latched rocker switch
    if (lchButLst != lchBut)  {
        lchButLst = lchBut;
        delay (10);     // debounce

        if (ON == lchBut)
            state = 3;
        else
            state = 0;
    }

    // otherwise check for momentary switch press
    else if (momButLst != momBut)  {
        momButLst = momBut;
        delay (10);     // debounce

        if (ON == momBut)  {
            if ((msec - msecLst) < 150)     // 2 fast clicks
                state = 0;
            else
                state = (state+1) % MAX_LED_STATE;      // increment and wrap
        }

        msecLst = msec;
    }


    // set LEDS to inverse of corresponding state bits
    byte st = state;
    for (unsigned n = 0; n < N_LED; n++)  {
        digitalWrite (ledPins [n], ! (st & 1)); // set to inverse
        st >>= 1;                               // shift right
    }
}

gcjr:
amended to recognize latch switch on 2nd pin

#if 0       // my  hardware

const byte momButPin  = A1;
const byte lchButPin  = A2;

byte ledPins = { 10, 11, 12 };

#else
const byte momButPin  = 7;
const byte lchButPin  = 6;

byte ledPins = { 8, 9, 10 };
#endif

Hi Greg, almost there.
Just to clarify, Pin 10 is not used. There is only two relay on pin 8 & 9.

I loaded up the code, here are the results:

-The latching position doesn’t trigger any relay but does reset the count.
-The double click doesn’t turn-off all relay or reset the count.
I think this might be due to the fact that you assumed that I was using Pin 10. This was just residual from a previous code.

In summary Button on Pin 6&7
Relays on Pin 8&9
Special Request: Double click should reset and turn-off both relays but also do the opposite which is turn-on both relays when in the OFF state.

Talk soon.
Thank you

i don’t post code i can’t check. i had hoped you would understand the code and and make it work for you

if the 3rd led isn’t used, the sequencing should still work for the 1st two

so more likely that i assume an active LOW output (ON = LOW) i should have inverted the enum states

enum { ON = HIGH, OFF = LOW };

i defined double click as < 150 msec. this may be more difficult for you to do. take a look at the value defining a double click.

Hi Greg, still no luck.

I did invert the states, As a result both relays are ON when booting the arduino. Should be OFF all relays should be OFF for safety purposes.

enum { OFF = LOW, ON = HIGH };

Also, the latching relay is connected independently to the Pin 6. This would turn ON and OFF both lights at the same time. I do not see the Pin 6 stated in the code. That might be why this latching relay is interfering with the momentary count and not accomplishing the independent function it was intended for.

Does that make sense?
Talk soon

Current Code:

#if 0       // my  hardware
const byte butPin  = A1;
byte ledPins [] = { 10, 11, 12 };

#else
const byte butPin  = 7;
byte ledPins [] = { 8, 9, 10 };
#endif

#define N_LED   sizeof(ledPins)
#define MAX_LED_STATE   (1 << N_LED)

enum { OFF = LOW, ON = HIGH };

byte butLst = OFF;
byte state  = 0;        // all OFF

unsigned long msecLst = 0;
unsigned long msec;

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

    for (unsigned n = 0; n < N_LED; n++)  {
        digitalWrite (ledPins [n], OFF);
        pinMode (ledPins [n], OUTPUT);
    }

    pinMode (butPin, INPUT_PULLUP);
}

// -----------------------------------------------------------------------------
void
loop (void)
{
    msec = millis ();
    byte but = digitalRead (butPin);

    if (butLst != but)  {   // check for change
        butLst = but;
        delay (10);   // debounce

        if (ON == but)  {       // process press
            if ((msec - msecLst) < 100)     // 2 fast clicks
                state = 0;
            else
                state = (state+1) % MAX_LED_STATE;      // increment and wrap

            // set LEDS to inverse of corresponding state bits
            byte st = state;
            for (unsigned n = 0; n < N_LED; n++)  {
                digitalWrite (ledPins [n], ! (st & 1)); // set to inverse
                st >>= 1;                               // shift right
            }
        }

        msecLst = msec;
    }
}

arduihome21:
Also, the latching relay is connected independently to the Pin 6.

are you looking at the 2nd version of code i posted. your last post seemed to repost my 1st version.

is it a latching "switch" or a 3rd "lathching" relay? i don't see a pin 6 in the code you posted

arduihome21:
I did invert the states, As a result both relays are ON when booting the arduino. Should be OFF all relays should be OFF for safety purposes.

this is why in the code i posted i set the state of the pin before configuring it as an OUTPUT. i didn't see this in the code you posted

i'm unsure about the active state of your outputs. in the code you posted, it appears the LEDs are turned on by setting the pin HIGH. one purpose for the enumeration is to avoid any confusion about whether HIGH/LOW is turning something on/off

enum { OFF = LOW, ON = HIGH };

Hi Greg, I did apply the enum. I just saw that didn't show up in the code above. My apologies.

You're correct. The code I posted Did not contain a pin 6. We need to add that. It was not in the original system.

is it a latching "switch" or a 3rd "lathching" relay? i don't see a pin 6 in the code you posted

There are two relays only. It is a latching switch.

i'm unsure about the active state of your outputs.

The active state occurs when the switch is engage = the output is HIGH (N/O). We need to trigger pin on HIGH from what I understand.

I'm stuck.

Post your latest code.

arduihome21:
It is a latching switch.

while i've never seen a switch like this, i got the impression that it is a rocker swtich. when presses on the one side, it latches (closed), pressing it again unlatches it, and is connected to pin 6. when pressed on the opposite side, is momentarily closed, pin 7

arduihome21:
The active state occurs when the switch is engage = the output is HIGH (N/O). We need to trigger pin on HIGH from what I understand.

active state of both the switches and relays.

sounds like you connect the switch(es) between the pin and 5V (?). a more common approach is to configure the input with a pullup and simply connect the switch between the pin and ground.

still not sure about what state turns on the relays. the code appears to set the LEDs high to turn them on. i assumed ON = LOW.

seems you still haven't looked thru the code to understand how it works. it's based on your explanations and the code you posted which appears incomplete.

i believe the code has all the functionality you're looking for. some minor changes may be needed, but you're in the best position to make those changes

wildbill:
Post your latest code.

Hi Wildbill, I am back to square one. I believe Greg did not read my original post where all the information he is assuming later was stated. I do not understand his code.

Thank you for your help.

Here is the code I started with.:

// Pin assignement WORKING FRONT LIGHTS
#define btnPin 7
#define led1Pin 8
#define led2Pin 9
#define led3Pin 10
enum fcnMode { 
OFF, 
LED1, 
LED2, 
ALL,
NBSTATE
}; // OFF = 0 and NBSTATE=4
int ledState1 = LOW,ledState2 = LOW,ledState3 = LOW;             // ledState used to set the LED
unsigned long buttonState = 0;
int funcState=3;
unsigned long currentMillis1,currentMillis2,currentMillis3;        // will store current time
unsigned long previousMillis1,previousMillis2,previousMillis3;        // will store last time LED was updated
const long interval1 = 100;           // interval at which to blink (milliseconds)
const long interval2 = 300;
const long interval3 = 500;
/******************************************************************\
* PRIVATE FUNCTION: setup
*
* PARAMETERS:
* ~ void
*
* RETURN:
* ~ void
*
* DESCRIPTIONS:
* Initiate inputs/outputs
*
\******************************************************************/
void setup(){
Serial.begin(9600); // initialize serial port
pinMode(btnPin,INPUT_PULLUP);
pinMode(led1Pin,OUTPUT);
pinMode(led2Pin,OUTPUT);
pinMode(led3Pin,OUTPUT);
}
/******************************************************************\
* PRIVATE FUNCTION: loop
*
* PARAMETERS:
* ~ void
*
* RETURN:
* ~ void
*
* DESCRIPTIONS:
* Main Function of the code 
\******************************************************************/
void loop(){
buttonPressed();
setMode();
}
/******************************************************************
* SUBFUNCTIONS 
\******************************************************************/
void buttonPressed() {
buttonState = pulseIn(btnPin,HIGH,1000000);
if (buttonState > 50){
funcState += 1;
Serial.print("Button state n: ");
Serial.println(funcState);
}
funcState=funcState%NBSTATE;
}
void setMode() {
// All Off
digitalWrite(led1Pin,LOW);
digitalWrite(led2Pin,LOW);
digitalWrite(led3Pin,LOW);

Serial.print("Function : ");
Serial.println(funcState); 
switch(funcState){

case LED1:
digitalWrite(led1Pin,HIGH);
break;
case LED2:
digitalWrite(led2Pin,HIGH);
break;
case ALL:
digitalWrite(led1Pin,HIGH);
digitalWrite(led2Pin,HIGH);
digitalWrite(led3Pin,HIGH);
break;
case OFF:
break;

}
}

Hardware
Arduino Uno
2 High Voltage Relay Connected to LED Flood Lights
1 Rocker Switch Triggers WHEN HIGH & N/O (LOW) .:

  • Rocking up is a latching contact (N/O LOW)
  • Rocking down is a momentary (N/O LOW)

I am a seasoned electrician.
I have two flood lights controlled by two high voltage relays. I am using a rocker switch the one used for ships with a fuse. They run on 12v. I have all the step-down hooked up to feed only 5v. to my Arduino Uno control pins 6 & 7.

Goals:
Momentary Rocker Position Function Pin 7:
1st click -Close Relay 1 ONLY
2nd click -Close Relay 2 ONLY
3rd click -Close Relay 1 & 2
4th click -Open Relay 1 & 2 (both lights off)
2 fast clicks -Open Relay 1 & 2 at any point in the loop (both lights off)

Latching Rocker Position Function Pin 6:

When HIGH -Close Relay 1 & 2 | AND IMPORTANT Reset Pin 7 State Logic
When LOW -Close Relay 1 & 2 | AND IMPORTANT Reset Pin 7 State Logic

HERE IS THE PROBLEM
The code below is for a typical Arduino board momentary push button (Normally HIGH when Closed) only connected to Pin 7

Current Hardware differences:
Rocker Switch (N/O LOW) with the Momentary position connected to Pin 7 and Latching position (N/O LOW) connected to Pin 6.

I call on someone to simplify this code for the above mentioned hardware.
Note: this code was designed for 3 lights with a push button N/C. It needs to be modified for a 2 light system with a Rocker Switch.

6v6gt:
I'm having difficulty understanding the rocker switch. Can you show a diagram of its electrical contact design.
The result of using the latch function is the same is the same in both cases : -Close Relay 1 & 2 | AND IMPORTANT Reset Pin 7 State Logic. Was that intended ?
In principle, the solution is a simple state machine.

Since you are "back at square 1", perhaps you could also answer this since it is clearly a source of confusion.

6v6gt:
Since you are "back at square 1", perhaps you could also answer this since it is clearly a source of confusion.

It's a it's a Rocker switch like one of those. It is connected directly to the pin 6 & 7.
Pin 6 receives 5v from the top latching position
Pin 7 receives 5v from the bottom momentary position

The result of using the latch function is the same is the same in both cases : -Close Relay 1 & 2 | AND IMPORTANT Reset Pin 7 State Logic. Was that intended ?
In principle, the solution is a simple state machine.

That's correct. That's what's intended.

So it appears to ba a single pole, double throw switch.

The top Terminal is connected to pin 6
The middle terminal (common) is wired to 5 volts
The bottom Terminal is connected to pin 7

Pin 6 and pin 7 have pull down resistors (say 10k)

A press on the bottom part of the rocker has the effect that pin 7 is momentarily pulled HIGH.
It reverts to a middle position on release, where neither pin 6 nor pin 7 is connected to HIGH.

A single press on the top part of the rocker latches and holds pin 6 HIGH.
A second press on the top part of the rocker unlatches it neither pin 6 nor pin 7 is connected to HIGH.

Is that it ?

Ignoring the 2 fast clicks for a moment, the rest of what you’re trying to do seems simple enough. However, I don’t understand the purpose of the latched switch since it apparently does the same thing whether it’s on or off.

It sounds like it could be a ‘centre-off’ spring return to centre SPDT switch.
One side is momentary, the other is a toggle.

lastchancename:
It sounds like it could be a ‘centre-off’ spring return to centre SPDT switch.
One side is momentary, the other is a toggle.

That's correct.

wildbill:
Ignoring the 2 fast clicks for a moment, the rest of what you're trying to do seems simple enough. However, I don't understand the purpose of the latched switch since it apparently does the same thing whether it's on or off.

The purpose is to make sure my wife is able to use it one way or another and to have a quick "all lights on" for security purposes.