Wi-Fi · разбор

Wi-Fi для Arduino: как подключить плату к сети

«Хочу, чтобы плата выходила в интернет» — самая частая просьба после первого мигающего светодиода. Разбираем, какой дорогой идти, почему плата не видит вашу сеть, сколько ей нужно тока и что она сможет делать дальше. Схемы на странице живые: их можно щёлкать. Все числа — из даташитов, исходников ядер и карточек наших плат.

Короткий ответ для нетерпеливых. У обычной Arduino Uno Wi-Fi нет и не появится: чипа радио на ней просто не установлено. Дешевле и проще всего не добавлять модуль к Uno, а взять отдельную плату, у которой радио уже внутри — например D1 mini за 290 ₽. Среда та же, скетч тот же, библиотеку ставить не нужно. Дальше по странице — почему так, и что делать, если менять плату нельзя.

Почему «модуль Wi-Fi» — это не то же самое, что модуль Bluetooth

С Bluetooth-модулем всё просто: он работает как удлинитель для двух проводов. Что плата отправила — то на телефоне появилось. Никакой библиотеки, никаких настроек. Люди по привычке ждут того же и от Wi-Fi, а получают совсем другое.

Wi-Fi — это не труба для байтов, а целая почтовая система. Чтобы отправить одно число, устройству нужно найти сеть, доказать роутеру, что оно знает пароль, получить адрес, узнать адрес получателя, собрать пакет, дождаться подтверждения и переслать заново то, что потерялось. Всё это — работа для отдельного процессора с собственной памятью.

Поэтому «модуль Wi-Fi» — это не деталь, а второй компьютер, который сильнее вашей Arduino. У модуля ESP-01, который чаще всего покупают к Uno, внутри чип ESP8266: он быстрее ATmega328 примерно в пять раз и памяти у него в двадцать раз больше. Возить такого пассажира и командовать им из Uno текстовыми командами — занятие неблагодарное. Гораздо честнее пересесть на него самого.

Отсюда главный вывод страницы, который экономит и деньги, и вечер: в большинстве случаев Wi-Fi к Arduino не добавляют, а меняют плату на такую, где он уже есть. Плата с радио внутри стоит дешевле, чем модуль плюс питание к нему, программируется в той же среде и тем же кодом.

Куда идти: зависит от того, что уже лежит на столеArduino Unoрадио внутри нетВозьмите отдельную плату с Wi-FiУправлять платой с телефона в своей же сетиD1 mini стоит дешевле проводов к нему и делает всё сама:и сеть, и скетч. Uno при этом останется свободной длядругого проекта.Почему: Через модуль ESP-01 та же задача решается втроедольше: Uno придётся диктовать модулю текстовые команды,а на это уходит почти вся её оперативная память.
Схема живая: слева — что у вас уже есть, справа — что нужно получить. Ответ меняется, и чаще всего он не тот, который подсказывает интуиция «куплю модуль к своей плате».

Четыре дороги и их честная цена

Дорог на самом деле четыре, и выбирать между ними стоит один раз — до покупки, а не после третьего вечера с паяльником.

ПутьЧто покупаетеЧто умеетПорядок ценыКому подходит
Плата, у которой Wi-Fi внутриОдна плата: D1 mini на чипе ESP8266 или плата на ESP32Всё сама: и сеть, и программа. Библиотека уже в ядре платыот 290 ₽Почти всем. Это самый короткий и самый дешёвый путь
Плата на ESP32 в корпусе Arduino UnoПлата того же размера и с той же гребёнкой, но с радио внутриТо же самое, плюс на неё садятся привычные шилды770 ₽Тем, у кого проект уже собран на шилдах и в корпусе
Отдельный модуль к Arduino UnoМодуль ESP-01, отдельное питание 3,3 В и делитель на линию приёмаТолько через текстовые AT-команды: Uno диктует, модуль отвечаету нас не продаётсяТем, кому нельзя менять основную плату. Это трудный путь
Провод вместо радиоEthernet-шилд или модуль W5500 плюс патч-кордТу же сеть, но без пароля, без помех и без переподключенийот 640 ₽Стационарным поделкам, которые должны работать годами

Про установку самих плат в среду тут не пишем, чтобы не пересказывать соседние страницы: как поставить поддержку ESP8266 и что означают надписи D1, D2, D4 на её выводах — на странице ESP8266, NodeMCU и Wemos D1 mini, а про ESP32 и её распиновку — здесь. Пакеты плат наша среда берёт с собственного зеркала, поэтому установка не упирается в закрытые сайты.

Что должно быть с вашей сетью, чтобы плата её увидела

Половина вопросов «плата не подключается» решается не в коде, а в настройках роутера. Причина в том, что радио у платы гораздо проще телефонного, и то, что телефон проглатывает не глядя, для платы оказывается непреодолимым.

Обычная домашняя сеть 2,4 ГГцРоутер2,4 ГГц5 ГГцПлата на ESPслышит только 2,4Телефонслышит обаРоутер вещает на 2,4 гигагерцах с паролем WPA2. Плата слышит сеть, называет её всписке и подключается по паролю.Что делать: Это тот случай, ради которого всё и затевалось. Ничего делать ненужно.
Шесть причин, по которым «телефон сеть видит, а плата не находит». Первые три встречаются чаще всего и не имеют отношения ни к коду, ни к паролю.

