Help with a Custom Sensor

I’m having trouble getting esphome to compile with a custom sensor I’m trying to implement (for an ms5611 baro). The default library esphome uses for that results in erroneous baro readings (prom read issues I think). I previously had the same esp8266+ms5611 sensor working perfectly for several years using a different library (MS5xxx.h). So I am just trying to get esphome to compile with this library instead.

A simplified version of my original .ino code looks like this:

#include <Wire.h>
#include <MS5xxx.h>

MS5xxx sensor(&Wire);

void setup() {
  sensor.connect();
}

void loop() {
  sensor.ReadProm();
  sensor.Readout();
  Serial.print("Pressure [Pa]: ");
  Serial.println(sensor.GetPres());
  delay(500);
}

My attempt to make a custom sensor looks like this:

ms5611trug.h:

#include "esphome.h"
#include "MS5xxx.h"
#include "Wire.h"

class ms5611trug : public PollingComponent, public Sensor {
	public:
		MS5xxx baro(&Wire);

	ms5611trug() : PollingComponent(60000) {}

	void setup() override {
		// This will be called by App.setup()
		Wire.begin(5,4);
		baro.connect();
	}
	void update() override {
		// This will be called by App.loop() 
		baro.ReadProm();
		baro.Readout();                   // Update MS5611 sensor
		float pressure = baro.GetPres()/100.0;
		publish_state(pressure);
	}
};

…and the relevant yaml:

esphome:
  includes:
    - ms5611trug.h
  libraries:
    - "MS5xxx"
	- "Wire"
	
sensor:
- platform: custom
  lambda: |-
    auto barometer = new ms5611trug();
    App.register_component(barometer);
    return {barometer};

  sensors:
    name: "Barometer"
    unit_of_measurement: hPa
    accuracy_decimals: 0

I’m pretty sure my problem is the MS5xxx baro(&Wire);. I’m sure the fix is simple, but I’m fairly wet behind the ears when it comes to the ++ part of C++. :wink:

I appreciate any pointers to get this working, gentle or not.:slight_smile:

Here is the compiler error messages:

src/ms5611trug.h:7:15: error: expected identifier before '&' token
   MS5xxx baro(&Wire);
               ^
src/ms5611trug.h: In member function 'virtual void ms5611trug::setup()':
src/ms5611trug.h:14:7: error: '((ms5611trug*)this)->ms5611trug::baro' does not have class type
   baro.connect();
       ^
src/ms5611trug.h: In member function 'virtual void ms5611trug::update()':
src/ms5611trug.h:18:7: error: '((ms5611trug*)this)->ms5611trug::baro' does not have class type
   baro.ReadProm();
       ^
src/ms5611trug.h:19:7: error: '((ms5611trug*)this)->ms5611trug::baro' does not have class type
   baro.Readout();                   // Update MS5611 sensor
       ^
src/ms5611trug.h:20:24: error: '((ms5611trug*)this)->ms5611trug::baro' does not have class type
   float pressure = baro.GetPres()/100.0;
                        ^
Archiving /data/garage/.pioenvs/garage/lib964/libWire.a
#include "esphome.h"
#include "MS5xxx.h"
#include "Wire.h"

class ms5611trug : public PollingComponent, public Sensor {
    public:
        MS5xxx baro;

    ms5611trug() : PollingComponent(60000) : baro(&Wire) { }

    void setup() override {
        // This will be called by App.setup()
        // Wire.begin(5,4);
        baro.connect();
    }
    void update() override {
        // This will be called by App.loop() 
        baro.ReadProm();
        baro.Readout();                   // Update MS5611 sensor
        float pressure = baro.GetPres()/100.0;
        publish_state(pressure);
    }
};

Thanks Simon, for taking the time to help me on discord. In case it gets buried there, I’m putting this here for reference. Using your above header file, together with the changes to my lambda:

  - platform: custom
    lambda: |-
      auto barometer = new ms5611trug::ms5611trug();
      App.register_component(barometer);
      return {barometer};

    sensors:
      name: "Garage Pressure"
      unit_of_measurement: hPa
      accuracy_decimals: 0

I get these compile errors:

In file included from src/main.cpp:75:0:
src/ms5611trug.h:9:9: error: extra qualification 'ms5611trug::' on member 'ms5611trug' [-fpermissive]
         ms5611trug::ms5611trug() : PollingComponent(60000) : baro(&Wire) { }
         ^
