Go Down

Topic: I need help with a manual or override switch between my 2 functions (Read 167 times) previous topic - next topic

sam87

Hi Arduino Community, I am new to Ardunio and I am working on a school project that is an automated bottle opener and crusher, I have setup my codes with Delay so the actuator extends then the opener does its things and then it retracts up using Delay in the Void setup area by sequencing different relays. ( I know I should probably look into implementing Millis() function but I did not know how to do it!)

I also have a button setup on my bread board where I want to take priority or have a manual switch to turn on if needed before the loop takes over. ( Right now I have to wait till the Void setup code finishes, then in the loop I have the buttons setup so I can manually crush up and down using the actuator)

What I like to do is either have an override key that my buttons move the actuator up and down before the delay codes work for the opening mechanism OR just have a manual switch so I can assign which code to use at the time, Could you please help?

here are the codes I have:

Code: [Select]

// constants won't change. They're used here to set pin numbers:
const int button1Pin = 1;     // the number of the pushbutton1 pin (Down)
const int button2Pin = 2;     // the number of the pushbutton2 pin (Up)
const int RELAY1 = 6;      // Actuator Retracting
const int RELAY2 = 7;      // Actuator Extending

// variables will change:
int button1State = 0;         // variable for reading the pushbutton status
int button2State = 0;         // variable for reading the pushbutton status

const int sensorPin = 0;    // select the input pin for the potentiometer
int sensorValue = 0;  // variable to store the value coming from the sensor


// initialize the pushbutton pin as an input:

// initialize the relay pin as an output:


const int RELAY3 = 4;      // Bottle Opener reverse
const int RELAY4 = 5;      // Bottle Opener opening

void setup() {

 //start serial connection
 Serial.begin(9600);


 // Initialise the Arduino data pins for OUTPUT
 pinMode(button1Pin, INPUT);
 pinMode(button2Pin, INPUT);
 pinMode(RELAY3, OUTPUT);
 pinMode(RELAY4, OUTPUT);
 pinMode(RELAY1, OUTPUT);
 pinMode(RELAY2, OUTPUT);


 digitalWrite(RELAY1, HIGH);
 delay(3000);
 digitalWrite(RELAY1, LOW);
 delay(1000);
 digitalWrite(RELAY3, LOW);
 delay(1000);
 digitalWrite(RELAY1, LOW);
 delay(1000);
 digitalWrite(RELAY2, HIGH);
 delay(1500);
 digitalWrite(RELAY2, LOW);
 delay(5000);
 digitalWrite(RELAY4, HIGH);
 delay(5500);
 digitalWrite(RELAY4, LOW);
 // Wait 5 seconds to retract + 2 + & - 2 -
 // Turns OFF Relays 2
 delay(5500);
 digitalWrite(RELAY3, HIGH);
 delay(3000);
 digitalWrite(RELAY3, LOW);
 delay(3000);
 
 
 digitalWrite(RELAY1, HIGH);         // Turns Relay On
 delay(2000);                          // Wait 45 seconds to retract + 2 + & - 2 -
 digitalWrite(RELAY2, LOW);
 delay(2000);
 digitalWrite(RELAY3, LOW);
 delay(2000);
 digitalWrite(RELAY4, LOW);          // Turns OFF Relays 2
 delay(2000);
 

}
void loop() {

 // read the value from the sensor:
 sensorValue = analogRead(sensorPin);
 //print out the value of the pushbutton
 Serial.println(sensorValue);   
 
 // read the state of the pushbutton values:
 button1State = digitalRead(button1Pin);
 button2State = digitalRead(button2Pin);

 // check if the pushbutton1 is pressed.
 // if it is, the buttonState is HIGH:
 // we also ensure tha the other button is not pushed to avoid conflict
 if (button1State == HIGH && button2State == LOW) {     
   // turn relay1 on:   
   digitalWrite(RELAY1, HIGH);     
 }
 // When we let go of the button, turn off the relay
 else if (digitalRead(RELAY1) == HIGH) {
   // turn relay1 off:
   digitalWrite(RELAY1, LOW);
 }
 
 // repeat the same procedure for the second pushbutton
 if (button1State == LOW && button2State == HIGH) {     
   // turn relay2 on:   
   digitalWrite(RELAY2, HIGH);
 }
 // When we let go of the button, turn off the relay
 else if (digitalRead(RELAY2) == HIGH) {
   // turn relay2 off:
   digitalWrite(RELAY2, LOW);
 } 
}