Самая частая история звучит так: «телефон эту сеть видит, а плата — нет». Почти всегда дело в диапазоне. Современный роутер вещает сразу в двух: 2,4 гигагерца и 5 гигагерц. Пятигигагерцевая сеть быстрее, и телефон обычно выбирает её. А радио у ESP8266 и ESP32 работает только на 2,4 — это заложено в самих чипах, и никакой настройкой это не меняется.

Отдельная ловушка — когда обе сети названы одинаково. Роутер считает это удобством: устройство само выберет, где лучше. Плата же видит только двухгигагерцевую половину, и получается, что иногда она подключается, а иногда нет, будто по настроению. Самое разумное — дать сети 2,4 ГГц собственное имя и указывать в скетче именно его.

Что нужно от сетиПочемуЧто сделать
Диапазон 2,4 ГГцРадио платы работает только здесь. Сеть на 5 ГГц она не увидит никогдаВ настройках роутера включите сеть 2,4 ГГц отдельным пунктом
Отдельное имя для 2,4 ГГцЕсли оба диапазона названы одинаково, плата видит только половину сети и подключается через разДайте двухгигагерцевой сети своё имя, например с добавкой -24
Защита WPA2WPA3 умеет только ESP32. В ядре ESP8266 такого способа защиты нет вовсеПоставьте WPA2 или смешанный режим WPA2/WPA3
Имя латиницейРусские буквы в имени сети — источник загадочных отказов: в скетче это байты, а не буквыПереименуйте сеть латиницей или заведите отдельную сеть для поделок
Пароль от 8 знаковКороче восьми знаков пароль WPA2 не бывает: плата такую сеть просто не приметПроверьте пароль в настройках роутера, а не по памяти
Не гостевая сетьВ гостевой сети устройства обычно изолированы друг от друга: плата подключится, но с телефона не откроетсяПосадите плату и телефон в одну и ту же основную сеть
Имя сети видноСкрытую сеть сканер не покажет, и найти опечатку в имени будет нечемНа время настройки включите объявление имени
Без входа через страницуСети в кафе и на работе просят нажать кнопку на странице входа. Плата этого сделать не можетДля поделок нужна обычная домашняя сеть или отдельная точка доступа

Первый скетч: посмотреть, что плата слышит

Прежде чем подключаться, полезно узнать, что плата вообще находит в эфире. Этот скетч печатает список сетей с номером канала и уровнем сигнала. Если вашей сети в списке нет — дальше можно не мучиться с паролем: проблема в диапазоне, в скрытом имени или в расстоянии.

Один и тот же текст работает и на ESP8266, и на ESP32: строчка #if defined(ESP8266) подставляет нужную библиотеку. Ставить её никуда не надо — она приезжает вместе с поддержкой платы.

// Что плата вообще слышит в эфире. Запускать до первого подключения:
// если вашей сети в списке нет - дело не в пароле, а в диапазоне,
// в скрытом имени или в расстоянии.
#if defined(ESP8266)
#include <ESP8266WiFi.h>
#define OPEN_NETWORK ENC_TYPE_NONE
#else
#include <WiFi.h>
#define OPEN_NETWORK WIFI_AUTH_OPEN
#endif

void setup() {
  Serial.begin(115200);
  delay(200);
  Serial.println();
  WiFi.mode(WIFI_STA);   // клиент, но пока никуда не подключаемся
  WiFi.disconnect();
  delay(100);
}

void loop() {
  Serial.println("Ищу сети...");
  int found = WiFi.scanNetworks();

  if (found <= 0) {
    Serial.println("Ни одной сети. Плата слышит только диапазон 2,4 ГГц.");
  } else {
    for (int i = 0; i < found; i++) {
      Serial.print(i + 1);
      Serial.print(". ");
      Serial.print(WiFi.SSID(i));
      Serial.print("  канал ");
      Serial.print(WiFi.channel(i));
      Serial.print("  сигнал ");
      Serial.print(WiFi.RSSI(i));
      Serial.print(" dBm  ");
      if (WiFi.encryptionType(i) == OPEN_NETWORK) {
        Serial.println("без пароля");
      } else {
        Serial.println("с паролем");
      }
    }
  }

  WiFi.scanDelete();     // освобождаем память под список
  delay(10000);
}

Уровень сигнала печатается в дБм и всегда отрицательный: чем ближе к нулю, тем лучше. Примерные ориентиры: до −60 — отлично, до −70 — нормально, дальше −75 начнутся потери пакетов и «плата отваливается».

Подключаемся к сети

Теперь собственно подключение. Обратите внимание на две вещи: ожидание ограничено двадцатью секундами (иначе непонятно, что происходит), а при неудаче печатается код состояния — по нему дальше и ведётся вся диагностика.

