Lekce 18 - Arduino - Práce s SD kartou
V minulé lekci, Arduino - Komunikace přes Bluetooth, jsme se naučili navázat komunikaci pomocí Bluetooth.
V tomto tutoriálu Arduina se naučíme připojit SD kartu. Vyzkoušíme si čtení i ukládání dat. Využijeme k tomu standardní modul čtečky SD karet, například tento. Velmi podobně se ale až na několik detailů zachází s téměř každým shieldem, který v sobě slot na SD kartu obsahuje.
Připojení SD karty k Arduinu
Samotnou SD kartu můžeme použít libovolnou, podmínkou je jen
naformátování v systému FAT nebo FAT32. Kartu nebudeme formátovat pomocí
nástrojů v operačním systému počítače. Místo toho k tomu použijeme
formátovací program ze stránek SD Asociace. Máme tedy
naformátováno a můžeme se pustit do práce. Na modulu máme piny
GND
, 5 V
, MISO
,
SCK
(/CLK
), MOSI
a CS
:
Arduino Mega | Arduino Uno | |
MOSI | 51 | 11 |
SCK | 52 | 12 |
MISO | 50 | 15 |
CS | 53 | 4 |
Pro Arduino Mega zapojíme čtečku dle prvního sloupečku. Pro jiný model
(např. Uno) použijeme druhý sloupeček. Pokud máme shield se slotem, bude s
Arduinem Mega fungovat pouze pokud má vývody k pinům 50 - 53 a slot je na
nich. Musíme si také zjistit, na který pin je přivedený
CS
.
Nejprve si ověříme funkčnost SD karty. Připojíme ji, otevřeme
Arduino IDE a v menu klikneme na File -> Examples
-> SD -> CardInfo. Knihovna pro SD kartu je již
součástí IDE. V kódu hned nad setupem najdeme v příkladu řádek
const int chipSelect = 4;
.
Pro Arduino Mega přepíšeme hodnotu na 53
. Pro shield
použijeme pin, na kterém je CS
. Pro ostatní Arduina ponecháme
hodnotu beze změny. Kód nahrajeme do Arduina s připojenou kartou. Pomocí
klávesové zkratky Ctrl + Shift + M otevřeme
sériový monitor, ve kterém uvidíme výstup:
Initializing SD card...Wiring is correct and a card is present. Card type: SD1 Volume type is FAT16 Volume size (bytes): 127041536 Volume size (Kbytes): 124064 Volume size (Mbytes): 121 Files found on the card (name, date and size in bytes):
Pokud by nastal nějaký problém, zobrazilo by se chybové hlášení:
Initializing SD card...initialization failed. Things to check: * is a card is inserted? * Is your wiring correct? * did you change the chipSelect pin to match your shield or module?
V takovém případě zkontrolujeme vedení, kartu a ochranu proti přepisu. Pokud je karta nesprávně naformátovaná, zobrazí se následující výpis:
Initializing SD card...Wiring is correct and a card is present. Card type: SDHC Could not find FAT16/FAT32 partition. Make sure you've formatted the card
V případě této chyby formátování zopakujeme. Nikdy ale nelze vyloučit, že karta je nějak poškozená. Vyplatí se tedy mít záložní a ověřit si i tu.
Pokud nám test vypsal charakteristiky karty správně, můžeme pokračovat.
Zápis dat na kartu
Pro demonstraci zápisu dat na kartu využijeme nám už známý modul DHT11. Na kartu budeme ukládat data, která nám tento modul poskytne.
Začneme tím, že naimportujeme všechny potřebné knihovny:
#include <dht11.h> #include <SD.h>
Vytvoříme nám již známý DHT11
:
dht11 cidlo; int dht11Pin = 7;
A nakonec inicializujeme SD kartu:
const int chipSelect = 53; // Nezapomeneme patřičně upravit hodnotu dle typu Arduina void setup() { SD.begin(chipSelect); }
Nyní se můžeme pustit do smyčky void loop()
. Začneme tím,
že si vytvoříme proměnné typu String
k uložení dat:
void loop() { cidlo.read(dht11Pin); String teplota = String(cidlo.temperature); String vlhkost = String(cidlo.humidity); String cas = String(millis()); teplota += " "; vlhkost += " "; cas += " "; String data = cas.substring(0,16) + teplota.substring(0,3) + vlhkost.substring(0,3);
Uložíme si do nich teplotu, vlhkost a také počet milisekund od
spuštění. Důvodem, proč za String
přidáváme ty mezery je
to, že funkce substring()
vezme z textového řetězce určitou
část, např. z času vezmeme jen 0 až 16-tý znak (indexování od nuly).
Proč to děláme si vyjasníme za chvíli. Nyní nám zbývá otevřít soubor
pro zápis:
File soubor = SD.open("mereni.txt", FILE_WRITE);
Soubor otvíráme pomocí funkce SD.open
. File
je
proměnná, do které se soubor uloží. Pojmenujeme si ji soubor
.
Otevřeme soubor mereni.txt
a budeme zapisovat. Pokud soubor
neexistuje, funkce jej vytvoří. Pokud existuje, bude připisovat data na jeho
konec. Po zápisu dat soubor nezapomeneme zavřít:
if(soubor) { soubor.println(data); soubor.close(); } delay(1000); }
Je velmi vhodné soubor vždy hned po zápisu dat zavřít a pamatovat si, že nikdy nemůžeme mít otevřeno více souborů současně.
Do našeho Arduina pak nahrajeme následující kód:
#include <dht11.h> #include <SD.h> dht11 cidlo; int dht11Pin = 7; const int chipSelect = 53; void setup() { SD.begin(chipSelect); } void loop() { cidlo.read(dht11Pin); String teplota = String(cidlo.temperature); String vlhkost = String(cidlo.humidity); String cas = String(millis()); teplota += " "; vlhkost += " "; cas += " "; String data =cas.substring(0,16) + teplota.substring(0,3) + vlhkost.substring(0,3) ; File soubor = SD.open("mereni.txt", FILE_WRITE); if(soubor) { soubor.println(data); soubor.close(); } delay(1000); }
Spustíme zapojení, necháme jej chvíli běžet a poté kartu jednoduše vyjmeme a otevřeme v počítači:

Vidíme, že na kartu se uložil soubor MERENI.TXT
. A to
přestože jsme v kódu uvedli mereni.txt
. Není to chyba, je to
vlastnost V souboru vidíme,
že délka (počet řádů čísla) naměřeného času narůstá, zatímco
teplota a vlhkost jsou stabilní. Právě zvětšování hodnoty času je
důvodem, proč jsme v kódu použili všechny ty mezery a funkci
substring()
.
Čtení dat z karty
Zapisovat hodnoty už umíme. Nyní je tedy čas vyzkoušet si i čtení dat.
Na SD kartě si v počítači vytvoříme soubor KECTENI.TXT
a
zapíšeme do něj toto:
Test čtení Arduinem z SD karty Nový řádek itnetwork.cz
Text poté vypíšeme na sériový port. Kód bude vypadat skoro stejně. Jen
smažeme část s DHT11
, tvoření řetězce, upravíme
otevírání souboru a přepíšeme kód zápisu:
#include <SD.h> const int chipSelect = 53; void setup() { Serial.begin(9600); SD.begin(chipSelect); File soubor = SD.open("kecteni.txt"); if(soubor) { int znaky = 0; while(soubor.available()) {znaky++; Serial.write(soubor.read()); } Serial.println(""); Serial.println("Soubor ma " + String(znaky) + "znaku, vcetne mezer a newline znacek"); } else { Serial.println("nepodarilo se otevrit soubor"); } } void loop() { }
V kódu nejprve připravíme SD kartu. Poté otevřeme soubor, ale tentokrát
bez parametru FILE_WRITE
, protože budeme jen číst. Arduino čte
tak, že přečte jeden znak a přejde k dalšímu. A navíc nám dá jen ASCII
hodnotu přečteného znaku. Proto nepoužíváme Serial.print()
,
ale write()
. Lze ale snadno získat i string
, stačí
nahradit část v podmínce touto úpravou:
int znaky = 0; String precteno = ""; while(soubor.available()) { znaky++; precteno += char(soubor.read()); } Serial.print(precteno); Serial.println(""); Serial.println("Soubor ma " + String(znaky) + "znaku, vcetne mezer a newline znacek");
Pomocí funkce char()
dostaneme z přečtené hodnoty znak,
který jen připojíme k textovému řetězci. Program nahrajeme, otevřeme
sériový monitor a výstup bude vypadat následovně:

Z výstupu je zřejmé, že bude lepší se vyvarovat použití diakritiky
Zdrojové kódy jsou opět k
dispozici ke stažení v příloze.
V příští lekci, Arduino - Využití I2C sběrnice, si vysvětlíme princip a možnosti I2C sběrnice.
Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 248x (2.48 kB)
Aplikace je včetně zdrojových kódů