MicroSD karta s ESP32 – zapojení, zápis a čtení souborů

SD karty dnes najdeme hlavně ve fotoaparátech, kamerách nebo různých přenosných zařízeních. Stejně dobře se ale hodí také k Arduinu, ESP32 a dalším vývojovým deskám. Umožňují jednoduše ukládat naměřené hodnoty, nastavení programu, obrázky nebo jiné soubory, které by se do vnitřní paměti mikrokontroléru nevešly.

Pro připojení microSD karty se nejčastěji používá malý modul komunikující přes sběrnici SPI. K jeho zapojení stačí napájení a čtyři vodiče sběrnice SPI. O práci se soubory se potom postará knihovna, takže vytvoření souboru nebo zápis textu není o mnoho složitější než výpis na sériový monitor.

V tomto článku použiji jednoduchý modul určený pro napájení a logické úrovně 3,3 V. Ten je vhodný například pro ESP nebo Raspberry Pi. Existují ale také větší moduly se stabilizátorem a převodníkem logických úrovní, které lze připojit přímo k 5V deskám, jako je Arduino UNO, Nano nebo Mega.

Ukážeme si zapojení modulu a základní práci se soubory. Vyzkoušíme vytvoření souboru, zápis dat, jejich následné přečtení a přidávání dalších záznamů bez smazání původního obsahu.

SD karta a microSD karta

Klasická SD karta a menší microSD karta pracují z pohledu programu prakticky stejně. Liší se hlavně fyzickou velikostí a tvarem kontaktů. Když vložíme microSD kartu do běžného SD adaptéru, adaptér neobsahuje žádnou aktivní elektroniku. Pouze propojí kontakty malé karty s větším konektorem.

Pro projekty s mikrokontroléry se dnes nejčastěji používají microSD moduly, protože zabírají méně místa. V programu se ale stále používá knihovna nazvaná SD.

Na paměťové kartě je souborový systém podobný tomu na pevném disku nebo USB flash disku. Mikrokontrolér proto může vytvářet soubory, zapisovat do nich text, znovu je otevřít, číst jejich obsah nebo je smazat.

Komunikace přes SPI

SD karta podporuje několik způsobů komunikace. Pro připojení k běžnému mikrokontroléru se často používá režim SPI, protože ho podporuje většina vývojových desek a k zapojení potřebuje jen několik vodičů. Knihovna SD potom zpřístupní práci se soubory pomocí jednoduchých příkazů, jako jsou open(), exists(), remove() nebo mkdir().

Sběrnice SPI používá čtyři hlavní signály:

VývodVýznam
SCKHodinový signál vytvářený mikrokontrolérem
MOSIData odesílaná z mikrokontroléru do SD karty
MISOData odesílaná z SD karty do mikrokontroléru
CSVýběr zařízení na sběrnici

Označení vývodů se může mezi moduly lišit. Místo MOSI může být uvedeno DI, DIN nebo CMD. Vývod MISO bývá označen také jako DO, DOUT nebo DAT0. Hodinový vstup může mít označení CLK místo SCK.

Na jedné SPI sběrnici může být připojeno více zařízení. Vodiče MOSI, MISO a SCK mohou být společné, ale každé zařízení musí mít vlastní signál CS.

Dvě běžné verze modulu

Při nákupu modulu je potřeba dávat pozor hlavně na jeho napájecí napětí a logické úrovně. Samotná SD karta používá napětí přibližně 3,3 V, ale moduly se vyrábějí ve dvou základních provedeních.

Jednoduchý modul pro 3,3 V

Jednoduchý modul obsahuje hlavně konektor pro kartu a několik drobných součástek. Nemá stabilizátor napětí ani převodník logických úrovní.

Takový modul se připojuje přímo k deskám používajícím logiku 3,3 V:

  • ESP32
  • ESP8266
  • Raspberry Pi Pico
  • Arduino Nano 33
  • většina moderních vývojových desek s procesory ARM

Napájení modulu i všechny datové signály musí mít 3,3 V.

Pozor: Jednoduchý 3,3 V modul nepřipojuj přímo k výstupům klasického Arduino UNO, Nano nebo Mega. Tyto desky používají 5 V logiku a jejich signály by mohly SD kartu poškodit.

Modul pro připojení k 5 V Arduinu