// Плата подключается к домашней сети Wi-Fi и печатает свой адрес.
// Один и тот же скетч работает и на ESP8266 (D1 mini, NodeMCU), и на
// ESP32: нужную библиотеку подставляет компилятор.
#if defined(ESP8266)
#include <ESP8266WiFi.h>
#else
#include <WiFi.h>
#endif

// Регистр букв важен: "MyHome" и "myhome" - это разные сети.
// Сеть должна быть в диапазоне 2,4 ГГц: пятигигагерцевую плата не увидит.
const char WIFI_SSID[] = "имя вашей сети";
const char WIFI_PASS[] = "пароль от сети";

void setup() {
  Serial.begin(115200);
  delay(200);
  Serial.println();

  WiFi.mode(WIFI_STA);                  // режим клиента: плата идёт к роутеру
  WiFi.begin(WIFI_SSID, WIFI_PASS);

  Serial.print("Подключаюсь");
  unsigned long start = millis();
  // Ждём не вечно, а 20 секунд: иначе непонятно, что вообще происходит.
  while (WiFi.status() != WL_CONNECTED && millis() - start < 20000) {
    delay(500);
    Serial.print(".");
  }
  Serial.println();

  if (WiFi.status() == WL_CONNECTED) {
    Serial.print("Готово. Адрес платы в сети: ");
    Serial.println(WiFi.localIP());
    Serial.print("Уровень сигнала: ");
    Serial.print(WiFi.RSSI());
    Serial.println(" dBm (ближе к нулю - лучше)");
  } else {
    // Расшифровка кодов - в таблице на странице: у ESP8266 и ESP32
    // одна и та же цифра означает разное.
    Serial.print("Не подключился. Код состояния: ");
    Serial.println((int)WiFi.status());
  }
}

void loop() {
  // Вся работа сделана один раз в setup().
}

Что должно появиться в мониторе порта: несколько точек, а потом строчка вида «Адрес платы в сети: 192.168.1.47». Этот адрес — то, что вам понадобится дальше: именно его набирают в браузере, чтобы открыть страницу управления.

Коды состояния: одна цифра — два разных смысла

Метод WiFi.status() возвращает число. Тонкость, о которой почти нигде не написано: у ESP8266 и ESP32 эти числа означают разное. Мы сверили их прямо по исходникам ядер, а не по чужим статьям.

КодESP8266ESP32Что это значит на практике
0простойпростойЕщё ничего не начиналось. Подождите или вызовите WiFi.begin()
1сеть не найденасеть не найденаИмя написано не так, сеть на 5 ГГц, сеть скрыта или плата слишком далеко
2сканирование законченосканирование законченоСлужебное состояние, встречается редко
3подключеноподключеноВсё хорошо: можно печатать адрес
4не удалось подключитьсяне удалось подключитьсяУ ESP32 это чаще всего неверный пароль: отдельного кода про пароль у неё нет
5связь потерянасвязь потерянаБыла связь и пропала: слабый сигнал или роутер перезагрузился
6неверный парольотключеноОдна цифра — два разных смысла. На ESP8266 проверьте пароль, на ESP32 — вызовите WiFi.begin() снова
7отключенотакого кода нетПлата отключена от сети намеренно или ещё не начинала
255такого кода нетрадио не запущеноНе вызван WiFi.mode() или радио выключено

Самая обидная строка — шестая. Человек читает в интернете «код 6 — неверный пароль», меняет пароль в скетче по десять раз, а у него ESP32, и шестёрка там означает всего лишь «сейчас не подключено». Проверьте, какая у вас плата, прежде чем верить чужой расшифровке.

Связь рвётся — и это нормально

Домашний Wi-Fi живёт своей жизнью: роутер перезагружают, соседи включают микроволновку, кто-то уносит плату в другую комнату. Скетч, который подключается один раз в setup(), после первого же обрыва становится мёртвым куском кода: сеть пропала, а он этого даже не заметил.

Правильный скетч сторожит связь и переподключается сам — и делает это, не останавливая программу. Никаких while с ожиданием сети в loop(): пока программа стоит в таком цикле, она не читает датчики и не отвечает на нажатия.

// Связь иногда пропадает: роутер перезагрузили, сигнал просел, помеха.
// Скетч следит за связью и переподключается, не останавливая программу:
// никаких delay() в ожидании сети.
#if defined(ESP8266)
#include <ESP8266WiFi.h>
// У D1 mini и NodeMCU встроенный светодиод инверсный: LOW - это «горит».
#define STATUS_LED LED_BUILTIN
#define LED_ON LOW
#define LED_OFF HIGH
#else
#include <WiFi.h>
// У плат на ESP32 единого встроенного светодиода нет: на большинстве он
// висит на выводе 2, а на некоторых его нет вовсе - тогда поставьте свой.
#define STATUS_LED 2
#define LED_ON HIGH
#define LED_OFF LOW
#endif

const char WIFI_SSID[] = "имя вашей сети";
const char WIFI_PASS[] = "пароль от сети";

const unsigned long RETRY_MS = 10000;   // как часто пробовать снова
unsigned long lastTry = 0;
bool wasConnected = false;

