13.2. Взаимодействие Arduino с SD-картой

Для SD-карт, как и для радиомодулей ХВее, которые мы рассмотрели в главе 11, требуется питание 3,3 В. Поэтому подключать SD-карту необходимо через переходник, который преобразует логические уровни и напряжение питания для SD-карты. Кроме того, связь с SD-картой возможна по интерфейсу SPI, описанному в главе 9. Arduino IDE поставляется с удобной библиотекой SD, реализующей функции низкого уровня и позволяющей легко читать и записывать файлы на SD-карту.

13.2.1. Платы расширения для SD-карт

Есть множество плат расширения (переходников) для подключения SD-карт к Arduino. Все рассмотреть в книге невозможно, опишем некоторые из популярных, указав их достоинства и недостатки.

Общие черты всех переходников SD-карт:

• подключаются к плате Arduino по интерфейсу SPI, через 6 контактов ICSP платы Arduino или к контактам цифровых выводов (11, 12 и 13 на Uno или 50, 51 и 52 на Mega);

- 277 -

• имеют вход выбора (CS), который может быть контактом по умолчанию (53 на Mega, 10 на других платах Arduino );

• подают питание 3,3 В на SD-карту и согласуют логические уровни.

Вот список наиболее распространенных плат расширения для SD-карт:

• Cooking Hacks Micro SD shield (http://www.exploringarduino.com/parts/cooking-hacks-SD-shield) (рис. 13. 7) используется для иллюстрации примеров этой главы. Это самый маленький переходник из рассматриваемых нами, и его можно подключить либо к цифровым контактам (8-13 на Uno ), либо к 6-контактному ICSP на Arduino. При подключении к контактам 8-13 вход выбора CS соединен с контактом 10. При подключении к разъему ICSP вход CS можно соединить с любым контактом Arduino. Это полезно, если контакт 10 платы Arduino занят. Переходник поставляется с SD-картой 2 Гбайт.

Рис. 13.7. Плата расширения Cooking Hacks Micro SD shield

• Official Arduino Wireless SD shield (http://www.exploringarduino.com/parts/arduino-wireless-shield) (рис. 13.8)- это первая из нескольких "официальных" плат расширения Arduino с поддержкой SD-карт. Переходник содержит схему для подключения радиомодуля ХВее и SD-карты памяти, что позволяет легко объединить примеры из настоящий главы и из главы 11. На этой плате расширения вход выбора SD-карты (CS) подключается к контакту 4 Arduino. Вы должны назначить контакт 10 как выход, а также указать в библиотеке, что контакт 4 подключен к CS.

• Official Arduino Ethernet SD shield (http://www.exploringarduino.com/parts/arduino-ethernet-shield) (рис. 13.9) позволяет подключить плату Arduino к проводной сети. Переходник также реализует интерфейс SD-карты, хотя в основном он служит для хранения файлов, которые будут доступны через сеть. Оба контроллера (Ethernet и SD-карты) на этом переходнике являются SPI-устрой

- 278 -

Рис. 13.8. Плата расширения Arduino Wireless SD shield

Рис. 13.9. Плата расширения Arduino Ethernet SD shield

ствами; вывод CS Ethemet подключается к контакту 10 платы Arduino, а вывод CS SD-карты - к контакту 4.

• Official Arduino Wi-Fi SD shield (http://www.exploringarduino.com/parts/arduino-wifi-shield) (рис. 13.10) также реализует подключение к сети, но через Wi-Fi. SD-карта, как и в Ethemet SD shield, служит для хранения файлов, доступных через сеть. Как и в Ethemet SD shield, Wi-Fi-контроллер для CS исполь

- 279 -

зует контакт 10, а SD-карта - контакт 4. Необходимо следить, чтобы оба устройства не были включены одновременно; активной может быть только одна линия CS (низкий логический уровень).

Adafruit data logging shield (http://www.exploringarduino.com/parts/ adafruitdata-logging-shield) (рис. 13. 11) особенно хорошо подходит для экспериментов,

Рис. 13.10. Плата расширения Arduino Wi-Fi SD shield

Рис. 13.11. Плата расширения Adafruit data logging shield

- 280 -

которые мы рассмотрим далее в этой главе, потому что включает в себя часы реального времени (RTC) и интерфейс SD-карты. Вывод CS SD-карты на этом переходнике назначен по умолчанию (53 на Mega, 10- на других платах Arduino ), а чип часов реального времени подключен к шине I2C.

На плате расширения SparkFun MicroSD shield (http://www.exploringarduino.com/parts/spark-fun-microSD-shield) (рис. 13.12) установлен только слот SD-карты. Тем не менее, предусмотрено монтажное поле для припаивания дополнительных компонентов. Вывод CS SD-карты подключен к контакту 8, его необходимо указать при использовании библиотеки SD с этим переходником.

Рис. 13.12. Плата расширения SparkFun MicroSD shield

13.2.2. SPI-интерфейс SD-карты

Как упоминалось ранее, связь платы Arduino с SD-картой осуществляется через SPI-интерфейс: контакты MOSI, MISO, SCLK (тактовые импульсы) и CS (выбор чипа). Для выполнения примеров этой главы мы будем использовать библиотеку SD. Это предполагает, что задействованы аппаратные SPI-контакты на плате Arduino, а в качестве CS назначен или контакт по умолчанию или определенный пользователем. Библиотека SD для правильной работы требует установки контакта для CS по умолчанию в качестве выхода, даже если для CS задан другой вывод.

В случае Uno это вывод 10, для платы Mega это вывод 53. Описанные далее примеры собраны на плате Arduino Uno с выводом CS, заданным по умолчанию.

13.2.3. Запись на SD-карту

Библиотека SD позволит создать несложный пример записи данных на SD-карту.

Будем получать данные с датчиков и записывать на карту. Данные хранятся в фай

- 281 -

ле под названием log.csv, в дальнейшем его можно открыть на компьютере. Важно отметить, что при форматировании карты в F АТ 16 имена файлов должны быть записаны в формате "8.3", т. е. расширение должно состоять из трех символов, а имя файла - не более чем из восьми символов.

Убедитесь, что переходник SD правильно подключен к плате Arduino и в него установлена SD-карта. Для Cooking Hacks Micro SD shield это будет выглядеть так, как на рис. 13.13 (используются контакты 8-13 Arduino и перемычка находится на правой стороне).

Рис. 13.13. Подключение платы расширения Cooking Hacks Micro SD shield

Для отладки программы будем контролировать статус нескольких функций библиотеки SD. Например, для установки связи с SD-картой необходимо вызвать следующую функцию (листинг 13.1 ):

Листинг 13.1. Функция инициализации SD-карты

if (!SD.begin(CS_pin))

{

Serial.println("Card Failure");

return;

}

Serial.println("Card Ready");

- 282 -

Обратите внимание, что мы не просто инициализируем обмен с картой с помощью функции so.begin (CS_pin), а получаем статус выполнения этой функции. При успешной инициализации программа выдает в последовательный порт сообщение об этом, в противном случае выводится сообщение о неуспехе и команда возврата останавливает дальнейшее выполнение программы.

При записи строки в файл подход аналогичный. Например, если вы хотите записать новую строку "hello" в файл, код будет выглядеть так, как в листинге 13.2.

Листинг 13.2. Функция записи информации на SD-карту

File dataFile = SD.open("log.csv", FILE_WRITE);

if (dataFile)

{

dataFile.println("hello");

dataFile.close();

// Данные не записываются,

// пока соединение не будет закрыто

}

else

{

Serial.println("Couldn't open log file");

}

В первой строке расположена команда создания нового файла (или открытие, если он уже существует) с названием log. csv. Если файл создан/открыт успешно, переменная dataFile получит значение true, и начнем процесс записи данных в файл.

В противном случае сообщаем об ошибке в последовательный порт. Запись строки данных в файл осуществляет функция da taFile.println(); чтобы предотвратить добавление символа новой строки, вызывайте функцию dataFile.print(). Все данные направляются в буфер и записываются в файл только после выполнения команды dataFile.close().

Теперь напишем простую программу, которая создает на SD-карте файл log.csv и каждые 5 секунд записывает в него через запятую метки и какое-либо сообщение (листинг 13.3). В каждой строке файла CSV будет записана временная метка (текущее значение функции millis()) и некоторый текст. Программа может показаться вам бесполезной, но на самом деле это важный пример, подготавливающий взаимодействие с реальными датчиками, чем мы займемся в дальнейших проектах.

Листинг 13.3. Тест записи данных на SD-карту- write_to_sd.ino

// Запись данных на SD-карту

#include <SD.h>

// Подключение контактов

// MOSI = pin 11

// MISO = pin 12

// SCLK = pin 13

- 283 -

// Подключение контакта выбора CS

const int CS_PIN = 10;

// Контакт для питания SD-карты

const int POW_PIN =8;

void setup()

{

Serial.begin(9600);

Serial.println ("Initializing Card");

// Установить CS как выход

pinMode(CS_PIN, OUTPUT);

// Для питания карты используется вывод 8, установить HIGH

pinMode(POW_PIN, OUTPUT);

digitalWrite(POW_PIN, HIGH);

if ( !SD.begin(CS_PIN))

{

Serial.println("Card Failure");

return;

}

Serial.println("Card Ready");

}

void loop()

{

long timeStamp = millis();

String dataString = "Hello There!";

// Открыть файл и записать в него

File dataFile = SD.open("log.csv", FILE_WRITE);

if (dataFile)

{

dataFile.print(timeStamp);

dataFile.print(",");

dataFile.println(dataString);

dataFile.close(); // Данные не записаны,

// пока соединение не закрыто!

// Вывод в монитор для отладки

Serial.print(timeStamp);

Serial.print(",");

Serial.println(dataString);

}

else

{

Serial.println("Couldn't open log file");

}

delay(5000);

}

- 284 -

Обратите внимание на несколько моментов, особенно если у вас такой же переходник, как у меня (Cooking Hacks Micro SD shield):

• CS можно установить на любом контакте; если это не контакт по умолчанию (10), то необходимо в setup() предусмотреть команду pinMode(10, OUTPUT), иначе библиотека SD не будет работать;

• питание на переходник подается через контакт 8, поэтому POW_PIN должен быть установлен в качестве выхода и в setup() необходимо определить его значение как HIGH;

• при каждом проходе цикла loop() временная метка обновляется значением текущего времени, прошедшего с начала выполнения программы в миллисекундах. Переменная должна иметь тип long, потому что millis() возвращает число больше, чем 16 бит.

Файл открывается для записи и в него добавляются данные, разделенные запятыми.

Мы также выводим эти данные в последовательный порт для отладочных целей.

Если вы откроете терминал последовательного порта, то увидите вывод данных как на рис. 13.14.

Рис. 13.14. и Рис. 13.15.

При возникновении ошибок проверьте правильность подключения переходника, убедитесь, что SD-карта отформатирована и должным образом вставлена. Для проверки корректности записи данных вставьте SD-карту в компьютер и откройте файл в программе просмотра электронных таблиц (рис. 13.15). Обратите внимание,

- 285 -

что данные располагаются в таблице с учетом разделяющих запятых и символов перехода на новую строку.

13.2.4. Чтение с SD-карты

Теперь рассмотрим чтение информации с SD-карты. При регистрации данных это не нужно, но может оказаться полезным для установки параметров программы. Например, можно указать частоту регистрации данных.

Вставьте SD-карту в компьютер и создайте на ней новый текстовый файл с именем speed.txt. В этом файле просто введите время обновления в миллисекундах. На рис. 13.16 показано, что я задал время, равное 1000 мс ( 1 с).

После записи желаемой скорости обновления сохраните файл на SD-карте и вставьте карту в переходник, подключенный к Arduino. Теперь изменим програм

Рис. 13.16. Пример файла данных

- 286 -

му, предусмотрев чтение этого файла, извлечение информации и установку скорости обновления данных для регистрации.

Открыть файл для чтения позволяет та же команда so.open(), но без указания второго параметра FILE_WRITE. Поскольку класс File наследует свойства от класса потока (так же, как serial), можно использовать многие из полезных команд, например parseInt(). Сказанное иллюстрирует листинг 13.4.

Листинг 13.4. Пример чтения информации с SD-карты

File commandFile=SD.open("speed.txt");

if (commandFile)

{

Serial.println ( "Reading Command File");

while(commandFile.available() )

{

refresh_rate=commandFile.parseInt();

}

Serial.print("Refresh Rate = ");

Serial.print(refresh_rate);

Serial.println("ms");

}

else

{

Serial.println("Could not read command file.");

return;

}

Программа из листинга 13.4 открывает файл для чтения и считывает целые значения. Значение сохраняется в переменной частоты обновления, которую необходимо будет определить в начале программы. После чтения файл следует закрыть.

Теперь можно объединить листинги 13.3 и 13.4 и менять скорость записи, основываясь на содержимом файла speed.txt, как показано в листинге 13.5.

Листинг 13.5. Чтение и запись с SD-карты- sd_read_write.ino

// Чтение и запись SD-карты

#include <SD.h>

// Подключение контактов

//MOSI = pin 11

//MISO = pin 12

//SCLK = pin 13

// Подключение контакта выбора CS

const int CS_PIN =10;

const int POW_PIN =8;

// Скорость опроса по умолчанию

int refresh rate = 5000;

- 287 -

void setup()

{

Serial.begin(9600);

Serial.println("Initializing Card");

// Установить CS как выход

pinMode(CS_PIN, OUTPUT);

// Для питания карты используется контакт 8, установить HIGH

pinMode(POW_PIN, OUTPUT);

digitalWrite(POW_PIN, HIGH);

if ( !SD.begin(CS_PIN))

{

Serial.println("Card Failure");

return;

}

Serial.println("Card Ready");

// Чтение настроек (speed.txt)

File commandFile = SD.open("speed.txt");

if (comrnandFile)

{

Serial.println ( "Reading Comrnand File");

while(commandFile.available())

{

refresh_rate = commandFile.parseInt();

}

Serial.print("Refresh Rate = ");

Serial.print(refresh_rate);

Serial.println("ms");

commandFile.close(); // Закрыть файл настроек

}

else

{

Serial.println("Could not read command file.");

return;

}

}

void loop()

{

long timeStamp = millis();

String dataString = "Hello There!";

// Открыть файл и записать в него

File dataFile = SD.open("log.csv", FILE_WRITE);

if (dataFile)

{

dataFile.print(timeStamp);

dataFile.print(",");

dataFile.println(dataString);

dataFile.close(); // Закрыть файл

- 288 -

// Вывод в последовательный порт для отладки

Serial.print(timeStarnp);

Serial.print(",");

Serial.println(dataString);

}

else

{

Serial.println("Couldn't open log file");

}

delay(refresh_rate);

}

После загрузки на плату и запуска программы данные будут записываться с частотой, указанной при настройке. За процессом можно наблюдать в мониторе последовательного порта (рис. 13.17).

Рис. 13.17. Регистрация данных на скорости Refresh Rate, указанной в настройках

Более 800 000 книг и аудиокниг! 📚

Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением

ПОЛУЧИТЬ ПОДАРОК