Пакет плат стоит, драйвер CP2102 встал без бубна, плата втыкается в макетку — и наступает странный момент: вроде всё готово, а нажать нечего. Первый скетч на новой плате — не столько программирование, сколько проверка, что среда, кабель и железо договорились между собой. На Uno я его давно промотал, а на ESP32 прогоняю после каждого обновления пакета плат: две минуты, и сразу видно — компилятор, загрузчик, порт и монитор живы. Правило простое: если первый скетч прошёл, любой отказ дальше — вопрос схемы или кода, а не среды; половина «сломанных плат», с которыми люди бегут на форумы, отсеивается уже на этом шаге.
Мигать будем встроенным светодиодом на GPIO 2: припаивать ничего не надо, результат виден с другого конца стола. Если вы пришли с Uno, ваша первая мигалка уже случилась в уроке про светодиод и pinMode — скетч здесь тот же по духу, отличия в деталях, и они показательные. Самое показательное различие вы заметите уже на загрузке — о нём отдельно ниже.
Скетч: GPIO 2 и встроенный светодиод
// Первая проверка платы: мигаем встроенным светодиодом на GPIO 2const int LED = 2; // светодиод DevKit сидит на GPIO 2 void setup() { Serial.begin(115200); // монитор порта ставьте на 115200 бод pinMode(LED, OUTPUT); Serial.println("Plata zhiva, nachinaem");} void loop() { digitalWrite(LED, HIGH); // HIGH — светим delay(500); digitalWrite(LED, LOW); // LOW — гасим delay(500);}Схема знакомая до звона: pinMode в setup, digitalWrite в loop. Меняются детали. Светодиод на DevKit сидит на GPIO 2, а не на 13, и зажигается высоким уровнем: HIGH — светит, LOW — гаснет. Serial.begin(115200) — почти все скетчи ESP32 шлют отладку на этой скорости; поставьте столько же в мониторе порта, иначе вместо строки «Plata zhiva» увидите кракозябры. Скорость одна на всю платформу: и загрузчик, и примеры, и ваши отладочные принты.
Сама загрузка тоже отличается. После нажатия «Загрузка» IDE сначала компилирует заметно дольше, чем на Uno: пакет плат тяжёлый, на среднем ноутбуке сборка идёт 30–90 секунд — это норма, второй раз кнопку не жмите. Дальше в консоли побежит esptool и строки вида Connecting........_____: подчёркивания — моменты, когда мост дёргает линиями и пытается ввести чип в режим прошивки. Как ставить скетч на плату по шагам и что означает каждая строка консоли, мы разбирали в уроке про первую загрузку; здесь логика та же, меняется только чип.
Что вы увидите, когда всё пошло хорошо: строки Writing at 0x00010000... (25%) и так до сотни процентов — esptool пишет ваш скетч во flash по кускам; затем Hard resetting via RTS pin — плата перезапускается сама, и через секунду в мониторе появляется строка из setup(). При самом первом старте в логе мелькают служебные строки загрузчика со словом boot: — это норма, их печатает чип до вашего кода. По времени всё укладывается в минуту-полторы вместе с компиляцией, и большая часть этого времени — сборка, а не передача. Если запись оборвалась на середине с ошибкой — не выдёргивайте кабель, просто повторите загрузку: flash переживает это спокойно.
Отличия от Uno, которые почувствуете руками
Первая неделя с ESP32 складывается из мелочей. Компиляция: 30–90 секунд против десятка у Uno при каждом изменении скетча — закладывайте это в ритм работы. Скорость монитора: 115200 вместо 9600, я однажды полчаса читал кракозябры и подозревал сгоревший UART, пока не глянул на селектор. Скорость выбрана не с потолка: загрузчик сам печатает отладку на 115200, и примеры плат держат ту же. Напряжение: захотели вывести мигалку наружу — светодиод через резистор 220 Ом на GPIO, но ни один пин не простит 5 В, логика тут 3.3-вольтовая.
GPIO 2 двуликий: светодиод на нём — это удобно, но линия участвует в страппинге при прошивке, как мы подробно разбирали в уроке про карту выводов DevKit. Посадите на неё схему, которая сильно тянет к земле в момент старта, — и очередная загрузка пойдёт через кнопку BOOT. Для опытов на макетке не страшно, в постоянных схемах я выношу мигалку на другой пин — на Uno такой вопрос не вставал вовсе, там светодиод ни на что кроме вывода не влияет.
А вот millis(), delay(), if и массивы работают ровно так же — платформа Arduino на ESP32 честно притворяется знакомой. Loop-функция крутится на ядре 1, WiFi-стек занимает ядро 0; пока вы не полезли в многопоточность, думать об этом не нужно. Исчезает и проблема SoftwareSerial: у ESP32 три аппаратных UART, и связка с GPS-модулем или второй платой обходится без эмуляции порта.
| Привычка с Uno | Как на ESP32 |
|---|---|
| Монитор порта на 9600 бод | 115200 бод — иначе кракозябры |
| Светодиод L на пине 13 | Светодиод на GPIO 2, активен высоким уровнем |
| Компиляция около 10 секунд | 30–90 секунд: пакет плат тяжёлый |
| Логика 5 В | Логика 3.3 В, 5 В на пины подавать нельзя |
| Один мозг на всё | Ядро 0 — WiFi, ядро 1 — ваш скетч |
Захотелось вывести мигалку с платы на макетку — берите любой GPIO из безопасного набора, резистор 220 Ом и обычный индикаторный светодиод: анод через резистор к пину, катод к GND. Как собрать это без пайки, показано в уроке про светодиод на макетке. Резистор ставится именно последовательно: без него ток ограничен только внутренним сопротивлением кристалла — пин просаживает линию, а кристалл деградирует за часы. При 3.3 В и 220 Ом через индикатор идёт около 7–10 мА: для пина безопасно, для глаз достаточно; для длинных проводов или ярких панелей я беру 330 Ом, чтобы погасить наводки. А вот мотор или реле так подключать нельзя — им нужен транзистор, и не забывайте соединять GND схемы с GND платы, иначе светодиод будет жить своей жизнью. Сам скетч при этом не меняется: помигаете и встроенным, и внешним индикатором одной прошивкой — заменится только константа LED.
Посмотрите на пары в логе: led=1 t=500, led=0 t=1000 и дальше — период держится без всяких пауз, потому что разность millis() - prev срабатывает сама. Шаблон разобран до винтика в уроке про millis вместо delay, и на ESP32 он работает с тем же unsigned long и тем же переполнением через 49,7 суток. Поменяйте 500 на 100 и убедитесь, что период отвечает моментально, — это лучшая демонстрация неблокирующего кода: на millis() паузы держатся ровно, тогда как при загруженном loop с delay() они плывут. Разница видна и в Serial: строки печатаются ровно, без рваных пауз.
И три эксперимента на закрепление: помигайте двумя светодиодами с разными периодами через два набора prev и interval — это ровно упражнение из урока про millis; выведите в Serial счётчик вспышек раз в десять секунд; пересадите мигалку на пин 33 из безопасного набора и убедитесь, что на загрузку она больше не влияет.
Платформа проверена, светодиод мигает — время дать плате настоящую работу. В следующем уроке подключаем её к домашней сети и впервые печатаем IP-адрес, полученный по воздуху: с него начинаются все WiFi-проекты, а светодиод на GPIO 2 станет индикатором подключения — зажжётся, когда придёт WL_CONNECTED. Если среда ещё не собрана, вернитесь к материалу про первый запуск и подключение к WiFi — там пакет плат, порты и драйверы по шагам.
- 1. Скетч загружен, а монитор порта показывает кракозябры. Первое действие?
- 2. На каком пине сидит встроенный светодиод платы DevKit V1?
- 3. Загрузка висит на строке Connecting........_____. Что делать?
- 4. Чем мигалка на millis() лучше delay(500) в loop()?
- 5. Какое напряжение нельзя подавать на GPIO ESP32?
- Первый скетч — проверка всей цепочки: компиляция, порт, загрузка, монитор на 115200 бод
- Светодиод DevKit — GPIO 2, HIGH светит; линия участвует в страппинге, лишних схем на неё не вешаем
- Connecting........_____ — зажать BOOT до строки Writing at 0x..., отпустить
- Компиляция 30–90 секунд — норма для пакета ESP32, кнопку дважды не жмём
- Мигалка на millis(): if (millis() - prev >= 500) — loop остаётся свободным для датчиков и Serial
Частые вопросы по теме урока
- Скетч загружен, а монитор порта показывает кракозябры. Первое действие?
- Кракозябры почти всегда означают несовпадение скоростей: ESP32 шлёт отладку на 115200 бод, монитор по умолчанию стоит на 9600. Селектор скорости живёт в правом нижнем углу монитора порта. Поставить скорость порта 115200 бод
- На каком пине сидит встроенный светодиод платы DevKit V1?
- На DevKit V1 светодиод подключен к GPIO 2 и зажигается высоким уровнем: digitalWrite(2, HIGH) — светит. GPIO 2
- Загрузка висит на строке Connecting........_____. Что делать?
- Автовход в режим прошивки не сработал. Кнопка BOOT прижимает GPIO 0 к земле — чип дожидается загрузчика и запись начинается. Строка Writing в консоли — сигнал, что дело сдвинулось. Зажать кнопку BOOT и держать до строки Writing at 0x...
- Чем мигалка на millis() лучше delay(500) в loop()?
- delay() останавливает весь цикл на полсекунды, а проверка millis() занимает микросекунды: датчики, кнопки и Serial между вспышками опрашиваются без пауз. Поэтому мигалка и опрос кнопки живут в одном loop, не мешая друг другу. loop() не блокируется: между переключениями крутится остальной код
- Какое напряжение нельзя подавать на GPIO ESP32?
- Логика ESP32 — 3.3 В, пины не толерантны к 5 В. Для связи с 5-вольтовой техникой нужен делитель или конвертер уровней. 5 В