First ESPHome Custom Sensor ZMPT101B Voltage Sensor

Hi,

Newbie question here, hope you can help. Have fully up to date HASS deployment on RPi4.

Trying to follow this guide: Custom Sensor Component — ESPHome
But get a configuration error:
Platform error sensor.custom - Integration ‘custom’ not found.”

It seems to not be liking the line -platform: custom in configuration.yaml. If I change this custom to esphome then it doesn’t show an error but of course doesn’t work.

Has this syntax perhaps changed and the guide not updated?

Thanks in advance
Cameron.

I implemented a couple of custom sensors a while back (granted, that was quite a few ESPHome versions ago), but the guide worked flawlessly.

Could you share your YAML and C++ code for the component? I suppose it’d be easier to figure this out when looking at the code.

Sure, here you go, not much in here so far so I wonder if there is a component that hasn’t installed properly. What processes platform: custom ? (THough it was an image I burnt to flash so can’t see how one module would be faulty)

# Configure a default setup of Home Assistant (frontend, api, etc)
default_config:
# Text to speech
tts:
  - platform: google_translate
group: !include groups.yaml
automation: !include automations.yaml
script: !include scripts.yaml
scene: !include scenes.yaml

#esphome - added by Cameron
esphome:
  includes:
    - zmpt101b_custom_sensor.h

sensor:
  - platform: systemmonitor
    resources:
      - type: disk_use_percent
      - type: disk_use
      - type: disk_free
      - type: memory_use_percent
      - type: memory_use
      - type: memory_free
      - type: processor_use
      - type: processor_temperature
      - type: last_boot
      - type: throughput_network_in
        arg: eth0
      - type: throughput_network_out
        arg: eth0
      - type: swap_use_percent
      - type: load_1m
      - type: load_5m
      - type: load_15m
 
  - platform: custom
    lambda: |-
      auto my_sensor = new ZMPT101B();
      App.register_component(my_sensor);
      return {my_sensor};
    sensors:
      name: "My custom Sensor"

# Unflashed SONOFF devices

sonoff:
  username: ***********
  password: **********
  reload: always

# Binary Sensor for workday
binary_sensor:
  - platform: workday
    country: ZA
    workdays: [mon, tue, wed, thu, fri]
    excludes: [sat, sun, holiday]

and for now, the basic c++ construct, I’ll build it out once the base integration works

class ZMPT101B : public PollingComponent, public Sensor {
 public:
  // constructor
  ZMPTB101B() : PollingComponent(15000) {}

  float get_setup_priority() const override { return esphome::setup_priority::HARDWARE; }

  void setup() override {
    // This will be called by App.setup()
  }
  void update() override {
	// This will be called every "update_interval" milliseconds.
    publish_state(42.0);
  }
};

I think problem is not in the custom sensor itself. Your configuration file contains entries which seem to be pertaining to Home Assistant rather than ESPHome framework: default_config, tts, systemmonitor senros, sonoff, workday platform for binary sensor. None of that exists in the context of an ESPHome device, so I’m guessing that’s simply your HASS config file, is it?

ESPHome is used for generating a custom firmware for ESP32 or ESP8266 devices. While it shares much of Home Assistant’s philosophy and structure of configuration files, it serves a completely different purpose. If you simply add ESPHome custom sensor to your HASS config, it just won’t work. HASS doesn’t have a custom platform for sensors.

If you’re trying to hook up the ZMPT101B senor to the RPi4 itself, you’ll need some additional components. The sensor doesn’t have any digital communication interfaces, simply outputs voltage in range 0-5V. RPi4 doesn’t have any analog-to-digital converters on board, so you’ll need to add one and use one of native Home Assistant integrations to control it.

There’s a nice article on Adafruit on how to hook up an ADC to RPi.

In case you’re still interested in building your own ESP-based device using ZMPT101B, here’s how to use it with ESPHome: if you strip the parts of configuration file which are not valid for ESPHome, leaving something like this:

#esphome - added by Cameron
esphome:
  platform: ESP8266
  board: esp07
  name: custom
  includes:
    - zmpt101b_custom_sensor.h

sensor:
  - platform: custom
    lambda: |-
      auto my_sensor = new ZMPT101B();
      App.register_component(my_sensor);
      return {my_sensor};
    sensors:
      name: "My custom Sensor"