Robin2

What you want to do can only happen if you get rid of the delay()s. Time for some learning. :)

Have a look at Using millis() for timing. A beginners guide  and at the demo Several Things at a Time


...R
Two or three hours spent thinking and reading documentation solves most programming problems.

Jimmus

Normally, you use setup() to initialize your Serial object and set the pinMode() on your pins and digitalWrite() all your pins to starting values.  You wouldn't put any relay movement code there.  It would be in a separate function called in an if conditional from the loop() function.

You can short circuit the crush sequence by checking for button pushes between short delays, and returning early if you get a push.

Sort of like this.  * Untested code *
Code: [Select]

// constants won't change. They're used here to set pin numbers:
const int button1Pin = 1;     // the number of the pushbutton1 pin (Down)
const int button2Pin = 2;     // the number of the pushbutton2 pin (Up)
const int RELAY1 = 6;      // Actuator Retracting
const int RELAY2 = 7;      // Actuator Extending

// variables will change:
int button1State = 0;         // variable for reading the pushbutton status
int button2State = 0;         // variable for reading the pushbutton status

const int sensorPin = 0;    // select the input pin for the potentiometer
int sensorValue = 0;  // variable to store the value coming from the sensor

const int RELAY3 = 4;      // Bottle Opener reverse
const int RELAY4 = 5;      // Bottle Opener opening

byte crushSequenceFlag = 0;  // Set to 1 when the Crush sequence has been run

void setup() {

 //start serial connection
 Serial.begin(9600);

// initialize the pushbutton pins and sensor pin as inputs:
 pinMode(button1Pin, INPUT);
 pinMode(button2Pin, INPUT);
 pinMode(sensorPin, INPUT);

// initialize the relay pins as outputs:
 pinMode(RELAY3, OUTPUT);
 pinMode(RELAY4, OUTPUT);
 pinMode(RELAY1, OUTPUT);
 pinMode(RELAY2, OUTPUT);

  // Initially, all the relays should be off
  digitalWrite(RELAY1, LOW);
  digitalWrite(RELAY2, LOW);
  digitalWrite(RELAY3, LOW);
  digitalWrite(RELAY4, LOW);
}

// This function returns 0 if no button was pushed, or 1 if a button was pushed.
byte delayWhileCheckingPushButtons(unsigned int delayTime)
{
  for (unsigned int i = 0; i < delayTime; i += 10)
  {
    delay(10);
    if (digitalRead(button1Pin) == HIGH || digitalRead(button2Pin) == HIGH)
      return(1);
  }
  return(0);
}

void crushSequence()
{
 digitalWrite(RELAY1, HIGH);
 if (delayWhileCheckingPushButtons(3000))
    return;
 digitalWrite(RELAY1, LOW);
 if (delayWhileCheckingPushButtons(1000))
    return;
 digitalWrite(RELAY3, LOW);
 if (delayWhileCheckingPushButtons(1000))
    return;
 digitalWrite(RELAY1, LOW);
 if (delayWhileCheckingPushButtons(1000))
    return;
 digitalWrite(RELAY2, HIGH);
 if (delayWhileCheckingPushButtons(1500))
    return;
 digitalWrite(RELAY2, LOW);
 if (delayWhileCheckingPushButtons(5000))
    return;
 digitalWrite(RELAY4, HIGH);
 if (delayWhileCheckingPushButtons(5500))
    return;
 digitalWrite(RELAY4, LOW);
 // Wait 5 seconds to retract + 2 + & - 2 -
 // Turns OFF Relays 2
 if (delayWhileCheckingPushButtons(5500))
    return;
 digitalWrite(RELAY3, HIGH);
 if (delayWhileCheckingPushButtons(3000))
    return;
 digitalWrite(RELAY3, LOW);
 if (delayWhileCheckingPushButtons(3000))
    return;
 
 digitalWrite(RELAY1, HIGH);         // Turns Relay On
 if (delayWhileCheckingPushButtons(2000))  // Wait 45 seconds to retract + 2 + & - 2 -
    return;
 digitalWrite(RELAY2, LOW);
 if (delayWhileCheckingPushButtons(2000))
    return;
 digitalWrite(RELAY3, LOW);
 if (delayWhileCheckingPushButtons(2000))
    return;
 digitalWrite(RELAY4, LOW);          // Turns OFF Relays 2
 if (delayWhileCheckingPushButtons(2000))
    return;
}

