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.
- Bodenfeuchtigkeitssensoren (4x)
- BME280 zur Übertragung von Temperatur und Luftfeuchtigkeit
- Relaismodule zur Steuerung
- einer 5V Wasserpumpe: mit einem Splitter werden zwei Schläuche mit Löchern über den Topf verlegt
- eines 5V Ultraschallzerstäuber: in der Praxis scheint dieses kleine Teil nicht wirklich was zu bringen, werde noch testen ob vielleicht 4 Zerstäuber eine spürparere Wirkung erzielen
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.
- M12 Steckverbinder: entsprechende Pins mit 3.3V, GND und PWM Pin verbunden.
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.