and add `#include “esphome.h” directive to the .h file, firmware compiles correctly (I just picked a random platform, board, and name; likely this will not match your project).

If you want integration with Home Assistant, you’ll need to set up API component.

# Example configuration entry
api:
  password: !secret api_password

There are additional integrations available for grabbing data from Home Assistant:

You’ll also need to configure WiFi component so the device you’re building can actually connect to the network.

ESPHome also comes with support for a range of ADC devices.

1 Like

Thanks. I understand my problem now I think. I assummed all config goes in config.yaml but you are saying that this config should go in the yaml file for the individual ESPHome device. (I have the ZMPT101B connected to a D1 mini that I’ve flashed with ESPHome).

Also had to move the custom file into the esphome sub-directory of the config directory.

Working perfectly now. Thank You.

Hi, I am looking to implement the same. Please could you share your ESP Config and your ZMPT101B file! Would be a great help as i am struggling with errors! Thanks in advanced!

Sure. Will do so tonight.

@Stringyb92 , here you go. You might be able to put together better formulas than I have in the custom module - there are others out there.

  1. snippet from my device config
esphome:
  name: mainsvoltagemeter
  includes:
    - zmpt101b_custom_sensor.h

sensor:
  - platform: custom
    lambda: |-
      auto my_sensor = new ZMPT101BSensor();
      App.register_component(my_sensor);
      return {my_sensor};
    sensors:
      name: "Mains Voltage"
      unit_of_measurement: V
      accuracy_decimals: 0
      state_class: "measurement"
  1. The custom module: zmpt101b_custom_sensor.h - this goes in the esphome folder
#include "esphome.h"
#include <Arduino.h>

#define VMAX 250
#define FREQUENCY 50
#define CALIBRATE_READ 130
#define CALIBRATE_ACTUAL 225
#define ZERO_VAC 788

class ZMPT101BSensor : public PollingComponent, public Sensor {
 public:
  // constructor
  ZMPT101BSensor() : PollingComponent(1000) {}

  float get_setup_priority() const override { return esphome::setup_priority::HARDWARE; }

  void setup() override {
    // This will be called by App.setup()
  }

  void update() override {
  // This will be called every "update_interval" milliseconds.

    uint32_t period = 1000000 / FREQUENCY;
    uint32_t t_start = micros();
    uint32_t Vsum = 0, measurements_count = 0;
    int32_t Vnow;

    while (micros() - t_start < period) {
      Vnow = analogRead(A0) - ZERO_VAC;
      Vsum += Vnow*Vnow;
      measurements_count++;
    }

    float Vrms = sqrt(Vsum / measurements_count) / CALIBRATE_READ * CALIBRATE_ACTUAL;
    publish_state(int(Vrms));

  }
};

2 Likes

I forgot to let you know, it worked perfectly! Many thanks!!

Hi I tried this codes.
giving me error’s while comiling

/config/esphome/rawpowersensor.yaml: In lambda function:
/config/esphome/rawpowersensor.yaml:32:28: error: expected type-specifier before ‘ZMPT101B’
32 | auto my_sensor = new ZMPT101B();
| ^~~~~~~~
/config/esphome/rawpowersensor.yaml:34:24: error: could not convert ‘{my_sensor}’ from ‘’ to ‘std::vectoresphome::sensor::Sensor*
34 | return {my_sensor};
| ^
| |
|
Compiling /data/custom/.pioenvs/custom/lib310/ESPAsyncTCP-esphome/tcp_axtls.c.o
Compiling /data/custom/.pioenvs/custom/libaf0/Hash/Hash.cpp.o
*** [/data/custom/.pioenvs/custom/src/main.cpp.o] Error 1
Compiling /data/custom/.pioenvs/custom/lib67b/ESP8266WiFi/BearSSLHelpers.cpp.o
========================= [FAILED] Took 23.40 seconds =========================

Please share your config file for the sensor - I would guess you are missing the “includes:” statement

Hii all;
Because I am facing the same issue with this DFRobot ozone sensor (SEN0321).Please share me some information to remove these errors
I will be waiting for your message

Please share your sensor config file and screenshot confirming you have put the zmpt101b.h file in the esphome directory

thanks for your reply camasway .
Actually ,i am facing issue with this sensor DFRobot_OzoneSensor .Unable to execute the custom code .
could you please help me .
i await for your response .

Hi, Please follow the instructions for logging posts.

If this is a different issue / not related to ZMPT101B please create a new post.
You need to include the error messages and your configurations in the post or no-one will be able to assist.

Hello. What do the strings mean?

#define CALIBRATE_READ 130
#define CALIBRATE_ACTUAL 225
#define ZERO_VAC 788

It’s for calibrating the sensor.

Zerovac is for the sensor reading when no power is applied.

Then a pair of readings for a known voltage.

In my case, the sensor reads 788 when no voltage is present, and 130 when the voltage is 225V

If I remember correctly…

Many thanks!

This looks like you’re re-implementing the ct_clamp component. You shouldn’t need any custom components to make this work.

@camasway Thanks for the example, In the above code, where to mention PIN? Do you have a wiring diagram? In ZMPT101B, I have VCC, OUT, GND, and GND.