(2022-07-10, 10:18 PM)SCarns Wrote: I made one for my holding tank using a capacitive sensor (used the MODA tank sensor from https://tankedge.com/accessories.html). I used SensESP, a voltage reducer (for reading the sensor), a 12volt to 5 volt buck converter (to power the board off of 12 volt) and a lot of trial and error to get it working. It lives in a water-proof case under my mattress next to the tank and connects to signalk via wifi.
Just upgraded it to the new SensESP, which took a few minutes, as I had to update the programming a bit, but it was even easier and cleaner than the first time. Once I figure out the concepts and stopped trying to "Over Program" the code, it all came together.
There is some calculations needed, but those are outside of SensESP. I add an extra SKPath so I can monitor the ADC read values (for empty & full), and then do the calculation for needed Mulitplier and Offset, which I can enter in the web set up for SensESP. I also use a long period for MovingAverage to help smooth out reading fluctuations. It's all done in a couple lines of code. Here's what I have:
//
// This application demonstrates core SensESP concepts in a very
// concise manner. You can build and upload the application as is
// and observe the value changes on the serial port monitor.
//
// You can use this source file as a basis for your own projects.
// Remove the parts that are not relevant to you, and add your own code
// for external hardware libraries.
#include "sensesp/sensors/analog_input.h"
#include "sensesp/sensors/sensor.h"
#include "sensesp/signalk/signalk_output.h"
#include <sensesp/transforms/linear.h>
#include <sensesp/transforms/moving_average.h>
#include "sensesp_app_builder.h"
using namespace sensesp;
reactesp::ReactESP app;
// The setup function performs one-time application initialization.
void setup() {
#ifndef SERIAL_DEBUG_DISABLED
SetupSerialDebug(115200);
#endif
// Construct the global SensESPApp() object
SensESPAppBuilder builder;
sensesp_app = (&builder)
// Set a custom hostname for the app.
->set_hostname("New-SensESP")
->set_wifi_manager_password("SensESP32")
// Optionally, hard-code the WiFi and Signal K server
// settings. This is normally not needed.
//->set_wifi("My WiFi SSID", "my_wifi_password")
//->set_sk_server("192.168.10.3", 80)
->get_app();
const char* sk_path0 = "tanks.blackWater.0.currentLevel";
const char* sk_read0 = "tanks.blackWater.0.reading";
const char* analog_in_config_path = "/blackWater/analogInput";
const char* linear_config_path = "/blackWater/linear";
const char* level_avg_samples = "/blackWater/average";
uint8_t pin0 = 35; // read pin for sensor "0"
uint read_delay = 1000; // read frequency
const float multiplier = 0.00862517325816782; // 100% divided by total range (high-low read)
const float offset = -0.380027721306852; // Offset to compensate for low-end
float scale = 1.0;
// Create a new Analog Input Sensor that reads an analog input pin0
// and sends it to SignalK.
auto* blackwater_read = new AnalogInput(
pin0, read_delay, analog_in_config_path);
blackwater_read->connect_to(new SKOutputFloat(sk_read0))
->connect_to(new Linear(multiplier, offset, linear_config_path)) // adjust for vacuum reading
->connect_to(new MovingAverage(120,scale, level_avg_samples))
->connect_to(new SKOutputFloat(
sk_path0, // Signal K path
new SKMetadata("ratio", // Define output units
"Blackwater Tank Volume") // Value description
))
->attach([blackwater_read]() {
debugD("Analog input value: %f", blackwater_read->get());
});
// Start networking, SK server connections and other SensESP internals
sensesp_app->start();
}
void loop() { app.tick(); }
_________
Works great.
I'm moving on to a vacuum switch on my fuel filters next with the idea I can monitor fuel suction and get an alarm when it's time to change filters or if there's water in the bowl.
Thank you for your answer. I appraciate it.
Some questions:
How dou you extract the parameters
const float multiplier = 0.00862517325816782; // 100% divided by total range (high-low read)
const float offset = -0.380027721306852; // Offset to compensate for low-end
float scale = 1.0;
?
what do you mean with "then do the calculation for needed Mulitplier and Offset, which I can enter in the web set up for SensESP": i can't find in the web interface the possibility to insert this parameters
Here my code if someone can find it useful...
Quote:// Signal K application template file.
//
// This application demonstrates core SensESP concepts in a very
// concise manner. You can build and upload the application as is
// and observe the value changes on the serial port monitor.
//
// You can use this source file as a basis for your own projects.
// Remove the parts that are not relevant to you, and add your own code
// for external hardware libraries.
// Boilerplate #includes:
#include "sensesp_app_builder.h"
#include "sensesp/signalk/signalk_output.h"
// Sensor-specific #includes:
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include "Adafruit_BMP3XX.h"
#define BMP_SCK 18
#define BMP_MISO 19
#define BMP_MOSI 23
#define BMP_CS 5
#define SEALEVELPRESSURE_HPA (1013.25)
// For RepeatSensor:
#include "sensesp/sensors/sensor.h"
using namespace sensesp;
// SensESP builds upon the ReactESP framework. Every ReactESP application
// must instantiate the "app" object.
reactesp::ReactESP app;
// (Specific to the BMP280, and I2C. Replace this with similar code to create an instance
// of whatever sensor you may be using in your project.)
// Create an instance of the sensor using its I2C interface.
Adafruit_BMP3XX bmp;
// (Replace this with whatever function you need to read whatever value you want
// to read from any other sensor you're using in your project.)
// Define the function that will be called every time we want
// an updated temperature value from the sensor. The sensor reads degrees
// Celsius, but all temps in Signal K are in Kelvin, so add 273.15.
float read_temp_callback() { return (bmp.temperature + 273.15); }
float read_press_callback() { return (bmp.pressure); }
// The setup function performs one-time application initialization
void setup() {
// Some initialization boilerplate when in debug mode
#ifndef SERIAL_DEBUG_DISABLED
SetupSerialDebug(115200);
#endif
// Create the global SensESPApp() object
SensESPAppBuilder builder;
sensesp_app = builder.set_hostname("Pressione")
->set_sk_server("10.10.10.1", 3000)
->set_wifi("*****", "******")
->get_app();
// (Do whatever is required to "start" your project's sensor here)
// Initialize the BMP280 using the default address
bmp.begin_I2C();
bmp.setTemperatureOversampling(BMP3_OVERSAMPLING_8X);
bmp.setPressureOversampling(BMP3_OVERSAMPLING_4X);
bmp.setIIRFilterCoeff(BMP3_IIR_FILTER_COEFF_3);
bmp.setOutputDataRate(BMP3_ODR_50_HZ);
// Read the sensor every 2 seconds
unsigned int read_interval = 2000;
// Create a RepeatSensor with float output that reads the temperature
// using the function defined above.
auto* air_press =
new RepeatSensor<float>(read_interval, read_press_callback);
// Set the Signal K Path for the output
const char* sk_path = "environment.outside.pressure";
// Send the temperature to the Signal K server as a Float
air_press->connect_to(new SKOutputFloat(sk_path));
// Start the SensESP application running
sensesp_app->start();
}
// loop simply calls `app.tick()` which will then execute all reactions as needed
void loop() {
bmp.performReading();
app.tick();
}
A question... as you see the sensor should read also the temerature, but i don't understand how to correct make two RepeatSernsor. Can you link some guide?
By the way, As you see, I have to manually set signalk ip adress and port as you see in the code, because espsens didn't find it automatically as it si suppoused should be.