Automatisierung

Ich versuche meine Grows durch den Einsatz von verschiedenen Sensoren und Aktoren zu automatisieren. Dies ist ein fortschreitender Prozess und ich bin noch weit von einem wirklich automatischen System entfernt. Dennoch möchte ich meine eingesetzte Technik dokumentieren. Aktuell ist vor allem der Fokus auf der Bewässerung und Überwachung, so dass ich mich zumindest rudimentär um die Pflanze von Unterwegs aus (über mein VPN) kümmern kann, sollte ich mal länger nicht Zuhause sein.

Hauptgrundlage zur Automatisierung ist eine lokale Instanz von Home Assistant in Zusammenspiel mit mehren ESPHome-Boards (ESP32).

Aktuell werden 4 ESP32 Devkit V1 Boards und eine ESPCam eingesetzt.

Board 1: LCW Sensoren + Relaismodul

Dieser ESP32 bildet das Kernstück der Automatisierung und ist auf meinem eigenen PCB Design angebracht.

lcw-tent.yaml (Einige Werte/Variable müssen natürlich entsprechend angepasst werden)
esphome:
  name: lcw-tent
  friendly_name: "LCW Tent"

esp32:
  board: esp32dev
  framework:
    type: arduino

logger:

api:
  encryption:
    key: "..."

ota:
  - platform: esphome
    password: "..."

wifi:
  networks:
    - ssid: !secret wifi_ssid
      password: !secret wifi_password
      bssid: !secret wifi_bssid_cave
      manual_ip:
        static_ip: !secret wifi_ip_lwc_tent
        gateway: !secret wifi_gateway
        subnet: !secret wifi_subnet
        dns1: !secret wifi_dns
  fast_connect: true

i2c:
  sda: GPIO21
  scl: GPIO22

sensor:
  - platform: bme280_i2c
    address: 0x76
    temperature:
      name: "Temperature"
      filters:
      - offset: -1
    pressure:
      name: "Pressure"
    humidity:
      name: "Humidity"
      filters:
      - offset: 2
    update_interval: 1s
  - platform: adc
    raw: true
    icon: "mdi:cup-water"
    update_interval: 200ms
    attenuation: 11db
    filters:
      - median:
            window_size: 9
            send_every: 5
            send_first_at: 5
    pin: GPIO33
    name: "Sensor 1 RAW"
    id: moisture1
  - platform: copy
    icon: "mdi:cup-water"
    accuracy_decimals: 1
    unit_of_measurement: "%"
    name: "Sensor 1"
    source_id: moisture1
    filters:
        - calibrate_linear:
            datapoints:
                - 2550 -> 0.0
                - 970 -> 100.0
        - lambda: if (x < 0) return 0;
            else if (x > 100) return 100;
            else return (x);
  - platform: adc
    raw: true
    icon: "mdi:cup-water"
    update_interval: 200ms
    attenuation: 11db
    filters:
      - median:
            window_size: 9
            send_every: 5
            send_first_at: 5
    pin: GPIO32
    name: "Sensor 2 RAW"
    id: moisture2
  - platform: copy
    icon: "mdi:cup-water"
    accuracy_decimals: 1
    unit_of_measurement: "%"
    name: "Sensor 2"
    source_id: moisture2
    filters:
        - calibrate_linear:
            datapoints:
                - 2544 -> 0.0
                - 988 -> 100.0
        - lambda: if (x < 0) return 0;
            else if (x > 100) return 100;
            else return (x);
  - platform: adc
    raw: true
    icon: "mdi:cup-water"
    update_interval: 200ms
    attenuation: 11db
    filters:
      - median:
            window_size: 9
            send_every: 5
            send_first_at: 5
    pin: GPIO35
    name: "Sensor 3 RAW"
    id: moisture3
  - platform: copy
    icon: "mdi:cup-water"
    accuracy_decimals: 1
    unit_of_measurement: "%"
    name: "Sensor 3"
    source_id: moisture3
    filters:
        - calibrate_linear:
            datapoints:
                - 2520 -> 0.0
                - 880 -> 100.0
        - lambda: if (x < 0) return 0;
            else if (x > 100) return 100;
            else return (x);
  - platform: adc
    raw: true
    icon: "mdi:cup-water"
    update_interval: 200ms
    attenuation: 11db
    filters:
      - median:
            window_size: 9
            send_every: 5
            send_first_at: 5
    pin: GPIO34
    name: "Sensor 4 RAW"
    id: moisture4
  - platform: copy
    icon: "mdi:cup-water"
    accuracy_decimals: 1
    unit_of_measurement: "%"
    name: "Sensor 4"
    source_id: moisture4
    filters:
        - calibrate_linear:
            datapoints:
                - 2530 -> 0.0
                - 920 -> 100.0
        - lambda: if (x < 0) return 0;
            else if (x > 100) return 100;
            else return (x);