Větší moduly určené pro Arduino obvykle obsahují stabilizátor napětí a obvod pro snížení logických úrovní. Modul se napájí 5 V a jeho elektronika upraví napájení i řídicí signály na hodnoty bezpečné pro kartu.

Taková verze je vhodná pro:

  • Arduino UNO
  • Arduino Nano s procesorem ATmega328P
  • Arduino Mega
  • další desky s 5 V logikou

Označení „5 V modul“ neznamená, že samotná karta pracuje s 5 V. Pět voltů se přivádí pouze na vstup modulu a ten napětí sníží.

Ne všechny moduly jsou zapojené stejně. Před připojením je proto dobré zkontrolovat popis výrobce nebo součástky osazené na desce. Pokud je na modulu například stabilizátor AMS1117 a několik rezistorů nebo převodník úrovní, pravděpodobně jde o verzi určenou pro 5 V.

Vývody modulu

Použitý modul má následující vývody:

Vývod moduluFunkce
VCCNapájení 3,3 V
GNDZem
CSVýběr SD karty
CLKHodinový signál SPI
MOSIData z ESP32 do karty
MISOData z karty do ESP32

Některé moduly mohou mít navíc vývod pro detekci vložené karty. Jednodušší provedení ho většinou nemají.

Detail vývodů použitého modulu

Zapojení k ESP32

Následující zapojení odpovídá desce Seeed Studio XIAO ESP32-C3. U jiných variant ESP32, například ESP32-S2 nebo ESP32-S3, mohou být výchozí SPI piny jiné. ESP32 umožňuje SPI signály přesměrovat na různé GPIO, takže je vždy dobré zkontrolovat zapojení konkrétní desky.

Modul microSDXIAO ESP32-C3
3V33V3
GNDGND
CSD5
SCKD8
MOSID10
MISOD9

Pin CS může být také jiný volný výstup. Jeho číslo ale musí odpovídat nastavení v programu.

Použij co nejkratší vodiče. SPI komunikace je rychlá a dlouhé vodiče mohou způsobovat chyby, zvlášť při použití nepájivého pole.

Zapojení modulu k ESP32-C3

Zapojení modulu pro 5 V k deskám Arduino UNO a Nano

Pro klasické Arduino UNO nebo Nano je nutné použít modul se stabilizátorem a převodem logických úrovní.

Modul pro 5 VArduino UNO nebo Nano
VCC5 V
GNDGND
CSD10
SCKD13
MOSID11
MISOD12

Vývod CS může být i jiný digitální pin. V programu potom stačí změnit jeho číslo.

U Arduino Mega jsou hardwarové SPI piny jiné:

SignálArduino Mega
CSD53 nebo jiný digitální výstup
SCKD52
MOSID51
MISOD50

Na deskách s konektorem ICSP jsou signály SPI vyvedené také na tomto šestipinovém konektoru.

Příprava paměťové karty

Pro první pokusy je nejjednodušší použít kartu s kapacitou několika gigabajtů až 32 GB a naformátovat ji jako FAT32. Menší starší karty mohou používat FAT16.

Karty s vyšší kapacitou bývají z výroby naformátované jako exFAT. Základní knihovna SD na všech deskách a ve všech verzích podporu exFAT zaručit nemusí. Pro maximální kompatibilitu je proto vhodná karta FAT16 nebo FAT32. Knihovna SdFat umí podle své dokumentace pracovat také s exFAT, ale její použití je složitější než u základní knihovny SD.

Před použitím doporučuji:

  1. Zálohovat případný obsah karty
  2. Naformátovat ji jako FAT32
  3. Pro první test nechat kartu prázdnou
  4. Bezpečně ji vysunout z počítače
  5. Vložit ji do modulu při vypnutém napájení

Při formátování není potřeba měnit velikost alokační jednotky. Výchozí nastavení obvykle funguje správně.

Názvy souborů

Pro dobrou kompatibilitu mezi ESP32 a klasickými Arduiny je vhodné používat krátké názvy ve formátu 8.3. To znamená nejvýše osm znaků před tečkou a tři znaky přípony.

Vhodné názvy:

DATA.TXT
MERENI.CSV
TEPLOTA.LOG
NASTAV.INI

Méně vhodný název:

mereni_teploty_v_dilne.csv

Klasická Arduino knihovna SD interně pracuje s krátkými názvy 8.3. Na některých modernějších deskách mohou fungovat i dlouhé názvy, ale krátké názvy bez mezer a diakritiky jsou nejbezpečnější.

