I'm trying to program an EPS32 board to open and close a linear actuator depending of the temperature a BME 280 sensor gets. It is for an automated gardening project :)
My code is functional but I would like to perfect it.
The actuator is currently connected with two GPIO pin, one to open and he other to close.
GOALS:
-
- Switch off relays when not used.
-
- Replace the use of delay() with millis()
Currently, the actuator is opening when temperature is above 27c°. Relay is on for 7 seconds which let the time to the actuator to go full course. Then, the relay is switch off. But if the temperature stay above 27, the "if" part of the loop is going on an on, meaning it turn on for 7 seconds, switch off for 7 seconds and so on... I would like to switch all relays off when not needed to save energy and extend components life. I suppose there might be something to do with && or even the analogRead() function to get the state of the actuator and apply actions from that but it is too complicated for me.
To open the actuator, I decided to time the course of the actuator and let the relay on for that timing with a delay() function. There is probably a different approach to this ( with analogRead() I suppose) but I find it simple and working. I would like to replace delay() with millis() function in order not to block the rest of the script (I plan to add fans, water valves, a float switch sensor...).
May you show me the way ?
#include <Adafruit_BME280.h>
#include <WiFi.h>
const char* ssid = "#####"; // ESP32 and ESP8266 uses 2.4GHZ wifi only
const char* password = "#####";
//MQTT Setup Start
#include <PubSubClient.h>
#define mqtt_server "####.###.##.##"
WiFiClient espClient;
PubSubClient client(espClient);
#define mqttActuator "growShed/Acuator"
#define mqttTemp1 "growShed/temp1"
int actuatorUp = 15; //GPIO de l'actuator
int actuatorDown = 2; //GPIO de l'actuator
int actuatorUpread = (!digitalRead(actuatorUp)); //read state of gpio : on or off
int actuatorDownread = (!digitalRead(actuatorDown)); //read state of gpio : on or off
//MQTT Setup End
Adafruit_BME280 bme1; // I2C
//utiliser les virgules sur les capteurs suivants
float temp1, hum1, pres1;
//gestion des délais entre chaque captations de data
unsigned long millisNow1 = 0; //for delay purposes (laisser 0)
unsigned int sendDelay1 = 2000; //delay before sending sensor info via MQTT
//gestion des délais entre chaque captations de data
unsigned long millisNow3 = 0; //for delay purposes (laisser 0)
unsigned int sendDelay3 = 7000; //delay before sending sensor info via MQTT
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
Serial.println();
// begin Wifi connect
Serial.println("Connecting to ");
Serial.println(ssid);
WiFi.mode(WIFI_STA);
WiFi.disconnect();
delay(2000);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.println(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address (wifi RaspPi) : ");
Serial.println(WiFi.localIP());
//end Wifi connect
client.setServer(mqtt_server, 1883);
//BME
delay(5000);
unsigned status;
status = bme1.begin(0x76);
if (!status) {
Serial.println("Could not find a valid BME280 sensor, check wiring, address, sensor ID!");
Serial.print("SensorID was: 0x"); Serial.println(bme1.sensorID(),16);
Serial.print(" ID of 0xFF probably means a bad address, a BMP 180 or BMP 085\n");
Serial.print(" ID of 0x56-0x58 represents a BMP 280,\n");
Serial.print(" ID of 0x60 represents a BME 280.\n");
Serial.print(" ID of 0x61 represents a BME 680.\n");
while (1);
}
//Acuator
pinMode(actuatorUp, OUTPUT);
digitalWrite(actuatorDown, HIGH); //Begin with actuator switched off
pinMode(actuatorDown, OUTPUT);
digitalWrite(actuatorUp, HIGH); //Begin with actuator switched off
//End Actuator
}
bool getValues() {
temp1 = round(bme1.readTemperature()); //rounded values
actuatorUpread = (digitalRead(actuatorUp)); //inverted value as the relay is inverted
Serial.print("BME 1 Temperature = ");
Serial.print(temp1);
Serial.println(" °C");
Serial.print("État de l'actuator haut = ");
Serial.println(actuatorUpread);
Serial.print("État de l'actuator bas = ");
Serial.print(actuatorDownread);
Serial.println();
}
void reconnect() {
// Loop until we're reconnected
int counter = 0;
while (!client.connected()) {
if (counter==5){
ESP.restart();
}
counter+=1;
Serial.println("Attempting MQTT connection...");
// Attempt to connect
if (client.connect("growTentController")) {
Serial.println("connected");
} else {
Serial.println("failed, rc=");
Serial.println(client.state());
Serial.println(" try again in 5 seconds");
// Wait 10 seconds before retrying
delay(5000);
}
}
}
void loop() {
// put your main code here, to run repeatedly:
if (!client.connected()){
reconnect();
}
if (millis() > millisNow1 + sendDelay1){
if (getValues()) {
client.publish(mqttTemp1, String(temp1).c_str(),true);
client.publish(mqttActuator, String(actuatorUpread).c_str(),true);
millisNow1 = millis();
}
}
//Acuator moving according to BME280 temperature sensor
temp1 = bme1.readTemperature();
if (millis() > millisNow3 + sendDelay3){
if ((temp1 > 27)){
digitalWrite(actuatorUp, LOW);
delay(7000); // approx the time it take to execute the full course of the acuator.
digitalWrite(actuatorUp, HIGH);
}
else {
digitalWrite(actuatorDown, LOW);
delay(7000); // approx the time it take to execute the full course of the acuator
digitalWrite(actuatorDown, HIGH);
}
millisNow3 = millis();
}
}