Contenu

Interrupteurs POE

Dans le cadre d’une rénovation, j’ai développé une solution domotique basée sur des ESP32 connectés en Ethernet et alimentés en PoE.
L’objectif est d’éviter les systèmes radio et de construire une architecture ouverte.

Choix de l’architecture

Avant de concevoir cette solution, j’ai expérimenté plusieurs approches de domotique.

Dans une précédente rénovation, j’ai utilisé des automates industriels qui offrent une grande fiabilité mais nécessitent beaucoup de câblage, utilisent souvent des solutions propriétaires et restent relativement coûteux pour un usage résidentiel.

J’avais installé chez une connaissance le standard KNX qui est également très répandu dans le domaine de la domotique filaire, mais le matériel reste également onéreux et l’écosystème repose en grande partie sur des solutions propriétaires.

Je souhaitais donc m’orienter vers une solution plus ouverte et plus flexible, basée sur des technologies open source.

Ne trouvant pas de solution correspondant exactement à mes besoins, j’ai envisagé en 2019 une architecture basée sur des microcontrôleurs connectés en Ethernet.

L’idée principale était :

  • alimentation via Power over Ethernet (PoE)
  • communication sur le réseau IP
  • modules capables de gérer interrupteurs et capteurs

ET lors d’une visite du site hackaday, j’ai découvert le module ESP32-PoE d’Olimex, qui combine ESP32, Ethernet et alimentation PoE pour un coût relativement faible.

dessous
dessous

Conception des interrupteurs

Les modules ESP32-PoE servent à la fois d’interrupteurs muraux et de capteurs environnementaux (température, humidité, luminosité, etc.) pour une ou plusieurs pièces.

Les interrupteurs utilisent les entrées tactiles capacitif de l’ESP32.
La surface tactile est constituée d’une plaque métallique avec un symbole découpé correspondant à la fonction.

Une LED RGB permet d’ajouter un rétroéclairage et des indications visuelles.

appui sur l’interrupteur
appui

Prototypage mécanique

Les boîtiers et supports internes sont réalisés en impression 3D.
Plusieurs types de PLA sont utilisés :

  • PLA bois pour certaines parties visibles
  • PLA noir ou blanc pour les structures internes
  • PLA transparent pour diffuser la lumière du rétroéclairage LED
    pièces
    pièces
    Pour la plaque en metal, les premiers prototypes ont été réalisés en aluminium, découpé avec une petite CNC personnelle. Cette solution fonctionnait mais présentait un temps de fabrication élevé et une finition moins bonne. Ayant un peu de pression pour terminer ma renovation j’ai fini par commander chez laserboost des plaques inox découpées au laser, plus on commande en volume plus le prix baisse ! .
    plaque inox livré
    plaque inox livré

Architecture matérielle actuelle

L’installation comprend actuellement :

  • 12 modules ESP32-PoE Olimex utilisés comme interrupteurs et sondes

  • 7 coffrets techniques équipés de WT32-ETH01 des modules esp32 ethernet sans POE

Chaque coffret peut piloter :

  • l’éclairage
  • les volets
  • le chauffage

Architecture logicielle

Les premiers prototypes étaient programmés avec Arduino. Lorsque j’ai découvert le projet ESPHome j’ai entièrement migré mes modules

Cela permet notamment :

  • une configuration rapide avec des fichiers Yaml
  • utilisation du protocole MQTT.
  • les mises à jour par le réseau avec OTA.

Voici un exemple de code esphome:

esphome:
  name: inter-01
  friendly_name: Inter-01 Salon

esp32:
  board: esp32-poe
  framework:
    type: esp-idf

logger:
  level: DEBUG

ota:
  - platform: esphome
    password: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

api:
  reboot_timeout: 0s

ethernet:
  type: LAN8720
  mdc_pin: GPIO23
  mdio_pin: GPIO18
  clk:
    pin: GPIO17
    mode: CLK_OUT
  phy_addr: 0
  power_pin: GPIO12
  manual_ip:
    static_ip: 192.168.1.100
    gateway: 192.168.1.1
    subnet: 255.255.255.0
    dns1: 192.168.1.1

mdns:
  disabled: false

mqtt:
  broker: !secret mqtt_ip
  username: !secret mqtt_user
  password: !secret mqtt_mdp

esp32_touch:
  #setup_mode: true

