Aide code compteur eau esphome

Bonjour,

J’aurais besoin d’un peu d’aide concernant le calcul de mon compteur d’eau.
Mon compteur à une petite pastille métallique qui fait 1 tour tous les litres. Je récupère donc l’info via un esp32 et un code que j’ai trouvé sur le net.
J’ai envie de dire, ça marche pas trop mal, sauf…ben oui.
En fait, malgré que esphome me dit que l’esp32 est online, sur mon Dashboard, j’ai plus de mentions « indisponible » que de données.
L’esp crée des variables qui stockent les données sauf que il arrive que ça se remet à 0 sans que j’en connaisse la raison. J’ai donc décidé de mettre en place un utility meter. Ça marche mais si j’ai une consommation pendant que l’esp est « indisponible », ben ça ne prends pas la consommation en compte. J’utilise le sensor.compteur_d_eau_consommation_courante pour l’utilité meter.
J’ai même essayé de mettre dans pulse counter un « total » mais ça ne compte pas tout non plus.
En fait, j’aurais aimé renseigner dans ha mon index et que l’esp l’incrémente continuellement.

Une idée?
Merci

Ci dessous, le code esphome


esphome:
  name: compteur_eau
  platform: ESP32
  board: esp-wrover-kit
  on_boot:
    priority: -10
    then:
      - script.execute: publish_states
# Enable logging
logger:

# Enable Home Assistant API
api:
  services:
    - service: reset_main_counter
      then:
        - script.execute: reset_main_counter
    - service: reset_secondary_counter
      then:
        - script.execute: reset_secondary_counter
ota:
  password: « caché"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_mdp

captive_portal:

substitutions:
  name: watermeter
  friendly_name: "Compteur d'eau"

# Documentations:
# https://github.com/esphome/issues/issues/664
# https://esphome.io/components/sensor/integration.html
# https://community.home-assistant.io/t/using-esphome-to-build-a-water-flow-rate-meter/119380/64

globals:
 - id: main_counter_pulses
   type: int
   restore_value: yes
   initial_value: '0'
 - id: secondary_counter_pulses
   type: int
   restore_value: yes
   initial_value: '0'
 - id: daily_counter_pulses
   type: int
   restore_value: yes
   initial_value: '0'
 - id: weekly_counter_pulses
   type: int
   restore_value: yes
   initial_value: '0'
 - id: monthly_counter_pulses
   type: int
   restore_value: yes
   initial_value: '0'
 - id: yearly_counter_pulses
   type: int
   restore_value: yes
   initial_value: '0'

 - id: event_quantity
   type: int
   restore_value: no
   initial_value: '0'
 - id: last_event_quantity
   type: int
   restore_value: no
   initial_value: '0'
 - id: event_counter
   type: int
   restore_value: no
   initial_value: '0'
 - id: current_event_quantity
   type: int
   restore_value: no
   initial_value: '0'
script:
  - id: reset_main_counter
    then:
      - lambda: |-
          id(main_counter_pulses) = 0;
          id(water_main_consumption).publish_state(id(main_counter_pulses));
  - id: reset_secondary_counter
    then:
      - lambda: |-
          id(secondary_counter_pulses) = 0;
          id(water_secondary_consumption).publish_state(id(secondary_counter_pulses));
  - id: publish_states
    then:
      - lambda: |-
          id(water_main_consumption).publish_state(id(main_counter_pulses));
          id(water_secondary_consumption).publish_state(id(secondary_counter_pulses));
          id(water_daily_consumption).publish_state(id(daily_counter_pulses));
          id(water_weekly_consumption).publish_state(id(weekly_counter_pulses));
          id(water_monthly_consumption).publish_state(id(monthly_counter_pulses));
          id(water_yearly_consumption).publish_state(id(yearly_counter_pulses));
          id(current_water_consumption).publish_state(id(event_quantity));