number:
  - platform: template
    name: Relay Duration
    icon: "mdi:camera-timer"
    id: lcw_relay_delay
    optimistic: true
    min_value: 1
    max_value: 60
    step: 1
    initial_value: 5

switch:
  - platform: gpio
    pin: GPIO27
    id: relay1
    inverted: true
  - platform: gpio
    pin: GPIO14
    id: relay2
    inverted: true
  - platform: template
    name: Humidifier Switch
    icon: "mdi:air-humidifier"
    optimistic: true
    on_turn_on:
      - switch.turn_on: relay2
    on_turn_off:
      - switch.turn_off: relay2

button:
  - platform: template
    name: Water Pump
    icon: "mdi:water-pump"
    on_press:
      - switch.turn_on: relay1
      - delay: !lambda "return id(lcw_relay_delay).state  * 1000;"
      - switch.turn_off: relay1
  - platform: template
    name: Humidifier
    icon: "mdi:air-humidifier"
    on_press:
      - switch.turn_on: relay2
      - delay: !lambda "return id(lcw_relay_delay).state  * 1000;"
      - switch.turn_off: relay2

Board 2: SANLight

Dieser ESP32 steuert die Helligkeit der SANLight EVO 3-80. Ich habe mich hierbei an folgender Anleitung orientiert. Hierzu wird folgendes eingesetzt:

  • Wieland Steckverbinder RST20I3S B1 ZR1S BL0: Aktuell schwer zu bekommen, es muss die Ausführung in lichtblau sein, andernfalls passt der Stecker nicht in die Lampe
  • PWM auf 0-10V Controller: wird mit den entsprechenden Anschlüssen an den Steckverbinder verbunden und wandelt ein PWM Signal des ESP32 in eine Spannung von 0-10V um die die Helligkeit der Lampe regelt
    Achtung: Ich hatte hier zunächst einen Spannungswandler der bei 0% trotzdem eine Grundspannung von 0.4V hatte und somit die Lampe nicht ausschalten konnte!
  • Spannungswandler 5-24V auf 3.3V: Nimmt die 12V Spannung der Lampe und versorgt so den ESP32 direkt mit Strom
sanlight.yaml (Die Anpassung von gamma_correct: 1 war hier wichtig um die richtige Spannung von 0-10V zu erreichen, dies kann allerdings auch vom PWM auf 0-10V Controller abhängen!)
esphome:
  name: sanlight
  friendly_name: "Sanlight"

esp32:
  board: esp32dev
  framework:
    type: arduino

logger:

api:
  encryption:
    key: "..."

ota:
  - platform: esphome
    password: "..."

wifi:
  networks:
    - ssid: !secret wifi_ssid
      password: !secret wifi_password
      bssid: !secret wifi_bssid_cave
      manual_ip:
        static_ip: !secret wifi_ip_sanlight
        gateway: !secret wifi_gateway
        subnet: !secret wifi_subnet
        dns1: !secret wifi_dns
  fast_connect: true

output:
  - platform: ledc
    pin: GPIO5
    id: gpio_5

light:
  - platform: monochromatic
    output: gpio_5
    name: "Sanlight EVO"
    gamma_correct: 1
    restore_mode: RESTORE_DEFAULT_ON

Board 3: Mars Hydro Fan

Dieser ESP32 steuert den Mars Hydro Fan. Ein PWM-Pin wurde direkt an den Speed-Controller-Stecker angeschlossen. Die drei Anschlüssen bestehen aus einem 3V Anschluss, Ground und dem Signal aus 0-3V um die Umdrehungsgeschwindigkeit des Lüfters zu steuern. Leider reichen die 3V des Lüfters nicht aus um den ESP32 mit Strom zu versorgen.

marshydro.yaml (Die Anpassung von max_power: 0.85 sowie zero_means_zero: True war wichtig um auf ungefähre 3V bei 100% zu kommen und den Lüfter bei 0% wirklich auszuschalten)
esphome:
  name: marshydro
  friendly_name: "Mars Hydro"