// Одна и та же цифра у двух чипов означает разное - поэтому две таблицы.
const char* statusName(int code) {
#if defined(ESP8266)
  switch (code) {
    case 0: return "простой";
    case 1: return "сеть с таким именем не найдена";
    case 2: return "сканирование закончено";
    case 3: return "подключено";
    case 4: return "не удалось подключиться";
    case 5: return "связь потеряна";
    case 6: return "неверный пароль";
    case 7: return "отключено";
  }
#else
  switch (code) {
    case 0: return "простой";
    case 1: return "сеть с таким именем не найдена";
    case 2: return "сканирование закончено";
    case 3: return "подключено";
    case 4: return "не удалось подключиться (чаще всего - пароль)";
    case 5: return "связь потеряна";
    case 6: return "отключено";
    case 255: return "радио не запущено";
  }
#endif
  return "неизвестный код";
}

void setup() {
  Serial.begin(115200);
  delay(200);
  Serial.println();
  pinMode(STATUS_LED, OUTPUT);
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  lastTry = millis();
}

void loop() {
  bool connected = (WiFi.status() == WL_CONNECTED);

  if (connected != wasConnected) {
    wasConnected = connected;
    if (connected) {
      Serial.print("Связь есть, адрес ");
      Serial.println(WiFi.localIP());
    } else {
      Serial.println("Связь пропала, пробую снова");
    }
  }

  if (!connected && millis() - lastTry > RETRY_MS) {
    lastTry = millis();
    Serial.print("Состояние: ");
    Serial.println(statusName((int)WiFi.status()));
    WiFi.disconnect();
    WiFi.begin(WIFI_SSID, WIFI_PASS);
  }

  // Пока нет связи - светодиод мигает, есть связь - горит ровно.
  if (connected) {
    digitalWrite(STATUS_LED, LED_ON);
  } else {
    digitalWrite(STATUS_LED, (millis() / 300) % 2 ? LED_ON : LED_OFF);
  }
}

Заодно этот скетч показывает состояние светодиодом: горит ровно — связь есть, мигает — идёт переподключение. Мелочь, а отлаживать поделку без монитора порта становится возможно.

Ещё одна вещь, о которой спрашивают: адрес платы может меняться. Роутер выдаёт его в аренду, и после перезагрузки плата может получить другой. Лечится двумя способами: либо в настройках роутера закрепить за платой постоянный адрес (это самый надёжный путь), либо задать адрес прямо в скетче методом WiFi.config(). Есть и третий, красивый способ — имя вида plata.local. Но полагаться на него нельзя: такие имена понимает не всякий телефон, Android научился этому только с двенадцатой версии, а многие роутеры режут нужную для этого групповую рассылку.

Питание: главная причина «плата сошла с ума»

Если запомнить со страницы только одно, пусть это будет вот что. Wi-Fi ест ток рывками. В покое плата потребляет около 80 миллиампер, но в момент передачи — короткими всплесками в несколько раз больше. Изготовитель чипа прямо пишет: источник должен отдавать не меньше 500 миллиампер.

Ток платы во времени: ровный фон и короткие всплески передачи400 мА0время50 мАНе хватит даже на спокойную работу!перезагрузкаОфициальный потолок этого вывода — 50 мА. Модуль просит больше уже в моментвключения радио, и плата уходит в бесконечную перезагрузку.
Пунктир — сколько тока способен отдать источник, синяя линия — сколько просит плата. Каждый всплеск выше пунктира это провал напряжения, и чип перезапускается. Изготовитель чипа прямо требует источник не меньше 500 мА.

Что происходит, если источник слабый: во время всплеска напряжение проседает, чип считает это сбоем питания и перезапускается. Со стороны это выглядит как заколдованный круг — плата стартует, доходит до подключения, перезагружается, стартует снова. Программу при этом можно переписывать бесконечно, толку не будет.

Отсюда же самая известная беда пути «модуль ESP-01 к Arduino Uno». Модуль пытаются питать от вывода 3V3 самой Uno, а у этого вывода официальный потолок — 50 миллиампер. Это в десять раз меньше требуемого. Модуль будет включаться, мигать и умирать при первой же попытке выйти в эфир.

Что помогает на практике: отдельный источник питания вместо вывода соседней платы; короткий и толстый USB-кабель вместо тонкого метрового; конденсатор на 470 микрофарад прямо у выводов питания платы — он сглаживает как раз короткие всплески. И общий минус: если питание отдельное, минус источника и минус платы должны быть соединены, иначе не работает ничего.

Проверяем, что плата действительно в интернете

Подключиться к роутеру и выйти в интернет — разные вещи. Самая простая и честная проверка: попросить у интернета точное время. Часы по сети умеет само ядро платы, библиотека не нужна.

// Проверка «плата действительно в интернете»: она спрашивает точное
// время у сервера времени и печатает его. Библиотека не нужна - часы
// по сети умеет само ядро платы.
#if defined(ESP8266)
#include <ESP8266WiFi.h>
#else
#include <WiFi.h>
#endif
#include <time.h>

const char WIFI_SSID[] = "имя вашей сети";
const char WIFI_PASS[] = "пароль от сети";

