Action disabled: recent

Daten auf eine SD-Karte speichern

Eine häufige Aufgabe für eingebettete Systeme ist die Erfassung von Messwerten über einen längeren Zeitraum. Bisher haben wir die Möglichkeit kennengelernt, die erfassten Daten via UART gleich weiter an einen PC zu senden. Steht jedoch nicht permanent ein PC in der Nähe, müssen Datenreihen solange vorgehalten werden, bis diese vom Anwender übernommen werden können. Eine elegante Möglichkeit ist die Speicherung von Daten auf einer SD-Karte. Das Erweiterungsboard für unser STM32F4-Discovery verfügt über einen Steckplatz für eine µSD-Karte.

Es sollen Analogdaten erfasst werden. Diese sind in einer Form auf der µSD-Karte zu speichern, die es erlaubt, die Daten in einer Tabellenkalkulation auszuwerten. Als einfaches Dateiformat bietet sich CSV an.

Falls Sie jetzt noch das Klassendiagramm geöffnet haben, wählen Sie im Kontextmenü (rechte Maustaste) des Diagramms den Menüpunkt nach oben. Falls das Projekt nicht mehr geöffnet ist, öffnen Sie das SiSy UML-Projekt wieder. Legen Sie ein neues Klassendiagramm an, wählen Sie die Sprache ARM C++ und stellen Sie die Hardware (STM32F407) ein. Beim Öffnen des Diagramms (rechte Maustaste, nach unten) laden Sie aus dem SiSy LibStore die Diagrammvorlage Application Grundgerüst für PEC Anwendungen (XMC, STM32, AVR). Weisen Sie das Treiberpaket für STM32F4 zu.

.

Wenn wir im vorhandenen Framework stöbern finden wir bereits fertige Klassen, um Dateien auf einer SD-Karte zu speichern.

Die ausgewählte Lösung für ein Dateisystem auf SD-Karte bietet uns ein schmales Interface zum Umgang mit unserer µSD-Karte. Von besonderem Interesse sind für uns die Klasse PecSdCardSpi selbst und die Klasse File. PecSdCardSpi ist abgeleitet von Volume. Das Volume wird intern durch einen VolumeManager verwaltet. Das geht uns eigentlich als Anwendungsentwickler solange nichts an, wie wir nur eine SD-Karte verwenden. Die SD-Karte meldet sich beim Initialisieren selbständig beim VolumeManager an. Die hier vorliegende Klasse PecSdCardSpi bildet ein FAT-Dateisystem ab und kann SD-Karten bis zu 1 GB verwalten. Die eigentliche Dateiarbeit erledigen die Klassen FileFind und File.

Wir müssen eine Datei anlegen oder finden, können diese dann öffen, darin schreiben und zum Schluss auch wieder schließen. All das bieten uns diese Klassen. Jetzt bleibt nur noch die Frage wo wir die SD-Karte an unseren Controller anschließen. Der STM32F4 besitzt für den physischen Zugriff auf Speicherkarten einen speziellen Baustein SDIO. Diese Verbindung brauchen wir auf unserem Zusatzboard nicht mit Kabeln patchen. Also dann frisch ans Werk.

Als Quelle für die Analogdaten benutzen wir eines der Potentiometer. Zur Sicherheit wollen wir uns die Aktivitäten als UART-Protokoll im SiSy-ControlCenter anzeigen lassen. Die SD-Karte bilden wir als Speichermedium ab auf der eine Datei enthalten ist, in welche wir die Daten ablegen.

Controller::onStart:
// µSD-Karte initialisieren
// Baudrate für das Terminal einstellen
// Nachschauen ob die Datei "log.csv" im Wurzelverzeichnes existiert
// WENN keine Datei "log.csv" gefunden wurde DANN
//     Datei "log.csv" anlegen

Zur Abwechslung binden wir die gewünschte Baudrate für unsere UART-Übertragung nicht als Template an, sondern initialisieren diese in der Startsequenz. Der Einfachheit halber legen wir unsere Datei erst mal in das Wurzelverzeichnis der Speicherkarte. Achten Sie darauf, dass Ihre Speicherkarte auch als FAT16 formatiert ist.

Controller::onWork:
// Analogwert erfassen
// erfassten Wert als Textzeile für die CSV-Datei formatieren
// Datei "log.csv" öffnen
// WENN Datei "log.csv" geöffnet wurde DANN
//    Textzeile in Datei "log.csv" anhängen
//    Datei "log.csv" schließen
// 1 Sekunde warten

Wir schauen uns den Entwurf nochmal in Ruhe an und realisieren diesen dann Schritt für Schritt. Zur Sicherheit ergänzen wir Protokollausgaben über die UART.

Controller::onStart:
sdCard.mount();
FileFind ff;
 
if(!ff.findFirst("/log.csv"))
{
	if (sdCard.logfile.create("/log.csv"))
		terminal.writeString("\nDatei log.csv erzeugt!");
	else
		terminal.writeString("\nFehler beim Anlegen der Datei log.csv!");
}
else
{
	terminal.writeString("\nDatei log.csv gefunden!");	
}
Controller::onWork:
String txt;
int wert;
wert=poti.getValue();
txt.format("%d\n",wert);
if (sdCard.logfile.open("/log.csv", false, true))
{
	sdCard.logfile.append(txt);
	sdCard.logfile.close();
	terminal.writeString("Daten angefügt=");
	terminal.writeString(txt);
}
else
{
	terminal.writeString("\nDatei konnte nicht geöffnet werden");
}
waitMs(1000);

Übersetzen Sie das Programm. Korrigieren Sie ggf. Schreibfehler. Übertragen Sie das lauffähige Programm in den Programmspeicher des Controllers und starten das Werkzeug ControlCenter.

  1. Erstellen (Kompilieren und Linken)
  2. Brennen
  3. Menü Werkzeuge, ControlCenter

Stellen Sie im ControlCenter die Parameter für die Verbindung mit dem Board ein. Achten Sie auf den richtigen COM-Port und die korrekte Baudrate. Beachten Sie, dass der Controller mit korrekt formatierter SD-Karte eingelegt, mindestens einen Startzyklus (ggf. manuelles RESET) durchlaufen muss, um die Datei „log.csv“ anzulegen. Beachten Sie die Verbindungen zur USB-UART-Bridge und zum Potentiometer.

Nach der Aufzeichnung der Daten können Sie die SD-Karte mit einem entsprechenden Adapter über den PC auslesen und in einer Tabellenkalkulation auswerten.

Videozusammenfassung

Erlernte und gefestigte Arbeitsschritte:

  1. eine ARM C++ Applikation entwerfen, erstellen und übertragen
  2. SD-Karte benutzen

Und natürlich diesen Abschnitt wiederum als Videozusammenfassung.

Übung

Entfernen Sie die UART-Protokollausgaben und erweitern Sie die Anwendung um eine LED, die jedes mal, wenn ein Datensatz geschrieben wurde, kurz aufblitzt. Benutzen Sie dafür eine grüne LED. Für den Fall, dass ein Fehler aufgetreten ist, benutzen Sie eine rote LED, welche den Fehler per Blinkcode signalisiert.

  • 1 x blinken, Fehler beim Schreiben
  • 2 x blinken, Fehler beim Öffnen der Datei
  • 3 x blinken, Fehler beim Anlegen der Datei

Nächstes Thema