void loop() {
  // Run the Crush sequence once.  The first time loop() runs.
  if (crushSequenceFlag == 0)
  {
    crushSequence();
    crushSequenceFlag = 1;
  }

 // read the value from the sensor:
 sensorValue = analogRead(sensorPin);
 //print out the value of the pushbutton
 Serial.println(sensorValue);   
 
 // read the state of the pushbutton values:
 button1State = digitalRead(button1Pin);
 button2State = digitalRead(button2Pin);

 // check if the pushbutton1 is pressed.
 // if it is, the buttonState is HIGH:
 // we also ensure tha the other button is not pushed to avoid conflict
 if (button1State == HIGH && button2State == LOW) {     
   // turn relay1 on:   
   digitalWrite(RELAY1, HIGH);     
 }
 // When we let go of the button, turn off the relay
 else if (digitalRead(RELAY1) == HIGH) {
   // turn relay1 off:
   digitalWrite(RELAY1, LOW);
 }
 
 // repeat the same procedure for the second pushbutton
 if (button1State == LOW && button2State == HIGH) {     
   // turn relay2 on:   
   digitalWrite(RELAY2, HIGH);
 }
 // When we let go of the button, turn off the relay
 else if (digitalRead(RELAY2) == HIGH) {
   // turn relay2 off:
   digitalWrite(RELAY2, LOW);
 } 
}

sam87

Thank you, The codes you provided only works with the buttons and moves the actuator up and down but the time sequenced opener motor and actuator going up and down portion of the code doesnt work and since I am not really good with codings I cant seem to figure out why! is there anyway you can tell me the logics in your code?


I am trying to have two functions= 1 to sequencing actuator to go to down(Relay2) for x seconds then opener Relay4 starts opening the bottle then Relay 3 reverses to release cap and open up, then Relay1 to retract the actuator to home base,

Then 2nd function based on my current code is in the loop and starts after the delays of the above and you can use buttons 1 and 2 to manually crush bottles, I want these two functions to be either have a switch to select in between the 2 or there is an over ride for the crushing mechanism to take priority. Is there a way you can help with it?



Also I looked into Millis and I was not able to do this using millis() instead of Delay().There is little time left for this project to be presented so I am not sure if theres time to change all of it up to millis with my current knowledge.


Thanks

MorganS

Try not to think about two independent functions. They're not independent. Halfway through the automatic cycle, you can't press the "manual crush" button and expect it to do that, can you?

Think of it as states. If you're in Idaho, you can go to Oregon or Nevada but you can't go to California without first passing through one of those states. If you're currently extending the actuator then you probably have to retract it before responding to the next button-push. If you're in Idaho, it also makes no sense to go to Idaho: you're already there. You must go to another state (like retract-actuator) before you can extend again.

The beginning of the automatic cycle, it moves the down actuator (please give them names and not just Relay1 and Relay2) and waits for either: 1. the cycle time expires, 2. the end-switch is hit by the actuator, 3. the emergency-stop button is pushed. Each of those transitions might take you to another state where something different happens. Now that may superficially look the same - both the normal-stop and emergency-stop will stop the actuator but there will be different rules on what you can do after each of those events, so those are actually two different states, which allows the machine to remember where it came from: did it come from the normal-stop or the emergency-stop?
"The problem is in the code you didn't post."

sam87