esp32:
  board: esp32dev
  framework:
    type: arduino

logger:

api:
  encryption:
    key: "..."

ota:
  - platform: esphome
    password: "..."

wifi:
  networks:
    - ssid: !secret wifi_ssid
      password: !secret wifi_password
      bssid: !secret wifi_bssid_cave
      manual_ip:
        static_ip: !secret wifi_ip_marshydro
        gateway: !secret wifi_gateway
        subnet: !secret wifi_subnet
        dns1: !secret wifi_dns
  fast_connect: true

output:
  - platform: ledc
    pin: GPIO5
    id: gpio_5
    max_power: 0.85
    zero_means_zero: True

fan:
  - platform: speed
    output: gpio_5
    name: "Mars Hydro Fan"
    restore_mode: RESTORE_DEFAULT_ON

Board 4: Temperatur und Luftfeuchtigkeit im Raum

Das vierte Board ist wieder ein LCW Board, allerdings nur mit einem BME280 ausgestattet um mir die Temperatur und relative Luftfeuchtigkeit im Raum außerhalb des Zeltes zu übermitteln.

  • BME280 zur Übertragung von Temperatur und Luftfeuchtigkeit
lcw-cave.yaml
esphome:
  name: lcw-cave
  friendly_name: "LCW Cave"

esp32:
  board: esp32dev
  framework:
    type: arduino

logger:

api:
  encryption:
    key: "..."

ota:
  - platform: esphome
    password: "..."

wifi:
  networks:
    - ssid: !secret wifi_ssid
      password: !secret wifi_password
      bssid: !secret wifi_bssid_cave
      manual_ip:
        static_ip: !secret wifi_ip_lcw_cave
        gateway: !secret wifi_gateway
        subnet: !secret wifi_subnet
        dns1: !secret wifi_dns
  fast_connect: true

i2c:
  sda: GPIO21
  scl: GPIO22

sensor:
  - platform: bme280_i2c
    address: 0x76
    temperature:
      name: "Temperature"
      filters:
      - offset: 1
    pressure:
      name: "Pressure"
    humidity:
      name: "Humidity"
    update_interval: 1s

ESPCam

Eine einfache ESPCam um auch einen Blick ins Zelt zu werfen ohne es zu öffnen, sowie um alle 24h einen Snapshot zu speichern.

tent-cam.yaml
esphome:
  name: tent-cam
  friendly_name: "Tent CAM"

esp32:
  board: esp32dev
  framework:
    type: arduino

logger:

api:
  encryption:
    key: "..."

ota:
  - platform: esphome
    password: "..."

wifi:
  networks:
    - ssid: !secret wifi_ssid
      password: !secret wifi_password
      bssid: !secret wifi_bssid_cave
      manual_ip:
        static_ip: !secret wifi_ip_tent_cam
        gateway: !secret wifi_gateway
        subnet: !secret wifi_subnet
        dns1: !secret wifi_dns
  fast_connect: true

esp32_camera:
  external_clock:
    pin: GPIO0
    frequency: 20MHz
  i2c_pins:
    sda: GPIO26
    scl: GPIO27
  data_pins: [GPIO5, GPIO18, GPIO19, GPIO21, GPIO36, GPIO39, GPIO34, GPIO35]
  vsync_pin: GPIO25
  href_pin: GPIO23
  pixel_clock_pin: GPIO22
  power_down_pin: GPIO32

  name: "Tent CAM"
  resolution: "1024x768"
  vertical_flip: false
  max_framerate: 10 fps
  idle_framerate: 1 fps
  jpeg_quality: 10
  wb_mode: home
  agc_gain_ceiling: 128x

esp32_camera_web_server:
  - port: 8080
    mode: stream
  - port: 8081
    mode: snapshot

Home Assistant Dashboard

Mein aktuelles Dashboard:

Die Bodenfeuchtesensoren müssen noch mal ordentlich kalibriert werden. Ich habe das Gefühl die Werte verändern sich nach der Kalibrierung wieder stark, wenn die Sensoren ins Substrat gesteckt werden. Eventuell muss ich auch in teurere Sensoren investieren. Mit der Relay-Duration kann ich steuern wie lange die Pumpe oder der Befeuchter laufen sollen. Den Befeuchter kann ich auch generell an- und ausschalten.