sensor:
  - platform: uptime
    name: "${friendly_name} uptime"
    
  - platform: pulse_counter
    id: water_pulse_counter
    name: "${friendly_name} Consommation instantanée"
    pin: 32
    update_interval: 2sec
    internal_filter: 10us
    unit_of_measurement: "L/min"
    accuracy_decimals: 0
    icon: "mdi:water"
    filters:
      # Divide by 60
      - multiply: 0.0167
      - lambda: return abs(x);
    total:
      unit_of_measurement: 'L'
      name: 'nombre litre'

  - platform: template
    id: water_main_consumption
    name: "${friendly_name} Principal"
    unit_of_measurement: "L"
    accuracy_decimals: 0
    icon: "mdi:water"

  - platform: template
    id: water_secondary_consumption
    name: "${friendly_name} Secondaire"
    unit_of_measurement: "L"
    accuracy_decimals: 0
    icon: "mdi:water"

  - platform: template
    id: water_daily_consumption
    name: "${friendly_name} Journalière"
    unit_of_measurement: "L"
    accuracy_decimals: 0
    icon: "mdi:water"

  - platform: template
    id: water_weekly_consumption
    name: "${friendly_name} Semaine"
    unit_of_measurement: "L"
    accuracy_decimals: 0
    icon: "mdi:water"

  - platform: template
    id: water_monthly_consumption
    name: "${friendly_name} Mois"
    unit_of_measurement: "L"
    accuracy_decimals: 0
    icon: "mdi:water"

  - platform: template
    id: water_yearly_consumption
    name: "${friendly_name} Année"
    unit_of_measurement: "L"
    accuracy_decimals: 0
    icon: "mdi:water"

  - platform: template
    id: current_water_consumption
    name: "${friendly_name} Consommation courante"
    unit_of_measurement: "L"
    accuracy_decimals: 0
    icon: "mdi:water"

  - platform: template
    id: last_water_consumption
    name: "${friendly_name} Dernière consommation"
    unit_of_measurement: "L"
    accuracy_decimals: 0
    icon: "mdi:water"
binary_sensor:
  - platform: gpio
    id: water_pulse
    pin: 32
    internal: true
    filters:
       - delayed_on_off: 50ms
       - lambda: |-
          id(main_counter_pulses) += x;
          id(secondary_counter_pulses) += x;
          id(daily_counter_pulses) += x;
          id(weekly_counter_pulses) += x;
          id(monthly_counter_pulses) += x;
          id(yearly_counter_pulses) += x;
          id(event_quantity) += x;
          return x;
    on_state:
       - script.execute: publish_states

switch:
  - platform: template
    name: "${friendly_name} reset main counter button"
    icon: "mdi:restart"
    turn_on_action:
      - script.execute: reset_main_counter

  - platform: template
    name: "${friendly_name} reset secondary counter button"
    icon: "mdi:restart"
    turn_on_action:
      - script.execute: reset_secondary_counter

  - platform: restart
    name: "${friendly_name} restart"
    
time:
  - platform: sntp
    on_time:
      - seconds: 0
        minutes: 0
        hours: 0
        then:
          - globals.set:
              id: daily_counter_pulses
              value: '0'
          - lambda: id(water_daily_consumption).publish_state(id(daily_counter_pulses));
      - seconds: 0
        minutes: 0
        hours: 0
        days_of_week: MON
        then:
          - globals.set:
              id: weekly_counter_pulses
              value: '0'
          - lambda: id(water_weekly_consumption).publish_state(id(weekly_counter_pulses));
      - seconds: 0
        minutes: 0
        hours: 0
        days_of_month: 1
        then:
          - globals.set:
              id: monthly_counter_pulses
              value: '0'
          - lambda: id(water_monthly_consumption).publish_state(id(monthly_counter_pulses));
      - seconds: 0
        minutes: 0
        hours: 0
        days_of_month: 1
        months: JAN
        then:
          - globals.set:
              id: yearly_counter_pulses
              value: '0'
          - lambda: id(water_yearly_consumption).publish_state(id(yearly_counter_pulses));

interval:
  # Save the last consumption
  #
  # An event is published when a water flow (>= 1L / 15 seconds) is
  # detected and followed by a stop of consumption for a defined time.
  - interval: 15sec
    then:
      - lambda: |-
          if (id(event_quantity) != id(last_event_quantity)) {
            // Water continues to flow
            // Reset event counter
            id(event_counter) = 0;
          } else {
            // Water no longer flows
            if (id(event_quantity)) {
              // 4 * 15 * 5 = 5min
              if (id(event_counter) < 4 * 5) {
                // Timeout is not reaches
                id(event_counter)++;
              } else {
                  // Timeout is reaches
                  id(last_water_consumption).publish_state(id(event_quantity));
                  // Send event to Home Assistant
                  api::HomeAssistantServiceCallAction<> *api;
                  api = new api::HomeAssistantServiceCallAction<>(api_apiserver, true);
                  // Event id length limit is 32 characters
                  api->set_service("esphome.last_consumption_changes");
                  api->play();
                  id(event_quantity) = 0;
              }
            }
          }
          id(last_event_quantity) = id(event_quantity);
  # Track the current consumption
  - interval: 2sec
    then:
      - lambda: |-
          if (id(event_quantity) != id(current_event_quantity)) {
            id(current_water_consumption).publish_state(id(event_quantity));
          }
          id(current_event_quantity) = id(event_quantity);

