PV-Routeur Solaire ESP Home

Intro

Dans un article précédent, je décrivais une première version de routeur PV monté sur la base d’une mesure de puissance tiers, dans mon cas, délivrée par mon onduleur Victron, et un pilotage de Triac via esp8266 délocalisé.

Dans cette version je vous propose un montage développé sous ESP Home donc complètement intégré à HA.

Mise à Jour:

  • 26/03/2024 – V1.2.0: Ajout calcul relais de suproduction
  • 25/03/2024 – V1.1.0: Nettoyage du code: Suppression Switch val routeur et Pmin
  • 01/08/2023 – V1.0.0: Remplacement de de « restore_value » par « restore_mode » dans les « switch » suite à rupture dans la version 2023-07 ESPHOME.

Liste des courses:

Dans cette version vous aurez besoin à minima:

nota: les liens sont donnés à titre d’exemple, je n’ai aucune relation commerciale avec ces vendeurs

  • Un ESP32
  • Une sonde de température Dallas ds18b20.
  • En option, et je vous le conseille, prenez un afficheur comme celui-ci:

Vous pouvez choisir d’autres modèles, mais il vous faudra modifier le code.

  • Un relais de délestage de surproduction:
  • Ou un relais Tout ou Rien 5V:

Principe de fonctionnement

La pince du module JSY est connectée en tête de votre tableau électrique principal en sortie de Linky, il mesure en permanence plusieurs grandeurs électriques, mais les deux qui nous intéressent principalement sont la mesure de puissance et le sens du courant dans la pince. L’ESP interroge en permanence (toutes les 750ms) le module via un port UART sous le protocole Modbus.

Avec ces deux grandeurs, l’ESP calcule le niveau de charge du triac sur une échelle de 0 à 100%.

Par convention , la puissance injectée sur le réseau est négative et la puissance soutirée est positive.

Donc plus la puissance est négative plus on ouvre le triac, on tend vers les 100%. L’algorithme retenu est plutôt simple: S= S+P*Coeff/1000 avec S la sortie triac, P, la puissance mesurée et Coeff un coefficient de réactivité.

A chaque lecture de la puissance la sortie S vers le triac est incrémentée ou décrémentée selon le signe de la puissance mesurée. Le coefficient « Coeff » rend l’algorithme plus ou moins réactif, il faut trouver le bon compromis pour une plus grande réactivité sans entrer dans un système oscillatoire.

La Partie Matérielle

Schéma Electronique:

Dans le schéma électronique qui suit vous retrouverez le câblage des différents éléments, vous y trouverez également des éléments non programmés comme le Triac 2 et le relais, c’est en prévision d’extension logicielle.

Modification du refroidissement du triac

Si vous souhaitez exploiter pleinement les capacités de votre triac 24A vous devez remplacer le refroidisseur en aluminium d’origine par un refroidisseur plus important.

La modification est clairement expliquez par le prof’solaire dans cette video.

La partie logicielle:

Capteur JSY-MK-194T

Ce module communique en modbus via un port serie. Il permet de remonter de nombreuses grandeurs physiques électriques via un tore déporté, avec lequel je mesure la puissance soutirée ou injectée sur le réseau, placé directement en sortie Linky, et un tore soudé sur la carte, avec lequel je mesure la puissance soutirée par l’ECS (Ballon Eau Chaude Sanitaire).

Sur chaque Tore, vous pouvez lire, la puissance, l’intensité, la tension, la fréquence, l’énergie.

Vous remarquez que la trame Modbus lit la totalité des grandeurs physiques du JSY (14 registres), cela optimise le temps de lecture en n’envoyant qu’une seule trame Modbus, le fait de supprimer des registres, segmenterai les trames et augmenterai le temps de réponse,cela étant, je n’affiche pas toutes les grandeurs mais libre à vous de les visualiser.

J’interroge le module toutes les 750 ms, ce qui donne une réactivité du système plutôt satisfaisante, en dessous, je rencontre des erreurs de lecture.

Vous trouverez ci après le descriptif des trames modbus du capteur:

Afin que le capteur JSY soit plus réactif, il faut augmenter sa vitesse de communication à 38400 bauds qui par défaut est à 4800 bauds.

La manipulation est très bien décrite sur le site du prof’Solair. Perso, j’ai utilisé le logiciel Windows et ce convertisseur USB<->Port série

Codage ESP

Vous trouverez ci après le code de l’ESP, c’est en service depuis quelques semaines avec des résultats très satisfaisants.

substitutions:
  device_name: "esp176-esp32-routeur-1r"
  friendly_name: esp176
  adress_ip: "192.168.0.176"
  time_timezone: "Europe/Paris"
  
esphome:
  name: ${device_name}
  platform: ESP32
  board: esp32dev
  project:
    name: "rem81.esp176-esp32-routeur"
    version: "1.2.0"
  on_boot:
    priority: 800
    # Force mode auto et temperature ok au demarrage
    then: 
      - switch.turn_on: modeauto
      - binary_sensor.template.publish:
          id: temperatureok
          state: ON

