My first post to the forum and apologies if this is the wrong board to post this. I have been using the Megunolink exponential filter on an ultrasonic tank level application. I am using three filters, one for distance, one for temperature corrected distance and one for level. The filters work well but I want to initialise them with the last recorded value rather than a constant so that when the board restarts for any reason, they take the initial value in the constructor from the last recorded value. I am using Blynk as the interface app and the distance and level values are written to and stored on the Blynk server.
As part of the sketch initialisation, I call these stored values, assign them to start variables and then initialise the filters with these variables. When the sketch starts, however, the filters are initialised with zero. I have written one of the start variables (the last recorded level filter value) to the serial monitor and I can verify that the correct last recorded value is being pulled from the server. I have attached the sketch and would certainly appreciate any thoughts.
Code: Select all
/* Comment this out to disable prints and save space */
#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <Filter.h>
#include <TimeLib.h>
#include <ArduinoOTA.h>
#include <DNSServer.h> //Local DNS Server used for redirecting all requests to the configuration portal
#include <ESP8266WebServer.h> //Local WebServer used to serve the configuration portal
#include <ESP8266mDNS.h>
#include <ESP8266HTTPUpdateServer.h>
#include <WidgetRTC.h>
#include <OneWire.h>
#include <DallasTemperature.h>
// Define pins and assign variables
#define oneWireBus 14 //Define temperature probe connected to pin 12 (D6)
#define trigPin 12 // Arduino pin tied to trigger pin on the ultrasonic sensor 13 D7).
#define echoPin 13 // Arduino pin tied to echo pin on the ultrasonic sensor 14 (D5).
//Define variables
int MAX_DISTANCE = 300; // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.
int TANK_FULL_HT = 202; // Height of liquid at 100% full in cm
int TANK_EMPTY_HT = 10; //Height of unusable liquid at base of tank in cm
int SENSOR_DIST = 26; //Distance from the sensor to the liquid at 100% full in cm
int TANK_DIA = 1003; //Tank diameter in cm
int TANK_FULL_VOL = 161892; // Tank volume at 100% in litres
long duration; // For Ping sensor
float distance; //distance calculated from ultrasonic sensor
float distanceCorrected; //Temperature corrected distance
float levelFilt; //current value of level from exponential filter
float temp;
float speedSound;
float LEVEL;
float levelStart; //variable to hold the last recorded level value (from Blynk Server). Used to initialise exponential filter
float distStart; //variable to hold the last recorded distance value (from Blynk Server). Used to initialise exponential filter
float distCorrStart; //variable to hold the last recorded temperature corrected distance value (from Blynk Server). Used to initialise exponential filter
// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "xxxxxxxxxxxxxxxxxxxxxxxxxxx"; //code for development board
// Your WiFi credentials.
// Set password to "" for open networks.
const char* host = "tank_level";
char ssid[] = "xxxxxxxx";
char pass[] = "xxxxxxxxxx";
// Mac address should be different for each device in your LAN
//byte arduino_mac[] = { 0x39, 0x7D, 0x11, 0xB4, 0x40, 0x7A };
IPAddress arduino_ip ( 192, 168, 1, 117);
IPAddress dns_ip ( 8, 8, 8, 8);
IPAddress gateway_ip ( 192, 168, 1, 101);
IPAddress subnet_mask(255, 255, 255, 0);
ESP8266WebServer httpServer(80);
ESP8266HTTPUpdateServer httpUpdater;
//Define onewire instance and pass to Dallas Temperatuure
OneWire oneWire(oneWireBus);
DallasTemperature sensors(&oneWire);
//Widget real time clock
WidgetRTC rtc;
BLYNK_CONNECTED() {
Blynk.syncVirtual(V1, V3, V6); //Sync the start values with the Blynk server value. V1 is corrected distance, V3 is distance, V6 is calculated level
rtc.begin();
}
BLYNK_WRITE(V1) { //calls the value stored on the Blynk Server
distCorrStart = param.asFloat(); //last recorded value of corrected distance
}
BLYNK_WRITE(V3) { //calls the value stored on the Blynk Server
distStart = param.asFloat(); //last recorded value of distance
}
BLYNK_WRITE(V6) { //calls the value stored on the Blynk Server
levelStart = param.asFloat(); //last recorded value of level
Serial.print("Level start ="); //check serial monitor to see if server value being called
Serial.println(levelStart);
}
// Define exponential filters for distance and tank level
ExponentialFilter<float> distFilter(5, distStart); //initialise distance filter with last recorded value
ExponentialFilter<float> distFilterCorrected(5, distCorrStart); //initialise corrected distance filter with last recorded value
ExponentialFilter<float> lvlFilter(5, levelStart); //initialise level filter with last recorded value
BlynkTimer timer;
void setup()
{
// Debug console
Serial.begin(115200);
// Define pin modes for the trigger and echo pins of ultrasonic sensor
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
// Hostname defaults to esp8266-[ChipID]
ArduinoOTA.setHostname("TankLevel");
WiFi.config(arduino_ip, dns_ip, gateway_ip, subnet_mask);
WiFi.begin(ssid, pass);
if (WiFi.status() != WL_CONNECTED) {
WiFi.begin(ssid, pass);
}
while (Blynk.connect() == false) //wait for Blynk to connect before proceeding
{
Blynk.config(auth);
}
MDNS.begin(host);
sensors.begin();
httpUpdater.setup(&httpServer);
httpServer.begin();
MDNS.addService("http", "tcp", 80);
Serial.printf("HTTPUpdateServer ready! Open http://%s.local/update in your browser\n", host);
ArduinoOTA.begin();
Serial.println("Ready");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
// Setup a Blynk timer function to be called every two seconds
timer.setInterval(2000L, myTimerEvent);
}
// This function calculates and sends tank level to Blynk every 5 seconds
void myTimerEvent()
{
// Send pulses to ultrasonic sensor
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(20);
digitalWrite(trigPin, LOW);
// End Pulse & Calculate distance
duration = pulseIn(echoPin, HIGH);
distance = (duration / (2)) / 29.1; //calculate distance from time measurement from ultrasonic sensor
distFilter.Filter(distance); //apply filter to distance measurement
// Get temperature to enable distance correction
sensors.requestTemperatures();
temp = sensors.getTempCByIndex(0);
//Calculate corrected distance based on temperature correction
speedSound = 331.3 + (0.606 * temp);
distanceCorrected = (duration / (20000.0)) * speedSound;
distFilterCorrected.Filter(distanceCorrected); //apply filter to corrected distance measurement
LEVEL = (((TANK_FULL_HT - TANK_EMPTY_HT) - (distance - SENSOR_DIST)) * 100) / (TANK_FULL_HT - TANK_EMPTY_HT);
lvlFilter.Filter(LEVEL); //apply filter to level calculation
levelFilt = lvlFilter.Current();
if (LEVEL > 100) LEVEL = 100;
else if (LEVEL < 0) LEVEL = 0;
// Send data to Blynk
Blynk.virtualWrite(V3, distFilter.Current()); //sends current filter value of distance to Blynk server
Blynk.virtualWrite(V1, distFilterCorrected.Current()); //sends current filter value of corrected distance to Blynk server
Blynk.virtualWrite(V5, lvlFilter.Current()); //sends current filter value of level to Blynk server
Blynk.virtualWrite(V0, distance); //sends current raw value of distance to Blynk server
Blynk.virtualWrite(V27, LEVEL); //sends current raw value of level to Blynk server
}
void loop()
{
Blynk.run();
timer.run(); // Initiates BlynkTimer
ArduinoOTA.handle();
httpServer.handleClient();
}