|
@@ -0,0 +1,111 @@
|
|
|
|
|
+# Prompt:
|
|
|
|
|
+# Ich stelle mir das Script so vor:
|
|
|
|
|
+# Wenn der Bodenfeuchte-Sensor meldet "Boden zu trocken" (Grenzwert aus der config.json),
|
|
|
|
|
+# dann prüfe den BME280-Wettersensor,
|
|
|
|
|
+# wenn der meldet, dass Luftfeuchtigkeit unter Grenzwert (aus der config.json)
|
|
|
|
|
+# und Temperatur über Grenzwert (aus config.json),
|
|
|
|
|
+# dann schalte Relais für Pumpe eine bestimmte Zeit (aus config.json) an. Prüfe sofort erneut.
|
|
|
|
|
+# Wenn Bodenfeuchte-Sensor "feucht genug" meldet,
|
|
|
|
|
+# gib nur Bodenfeuchte und Werte des BME280 aus.
|
|
|
|
|
+# Wenn Bodenfeuchte Sensor "zu nass" meldet,
|
|
|
|
|
+# gib Bodenfeuchte und Werte des BME280 und "Warnung: viel zu feucht" aus.
|
|
|
|
|
+# ########################################################################
|
|
|
|
|
+#
|
|
|
|
|
+# Ziel – Ein einzelnes Python‑Programm für den Raspberry Pi, das
|
|
|
|
|
+#
|
|
|
|
|
+# ========================================================================
|
|
|
|
|
+# die Bodenfeuchte‑Sensor-Ausgabe (analog) liest,
|
|
|
|
|
+# die Temperatur/Feuchte‑Ausgabe des BME280 liest,
|
|
|
|
|
+# prüft, ob beide Messwerte unter bzw. über einem Schwellwert liegen, und
|
|
|
|
|
+# steuert per GPIO‑Pin einen MOSFET‑Relais für eine bestimmte Zeit an.
|
|
|
|
|
+# Das Skript nutzt dafür
|
|
|
|
|
+# -----------------------------------------------------------------------
|
|
|
|
|
+# I²C (BME280)
|
|
|
|
|
+# SPI (ADC zum Bodenfeuchte‑Sensor)
|
|
|
|
|
+# GPIO (Pumpen‑Relais)
|
|
|
|
|
+# Im Folgenden ein kompletter, kommentierter Python‑Code inklusive des
|
|
|
|
|
+# Konfigurations‑ und Logfiles.
|
|
|
|
|
+# #######################################################################
|
|
|
|
|
+
|
|
|
|
|
+#!/usr/bin/env python3
|
|
|
|
|
+"""
|
|
|
|
|
+Automatisches Bewässerungs‑Skript
|
|
|
|
|
+- Liest Bodenfeuchte und BME280‑Daten
|
|
|
|
|
+- Prüft Schwellenwerte (aus config.json)
|
|
|
|
|
+- Steuert Relais für Pumpen‑Ansteuerung
|
|
|
|
|
+- Loggt alles in CSV
|
|
|
|
|
+
|
|
|
|
|
+Benötigte Bibliotheken:
|
|
|
|
|
+ * adafruit_bme280 – I²C‑BME280
|
|
|
|
|
+ * adafruit_mcp3008 – SPI‑ADC
|
|
|
|
|
+ * busio, board, digitalio – Hardware‑I/O
|
|
|
|
|
+"""
|
|
|
|
|
+
|
|
|
|
|
+import json
|
|
|
|
|
+import time
|
|
|
|
|
+import csv
|
|
|
|
|
+from pathlib import Path
|
|
|
|
|
+
|
|
|
|
|
+# ---- 1. Imports für Hardware -------------------------------------------------
|
|
|
|
|
+import board
|
|
|
|
|
+import busio
|
|
|
|
|
+import digitalio
|
|
|
|
|
+import analogio # falls ein Analog‑GPIO‑Sensor benutzt wird
|
|
|
|
|
+from adafruit_bme280 import Adafruit_BME280_I2c
|
|
|
|
|
+from adafruit_mcp3008 import MCP3008
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+# ---- 2. Konfiguration laden --------------------------------------------------
|
|
|
|
|
+def load_config(path: str = "config.json") -> dict:
|
|
|
|
|
+ """Liest die JSON‑Konfig (default 'config.json')."""
|
|
|
|
|
+ with open(Path(path), "r", encoding="utf-8") as f:
|
|
|
|
|
+ return json.load(f)
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+cfg = load_config()
|
|
|
|
|
+PIN_PUMP = cfg["gpio_pump_pin"]
|
|
|
|
|
+POLL_SEC = cfg.get("poll_interval_sec", 300) # default: 5 min
|
|
|
|
|
+LOG_FILE = cfg["log_file"]
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+# ---- 3. Hardware‑Initialisierung ---------------------------------------------
|
|
|
|
|
+
|
|
|
|
|
+# I²C‑Bus (BME280)
|
|
|
|
|
+i2c_bus = busio.I2C(board.SCL, board.SDA, frequency=400_000) # 400 kHz
|
|
|
|
|
+bme280 = Adafruit_BME280_I2c(i2c_bus)
|
|
|
|
|
+
|
|
|
|
|
+# SPI‑Bus (ADC – hier MCP3008 für den Bodenfeuchte‑Sensor)
|
|
|
|
|
+spi_bus = busio.spi.SPI(board.CS0, board.MOSI, board.MISO,
|
|
|
|
|
+ board.SCK, busio.spi.OE)
|
|
|
|
|
+adc = MCP3008(spi_bus) # Kanal 0: Bodenfeuchte
|
|
|
|
|
+
|
|
|
|
|
+# GPIO‑Pin (Pumpen‑Relais)
|
|
|
|
|
+pump_pin = digitalio.DigitalInOut(board.GP(PIN_PUMP))
|
|
|
|
|
+pump_pin.switch_to_output()
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+# ---- 4. Messfunktionen ----------------------------------------------------
|
|
|
|
|
+def read_moisture() -> float:
|
|
|
|
|
+ """Liest den analog‑Sensor (ADC Channel 0) und liefert Bodenfeuchte in m³/m³."""
|
|
|
|
|
+ raw_val = adc.read(0) # ADC‑Wert 0…1023
|
|
|
|
|
+ # Umrechnung: 5 V → 3.3 V (MCP3008 → 10‑Bit)
|
|
|
|
|
+ return raw_val * (5 / 1024)
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+def read_bme280() -> tuple[float, float, float]:
|
|
|
|
|
+ """Liest Temperatur, Luftfeuchte und Druck aus dem BME280."""
|
|
|
|
|
+ temp = bme280.temperature
|
|
|
|
|
+ humid = bme280.humidity
|
|
|
|
|
+ press = bme280.pressure
|
|
|
|
|
+ return temp, humid, press
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+def should_water(moist: float) -> bool:
|
|
|
|
|
+ """Gibt True zurück, wenn Bodenfeuchte unter Grenzwert liegt."""
|
|
|
|
|
+ return moist < cfg["moist_threshold"]
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+# ---- 5. Pumpen‑Steuerung -------------------------------------------------
|
|
|
|
|
+def pump
|
|
|
|
|
+
|
|
|
|
|
+## Soso, hier hat der Plappergeier aufgehört.
|