Мою первую загрузку закончила красная строка внизу окна: «avrdude: stk500_recv(): programmer is not responding». Я перечитал её раз десять, погуглил целиком, нашёл сорок тем на форумах и ни в одной не нашёл себя. Плата была подключена, порт выбран, «Проверить» проходило на ура — а стрелка «Загрузить» упиралась в эту фразу снова и снова. Причиной оказался пункт меню, о котором я в тот вечер не знал, но обо всём по порядку.
В симуляторе этого сценария нет: виртуальная плата грузится всегда и мгновенно. Это удобно для тренировки кода, но настоящий ритуал — компиляция, заливка, чтение ошибок — отрабатывается только на реальной связке «среда + плата». Здесь я разберу ритуал по шагам: что делает каждая кнопка, зачем плате reset при загрузке и как по одному сообщению об ошибке понять, что именно чинить. Даже «не та плата» в меню «Инструменты» — полноценный кандидат в причины, у него будет отдельный абзац ниже.
«Проверить» и «Загрузить»: что делает каждая кнопка
Кнопка с галочкой — «Проверить» — запускает только компиляцию. Компилятор avr-gcc переводит ваш текст в машинный код для чипа ATmega328P, результат складывается во временную папку (глубоко в AppData, искать не обязательно), и на этом всё: в плату не уходит ни байт. Быстрая операция, её смысл — поймать синтаксические ошибки до того, как вы полезли кабелем.
Кнопка со стрелкой — «Загрузить» — делает то же самое плюс вторую фазу: утилита avrdude берёт собранный файл и заливает его в память чипа. Механика достойна уважения: среда дёргает сигнальную линию USB, плата делает reset и перезапускается в загрузчик — маленькую программу, живущую в конце Flash-памяти. Optiboot на Uno первые секунды после reset слушает порт на скорости 115200 бод: нет команды — передаёт управление вашему скетчу, есть — принимает новые байты и записывает поверх старой прошивки. Поэтому во время загрузки мигают TX и RX, а светодиод L делает короткую вспышку: плата перезапустилась в загрузчик.
Отсюда практический вывод: если после неудачной заливки скетч на плате уже крутится, повторная загрузка всё равно сработает — среда сама передёрнет reset. Исключение — платы-клоны с капризным авто-reset: про них и про кнопку Reset ниже.
И важная деталь: «Проверить» не требует платы вообще. Если железо ещё едет с маркетплейса, весь синтаксис отрабатывается на галочке; а симулятор ниже подхватывает вторую половину — поведение программы. Связка «галочка + симулятор» закрывает первые недели тренировок почти без настоящего железа, потом переносите накопленный код на плату одной загрузкой.
Рабочая лошадка этого урока — скетч из симулятора ниже: он мигает светодиодом и печатает такты в Serial. Залейте его на настоящую плату и сверяйте поведение с монитором порта — так вы увидите обе фазы загрузки своими глазами.
Красный текст внизу: учимся читать ошибки компиляции
Первое правило, сэкономившее мне десятки часов: читать первую ошибку, а не последнюю. Окно вывода — это лог: после настоящей ошибки компилятор вываливает пачку сопутствующих сообщений, а в самом низу часто сидит бессмысленное «collect2.exe returned 1». Новичок смотрит на последнюю строку, не понимает её и идёт гуглить мусор. Свиток вверх до первой строки со словом error — там настоящая причина. В 2.x этот лог живёт на вкладке «Вывод» внизу окна и успех подсвечивается зелёным; в 1.8.x — обычной консолью в нижней части окна. Разница только в упаковке: суть — тот же лог, и правила чтения одни.
Три ошибки закрывают процентов восемьдесят первых вечеров. Первая: «expected ';' before '}' token» — забыта точка с запятой. Хитрость в том, что компилятор укажет строкой ниже настоящего места: сам пропущенный знак он обнаруживает, когда начинается следующая инструкция. Увидели ошибку на строке 42 — проверяйте конец строки 41.
Вторая: «'Digitalwrite' was not declared in this scope». В C++ регистр букв значим: digitalWrite существует, Digitalwrite — нет. Сообщение «was not declared» почти всегда значит «опечатка в имени»: проверьте регистр и правописание функции или переменной.
Третья: «No such file or directory» рядом со строкой #include — среда не нашла библиотеку. Это мостик к следующему уроку: библиотека либо не установлена, либо установлена не та версия.
Мой личный тупик из первого месяца: я целый час правил «пятую ошибку из списка», потому что она выглядела страшнее всех. Первая же, скучная, была пропущенной запятой в объявлении переменной — и пятая исчезла сама. Лечение симптома — всегда один ход: наверх лога, к первой ошибке, одна правка, снова «Проверить».
«Не удаётся подключиться к плате»: разбор по симптомам
Если в ошибке фигурирует avrdude, компиляция прошла — проблема случилась на этапе связи с платой. Сообщения разные, и по формулировке можно поставить диагноз почти наверняка.
«avrdude: ser_open(): can't open device COM3: Отказано в доступе» — порт занят кем-то другим: открытым Serial-монитором, второй копией IDE, слайсером или любой утилитой, которая умеет в COM-порты. Лечение: закрыть монитор (в 1.8.x среда не умеет освобождать порт сама, в 2.x обычно справляется) и повторить загрузку.
«avrdude: stk500_recv(): programmer is not responding» или «not in sync: resp=0x00» — плата не отвечает загрузчику. Причины по частоте: выбран не тот порт; выбрана не та плата; зарядный кабель; и классика жанра — Nano со старым загрузчиком. У китайских Nano 2000-х годов рождения загрузчик общается на скорости 57600, у новых — 115200: если выбрать в «Инструменты → Процессор» пункт «ATmega328P» вместо «ATmega328P (Old Bootloader)», получите ровно эту ошибку. Смена пункта меню лечит за десять секунд.
К слову о «не той плате»: avrdude сверяет сигнатуру чипа перед заливкой. Выберете Mega вместо Uno — увидите «expected signature for ATmega2560 is 1E 98 02» — честная защита от записи прошивки не в тот чип. Так что странная на вид строчка с hex-кодом — это паспорт железа, а не сбой.
Сюда же — та самая кнопка Reset. Загрузчик живёт первые секунды после перезапуска платы. Если скетч на плате упорно мешает заливке (например, спамит в Serial или перезапускается по кругу), вручную нажмите Reset на плате, а затем сразу — «Загрузить»: плата войдёт в загрузчик заново и будет ждать прошивку. На Uno авто-reset работает сам, на капризных клонах кнопка — легальный обходной путь, о котором стоит знать заранее.
Порядок диагностики я держу такой: порт → плата и процессор → кабель → закрыть монитор → ручной Reset. По этой лесенке доходит почти любая «не удаётся подключиться к плате».
- Разнесите такты: поставьте delay(100) и delay(900) в один цикл. Светодиод будет мигать «коротко-длинно», а Serial покажет асимметрию — так проще заметить, что вывод и реальность совпадают. Общий период при этом остаётся 1000 мс, меняется только скважность внутри цикла.
- Добавьте счётчик тактов: заведите
int n = 0;над setup(), в loop() увеличивайте на единицу и печатайте номер такта. После «перезагрузки» счётчик начнётся с нуля — как и на настоящей плате после заливки. - В настоящей IDE уберите точку с запятой после
digitalWrite(led, HIGH)и нажмите «Проверить». Прочитайте ПЕРВУЮ строку с error и найдите виновную строку выше. Верните знак — рефлекс «первая ошибка → строка выше» должен закрепиться. - Выберите в «Инструменты → Плата» не ту плату и попробуйте загрузить на настоящем железе: получите ошибку несовпадения. Теперь вы знаете, что «не в синхронизации» бывает и от неверного выбора платы.
- «Проверить» = только компиляция; «Загрузить» = компиляция + заливка через avrdude и загрузчик
- После reset загрузчик слушает порт несколько секунд на 115200 бод (Optiboot на Uno); авто-reset срабатывает по сигналу с USB
- Читать первую ошибку в логе, а не последнюю; настоящая строка обычно на одну выше указанной
- «Отказано в доступе» = порт занят: закройте Serial-монитор и другие программы
- Nano со старым загрузчиком: «Инструменты → Процессор → ATmega328P (Old Bootloader)»
- Кнопка Reset — легальный способ вернуть плату в загрузчик, когда авто-reset капризничает
- Первые компиляции после установки идут дольше — ядро собирается целиком; это норма, а не поломка
- 1. Что именно делает кнопка «Проверить»?
- 2. Компилятор указывает на строку 42. Где чаще всего настоящая ошибка?
- 3. avrdude пишет «not in sync: resp=0x00» на китайской Nano. Что проверить первым?
- 4. Почему после неудачной заливки помогает нажать Reset и сразу начать загрузку?
Ритуал сложился: «Проверить» — ловим синтаксис, «Загрузить» — смотрим на TX/RX, читаем Serial. Ошибки больше не красная тряпка: у каждой формулировки есть свой диагноз и своё лечение, а порядок диагностики — короткая лесенка, а не блуждание. Остался последний инструмент первых дней — библиотеки. Именно из-за них «скетч с форума не собирается» даже у тех, кто уже освоил загрузку: менеджер библиотек, ZIP-архивы и версии поджидают в следующем уроке.
Частые вопросы по теме урока
- Что именно делает кнопка «Проверить»?
- «Проверить» запускает только компиляцию: avr-gcc превращает код в машинный, но в плату не уходит ни байт. Запись делает «Загрузить». Компилирует скетч, ничего не записывая в плату
- Компилятор указывает на строку 42. Где чаще всего настоящая ошибка?
- Компилятор замечает проблему, когда начинается следующая инструкция, поэтому указанная строка отстаёт от истинного места примерно на одну строку вверх. Обычно строкой выше — например, забытая точка с запятой
- avrdude пишет «not in sync: resp=0x00» на китайской Nano. Что проверить первым?
- Старый загрузчик Nano общается на 57600 бод, новый — на 115200. Неверный выбор пункта «Процессор» даёт ровно эту ошибку; смена пункта лечит за секунды. Пункт «Инструменты → Процессор: ATmega328P (Old Bootloader)»
- Почему после неудачной заливки помогает нажать Reset и сразу начать загрузку?
- Загрузчик живёт в первые секунды после перезапуска платы. Ручной Reset запускает его заново, и у вас есть окно, когда порт слушает загрузчик, а не ваш скетч. Плата заново входит в загрузчик и ждёт прошивку несколько секунд