Bemerkung
Hallo, willkommen in der SunFounder Raspberry Pi & Arduino & ESP32 Enthusiasten-Community auf Facebook! Tauchen Sie mit anderen Enthusiasten tiefer in Raspberry Pi, Arduino und ESP32 ein.
Warum beitreten?
Expertenunterstützung: Lösen Sie Probleme nach dem Kauf und technische Herausforderungen mit Hilfe unserer Community und unseres Teams.
Lernen & Teilen: Tauschen Sie Tipps und Tutorials aus, um Ihre Fähigkeiten zu verbessern.
Exklusive Vorschauen: Erhalten Sie frühzeitigen Zugang zu neuen Produktankündigungen und Sneak Peeks.
Sonderrabatte: Genießen Sie exklusive Rabatte auf unsere neuesten Produkte.
Festliche Aktionen und Gewinnspiele: Nehmen Sie an Gewinnspielen und Feiertagsaktionen teil.
👉 Bereit, mit uns zu entdecken und zu gestalten? Klicken Sie auf [here] und treten Sie noch heute bei!
(Beispiel) Intelligente Wetterstation
Einführung
Dieses Projekt erstellt eine umfassende intelligente Wetterstation, die lokale Umweltsensoren mit globalen Wetterdaten und AI-Analyse kombiniert. Das System integriert:
Lokale Sensordaten von DHT11 (Temperatur/Luftfeuchtigkeit) und LDR (Lichtsensor)
Globale Wettervorhersagen über die OpenWeather-API
AI-gestützte Sprachanalyse mit den GPT- und TTS-Funktionen von OpenAI
Visuelle Anzeige auf einem 128x64-OLED-Display
Interaktive Taste für spontane, AI-generierte Wetterauswertungen
Die Wetterstation vergleicht automatisch lokale Bedingungen mit Vorhersagedaten und liefert intelligente Empfehlungen per Sprachausgabe. So entsteht eine vollständige Lösung zur Umgebungsüberwachung.
Sie können auch andere LLM- und TTS-Module verwenden, um Ihre eigenen intelligenten Geräte zu entwickeln. Siehe:
Was Sie benötigen
Für dieses Projekt werden die folgenden Komponenten benötigt:
COMPONENT |
PURCHASE LINK |
|---|---|
- |
|
- |
|
Raspberry Pi |
- |
Schaltplan
Verbinden Sie die Komponenten wie folgt mit dem Fusion HAT+:
API-Schlüssel erstellen und speichern
Gehen Sie zu OpenAI Platform und melden Sie sich an. Klicken Sie auf der Seite API keys auf Create new secret key.
Füllen Sie die Angaben aus (Owner, Name, Project und gegebenenfalls Berechtigungen) und klicken Sie dann auf Create secret key.
Sobald der Schlüssel erstellt wurde, kopieren Sie ihn sofort — später wird er nicht noch einmal angezeigt. Falls Sie ihn verlieren, müssen Sie einen neuen erstellen.
Erstellen Sie in Ihrem Projektordner (zum Beispiel:
/) eine Datei mit dem Namensecret.py:cd ~/ai-lab-kit/llm sudo nano secret.py
Fügen Sie Ihren Schlüssel wie folgt in die Datei ein:
# secret.py # Store secrets here. Never commit this file to Git. OPENAI_API_KEY = "sk-xxx"
Abrechnung aktivieren und Modelle prüfen
Bevor Sie den Schlüssel verwenden, öffnen Sie in Ihrem OpenAI-Konto die Seite Billing, hinterlegen Sie Ihre Zahlungsdaten und laden Sie ein kleines Guthaben auf.
Wechseln Sie anschließend zur Seite Limits, um zu prüfen, welche Modelle für Ihr Konto verfügbar sind, und kopieren Sie die genaue Modell-ID für die Verwendung im Code.
OpenWeather-API-Schlüssel abrufen
OpenWeather ist ein Onlinedienst der OpenWeather Ltd, der über eine API weltweite Wetterdaten bereitstellt, darunter aktuelle Wetterdaten, Vorhersagen, Nowcasts und historische Wetterdaten für jeden geografischen Ort.
Besuchen Sie OpenWeather und melden Sie sich an bzw. erstellen Sie ein Konto.
Öffnen Sie über die Navigationsleiste die API-Seite.
Suchen Sie Current Weather Data und klicken Sie auf Subscribe.
Abonnieren Sie unter Current weather and forecasts collection den passenden Dienst. Für unser Projekt reicht die kostenlose Version völlig aus.
Kopieren Sie den Schlüssel von der Seite API keys.
Öffnen Sie die Datei
secret.pymit folgendem Befehl:cd ~/ai-lab-kit/llm sudo nano secret.py
Fügen Sie den kopierten API-Schlüssel hinzu:
OPENWEATHER_API_KEY = "732exxxxxxxxxxxxxxxxxxxxx919b"Drücken Sie
Ctrl + X,Yund anschließendEnter, um die Datei zu speichern und den Editor zu beenden.
Beispiel ausführen
Code ausführen
cd ~/ai-lab-kit/llm sudo python3 llm_openai_weather.py
Was Sie nach dem Start des Skripts sehen
Das OLED schaltet sich ein und beginnt, Wetterinformationen anzuzeigen.
Das Programm gibt im Terminal Startinformationen aus, darunter die Zielstadt und den verwendeten Button-Pin.
Das OLED wechselt automatisch alle 10 Sekunden zwischen den Seiten (insgesamt 3 Seiten):
Seite 1: Lokale Sensoren (DHT11 + LDR) Zeigt lokale Temperatur, Luftfeuchtigkeit und Lichtstärke an (einschließlich einer kleinen Lichtbalkenanzeige).
Seite 2: Wettervorhersage (OpenWeather) Zeigt die aktuelle Temperatur, die Wetterbeschreibung und die letzte Aktualisierungszeit an.
Seite 3: AI-Auswertung Zeigt die Unterschiede zwischen den lokalen Sensordaten und den OpenWeather-Daten sowie einen einfachen Komfortstatus an (z. B. Comfortable / Warm / Cool / Humid / Dry).
AI-Sprachanalyse auslösen
Drücken Sie die Taste an GPIO 27, damit die AI eine kurze Analyse im Stil eines „Wetterreporters“ erstellt.
Im Terminal wird ein Abschnitt
AI Analysisausgegeben, einschließlich:Lokale Messwerte (Temperatur / Luftfeuchtigkeit / Licht)
Externe Wetterdaten (OpenWeather-Temperatur + Beschreibung)
Eine kurze, von der AI erzeugte Zusammenfassung
Das OLED zeigt vorübergehend SPEAKING…
Die Analyse wird über den Lautsprecher mit OpenAI TTS gesprochen
Aktualisierungsverhalten der Daten
Die lokalen Sensoren werden etwa alle 2 Sekunden aktualisiert.
Die OpenWeather-Daten werden etwa alle 5 Minuten aktualisiert.
Der Lichtwert wird automatisch geglättet, um Flackern zu reduzieren.
Programm beenden
Drücken Sie im Terminal
Ctrl+C, um das Programm zu beenden.Das OLED wird gelöscht und das Programm wird sicher beendet.
Code
Hier ist das vollständige Python-Skript für die intelligente Wetterstation:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Smart Weather Station with AI Assistant
- Reads local temperature & humidity from DHT11 on GPIO 17
- Reads light level from LDR on ADC A0 (0..4095)
- Fetches weather forecast from OpenWeather API
- Provides AI voice analysis using OpenAI (triggered by button)
- Displays all information on 128x64 SSD1306 OLED
"""
import time
import requests
from datetime import datetime
from statistics import mean
from fusion_hat.modules import DHT11
from fusion_hat.adc import ADC
from fusion_hat.pin import Pin, Mode, Pull
from PIL import Image, ImageDraw, ImageFont
import adafruit_ssd1306
import board
from sunfounder_voice_assistant.tts import OpenAI_TTS
from secret import OPENAI_API_KEY, OPENWEATHER_API_KEY
from signal import pause
# Configuration
DHT_PIN = 17 # DHT11 uses GPIO 17
LDR_CH = 0
I2C_ADDR = 0x3C
# OpenWeather API Configuration
CITY_NAME = "Shanghai"
COUNTRY_CODE = "CN"
LATITUDE = 31.2304
LONGITUDE = 121.4737
UNITS = "metric"
# Update intervals in seconds
WEATHER_UPDATE_INTERVAL = 300
SENSOR_UPDATE_INTERVAL = 2
# GPIO Pins
BUTTON_PIN = 27 # Button uses GPIO 27
# OLED Setup
WIDTH, HEIGHT = 128, 64
i2c = board.I2C()
oled = adafruit_ssd1306.SSD1306_I2C(WIDTH, HEIGHT, i2c, addr=I2C_ADDR)
oled.fill(0)
oled.show()
# Load fonts
try:
font_small = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 10)
font_medium = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 12)
font_large = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 14)
except:
print("Warning: Using default font")
font_small = ImageFont.load_default()
font_medium = ImageFont.load_default()
font_large = ImageFont.load_default()
image = Image.new("1", (WIDTH, HEIGHT))
draw = ImageDraw.Draw(image)
# Sensors
dht = DHT11(pin=DHT_PIN)
ldr = ADC(LDR_CH)
# Button for triggering AI analysis
button = Pin(BUTTON_PIN, mode=Mode.IN, pull=Pull.DOWN)
# OpenWeather API Class
class WeatherAPI:
def __init__(self, api_key, city, country_code, lat=None, lon=None):
self.api_key = api_key
self.city = city
self.country_code = country_code
self.lat = lat
self.lon = lon
self.current_weather = None
self.forecast = None
self.last_update = 0
def get_weather_url(self):
if self.lat and self.lon:
return f"https://api.openweathermap.org/data/2.5/weather?lat={self.lat}&lon={self.lon}&appid={self.api_key}&units={UNITS}"
else:
return f"https://api.openweathermap.org/data/2.5/weather?q={self.city},{self.country_code}&appid={self.api_key}&units={UNITS}"
def get_forecast_url(self):
if self.lat and self.lon:
return f"https://api.openweathermap.org/data/2.5/forecast?lat={self.lat}&lon={self.lon}&appid={self.api_key}&units={UNITS}"
else:
return f"https://api.openweathermap.org/data/2.5/forecast?q={self.city},{self.country_code}&appid={self.api_key}&units={UNITS}"
def update_weather(self):
try:
# Current weather
response = requests.get(self.get_weather_url(), timeout=10)
if response.status_code == 200:
self.current_weather = response.json()
print(f"Weather API success: {self.current_weather['weather'][0]['description']}")
else:
print(f"Weather API error: {response.status_code}")
return False
# Forecast
response = requests.get(self.get_forecast_url(), timeout=10)
if response.status_code == 200:
self.forecast = response.json()
self.last_update = time.time()
return True
except Exception as e:
print(f"Weather API error: {e}")
return False
def get_temperature(self):
if self.current_weather:
return self.current_weather['main']['temp']
return None
def get_humidity(self):
if self.current_weather:
return self.current_weather['main']['humidity']
return None
def get_weather_description(self):
if self.current_weather:
return self.current_weather['weather'][0]['description'].title()
return None
def get_weather_condition(self):
if self.current_weather:
weather_id = self.current_weather['weather'][0]['id']
if weather_id < 300:
return "TSTORM"
elif weather_id < 600:
return "RAIN"
elif weather_id < 700:
return "SNOW"
elif weather_id == 800:
return "CLEAR"
elif weather_id < 900:
return "CLOUDS"
else:
return "OTHER"
return "N/A"
def get_forecast_summary(self):
if not self.forecast or 'list' not in self.forecast:
return "No forecast"
forecasts = self.forecast['list'][:8]
temps = [f['main']['temp'] for f in forecasts]
min_temp = min(temps)
max_temp = max(temps)
conditions = {}
for f in forecasts:
condition = f['weather'][0]['main']
conditions[condition] = conditions.get(condition, 0) + 1
most_common = max(conditions, key=conditions.get)
return f"{min_temp:.0f}-{max_temp:.0f}C {most_common}"
# AI Weather Analyst Class
class WeatherAI:
def __init__(self, api_key):
self.api_key = api_key
self.tts = OpenAI_TTS(api_key=api_key)
self.tts.set_voice(self.tts.Voice.ALLOY)
self.is_speaking = False
def analyze_weather(self, local_temp, local_hum, local_light, weather_data):
temp_diff = abs(local_temp - weather_data.get('current_temp', local_temp)) if weather_data.get('current_temp') else 0
if temp_diff > 3:
accuracy = "significantly different from"
elif temp_diff > 1:
accuracy = "slightly different from"
else:
accuracy = "very close to"
recommendations = []
if local_hum > 80:
recommendations.append("It's quite humid")
elif local_hum < 30:
recommendations.append("The air is dry")
if local_light > 80:
recommendations.append("It's bright here")
elif local_light < 20:
recommendations.append("It's quite dark")
weather_desc = weather_data.get('weather_desc', '').lower()
if 'rain' in weather_desc or 'drizzle' in weather_desc or 'thunderstorm' in weather_desc:
recommendations.append("Don't forget an umbrella")
elif 'clear' in weather_desc:
recommendations.append("Great day to go outside")
elif 'cloud' in weather_desc:
recommendations.append("Partly cloudy today")
rec_text = ". ".join(recommendations) + "." if recommendations else "Conditions are normal."
analysis = f"Local sensors show {local_temp:.1f}C, which is {accuracy} the forecast. {rec_text}"
return analysis
def speak_analysis(self, analysis_text):
if self.is_speaking:
print("Already speaking, please wait...")
return False
try:
self.is_speaking = True
print(f"Speaking analysis: {analysis_text}")
self.tts.say(analysis_text, instructions="speak clearly and professionally like a weather reporter")
self.is_speaking = False
return True
except Exception as e:
print(f"TTS error: {e}")
self.is_speaking = False
return False
# Light sensor helper
_light_window = []
def light_percent(raw, min_val=0, max_val=4095):
global _light_window
_light_window.append(raw)
if len(_light_window) > 5:
_light_window.pop(0)
smooth_raw = int(mean(_light_window))
pct = (smooth_raw - min_val) / (max_val - min_val) * 100 if max_val > min_val else 50
pct = max(0, min(100, pct))
return int(pct), smooth_raw
# Display Manager Class
class DisplayManager:
def __init__(self):
self.current_page = 0
self.num_pages = 3
self.last_page_change = 0
self.page_cycle_interval = 10
def next_page(self):
self.current_page = (self.current_page + 1) % self.num_pages
self.last_page_change = time.time()
def should_change_page(self):
return time.time() - self.last_page_change > self.page_cycle_interval
def draw_page(self, page_num, local_temp, local_hum, light_pct, weather_api, weather_ai):
draw.rectangle((0, 0, WIDTH, HEIGHT), outline=0, fill=0)
if page_num == 0:
self._draw_local_sensors(local_temp, local_hum, light_pct)
elif page_num == 1:
self._draw_weather_forecast(weather_api)
elif page_num == 2:
self._draw_ai_insights(local_temp, local_hum, light_pct, weather_api)
# Page indicator at bottom right
indicator = f"{page_num+1}/{self.num_pages}"
indicator_width = len(indicator) * 6
draw.text((WIDTH - indicator_width - 2, HEIGHT - 10), indicator, font=font_small, fill=255)
def _draw_local_sensors(self, temp, hum, light):
# Title at top
draw.text((2, 2), "LOCAL SENSORS", font=font_medium, fill=255)
# Temperature - larger font on first line
temp_text = f"Temp: {temp:.1f} C"
draw.text((10, 18), temp_text, font=font_large, fill=255)
# Humidity - second line
hum_text = f"Humidity: {hum:.1f}%"
draw.text((10, 38), hum_text, font=font_medium, fill=255)
# Light with bar on same line
light_text = f"Light: {light}%"
draw.text((10, 53), light_text, font=font_small, fill=255)
# Light bar positioned next to text, not overlapping
bar_x = 60 # Position after "Light: XX%"
bar_y = 55
bar_width = 50
bar_height = 4
# Draw background bar
draw.rectangle((bar_x, bar_y, bar_x + bar_width, bar_y + bar_height), outline=255, fill=0)
# Draw filled portion
fill_width = int(bar_width * light / 100)
if fill_width > 0:
draw.rectangle((bar_x, bar_y, bar_x + fill_width, bar_y + bar_height), outline=0, fill=255)
def _draw_weather_forecast(self, weather_api):
draw.text((2, 2), "WEATHER", font=font_medium, fill=255)
if not weather_api.current_weather:
draw.text((10, 25), "No weather data", font=font_medium, fill=255)
draw.text((10, 45), "Check connection", font=font_small, fill=255)
return
current_temp = weather_api.get_temperature()
weather_desc = weather_api.get_weather_description()
weather_cond = weather_api.get_weather_condition()
# Temperature - large font
if current_temp is not None:
draw.text((10, 18), f"{current_temp:.0f} C", font=font_large, fill=255)
# Weather description
if weather_desc:
desc_text = weather_desc[:15]
draw.text((10, 38), desc_text, font=font_medium, fill=255)
# Weather condition
if weather_cond:
draw.text((10, 53), weather_cond, font=font_small, fill=255)
# Update time at top right
if weather_api.last_update > 0:
update_time = datetime.fromtimestamp(weather_api.last_update).strftime("%H:%M")
update_text = f"Up: {update_time}"
update_width = len(update_text) * 6
draw.text((WIDTH - update_width - 2, 2), update_text, font=font_small, fill=255)
def _draw_ai_insights(self, local_temp, local_hum, light_pct, weather_api):
draw.text((2, 2), "AI INSIGHTS", font=font_medium, fill=255)
api_temp = weather_api.get_temperature() if weather_api.current_weather else None
api_hum = weather_api.get_humidity() if weather_api.current_weather else None
line_y = 18
# Temperature difference
if api_temp is not None:
temp_diff = local_temp - api_temp
temp_symbol = "+" if temp_diff > 0 else "" if temp_diff == 0 else ""
diff_text = f"Temp: {temp_symbol}{temp_diff:.1f}C"
draw.text((10, line_y), diff_text, font=font_medium, fill=255)
line_y += 15
# Humidity difference
if api_hum is not None:
hum_diff = local_hum - api_hum
hum_symbol = "+" if hum_diff > 0 else "" if hum_diff == 0 else ""
diff_text = f"Hum: {hum_symbol}{hum_diff:.1f}%"
draw.text((10, line_y), diff_text, font=font_medium, fill=255)
line_y += 15
# Comfort level
comfort = "Normal"
comfort_color = 255
if 20 <= local_temp <= 25 and 40 <= local_hum <= 60:
comfort = "Comfortable"
comfort_color = 255
elif local_temp > 28:
comfort = "Warm"
comfort_color = 255
elif local_temp < 16:
comfort = "Cool"
comfort_color = 255
elif local_hum > 70:
comfort = "Humid"
comfort_color = 255
elif local_hum < 30:
comfort = "Dry"
comfort_color = 255
draw.text((10, line_y), f"Feel: {comfort}", font=font_small, fill=comfort_color)
# Button hint at bottom left
draw.text((2, HEIGHT - 10), "Press BTN for AI", font=font_small, fill=255)
# Main Application Class
class SmartWeatherStation:
def __init__(self):
print("Initializing Smart Weather Station...")
self.weather_api = WeatherAPI(OPENWEATHER_API_KEY, CITY_NAME, COUNTRY_CODE, LATITUDE, LONGITUDE)
self.weather_ai = WeatherAI(OPENAI_API_KEY)
self.display = DisplayManager()
self.local_temp = 0.0
self.local_hum = 0.0
self.light_pct = 0
self.raw_adc = 0
self.last_weather_update = 0
self.last_sensor_update = 0
# Setup button callback
button.when_activated = self._button_pressed
# Initial readings
self._update_sensors()
self.weather_api.update_weather()
print("Smart Weather Station ready!")
print(f"City: {CITY_NAME}")
print(f"Temperature unit: {UNITS}")
print(f"Button on GPIO {BUTTON_PIN} for AI analysis")
print("="*50)
def _update_sensors(self):
try:
result = dht.read()
if result:
hum, temp = result
self.local_hum = float(hum)
self.local_temp = float(temp)
raw = ldr.read()
self.light_pct, self.raw_adc = light_percent(raw)
self.last_sensor_update = time.time()
return True
except Exception as e:
print(f"Sensor error: {e}")
return False
def _update_weather(self):
if time.time() - self.last_weather_update > WEATHER_UPDATE_INTERVAL:
print("Updating weather data...")
if self.weather_api.update_weather():
self.last_weather_update = time.time()
return True
return False
def _button_pressed(self):
"""Called when button is pressed"""
print("\n" + "="*50)
print("Button pressed! Triggering AI analysis...")
print("="*50)
# Update sensors first to get latest data
self._update_sensors()
# Get weather data
api_temp = self.weather_api.get_temperature()
if api_temp is None:
print("No weather data available. Please wait for update.")
return
# Prepare weather data for analysis
weather_data = {
'current_temp': api_temp,
'weather_desc': self.weather_api.get_weather_description(),
'forecast_summary': self.weather_api.get_forecast_summary()
}
# Generate analysis
analysis = self.weather_ai.analyze_weather(
self.local_temp,
self.local_hum,
self.light_pct,
weather_data
)
print(f"\nAI Analysis:")
print(f"Local: {self.local_temp:.1f}C, {self.local_hum:.1f}%, Light: {self.light_pct}%")
print(f"Remote: {api_temp}C, {self.weather_api.get_weather_description()}")
print(f"Analysis: {analysis}")
# Show "Speaking..." on display
self._show_speaking_message()
# Speak the analysis
success = self.weather_ai.speak_analysis(analysis)
if success:
print("Analysis completed successfully!")
else:
print("Analysis failed or interrupted.")
print("="*50)
def _show_speaking_message(self):
"""Display a temporary "Speaking..." message"""
draw.rectangle((0, 0, WIDTH, HEIGHT), outline=0, fill=0)
draw.text((WIDTH//2 - 40, HEIGHT//2 - 10), "SPEAKING...", font=font_medium, fill=255)
oled.image(image)
oled.show()
def run(self):
print("\n" + "="*50)
print("SMART WEATHER STATION")
print("="*50)
print("Display Pages:")
print("1. Local Sensors (DHT11 + LDR)")
print("2. Weather Forecast (OpenWeather)")
print("3. AI Insights (Comparisons)")
print("")
print(f"Press button on GPIO {BUTTON_PIN} for AI voice analysis")
print("Press Ctrl+C to exit")
print("="*50 + "\n")
try:
while True:
current_time = time.time()
# Update sensors periodically
if current_time - self.last_sensor_update > SENSOR_UPDATE_INTERVAL:
self._update_sensors()
# Update weather data periodically
self._update_weather()
# Auto-cycle display pages
if self.display.should_change_page():
self.display.next_page()
# Draw current page
self.display.draw_page(
self.display.current_page,
self.local_temp,
self.local_hum,
self.light_pct,
self.weather_api,
self.weather_ai
)
# Update OLED display
oled.image(image)
oled.show()
# Small delay to prevent CPU overload
time.sleep(0.1)
except KeyboardInterrupt:
print("\nShutting down...")
finally:
# Cleanup
oled.fill(0)
oled.show()
print("Smart Weather Station stopped.")
# Main Entry Point
if __name__ == "__main__":
if not OPENAI_API_KEY or OPENAI_API_KEY == "your-openai-api-key-here":
print("ERROR: Please set your OpenAI API key in secret.py")
exit(1)
if not OPENWEATHER_API_KEY or OPENWEATHER_API_KEY == "your-openweather-api-key-here":
print("ERROR: Please set your OpenWeather API key in secret.py")
print("Get one at: https://openweathermap.org/api")
exit(1)
station = SmartWeatherStation()
station.run()
Code verstehen
Sensorintegration
Das System liest Daten von zwei lokalen Sensoren aus:
# DHT11 für Temperatur und Luftfeuchtigkeit dht = DHT11(pin=DHT_PIN) result = dht.read() # Gibt (humidity, temperature) zurück # LDR (lichtabhängiger Widerstand) über ADC ldr = ADC(LDR_CH) raw = ldr.read() # Gibt einen Wert von 0–4095 zurück
OpenWeather-API-Integration
Die Klasse
WeatherAPIverwaltet die Verbindung zu OpenWeather für aktuelle Wetterbedingungen und Vorhersagen:class WeatherAPI: def update_weather(self): # Endpoint für aktuelles Wetter response = requests.get(self.get_weather_url(), timeout=10) self.current_weather = response.json() # Endpoint für Vorhersage response = requests.get(self.get_forecast_url(), timeout=10) self.forecast = response.json()
AI-Analyse-Engine
Die Klasse
WeatherAIerzeugt intelligente Wetteranalysen und wandelt diese in Sprache um:class WeatherAI: def analyze_weather(self, local_temp, local_hum, local_light, weather_data): # Temperaturdifferenz berechnen temp_diff = abs(local_temp - weather_data.get('current_temp', local_temp)) # Empfehlungen basierend auf den Bedingungen erstellen recommendations = [] if local_hum > 80: recommendations.append("It's quite humid") # Analyse-Text erstellen analysis = f"Local sensors show {local_temp:.1f}C..." return analysis def speak_analysis(self, analysis_text): self.tts.say(analysis_text, instructions="speak clearly...")
Mehrseitiges Display-System
Der
DisplayManagerverwaltet drei Informationsseiten, die automatisch wechseln:class DisplayManager: def draw_page(self, page_num, ...): if page_num == 0: self._draw_local_sensors(...) elif page_num == 1: self._draw_weather_forecast(...) elif page_num == 2: self._draw_ai_insights(...) def _draw_local_sensors(self, temp, hum, light): # Temperatur, Luftfeuchtigkeit und Lichtstärke mit Fortschrittsbalken zeichnen
Button-Ereignisverarbeitung
Beim Drücken der Taste wird eine AI-Sprachanalyse ausgelöst:
button = Pin(BUTTON_PIN, mode=Mode.IN, pull=Pull.DOWN) button.when_activated = self._button_pressed def _button_pressed(self): # Sensoren aktualisieren, Analyse erstellen und sprechen analysis = self.weather_ai.analyze_weather(...) self.weather_ai.speak_analysis(analysis)
Daten-Glättung für den Lichtsensor
Der Lichtsensor verwendet einen gleitenden Mittelwert für stabilere Messwerte:
def light_percent(raw, min_val=0, max_val=4095): _light_window.append(raw) if len(_light_window) > 5: _light_window.pop(0) smooth_raw = int(mean(_light_window)) # Gleitender Durchschnitt pct = (smooth_raw - min_val) / (max_val - min_val) * 100
Hauptanwendungsschleife
Die Klasse
SmartWeatherStationkoordiniert alle Komponenten mit korrektem Timing:def run(self): while True: # Sensoren alle 2 Sekunden aktualisieren if time.time() - self.last_sensor_update > SENSOR_UPDATE_INTERVAL: self._update_sensors() # Wetterdaten alle 5 Minuten aktualisieren self._update_weather() # Seiten alle 10 Sekunden automatisch wechseln if self.display.should_change_page(): self.display.next_page() # Aktuelle Seite anzeigen self.display.draw_page(...)
Fehlerbehebung
Fehler „DHT11 read failed“
Verkabelung prüfen: VCC (3.3V), DATA (GPIO 17), GND
Einen 10kΩ Pull-up-Widerstand zwischen DATA und VCC hinzufügen
Sensor von Wärmequellen fernhalten (Raspberry Pi kann selbst Wärme erzeugen)
Kleine Verzögerung zwischen Messungen einfügen:
time.sleep(2)
OpenWeather-API-Fehler
Prüfen, ob der API-Schlüssel korrekt und gültig ist
Internetverbindung testen:
ping 8.8.8.8Stadtname und Ländercode überprüfen
Kostenlose API hat Limits (60 Aufrufe/Minute, 1.000.000 Aufrufe/Monat)
OLED-Display zeigt nichts
I2C-Verbindung prüfen:
sudo i2cdetect -y 1(sollte 0x3C anzeigen)Prüfen, ob das OLED mit Strom versorgt wird (3.3V oder 5V je nach Modell)
Richtige I2C-Adresse sicherstellen (0x3C oder 0x3D)
Kein Ton bei TTS
Audioausgabe prüfen:
sudo raspi-config→ System Options → AudioAudiotest durchführen:
speaker-test -t sine -f 440Prüfen, ob der OpenAI-TTS-API-Schlüssel genügend Credits hat
Internetverbindung für API-Aufrufe prüfen
Button reagiert nicht
Verkabelung prüfen: Taste zwischen GPIO 27 und GND
Prüfen, ob Pull-down-Widerstand im Code aktiviert ist
Taste mit einfachem Testskript überprüfen
Ungenaue Lichtmessung
LDR kalibrieren, indem
min_valundmax_valinlight_percent()angepasst werdenLDR vollständig abdecken, um den Minimalwert zu bestimmen
LDR hellem Licht aussetzen, um den Maximalwert zu bestimmen
Sicherstellen, dass der LDR nicht im Schatten anderer Bauteile liegt
Wetterdaten veraltet
WEATHER_UPDATE_INTERVALerhöhen, um häufiger zu aktualisierenPrüfen, ob API-Aufrufe erfolgreich sind (Fehlermeldungen beachten)
Systemzeit prüfen:
date
Diese intelligente Wetterstation zeigt, wie lokale Sensordaten, Cloud-Dienste und AI kombiniert werden können, um ein fortschrittliches Umgebungsüberwachungssystem zu schaffen, das praktische Erkenntnisse und intelligente Empfehlungen liefert.