binary_sensor:
  - platform: esp32_touch
    name: "Bt lumiere cuisine"
    id: btlumiere
    pin: GPIO00
    threshold: 300
    on_press:
      then:
        - light.turn_on:
            id: rbtlumiere
            transition_length: 0s
            brightness: 100%
            red: 100%
            green: 100%
            blue: 100%
        - mqtt.publish:
            topic: "maison/lumiere/salon"
            payload: "TOGGLE"

    on_release: 
      then:
        - light.turn_on:
            id: rbtlumiere
            brightness: !lambda 'return id(default_brit) / 255.0;'
            red: !lambda 'return id(default_red) / 255.0;'
            green: !lambda 'return id(default_green) / 255.0;'
            blue: !lambda 'return id(default_blue) / 255.0;'    


  - platform: esp32_touch
    name: "Bt volet haut"
    id: btvolethaut
    pin: GPIO04
    threshold: 300
    on_press:
      then:
        - light.turn_on:
            id: rbtvolethaut
            transition_length: 0s
            brightness: 100%
            red: 100%
            green: 100%
            blue: 100%
    on_release: 
      then:
        - light.turn_on:
            id: rbtvolethaut
            brightness: !lambda 'return id(default_brit) / 255.0;'
            red: !lambda 'return id(default_red) / 255.0;'
            green: !lambda 'return id(default_green) / 255.0;'
            blue: !lambda 'return id(default_blue) / 255.0;' 

  - platform: esp32_touch
    name: "Bt volet bas"
    id: btvoletbas
    pin: GPIO32
    threshold: 300
    on_press:
      then:
        - light.turn_on:
            id: rbtvoletbas
            transition_length: 0s
            brightness: 100%
            red: 100%
            green: 100%
            blue: 100%
    on_release: 
      then:
        - light.turn_on:
            id: rbtvoletbas
            brightness: !lambda 'return id(default_brit) / 255.0;'
            red: !lambda 'return id(default_red) / 255.0;'
            green: !lambda 'return id(default_green) / 255.0;'
            blue: !lambda 'return id(default_blue) / 255.0;' 

  - platform: esp32_touch
    name: "Bt lumiere exterieur"
    id: btlumiereext
    pin: GPIO14
    threshold: 300
    on_press:
      then:
        - light.turn_on:
            id: rbtlumiereext
            transition_length: 0s
            brightness: 100%
            red: 100%
            green: 100%
            blue: 100%
    on_release: 
      then:
        - light.turn_on:
            id: rbtlumiereext
            brightness: !lambda 'return id(default_brit) / 255.0;'
            red: !lambda 'return id(default_red) / 255.0;'
            green: !lambda 'return id(default_green) / 255.0;'
            blue: !lambda 'return id(default_blue) / 255.0;'    

globals:
  - id: default_brit
    type: int
    restore_value: true
    initial_value: '75'
  - id: default_red
    type: int
    restore_value: true
    initial_value: '0'
  - id: default_green
    type: int
    restore_value: true
    initial_value: '0'
  - id: default_blue
    type: int
    restore_value: true
    initial_value: '255'

light:
  - platform: esp32_rmt_led_strip
    rgb_order: GRB
    pin: GPIO01
    num_leds: 4
    chipset: SK6812
    name: "busLight"
    id: buslight
    internal: true
  - platform: partition
    id: rbtlumiere
    segments:
      - id: buslight
        from: 3
        to: 3
    on_turn_on:
      - light.turn_on:
          id: rbtlumiere
          brightness: !lambda 'return id(default_brit) / 255.0;'
          red: !lambda 'return id(default_red) / 255.0;'
          green: !lambda 'return id(default_green) / 255.0;'
          blue: !lambda 'return id(default_blue) / 255.0;' 
  - platform: partition
    id: rbtvolethaut
    segments:
      - id: buslight
        from: 1
        to: 1
    on_turn_on:
      - light.turn_on:
          id: rbtvolethaut
          brightness: !lambda 'return id(default_brit) / 255.0;'
          red: !lambda 'return id(default_red) / 255.0;'
          green: !lambda 'return id(default_green) / 255.0;'
          blue: !lambda 'return id(default_blue) / 255.0;' 
  - platform: partition
    id: rbtvoletbas
    segments:
      - id: buslight
        from: 2
        to: 2
    on_turn_on:
      - light.turn_on:
          id: rbtvoletbas
          brightness: !lambda 'return id(default_brit) / 255.0;'
          red: !lambda 'return id(default_red) / 255.0;'
          green: !lambda 'return id(default_green) / 255.0;'
          blue: !lambda 'return id(default_blue) / 255.0;' 
  - platform: partition
    id: rbtlumiereext
    segments:
      - id: buslight
        from: 0
        to: 0
    on_turn_on:
      - light.turn_on:
          id: rbtlumiereext
          brightness: !lambda 'return id(default_brit) / 255.0;'
          red: !lambda 'return id(default_red) / 255.0;'
          green: !lambda 'return id(default_green) / 255.0;'
          blue: !lambda 'return id(default_blue) / 255.0;' 

État actuel du projet

Le système fonctionne très bien mais il me reste encore beaucoup de choses à intégrer. Avec les évolutions récentes d’ESPHome et de Home Assistant, plusieurs pistes sont envisagées :

  • l’ajout de capteurs de présence mmWave pour améliorer la détection de présence
  • Du son pour les alarmes soit avec un buzzer piezo ou un petit hautparleur sur I2S
  • l’intégration d’assistants vocaux locaux avec des microphones sur ESP32
  • La connection d’ écrans LCD tactiles

Le projet continue donc d’évoluer au fil des expérimentations …