Solved - One latching button two relays

I'm pretty good with electronics but my programming skills are pretty basic. I want to be able to use one button to turn on two relays but I want one relay to stay on while the button is latched and the other relay to turn off after one second.

const int buttonPin = 2;  // the number of the pushbutton pin
//const int buttonPin2 = 3;  // the number of the pushbutton pin
const int relay1 = 12;  // the number of the LED pin
const int relay2 = 11;  // the number of the LED pin

// variables will change:
int buttonState = 0;  // variable for reading the pushbutton status
const long interval = 1000;

void setup() {

  pinMode(relay1, OUTPUT);
  pinMode(relay2, OUTPUT);
  pinMode(buttonPin, INPUT);
  //pinMode(buttonPin2, INPUT);
}

void loop() {
  // read the state of the pushbutton value:
  unsigned long currentMils = millis();
  buttonState = digitalRead(buttonPin);

  // check if the pushbutton is pressed. If it is, the buttonState is HIGH:
  if (buttonState == HIGH) {
    // turn LED on:
    digitalWrite(relay1, HIGH);
    digitalWrite(relay2, HIGH);
    if (currentMils = interval) {
      digitalWrite(relay2, LOW);
    }

  } else {
    // turn LED off:
    digitalWrite(relay1, LOW);
  }
}

I would greatly appreciate any help. Thank you.

Not perfect, but an improvement.

const int buttonPin = 2;  // the number of the pushbutton pin
//const int buttonPin2 = 3;  // the number of the pushbutton pin
const int relay1 = 12;  // the number of the LED pin
const int relay2 = 11;  // the number of the LED pin

// variables will change:
int buttonState = 0;  // variable for reading the pushbutton status
const long interval = 1000;

void setup() {

  pinMode(relay1, OUTPUT);
  pinMode(relay2, OUTPUT);
  pinMode(buttonPin, INPUT);
  //pinMode(buttonPin2, INPUT);
}

void loop() 
{
  // read the state of the pushbutton value:
  buttonState = digitalRead(buttonPin);

  // check if the pushbutton is pressed. If it is, the buttonState is HIGH:
  if (buttonState == HIGH) 
  {
    // turn LEDs on:
    digitalWrite(relay1, HIGH);
    digitalWrite(relay2, HIGH);
    // Timeout
    delay(interval);
    // Back off
    digitalWrite(relay2, LOW);
  }
  else 
  {
    // turn LED off:
    digitalWrite(relay1, LOW);
  }
}
1 Like

