clean up measurements and serial output

This commit is contained in:
interfisch 2023-05-07 16:20:17 +02:00
parent c6dc842d6f
commit a8def64601
6 changed files with 331 additions and 105 deletions

View File

@ -6,6 +6,10 @@
bool ec_flag_measurement_available=false;
#define EC_ADC_UNAVAILABLE 0
#define EC_UNAVAILABLE -1
#define EC_PIN_RELAY_PROBE 27
@ -16,7 +20,7 @@ bool ec_flag_measurement_available=false;
#define EC_RESOLUTION 8
#define EC_FREQUENCY 5000
#define EC_CALIB_ARRAY_SIZE 256
#define EC_CALIB_ARRAY_SIZE 128
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
@ -46,8 +50,10 @@ 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_tempadjust_alpa=0.2; //TODO
float ec_tempadjust_alpa=0.02;
float ec_reference_adc=6016.88; //adc reference value for the calibration resistor measurement.
//EC short circuit adc value: 17497 (for connection restistance testing)
//EC open circuit adc value: 738
//x^0*p[0] + ... + x^n*p[n]
//float ec_calibration_polynom[]={691.5992624638029,-1.4015367296761692,0.0008513503472324141,-2.2140576823179093e-07,2.8962580780180067e-11,-1.8577565383307114e-15,4.7162479484903865e-20};
@ -62,6 +68,7 @@ void ec_setRange(uint8_t range);
void ec_connectProbe(bool);
void ec_releaseRelay();
float ec_getECfromADC(float adc);
float ec_calculateEC25(float pEC,float pTemp);
void ec_setup() {
ledcSetup(EC_PWM_CH, EC_FREQUENCY, EC_RESOLUTION);
@ -93,10 +100,16 @@ void ec_loop(unsigned long loopmillis) {
if (ec_measurementReady()) {
ec_releaseRelay();
ec_adc=getMean(ec_array,EC_ARRAY_SIZE);
if (isValueArrayOK(ec_calib_array,EC_CALIB_ARRAY_SIZE,0)){
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);
ec25=ec_calculateEC25(ec,tempC_reservoir);
}else{
ec_calib_adc=EC_ADC_UNAVAILABLE;
ec_adc_adjusted=EC_ADC_UNAVAILABLE;
ec=EC_UNAVAILABLE;
ec25=EC_UNAVAILABLE;
}
ec_flag_measurement_available=true;
@ -189,5 +202,10 @@ float ec_getECfromADC(float adc) {
return _ec;
}
float ec_calculateEC25(float pEC,float pTemp)
{
return pEC/(1.0+ec_tempadjust_alpa*(pTemp-25.0));
}
#endif

View File

@ -5,7 +5,7 @@
uint16_t flow_counter=0; //maximum counts/s measured with Eden 128 Pump was 171
void IRAM_ATTR isr_flow();
unsigned long last_read_flow=0;
#define READINTERVAL_FLOW 1000
#define READINTERVAL_FLOW 2000
float flow_factor=7.5; //F=7.5*flowrate[L/min]
float flow;

View File

@ -2,25 +2,95 @@
#define _SOILMOISTURE_H_
#define SM1_ADS_CHANNEL 1
#define SM2_ADS_CHANNEL 2
#define SM3_ADS_CHANNEL 3
#define READINTERVAL_SM 100
//Calibration values
//high=adc value for sensor in air
//low=adc value for sensor in NaCl solution at 25°C with 12880 uS/cm
float sm1_low=45555;
float sm1_high=11799;
float sm2_low=3235;
float sm2_high=16050;
float sm3_low=0;
float sm3_high=16000;
//sm1 is underwater reservoir soilmoisture sensor (#2)
//sm2 is soilmoisture sensor (#1)
unsigned long last_read_sm=0;
#define SM_SIZE 16
uint8_t sm_mean_pos=0;
uint16_t sm_mean[SM_SIZE];
uint16_t sm_mean1array[SM_SIZE];
uint16_t sm_mean2array[SM_SIZE];
uint16_t sm_mean3array[SM_SIZE];
#define SM_DISCONNECTED -1
float sm_mean1=SM_DISCONNECTED;
float sm_mean2=SM_DISCONNECTED;
float sm_mean3=SM_DISCONNECTED;
uint8_t sm_readchannel=0;
void sm_setup() {
for (uint16_t i=0;i<SM_SIZE;i++) {
sm_mean1array[i]=SM_DISCONNECTED;
sm_mean2array[i]=SM_DISCONNECTED;
sm_mean3array[i]=SM_DISCONNECTED;
}
}
void sm_loop(unsigned long loopmillis) {
if (loopmillis>=last_read_sm+READINTERVAL_SM) {
last_read_sm=loopmillis;
switch (sm_readchannel) {
case 0:
sm_mean1array[sm_mean_pos]=ADS.readADC(SM1_ADS_CHANNEL);
sm_readchannel++;
uint16_t value = ADS.readADC(SM1_ADS_CHANNEL);
sm_mean[sm_mean_pos]=value;
sm_mean_pos++;
sm_mean_pos%=SM_SIZE;
break;
case 1:
sm_mean2array[sm_mean_pos]=ADS.readADC(SM2_ADS_CHANNEL);
sm_readchannel++;
break;
default: //2 and above
sm_mean3array[sm_mean_pos]=ADS.readADC(SM3_ADS_CHANNEL);
sm_readchannel=0;
sm_mean_pos++;
sm_mean_pos%=SM_SIZE;
last_read_sm=loopmillis;
if (isValueArrayOK(sm_mean1array,SM_SIZE,SM_DISCONNECTED)){
float _sm_mean_raw;
_sm_mean_raw=getMean(sm_mean1array,SM_SIZE);
sm_mean1=mapf(_sm_mean_raw,sm1_low,sm1_high,1.0,0.0);
_sm_mean_raw=getMean(sm_mean2array,SM_SIZE);
sm_mean2=mapf(_sm_mean_raw,sm2_low,sm2_high,1.0,0.0);
_sm_mean_raw=getMean(sm_mean3array,SM_SIZE);
sm_mean3=mapf(_sm_mean_raw,sm3_low,sm3_high,1.0,0.0);
}
break;
}
//Serial.print(getMean(sm_mean,SM_SIZE)); Serial.print("\t "); Serial.println(value);
}

View File

@ -25,30 +25,34 @@ DallasTemperature sensors(&oneWire);
uint16_t tempCmean_pos=0;
// arrays to hold device addresses
DeviceAddress thermometerReservoir={0x28,0xFF,0x30,0xBA,0x85,0x16,0x03,0xB5};
float tempC_reservoir;
float tempCmean_reservoir[TEMPMEAN_SIZE];
float tempC_reservoir; //last reading
float tempCmean_reservoir_array[TEMPMEAN_SIZE];
float tempCmean_reservoir=DEVICE_DISCONNECTED_C;
DeviceAddress thermometerAir={0x28,0xFF,0x6C,0x1C,0x72,0x16,0x05,0x8B};
float tempC_air;
float tempCmean_air[TEMPMEAN_SIZE];
float tempC_air; //last reading
float tempCmean_air_array[TEMPMEAN_SIZE];
float tempCmean_air=DEVICE_DISCONNECTED_C;
void temperature_setup() {
//initialize mean array
for (uint16_t i=0;i<TEMPMEAN_SIZE;i++) {
tempCmean_reservoir[i]=-127;
tempCmean_air[i]=-127;
tempCmean_reservoir_array[i]=-127;
tempCmean_air_array[i]=-127;
}
sensors.begin();
delay(1000);
//Serial.print("Locating devices...");
//Serial.print("Found ");
//Serial.print(sensors.getDeviceCount(), DEC);
//Serial.println(" devices.");
Serial.print("Locating devices...");
Serial.print("Found ");
Serial.print(sensors.getDeviceCount(), DEC);
Serial.println(" devices.");
delay(1000);
@ -101,7 +105,12 @@ void temperature_loop(unsigned long loopmillis) {
{
Serial.print(" Error reading: "); printAddress(thermometerReservoir);
}else{
tempCmean_reservoir[tempCmean_pos]=tempC_reservoir;
tempCmean_reservoir_array[tempCmean_pos]=tempC_reservoir;
if (isValueArrayOKf(tempCmean_reservoir_array,TEMPMEAN_SIZE,DEVICE_DISCONNECTED_C)) {
tempCmean_reservoir=getMeanf(tempCmean_reservoir_array,TEMPMEAN_SIZE);
}else{
tempCmean_reservoir=DEVICE_DISCONNECTED_C;
}
}
tempC_air = sensors.getTempC(thermometerAir);
@ -109,7 +118,12 @@ void temperature_loop(unsigned long loopmillis) {
{
Serial.print(" Error reading: "); printAddress(thermometerReservoir);
}else{
tempCmean_air[tempCmean_pos]=tempC_air;
tempCmean_air_array[tempCmean_pos]=tempC_air;
if (isValueArrayOKf(tempCmean_air_array,TEMPMEAN_SIZE,DEVICE_DISCONNECTED_C)) {
tempCmean_air=getMeanf(tempCmean_air_array,TEMPMEAN_SIZE);
}else{
tempCmean_air=DEVICE_DISCONNECTED_C;
}
}
tempCmean_pos++;

View File

@ -6,12 +6,20 @@
#define HCSR04_PIN_ECHO 17
#define HCSR04_PIN_TRIGGER 16
#define HCSR04_TIMEOUT 5000 //default is 100000 (uS)
#define READINTERVAL_HCSR04 100
#define READINTERVAL_HCSR04 500
#define WATERLEVELMEAN_SIZE 32
float waterlevelMean[WATERLEVELMEAN_SIZE];
uint16_t waterlevelMean_pos=0;
float waterlevelMean_array[WATERLEVELMEAN_SIZE];
uint16_t waterlevelMean_array_pos=0;
#define WATERLEVEL_UNAVAILABLE -1
float waterlevel=WATERLEVEL_UNAVAILABLE;
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
float waterlevel_distanceToVolume(float distance);
void waterlevel_setup() {
@ -19,7 +27,7 @@ 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<WATERLEVELMEAN_SIZE;i++) {
waterlevelMean[i]=-1; //-1 is also timeout value
waterlevelMean_array[i]=-1; //-1 is also timeout value
}
}
@ -30,15 +38,50 @@ void waterlevel_loop(unsigned long loopmillis) {
if (loopmillis>=last_read_hcsr04+READINTERVAL_HCSR04) {
last_read_hcsr04=loopmillis;
float temperature=20.0;
if (tempC_air!=DEVICE_DISCONNECTED_C && isValueArrayOKf(tempCmean_air,TEMPMEAN_SIZE,DEVICE_DISCONNECTED_C)) { //sensor ok
temperature=getMeanf(tempCmean_air,TEMPMEAN_SIZE);
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_MAXFAILS) {
waterlevel_failcounter++;
}
}
if (isValueArrayOKf(waterlevelMean_array,WATERLEVELMEAN_SIZE,WATERLEVEL_UNAVAILABLE)){
float _distance=getFilteredf(waterlevelMean_array,WATERLEVELMEAN_SIZE,8);
waterlevel=waterlevel_distanceToVolume(_distance);
//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 (waterlevel_failcounter>=WATERLEVEL_FAILTHRESHOLD) { //too many failed readings
waterlevel=-1;
/*if (debug) {
Serial.print("Waterlevel Failcounter="); Serial.println(waterlevel_failcounter);
}*/
}
waterlevelMean[waterlevelMean_pos]=distances[0];
waterlevelMean_pos++;
waterlevelMean_pos%=WATERLEVELMEAN_SIZE;
}
}
float waterlevel_distanceToVolume(float distance){
return distance;
}
#endif

View File

@ -1,18 +1,20 @@
#include <Arduino.h>
bool flag_print=false;
bool debug=true; //print Serial information
#include "helpfunctions.h"
#include "ADS1X15.h"
ADS1115 ADS(0x48);
// ######## EC
#include "ec.h"
// ######## Temperature
#include "temperature.h"
// ######## EC
#include "ec.h"
// ######## Water Level
#include "waterlevel.h"
@ -25,13 +27,13 @@ ADS1115 ADS(0x48);
#include "soilmoisture.h"
unsigned long last_print=0;
unsigned long last_check=0;
bool valueError=false;
#define PIN_BUTTON 12
#define PIN_LED 13
@ -50,15 +52,19 @@ void setup() {
ADS.setGain(0);
Serial.println("Setup EC");
ec_setup();
Serial.println("Setup Waterlevel");
waterlevel_setup();
Serial.println("Setup Temperature");
temperature_setup();
Serial.println("Setup Flow");
flow_setup();
//Serial.println("Setup finished");
Serial.println("Finished Setup");
delay(200);
//Test adc to ec function output
@ -76,102 +82,177 @@ void setup() {
//Serial.println("time,tempReservoir,ECadcCalib,ECadc,ECadcAdjusted,EC,EC25");
Serial.println("time,tempReservoir,ECadcCalib,ECadc,ECadcAdjusted,sm");
//Serial.println("time,tempReservoir,ECadcCalib,ECadc,ECadcAdjusted,sm");
}
void loop() {
unsigned long loopmillis=millis();
flag_print=false;
ec_loop(loopmillis);
temperature_loop(loopmillis);
//waterlevel_loop(loopmillis);
waterlevel_loop(loopmillis);
//flow_loop(loopmillis);
flow_loop(loopmillis);
sm_loop(loopmillis);
static bool getReading=false;
if (!getReading && !digitalRead(PIN_BUTTON)) {
getReading=true;
last_measurement_ec=0; //force ec reading now
ec_flag_measurement_available=false;
digitalWrite(PIN_LED,HIGH);
if (!digitalRead(PIN_BUTTON)) {
valueError=false;
Serial.println("Reset ValueError flag by user");
digitalWrite(PIN_LED,valueError);
delay(100);
}
if (loopmillis>last_check+2000) { //check values
if (loopmillis>last_print+2000) {
//if (ec_flag_measurement_available && getReading) {
if (ec_flag_measurement_available) {
last_print=loopmillis;
getReading=false;
ec_flag_measurement_available=false;
digitalWrite(PIN_LED,LOW);
last_check=loopmillis;
Serial.print(millis()/1000.0,2); Serial.print(",");
Serial.print(getMeanf(tempCmean_reservoir,TEMPMEAN_SIZE)); Serial.print(",");
//Serial.print(getMean(sm_mean,SM_SIZE)); Serial.print(",");
Serial.print(ec_calib_adc); Serial.print(",");
Serial.print(ec_adc); Serial.print(",");
Serial.print(ec_adc_adjusted); Serial.print(",");
//Serial.print(ec); Serial.print(",");
//Serial.print(ec25);
Serial.print(getMean(sm_mean,SM_SIZE));
if (tempCmean_air==DEVICE_DISCONNECTED_C || tempCmean_reservoir==DEVICE_DISCONNECTED_C) {
valueError=true;
}
if (waterlevel==WATERLEVEL_UNAVAILABLE) {
valueError=true;
}
if (sm_mean1==SM_DISCONNECTED || sm_mean2==SM_DISCONNECTED) {
valueError=true;
}
if (ec==EC_UNAVAILABLE){
valueError=true;
}
digitalWrite(PIN_LED,valueError);
if (debug) {
Serial.println("_______________________");
Serial.print(millis()/1000.0,2); Serial.println(":");
Serial.print("temperature reservoir,air = ");
Serial.print(tempCmean_reservoir); Serial.print(","); Serial.print(tempCmean_air);
Serial.println();
Serial.print("sm_mean 1,2,3 = ");
Serial.print(sm_mean1); Serial.print(",");
Serial.print(sm_mean2); Serial.print(",");
Serial.print(sm_mean3);
Serial.println();
/*
if (isValueArrayOKf(tempCmean_reservoir,TEMPMEAN_SIZE,DEVICE_DISCONNECTED_C)){
Serial.print("\t Treservoir="); Serial.print(getMeanf(tempCmean_reservoir,TEMPMEAN_SIZE)); Serial.print("\t Tair="); Serial.print(getMeanf(tempCmean_air,TEMPMEAN_SIZE));
}else{
Serial.print("\t waiting for temperature");
}
if (isValueArrayOKf(waterlevelMean,WATERLEVELMEAN_SIZE,-1.0)){
float _max=getMaxf(waterlevelMean,WATERLEVELMEAN_SIZE);
float _min=getMinf(waterlevelMean,WATERLEVELMEAN_SIZE);
float _filteredWaterlevel=getFilteredf(waterlevelMean,WATERLEVELMEAN_SIZE,8);
float _meanWaterlevel=getMeanf(waterlevelMean,WATERLEVELMEAN_SIZE);
Serial.print("\t Dist="); Serial.print(_filteredWaterlevel); Serial.print("mm"); Serial.print("(+- "); Serial.print((_max-_min)/2.0); Serial.print(")"); Serial.print(" [mean="); Serial.print(_meanWaterlevel); Serial.print("]");
}else{
Serial.print("\t waiting for distance");
}
Serial.print("\t Flow="); Serial.print(flow,2);
Serial.print("\t Flowsum="); Serial.print(flow_counter_sum);
Serial.println();
Serial.print("sm_mean 1,2,3 = ");
Serial.print(getMean(sm_mean1array,SM_SIZE)); Serial.print(",");
Serial.print(getMean(sm_mean2array,SM_SIZE)); Serial.print(",");
Serial.print(getMean(sm_mean3array,SM_SIZE));
Serial.println();
Serial.print("sm_max 1,2,3 = ");
Serial.print(getMax(sm_mean1array,SM_SIZE)); Serial.print(",");
Serial.print(getMax(sm_mean2array,SM_SIZE)); Serial.print(",");
Serial.print(getMax(sm_mean3array,SM_SIZE));
Serial.println();
Serial.print("sm_min 1,2,3 = ");
Serial.print(getMin(sm_mean1array,SM_SIZE)); Serial.print(",");
Serial.print(getMin(sm_mean2array,SM_SIZE)); Serial.print(",");
Serial.print(getMin(sm_mean3array,SM_SIZE));
Serial.println();
//Serial.print(getMax(sm_mean3array,SM_SIZE)); Serial.println();
*/
Serial.print("Flow = "); Serial.print(flow);
Serial.println();
Serial.print("EC ec_calib_adc,ec_adc,ec_adc_adjusted = ");
Serial.print(ec_calib_adc); Serial.print(",");
Serial.print(ec_adc); Serial.print(",");
Serial.print(ec_adc_adjusted);
Serial.println();
Serial.print("EC ec,ec25 = ");
Serial.print(ec); Serial.print(",");
Serial.print(ec25);
Serial.println();
Serial.print("Waterlevel="); Serial.print(waterlevel);
Serial.println();
}
/*
Serial.print(millis()/1000.0,2); Serial.print(",");
Serial.print(getMeanf(tempCmean_reservoir_array,TEMPMEAN_SIZE)); Serial.print(",");
//Serial.print(getMean(sm_mean,SM_SIZE)); Serial.print(",");
Serial.print(ec_calib_adc); Serial.print(",");
Serial.print(ec_adc); Serial.print(",");
Serial.print(ec_adc_adjusted); Serial.print(",");
Serial.print(ec); Serial.print(",");
Serial.print(ec25);
Serial.print(getMean(sm_mean,SM_SIZE));
Serial.println();
if (tempCmean_reservoir!=DEVICE_DISCONNECTED_C){
Serial.print("\t Treservoir="); Serial.print(tempCmean_reservoir); Serial.print("\t Tair="); Serial.print(tempCmean_air);
}else{
Serial.print("\t waiting for temperature");
}
if (isValueArrayOKf(waterlevelMean,WATERLEVELMEAN_SIZE,-1.0)){
float _max=getMaxf(waterlevelMean,WATERLEVELMEAN_SIZE);
float _min=getMinf(waterlevelMean,WATERLEVELMEAN_SIZE);
float _filteredWaterlevel=getFilteredf(waterlevelMean,WATERLEVELMEAN_SIZE,8);
float _meanWaterlevel=getMeanf(waterlevelMean,WATERLEVELMEAN_SIZE);
Serial.print("\t Dist="); Serial.print(_filteredWaterlevel); Serial.print("mm"); Serial.print("(+- "); Serial.print((_max-_min)/2.0); Serial.print(")"); Serial.print(" [mean="); Serial.print(_meanWaterlevel); Serial.print("]");
}else{
Serial.print("\t waiting for distance");
}
Serial.print("\t Flow="); Serial.print(flow,2);
Serial.print("\t Flowsum="); Serial.print(flow_counter_sum);
Serial.println();
*/
}
}
/*
TODO:
- waterlevel nur -1
- waterlevel distance to volume fukntion
- soilmoisture min max calibartion einfügen
*/