wifi:
  networks:
    - ssid: !secret wifi
      password: !secret mdpwifi
  reboot_timeout: 5min

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

# Enable logging
logger:
  baud_rate: 0
  level: DEBUG
  # level: INFO

api:

ota:

web_server:
  port: 80

# Protocole afficheur
i2c:
  sda: GPIO21 
  scl: GPIO22
  scan: True
  id: bus_a

# Protocole du JSK
uart:
  id: mod_bus
  tx_pin: 17
  rx_pin: 16
  baud_rate: 38400
  stop_bits: 1
#  debug:
#    direction: BOTH
#    dummy_receiver: false
#    after:
#      timeout: 150ms
#    sequence:
#      - lambda: |-
#          UARTDebug::log_string(direction, bytes);

modbus:
#flow_control_pin: 5
  #send_wait_time: 200ms
  id: modbus1

modbus_controller:
  - id: jsymk
    ## the Modbus device addr
    address: 0x1
    modbus_id: modbus1
    update_interval: 0.75s
    command_throttle: 50ms
    
    # setup_priority: -10

globals:
   - id: increment
     type: float
     restore_value: no
     initial_value: '0'
   - id: striac
     type: float
     restore_value: yes

# Sonde Temperature Dallas
dallas:
  - pin: GPIO27 #
    update_interval: 60s

# Informations supplementaires sur le WIFI
#text_sensor:
#  - platform: wifi_info
#    ip_address:
#      name: ${friendly_name}_ESP IP Address
#    ssid:
#      name: ${friendly_name}_ESP Connected SSID
#    bssid:
#      name: ${friendly_name}_ESP Connected BSSID
#    mac_address:
#      name: ${friendly_name}_ESP Mac Wifi Address
#    scan_results:
#      name: ${friendly_name}_ESP Latest Scan Results


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

# Temperature triac OK
  - platform: template
    name: "${friendly_name} Temp Ok"
    id: temperatureok

# Validation du routeur à déclarer dans HA
  - platform: homeassistant
    name: "Validation Routeur"
    entity_id: "input_boolean.inter_validation_routeur"
    id: val_routeur    

# Input Number
number:
  # Seuil Max sortie triac
  - platform: template
    name: "${friendly_name} P Max"
    id: pmax
    optimistic: true
    restore_value: true
    mode: box
    min_value: 50
    max_value: 100
    unit_of_measurement: "%"
    step: 1

# Seuil MAX temperature
  - platform: template
    name: "${friendly_name} T Max"
    id: tmax
    optimistic: true
    restore_value: true
    mode: box
    min_value: 0
    max_value: 75
    unit_of_measurement: "C°"
    step: 0.1

# Coeff Réactivité
  - platform: template
    name: "${friendly_name} Coeff R"
    id: coeff_r
    optimistic: true
    restore_value: true
    mode: box
    min_value: 0
    max_value: 10
    unit_of_measurement: ""
    step: 0.1


sensor:  

# tension de l'alimentation
  - platform: modbus_controller
    modbus_controller_id: jsymk
    id: Tension
    #name: "${friendly_name} Tension JSYMK"
    address: 0x0048
    unit_of_measurement: "V"
    register_type: holding
    value_type: U_DWORD
    accuracy_decimals: 1
    filters:
      - multiply: 0.0001
    register_count: 1
    response_size: 4

# Intensité traversant le tore
  - platform: modbus_controller
    modbus_controller_id: jsymk
    id: Itore
    name: "${friendly_name} I_ECS JSYMK"
    address: 0x0049
    unit_of_measurement: "A"
    register_type: holding
    value_type: U_DWORD
    accuracy_decimals: 1
    filters:
      - multiply: 0.0001
    register_count: 1
    response_size: 4

# Puissance traversant le tore
  - platform: modbus_controller
    modbus_controller_id: jsymk
    id: puecs
    name: "${friendly_name} P_ECS JSYMK"
    address: 0x004A
    unit_of_measurement: "W"
    register_type: holding
    value_type: U_DWORD
    accuracy_decimals: 1
    filters:
      - multiply: 0.0001
    register_count: 1
    response_size: 4

# Energie lue dans le tore
  - platform: modbus_controller
    modbus_controller_id: jsymk
    id: energietore
    name: "${friendly_name} Energie ECS JSYMK"
    address: 0x004B
    unit_of_measurement: "kWh"
    register_type: holding
    value_type: U_DWORD
    accuracy_decimals: 1
    filters:
      - multiply: 0.0001
    register_count: 1
    response_size: 4

# FP lue dans le tore
  - platform: modbus_controller
    modbus_controller_id: jsymk
    id: fptore
    #name: "${friendly_name} FP Tore JSYMK"
    address: 0x004C
    register_type: holding
    value_type: U_DWORD
    accuracy_decimals: 1
    filters:
      - multiply: 0.0001
    register_count: 1
    response_size: 4