const long TIMEZONE_SEC = 3 * 3600;   // Москва: плюс три часа от UTC

void setup() {
  Serial.begin(115200);
  delay(200);
  Serial.println();

  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println();
  Serial.print("Адрес платы: ");
  Serial.println(WiFi.localIP());

  // Два сервера на случай, если первый не ответит.
  configTime(TIMEZONE_SEC, 0, "ru.pool.ntp.org", "pool.ntp.org");

  Serial.print("Жду время");
  time_t now = time(nullptr);
  while (now < 100000) {          // пока часы не заведены, время близко к нулю
    delay(300);
    Serial.print(".");
    now = time(nullptr);
  }
  Serial.println();
}

void loop() {
  time_t now = time(nullptr);
  struct tm* t = localtime(&now);

  char line[32];
  snprintf(line, sizeof(line), "%02d:%02d:%02d  %02d.%02d.%04d",
           t->tm_hour, t->tm_min, t->tm_sec,
           t->tm_mday, t->tm_mon + 1, t->tm_year + 1900);
  Serial.println(line);

  delay(1000);
}

Если время пришло — сеть настоящая, наружу плата ходит. Заодно вы получили часы, которые не нужно заводить и которые не убегают: это тот самый случай, когда модуль часов реального времени можно не покупать вовсе, если у поделки всегда есть сеть.

Кто кому звонит: три роли платы

Дальше начинается самое интересное — и здесь новички чаще всего заходят в тупик, потому что не различают три совершенно разные схемы работы. Разница между ними не в коде, а в том, кто начинает разговор.

Плата — клиент: сама стучится наружуПлатаИнтернетсервер в сетиТелефончитает потомПлата раз в минуту открывает соединение, отдаёт показания и кладёт трубку. Наружуникто не звонит.Плюс: Работает из любой сети, даже из мобильного модема: наружу выйти можно всегда.Минус: Управлять платой так нельзя — она сама решает, когда выйти на связь.Где встречается: Погодная станция, счётчик, датчик протечки.
Три роли, из которых складываются все проекты с Wi-Fi. Каждой посвящена своя статья: сервер на плате, посредник и обновление прошивки по воздуху.

Первая роль — плата звонит сама. Раз в минуту открывает соединение, отдаёт показания и кладёт трубку. Так работают погодные станции и счётчики. Управлять такой платой нельзя: она выходит на связь по своему расписанию.

Вторая роль — звонят плате. На ней живёт маленький сайт, вы набираете её адрес в браузере и щёлкаете кнопки. Это самый наглядный способ управления, и работает он без интернета вообще — достаточно домашней сети. Но и только внутри неё: из интернета домашняя плата не видна, роутер её прячет.

Третья роль — оба звонят посреднику. И плата, и телефон соединяются с общим сервером, и он передаёт сообщения в обе стороны. Это единственный по-настоящему рабочий способ управлять поделкой из другого города, и при этом не открывать дырок в домашнем роутере.

Каждой роли посвящена отдельная статья — они продолжают эту:

Если менять плату нельзя: модуль ESP-01 к Arduino Uno

Бывает, что основную плату трогать нельзя: проект собран, отлажен, залит в корпус. В этом случае к Uno добавляют модуль ESP-01. Путь рабочий, но трудный, и честно перечислить трудности лучше заранее.

Модуль общается с платой по последовательному порту текстовыми командами — они начинаются с букв AT. Чтобы отправить одно число на сервер, Uno должна составить и передать несколько таких команд, а потом разобрать ответы. Каждая команда — это строка в памяти, а оперативной памяти у Uno всего два килобайта. На практике половина её уходит на обслуживание модуля.

Плюс к этому три обязательных условия:

  • Питание 3,3 вольта и не меньше 500 миллиампер. Не от вывода 3V3 платы Uno — там потолок 50 миллиампер, этого не хватит.
  • Делитель на линию приёма модуля. Выводы модуля рассчитаны на 3,3 вольта, а Uno выдаёт 5. Два резистора решают вопрос — точно так же, как для Bluetooth-модуля.
  • Скорость. Заводская скорость AT-прошивки обычно 115 200, а программный порт Uno на такой скорости уже не тянет: в мониторе будет каша. Скорость модуля меняют один раз командой AT+UART_DEF=9600,8,1,0,0 через USB-переходник, и дальше живут на 9600.

Первое, что стоит сделать с новым модулем, — просто поговорить с ним руками. Этот скетч превращает Uno в мост: что вы пишете в мониторе порта, уходит в модуль, что отвечает модуль — появляется на экране. Наберите AT и нажмите ввод: живой модуль ответит OK.

// Мост между монитором порта и модулем ESP-01: всё, что вы напишете
// в мониторе, уходит в модуль, всё, что ответит модуль, - на экран.
// Так модулю диктуют AT-команды руками, чтобы понять, живой ли он.
//
// ВАЖНО ПРО ПИТАНИЕ. Модуль питается 3,3 вольта и в момент передачи
// просит куда больше, чем даёт вывод 3V3 платы Uno (у него потолок
// 50 мА). Нужен отдельный источник 3,3 В на 500 мА и общий минус.
// Линия RX модуля тоже рассчитана на 3,3 В - к выводу 3 идёт делитель
// из двух резисторов, как и для Bluetooth-модуля.
#include <SoftwareSerial.h>

