Compteur énergie. pulse_meter/pulse_counter ou autre?

Bonjour,

Je suis un ancien utilisateur Domoticz et j’ai enfin décidé de migrer vers HA. Je savais que ça n’allait pas être simple mais je m’y suis lancé.

Après 3 jours de recherches et de temps passé avec notre nouvel ami ChatGPT. Je bloque sur le comptage des kWh généré par mon onduleur et mes PV. J’ai donc décidé de vous solliciter.

Actuellement avec Domoticz, je mesure avec une entrée GPIO de mon Raspberry les pulses de mon compteur ABB OD4165, qui à une sortie S0 (contact sec) et qui envoie 100 pulses/kWh. Ce qui fait 10w par pulse.
Mon compteur « vert »:

Domoticz compte correctement:

Je veux donc utiliser ce même système fiable avec HA. Mon onduleur n’a pas de carte réseau, je ne peux donc pas m’y connecter. La carte réseau coute +/- 350€, je passe mon tour et récupère le signal du compteur ABB.

HA ne gère pas nativement les GPIO de mon raspberry, je me suis dit que j’allais passer par un ESP8266 via le GPIO14 et le GND avec un pull-up. Mon ESP est bien connecté à HA.
Après m’être documenté sur ESPHome Docs — ESPHome je me suis dis que j’allais utiliser un pulse counter ou un pulse meter. Dans mon cas, je pense que le pulse counter est plus adapté que le meter car ils ont stipulé « Si vous souhaitez compter les impulsions d’un simple interrupteur à lames, le moyen le plus simple est d’utiliser les résistances pull-up/pull-down internes. » qui correspond à mon cas.
Je cherche donc à avoir un un simple sensor qui additionne 10w à chaque pulse de mon compteur « vert »
Dans la config de mon ESP8266, j’y ai donc noté ceci:

sensor:
  - platform: pulse_counter
    name: "Production Totale"
    id: sensor_production_totale
    pin:
      number: GPIO14
      inverted: true
      mode:
        input: true
        pullup: true
    unit_of_measurement: 'kWh'
    device_class: energy
    state_class: total_increasing  # Cela indique que c'est un total qui augmente
    filters:
      - multiply: 0.01  # Chaque impulsion représente 0.01 kWh (pour 100 pulses/kWh)` je ne suis pas sur de cette valeur`
      - debounce: 1000ms #afin de simuler manuellement un pulse

C’est ici que je ne comprends pas le fonctionnement de HA. Je simule manuellement des pulses et j’ai l’impression qu’il mesure n’importe comment et les valeurs ne sont pas mises à jour en temps réél. Car lorsque je regarde les log de l’ESP j’obtiens ceci:


Je ne comprends pas pourquoi il calcule le nombre de pulse/min et je voudrais dans un premier temps que production s’incrémente de 10W/pulse.

Svp aidez-moi car je sèche .

Merci d’avance

System Information


version core-2025.3.2
installation_type Home Assistant OS
dev false
hassio true
docker true
user root
virtualenv false
python_version 3.13.2
os_name Linux
os_version 6.6.73-haos
arch x86_64
timezone Europe/Brussels
config_dir /config
Home Assistant Cloud
logged_in false
can_reach_cert_server ok
can_reach_cloud_auth ok
can_reach_cloud ok
Home Assistant Supervisor
host_os Home Assistant OS 14.2
update_channel stable
supervisor_version supervisor-2025.03.2
agent_version 1.6.0
docker_version 27.2.0
disk_total 30.8 GB
disk_used 4.9 GB
healthy true
supported true
host_connectivity true
supervisor_connectivity true
ntp_synchronized true
virtualization oracle
board ova
supervisor_api ok
version_api ok
installed_addons File editor (5.8.0), ESPHome Device Builder (2025.2.2)
Dashboards
dashboards 1
resources 0
views 4
mode storage
Network Configuration
adapters lo (disabled), enp0s3 (enabled, default, auto), docker0 (disabled), hassio (disabled), veth30dfb09 (disabled), veth1680de4 (disabled), vethb386c5a (disabled), veth194152c (disabled), veth656dec6 (disabled), vethe523aa0 (disabled), vethfb4761a (disabled)
ipv4_addresses lo (127.0.0.1/8), enp0s3 (192.168.1.38/24), docker0 (172.30.232.1/23), hassio (172.30.32.1/23), veth30dfb09 (), veth1680de4 (), vethb386c5a (), veth194152c (), veth656dec6 (), vethe523aa0 (), vethfb4761a ()
ipv6_addresses lo (::1/128), enp0s3 (2a02:a03f:adde:ce00:e2f6:9265:209f:170b/64, fe80::f7c7:c271:cadb:7358/64), docker0 (fe80::42:6aff:fec7:ff05/64), hassio (fe80::42:1dff:fec5:4134/64), veth30dfb09 (fe80::344b:bff:fe1c:1bb1/64), veth1680de4 (fe80::343a:14ff:fe57:e318/64), vethb386c5a (fe80::208f:4dff:fec8:1bdc/64), veth194152c (fe80::10a3:fdff:fe43:abe3/64), veth656dec6 (fe80::5c4d:18ff:fe5a:dfb7/64), vethe523aa0 (fe80::e495:bff:fe90:a048/64), vethfb4761a (fe80::2c5f:94ff:fe5d:8d1f/64)
announce_addresses 192.168.1.38, 2a02:a03f:adde:ce00:e2f6:9265:209f:170b, fe80::f7c7:c271:cadb:7358
Recorder
oldest_recorder_run 9 mars 2025 à 08:36
current_recorder_run 11 mars 2025 à 18:52
estimated_db_size 5.73 MiB
database_engine sqlite
database_version 3.48.0
___