# Energie NEG lue dans le tore
  - platform: modbus_controller
    modbus_controller_id: jsymk
    id: energietoren
    name: "${friendly_name} Energie ECS Neg JSYMK"
    address: 0x004D
    unit_of_measurement: "kWh"
    register_type: holding
    value_type: U_DWORD
    accuracy_decimals: 1
    filters:
      - multiply: 0.0001     
    register_count: 1
    response_size: 4 
# Sens du courant dans la pince
  - platform: modbus_controller
    modbus_controller_id: jsymk
    id: senspince
    #name: "${friendly_name} Sens_Pince JSYMK"
    address: 0x004E
    register_type: holding
    value_type: U_DWORD
    bitmask: 0X00010000
    filters:
      - multiply: 1
    register_count: 1
    response_size: 4
# Sens du courant dans le tore
  - platform: modbus_controller
    modbus_controller_id: jsymk
    id: senstor
    #name: "${friendly_name} Sens_Tore JSYMK"
    address: 0x004E
    register_type: holding
    value_type: U_DWORD
    accuracy_decimals: 0
    bitmask: 0X01000000
    filters:
      - multiply: 1
    register_count: 1
    response_size: 4

# Fréquence de l'alimentation  
  - platform: modbus_controller
    modbus_controller_id: jsymk
    id: frequence
    #name: "${friendly_name} Frequence JSYMK"
    address: 0x004F
    unit_of_measurement: "hz"    
    register_type: holding
    value_type: U_DWORD
    accuracy_decimals: 1
    filters:
      - multiply: 0.01
    register_count: 1
    response_size: 4

# tension de l'alimentation
  - platform: modbus_controller
    modbus_controller_id: jsymk
    id: Tension2
    #name: "${friendly_name} U_Reseau JSYMK"
    address: 0x0050
    unit_of_measurement: "V"
    register_type: holding
    value_type: U_DWORD
    accuracy_decimals: 1
    filters:
      - multiply: 0.0001
    register_count: 1
    response_size: 4
    
# Intensité lue dans la pince
  - platform: modbus_controller
    modbus_controller_id: jsymk
    id: Ireseau
    #name: "${friendly_name} I_Reseau JSYMK"
    address: 0x0051
    unit_of_measurement: "A"
    register_type: holding
    value_type: U_DWORD
    accuracy_decimals: 1
    filters:
      - multiply: 0.0001
    register_count: 1
    response_size: 4

# puissance lue dans la pince
  - platform: modbus_controller
    modbus_controller_id: jsymk
    id: pureseau
    #name: "${friendly_name} P_Reseau JSYMK"
    address: 0x0052
    unit_of_measurement: "W"
    register_type: holding
    value_type: U_DWORD
    accuracy_decimals: 1
    filters:
      - multiply: 0.0001
    register_count: 1
    response_size: 4 
    on_value:
      then:
        - lambda: |-
            if ( id(senspince).state == 1 ) {
              id(pureseau1).publish_state( id(pureseau).state *-1);
            } else {
              id(pureseau1).publish_state( id(pureseau).state );
            }

    
# Energie lue dans la pince
  - platform: modbus_controller
    modbus_controller_id: jsymk
    id: energiepince
    #name: "${friendly_name} Energie Reseau JSYMK"
    address: 0x0053
    unit_of_measurement: "kWh"
    register_type: holding
    value_type: U_DWORD
    accuracy_decimals: 1
    filters:
      - multiply: 0.0001
    register_count: 1
    response_size: 4

# Energie lue dans le tore
  - platform: modbus_controller
    modbus_controller_id: jsymk
    id: fppince
    #name: "${friendly_name} FP Pince JSYMK"
    address: 0x0054
    register_type: holding
    value_type: U_DWORD
    accuracy_decimals: 1
    filters:
      - multiply: 0.0001
    register_count: 1
    response_size: 4

# Energie NEG lue dans le tore
  - platform: modbus_controller
    modbus_controller_id: jsymk
    id: energienegpince
    #name: "${friendly_name} Energie ECS Neg JSYMK"
    address: 0x0055
    unit_of_measurement: "kWh"
    register_type: holding
    value_type: U_DWORD
    accuracy_decimals: 1
    filters:
      - multiply: 0.0001     
    register_count: 1
    response_size: 4 
    
# Informations WI_FI
  - platform: wifi_signal # Affiche le signal WiFi strength/RSSI en dB
    name: "${friendly_name} WiFi Signal dB"
    id: wifi_signal_db
    update_interval: 60s
    entity_category: "diagnostic"

  - platform: copy # Affiche le signal WiFi strength en %
    source_id: wifi_signal_db
    name: "${friendly_name} WiFi Signal Percent"
    filters:
      - lambda: return min(max(2 * (x + 100.0), 0.0), 100.0);
    unit_of_measurement: "Signal %"
    entity_category: "diagnostic"