// 2 - принимаем от модуля (его TX), 3 - передаём модулю (его RX).
SoftwareSerial esp(2, 3);

// Заводская скорость AT-прошивки обычно 115200, но программный порт
// на такой скорости уже не тянет: в мониторе будет каша. Скорость
// модуля меняют один раз командой AT+UART_DEF=9600,8,1,0,0 через
// USB-переходник, а дальше работают на 9600.
const long ESP_BAUD = 9600;

void setup() {
  Serial.begin(9600);
  esp.begin(ESP_BAUD);
  Serial.println("Мост открыт. Наберите AT и нажмите ввод.");
  Serial.println("В мониторе выберите окончание строки «NL и CR».");
}

void loop() {
  while (esp.available()) {
    Serial.write(esp.read());
  }
  while (Serial.available()) {
    esp.write(Serial.read());
  }
}

В мониторе порта обязательно выберите окончание строки «NL и CR» — без него модуль не поймёт, что команда закончилась, и будет молчать. Это тот же порядок, что и при настройке Bluetooth-модуля.

Есть и промежуточный вариант — платы, у которых на одной плате стоят и ATmega, и ESP8266, а между ними переключатель. Про них написано на странице про ESP8266: там же разобрано, почему такие платы удобны в теории и капризны на практике.

Провод вместо радио: когда Ethernet лучше

Про этот путь почти не пишут, а он часто оказывается лучшим. Если поделка стоит на месте и рядом есть роутер, сетевой кабель даёт то, чего радио не даст никогда: отсутствие пароля, отсутствие помех, отсутствие переподключений и заметно меньшую задержку.

Шилд W5500 садится на Arduino Uno сверху и занимает шину SPI и вывод 10. Модуль той же микросхемы подключается пятью проводами к любой плате. Работает это с обычной Arduino Uno — тот случай, когда менять плату не нужно.

// Сеть по проводу: тот же интернет, только без радио и без пароля.
// Шилд или модуль W5500 садится на шину SPI, выбор кристалла - вывод 10.
#include <SPI.h>
#include <Ethernet.h>

// Любой адрес, лишь бы в сети он был один такой.
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};

void setup() {
  Serial.begin(9600);
  while (!Serial) {
    ;
  }

  Ethernet.init(10);          // вывод выбора кристалла у шилда W5500

  Serial.println("Спрашиваю адрес у роутера...");
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Роутер адрес не выдал.");
    if (Ethernet.hardwareStatus() == EthernetNoHardware) {
      Serial.println("Плата не видит сам модуль: проверьте SPI и питание.");
    } else if (Ethernet.linkStatus() == LinkOFF) {
      Serial.println("Кабель не воткнут или мёртв.");
    }
    return;
  }

  Serial.print("Готово. Адрес платы: ");
  Serial.println(Ethernet.localIP());
}

void loop() {
  // Раз в несколько минут аренда адреса продлевается сама.
  Ethernet.maintain();
  delay(1000);
}

Дальше код почти не отличается от Wi-Fi: те же соединения, те же запросы, только вместо WiFiClient используется EthernetClient. Минус ровно один — провод. Если поделка должна ездить или висеть на стене без розетки рядом, Ethernet отпадает.

Что делать, если не работает

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

Что видноЧто на самом делеЧто сделать
Плата бесконечно перезагружается, как только доходит до подключенияИсточнику не хватает тока на всплеск передачиОтдельное питание не меньше 500 мА, короткий и толстый USB-кабель, конденсатор 470 мкФ по питанию
В мониторе порта каша из непонятных знаков, потом нормальный текстЭто не ошибка: загрузчик ESP8266 всегда говорит на скорости 74 880, а ваш скетч — на своейНичего не делайте. Если каша идёт всё время — поставьте в мониторе ту же скорость, что в Serial.begin()
Сканер не показывает мою домашнюю сетьСеть на 5 ГГц, имя скрыто или роутер далекоВключите на роутере сеть 2,4 ГГц с отдельным именем и подойдите ближе
Состояние 6 на плате ESP8266Неверный пароль — на этом чипе для него есть отдельный кодСкопируйте пароль из настроек роутера, а не по памяти: путают ноль и букву O, дефис и тире
Состояние 1: сеть не найдена, хотя телефон её видитИмя написано не буква в букву или сеть в другом диапазонеСверьте имя со списком из сканера, а не с экрана телефона
Плата подключилась, адрес есть, но с телефона не открываетсяПлата и телефон в разных сетях или в гостевой сети включена изоляцияОдна и та же сеть для обоих, изоляцию клиентов выключить
Адрес платы 0.0.0.0Роутер не выдал адрес: закончился запас адресов или включён фильтр по MACПерезагрузите роутер, проверьте фильтр, при необходимости задайте плате постоянный адрес
Имя вида «плата.local» не открывается на телефонеТакие имена понимает не всякий телефон: Android научился этому только с двенадцатой версии, и роутер может резать групповую рассылкуОткройте по числовому адресу и закрепите его за платой в настройках роутера
После перезагрузки роутера плата не вернулась в сетьВ скетче нет переподключения: связь установили один раз в setup()Возьмите скетч со сторожем связи из раздела «Связь рвётся»
У стола работает, в дальней комнате отваливаетсяСлабый сигнал: у платы антенна на самой плате и она хуже телефоннойПечатайте WiFi.RSSI(): дальше −75 dBm начинаются потери. Разверните плату, уберите металл рядом, поставьте ближе к роутеру
«Sketch too big» на плате, у которой 4 МБ памятиПамять поделена: скетчу отведена не вся флеш-память, а её часть — вторая половина зарезервирована под обновление по воздухуРазбор целиком — в статье про прошивку по воздуху
Работает, но раз в сутки зависаетДлинные delay() и блокирующие циклы: пока программа стоит, радио не обслуживаетсяУберите delay() из loop(), считайте время по millis(), в тяжёлых циклах вызывайте delay(0) или yield()

