From 6e2b02e121c33ef2170af5db39911ee0dd667d15 Mon Sep 17 00:00:00 2001 From: Fisch Date: Sat, 11 May 2024 09:20:37 +0200 Subject: [PATCH] add seconds waterlevel sensor --- include/ec.h | 13 +- include/temperature.h | 7 + include/waterlevel.h | 338 +++++++++++++++++++++++++++++------ include/waterlevel_vl6180x.h | 95 ++++++++++ include/wifi_functions.h | 13 ++ platformio.ini | 3 +- src/main.cpp | 94 +++++++--- 7 files changed, 487 insertions(+), 76 deletions(-) create mode 100644 include/waterlevel_vl6180x.h diff --git a/include/ec.h b/include/ec.h index 073d7c0..6dbe7ba 100644 --- a/include/ec.h +++ b/include/ec.h @@ -96,6 +96,7 @@ void ec_connectProbe(bool, uint8_t); void ec_releaseRelay(); 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); +bool ec_measurementRunning(); void ec_setup() { /* @@ -218,12 +219,17 @@ void ec_loop(unsigned long loopmillis) { } - if (ec_array_poslast_read_ec+EC_READ_INTERVAL) { //take reading into array last_read_ec=loopmillis; - if (loopmillis>ec_last_change_relay+EC_RELAY_SWITCH_SETTLETIME) { //values have settled + if (loopmillis>ec_last_change_relay+EC_RELAY_SWITCH_SETTLETIME) { //values have settled + Serial.print("Get ADC Reading"); uint16_t value = ADS.readADC(EC_ADS_CHANNEL); + Serial.print(". Write to pos "); + Serial.println(ec_array_pos); + + ec_array[ec_array_pos]=value; @@ -326,5 +332,8 @@ float ec_calculateEC25(float pEC,float pTemp) return pEC/(1.0+ec_tempadjust_alpa*(pTemp-25.0)); } +bool ec_measurementRunning() { + return (ec_array_poslast_read_ds18b20+READINTERVAL_DS18B20) { if (loopmillis>last_read_ds18b20+READINTERVAL_DS18B20*10) { //timeout Serial.println("Warn: Request Temperatures Timeout!"); + publishInfo("error/temperature","Warn: Request Temperatures Timeout!"); flag_requestTemperatures=false; } if (!flag_requestTemperatures) { @@ -134,6 +138,7 @@ void temperature_loop(unsigned long loopmillis) { if (tempC_reservoir_a == DEVICE_DISCONNECTED_C) { Serial.print(" Error reading: "); printAddress(thermometerReservoirA); + publishInfo("error/temperature","Error reading thermometerReservoirA"); }else{ tempCmean_reservoir_a_array[tempCmean_pos]=tempC_reservoir_a; if (isValueArrayOKf(tempCmean_reservoir_a_array,TEMPMEAN_SIZE,DEVICE_DISCONNECTED_C)) { @@ -148,6 +153,7 @@ void temperature_loop(unsigned long loopmillis) { if (tempC_reservoir_b == DEVICE_DISCONNECTED_C) { Serial.print(" Error reading: "); printAddress(thermometerReservoirB); + publishInfo("error/temperature","Error reading thermometerReservoirB"); }else{ tempCmean_reservoir_b_array[tempCmean_pos]=tempC_reservoir_b; if (isValueArrayOKf(tempCmean_reservoir_b_array,TEMPMEAN_SIZE,DEVICE_DISCONNECTED_C)) { @@ -161,6 +167,7 @@ void temperature_loop(unsigned long loopmillis) { if (tempC_case == DEVICE_DISCONNECTED_C) { Serial.print(" Error reading: "); printAddress(thermometerCase); + publishInfo("error/temperature","Error reading thermometerCase"); }else{ tempCmean_case_array[tempCmean_pos]=tempC_case; if (isValueArrayOKf(tempCmean_case_array,TEMPMEAN_SIZE,DEVICE_DISCONNECTED_C)) { diff --git a/include/waterlevel.h b/include/waterlevel.h index 4072081..69cd0ab 100644 --- a/include/waterlevel.h +++ b/include/waterlevel.h @@ -2,94 +2,332 @@ #define _WATERLEVEL_H_ #include -#include +#include //pololu/VL53L0X@^1.3.1 -VL6180X sensor; + + + +// +++++++++++++++ Common Parameters ++++++++++ + +#define READINTERVAL_WATERLEVEL 500 +#define WATERLEVELMEAN_SIZE 16 +#define WATERLEVELMEAN_FILTER_CUTOFF 4 //max value is around WATERLEVELMEAN_SIZE/2 + + +#define WATERLEVEL_UNAVAILABLE -1 //-1 is also timeout value + + +// +++++++++++++++ VL53L0X +++++++++++++++ +VL53L0X sensorA; +#define PIN_VL53L0X_XSHUT 19 +// Uncomment this line to use long range mode. This +// increases the sensitivity of the sensor and extends its +// potential range, but increases the likelihood of getting +// an inaccurate reading because of reflections from objects +// other than the intended target. It works best in dark +// conditions. + +//#define LONG_RANGE + +// Uncomment ONE of these two lines to get +// - higher speed at the cost of lower accuracy OR +// - higher accuracy at the cost of lower speed + +//#define HIGH_SPEED +#define HIGH_ACCURACY + + + + +float waterlevelAMean_array[WATERLEVELMEAN_SIZE]; +uint16_t waterlevelAMean_array_pos=0; +float waterlevelA=WATERLEVEL_UNAVAILABLE; //distance from floor to water surface [mm] +float watervolumeA=WATERLEVEL_UNAVAILABLE; //calculated Volume in Reservoir + + +//Calibration +float waterlevelA_calib_offset=532.78; //c +float waterlevelA_calib_factor=-1.179; //m + + +float waterlevelA_calib_reservoirArea=20*20*3.1416; //area in cm^2. barrel diameter inside is 400mm + +uint16_t distanceA_unsuccessful_count=0; + +// +++++++++++++++ VL6180X +++++++++++++++ +VL6180X sensorB; // To try different scaling factors, change the following define. // Valid scaling factors are 1, 2, or 3. #define SCALING 1 -#define READINTERVAL_WATERLEVEL 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 + +float waterlevelBMean_array[WATERLEVELMEAN_SIZE]; +uint16_t waterlevelBMean_array_pos=0; +float waterlevelB=WATERLEVEL_UNAVAILABLE; //distance from floor to water surface [mm] +float watervolumeB=WATERLEVEL_UNAVAILABLE; //calculated Volume in Reservoir //Calibration -float waterlevel_calib_offset_measured=86; //Sollwert -float waterlevel_calib_offset_sensor=78; //Istwert -//raw reading is 78mm, ruler reads 86mm. VL8160 sensor is 169mm above bottom of reservoir. - -float waterlevel_calib_reservoirArea=27*36.5; //area in cm^2 +float waterlevelB_calib_offset=260.86; //c +float waterlevelB_calib_factor=-1.107; //m -float waterlevel_heightToVolume(float distance); +float waterlevelB_calib_reservoirArea=56.5*36.5; //area in cm^2 + +uint16_t distanceB_unsuccessful_count=0; -mqttValueTiming timing_waterlevel; + + +float waterlevelA_heightToVolume(float distance); +float waterlevelB_heightToVolume(float distance); + + +mqttValueTiming timing_waterlevelA; +mqttValueTiming timing_waterlevelB; void waterlevel_setup() { - timing_waterlevel.minchange=0.0; - timing_waterlevel.maxchange=3.0; - timing_waterlevel.mintime=30*000; - timing_waterlevel.maxtime=60*60*1000; + pinMode(PIN_VL53L0X_XSHUT, OUTPUT); + digitalWrite(PIN_VL53L0X_XSHUT, LOW); //pull to GND + + + + + /* Wire.begin(); - sensor.init(); - sensor.configureDefault(); - sensor.setScaling(SCALING); - sensor.setTimeout(500); + byte error, address; + int nDevices; + + delay(500); + Serial.println("Scanning..."); + + nDevices = 0; + for(address = 1; address < 127; address++ ) + { + // The i2c_scanner uses the return value of + // the Write.endTransmisstion to see if + // a device did acknowledge to the address. + Wire.beginTransmission(address); + error = Wire.endTransmission(); + + if (error == 0) + { + Serial.print("I2C device found at address 0x"); + if (address<16) + Serial.print("0"); + Serial.print(address,HEX); + Serial.println(" !"); + + nDevices++; + } + else if (error==4) + { + Serial.print("Unknown error at address 0x"); + if (address<16) + Serial.print("0"); + Serial.println(address,HEX); + } + } + */ + + + + + timing_waterlevelA.minchange=0.0; + timing_waterlevelA.maxchange=3.0; + timing_waterlevelA.mintime=30*000; + timing_waterlevelA.maxtime=60*60*1000; + + timing_waterlevelB.minchange=0.0; + timing_waterlevelB.maxchange=3.0; + timing_waterlevelB.mintime=30*000; + timing_waterlevelB.maxtime=60*60*1000; + + + + Wire.begin(); + Serial.print("I2C Clock Speed="); + Serial.println(Wire.getClock()); + + + sensorB.setTimeout(1000); + Serial.println("init A"); + sensorB.init(); + Serial.println("set addr 0x2A"); + sensorB.setAddress(0x2A); //change address + Serial.println("conf Default"); + sensorB.configureDefault(); + Serial.println("set scaling"); + sensorB.setScaling(SCALING); + + + + /* + Serial.println("Connect second sensor now!"); + delay(1000); + Serial.println("waiting 5s"); + delay(5000); + Serial.println("done waiting");*/ + + + // Stop driving this sensor's XSHUT low. This should allow the carrier + // board to pull it high. (We do NOT want to drive XSHUT high since it is + // not level shifted.) Then wait a bit for the sensor to start up. + pinMode(PIN_VL53L0X_XSHUT, INPUT); + delay(50); + + + sensorA.setTimeout(1000); + if (!sensorA.init()) + { + Serial.println("Failed to detect and initialize sensorA!"); + publishInfo("error/waterlevel","Failed to detect and initialize sensorA"); + delay(1000); + } + + + + #if defined LONG_RANGE + // lower the return signal rate limit (default is 0.25 MCPS) + sensorA.setSignalRateLimit(0.1); + // increase laser pulse periods (defaults are 14 and 10 PCLKs) + sensorA.setVcselPulsePeriod(VL53L0X::VcselPeriodPreRange, 18); + sensorA.setVcselPulsePeriod(VL53L0X::VcselPeriodFinalRange, 14); + #endif + + #if defined HIGH_SPEED + // reduce timing budget to 20 ms (default is about 33 ms) + sensorA.setMeasurementTimingBudget(20000); + #elif defined HIGH_ACCURACY + // increase timing budget to 200 ms + sensorA.setMeasurementTimingBudget(200000); + #endif + + + + + for (uint16_t i=0;i=last_read_waterlevel+READINTERVAL_WATERLEVEL) { - last_read_waterlevel=loopmillis; - - - uint16_t distance=sensor.readRangeSingleMillimeters(); - - Serial.print("Distance reading:"); Serial.println(distance); + switch(waterlevel_loop_select) + { + case 0: + // ############ A - if (distance!=WATERLEVEL_UNAVAILABLE) { //successful - waterlevelMean_array[waterlevelMean_array_pos]=distance; - waterlevelMean_array_pos++; - waterlevelMean_array_pos%=WATERLEVELMEAN_SIZE; - } - - if (isValueArrayOKf(waterlevelMean_array,WATERLEVELMEAN_SIZE,WATERLEVEL_UNAVAILABLE)){ - float _filteredDistance=getFilteredf(waterlevelMean_array,WATERLEVELMEAN_SIZE,WATERLEVELMEAN_FILTER_CUTOFF); + static unsigned long last_read_waterlevelA; + if (loopmillis>=last_read_waterlevelA+READINTERVAL_WATERLEVEL) { + last_read_waterlevelA=loopmillis; + + uint16_t distance=sensorA.readRangeSingleMillimeters(); //error=65535 + + //Serial.print("Distance reading A="); Serial.print(distance);Serial.println(); - //Invert distance and offset - waterlevel=(waterlevel_calib_offset_sensor+waterlevel_calib_offset_measured)-_filteredDistance; - watervolume=waterlevel_heightToVolume(waterlevel); + + if (distance!=WATERLEVEL_UNAVAILABLE && distance!=65535) { //successful + waterlevelAMean_array[waterlevelAMean_array_pos]=distance; + waterlevelAMean_array_pos++; + waterlevelAMean_array_pos%=WATERLEVELMEAN_SIZE; + distanceA_unsuccessful_count=0; + }else{ + distanceA_unsuccessful_count++; + if (distanceA_unsuccessful_count%20==0) { + String _text="Distance A unsuccessful count="; + _text.concat(distanceA_unsuccessful_count); + _text.concat(" distance="); + _text.concat(distance); + publishInfo("error/waterlevel",_text); + } + } - //float _meanWaterlevel=getMeanf(waterlevelMean,WATERLEVELMEAN_SIZE); - //Serial.print("\t Dist="); Serial.print(_filteredWaterlevel); Serial.print("mm"); Serial.print("(+- "); Serial.print((getMaxf(waterlevelMean,WATERLEVELMEAN_SIZE)-getMinf(waterlevelMean,WATERLEVELMEAN_SIZE))/2.0); Serial.print(")"); Serial.print(" [mean="); Serial.print(_meanWaterlevel); Serial.print("]"); + + if (isValueArrayOKf(waterlevelAMean_array,WATERLEVELMEAN_SIZE,WATERLEVEL_UNAVAILABLE)){ + float _filteredDistance=getFilteredf(waterlevelAMean_array,WATERLEVELMEAN_SIZE,WATERLEVELMEAN_FILTER_CUTOFF); + //Serial.print("Filtered reading A="); Serial.print(_filteredDistance);Serial.println(); + + //Invert distance and offset + waterlevelA=constrain(waterlevelA_calib_offset+waterlevelA_calib_factor*_filteredDistance,0,1000); + watervolumeA=waterlevelA_heightToVolume(waterlevelA); + + //float _meanWaterlevel=getMeanf(waterlevelMean,WATERLEVELMEAN_SIZE); + //Serial.print("\t Dist="); Serial.print(_filteredWaterlevel); Serial.print("mm"); Serial.print("(+- "); Serial.print((getMaxf(waterlevelMean,WATERLEVELMEAN_SIZE)-getMinf(waterlevelMean,WATERLEVELMEAN_SIZE))/2.0); Serial.print(")"); Serial.print(" [mean="); Serial.print(_meanWaterlevel); Serial.print("]"); + } } + waterlevel_loop_select++; + break; + case 1: + + // ############ B + + static unsigned long last_read_waterlevelB; + if (loopmillis>=last_read_waterlevelB+READINTERVAL_WATERLEVEL) { + last_read_waterlevelB=loopmillis; + + + uint16_t distance=sensorB.readRangeSingleMillimeters(); //out of range =255 + + //Serial.print("Distance reading B="); Serial.print(distance);Serial.println(); + + + if (distance!=WATERLEVEL_UNAVAILABLE) { //successful + waterlevelBMean_array[waterlevelBMean_array_pos]=distance; + waterlevelBMean_array_pos++; + waterlevelBMean_array_pos%=WATERLEVELMEAN_SIZE; + distanceB_unsuccessful_count=0; + }else{ + distanceB_unsuccessful_count++; + if (distanceB_unsuccessful_count%20==0) { + String _text="Distance B unsuccessful count="; + _text.concat(distanceB_unsuccessful_count); + _text.concat(" distance="); + _text.concat(distance); + publishInfo("error/waterlevel",_text); + } + } + + + if (isValueArrayOKf(waterlevelBMean_array,WATERLEVELMEAN_SIZE,WATERLEVEL_UNAVAILABLE)){ + float _filteredDistance=getFilteredf(waterlevelBMean_array,WATERLEVELMEAN_SIZE,WATERLEVELMEAN_FILTER_CUTOFF); + + //Serial.print("Filtered reading B="); Serial.print(_filteredDistance);Serial.println(); + //Invert distance and offset + waterlevelB=constrain(waterlevelB_calib_offset+waterlevelB_calib_factor*_filteredDistance,0,1000); + watervolumeB=waterlevelB_heightToVolume(waterlevelB); + + + //float _meanWaterlevel=getMeanf(waterlevelMean,WATERLEVELMEAN_SIZE); + //Serial.print("\t Dist="); Serial.print(_filteredWaterlevel); Serial.print("mm"); Serial.print("(+- "); Serial.print((getMaxf(waterlevelMean,WATERLEVELMEAN_SIZE)-getMinf(waterlevelMean,WATERLEVELMEAN_SIZE))/2.0); Serial.print(")"); Serial.print(" [mean="); Serial.print(_meanWaterlevel); Serial.print("]"); + } + + waterlevel_loop_select=0; + break; + } } } -float waterlevel_heightToVolume(float distance){ - return waterlevel_calib_reservoirArea/100 * distance/100; //area[cm^2] in dm^2 * height in dm = dm^3= L +float waterlevelA_heightToVolume(float distance){ + return waterlevelA_calib_reservoirArea/100 * distance/100; //area[cm^2] in dm^2 * height in dm = dm^3= L +} + + +float waterlevelB_heightToVolume(float distance){ + return waterlevelB_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/waterlevel_vl6180x.h b/include/waterlevel_vl6180x.h new file mode 100644 index 0000000..8f72cdb --- /dev/null +++ b/include/waterlevel_vl6180x.h @@ -0,0 +1,95 @@ +#ifndef _WATERLEVEL_H_ +#define _WATERLEVEL_H_ + +#include +#include //https://github.com/pololu/vl6180x-arduino + + +VL6180X sensor; +// To try different scaling factors, change the following define. +// Valid scaling factors are 1, 2, or 3. +#define SCALING 1 + + +#define READINTERVAL_WATERLEVEL 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 + + +//Calibration +float waterlevel_calib_offset_measured=86; //Sollwert +float waterlevel_calib_offset_sensor=78; //Istwert +//raw reading is 78mm, ruler reads 86mm. VL8160 sensor is 169mm above bottom of reservoir. + +float waterlevel_calib_reservoirArea=27*36.5; //area in cm^2 + + +float waterlevel_heightToVolume(float distance); + + +mqttValueTiming timing_waterlevel; + +void waterlevel_setup() { + + timing_waterlevel.minchange=0.0; + timing_waterlevel.maxchange=3.0; + timing_waterlevel.mintime=30*000; + timing_waterlevel.maxtime=60*60*1000; + + Wire.begin(); + + sensor.init(); + sensor.configureDefault(); + sensor.setScaling(SCALING); + sensor.setTimeout(500); + + for (uint16_t i=0;i=last_read_waterlevel+READINTERVAL_WATERLEVEL) { + last_read_waterlevel=loopmillis; + + + uint16_t distance=sensor.readRangeSingleMillimeters(); + + 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 (isValueArrayOKf(waterlevelMean_array,WATERLEVELMEAN_SIZE,WATERLEVEL_UNAVAILABLE)){ + float _filteredDistance=getFilteredf(waterlevelMean_array,WATERLEVELMEAN_SIZE,WATERLEVELMEAN_FILTER_CUTOFF); + + + //Invert distance and offset + waterlevel=(waterlevel_calib_offset_sensor+waterlevel_calib_offset_measured)-_filteredDistance; + watervolume=waterlevel_heightToVolume(waterlevel); + + //float _meanWaterlevel=getMeanf(waterlevelMean,WATERLEVELMEAN_SIZE); + //Serial.print("\t Dist="); Serial.print(_filteredWaterlevel); Serial.print("mm"); Serial.print("(+- "); Serial.print((getMaxf(waterlevelMean,WATERLEVELMEAN_SIZE)-getMinf(waterlevelMean,WATERLEVELMEAN_SIZE))/2.0); Serial.print(")"); Serial.print(" [mean="); Serial.print(_meanWaterlevel); Serial.print("]"); + } + + + } +} + +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_functions.h b/include/wifi_functions.h index 0cabfbd..fa1b438 100644 --- a/include/wifi_functions.h +++ b/include/wifi_functions.h @@ -31,6 +31,7 @@ bool enableTiming=true; bool publishValueTimed(String topic,float value,uint8_t decimals,mqttValueTiming &mqttvt,unsigned long loopmillis); void publishValue(String topic,float value,uint8_t decimals); +void publishInfo(String topic,String text); void connect() { Serial.print("checking wifi..."); @@ -97,6 +98,13 @@ bool mqtt_loop(unsigned long loopmillis) { return false; } +bool publishValueTimedOverride(String topic,float value,uint8_t decimals,mqttValueTiming &mqttvt,unsigned long loopmillis) { + mqttvt.lasttime=loopmillis; + mqttvt.lastvalue=value; + publishValue(topic,value,decimals); + return true; +} + bool publishValueTimed(String topic,float value,uint8_t decimals,mqttValueTiming &mqttvt,unsigned long loopmillis) { unsigned long timediff=loopmillis-mqttvt.lasttime; float valuediff=abs(value-mqttvt.lastvalue); @@ -122,4 +130,9 @@ void publishValue(String topic,float value,uint8_t decimals) { Serial.print("Publish Topic="); Serial.print((String)client_id+"/"+topic); Serial.print(" Message="); Serial.println(buffer); } +void publishInfo(String topic,String text) { + client.publish((String)client_id+"/"+topic, text); + Serial.print("Publish Topic="); Serial.print((String)client_id+"/"+topic); Serial.print(" Message="); Serial.println(text); +} + #endif \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index 1203da0..a0f4bf2 100644 --- a/platformio.ini +++ b/platformio.ini @@ -19,5 +19,6 @@ lib_deps = https://github.com/milesburton/Arduino-Temperature-Control-Library/ https://github.com/emilv/ArduinoSort/ robtillaart/ADS1X15@^0.3.9 - 256dpi/MQTT@^2.5.1 + 256dpi/MQTT@^2.5.1 + pololu/VL53L0X@^1.3.1 https://github.com/pololu/vl6180x-arduino \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index e40b1f4..020b8ad 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,10 +1,16 @@ #include +/*TODO +mqtt function_: valueerror quittieren +mqtt function: device reboot +check if sendallnext_flag does anything +Do not send first flow value (when filter aray is not full) +*/ #include "wifi_functions.h" -bool debug=true; //print Serial information +bool debug=false; //print Serial information bool mqtt=true; bool eccalibrationoutput=false; //serial output for ec calibration /* Write to file with: @@ -25,6 +31,8 @@ ADS1115 ADS(0x48); #include "temperature.h" +// ######## Water Level +#include "waterlevel.h" // ######## EC @@ -32,9 +40,6 @@ ADS1115 ADS(0x48); -// ######## Water Level -#include "waterlevel.h" - // ######## Flow Rate #include "flow.h" @@ -45,13 +50,16 @@ ADS1115 ADS(0x48); + +bool valueError=false; + unsigned long last_check=0; -bool valueError=false; + #define PIN_BUTTON 12 #define PIN_LED 13 @@ -69,9 +77,14 @@ void setup() { connect(); } + + Serial.println("Setup Waterlevel"); + waterlevel_setup(); + //init ADS1115 if (!ADS.begin()) { Serial.println("Error:"); delay(2000); Serial.println("ADS1115 Init Error!"); + publishInfo("error/general","ADS1115 Init Error"); } ADS.setGain(0); @@ -79,8 +92,6 @@ void setup() { Serial.println("Setup EC"); ec_setup(); - Serial.println("Setup Waterlevel"); - waterlevel_setup(); //temporarily disabled Serial.println("Setup Temperature"); temperature_setup(); @@ -125,7 +136,9 @@ void loop() { temperature_loop(loopmillis); - waterlevel_loop(loopmillis); + if (!ec_measurementRunning()){ //skip tof read when ec measurement running, because vlxx sensor reading takes quite long per cycle + waterlevel_loop(loopmillis); + } flow_loop(loopmillis); @@ -198,6 +211,13 @@ void loop() { digitalWrite(PIN_LED,valueError); } + if (distanceA_unsuccessful_count>20) { + valueError=true; + } + if (distanceB_unsuccessful_count>20) { + valueError=true; + } + if (debug) { @@ -262,9 +282,12 @@ void loop() { Serial.print(ec25_B); Serial.println(); - Serial.print("Waterlevel,Volume = "); - Serial.print(waterlevel); Serial.print(","); - Serial.print(watervolume); + Serial.print("A Waterlevel,Volume = "); + Serial.print(waterlevelA); Serial.print(","); + Serial.print(watervolumeA); Serial.println(); + Serial.print("B Waterlevel,Volume = "); + Serial.print(waterlevelB); Serial.print(","); + Serial.print(watervolumeB); Serial.println(); @@ -302,13 +325,38 @@ void loop() { } */ - publishValueTimed("nft/flow/flow",flow_a,2,timing_flow_a,loopmillis); - publishValueTimed("db/flow/flow",flow_b,2,timing_flow_b,loopmillis); - if (waterlevel!=WATERLEVEL_UNAVAILABLE) { - bool _published=publishValueTimed("waterlevel/height",waterlevel,2,timing_waterlevel,loopmillis); + + static float last_flow_a=0; + if (flow_a==0.0 && last_flow_a!=flow_a) { + publishValueTimedOverride("nft/flow",flow_a,2,timing_flow_a,loopmillis); //publish without waiting if flow is 0 + }else{ + publishValueTimed("nft/flow",flow_a,2,timing_flow_a,loopmillis); + } + last_flow_a=flow_a; + + + static float last_flow_b=0; + if (flow_b==0.0 && last_flow_b!=flow_b) { + publishValueTimedOverride("db/flow",flow_b,2,timing_flow_b,loopmillis); //publish without waiting if flow is 0 + }else{ + publishValueTimed("db/flow",flow_b,2,timing_flow_b,loopmillis); + } + last_flow_b=flow_b; + + + + if (waterlevelA!=WATERLEVEL_UNAVAILABLE) { + bool _published=publishValueTimed("nft/waterlevel/height",waterlevelA,2,timing_waterlevelA,loopmillis); if (_published) { //use height for timing. send calculated volume with it - publishValue("waterlevel/volume",watervolume,2); + publishValue("nft/waterlevel/volume",watervolumeA,2); + } + } + + if (waterlevelB!=WATERLEVEL_UNAVAILABLE) { + bool _published=publishValueTimed("db/waterlevel/height",waterlevelB,2,timing_waterlevelB,loopmillis); + if (_published) { //use height for timing. send calculated volume with it + publishValue("db/waterlevel/volume",watervolumeB,2); } } @@ -322,15 +370,15 @@ void loop() { //Probe A if (ec_adc_A!=0) { - publishValue("nft/ec/adc",ec_adc_A,0); + publishValue("db/ec/adc",ec_adc_A,0); } if (ec_adc_adjusted_A!=0) { - publishValue("nft/ec/adcadjusted",ec_adc_adjusted_A,0); + publishValue("db/ec/adcadjusted",ec_adc_adjusted_A,0); } if (ec_A!=EC_UNAVAILABLE){ - publishValue("nft/ec/ec",ec_A,0); - publishValue("nft/ec/sc",ec25_A,0); + publishValue("db/ec/ec",ec_A,0); + publishValue("db/ec/sc",ec25_A,0); } //Probe B @@ -339,11 +387,11 @@ void loop() { } if (ec_adc_adjusted_B!=0) { - publishValue("db/ec/adcadjusted",ec_adc_adjusted_B,0); + publishValue("nft/ec/adcadjusted",ec_adc_adjusted_B,0); } if (ec_B!=EC_UNAVAILABLE){ - publishValue("db/ec/ec",ec_B,0); - publishValue("db/ec/sc",ec25_B,0); + publishValue("nft/ec/ec",ec_B,0); + publishValue("nft/ec/sc",ec25_B,0); } }