############### TEMPLATE  ######################"
# Affichage dans HA et sur l'afficheur
  - platform: template
    name: "${friendly_name} Pu Reseau"
    id: pureseau1
    unit_of_measurement: "W"
    state_class: "measurement"  
 
  - platform: template
    name: "${friendly_name} Increment"
    id: afincrement
    unit_of_measurement: ""
    accuracy_decimals: 2
    state_class: "measurement"

  - platform: template
    name: "${friendly_name} Sortie Triac"
    id: afstriac
    unit_of_measurement: "%"
    state_class: "measurement"  
    accuracy_decimals: 2

# Sonde Temperature radiateur
  - platform: dallas
    address: 0xeb012112e461b128
    name: "${friendly_name} Temp triac"
    id: temp_triac
    filters:
      - filter_out: NAN
    on_value:
      then:
        if:
          condition:
            lambda: 'return id(temp_triac).state < id(tmax).state;'
        # Si Temp Triac inferieur au seuil alors OK
          then:
            - binary_sensor.template.publish:
                id: temperatureok
                state: ON
        # Sinon attendre 60s avant retour à la normal
          else:
            - binary_sensor.template.publish:
                id: temperatureok
                state: OFF
            - delay: 60s
 
switch:
  - platform: gpio
    name: "${friendly_name} Relais"
    pin: GPIO5
    id: relais

  - platform: template
    name: "${friendly_name} Mode Auto"    
    id: modeauto
    optimistic: true
    restore_mode: always_on

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

output:
#LEDS --------------------------------------
  - id: led_conso
    platform: gpio
    pin: GPIO32
    
  - id: led_injec
    platform: gpio
    pin: GPIO25
# Pilotage du Dimmer ------------------------
  - platform: ac_dimmer
    id: ecs
    gate_pin: GPIO33
    method: leading
    zero_cross_pin:
      number: GPIO34 
      mode:
        input: true
      inverted: yes
    min_power: 5%

light:
  - platform: monochromatic
    name: "${friendly_name}+STriac"
    output: ecs
    id: gradateur
    default_transition_length: 50ms

# Affichage
display:
  - platform: lcd_pcf8574
    dimensions: 20x4
    address: 0x27
    update_interval: 2s
    lambda: |-
      it.printf(0,0,"Pr=%0.0fW",id(pureseau1).state);
      it.printf(10,0,"Pe=%0.0fW ",id(puecs).state);
      it.printf(0,1,"Tr=%0.1f%%",id(striac));
      it.printf(10,1,"Val:%s", id(val_routeur).state ? "OK" : "NOK");
      it.printf(0,2,"Tp=%0.1fc", id(temp_triac).state);
      it.printf(10,2,"Etat=%s", id(temperatureok).state ? "OK" : "NOK");
      it.printf(0,3,"Mode=%s", id(modeauto).state ? "Auto" : "Manu");
      it.printf(10,3,"Inc=%0.1f ",id(increment)); 

interval:
  - interval: 1s
    then:
      - script.execute: calcul_injection

  - interval: 2s
    then:
      - script.execute: etat_production 

# Script activation relais si le triac est au max pendant x sec
  - interval: 60s
    then:
      - script.execute: calcul_relais_surprod      

# ------------------------  Scripts
script:
# 
# ------------------------ Calcul puissance injection 
  - id: calcul_injection
    mode: single
    then:
      - lambda: |-
         id(increment) = id(pureseau1).state*id(coeff_r).state/1000*-1;
 
      - lambda: |-
         id(striac) = id(striac)+id(increment);            
               
          if (!isnan(id(striac))) {
            id(striac) = id(striac)+id(increment);
          }else{
            id(striac)=0;
            }

          if (id(striac) <= 0){
            id(striac) = 0;
          } else if(id(striac)>=id(pmax).state){
            id(striac) = id(pmax).state;
          }        
      - logger.log:
          format: "Log S Triac %f - Increment %f"
          args: [ 'id(striac)', 'id(increment)' ]
          level: "info"
      

      # Si Routeur Validé et mode auto et temperature ok alors on active le triac
      - if: 
          condition:
            and:
              - binary_sensor.is_on: val_routeur
              - switch.is_on: modeauto
              - binary_sensor.is_on: temperatureok
        

          then:
              - light.turn_on:
                  id: gradateur
                  brightness: !lambda |-
                    return id(striac)/100 ;
              - logger.log:
                  format: "Log Auto OK STriac %f - Increment %f"
                  args: [ 'id(striac)', 'id(increment)' ]
                  level: "info"         

      # Si mode routeur devalidé ou temp NOK alors on désactive le triac 
      - if: 
          condition:
            and:
              - switch.is_on: modeauto
              - or:
                - binary_sensor.is_off: val_routeur
                - binary_sensor.is_off: temperatureok                    
                   
          then:
            - lambda: |-
                id(striac) = 0;
                id(increment) = 0;
            - light.turn_off: gradateur
            - logger.log:
                format: "Log Auto NOk STriac %f - Increment %f"
                args: [ 'id(striac)', 'id(increment)' ]
                level: "info"                         


      # Si mode routeur manu
      - if: 
          condition:
            and:
              - switch.is_off: modeauto
          then:
            - lambda: |-
                id(striac) = 0;
                id(increment) = 0;
            - logger.log:
                format: "Log Manu STriac %f - Increment %f"
                args: [ 'id(striac)', 'id(increment)' ]
                level: "info"                         
    # Affichage STriac et Increment
      - lambda: |-
            id(afstriac).publish_state( id(striac) );
            id(afincrement).publish_state( id(increment) );

      - logger.log:
          format: "Log Fin STriac %f - Increment %f"
          args: [ 'id(striac)', 'id(increment)' ]
          level: "info"

