Ардуино: запись и чтение micro-SD карт

Существует множество различных типов носителей данных на основе так называемой флеш-памяти. Мы пользуемся обычными флешками для передачи файлов друг-другу, micro-SD картами для увеличения свободного места в смартфонах, даже вместо старого доброго жесткого диска в современных ноутбуках используем SSD носители — ту же флеш-память.

Модуль микро-SD карт

Флеш-память не имеет движущихся частей, в отличие от старинных дискет и более новых жестких дисков. Скорость чтения и записи такой памяти выше чем у всех прежних носителей, а энергопотребление — наоборот ниже. Другими словами, если мы хотим в наших электронных устройствах и роботах хранить какие-то данные, то рационально будет воспользоваться именно флеш-памятью.

Зачем может понадобиться карта памяти? Например, для того, чтобы записывать на неё данные с различных датчиков нашего устройства. Кроме самих показаний датчиков, рационально еще записывать время съема этих показаний — это называется журналированием. Таким образом, подключив к Ардуино датчики температуры, влажности и давления, а также часы реального времени и карту памяти мы сможем сделать настоящую погодную станцию!

Разберем как именно карта памяти подключается к Ардуино и каким образом осуществляется её запись и чтение.

1. Подключение модуля micro-SD карт к Ардуино

В этом уроке мы будем читать и записывать данные на micro-SD карту. В плане подключения в Ардуино, модуль micro-SD ничем не отличается от модуля для обычных SD карт.

Модуль подключается к Ардуино по SPI шине, а значит нужно соединить уже знакомые по другим урокам контакты в стандартном порядке:

Модуль micro-SD карт GND VCC CS MOSI MISO SCK
Ардуино Уно GND +5V 4 11 12 13

Принципиальная схема

Модуль микро-SD карт и Ардуино на макетной плате

Внешний вид макета

Микро-SD карта и Ардуино

2. Программа для чтения micro-SD карты

Чтобы проверить работу устройства, напишем простую программу, которая будет лишь считывать с карты служебную информацию: тип карты, тип файловой системы, размер первого раздела и список файлов на нём.

#include <SPI.h>
#include <SD.h>

Sd2Card card;
SdVolume volume;
SdFile root;

const int chipSelect = 4;

void setup() {
    Serial.begin(9600);
    Serial.print("\nInitializing SD card...");

    if (!card.init(SPI_HALF_SPEED, chipSelect)) {
        // неверное подключение или карта неисправна
        Serial.println("initialization failed");
        return;
    } else {
        // всё ок!
        Serial.println("Wiring is correct and a card is present.");
    }

    // считываем тип карты и выводим его в COM-порт
    Serial.print("\nCard type: ");
    switch (card.type()) {
        case SD_CARD_TYPE_SD1:
            Serial.println("SD1");
            break;
        case SD_CARD_TYPE_SD2:
            Serial.println("SD2");
            break;
        case SD_CARD_TYPE_SDHC:
            Serial.println("SDHC");
            break;
        default:
            Serial.println("Unknown");
    }

    // инициализация файловой системы
    if (!volume.init(card)) {
        // неверная файловая система
        Serial.println("Could not find FAT16/FAT32 partition.");
        return;
    }

    // считываем тип и вычисляем размер первого раздела
    uint32_t volumesize;
    Serial.print("\nVolume type is FAT");
    Serial.println(volume.fatType(), DEC);
    Serial.println();

    volumesize = volume.blocksPerCluster(); // блоков на кластер
    volumesize *= volume.clusterCount(); // кластеров
    volumesize *= 512; // 512 байтов в блоке, итого байт.. 
    Serial.print("Volume size (bytes): ");
    Serial.println(volumesize);
    Serial.print("Volume size (Kbytes): ");
    volumesize /= 1024;
    Serial.println(volumesize);
    Serial.print("Volume size (Mbytes): ");
    volumesize /= 1024;
    Serial.println(volumesize);

    Serial.println("\nFiles found on the card (name, date and size in bytes): ");
    root.openRoot(volume);
    // выводим список файлов
    root.ls(LS_R | LS_DATE | LS_SIZE);
}

void loop(void) {
}

Загружаем программу в Ардуино и открываем монитор COM-порта:

Модуль микро-SD карт и Ардуино

Если появилась подобная информация, значит с картой и модулем всё в порядке. Можно приступать к дальнейшей работе.

3. Программа для записи данных на micro-SD карту

Теперь попробуем создать новый файл на карте и записать туда простую фразу «Hello from robotclass».

#include <SPI.h>
#include <SD.h>

const int chipSelect = 4;

void setup() {
    Serial.begin(9600);

    if (!SD.begin(chipSelect)) {
        Serial.println("Card failed, or not present");
        return;
    }
    // строка, которую мы запишем в файл
    String dataString = "Hello from RobotClass";

    // открываем файл, в который будет записана строка
    File dataFile = SD.open("test.txt", FILE_WRITE);

    if (dataFile) {
        // записываем строку в файл
        dataFile.println(dataString);
        dataFile.close();
        Serial.println("Success!");
    } else {
        // выводим ошибку если не удалось открыть файл
        Serial.println("error opening file");
    }
}

void loop() {
}

Загружаем программу. Затем выключаем Ардуино, достаем микро-SD карту из модуля и проверяем на компьютере её содержимое. В корне карты должен появиться файл test.txt с нашей фразой «Hello from RobotClass».

Примечание! Имя файла, которое указывается в функции open не должно содержать более 8 букв (не включая расширение).

4. Программа для чтения данных с micro-SD карты

Наконец, прочитаем файл test.txt и выведем в COM-порт текст из него.

#include <SPI.h>
#include <SD.h>

const int chipSelect = 4;

void setup() {
    Serial.begin(9600);

   if( !SD.begin( chipSelect )){
       Serial.println("initialization failed!");
       return;
    }
    // открываем файл для чтения
    File myFile = SD.open("test.txt");
    if (myFile) {
        // считываем все байты из файла и выводим их в COM-порт
        while (myFile.available()) {
            Serial.write(myFile.read());
        }
        // закрываем файл
        myFile.close();
    } else {
        // выводим ошибку если не удалось открыть файл
        Serial.println("error opening test.txt");
    }
}
void loop() {
}

Загружаем программу и открываем монитор COM-порта. На экране должен появиться весь текст из файла test.txt

Заключение

В следующем уроке мы попробуем добавить в схему часы реального времени и датчик температуры. Оставив такое устройство на целый день мы сможем в итоге построить дневной график температуры.


Изменено: