Note de ce sujet :
  • Moyenne : 0 (0 vote(s))
  • 1
  • 2
  • 3
  • 4
  • 5
Autonomie en Normandie : Deye 8K, Batterie 314Ah et Routage 4 voies
#1
Bonjour à tous,

Je vous sollicite pour valider la partie logicielle de mon futur projet d'installation. Actuellement, je tourne avec 6 kWc de panneaux sur micro-onduleurs et un routeur F1ATB sur mon chauffe-eau.
Le projet à venir :
Je vais installer un onduleur Deye 8K avec une batterie DIY 16S 314Ah. Le cerveau sera un mini PC sous HAOS (bare metal), relié à l'onduleur en RS485/USB.

Mon ambition :
  • Off-Grid partiel : Par fierté et pour couper l'abonnement, je vise l'autonomie de début avril à fin septembre.
  • Gestion de l'inertie : Utiliser le surplus pour chauffer mes dalles (très utile pour les nuits fraîches en Normandie) via un routeur F1ATB 4 voies (1 ECS 2000W + 3 dalles 1500W).
La genèse du code :

Comme je n'y connais rien en informatique, j'ai fait travailler trois IA en collaboration. Je leur ai soumis mes idées et elles ont généré ce code YAML. Elles m'assurent qu'il est parfait, mais je préfère l'avis d'humains qui pratiquent le code au quotidien !
Logique du code :
  • Protection Batterie : Coupure du routage à 30% de SOC, reprise à 35%.
  • Rampes Intelligentes : Montée progressive (paliers de 10 à 20%) et descente rapide (palier de 15%) pour protéger la batterie des appels de charge de la maison ou des passages nuageux.
  • Calcul Hybride : Utilisation de PV - Load - Grid pour fonctionner aussi bien l'hiver (On-Grid avec pince CT réseau) que l'été (Off-Grid).
Bien sûr, les noms des entités et les valeurs de
 puissance devront être ajustés une fois le matériel en place ; ce qui m'intéresse avant tout, c'est de valider la structure du code et la logique des rampes.

Le code envisagé :

# ============================================================
# FILTER SENSOR — lissage surplus brut
# ============================================================
sensor:
  - platform: filter
    name: "Surplus Solaire Lissé"
    unique_id: surplus_solaire_lisse
    entity_id: sensor.surplus_solaire_brut
    filters:
      - filter: moving_average
        window_size: 3
        precision: 0
      - filter: range
        lower_bound: 0
        upper_bound: 8500

# ============================================================
# TEMPLATE SENSORS — surplus brut + consignes par voie
# ============================================================
template:
  - sensor:
      - name: "Surplus Solaire Brut"
        unique_id: surplus_solaire_brut
        unit_of_measurement: "W"
        state_class: measurement
        device_class: power
        state: >
          {% set pv = states('sensor.deye_pv_power') | float(0) %}
          {% set load = states('sensor.deye_load_power') | float(0) %}
          {% set grid = states('sensor.deye_grid_power') | float(0) %}
          {{ [pv - load - grid, 0] | max | int }}

      # --- Voie 1 : chauffe-eau 2000 W ---
      - name: "F1ATB V1 consigne pct"
        unique_id: f1atb_v1_pct
        unit_of_measurement: "%"
        state: >
          {% set soc = states('sensor.deye_battery_soc') | float(0) %}
          {% set seuil = 100 if soc > 90 else 200 %}
          {% set s = states('sensor.surplus_solaire_lisse') | float(0) %}
          {% set s = 0 if s < seuil else s %}
          {{ [[s / 2000 * 100, 0] | max, 100] | min | round(0) | int }}

      # --- Voie 2 : dalle 1 — 1500 W ---
      - name: "F1ATB V2 consigne pct"
        unique_id: f1atb_v2_pct
        unit_of_measurement: "%"
        state: >
          {% set soc = states('sensor.deye_battery_soc') | float(0) %}
          {% set seuil = 100 if soc > 90 else 200 %}
          {% set s = states('sensor.surplus_solaire_lisse') | float(0) %}
          {% set s = 0 if s < seuil else s %}
          {% set reste = [s - 2000, 0] | max %}
          {{ [[reste / 1500 * 100, 0] | max, 100] | min | round(0) | int }}

      # --- Voie 3 : dalle 2 — 1500 W ---
      - name: "F1ATB V3 consigne pct"
        unique_id: f1atb_v3_pct
        unit_of_measurement: "%"
        state: >
          {% set soc = states('sensor.deye_battery_soc') | float(0) %}
          {% set seuil = 100 if soc > 90 else 200 %}
          {% set s = states('sensor.surplus_solaire_lisse') | float(0) %}
          {% set s = 0 if s < seuil else s %}
          {% set reste = [s - 2000 - 1500, 0] | max %}
          {{ [[reste / 1500 * 100, 0] | max, 100] | min | round(0) | int }}

      # --- Voie 4 : dalle 3 — 1500 W ---
      - name: "F1ATB V4 consigne pct"
        unique_id: f1atb_v4_pct
        unit_of_measurement: "%"
        state: >
          {% set soc = states('sensor.deye_battery_soc') | float(0) %}
          {% set seuil = 100 if soc > 90 else 200 %}
          {% set s = states('sensor.surplus_solaire_lisse') | float(0) %}
          {% set s = 0 if s < seuil else s %}
          {% set reste = [s - 2000 - 1500 - 1500, 0] | max %}
          {{ [[reste / 1500 * 100, 0] | max, 100] | min | round(0) | int }}

