Hello,
I’m having difficulty with the millis function to delay the start of an event.
In this case I want to drive an output LOW after an input has been pulled HIGH but the input will remain HIGH the entire cycle.
I have managed to somewhat make it work but I think the “button check” portion of the code is causing my trouble. The code only executes after the button has been held down for a period of time and then released.
Any suggestions?
Thanks in advance!
const byte SW1 = 3; //cycle start switch
int SW1State = 0; // current state of the button SW1
int lastSW1State = 0; // previous state of the button SW1
unsigned long SW1PushedMillis; // when button (SW1) was switched
unsigned long stepperTurnedOnAt; // when STEPPER was turned on
unsigned long turnOnDelay = 3000; // turn on STEPPER after this time
bool stepperReady = false; // flag for when button SW1 is let go
bool stepperState = false; // for STEPPER is on or not.
#include <AccelStepper.h>
AccelStepper stepper(AccelStepper::DRIVER, 9, 8);
void setup() {
pinMode(8, OUTPUT);//stepper driver direction control
digitalWrite(8, LOW);//output to control direction of motor
pinMode(9, OUTPUT);//driver output to stepper driver
digitalWrite(9, LOW);//output to drive stepper controller
pinMode(SW1, INPUT);//cycle start switch
pinMode(11, OUTPUT); // enable pin on driver
digitalWrite(11, HIGH); // disables driver output when high
stepper.setMaxSpeed(1000);
stepper.setSpeed(200);
}
void loop() {
stepper.runSpeed();
// get the time at the start of this loop()
unsigned long currentMillis = millis();
// read the pushbutton input pin:
SW1State = digitalRead(SW1);
// compare the buttonState to its previous state
if (SW1State != lastSW1State) {
// if the state has changed
if (SW1State == HIGH) {
// update the time when button was pushed
SW1PushedMillis = currentMillis;
stepperReady = true;
}
if (stepperReady) {
if ((unsigned long)(currentMillis - SW1PushedMillis) >= turnOnDelay) {
digitalWrite(11, LOW);
// setup our next "state"
stepperState = true;
// save when the STEPPER turned on
stepperTurnedOnAt = currentMillis;
// wait for next button press
stepperReady = false;
}
// save the current state as the last state, for next time through the loop
lastSW1State = SW1State;
}
}
}
LesPaul:
In this case I want to drive an output LOW after an input has been pulled HIGH but the input will remain HIGH the entire cycle.
I can't relate that to your code and I can't figure what is the purpose of your code.
To implement what I have quoted above, all you need is (pseudo code)
if (input == HIGH) {
output = LOW;
}
My guess is that you have not identified your requirement sufficiently clearly. When I get stuck I write things down (on a piece of paper or on a text editor) so I can see the whole requirement clearly.
Robin2:
I can't relate that to your code and I can't figure what is the purpose of your code.
To implement what I have quoted above, all you need is (pseudo code)
if (input == HIGH) {
output = LOW;
}
My guess is that you have not identified your requirement sufficiently clearly. When I get stuck I write things down (on a piece of paper or on a text editor) so I can see the whole requirement clearly.
...R
Robin, the purpose of my code is to drive pin 11 low 3 seconds after an input has been made, the input will remain on the entire cycle. Sorry if I didn't explain it well enough to begin with.
the purpose of my code is to drive pin 11 low 3 seconds after an input has been made, the input will remain on the entire cycle. Sorry if I didn't explain it well enough to begin with.
You still haven't. What will cause pin 11 to go (back to) HIGH?
Detecting when pin goes HIGH (or LOW) ("the input") is trivial. That is the purpose of the state change detection example.
Recording when that happened is trivial. That's what the millis() function is for.
Independently, determining that now (millis() again) minus then (when the input was made) exceeds, or does not exceed, some interval is trivial. Taking the appropriate action - setting pin 11 LOW - is easy. Setting pin 11 LOW when it is already LOW doesn't hurt a thing. On the other hand, keeping track of its state is easy, so setting it LOW when it is already LOW isn't necessary.
But, when should it go HIGH again? 3 seconds after the input ends? A week from next Tuesday? Never?
It seems perfectly simple. The problem with the code is what I hinted at in post #1
Currently, this:
if (stepperReady) {
if ((unsigned long)(currentMillis - SW1PushedMillis) >= turnOnDelay) {
digitalWrite(11, LOW);
// setup our next "state"
stepperState = true;
// save when the STEPPER turned on
stepperTurnedOnAt = currentMillis;
// wait for next button press
stepperReady = false;
}
}
is only executed when the switch changes state… you want it outside of the if (SW1State != lastSW1State) { … }
so it executes when the ‘stepperReady’ flag has been set.
LesPaul:
Robin, the purpose of my code is to drive pin 11 low 3 seconds after an input has been made, the input will remain on the entire cycle. Sorry if I didn't explain it well enough to begin with.
Ahhh - that is much clearer - why didn't you say so in your Original Post
Is it necessary for the input to stay HIGH throughout the 3 seconds or will a momentary HIGH be sufficient.
First, I want to thank everyone for their feedback.
Please understand that I have only been tinkering with programming for a couple of months.
Tony, Yes you are correct the code only executes after the state changes from LOW to HIGH and back to LOW and the SW1 must be held HIGH for at least the duration of the turnONdelay for that to work. SW1 will be held HIGH the entire event.
Paul, I'm trying to learn one thing at the time. At some point in the future I will want OUTPUT 11 to be driven HIGH once again with another input from a IR photo eye. IT does not have to be a timed event meaning, it may take an hour for the cycle to complete. I just want to be able to drive it high when the IR sensor is met.
Robin, Yes due to the nature of this test the input will have no choice but to be HIGH the entire event.
This input will be handled through an Omron roller switch on a feed chute, when the chute is closed for loading of the hopper will the input change from HIGH to LOW.
Thank you once again for being patient with an old man.
KE4CVD
LesPaul:
Robin, Yes due to the nature of this test the input will have no choice but to be HIGH the entire event.
That does not actually answer my question. The code will need to be different if there must be a test for a continuous HIGH compared to the situation where a momentary high is sufficient.
Thank you once again for being patient with an old man.
You are lot younger than I am, so less of the "old", thank you.