SignalK / SensESP

Universal Signal K sensor framework for the ESP32 platform
https://signalk.org/SensESP/
Apache License 2.0
146 stars 80 forks source link

fuel_level_sensor_example.cpp - MovingAverage not working #633

Closed Paluty closed 1 year ago

Paluty commented 1 year ago

Hi, I installed SensESP on an ESP32 and got the first sensors working and showing on the SignalK Server. Thank you so much to everyone involved in this. Amazing work!

I want to add an analog tank gauge. This is the code I use:

/// Tank Sensor on Pin 34
  // If you're using an ESP32, you must specify the pin number: AnalogInput(14);
  // You can also specify any read interval: AnalogInput(A0, 500);
   AnalogInput* input = new AnalogInput(34, 500);

  // scale factor. this will depend on your circuit:
  // 1. Take the maximum analog input value (i.e. value when sensor is at the
  // high end)
  // 2. Divide 1 by max value. In my case: 1 / 870 = 0.001149425
  //float scale = 0.001149425F;
    float scale = 0.00209205021F; //1/478
  // Takes a moving average for every 10 values, with scale factor
  //MovingAverage* avg = new MovingAverage(10, scale);
    MovingAverage* avg = new MovingAverage(2, scale); 
  // Connect avg. value to a SK path
  // See this link for available tank paths:
  // https://signalk.org/specification/1.4.0/doc/vesselsBranch.html#vesselsregexptanks
  input->connect_to(avg)->connect_to(
      new SKOutputFloat("tanks.fuel.0.currentLevel"));

The code from the example (fuel_level_sensor_example.cpp) included in this repository has not been deleted but commented out. For better overview the same code without comments:

   AnalogInput* input = new AnalogInput(34, 500);
    float scale = 0.00209205021F; //1/478
    MovingAverage* avg = new MovingAverage(2, scale); 
    input->connect_to(avg)->connect_to(
      new SKOutputFloat("tanks.fuel.0.currentLevel"));

Readings in SignalK are 473 for an empty tank and 474 for a full tank.

If I change the last three lines to input->connect_to( new SKOutputFloat("tanks.fuel.0.currentLevel")); I get useful readings in SignalK being 44,1 for an empty tank and 478 for a full tank. Based on this I figured that I have to correct it with factor 0.00209205021F. However, the "scale" multiplyer does not seem to be effective and the "MovingAverage" seems to mess up the result somehow. No changes wheter I choose moving average from 10 or 2 readings. I changed it to 2 to have more responsive data.

The required libraries included being: `#include "sensesp_app_builder.h"

include "sensesp/sensors/analog_input.h"

include "sensesp/signalk/signalk_output.h"

include "sensesp/transforms/moving_average.h"`

Any help or hints much appreciated.

Thanks Paluty

Paluty commented 1 year ago

MovingAverage still not working but got my signalk readings corrected by using this code:

uint8_t FuelPin = 34; AnalogInput* input = new AnalogInput(FuelPin, 5000); const float gaugefactor = 0.00209205021; const float offset = 0; input->connect_to( new Linear(gaugefactor, offset))->connect_to( new SKOutputFloat("tanks.fuel.0.currentLevel"));

Resolution seems to be rather low but that might be a hardware issue.

Paluty commented 1 year ago

Hi again,

wrong forum here I realised in the meantime. However, wanted to document how I solved this issue before closing:

I had the issue that the moving average messed up the data and realized later that for some reason the analog readings do not represent the low resistor part of the tank gauge. This is how I fixed both issued. Maybe it helps another noob like me.

`#include "sensesp/transforms/curveinterpolator.h"

// Curve Interpolater for fuel tank gauge - PIN 34 class TankInterpreter : public CurveInterpolator { public: TankInterpreter(String config_path = "") : CurveInterpolator(NULL, config_path) { // Populate a lookup table to translate readout GPIO34 to tank status clear_samples(); // addSample(CurveInterpolator::Sample(GPIO34, tank status)); add_sample(CurveInterpolator::Sample(150, 0)); add_sample(CurveInterpolator::Sample(190, 0.125)); add_sample(CurveInterpolator::Sample(235, 0.25)); add_sample(CurveInterpolator::Sample(275, 0.375)); add_sample(CurveInterpolator::Sample(335, 0.5)); add_sample(CurveInterpolator::Sample(365, 0.625)); add_sample(CurveInterpolator::Sample(415, 0.75)); add_sample(CurveInterpolator::Sample(440, 0.875)); add_sample(CurveInterpolator::Sample(490, 1)); add_sample(CurveInterpolator::Sample(510, 1.1)); } }; and within the setup section /// Tank Sensor on Pin 34 corrected - working - printing ration 0 to 1.0, low tank levels not visible uint8_t FuelPin = 34; AnalogInput* input = new AnalogInput(FuelPin, 5000); input->connect_to(new MovingAverage(10, 1)) ->connect_to(new TankInterpreter("/Fuel Tank/curve")) ->connect_to(new SKOutputFloat("tanks.fuel.0.currentLevel" , "/Fuel Tank/sk_path"));`

This solves my issues to a level with which I am happy to go live on board.