Potřebné knihovny

Pro ESP32 použijeme tři knihovny:

#include <SPI.h>       //komunikace po SPI
#include <FS.h>        //práce se souborovým systémem
#include <SD.h>        //práce s SD kartou

Tyto knihovny jsou součástí podpory ESP32 pro Arduino IDE. Není tedy nutné instalovat náhodnou knihovnu se stejným nebo podobným názvem.

Pro Arduino UNO, Nano nebo Mega stačí:

#include <SPI.h>       //komunikace po SPI
#include <SD.h>        //práce s SD kartou

Knihovna SD nabízí vytváření, otevírání, čtení a zápis souborů a základní práci s adresáři.

První test SD karty s ESP32

První program provede několik základních operací:

  • inicializuje SPI a SD kartu
  • vytvoří soubor
  • zapíše do něj první řádek
  • přidá další řádek
  • přečte celý obsah souboru
  • vypíše ho do sériového monitoru rychlostí 115200 Bd
///////////////////////TEST_SD_KARTY fw v.0.1 ////////////////////////////////
///////////////////////14.7.2026 /////////////////////////////////////////////
///////////////////////www.michaluvbrloh.cz//////////////////////////////////

#include <SPI.h>       //komunikace po SPI
#include <FS.h>        //práce se souborovým systémem
#include <SD.h>        //práce s SD kartou

const byte SD_CS = D5;        //výběr SD karty
const byte SD_SCK = D8;      //hodinový signál SPI
const byte SD_MISO = D9;     //data z SD karty do ESP32
const byte SD_MOSI = D10;     //data z ESP32 do SD karty

const char SOUBOR[] = "/TEST.TXT";    //název testovacího souboru

/////////////////////////////po spuštění///////////////////////////////////////////////////////////////////////////////////////
void setup()
  {
    Serial.begin(115200);             //start sériové linky
    delay(1000);                      //pauza po spuštění

    pinMode(SD_CS, OUTPUT);
    digitalWrite(SD_CS, HIGH);

    Serial.println();
    Serial.println(F("Test SD karty"));

    SPI.begin(SD_SCK, SD_MISO, SD_MOSI, SD_CS);    //nastavení SPI pinů

    if(!SD.begin(SD_CS))         //pokus o spuštění SD karty
      {
        Serial.println(F("Chyba inicializace SD karty"));
        while(1)                      //zastav program
          {
            delay(1000);
          }
      }

    Serial.println(F("SD karta je pripravena"));

    zapisNovySoubor();                //vytvoř nový soubor
    pridejDoSouboru();                //přidej další řádek
    prectiSoubor();                   //přečti obsah souboru
  }

/////////////////////////////hlavní smyčka/////////////////////////////////////////////////////////////////////////////////////
void loop()
  {
    //program po provedení testu nic dalšího nedělá
  }

/////////////////////////////zápis nového souboru//////////////////////////////////////////////////////////////////////////////
void zapisNovySoubor()
  {
    File soubor = SD.open(SOUBOR, FILE_WRITE);     //otevři soubor pro nový zápis

    if(!soubor)                                    //pokud se soubor nepodařilo otevřít
      {
        Serial.println(F("Soubor se nepodarilo vytvorit"));
        return;
      }

    soubor.println(F("Prvni radek souboru"));      //zapiš text
    soubor.close();                                //uzavři soubor

    Serial.println(F("Novy soubor byl vytvoren"));
  }

/////////////////////////////přidání do souboru////////////////////////////////////////////////////////////////////////////////
void pridejDoSouboru()
  {
    File soubor = SD.open(SOUBOR, FILE_APPEND);    //otevři soubor pro přidání dat

    if(!soubor)                                    //pokud se soubor nepodařilo otevřít
      {
        Serial.println(F("Soubor se nepodarilo otevrit"));
        return;
      }

    soubor.println(F("Druhy radek souboru"));      //přidej nový řádek
    soubor.close();                                //uzavři soubor

    Serial.println(F("Dalsi radek byl pridan"));
  }

