HA-Gestion Eau Chaude Sanitaire

Intro

Lorsque la production d’Eau Chaude Sanitaire est comme chez moi produite par un ballon eau chaude électrique classique , elle peut être très énergivore et coûter un max si elle n’est pas maîtrisée.

C’est pourquoi je tente de la réduire au minimum, pour ce faire, j’utilise au mieux le surplus de production générée par mon installation photovoltaïque décrite dans mon article https://domo.rem81.com/2022/11/13/pv-photovoltaique/ et bien entendu mon système domotique préféré Home Assistant.

Terminologie:

Commençons par décrire les termes communément employés dans cet article:

  • HA: Home Assistant
  • PV: photoVoltaique
  • RPV: Routeur PhotoVoltaique
  • BECS: Ballon Eau Chaude sanitaire
  • RPE: Réseau Electrique Public, réseau Enedis (anciennement réseau EDF).

Solution proposée

Mis en oeuvre d’un routeur photovoltaïque.

Un RPV est un système électronique par lequel transite l’alimentation de votre BECS (on dit qu’il est raccordé en série). Ce système module la puissance du signal électrique transmise au BECS en fonction du surplus de puissance injecté dans le RPE. Des que le système détecte une injection supérieure à un seuil généralement paramétrable, il calcul la puissance du signal de sortie du RPV dans une fourchette Min/Max les deux étant aussi généralement paramétrable: Min = 0%, Max est fonction de la puissance du BECS et du RPV. De ce fait la consommation va augmenter jusqu’à ce le RPV calcul un soutirage dans le RPE, il adapte ainsi en permanence la puissance appliqué au BECS.

Vous trouverez dans cet article publié par l’association ‘P’TITWATT’ des explications bien plus compréhensible que la mienne.

Cet d’ailleurs ce routeur que j’utilise mais j’y reviendrai dans un article spécifique.

Modifications électriques du tableau principal

Comme je n’aime pas mélanger les sources électriques, j’ai modifié alimentation de mon BECS comme suit:

le disjoncteur Q23 protège électriquement le BECS, le disjoncteur Q28 protège électriquement le circuit de mesure tension du routeur et le circuit de commande des contacteurs. J’aurai également tout alimenter depuis le Q23 mais mon Q28 était disponible!.

Les contacteur PV et Réseau sont des contacteurs type chauffe-eau avec le mode Arret/Auto/Marche, pratique si la domotique est hors service.

Ils sont commandés par HA via un module Wago mais ce peut être bien entendu n’importe quel « switch » de puissance pilotés par HA.

Vous avez compris que le contacteur PV alimente le BECS via le routeur et que le contacteur « Réseau » l’alimente en direct depuis le réseau.

Modification électrique du ballon

Thermostat électromécanique

Si votre ballon est équipé d’un thermostat électromécanique comme le mien, il n’y a rien à faire et surtout il faut garder le thermostat opérationnel sous risque de le transformer en cocote minute si HA venait à déconner.

Thermostat électronique

Si votre ballon est équipé d’un thermostat Electronique, c’est plus compliqué, il faudra dissocier l’alimentation électrique de l’électronique du thermostat, de l’alimentation électrique des résistances. La première devra toujours etre alimenté directement depuis le réseau, la deuxième pourra transiter par le RPV. Là encore il faut garder le thermostat opérationnel.

Ballon Thermodynamique

Dans ce cas c’est plus compliqué car vous ne pouvez pas l’alimenter électriquement directement via le RPV sans effectuer de modifications, vous risquez tout simplement de le cramer.

Malheureusement, je ne saurai pas vous aider sur ce coup, mais GOOGLE est votre ami, il vous apportera certainement la solution.

Mesure de température de l’eau

Solution

De mon point de vue il est intéressant de connaitre la température de l’eau à l’intérieur du BECS. Mon ballon n’étant pas équipé d’une sonde ni même d’un emplacement pour y loger une sonde, j’ai utilisé un ESP01 avec une sonde ds18b20. J’ai fait un trou de 8mm à mi-hauteur dans l’enveloppe extérieur du ballon et j’ai glissé ma sonde dans l’isolant au contact de la cuve métallique contenant l’eau chaude. J’ai étalonné la chaîne de mesure avec la température de l’eau chaude sortie robinet en jouant sur filters: – offset: 8.0 dans le code ESP, cela donne une bonne indication, et je ne suis pas au degré prêt.