Честно про безопасность

Поделка на ESP в домашней сети — это устройство без пароля. Любой, кто уже подключён к вашему Wi-Fi, может открыть её страницу и нажать все кнопки. Для настольной лампы это не беда, для замка на двери — беда.

Второе: пароль от сети лежит в скетче открытым текстом и вместе с прошивкой попадает во флеш-память платы. Тот, у кого плата окажется в руках, прочитает его за минуту. Не заливайте в поделки, которые уезжают из дома, пароль от основной сети — заведите для них отдельную.

Третье, и самое важное: не открывайте на роутере «проброс порта» к плате, чтобы дотянуться до неё из интернета. Так вы выставляете наружу устройство без единой проверки прав, и находят такие устройства за часы, а не за годы. Правильный способ достать поделку издалека — посредник, про которого написано в отдельной статье.

Что купить

Всё проверено 24 августа 2026 года: каждая карточка открыта отдельно, цена и артикул взяты с самой страницы товара. Того, чего нет в наличии, в подборке нет.

WeMos D1 mini на ESP8266

Самый короткий путь к Wi-Fi: плата размером с половину спичечного коробка, разъём micro-USB на борту, радио внутри. Дешевле, чем отдельный модуль с питанием к нему. С неё имеет смысл начинать, если проект небольшой и выводов нужно немного.

290 ₽
Открыть карточку
арт. 867 · цена и наличие на 24.08.2026

Piranha ESP32 v2

Шаг вперёд от D1 mini: два ядра, гораздо больше памяти, встроенный Bluetooth и запас на защищённые соединения. Именно её стоит брать, если поделка будет ходить в интернет, а не только по домашней сети.

690 ₽
Открыть карточку
арт. 1453 · цена и наличие на 24.08.2026

WeMos ESP32 D1/R32 — ESP32 в корпусе Uno

Тот самый случай «проект собран на шилдах, менять механику не хочется»: размер, отверстия и гребёнка как у Arduino Uno, а внутри ESP32 с Wi-Fi. Помните про вольты: выводы у неё трёхвольтовые, шилды с выходом 5 вольт нужно проверять по схеме.

770 ₽
Открыть карточку
арт. 1121 · цена и наличие на 24.08.2026

Источник питания 5 В, 2 А

То самое «нормальное питание», без которого половина проектов с Wi-Fi живёт в вечной перезагрузке. Два ампера — запас вчетверо больше требуемого: хватит и плате, и датчикам, и подсветке.

986 ₽
Открыть карточку
арт. 491 · цена и наличие на 24.08.2026

Понижающий преобразователь LM2596

Если питание уже есть, но на 9 или 12 вольт, этот модуль сделает из него ровные 5 вольт с хорошим запасом по току. Дешевле отдельного блока питания и удобнее для поделки внутри корпуса.

144 ₽
Открыть карточку
арт. 110 · цена и наличие на 24.08.2026

Ethernet Shield W5500

Сеть по проводу для Arduino Uno и Mega: садится сверху, занимает шину SPI и вывод 10. Ни пароля, ни помех, ни переподключений — для стационарной поделки это часто удобнее радио.

1361 ₽
Открыть карточку
арт. 1295 · цена и наличие на 24.08.2026

Сетевой модуль W5500

Та же микросхема, но не шилдом, а отдельной платой на пять проводов. Подойдёт любой плате, а не только той, что в корпусе Uno, и стоит вдвое дешевле шилда.

640 ₽
Открыть карточку
арт. 854 · цена и наличие на 24.08.2026

Патч-корд RJ45, 30 см

Короткий сетевой кабель до роутера. Мелочь, о которой вспоминают, когда шилд уже приехал, а воткнуть его нечем.

65 ₽
Открыть карточку
арт. 1637 · цена и наличие на 24.08.2026

Провода «папа-мама», 40 штук

Ими соединяют плату с датчиками и модулем сети: с одной стороны штырёк, с другой гнездо. Длина 20 см, десять цветов.