/////////////////////////////čtení souboru/////////////////////////////////////////////////////////////////////////////////////
void prectiSoubor()
  {
    File soubor = SD.open(SOUBOR, FILE_READ);      //otevři soubor pro čtení

    if(!soubor)                                    //pokud se soubor nepodařilo otevřít
      {
        Serial.println(F("Soubor se nepodarilo otevrit pro cteni"));
        return;
      }

    Serial.println();
    Serial.println(F("Obsah souboru:"));

    while(soubor.available())                      //dokud jsou v souboru data
      {
        Serial.write(soubor.read());               //vypiš jeden znak
      }

    soubor.close();                                //uzavři soubor
    Serial.println();
  }

Program používá piny ESP32-C3. Pokud používáš jinou variantu desky, změň konstanty SD_SCK, SD_MISO, SD_MOSI a SD_CS.

Po spuštění by se měl v sériovém monitoru objevit přibližně tento výpis:

Výpis prvního programu

Po vypnutí napájení můžeme kartu vložit do počítače. V kořenovém adresáři by měl být soubor TEST.TXT se dvěma řádky textu.

Soubor TEST.TXT otevřený v počítači

Proč je důležité soubor uzavřít

Po dokončení zápisu voláme:

soubor.close();

Data se při zápisu nemusí okamžitě fyzicky uložit do paměťových buněk karty. Část dat může zůstat ve vyrovnávací paměti. Uzavření souboru zapíše zbývající data a aktualizuje informace v souborovém systému.

Kdybychom ihned po zápisu vypnuli napájení nebo vytáhli kartu, soubor může zůstat neúplný. V horším případě se může poškodit i souborový systém.

Pozor: SD kartu nikdy nevytahuj během zápisu. Před vyjmutím vypni zařízení nebo v programu zajisti, že jsou všechny soubory uzavřené.

Místo uzavření lze během delšího zápisu použít také:

soubor.flush();

Příkaz uloží čekající data, ale ponechá soubor otevřený. Úplné uzavření souboru pomocí close() je po skončení práce stále potřeba.

Rozdíly v zápisu na ESP32 a klasickém Arduinu

Přestože se na obou platformách používá knihovna nazvaná SD, chování režimů souboru se liší.

Na ESP32 platí:

FILE_WRITE       //vytvoření nebo přepsání souboru
FILE_APPEND      //přidání dat na konec

U klasické Arduino knihovny SD pro UNO, Nano a Mega je FILE_WRITE definováno také s příznakem pro přidávání na konec existujícího souboru.

Pokud chceme na klasickém Arduinu vytvořit zcela nový soubor a případný starý obsah smazat, můžeme nejprve soubor odstranit:

if(SD.exists("TEST.TXT"))       //pokud soubor existuje
  {
    SD.remove("TEST.TXT");      //smaž starý soubor
  }

File soubor = SD.open("TEST.TXT", FILE_WRITE);    //vytvoř nový soubor

Na ESP32 používáme cesty začínající lomítkem:

"/TEST.TXT"

U klasické Arduino knihovny se často používá název bez úvodního lomítka:

"TEST.TXT"

Záznam měření do CSV souboru

Jedním z nejčastějších použití SD karty je ukládání měření. Následující program jednou za sekundu načte analogovou hodnotu a uloží ji společně s časem od spuštění do souboru MERENI.CSV.

Hodnoty jsou oddělené středníkem. Takový soubor lze otevřít v tabulkovém procesoru a následně z něj vytvořit graf.

///////////////////////ZAPIS_MERENI_NA_SD fw v.0.1 ///////////////////////////
///////////////////////14.7.2026 /////////////////////////////////////////////
///////////////////////www.michaluvbrloh.cz//////////////////////////////////

#include <SPI.h>       //komunikace po SPI
#include <FS.h>        //práce se souborovým systémem
#include <SD.h>        //práce s SD kartou

const byte SD_CS = D5;        //výběr SD karty
const byte SD_SCK = D8;       //hodinový signál SPI
const byte SD_MISO = D9;      //data z SD karty do ESP32
const byte SD_MOSI = D10;     //data z ESP32 do SD karty

const byte MERENI_PIN = A0;              //analogový vstup
const char SOUBOR[] = "/MERENI.CSV";     //soubor s měřením

unsigned long posledniUlozeni = 0;       //čas posledního uložení
const unsigned long INTERVAL = 1000;     //interval zápisu v milisekundách