Que dit le log de l’esp à partir de ESPHome?
Tu devrais voir toutes les publications dans le log en live, peut-être y a t’il quelque chose qui indique pourquoi l’entité passe en indisponible.

Sinon la force du wifi à ton compteur est bonne, toujours dans le log de l’ESP?

Ben il est vrai que j’ai régulièrement ce message mais je ne vois pas comment le résoudre car le wifi passe plus ou moins bien: -73db.

WARNING Can’t connect to ESPHome API for compteur-eau.local: Error connecting to (‹ 192.168.1.30 ›, 6053): [Errno 111] Connect call failed (‹ 192.168.1.30 ›, 6053)

Je me demandais si vous ne connaîtriez pas un code pour que esphome cumule la valeur jusqu’à transmission à ha?

Merci

Les objets connectés c’est cool, mais cela ne veut pas dire qu’une connexion doit être obligatoire pour fonctionner. Un développement selon ce principe pose souvent des problèmes, comme dans ton cas.

Tu veux un système de comptage… aucun soucis. Mais il faut que ce soit ton capteur qui compte, pas HA. ton esp doit être autonome, et HA seulement un lecteur et affichage.

Pour intégrer ça directement dans esphome : Pulse Counter Sensor — ESPHome
Il y a aussi un bel exemple sur cette page : GitHub - hugokernel/esphome-water-meter: Measurement of water consumption directly from your water meter with a TCRT5000 like sensor and ESPHome.

1 « J'aime »

Hello
Tu peux regarder le code que j’utilise pour faire cela dans ma réalisation
Amitiés
Philippe

https://forum.hacf.fr/t/une-solution-complete-de-recuperation-des-donnees-eau-gaz-et-electricite/6507

Bonjour,
Merci de ta réponse.
C’est effectivement ce que fait mon esp, il gère tout lui même mais il lui arrive régulièrement de se remettre à zéro et ça m’embête. J’aurais aimé avoir sur ha l’index de mon compteur (style: 775,654 m3).
Il faudrait que je trouve le moyen d’avoir une variable sur l’esp qui ne se réinitialise jamais. Dans ce cas, je peux créer un compteur sur ha avec mon index d’aujourd’hui et que par la suite, l’esp rajoute le montant de la variable qui ne se réinitialise pas.
Pour le sujet que tu indiques, si tu regardes mon code, c’est justement celui-là que j’ai utilisé.
Merci

Bonjour,
C’est effectivement intéressant. J’ai juste un peu de mal à comprendre la différence que tu fais entre pulse counter et pulse meter.
Je vais essayer ton code et si j’ai des soucis, tu voudras bien m’aider à comprendre ?
Merci

Ton code fait beaucoup de chose que les autres ne font pas. Tu as utilisé un principe totalement différent.

Le code par exemple de @Pbranly compte, et se réinitialise 1 fois par jour.
Toi, tu comptes, mais tu fais de la publication systématiquement en permanence. L’ESP est un petit ordinateur avec des capacités limitées, et il semblerait qui tu « satures » ce système qui se réinitialise.

Il y a aussi la possibilité d’un problème d’alimentation. a chaque coupure d’alimentation, il y a perte de données et réinitialisation.

Afin de trouver la cause de tout cela, tu pourrais déjà activer les logs sur l’esp afin de savoir ce qui occasionne la réinitialisation.

Ensuite tu pourrais essayer un code plus léger, qui ne publie pas en permanence (ou une fois par heure par exemple).Tu peux aussi supprimer la majorité de tes variables, Une seule suffit, le nombre d’impulsion. Les autres, c’est du stockage et travail de statistique.
Voilà avec ça, tu devrais pouvoir faire évoluer les symptômes( enfin plutôt les supprimer :wink: )

Pour terminer, il est possible de stocker une variable en eeprom, mais cela ne va pas régler ton problème de réinitialisation

Un ESP32 c’est petit mais ça reste tout de même largement trop puissant pour gérer un compteur d’eau!
Mais c’est un microcontrôleur qui se contente de répéter en boucle ce qu’on lui a demandé de faire. Mais contrairement à un ordinateur il ne fait qu’une seule chose à la fois.
(Précision, l’ESP32 est dual thread, mais ESPHome utilise un côté pour le wifi et tout ce qui est connexion. Et le 2eme pour le programme.)

