Skip to content

Technik Blog

Programmieren | Arduino | ESP32 | MicroPython | Python | Raspberry Pi | Raspberry Pi Pico

Menu
  • Smarthome
  • Arduino
  • ESP32 & Co.
  • Raspberry Pi & Pico
  • Solo Mining
  • Über mich
  • Deutsch
  • English
Menu

MAKER Pi Pico #2 – Sensordaten auf einer SD-Card speichern

Posted on 6. September 20217. Juni 2024 by Stefan Draeger

In diesem Beitrag möchte ich dir zeigen, wie du Sensordaten am MAKER Pi Pico mit dem SD-Card Adapter auf einer entsprechenden Micro SD-Card speichern kannst.

MAKER Pi Pico - schreiben von Daten auf die SD-Karte
Dieses Video auf YouTube ansehen.

Im letzten Beitrag habe ich dir gezeigt wie du Sensordaten an den IoT Service ThingSpeak senden kannst, wenn du aber einmal keine WiFi Verbindung hast oder aber dein eigenes Dashboard erstellen möchtest dann kannst du mit diesem Feature deine Daten sicher zwischenspeichern.

Den MAKER Pi Pico selber, habe ich dir bereits im Beitrag Maker Pi Pico von Cytron vorgestellt.

MAKER Pi Pico
MAKER Pi Pico

  • Benötigte Ressourcen zum Nachbau
  • Schaltung & Aufbau
  • Pinout des SD-Card Adapters
  • Programmieren des SD-Card Adapters am MAKER Pi Pico
    • Mounten einer SD-Card & schreiben einer Zeile in eine Textdatei
    • lesen von Dateien einer SD-Card
  • Ausgabe auf der Konsole
  • Schreiben von Sensordaten auf der SD-Karte
    • Was ist das CSV Format?
    • Daten im CSV Format schreiben & lesen
      • Ausgabe auf der Konsole
    • Zeitstempel für die Sensordaten
      • Aufbau einer WiFi Verbindung und laden des Zeitstempels von der Webseite
    • schreiben der Sensordaten im CSV Format
      • Video – schreiben der DHT11 Sensorwerte in eine CSV Datei auf der SD-Karte

Benötigte Ressourcen zum Nachbau

Möchtest du die Beispiele aus dem Beitrag nachbauen, so benötigst du folgende Ressourcen:

  • MAKER Pi Pico*,
    • Micro USB Datenkabel*,
  • DHT11 Sensor*,
  • SD-Card mit 16 GB*,
  • USB SD-Card Reader für den PC*

Hinweis von mir: Die mit einem Sternchen (*) markierten Links sind Affiliate-Links. Wenn du über diese Links einkaufst, erhalte ich eine kleine Provision, die dazu beiträgt, diesen Blog zu unterstützen. Der Preis für dich bleibt dabei unverändert. Vielen Dank für deine Unterstützung!

MAKER Pi Pico mit Micro SD-Card
MAKER Pi Pico mit Micro SD-Card

Schaltung & Aufbau

In diesem Beitrag verwende ich den DHT11 Sensor mit Grove Schnittstelle. Der DHT11 Sensor hat den Vorteil das diese zwei Werte liefert (Temperatur, rel. Luftfeuchtigkeit), jedoch den Nachteil das dieser nicht zuverlässig Werte liefert bzw. das Auslesen nicht zuverlässig funktioniert.

MAKER Pi Pico mit DHT11 Sensor und Micro SD-Karte
MAKER Pi Pico mit DHT11 Sensor und Micro SD-Karte

Pinout des SD-Card Adapters

Der MAKER Pi Pico hat einen SD-Card Adapter onBoard d.h. wir müssen uns nicht zusätzlich ein Modul besorgen und ggf. umständlich anschließen.

Wenn du „nur“ den Raspberry Pi Pico verwenden möchtest dann gebe ich dir hier das Pinout des SD-Card Adapters.

Raspberry Pi
Pico GPIO
SD ModeSPI Mode
GP10CLKSCK
GP11CMDSDI / MOSI
GP12DAT0SDO / MISO
GP13DAT1X
GP14DAT2X
GP15CD/DAT3CSn
Pinout des SD-Card Adapters am MAKER Pi Pico

Auf der Seite Maker Pi Pico Datasheet findest du weitere technische Daten zum MAKER Pi Pico.

Anschluss eines SD-Card Adapters an den Raspberry Pi Pico
Anschluss eines SD-Card Adapters an den Raspberry Pi Pico