/////////////////////////////po spuštění///////////////////////////////////////////////////////////////////////////////////////
void setup()
  {
    Serial.begin(115200);                //start sériové linky
    delay(1000);                         //pauza po spuštění

    pinMode(SD_CS, OUTPUT);
    digitalWrite(SD_CS, HIGH);

    SPI.begin(SD_SCK, SD_MISO, SD_MOSI, SD_CS);    //nastavení SPI pinů

    if(!SD.begin(SD_CS))            //pokus o spuštění SD karty
      {
        Serial.println(F("Chyba inicializace SD karty"));
        while(1)                         //zastav program
          {
            delay(1000);
          }
      }

    Serial.println(F("SD karta je pripravena"));

    pripravSoubor();                     //vytvoř soubor a hlavičku
  }

/////////////////////////////hlavní smyčka/////////////////////////////////////////////////////////////////////////////////////
void loop()
  {
    if(millis() - posledniUlozeni >= INTERVAL)     //pokud uplynul interval
      {
        posledniUlozeni = millis();                //ulož aktuální čas
        ulozMereni();                              //zapiš jeden řádek
      }
  }

/////////////////////////////příprava souboru//////////////////////////////////////////////////////////////////////////////////
void pripravSoubor()
  {
    if(SD.exists(SOUBOR))                //pokud soubor již existuje
      {
        Serial.println(F("Soubor MERENI.CSV uz existuje"));
        return;
      }

    File soubor = SD.open(SOUBOR, FILE_WRITE);     //vytvoř nový soubor

    if(!soubor)                           //pokud se soubor nepodařilo vytvořit
      {
        Serial.println(F("Soubor se nepodarilo vytvorit"));
        return;
      }

    soubor.println(F("cas_ms;hodnota"));  //zapiš názvy sloupců
    soubor.close();                       //uzavři soubor

    Serial.println(F("Soubor MERENI.CSV byl vytvoren"));
  }

/////////////////////////////uložení měření////////////////////////////////////////////////////////////////////////////////////
void ulozMereni()
  {
    int hodnota = analogRead(MERENI_PIN);           //načti analogový vstup

    File soubor = SD.open(SOUBOR, FILE_APPEND);     //otevři soubor pro přidání

    if(!soubor)                                     //pokud otevření selhalo
      {
        Serial.println(F("Chyba otevreni souboru"));
        return;
      }

    soubor.print(millis());                         //zapiš čas od spuštění
    soubor.print(';');                              //odděl hodnoty
    soubor.println(hodnota);                        //zapiš naměřenou hodnotu
    soubor.close();                                 //uzavři soubor

    Serial.print(F("Ulozeno: "));
    Serial.println(hodnota);
  }

Pin A0 odpovídá použitému ESP32-C3 a slouží zde pouze jako ukázkový analogový vstup. U jiné desky je potřeba zvolit vhodný ADC pin.

Výpis na sériový port z druhého programu

Čas je uložený v milisekundách od spuštění programu. Pro skutečný datalogger lze ESP32 doplnit například o RTC modul DS3231 a ukládat skutečné datum a čas.

Ukázka souboru MERENI.CSV v tabulkovém procesoru

Zápis po každém měření, nebo ponechání souboru otevřeného

Ukázkový program soubor při každém měření otevře, zapíše jeden řádek a znovu ho uzavře.

Výhodou je, že jsou data po každém zápisu uložená. Pokud se zařízení neočekávaně restartuje nebo se odpojí napájení, přijdeme obvykle nejvýše o právě zapisovaný řádek.

Nevýhodou je větší režie a pomalejší zápis. Při ukládání několikrát za sekundu to většinou nevadí. Při velmi rychlém záznamu by bylo lepší soubor ponechat otevřený, data zapisovat po větších blocích a pravidelně používat flush().

Je ale potřeba počítat s tím, že čím déle zůstávají data pouze ve vyrovnávací paměti, tím více jich můžeme ztratit při výpadku napájení.

Další práce se soubory na kartě

Výpis souborů na kartě

Obsah karty můžeme vypsat podobně jako seznam souborů v počítači.

Do programu můžeme přidat následující funkci:

/////////////////////////////výpis souborů/////////////////////////////////////////////////////////////////////////////////////
void vypisSoubory()
  {
    File adresar = SD.open("/");          //otevři hlavní adresář

    if(!adresar)                          //pokud otevření selhalo
      {
        Serial.println(F("Adresar se nepodarilo otevrit"));
        return;
      }

    if(!adresar.isDirectory())            //pokud nejde o adresář
      {
        Serial.println(F("Zadana cesta neni adresar"));
        adresar.close();
        return;
      }

    File polozka = adresar.openNextFile();    //otevři první položku

    while(polozka)                           //dokud existuje další položka
      {
        if(polozka.isDirectory())            //pokud jde o adresář
          {
            Serial.print(F("ADRESAR: "));
            Serial.println(polozka.name());
          }
        else                                 //pokud jde o soubor
          {
            Serial.print(F("SOUBOR: "));
            Serial.print(polozka.name());
            Serial.print(F("  VELIKOST: "));
            Serial.println(polozka.size());
          }

        polozka.close();                     //uzavři položku
        polozka = adresar.openNextFile();    //otevři další položku
      }

    adresar.close();                         //uzavři hlavní adresář
  }

Funkci zavoláme například na konci setup():

vypisSoubory();
Výpis obsahu SD karty

Mazání souborů

Před smazáním můžeme nejprve zkontrolovat, zda soubor existuje:

if(SD.exists("/TEST.TXT"))       //pokud soubor existuje
  {
    if(SD.remove("/TEST.TXT"))   //pokus o smazání souboru
      {
        Serial.println(F("Soubor byl smazan"));
      }
    else
      {
        Serial.println(F("Soubor se nepodarilo smazat"));
      }
  }
else
  {
    Serial.println(F("Soubor neexistuje"));
  }

Otevřený soubor je vhodné před smazáním nejprve uzavřít.

Vytváření adresářů

Větší množství souborů můžeme rozdělit do adresářů:

if(SD.mkdir("/LOG"))             //vytvoř adresář LOG
  {
    Serial.println(F("Adresar byl vytvoren"));
  }
else
  {
    Serial.println(F("Adresar se nepodarilo vytvorit"));
  }

Soubor uvnitř adresáře potom otevřeme pomocí celé cesty:

File soubor = SD.open("/LOG/DATA.CSV", FILE_APPEND);

Prázdný adresář lze odstranit:

SD.rmdir("/LOG");

Přejmenování souboru

Knihovna pro ESP32 umožňuje také přejmenování souboru:

if(SD.rename("/TEST.TXT", "/POKUS.TXT"))
  {
    Serial.println(F("Soubor byl prejmenovan"));
  }
else
  {
    Serial.println(F("Soubor se nepodarilo prejmenovat"));
  }

Přejmenování nemusí být dostupné ve stejné podobě ve všech implementacích Arduino knihovny SD. Při přenosu programu na jinou desku je proto dobré zkontrolovat dokumentaci konkrétního jádra.

Ukládání různých typů dat

Do souboru nemusíme zapisovat jen text. Objekt File používá podobné příkazy jako sériová linka:

soubor.print(hodnota);           //zápis bez ukončení řádku
soubor.println(hodnota);         //zápis s ukončením řádku
soubor.write(znak);              //zápis jednoho bajtu
soubor.write(buffer, delka);     //zápis bloku bajtů

Pomocí print() se číslo převede na čitelný text. Hodnota 1234 tedy zabere v souboru čtyři znaky.

Pomocí write() lze ukládat přímo binární data. Binární soubor je úspornější a zápis může být rychlejší, ale jeho obsah není běžně čitelný v textovém editoru.

Pro jednoduché měření a ladění je proto většinou praktičtější textový nebo CSV soubor.

Stabilita a složitější zapojení

Napájení a stabilita

SD karta může mít během zápisu krátkodobě výrazně vyšší odběr než v klidu. Napájení proto musí být dostatečně stabilní. Pokud se karta někdy inicializuje a jindy ne, nemusí být problém pouze v programu.

Pomoci může:

  • zkrácení vodičů
  • kontrola společné země
  • kvalitnější napájecí zdroj
  • přidání kondenzátoru poblíž modulu
  • snížení rychlosti SPI
  • vyzkoušení jiné paměťové karty

K modulu lze zkusit připojit například elektrolytický kondenzátor 47 až 220 µF mezi napájení a zem. Je nutné dodržet jeho polaritu. Vhodné je doplnit také keramický kondenzátor 100 nF.

Snížení rychlosti SPI

Některé moduly, paměťové karty nebo zapojení na nepájivém poli nemusí spolehlivě fungovat při vysoké rychlosti.