Schéma Electronique

Les sondes peuvent se mettre en parallèle, j’en ai prévu trois dans mon schéma. La led n’est pas obligatoire

Exemple de circuit imprimé conçu avec EAGLE

Vous pouvez sous traiter la fabrication de ce type de PCB à https://jlcpcb.com/ ça coûte que dalle, c’est du travail de pro, faut pas etre pressé et c’est quantité 5 minimum, exemple en dessous pour ce PCB: 1.99+3.46€!!

Code de l’ESP01

substitutions:
  device_name: esp126-temp-ecs
  friendly_name: esp126
  adress_ip: "192.168.0.126"
  time_timezone: "Europe/Paris"

esphome:
  name: ${device_name}
  platform: ESP8266
  board: esp01_1m  
  
wifi:
  networks:
    - ssid: !secret wifi_mi4
      password: !secret mdpwifi_mi4
      priority: 2    
    - ssid: !secret wifi_esp
      password: !secret mdpwifi_esp
      priority: 1
    - ssid: !secret wifi
      password: !secret mdpwifi
      priority: 0
  reboot_timeout: 5min
    

  manual_ip:
    static_ip: ${adress_ip}
    gateway: 192.168.0.254
    subnet: 255.255.255.0

captive_portal:

# Enable logging
logger:

# Enable Home Assistant API
api:

ota:

web_server:
  port: 80

# Configuration Dalas
dallas:
  - pin: GPIO0

#Etat de la connection
binary_sensor:
  - platform: status
    name: "${friendly_name} Status"

switch:    

  - platform: restart
    name: "${friendly_name} Restart"
    
        
sensor:

  - platform: dallas
    address: 0xCA00AA2D00000328
    name: "${friendly_name} temp_ecs"
    filters:
      - offset: 8.0
    
  - platform: wifi_signal
    name: "${friendly_name} WiFi Signal Sensor"
    update_interval: 60s

  - platform: uptime
    name: "${friendly_name} Uptime Sensor"
    update_interval: 60s

text_sensor:
  # IP address #
  - platform: wifi_info
    ip_address:
      name: "${friendly_name} IP address"
      icon: "mdi:network-outline"
    ssid:
      name: "${friendly_name} Connected SSID"
    bssid:
      name: "${friendly_name} Connected BSSID"

Automatismes

Cahier des charges:

  • Rester maître du système en pilotant depuis HA et non depuis le Linky
  • Privilégier la charge des batteries PhotoVoltaique, puis la chauffe du ballon: Lorsque les batteries seront pleines et si production PV supérieure à Conso, alors on va injecter dans le réseau et le router PV réagira en conséquence.
  • Chauffer le ballon la nuit en heure creuse si pas assez chaud par manque d’ensoleillement dans les jours précédents.
  • Avoir un mode secours si la production PV n’est pas suffisante sur le long terme.
  • Trois modes de fonctionnement:
    • Auto (Automatique)
    • Arret (Arret Forcé)
    • Marche (Marche forcée).

Mode Automatique:

Dans ce mode, je distingue le jour et la nuit, le jour est réservé à l’utilisation du routeur, la nuit, uniquement en mode secours, si l’eau n’est pas assez chaude.

La nuit, choix 1:

  • si ECS est en mode automatique
  • si nous sommes après le couché du soleil et avant le levé du soleil
  • si la température du BECS descend en dessous du seuil température basse
  • si le linky est en heure Creuse
    • Alors j’enclenche le relais ECS_Réseau donc, je chauffe plein pot.

La nuit, choix 2:

  • si nous sommes après le coucher du soleil et avant le levé du soleil
    • ET
  • si la température du BECS monte au dessus du seuil température haute
    • OU
  • si le linky passe en heure pleine
    • Alors je coupe le relais ECS_Réseau, j’arrete de chauffer.