In meinem Fall brauche ich nur den DHT11 Sensor anschließen und das Micro USB Kabel anschließen und bin mit dem Aufbau für diesen Beitrag fertig.

Programmieren des SD-Card Adapters am MAKER Pi Pico

Für die nachfolgenden Beispiele verwende ich das Tutorial „Write Read Data to SD Card Using Maker Pi Pico and CircuitPython“ als Basis. Dieses Tutorial ist zwar in Englisch, aber durch die recht einfache Skriptsprache CircuitPython kann man den Quellcode gut lesen und verstehen.

Mounten einer SD-Card & schreiben einer Zeile in eine Textdatei

Zunächst wollen wir eine SD-Karte mounten quasi einbinden und in eine Datei eine Textzeile schreiben.

from board import *
from time import *
import busio
import sdcardio
import storage

# eine Pause von 1 Sekunde 
sleep(1)
 
# definieren der Pins der SD-Card
spi = busio.SPI(GP10, MOSI=GP11, MISO=GP12)
cs = GP15
sd = sdcardio.SDCard(spi, cs)

# einbinden der SD Karte
vfs = storage.VfsFat(sd)
storage.mount(vfs, '/sd')

# öffnen der Datei pico.txt zum schreiben
# wenn diese Datei nicht existiert dann
# wird diese zuvor erstellt
with open("/sd/pico.txt", "w") as file:
 # schreiben einer Zeile in die Datei
 file.write("Hello, world!")
 # schreiben eines Zeilenumbruchs
 file.write("\r\n")

lesen von Dateien einer SD-Card

Da wir nun Daten auf die SD-Karte geschrieben haben, möchten wir diese ggf. auch auslesen.

Im Beitrag Python #10: Dateiverarbeitung habe ich dir gezeigt wie man mit Dateien & Verzeichnisse in Python arbeitet. Dieses können wir auf die leicht abgewandelte Skriptsprache CircuitPython anwenden.

from board import *
from time import *
import busio
import sdcardio
import storage

# eine Pause von 1 Sekunde 
sleep(1)
 
# definieren der Pins der SD-Card
spi = busio.SPI(GP10, MOSI=GP11, MISO=GP12)
cs = GP15
sd = sdcardio.SDCard(spi, cs)

# einbinden der SD Karte
vfs = storage.VfsFat(sd)
storage.mount(vfs, '/sd')

# schreiben von 3 Einträgen in die Datei "greeting.txt"
# durch den Parameter "a" (a - append / anhängen )
# wird beim nächsten Start des Programmes die Datei
# NICHT überschrieben sondern 3 zusätzliche Einträge hinzugefügt
for i in range(3):
    # Datei "greeting.txt" zum schreiben öffnen, die Daten werden
    # an das Ende der Datei geschrieben
    with open("/sd/greeting.txt", "a") as file:
        # schreiben einer Zeile in die Datei
        file.write("Hello World!")
        # schreiben eines Zeilenumbruchs
        file.write("\r\n")

# lesen der zuvor geschriebenen Daten von der SD Karte
with open("/sd/greeting.txt", "r") as file:
    for line in file:
        print(line)

Ausgabe auf der Konsole

Auf der Konsole werden nun die zuvor geschriebenen Daten angezeigt.

code.py Ausgabe:
Hello World!
Hello World!
Hello World!

Sollte das Programm jedoch mehrfach gestartet werden, so werden je Start 3 weiteren Datenzeilen hinzugefügt.

Schreiben von Sensordaten auf der SD-Karte

Möchte man Sensordaten schreiben so empfiehlt es sich diese Strukturiert zu schreiben. Man kann hierfür das JSON Format, XML oder auch das recht einfache CSV Format wählen.

Da wir lediglich die 4 Werte,

  • Index,
  • Zeitstempel,
  • Temperatur,
  • rel. Luftfeuchtigkeit

schreiben möchten, reicht für diesen Fall das CSV Format aus. (Mit den anderen beiden Formaten werde ich mich gesondert auf meinem Blog befassen.)

Was ist das CSV Format?

Das CSV Format ist wie erwähnt das einfachste Format. Die Daten werden dabei mit einem definierten Symbol getrennt in einer Zeile gespeichert. Eine Zeile endet immer mit einem Zeilenumbruch „\r\n“.

1;2021-08-22 13:30;13;52
2;2021-08-22 13:31;15;49

Das Symbol zum Trennen von Daten innerhalb einer Zeile ist normalerweise das Semikolon. Aber es kann auch jedes andere Symbol verwendet werden. Ein Problem tritt jedoch auf wenn dieses Symbol innerhalb eines Textes in der Zeile vorkommt, dann kann ein Parser schon an seine grenzen stoßen.

