water_bot.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. # Prompt:
  2. # Ich stelle mir das Script so vor:
  3. # Wenn der Bodenfeuchte-Sensor meldet "Boden zu trocken" (Grenzwert aus der config.json),
  4. # dann prüfe den BME280-Wettersensor,
  5. # wenn der meldet, dass Luftfeuchtigkeit unter Grenzwert (aus der config.json)
  6. # und Temperatur über Grenzwert (aus config.json),
  7. # dann schalte Relais für Pumpe eine bestimmte Zeit (aus config.json) an. Prüfe sofort erneut.
  8. # Wenn Bodenfeuchte-Sensor "feucht genug" meldet,
  9. # gib nur Bodenfeuchte und Werte des BME280 aus.
  10. # Wenn Bodenfeuchte Sensor "zu nass" meldet,
  11. # gib Bodenfeuchte und Werte des BME280 und "Warnung: viel zu feucht" aus.
  12. # ########################################################################
  13. #
  14. # Ziel – Ein einzelnes Python‑Programm für den Raspberry Pi, das
  15. #
  16. # ========================================================================
  17. # die Bodenfeuchte‑Sensor-Ausgabe (analog) liest,
  18. # die Temperatur/Feuchte‑Ausgabe des BME280 liest,
  19. # prüft, ob beide Messwerte unter bzw. über einem Schwellwert liegen, und
  20. # steuert per GPIO‑Pin einen MOSFET‑Relais für eine bestimmte Zeit an.
  21. # Das Skript nutzt dafür
  22. # -----------------------------------------------------------------------
  23. # I²C (BME280)
  24. # SPI (ADC zum Bodenfeuchte‑Sensor)
  25. # GPIO (Pumpen‑Relais)
  26. # Im Folgenden ein kompletter, kommentierter Python‑Code inklusive des
  27. # Konfigurations‑ und Logfiles.
  28. # #######################################################################
  29. #!/usr/bin/env python3
  30. """
  31. Automatisches Bewässerungs‑Skript
  32. - Liest Bodenfeuchte und BME280‑Daten
  33. - Prüft Schwellenwerte (aus config.json)
  34. - Steuert Relais für Pumpen‑Ansteuerung
  35. - Loggt alles in CSV
  36. Benötigte Bibliotheken:
  37. * adafruit_bme280 – I²C‑BME280
  38. * adafruit_mcp3008 – SPI‑ADC
  39. * busio, board, digitalio – Hardware‑I/O
  40. """
  41. import json
  42. import time
  43. import csv
  44. from pathlib import Path
  45. # ---- 1. Imports für Hardware -------------------------------------------------
  46. import board
  47. import busio
  48. import digitalio
  49. import analogio # falls ein Analog‑GPIO‑Sensor benutzt wird
  50. from adafruit_bme280 import Adafruit_BME280_I2c
  51. from adafruit_mcp3008 import MCP3008
  52. # ---- 2. Konfiguration laden --------------------------------------------------
  53. def load_config(path: str = "config.json") -> dict:
  54. """Liest die JSON‑Konfig (default 'config.json')."""
  55. with open(Path(path), "r", encoding="utf-8") as f:
  56. return json.load(f)
  57. cfg = load_config()
  58. PIN_PUMP = cfg["gpio_pump_pin"]
  59. POLL_SEC = cfg.get("poll_interval_sec", 300) # default: 5 min
  60. LOG_FILE = cfg["log_file"]
  61. # ---- 3. Hardware‑Initialisierung ---------------------------------------------
  62. # I²C‑Bus (BME280)
  63. i2c_bus = busio.I2C(board.SCL, board.SDA, frequency=400_000) # 400 kHz
  64. bme280 = Adafruit_BME280_I2c(i2c_bus)
  65. # SPI‑Bus (ADC – hier MCP3008 für den Bodenfeuchte‑Sensor)
  66. spi_bus = busio.spi.SPI(board.CS0, board.MOSI, board.MISO,
  67. board.SCK, busio.spi.OE)
  68. adc = MCP3008(spi_bus) # Kanal 0: Bodenfeuchte
  69. # GPIO‑Pin (Pumpen‑Relais)
  70. pump_pin = digitalio.DigitalInOut(board.GP(PIN_PUMP))
  71. pump_pin.switch_to_output()
  72. # ---- 4. Messfunktionen ----------------------------------------------------
  73. def read_moisture() -> float:
  74. """Liest den analog‑Sensor (ADC Channel 0) und liefert Bodenfeuchte in m³/m³."""
  75. raw_val = adc.read(0) # ADC‑Wert 0…1023
  76. # Umrechnung: 5 V → 3.3 V (MCP3008 → 10‑Bit)
  77. return raw_val * (5 / 1024)
  78. def read_bme280() -> tuple[float, float, float]:
  79. """Liest Temperatur, Luftfeuchte und Druck aus dem BME280."""
  80. temp = bme280.temperature
  81. humid = bme280.humidity
  82. press = bme280.pressure
  83. return temp, humid, press
  84. def should_water(moist: float) -> bool:
  85. """Gibt True zurück, wenn Bodenfeuchte unter Grenzwert liegt."""
  86. return moist < cfg["moist_threshold"]
  87. # ---- 5. Pumpen‑Steuerung -------------------------------------------------
  88. def pump
  89. ## Soso, hier hat der Plappergeier aufgehört.