Le jour, choix 3:

  • si ECS est en mode automatique
  • si nous sommes après le levé du soleil et avant le couché du soleil
  • si le input.boolean « validation du routeur PV » est sur ON

Le jour, choix 4:

  • si le input.boolean « validation du routeur PV » passe de ON à OFF
    • Alors je coupe le relais ECS_PV

Mode Arrêt Forcé:

Dans ce mode, je coupe les relais ECS_Réseau et ECS_PV.

Mode Marche Forcé:

Dans ce mode, je coupe le relais ECS_PV et j’active le relais ECS_Réseau, je force le chauffage via le réseau avec bien sur le thermostat électromécanique intégré au BECS en sécurité.

Script gestion relais

Afin d’éviter un chevauchement des relais PV et Réseau, j’ai créé trois scripts que je lance depuis les automatismes ou depuis le tableau de bord:

  • ECS_OFF: les deux relais sont sur Off
  • ECS_PV: Désactivation du relais ECS_PV, délai 2s, activation du relais ECS_Réseau
  • ECS_Réseau: Désactivation du relais ECS_réseau, délai 2s, activation du relais ECS_PV

Code de l’automatisme:

alias: 1_2_3 ECS Automatismes
description: ""
trigger:
  - platform: state
    entity_id:
      - input_select.ecs_ssol
  - platform: sun
    event: sunrise
    offset: 0
    id: levee_soleil
  - platform: sun
    event: sunset
    offset: 0
    id: couche_soleil
  - platform: state
    entity_id:
      - sensor.linky_ptec
    from: HC..
    to: HP..
    id: HC-HP
  - platform: state
    entity_id:
      - sensor.linky_ptec
    from: HP..
    to: HC..
    id: HP-HC
  - platform: numeric_state
    entity_id: sensor.esp126_temp_ecs
    id: t_bas
    below: 40
  - platform: numeric_state
    entity_id: sensor.esp126_temp_ecs
    above: 45
    id: t_haut
  - platform: state
    entity_id:
      - input_boolean.ecs_av_pv
    from: "on"
    to: "off"
    id: arret_pv_routeur
  - platform: state
    entity_id:
      - input_boolean.ecs_av_pv
    from: "off"
    to: "on"
    id: avect_pv_routeur
condition: []
action:
  - choose:
      - conditions:
          - condition: state
            entity_id: input_select.ecs_ssol
            state: Auto
          - condition: sun
            before: sunrise
            after: sunset
          - condition: numeric_state
            entity_id: sensor.esp126_temp_ecs
            below: 40
          - condition: state
            entity_id: sensor.linky_ptec
            state: HC..
        sequence:
          - service: script.ecs_on
            data: {}
      - conditions:
          - condition: state
            entity_id: input_select.ecs_ssol
            state: Auto
          - condition: or
            conditions:
              - condition: trigger
                id: HC-HP
              - condition: numeric_state
                entity_id: sensor.esp126_temp_ecs
                above: 45
          - condition: sun
            before: sunrise
            after: sunset
        sequence:
          - service: script.ecs_off_off
            data: {}
      - conditions:
          - condition: state
            entity_id: input_select.ecs_ssol
            state: Auto
          - condition: sun
            before: sunset
            after: sunrise
          - condition: state
            entity_id: input_boolean.ecs_av_pv
            state: "on"
        sequence:
          - service: script.ecs_off
            data: {}
      - conditions:
          - condition: trigger
            id: arret_pv_routeur
          - condition: state
            entity_id: input_select.ecs_ssol
            state: Auto
        sequence:
          - service: script.ecs_off_off
            data: {}
      - conditions:
          - condition: state
            entity_id: input_select.ecs_ssol
            state: At Forcé
        sequence:
          - service: script.ecs_off_off
            data: {}
      - conditions:
          - condition: state
            entity_id: input_select.ecs_ssol
            state: Ma Forcée
        sequence:
          - service: script.ecs_on
            data: {}
    default: []
mode: single

Tableau de bord:

Exemple de carte

Code de la carte

