OpenMarine

Full Version: esp32/8266 signalk or mqtt?
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Good morning,
i just managed to assembly and make an esp32 with bm388 works with espsens comunicate directly in signalk.
It cost for me a lot of work, and now i'm planning to make a wifi sensor for the water tank. 
As i'm more confortable with mqtt, i's better to use esphome and mqtt and then the integration for signalk via node-red or working with espsens?
I want to use a no contact water sensor, so some calulation is necessary to extract the amount of water.
Some of you have try to make it? 
Some idea or advice?
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.
(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  Blush


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.
I don’t assign the SignalK access point in the code, as SenESP sets up its own Wi-Fi access point, which I simply connect to and assign client setting from there. That way, if I ever have to change a router or have other settings, I can just reconnect and change them without having to reprogram the unit.

SensESP starting documentation is here: https://signalk.org/SensESP/
SenESP sytanx, definitions, etc is here: https://signalk.org/SensESP/generated/docs/index.html
Project template is here: https://github.com/SensESP/SensESP-project-template