From f0678485be7d27280f3f0661a06cd9256d87ec9e Mon Sep 17 00:00:00 2001 From: Fisch Date: Tue, 23 Apr 2024 23:39:18 +0200 Subject: [PATCH] ec probe calibration --- include/ec.h | 112 +++++++++-- include/ec_old_with_calibration.h | 312 ++++++++++++++++++++++++++++++ include/temperature.h | 2 + include/waterlevel_hcsr04.h | 99 ++++++++++ include/wifi_settings.h | 4 +- messung/approximate.py | 30 +-- messung/requirements.txt | 4 + src/main.cpp | 100 +++++++--- 8 files changed, 602 insertions(+), 61 deletions(-) create mode 100644 include/ec_old_with_calibration.h create mode 100644 include/waterlevel_hcsr04.h create mode 100644 messung/requirements.txt diff --git a/include/ec.h b/include/ec.h index 5f7bde8..c94e238 100644 --- a/include/ec.h +++ b/include/ec.h @@ -2,11 +2,13 @@ #define _EC_H_ #include +/* mqttValueTiming timing_ec_adc; mqttValueTiming timing_ec_calibadc; mqttValueTiming timing_ec_adcadjusted; mqttValueTiming timing_ec_ec; mqttValueTiming timing_ec_sc; +*/ @@ -17,6 +19,7 @@ bool ec_flag_measurement_available=false; #define EC_PIN_RELAY_PROBE 27 +#define EC_PIN_RELAY_PROBESELECT 26 //#define EC_PIN_ADC 4 @@ -26,7 +29,8 @@ bool ec_flag_measurement_available=false; #define EC_RESOLUTION 8 #define EC_FREQUENCY 5000 -#define EC_CALIB_ARRAY_SIZE 128 +//#define EC_CALIB_ARRAY_SIZE 128 +#define EC_CALIB_ARRAY_SIZE 32 //temporarily changed uint16_t ec_calib_array[EC_CALIB_ARRAY_SIZE]; uint16_t ec_calib_array_pos=0; #define EC_CALIB_READ_INTERVAL 250 //interval of reading adc value inside a measurement @@ -48,13 +52,22 @@ unsigned long ec_last_change_relay=0; //millis of last relay change enum ECState{IDLE,MEASURE}; +uint8_t probeselect=0; +const uint8_t num_probes=2; + ECState ecstate=IDLE; -float ec_adc; -float ec_adc_adjusted; //adjusted for reference resistor float ec_calib_adc; -float ec; //ec value after adjustment for reference (at current temperature) -float ec25; //ec value but temperature adjusted for 25 degC + +float ec_adc_A; +float ec_adc_adjusted_A; //adjusted for reference resistor +float ec_A; //ec value after adjustment for reference (at current temperature) +float ec25_A; //ec value but temperature adjusted for 25 degC + +float ec_adc_B; +float ec_adc_adjusted_B; //adjusted for reference resistor +float ec_B; //ec value after adjustment for reference (at current temperature) +float ec25_B; //ec value but temperature adjusted for 25 degC float ec_tempadjust_alpa=0.02; float ec_reference_adc=6016.88; //adc reference value for the calibration resistor measurement. @@ -66,21 +79,27 @@ float ec_reference_adc=6016.88; //adc reference value for the calibration resist //float ec_calibration_polynom[]={1033.928052655456,-3.8909104921922895,0.005627541436014758,-4.103988840997024e-06,1.7231981870816133e-09,-4.433707707721975e-13,7.203892111369395e-17,-7.406549810844244e-21,4.667420606439905e-25,-1.6439457516812463e-29,2.477292190335455e-34}; //20220505 //float ec_calibration_polynom[]={-323.68589929771457,0.5836096440900665,-0.000279737392438965,5.98673062873e-08,-5.4460235093798435e-12,1.8535134644431135e-16}; //20230509 //float ec_calibration_polynom[]={212.6826331524675,-0.6043878865263305,0.000571551634082491,-1.827897106718841e-07,2.682337041246909e-11,-1.8368511021965982e-15,4.8269168538877025e-20}; //20230509 manuell -float ec_calibration_polynom[]={-202.42892340068445,0.3775267988688599,-0.0001603031198536654,3.398964768344757e-08,-3.0277753798278316e-12,1.0137804308289433e-16}; //20230620, graphite electrodes -float ec_calibration_linearize_below_adc=4000; //use linear approximation below this adc value. 0=disable -float ec_calibration_linear_lowADC=746; //x0 -float ec_calibration_linear_lowEC=0; //y0 +float ec_calibration_polynom_A[]={18.953002079376887,-0.057529180570340156,7.44612274805891e-05,-8.847448650204697e-09,5.388914121653647e-13}; //20240423, graphite electrodes +float ec_calibration_linearize_below_adc_A=2000; //use linear approximation below this adc value. 0=disable +float ec_calibration_linear_lowADC_A=728; //x0 +float ec_calibration_linear_lowEC_A=0; //y0 + + +float ec_calibration_polynom_B[]={40.838922264426685,-0.08846039894456156,7.671298605466989e-05,-9.161423581523883e-09,5.529701600660142e-13}; //20240423, graphite electrodes +float ec_calibration_linearize_below_adc_B=2000; //use linear approximation below this adc value. 0=disable +float ec_calibration_linear_lowADC_B=728; //x0 +float ec_calibration_linear_lowEC_B=0; //y0 bool ec_measurementReady(); void ec_startMeasurement(); void ec_setRange(uint8_t range); -void ec_connectProbe(bool); +void ec_connectProbe(bool, uint8_t); void ec_releaseRelay(); -float ec_getECfromADC(float adc); +float ec_getECfromADC(float adc, float ec_calibration_polynom[], size_t len_ec_calibration_polynom, float ec_calibration_linearize_below_adc, float ec_calibration_linear_lowADC, float ec_calibration_linear_lowEC); float ec_calculateEC25(float pEC,float pTemp); void ec_setup() { - + /* timing_ec_adc.minchange=0.0; timing_ec_adc.maxchange=250; timing_ec_adc.mintime=10*000; @@ -105,13 +124,14 @@ void ec_setup() { timing_ec_sc.maxchange=50; timing_ec_sc.mintime=10*000; timing_ec_sc.maxtime=60*60*1000; - + */ ledcSetup(EC_PWM_CH, EC_FREQUENCY, EC_RESOLUTION); ledcAttachPin(EC_PIN_FREQ, EC_PWM_CH); ledcWrite(EC_PWM_CH, 127); //50% duty cycle pinMode(EC_PIN_RELAY_PROBE,OUTPUT); //LOW=Calibration/idle, HIGH=Probe connected + pinMode(EC_PIN_RELAY_PROBESELECT,OUTPUT); //LOW=Probe A, HIGH=Probe B ec_releaseRelay(); } @@ -125,10 +145,12 @@ void ec_loop(unsigned long loopmillis) { case IDLE: if (loopmillis>last_measurement_ec+EC_MEASUREMENT_INTERVAL || force_ec_measurement) { //start measurement if idle + //Serial.println("DEBUG: Start measurement"); last_measurement_ec=loopmillis; force_ec_measurement=false; ec_startMeasurement(); - ec_connectProbe(true); + ec_connectProbe(true,0); //Probe A + ecstate=MEASURE; } @@ -136,23 +158,58 @@ void ec_loop(unsigned long loopmillis) { case MEASURE: if (ec_measurementReady()) { + //Serial.println("DEBUG: Measurement Ready"); + float ec_adc; + float ec_adc_adjusted; + float ec; + float ec25; + ec_releaseRelay(); ec_adc=getMean(ec_array,EC_ARRAY_SIZE); if (isValueArrayOK(ec_calib_array,EC_CALIB_ARRAY_SIZE,EC_ADC_UNAVAILABLE)){ ec_calib_adc=getMean(ec_calib_array,EC_CALIB_ARRAY_SIZE); ec_adc_adjusted=mapf(ec_adc,0,ec_calib_adc,0,ec_reference_adc); - ec=ec_getECfromADC(ec_adc_adjusted); + if (probeselect==0) { + ec=ec_getECfromADC(ec_adc_adjusted, ec_calibration_polynom_A, sizeof(ec_calibration_polynom_A), ec_calibration_linearize_below_adc_A, ec_calibration_linear_lowADC_A, ec_calibration_linear_lowEC_A); + }else if (probeselect==1) { + ec=ec_getECfromADC(ec_adc_adjusted, ec_calibration_polynom_B, sizeof(ec_calibration_polynom_B), ec_calibration_linearize_below_adc_B, ec_calibration_linear_lowADC_B, ec_calibration_linear_lowEC_B); + } ec25=ec_calculateEC25(ec,tempC_reservoir); + //Serial.println("DEBUG: EC OK"); }else{ ec_calib_adc=EC_ADC_UNAVAILABLE; ec_adc_adjusted=EC_ADC_UNAVAILABLE; ec=EC_UNAVAILABLE; ec25=EC_UNAVAILABLE; + //Serial.println("DEBUG: EC unavailable"); } - ec_flag_measurement_available=true; + if (probeselect==0) { + //Serial.println("DEBUG: Assigning to A"); + ec_adc_A=ec_adc; + ec_adc_adjusted_A=ec_adc_adjusted; + ec_A=ec; + ec25_A=ec25; + + last_measurement_ec=loopmillis; + force_ec_measurement=false; + ec_startMeasurement(); + probeselect=1; //Select Probe B + ec_connectProbe(true,probeselect); //Probe B + ecstate=MEASURE; + + }else if(probeselect==1) { + //Serial.println("DEBUG: Assigning to B"); + ec_adc_B=ec_adc; + ec_adc_adjusted_B=ec_adc_adjusted; + ec_B=ec; + ec25_B=ec25; + + probeselect=0; //Reset to Probe A + ec_flag_measurement_available=true; + ecstate=IDLE; + } - ecstate=IDLE; } break; @@ -209,21 +266,36 @@ bool ec_measurementReady(){ } -void ec_connectProbe(bool relay) { +void ec_connectProbe(bool relay, uint8_t probeselect) { bool val=digitalRead(EC_PIN_RELAY_PROBE); + bool valsel=digitalRead(EC_PIN_RELAY_PROBESELECT); if (val!=relay) { //write only if different digitalWrite(EC_PIN_RELAY_PROBE,relay); + //Serial.print("DEBUG: Set Relay to "); Serial.println(relay); + ec_last_change_relay=millis(); + } + if (valsel!=probeselect) { //write only if different + if (probeselect==0) { + digitalWrite(EC_PIN_RELAY_PROBESELECT,false); + //Serial.println("DEBUG: Selected Probe A"); + }else if (probeselect==1) { + digitalWrite(EC_PIN_RELAY_PROBESELECT,true); + //Serial.println("DEBUG: Selected Probe B"); + } ec_last_change_relay=millis(); } } void ec_releaseRelay() { digitalWrite(EC_PIN_RELAY_PROBE,LOW); + digitalWrite(EC_PIN_RELAY_PROBESELECT,LOW); + //Serial.println("DEBUG: Released Relays"); ec_last_change_relay=millis(); } -float ec_getECfromADC(float adc) { - uint8_t polynom_order=sizeof(ec_calibration_polynom) / sizeof(ec_calibration_polynom[0]); +float ec_getECfromADC(float adc, float ec_calibration_polynom[], size_t len_ec_calibration_polynom, float ec_calibration_linearize_below_adc, float ec_calibration_linear_lowADC, float ec_calibration_linear_lowEC) { + //uint8_t polynom_order=sizeof(ec_calibration_polynom) / sizeof(ec_calibration_polynom[0]); + uint8_t polynom_order=len_ec_calibration_polynom / sizeof(ec_calibration_polynom[0]); double _ec=0; if (adc>=ec_calibration_linearize_below_adc) { //adc is in range where polynomial approximation fits well for (uint8_t i=0;i + +#define EC_PIN_RELAY_PROBE 27 +#define EC_PIN_RELAY_CALIBRATION 26 +#define EC_PIN_RELAY_RANGE 25 + + +#define EC_PIN_ADC 4 +#define EC_PIN_FREQ 5 +#define EC_PWM_CH 0 +#define EC_RESOLUTION 8 +#define EC_FREQUENCY 5000 + +#define EC_ARRAY_SIZE 128 +uint16_t ec_array_rangeLow[EC_ARRAY_SIZE]; +uint16_t ec_array_rangeHigh[EC_ARRAY_SIZE]; +uint16_t ec_array_pos=EC_ARRAY_SIZE*2; +#define EC_MEASUREMENT_INTERVAL 10000 //complete filtered measurement every x ms + //One filtered measurement takes EC_READ_INTERVAL*EC_ARRAY_SIZE*2 +#define EC_READ_INTERVAL 5 //interval of reading adc value inside a measurement + + + +float ec_calib_rangeLow_Rlow=0; //adc value for low value resistor on low resistor value range +float ec_calib_rangeLow_Rhigh=0; //adc value for high value resistor on low resistor value range +float ec_calib_rangeHigh_Rlow=0; //adc value for low value resistor on high resistor value range +float ec_calib_rangeHigh_Rhigh=0; //adc value for high value resistor on high resistor value range +const float ec_calibresistor_low=990; //value of low value calibration resistor. Low is Relay NO +const float ec_calibresistor_high=9943; //value of high value calibration resistor. HIGH is Relay NC + +unsigned long ec_last_calibration=0; //millis of last calibration +#define EC_CALIBRATION_VALID_TIME 120000 //time in ms a calibration is valid for +#define EC_RELAY_SWITCH_SETTLETIME 500 //time until voltage of ec circuit has settled + +unsigned long ec_last_change_relay=0; //millis of last relay change + +enum ECState{IDLE,CALIBRATELOW,CALIBRATEHIGH,MEASURE}; + +ECState ecstate=CALIBRATELOW; + + +bool ec_measurementReady(); +void ec_startMeasurement(); +void ec_setRange(bool); +void ec_connectProbe(bool); +void ec_setCalibration(bool calib); +void ec_releaseRelay(); +void ec_startCalibration(); +void ec_checkIfSettleTimeOK(); +float ec_getResistance(float adc,float caliblow,float resistorlow,float calibhigh,float resistorhigh); + +void ec_setup() { + pinMode(EC_PIN_ADC,INPUT); + + ledcSetup(EC_PWM_CH, EC_FREQUENCY, EC_RESOLUTION); + ledcAttachPin(EC_PIN_FREQ, EC_PWM_CH); + ledcWrite(EC_PWM_CH, 127); //50% duty cycle + + pinMode(EC_PIN_RELAY_PROBE,OUTPUT); //LOW=Calibration/idle, HIGH=Probe connected + pinMode(EC_PIN_RELAY_CALIBRATION,OUTPUT); //LOW=NC Calibration Resistor, HIGH=NO Calib. Res. + pinMode(EC_PIN_RELAY_RANGE,OUTPUT); //LOW=NC Range Resistor, HIGH=NO Range Resistor + ec_releaseRelay(); + + + ec_startCalibration(); +} + +void ec_loop(unsigned long loopmillis) { + static unsigned long last_measurement_ec=0; + static unsigned long last_read_ec=0; + + switch (ecstate) { + case IDLE: + + if (loopmillis>ec_last_calibration+EC_CALIBRATION_VALID_TIME) { //calibration needed + ec_last_calibration=loopmillis; + ecstate=CALIBRATELOW; + + ec_startCalibration(); + } + + + if (loopmillis>last_measurement_ec+EC_MEASUREMENT_INTERVAL && ecstate==IDLE) { //start measurement if idle + last_measurement_ec=loopmillis; + ec_startMeasurement(); + ec_connectProbe(true); + ecstate=MEASURE; + Serial.println("EC Take Measurement"); + } + break; + + + case CALIBRATELOW: + if (ec_measurementReady()) { + //Serial.println("EC CALIBRATELOW measurement ready"); + //save measurement + ec_calib_rangeLow_Rlow=getMean(ec_array_rangeLow,EC_ARRAY_SIZE); + ec_calib_rangeHigh_Rlow=getMean(ec_array_rangeHigh,EC_ARRAY_SIZE); + + //ec_checkIfSettleTimeOK(); + + //Switch to High calibration + ecstate=CALIBRATEHIGH; + + ec_setCalibration(HIGH); + ec_setRange(LOW); + ec_startMeasurement(); + //Serial.println("EC Start calibration high"); + } + break; + + case CALIBRATEHIGH: + if (ec_measurementReady()) { + //Serial.println("EC CALIBRATEHIGH measurement ready"); + //save measurement + ec_calib_rangeLow_Rhigh=getMean(ec_array_rangeLow,EC_ARRAY_SIZE); + ec_calib_rangeHigh_Rhigh=getMean(ec_array_rangeHigh,EC_ARRAY_SIZE); + + //ec_checkIfSettleTimeOK(); + + //Serial.println("EC Release Relay"); + ec_releaseRelay(); + + ecstate=IDLE; + + /* + Serial.println("EC Calibration done"); + Serial.print("ec_calib_rangeLow_Rlow="); Serial.println(ec_calib_rangeLow_Rlow); + Serial.print("ec_calib_rangeHigh_Rlow="); Serial.println(ec_calib_rangeHigh_Rlow); + Serial.print("ec_calib_rangeLow_Rhigh="); Serial.println(ec_calib_rangeLow_Rhigh); + Serial.print("ec_calib_rangeHigh_Rhigh="); Serial.println(ec_calib_rangeHigh_Rhigh); + */ + Serial.println("EC Calibration Result: "); + Serial.print(ec_calib_rangeLow_Rlow); + Serial.print(", "); Serial.print(ec_calib_rangeHigh_Rlow); + Serial.print(", "); Serial.print(ec_calib_rangeLow_Rhigh); + Serial.print(", "); Serial.println(ec_calib_rangeHigh_Rhigh); + + + } + break; + + case MEASURE: + if (ec_measurementReady()) { + ec_releaseRelay(); + float adc_rangelow=getMean(ec_array_rangeLow,EC_ARRAY_SIZE); + float adc_rangehigh=getMean(ec_array_rangeHigh,EC_ARRAY_SIZE); + + Serial.println(); + float resistance_rangelow=ec_getResistance(adc_rangelow,ec_calib_rangeLow_Rlow,ec_calibresistor_low,ec_calib_rangeLow_Rhigh,ec_calibresistor_high); + Serial.print("Range Low: ADC="); Serial.print(adc_rangelow); Serial.print(", resistance="); Serial.println(resistance_rangelow); + Serial.println(); + float resistance_rangehigh=ec_getResistance(adc_rangehigh,ec_calib_rangeHigh_Rlow,ec_calibresistor_low,ec_calib_rangeHigh_Rhigh,ec_calibresistor_high); + Serial.print("Range High: ADC="); Serial.print(adc_rangehigh); Serial.print(", resistance="); Serial.println(resistance_rangehigh); + ecstate=IDLE; + } + + break; + + } + + + + if (loopmillis>last_read_ec+EC_READ_INTERVAL && ec_array_pos/2ec_last_change_relay+EC_RELAY_SWITCH_SETTLETIME) { //values have settled + uint16_t value=analogRead(EC_PIN_ADC); + if (ec_array_pos=EC_ARRAY_SIZE*2) { //reached end of both arrays + return true; + }else{ + return false; + } +} + +void ec_setRange(bool range) { + //range low means low resistor value -> NO -> relay High + bool val=digitalRead(EC_PIN_RELAY_RANGE); + if (val!=!range) { //write only if different + digitalWrite(EC_PIN_RELAY_RANGE,!range); + ec_last_change_relay=millis(); + } +} + +void ec_connectProbe(bool relay) { + bool val=digitalRead(EC_PIN_RELAY_PROBE); + if (val!=relay) { //write only if different + digitalWrite(EC_PIN_RELAY_PROBE,relay); + ec_last_change_relay=millis(); + } +} + +void ec_setCalibration(bool calib) { + //calib low means low resistor value -> NO -> relay high + ec_connectProbe(false); + bool val=digitalRead(EC_PIN_RELAY_CALIBRATION); + if (val!=!calib) { //write only if different + digitalWrite(EC_PIN_RELAY_CALIBRATION,!calib); + ec_last_change_relay=millis(); + } +} + +void ec_releaseRelay() { + digitalWrite(EC_PIN_RELAY_PROBE,LOW); + digitalWrite(EC_PIN_RELAY_CALIBRATION,LOW); + digitalWrite(EC_PIN_RELAY_RANGE,LOW); + ec_last_change_relay=millis(); +} + +void ec_checkIfSettleTimeOK() { + /* + Serial.print("ec_array_rangeLow[0]="); Serial.println(ec_array_rangeLow[0]); + Serial.print("rangeLow min="); Serial.println(getMin(ec_array_rangeLow,EC_ARRAY_SIZE)); + Serial.print("rangeLow max="); Serial.println(getMax(ec_array_rangeLow,EC_ARRAY_SIZE)); + */ + if (ec_array_rangeLow[0]<=getMin(ec_array_rangeLow,EC_ARRAY_SIZE) || ec_array_rangeLow[0]>=getMax(ec_array_rangeLow,EC_ARRAY_SIZE)){ + //is first value the highest or lowest? + Serial.println("Warning: EC_RELAY_SWITCH_SETTLETIME might be too low! (ec_calib_rangeLow_Rlow)"); + } + + /* + Serial.print("ec_array_rangeHigh[0]="); Serial.println(ec_array_rangeHigh[0]); + Serial.print("rangeHigh min="); Serial.println(getMin(ec_array_rangeHigh,EC_ARRAY_SIZE)); + Serial.print("rangeHigh max="); Serial.println(getMax(ec_array_rangeHigh,EC_ARRAY_SIZE)); + */ + if (ec_array_rangeHigh[0]<=getMin(ec_array_rangeHigh,EC_ARRAY_SIZE) || ec_array_rangeHigh[0]>=getMax(ec_array_rangeHigh,EC_ARRAY_SIZE)){ + //is first value the highest or lowest? + Serial.println("Warning: EC_RELAY_SWITCH_SETTLETIME might be too low! (ec_array_rangeHigh)"); + } +} + + +float ec_getResistance(float adc,float caliblow,float resistorlow,float calibhigh,float resistorhigh) +{ + //adc = adc reading to calculate resistance for + //caliblow = adc value from calibration. Low resistance + //resistorlow = actual resistor value. Low resistance + //calibhjgh = adc value from calibration. High resistance + //resistorhigh = actual resistor value. High resistance + + //y=mx+a; + //resistorlow=m*caliblow+a; + //resistorhigh=m*calibhigh+a; + + //linear interpolation interpolate + double m=(resistorhigh-resistorlow)/(calibhigh-caliblow); + float a=resistorlow-m*caliblow; + + Serial.print("m="); Serial.println(m); + Serial.print("a="); Serial.println(a); + + return m*adc+a; +} + +#endif \ No newline at end of file diff --git a/include/temperature.h b/include/temperature.h index b063c10..d64eb6e 100644 --- a/include/temperature.h +++ b/include/temperature.h @@ -140,6 +140,7 @@ void temperature_loop(unsigned long loopmillis) { } } + /* temporarily disabled tempC_air = sensors.getTempC(thermometerAir); if (tempC_air == DEVICE_DISCONNECTED_C) { @@ -152,6 +153,7 @@ void temperature_loop(unsigned long loopmillis) { tempCmean_air=DEVICE_DISCONNECTED_C; } } + */ tempC_case = sensors.getTempC(thermometerCase); if (tempC_case == DEVICE_DISCONNECTED_C) diff --git a/include/waterlevel_hcsr04.h b/include/waterlevel_hcsr04.h new file mode 100644 index 0000000..84aaa35 --- /dev/null +++ b/include/waterlevel_hcsr04.h @@ -0,0 +1,99 @@ +#ifndef _WATERLEVEL_H_ +#define _WATERLEVEL_H_ + + +#include +#define HCSR04_PIN_ECHO 17 +#define HCSR04_PIN_TRIGGER 16 +#define HCSR04_TIMEOUT 5000 //default is 100000 (uS) +#define READINTERVAL_HCSR04 200 + +#define WATERLEVELMEAN_SIZE 32 +#define WATERLEVELMEAN_FILTER_CUTOFF 8 //max value is around WATERLEVELMEAN_SIZE/2 +float waterlevelMean_array[WATERLEVELMEAN_SIZE]; +uint16_t waterlevelMean_array_pos=0; +#define WATERLEVEL_UNAVAILABLE -1 +float waterlevel=WATERLEVEL_UNAVAILABLE; //distance from floor to water surface [mm] +float watervolume=WATERLEVEL_UNAVAILABLE; //calculated Volume in Reservoir + +uint16_t waterlevel_failcounter=0; +#define WATERLEVEL_MAXFAILS 15 //maximum counter value +#define WATERLEVEL_FAILTHRESHOLD 10 //if failcounter is greater or equal this value waterlevel will not be valid + +//Calibration +float waterlevel_calib_offset_measured=0; //Sollwert +float waterlevel_calib_offset_sensor=178.67; //Istwert + +float waterlevel_calib_reservoirArea=27*36.5; //area in cm^2 + + +float waterlevel_heightToVolume(float distance); + + +void waterlevel_setup() { + + //HCSR04.begin(HCSR04_PIN_TRIGGER, HCSR04_PIN_ECHO); + HCSR04.begin(HCSR04_PIN_TRIGGER, HCSR04_PIN_ECHO,HCSR04_TIMEOUT, HCSR04.eUltraSonicUnlock_t::unlockSkip); + for (uint16_t i=0;i=last_read_hcsr04+READINTERVAL_HCSR04) { + last_read_hcsr04=loopmillis; + float temperature=20.0; + if (tempCmean_air!=DEVICE_DISCONNECTED_C) { //sensor ok + temperature=tempCmean_air; + } + + double* distances = HCSR04.measureDistanceMm(temperature); + double distance=distances[0]; + //Serial.print("Distance reading:"); Serial.println(distance); + + if (distance!=WATERLEVEL_UNAVAILABLE) { //successful + waterlevelMean_array[waterlevelMean_array_pos]=distance; + waterlevelMean_array_pos++; + waterlevelMean_array_pos%=WATERLEVELMEAN_SIZE; + if (waterlevel_failcounter>0) { //reduce failcounter if sucessfull + waterlevel_failcounter--; + } + }else{ + if (waterlevel_failcounter=WATERLEVEL_FAILTHRESHOLD) { //too many failed readings + waterlevel=WATERLEVEL_UNAVAILABLE; + watervolume=WATERLEVEL_UNAVAILABLE; + /*if (debug) { + Serial.print("Waterlevel Failcounter="); Serial.println(waterlevel_failcounter); + }*/ + } + + } +} + +float waterlevel_heightToVolume(float distance){ + return waterlevel_calib_reservoirArea/100 * distance/100; //area[cm^2] in dm^2 * height in dm = dm^3= L +} + +#endif \ No newline at end of file diff --git a/include/wifi_settings.h b/include/wifi_settings.h index 45d18c8..e40520f 100644 --- a/include/wifi_settings.h +++ b/include/wifi_settings.h @@ -1,6 +1,6 @@ -const char ssid[] = ""; -const char pass[] = ""; +const char ssid[] = "fischnetziot"; +const char pass[] = "LiMkJ1sVcEAU68MPEgJ"; const char mqtt_host[] = "10.0.0.1"; const char client_id[] = "hydroponic"; \ No newline at end of file diff --git a/messung/approximate.py b/messung/approximate.py index cc4caf4..deb85ad 100644 --- a/messung/approximate.py +++ b/messung/approximate.py @@ -1,3 +1,5 @@ +#Use venv + import numpy as np from scipy.optimize import curve_fit @@ -8,32 +10,36 @@ import matplotlib.pyplot as plt from pandas import * # reading CSV file -data = read_csv("20230620_NaCl_raw.csv") +data = read_csv("20240423_EC_Calibration.csv") # converting column data to list -#solutionAdded = data['solutionAdded'].tolist() #in ml +solutionAdded = data['solutionAdded'].tolist() #in ml tempReservoir = data['tempReservoir'].tolist() #in C -adc = data['ECadcAdjusted'].tolist() #adc reading +adc = data['ECadcAdjusted_B'].tolist() #adc reading -solutionConcentration=5924.8 #mg/L NaCl -startWaterAmount=0.3 #L +#solutionConcentration=5924.8 #mg/L NaCl +solutionConcentration=5690 #mg/L NaCl +startWaterAmount=300 #mL (same unit as solutionAded) ppmToECfactor=1/0.46 -#concentration = [x*solutionConcentration/(startWaterAmount+x) for x in solutionAdded] -#ECcalculated = [x*ppmToECfactor for x in concentration] #uS/cm +concentration = [x*solutionConcentration/(startWaterAmount+x) for x in solutionAdded] +ECcalculated = [x*ppmToECfactor for x in concentration] #uS/cm -ECmeasured = data['ecMeasured'].tolist() #in C +#ECmeasured = data['ecMeasured'].tolist() #in C -#print(concentration) -#print(ECcalculated) +print("Concentration") +print(concentration) +print("") +print("ECcalculated") +print(ECcalculated) x = adc -#y = ECcalculated -y = ECmeasured +y = ECcalculated +#y = ECmeasured diff --git a/messung/requirements.txt b/messung/requirements.txt new file mode 100644 index 0000000..4c24399 --- /dev/null +++ b/messung/requirements.txt @@ -0,0 +1,4 @@ +numpy==1.22 +scipy +matplotlib +pandas diff --git a/src/main.cpp b/src/main.cpp index da71d13..9b85348 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,9 +4,13 @@ #include "wifi_functions.h" -bool debug=true; //print Serial information -bool mqtt=true; -bool eccalibrationoutput=false; //serial output for ec calibration +bool debug=false; //print Serial information +bool mqtt=false; +bool eccalibrationoutput=true; //serial output for ec calibration +/* Write to file with: +sudo stty -F /dev/ttyUSB0 115200 +cat /dev/ttyUSB0 | tee received.txt +*/ @@ -75,8 +79,8 @@ void setup() { Serial.println("Setup EC"); ec_setup(); - Serial.println("Setup Waterlevel"); - waterlevel_setup(); + //Serial.println("Setup Waterlevel"); + //waterlevel_setup(); //temporarily disabled Serial.println("Setup Temperature"); temperature_setup(); @@ -116,7 +120,7 @@ void loop() { temperature_loop(loopmillis); - waterlevel_loop(loopmillis); + //waterlevel_loop(loopmillis); flow_loop(loopmillis); @@ -132,11 +136,23 @@ void loop() { delay(100); } + + + if (eccalibrationoutput && !digitalRead(PIN_BUTTON) && !getReading) { - getReading=true; - force_ec_measurement=true; - ec_flag_measurement_available=false; - digitalWrite(PIN_LED,HIGH); + if (!isValueArrayOK(ec_calib_array,EC_CALIB_ARRAY_SIZE,EC_ADC_UNAVAILABLE)) { + for (uint8_t blink=0;blink<5;blink++) { + digitalWrite(PIN_LED,HIGH); + delay(100); + digitalWrite(PIN_LED,LOW); + delay(100); + } + }else{ + getReading=true; + force_ec_measurement=true; + ec_flag_measurement_available=false; + digitalWrite(PIN_LED,HIGH); + } } @@ -148,8 +164,10 @@ void loop() { Serial.print(loopmillis); Serial.print(","); Serial.print(tempCmean_reservoir); Serial.print(","); Serial.print(ec_calib_adc); Serial.print(","); - Serial.print(ec_adc); Serial.print(","); - Serial.print(ec_adc_adjusted); + Serial.print(ec_adc_A); Serial.print(","); + Serial.print(ec_adc_adjusted_A); Serial.print(","); + Serial.print(ec_adc_B); Serial.print(","); + Serial.print(ec_adc_adjusted_B); Serial.println(); } @@ -164,7 +182,7 @@ void loop() { if (sm_mean1==SM_DISCONNECTED || sm_mean2==SM_DISCONNECTED) { valueError=true; } - if (ec==EC_UNAVAILABLE){ + if (ec_A==EC_UNAVAILABLE || ec_B==EC_UNAVAILABLE){ valueError=true; } @@ -213,14 +231,25 @@ void loop() { Serial.print("Flow = "); Serial.print(flow); Serial.println(); - Serial.print("EC ec_calib_adc,ec_adc,ec_adc_adjusted = "); + Serial.print("EC ec_calib_adc,ec_adc_A,ec_adc_adjusted_A = "); Serial.print(ec_calib_adc); Serial.print(","); - Serial.print(ec_adc); Serial.print(","); - Serial.print(ec_adc_adjusted); + Serial.print(ec_adc_A); Serial.print(","); + Serial.print(ec_adc_adjusted_A); Serial.println(); - Serial.print("EC ec,ec25 = "); - Serial.print(ec); Serial.print(","); - Serial.print(ec25); + Serial.print("EC ec_A,ec25_A = "); + Serial.print(ec_A); Serial.print(","); + Serial.print(ec25_A); + Serial.println(); + + + Serial.print("EC ec_calib_adc,ec_adc_B,ec_adc_adjusted_B = "); + Serial.print(ec_calib_adc); Serial.print(","); + Serial.print(ec_adc_B); Serial.print(","); + Serial.print(ec_adc_adjusted_B); + Serial.println(); + Serial.print("EC ec_B,ec25_B = "); + Serial.print(ec_B); Serial.print(","); + Serial.print(ec25_B); Serial.println(); Serial.print("Waterlevel,Volume = "); @@ -273,18 +302,35 @@ void loop() { if (ec_flag_measurement_available){ ec_flag_measurement_available=false; - if (ec_adc!=0) { - publishValue("ec/adc",ec_adc,0); - } + if (ec_calib_adc!=0) { publishValue("ec/eccalibadc",ec_calib_adc,0); } - if (ec_adc_adjusted!=0) { - publishValue("ec/adcadjusted",ec_adc_adjusted,0); + + //Probe A + if (ec_adc_A!=0) { + publishValue("ecA/adc",ec_adc_A,0); } - if (ec!=EC_UNAVAILABLE){ - publishValue("ec/ec",ec,0); - publishValue("ec/sc",ec25,0); + + if (ec_adc_adjusted_A!=0) { + publishValue("ecA/adcadjusted",ec_adc_adjusted_A,0); + } + if (ec_A!=EC_UNAVAILABLE){ + publishValue("ecA/ec",ec_A,0); + publishValue("ecA/sc",ec25_A,0); + } + + //Probe B + if (ec_adc_B!=0) { + publishValue("ecB/adc",ec_adc_B,0); + } + + if (ec_adc_adjusted_B!=0) { + publishValue("ecB/adcadjusted",ec_adc_adjusted_B,0); + } + if (ec_B!=EC_UNAVAILABLE){ + publishValue("ecB/ec",ec_B,0); + publishValue("ecB/sc",ec25_B,0); } }