SD-карта довольно распространённый тип носителя в наше время. Каждый разработчик рано или поздно сталкивается с необходимостью хранить большой объём данных и\или использовать для каких-либо долгосрочных целей энергонезависимый носитель информации. На рынке существует огромное множество модулей для подключения SD-карт к Arduino или любому другому микроконтроллеру.
Практическое использование одного из таких модулей с разбором кода и схемотехнике предлагаю рассмотреть вам в этой статье.
На днях мне пришёл заказанный модуль для работы с SD-картами. В этом посте я расскажу, как усовершенствовать, сделанный нами в прошлом, датчик для измерения температуры, а именно – мы избавим себя от надобности копирования данных из консоли вывода в Excel для дальнейшего анализа, заставив Arduino сохранять данные на SD-карту в виде csv-файла. Данные будут записываться в файл в два столбца – в первом будут единицы времени (или просто номер строки), а во втором значение напряжения на термисторе или ином датчике, которое, как Вы помните, пропорционально температуре.
Необходимые компоненты
- Необходимые компоненты здесь те же, что и в посте про измеритель температуры
 - Модуль для работы с SD-картами
 
Собираем схему
Описывать схему сборки измерителя температуры я не буду, если Вы забыли или не знаете как его собирать – обратитесь к посту, ссылка на который указана выше.
Рассмотрим схему подключения SD модуля. Каждый модуль имеет следующие контакты: GND, 5V, 3V (3.3V), CS, MOSI, SCLK (SCK), MISO, GND. Подключим некоторые из этих контактов к следующим контактам Arduino:
- GND – к земле с Arduino;
 - 5V разъём к 5 вольтовому разъёму Arduino. (Аналогично 3.3V) Подключать оба разъёма одновременно – бессмысленно, я подключаю только 5V;
 - CS – к 4 разъёму;
 - MOSI – к 11 разъёму;
 - SCLK (SCK) – к 13 разъёму;
 - MISO – к 12 разъёму.
 
На этом наше подключение окончено. Для подключения можете использовать макетную плату – просто втыкаете туда SD модуль и в правильном порядке протягиваете провода от соответствующих дорожек к нужным разъёмам.
Подготавливаем SD-карту
SD модуль работает только с SD картами, отформатированными под файловую систему FAT16 или FAT32. Карту необходимо заранее отформатировать на компьютере. БУДЬТЕ ВНИМАТЕЛЬНЫ! При форматировании все данные, находящиеся на носителе, будут уничтожены! Не забудьте переписать их в другое место перед форматированием!
Программируем Arduino
// Подключаем библиотеку для работы с шиной SPI (необходима для работы библиотеки SD)
#include <SPI.h>
// Подключаем библиотеку для работы с SD-картами
#include <SD.h>
File myFile;
// Задаём начальное время (точку отсчёта)
int time = 0;
// Указываем номер аналогового разъёма для считывания данны
int tempPin = 0;
void setup()
{
 // Открываем serial порт
  Serial.begin(9600);
  // Выдаём сообщение о том, что начинается инициализация SD-карты
  Serial.print("Initializing SD card...");
   pinMode(10, OUTPUT);
   // Проверяем готовность SD модуля. Если модуль не готов - выдаём сообщение
  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    return;
  }
  // Проверяем, существует ли на карте файл data.csv, если существует, то удаляем его.
  if(SD.exists("data.csv")) {
    SD.remove("data.csv");
  }
  // Выводим сообщение о том, что инициализация прошла успешно
  Serial.println("initialization done.");
}
void loop()
{
    // Считываем данные (напряжение) с нулевого аналогового разъёма.
    int temp = analogRead(tempPin);
    // Увеличиваем значение времени (номер строки) на единицу. Если вы будете записывать данные раз в минуту, но хотите чтобы время записывалось в секундах - прибавляйте не единицу, а 60.
    time = time + 1;
  // Открываем файл data.csv для записи
  myFile = SD.open("data.csv", FILE_WRITE);
  // Если удалось открыть файл для записи, то записываем данные
  if (myFile) {
    // Выводим данные на экран
    Serial.print(time);
    Serial.print("; ");
    Serial.println(temp);
    // Записываем время
    myFile.print(time);
    // Добавляем точку с запятой
    myFile.print(";");
    // Добавляем температуру и добавляем перенос строки
    myFile.println(temp);
    // закрываем файл
    myFile.close();
  } else {
    // Выводим сооб щение о том, что открыть файл не удалось
    Serial.println("error opening data.csv");
  }
  // Повторяем считывание данных с датчика и запись на флэш-карту через одну секунду
  delay(1000);
}
Загружаем наш скетч в Arduino, запускаем консоль (ctrl+shift+M) в среде Arduino и видим на экране каждую секунду две пары значений – номер строки (или же время) и значение напряжение, соответствующее данной температуре. Подождите, например, 10 секунд и отключите питание от Arduino. Извлеките карточку и вставьте её в компьютер. На карте у вас будет файл data.csv, открыв который в Excel вы увидите 2 столбика значений, что и в консоли Arduino. Теперь вы можете построить график или рассчитать среднее значение температуры в вашей комнате за какой-то промежуток времени.
ВНИМАНИЕ! Флэш-память имеет ограниченный ресурс записи, поэтому для увеличения срока жизни флэшки, оптимизируйте количество записей в память. Например, в нашем случае, сделайте массив и таймер. Массив будет хранить, допустим, 10 значений и затем записывать их на флэш, либо когда будет накоплено 10 значений, либо когда таймер отсчитает 1 минуту.Таким образом количество записей во флэш будет уменьшено до 10 раз.
На этом всё, задавайте свои вопросы мне в комментариях к этому посту, до скорых встреч!
		
