I've been trying without any success to add a timer to this code.
What I'm wanting to do is turn the relay on and off with the button (this part works), but when the relay is turned on start a delay off timer to turn off the relay after X seconds
int button1 = 0;
int rl1 = 5;
//States for Relay and Button (1)
int state1 = HIGH; // the current state of the output pin
int reading1; // the current reading from the input pin
int previous1 = LOW; // the previous reading from the input pin
long time1 = 0; // the last time the output pin was toggled
long debounce1 = 200; // the debounce time, increase if the output flickers
unsigned long turnOnDelay = 3000;
void setup() {
// put your setup code here, to run once:
pinMode(button1, INPUT);
pinMode(button1, INPUT_PULLUP);
pinMode(rl1, OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
reading1 = digitalRead(button1);
unsigned long currentMillis = millis();
//Condition Relay 1
if (reading1 == HIGH && previous1 == LOW && millis() - time1 > debounce1) {
if (state1 == HIGH)
state1 = LOW;
else
state1 = HIGH;
time1 = millis();
}
digitalWrite(rl1, state1);
previous1 = reading1;
}
Hello mayfield016,
nobody is responding you ? a few remarks ! (I am not so fluent in english...)
Syntax : it is better to separate with ( ) the different terms, otherwise it is necessary to know the priority of treatment of the conditions. I forgot it for a long time!
But even when you are used to programming, condensing multiple conditions in a single line of instructions is difficult to understand, and often leads to logic errors (beyond 2 conditions, at least for me...)
Separate them :
unsigned long turnOnStart; // place it at the top of code
if (reading1 == HIGH) { // button is pressed
turnOnStart = millis(); // start the timer
digitalWrite(rl1, 1); // relay ON
}
else { // button is released
if (millis()-turnOnStart > turnOnDelay) { // decrease the timer, and at the end,
digitalWrite(rl1, 0); // turn relay OFF
}
}
I sometimes spend several hours looking for a silly mistake.
I forgot, I always work in negative logic on my buttons: they are active when set to zero; I forgot the inversion (!) in my button test.
if (!digitalRead(button1))
voilà la correction
int button1 = 0; // pin Button (but pin 0 & 1 are for serial, prefer 2 or else
int rl1 = 5; // pin Relay
int turnOnDelay; // tempo (3000 * 1 millisecond = 3 seconds)
unsigned long previousMillis; // for count the millisecond
void setup() { // put your setup code here, to run once:
pinMode(button1, INPUT);
pinMode(button1, INPUT_PULLUP);
pinMode(rl1, OUTPUT);
}
void loop() { // put your main code here, to run repeatedly:
if (!digitalRead(button1)) { // in this case, no need for debounce
turnOnDelay = 3000; // tempo 3 seconds begin when button is released
digitalWrite(rl1, 1); // turn ON the relay
PORTB |= B00100000; // PB5 = 1 (internal led ON)
}
if (previousMillis != millis()) { // wait for 1 millisecond delay
previousMillis = millis(); // reload for next millisecond
if (turnOnDelay) { // if turnOnDelay > 0 (button was activated)
turnOnDelay--; // decrease 3 seconds tempo (3000 * 1 millisecond)
if (turnOnDelay == 0) {
digitalWrite(rl1, 0); // when it reach 0, turn OFF the relay
PORTB &= B11011111; // PB5 = 0 (internal led OFF)
}
}
}
}
You use pin 0 as button input, but pins 0 and 1 are also used for the serial link; later on, you could choose another pin, we prefer to keep those to use with the serial monitor, for example.
sorry, I could have put a more understandable instruction :
PORTB |= Bxxxxxxxx
is the same as :
digitalWrite(13, 1); // turn ON the internal LED
digitalWrite(13, 0); // turn OFF the internal LED
I have been playing around with your code and it's getting me closer. What would I need to add to the code to manually turn off the relay before the timer does?
for example push button to turn on - timer starts then before timer times out a button press turns off relay/cancels timer
int button1 = 0; // pin Button (but pin 0 & 1 are for serial, prefer 2 or else
int rl1 = 5; // pin Relay
int turnOnDelay; // tempo (3000 * 1 millisecond = 3 seconds)
unsigned long previousMillis; // for count the millisecond
void setup() { // put your setup code here, to run once:
pinMode(button1, INPUT);
pinMode(button1, INPUT_PULLUP);
pinMode(rl1, OUTPUT);
digitalWrite(rl1, 1);
digitalWrite(13, 0);
}
void loop() { // put your main code here, to run repeatedly:
if (!digitalRead(button1)) { // in this case, no need for debounce
turnOnDelay = 3000; // tempo 3 seconds begin when button is released
digitalWrite(rl1, 0); // turn ON the relay
//PORTB |= B00100000; // PB5 = 1 (internal led ON)
digitalWrite(13, 1); // turn ON the internal LED
}
if (previousMillis != millis()) { // wait for 1 millisecond delay
previousMillis = millis(); // reload for next millisecond
if (turnOnDelay) { // if turnOnDelay > 0 (button was activated)
turnOnDelay--; // decrease 3 seconds tempo (3000 * 1 millisecond)
if (turnOnDelay == 0) {
digitalWrite(rl1, 1); // when it reach 0, turn OFF the relay
//PORTB &= B11011111; // PB5 = 0 (internal led OFF)
digitalWrite(13, 0); // turn OFF the internal LED
}
}
}
}
I simplified a part at the bottom of the code that was unnecessarily complicated.
With a second button, it would be very easy, I let you do it!
With the same button, it's feasible, BUT : we start to multiply the conditions, as soon as other conditions will be necessary, it will be too complicated to use the same approach : we'll have to use the state machine ! on the other hand, you'll see that now, the debounce becomes necessary on the button1...
int button1 = 0; // pin Button1 (but pin 0 & 1 are for serial, prefer 2 or else
int rl1 = 5; // pin Relay
unsigned long previousMillis; // for count the millisecond
#define turnOnDelay 3000 // 3000 * 1 millisecond = 3 seconds
void setup() { // put your setup code here, to run once:
pinMode(button1, INPUT);
pinMode(button1, INPUT_PULLUP);
pinMode(rl1, OUTPUT);
digitalWrite(rl1, 1); // relay
digitalWrite(13, 0); // internal LED
}
void loop() { // put your main code here, to run repeatedly:
if (!digitalRead(button1)) { // in this case, no need for debounce
if (millis()-previousMillis <= turnOnDelay) // button1 was recently activated, it is a second hit
previousMillis = 0; // force previousMillis to activate "line 30"
else {
previousMillis = millis(); // delay will start at the release of button1
digitalWrite(rl1, 0); // turn xx the relay
digitalWrite(13, 1); // turn ON the internal LED
}
}
if (millis()-previousMillis > turnOnDelay) { // 3000 milliseconds after button1 is released,
digitalWrite(rl1, 1); // turn xx the relay
digitalWrite(13, 0); // turn OFF the internal LED
}
}
You might find these tutorials useful Debouncing Switches in Arduino handles button inputs and lets you check for change of state How to write Timers and Delays in Arduino covers timers and as noted above don't combine timer tests with other logical tests. Multi-tasking in Arduino covers structuring your code as a series of tasks like {check button, start time} {check timer finished do something}