Daten im CSV Format schreiben & lesen

Wollen wir zunächst ein paar Daten im CSV Format schreiben und lesen.

for i in range(3):
    with open("/sd/date.txt", "a") as file:
        # schreiben einer CSV Datenzeile in die Datei
        file.write(str(i))
        # Trenner der CSV Datei
        file.write(";")
        file.write("2021-08-22 13:3"+str(i))
        file.write(";")
        file.write(str(24))
        file.write(";")
        file.write(str(48))
        # schreiben eines Zeilenumbruchs
        file.write("\r\n")

# lesen der zuvor geschriebenen Daten von der SD Karte
with open("/sd/date.txt", "r") as file:
    for line in file:
        single_line = line.strip()
        # entpacken einer Zeile in die Variablen
        index, timestamp, temp, humi = single_line.split(";")
        # ausgeben der Daten auf der Konsole
        print("Index:", str(index))
        print("Zeitstempel:", str(timestamp))
        print("Temperatur:", str(temp))
        print("rel. Luftfeuchtigkeit:", str(humi))

Ausgabe auf der Konsole

Auf der Konsole werden nun 3 Blöcke ausgegeben mit den zuvor gespeicherten Daten.

code.py Ausgabe:
Index: 0
Zeitstempel: 2021-08-22 13:30
Temperatur: 24
rel. Luftfeuchtigkeit: 48
Index: 1
Zeitstempel: 2021-08-22 13:31
Temperatur: 24
rel. Luftfeuchtigkeit: 48
Index: 2
Zeitstempel: 2021-08-22 13:32
Temperatur: 24
rel. Luftfeuchtigkeit: 48

Zeitstempel für die Sensordaten

Der MAKER Pi Pico verfügt über ein paar sehr nützliche Features aber eine RealTimeClock ist (bisher) nicht verbaut somit müsste man über die Pins ein solches Modul zusätzlich anschließen oder aber über einen aufgesteckten ESP01 und einer WiFi Verbindung von einem NTP Server die Zeitstempel holen.