Tu peux regarder si tu ne peux pas utiliser un Zipulses. Il est conçu spécifiquement pour compter des impulsions. Je l’utilise pour mon compteur de gaz, mais d’autres s’en servent pour un compteur d’eau.
GitHub - fairecasoimeme/ZiPulses: Pulses Zigbee sensor to capture Gazpar or water counter

Salut

Pour le comptage par impulsion avec des ESP, j’utilise pas les sensor pulse ou counter.

J’utilise un binary sensor qui comptabilise les impulsions.

Je te post (dans la soirée) le code de ce que j’ai fait pour mon compteur gaz qui donne une impulsion pour 10l.

voila le code que j’utilise pour mon compteur Gazpar.
Ce code est a adapté en fonction de ton besoin.

##################################
# Debut : Device Specific Config #
##################################     

substitutions:
  name: compteur_gazpar
  friendly_name0: "ESPHOME ESP3 GAZPAR"
  friendly_name1: "Gazpar"
  friendly_name2: "Esp Gazpar"
  friendly_name3: "Temp EXT"


globals:
    
  - id: gazpar_pulse_counter
    type: float     # Le counter n'est pas integer car il sert aussi pour la division m3
    initial_value: "0" 

  - id: factor_conversion_m3_kwh  # pour la conversion m" en kWh pour le gaz.
    type: float


#################
# Binary Sensor #
#################
# Binary sensor utilisé pour comptage des impulsions et Totalisateur

binary_sensor:

  - platform: gpio
    pin:
      number: GPIO32
#      allow_other_uses: true
      mode: INPUT_PULLUP
      inverted: True
    filters:
      - delayed_on: 130ms
      - delayed_off: 130ms 
    name: "${friendly_name1} counter state"
    id: gazpar_counter_state

    on_press:
      then: 
        - lambda: |-
            // increment le compteur ECS puis publish mqtt
            id(gazpar_pulse_counter) += 1;
            id(gazpar_counter_pulse).publish_state(id(gazpar_pulse_counter));
            id(gazpar_counter_m3).publish_state(id(gazpar_pulse_counter)/100);
            id(gazpar_counter_m3_kwh).publish_state((id(gazpar_pulse_counter)/100)*(id(factor_conversion_m3_kwh)));
 #          id(gazpar_counter_m3_kwh).publish_state((id(gazpar_pulse_counter)/100)*11.27);           

##  Status ESP connexion   
  - platform: status
    name: ${friendly_name2} status   

##########
# sensor #
##########
sensor:

  - platform: homeassistant     # Import facteur de conversion de entité HA)
    id: factor_conversion_kwh_from_ha
    entity_id: sensor.gazpar_21593632397008_conversion_factor

## Mise a jour de la valeur importé de HA , Dans Id globals de ESP :
    on_value:
      then:
        - globals.set:
            id: factor_conversion_m3_kwh
            value: !lambda 'return float(x);'


## Comptage impulsion  
  - platform: template
    name: "${friendly_name1} counter pulse"
    id: gazpar_counter_pulse
    unit_of_measurement: ''
    accuracy_decimals: 0  # Précision en entiers
    icon: "mdi:counter"
    #update_interval: 5s  # Mise à jour sur changement de valeur

 
## Comptage m³ (utilisé pour le compteur services HA)
  - platform: template
    name: "${friendly_name1} counter m3"
    id: gazpar_counter_m3
    unit_of_measurement: 'm³'
    accuracy_decimals: 3  # Précision en entiers
    state_class: total_increasing
    device_class: gas    

## Comptage m³/kwh (utilisé pour le compteur services HA)
  - platform: template
    name: "${friendly_name1} counter Kwh"
    id: gazpar_counter_m3_kwh
    unit_of_measurement: 'kWh'
    accuracy_decimals: 3  # Précision en entiers
    state_class: total_increasing
    device_class: energy  

Hello,

Pour ma part avec un esp pour le comptage eau (1 pulse/litre) et gaz (1 pulse/10 litres) j’ai la config (extrait) suivante :

globals:
  - id: gaz_total_pulses
    type: int
    restore_value: false
    initial_value: '0'

  - id: eau_total_pulses
    type: int
    restore_value: false
    initial_value: '0'