Here you almost certainly want == (test for equality), not = (assignment).

    if (currentMils = interval) {

but more important is you have not followed the necessary pattern for timing.

Review "blink without delay", an example in the IDE.

The essence of timing is to

  • note the time when you start something
  • continuously check if an interval has passed meaning stop.

Use unsigned long variables.

Set a timer when you turn the relay on

    myTimer = millis();  // time we started timing

    // turn relay on

check a timer to see if relay should be turnt off.

    if (millis() - myTimer > 5000) {  // has five seconds elapsed

        // turn relay off

    }

HTH

a7

1 Like

I really appreciate the help but your code did the exactly the same as mine but two thumbs up for the effort

Looks like if you keep the button down, the relay that is supposed to turn off after some time will be continuously retriggerable, perhaps just appearing to stay on.

a7

1 Like

Thank you, give me a few minutes to try it and I'll let you know. Thank you.

That's exactly what happens.

Considering that I removed this bug

if (currentMils = interval)

that's unlikely

Yup, that's expected. Hence my comment that it's not perfect, just improved. Incomplete requirements that require guessing at what the poster wants are ignored.

Yeah, what sense could anyone make of a statement like

:expressionless:

a7

@autonomousKaos you picked a good problem for running into some basic issues with doing things because a button got, or stayed, pressed.

I usually recommend that noobs take the trouble to learn how to debounce a pushbutton, and recognize and act when it gets pushed, not because it is (still) being pushed.

And of course you need to master the blink without delay paradigm.

For the button handling, I post a sketch showing how a library, here ezButton, can be used to solve up a bigger half of this hole problem.

I can't test this - right now the power is blinking on and off due to who knows why? and I am leaving the big rig off until this settles.

But close:

// not cheating - use  button library
#  include <ezButton.h>

// wire the button between the pin and ground
ezButton myButton(2);  // ez button on pin 2

void setup() {
  Serial.begin(115200);
  Serial.println("Easy ezButton Examlpe"):

  myButton.setDebounceTime(20);
}

void loop() {

  myButton.loop();  // check on what's up with the button

  if (myButton.isPressed()) {
    Serial.println("I see the button go down");
  }

  if (myButton.isReleased()) {
    Serial.println("I see the button go up");
  }
}

Imma bet you can use that example and figure out where you might add statements to turn on and off relays, and start and check timers.

a7

This is a reply to all, I'm sharing my tinkercad project and you can try you're changes on it and let me know if you get anything different from my experience. Just to clarify, I want the LED to stay on while the button is latched and the piezo busser to come on at the same time but turn off after 1 second. Thank you both for your help, Your ideas are helpful with my thought process.

Tinkercad Project

Actual Button
Actual Relay
Piezo

Hello autonomousKaos

Welcome to the world's best Arduino forum ever.

What is the task of your sketch in real life?

It may be that your original sketch behaves the same as an offered "improvement".

Yours would have the output you want following the pushbutton doing just that, or appearing to, and the other output would have been rapidly switching between HIGH and LOW, being HIGH for considerably longer than LOW and thus too appearing to be on alla time.

Rather than have us try our changes on your code, it would make more sense for you to apply our advices to your next steps, be they tinkering with the code or reading about

  • blink without delay

  • button debouncing

  • state change detection

a7

Let's say we're playing hokey and you hit a guy in his face with you're stick. The ref gives you a penalty and the penalty light and a buzzer come on at the same when the ref pushes his pause button. I don't want the buzzer to be on the whole length of time he's pressing pause button.

You could try it like this..

Red is latched, green is not.

1 Like

Hello autonomousKaos

Check this example that has to be configured to your hardware setup.

//https://forum.arduino.cc/t/one-latching-button-two-relays/1241251/1
//https://europe1.discourse-cdn.com/arduino/original/4X/7/e/0/7e0ee1e51f1df32e30893550c85f0dd33244fb0e.jpeg
#define ProjectName "One latching button two relays"
#define NotesOnRelease "Arduino MEGA tested"
// make names
enum TimerEvent {NotExpired, Expired};
enum TimerControl {Halt, Run};
enum RelayNames {RelayOne, RelayTwo};
enum ButtonStates {Released, Pushed};
// make variables
uint32_t currentMillis = millis();
constexpr uint8_t RelayPins[] {9, 10};
constexpr uint8_t ButtonPin {A0}; // configured as INPUT_PULLUP
// make structures
struct TIMER
{
  uint32_t interval;
  uint8_t control;
  uint32_t now;
  uint8_t expired(uint32_t currentMillis)
  {
    uint8_t timerEvent = currentMillis - now >= interval and control;
    if (timerEvent == Expired) now = currentMillis;
    return timerEvent;
  }
};
struct BUTTON2RELAY
{
  uint8_t name;
  uint8_t relay;
  uint8_t button;
  uint8_t stateOld;
  TIMER wait;
  TIMER debounce;
  void make()
  {
    pinMode (button, INPUT_PULLUP);
    pinMode (relay, OUTPUT);
    stateOld = digitalRead(button) ? LOW : HIGH;
    wait.interval = 1000;
    wait.control = Halt;
    wait.now = currentMillis;
    debounce.interval = 20;
    debounce.control = Run;
    debounce.now = currentMillis;
  }
  void run()
  {
    if (debounce.expired(currentMillis) == Expired)
    {
      uint8_t stateNew = digitalRead(button) ? LOW : HIGH;
      if (stateOld != stateNew)
      {
        stateOld = stateNew;
        switch (name)
        {
          case RelayOne:
            digitalWrite(relay, stateOld);
            break;
          case RelayTwo:
            if (stateNew == Pushed)
            {
              digitalWrite(relay, HIGH);
              wait.control = Run;
              wait.now = currentMillis;
            }
            break;
        }
      }
    }
    if (wait.expired(currentMillis) == Expired) digitalWrite(relay, LOW);
  }
} button2relays[]
{
  {RelayOne, RelayPins[RelayOne], ButtonPin, 0, 0, 0, 0, 0, 0, 0},
  {RelayTwo, RelayPins[RelayTwo], ButtonPin, 0, 0, 0, 0, 0, 0, 0},
};
// make support
void heartBeat(const uint8_t LedPin, uint32_t currentMillis)
{
  static bool setUp = false;
  if (setUp == false) pinMode (LedPin, OUTPUT), setUp = true;
  digitalWrite(LedPin, (currentMillis / 500) % 2);
}
// make application
void setup()
{
  Serial.begin(115200);
  Serial.print("Source: "), Serial.println(__FILE__);
  Serial.print(ProjectName), Serial.print(" - "), Serial.println(NotesOnRelease);
  for (auto &button2relay : button2relays) button2relay.make();
  Serial.println(" =-> and off we go\n");
}
void loop()
{
  currentMillis = millis();
  heartBeat(LED_BUILTIN, currentMillis);
  for (auto &button2relay : button2relays) button2relay.run();
}

Have a nice day and enjoy coding in C++.

Thank you everyone for the help @jimLee that was exactly what I was looking for now I get to do research on callback functions @paulpaulson that example is a little above my level but thank you and I will definitely be taking that on in the near future, again thank you all for the help