Arm and Engage relays with 1 button

Wayne

Well-known member
I'm trying to use millis() in this setup and have an issue.. Here is the info:

The conditions: (one pedal)
Press pedal once activates the ARM relay.
If pedal is not pressed in 9 secs drop ARM relay.
If pedal is pressed within 9 secs engage the Expose Relay and hold the ARM relay until pedal is released.
If during the 9 secs and the pedal is tap, drop the ARM relay and do not engage the Expose relay.
How long is a tap, prob a sec or so..

I have it all working until the tap.
If I tap quick, the ARM relay which is on and it drops without engaging the Expose relay.
If a bit longer, the Expose pops on and along with the ARM relay but both drops when pedal is released.

Code is kinda a hit or miss.. I can post it if required. Not long..

A good chance is that the start of this code was probably in the wrong mind path and I stuck to it.

My code using millis() seems that I can't stop once its started. So some part plays with the relays (Engage I think)

Wayne
 
Yup, if I do it pass a few seconds or before the timeout of 9 secs, the Engage relay pops on and off.. quick but it could cause an issue.. If I do it within a sec or a little more it does not engage the Engage relay..
 
Code: Not at all clean...

Code:
unsigned long time_now = 0;
unsigned long time_now2 = 0;
int LED = 25;
int LED2 = 26;
int SW = 23;
int SWwasLO = 0;
int noGO = 0;
int norepeat = 0;
void setup() {

  Serial.begin(115200);
  pinMode(LED, OUTPUT);
  pinMode(LED2, OUTPUT);
  pinMode(SW, INPUT_PULLUP);
  //digitalWrite(LED,LOW);
  //digitalWrite(LED2,LOW);
}

void loop() {

  if ((digitalRead(SW) == 0) && (SWwasLO == 1) && ((millis() - time_now > 420)))
  {
    //delay(10);
    Serial.println("At Start SW==0 SWwasLO ==1 and millis time_now");
    time_now = (millis() + 9000);
    //time_now = 0;
    //digitalWrite(LED2, HIGH);
    noGO = 1;
  }

  if (digitalRead(SW) == 0 && SWwasLO == 0)
  {
    armrlyheld();
  } 
  if ((digitalRead(SW) == 1) && (SWwasLO == 1))//&& (time_now2 ==0))
  {
    timeoutrlys();
  }

  if ((digitalRead(SW) == 0) && (digitalRead(LED) == LOW) && (norepeat == 0) && (noGO == 1) && (SWwasLO == 1) && (millis() - time_now2 > 3000))
  {
    Serial.println("ARM and EXPOSE relay on");
    digitalWrite(LED2, LOW);
    //norepeat=1;
    time_now2 = 0;
  } else if ((digitalRead(SW) == 0) && (digitalRead(LED) == LOW) && (norepeat == 0) && (noGO == 1) && (SWwasLO == 1) && (millis() - time_now2 > 1020))
  {
    Serial.println(" Dropping ARM and EXPOSE");
    //digitalWrite(LED2, HIGH);
    //norepeat=1;
    time_now2 = 0;
    //SWwasLO = 0;
  }
}

void armrlyheld()
{
  Serial.println("ARM Relay Held");
  digitalWrite(LED, LOW);
  digitalWrite(LED2, HIGH);
  time_now = millis();
  time_now2 = millis();
  SWwasLO = 1;
  noGO = 1;
}

void timeoutrlys()
{
  if (millis() - time_now > 9000) {
    Serial.println("ARM and EXPOSED Relay Timed Out or Dropped");
    digitalWrite(LED, HIGH);
    digitalWrite(LED2, HIGH);
    time_now = 0;
    SWwasLO = 0;
    norepeat = 0;
    time_now2 = 0;
  }
}
 
From your description, I envisioned state driven code and a switch case type of structure. For example:

Code:
loop(){

static unsigned long t;

   if( t != millis() ){
     t = millis();
     
     if( digitalRead(SW) == 0 ) ++pressed, not_pressed = 0;
     else ++not_pressed, pressed = 0;
   
     switch( state ){
        case IDLE:   if( pressed > 50 ) state = ARM1;   
        break;

        case ARM1:   if( not_pressed > 50 ) state = ARM2;  // require release to enter ARM
        break;

        case ARM2:   if( pressed > 50 ) state = ARM3;
                     if( not_pressed > 9000 ) state = IDLE;
        break;
  
        case ARM3:   if( pressed > 1000 ) state = EXPOSE;   // expose or cancel
                     if( not_pressed > 50 ) state = IDLE;
        break;

        case EXPOSE: if( not_pressed > 50 ) state = IDLE;
        break;

     }


   }

}
 
From your description, I envisioned state driven code and a switch case type of structure. For example:

Code:
loop(){

static unsigned long t;

   if( t != millis() ){
     t = millis();
     
     if( digitalRead(SW) == 0 ) ++pressed, not_pressed = 0;
     else ++not_pressed, pressed = 0;
   
     switch( state ){
        case IDLE:   if( pressed > 50 ) state = ARM1;   
        break;

        case ARM1:   if( not_pressed > 50 ) state = ARM2;  // require release to enter ARM
        break;

        case ARM2:   if( pressed > 50 ) state = ARM3;
                     if( not_pressed > 9000 ) state = IDLE;
        break;
  
        case ARM3:   if( pressed > 1000 ) state = EXPOSE;   // expose or cancel
                     if( not_pressed > 50 ) state = IDLE;
        break;

        case EXPOSE: if( not_pressed > 50 ) state = IDLE;
        break;

     }


   }

}

Wow, never did I think of switch case. I'm going to give this a go..

This is a great help.
Note: don't type and hiccup at the same time.. Does not work well when typing..
 
Wow, never did I think of switch case. I'm going to give this a go..

This is a great help.
Note: don't type and hiccup at the same time.. Does not work well when typing..

Success... Works really good. Did lower the >1000 to >300 and works great.

Thanks a bunch.. If -Then are good. I did use Switch Case on another project of which PJRC ends up selling a few bootloaders once in awhile.

Note to Paul, If the 2800 project (not this one) goes and works with the proto boards, be needing 100 of those chips.
The process is develop, get samples, fix design if needed, test test test and give to customer. Not this time.. Its get 5 boards to give to cust. They test.. then get the rest.

I hope I coded good and that the outputs are at least 5 v to drive their equipment.

On scope it looked good..
 
Back
Top