Pages: [1] 2   Go Down
Author Topic: Momentary switch with latching code  (Read 9713 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello,

I've been doing simple things with the arduino but I'm having a few problems some code for a momentary switch and I'm not sure how to "latch" the code so it doesn't continue switching a relay when the switch is held.

Here is what I'm trying to achieve:

When the momentary switch is pressed, I need the LED to light (uno led on pin 13) and the relay to switch.  When pressed again the LED should turn off and the relay switch back.  I'm using a dual latching relay that has a current pulse requirement of around 20mA @5V.  WIth the code I posted below the relay is switching via a short pulse on a high and low pin and the led is lighting.  The problem is that the LED and relay continue to change status when the switch is held.  I need it to stop switching and retain the status if the switch is held by accident.  Right now it will flip a few times on one short push.  It's also slightly erratic, sometimes it doesn't register the switch.  Also, I'm using an external pull up resistor, not the uno's internal pull up.

Thanks for any assistance!

Code:
/*
 Alternating LED and relay switching
 */

#include <Bounce.h>

const int inputPin = 2;      // momentary switch
const int ledPin =  13;      // the number of the LED pin
const int relayPin1 =  12;   // relay +
const int relayPin2 = 11;    // relay -

int ledState = LOW;           // the current state of the output pin
int lastbuttonState = LOW;   // the previous reading from switch

Bounce bouncer = Bounce(inputPin,75);   //setting up debounce for the push button

void setup()
{
  pinMode(inputPin, INPUT);
  pinMode(ledPin, OUTPUT);
  pinMode(relayPin1, OUTPUT);
  pinMode(relayPin2, OUTPUT);
}

void loop() {

  bouncer.update ( );    // Update the debouncer for the push button

  int value = bouncer.read();     // Get the update value

  int reading = value == HIGH;

  if (lastbuttonState == LOW && reading == HIGH)
  {
    digitalWrite (ledPin, HIGH);
    digitalWrite (relayPin2, LOW);
    digitalWrite (relayPin1, HIGH);
    delay (100);
    digitalWrite (relayPin1, LOW);
  }
bouncer.update ( );    // Update the debouncer for the push button

int val = bouncer.read();     // Get the update value

  int read = val == HIGH;
 
 if (lastbuttonState == LOW && read == HIGH)
  {
    digitalWrite (ledPin, LOW);
    digitalWrite (relayPin1, LOW);
    digitalWrite (relayPin2, HIGH);
    delay (100);
    digitalWrite (relayPin1, LOW);
  }
}
Logged

Belgium
Offline Offline
Full Member
***
Karma: 6
Posts: 135
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I Haven't read the full code but the following pops out:

  • The following line is bit strange:     int reading = value == HIGH;
  • in the second block i see two times in a row : digitalWrite (relayPin1, LOW);
  • When is 'lastbuttonState' made high in the code
« Last Edit: March 02, 2013, 02:36:11 pm by astrofrostbyte » Logged

Gear: Arduino- Uno,Due,Ethernet,  OLS, Buspirate, J-Link, TDS1002, Rigol DG1022

Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks, it should have been     digitalWrite(relayPin2, LOW)  but it's still acting the same.

The switch sometimes switches the led and relay and sometimes it does not.  I don't know if it's the way I have the debounce code/library written or not.  But if I hold the switch it cycles the relay and LED.  I need it to "latch"

Without     int reading = value == HIGH;  the code does not work

Here is the updated code

Code:
/*
 Alternating LED's
 */

#include <Bounce.h>

const int inputPin = 2;    // momentary switch
const int ledPin =  13;      // the number of the LED pin
const int relayPin1 =  12;
const int relayPin2 = 11;

int ledState = LOW;           // the current state of the output pin
int lastbuttonState = LOW;   // the previous reading from first push button pin

Bounce bouncer = Bounce(inputPin,75);   //setting up debounce for the first push button

void setup()
{
  pinMode(inputPin, INPUT);
  pinMode(ledPin, OUTPUT);
  pinMode(relayPin1, OUTPUT);
  pinMode(relayPin2, OUTPUT);
}

void loop() {

  bouncer.update ( );    // Update the debouncer for the push button

  int value = bouncer.read();     // Get the update value

  int reading = value == HIGH;

  if (lastbuttonState == LOW && reading == HIGH)
  {
    digitalWrite (ledPin, HIGH);
    digitalWrite (relayPin2, LOW);
    digitalWrite (relayPin1, HIGH);
    delay (500);
    digitalWrite (relayPin1, LOW);
  }
bouncer.update ( );    // Update the debouncer for the push button

int val = bouncer.read();     // Get the update value

  int read = val == HIGH;
 
 if (lastbuttonState == LOW && read == HIGH)
  {
    digitalWrite (ledPin, LOW);
    digitalWrite (relayPin1, LOW);
    digitalWrite (relayPin2, HIGH);
    delay (500);
    digitalWrite (relayPin2, LOW);
  }
}


Logged

Belgium
Offline Offline
Full Member
***
Karma: 6
Posts: 135
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

See if you can follow the following,  it has a statemachine (switch-case) that 'walks' through the stages of how the system should behave.
Its a common way to code these types of things

State/Case 0:  the system is OFF and in rest, we are waiting for someone to push a button.  
                      If someone pushes button we switch on Relay and led and go to the next state
State/case 1:  here we wait untill the button is released
                      if button is released we go to the next state.
State/case 2:  here the system is ON and we are in rest,  we are waiting for someone to push button

...etc....

Code:
/*  Alternating LED's  */
#include <Bounce.h>

const int inputPin = 2;    // momentary switch
const int ledPin =  13;      // the number of the LED pin
const int relayPin1 =  12;
const int relayPin2 = 11;

byte mode = 0;

Bounce bouncer = Bounce(inputPin,75);   //settup debounce for first push button

void setup()
{ pinMode(inputPin, INPUT);
  pinMode(ledPin, OUTPUT);
  pinMode(relayPin1, OUTPUT);
  pinMode(relayPin2, OUTPUT);
}

void loop() {
  bouncer.update ( );    // Update the debouncer for the push button
  switch( mode )
  {
    case 0://------------------------ I'm off and in restmode
      if ( bouncer.read() == HIGH )
      { // switch relay ON
        // switch LED ON
        mode = 1;
      }
      break;
    case 1://------------------------ I'm in ON mode, w8 4 keyrelease
      if ( bouncer.read() == LOW )
        mode = 2;
      break;
    case 2://------------------------ I'm ON and in restmode
      if ( bouncer.read() == HIGH )
      { // switch relay OFF
        // switch LED OFF
        mode = 3;
      }
      break;
    case 3://------------------------ I'm in OFF mode, w8 4 keyrelease
      if ( bouncer.read() == LOW )
        mode = 0;
      break;
  }//switch


}//loop

Code is untested and the case gives you the framework, still need to fill in the Relay ON/OFF and LED On/OFF
« Last Edit: March 02, 2013, 03:39:02 pm by astrofrostbyte » Logged

Gear: Arduino- Uno,Due,Ethernet,  OLS, Buspirate, J-Link, TDS1002, Rigol DG1022

Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks so much for the help.  I'll plug in the missing pieces and try it out!

 smiley
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Got it, works perfect.  Thank you for steering me in the correct direction.  I looked into switch cases much deeper and it certainly helped fill in some of the gaps of my newbie knowledge.

Thanks again for your help.
Logged

Belgium
Offline Offline
Full Member
***
Karma: 6
Posts: 135
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

no prob's glad to help.
Logged

Gear: Arduino- Uno,Due,Ethernet,  OLS, Buspirate, J-Link, TDS1002, Rigol DG1022

Lost Wages
Offline Offline
Full Member
***
Karma: 11
Posts: 103
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Nice work astro. Karma bump.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 9
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey There,

I am a newbie to arduino and am trying to accomplish the same problem. This is an awesome case statement code, but is not working as anticipated. I am using the same 5V relay with 20mA switching current.

Could you post the updated code used? I know it has been a year since this thread was active but if you still have it saved I would greatly appreciate it.

Thanks!
Logged

UK
Offline Offline
Tesla Member
***
Karma: 106
Posts: 6392
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@cterjesen,  can you describe what you are trying to do?

If you just want to press a button and have a relay stay on for a specified time something like this should work (not tested)

Code:
unsigned long relayDuration = 5000;  // number of millisecs - adust to suit
unsigned long relayStartMillis = 0;
byte switchVal = HIGH;
boolean relayOn = false;
byte switchPin = 8;
byte relayPin = 9;

void setup() {
   pinMode(switchPin, INPUT_PULLUP);  // pin will be HIGH when switch is open
   pinMode(relayPin, OUTPUT);
   digitalWrite(relayPin, LOW); // assume LOW = off
}

void loop() {
   readPin();
   operateRelay();
}

void readPin() {
  switchVal = digitalRead(switchPin);
}

void operateRelay() {
   if (relayOn == false) {
      if (switchVal == HIGH) {
          relayStartMillis = millis();
          digitalWrite(relayPin, HIGH);
          relayON = true;
      }
   }
  else {   // this happens if relayON == true
      if (millis() - relayStartMills >= relayDuration) {     // time has expired
           digitalWrite(relayPin, LOW);
           relayON = false;
       }
   }
}

...R
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 9
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey Robin2,

Thanks for the quick reply!

Here is my situation: I am using a single coil DPDT latching relay to switch between 2 audio signals. I would like to control the relay with a momentary switch that sends a quick pulse to the relay.

The ultimate goal is to program an ATtiny85 to switch the relay. I understand that I need a transistor network to increase current to switch the relay because like the Arduino Uno, the ATtiny85 has a max current output of only 20mA. The relay needs around 30mA to switch. I have been trying it with a 2n3904 transistor and have been having luck switching the relay but not being able to switch it back. Here is the data sheet for the AL-5WN-K relay that I am using:

http://www.fujitsu.com/downloads/MICRO/fcai/relays/a.pdf

This page has helped me clarify how to operate a single coil relay with an Arduino but a quick glance at the schematic shows that current will only flow in one direction.

http://www.electroschematics.com/8975/arduino-control-relay/

I greatly appreciate your help Robin2!
Logged

UK
Offline Offline
Tesla Member
***
Karma: 106
Posts: 6392
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

a quick glance at the schematic shows that current will only flow in one direction.

Why would you want it to flow in 2 directions?

It sounds like you don't have a problem with code (so maybe I have been wasting my time) and that your problem is with the transistor connection. That's not my specialty.

It probably would have made more sense if you had started your own Thread with a title that reflects your own problem. You could still do that. Just include a link to this for continuity.

...R
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 9
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The relay is a single coil DPDT latching relay. If the current flows in 1 direction, the relay switches. Visa versa.

The code you provided almost worked but I cannot figure out how to tweak. My digital in on pin 8 (the switch) and my relay pins are on pin 2 and 3. Here is what I need to happen:

Switch is press (pin 8 reads a signal)

Pin 2 == High
Pin 3 == Low

this only needs to be a short pulse then

Pin 2 == Low
Pin 3 == Low

Until the button is pressed again THEN

Pin 2 == LOW
Pin 3 == HIGH

again, this only needs to be a small pulse.
 
I am very new to arduino but I understand this is what has to happen. Could you help me write this out?
Logged

UK
Offline Offline
Tesla Member
***
Karma: 106
Posts: 6392
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I am a little concerned by your requirement to change the state of two pins to drive one relay. I hope you are not expecting the Arduino pins to provide the full current for the relay coil. Can you draw a wiring diagram for your project and post a photo of the drawing?

As to the code (assuming you do need to control 2 pins) ...

Where my code in the function operateRelay() has
Code:
digitalWrite(relayPin, HIGH);
you could just add another line so it looks like
Code:
digitalWrite(relayPin, HIGH);
digitalWrite(relayPin2, LOW);

...R
Logged

UK
Offline Offline
Tesla Member
***
Karma: 106
Posts: 6392
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

hi, may i ask you some question? Arduino R3  got code for timer???if got can you show me??thanks~~

As this is a new question, please start your own Thread - you will get help much more easily that way.

...R

Edit to add - it looks like someone deleted something I replied to.
« Last Edit: June 09, 2014, 01:28:28 pm by Robin2 » Logged

Pages: [1] 2   Go Up
Jump to: