Arduino Switch to Turn a Relay timer

2019-09-09 03:18发布

问题:

Briefly: I would like to turn on a relay for 30 seconds, after I toggle a switch on.

I'm trying to do a blinds automation at home.

I have a simple ON-OFF-ON switch, attached to an Arduino connected to Relays.

I want to turn on Relay#1 for a maximum of 30 seconds if I toggle the switch down from center. In other words, relay turns on when I switch, and when timer reaches 30 seconds relay turns off.

similarly I want to turn on Relay#2 for exactly 30 seconds if I toggle the switch up from center

And when I switch back to center, I would like the timer to reset.

I could not figure out how. Could anyone help?

I have been trying to use elapsedMillis library for this, which is a nice library that helps me avoid using Delays: http://playground.arduino.cc/Code/ElapsedMillis

However even though I could work the relays without the 30 second limitation, I couldn't figure out the code to end working of the relays. Here is my current code:

      #include <elapsedMillis.h>
    #define RELAY_ON 0
    #define RELAY_OFF 1

    #define RELAY1_TURNS_ON_BLINDS  5
    #define RELAY2_SHUTS_DOWN_BLINDS 6

    #define shutswitch A0
    #define openswitch A1

    bool LocalCommandToOpen;
    bool LocalCommandToShut;

    void setup() ////////SETUP////////
    {
    digitalWrite(RELAY1_TURNS_ON_BLINDS, RELAY_OFF);
     digitalWrite(RELAY2_SHUTS_DOWN_BLINDS, RELAY_OFF);

     pinMode(RELAY1_TURNS_ON_BLINDS, OUTPUT);
     pinMode(RELAY2_SHUTS_DOWN_BLINDS, OUTPUT);

     pinMode(shutswitch, INPUT);
     pinMode(openswitch, INPUT);
        } ////SETUP

  void loop() { ///////LOOP
         if (digitalRead(shutswitch) == 1)
     {
       LocalCommandToOpen = 1;
     }
     else
     {
       LocalCommandToOpen = 0;
     }

      if ( digitalRead(openswitch) == 1)
     {
       LocalCommandToShut = 1;
     }
     else
     {
       LocalCommandToShut = 0;
     }

    unsigned int CloseInterval = 14000;
     elapsedMillis timeElapsedSinceCloseButtonPush = 0;
     unsigned int OpenInterval = 14000;
     elapsedMillis timeElapsedSinceOpenButtonPush = 0;



     //MANUAL SWITCH OPERATION

     if ( LocalCommandToShut == 1 )
     {
       digitalWrite(RELAY1_TURNS_ON_BLINDS, RELAY_OFF);
       digitalWrite(RELAY2_SHUTS_DOWN_BLINDS, RELAY_ON);
     }
     else
     {
       digitalWrite(RELAY2_SHUTS_DOWN_BLINDS, RELAY_OFF);
     }

    //MANUEL DUGME ILE ACMA
     if ( LocalCommandToOpen == 1)
     {
       digitalWrite(RELAY2_SHUTS_DOWN_BLINDS, RELAY_OFF);
       digitalWrite(RELAY1_TURNS_ON_BLINDS, RELAY_ON);
     }
     else
     {
       digitalWrite(RELAY1_TURNS_ON_BLINDS, RELAY_OFF);
     }

     delay(500);

    } /////////////////LOOP////////////////////////////////////

回答1:

One suggestion here is to use a "state machine", so that upon a switch transition, you get 'State 1'; in that state, a timer starts, and puts you in 'State 2'. In 'State 2', you check the time, and if it goes beyond X seconds, you go to 'State 3'. You can monitor the transition of a switch from low to high (or high to low), and use this to reset the state of the system.

A sample bit of code gives you an idea of how to implement this. The variable 'SystemState' is an integer, and SYSTEM_ABORT, SYSTEM_IDLE, etc. are constants.

The beauty of this is that the transition is easy to figure out. For example, if you are in the SYSTEM_WAIT state, the only thing you are looking for is the time to be greater than 5 seconds. Also, you can look at input transitions or values to set states (like SystemStopButton == 0, to set the state to be 'SYSTEM_ABORT').

    // SystemStopButton is an input

    void SystemStateMachine(void)
      ///////////////////////////////////////////////////////////////////////////////////////////
        {

          if (SystemStopButton == 0)
          {
            SystemState = SYSTEM_ABORT;
          }

          switch (SystemState)
          {
            case SYSTEM_IDLE:
              {
                RunPinState = OFF;
                StopPinState = OFF;
                if (SystemRunButton == 0)
                {
                  SystemState = SYSTEM_START;
                  ShowStep();
                }
                break;
              }
            case SYSTEM_START:
              {
                StandardMessage = "START  ";
                RunPinState = ON;
                StopPinState = OFF;
                SystemState = SYSTEM_WAIT;
                ShowStep();
                break;
              }
            case SYSTEM_WAIT: // wait for 5 seconds
              {
                StandardMessage = "WAIT    ";
                if ((CurrentMillis - StateStepTimeMillis) > 5000)
                {
                  SystemState = SYSTEM_RETRACT;
                  ShowStep();
                }
                break;
              }

            case SYSTEM_RETRACT: //
              {
                StandardMessage = "RETRACT";
                /* motor stuff goes here... */
                if ((CurrentMillis - StateStepTimeMillis) > 5000)
                {
                  SystemState = SYSTEM_ADVANCE_TAPE_WAIT
                  ShowStep();
                }
                break;
              }

            // etc. etc. etc.

          case SYSTEM_ABORT: //
              {
                StandardMessage = "ABORT";
                /* motor stop stuff goes here... */
          SystemState=SYSTEM_IDLE;
                break;
              }

            default:
              {
                break;
              }
          }


        }

        void ShowStep(void)
        /////////////////////////////////////////////////////////////////////
        // show step and set time so we can keep track of time in each step
        {
          Serial.print("SystemState = ");
          Serial.println(String(SystemState));
          SetStepTime();
        }

        void SetStepTime(void)
        /////////////////////////////////////////////////////////////////////
        {
          StateStepTimeMillis = CurrentMillis;
        }


回答2:

You might use a state machine; this makes things a bit easier to follow.

Similar to:

Arduino Switch to Turn a Relay timer

A nice discussion of state machines is here:

Complicated state transitions: best practices