That makes sense, However I am not sure how to stop with a press of a button. Also I wanna be able to choose which function to run first with a press of a button (Introducing a button 3 if needed), is there a way to do it?


My codes so far:
Code: [Select]

// constants won't change. They're used here to set pin numbers:
const int button1Pin = 1;     // the number of the pushbutton1 pin (Down)
const int button2Pin = 2;     // the number of the pushbutton2 pin (Up)
const int RELAY1 = 6;      // Actuator Retracting
const int RELAY2 = 7;      // Actuator Extending

// variables will change:
int button1State = 0;         // variable for reading the pushbutton status
int button2State = 0;         // variable for reading the pushbutton status

const int sensorPin = 0;    // select the input pin for the potentiometer
int sensorValue = 0;  // variable to store the value coming from the sensor


// initialize the pushbutton pin as an input:

// initialize the relay pin as an output:


const int RELAY3 = 4;      // Bottle Opener reverse
const int RELAY4 = 5;      // Bottle Opener opening

void setup() {

 //start serial connection
 Serial.begin(9600);


 // Initialise the Arduino data pins for OUTPUT
 pinMode(button1Pin, INPUT);
 pinMode(button2Pin, INPUT);
 pinMode(RELAY3, OUTPUT);
 pinMode(RELAY4, OUTPUT);
 pinMode(RELAY1, OUTPUT);
 pinMode(RELAY2, OUTPUT);


 digitalWrite(RELAY1, HIGH);
 delay(3000);
 digitalWrite(RELAY1, LOW);
 delay(1000);
 digitalWrite(RELAY3, LOW);
 delay(1000);
 digitalWrite(RELAY1, LOW);
 delay(1000);
 digitalWrite(RELAY2, HIGH);
 delay(1500);
 digitalWrite(RELAY2, LOW);
 delay(5000);
 digitalWrite(RELAY4, HIGH);
 delay(5500);
 digitalWrite(RELAY4, LOW);
 // Wait 5 seconds to retract + 2 + & - 2 -
 // Turns OFF Relays 2
 delay(5500);
 digitalWrite(RELAY3, HIGH);
 delay(3000);
 digitalWrite(RELAY3, LOW);
 delay(3000);
 
 
 digitalWrite(RELAY1, HIGH);         // Turns Relay On
 delay(2000);                          // Wait 45 seconds to retract + 2 + & - 2 -
 digitalWrite(RELAY2, LOW);
 delay(2000);
 digitalWrite(RELAY3, LOW);
 delay(2000);
 digitalWrite(RELAY4, LOW);          // Turns OFF Relays 2
 delay(2000);
 

}
void loop() {

 // read the value from the sensor:
 sensorValue = analogRead(sensorPin);
 //print out the value of the pushbutton
 Serial.println(sensorValue);   
 
 // read the state of the pushbutton values:
 button1State = digitalRead(button1Pin);
 button2State = digitalRead(button2Pin);

 // check if the pushbutton1 is pressed.
 // if it is, the buttonState is HIGH:
 // we also ensure tha the other button is not pushed to avoid conflict
 if (button1State == HIGH && button2State == LOW) {     
   // turn relay1 on:   
   digitalWrite(RELAY1, HIGH);     
 }
 // When we let go of the button, turn off the relay
 else if (digitalRead(RELAY1) == HIGH) {
   // turn relay1 off:
   digitalWrite(RELAY1, LOW);
 }
 
 // repeat the same procedure for the second pushbutton
 if (button1State == LOW && button2State == HIGH) {     
   // turn relay2 on:   
   digitalWrite(RELAY2, HIGH);
 }
 // When we let go of the button, turn off the relay
 else if (digitalRead(RELAY2) == HIGH) {
   // turn relay2 off:
   digitalWrite(RELAY2, LOW);
 } 
}

MorganS

Here's the best tutorial available online for state machines: http://www.thebox.myzen.co.uk/Tutorial/State_Machine.html

Yes, you can add another button. Whatever you want. But start by drawing the states on a piece of paper and deciding which button is going to do what. You will very quickly end up with many, many states.
"The problem is in the code you didn't post."

Go Up