binary_sensor:
  - platform: gpio
    id: internal_pulse_counter
    pin:
      number: GPIO27
      mode:
        input: true
        pullup: true
    internal: true
    filters:
      - delayed_on: 100ms
    on_press:
      then:
        - lambda: id(gaz_total_pulses) += 1;

  - platform: gpio
    id: internal_eau_pulse_counter
    pin:
      number: GPIO16
      mode:
        input: true
        pullup: true
    internal: true
    filters:
      - delayed_on: 100ms
    on_press:
      then:
        - lambda: id(eau_total_pulses) += 1;

sensor:
  - platform: template
    id: gazpar_gaz
    name: "Gazpar Gaz"
    device_class: gas
    unit_of_measurement: "m³"
    state_class: "total_increasing"
    icon: "mdi:fire"
    accuracy_decimals: 2
    lambda: |-
        return id(gaz_total_pulses) * 0.01;

  - platform: template
    id: consommation_eau
    name: "Consommation eau"
    device_class: water
    unit_of_measurement: "L"
    state_class: "total_increasing"
    icon: "mdi:water"
    accuracy_decimals: 2
    lambda: |-
        return id(eau_total_pulses);

Dans HomeAssistant j’ai ensuite des compteurs de services pour chaque consommation.

A+

Merci pour vos réponses.
Avec le yaml ci dessous j’ai réussi à afficher ce que je voulais mais dans la partie Energie ma production reste à 0 alors que j’ai bien une valeur dans l’entité et mon dashboard. Une idée du pourquoi ?


sensor:
  - platform: pulse_counter
    pin:
      number: GPIO14
      mode:
        input: true
        pullup: true
      inverted: true
    name: "Puissance instantanée"
    update_interval: 60s  # Intervalle de mise à jour
    internal_filter: 75ms  # Filtre anti-rebond mécanique
    unit_of_measurement: "W"
    accuracy_decimals: 0
    filters:
      - multiply: 0.01  # Convertit les impulsions en kW (100 pulses = 1 kWh, donc 1 pulse = 0.01 kW)
    total:
      device_class: "energy"  # Ajout de la classe d'appareil correcte
      state_class: "total_increasing"
      name: "Production journalière"
      unit_of_measurement: "kWh"
      accuracy_decimals: 2
      filters:
        - multiply: 0.01  # Convertit les impulsions en kWh

Salut
Si tu viens juste de le faire c’est normal. Il est précisé qu’il faut une a deux heures pour que les premières valeurs remontent.
De plus a cette heure ci la production ne devrait pas remonter grand chose non?

Ok merci. Je verrai demain du coup.
Une dernière chose, sait-on éviter que les données de l’entité se réinitialise après un redémarrage de HA ou du ESP?

Au redémarrage de ha ça ne devrait pas se remettre a zero et ce qui est inscrit dans le dashboard énergie ne se remettra pas a zero non plus.
Si tu veux voir cette valeur ailleurs que dans le dashboard énergie tu peux toujours rajouter un compteur de service public avec comme source ton total.
Lui gardera sa valeur quoi qu’il en soit meme si côté esp ça repart a zéro.

Il est peut être possible de faire ça côté esp mais je n’ai jamais regardé.

Je me posais la questions de savoir si c’était mieux pulse_meter ou pulse_counter et au final votre solution du binary_sensor était la meilleure.

Pour les suivants qui se poseraient la question:

captive_portal:

globals:
  - id: last_pulse_time
    type: float
    restore_value: false
    initial_value: '0'
  - id: pv_power
    type: float
    restore_value: false
    initial_value: '0'
  - id: pv_total_pulses
    type: int
    restore_value: false
    initial_value: '0'

binary_sensor:
  - platform: gpio
    id: internal_pulse_counter
    pin:
      number: GPIO14  # Assure-toi que c'est le bon GPIO
      mode:
        input: true
        pullup: true
    internal: true
    filters:
      - delayed_on: 85ms
    on_press:
      then:
        - lambda: |-
            float now = millis() / 1000.0;  // Temps actuel en secondes
            float delta_t = now - id(last_pulse_time);
            if (delta_t > 0) {
              id(pv_power) = 36000.0 / delta_t;  // Calcul de la puissance
            }
            id(last_pulse_time) = now;  // Mise à jour du dernier pulse
            id(pv_total_pulses) += 1;  // Incrémentation du compteur total

sensor:
  - platform: template
    id: pv_production
    name: "Production Photovoltaïque"
    device_class: energy
    unit_of_measurement: "kWh"
    state_class: total_increasing
    icon: "mdi:solar-power"
    accuracy_decimals: 2
    lambda: return id(pv_total_pulses) * 0.01;  # 1 pulse = 0.01 kWh

  - platform: template
    id: puissance_pv
    name: "Puissance Photovoltaïque"
    unit_of_measurement: "W"
    device_class: power
    state_class: measurement
    accuracy_decimals: 2
    lambda: |-
      return id(pv_power);

# Vérification périodique de la puissance et remise à zéro si aucune activité
interval:
  - interval: 300s  # Vérification toutes les 5 minutes
    then:
      - lambda: |-
          float now = millis() / 1000.0;
          float delta_t = now - id(last_pulse_time);
          if (delta_t > 600) {  // Si aucune mise à jour pendant 10 minutes
            id(pv_power) = 0;  // Réinitialisation de la puissance à zéro
          }