SD-Card – // · SD-Card – 3 SD-Card Erforderliche Libraries a zur Ansteuerung einer SD-Karte...
Transcript of SD-Card – // · SD-Card – 3 SD-Card Erforderliche Libraries a zur Ansteuerung einer SD-Karte...
SD-Card – https://erik-bartmann.de/
ESP32 Pico-Board
ESP32 Addon
SD-Card Vers. 1.1
© by Erik Bartmann, November 2018
SD-Card – https://erik-bartmann.de/ Seite 2
S D - C a r d
n diesem ESP32-Addon wollen wir
uns dem Thema der permanenten
Datenspeicherung widmen. Es gibt
Möglichkeiten, Messdaten z.B. im
einem EEPROM (Electrical Erasable
Programmable Read Only Memory),
also einem ist ein elektrisch
lösch- und programmierbarer
Halbleiterspeicher
abzulegen. Im
Mikrocontroller eines
Arduino ist ein derartiger
Bereich vorhanden. Der
ESP32 verfügt ebenfalls über
einen ähnlichen Speicher, der
mithilfe der Arduino-EEPROM-Library
Daten mit einem Volumen bis zu 512
Bytes in einem Flash-Speicher ablegt.
Doch das ist nicht unser Thema dieses
Addons. Wir wollen größere
Datenmengen speichern und was bietet
sich besser an, als die Flut von Daten,
die manchmal anfallen, auf einer SD-
Karte zu speichern. Der ESP32
kann natürlich - wie auch der
Arduino - eine SD-
Karte ansprechen.
Das erfolgt über den
SPI-Bus, der vom ESP32
unterstützt wird. Ein SD-Card-
Reader ist schon für unter 4€ zu
bekommen und es werden Typen für
SD- bzw. Mikro-SD-Karten angeboten.
Die Wahl bleibt jedem selbst
überlassen und spiel im Endeffekt keine
Rolle.
I
SD-Card – https://erik-bartmann.de/
3 SD-Card
Erforderliche Libraries a zur Ansteuerung einer SD-Karte auf dem ESP32 der SPI-Bus mit den Signalen
MOSI, MISO, SCK und CS verwendet werden, ist eine zusätzliche Installation einer
Library nicht erforderlich, denn sie ist standardmäßig schon in der Arduino-
Entwicklungsumgebung implementiert. Die Einbindung erfolgt über
#include <SPI.h>
Das ist jedoch nur die halbe Miete, denn es ist noch eine weitere softwaremäßige
Unterstützung von Nöten. Die Daten müssen auf der SD-Karte ja in einem bestimmten
Filesystem abgelegt werden. Es werden hierbei FAT16 bzw. FAT32 für SD- bzw. SDHC-
Karten unterstützt. Die Einbindung erfolgt über
#include "SD.h"
Der SD-Card Adapter s gibt auf dem Markt die unterschiedlichsten SD-Card-Adapter bzw.- Module mit
einer SPI-Anbindung. In meiner Kramkiste habe ich den folgenden gefunden und
ich kann noch nicht einmal sagen, von welcher Firma das Teil ist. Von irgendwo aus
chinesischen Gefilden vermute ich.
Abbildung 1 Ein SD-Card-Adapter
In meinem Fall muss der Adapter mit einer „normalen“ SD-Karte bestückt werden. Es
gibt jedoch auch sogenannte microSD-Karten. Auf der folgenden Abbildung sind beide
Varianten zu sehen.
D
E
SD-Card – https://erik-bartmann.de/
4 SD-Card
Abbildung 2 micro-SD und SD-Karte
Für den Fall, dass jemand ein SD-Card-Adapter besitzt, jedoch eine microSD-Karte,
bedeutet das nicht unbedingt ein Drama, denn es gibt entsprechende micro-Adapter,
die eine microSD-Karte aufnehmen und es ermöglichen, einen SD-Card-Adapter damit
zu füttern.
Abbildung 3 Der micro-Adapter
Sehen wir uns kurze die Anschlüsse des SD-Card-Adapters aus der Nähe an. Auf der
Abbildung kann man die einzelnen Pins aufgrund der Beschriftung eindeutig
identifizieren. Die hier gezeigte Reihenfolge ist bei unterschiedlichen Adaptern nicht
immer gleich und ich rate, auf jeden Fall auf die Pinbeschreibung zu achten.
Abbildung 4 Der SD-Card-Adapter mit seinen Pins
SD-Card – https://erik-bartmann.de/
5 SD-Card
Die Formatierung der SD-Karte Kommen wir zur Formatierung der SD-Karte, die in anhand des Windows-Betriebssystems
zeige. Für die Formatierung einer SD-Karte ist natürlich ein SD-Card-Reader erforderlich, auf
den ich nicht weiter eingehe. Nach dem Einstecken der SD-Karte in den Reader ist sie
normalerweise im Windows-Explorer sichtbar.
Abbildung 5 Die SD-Karte im Dateisystem
Es ist an dieser Stelle sehr wichtig darauf zu achten, on auch das richtige Laufwerk ausgewählt
ist. Eine unbeabsichtigte Formatierung ist schnell durchgeführt und die Restaurierung der
verlorenen Daten kann einiges an Stress bedeuten und nicht immer von Erfolg gekrönt sein. Ab
besten steckt man die Karte ein und zieht sie nach dem Erkennen durch das Betriebssystem
wieder heraus. Durch die Beobachtung des Explorers bei diesem Vorgang kann der
Laufwerksbuchstabe der SD-Karte eigentlich zweifelsfrei ermittelt werden. Gehen wir davon
aus, dass der richtige Laufwerksbuchstabe identifiziert wurde und wählen dann den
Menüpunkt Formatieren… aus.
SD-Card – https://erik-bartmann.de/
6 SD-Card
Es öffnet sich ein Dialogfenster, in dem im ersten Schritt das gewünschte Dateisystem - für uns
FAT32 - gewählt werden kann.
Die Formatierung beginnt mit dem Klick auf die Starten-Schaltfläche, wobei die
Formatierungsoption Schnellformatierung angewählt bleiben kann. Nach dem Bestätigen der
Abfrage, ob die Formatierung wirklich durchgeführt werden soll, endet der Vorgang mit der
Meldung über die erfolgreich abgeschlossene Formatierung.
Abbildung 6 Die Formatierung der SD-Karte wurde erfolgreich abgeschlossen
Nun kann die SD-Karte in den SD-Card-Adapter eingeschoben werden, wobei sie mit leichtem
Druck hörbar (Klick-Klick ) einrastet, was nur bei „normalen“ SD-Karten der Fall ist.
SD-Card – https://erik-bartmann.de/
7 SD-Card
Abbildung 7 Die eingeschobene SD-Karte
Sehen wir uns den Schaltungsaufbau und den Schaltplan an.
Der Schaltungsaufbau und der Schaltplan ür einen ersten Test habe ich den SD-Card-Adapter auf dem kleinen Breadboard
des ESP32-Pico-Discoveryboards [1] platziert und durch flexiblen Steckbrücken
(Male-Female) mit dem ESP32 verbunden.
Abbildung 8 Der SD-Card-Adapter auf dem ESP32-Pico-Discoveryboard
F
SD-Card – https://erik-bartmann.de/
8 SD-Card
Da die genaue Verkabelung aus dieser Ansicht etwas schwierig ist, liefere ich den Schaltplan
nach, der wie folgt ausschaut.
Abbildung 9 Der Schaltplan zur Ansteuerung des SD-Card-Adapters
Es ist gut zu sehen, dass die einzelnen Anschlüsse des SPI-Busses verwendet werden. Sie sind
ebenfalls auf dem ESP32-Pico-Discoveryboard beschriftet, so dass eine längere Suche nach den
korrekten Pins entfällt.
IO19/MISO
IO23/MOSI
IO18/SCLK
IO05/CS
Abbildung 10 Die SPI-Pins auf dem ESP32-Pico-Discoveryboard
Nach diesen vorbereitenden Informationen können wir uns den ESP32-Code anschauen.
SD-Card – https://erik-bartmann.de/
9 SD-Card
Der ESP32-Code ür einen ersten Code-Test wollen wir eine Datei auf der SD-Karte anlegen und diese
mit ein paar Informationen versehen. Wichtig bei derartigen Aktionen der
Speicherung von Daten sind neben den eigentlichen Daten, Zusatzinformationen wie
z.B. das Datum. Darüber lassen sich dann später detaillierte Auswertungen bzw.
Reporte generieren. Doch dazu in einem späteren SD-Addon mehr. Der folgende Code
basiert auf den ESP32-Beispielen, die unter dem Menü Datei|Beispiele|SD(esp32) zu
finden sind. Dem zu Grunde liegen die folgenden Methoden für den Zugriff auf die SD-
Karte.
listDir void listDir(fs::FS &fs, const char * dirname, uint8_t levels){
Serial.printf("Listing directory: %s\n", dirname);
File root = fs.open(dirname);
if(!root){
Serial.println("Failed to open directory");
return;
}
if(!root.isDirectory()){
Serial.println("Not a directory");
return;
}
File file = root.openNextFile();
while(file){
if(file.isDirectory()){
Serial.print(" DIR : ");
Serial.println(file.name());
if(levels){
listDir(fs, file.name(), levels -1);
}
} else {
Serial.print(" FILE: ");
Serial.print(file.name());
Serial.print(" SIZE: ");
Serial.println(file.size());
}
file = root.openNextFile();
}
}
F
SD-Card – https://erik-bartmann.de/
10 SD-Card
createDir void createDir(fs::FS &fs, const char * path){
Serial.printf("Creating Dir: %s\n", path);
if(fs.mkdir(path)){
Serial.println("Dir created");
} else {
Serial.println("mkdir failed");
}
}
removeDir void removeDir(fs::FS &fs, const char * path){
Serial.printf("Removing Dir: %s\n", path);
if(fs.rmdir(path)){
Serial.println("Dir removed");
} else {
Serial.println("rmdir failed");
}
}
readFile void readFile(fs::FS &fs, const char * path){
Serial.printf("Reading file: %s\n", path);
File file = fs.open(path);
if(!file){
Serial.println("Failed to open file for reading");
return;
}
Serial.print("Read from file: ");
while(file.available()){
Serial.write(file.read());
}
file.close();
}
SD-Card – https://erik-bartmann.de/
11 SD-Card
writeFile void writeFile(fs::FS &fs, const char * path, const char * message){
Serial.printf("Writing file: %s\n", path);
File file = fs.open(path, FILE_WRITE);
if(!file){
Serial.println("Failed to open file for writing");
return;
}
if(file.print(message)){
Serial.println("File written");
} else {
Serial.println("Write failed");
}
file.close();
}
appendFile void appendFile(fs::FS &fs, const char * path, const char * message){
Serial.printf("Appending to file: %s\n", path);
File file = fs.open(path, FILE_APPEND);
if(!file){
Serial.println("Failed to open file for appending");
return;
}
if(file.print(message)){
Serial.println("Message appended");
} else {
Serial.println("Append failed");
}
file.close();
}
SD-Card – https://erik-bartmann.de/
12 SD-Card
renameFile void renameFile(fs::FS &fs, const char * path1, const char * path2){
Serial.printf("Renaming file %s to %s\n", path1, path2);
if (fs.rename(path1, path2)) {
Serial.println("File renamed");
} else {
Serial.println("Rename failed");
}
}
deleteFile void deleteFile(fs::FS &fs, const char * path){
Serial.printf("Deleting file: %s\n", path);
if(fs.remove(path)){
Serial.println("File deleted");
} else {
Serial.println("Delete failed");
}
}
testFileIO void testFileIO(fs::FS &fs, const char * path){
File file = fs.open(path);
static uint8_t buf[512];
size_t len = 0;
uint32_t start = millis();
uint32_t end = start;
if(file){
len = file.size();
size_t flen = len;
start = millis();
while(len){
size_t toRead = len;
if(toRead > 512){
toRead = 512;
}
file.read(buf, toRead);
len -= toRead;
}
end = millis() - start;
Serial.printf("%u bytes read for %u ms\n", flen, end);
file.close();
} else {
SD-Card – https://erik-bartmann.de/
13 SD-Card
Serial.println("Failed to open file for reading");
}
file = fs.open(path, FILE_WRITE);
if(!file){
Serial.println("Failed to open file for writing");
return;
}
size_t i;
start = millis();
for(i=0; i<2048; i++){
file.write(buf, 512);
}
end = millis() - start;
Serial.printf("%u bytes written for %u ms\n", 2048 * 512, end);
file.close();
}
Schauen wir uns aufgrund der hier gezeigten Methoden den Hauptsketch an, wobei die
Anweisungen lediglich in der setup-Funktion zu finden sind und einmalig ausgeführt
werden.
Der Hauptsketch Der ESP32-Code für dieses Addon [2] ist unter der folgenden Internetadresse herunterzuladen.
https://github.com/erikbartmann/ElektorESP32/tree/master/Addons/SDCard
Der Code des Hauptsketches schaut wie folgt aus.
#include "FS.h"
#include "SD.h"
#include "SPI.h"
#include "SDAccess.h"
void setup() {
Serial.begin(9600);
if (!SD.begin()) {
Serial.println("Card Mount Failed");
return;
}
uint8_t cardType = SD.cardType();
if (cardType == CARD_NONE) {
Serial.println("No SD card attached");
SD-Card – https://erik-bartmann.de/
14 SD-Card
return;
}
Serial.print("SD Card Type: ");
if (cardType == CARD_MMC) {
Serial.println("MMC");
} else if (cardType == CARD_SD) {
Serial.println("SDSC");
} else if (cardType == CARD_SDHC) {
Serial.println("SDHC");
} else {
Serial.println("UNKNOWN");
}
uint64_t cardSize = SD.cardSize() / (1024 * 1024);
Serial.printf("SD Card Size: %lluMB\n", cardSize);
/*
listDir(SD, "/", 0);
createDir(SD, "/mydir");
listDir(SD, "/", 0);
removeDir(SD, "/mydir");
listDir(SD, "/", 2);
writeFile(SD, "/hello.txt", "Hello ");
appendFile(SD, "/hello.txt", "World!\n");
readFile(SD, "/hello.txt");
deleteFile(SD, "/foo.txt");
renameFile(SD, "/hello.txt", "/foo.txt");
readFile(SD, "/foo.txt");
testFileIO(SD, "/test.txt");
*/
writeFile(SD, "/data.log", "Das ist der erste Eintrag in der 1.Zeile\r\n");
appendFile(SD, "/data.log", "Das ist der nächste Eintrag in 2.Zeile\r\n");
appendFile(SD, "/data.log", "Das ist der nächste Eintrag in 3.Zeile\r\n");
}
void loop() { /* leer */ }
Über die writeFile-Methode wird initial die Text- bzw. Log-Datei auf der SD-Karte
erzeugt. Falls sie schon unter dem Namen vorhanden sein sollte, wird sie
überschrieben. Über die appendFile-Methode wird der genannten Datei eine neue
Zeile hinzugefügt.
SD-Card – https://erik-bartmann.de/
15 SD-Card
Sehen wir uns zunächst die Statusmeldungen im Serial-Monitor an.
Abbildung 11 Die Anzeigen im Serial-Monitor
Es ist zu erkennen, dass die Log-Datei erzeugt und nachfolgend zwei Nachrichten hinzugefügt
wurden. Der Inhalt der Log-Datei gestaltet sich dann wie folgt.
Abbildung 12 Der Inhalt der Log-Datei
Über die anderen Methoden, die im Hauptsketch auskommentiert waren, sind
entsprechende Funktionen aufrufbar, wobei die Namen sprechend sind und hier nicht
erläutert werden müssen.
SD-Card – https://erik-bartmann.de/
16 SD-Card
Ein anderer SD-Karten-Adapter s gibt auch SD-Karten Adapter, die über einen einzigen Spannungsversorgungspin
lediglich mit 5V betrieben werden können. Er besitzt dann meistens die
Bezeichnung Vcc. Um ganz sicher zu sein, sollte das Datenblatt des Herstellers zur Rate
gezogen werden.
Abbildung 13 SD-Karten-Adapter mit einem einzigen Spannungsversorgungspin für 5V
Über einen auf der Platine befindlichen Spannungswandler (LDO – Low-Drop-Out) wird
die angelegte Spannung von 5V auf 3,3V heruntergeregelt.
Es ist natürlich ebenfalls wichtig, dass z.B. die Datenleitungen MISO/MOSI ebenfalls
mit 3,3V arbeiten, denn das ESP32-Board soll nicht durch eine Signalleitung, die einen
Spannungspegel von 5V aufweist, beschädigt werden.
E
SD-Card – https://erik-bartmann.de/
17 SD-Card
Im nächsten ESP32-SDCard-Addon werden wir uns mit der Messwertaufnahme und
SD-Karten Speicherung befassen.
Frohes Frickeln
Web-Links [1]: https://www.erik-bartmann.de/?Projekte___ESP32_Discovery-Board
[2]: https://github.com/erikbartmann/ElektorESP32/tree/master/Addons/SDCard
Das ESP32-Praxisbuch
https://www.elektor.de/das-esp32-praxisbuch
https://www.erik-bartmann.de/