implement mqtt dynamic value publishing

This commit is contained in:
interfisch 2023-05-10 22:27:59 +02:00
parent 60d75da482
commit 84c1f23389
7 changed files with 248 additions and 26 deletions

View File

@ -2,6 +2,12 @@
#define _EC_H_
#include <Arduino.h>
mqttValueTiming timing_ec_adc;
mqttValueTiming timing_ec_calibadc;
mqttValueTiming timing_ec_adcadjusted;
mqttValueTiming timing_ec_ec;
mqttValueTiming timing_ec_sc;
bool ec_flag_measurement_available=false;
@ -29,7 +35,7 @@ uint16_t ec_calib_array_pos=0;
uint16_t ec_array[EC_ARRAY_SIZE];
uint16_t ec_array_pos=EC_ARRAY_SIZE;
unsigned long last_measurement_ec=0;
#define EC_MEASUREMENT_INTERVAL 30000 //complete filtered measurement every x ms
#define EC_MEASUREMENT_INTERVAL 10*60*1000 //complete filtered measurement every x ms
//One filtered measurement takes EC_READ_INTERVAL*EC_ARRAY_SIZE*4
#define EC_READ_INTERVAL 10 //interval of reading adc value inside a measurement. one reading takes about 9-10ms
@ -73,6 +79,33 @@ float ec_getECfromADC(float adc);
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;
timing_ec_adc.maxtime=60*60*1000;
timing_ec_calibadc.minchange=0.0;
timing_ec_calibadc.maxchange=250;
timing_ec_calibadc.mintime=10*000;
timing_ec_calibadc.maxtime=60*60*1000;
timing_ec_adcadjusted.minchange=0.0;
timing_ec_adcadjusted.maxchange=2.0;
timing_ec_adcadjusted.mintime=10*000;
timing_ec_adcadjusted.maxtime=30*60*1000;
timing_ec_ec.minchange=0.0;
timing_ec_ec.maxchange=50;
timing_ec_ec.mintime=10*000;
timing_ec_ec.maxtime=60*60*1000;
timing_ec_sc.minchange=0.0;
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
@ -86,11 +119,13 @@ void ec_loop(unsigned long loopmillis) {
static unsigned long last_read_ec=0;
switch (ecstate) {
case IDLE:
if (loopmillis>last_measurement_ec+EC_MEASUREMENT_INTERVAL && ecstate==IDLE) { //start measurement if idle
if (loopmillis>last_measurement_ec+EC_MEASUREMENT_INTERVAL || force_ec_measurement) { //start measurement if idle
last_measurement_ec=loopmillis;
force_ec_measurement=false;
ec_startMeasurement();
ec_connectProbe(true);
@ -135,6 +170,7 @@ void ec_loop(unsigned long loopmillis) {
ec_array_pos++;
}
}
}else{ //measurement not running, then take calibration readings
if (loopmillis>last_read_ec+EC_CALIB_READ_INTERVAL) { //take reading into array
@ -148,7 +184,9 @@ void ec_loop(unsigned long loopmillis) {
ec_calib_array_pos++;
ec_calib_array_pos%=EC_CALIB_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);
}
}
}
}
@ -201,7 +239,12 @@ float ec_getECfromADC(float adc) {
_ec=mapf(adc,x0,x1,y0,y1); //linear approximation
}
return _ec;
if (_ec>=0) {
return _ec;
}else{
return 0;
}
}
float ec_calculateEC25(float pEC,float pTemp)

View File