161 ₽
Открыть карточку
арт. 361 · цена и наличие на 24.08.2026

Дальше по теме

Частые вопросы

Можно ли подключить Wi-Fi к Arduino Uno?

Можно, но почти всегда не нужно. К Uno добавляют модуль ESP-01, и тогда Uno командует им текстовыми AT-командами: на каждую отправку данных уходит несколько строк, а оперативной памяти у Uno всего два килобайта — половина её тратится на обслуживание модуля. Плюс модулю нужно отдельное питание 3,3 вольта минимум на 500 миллиампер (вывод 3V3 у Uno отдаёт максимум 50 миллиампер) и делитель на линию приёма. Отдельная плата, у которой радио уже внутри, стоит дешевле такого набора, программируется в той же среде и делает всё сама. Uno имеет смысл оставлять только тогда, когда проект уже собран и менять его нельзя.

Почему плата не видит мою сеть Wi-Fi, хотя телефон её видит?

Чаще всего сеть работает на 5 гигагерцах. Радио у ESP8266 и ESP32 умеет только диапазон 2,4 гигагерца — это свойство самих чипов, настройками оно не меняется. Вторая по частоте причина: обе сети роутера названы одинаково, и плата видит только двухгигагерцевую половину — тогда она подключается через раз. Третья: имя сети скрыто, и в списке сканера её нет вовсе. Реже встречаются WPA3 (его понимает ESP32, но не ESP8266), русские буквы в имени сети и фильтр по MAC-адресам. Запустите сканер сетей: если вашей сети нет в его списке, дело не в пароле.

Какую плату с Wi-Fi взять новичку?

Для первого проекта — D1 mini на чипе ESP8266: размером с половину спичечного коробка, разъём USB на борту, стоит меньше трёхсот рублей. Если поделка будет ходить в интернет, а не только по домашней сети, лучше сразу брать ESP32: у неё два ядра и заметно больше памяти, а значит, ей по силам защищённые соединения, без которых современные сайты и мессенджеры не работают. Если проект уже собран на шилдах в корпусе Arduino Uno, есть плата на ESP32 ровно того же размера и с той же гребёнкой — только помните, что выводы у неё трёхвольтовые.

Нужна ли библиотека, чтобы плата вышла в Wi-Fi?

Нет. Работа с сетью входит в поддержку самой платы: для ESP8266 это ESP8266WiFi.h, для ESP32 — WiFi.h, и обе приезжают вместе с пакетом платы. Ничего скачивать и класть в папку библиотек не нужно. Более того, один и тот же скетч можно написать сразу для обеих плат: строчка #if defined(ESP8266) подставит нужный заголовок. Библиотеки понадобятся позже и по делу — например, для работы с MQTT.

Почему плата перезагружается, когда подключается к сети?

Это почти всегда питание, а не программа. Wi-Fi потребляет ток рывками: в покое около 80 миллиампер, а в момент передачи короткими всплесками в несколько раз больше. Изготовитель чипа прямо требует источник не меньше 500 миллиампер. Когда источник слабый, во время всплеска напряжение проседает, чип считает это сбоем и перезапускается — получается бесконечный круг «старт, подключение, перезагрузка». Лечится отдельным источником питания вместо вывода соседней платы, коротким толстым USB-кабелем и конденсатором на 470 микрофарад у выводов питания.

Можно ли управлять платой через интернет, а не только из дома?

Можно, но не тем способом, который приходит в голову первым. Веб-страница, которую плата отдаёт браузеру, работает только внутри домашней сети: из интернета плата не видна, её прячет роутер. Пробрасывать к ней порт на роутере не стоит — так наружу выставляется устройство, у которого нет ни пароля, ни проверки прав, и находят такие устройства за часы. Правильный путь — посредник: и плата, и телефон соединяются с одним сервером, и он передаёт сообщения в обе стороны. Именно так устроены MQTT и боты в мессенджерах.

Wi-Fi или Bluetooth — что выбрать для управления с телефона?

Если телефон и плата рядом, а интернет не нужен — Bluetooth проще: не нужны ни роутер, ни пароль, ни адреса, и модуль работает как удлинитель провода. Если нужно управлять из другой комнаты, показывать данные на обычной веб-странице, писать в умный дом или выходить наружу — только Wi-Fi. Ещё одно отличие важно владельцам iPhone: популярный Bluetooth-модуль HC-05 с айфоном не работает вовсе, а Wi-Fi одинаково доступен с любого телефона, потому что страница открывается в обычном браузере.

Что для этого нужно в среде

Все скетчи с этой страницы собираются в Trema IDE без единой скачанной библиотеки: работа с сетью входит в поддержку самих плат. Поддержку ESP8266 и ESP32 среда берёт с нашего собственного зеркала, поэтому установка не упирается в закрытые сайты и не требует ручной правки ссылок.

Что почитать рядом: как поставить поддержку платы — ESP8266 и ESP32. Что делать, если скетч не заливается — Ошибка загрузки. Куда подключать остальные модули — Модули для Arduino. Идеи для проектов — Проекты на Arduino.