Общие сведения:
Trema-модуль адаптер microSD — адаптер карт памяти microSD, который вы можете использовать для записи значений аналоговых и цифровых выводов Arduino.
Видео:
Спецификация:
- Поддерживаемые карты памяти: microSD-карты (FAT16/FAT32);
- Объём карты памяти: SD до 2Gb / SDHC до 32Gb;
- Питание: 5В;
- Интерфейс: SPI;
- Вывод INS для идентификации наличия вставленной карты
- Все модули линейки "Trema" выполнены в одном формате
Подключение:
Для удобства подключения к Arduino воспользуйтесь Trema Shield, Trema Power Shield, Motor Shield или Trema Set Shield.
Выводы Trema SD | Выводы Piranha Uno/Arduino Uno | Выводы Arduino Mega | Выводы Arduino Leonardo |
MISO | 12 | 50 | ICSP_MISO |
MOSI | 11 | 51 | ICSP_MOSI |
SCK | 13 | 52 | ICSP_SCK |
SS(SC) | 10 | 53 | ICSP_SS |
INS | Любой вывод | Любой вывод | Любой вывод |
GND | GND | GND | GND |
Vcc | 5V | 5V | 5V |
Модуль удобно подключать 5 способами, в зависимости от ситуации:
Способ - 1 : Используя проводной шлейф и Piranha UNO
Используя провода «Папа — Мама», подключаем напрямую к контроллеру Piranha UNO
Способ - 2 : Используя Trema Set Shield
Модуль можно подключить к любому из входов Trema Set Shield ( при использовании программного последовательного порта )
Способ - 3 : Используя проводной шлейф и Trema Shield
Используя 3-х проводной шлейф и 4 провода «Мама — Мама», к Trema Shield, Trema-Power Shield, Motor Shield, Trema Shield NANO и тд.
Способ - 4 : Используя провода и Arduino Mega
Используя провода «Папа — Мама», подключаем напрямую к контроллеру Arduino Mega
Способ - 5 : Используя провода и Arduino Leonardo
Используя 4 провода «Папа — Мама» и 3 провода «Мама — Мама», подключаем напрямую к контроллеру Arduino Leonardo
Питание:
Данный модуль питается от источника постоянного напряжения 5В.
Подробнее о модуле:
Модуль поддерживает карты microSD. Для работы с библиотекой Arduino карта должна быть отформатирована в формате FAT16 или FAT32.
У модуля есть возможность снизить энергопотребление путём отключения индикаторных светодиодов. Это производится посредством удаления двух напаянных джамперов на нижней стороне платы:
На модуле имеется вывод "INS", определяющий наличие карты.
Примеры:
Внимание: во избежание потери данных рекомендуем извлекать microSD карту во время загрузки скетча в микроконтроллер.
Инициализация карты, создание и запись файла
#include <SPI.h> // Подключаем библиотеку для работы с шиной SPI #include <SD.h> // Подключаем библиотеку для работы с SD картой #define INS 7 // определяем номер вывода, отвечающего за определение наличия карты void setup() { Serial.begin(9600); // инициализируем работу с аппаратным последовательным портом и указываем скорость работы 9600 бод while(!Serial); // Ждём соединения с последовательном портом (необходимо для совместимости с Arduino Leonardo pinMode(INS, INPUT_PULLUP); // объявляем режим вывода INS Serial.println("Waiting for the card to be inserted"); // выводим текст в последовательный порт. while(digitalRead(INS)); // ждем пока будет вставлена карта delay(1000); // ждем секунду, чтобы убедиться что карта вставлена полностью if (!SD.begin()) { // Проверяем, есть ли связь с картой и, если нет, то // Если SD.begin() зависает, укажите номер вывода SS: SD.begin(10); Serial.println("Initialization failed"); // выводим текст в последовательный порт. while(true); // Скетч не выполняется дальше } Serial.println("Card OK"); // выводим текст в последовательный порт. File myFile = SD.open("file.txt", FILE_WRITE); // создаём файл для записи char c = '@'; // создаём переменную int i = 42; // создаём переменную float f = 3.14; // создаём переменную String s = "trema"; // создаём переменную myFile.println(c); // записываем переменную в файл myFile.println(i); // записываем переменную в файл myFile.println(f); // записываем переменную в файл myFile.println(s); // записываем переменную в файл myFile.close(); // закрываем файл Serial.println("done"); // выводим текст в последовательный порт. } void loop() { // }
Чтение из файла в последовательный порт
#include <SPI.h> // Подключаем библиотеку для работы с протоколом SPI #include <SD.h> // Подключаем библиотеку для работы с SD картой void setup() { Serial.begin(9600); // инициализируем работу с аппаратным последовательным портом и указываем скорость работы 9600 бод while(!Serial); // Ждём соединения с последовательным портом (необходимо для совместимости с Arduino Leonardo if (!SD.begin()) { // Проверяем, есть ли связь с картой и, если нет, то // Если SD.begin() зависает, укажите номер вывода SS: SD.begin(10); Serial.println("Initialization\ failed"); // выводим текст в последовательный порт. while(true); // Скетч не выполняется дальше. } Serial.println("Card OK"); // Выводим текст в последовательный порт. File myFile = SD.open("file.txt"); // Открываем файл для чтения, while(myFile.available()) Serial.write(myFile.read()); // выводим содержимое файла в последовательный порт, myFile.close(); // закрываем файл } void loop() { // }
Чтение из файла в переменные и удаление файла
#include <SPI.h> // Подключаем библиотеку для работы с протоколом SPI #include <SD.h> // Подключаем библиотеку для работы с SD картой char c = 0; // создаём глобальную переменную для чтения из файла int i = 0; // создаём глобальную переменную для чтения из файла float f = 0; // создаём глобальную переменную для чтения из файла String s = ""; // создаём глобальную переменную для чтения из файла void setup() { Serial.begin(9600); // инициализируем работу с аппаратным последовательным портом и указываем скорость работы 9600 бод while(!Serial); // Ждём соединения с последовательном портом (необходимо для совместимости с Arduino Leonardo if (!SD.begin()) { // проверяем, есть ли связь с картой и, если нет, то // Если SD.begin() зависает, укажите номер вывода SS: SD.begin(10); Serial.println("Initialization failed"); // выводим текст в монитор последовательного порта, while(true); // скетч не выполняется дальше. } Serial.println("Card OK"); // выводим текст в монитор последовательного порта, File myFile = SD.open("file.txt"); // открываем ранее созданный файл file.txt if (!myFile) { // если файл file.txt не найден Serial.println("file not found"); // выводим текст в монитор последовательного порта, while(true); // скетч не выполняется дальше. } else { // Если файл file.txt найден, char Bytes[10]; // создаём переменную для хранения байтов в формате char, int k = 0; // создаём переменную-итератор, while(myFile.available() && // пока файл не кончился, ((Bytes[k] = myFile.read()) != '\n')) ++k; // читаем байты из файла до символа новой строки, c = Bytes[0]; // записываем первый байт в переменную char, k = 0; // сбрасываем итератор, while(myFile.available() && // пока файл не кончился, ((Bytes[k] = myFile.read()) != '\n')) ++k; // читаем байты дальше до следующего символа новой строки, i = atoi(Bytes); // конвертируем в int, k = 0; // сбрасываем итератор, while(myFile.available() && // пока файл не кончился, ((Bytes[k] = myFile.read()) != '\n')) ++k; // читаем байты дальше до следующего символа новой строки, f = atof(Bytes); // конвертируем в float, while(myFile.available() && // пока файл не кончился, ((s += char(myFile.read())))); // читаем байты и сразу конкатенируем в переменную String. myFile.close(); // Закрываем файл. SD.remove("file.txt"); // Удаляем файл. } } void loop() { Serial.println(c); // Выводим переменную в последовательный порт. Serial.println(i); // Выводим переменную в последовательный порт. Serial.println(f); // Выводим переменную в последовательный порт. Serial.println(s); // Выводим переменную в последовательный порт. delay(i*100); // Ждём 4200 миллисекунд }
Информация о карте и листинг файлов, используя утилитные функции библиотеки SD
#include <SPI.h> // Подключаем библиотеку для работы с протоколом SPI #include <SD.h> // Подключаем библиотеку для работы с SD картой Sd2Card card; // создаём объект утилитной библеотеки Sd2Card SdVolume partition; // создаём объект тома утилитной библеотеки Sd2Card SdFile root; // создаём объект корневого файла утилитной библеотеки Sd2Card void setup() { Serial.begin(9600); // инициализируем работу с аппаратным последовательным портом, while (!Serial); // ждём соединения с последовательным портом (необходимо для совместимости с Arduino Leonardo). if (!card.init(SPI_HALF_SPEED)){ // Если карта не найдена (SPI_HALF_SPEED = F_CPU/4), Serial.println("initialization\ failed"); // выводим текст в монитор последовательного порта. while(true); // Скетч не выполняется дальше. } else Serial.println("Card OK"); // Если карта найдена switch (card.type()){ // проверяем тип карты: case SD_CARD_TYPE_SD1: // тип карты SD1, Serial.println("SD1"); break; case SD_CARD_TYPE_SD2: Serial.println("SD2"); // тип карты SD2, break; case SD_CARD_TYPE_SDHC: Serial.println("SDHC"); // тип карты SDHC, break; default: Serial.println("Unknown type"); // тип карты неизвестен. } if (!partition.init(card)) { // Открываем раздел карты, если не найден - Serial.println("No partition found.\ // выводим текст в монитор последовательного порта. Make sure card is\ is formatted as\ FAT16 or FAT32"); while(true); // Скетч не выполняется дальше. } uint32_t part_size; // Создаём переменную для расчета размера раздела карты: part_size = partition.blocksPerCluster(); // кол-во блоков в кластере part_size *= partition.clusterCount(); // умножаем на кол-во кластеров, part_size /= 2; // 1 блок - 512 байтов. part_size /= 1024; // Размер в мегабайтах. Serial.print("Partition size in Mb: "); // Выводим текст в монитор последовательного порта. Serial.println(part_size); // Выводим размер в мегабайтах в монитор последовательного порта. Serial.print("Partition size in Gb: "); // Выводим текст в монитор последовательного порта. Serial.print(float(part_size) / 1024.0); // Выводим размер в гигабайтах в монитор последовательного порта. Serial.println("Root directory:"); // Выводим текст в монитор последовательного порта. root.openRoot(partition); // Открываем корневой каталог раздела, root.ls (LS_R | LS_SIZE, 3); // вызываем утилитную функцию листинга открытого каталога. } void loop() { // }
Листинг файлов без использования утилитных функций
#include <SPI.h> // Подключаем библиотеку для работы с протоколом SPI #include <SD.h> // Подключаем библиотеку для работы с SD картой void setup() { Serial.begin(9600); // инициализируем работу с аппаратным последовательным портом и указываем скорость работы 9600 бод while(!Serial); // Ждём соединения с последовательном портом (необходимо для совместимости с Arduino Leonardo) if (!SD.begin()) { // Проверяем, есть ли связь с картой и, если нет, то // Если SD.begin() зависает, укажите номер вывода SS: SD.begin(10); Serial.println("Initialization failed"); // выводим текст в монитор последовательного порта. while(true); // Скетч не выполняется дальше } Serial.println("Card OK"); // выводим текст в монитор последовательного порта. Serial.println("Type: "); // выводим текст в монитор последовательного порта. File root = SD.open("/"); // открываем корневой каталог printRoot(root); // вызываем функцию листинга } void loop() { // } void printRoot(File dir) { // функция листинга директории. while(true) { File entry = dir.openNextFile(); // Открываем следующий файл, if (! entry) { // если файлов не осталось break; // выходим из цикла. } Serial.print(entry.name()); // Выводим имя файла в последовательный порт. if (entry.isDirectory()) { // Если файл является директорией Serial.println("/"); // Выводим косую черту, printRoot(entry); // рекурсия в директорию (функция вызывает сама себя). } else { // Если не директория - Serial.print("\t\t\t\t"); // выводим отступ Serial.println(entry.size(), DEC); // и размер файла в байтах } } }
Создание лог-файла с использованием часов реального времени и датчика звука.
#include "SPI.h" // подключаем библиотеку для работы с шиной SPI #include "SD.h" // подключаем библиотеку для работы с SD картой #include "iarduino_RTC.h" // подключаем библиотеку iarduino_RTC time(RTC_DS1307); // объявляем объект time для модуля на базе чипа DS1307 File myFile; // объявляем объект myFile для работы с файлом на SD-карте const uint8_t SOUND_SENSOR = A1; // вывод, к которому подключен датчик звука String REAL_TIME; // переменная для значений реального времени uint16_t LOUDNESS; // переменная для аналоговых значений датчика звука void setup() { Serial.begin(9600); // инициализируем работу с аппаратным последовательным портом и указываем скорость работы 9600 бод pinMode(SOUND_SENSOR, INPUT); // настраиваем вывод A1 на работу в режиме ВХОДА time.begin(); // Инициируем RTC модуль time.settime(0, 15, 15, 14, 5, 19, 2); // Устанавливаем время: 0 сек, 15 мин, 15 час, 14, мая, 2019 года, вторник if (!SD.begin()) { // Проверяем, есть ли связь с картой и, если нет, то // Если SD.begin() зависает, укажите номер вывода SS: SD.begin(10); Serial.println("Initialization failed"); // выводим текст в последовательный порт. while (true); // Скетч не выполняется дальше } Serial.println("Card OK"); // выводим текст, что всё прошло успешно, в последовательный порт. } void loop() { if (millis() % 5000 == 0) { // если прошло 5 секунд, то REAL_TIME = time.gettime("d-m-Y, H:i:s"); // записываем значение, считанное с часов реального времени, в переменную REAL_TIME LOUDNESS = analogRead(SOUND_SENSOR); // записываем значение, считанное с датчика звука, в переменную LOUDNESS myFile = SD.open("test.txt", FILE_WRITE); // создаём файл test.txt для записи значений myFile.print(REAL_TIME); // записываем переменную в файл myFile.print(","); // записываем разделительный символ myFile.println(LOUDNESS); // записываем переменную в файл myFile.close(); // закрываем файл } }
Описание функций библиотеки:
На заметку: Библиотека SD входит в стандартный набор библиотек Arduino
Подключение библиотеки:
#include <SPI.h> // Подключаем библиотеку для работы с шиной SPI #include <SD.h> // Подключаем библиотеку для работы с SD картой
Функция begin();
- Назначение: инициирование работы с картой;
- Синтаксис: begin();
- Параметры: ВЫВОД CS(chip select) – опциональный параметр, по умолчанию вывод SS(slave select) шины SPI. Вывод 10 на Piranha Uno, Arduino Leonardo; вывод 53 на Arduino Mega;
- Возвращаемые значения: bool - результат инициализации (true / false);
- Примечание:
- Функцию необходимо вызвать до обращения к любым другим функциям библиотеки;
- Функцию достаточно вызвать один раз в коде
setup
; - Функцию можно использовать для определения наличия SD карты;
- Для некоторых плат, нужно указывать вывод CS в качестве параметра функции, даже если используется аппаратный вывод CS шины SPI. Иначе функция "зависнет".
- Аппаратный вывод CS шины SPI не может быть использован в качестве выхода, даже если он не используется как вывод CS шины SPI.
- Пример:
SD.begin(); // Инициализируем SD карту используется аппаратный вывод CS шины SPI. SD.begin(10); // Инициализируем SD карту используя вывод 10 в качестве вывода CS.
Функция exists();
- Назначение: проверка существования файла или директории на SD карте;
- Синтаксис: exists(ИМЯ);
- Параметры: ИМЯ — строка String, имя файла для проверки. Может включать директории, разделённые косой чертой (прямой слэш - /);
- Возвращаемые значения: bool — true - файл существует/ false - файл не существует;
- Примечание: нет;
- Пример:
SD.exists("file.txt"); // проверяем наличие файла "file.txt"
Функция mkdir();
- Назначение: создание новой директории (папки);
- Синтаксис: mkdir(ИМЯ);
- Параметры: ИМЯ – строка String, имя создаваемой директории
- Возвращаемые значения:
- true - директория создана / false – директория не создана;
- Примечание: можно создавать сразу несколько вложенных директорий, разделённых косой чертой (прямой слэш - /). Если запустить пример указанный ниже, на пустой SD-карте, то будут созданы три директории вложенные друг в друга.
- Пример:
SD.mkdir("FOLDER1/FOLDER2/FOLDER3"); // создаём папку
Функция open();
- Назначение: открытие файла, создание файла (файл будет создан, если открыт в режиме записи и не существует);
- Синтаксис: open(ИМЯ), open(ИМЯ, РЕЖИМ);
- Параметры:
- ИМЯ — строка String, имя файла. Может включать директории, разделённые косой чертой (прямой слэш - /).
- РЕЖИМ – необязательный параметр, определяющий цель открытия файла:
- FILE_READ – открыть для чтения (указатель в начале файла). По умолчанию.
- FILE_WRITE – открыть для записи (указатель в конце файла).
- Возвращаемые значения:
- объект File. Если файл не найден, объект возвращает false;
- Примечание: нет;
- Пример:
SD.open("file.txt", FILE_WRITE); // открываем файл file.txt для записи
Функция remove();
- Назначение: удаление файла.
- Синтаксис: remove(ИМЯ);
- Параметры: ИМЯ — имя файла для удаления. Может включать директории, разделённые косой чертой (прямой слэш - /).
- Возвращаемые значения:
- при успешном выполнении true, иначе false;
- Примечание: нет;
- Пример:
SD.remove("file.txt"); // удаляем файл file.txt
Функция rmdir();
- Назначение: удаление пустой директории (папки);
- Синтаксис: rmdir(ИМЯ);
- Параметры: ИМЯ — имя директории (папки) для удаления;
- Возвращаемые значения:
- при успешном выполнении true, иначе false;
- Примечание: нет;
- Пример:
SD.rmdir("FOLDER"); // удаляем папку FOLDER
Описание объекта File:
Инициализация объекта:
Files myFile=SD.open("file.txt"); // открываем файл для чтения
Функция name();
- Назначение: возврат имени открытого файла в объекте myFile;
- Синтаксис: name();
- Параметры: нет
- Возвращаемые значения:
- строка String – имя файла;
- Примечание: нет;
- Пример:
String filename = myFile.name(); // создаём переменную строки, хранящую название файла
Функция available();
- Назначение: возврат количества байтов, доступных для чтения;
- Синтаксис: available();
- Параметры: нет
- Возвращаемые значения:
- целое число int — количество байтов для чтения;
- Примечание: нет;
- Пример:
int bytes = myFile.available(); // записываем количество доступных байтов в целочисленную переменную bytes
Функция close();
- Назначение: закрытие файла и запись данных;
- Синтаксис: close();
- Параметры: нет;
- Возвращаемые значения: нет;
- Примечание: нет;
- Пример:
myFile.close(); // закрываем открытый файл
Функция flush();
- Назначение: записать требующие записи данные на карту, выполняется автоматически при использовании функции close();
- Синтаксис: exists();
- Параметры: нет;
- Возвращаемые значения: нет;
- Примечание: нет;
- Пример:
myFile.flush(); // записываем несохраненные данные на SD карту
Функция peek();
- Назначение: Чтение байта из файла без сдвига позиции чтения. При следующем вызове функции будет возвращено то же значение;
- Синтаксис: peek();
- Параметры: нет
- Возвращаемые значения:
- byte или -1 (EOF), если байтов для чтения не осталось;
- Примечание: нет;
- Пример:
myFile.peek(); // считываем текущий байт
Функция position();
- Назначение: возврат позиции в файле, в которую будет записан следующий байт;
- Синтаксис: position();
- Параметры: нет
- Возвращаемые значения:
- unsigned long — значение позиции;
- Примечание: нет;
- Пример:
myFile.position(); // узнаём позицию в файле
Функция print();
- Назначение: проверка существования файла или директории на SD карте;
- Синтаксис: print(ДАННЫЕ); print(ДАННЫЕ, СИСТЕМА СЧИСЛЕНИЯ);
- Параметры: ДАННЫЕ — данные для записи char, int, long, byte, String; СИСТЕМА СЧИСЛЕНИЯ — опционально (по умолчанию DEC), система счисления в которой будут записаны числа: BIN - двоичная, DEC - десятеричная, OCT - восьмеричная, HEX — шестнадцатеричная;
- Возвращаемые значения:
- byte — количество записанных байтов;
- Примечание: нет;
- Пример:
int x = 123; myFile.print(x, HEX); // записываем в файл значение переменной в шестнадцатеричной системе счисления (будет записано "7B")
Функция println();
- Назначение: запись данных в файл, открытый для записи с последующим символом новой строки;
- Синтаксис: println(); println(ДАННЫЕ); println(ДАННЫЕ, СИСТЕМА СЧИСЛЕНИЯ);
- Параметры: ДАННЫЕ — данные для записи char, int, long, byte, String; СИСТЕМА СЧИСЛЕНИЯ — опционально (по умолчанию DEC), система счисления в которой будут записаны числа: BIN - двоичная, DEC - десятеричная, OCT - восьмеричная, HEX — шестнадцатеричная;
- Возвращаемые значения:
- количество записанных байтов;
- Примечание: нет;
- Пример:
myFile.println(); // записываем в открытый файл символ новой строки
Функция seek();
- Назначение: перемещение на новую позицию в файле;
- Синтаксис: seek(ПОЗИЦИЯ);
- Параметры: ПОЗИЦИЯ — unsigned long, позиция в файле на которую нужно переместиться;
- Возвращаемые значения:
- true - успешное выполнение / false - неуспешное выполнение;
- Примечание: нет;
- Пример:
bool out = myFile.seek(myFile.size()+1); // перемещение на несуществующую позицию в файле.
Функция size();
- Назначение: Узнать размер открытого файла;
- Синтаксис: size();
- Параметры: нет
- Возвращаемые значения:
- размер файла в unsigned long;
- Примечание: нет;
- Пример:
unsigned long filesize = myFile.size(); // узнаём размер открытого файла
Функция read();
- Назначение: проверка существования файла или директории на SD карте;
- Синтаксис: read(БУФЕР, ДЛИННА);
- Параметры: БУФЕР — массив элементов, ДЛИННА — количество элементов в массиве;
- Возвращаемые значения:
- byte следующий байт / EOF конец файла;
- Примечание: нет;
- Пример:
byte data = myFile.read(); // записываем прочитанный байт в переменную data
Функция write();
- Назначение: запись в файл без конвертирования;
- Синтаксис: write(ДАННЫЕ), write(БУФЕР, ДЛИННА);
- Параметры: ДАННЫЕ - данные для записи byte, char или String. БУФЕР — массив символов или байтов для записи, ДЛИННА — количество элементов массива
- Возвращаемые значения:
- количество записанных байт;
- Примечание: нет;
- Пример:
myFile.write(123); // записываем в виде байта число 123
Функция isDirectory();
- Назначение: проверка существования файла или директории на SD карте;
- Синтаксис: isDirectory();
- Параметры: нет
- Возвращаемые значения:
- true - файл является директорией / false - файл не является директорией;
- Примечание: нет;
- Пример:
if (myFile.isDirectory()) Serial.println("/"); //выводим слэш, если файл является директорией
Функция openNextFile();
- Назначение: возвращает следующий файл в директории;
- Синтаксис: openNextFile();
- Параметры: нет
- Возвращаемые значения: объект File или false, если файл не может быть открыт;
- следующий файл или папка в открытой директории;
- Примечание: нет;
- Пример:
File dir = SD.open("/"); //открываем корневую директорию SD карты File myFile = dir.openNextFile(); //открываем первый файл в директории
Функция rewindDirectory();
- Назначение: проверка существования файла или директории на SD карте;
- Синтаксис: rewindDirectory();
- Параметры: нет;
- Возвращаемые значения:нет;
- Примечание: нет;
- Пример:
if (!myFile) dir.rewindDirectory(); //возвращаемся к первому файлу, если файл не существует
Обсуждение