@ -1,6 +1,8 @@
#ifndef _FLOW_H_
#define _FLOW_H_
mqttValueTiming timing_flow;
#define FLOW_PIN 19
uint16_t flow_counter=0; //maximum counts/s measured with Eden 128 Pump was 171
void IRAM_ATTR isr_flow();
@ -15,8 +17,13 @@ uint32_t flow_counter_sum=0;
void flow_setup() {
pinMode(FLOW_PIN, INPUT_PULLUP);
attachInterrupt(FLOW_PIN, isr_flow, CHANGE);
timing_flow.minchange=0.0;
timing_flow.maxchange=0.5;
timing_flow.mintime=1*000;
timing_flow.maxtime=30*60*1000;
pinMode(FLOW_PIN, INPUT_PULLUP);
attachInterrupt(FLOW_PIN, isr_flow, CHANGE);
}
void flow_loop(unsigned long loopmillis) {

View File

@ -7,11 +7,14 @@
#define READINTERVAL_SM 100
mqttValueTiming timing_soilmoisture_sm1;
mqttValueTiming timing_soilmoisture_sm2;
mqttValueTiming timing_soilmoisture_sm3;
//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_low=4555;
float sm1_high=11799;
float sm2_low=3235;
float sm2_high=16050;
@ -43,6 +46,23 @@ uint8_t sm_readchannel=0;
void sm_setup() {
timing_soilmoisture_sm1.minchange=0.0;
timing_soilmoisture_sm1.maxchange=0.05;
timing_soilmoisture_sm1.mintime=2*1000;
timing_soilmoisture_sm1.maxtime=60*60*1000;
timing_soilmoisture_sm2.minchange=0.0;
timing_soilmoisture_sm2.maxchange=0.05;
timing_soilmoisture_sm2.mintime=2*1000;
timing_soilmoisture_sm2.maxtime=60*60*1000;
timing_soilmoisture_sm3.minchange=0.0;
timing_soilmoisture_sm3.maxchange=0.05;
timing_soilmoisture_sm3.mintime=2*1000;
timing_soilmoisture_sm3.maxtime=60*60*1000;
for (uint16_t i=0;i<SM_SIZE;i++) {
sm_mean1array[i]=SM_DISCONNECTED;
sm_mean2array[i]=SM_DISCONNECTED;

View File

@ -2,6 +2,9 @@
#define _TEMPERATURE_H_
mqttValueTiming timing_temperature_reservoir;
mqttValueTiming timing_temperature_air;
#include <OneWire.h>
#include <DallasTemperature.h>
@ -38,6 +41,15 @@ float tempCmean_air=DEVICE_DISCONNECTED_C;
void temperature_setup() {
timing_temperature_reservoir.minchange=0.0;
timing_temperature_reservoir.maxchange=0.5;
timing_temperature_reservoir.mintime=2*1000;
timing_temperature_reservoir.maxtime=60*60*1000;
timing_temperature_air.minchange=0.0;
timing_temperature_air.maxchange=0.5;
timing_temperature_air.mintime=2*1000;
timing_temperature_air.maxtime=60*60*1000;
//initialize mean array
for (uint16_t i=0;i<TEMPMEAN_SIZE;i++) {

View File

@ -6,38 +6,116 @@
#include <MQTT.h>
#include "wifi_settings.h"
#include "helpfunctions.h"
struct mqttValueTiming{
float minchange;
float maxchange;
unsigned long mintime;
unsigned long maxtime;
float lastvalue=0;
unsigned long lasttime=0;
};
WiFiClient net;
MQTTClient client;
bool sendallnext_flag=false;
bool enableTiming=true;
bool force_ec_measurement=false;
void publishValueTimed(String topic,float value,uint8_t decimals,mqttValueTiming &mqttvt,unsigned long loopmillis);
void publishValue(String topic,float value,uint8_t decimals);
void connect() {
Serial.print("checking wifi...");
while (WiFi.status() != WL_CONNECTED) {
uint8_t timeout=0;
while (WiFi.status() != WL_CONNECTED && timeout<10) {
timeout++;
Serial.print(".");
delay(1000);
delay(500);
}
Serial.print("\nconnecting...");
while (!client.connect(client_id, "public", "public")) {
Serial.print(".");
delay(1000);
if (WiFi.status() == WL_CONNECTED)
{
Serial.print("\nconnecting...");
timeout=0;
#define CONNECT_TIMEOUT 5
while (!client.connect(client_id, "public", "public") && timeout<CONNECT_TIMEOUT) {
Serial.print(".");
delay(1000);
timeout++;
}
if (timeout>=CONNECT_TIMEOUT) {
Serial.println("\nconnection failed!");
}else{
Serial.println("\nconnected!");
client.subscribe((String)client_id+"/sendall");
client.subscribe((String)client_id+"/ec/trigger");
// client.unsubscribe("/hello");
}
}
Serial.println("\nconnected!");
client.subscribe("/hello");
// client.unsubscribe("/hello");
}
void messageReceived(String &topic, String &payload) {
Serial.println("incoming: " + topic + " - " + payload);
if (topic==((String)client_id+"/sendall") && payload=="true") {
sendallnext_flag=true;
Serial.println("Send all values next time");
}
if (topic==((String)client_id+"/ec/trigger") && payload=="true") {
force_ec_measurement=true;
Serial.println("Forced EC Measurement");
}
}
// Note: Do not use the client in the callback to publish, subscribe or
// unsubscribe as it may cause deadlocks when other things arrive while
// sending and receiving acknowledgments. Instead, change a global variable,
// or push to a queue and handle it in the loop after calling `client.loop()`.
bool mqtt_loop(unsigned long loopmillis) {
static unsigned long last_client_loop=0;
#define CLIENT_LOOP_INTERVAL 10 //ms. fixes some wifi issues. from example https://registry.platformio.org/libraries/256dpi/MQTT/examples/ESP32DevelopmentBoard/ESP32DevelopmentBoard.ino
if (loopmillis >= last_client_loop+CLIENT_LOOP_INTERVAL) {
last_client_loop=loopmillis;
client.loop();
static unsigned long last_connection_try=0;
#define RETRY_CONNECTION 60000
if (!client.connected()) {
if (loopmillis-last_connection_try>RETRY_CONNECTION) {
connect();
}
}else{
return true;
}
}
return false;
}
void 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);
valuediff=constrain(valuediff,mqttvt.minchange,mqttvt.maxchange);
unsigned long sendafter=mapf(valuediff,mqttvt.minchange,mqttvt.maxchange,mqttvt.maxtime,mqttvt.mintime); //map valuediff to time when to send
/*Serial.println();
Serial.print("timediff="); Serial.print(timediff);
Serial.print(" valuediff="); Serial.print(valuediff);
Serial.print(" sendafter="); Serial.println(sendafter);*/
if (timediff>=sendafter || !enableTiming) {
mqttvt.lasttime=loopmillis;
mqttvt.lastvalue=value;
publishValue(topic,value,decimals);
}
}
void publishValue(String topic,float value,uint8_t decimals) {
char buffer[16];
dtostrf(value,1,decimals,buffer);
client.publish((String)client_id+"/"+topic, buffer);
Serial.print("Publish Topic="); Serial.print((String)client_id+"/"+topic); Serial.print(" Message="); Serial.println(buffer);
}
#endif

View File

@ -1,6 +1,6 @@
const char ssid[] = "ssid";
const char pass[] = "pass";
const char ssid[] = "";
const char pass[] = "";
const char mqtt_host[] = "10.0.0.1";
const char client_id[] = "hydroponic";

View File

@ -1,11 +1,13 @@
#include <Arduino.h>
#include "wifi_functions.h"
bool debug=true; //print Serial information
#include "helpfunctions.h"
#include "ADS1X15.h"
@ -15,6 +17,9 @@ ADS1115 ADS(0x48);
// ######## Temperature
#include "temperature.h"
// ######## EC
#include "ec.h"
@ -31,6 +36,8 @@ ADS1115 ADS(0x48);
#include "soilmoisture.h"
unsigned long last_check=0;
@ -72,6 +79,9 @@ void setup() {
Serial.println("Setup Flow");
flow_setup();
Serial.println("Setup Soilmoisture");
sm_setup();
Serial.println("Finished Setup");
delay(200);
@ -96,6 +106,8 @@ void setup() {
void loop() {
unsigned long loopmillis=millis();
enableTiming=true; //reactivate
ec_loop(loopmillis);
@ -210,9 +222,59 @@ void loop() {
}*/
Serial.println();
}
if (mqtt_loop(loopmillis)) {
if (sendallnext_flag) {
sendallnext_flag=false;
enableTiming=false;
}
if (tempCmean_reservoir!=DEVICE_DISCONNECTED_C) {
publishValueTimed("temperature/reservoir",tempCmean_reservoir,2,timing_temperature_reservoir,loopmillis);
}
if (tempCmean_air!=DEVICE_DISCONNECTED_C) {
publishValueTimed("temperature/air",tempCmean_air,2,timing_temperature_air,loopmillis);
}
if (sm_mean1!=SM_DISCONNECTED) {
publishValueTimed("soilmoisture/sm1",sm_mean1,3,timing_soilmoisture_sm1,loopmillis);
}
if (sm_mean2!=SM_DISCONNECTED) {
publishValueTimed("soilmoisture/sm2",sm_mean2,3,timing_soilmoisture_sm2,loopmillis);
}
if (sm_mean3!=SM_DISCONNECTED) {
publishValueTimed("soilmoisture/sm3",sm_mean3,3,timing_soilmoisture_sm3,loopmillis);
}
publishValueTimed("flow/flow",flow,2,timing_flow,loopmillis);
if (ec_adc!=0) {
publishValueTimed("ec/adc",ec_adc,0,timing_ec_adc,loopmillis);
}
if (ec_calib_adc!=0) {
publishValueTimed("ec/eccalibadc",ec_calib_adc,0,timing_ec_calibadc,loopmillis);
}
if (ec_adc_adjusted!=0) {
publishValueTimed("ec/adcadjusted",ec_adc_adjusted,0,timing_ec_adcadjusted,loopmillis);
}
if (ec!=EC_UNAVAILABLE){
publishValueTimed("ec/ec",ec,0,timing_ec_ec,loopmillis);
publishValueTimed("ec/sc",ec25,0,timing_ec_sc,loopmillis);
}
}
}