In diesem Beispiel möchte ich einen Zeitstempel von einem kleinen PHP-Skript auf einer meiner Subdomains lesen (https://zeitstempel.draeger-it.blog/). Der Vorteil ist, dass ich das Format gleich definieren kann und somit der Code im Mu-Editor recht übersichtlich bleibt. Für diese Lösung benötigst du ein aktive WiFi Verbindung zu einem lokalen WLAN Netzwerk.

Aufbau einer WiFi Verbindung und laden des Zeitstempels von der Webseite

Wie du am MAKER Pi Pico mit dem ESP01 eine WiFi Verbindung zu deinem WLAN Netzwerk aufbaust habe ich dir im Beitrag Maker Pi Pico von Cytron bereits gezeigt.

Hier möchte ich dir lediglich das fertige Programm zum lesen eines Zeitstempels zeigen. Dieser Beitrag soll sich hautpsächlich darum drehen wie du nun die Sensordaten mit eben diesem Zeitstempel auf einer SD-Card im CSV Format speicherst.

import time
import board
import adafruit_dht
import busio
import adafruit_requests as requests
import adafruit_espatcontrol.adafruit_espatcontrol_socket as socket
from adafruit_espatcontrol import adafruit_espatcontrol

secrets = {
    "ssid" : "FRITZBox7590GI24",                                    
    "password" : "abc"
}

timestamp_url = "http://zeitstempel.draeger-it.blog/"

RX = board.GP17
TX = board.GP16
uart = busio.UART(TX, RX, receiver_buffer_size=2048) 

esp = adafruit_espatcontrol.ESP_ATcontrol(uart, 115200, debug=False)
requests.set_socket(socket, esp)

print("Resetting ESP module")
esp.soft_reset()

# Aufbau der WiFi Verbindung
while not esp.is_connected:
    print("Connecting...")
    esp.connect(secrets)

print("lesen des Zeitstempels von ", timestamp_url)
# Endlosschleife...
while True:
    try:
        r = requests.get(timestamp_url)
        print("Zeitstempel:", r.text)
        time.sleep(2) 
    except:
        print("Fehler beim lesen des Zeitstempels von", timestamp_url)

In diesem kurzen Video zeige ich dir nun die Ausführung des oben gezeigten Programmes. (Das Passwort zu meinem WiFi-Netzwerk habe ich hier mit einem schwarzen Balken unkenntlich gemacht.)

Auf der Konsole sieht man den gelesenen Zeitstempel sowie ab und zu das nicht erfolgreich gelesen werden konnte. Ich denke das liegt hier vielmehr an einem Timeout der Verbindung, welcher zu kurz gewählt wurde. Hier kann man sich aber Abhilfe schaffen und ggf. eine kleine Schleife von 10 Durchläufen erzeugen und somit 10-mal probieren einen gültigen Zeitstempel zu laden.

Lesen eines Zeitstempels von einer Webseite.

schreiben der Sensordaten im CSV Format

Da wir nun wissen wie wir Daten auf die SD-Card schreiben und lesen, sowie einen Zeitstempel haben ist der nächste Schritt die Sensordaten auszulesen und diese Daten auf die SD-Card zu schreiben.

Damit unser Index (die erste Spalte in der CSV Datei) fortlaufend geschrieben wird, laden wir die CSV Datei beim starten des Mikrocontrollers und speichern und die Anzahl der Zeilen dieser Datei in einer Variable „index“.

import time
import board
import adafruit_dht
import busio
import adafruit_requests as requests
import adafruit_espatcontrol.adafruit_espatcontrol_socket as socket
from adafruit_espatcontrol import adafruit_espatcontrol
import adafruit_dht
import sdcardio
import storage

secrets = {
    "ssid" : "FRITZBox7590GI24",
    "password" : "abc"
}

timestamp_url = "http://zeitstempel.draeger-it.blog/"

RX = board.GP17
TX = board.GP16
uart = busio.UART(TX, RX, receiver_buffer_size=2048)
esp = adafruit_espatcontrol.ESP_ATcontrol(uart, 115200, debug=False)
requests.set_socket(socket, esp)

# initialisieren eines DHT11 Sensors am GP27
dhtDevice = adafruit_dht.DHT11(board.GP27)

# Zähler für den Index innerhalb der CSV Datei
index = 0

# Dateiname für die Sensordaten
csv_filename = "/sd/measurements.csv"

# definieren der Pins der SD-Card
spi = busio.SPI(board.GP10, MOSI=board.GP11, MISO=board.GP12)
cs = board.GP15
sd = sdcardio.SDCard(spi, cs)

# einbinden der SD Karte
vfs = storage.VfsFat(sd)
storage.mount(vfs, '/sd')

# lesen der Sensorwerte des DHT Sensors
def read_dht_values():
    result = {}
    # Schleife von 0 bis 9
    for i in range(9):
        try:
            # lesen der Sensorwerte
            result["temp"] = dhtDevice.temperature
            result["humi"] = dhtDevice.humidity
            # Wenn die Temperatur ODER die rel. Luftfeuchtigkeit nicht vom Typ None ist dann,
            # soll die aeussere Schleife verlassen werden.
            if(result["temp"] is not None or result["humi"] is not None):
                break;
            else:
                # Wenn die Daten nicht gelesen werden konnten, dann eine kleine
                # Pause von 2 Sekunden einlegen.
                time.sleep(2)
        except RuntimeError as error:
            print(error.args[0])
        except Exception as error:
            # Im Fall eines Schwerwiegenden Fehlers, so wird das Programm beendet.
            dhtDevice.exit()
            raise error
    return result

def setup():
    # Zugriff auf die Globale Variable "index"
    global index
    print("Setup")
    # Reset des ESP01 Modules
    esp.soft_reset()

    # Aufbau der WiFi Verbindung
    while not esp.is_connected:
        print("Verbindung zu", secrets["ssid"],"wird aufgebaut...")
        esp.connect(secrets)
    try:
        index = sum(1 for line in open(csv_filename))     
        print("Datei", csv_filename,"enthaelt", str(index), "Zeilen")
    except:
        print("Datei wurde nicht gefunden.")
        index = 0    

# lesen des Zeitstempels von der Webseite
def read_timestamp():
    timestamp = "-undefined-"
    for i in range(10):
        try:
            r = requests.get(timestamp_url)
            timestamp = r.text
            # Wenn der Code bis hier funktioniert hat,
            # dann kann die aeussere Schleife verlassen werden.
            break;            
        except:
            pass
        time.sleep(1)
    return timestamp
    
def loop():
    global index
    # lesen des Zeitstempels
    timestamp = read_timestamp()
    # lesen der Sensordaten
    dht_values = read_dht_values()
    # incrementieren des Indexes
    index = index + 1
    # Aufbau der CSV Datenzeile
    csv_line = str(index) + ";" + timestamp + ";" + str(dht_values["temp"]) + ";" + str(dht_values["humi"])
    # Ausgeben der CSV Datenzeile auf der Komandozeile
    print(csv_line)
    # schreiben der CSV Datenzeile in die Datei
    with open(csv_filename, "a") as file:
        file.write(csv_line)        
        # hinzufügen eines Zeilenumbruchs am Zeilenende
        file.write("\r\n")

# einmaliges Ausführen der Funktion "setup"
setup()

# Endlosschleife, welche die Funktion "loop" ausführt
while True:
    loop()
    # eine Pause von 1 Sekunde
    time.sleep(1)
    

Video – schreiben der DHT11 Sensorwerte in eine CSV Datei auf der SD-Karte

Schreibe einen Kommentar Antworten abbrechen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Fragen oder Feedback?

Du hast eine Idee, brauchst Hilfe oder möchtest Feedback loswerden?
Support-Ticket erstellen

Newsletter abonnieren

Bleib auf dem Laufenden: Erhalte regelmäßig Updates zu neuen Projekten, Tutorials und Tipps rund um Arduino, ESP32 und mehr – direkt in dein Postfach.

Jetzt Newsletter abonnieren

Unterstütze meinen Blog

Wenn dir meine Inhalte gefallen, freue ich mich über deine Unterstützung auf Tipeee.
So hilfst du mit, den Blog am Leben zu halten und neue Beiträge zu ermöglichen.

draeger-it.blog auf Tipeee unterstützen

Vielen Dank für deinen Support!
– Stefan Draeger

Kategorien

Tools

  • Unix-Zeitstempel-Rechner
  • ASCII Tabelle
  • Spannung, Strom, Widerstand und Leistung berechnen
  • Widerstandsrechner
  • 8×8 LED Matrix Tool
  • 8×16 LED Matrix Modul von Keyestudio
  • 16×16 LED Matrix – Generator

Links

Blogverzeichnis Bloggerei.de TopBlogs.de das Original - Blogverzeichnis | Blog Top Liste Blogverzeichnis trusted-blogs.com

Stefan Draeger
Königsberger Str. 13
38364 Schöningen

Tel.: 01778501273
E-Mail: info@draeger-it.blog

Folge mir auf

  • Impressum
  • Datenschutzerklärung
  • Disclaimer
  • Cookie-Richtlinie (EU)
©2025 Technik Blog | Built using WordPress and Responsive Blogily theme by Superb
Cookie-Zustimmung verwalten
Wir verwenden Technologien wie Cookies, um Geräteinformationen zu speichern und/oder darauf zuzugreifen. Wir tun dies, um das Surferlebnis zu verbessern und um personalisierte Werbung anzuzeigen. Wenn Sie diesen Technologien zustimmen, können wir Daten wie das Surfverhalten oder eindeutige IDs auf dieser Website verarbeiten. Wenn Sie Ihre Zustimmung nicht erteilen oder zurückziehen, können bestimmte Funktionen beeinträchtigt werden.
Funktional Immer aktiv
Die technische Speicherung oder der Zugang ist unbedingt erforderlich für den rechtmäßigen Zweck, die Nutzung eines bestimmten Dienstes zu ermöglichen, der vom Teilnehmer oder Nutzer ausdrücklich gewünscht wird, oder für den alleinigen Zweck, die Übertragung einer Nachricht über ein elektronisches Kommunikationsnetz durchzuführen.
Vorlieben
Die technische Speicherung oder der Zugriff ist für den rechtmäßigen Zweck der Speicherung von Präferenzen erforderlich, die nicht vom Abonnenten oder Benutzer angefordert wurden.
Statistiken
Die technische Speicherung oder der Zugriff, der ausschließlich zu statistischen Zwecken erfolgt. Die technische Speicherung oder der Zugriff, der ausschließlich zu anonymen statistischen Zwecken verwendet wird. Ohne eine Vorladung, die freiwillige Zustimmung deines Internetdienstanbieters oder zusätzliche Aufzeichnungen von Dritten können die zu diesem Zweck gespeicherten oder abgerufenen Informationen allein in der Regel nicht dazu verwendet werden, dich zu identifizieren.
Marketing
Die technische Speicherung oder der Zugriff ist erforderlich, um Nutzerprofile zu erstellen, um Werbung zu versenden oder um den Nutzer auf einer Website oder über mehrere Websites hinweg zu ähnlichen Marketingzwecken zu verfolgen.
Optionen verwalten Dienste verwalten Verwalten von {vendor_count}-Lieferanten Lese mehr über diese Zwecke
Einstellungen anzeigen
{title} {title} {title}