From 09d416774a898ed53e93c8c494b295d14a35f409 Mon Sep 17 00:00:00 2001 From: Denis Denisov Date: Tue, 6 Sep 2022 23:25:44 +0300 Subject: [PATCH] Added heating. Added "dry work" prevention. More fixes --- well_control.ino | 180 +++++++++++++++++++++++++++++++++++--------- well_control.items | 12 ++- well_control.things | 10 ++- 3 files changed, 160 insertions(+), 42 deletions(-) diff --git a/well_control.ino b/well_control.ino index b0f3bed..32caa6e 100644 --- a/well_control.ino +++ b/well_control.ino @@ -9,7 +9,14 @@ #define SENSOR_UPDATE_INTERVAL 500 #define SCREEN_UPDATE_INTERVAL 200 // Interval between allowed switch-states of the pump -#define PUMP_SWITCH_INTERVAL 1000 +#define PUMP_SWITCH_INTERVAL 5000 +// Interval considering "rather long" to work for pump without pressure increase +#define PUMP_UNPRODUCTIVE_TIMEOUT 60000 +// amount of pressure what we consider "productive increase" (in 0.01 of bar) +#define PRESSURE_PRODUCTIVE_INCREASE 50 +// In fact, pump needs to be able to increase pressure by PRESSURE_PRODUCTIVE_INCREASE +// in PUMP_UNPRODUCTIVE_TIMEOUT time of working + #define MODE_AUTO 0 #define MODE_MANUAL 1 @@ -17,14 +24,22 @@ #define REGISTER_CURRENT_TEMP 0 #define REGISTER_CURRENT_HUM 1 #define REGISTER_CURRENT_PRESS 2 -#define REGISTER_CUR_STATE 3 -#define REGISTER_MODE 4 +#define REGISTER_PUMP_STATE 3 +#define REGISTER_PUMP_MODE 4 #define REGISTER_P_ON 5 #define REGISTER_P_OFF 6 +#define REGISTER_T_ON 7 +#define REGISTER_T_OFF 8 +#define REGISTER_HEAT_MODE 9 +#define REGISTER_HEAT_STATE 10 +#define REGISTER_PUMP_ERROR 11 #define DHTPIN D3 #define DHTTYPE AM2301 +#define PUMP_PIN D4 +#define HEATER_PIN D0 + ModbusIP mb; DHT dht(DHTPIN, DHTTYPE); rgb_lcd lcd; @@ -35,15 +50,23 @@ unsigned long last_update; int p_on = 150; int p_off = 250; -int cur_mode = MODE_AUTO; -int cur_state = 0; +int cur_pump_mode = MODE_AUTO; +int cur_pump_state = 0; int cur_p = 0; int cur_t = 0; int cur_hum = 0; +int t_on = 200; // 2 degrees +int t_off = 1500; // 15 degrees +int cur_heat_mode = MODE_AUTO; +int cur_heat_state = 0; + +bool error_pump = false; +bool error_heat = false; void setup() { - pinMode(D4, OUTPUT); + pinMode(PUMP_PIN, OUTPUT); + pinMode(HEATER_PIN, OUTPUT); pinMode(DHTPIN, INPUT); pinMode(A0, INPUT); @@ -75,10 +98,20 @@ void setup() mb.addHreg(REGISTER_CURRENT_TEMP, cur_t); mb.addHreg(REGISTER_CURRENT_HUM, cur_hum); mb.addHreg(REGISTER_CURRENT_PRESS, cur_p); - mb.addHreg(REGISTER_CUR_STATE, cur_state); - mb.addHreg(REGISTER_MODE, cur_mode); + mb.addHreg(REGISTER_PUMP_STATE, cur_pump_state); + mb.addHreg(REGISTER_PUMP_MODE, cur_pump_mode); mb.addHreg(REGISTER_P_ON, p_on); mb.addHreg(REGISTER_P_OFF, p_off); + mb.addHreg(REGISTER_T_ON, t_on); + mb.addHreg(REGISTER_T_OFF, t_off); + mb.addHreg(REGISTER_HEAT_STATE, cur_heat_state); + mb.addHreg(REGISTER_HEAT_MODE, cur_heat_mode); + mb.addHreg(REGISTER_PUMP_ERROR, error_pump); + // + Serial.print("Heater pin "); + Serial.println(HEATER_PIN); + Serial.print("Pump pin "); + Serial.println(PUMP_PIN); } @@ -94,9 +127,11 @@ void UpdateDHTData() // Workings with pressure sensor /////////////////////////////////////////////////////////////////////////////////////////////////// -const int MEASURES_AMOUNT = 100; +const int MEASURES_AMOUNT = 1000; int measures[MEASURES_AMOUNT]; int measure_pos = 0; +// добавка к измеренному значению (поправка на особенности датчика) +float PRESSURE_CALIBRATION = -2; void UpdatePressure() { @@ -106,8 +141,9 @@ void UpdatePressure() float p_volt = (p_int / 1024.0f) * 3.3f; // divide by maximal input voltage from sensor (it is 2.5) // and then multiply by sensor max value (10 bar) - we will get pressure in bar + // also add one atmosphere (1.01325 bar), because sensor reads excess pressure (not absolute) // finally multiply by 100 as we have int registers - measures[measure_pos] = (int)(((p_volt / 2.5f) * 10) * 100); + measures[measure_pos] = (int)(((p_volt / 2.5f) * 10 + 1.01325) * 100); measure_pos++; // We will use average of MEASURES_AMOUNT last sensor readings // excluding minimal and maximal value (to get rid of peaks) @@ -125,7 +161,7 @@ void UpdatePressure() if (i == min_pos || i == max_pos) continue; sum += measures[i]; } - cur_p = sum / (MEASURES_AMOUNT - 2); + cur_p = sum / (MEASURES_AMOUNT - 2) + PRESSURE_CALIBRATION * 100; } /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -145,51 +181,114 @@ void UpdateDisplay() lcd.setCursor(0, 1); lcd.print("H: "); lcd.print(cur_hum / 100); - lcd.print(" WiFi: "); - lcd.print(WiFi.status()); - // print current error - // - if (cur_state) + if (error_pump) { - lcd.setRGB(0, 0, 255); + lcd.print(" PUMP ERR"); } else { - lcd.setRGB(0, 255, 0); + lcd.print(" WiFi: "); + lcd.print(WiFi.status()); + } + // + if (error_pump) + { + lcd.setRGB(255, 0, 0); + } + else + { + if (cur_pump_state) + { + lcd.setRGB(0, 0, 255); + } + else + { + lcd.setRGB(0, 255, 0); + } } last_screen_update = current; } } unsigned long last_pump_switch = 0; +unsigned long last_pump_on = 0; +int last_pump_p = 0; void UpdatePump() { unsigned long current = millis(); - int new_state = cur_state; - if (cur_mode == MODE_AUTO) + int new_state = cur_pump_state; + if (cur_pump_mode == MODE_AUTO) { if (cur_p < p_on) new_state = 1; else if (cur_p > p_off) new_state = 0; if ((current < last_pump_switch || current - last_pump_switch > PUMP_SWITCH_INTERVAL) - && new_state != cur_state) + && new_state != cur_pump_state + && cur_t > t_on) // turning on pump only if temperature is high enough { - Serial.print("CHANGE STATE "); - Serial.print(cur_p); - Serial.print(" "); - Serial.print(p_on); - Serial.print(" "); - Serial.print(p_off); - cur_state = new_state; - mb.Hreg(REGISTER_CUR_STATE, cur_state); + Serial.print("CHANGE STATE "); + Serial.print(cur_p); + Serial.print(" "); + Serial.print(p_on); + Serial.print(" "); + Serial.print(p_off); + cur_pump_state = new_state; + mb.Hreg(REGISTER_PUMP_STATE, cur_pump_state); last_pump_switch = current; + if (new_state == 1) + { + last_pump_on = current; + last_pump_p = cur_p; + } } } else { - cur_state = mb.Hreg(REGISTER_CUR_STATE); + cur_pump_state = mb.Hreg(REGISTER_PUMP_STATE); } - digitalWrite(D4, cur_state); + if (error_pump) + { + cur_pump_state = 0; + } + digitalWrite(PUMP_PIN, cur_pump_state); + // check for unproductive + if (cur_pump_state == 1) + { + if (current < last_pump_on || current - last_pump_on >= PUMP_UNPRODUCTIVE_TIMEOUT) + { + if (cur_p - last_pump_p < PRESSURE_PRODUCTIVE_INCREASE) + { + error_pump = true; + cur_pump_state = 0; + } + else + { + // the pump is working, will perform new check in PUMP_UNPRODUCTIVE_TIMEOUT + last_pump_p = cur_p; + last_pump_on = current; + } + } + } +} + +void UpdateHeater() +{ + int new_state = cur_heat_state; + if (cur_heat_mode == MODE_AUTO) + { + if (cur_t < t_on) new_state = 1; + else if (cur_t > t_off) new_state = 0; + if (new_state != cur_heat_state) + { + cur_heat_state = new_state; + mb.Hreg(REGISTER_HEAT_STATE, cur_heat_state); + } + } + else + { + cur_heat_state = mb.Hreg(REGISTER_HEAT_STATE); + } + digitalWrite(HEATER_PIN, cur_heat_state); } void loop() @@ -206,8 +305,13 @@ void loop() mb.task(); p_on = mb.Hreg(REGISTER_P_ON); p_off = mb.Hreg(REGISTER_P_OFF); - cur_mode = mb.Hreg(REGISTER_MODE); + cur_pump_mode = mb.Hreg(REGISTER_PUMP_MODE); + t_on = mb.Hreg(REGISTER_T_ON); + t_off = mb.Hreg(REGISTER_T_OFF); + cur_heat_mode = mb.Hreg(REGISTER_HEAT_MODE); + error_pump= mb.Hreg(REGISTER_PUMP_ERROR); UpdatePump(); + UpdateHeater(); if (u) { Serial.print("Current pressure: "); @@ -216,15 +320,21 @@ void loop() Serial.print(cur_t); Serial.print(" h "); Serial.print(cur_hum); - Serial.print(" state "); - Serial.println(cur_state); + Serial.print(" pump "); + Serial.print(cur_pump_state); + Serial.print(" heat "); + Serial.println(cur_heat_state); } mb.Hreg(REGISTER_P_ON, p_on); mb.Hreg(REGISTER_P_OFF, p_off); - mb.Hreg(REGISTER_MODE, cur_mode); + mb.Hreg(REGISTER_PUMP_MODE, cur_pump_mode); + mb.Hreg(REGISTER_T_ON, t_on); + mb.Hreg(REGISTER_T_OFF, t_off); + mb.Hreg(REGISTER_HEAT_MODE, cur_heat_mode); mb.Hreg(REGISTER_CURRENT_TEMP, cur_t); mb.Hreg(REGISTER_CURRENT_HUM, cur_hum); mb.Hreg(REGISTER_CURRENT_PRESS, cur_p); + mb.Hreg(REGISTER_PUMP_ERROR, error_pump); UpdateDisplay(); if (WiFi.status() != WL_CONNECTED) { diff --git a/well_control.items b/well_control.items index af0588d..0a051e1 100644 --- a/well_control.items +++ b/well_control.items @@ -1,7 +1,11 @@ -Number Well_P_on "Well turn on pressure [%.2f]" {channel="modbus:data:Well:W:Well_P_on:number"} -Number Well_P_off "Well turn off temperature [%.2f]" {channel="modbus:data:Well:W:Well_P_off:number"} +Number Well_P_on "Well pump turn on pressure [%.2f]" {channel="modbus:data:Well:W:Well_P_on:number"} +Number Well_P_off "Well pump turn off pressure [%.2f]" {channel="modbus:data:Well:W:Well_P_off:number"} Number Well_P "Well current pressure [%.2f]" {channel="modbus:data:Well:W:Well_P:number"} Number Well_Temp "Well temperature [%.1f °C]" {channel="modbus:data:Well:W:Well_Temp:number"} Number Well_Hum "Well humidity [%.1f%%]" {channel="modbus:data:Well:W:Well_Hum:number"} -Number Well_Mode "Well mode" {channel="modbus:data:Well:W:Well_Mode:number"} -Switch Well_State "Well state" {channel="modbus:data:Well:W:Well_State:switch"} +Number Well_Pump_Mode "Well pump mode" {channel="modbus:data:Well:W:Well_Pump_Mode:number"} +Switch Well_Pump_State "Well pump state" {channel="modbus:data:Well:W:Well_Pump_State:switch"} +Number Well_T_on "Well turn on heater [%.2f]" {channel="modbus:data:Well:W:Well_T_on:number"} +Number Well_T_off "Well turn off temperature [%.2f]" {channel="modbus:data:Well:W:Well_T_off:number"} +Number Well_Heat_Mode "Well heater mode" {channel="modbus:data:Well:W:Well_Heat_Mode:number"} +Switch Well_Heat_State "Well heater state" {channel="modbus:data:Well:W:Well_Heat_State:switch"} \ No newline at end of file diff --git a/well_control.things b/well_control.things index 318040c..0ac7792 100644 --- a/well_control.things +++ b/well_control.things @@ -1,11 +1,15 @@ Bridge modbus:tcp:Well [ host="192.168.0.24", port=15000, id=1 ] { - Bridge poller W[start = 0, length = 7, type = "holding", refresh = 500] { + Bridge poller W[start = 0, length = 11, type = "holding", refresh = 500] { Thing data Well_Temp[readStart = "0", readValueType = "int16", readTransform="JS(divide100.js)"] Thing data Well_Hum[readStart = "1", readValueType = "int16", readTransform="JS(divide100.js)"] Thing data Well_P[readStart = "2", readValueType = "int16", readTransform="JS(divide100.js)"] - Thing data Well_State[readStart = "3", readValueType = "int16", writeStart="3", writeValueType="int16", writeType="holding"] - Thing data Well_Mode[readStart = "4", readValueType = "int16", writeStart="4", writeValueType="int16", writeType="holding"] + Thing data Well_Pump_State[readStart = "3", readValueType = "int16", writeStart="3", writeValueType="int16", writeType="holding"] + Thing data Well_Pump_Mode[readStart = "4", readValueType = "int16", writeStart="4", writeValueType="int16", writeType="holding"] Thing data Well_P_on[readStart = "5", readValueType = "int16", readTransform="JS(divide100.js)", writeStart="5", writeValueType="int16", writeTransform="JS(multiply100.js)", writeType="holding"] Thing data Well_P_off[readStart = "6", readValueType = "int16", readTransform="JS(divide100.js)", writeStart="6", writeValueType="int16", writeTransform="JS(multiply100.js)", writeType="holding"] + Thing data Well_T_on[readStart = "7", readValueType = "int16", readTransform="JS(divide100.js)", writeStart="7", writeValueType="int16", writeTransform="JS(multiply100.js)", writeType="holding"] + Thing data Well_T_off[readStart = "8", readValueType = "int16", readTransform="JS(divide100.js)", writeStart="8", writeValueType="int16", writeTransform="JS(multiply100.js)", writeType="holding"] + Thing data Well_Heat_Mode[readStart = "9", readValueType = "int16", writeStart="9", writeValueType="int16", writeType="holding"] + Thing data Well_Heat_State[readStart = "10", readValueType = "int16", writeStart="10", writeValueType="int16", writeType="holding"] } }