type: entities
entities:
  - entities:
      - entity: input_select.ecs_ssol
        name: Mode
      - entity: input_boolean.ecs_av_pv
        name: Roteur PV
    entity: input_select.ecs_ssol
    icon: mdi:flash
    name: Fonctionnement
    show_state: false
    type: custom:multiple-entity-row
  - entities:
      - entity: sensor.ecocompteur_ecs
        name: Pu
      - entity: sensor.mp2_charge_batteries
        name: Ch Bat
    entity: sensor.ecocompteur_ecs
    icon: mdi:flash
    name: Puissance
    show_state: false
    type: custom:multiple-entity-row
  - entities:
      - entity: sensor.energie_ecs_jour
        name: Res+PV
      - entity: sensor.energie_ecs_reseau_jour
        name: Reseau
      - entity: sensor.energie_ecs_pv_jour
        name: PV
    entity: sensor.energie_ecs_jour
    icon: mdi:flash
    name: Conso Jour
    show_state: false
    type: custom:multiple-entity-row
  - entities:
      - entity: sensor.esp126_temp_ecs
        name: T°
      - entity: sensor.ecs_chauffage_ce_jour
        name: Tps Ch
    entity: sensor.energie_ecs_jour
    icon: mdi:temperature-celsius
    name: Temp
    show_state: false
    type: custom:multiple-entity-row
  - entities:
      - entity: binary_sensor.ecs_chauffe
        name: Chauffage
      - entity: switch.cde_relais_ecs
        name: Rel ECS
      - entity: switch.cde_relais_ecs_router_pv
        name: Rel PV
    entity: switch.cde_relais_ecs
    icon: mdi:water-boiler
    name: Cde
    show_state: false
    type: custom:multiple-entity-row
  - entities:
      - entity: switch.cde_relais_ecs
        name: Relais ECS
      - entity: switch.cde_relais_ecs_router_pv
        name: Relais Routeur PV
      - entity: script.ecs_reseau
      - entity: script.ecs_pv
      - entity: script.ecs_off
    head:
      label: Commandes
      type: section
    padding: 0
    type: custom:fold-entity-row
how_header_toggle: false
show_header_toggle: false

Déclaration de entités:

  • sensor.ecocompteur_ecs: est le sensor de mesure de puissance du BECS
####################################################
#                                                  #
#              EAU CHAUDE SANITAIRE                #
#                                                  #
####################################################

input_select:
  ecs_ssol:
    name: Ecs_SSol
    icon: mdi:water-boiler
    options:
      - Auto
      - At Forcé
      - Ma Forcée

input_boolean:
  ecs_av_pv:
    name: Ecs PV(=1 avec Routeur PV)
  
sensor:
# Affichage du temps de fonctionnement ce jour
  - platform: history_stats
    name: ECS Chauffage ce jour
    entity_id: binary_sensor.ecs_chauffe
    state: 'on'
    type: time
    start: '{{ now().replace(hour=0).replace(minute=0).replace(second=0) }}'
    end: '{{ now() }}'


template:
####################################
# Si puissance superieur à 500w = ECS en Marche
  - binary_sensor:
    - name: "ecs_chauffe"
      unique_id: "ecs_chauffe"
      device_class: heat
      state: >-
          {% set a=states('sensor.ecocompteur_ecs')|float(default=0) %}
          {{ a > 500 }}

# 
  - sensor:

############################################ 21/12/2022
# sensor.ecocompteur_ecs:
# Si switch.cde_relais_ecs->
#   template: sensor.puissance_ecs_reseau_w->
#     template: sensor.puissance_ecs_reseau_kw
#     Integration en kW: sensor.energie_ecs_reseau->
#       utility_meter: energy_ecs_reseau_usage_daily->
#          sensor.energy_ecs_reseau_usage_daily_hp
#          sensor.energy_ecs_reseau_usage_daily_hc 

# Si switch.cde_relais_ecs_router_pv->
#   template: sensor.puissance_ecs_pv_w->
#     template: sensor.puissance_ecs_pv_kw
#     Integration en kW: sensor.energie_ecs_pv->
#       utility_meter: energy_ecs_pv_usage_daily->
#          sensor.energy_ecs_pv_usage_daily_hp
#          sensor.energy_ecs_pv_usage_daily_hc 