# ============================================================
# AUTOMATIONS
# ============================================================
automation:

  # 1. REGULATION PRINCIPALE — ramp adaptatif toutes les 2s
  - alias: "F1ATB - Regulation triacs finale"
    id: f1atb_regulation_finale
    mode: queued
    max: 2
    trigger:
      - platform: time_pattern
        seconds: "/2"
      - platform: event
        event_type: f1atb_resume
    condition:
      - condition: numeric_state
        entity_id: sensor.deye_battery_soc
        above: 30
    action:
      - variables:
          soc: "{{ states('sensor.deye_battery_soc') | float(0) }}"
          surplus: "{{ states('sensor.surplus_solaire_lisse') | float(0) }}"
          step_up: >
            {% if soc > 95 %} 20
            {% elif soc > 80 %} 15
            {% else %} 10
            {% endif %}
          step_down: "{{ 15 if surplus < 500 else 8 }}"
          seuil: 3
      - repeat:
          for_each:
            - { sensor: "sensor.f1atb_v1_consigne_pct", entity: "number.f1atb_voie_1" }
            - { sensor: "sensor.f1atb_v2_consigne_pct", entity: "number.f1atb_voie_2" }
            - { sensor: "sensor.f1atb_v3_consigne_pct", entity: "number.f1atb_voie_3" }
            - { sensor: "sensor.f1atb_v4_consigne_pct", entity: "number.f1atb_voie_4" }
          sequence:
            - variables:
                new_val: "{{ states(repeat.item.sensor) | int(0) }}"
                old_val: "{{ states(repeat.item.entity) | int(0) }}"
            - if:
                - condition: template
                  value_template: "{{ (new_val - old_val) | abs > seuil }}"
              then:
                - service: number.set_value
                  target:
                    entity_id: "{{ repeat.item.entity }}"
                  data:
                    value: >
                      {% if new_val > old_val %}
                        {{ [old_val + step_up, new_val] | min }}
                      {% else %}
                        {{ [old_val - step_down, new_val] | max }}
                      {% endif %}

  # 2. COUPURE SOC BAS — tout à 0 immédiatement
  - alias: "F1ATB - Coupure SOC bas"
    id: f1atb_coupure_soc
    mode: single
    trigger:
      - platform: numeric_state
        entity_id: sensor.deye_battery_soc
        below: 30
    action:
      - service: number.set_value
        target:
          entity_id:
            - number.f1atb_voie_1
            - number.f1atb_voie_2
            - number.f1atb_voie_3
            - number.f1atb_voie_4
        data:
          value: 0

  # 3. REPRISE APRES SOC BAS — hysteresis 30/35%
  - alias: "F1ATB - Reprise SOC"
    id: f1atb_reprise_soc
    mode: single
    trigger:
      - platform: numeric_state
        entity_id: sensor.deye_battery_soc
        above: 35
    action:
      - delay: "00:00:15"
      - event: f1atb_resume

  # 4. RESYNC PERIODIQUE — rattrape les dérives toutes les minutes
  - alias: "F1ATB - Resync periodique"
    id: f1atb_resync
    mode: single
    trigger:
      - platform: time_pattern
        minutes: "/1"
    condition:
      - condition: numeric_state
        entity_id: sensor.deye_battery_soc
        above: 30
    action:
      - service: number.set_value
        target: { entity_id: number.f1atb_voie_1 }
        data: { value: "{{ states('sensor.f1atb_v1_consigne_pct') | int(0) }}" }
      - service: number.set_value
        target: { entity_id: number.f1atb_voie_2 }
        data: { value: "{{ states('sensor.f1atb_v2_consigne_pct') | int(0) }}" }
      - service: number.set_value
        target: { entity_id: number.f1atb_voie_3 }
        data: { value: "{{ states('sensor.f1atb_v3_consigne_pct') | int(0) }}" }
      - service: number.set_value
        target: { entity_id: number.f1atb_voie_4 }
        data: { value: "{{ states('sensor.f1atb_v4_consigne_pct') | int(0) }}" }

