add seconds waterlevel sensor

This commit is contained in:
interfisch 2024-05-11 09:20:37 +02:00
parent feeec8ffd4
commit 6e2b02e121
7 changed files with 487 additions and 76 deletions

View File

@ -96,6 +96,7 @@ void ec_connectProbe(bool, uint8_t);
void ec_releaseRelay(); 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_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); float ec_calculateEC25(float pEC,float pTemp);
bool ec_measurementRunning();
void ec_setup() { void ec_setup() {
/* /*
@ -218,12 +219,17 @@ void ec_loop(unsigned long loopmillis) {
} }
if (ec_array_pos<EC_ARRAY_SIZE) { //measurement running if (ec_measurementRunning()) { //measurement running
if (loopmillis>last_read_ec+EC_READ_INTERVAL) { //take reading into array if (loopmillis>last_read_ec+EC_READ_INTERVAL) { //take reading into array
last_read_ec=loopmillis; 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); uint16_t value = ADS.readADC(EC_ADS_CHANNEL);
Serial.print(". Write to pos ");
Serial.println(ec_array_pos);
ec_array[ec_array_pos]=value; 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)); return pEC/(1.0+ec_tempadjust_alpa*(pTemp-25.0));
} }
bool ec_measurementRunning() {
return (ec_array_pos<EC_ARRAY_SIZE);
}
#endif #endif

View File

@ -99,6 +99,9 @@ void temperature_setup() {
DeviceAddress _addr; DeviceAddress _addr;
if (!oneWire.search(_addr)) { if (!oneWire.search(_addr)) {
Serial.print("Error: Device not found"); Serial.print("Error: Device not found");
String _text="Error: Device not found. id=";
_text.concat(i);
publishInfo("error/temperature",_text);
}else{ }else{
Serial.print("Found device. Address:"); Serial.print("Found device. Address:");
printAddress(_addr); printAddress(_addr);
@ -120,6 +123,7 @@ void temperature_loop(unsigned long loopmillis) {
if (loopmillis>last_read_ds18b20+READINTERVAL_DS18B20) { if (loopmillis>last_read_ds18b20+READINTERVAL_DS18B20) {
if (loopmillis>last_read_ds18b20+READINTERVAL_DS18B20*10) { //timeout if (loopmillis>last_read_ds18b20+READINTERVAL_DS18B20*10) { //timeout
Serial.println("Warn: Request Temperatures Timeout!"); Serial.println("Warn: Request Temperatures Timeout!");
publishInfo("error/temperature","Warn: Request Temperatures Timeout!");
flag_requestTemperatures=false; flag_requestTemperatures=false;
} }
if (!flag_requestTemperatures) { if (!flag_requestTemperatures) {
@ -134,6 +138,7 @@ void temperature_loop(unsigned long loopmillis) {
if (tempC_reservoir_a == DEVICE_DISCONNECTED_C) if (tempC_reservoir_a == DEVICE_DISCONNECTED_C)
{ {
Serial.print(" Error reading: "); printAddress(thermometerReservoirA); Serial.print(" Error reading: "); printAddress(thermometerReservoirA);
publishInfo("error/temperature","Error reading thermometerReservoirA");
}else{ }else{
tempCmean_reservoir_a_array[tempCmean_pos]=tempC_reservoir_a; tempCmean_reservoir_a_array[tempCmean_pos]=tempC_reservoir_a;
if (isValueArrayOKf(tempCmean_reservoir_a_array,TEMPMEAN_SIZE,DEVICE_DISCONNECTED_C)) { 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) if (tempC_reservoir_b == DEVICE_DISCONNECTED_C)
{ {
Serial.print(" Error reading: "); printAddress(thermometerReservoirB); Serial.print(" Error reading: "); printAddress(thermometerReservoirB);
publishInfo("error/temperature","Error reading thermometerReservoirB");
}else{ }else{
tempCmean_reservoir_b_array[tempCmean_pos]=tempC_reservoir_b; tempCmean_reservoir_b_array[tempCmean_pos]=tempC_reservoir_b;
if (isValueArrayOKf(tempCmean_reservoir_b_array,TEMPMEAN_SIZE,DEVICE_DISCONNECTED_C)) { 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) if (tempC_case == DEVICE_DISCONNECTED_C)
{ {
Serial.print(" Error reading: "); printAddress(thermometerCase); Serial.print(" Error reading: "); printAddress(thermometerCase);
publishInfo("error/temperature","Error reading thermometerCase");
}else{ }else{
tempCmean_case_array[tempCmean_pos]=tempC_case; tempCmean_case_array[tempCmean_pos]=tempC_case;
if (isValueArrayOKf(tempCmean_case_array,TEMPMEAN_SIZE,DEVICE_DISCONNECTED_C)) { if (isValueArrayOKf(tempCmean_case_array,TEMPMEAN_SIZE,DEVICE_DISCONNECTED_C)) {

View File

@ -2,94 +2,332 @@
#define _WATERLEVEL_H_ #define _WATERLEVEL_H_
#include <Wire.h> #include <Wire.h>
#include <VL6180X.h> #include <VL53L0X.h> //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. // To try different scaling factors, change the following define.
// Valid scaling factors are 1, 2, or 3. // Valid scaling factors are 1, 2, or 3.
#define SCALING 1 #define SCALING 1
#define READINTERVAL_WATERLEVEL 200
#define WATERLEVELMEAN_SIZE 32
#define WATERLEVELMEAN_FILTER_CUTOFF 8 //max value is around WATERLEVELMEAN_SIZE/2 float waterlevelBMean_array[WATERLEVELMEAN_SIZE];
float waterlevelMean_array[WATERLEVELMEAN_SIZE]; uint16_t waterlevelBMean_array_pos=0;
uint16_t waterlevelMean_array_pos=0; float waterlevelB=WATERLEVEL_UNAVAILABLE; //distance from floor to water surface [mm]
#define WATERLEVEL_UNAVAILABLE -1 float watervolumeB=WATERLEVEL_UNAVAILABLE; //calculated Volume in Reservoir
float waterlevel=WATERLEVEL_UNAVAILABLE; //distance from floor to water surface [mm]
float watervolume=WATERLEVEL_UNAVAILABLE; //calculated Volume in Reservoir
//Calibration //Calibration
float waterlevel_calib_offset_measured=86; //Sollwert float waterlevelB_calib_offset=260.86; //c
float waterlevel_calib_offset_sensor=78; //Istwert float waterlevelB_calib_factor=-1.107; //m
//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); 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() { 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(); Wire.begin();
sensor.init(); byte error, address;
sensor.configureDefault(); int nDevices;
sensor.setScaling(SCALING);
sensor.setTimeout(500); 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<WATERLEVELMEAN_SIZE;i++) { for (uint16_t i=0;i<WATERLEVELMEAN_SIZE;i++) {
waterlevelMean_array[i]=-1; //-1 is also timeout value waterlevelAMean_array[i]=WATERLEVEL_UNAVAILABLE; //-1 is also timeout value
waterlevelBMean_array[i]=WATERLEVEL_UNAVAILABLE; //-1 is also timeout value
} }
} }
void waterlevel_loop(unsigned long loopmillis) { void waterlevel_loop(unsigned long loopmillis) {
static uint8_t waterlevel_loop_select=0;
static unsigned long last_read_waterlevel; switch(waterlevel_loop_select)
if (loopmillis>=last_read_waterlevel+READINTERVAL_WATERLEVEL) { {
last_read_waterlevel=loopmillis; case 0:
// ############ A
uint16_t distance=sensor.readRangeSingleMillimeters();
Serial.print("Distance reading:"); Serial.println(distance);
if (distance!=WATERLEVEL_UNAVAILABLE) { //successful static unsigned long last_read_waterlevelA;
waterlevelMean_array[waterlevelMean_array_pos]=distance; if (loopmillis>=last_read_waterlevelA+READINTERVAL_WATERLEVEL) {
waterlevelMean_array_pos++; last_read_waterlevelA=loopmillis;
waterlevelMean_array_pos%=WATERLEVELMEAN_SIZE;
}
if (isValueArrayOKf(waterlevelMean_array,WATERLEVELMEAN_SIZE,WATERLEVEL_UNAVAILABLE)){
float _filteredDistance=getFilteredf(waterlevelMean_array,WATERLEVELMEAN_SIZE,WATERLEVELMEAN_FILTER_CUTOFF);
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; if (distance!=WATERLEVEL_UNAVAILABLE && distance!=65535) { //successful
watervolume=waterlevel_heightToVolume(waterlevel); 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){ float waterlevelA_heightToVolume(float distance){
return waterlevel_calib_reservoirArea/100 * distance/100; //area[cm^2] in dm^2 * height in dm = dm^3= L 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 #endif

View File

@ -0,0 +1,95 @@
#ifndef _WATERLEVEL_H_
#define _WATERLEVEL_H_
#include <Wire.h>
#include <VL6180X.h> //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<WATERLEVELMEAN_SIZE;i++) {
waterlevelMean_array[i]=-1; //-1 is also timeout value
}
}
void waterlevel_loop(unsigned long loopmillis) {
static unsigned long last_read_waterlevel;
if (loopmillis>=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

View File

@ -31,6 +31,7 @@ bool enableTiming=true;
bool publishValueTimed(String topic,float value,uint8_t decimals,mqttValueTiming &mqttvt,unsigned long loopmillis); bool publishValueTimed(String topic,float value,uint8_t decimals,mqttValueTiming &mqttvt,unsigned long loopmillis);
void publishValue(String topic,float value,uint8_t decimals); void publishValue(String topic,float value,uint8_t decimals);
void publishInfo(String topic,String text);
void connect() { void connect() {
Serial.print("checking wifi..."); Serial.print("checking wifi...");
@ -97,6 +98,13 @@ bool mqtt_loop(unsigned long loopmillis) {
return false; 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) { bool publishValueTimed(String topic,float value,uint8_t decimals,mqttValueTiming &mqttvt,unsigned long loopmillis) {
unsigned long timediff=loopmillis-mqttvt.lasttime; unsigned long timediff=loopmillis-mqttvt.lasttime;
float valuediff=abs(value-mqttvt.lastvalue); 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); 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 #endif

View File

@ -19,5 +19,6 @@ lib_deps =
https://github.com/milesburton/Arduino-Temperature-Control-Library/ https://github.com/milesburton/Arduino-Temperature-Control-Library/
https://github.com/emilv/ArduinoSort/ https://github.com/emilv/ArduinoSort/
robtillaart/ADS1X15@^0.3.9 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 https://github.com/pololu/vl6180x-arduino

View File

@ -1,10 +1,16 @@
#include <Arduino.h> #include <Arduino.h>
/*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" #include "wifi_functions.h"
bool debug=true; //print Serial information bool debug=false; //print Serial information
bool mqtt=true; bool mqtt=true;
bool eccalibrationoutput=false; //serial output for ec calibration bool eccalibrationoutput=false; //serial output for ec calibration
/* Write to file with: /* Write to file with:
@ -25,6 +31,8 @@ ADS1115 ADS(0x48);
#include "temperature.h" #include "temperature.h"
// ######## Water Level
#include "waterlevel.h"
// ######## EC // ######## EC
@ -32,9 +40,6 @@ ADS1115 ADS(0x48);
// ######## Water Level
#include "waterlevel.h"
// ######## Flow Rate // ######## Flow Rate
#include "flow.h" #include "flow.h"
@ -45,13 +50,16 @@ ADS1115 ADS(0x48);
bool valueError=false;
unsigned long last_check=0; unsigned long last_check=0;
bool valueError=false;
#define PIN_BUTTON 12 #define PIN_BUTTON 12
#define PIN_LED 13 #define PIN_LED 13
@ -69,9 +77,14 @@ void setup() {
connect(); connect();
} }
Serial.println("Setup Waterlevel");
waterlevel_setup();
//init ADS1115 //init ADS1115
if (!ADS.begin()) { if (!ADS.begin()) {
Serial.println("Error:"); delay(2000); Serial.println("ADS1115 Init Error!"); Serial.println("Error:"); delay(2000); Serial.println("ADS1115 Init Error!");
publishInfo("error/general","ADS1115 Init Error");
} }
ADS.setGain(0); ADS.setGain(0);
@ -79,8 +92,6 @@ void setup() {
Serial.println("Setup EC"); Serial.println("Setup EC");
ec_setup(); ec_setup();
Serial.println("Setup Waterlevel");
waterlevel_setup(); //temporarily disabled
Serial.println("Setup Temperature"); Serial.println("Setup Temperature");
temperature_setup(); temperature_setup();
@ -125,7 +136,9 @@ void loop() {
temperature_loop(loopmillis); 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); flow_loop(loopmillis);
@ -198,6 +211,13 @@ void loop() {
digitalWrite(PIN_LED,valueError); digitalWrite(PIN_LED,valueError);
} }
if (distanceA_unsuccessful_count>20) {
valueError=true;
}
if (distanceB_unsuccessful_count>20) {
valueError=true;
}
if (debug) { if (debug) {
@ -262,9 +282,12 @@ void loop() {
Serial.print(ec25_B); Serial.print(ec25_B);
Serial.println(); Serial.println();
Serial.print("Waterlevel,Volume = "); Serial.print("A Waterlevel,Volume = ");
Serial.print(waterlevel); Serial.print(","); Serial.print(waterlevelA); Serial.print(",");
Serial.print(watervolume); Serial.print(watervolumeA); Serial.println();
Serial.print("B Waterlevel,Volume = ");
Serial.print(waterlevelB); Serial.print(",");
Serial.print(watervolumeB);
Serial.println(); 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 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 //Probe A
if (ec_adc_A!=0) { 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) { 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){ if (ec_A!=EC_UNAVAILABLE){
publishValue("nft/ec/ec",ec_A,0); publishValue("db/ec/ec",ec_A,0);
publishValue("nft/ec/sc",ec25_A,0); publishValue("db/ec/sc",ec25_A,0);
} }
//Probe B //Probe B
@ -339,11 +387,11 @@ void loop() {
} }
if (ec_adc_adjusted_B!=0) { 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){ if (ec_B!=EC_UNAVAILABLE){
publishValue("db/ec/ec",ec_B,0); publishValue("nft/ec/ec",ec_B,0);
publishValue("db/ec/sc",ec25_B,0); publishValue("nft/ec/sc",ec25_B,0);
} }
} }