Na ESP32 lze při inicializaci nastavit nižší frekvenci:

if(!SD.begin(SD_CS, SPI, 4000000))     //SPI frekvence 4 MHz
  {
    Serial.println(F("Chyba inicializace SD karty"));
  }

4 MHz jsou pro běžné ukládání měření stále dostatečně rychlé. Pokud zapojení s nižší rychlostí funguje a s vyšší ne, bývá problém v kvalitě signálu, délce vodičů nebo konstrukci modulu.

Více zařízení na jedné SPI sběrnici

Displej, SD karta a další moduly mohou používat stejné vodiče MOSI, MISO a SCK. Každý modul ale musí mít vlastní pin CS.

Před zahájením komunikace musí být ostatní zařízení deaktivovaná nastavením jejich CS do logické jedničky. Knihovny to obvykle řeší automaticky, ale u levných modulů se může stát, že jejich převodník úrovní nepustí vodič MISO správně do stavu vysoké impedance.

Pokud každé zařízení funguje samostatně, ale společně na jedné sběrnici už ne, může být problém právě v některém z modulů nebo v řízení signálů CS.

Časté problémy

Inicializace SD karty selhala

Nejčastější příčiny:

  • špatně zapojené MOSI a MISO
  • nesprávně nastavený pin CS
  • chybějící společná zem
  • 5 V signály přivedené do 3,3 V modulu
  • nevhodný souborový systém
  • příliš dlouhé vodiče
  • nedostatečné napájení
  • vadná nebo nekompatibilní karta

Nejprve je vhodné zkontrolovat zapojení a vyzkoušet kartu FAT32 s menší kapacitou.

Při zprovozňování zkušebních programů mi SD karta stále nechtěla fungovat. Po kontrole všech možných i nemožných příčin se nakonec ukázalo, že mám v programu špatně označené piny připojené k ESP32.

U některých desek stačí zadat pouze číslo pinu, jinde je potřeba použít číslo GPIO a u mé desky bylo nutné uvést označení pinu včetně písmene, například D8. Pokud máš všechno správně zapojené a karta přesto nefunguje, zkontroluj také způsob označení pinů v programu. Ten se může u různých desek lišit.

Karta funguje pouze někdy

Příčinou bývá nestabilní napájení, špatný kontakt v konektoru nebo příliš dlouhé vodiče. Pomoci může kondenzátor u modulu a snížení rychlosti SPI.

Soubor se nevytvoří

Zkontroluj:

  • zda inicializace karty proběhla úspěšně
  • zda název souboru není příliš dlouhý
  • zda neobsahuje diakritiku nebo nepovolené znaky
  • zda cesta k adresáři opravdu existuje

Původní obsah souboru zmizel

Na ESP32 režim FILE_WRITE soubor otevře pro nový zápis a původní obsah nahradí. Pro přidávání nových řádků používej:

FILE_APPEND

Na klasické Arduino knihovně se chování FILE_WRITE liší a data se standardně přidávají na konec.

Na kartě je po výpadku poškozený soubor

Soubor pravděpodobně nebyl správně uzavřený nebo došlo k výpadku během zápisu. Pomůže častější volání close() nebo flush(), případně záložní napájení zařízení.

ESP32 se při práci s kartou restartuje

Může jít o pokles napájecího napětí, problém s použitými GPIO nebo konflikt s piny interní flash paměti. To je důležité hlavně u některých variant ESP32-S3, kde mohou být určité piny už využité pro flash nebo PSRAM.

SD karta není náhrada za všechno

SD karta nabízí velkou kapacitu a soubory lze jednoduše přenést do počítače. Nehodí se ale úplně pro každý typ dat.

Pro několik konfiguračních hodnot může být jednodušší použít EEPROM nebo interní flash paměť. SD karta se hodí hlavně tehdy, když:

  • ukládáme velké množství měření
  • potřebujeme soubory přenášet do počítače
  • ukládáme obrázky, zvuk nebo webové soubory
  • chceme snadno vyměnit celé úložiště
  • vnitřní paměť mikrokontroléru nestačí

Je také potřeba počítat s tím, že karta používá flash paměť s omezeným počtem zápisů. Při velmi častém ukládání jednotlivých bajtů je lepší data nejprve seskupit a zapisovat je po větších blocích.

Možnosti využití