# Calcul puissance ECS si mode réseau
# L'integrale de rieumman et les utily_meter sont déclarés dans "/config/helpers"
    - name: puissance_ecs_reseau_w
      unique_id: "puissance_ecs_reseau_w"
      device_class: "power"
      state_class: "measurement"    
      unit_of_measurement: "W"
      state: >-
        {% set pu_ecs=states('sensor.ecocompteur_ecs')|float(default=0) %}
        {% set rel_ecs=states('switch.cde_relais_ecs')%}
        {% if (pu_ecs>0) and (rel_ecs=="on")%}          
          {{ pu_ecs }}
        {%else%}
          0
        {%endif%}

    - name: puissance_ecs_reseau_kw
      unique_id: "puissance_ecs_reseau_kw"
      device_class: "power"
      state_class: "measurement"    
      unit_of_measurement: "kW"
      state: >-
        {% set p=states('sensor.puissance_ecs_reseau_w')|float(default=0) %}
        {{ p/1000 }}

    - name: "energie ecs reseau jour"
      unique_id: "energie_ecs_reseau_jour"
      state: >-
        {% set p = states('sensor.energy_ecs_reseau_usage_daily_hp') | float(default=0) | round(2) %}
        {% set o = states('sensor.energy_ecs_reseau_usage_daily_hc') | float(default=0) | round(2) %}
        {{ (o + p) | round(2) }}
      unit_of_measurement: "kWh"
      device_class: "energy"
      state_class: "total"

# Calcul puissance ECS si mode PV
    - name: puissance_ecs_pv_w
      unique_id: "puissance_ecs_pv_w"
      device_class: "power"
      state_class: "measurement"    
      unit_of_measurement: "W"
      state: >-
        {% set pu_ecs=states('sensor.ecocompteur_ecs')|float(default=0) %}
        {% set rel_ecs=states('switch.cde_relais_ecs_router_pv')%}
        {% if (pu_ecs>0) and (rel_ecs=="on")%}          
          {{ pu_ecs }}
        {%else%}
          0
        {%endif%}
        
    - name: puissance_ecs_pv_kw
      unique_id: "puissance_ecs_pv_kw"
      device_class: "power"
      state_class: "measurement"    
      unit_of_measurement: "kW"
      state: >-
        {% set p=states('sensor.puissance_ecs_pv_w')|float(default=0) %}
        {{ p/1000 }}

    - name: "Energie ecs pv jour"
      unique_id: "energie_ecs_pv_jour"
      state: >-
        {% set p = states('sensor.energy_ecs_pv_usage_daily_hp') | float(default=0) | round(2) %}
        {% set o = states('sensor.energy_ecs_pv_usage_daily_hc') | float(default=0) | round(2) %}
        {{ (o + p) | round(2) }}
      unit_of_measurement: "kWh"
      device_class: "energy"
      state_class: "total"

# Cumul de Energie ECS Reseau et PV
    - name: "Energie ECS Jour"
      unique_id: "energie_ecs_jour"
      state: >-
        {% set p = states('sensor.energie_ecs_reseau_jour') | float(default=0) | round(2) %}
        {% set o = states('sensor.energie_ecs_pv_jour') | float(default=0) | round(2) %}
        {{ (o + p) | round(2) }}
      unit_of_measurement: "kWh"
      device_class: "energy"
      state_class: "total"  


###########################################################


# Puissance produite en surplus et injectée dans l'ECS en mode PV en W 
    - name: puissance_ecs_surplus_injectee_w
      unique_id: "puissance_ecs_surplus_injectee_w"
      device_class: "power"
      state_class: "measurement"    
      unit_of_measurement: "W"
      state: >-
        {% set pu_ecs=states('sensor.ecocompteur_ecs')|float(default=0) %}
        {% set prod=states('sensor.envoy_122103023124_current_power_production')|float(default=0) %}
        {% set rel_ecs=states('switch.cde_relais_ecs_router_pv')%}
        {% if (pu_ecs>0) and (prod>10) and (rel_ecs=="on")%}          
          {{ pu_ecs }}
        {%else%}
          0
        {%endif%}


