Hello everyone, I have been stuck on this problem for months, went completely out of my way and learned some Circuitpython and kind of got it right but not all the way, so I am back at it with Arduino. I can accomplish my goal using delay() but not using millis().
Ultimate goal is to keep pump running for some time after boiler shuts off
I have two relays and two buttons, pressing the start button turns on both relays, boiler and pump, pressing the stop button will shut off one relay ( boiler) but keep the pump relay on for some time, using delay() prevents me from starting the boiler while the delay is executing.
I would appreciate any kind of help.
const int start = 6, boiler = 4, pump = 3, stop = 8;
const long time= 300;
void setup(void) {
pinMode(start, INPUT_PULLUP);
pinMode(stop, INPUT_PULLUP);
pinMode(boiler, OUTPUT);
pinMode(pump, OUTPUT);
delay(500);
Serial.begin(9600);
delay(200);
digitalWrite(pump, LOW);
digitalWrite(boiler, LOW);
}
void heating() {
digitalWrite(pump, HIGH);
digitalWrite(boiler, HIGH);
}
void loop() {
if (digitalRead(start) == LOW && (digitalRead(boiler) == LOW)) {
heating();
}
else if (digitalRead(stop) == LOW && digitalRead(boiler) == HIGH) {
digitalWrite(boiler, LOW);
delay(time);
digitalWrite(pump, LOW);
}
}
Please post the millis using code.
J-M-L
November 8, 2023, 2:57pm
3
drjafet:
I have two relays and two buttons, pressing the start button turns on both relays, boiler and pump, pressing the stop button will shut off one relay ( boiler) but keep the pump relay on for some time, using delay() prevents me from starting the boiler while the delay is executing.
seems a perfect use case for a state machine (and use a button library to make your life easy)
(the top transition is for an emergency stop if needed)
details
here is what it looks like (now that you are searching for yourself I can post that )
Boiler+Pump - Wokwi ESP32, STM32, Arduino Simulator
#include <Toggle.h>
const int RELAY_OFF = LOW;
const int RELAY_ON = HIGH;
const byte pumpRelayPin = 9;
const byte boilerRelayPin = 8;
const byte startButtonPin = 3;
const byte stopButtonPin = 2;
const unsigned long waitTime = 5000ul; // 5s in ms
unsigned long startTime;
Toggle startButton, stopButton;
enum {OFF, BOTH, WAIT_A_BIT} state = OFF;
void setup() {
pinMode(pumpRelayPin, OUTPUT); digitalWrite(pumpRelayPin, RELAY_OFF); // pump off
pinMode(boilerRelayPin, OUTPUT); digitalWrite(boilerRelayPin, RELAY_OFF); // boiler off
startButton.begin(startButtonPin);
stopButton.begin(stopButtonPin);
Serial.begin(115200);
}
void loop() {
switch (state) {
case OFF:
startButton.poll();
if (startButton.onPress()) {
digitalWrite(pumpRelayPin, RELAY_ON); // pump ON
digitalWrite(boilerRelayPin, RELAY_ON); // boiler ON
state = BOTH;
}
break;
case BOTH:
stopButton.poll();
if (stopButton.onPress()) {
digitalWrite(boilerRelayPin, RELAY_OFF); // boiler OFF
startTime = millis();
state = WAIT_A_BIT;
}
break;
case WAIT_A_BIT:
stopButton.poll();
if (stopButton.onPress() || (millis() - startTime >= waitTime)) {
digitalWrite(pumpRelayPin, RELAY_OFF); // pump OFF
state = OFF;
}
break;
}
}
if you want to start the boiler again while the pump is still active, you need to also add a transition from the WAIT_A_BIT state by testing if the startButton is pressed
1 Like
I am looking into it right now, thanks for pointing me to it
J-M-L
November 8, 2023, 4:49pm
5
if you want to be able to start the boiler again while the pump is still active, you need to also add a transition from the WAIT_A_BIT state by testing if the startButton is pressed going to the BOTH state
This state machine stuff is what I have been looking for, I have a somewhat functional sketch, I just cant make the timer work.
const uint16_t timeInterval = 5000;
const uint8_t pilotLight = 13;
const uint8_t boiler = 4;
const uint8_t pump = 3;
const uint8_t start = 6;
const uint8_t stop = 8;
unsigned long previousMillis = 0;
unsigned long currentMillis;
enum states {
HEATING,
COOLDOWN,
STAND_BY
};
states state;
void setup() {
pinMode(pilotLight, OUTPUT);
pinMode(boiler, OUTPUT);
pinMode(pump, OUTPUT);
pinMode(start, INPUT);
pinMode(stop, INPUT);
digitalWrite(pilotLight, LOW);
digitalWrite(boiler, LOW);
digitalWrite(pump, LOW);
state = STAND_BY;
}
void loop() {
switch (state) {
case HEATING:
digitalWrite(pilotLight, LOW);
digitalWrite(boiler, HIGH);
digitalWrite(pump, HIGH);
if (digitalRead(stop) == HIGH) { // If stop is pressed,
state = COOLDOWN;
currentMillis = millis();
// turn on pump
}
break;
case COOL_DOWN:
digitalWrite(pilotLight, HIGH); // turn off pilotLight,
digitalWrite(boiler, HIGH);
digitalWrite(pump, LOW);
if (currentMillis - previousMillis > timeInterval) {
state = STAND_BY;
previousMillis = currentMillis;
}
break;
case STAND_BY:
digitalWrite(pilotLight, HIGH); // Set pilotLight high initially
digitalWrite(boiler, LOW); // Set boiler low initially
digitalWrite(pump, LOW);
if (digitalRead(start) == HIGH) {
state = HEATING;
}
break;
}
Serial.println(currentMillis);
}
J-M-L
November 8, 2023, 5:54pm
7
good progress
I added to post#3 (while you were working...) a solution using the Toggle library to handle the buttons. This code implements the state machine as it looks in the drawing. (click on the details triangle to see that)
that will give you some food for thoughts and you can add the missing transition to go back to the BOTH state if you press the start button whilst being in the WAIT_A_BIT state
I've seen that, that is awesome, I have other projects that I will approach this way, thank you!
J-M-L
November 8, 2023, 6:21pm
9
it's a good way to think about the code in an asynchronous way and the code is easy to read too
have fun !
system
Closed
May 6, 2024, 6:21pm
10
This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.