# -------------------------------------------  Pilotage led
  - id: etat_production
    mode: single
    then:
     - if: 
         condition:
           sensor.in_range:
              id: pureseau1
              below: 50
              above: -50
         then:
           - output.turn_on: led_conso
           - output.turn_on: led_injec
                
     - if: 
         condition:
           sensor.in_range:
             id: pureseau1
             above: 50
         then:
           - output.turn_off: led_injec
           - output.turn_on: led_conso

     - if: 
         condition:
           sensor.in_range:
             id: pureseau1
             below: -50
         then:
          - output.turn_off: led_conso
          - output.turn_on: led_injec

# Calcul du relais de surproduction
  - id: calcul_relais_surprod
    mode: single
    then:
     # Si sortie triac > pmax-5%, ce qui signifie que le triac est au max sans effet, pendant plus de 30s
     # alors on active le relais
     # si triac <= 0 alors on desactive le relais
      - if: 
          condition:
            - lambda: 'return id(striac)>=id(pmax).state-5;'
          then:
            - delay: 30s
            - switch.turn_on: relais
            - logger.log: "Relais Activé"
      - if: 
          condition:
            - lambda: 'return id(striac)<=0;'
          then:
            - switch.turn_off: relais
            - logger.log: "Relais Désctivé"
      
    
    

Paramètres:

Vous pouvez régler:

  • La puissance maximum que peut délivrer le triac. Je l’ai limité à 80% ce qui correspond à 2000 W dans mon cas (Ballon ECS de 300l). Pour l’estimer au mieux, passer en mode MANUEL et augmenter progressivement la sortie triac tout en visualisant l’intensité absorbée par l’ECS, perso je me limite à 10/11A. Au delà le triac monte trop en température.
  • la puissance minimum: Valeur en dessous laquelle le triac ne donne rien
  • le coefficient R (réactivité): Voir explication dans « Principe de Fonctionnement ».
  • la température maximum du refroidisseur du triac: Si supérieure à ce seuil, met la sortie triac à 0%.

Vous pouvez piloter:

  • L’interrupteur de validation du routeur: Déclaré et programmé dans HA
  • Définir le seuil PMAX pour ne pas trop solliciter le TRIAC
  • Définir le coefficient R (Réactivité)
  • Définir la Température MAX du triac
  • Le relais de délestage
  • Un mode Manuel/Auto: Manuel vous donne la possibilité de piloter la sortie triac.
  • Le triac.

Grandeurs physiques:

Vous retrouverez:

  • Dans mon cas j’affiche la température de l’ECS, mesurée avec un autre ESP, voir cet article.
  • La puissance soutirée ou injectée sur le réseau.
  • La puissance et l’intensité de l’ECS.
  • La valeur de l’incrément.
  • La sortie Triac.
  • L’énergie soutirée par l’ECS sur le réseau.
  • L’énergie économisée par le routeur par jour et totale. L’énergie par jour est calculée dans une entrée HA: voir mon article https://domo.rem81.com/2022/06/06/ha-compteur-de-service-utility-meter/.
  • L’état du binary-sensor: température Ok.
  • La température du triac.

Automatisation:

Le fonctionnement routeur est validé par un input_number déclaré dans HA.

La validation du routeur dépend de votre configuration: Si votre installation solaire ne comporte pas de batteries, vous pouvez vous inspirer de cet article https://domo.rem81.com/2022/11/25/ha-gestion-eau-chaude-sanitaire/. Depuis cet article, mon installation PV a évoluée avec l’ajout de batteries de stockage, depuis leur mise en service je valide le routeur lorsque les batteries sont chargées.

Plus simplement, vous pouvez le valider entre le levé et le couché du soleil.

Relais Delestage:

Dans mon programme, j’utilise le GPIO5 mais d’autres GPIO sont disponibles pour cet usage, cet article les décrits parfaitement.

Toutes les minutes, on teste si le triac est au maximum pendant plus de 30s alors on active le relais de délestage sinon on le désactive

Affichage Local:

Localement j’affiche:

  • Pr: Puissance sur le réseau (sortie Linky)
  • Pe: Puissance Absorbée par le ballon ECS
  • Tr: Valeur pilotage triac
  • Val: Routeur Validée
  • Tp: Température triac
  • Etat: OK si Température Triac inférieur au seuil sinon NOK
  • Mode: Automatique ou Manuel
  • Inc: Valeur de l’incrementCapture d’écran du 2024-03-26 11-28-57
  • LED Rouge et Jaune allumées: Puissance Réseau entre -50 et 50 W
  • LED Rouge allumée et Jaune éteinte: On rejette plus de 50 W sur le réseau
  • LED Rouge éteinte et Jaune allumée: On soutire plus de 50 W sur le réseau
  • LED Verte allumée: Coffret sous tension