# Puissance produite en surplus et injectée dans l'ECS en mode PV en kW 

    - name: puissance_ecs_surplus_injectee
      unique_id: "puissance_ecs_surplus_injectee"
      device_class: "power"
      state_class: "measurement"    
      unit_of_measurement: "kW"
      state: >-
        {% set a=states('sensor.puissance_ecs_surplus_injectee_w')|float(default=0) %}
        {% if (a>0) %}          
          {{ a/1000 }}
        {%else%}
          0
        {%endif%}

# Puissance disponible sans routeur ecs
# Utilisé dans esp141-affichage_pv
    - name: puissance_dispo_sans ecs
      unique_id: "puissance_dispo_sans_ecs"
      device_class: "power"
      state_class: "measurement"    
      unit_of_measurement: "W"
      state: >-
        {% set pu_ecs=states('sensor.ecocompteur_ecs')|float(default=0) %}
        {% set prod=states('sensor.envoy_122103023124_current_power_production')|float(default=0) %}
        {% set conso = states('sensor.envoy_122103023124_today_s_energy_consumption') | float(default=0) | round(2) %}        
        {% set rel_ecs=states('switch.cde_relais_ecs_router_pv')%}
        {% if (prod>conso) and (pu_ecs>0) and (rel_ecs=="on")%}          
          {{ prod-conso+pu_ecs }}
        {%else%}
          0
        {%endif%}



Conclusion:

Ca peut paraître un peu compliqué pour certain, mais tout n’est pas à prendre, surtout si vous n’avez pas de batteries, dans ce cas il faut modifier l’automatisme

4 Comments on “HA-Gestion Eau Chaude Sanitaire”

  1. Bonjour rem81
    C’est exactement le sujet que je souhaite mettre en place, via un power router (et un dimmer de chez Robotdyn).
    C’est effectivement assez compliqué pour les modestes compétences mais j’aime apprendre 🙂 Et là je me régale :))
    Si j’ai bien compris, tu as un article à venir pour le routeur…parceque là je suis perdu pour le p pilotage… Et comment tu gères les variations de production PV et/ou de consommation?
    Merci pour tous ces partages d’expérience

    1. Bonjour
      L’article sur le routeur concernera le P’TitWat, c’est celui que j’utilise depuis plusieurs mois maintenant. Quand à la gestion des variations de production/consommation, c’est le role du routeur. Quand il détecte un courant inverse en entrée de réseau, ce qui signifie que tu injecte sur le réseau, le routeur pilote laisse passer une quantité de puissance vers le ballon, du coup l’injection va diminuée pour redevenir du soutirage, le routeur va fermer le robinet vers le ballon, et tu repasse en soutirage, etc.. Le routeur une fois bien réglé va piloté la puissance du ballon pour être autour du zero injection/consommation, c’est automatique tu le laisses faire le job.

      1. Merci pour ton retour
        Ma question portait plus sur le pilotage du router via HA.
        J’explique mon cas particulier : je suis en triphasé, donc les solutions « classique », comme celle du power router P’TiWATT, qui s’appuyent sur 1 seul capteur de courant et de tension ne peut être mis en oeuvre puisqu’il faut « surveiller » les 3 phases.
        Mon idée, et étant donné que j’ai déjà une surveillance de mes 3 phases (via un Shelly 3EM), c’est de piloter le dimmer directement DEPUIS HA. Si je fais la somme algébrique des 3 phases, j’obtiens le profil Consommateur (si >0) ou Excédentaire (si <0). Si je suis Excédentaire, j'envoi au dimmer la quantité en trop (via l'intégration ESPHome AC Dimmer component).
        Déjà, est-ce correct ? Et si oui 😉 reste la difficulté pour moi de faire sous HA le bon échantillonnage pour écrêter ou faire la moyenne sur les x dernières minutes.

        1. Bonjour. C’est à essayer, je préconiserai de traiter l’info des shelly directement dans l’ESP afin d’être le plus réactif possible, je ne sais pas si tu peux faire communiquer ton shelly directement avec ESP sans passer par HA

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.