Подскажите пожалуйста интернет магазин где можно купить плату расширения на SD.
Сам контроллер нашел. А вот платку никак не могу найти, ну или как она точно называется…
Ответ для Сергей: Что значит плату расширения на SD? SD модуль для работы с картами? Я покупал на eBay: http://www.ebay.com/itm/140717254516
Хорошая статья! Спасибо Илья! Как для меня, начинающего, ( Купил год назад Мегу 1280) хороший пример для изучения — как записать в файл данные с Ардуино и потом открыть в Екселе.. А не могли бы Вы показать, как можно прямо в Екселе считывать данные с Ардуины? Или хотя бы на компьютер записать (сохранить) этот файл?
Ответ для Юрий: Мне очень приятно, что статья оказалась полезной для Вас. 🙂
спасибо, оказалось полезно. Правда заработало только после добавления библиотеки #include
Ответ для Дмитрий: не за что!
Добрый день!
Интересует такой момент: как организовать поиск внутри файла на cd карте?
Добрый день! Конкретно сказать не могу, но надо считать файл в оперативную память (массив) и искать в нём перебором.
а как правильно закрывать показания? То есть, просто выдергивать карту из ридера и смотреть файл? Иногда бывает, что в это время как раз шла запись в файл и он оказывается битым…
По хорошему надо в программе предусмотреть возможность остановки, например, по нажатию кнопки. Выдёргивать просто так — точно не вариант. после myFile.close(); файл будет закрыт и можно извлечь, если конечно не начался новый цикл и файл не открыли для записи снова
Приходится каждую секунду открывать файл-записать-закрыть файл. нельзя ли в функции loop только писать данные,а открытие и закрытие вынести за пределы?
А сколько каналов (входов) одновременно можно регистрировать (записывать) на SD. И не затруднит ли вас скейч на несколько вхадов показать???
Для записи на карту нет понятия каналов. Вы записываете данные. Каждое значение датчика — это, по сути, переменная. Вы можете записывать неограниченное число переменных. В моем скетче вы можете видеть, как я записываю время (переменная time), затем ставлю символ точки с запятой и затем записываю данные температуры (переменная temp). Просто добавьте ещё переменных через разделитель (точка с запятой).
Почему не получена библиотека SPI?
Упустил. Спасибо за замечание! Я даже удивлён, что за столько времени с момента публикации статьи, никто не упомянул об этом 😀