Résultats:

La courbe ci dessous (extraite de Graphana) illustre l’efficacité et la réactivité du routeur. Ce jour là, à partir de 15:45 l’ECS ne chauffe plus, il a atteint ses 70°C, conclusion: on injecter sur le réseau.

Le graphique suivant illustre les économies réalisées en kWh, les jours à 0 sont dû à un faible ensoleillement, dans mon cas je privilégie la charge des batteries avant de router vers l’ECS.

Liens vers des routeurs à monter soi-même:

Bien entendu cette liste est non exhaustive, si vous avez d’autres liens, n’hésiter pas à me les transmettre, je les ajouterai.

Conclusion

Un routeur solaire de plus! Celui ci est complément intégré à Home Assistant, et en plus il coûte pas trop cher. N’hésitez par me faire par de vos remarques.

45 Comments on “PV-Routeur Solaire ESP Home”

  1. Tres beau projet 🙂
    Bravo

    Avec le recul, vous êtes satisfait du JSY-MK-194T. ?
    il peut lire en négatif contrairement au pzem004t si je comprends bien.
    vous avez hésité avec un autre dispositif ?

    merci

    1. Bonjour
      Le JSY répond à mes attentes, facilement intégrable dans ESPHome, je n’en connais pas d’autre qui mesure la puissance dans les deux sens à ce prix là, il convient parfaitement pour ce type d’application. Le PZEM que j’utilise par ailleurs pour mesurer des puissances et des énergies sans donner le sens du courant répondent également à mes besoins.

      1. Bonsoir,
        il existe des compteurs++ comme le SDM120CT de Eastron que j’ai testé, mais le JSY-MK-194T a un avantage indéniable, il a deux voies!

  2. Salut @rem81,

    tout d’abord merci pour ton portage sur EspHome cependant je voulais te demander s’il y avait la possibilité de découper en 2 parties ton routeur. Je m’explique : Mon tableau principal est à l’opposé de ma piscine, disposant d’une résistance chauffante ON/OFF sur celle-ci mais ne disposant de qu’une seule arrivée électrique pour l’ensemble pompe + lumière + résistance, l’idée serait d’avoir 2 esphome, une partie mesure avec pince ampèremétrique au niveau du tableau, la seconde au niveau de la piscine, les deux étant intimement lié. En cas de rupture de communication entre les deux ou de figeage de la partie mesure, la sortie du routeur se mettrait automatiquement à zéro.

    En espérant avoir été claire sur mon besoin.

  3. Bonjour
    Est ce possible d’utiliser les valeurs d’un shelly em remontées à home assistant au lieu d’un Capteur JSY-MK-194T branché directement sur l’esp32 ?
    Merci

    1. Bonjour, je ne sais pas, j’ n(utilise pas de shelly mais il faut que le capteur indique le sens du courant (puissance négative en injection et positive en soutirage) et soit suffisamment réactif (moins d’un seconde. Cdlt

      1. Avec plasir…. On est en train de travailler sur le PVbrain 2.0, notamment avec un routeur solaire intégré (Ongrid-AC/Offgrid-DC)… Pour la partie AC on voulait exactement utilisé ce composant et réguler en PID.

    1. Oui, je comptabilise les Kwh dans HA, je les déclare dans le config/helpers « compteurs de service publics..’. je comptabilise également la puissance routée dans l’ECS, via la voie 2 du JSK.

  4. Bonjour,

    Tout d’abord un immense merci pour ce routeur via esphome, je suis débutant en tout et j’y suis parvenu !! J’ai une petite question, si je me rends sur le web server de esp il y a un slider de 0 à 255 sous la sortie +STriac, celui ci permet de gérer en mode manuel l’ouverture du triac ce qui est très pratique je trouve.
    Ce slider n’existe pas via l’intégration esphome dans HA, j’ai cherché et fait divers test mais je ne suis pas parvenu à avoir un slider fonctionnel dans HA.
    Si vous avez une piste je suis preneur !!!
    En tous cas merci encore pour ce bel article très clair pour un débutant comme moi.
    Bien cordialement,
    Thibaut

    1. Bonjour et merci pour votre retour d’experience. Pour piloter le triac en manu depuis HA, il faut dévalider le mode auto, vous pourrez ensuite agir sur la sortie triac. Cdlt

      1. Je vous remercie pour votre réponse, je me suis mal exprimé je pense.
        Dans HA j’ai bien un switch +STriac qui peut être mis en On et Off lorsque on est en mode manuel.
        En off le triac est à 0% et en On il est à 100%, c’est du tout ou rien.
        Ce que permet le slider ou plutôt le curseur dans le mini serveur web de l’esp, c’est de régler en mode manuel la sortie triac entre 0 et 100%.
        A moins que j’ai raté quelque chose, ce n’est pas faisable dans HA car ce curseur n’y est pas.
        J’ai bien tenté de limiter via Pmax mais cela n’a pas d’influence en mode manuel.
        Difficile d’avoir les bons termes quand on est débutant mais j’apprends, et des articles comme les vôtres sont des plus instructifs !!

        1. Re Bonjour, j’ai bien compris sous HA qd vous cliquez sus switch+triac vous pouvez bouger le curseur dans le sens vertical, je vous envoi une copie d’écran par mail

  5. Le matos vient d’être commandé, hâte de le construire ! ^^
    Merci pour lees différents articles et les partages 🙂

  6. C’est fonctionnel au niveau de la télémétrie du linky mais dans les faits cela ne marche pas car la resistance du cumulus est fixe et le triac est un interrupteur 1/0

  7. Bonjour, merci pour ce beau partage.

    Les images en fin d’article ne sont plus disponibles, de même pour la référence du dissipateur qui m’intéresserait bien 🙂 Pas très grave, mais j’en profite pour le signaler 🙂

    Dans mon cas, j’aimerais bien pouvoir repartir de ce routeur PV en l’adaptant. Je ne sais pas si c’est une bonne idée, mais je pousserais bien à ce qu’il puisse récupérer les mesures de consommation / injection linky depuis mon home assistant (mqtt par exp), au lieu de remettre en place une sonde de mesure sur la phase de l’installation électrique.
    Ce serait sans doute moins réactif car mes mesures teleinfo sont updatées toutes les 5 sec, mais ca pourrait convenir. Ce serait aussi sans doute moins ‘autonome’.
    -> Est-ce que cette piste avait été étudiée ?

    L’autre évolution serait de pouvoir piloter la résistance de mon ECS thermodynamique en complément de son pilotage par le ballon lui même, sans doute via module relais. L’idée serait de pouvoir garder les cycles anti-légionellose que le ballon effectue périodiquement en s’appuyant sans doute sur la résistance électrique en complément du chauffage en mode PAC.

    Merci en tous cas pour ce beau partage qui est une vraie mine d’or 🙂
    Surtout avec ESP home 🙂

    1. Bonjour « Zener », merci pour ton retour d’experience. J’ai mis à jour les images de l’article, suite à la migration de mon site WP vers un nouveau serveur, quelques liens ont sautés. Pour la lecture des infos sur le linky regarde sur ce site, tu devrais trouvé ton bonheur, c’est beaucoup plus complet que mon article! https://f1atb.fr/fr/realisation-dun-routeur-photovoltaique-multi-sources-multi-modes-et-modulaire/ . Pour le ballon thermo, je ne peux pas t’aider, mais je sais que certain ballon ont une entrée dédiée à cette fonction de routage, sinon effectivement, il faut adapter le cablage et « attaquer directement » les resistances, (avec un relais inverseur par exe) tout en gardant les fonctions de sécurité indépendantes de HA, le thermostat par ex. Bon courage @+
      PS: j’ai trouvé cette video, https://www.youtube.com/watch?v=KsaOw1Ar9bc il évoque une résistance d’appoint, c’est peut être sur celle ci qu’il faut envoyer le routage!

  8. Bonjour Remi81,
    Très bon travail. J’ai tenté de faire un routeur solaire également en m’inspirant de quelques ressources sur internet dont ton site. En ce qui me concerne, l’automatisation est gérée par Homeassistant qui mesure le surplus et régule le triac via ESPHOME. Mon Triac est un Robodyn un peu plus gros (le 40a) d’ aliexpress, celui avec le gros radiateur. Ce routeur envoie l’énergie de surplus vers ma dalle électrique chauffante. Cependant, la régulation de 0 à 100% de mon Triac n’est pas du tout linéaire et donc non proportionnelle. J’ai donc énomément de difficultés à réguler mon surplus ( Fonctions d’approximation après avoir effecué des mesures à 0,10,20,30?…100%). J’utilise également la librairie ac_dimmer de esphome. Personne n’ai touché par ce problème ? Toi non plus ?

    1. Bonjour
      Merci pour ton retour d’expérience. J’utilise la librairie ac_dimmer d’origine. Dans cet artcicle, la régulation étant traitée par l’ESP toutes les secondes avec une lecture de la puissance réseau toutes les 750ms, j’assure ainsi une régularité dans le calcul de l’incrément, peut importe la linéarité du dimmer, « l’algorithme » incrément ou décrémente jusqu’à trouver un point d’équilibre.

  9. Et oui, bien sûr… Tu n’as pas besoin de connaitre non plus la puissance de la résistance de l’ECS ou même du chauffage puisque ton alogo « tatonne » en permanence pour être sur le point d’équilibre. Ta méthode est plus pertinente que la mienne. En ce qui me concerne, je me base uniquement sur les retour de l’API de ma passerelle Enphase Metered et de ses 2 tores (conso et prod) et donc beaucoup moins réactif (Toutes les 8/10 secondes). Je pense que je vais ajouter un tore de lecture dans mon installation, ce qui rendra mon système beaucoup plus rapide, et plus autonome.
    Pour info, voici mon dimmer 40A: https://fr.aliexpress.com/item/1005006211999051.html?spm=a2g0o.order_list.order_list_main.93.54655e5bBOQHhM&gatewayAdapt=glo2fra

    En tout cas, merci pour ton retour.

      1. Je connaissais très bien ce site (F1ATB) car c’est l’un des premiers qui m’a inspiré, mais la flemme de reprendre un code déjà tout prêt m’a amené à repartir de 0. Et en plus, je me suis dit que ce serait beaucoup plus facile a faire depuis Home Assistant et Esphome. Grâce à ta remarque consernant l’incrémentation/décrémentation, je me suis repenché sur mon problème et j’ai modifié mon projet. J’ai copié le flow Nodered sur ce Github https://github.com/Maarten234/Enphase-Envoy-D7.0.X-node-red que j’ai collé sur un de mes serveur nodered. J’ai adapté pour publier en mqtt toutes les secondes vers homeassistant. Et me voilà maintenant avec un relevé beaucoup plus précis de ce que produis/consomme sur le réseau électrique. J’ai donc pu changer ma méthode de routage en faisant comme tu l’as dit des incréments/décréments de 1%. Ma dalle est donc alimentée par le surplus et ça macrhe plutot très bien. Bientôt, je renverrais vers l’eau chaude sanitaire dés que l’on sera complètement sortis des jours froids. Merci à toi pour les conseils.

        1. Bonjour, merci pour ces informations, je ne connaissais pas ce github enphase. le couple (NodeRed / MQTT) est une très bonne solution, réactive, et à moindre cout pour ceux qui utilise enphase, je me l’a note dans un coin!
          Encore merci. Slts

  10. Bonjour j’ai installer votre routeur sur mon HA.
    Cependant il ne fonctionne pas en mode Auto, je n’ai pas de sonde sur le triac donc j’ai commenter la ligne « – binary_sensor.is_on: temperatureok » mais il ne se lance pas je ne comprend pas pourquoi. Si vous pouvez m’aider. Merci d’avance.

    1. Bonjour, essayes en supprimant la ligne « – binary_sensor.is_off: temperatureok  » ça doit fonctionner.
      Sinon envoies mois ton fichier log
      Slts

          1. Oui j’avais mis à 100 pour voir mais pour l’instant je suis passer à 10 et je verrais sur le long terme je me suis dit vu que ç a va jusqu’a 1000… Oui j’utilise bien la dernière version je te joints des nouveaux logs : https://uploadnow.io/f/czBJH9y

  11. Ok je vois que tu es en auto
    Commences par une petite valeur pour le coeff (1.5 par ex) tu ajustera par la suite.
    Je vois que ton incrément est négatif. Est ce que tu as bien une valeur négative de la puissance quand tu injecte sur le réseau et une valeur positive quand tu soutires? sinon il faut inverser la pince
    A cette heure tu devrais avoir du positif
    Le principe de régulation est simple:
    increment=puissance reseau * coef r / 1000*-1
    striac= striac+increment.
    si striac < à 0 alors striac=0 si striac>100 alors striac =100.
    Donc si increment<0 alors striac <0 donc striac=0
    L'increment ne doit pas évolué trop rapidement sinon tu vas vite sortir de la fourchette admissible par le triac: 0 à 100.

    1. J’ai une puissance positive quand y a pas de soleil et négative quand j’ai trop de soleil et pas de réinjection quand le routeur est stoppé de ce côté là je pense que c’est bon.
      Je pense que le problème vient de validation routeur qui est bizarrement un binary_sensor et pas un switch je n’ai pas compris pourquoi et dans HA il apparait bien en switch donc je suis perdu sur ce point la. Lorsque je comment toute la partie « si routeur dévalidé » j’arrive bien à mettre en route le routeur. Donc je ne sais pas pourquoi il reste dans cette boucle alors qu’il devrait être dans la boucle « Prod > seuil et mode auto OK »

      1. J’ai vu également qu’il y a un val_router et val_routeur y aurais pas une erreur à ce niveau la ?

        1. Bonsoir. Effectivement, c’est bien le binary_sensor qui valide le routeur c’est un « input_boolean.inter_validation_routeur » déclaré dans HA. Le « switch val_router » ne sert plus, j’aurais du le virer avant, c’est ce que je viens de faire dans la mise à jour du pgm. Au début j’utilisais ce switch mais, je ne sais pas pourquoi, il de dévalisait tout seul et le routeur s’arrêtait sans raison. C’est pourquoi j’ai déclaré ce input_boolean dans HA et c’est lui, sous certaines conditions, qui valide le routeur. je t’invite à charger le pgm mis à jour en commentant la partie température. une fois fonctionnel, Tu pourras mettre le niveau de log à « info » au lieu de « débug », les logs seront moins lourds.

Laisser un commentaire

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