From 2cd0a0f48b5b89bcf85cc17cd1f05eb0e46747c7 Mon Sep 17 00:00:00 2001 From: c3ma Date: Wed, 6 Oct 2021 21:24:34 +0200 Subject: [PATCH] initial flowmeter logic and calculation --- esp32/include/ControllerConfiguration.h | 6 +- esp32/include/LogDefines.h | 3 + esp32/src/PlantCtrl.cpp | 13 +++- esp32/src/main.cpp | 89 +++++++++++++++++-------- 4 files changed, 78 insertions(+), 33 deletions(-) diff --git a/esp32/include/ControllerConfiguration.h b/esp32/include/ControllerConfiguration.h index 2d71e1a..a486752 100644 --- a/esp32/include/ControllerConfiguration.h +++ b/esp32/include/ControllerConfiguration.h @@ -84,7 +84,11 @@ */ #define FIRMWARE_VERSION "sw 1.4 hw 0.10" -#define TIMED_LIGHT_PIN CUSTOM1_PIN5 +#define TIMED_LIGHT_PIN CUSTOM1_PIN5 +#define FLOWMETER_PIN CUSTOM1_PIN1 +#ifdef FLOWMETER_PIN + #define FLOWMETER_FLOWFACTOR 22 /** F = 22 * Q;Q = L/min */ +#endif #define MOIST_SENSOR_MAX_FRQ 60000 // 60kHz (500Hz margin) #define MOIST_SENSOR_MIN_FRQ 1000 // 1kHz (500Hz margin) diff --git a/esp32/include/LogDefines.h b/esp32/include/LogDefines.h index 923ba80..a85c6bc 100644 --- a/esp32/include/LogDefines.h +++ b/esp32/include/LogDefines.h @@ -17,6 +17,9 @@ #define LOG_PUMP_BUTNOTANK_MESSAGE "Want to pump but no water" #define LOG_PUMP_BUTNOTANK_CODE -3 +#define LOG_HARDWARECOUNTER_ERROR_MESSAGE "PCNR returned error" +#define LOG_HARDWARECOUNTER_ERROR_CODE -4 + #define LOG_PUMP_AND_DOWNLOADMODE "Download mode, ignoring pump request" #define LOG_PUMP_AND_DOWNLOADMODE_CODE 2 diff --git a/esp32/src/PlantCtrl.cpp b/esp32/src/PlantCtrl.cpp index a2bd4f3..ea45eb5 100644 --- a/esp32/src/PlantCtrl.cpp +++ b/esp32/src/PlantCtrl.cpp @@ -97,10 +97,17 @@ void Plant::stopMoistureMeasurement(void) { int16_t pulses; pcnt_unit_t unit = (pcnt_unit_t) (PCNT_UNIT_0 + this->mPlantId); pcnt_counter_pause(unit); - pcnt_get_counter_value(unit, &pulses); + esp_err_t result = pcnt_get_counter_value(unit, &pulses); pcnt_counter_clear(unit); - - this->mMoisture_freq = pulses * (1000 / MOISTURE_MEASUREMENT_DURATION); + + + if(result != ESP_OK){ + //FIXME log(LOG_LEVEL_ERROR, LOG_HARDWARECOUNTER_ERROR_MESSAGE, LOG_HARDWARECOUNTER_ERROR_CODE); + this -> mMoisture_freq = -1; + } else { + this->mMoisture_freq = pulses * (1000 / MOISTURE_MEASUREMENT_DURATION); + } + } void Plant::postMQTTconnection(void) diff --git a/esp32/src/main.cpp b/esp32/src/main.cpp index 39e041c..0bcb58f 100644 --- a/esp32/src/main.cpp +++ b/esp32/src/main.cpp @@ -33,6 +33,7 @@ #include "soc/rtc_cntl_reg.h" #include #include +#include "driver/pcnt.h" /****************************************************************************** * DEFINES @@ -92,7 +93,7 @@ unsigned long setupFinishedTimestamp; bool pumpStarted = false; long pumpTarget = -1; -#ifdef FLOWMETER +#ifdef FLOWMETER_PIN long pumpTargetMl = -1; #endif @@ -591,6 +592,38 @@ bool switch7(const HomieRange &range, const String &value) return mPlants[6].switchHandler(range, value); } +void initPumpLogic() +{ + //set targets + pumpTarget = millis() + (mPlants[pumpToRun].getPumpDuration() * 1000); +#ifdef FLOWMETER_PIN + pumpTargetMl = mPlants[pumpToRun].getPumpDuration(); + + //0-6 are used for moisture measurment + pcnt_unit_t unit = (pcnt_unit_t)(PCNT_UNIT_7); + pcnt_config_t pcnt_config = {}; // Instancia PCNT config + pcnt_config.pulse_gpio_num = FLOWMETER_PIN; // Configura GPIO para entrada dos pulsos + pcnt_config.ctrl_gpio_num = PCNT_PIN_NOT_USED; // Configura GPIO para controle da contagem + pcnt_config.unit = unit; // Unidade de contagem PCNT - 0 + pcnt_config.channel = PCNT_CHANNEL_0; // Canal de contagem PCNT - 0 + pcnt_config.counter_h_lim = INT16_MAX; // Limite maximo de contagem - 20000 + pcnt_config.pos_mode = PCNT_COUNT_DIS; // Incrementa contagem na subida do pulso + pcnt_config.neg_mode = PCNT_COUNT_INC; // Incrementa contagem na descida do pulso + pcnt_config.lctrl_mode = PCNT_MODE_KEEP; // PCNT - modo lctrl desabilitado + pcnt_config.hctrl_mode = PCNT_MODE_KEEP; // PCNT - modo hctrl - se HIGH conta incrementando + pcnt_unit_config(&pcnt_config); // Configura o contador PCNT + + pcnt_counter_clear(unit); // Zera o contador PCNT + pcnt_counter_resume(unit); +#endif + //enable power + WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); + digitalWrite(OUTPUT_ENABLE_PUMP, HIGH); + delay(100); + WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 1); + + mPlants[pumpToRun].activatePump(); +} void pumpActiveLoop() { @@ -598,28 +631,30 @@ void pumpActiveLoop() if (!pumpStarted) { - //enable power - WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); - digitalWrite(OUTPUT_ENABLE_PUMP, HIGH); - delay(100); - WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 1); - - mPlants[pumpToRun].activatePump(); - //set targets - pumpTarget = millis() + (mPlants[pumpToRun].getPumpDuration() * 1000); -#ifdef FLOWMETER - pumpTargetMl = mPlants[pumpToRun].getPumpDuration(); -#endif + initPumpLogic(); pumpStarted = true; } -#ifdef FLOWMETER - long pumped = //readFlowMeterCounter * ratio; - if(pumped >= pumpTargetMl)) - { +#ifdef FLOWMETER_PIN + int16_t pulses; + pcnt_unit_t unit = (pcnt_unit_t) (PCNT_UNIT_7); + esp_err_t result = pcnt_get_counter_value(unit, &pulses); + if(result != ESP_OK){ + log(LOG_LEVEL_ERROR, LOG_HARDWARECOUNTER_ERROR_MESSAGE, LOG_HARDWARECOUNTER_ERROR_CODE); targetReached = true; + } else { + /**FLOWMETER_FLOWFACTOR * (L/Min) = F; + given 1L/min -> FLOWMETER_FLOWFACTOR*60 pulses per liter + -> 1000/result -> ml pro pulse; + -> result * pulses ->*/ + long pumped = (FLOWMETER_FLOWFACTOR * 60) * pulses / 1000; + if(pumped >= pumpTargetMl) + { + targetReached = true; + pcnt_counter_pause(unit); + } + mPlants[pumpToRun].setProperty("waterusage").send(String(pumped)); } - mPlants[pumpToRun].setProperty("waterusage").send(String(pumped)); #else if (millis() > pumpTarget) { @@ -629,6 +664,7 @@ void pumpActiveLoop() if (targetReached) { + //disable all digitalWrite(OUTPUT_ENABLE_PUMP, LOW); for (int i = 0; i < MAX_PLANTS; i++) @@ -724,8 +760,7 @@ void setup() // Set default values //in seconds - deepSleepTime.setDefaultValue(600).setValidator([](long candidate) - { return (candidate > 0) && (candidate < (60 * 60 * 2) /** 2h max sleep */); }); + deepSleepTime.setDefaultValue(600).setValidator([](long candidate) { return (candidate > 0) && (candidate < (60 * 60 * 2) /** 2h max sleep */); }); deepSleepNightTime.setDefaultValue(600); ntpServer.setDefaultValue("pool.ntp.org"); @@ -735,17 +770,13 @@ void setup() waterLevelVol.setDefaultValue(5000); /* 5l in ml */ lipoSensorAddr.setDefaultValue(""); waterSensorAddr.setDefaultValue(""); - pumpIneffectiveWarning.setDefaultValue(5).setValidator([](long candidate) - { return (candidate > 0) && (candidate < (20)); }); + pumpIneffectiveWarning.setDefaultValue(5).setValidator([](long candidate) { return (candidate > 0) && (candidate < (20)); }); #if defined(TIMED_LIGHT_PIN) - timedLightStart.setDefaultValue(18).setValidator([](long candidate) - { return (candidate > 0) && (candidate < (25)); }); - timedLightEnd.setDefaultValue(23).setValidator([](long candidate) - { return (candidate > 0) && (candidate < (24)); }); + timedLightStart.setDefaultValue(18).setValidator([](long candidate) { return (candidate > 0) && (candidate < (25)); }); + timedLightEnd.setDefaultValue(23).setValidator([](long candidate) { return (candidate > 0) && (candidate < (24)); }); timedLightOnlyWhenDark.setDefaultValue(true); - timedLightVoltageCutoff.setDefaultValue(3.8).setValidator([](double candidate) - { return (candidate > 3.3) && (candidate < (4.2)); }); + timedLightVoltageCutoff.setDefaultValue(3.8).setValidator([](double candidate) { return (candidate > 3.3) && (candidate < (4.2)); }); #endif // TIMED_LIGHT_PIN Homie.setLoopFunction(homieLoop); @@ -922,7 +953,7 @@ void plantcontrol() readOneWireSensors(); Serial << "W : " << waterRawSensor.getAverage() << " cm (" << String(waterLevelMax.get() - waterRawSensor.getAverage()) << "%)" << endl; - + float batteryVoltage = battery.getVoltage(BATTSENSOR_INDEX_BATTERY); float chipTemp = battery.getTemperature(); Serial << "Chip Temperatur " << chipTemp << " °C " << endl;