Pour moi les soucis de connexion c’est une grosse problématique là, mais il est possible que ça vienne du nombre de publications faites, si c’était des reboot ça se verrait dans les logs.
Simplifier pour commencer aidera à voir si c’est des soucis réseau ou pas…
Comme le dit @bricodx je partirais sur quelque chose de plus simple, et potentiellement évoluer pas à pas.

Les multiples compteurs c’est pas nécessaire effectivement c’est plutôt un truc à gérer dans HA en fait. C’est un capteur, donc faudrait pas qu’il perde de vue son rôle initial: capter. Et blinder cette aprtie là avant de faire autre chose.

Pas de problème
Sinon il y a un moyen pour mémoriser une valeur dans l’esp. mais ça veut dire écrire sans arrêt dans l’éprouva qui n’est pas faite pour ça
Mon code fait aussi rebooter l’esp de temps en temps. Comme je ne gère que des valeurs relatives ca n’a quasi pas d’importance
Phil

Bonjour,
J’ai essayé ton code. Alors que j’ai le même type de compteur que toi, à 1l près, il me compte le double de consommation et je ne comprends pas pourquoi. La seule raison que je vois est qu’il compterait 1 pulse à chaque changement d’état…
Une idée ?

J’ai plusieurs questions.
Mais d’abord , j’ai réglé le problème de « indisponible ». En fait, c’est mon esp qui est hs. J’avais pas envie de le changer car tout démonter et refaire. Mais bon, maintenant c’est fait.

Plusieurs questions:

  • quelle est la différence entre pulse counter et pulse meter ? Lequel est conseillé pour mon utilisation ?
  • si vous regardez le code mis en présentation, on peut voir que quand il y a une pulse, il la stock dans « abs (x ) ». Le seul souci, c’est que si je redémarre mon esp, il estime que x est = à 1 et donc incrémente tous mes capteurs de 1. Même si aucune consommation.
    Connaîtriez vous le moyen de remettre ce « x » à zéro a chaque redémarrage ? J’ai essayé des trucs mais rien de concluant.
  • et je bloque toujours sur la manière de faire un compteur qui d’incréments continuellement. Par contre, si j’arrivais à ce que ce « x » revienne à 0 a chaque redémarrage, je pense que j’y arriverais.

Merci

Bonjour j’ai eu exactement le même problème avec la partie gaz , subitement il y avait une double impulsion générée en interne par l’Esp. J’avais mis empiriquement une division par deux dans le code pour régler le problème et c’était redevenu impeccable . Ça ne le faisait pas pour l’eau bizarrement .
Et puis subitement après une mise à jour d’ESPHOME ces consos d’eau sont devenues divisées par deux ! J’ai donc supprime mon diviseur par 2 sans comprendre
J’ai soupçonné une régression dans le code d ESPHOME
Je suis actuellement en 2022.2.6
Amitiés
Philippe

Type counter :
Je crois que tu peux utiliser les deux. De mémoire j’étais parti de l’autre. Je ne me souviens plus pourquoi j’ai changé !

Increment au démarrage:
j’avais jamais fait attention . Baaaa 1 litre à chaque démarrage ça te fait une erreur inférieure à 1% quand il y a redémarrage … pas grave ! Ceci dit il doit y avoir une solution pour mettre la valeur à zéro au redémarrage . Il faut comparer cette erreur à celle que tu auras si tu rates des pulses pendant le reboot !

Increment continuel :
Je ne vois pas de solution fiable à terme dans lESP. Il faudrait écrire sans arrêt la valeur dans lESP donc risquer d’user prématurément leprom de celui ci.
Est ce vraiment utile de vouloir calquer la valeur du compteur ? Si oui pars plutôt sur une solution espcam avec reconnaissance de caractères . Il y a pas mal de tutos sur cette solution .
Amitiés
Philippe

Pour moi c’est une zone complètement flou du code, et à mon avis c’est une erreur de codage. Si tu regardes comment c’est construit : dans pulse counter il y a consommation L/min et de la quantité nombre de litre . Tout est mélangé

le compteur capte le impulsion, qui est une quantité d’impulsion, et totalise qui est une quantité d’impulsion.

# Divide by 60
      - multiply: 0.0167

Ca n’a aucune raison d’être dans cette partie.