Votre avis :
Avant d'acheter tout le matériel et de lancer le montage, est-ce que cette logique de régulation via Home Assistant vous semble tenir la route ? 

Merci pour votre aide et vos retours d'expérience !
Répondre

#2
Bonjour,
Le projet est intéressant mais ta démarche est plus qu'osée de mon point de vue .
Tu dis ne rien y connaitre en info et avoir fait tourné 3 IA , ouais ...

De plus, tu n'a pas le matos et le code a été généré ainsi sans avoir été encore testé , évalué, validé ... avec surement des ajustements et erreurs ou calculs en cascade.
Je suis informaticien et ancien électronicien de métier et tous mes essais , sollicitations d'IA m'ont appris que les IA peuvent se planter parfois lamentablement sur des aspects spécifiques.
Malgré cela, les IA apprennent , évoluent et elles produisent du code qui s'avère être de plus en plus fiables mais pas exempts de bugs et de défauts ....

Perso : je procède différemment, :
- je découpe mon code par blocs indépendant,
- je teste , valide le code
- puis recette en situation réelle.
je commente mon code, je le versionne ( de manière à faciliter le suivi et le retour éventuel arrière)

J'ai procédé ainsi pour développer mon afficheur solaire dernièrement et même si les IA sollicitées m'ont permis d'avancer rapidement , j'avoue que parfois elles se sont bien plantées ...
Pour moi, difficile de faire une validation (même) "théorique" sans disposer de la structure matérielle et paramétrée qui va avec ...
Config : 3 routeurs F1ATB en V17.15 - 2 routeurs fixes en mode Triacs + 1 routeur mobile polyvalent en mode : Triac+SSR + 1 afficheur distant ESP32-S3
PV : (8*425W + Onduleur SunGrow 3KW) + (2 *500w + MO Hoymiles HMS-1000W-2T)
Supervision & Domotique : F1atb + Home Assistant / Shelly & MQTT
Répondre

#3
(Il y a 2 heures)Sgb31 a écrit : Bonjour,
Le projet est intéressant mais ta démarche est plus qu'osée de mon point de vue .
Tu dis ne rien y connaitre en info et avoir fait tourné 3 IA , ouais ...

De plus, tu n'a pas le matos et le code a été généré ainsi sans avoir été encore testé , évalué, validé ... avec surement des ajustements et erreurs ou calculs en cascade.
Je suis informaticien et ancien électronicien de métier et tous mes essais , sollicitations d'IA m'ont appris que les IA peuvent se planter parfois lamentablement sur des aspects spécifiques.
Malgré cela, les IA apprennent , évoluent et elles produisent du code qui s'avère être de plus en plus fiables mais pas exempts de bugs et de défauts ....

Perso : je procède différemment, :
- je découpe mon code par blocs indépendant,
- je teste , valide le code
- puis recette en situation réelle.
je commente mon code, je le versionne ( de manière à faciliter le suivi et le retour éventuel arrière)

J'ai procédé ainsi pour développer mon afficheur solaire dernièrement et même si les IA sollicitées m'ont permis d'avancer rapidement , j'avoue que parfois elles se sont bien plantées ...
Pour moi, difficile de faire une validation (même) "théorique" sans disposer de la structure matérielle et paramétrée qui va avec ...
Bonjour Sgb31,
Merci pour ton retour d'expérience ! Je comprends tout à fait ton point de vue de professionnel. 
C'est vrai que ma démarche est osée, mais c'est aussi ce qui rend le projet passionnant.
Je suis bien conscient que l'IA peut se planter, c'est d'ailleurs pour ça que j'ai confronté trois modèles différents (Gemini, Claude et ChatGPT) sur les mêmes problématiques.
 Elles se sont d'ailleurs corrigées entre elles sur des points critiques (comme le signe du grid ou les limites du filtre de lissage).
Mon objectif n'est pas de copier-coller sans comprendre, mais de préparer une base logique solide avant de recevoir le matériel. 
Une fois le materiel arrivés, je compte bien suivre ta méthode : tester bloc par bloc, vérifier les remontées de puissance et ajuster le code en situation réelle.
Au plaisir d'échanger sur les tests concrets dès que l'installation sera sous tension !
Répondre



Atteindre :


Utilisateur(s) parcourant ce sujet :
alexandeur, 2 visiteur(s)

Moteur MyBB, © 2002-2026 Melroy van den Berg.