Kleine Wettestation mit BME280, grafischer Darstellung und OLED-Display

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
__MiB__
User
Beiträge: 7
Registriert: Sonntag 8. September 2024, 19:07

Hallo zusammen,

Ein neues Problem:
Ich experimentiere noch etwas herum. Der folgende Code soll auf dem Bildschirm eine grafische Darstellung der Werte als Kurve IN 3 x-y-Systemen anzeigen. Gleichzeitig inm Shell Fenster die Momentanwerte incl. Datum und Zeit anzeigen sowie zunächst Datum und Zeit auf einem kleinen OLED-Display (I²C).

Einzeln funktionieren die Scripte, also einmal ohne den Code für das OLED und einmal ausschließlich der Code für das OLED.

Beide Programmteile zusammen:

Code: Alles auswählen

import smbus2
import bme280
import time
import matplotlib.pyplot as plt
from datetime import datetime
import board
import busio
from adafruit_ssd1306 import SSD1306_I2C
from PIL import Image, ImageDraw, ImageFont

# BME280 sensor address (default address)
address = 0x77

# Initialize I2C bus
bus = smbus2.SMBus(1)

# Load calibration parameters
calibration_params = bme280.load_calibration_params(bus, address)

# Create lists to store historical sensor data
timestamps = []
temperature_celsius_values = []
humidity_values = []
pressure_values = []

# Create a variable to control the loop
running = True

# Set up the plot
plt.ion()  # Turn on interactive mode
fig, axs = plt.subplots(3, 1, sharex=True, figsize=(10, 8))
fig.suptitle('Real-time Sensor Readings')

# Labels for the subplots
axs[0].set_ylabel('Temp. (°C)')
axs[1].set_ylabel('Luftf. (%)')
axs[2].set_ylabel('Druck (hPa)')

# I2C-Initialisierung
i2c = busio.I2C(board.SCL, board.SDA)
oled_width = 128
oled_height = 64

# OLED-Display initialisieren
oled = SSD1306_I2C(oled_width, oled_height, i2c)

# Loop forever
while running:
    try:
        # Read sensor data
        # print('Running')
        data = bme280.sample(bus, address, calibration_params)

        # Extract temperature, pressure, humidity, and corresponding timestamp
        # round Data to 1 digit
        temperature_celsius = round(data.temperature, 1)
        humidity = round(data.humidity, 1)
        pressure = round(data.pressure, 1)
        timestamp = data.timestamp
        
        # getting the current date and time
        current_datetime = datetime.now()
        # getting the date and time from the current date and time in the given format
        current_date = current_datetime.strftime("%Y.%m.%d")
        # getting the time from the current date and time in the given format
        current_time = current_datetime.strftime("%H:%M:%S")
        

        # Append data to lists
        timestamps.append(timestamp)
        temperature_celsius_values.append(temperature_celsius)
        humidity_values.append(humidity)
        pressure_values.append(pressure)
        
        # print data to screen
        print("Datum  :", current_date)
        print("Zeit   :", current_time)
        print("Temp.  : ", temperature_celsius, "°C")
        print("Luftf. : ", humidity, "%")
        print("Luftdr.:", pressure, "hpa")
        print()
        
        # Bild erstellen für OLED
        image = Image.new("1", (oled_width, oled_height))
        draw = ImageDraw.Draw(image)

        # Schriftarten festlegen
        FreeSans12 = ImageFont.truetype('FreeSans.ttf', 12)
        FreeSans20 = ImageFont.truetype('FreeSans.ttf', 20)

        # Bildschirm löschen
        draw.rectangle((0, 0, oled_width, oled_height), outline=0, fill=0)

        # Text auf dem Bildschirm anzeigen
        font = ImageFont.load_default()
        draw.text((0, 0), "Datum:", font=font, fill=255)
        draw.text((0,13), current_date, font=FreeSans20, fill=255)
        draw.text((0,30), "Zeit:", font=font, fill=255)
        draw.text((0,43), current_time, font=FreeSans20, fill=255)

        # Bild auf OLED anzeigen
        oled.image(image)
        oled.show()

        # Plot the data
        for i, (ax, values, label) in enumerate(zip(axs, [temperature_celsius_values, humidity_values, pressure_values], ['Temp. (°C)', 'Luftf. (%)', 'Druck (hPa)'])):
            ax.clear()
            ax.plot(timestamps, values, label=label)
            # ax.legend()
            ax.set_ylabel(label)

        axs[-1].set_xlabel('Zeit')

        fig.autofmt_xdate(rotation=67)
        plt.pause(1)  # Pause for 1 second to update the plot

        time.sleep(0) # alle 4 Sekunden den Loop wiederholen

    except KeyboardInterrupt:
        print('Program stopped')
        running = False
    except Exception as e:
        print('An unexpected error occurred:', str(e))
        running = False

# Close the plot at the end
Kann man sicher eleganter schreiben, aber ich habe noch nicht so viel Erfahrung damit.

Wenn ich das Script laufen lasse, kommt folgende Fehlermeldung und das Programm stoppt:

Code: Alles auswählen

An unexpected error occurred: [Errno 121] Remote I/O error
Es öffnet sich dann noch das Fenster, in dem die 3 Koordinatensysteme angezeigt werden, dann tut sich nichts mehr.

Wenn ich das Script Schritt für Schritt durchgehe, funktioniert es. Ist aber nicht Sinn der Sache :)

Wo könnte der Fehler sein? Ich suche schon seit Stunden...
Der Tipp, nach dem

Code: Alles auswählen

# Initialize I2C bus
bus = smbus2.SMBus(1)
noch ein

Code: Alles auswählen

time.sleep(1)
einzufügen, hat nicht funktioniert :(

Kennt jemand eine Lösung oder einen Weg, wie man einen solchen Fehler analysiert?
Benutzeravatar
Dennis89
User
Beiträge: 1517
Registriert: Freitag 11. Dezember 2020, 15:13

Hallo,

schau mal in dein anderes Thema, lese dir die Tipps von @Sirius3 durch, besonders den Teil mit der Fehlerbehandlung. Das hatte er ja dann auch verbessert/weggelassen. Wenn du dass bei dir jetzt auch machst, bekommst du schon mal eine aussagekräftigere Fehlermeldung.

Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Antworten