Séparément si on veut une consommation, c’est pas un problème, mais là en mélangeant …

return abs(x)

Ca ne stocke pas, ça fait juste en sorte que la valeur soit positive : par exemple si X = -4 ça retourne X = 4 . Mais ça ne change pas la valeur

Bonjour,

Je dois t’avouer que tu m’as perdu.
Pour le « nombre de litre », c’est moi qui l’ai rajouté. C’était un essai. Mais ça ne donne rien de cohérent.
Si « x » ne stock pas le chiffre 1, alors comment se fait il que quand l’esp redémarre, il m’ajoute systématiquement 1 litre ?

Le:

  • multiply: 0.0167

Tu le mettrais où alors ? Parce que ça a l’air de fonctionner cette partie.
En te remerciant

C’est pas une question que ça fonctionne ou pas, surtout que ça ne fonctionne pas vraiment puisque tu es là :crazy_face:
Pour ton besoin il y a plusieurs étapes, et dans ton code elles sont toutes mélangées.
Les étapes nécessaires sont le comptage ( et mémorisation) , puis les calculs, et en dernier l’affichage.
Donc ton esp doit compter et mémoriser. Pour l’affichage c’est a part, par exemple dans un template (sur l’esp) ou en externe sur HA

binary_sensor:
  - platform: gpio
    id: water_pulse
    pin: 32
    internal: true
    filters:
       - delayed_on_off: 50ms
       - lambda: |-
          id(main_counter_pulses) += x;
          id(secondary_counter_pulses) += x;
          id(daily_counter_pulses) += x;
          id(weekly_counter_pulses) += x;
          id(monthly_counter_pulses) += x;
          id(yearly_counter_pulses) += x;
          id(event_quantity) += x;
          return x;

Il est incrémenté ici, il me semble
Un autre truc que je trouve bizarre: tu captes ton gpio32 dans un sensor puis dans un binary sensor. C’est quoi l’intérêt de faire une double capture ?

Le code de @Pbranly fait la même chose que toi mais en beaucoup plus simple et direct.
Je pense que ce serait bien de repartir de 0 et refaire un code propre (actuellement je n’arrive même pas à comprendre le cheminement de ton code pour faire un truc qui à la base est simple).

Si tu veux je peux t’aider pour refaire ton yaml

Merci de ta réponse.
Pour être franc, je ne le comprends pas non plus. Il n’est pas de moi, je l’ai pêché sur le net. Je ne m’y connais pas assez en programmation pour le faire moi même. Et donc, ta proposition d’aide serait géniale. Si en plus tu pouvais me décrire pourquoi telle ou telle formule et me la décrire, ce serait super. Ça me permettrait peut-être de comprendre.
En te remerciant

esphome:
  name: compteur_eau
  platform: ESP32
  board: esp-wrover-kit
# Enable logging
logger:

# Enable Home Assistant API
api:
 
ota:
  password: « caché"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_mdp

captive_portal:

substitutions:
  name: watermeter
  friendly_name: "Compteur d'eau"

sensor:
  - platform: uptime
    name: "${friendly_name} uptime"
    
  - platform: pulse_meter
    id: water_pulse_counter
    name: "${friendly_name} nbre litres"
    pin: 32
    internal_filter: 100us
    unit_of_measurement: "L"
    accuracy_decimals: 0
    total:
      unit_of_measurement: 'L'
      name: 'nombre total litres'
      id: water_total_counter


switch:
  - platform: restart
    name: "${friendly_name} restart"
    
time:
  - platform: homeassistant
    on_time:
      - seconds: 59
        minutes: 59
        hours: 23
        then:  
          - pulse_meter.set_total_pulses:
              id: water_pulse_counter
              value: 0

Là, c’est raccourci au maximum mais c’est presque suffisant.

pour t’expliquer, il y a le sensor pulse-meter qui compte et totalise. Puis il y a time qui a 23h59min59s remet le compteur total à zéro.

Sans aller plus loin, tu vas voir que HA reçoit ces informations. A partir de là, il faut penser à l’affichage.

Est ce que tu veux afficher des infos sur la page web de ton esp (chose pas forcément très intéressant), ou seulement dans HA ???

Pour HA tu es capables d’afficher les statistiques que tu veux avec des templates.

type: statistics-graph
title: 'My Graph'
entities:
  - sensor.nombre_total_litres
period: day

Ca va t’afficher un graphique avec ta consommation d’eau sur 24h. Statistics Graph Card - Home Assistant