Новая карта с маркетплейса пришла в понедельник, а в среду логгер отказался стартовать: SD.begin(CS) честно возвращал false, монитор печатал мою строчку про карту и вставал в вечный цикл. Хуже всего было то, что карта была рабочая: в кардридере ноутбука открывалась, файлы показывала, объём показывала. Виноват ли модуль, скетч или провода — было непонятно, и вечер я потратил на перебор всего сразу, вместо того чтобы идти по списку. Смена карты, смена модуля, другой шнур — всё по кругу, и к ночи я уже подозревал плату в фальсификации.
Список появился потом, и с тех пор молчащий begin перестал быть поводом для паники: файловая система, питание, шина с CS, честность карты — четыре проверки, из которых три делаются без паяльника. Девять из десяти случаев лежат в первых двух пунктах, и именно туда я теперь иду в первую очередь. Четвёртый пункт — про деньги: клоны дороже всех обходятся постфактум, когда журнал за месяц оказывается дырявым.
Общие приёмы уже выкладывались в уроке про чек-лист и в уроке про первый запуск; здесь — то, что вскрылось позже и больнее: карты в exFAT, клоны с приписанным объёмом, занятый CS и тайминги SPI, на которых карта работает в ридере и молчит в Arduino. Все четыре истории — с числами и проверками, которые умещаются на одном листе, и порядок здесь не эстетика: каждый следующий пункт требует инструментов и времени, а первые два — вообще ничего.
Файловая система и питание: первые две проверки
Файловая система. Библиотека SD читает только FAT16 и FAT32; exFAT она не понимает — ни в begin, ни потом. Карты на 64 ГБ и больше продаются отформатированными в exFAT, потому что FAT32 для таких объёмов в Windows просто не предлагается. Симптом одинаково тупой: begin возвращает false без всяких пояснений. Лечение — переформатировать карту в FAT32, причём для 64 ГБ штатной кнопки в Windows нет, нужна утилита, умеющая большие тома. Перед форматированием вытащите с карты всё нужное: переформатирование стирает том целиком, журналов это тоже касается. Какие тома вообще берёт библиотека и почему — в уроке про форматирование и пределы. Кстати, карта на 32 ГБ с завода обычно FAT32 — с ней таких приключений не бывает.
Питание — вторая проверка, и тут у модулей два лагеря. Модуль с AMS1117 на борту хочет 5 В на вход и сам выдаёт карте 3,3 В; голая карта без стабилизатора питается строго 3,3 В, и пять вольт для неё приговор. Перепутанный лагерь выглядит по-разному: от честного false до старта на секунду и смерти при первой записи. Оба симптома я видел на одной и той же схеме — в зависимости от того, куда вставлен джампер питания модуля. Мультиметр на держателе карты решает спор за минуту — уровни и зачем нужны делители разобраны в уроке про 3,3 и 5 В. Заодно мультиметром ловится и второй лагерь: модуль без стабилизатора, питаемый резисторным делителем, проседает при пике инициализации.
CardInfo из примеров библиотеки — скетч, с которого я начинаю любую проверку, раньше собственного кода. Он печатает тип карты, тип тома FAT16/FAT32, число кластеров и список файлов; ниже — его причёсанная версия. Листится он из примеров библиотеки: File > Examples > SD > CardInfo — к этому скетчу я возвращаюсь чаще всех остальных. Если CardInfo молчит, ваш логгер ни при чём: идите в питание и шину. Если пишет про неопознанный том — вы уже знаете про exFAT. Единственный минус примера — он молчит о питании: CardInfo предполагает, что электрическая часть уже собрана правильно.
CS, клоны и тайминги SPI
CS-пин — любимая грабля сборок с шилдами. На Ethernet-шилде W5100 сидит на D10, а SD этого же шилда — на D4: передавать в SD.begin десятый вывод бессмысленно, карте нужен её собственный выбор. Проверяется переводом begin на D4 — молчание уходит, и вопрос закрыт. На общей SPI-шине каждый чип обязан видеть свой CS в OUTPUT, иначе молчащий чип поднимается в Hi-Z и портит шину для остальных — механика дележа разобрана в уроке про CS и общую шину. Голый CS, висящий в воздухе, ловит помехи и включает чип в случайные моменты — выглядит как помехи, лечится подтяжкой.
Клоны — отдельный жанр. Карта с наклейкой «2 ТБ» за две сотни рублей внутри — перепрошитые 8 ГБ: контроллер показывает чужой объём, а физические ячейки кончаются раньше. Классический симптом: сначала всё работает, потом файлы после заполнения фантомного объёма теряются или читаются кусками. Причём первые гигабайты у клона обычно живые: беда приходит к концу адресного пространства. Проверка одна и честная — fill-тест: пишем файл до отказа и сверяем, сколько записалось на самом деле — тест запускается прямо в кардридере утилитой или скетчем-наполнителем. Пределы честных объёмов и историю форматов собирал в уроке про 4 ГБ и пределы. Цена вопроса смешная: честные 8-16 ГБ стоят на порядок меньше, чем вечер поиска потерянного журнала.
Тайминги SPI — причина, по которой карта в кардридере работает, а в Arduino нет: ридер питает карту ровно и гонит интерфейс на паспортной скорости, а дешёвый модуль даёт SPI 8 МГц через резисторные делители с заваленными фронтами. Начинайте с card.init(SPI_HALF_SPEED, CS) — половина молчащих карт поднимается на полускорости, а провода короче десяти сантиметров лечат большинство остальных. Полускорость на логгере ничего не стоит: журналу хватает и её с большим запасом. Если не помогло и это — меняйте модуль на вариант с микросхемой-конвертером уровней; основы шины при необходимости в уроке про SPI. Ещё один признак тайминговой беды: карта поднимается через раз, от перезапуска к перезапуску, — это чистая электрика, а не файлы.
#include <SPI.h>#include <SD.h> const int CS_PIN = 10; Sd2Card card;SdVolume volume;SdFile root; void setup() { Serial.begin(9600); Serial.println("CardInfo: диагностика карты"); if (!card.init(SPI_HALF_SPEED, CS_PIN)) { // HALF_SPEED для кривых сборок Serial.println("card.init: карта не отвечает"); Serial.println("проверь питание модуля и провода SPI"); while (true) delay(500); } Serial.print("карта отвечает, тип: "); switch (card.type()) { case SD_CARD_TYPE_SD1: Serial.println("SD1 (старые, до 1 ГБ)"); break; case SD_CARD_TYPE_SD2: Serial.println("SD2 (SDSC, 1-2 ГБ)"); break; case SD_CARD_TYPE_SDHC: Serial.println("SDHC (4-32 ГБ)"); break; default: Serial.println("неизвестный тип - подозрение на клон"); } if (!volume.init(card)) { Serial.println("том не распознан: файловая система не FAT16/FAT32"); Serial.println("exFAT библиотека не читает - переформатируй карту"); while (true) delay(500); } Serial.print("кластеров: "); Serial.print(volume.clusterCount()); Serial.print(", по "); Serial.print(volume.blocksPerCluster() * 512UL / 1024UL); Serial.println(" КБ"); Serial.print("том: "); Serial.println(volume.fatType() == 16 ? "FAT16" : "FAT32"); if (root.openRoot(volume)) { root.ls(LS_R | LS_DATE | LS_SIZE); } else { Serial.println("корень не открылся"); }} void loop() { delay(1000);}В меню каждый пункт печатает то, что на сборке показал бы конкретный инструмент: CardInfo, мультиметр или fill-тест. Прогоните всё кнопкой, потом позовите отдельные пункты числами — на реальной диагностике я иду ровно в этом порядке, от дешёвых проверок к дорогим: файловая система без паяльника, питание мультиметром, шина переездом на полускорость, честность носителя файлом до отказа. На моей практике четыре пункта закрывают девять случаев из десяти, а оставшийся — почти всегда модуль, а не карта.
Отдельная ценность меню в том, что каждый пункт говорит «похоже на» и называет лечение: том не распознан — переформатируйте; CS занят — смените пин; кластеров меньше, чем на наклейке, — клон. Каждая фраза — готовый вывод, а не приглашение к размышлению. В Serial-варианте удобно гонять этот список на новой карте ещё до сборки: одна минута в мониторе против сборки-разборки макетки потом. Заодно список работает как инструкция для коллег: человек без опыта читает пункт и делает то, что написано, без звонка вам.
| Симптом | Вероятная причина | Чем проверять |
|---|---|---|
| begin false, в ридере работает | exFAT на карте или тайминги SPI | CardInfo: тип тома; HALF_SPEED и провода короче 10 см |
| begin false, модуль тёплый на пальцах | 5 В на голую карту | мультиметр на выводах карты: там должно быть 3,3 В |
| пишет, потом файлы теряются | клон с маркетплейса | fill-тест: файл до отказа и сверка записанного объёма |
| молчит только с шилдом | CS занят соседним чипом | SD на D4, все CS на шине держатся в OUTPUT |
Порядок проверок — половина успеха: файловая система, питание, шина с CS, честность носителя. Наоборот — путь к вечеру с паяльником и осадком: я когда-то начинал с перепайки проводов там, где карте мешал exFAT. Если же все четыре пункта прошли, а begin молчит — остаются сам модуль и ваш скетч, и CardInfo как раз отделил одно от другого: модуль меняется за пять минут, скетч проверяется на эталонной карте, и цепочка подозреваемых на этом заканчивается.
Мнение на прощание: половина карт, которые «не работают с Arduino», — это карты в exFAT и клоны, и обе беды ловятся до пайки, в кардридере и мониторе. Держите эталонную карту, прогоняйте новую через два теста — и слово «SD молчит» перестанет значить вечер с монтажкой: оно будет значить один пункт из четырёх, а не туман.
- 1. Карта на 64 ГБ не поднимается в SD.begin. Первая гипотеза?
- 2. Карта с наклейкой «2 ТБ» с маркетплейса. Что внутри на самом деле?
- 3. CardInfo молчит на card.init. С чего начать?
- 4. На Ethernet-шилде SD.begin с CS=10 падает. Почему?
- 5. Модуль SD со стабилизатором AMS1117: куда подавать питание?
- Библиотека SD читает только FAT16/FAT32: карта 64+ ГБ с завода в exFAT не поднимется — переформатировать.
- CardInfo из примеров — первый скетч: тип карты, тип тома, кластеры; он отделяет карту от вашего кода.
- Клоны врут в объёме: «2 ТБ» могут оказаться 8 ГБ; fill-тест файлом до отказа вскрывает это за минуты.
- Питание: модуль со стабилизатором — 5 В на вход и 3,3 В на карте; голая карта питается строго 3,3 В.
- CS-пины делят шину: на Ethernet-шилде SD живёт на D4, а все CS держатся в OUTPUT.
Частые вопросы по теме урока
- Карта на 64 ГБ не поднимается в SD.begin. Первая гипотеза?
- Карты 64+ ГБ с завода в exFAT, а библиотека SD читает только FAT16/FAT32. Лечение — переформатирование в FAT32 утилитой, умеющей большие тома. Карта в exFAT: библиотеке нужны FAT16/FAT32
- Карта с наклейкой «2 ТБ» с маркетплейса. Что внутри на самом деле?
- Клоны показывают чужой объём, а физические ячейки кончаются раньше. Проверка честная: пишем файл до отказа и сверяем, сколько записалось. Перепрошитые 8 ГБ — вскрывается fill-тестом
- CardInfo молчит на card.init. С чего начать?
- Половина молчащих карт поднимается на полускорости, а короткие провода лечат большинство остальных. Дальше — питание модуля и другой модуль с конвертером уровней. SPI_HALF_SPEED и провода короче 10 см
- На Ethernet-шилде SD.begin с CS=10 падает. Почему?
- На Ethernet-шилде W5100 занимает D10, а SD живёт на D4. И все CS на общей шине держатся в OUTPUT, чтобы молчащие чипы не портили шину из Hi-Z. W5100 сидит на D10 — SD нужен свой CS, обычно D4
- Модуль SD со стабилизатором AMS1117: куда подавать питание?
- Модуль с AMS1117 ждёт 5 В на входе и сам понижает до 3,3 В для карты. Голая карта без стабилизатора питается строго 3,3 В — пять вольт её убивают. 5 В на вход модуля — стабилизатор даст карте 3,3 В