src/ms5611trug.h:11:14: error: extra qualification 'ms5611trug::' on member 'setup' [-fpermissive]
         void ms5611trug::setup() override {
              ^
src/ms5611trug.h:16:14: error: extra qualification 'ms5611trug::' on member 'update' [-fpermissive]
         void ms5611trug::update() override {
              ^
src/ms5611trug.h: In constructor 'ms5611trug::ms5611trug()':
src/ms5611trug.h:9:58: error: no matching function for call to 'MS5xxx::MS5xxx()'
         ms5611trug::ms5611trug() : PollingComponent(60000) : baro(&Wire) { }
                                                          ^
src/ms5611trug.h:9:58: note: candidates are:
In file included from src/ms5611trug.h:2:0,
                 from src/main.cpp:75:
/data/garage/.piolibdeps/garage/MS5xxx_ID470/src/MS5xxx.h:58:5: note: MS5xxx::MS5xxx(TwoWire*)
     MS5xxx(TwoWire *aWire);
     ^
/data/garage/.piolibdeps/garage/MS5xxx_ID470/src/MS5xxx.h:58:5: note:   candidate expects 1 argument, 0 provided
/data/garage/.piolibdeps/garage/MS5xxx_ID470/src/MS5xxx.h:45:7: note: constexpr MS5xxx::MS5xxx(const MS5xxx&)
 class MS5xxx
       ^
/data/garage/.piolibdeps/garage/MS5xxx_ID470/src/MS5xxx.h:45:7: note:   candidate expects 1 argument, 0 provided
/data/garage/.piolibdeps/garage/MS5xxx_ID470/src/MS5xxx.h:45:7: note: constexpr MS5xxx::MS5xxx(MS5xxx&&)
/data/garage/.piolibdeps/garage/MS5xxx_ID470/src/MS5xxx.h:45:7: note:   candidate expects 1 argument, 0 provided
In file included from src/main.cpp:75:0:
src/ms5611trug.h:9:60: error: expected '{' before ':' token
         ms5611trug::ms5611trug() : PollingComponent(60000) : baro(&Wire) { }
                                                            ^
src/main.cpp: In lambda function:
src/main.cpp:455:28: error: expected type-specifier
       auto barometer = new ms5611trug::ms5611trug();
                            ^
src/main.cpp:457:24: error: could not convert '{barometer}' from '<brace-enclosed initializer list>' to 'std::vector<esphome::sensor::Sensor*>'
       return {barometer};
                        ^
src/main.cpp:458:3: warning: control reaches end of non-void function [-Wreturn-type]
   });
   ^
*** [/data/garage/.pioenvs/garage/src/main.cpp.o] Error 1

I also figured I should mention this device also has a bh1750 sensor (same i2c pins as the ms5611). I’m not sure if my usage of Wire.h will cause problems with the bh1750 after I get past this header syntax issue.

That change I was suggesting was just wrong. I’ve updated the header file so it should be correct now. And take the extra ms5611trug:: out of the yaml.

If you have another i2c device on the same bus that you’re using and you want esphome to manage it, that won’t work.

I would suggest finding out why the code in esphome is giving you the wrong values by comparing against the code in the other library.

That last change still doesn’t compile:

In file included from src/main.cpp:75:0:
src/ms5611trug.h: In constructor 'ms5611trug::ms5611trug()':
src/ms5611trug.h:9:46: error: no matching function for call to 'MS5xxx::MS5xxx()'
         ms5611trug() : PollingComponent(60000) : baro(&Wire) { }
                                              ^
src/ms5611trug.h:9:46: note: candidates are:
In file included from src/ms5611trug.h:2:0,
                 from src/main.cpp:75:
/data/garage/.piolibdeps/garage/MS5xxx_ID470/src/MS5xxx.h:58:5: note: MS5xxx::MS5xxx(TwoWire*)
     MS5xxx(TwoWire *aWire);
     ^
/data/garage/.piolibdeps/garage/MS5xxx_ID470/src/MS5xxx.h:58:5: note:   candidate expects 1 argument, 0 provided
/data/garage/.piolibdeps/garage/MS5xxx_ID470/src/MS5xxx.h:45:7: note: constexpr MS5xxx::MS5xxx(const MS5xxx&)
 class MS5xxx
       ^
/data/garage/.piolibdeps/garage/MS5xxx_ID470/src/MS5xxx.h:45:7: note:   candidate expects 1 argument, 0 provided
/data/garage/.piolibdeps/garage/MS5xxx_ID470/src/MS5xxx.h:45:7: note: constexpr MS5xxx::MS5xxx(MS5xxx&&)
/data/garage/.piolibdeps/garage/MS5xxx_ID470/src/MS5xxx.h:45:7: note:   candidate expects 1 argument, 0 provided
In file included from src/main.cpp:75:0:
src/ms5611trug.h:9:48: error: expected '{' before ':' token
         ms5611trug() : PollingComponent(60000) : baro(&Wire) { }
                                                ^
*** [/data/garage/.pioenvs/garage/src/main.cpp.o] Error 1

You may well be right about fixing the built in library being the better hunt vs patching it this way. I’ll see what I can do with that… unfortunately when I glanced at it a few weeks ago (having the same thought of comparing the 2 libs), I got lost pretty quick (I’m not a professional programmer, just a hobbyist). I’ll give it the old college try either way.

More reference… and a link to the github issue:

I compared the esphome ms5611 library that fails to the ms5xxx library that works, and found at least one difference. ms5xxx only delays 3ms after sending reset (inside it’s ‘ReadProm’ function), where as esphome is delaying 100ms after reset (in the ‘setup’ function). Otherwise, both libraries have the same 10ms delay between reading and converting commands; worthy of note the ms5xxx library also has reduced delays for lower resolutions (10ms is the longest, for 4k). I assume esphome also uses 4k (default?.. otherwise the 10ms timeouts might be reduced as well). Also, the nitty gritty coding to create the i2c comms is a bit over my head. Assuming the esphome library is doing that part correctly, the only real difference this newb can see so far is in that delay after reset.

So I’d like to first try with that post reset delay reduced to 3 from 100 (fingers crossed it’s that simple). Unfortunately, when I dig in my esphome/device/src/esphome folder where the ms5611.cpp in question resides, any edits are overwritten upon compiling (the readme mentions using custom components folder for this… sigh more to learn).