Modul pro microSD kartu lze použít například pro:

  • záznam teploty, vlhkosti nebo tlaku
  • ukládání GPS trasy
  • dlouhodobé měření spotřeby energie
  • záznam chyb a událostí zařízení
  • ukládání nastavení
  • načítání obrázků pro displej
  • přehrávání zvukových souborů
  • ukládání fotografií z ESP32-CAM
  • jednoduchý webový server se soubory
  • zálohování dat z jiných modulů

Závěr

Modul pro microSD kartu představuje jednoduchý způsob, jak k Arduinu nebo ESP32 přidat velké a snadno přenosné úložiště. Pro základní práci stačí připojit sběrnici SPI, inicializovat knihovnu a otevřít požadovaný soubor.

Nejdůležitější je vybrat správnou verzi modulu. Jednoduchý modul bez převodníku je určený pro desky používající 3,3V logiku. Pro klasické Arduino UNO, Nano nebo Mega je bezpečnější použít větší modul se stabilizátorem napětí a převodníkem logických úrovní.

V ukázkách jsme si ověřili vytvoření, čtení i doplňování souboru a také jednoduchý zápis naměřených hodnot do CSV. Při zapojování je potřeba hlídat správnou napěťovou verzi modulu, krátké vodiče, stabilní napájení a rozdíl mezi režimy FILE_WRITE a FILE_APPEND.

Tím je základ pro vlastní datalogger hotový. Dál už stačí připojit konkrétní senzor nebo RTC modul a začít ukládat skutečná data.

Moduly pro SD kartu zakoupíte na Laskakit.cz, přímý odkaz je ZDE.

Další díly ze začátečnické série o modulech najdete ZDE.

4 komentáře u „MicroSD karta s ESP32 – zapojení, zápis a čtení souborů“

  1. Pěkné 🙂
    Jen připodotknu, že s některými SD čtečkami můžou být problémy s tím, že, i když nejsou vybrané, tak stejně posílají data a tak ruší ostatní zařízení na tom, samém SPI. Někdy se to dá HW opravit na čtečce, vždycky se to dá odstínit HW na desce, která tu čtečku používá a nejjednoduší je se tomu vyhnout tím, že na stejné SPI nedáváme jiná zařízení 🙂 (Píšu o tom tady a jsou tam další odkazy https://github.com/githubgilhad/MegaHomeFORTH/blob/master/HW/Foto/SD_card/SD_card.rst )

    Taky vyžaduje mít při vložení/zapnutí CS==0V, aby SD karta naběhla ve správném režimu.

    1. Dobrá připomínka. Já jsem nikdy problém s rušením neměl ale uznávám že se stát může. A při použití více zařízení na jedné SPI je samozřejmě nutné pohlídat si CS aby se nehádaly.

      1. Tady je problém, že SD karta ve skutečnosti není SPI zařízení, jen se někdy „chová docela podobně“. Jenže občas ignoruje, že není vybrána přez CS a prostě na sběrnici něco pošle a tím rozhodí jiné zařízení, které skutečně dodržuje SPI. Na netu se to řeší každou chvíli. A ještě k opravdovému rušení – použil jsem SD kartu s UNO R3 a vše chodilo, použil jsem ji zcela stejně jinde na PCB a najednou to chodilo jen občas a s chybama. Nejspíš tam byl moc dlouhý a klikatý spoj a možná vedl ve špatném sousedství, ale elektrolotický kondenzátor a pullup odpory 10k na všechny piny tomu pomohly tak, že to teď chodí furt. (Empirická zkušenost, ale někomu může pomoct, když to bude „nějak zlobit“. Přidat odpor bylo jednodušší, než měnit PCB a zase ho odebrat by taky nebyl problém.)

    2. Na problém s CS pinem čtečky jsem už upozorňoval tady:
      https://forum.hwkitchen.cz/viewtopic.php?t=2016

      Když je CS v HIGH, měla by být karta deaktivovaná (její výstupní MISO pin se přepne do vysoké impedance), ale kvůli špatně navrženému plošňáku se za převodníkem úrovní na MISO objeví trvalé LOW, které zablokuje další komunikaci mezi zařízeními na SPI sběrnici.

      Nevím, jak je to s ESP32, ale na Arduinech a STM už se dneska doporučuje místo knihovny „SD.h“ používat novější „SdFat.h“.

      Ale jinak dobrý článek.

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *