Esp смотреть руководство

Здравствуйте, коллеги и энтузиасты!

Последние пару лет практически все прототипирование несложных IoT-устройств я делаю на NodeMCU, хотя зачастую она и великовата по размеру, и дороговата, и избыточна по функционалу. А все потому, что имела неудачный опыт с ESP-01, которая совершенно не поддавалась прошивке. Сейчас пришло время преодолеть этот барьер и освоить другие железки, от которых мне нужно следующее — Wi-Fi и пины для подключения периферии.

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

Несколько представленных в статье модулей (ESP-01, ESP-07, ESP-12E, ESP-12F) и плат (Goouuu Mini-S1, WeMos D1 mini и NodeMCU V2) базируются на контроллере ESP8266, использование которого позволяет простым и дешевым способом добавить в своё устройство беспроводную связь через Wi-Fi. 

Так выглядит модельный ряд модулей на базе чипа ESP8266. 

Последняя плата из тех, о которых я расскажу (ESP32 WROOM DevKit v1), построена на контроллере семейства ESP32 — более продвинутой по своим возможностям версии ESP8266. 

Все представленные модели можно программировать и загружать прошивки через Arduino IDE точно так же, как при работе с Arduino.

  • ESP-01

  • ESP-07

  • ESP-12E

  • ESP-12F

  • Goouuu Mini-S1

  • WeMos D1 mini

  • NodeMCU V2

  • ESP32 WROOM DevKit v1

Настройка среды программирования Arduino IDE

По умолчанию среда IDE настроена только на AVR-платы. Для платформ, представленных ниже, необходимо добавить в менеджере плат дополнительную поддержку.

1) Открываем среду программирования Arduino IDE.

2) В пункте меню File (Файл) выбираем Preferences (Настройки). В окне Additional Boards Manager URLs вводим через запятую адреса http://arduino.esp8266.com/stable/package_esp8266com_index.json и https://dl.espressif.com/dl/package_esp32_index.json.

http://arduino.esp8266.com/stable/package_esp8266com_index.json, https://dl.espressif.com/dl/package_esp32_index.json

3) Нажимаем OK.

4) В пункте меню Tools (Инструменты) -> Board (Плата) выбираем Boards manager (Менеджер плат).

Находим в списке платформы на ESP8266 и нажимаем на кнопку Install (Установить).

6) Надпись INSTALLED сообщает, что дополнения успешно установлены.

7) Аналогичным образом устанавливаем дополнение для ESP32.

8) Теперь нам доступны к программированию платформы с модулем ESP8266 и ESP32.

9) Для подключения плат к платформе Интернета вещей используем библиотеку EspMQTTClient. Чтобы ее установить, в пункте меню Tools (Инструменты) выбираем Manage Libraries (Управлять библиотеками). Находим и устанавливаем библиотеку EspMQTTClient. Может появиться сообщение об установке дополнительных библиотек. Выбираем “Install all”.

Примечание — Также для работы с платами понадобится установить драйверы CH340 (WeMos и Goouuu) и CP2102 (для остальных). Их отсутствие повлияет на то, найдет ли Arduino IDE COM-порт, к которому подключена плата.

Код прошивки

Для прошивки всех используемых ниже модулей используем один и тот же код.

Основные функции:

  1. Установка Wi-Fi соединения

  2. Подключение к объекту на платформе Rightech IoT Cloud по протоколу MQTT

  3. Отправка рандомных значений по температуре («base/state/temperature») и влажности («base/state/humidity») каждые 5 секунд (PUB_DELAY)

  4. Получение сообщений о переключении света («base/relay/led1»)

#include "Arduino.h"
#include "EspMQTTClient.h" /* https://github.com/plapointe6/EspMQTTClient */
                           /* https://github.com/knolleary/pubsubclient */
#define PUB_DELAY (5 * 1000) /* 5 seconds */

EspMQTTClient client(
  "<wifi-ssid>",
  "<wifi-password>",

  "dev.rightech.io",
  "<ric-mqtt-client-id>"
);

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

void onConnectionEstablished() {
  client.subscribe("base/relay/led1", [] (const String &payload)  {
    Serial.println(payload);
  });
}

long last = 0;
void publishTemperature() {
  long now = millis();
  if (client.isConnected() && (now - last > PUB_DELAY)) {
    client.publish("base/state/temperature", String(random(20, 30)));
    client.publish("base/state/humidity", String(random(40, 90)));
    last = now;
  }
}

void loop() {
  client.loop();
  publishTemperature();
}

Работоспособность кода будем проверять на платформе Rightech IoT Cloud, именно поэтому в качестве адреса MQTT-брокера указан dev.rightech.io. Идентификаторами клиентов служат идентификаторы объектов, созданных на платформе. Под каждую проверку я завела на платформе отдельный объект, именно поэтому во всех скринах кодов, которые будут далее представлены, отличается только строка <ric-mqtt-client-id>. 

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

Модули на базе ESP8266

Для работы с модулями на базе ESP8266 есть два варианта:

  1. Работа с AT командами (в стандартной прошивке Wi-Fi модуль общается с управляющей платой через «AT-команды» по протоколу UART);

  2. Wi-Fi модуль как самостоятельный контроллер (все представленные модули очень умные: внутри чипа прячется целый микроконтроллер, который можно программировать на языке C++ через Arduino IDE).

В статье будем рассматривать второй вариант — прошивка модулей в виде самостоятельного полноценного устройства. Здесь также есть два варианта прошивки с точки зрения железа:

  1. Через плату Arduino;

  2. Через USB-Serial адаптер.

Рассмотрим второй вариант — использовать адаптер на базе чипа CP2102 (например, такой https://www.chipdip.ru/product/cp2102-usb-uart-board-type-a?frommarket=https%3A%2F%2Fmarket.yandex.ru%2Fsearch%3Frs%3DeJwzSvKS4xKzLI&ymclid=16146772489486451735000001). Обязательно обратите внимание на то, чтобы адаптер позволял выдавать выходное напряжение 3.3 В, не больше!

1. ESP-01

ESP-01 — самый популярный модуль на ESP8266. PCB антенна обеспечивает дальность до 400 м на открытом пространстве. 

Внешний вид

Питание

Родное напряжение модуля — 3,3 В. Его пины не толерантны к 5 В. Если вы подадите напряжение выше, чем 3,3 В на пин питания, коммуникации или ввода-вывода, модуль выйдет из строя.

Подключение периферии

2 порта ввода-вывода общего назначения

Распиновка

Подключение к IoT

Аппаратная часть

1) Собираем схему

ESP-01

USB-Serial

VCC

VCC

CH_PD

VCC

TX

RX

RX

TX

GND

GND

GPIO 0 — сначала не подключен, но будет использоваться для перевода в режим программирования далее, поэтому к нему уже подведен провод

RST, GPIO 2 — не подключены

RTS, CTS — не подключены

2) Переводим в режим программирования (необходимо каждый раз выполнять перед прошивкой модуля)

2.1) Отключаем питание от модуля

2.2) Подключаем пин GPIO 0  к GND

ESP-01

USB-Serial

VCC

VCC

CH_PD

VCC

TX

RX

RX

TX

GND

GND

GPIO 0

GND

RST, GPIO 2 — не подключены

RTS, CTS — не подключены

2.3) Подключаем модуль к питанию

2.4) Железо готово, приступаем к программной части.

Программная часть

1) Выбираем плату: Tools (Инструменты) -> Board(Плата) Generic ESP8266 Module.

2) Вставляем подготовленный код.

3) Задаем данные для подключения Wi-Fi и идентификатор своего объекта на платформе.

4) Компилируем и загружаем скетч на плату.

5) Для обычной работы модуля (не для режима прошивки) пин GPIO 0 должен быть свободен, поэтому отключаем его от GND.

6) Переподключаем питание ESP-01 (например, вытаскиваем и вставляем обратно адаптер).

7) Видим появление данных на платформе.

Средняя цена

~ 100 рублей

Где купить

Прим. — Здесь и далее даны ссылки на магазины, из которых я либо заказывала сама, либо мне их рекомендовали. Это не реклама, а просто желание помочь быстрее найти нужную железку. Вы можете заказывать в любых других понравившихся магазинах =)

В России

В Китае

2. ESP-07

Особенности этого модуля — керамическая антенна и разъем для внешней антенны, металлический экран.

Внешний вид

Питание

3 — 3,6 В

Подключение периферии

  • 9 портов ввода-вывода общего назначения

  • 1 аналоговый вход

Распиновка

Подключение к IoT

Аппаратная часть

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

1) Собираем схему

ESP-07

USB-Serial

VCC

VCC

CH_PD (рекомендуется через резистор)

VCC

TX

RX

RX

TX

GND

GND

GPIO 15 (рекомендуется через резистор)

GND

GPIO 0 — сначала не подключен, но будет использоваться для перевода в режим программирования далее, поэтому к нему уже подведен провод

все остальные контакты не подключены

RTS, CTS — не подключены

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

2) Переводим в режим программирования (необходимо каждый раз выполнять перед прошивкой модуля)

2.1) Отключаем питание от модуля

2.2) Подключаем пин GPIO 0  к GND

ESP-07

USB-Serial

VCC

VCC

CH_PD

VCC

TX

RX

RX

TX

GND

GND

GPIO 15 

GND

GPIO 0

GND

все остальные контакты не подключены

RTS, CTS — не подключены

2.3) Подключаем модуль к питанию

2.4) Железо готово, приступаем к программной части.

Программная часть

1) Выбираем плату: Tools (Инструменты) -> Board(Плата) Generic ESP8266 Module.

2) Вставляем подготовленный код.

3) Задаем данные для подключения Wi-Fi и идентификатор своего объекта на платформе.

4) Компилируем и загружаем скетч на плату.

5) Для обычной работы модуля (не для режима прошивки) пин GPIO 0 должен быть свободен, поэтому отключаем его от GND.

6) Переподключаем питание ESP-07 (например, вытаскиваем и вставляем обратно адаптер).

7) Видим появление данных на платформе.

Средняя цена

~ 160 рублей

Где купить

В России

В Китае

3. ESP-12E

Внешний вид

Питание

3 — 3,6 В

Подключение периферии

  • 17 портов ввода-вывода общего назначения

  • 1 аналоговый вход

Распиновка

Подключение к IoT

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

1) Выбираем плату: Tools (Инструменты) -> Board(Плата) Generic ESP8266 Module.

2) Вставляем подготовленный код.

3) Задаем данные для подключения Wi-Fi и идентификатор своего объекта на платформе.

4) Компилируем и загружаем скетч на плату.

5) Для обычной работы модуля (не для режима прошивки) пин GPIO 0 должен быть свободен, поэтому отключаем его от GND.

6) Переподключаем питание ESP-12 (например, вытаскиваем и вставляем обратно адаптер).

7) Видим появление данных на платформе.

Средняя цена

~ 170 рублей

Где купить

В России

В Китае

4. ESP-12F на Wi-Fi Troyka-модуль

Внешний вид

Разберемся с этим модулем на примере его распайки на Wi-Fi Troyka-модуль производства Амперки. Хоть он и дороже, но взаимодействовать с ним гораздо приятнее. Уже есть ножки, распаянные со со стандартным шагом 2,54 мм, дополнительные защиты, регуляторы напряжения, которые помогают избежать неожиданного поведения и поломок при первых опытах. К слову, когда у меня в далекие времена не получалось подружиться с ESP-01, а время уже поджимало, я взяла этот модуль, и все дальше пошло гладко.

Питание

Рабочее напряжение ESP8266 — 3,3 вольта. Но на Troyka-модуле предусмотрен стабилизатор уровня напряжения, поэтому он работает и от 5 В.

Подключение периферии

5 портов ввода-вывода общего назначения

Максимальный ток с пина: 12 мА

Распиновка

Подключение к IoT

Аппаратная часть

Опять же подключаем через адаптер. На сайте Амперки есть прекрасная схемка. 

1) Собираем схему

Troyka

USB-Serial

VCC

VCC

TX

RX

RX

TX

GND

GND

все остальные контакты не подключены

RTS, CTS — не подключены

2) Переводим в режим программирования (необходимо каждый раз выполнять перед прошивкой модуля)

2.1) Зажимаем кнопку PROG

2.2) Нажимаем и отпускаем кнопку RESET

2.3) Отпускаем кнопку PROG

Программная часть

1) Выбираем плату: Tools (Инструменты) -> Board(Плата) Generic ESP8266 Module.

2) Вставляем подготовленный код.

3) Задаем данные для подключения Wi-Fi и идентификатор своего объекта на платформе.

4) Компилируем и загружаем скетч на плату.

5) Переподключаем питание (например, вытаскиваем и вставляем обратно адаптер).

6) Видим появление данных на платформе.

Текущая цена

~ 850 рублей

Где купить

В России

Платы на базе ESP8266

Если с модулями приходилось немного повозиться, то все представленные ниже платы можно сразу подключать к USB-порту компьютера.

1. Goouuu Mini-S1

Внешний вид

Питание

5 В (Крайне не рекомендуется запитывать через вывод 3V3. Входящее напряжение будет поступать на чип ESP8266 напрямую, минуя все защиты от перенапряжения и короткого замыкания.)

Подключение периферии

  • 11 цифровых входов/выходов

  • 1 аналоговый вход

Выходы питания 3.3 В и 5 В.

Распиновка

Подключение к IoT

1) Выбираем плату: Tools (Инструменты) -> Board(Плата) Wemos D1 R1 (или Generic ESP8266 Module, так тоже работает).

2) Вставляем подготовленный код.

3) Задаем данные для подключения Wi-Fi и идентификатор своего объекта на платформе.

4) Компилируем и загружаем скетч на плату.

5) Видим появление данных на платформе.

Средняя цена

~ 300 рублей

Где купить

В России

В Китае

2. WeMos D1 mini

Внешний вид

Питание

5 В

Подключение периферии

  • 11 цифровых входов-выходов

  • 1 аналоговый вход

Выходы питания 3.3 В и 5 В.

Распиновка

Подключение к IoT

1) Выбираем плату: Tools (Инструменты) -> Board(Плата) Wemos D1 R1 (или Generic ESP8266 Module).

2) Вставляем подготовленный код.

3) Задаем данные для подключения Wi-Fi и идентификатор своего объекта на платформе.

4) Компилируем и загружаем скетч на плату.

5) Видим появление данных на платформе.

Средняя цена

~ 220 рублей

Где купить

В России

В Китае

3. NodeMCU V2

Внешний вид

Питание

5 — 10 В

Подключение периферии

  • 11 портов ввода-вывода общего назначения

  • 1 аналоговый вход

Максимальный выходной ток пина 3V3: 600 мА

Распиновка

Подключение к IoT

1) Выбираем плату: Tools (Инструменты) -> Board(Плата) NodeMCU 1.0 (или Generic ESP8266 Module).

2) Вставляем подготовленный код.

3) Задаем данные для подключения Wi-Fi и идентификатор своего объекта на платформе.

4) Компилируем и загружаем скетч на плату.

5) Видим появление данных на платформе.

Средняя цена

~ 240 рублей

Где купить

В России

В Китае

Плата на базе ESP32

ESP32 WROOM DevKit v1

Внешний вид

Питание

5 — 14 В

Подключение периферии

  • Цифровые входы/выходы: 21 пин 1–5, 12–19, 21–23, 25–27, 32 и 33Контакты ввода-вывода общего назначения. Пины могут быть настроены на вход или на выход. Логический уровень единицы — 3,3 В, нуля — 0 В. Максимальный ток выхода — 12 мА.

  • Цифровые входы: 4 пина 34–36 и 39Контакты ввода общего назначения. Могут быть настроены только на вход.

  • ШИМ: все пины ввода-выводаПозволяет выводить аналоговые значения в виде ШИМ-сигнала с разрядность 16 бит. Максимальное количество каналов 16.

  • АЦП: 15 пинов 2, 4, 12–15, 25–27, 32–36 и 39Позволяет представить аналоговое напряжение в цифровом виде с разрядностью 12 бит.

  • ЦАП: пины 25(DAC1) и 26(DAC2)Аналоговый выход цифро-аналогового преобразователя, который позволяет формировать 8-битные уровни напряжения.

Максимальный выходной ток пина 3V3: 1 А

Распиновка

Подключение к IoT

1) Выбираем плату: Tools (Инструменты) -> Board(Плата) DOIT ESP32 DEVKIT V1.

2) Вставляем подготовленный код.

3) Задаем данные для подключения Wi-Fi и идентификатор своего объекта на платформе.

4) Компилируем и загружаем скетч на плату.

5) Видим появление данных на платформе.

Средняя цена

~ 520 рублей

Где купить

В России

В Китае 


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

Ссылка на видеоинструкцию >>> https://youtu.be/7XzaUGr3-BA

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.

С каким из описанных устройств вы уже работали?


1.9%
Wi-Fi Troyka-модуль
3

Проголосовали 158 пользователей.

Воздержался 21 пользователь.

разделы: Интернет вещей , дата: 21 ноября 2018г.


Собственная плата с модулем ESP12E

Появившись четыре года назад, модули на базе чипа ESP8266 наделали много шума, прежде всего своей ценой. Производителем чипов была на тот момент никому неизвестная китайская фирма «Espressif Systems», зарегистрированная в Шанхае. Спустя некоторое время, многие фирмы представили на рынок аналогичные модули собственного изготовления, но по цене они были (и есть) в два — пять раз дороже модулей на ESP8266.

В 2016-ом году, фирма «Espressif Systems» представила на рынок ESP32, который существенно превосходил по своим возможностям ESP8266, и интерес к ESP8266 начал сходить на нет.

ESP32 это двухядерный микроконтроллер, или SoC если угодно, работающий на частоте 240MHz и снабженный радио-интерфейсами: WIFI стандарта 802.11 n (2.4 GHz), с пропускной способностью до 150 Mbps, и Bluetooth Low Energy стандарта 4.2, который был принят четыре года назад. ЦПУ имеет архитектуру Xtensa, есть аппаратная поддержка чисел с плавающей запятой, 7-уровневый конвейер, 520 кБ(!) ОЗУ, и многое другое (см. документацию: ESP32 Datasheet).

Если конкурентов ESP8266 изготавливают все кому не лень, то у ESP32 конкурентов с сопоставимой ценой фактически нет.

Модули на ESP8266 послужили основой для огромного количества «умных розеток» и им подобных устройств. Если говорить о ESP12 модулях, то здесь имеется около 50 Кбайт ОЗУ, 4 Мбайт флеш-памяти, частота ЦПУ 80МГц, встроенный WiFi контроллер. При этом цена за все это добро — около двух долларов. К сожалению, фирма производитель не предоставляет документацию на чип. Модули поставляются как готовые устройства с AT-интерфейсом и с возможностью программирования через Arduino IDE, используя для этого официальный SDK. Поэтому все изыскания относительно устройства аппаратной части ESP8266 являются результатом исследования энтузиастов.

В статье разбирается подключение, прошивка, и работа с AT командами ESP8266. Изначально статья была целиком посвящена только ESP8266, но впоследствии я решил добавить главу о перепрошивке модуля с ESP32. AT команды в ESP32 практически все те же, что и в ESP8266, так что, все сказанное относительно работы с AT-командам ESP8266 можно отнести и к ESP32.

Большая часть материала статьи посвящена режиму работы ESP8266, когда он работает в режиме WIFI модема с AT-интерфейсом. Разбираются типовые вопросы: как настроить, что-то скачать, переслать свои данные на сервер, и т.д. Предполагается, что уровень знаний читателя о сетях нулевой. Поэтому я постарался расписать всё максимально доходчиво. Для наглядности, показана работа с программами tcpdump и Wireshark для анализа трафика ESP8266. В качестве вспомогательного оборудования используется WiFi роутер с прошивкой OpenWRT, но вместо него можно использовать любой компьютер с Linux.

    Список используемой документации:

  1. ESP8266 Overview | Espressif Systems Страница продукта на сайте производителя.
  2. ESP8266EX Resources | Espressif Systems Страница с материалами на сайте производителя.
  3. ESP8266 SDK
    Getting Started Guide
  4. ESP8266 Technical Reference
  5. ESP-01/07/12 Series Modules User’s Manual
  6. ESP8266 AT Instruction Set
  7. ESP8266 AT Command Examples
  8. ESP32 AT Instruction Set and Examples
  9. Netcat Cheat Sheet
  10. Xtensa Instruction Set Architecture (ISA)
  11. Статья: «ESP8266 — подключение и обновление прошивки – esp8266»
  12. Статья на хабре: «Reverse Engineering ESP8266 — часть 1»
  13. Статья на хабре: «Reverse Engineering ESP8266 — часть 2»
  14. ESP8266 быстрый старт
  15. ESP8266 продолжение. Модуль ESP-12
  16. Статья на хабре: «Новые ревизии модулей на базе ESP8266 не умеют писать в SPI Flash»
  17. Книга Дэвида Тейнсли «Linux и UNIX: программирование в shell. Руководство разработчика», глава 29 «Сценарии cgi».

Содержание:

    I. Описание ESP8266

  1. Распиновка и подключение модулей ESP12
  2. Формат загрузочного лога, режимы работы SPI флеш-памяти
  3. Баг в Linux драйвере USB-UART преобразователя CP2102
    II. Прошивка ESP8266

  1. Использование esptool
  2. Первый способ прошивки
  3. Второй способ прошивки
  4. Третий способ прошивки
  5. Прошивка модуля ESP12E AT-интерпретатором версии 1.7.0 (август 2018г)
    III. Использование связки ESP8266 + OpenWRT

  1. Связка OpenWRT + ESP8266, использование сниффера tcpdump и анализатора траффика Wireshark для иследования трафика ESP8266
  2. Получение даты и времени через сеть, используя NTP
    IV. Связь ESP8266 с Web сервером на OpenWRT

  1. Связь ESP8266 с Web сервером на OpenWrt: настройка OpenWRT
  2. АТ-команды для установки TCP/UDP соединения
  3. Получение web-страницы от сервера на OpenWRT
  4. Получение лога погоды от сервера на OpenWRT
    V. Связь ESP8266 с Web сервером на OpenWRT посредством CGI скриптов

  1. Управление OpenWRT через ESP8266 посредством CGI интерфейса
  2. Отправка данных от ESP8266 на web-сервер OpenWRT через GET запрос
  3. Отправка данных от ESP8266 на web-сервер OpenWRT через POST запрос
    VI. Прозрачный режим соединения (UART-WiFi passthrough)

  1. Управление Linux/OpenWRT используя режим «UART-WiFi passthrough»
    VI. Плата NodeMCU с модулем ESP-WROOM-32

  1. Прошивка ESP32 в интерпретатор AT-команд

1) Распиновка и подключение модулей ESP12

Распиновка модулей ES8266

Т.к. я счастливый обладатель двух модулей ESP12E и одного NodeMCU v.3 (он тоже на базе ESP12E), то далее речь пойдёт именно о них.

Распиновка модуля ESP12E:

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

Замечу, что модуль имеет светодиод подключённый к GPIO_2.

Модули ESP12E/ESP12F были спроектированы компанией Ai-Thinker. У них на сайте имеется хороший мануал по модулям их производства: ESP-01/07/12 Series Modules User’s Manual. Но фактически, модули могут изготавливаются в Китае кем угодно.

Посмотреть модельный ряд модулей Ai-Thinker на базе чипа ESP8266, можно на следующей картинке:

Из всего ряда в ходу сейчас остались: ESP01 который имеет выводы с шагом 2.5 мм, ESP07 который имеет разъём для внешней антенны, и ESP12E/ESP12F. Замечу, что модули ESP01 идут с флешкой на 1 мегабайт, а первые модели шли вообще с 512кБ флеш-памяти.

Распиновка модуля Nodemcu v.3:

Здесь имеется две кнопки: «RESET», и непонятная кнопка «FLASH». Непонятна она потому, что прошивка у NodeMCU происходит в автоматическом режиме, кнопку «FLASH» для этого зажимать не нужно. Также NodeMCU имеет линейный стабилизатор на 3.3 Вольт и USB-UART преобразователь на чипе CP2102. Данную плату можно использовать с беспаячной макеткой, в то время как вариант платы с чипом ch340g туда уже не влазит. Т.е. влазить то он влазит, но при этом закрывает все контактные ячейки.

К недостаткам платы NodeMCU я отнесу то, что она не умеет работать с режимом глубокого сна ESP8266 (deep sleep). После «засыпания» проснуться ESP8266 уже не может, приходится нажимать Reset.

Фирма «Espressif Systems» выпускает свой модуль на базе ESP8266 под обозначением ESP-WROOM-02. В документации во всех примерах используется именно он. Данный модуль имеет сертификат FCC для продажи на территории США:

Заметьте, что на плате имеется знак чувствительности к электростатике. Зимой при сухом воздухе это особенно актуально.

Подключение модуля

Если плату NodeMCU можно сразу подключать к USB-порту компьютера, то с модулем ESP12 придётся немного повозится.

Нам понадобится USB-UART преобразователь с 3.3 вольтовой логикой, паяльник и несколько проводов. В ESP8266 SDK Getting Started Guide приводится следующая схема подключения:

На фотографии слева видны три провода ведущие к USB-UART преобразователю, «земля» подключена к GPIO_0 и GPIO_15, питание 3.3 Вольт подаётся на EN-пин.

Выглядит это так:

Обратите внимание на жёлтый провод с коннектором. При включении, ESP8266 проверяет состояние GPIO_0. Если он оказывается подключён к «земле», то ESP8266 входит в режим прошивки и какое-то время ждёт, поступление прошивки через UART. Т.о. для прошивки ESP8266 контакт GPIO_0 должен быть подтянут к «земле», для обычной работы он должен быть свободен.

В случае использования модуля ESP12E, подключение будет таким:

Здесь кроме всего прочего, в питанию подтягивается ещё и RESET.

Но всё-таки скрутки проводов — это не дело. Мой взгляд на али привлёк такой адаптер:

Здесь уже есть пара подтягивающих резисторов: GPIO_15 к «земле» и CP_PD/EN к питанию. Отсутствует нижняя группа контактов, но она используется чипом ESP8266 для соединения с флеш-памятью, т.е. для вас она бесполезна. На обратной стороне адаптера имеется опциональная площадка для линейного регулятора на 3.3В в корпусе SOT-89, но вот конденсаторы для него впаивать некуда, так что это площадка бесполезна. В макетку этот адаптер тоже не запихнёшь, габариты не позволят. Но в остальном, на мой взгляд это лучше чем скрутка проводов.

И все-таки я решил делать свою плату. Я уже упоминал, что весной у меня была возможность заказать два комплекта печатных плат в Китае. И если первым комплектом была STM8 Board, то вторым комплектом я заказал платы для ESP8266.

В качестве схемы я выбрал простую схему из статьи «ESP8266 — подключение и обновление прошивки – esp8266»:

Я не пытался предварительно собрать её на макетке, чтобы проверить работоспособность, или найти ошибки. Поэтому косяки я отлавливал уже на «железе» ;)

Что же с этой схемой не так? Во-первых, здесь перепутаны контакты GPIO_4 и GPIO_5. К счастью, в моем случае это оказалось не принципиально. Во-вторых, здесь не хватает кнопки на CH_PD/EN. Этот пин отключает питание esp8266. Когда требуется перепрошить ESP12, то приходится выполнять такую последовательность: «Отключите CH_PD от питания, подключите GPIO0 модуля к GND, подключите обратно CH_PD модуля.» Мне приходилось просто отключать питание ESP12. Повторять это последовательность по двадцать раз кряду — сильно утомляет. Кнопка с фиксацией на CH_PD/EN и светодиод индикации питания решила бы все проблемы. В принципе, можно использовать USB хаб с кнопками вкл/выкл для питания такой платы. Это удобно. В третьих, здесь не помешали бы подтягивающие резисторы на свободных GPIO. В HiZ состоянии они смогут значительно уменьшить энергопотребление. Если даже они не нужны, то их можно и не впаивать.

К преимуществам данной схемы я могу отнести то, что режим энергосбережения deep sleep здесь работает без каких-либо вопросов. Сам бы я не скоро догадался, что для этого надо ставить резистор на GPIO16.

Вариант платы который у меня получился по этой схеме:

Здесь есть линейный стабилизатор на 3.3 В, кнопка Reset, джампер на GPIO_0, и штыревой разъём для USB-UART преобразователя на чипе FT232RL.

Как я уже сказал, не хватает кнопки питания.

Ещё хотелось бы коснуться темы автозагрузки прошивки в ESP8266, т.е. когда не надо вручную соединять GPIO_0 с землёй для перепрошивки. В статье: «ESP8266 — подключение и обновление прошивки – esp8266» предлагается такая схема с автозагрузкой прошивки:

В руководстве Ai-Thinker я нашёл на мой взгляд более грамотную, схему узла автозагрузки:

В любом случае, для дальнейшей работы вполне сгодится недорогая плата NodeMCU, в которой есть эта самая автозагрузка (правда там не работает ражим энергосбережения «deep sleep»).

2) Формат загрузочного лога, режимы работы SPI флеш-памяти

Для того что бы можно было приступить к изучению AT-команд ESP8266, сначала нужно научиться перепрошивать этот самый ESP8266. Актуальная на настоящий момент версия AT-интерпретатора — 1.7.0, и мне хотелось бы рассказывать о работе именно с этой версией AT-интерпретатора.

Если вы только что приобрели модуль ESP12, то там уже должен быть уже прошит интерпретатор AT-команд, скорее всего какой-нибудь старой версии. В модулях которые я приобрёл, прошивка оказалось годичной давности.

Нам потребуется терминальная программа, и т.к. в дальнейшем все-равно придётся использовать Arduino IDE, то я буду использовать монитор последовательного порта Arduino IDE.

После подключения к ESP12, в мониторе последовательного порта нужно будет выставить окончание строки: «NL & CR» и скорость порта 115200 бод. После нужно подать команду: «AT» и в ответ должно прийти «ОК»:

Если отклик «OK» был получен, то ваш модуль ESP12 в порядке и можно начинать работу с ним. В противном случае попробуйте перезагрузить ESP8266 и попробовать снова.

Предположим, что ваш модуль в порядке. Для начала полезно будет взглянуть на загрузочный лог. Для этого смените скорость порта в терминальной программе на 74880 бод и нажмите Reset для перезагрузки ESP8266. В терминале появится такой лог:

 ets Jan  8 2013,rst cause:2, boot mode:(3,6)

load 0x40100000, len 2408, room 16 
tail 8
chksum 0xe5
load 0x3ffe8000, len 776, room 0 
tail 8
chksum 0x84
load 0x3ffe8310, len 632, room 0 
tail 8
chksum 0xd8
csum 0xd8

2nd boot version : 1.6
  SPI Speed      : 40MHz
  SPI Mode       : QIO
  SPI Flash Size & Map: 32Mbit(512KB+512KB)
jump to run user1 @ 1000

rf cal sector: 1017
rf[112] : 00
rf[113] : 00
rf[114] : 01

SDK ver: 2.0.0(5a875ba) compiled @ Aug  9 2016 15:12:27
phy ver: 1055, pp ver: 10.2

"�j�� 

На что нужно смотреть в этом логе?

Версия загрузчика:

  2nd boot version : 1.6

Версия загрузчика, версия SDK и версия AT-интерфейса — это разные вещи. За формат загрузочного лога отвечает именно загрузчик. Актуальная на данный момент версия загрузчика — 1.7.

В данном случае загрузчик нам сразу печатает версию SDK:

  SDK ver: 2.0.0(5a875ba) compiled @ Aug  9 2016 15:12:27

Имеем SDK двухлетней давности, актуальная версия SDK на настоящий момент — 3.0.0.

  SPI Flash Size & Map: 32Mbit(512KB+512KB)

Это формат прошивки: имеется 32-мегабитная флешка, 512кБ отведено под SDK, ещё 512 кБ отведено под пользовательскую прошивку. Заметьте, это не тест. Вместо , 32Mbit может быть запросто и меньший размер при фактически 32Mbit флешке. Это нормально. Идём дальше:

  SPI Speed      : 40MHz
  SPI Mode       : QIO

Согласно документации на чип winbond 25q32 (Datasheet) может работать на максимальной частоте 100MHz. При этом поддерживаются четыре режима работы: Stndard SPI, Dual SPI, Quad SPI и QPI. Dual SPI эквивалентен скорости работы: частота SPI x 2. Режимы Quad и QPI эквивалентны по скорости работы: частота SPI x 4. «Расплатой» за такие фокусы служит использование дополнительных GPIO для обмена. В вики проекта esptool имеется табличка с режимами работы флеш-памяти ESP8266:

Option Mode Name Pins Used Speed (ESP8266 & ESP32)
qio Quad I/O 4 pins used for address & data Fastest
qout Quad Output 4 pins used for data Approx 15% slower than qio
dio Dual I/O 2 pins used for address & data Approx 45% slower than qio
dout Dual Output 2 pins used for data Approx 50% slower than qio

Судя по этой публикации: «Новые ревизии модулей на базе ESP8266 не умеют писать в SPI Flash», сейчас в ESP модулях используется флешка PUYA P25Q80 (Datasheet). С ней могут быть нюансы. Еще одним нюансом является то, что при использовании флешки на 4 мегабайта и больше, следует использовать режим DIO.

В вики сайта esp8266.com имеется карта памяти ESP8266 с определением границ различных регионов, составленная в результате исследования чипа. Я приведу её сокращённую версию взятую из статьи — «Reverse Engineering ESP8266 — часть 1»:

Диапазон Описание
0x3FFE8000

0x3FFFBFFF
оперативная память для пользовательских приложений. При старте модуля может инициализироваться значениями из пользовательской прошивки.
0x3FFFC000

0x3FFFFFFF
системная оперативная память
0x40000000

0x4000FFFF
системный ROM. Отсюда стартует процессор, загружается пользовательская прошивка и здесь находятся основные системные библиотеки.
0x40100000

0x4010FFFF
оперативная память, содержит пользовательскую прошивку
0x40240000

0x40271FFF
вторая часть пользовательской прошивки. Здесь находятся код подключенных библиотек и SDK. Подмаплено к flash по адресу 40000h.

В логе печатается результат проверки контрольных сумм регионов: iram1 и dram0. Контрольной суммой является результат последовательно выполнения операции исключающего ИЛИ (XOR).

load 0x40100000, len 2408, room 16 
tail 8
chksum 0xe5
load 0x3ffe8000, len 776, room 0 
tail 8
chksum 0x84
load 0x3ffe8310, len 632, room 0 
tail 8
chksum 0xd8
csum 0xd8

Теперь обратим внимание на эту строку загрузчика:

jump to run user1 @ 1000

Здесь осуществляется переход на пользовательскую программу, в данном случае это AT-интерпретатор.

"�j�� 

Это выводится слово: «ready».

3) Баг в Linux драйвере USB-UART преобразователя CP2102

Сейчас я хочу рассказать об одной проблеме, которая касается только Linux-пользователей. Linux-драйвер USB-UART преобразователя CP2102, который используется в платах NodeMCU не умеет работать на скорости 74880 бод. Проявляется это в такой ошибке:

Я проверял на трёх чипах CP2102, все они выдавали такую ошибку. Это означает, что скорость 74880 бод на них не работает. И например лог загрузки такой платы выглядит так:

Здесь нечитаемыми символами идёт вывод версии SDK. На первый взгляд проблема может показаться несущественной. Но когда вы прошьёте ESP8266 какой-нибудь глючной прошивкой, то ошибки вам будут сыпаться именно на скорости 74880. И вы их прочитать не сможете. Повторю ещё раз, что эта проблема имеется только в Linux-драйвере. В Windows всё работает как часы. Версия моего ядра: 4.4.12, надеюсь в более свежих версиях этот баг уже исправлен.

4) Использование esptool

Для прошивки ESP8266 будем использовать флешер — esptool. Это программа с открытым кодом компании «Espressif Systems». Домашняя страница проекта: https://github.com/espressif/esptool. Программа устанавливается следующей командой:

$ pip install esptool

Проверяем:

$ esptool.py -h
usage: esptool [-h] [--port PORT] [--baud BAUD]
               {load_ram,dump_mem,read_mem,write_mem,write_flash,run,image_info,make_image,elf2image,read_mac,chip_id,flash_id,read_flash,verify_flash,erase_flash,version}
               ...

esptool.py v1.2 - ESP8266 ROM Bootloader Utility

positional arguments:
  {load_ram,dump_mem,read_mem,write_mem,write_flash,run,image_info,make_image,elf2image,read_mac,chip_id,flash_id,read_flash,verify_flash,erase_flash,version}
                        Run esptool {command} -h for additional help
    load_ram            Download an image to RAM and execute
    dump_mem            Dump arbitrary memory to disk
    read_mem            Read arbitrary memory location
    write_mem           Read-modify-write to arbitrary memory location
    write_flash         Write a binary blob to flash
    run                 Run application code in flash
    image_info          Dump headers from an application image
    make_image          Create an application image from binary files
    elf2image           Create an application image from ELF file
    read_mac            Read MAC address from OTP ROM
    chip_id             Read Chip ID from OTP ROM
    flash_id            Read SPI flash manufacturer and device ID
    read_flash          Read SPI flash content
    verify_flash        Verify a binary blob against flash
    erase_flash         Perform Chip Erase on SPI flash
    version             Print esptool version

optional arguments:
  -h, --help            show this help message and exit
  --port PORT, -p PORT  Serial port device
  --baud BAUD, -b BAUD  Serial port baud rate used when flashing/reading

Подключим ESP8266 к компьютеру и попробуем установить контакт:

$ esptool.py chip_id
esptool.py v1.2
Connecting...
Chip ID: 0x0041280f
$ esptool.py flash_id
esptool.py v1.2
Connecting...
Manufacturer: ef
Device: 4016

Перед вводом команд нужно выполнить процедуру: «а) отключить питание от ESP8266; б) установить перемычку между GPIO_0 и GND; в) включить питание на ESP8266; г) перед вводом команды нажать Reset, подождать одну секунду, и нажать enter для ввода команды». Такую процедуру следует повторять каждый раз при использовании esptool. Для возвращения в нормальный режим работы следует выполнить обратную последовательность: «а) отключить питание от ESP8266; б) убрать перемычку с пинов GPIO_0 и GND; в) включить питание на ESP8266». Если необходимо выполнить несколько команд, то переключаться каждый раз между нормальным и режимом прошивки не нужно. Переключаетесь в режим прошивки, после чего жмёте reset перед каждой командой. Если у вас плата NodeMCU или любая другая плата с возможностью автоматической прошивки, то ничего этого делать не надо, там всё делается автоматически.

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

$ esptool.py --port /dev/ttyUSB0 read_flash 0x00000 0x400000 ./esp8266_firmware.bin

Здесь первое число 0х00000 — это начальный адрес для считывания, второе число 0х400000 — это размер прошивки т.е. 4 мегабайта.

После ввода команды запустится процесс считывания прошивки который займёт примерно минут пять или шесть:

esptool.py v1.2
Connecting...
Running Cesanta flasher stub...
Reading 4194304 @ 0x0... 4194304 (100 %)
Read 4194304 bytes at 0x0 in 391.9 seconds (85.6 kbit/s)..

5) Первый способ прошивки

Теперь мы можем уже что-нибудь прошить. Поначалу, прошивки которые лежат на сайте «Espressif Systems» у меня сыпали логами с ошибками (с последней прошивкой, которая была выложена на сайте Espressif в августе (SDK 3.0.0) в самом деле имеются сложности, но об этом позже), собирать прошивку самому у меня не было желания, поэтому самым простым способом оказалось взять прошивку на сайте ElectroDragon: «ESP8266 AT-Command firmware — ElectroDragon». Там имеется хорошая вики с инструкций по прошивке.

На сайте ElectroDragon: «ESP8266 AT-Command firmware — ElectroDragon» имеется две прошивки, первая подчёркнута красным, вторая обведена синим:

Самый простой способ прошивки — это прошивка одним файлом, как прошиваются микроконтроллеры. С ESP8266 тоже можно так работать. Скачаем и распакуем второй файл, который подчёркнут красным (альтернативная ссылка). Там будут два файла: AiThinker_ESP8266_DIO_32M_32M_20160615_V1.5.4.bin, AiThinker_ESP8266_DIO_8M_8M_20160615_V1.5.4.bin и Readme следующего содержания:

******************************************************************
AiThinker_ESP8266_DIO_8M_8M_20160615_V1.5.4.bin

MD5: 8E9E9252317A9BCA67673C17B9E3E075

FirmWare Infomation:
SPI MODE: DIO
Flash Size: 8Mbit
File Size: 8Mbit
SPI SPEED: 40MHz
SDK Version: V1.5.4
Release Date: 2016.6.15

******************************************************************
AiThinker_ESP8266_DIO_32M_32M_20160615_V1.5.4.bin

MD5: B561B49242DC88EA5CBFCAB0CF287BF5

FirmWare Infomation:
SPI MODE: DIO
Flash Size: 32Mbit
File Size: 32Mbit
SPI SPEED: 40MHz
SDK Version: V1.5.4
Release Date: 2016.6.15

******************************************************************

How to download:
1. Please select the firmware in ESP_DOWNLOAD_TOOL_V2.4;
2. The address should write 0x00000;
3. If you don’t know how to config your download panel, please checked the «DoNotChgBin». That will be download the bin as default setting.

More infomation please visit http://www.ai-thinker.com/
If you have any question, please send your mail to support@aithinker.com

Файлы AiThinker_ESP8266_DIO_32M_32M_20160615_V1.5.4.bin, AiThinker_ESP8266_DIO_8M_8M_20160615_V1.5.4.bin это прошивки для плат с флешками на 8Mbit и 32Mbit. В разделе «FirmWare Infomation» указаны режимы флеш-памяти для прошивки. Т.к. на ESP12 установлена флешка на 32Mbit, то нам для прошивки понадобится файл: «AiThinker_ESP8266_DIO_32M_32M_20160615_V1.5.4.bin».

Проверяем контрольную сумму:

$ md5sum AiThinker_ESP8266_DIO_32M_32M_20160615_V1.5.4.bin
b561b49242dc88ea5cbfcab0cf287bf5  AiThinker_ESP8266_DIO_32M_32M_20160615_V1.5.4.bin

Ок. Контрольная сумма совпадает. Тогда прошиваем следующей командой:

esptool.py --port /dev/ttyUSB0 --baud 115200 write_flash -fm dio -ff 40m -fs 32m 0x00000 ./AiThinker_ESP8266_DIO_32M_32M_20160615_V1.5.4.bin 

Здесь опции: «-fm dio -ff 40m -fs 32m» задают режим работы флеш памяти, которые были указаны в «FirmWare Infomation». Число 0х00000 — это адрес с которого начинается запись. После ввода команды запустится счётчик с процентами выполнения. Процесс прошивки займёт опять же минут пять или шесть:

esptool.py v1.2
Connecting...
Running Cesanta flasher stub...
Flash params set to 0x0240
Writing 4194304 @ 0x0... 4194304 (100 %)
Wrote 4194304 bytes at 0x0 in 362.7 seconds (92.5 kbit/s)...
Leaving...

После завершения прошивки открываем терминал и вводим тестовую команду «AT», если в ответ пришло «OK», значит все в порядке, у нас все получилось.

Далее нам понадобится справочник по AT командам. Они варьируются в зависимости от версии SDK, но мы пока будем использовать только самые базовые. Справочник нужно будет скачать с сайта «Espressif Systems»:

Прямая ссылка на актуальную версию справочника — ESP8266 AT Instruction Set.

Команды АТ-интерфейса можно сравнить с переменными, функциями или может быть с функторами в обычной программе. Соответственно, у этих функций/команд можно запросить текущие параметры (Query Command), тогда после имени команды используется знак вопроса. Можно назначить свои параметры (Set Command), когда после имени команды используется символ «=». Можно запустить команду на выполнение (Execute Command). Также имеется тест команды (Test Command») когда проверяется, поддерживается ли данная команда данным АТ-интерпретатором. Для теста используется комбинация символов: «=?». Не все команды поддерживают все четыре типа обращения к ним, поэтому некоторые из них выглядят как операторы, другие как переменные, третьи как функторы.

Первым делом нам понадобится информация о версиях имеющегося на борту ПО. Она извлекается с помощью команды: AT+GMR

AT+GMR — Вывод информации о версиях ПО

Execute Command: AT+GMR
Отклик: <AT version info>
<SDK version info>
<compile time>
OK
Параметры: • <AT version info>: версия AT-интерпретатора.

• <SDK version info>: версия SDK.

• <compile time>: дата компиляции BIN-файла.

Выполняем:

AT+GMR
AT version:1.1.0.0(May 11 2016 18:09:56)
SDK version:1.5.4(baaeaebb)
Ai-Thinker Technology Co. Ltd.
Jun 13 2016 11:29:20
OK

На сайте ElectroDragon: «ESP8266 AT-Command firmware — ElectroDragon» прошивки время от времени обновляются, вот отчёт о версиях ПО прошивки которую я брал там летом:

AT+GMR

AT version:0.40.0.0(Aug  8 2015 14:45:58)
SDK version:1.3.0
Ai-Thinker Technology Co.,Ltd.
Build:1.3.0.2 Sep 11 2015 11:48:04
OK

Вот ещё отчёт прошивки которая была зашита к купленных мною модулях:

AT+GMR

AT version:1.3.0.0(Jul 14 2016 18:54:01)
SDK version:2.0.0(5a875ba)
Farylink Technology Co., Ltd. v1.0.0.2
May 11 2017 22:23:58
OK

Я думаю, что если бы это были оригинальные модули Ai-Thinker, то здесь бы не стояло упоминание какой-то непонятной фирмы: «Farylink Technology Co., Ltd.»

Теперь для обновления прошивки из «облака» нам понадобиться подключиться к интернет. Для этого нам понадобится следующие команды:

AT+CWMODE_CUR — Установка текущего режима Wi-Fi; Конфигурация НЕ СОХРАНЯЕТСЯ во флеш-памяти

Команды: Test Command:
AT+CWMODE_CUR=?
Query Command:
AT+CWMODE_CUR?
Назначение: запрашивает текущий режим работы Wi-Fi ESP8266.
Set Command:
AT+CWMODE_CUR=<режим>
Назначение: устанавливает текущий режим работы Wi-Fi ESP8266.
Отклик: +CWMODE_CUR:<режим>
OK
+CWMODE_CUR:<режим>
OK
OK
Параметры: <режим>:
‣ 1: Station mode
‣ 2: SoftAP mode
‣ 3: SoftAP+Station mode
Замечания: Конфигурация НЕ СОХРАНЯЕТСЯ во флеш-памяти
Примеры: AT+CWMODE_CUR=3

AT+CWMODE_DEF — Установка режима Wi-Fi по умолчанию; Конфигурация сохраняется во флеш-памяти

Команды: Test Command:
AT+CWMODE_DEF=?
Query Command:
AT+CWMODE_DEF?
Назначение: запрашивает текущий режим работы Wi-Fi ESP8266.
Set Command:
AT+CWMODE_DEF=<режим>
Назначение: устанавливает режим работы Wi-Fi по умолчанию.
Отклик: +CWMODE_DEF:<режим>
OK
+CWMODE_DEF:<режим>
OK
OK
Параметры: <режим>:
‣ 1: Station mode
‣ 2: SoftAP mode
‣ 3: SoftAP+Station mode
Замечания: Изменённое значение будет сохранено в области параметров
Примеры: AT+CWMODE_DEF=3

Устанавливаем режим клиента (Station):

AT+CWMODE_CUR=1 

OK

Поверяем:

AT+CWMODE_CUR? 
+CWMODE_CUR:1

OK

Смотрим какой режим работы Wifi установлен по умолчанию:

AT+CWMODE_DEF? 
+CWMODE_DEF:2

OK

Теперь нам нужно найти точку доступа. Делается это с помощью команды AT+CWLAP:

AT+CWLAP — вывод списка точек доступа WiFi

Команды: Set Command:
AT+CWLAP[=<ssid>,<mac>,<channel>,<scan_type>, <scan_time_min>,<scan_time_max>]
Действие: выполняет поиск точки
доступа с определённым SSID
и/или MAC-адресом, на определённом канале.
Execute Command:
AT+CWLAP
Действие: выводит список всех доступных точек доступа WiFi.
Отклик: +CWLAP:<ecn>,<ssid>,<rssi>,<mac>,<channel>,
<freq offset>,<freq cali>,
<pairwise_cipher>,<group_cipher>,<bgn>,<wps>

OK

+CWLAP:<ecn>,<ssid>,<rssi>,<mac>,<channel>,
<freq offset>,<freq cali>,
<pairwise_cipher>,<group_cipher>,<bgn>,<wps>

OK

Параметры:
  • [<scan_type>]: не обязательный параметр
    ‣ 0: активное сканирование
    ‣ 1: пассивное сканирование
  • [<scan_time_min>] : не обязательный параметр, задаётся в мс, диапазон: [0,1500]
    ‣ При активном сканировании, <scan_time_min> задаёт минимальное время сканирования каждого канала, по умолчанию равно 0
    ‣ При пассивном сканировании, значение параметра <scan_time_min> не имеет значения и оно может быть пропущено.
  • [<scan_time_max>] : не обязательный параметр, задаётся в мс, диапазон: [0,1500]
    ‣ При активном сканировании, <scan_time_max> задаёт максимальное время сканирования для каждого канала; если значение сброшено в ноль, то будет использоваться значение по умолчанию 120 мс.
    ‣ При пассивном сканировании, <scan_time_max> задаёт время сканирования каждого канала, по умолчанию используется значение в 360 мс
  • <ecn>: метод шифрования:
    ‣ 0: OPEN
    ‣ 1: WEP
    ‣ 2: WPA_PSK
    ‣ 3: WPA2_PSK
    ‣ 4: WPA_WPA2_PSK
    ‣ 5: WPA2_Enterprise (AT can NOT connect to WPA2_Enterprise AP for now.)
  • <ssid>: строковый параметр, задаёт SSID точки доступа.
  • <rssi>: уровень сигнала.
  • <mac>: строковый параметр, задаёт MAC адрес точки доступа.
  • <channel>: номер канала.
  • <freq offset>: frequency offset of AP; unit: KHz. The value of ppm is <freq offset>/2.4.
  • <freq calibration>: calibration for frequency offset.
  • <pairwise_cipher>:
    ‣ 0:CIPHER_NONE
    ‣ 1:CIPHER_WEP40
    ‣ 2:CIPHER_WEP104
    ‣ 3:CIPHER_TKIP
    ‣ 4:CIPHER_CCMP
    ‣ 5:CIPHER_TKIP_CCMP
    ‣ 6:CIPHER_UNKNOWN
  • <group_cipher>:задаёт тип шифра, значения такие же как и для <pairwise_cipher>
  • <bgn>:
    ‣ bit0 управляет 802.11b режимом; bit1 управляет 802.11g режимом; bit2 управляет 802.11n режимом;
    ‣ Если значение bit установлено в 1, то соответствующий 802.11 режим будет включён; Если бит будет сброшен в ноль, соответствующий 802.11 режим будет отключён.
  • <wps>:0 — WPS будет отключено; 1 — WPS будет включено.
Примеры: поиск определённой точки доступа:
AT+CWLAP=»Wi-Fi»,»ca:d7:19:d8:a6:44″,6
или поиск точки доступа по SSID:
AT+CWLAP=»Wi-Fi»
или включение режима пассивного сканирования:
AT+CWLAP=,,,1,,

Сканируем воздух:

AT+CWLAP

+CWLAP:(4,"ROSTELECOM_F0DB",-89,"2c:e4:12:3d:f0:dc",1,-24,0)
+CWLAP:(4,"TP-LINK_A469B8",-92,"b0:48:7a:a4:69:b8",1,11,0)
+CWLAP:(4,"WiFi-DOM.ru-5723",-89,"cc:7b:36:b3:1f:79",1,-9,0)
+CWLAP:(4,"Russkikh",-93,"f0:b4:29:d6:8d:f2",1,-4,0)
+CWLAP:(4,"WiFi-DOM.ru-1784",-84,"ac:64:62:83:19:08",2,13,0)
+CWLAP:(3,"Keenetic-7788",-91,"04:bf:6d:97:08:e4",4,21,0)
+CWLAP:(3,"servant",-75,"14:cc:20:33:44:4e",6,11,0)
+CWLAP:(4,"WiFi-DOM.ru-5838",-92,"d4:76:ea:20:02:38",6,-19,0)
+CWLAP:(4,"ASUS",-90,"00:1a:2b:3c:ff:02",7,6,0)
+CWLAP:(4,"elektrik018",-87,"f0:7d:68:95:b8:e2",9,-7,0)
+CWLAP:(4,"DOM.RU",-89,"c0:4a:00:4d:3f:7c",10,20,0)
+CWLAP:(3,"NETGEAR_146",-76,"c4:3d:c7:8f:44:74",11,-2,0)
+CWLAP:(3,"Alien",-22,"00:90:4c:c1:00:00",11,10,0)
+CWLAP:(4,"WiFi-DOM.ru-1587",-85,"a0:ec:81:23:5a:b1",11,1,0)
+CWLAP:(4,"Brute",-59,"40:f2:01:c1:25:2b",11,10,0)
+CWLAP:(4,"WiFi-DOM.ru-8332",-79,"20:89:87:94:d6:ed",11,-12,0)
+CWLAP:(3,"MTSRouter-9B1812",-90,"1c:5f:2b:9b:18:12",13,6,0)

OK

AT+CWJAP_CUR — подключение к точке доступа, конфигурация НЕ сохраняется во флеш-памяти

Команды: Query Command:
AT+CWJAP_CUR?
Действие: печатает точку доступа к которой в данный момент подключён ESP8266.
Set Command:
AT+CWJAP_CUR=<ssid>,<pwd>,[<bssid>][,<pci_en>]
Действие: подключается к указанной точке доступа.
Отклик: +CWJAP_CUR:<ssid>,<bssid>,<channel>,<rssi>

OK

OK

или

+CWJAP_CUR:<error code>

FAIL

Параметры: <ssid>: строковый параметр показывающий SSID целевой точки доступа.
  • <ssid>: SSID целевой точки доступа.
  • <pwd>: пароль, максимум 64 символа ASCII.
  • [<bssid>]: опциональный параметр к качестве которого используется MAC-адрес целевой точки доступа. Используется когда несколько точек доступа имеют одинаковый SSID.
  • [<pci_en>]: опциональный параметр который отключает подключение по WEP и к открытым точкам доступа. Может использоваться для PCI аутентификация.
  • <error code>: (for reference only)
    ‣ 1: истечение таймаута.
    ‣ 2: неверный пароль.
    ‣ 3: не получается найти точку доступа.
    ‣ 4: ошибка соединения.

Эта команда требует чтобы ESP8266 находился в режиме клиента (Station). Эскейп-последовательности используются, когда SSID или пароль содержат в себе специальные символы, такие как: , или ” или .

Замечания: Изменения конфигурации НЕ сохраняются во флеш-памяти.
Примеры: AT+CWJAP_CUR=»abc»,»0123456789″

К примеру, для подключения к точке доступа: «ab,c» с паролем: «0123456789»», следует выполнить следующую команду:

AT+CWJAP_CUR=»ab\,c»,»0123456789″\»

Если несколько точект доступа имеют одинаковый SSID: «abc», то подключиться можно через BSSID:

AT+CWJAP_CUR=»abc»,»0123456789″,»ca:d7:19:d8:a6:44″

AT+CWJAP_DEF — подключение к точке доступа, конфигурация сохраняется во флеш-памяти

Команды: Query Command:
AT+CWJAP_DEF?
Действие: печатает точку доступа к которой в данный момент подключён ESP8266.
Set Command:
AT+CWJAP_DEF=<ssid>,<pwd>,[<bssid>][,<pci_en>]
Действие: подключается к указанной точке доступа.
Отклик: +CWJAP_DEF:<ssid>,<bssid>,<channel>,<rssi>

OK

OK

или

+CWJAP_DEF:<error code>

FAIL

Параметры: <ssid>: строковый параметр показывающий SSID целевой точки доступа.
  • <ssid>: SSID целевой точки доступа.
  • <pwd>: пароль, максимум 64 символа ASCII.
  • [<bssid>]: опциональный параметр к качестве которого используется MAC-адрес целевой точки доступа. Используется когда несколько точек доступа имеют одинаковый SSID.
  • [<pci_en>]: опциональный параметр который отключает подключение по WEP и к открытым точкам доступа. Может использоваться для PCI аутентификация.
  • <error code>: (for reference only)
    ‣ 1: истечение таймаута.
    ‣ 2: неверный пароль.
    ‣ 3: не получается найти точку доступа.
    ‣ 4: ошибка соединения.

Эта команда требует чтобы ESP8266 находился в режиме клиента (Station). Эскейп-последовательности используются, когда SSID или пароль содержат в себе специальные символы, такие как: , или ” или .

Замечания: Изменения конфигурации сохранются во флеш-памяти.
Примеры: AT+CWJAP_DEF=»abc»,»0123456789″

К примеру, для подключения к точке доступа: «ab,c» с паролем: «0123456789»», следует выполнить следующую команду:

AT+CWJAP_DEF=»ab\,c»,»0123456789″\»

Если несколько точек доступа имеют одинаковый SSID: «abc», то подключиться можно через BSSID:

AT+CWJAP_DEF=»abc»,»0123456789″,»ca:d7:19:d8:a6:44″

Подключаемся к точке доступа:

AT+CWJAP_CUR="Alien","password"
WIFI CONNECTED
WIFI GOT IP

OK

Далее смотрим IP адрес который получил ESP8266:

AT+CIFSR — показать локальный IP адрес

Execute Command: AT+CIFSR
Отклик: +CIFSR:APIP,<SoftAP IP address>
+CIFSR:APMAC,<SoftAP MAC address>
+CIFSR:STAIP,<Station IP address>
+CIFSR:STAMAC,<Station MAC address>
OK
Параметры: <IP address>:
IP адрес ESP8266 в режиме SoftAP;
IP адрес ESP8266 в режиме клиента (Station)
<MAC address>:
MAC адрес ESP8266 в режиме SoftAP;
MAC адрес ESP8266 в режиме клиента (Station).
Замечания: Station IP можно получить только когда ESP8266 находится в режиме клиента и при этом подключён к точке доступа
AT+CIFSR 
+CIFSR:STAIP,"192.168.1.125"
+CIFSR:STAMAC,"60:01:94:41:28:0f"

OK

Пробуем достучаться до интернета :

AT+PING — посылка Ping пакета

Set Command: AT+PING=<IP>
Действие: посылка ping пакета.
Отклик: +<time>

OK

или

+timeout

ERROR

Параметры:
  • <IP>: IP хоста или имя домена
  • <time>: время отклика на ping
Примеры: AT+PING=»192.168.1.1″

AT+PING=»www.baidu.com»

AT+PING="ya.ru" 
+32

OK

Обновление прошивки из «облака» осуществляется с помощью команды CIUPDATE:

AT+CIUPDATE — Обновление прошивки через Wi-Fi

Execute Command: AT+CIUPDATE

Действие: обновление ПО

Отклик: +CIPUPDATE:<n>

OK

Параметры отклика:
  • <n>:
    ‣ 1: поиск сервера.
    ‣ 2: подключение к серверу.
    ‣ 3: запрос версии ПО.
    ‣ 4: запуск обновления.
Замечания:
  • Скорость обновления зависит от скорости интернет-соединения.
  • ERROR будет возвращён, если обновление прервётся из-за неудовлетворительного интернет-соединения. Подождите некоторое время, прежде чем повторять попытку.
Замечания:
  • При использовании Espressif’s AT BIN (/ESP8266_NONOS_SDK/bin/at), команда AT+CIUPDATE загрузит новый AT BIN из облака Espressif.
  • Если используется скомпилированная самостоятельно прошивка AT BIN, то самостоятельно нужно скомпилировать и обновление для AT+CIUPDATE. Espressif предоставляет в SDK пример локального обновления в (/ESP8266_NONOS_SDK/example/at).
  • После обновления рекомендуется выполнить AT+RESTORE для восстановления установок по умолчанию.

Обновляем:

AT+CIUPDATE 
+CIPUPDATE:1
+CIPUPDATE:2
+CIPUPDATE:3
+CIPUPDATE:4

OK

Обновление занимает где-то одну минуту. После обновления выполняем сброс настроек:

AT+RESTORE — Сброс к заводским настройкам

Execute Command: AT+RESTORE
Отклик: OK
Параметры: Выполнение этой команды сбросит все настройки сохранённые на флешке, что вернёт прошивку к заводским настройкам. После выполнения команды чип будет перезагружен.

В случае, если использовались команды с суффиксом CUR, то для сброса будет достаточно обычного Reset:

AT+RST — Перезагрузка модуля

Execute Command: AT+RST
Отклик: OK
Параметры: отсутствуют

Выполняем сброс:

Обратите внимание, что вектор старта программы изменился с 0х01000 на 0х81000. Если теперь перешить загрузчик который вернёт вектор старта на 0х01000, то будет запускаться старая прошивка. Т.е. она никуда не делась.

Проверяем версии ПО:

AT+GMR
AT version:1.2.0.0(Jul  1 2016 20:04:45)
SDK version:1.5.4.1(39cb9a32)
Ai-Thinker Technology Co. Ltd.
v1.5.4.1-a Nov 30 2017 15:54:51
OK

Обновился AT-интерпретатор с версии «AT version:1.1.0.0(May 11 2016 18:09:56)» до «AT version:1.2.0.0(Jul 1 2016 20:04:45)». Негусто.

6) Второй способ прошивки

На самом деле ESP8266 почти никогда не прошивается одним файлом. Во-первых это долго, во-вторых неудобно. ESP8266 прошивается по регионам. Загрузчик в один регион, SDK в другой, AT-bin в третий. Это быстрее и удобнее, хотя поначалу может сбить с толку. Исключением является создание и восстановление backup прошивки.

Скачаем теперь с сайта «ESP8266 AT-Command firmware — ElectroDragon» прошивку обведённую синим (альтернативная ссылка):

После распаковки архива у нас будет следующая структура файлов и каталогов:

$ tree .
.
└── 
    ├── 
    │   ├── user1.2048.new.5.bin
    │   └── user2.2048.new.5.bin
    ├── 
    │   ├── user1.1024.new.2.bin
    │   └── user2.1024.new.2.bin
    ├── README.md
    ├── blank.bin
    ├── boot_v1.5.bin
    ├── esp_init_data_default.bin
    └── 
        ├── eagle.flash.bin
        └── eagle.irom0text.bin

4 directories, 11 files

Подозреваю, что предполётный инструктаж будет находится в файле README.md:

# BOOT MODE
## download
### Flash size 8Mbit: 512KB+512KB
boot_v1.2+.bin 0x00000
user1.1024.new.2.bin 0x01000
esp_init_data_default.bin 0xfc000 (optional)
blank.bin 0x7e000 & 0xfe000

### Flash size 16Mbit: 512KB+512KB
boot_v1.2+.bin 0x00000
user1.1024.new.2.bin 0x01000
esp_init_data_default.bin 0x1fc000 (optional)
blank.bin 0x7e000 & 0x1fe000

### Flash size 16Mbit-C1: 1024KB+1024KB
boot_v1.2+.bin 0x00000
user1.2048.new.5.bin 0x01000
esp_init_data_default.bin 0x1fc000 (optional)
blank.bin 0xfe000 & 0x1fe000

### Flash size 32Mbit: 512KB+512KB
boot_v1.2+.bin 0x00000
user1.1024.new.2.bin 0x01000
esp_init_data_default.bin 0x3fc000 (optional)
blank.bin 0x7e000 & 0x3fe000

### Flash size 32Mbit-C1: 1024KB+1024KB
boot_v1.2+.bin 0x00000
user1.2048.new.5.bin 0x01000
esp_init_data_default.bin 0x3fc000 (optional)
blank.bin 0xfe000 & 0x3fe000

# NON-BOOT MODE
## download
eagle.flash.bin 0x00000
eagle.irom0text.bin 0x10000
blank.bin
Flash size 8Mbit: 0x7e000 & 0xfe000
Flash size 16Mbit: 0x7e000 & 0x1fe000
Flash size 16Mbit-C1: 0xfe000 & 0x1fe000
Flash size 32Mbit: 0x7e000 & 0x3fe000
Flash size 32Mbit-C1: 0xfe000 & 0x3fe000
esp_init_data_default.bin (optional)
Flash size 8Mbit: 0xfc000
Flash size 16Mbit: 0x1fc000
Flash size 16Mbit-C1: 0x1fc000
Flash size 32Mbit: 0x3fc000
Flash size 32Mbit-C1: 0x3fc000

## compile
modify eagle.app.v6.ld, as
irom0_0_seg : org = 0x40210000, len = 0x6C000

NOTICE: UPDATE is not supported in non-boot mode; 4Mbit Flash is not supported in non-boot mode;

# Update steps
1.Make sure TE(terminal equipment) is in sta or sta+ap mode

AT+CWMODE=3
OK

2.Make sure TE got ip address

AT+CWJAP=»ssid»,»12345678″
OK

AT+CIFSR
192.168.1.134

3.Let’s update

AT+CIUPDATE
+CIPUPDATE:1 found server
+CIPUPDATE:2 connect server
+CIPUPDATE:3 got edition
+CIPUPDATE:4 start start

OK

NOTICE: If there are mistakes in the updating, then break update and print ERROR.

Т.к. у нас флешка на 32Mbit, нас будет интересовать фрагмент выделенный красным.

Очищаем флешку:

$ esptool.py -p /dev/ttyUSB0 erase_flash
esptool.py v1.2
Connecting...
Running Cesanta flasher stub...
Erasing flash (this may take a while)...
Erase took 6.8 seconds

После чего, руководствуясь адресами в выделенном красным фрагменте, составляем следующую команду:

$ esptool.py -p /dev/ttyUSB0 write_flash -fm dio -ff 40m -fs 32m 0x00000 ./AT_bin/boot_v1.5.bin 0x01000 ./AT_bin/512+512/user1.1024.new.2.bin  0x3fc000 ./AT_bin/esp_init_data_default.bin 0x7e000 ./AT_bin/blank.bin 0x3fe000 ./AT_bin/blank.bin

Прошиваем:

$ esptool.py -p /dev/ttyUSB0 write_flash -fm dio -ff 40m -fs 32m 0x00000 ./AT_bin/boot_v1.5.bin 0x01000 ./AT_bin/512+512/user1.1024.new.2.bin  0x3fc000 ./AT_bin/esp_init_data_default.bin 0x7e000 ./AT_bin/blank.bin 0x3fe000 ./AT_bin/blank.bin 
esptool.py v1.2
Connecting...
Running Cesanta flasher stub...
Flash params set to 0x0240
Writing 4096 @ 0x0... 4096 (100 %)
Wrote 4096 bytes at 0x0 in 0.4 seconds (90.5 kbit/s)...
Writing 401408 @ 0x1000... 401408 (100 %)
Wrote 401408 bytes at 0x1000 in 34.7 seconds (92.6 kbit/s)...
Writing 4096 @ 0x3fc000... 4096 (100 %)
Wrote 4096 bytes at 0x3fc000 in 0.4 seconds (90.4 kbit/s)...
Writing 4096 @ 0x7e000... 4096 (100 %)
Wrote 4096 bytes at 0x7e000 in 0.4 seconds (90.3 kbit/s)...
Writing 4096 @ 0x3fe000... 4096 (100 %)
Wrote 4096 bytes at 0x3fe000 in 0.4 seconds (90.5 kbit/s)...
Leaving...

Проверяем:

AT

OK

AT+GMR

AT version:1.1.0.0(May 11 2016 18:09:56)
SDK version:1.5.4(baaeaebb)
compile time:May 20 2016 15:06:44
OK

Далее, так же как предыдущем случае обновляем прошивку:

AT+CWMODE_CUR=1


OK
AT+CWLAP

+CWLAP:(4,"WiFi-DOM.ru-5723",-90,"cc:7b:36:b3:1f:79",1,-9,0)
+CWLAP:(3,"DIR-48",-91,"28:10:7b:f2:65:ea",1,13,0)
+CWLAP:(4,"WiFi-DOM.ru-1784",-87,"ac:64:62:83:19:08",2,21,0)
+CWLAP:(3,"Keenetic-4263",-91,"10:7b:ef:5d:17:64",3,3,0)
+CWLAP:(3,"Keenetic-7788",-90,"04:bf:6d:97:08:e4",4,20,0)
+CWLAP:(3,"servant",-79,"14:cc:20:33:44:4e",6,11,0)
+CWLAP:(4,"Super S",-83,"f8:1a:67:50:32:ee",6,10,0)
+CWLAP:(4,"WiFi-DOM.ru-5838",-92,"d4:76:ea:20:02:38",6,-17,0)
+CWLAP:(4,"WiFi-DOM.ru-8332",-81,"20:89:87:94:d6:ed",11,-12,0)
+CWLAP:(4,"Brute",-67,"40:f2:01:c1:25:2b",11,10,0)
+CWLAP:(4,"ROSTELECOM_F0DB",-87,"2c:e4:12:3d:f0:dc",11,-24,0)
+CWLAP:(3,"Alien",-33,"00:90:4c:c1:00:00",11,10,0)
+CWLAP:(3,"Дмитрий",-87,"d4:6e:0e:64:e5:86",12,3,0)

OK
AT+CWJAP_CUR="Alien","password"

WIFI CONNECTED
WIFI GOT IP

OK
AT+CIFSR

+CIFSR:STAIP,"192.168.1.125"
+CIFSR:STAMAC,"60:01:94:41:28:0f"

OK
AT+PING="ya.ru"

+34

OK
AT+CIUPDATE

+CIPUPDATE:1
+CIPUPDATE:2
+CIPUPDATE:3
+CIPUPDATE:4

ERROR
AT+PING="ya.ru"

+33

OK
AT+CIUPDATE

+CIPUPDATE:1
+CIPUPDATE:2
+CIPUPDATE:3
+CIPUPDATE:3
+CIPUPDATE:4

OK

По логу видно что в даннном случае не обошлось без ошибки при обновлении. Процедуру пришлось повторять. И несмотря на то, что я использовал команды с суффиксом CUR, после перезагрузки ESP8266 вновь подключается в точке доступа.

Делаем RESTORE, затем смотрим на версии того что прилетело по воздуху:

AT+GMR
AT version:1.6.2.0(Apr 13 2018 11:10:59)
SDK version:2.2.1(6ab97e9)
compile time:Jun  7 2018 19:34:27
Bin version(Wroom 02):1.6.2
OK

Вот это уже лучше, прошивка этого года. Пробуем дать команду из свежего SDK:

AT+SYSRAM — Проверка оставшейся свободной памяти в ОЗУ

Query Command: AT+SYSRAM?
Отклик: +SYSRAM:<remaining RAM size>

OK

Параметры отклика: <remaining RAM size>: оставшаяся свободная память в байтах.

Выполняем:

AT+SYSRAM? 
+SYSRAM:33432

OK

Имеем свободные 32 кбайта ОЗУ. Это уже что-то.

7) Третий способ прошивки

На самом деле, совсем не обязательно так все усложнять, мне просто хотелось показать процесс обновления прошивки «по воздуху». Прошивки с такой возможностью таки и называются: «over the air» или «OTA».

Для загрузки нужной прошивки мы можем зайти на сайт ESP8266EX Resources | Espressif Systems и скачать прошивку нужной версии. В этом случае ничего обновлять уже не придётся.

Как я уже говорил, с прошивкой AT-интерпретатора последней версии 1.7 имеются проблемы, она не поддерживает флешки 32Mbit, но мы можем загрузить прошивку версии 1.6. Это та же версия, что мы получили через обновление, но стартовать она будет с адреса 0x01000, а не 0х81000.

Скачиваем прошивку версии 1.6.2:

$ esptool.py -p /dev/ttyUSB0 write_flash -fm dio -ff 40m -fs 32m 0x00000 ./boot_v1.7.bin  0x01000 ./at/512+512/user1.1024.new.2.bin   0x3fc000 ./esp_init_data_default_v05.bin 0x7e000 ./blank.bin 0x3fe000 ./blank.bin

После распаковки архива видим следующую структуру файлов и каталогов:

$ tree .
.
├── 
│   ├── 
│   │   ├── user1.2048.new.5.bin
│   │   └── user2.2048.new.5.bin
│   ├── 
│   │   ├── user1.1024.new.2.bin
│   │   └── user2.1024.new.2.bin
│   └── README.md
├── 
│   ├── 
│   │   ├── user1.2048.new.5.bin
│   │   └── user2.2048.new.5.bin
│   ├── 
│   │   ├── user1.1024.new.2.bin
│   │   └── user2.1024.new.2.bin
│   └── README.md
├── blank.bin
├── boot_v1.2.bin
├── boot_v1.6.bin
├── boot_v1.7.bin
├── esp_init_data_default_v05.bin
└── esp_init_data_default_v08.bin

6 directories, 16 files

В README.md имеются следующие указания для нашей флешки:

### Flash size 32Mbit: 512KB+512KB
boot_v1.2+.bin 0x00000
user1.1024.new.2.bin 0x01000
esp_init_data_default.bin 0x3fc000 (optional)
blank.bin 0x7e000 & 0x3fe000

В соответствии с этими указаниями, составляем команду для прошивки ESP8266:

$ esptool.py -p /dev/ttyUSB0 write_flash -fm dio -ff 40m -fs 32m 0x00000 ./boot_v1.7.bin  0x01000 ./at/512+512/user1.1024.new.2.bin   0x3fc000 ./esp_init_data_default_v05.bin 0x7e000 ./blank.bin 0x3fe000 ./blank.bin

Прошивка занимает примерно секунд сорок. После перезагрузки сразу будет доступен AT-интерпретатор версии 1.6.2.

8) Прошивка модуля ESP12E AT-интерпретатором версии 1.7.0

Если верить примечанию к выпуску, АT-интерпретатор на SDK версии 3.0.0 примечателен оптимизацией работы с ОЗУ в результате чего экономится около 17 кБайт(!) ОЗУ. Кроме того, имеются какие-то сложности с форматом прошивки из-за чего рекомендуется использовать формат 16Mbit или 32Mbit-C1.

К сожалению, формат 32MBit-C1 использовать не получилось. Здесь: Flashing AT 1.7.0 binary firmware in 32m-c1 mode not working было подсказано временное решение — использовать формат 16Mbit-C1.

После распаковки архива с прошивкой получаем следующую структуру каталогов:

$ tree .
.
├── 
│   ├── 
│   │   ├── user1.2048.new.5.bin
│   │   └── user2.2048.new.5.bin
│   └── README.md
├── 
│   ├── 
│   │   ├── user1.2048.new.5.bin
│   │   └── user2.2048.new.5.bin
│   └── README.md
├── blank.bin
├── boot_v1.2.bin
├── boot_v1.6.bin
├── boot_v1.7.bin
├── esp_init_data_default_v05.bin
└── esp_init_data_default_v08.bin

4 directories, 12 files

В README.md для формата 16Mbit-C1 указаны следующие границы регионов:

### Flash size 16Mbit-C1: 1024KB+1024KB
boot_v1.2+.bin 0x00000
user1.2048.new.5.bin 0x01000
esp_init_data_default.bin 0x1fc000
blank.bin 0xfe000 & 0x1fe000

Прошиваем ESP8266 следующей командой:

$ esptool.py -p /dev/ttyUSB0 write_flash -fm qio -ff 40m -fs 16m-c1  0x00000 ./boot_v1.7.bin  0x01000 ./at/1024+1024/user1.2048.new.5.bin  0x1fc000 ./esp_init_data_default_v05.bin 0xfe000 ./blank.bin 0x1fe000 ./blank.bin

После прошивки получаем следующий лог загрузки:

Проверяем версии SDK и AT-интерпретатора:

AT+GMR
AT version:1.7.0.0(Aug 16 2018 00:57:04)
SDK version:3.0.0(d49923c)
compile time:Aug 23 2018 16:58:12
Bin version(Wroom 02):v1.7.0
OK

Смотрим на размер свободной ОЗУ:

AT+SYSRAM?
+SYSRAM:68304

OK

Как видно, «лёгким движением руки», свободная память увеличилась до 65 кБайт.

Настройка OpenWRT

# ifconfig
br-lan    Link encap:Ethernet  HWaddr 00:90:4C:C0:00:00  
          inet addr:192.168.1.10  Bcast:192.168.1.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:586247 errors:0 dropped:172 overruns:0 frame:0
          TX packets:765349 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:80654767 (76.9 MiB)  TX bytes:927523774 (884.5 MiB)

eth0      Link encap:Ethernet  HWaddr 00:90:4C:C0:00:00  
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1211990 errors:0 dropped:5813 overruns:0 frame:0
          TX packets:989428 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:1049054139 (1000.4 MiB)  TX bytes:570831642 (544.3 MiB)
          Interrupt:4 

eth0.1    Link encap:Ethernet  HWaddr 00:90:4C:C0:00:00  
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:336656 errors:0 dropped:0 overruns:0 frame:0
          TX packets:409897 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:64973771 (61.9 MiB)  TX bytes:475515814 (453.4 MiB)

eth0.2    Link encap:Ethernet  HWaddr 00:90:4C:C0:00:00  
          inet addr:192.168.1.2  Bcast:192.168.1.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:870395 errors:0 dropped:414 overruns:0 frame:0
          TX packets:580252 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:953212514 (909.0 MiB)  TX bytes:87848472 (83.7 MiB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:1478 errors:0 dropped:0 overruns:0 frame:0
          TX packets:1478 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:138346 (135.1 KiB)  TX bytes:138346 (135.1 KiB)

wlan0     Link encap:Ethernet  HWaddr 00:90:4C:C1:00:00  
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:262475 errors:0 dropped:0 overruns:0 frame:0
          TX packets:371714 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:32 
          RX bytes:29702085 (28.3 MiB)  TX bytes:467137364 (445.4 MiB)
# df -h
Filesystem                Size      Used Available Use% Mounted on
rootfs                    2.0G     80.4M      1.8G   4% /
/dev/root                 2.0M      2.0M         0 100% /rom
tmpfs                    14.3M    592.0K     13.7M   4% /tmp
tmpfs                   512.0K         0    512.0K   0% /dev
/dev/sda2                 2.0G     80.4M      1.8G   4% /
/dev/sda3                 1.6G     37.2M      1.5G   2% /home
# cat /etc/config/network 

config switch 'eth0'
        option name 'eth0'
        option reset '1'
        option enable_vlan '1'

config switch_vlan
        option device 'eth0'
        option vlan '1'
        option ports '1 2 3 4 5t'

config switch_vlan
        option device 'eth0'
        option vlan '2'
        option ports '0 5t'

config interface 'loopback'
        option ifname 'lo'
        option proto 'static'
        option ipaddr '127.0.0.1'
        option netmask '255.0.0.0'

config globals 'globals'
        option ula_prefix 'fdf3:a699:4f2f::/48'

config interface 'lan'
        option ifname 'eth0.1'
        option force_link '1'
        option type 'bridge'
        option proto 'static'
        option ipaddr '192.168.1.10'
        option netmask '255.255.255.0'
        option dns '78.85.0.1'
        option ip6assign '60'

config interface 'wan'
        option ifname 'eth0.2'
        option proto 'dhcp'

# cat /etc/config/fstab 
global automount
        option from_fstab 1
        option anon_mount 0
        
config global autoswap
        option from_fstab 1
        option anon_swap 0
                
config mount
        option target   /
        option device   /dev/sda2
        option fstype   ext3
        option options  rw,sync
        option enabled  1
        option enabled_fsck 0
                                                
config mount
        option target   /home
        option device   /dev/sda3
        option fstype   ext3
        option options  rw,sync
        option enabled  1
        option enabled_fsck 0
                                        
config swap
        option device   /dev/sda1
        option enabled  1
# free
             total         used         free       shared      buffers
Mem:         29268        23160         6108            0         3572
-/+ buffers:              19588         9680
Swap:       102396            0       102396
# netstat -l 
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       
tcp        0      0 0.0.0.0:www             0.0.0.0:*               LISTEN      
tcp        0      0 0.0.0.0:domain          0.0.0.0:*               LISTEN      
tcp        0      0 OpenWrt.lan:ssh         0.0.0.0:*               LISTEN      
netstat: /proc/net/tcp6: No such file or directory
udp        0      0 0.0.0.0:domain          0.0.0.0:*                           
udp        0      0 0.0.0.0:bootps          0.0.0.0:*                           
udp        0      0 0.0.0.0:ntp             0.0.0.0:*                           
netstat: /proc/net/udp6: No such file or directory
netstat: /proc/net/raw6: No such file or directory
Active UNIX domain sockets (only servers)
Proto RefCnt Flags       Type       State         I-Node Path
unix  2      [ ACC ]     STREAM     LISTENING        652 /var/run/ubus.sock
# cat /etc/config/wireless 

config wifi-device 'radio0'
        option type 'mac80211'
        option macaddr '00:90:4c:c1:00:00'
        option channel '11'

config wifi-iface
        option device 'radio0'
        option network 'lan'
        option mode 'ap'
        option ssid 'Alien'
        option encryption 'psk2'
        option key 'password'
config system
        option hostname 'OpenWrt'
        option zonename 'Europe/Samara'
        option timezone 'SAMT-4'
        option conloglevel '8'
        option cronloglevel '8'

config timeserver 'ntp'
        list server '0.openwrt.pool.ntp.org'
        list server '1.openwrt.pool.ntp.org'
        list server '2.openwrt.pool.ntp.org'
        list server '3.openwrt.pool.ntp.org'
        option enabled '1'
        option enable_server '1'
# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere            ctstate RELATED,ESTABLISHED 
ACCEPT     all  --  anywhere             anywhere            
syn_flood  tcp  --  anywhere             anywhere            tcp flags:FIN,SYN,RST,ACK/SYN 
input_rule  all  --  anywhere             anywhere            
input      all  --  anywhere             anywhere            

Chain FORWARD (policy DROP)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere            ctstate RELATED,ESTABLISHED 
forwarding_rule  all  --  anywhere             anywhere            
forward    all  --  anywhere             anywhere            
reject     all  --  anywhere             anywhere            

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere            ctstate RELATED,ESTABLISHED 
ACCEPT     all  --  anywhere             anywhere            
output_rule  all  --  anywhere             anywhere            
output     all  --  anywhere             anywhere            

Chain forward (1 references)
target     prot opt source               destination         
zone_lan_forward  all  --  anywhere             anywhere            
zone_wan_forward  all  --  anywhere             anywhere            

Chain forwarding_lan (1 references)
target     prot opt source               destination         

Chain forwarding_rule (1 references)
target     prot opt source               destination         

Chain forwarding_wan (1 references)
target     prot opt source               destination         

Chain input (1 references)
target     prot opt source               destination         
zone_lan   all  --  anywhere             anywhere            
zone_wan   all  --  anywhere             anywhere            

Chain input_lan (1 references)
target     prot opt source               destination         

Chain input_rule (1 references)
target     prot opt source               destination         

Chain input_wan (1 references)
target     prot opt source               destination         

Chain output (1 references)
target     prot opt source               destination         
zone_lan_ACCEPT  all  --  anywhere             anywhere            
zone_wan_ACCEPT  all  --  anywhere             anywhere            

Chain output_rule (1 references)
target     prot opt source               destination         

Chain reject (5 references)
target     prot opt source               destination         
REJECT     tcp  --  anywhere             anywhere            reject-with tcp-reset 
REJECT     all  --  anywhere             anywhere            reject-with icmp-port-unreachable 

Chain syn_flood (1 references)
target     prot opt source               destination         
RETURN     tcp  --  anywhere             anywhere            tcp flags:FIN,SYN,RST,ACK/SYN limit: avg 25/sec burst 50 
DROP       all  --  anywhere             anywhere            

Chain zone_lan (1 references)
target     prot opt source               destination         
input_lan  all  --  anywhere             anywhere            
zone_lan_ACCEPT  all  --  anywhere             anywhere            

Chain zone_lan_ACCEPT (5 references)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            

Chain zone_lan_DROP (0 references)
target     prot opt source               destination         
DROP       all  --  anywhere             anywhere            
DROP       all  --  anywhere             anywhere            

Chain zone_lan_REJECT (0 references)
target     prot opt source               destination         
reject     all  --  anywhere             anywhere            
reject     all  --  anywhere             anywhere            

Chain zone_lan_forward (1 references)
target     prot opt source               destination         
zone_wan_ACCEPT  all  --  anywhere             anywhere            
forwarding_lan  all  --  anywhere             anywhere            
zone_lan_ACCEPT  all  --  anywhere             anywhere            

Chain zone_wan (1 references)
target     prot opt source               destination         
ACCEPT     udp  --  anywhere             anywhere            udp dpt:bootpc 
ACCEPT     icmp --  anywhere             anywhere            icmp echo-request 
ACCEPT     igmp --  anywhere             anywhere            
input_wan  all  --  anywhere             anywhere            
zone_wan_REJECT  all  --  anywhere             anywhere            

Chain zone_wan_ACCEPT (2 references)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            

Chain zone_wan_DROP (0 references)
target     prot opt source               destination         
DROP       all  --  anywhere             anywhere            
DROP       all  --  anywhere             anywhere            

Chain zone_wan_REJECT (2 references)
target     prot opt source               destination         
reject     all  --  anywhere             anywhere            
reject     all  --  anywhere             anywhere            

Chain zone_wan_forward (1 references)
target     prot opt source               destination         
zone_lan_ACCEPT  esp  --  anywhere             anywhere            
zone_lan_ACCEPT  udp  --  anywhere             anywhere            udp dpt:isakmp 
forwarding_wan  all  --  anywhere             anywhere            
zone_wan_REJECT  all  --  anywhere             anywhere 
# cat  /etc/config/firewall 
config defaults
        option syn_flood        1
        option input            ACCEPT
        option output           ACCEPT
        option forward          REJECT
# Uncomment this line to disable ipv6 rules
#       option disable_ipv6     1

config zone
        option name             lan
        list   network          'lan'
        option input            ACCEPT
        option output           ACCEPT
        option forward          ACCEPT

config zone
        option name             wan
        list   network          'wan'
        list   network          'wan6'
        option input            REJECT
        option output           ACCEPT
        option forward          REJECT
        option masq             1
        option mtu_fix          1

config forwarding
        option src              lan
        option dest             wan

# We need to accept udp packets on port 68,
# see https://dev.openwrt.org/ticket/4108
config rule
        option name             Allow-DHCP-Renew
        option src              wan
        option proto            udp
        option dest_port        68
        option target           ACCEPT
        option family           ipv4

# Allow IPv4 ping
config rule
        option name             Allow-Ping
        option src              wan
        option proto            icmp
        option icmp_type        echo-request
        option family           ipv4
        option target           ACCEPT

config rule
        option name             Allow-IGMP
        option src              wan
        option proto            igmp
        option family           ipv4
        option target           ACCEPT

# Allow DHCPv6 replies
# see https://dev.openwrt.org/ticket/10381
config rule
        option name             Allow-DHCPv6
        option src              wan
        option proto            udp
        option src_ip           fe80::/10
        option src_port         547
        option dest_ip          fe80::/10
        option dest_port        546
        option family           ipv6
        option target           ACCEPT

config rule
        option name             Allow-MLD
        option src              wan
        option proto            icmp
        option src_ip           fe80::/10
        list icmp_type          '130/0'
        list icmp_type          '131/0'
        list icmp_type          '132/0'
        list icmp_type          '143/0'
        option family           ipv6
        option target           ACCEPT

# Allow essential incoming IPv6 ICMP traffic
config rule
        option name             Allow-ICMPv6-Input
        option src              wan
        option proto    icmp
        list icmp_type          echo-request
        list icmp_type          echo-reply
        list icmp_type          destination-unreachable
        list icmp_type          packet-too-big
        list icmp_type          time-exceeded
        list icmp_type          bad-header
        list icmp_type          unknown-header-type
        list icmp_type          router-solicitation
        list icmp_type          neighbour-solicitation
        list icmp_type          router-advertisement
        list icmp_type          neighbour-advertisement
        option limit            1000/sec
        option family           ipv6
        option target           ACCEPT

# Allow essential forwarded IPv6 ICMP traffic
config rule
        option name             Allow-ICMPv6-Forward
        option src              wan
        option dest             *
        option proto            icmp
        list icmp_type          echo-request
        list icmp_type          echo-reply
        list icmp_type          destination-unreachable
        list icmp_type          packet-too-big
        list icmp_type          time-exceeded
        list icmp_type          bad-header
        list icmp_type          unknown-header-type
        option limit            1000/sec
        option family           ipv6
        option target           ACCEPT

# include a file with users custom iptables rules
config include
        option path /etc/firewall.user


### EXAMPLE CONFIG SECTIONS
# do not allow a specific ip to access wan
#config rule
#       option src              lan
#       option src_ip   192.168.45.2
#       option dest             wan
#       option proto    tcp
#       option target   REJECT

# block a specific mac on wan
#config rule
#       option dest             wan
#       option src_mac  00:11:22:33:44:66
#       option target   REJECT

# block incoming ICMP traffic on a zone
#config rule
#       option src              lan
#       option proto    ICMP
#       option target   DROP

# port redirect port coming in on wan to lan
#config redirect
#       option src                      wan
#       option src_dport        80
#       option dest                     lan
#       option dest_ip          192.168.16.235
#       option dest_port        80
#       option proto            tcp

# port redirect of remapped ssh port (22001) on wan
#config redirect
#       option src              wan
#       option src_dport        22001
#       option dest             lan
#       option dest_port        22
#       option proto            tcp

# allow IPsec/ESP and ISAKMP passthrough
config rule
        option src              wan
        option dest             lan
        option proto            esp
        option target           ACCEPT

config rule
        option src              wan
        option dest             lan
        option dest_port        500
        option proto            udp
        option target           ACCEPT

### FULL CONFIG SECTIONS
#config rule
#       option src              lan
#       option src_ip   192.168.45.2
#       option src_mac  00:11:22:33:44:55
#       option src_port 80
#       option dest             wan
#       option dest_ip  194.25.2.129
#       option dest_port        120
#       option proto    tcp
#       option target   REJECT

#config redirect
#       option src              lan
#       option src_ip   192.168.45.2
#       option src_mac  00:11:22:33:44:55
#       option src_port         1024
#       option src_dport        80
#       option dest_ip  194.25.2.129
#       option dest_port        120
#       option proto    tcp

9) Связка OpenWRT + ESP8266, использование сниффера tcpdump и анализатора Wireshark для исследования трафика ESP8266

У меня имеется точка доступа с установленной OpenWRT. Это позволяет мне полностью контролировать трафик идущий с ESP8266. OpenWRT, кстати, в наши времена можно установить почти на любую «кофеварку». Народ изгаляется и ставит OpenWRT на всякое барахло: Руководство по доведению «до кондиции» клона популярного китайского мини-роутера Hame A15, он же «unbranded A5-V11», я же пользуюсь классикой — DIR-320 rev.A2. DIR-320 имеет репутацию «неубиваемого роутера». Даже после прошивки его в OpenWRT, все-равно можно вызвать родной загрузчик для восстановления прошивки. Это часто выручало меня на первых порах, когда в результате неудачной настройки, до OpenWRT становилось невозможно достучаться из сети.

Установка OpenWRT на роутер позволяет, по сути, превратить его в одноплатный компьютер. У меня установлена версия «Attitude Adjustment 12.09», в качестве корневого раздела используется флешка на 4 GB. Это позволяет устанавливать приложения без оглядки на занимаемое ими пространство, кроме того, на роутере можно размещать простенькие сайты, для которых не планируется высокая загруженность. OpenWRT может работать в паре с ESP8266, беря на работу по парсингу страниц, работу с защищенными соединениями и разграничении подсетей.

Итак, сбрасываем ESP8266 командой: «AT+RESTORE», на OpenWRT запускаем tcpdump командой: «tcpdump -i wlan0 -n», после чего ESP8266 подключаем точке доступа с OpenWRT:

AT+CWMODE_CUR=1

OK
AT+CWJAP="Alien","password"
WIFI CONNECTED
WIFI GOT IP

OK

Syslog в OpenWRT выводится по команде: «logread», и в данном случае, при подключении ESP8266 можно будет увидеть следующую картинку:

Nov 10 08:30:20 OpenWrt daemon.info hostapd: wlan0: STA 60:01:94:41:28:0f IEEE 802.11: authenticated
Nov 10 08:30:20 OpenWrt daemon.info hostapd: wlan0: STA 60:01:94:41:28:0f IEEE 802.11: associated (aid 1)
Nov 10 08:30:20 OpenWrt daemon.info hostapd: wlan0: STA 60:01:94:41:28:0f WPA: pairwise key handshake completed (RSN)
Nov 10 08:30:20 OpenWrt daemon.info dnsmasq-dhcp[2108]: DHCPDISCOVER(br-lan) 60:01:94:41:28:0f 
Nov 10 08:30:20 OpenWrt daemon.info dnsmasq-dhcp[2108]: DHCPOFFER(br-lan) 192.168.1.11 60:01:94:41:28:0f 
Nov 10 08:30:20 OpenWrt daemon.info dnsmasq-dhcp[2108]: DHCPREQUEST(br-lan) 192.168.1.11 60:01:94:41:28:0f 
Nov 10 08:30:20 OpenWrt daemon.info dnsmasq-dhcp[2108]: DHCPACK(br-lan) 192.168.1.11 60:01:94:41:28:0f ESP12_A

Здесь, сначала через демон hostapd устанавливается беспроводное соединение. MAC адрес «60:01:94:41:28:0f» в данном случае — это мой ESP8266. После чего, DHCP в соответствии с моей настройкой, выдает клиенту с данным MAC адресом локальный IP «192.168.1.11» и обозначает его хост как «ESP12_A». За этот процесс отвечает следующее правило в /etc/config/dhcp:

config host
        option name 'ESP12_A'
        option mac '60:01:94:41:28:0f'
        option ip '192.168.1.11'

Замечу, что для поддержки WiFi у меня в OpenWRT установлен пакет wpad-mini, который обеспечивает минимальный функционал и не занимает много места.

tcpdump при этом выдаёт нам следующий лог:

08:30:20.171350 60:01:94:41:28:0f > ff:ff:ff:ff:ff:ff Null Unnumbered, xid, Flags [Response], length 6: 01 00
08:30:20.183276 EAPOL key (3) v2, len 95
08:30:20.188693 EAPOL key (3) v1, len 117
08:30:20.194392 EAPOL key (3) v2, len 151
08:30:20.200214 EAPOL key (3) v1, len 95
08:30:20.257746 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 60:01:94:41:28:0f, length 308
08:30:20.258239 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 60:01:94:41:28:0f, length 308
08:30:20.261535 IP 192.168.1.10.67 > 192.168.1.11.68: BOOTP/DHCP, Reply, length 300
08:30:20.273383 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 60:01:94:41:28:0f, length 308
08:30:20.273797 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 60:01:94:41:28:0f, length 308
08:30:20.280894 IP 192.168.1.10.67 > 192.168.1.11.68: BOOTP/DHCP, Reply, length 300
08:30:20.286433 ARP, Request who-has 192.168.1.11 tell 0.0.0.0, length 28
08:30:20.286763 ARP, Request who-has 192.168.1.11 tell 0.0.0.0, length 28
08:30:20.473236 ARP, Request who-has 192.168.1.11 tell 0.0.0.0, length 28
08:30:20.473464 ARP, Request who-has 192.168.1.11 tell 0.0.0.0, length 28
08:30:20.973475 ARP, Request who-has 192.168.1.11 tell 192.168.1.11, length 28
08:30:20.973769 ARP, Request who-has 192.168.1.11 tell 192.168.1.11, length 28

Пока клиент не авторизируется, то он может общатся только на протоколе EAPOL, через который в данном случае происходит авторизация. После авторизации идет получение параметров сети через BOOTP-протокол.

С помощью tcpdump можно записать сессию в отдельный файл, что бы потом его можно было внимательно исследовать в программе-анализаторе трафика Wireshark. Выполняем в OpenWRT команду:

# tcpdump -i wlan0 -n -w alien.cap

После завершения сессии, копируем файл alien.cap на локальную машину:

$ scp root@alien:/root/alien.cap ./

Затем открываем файл alien.cap в Wireshark.

Wireshark это ещё один «швейцарский нож» который умеет декодировать множество сетевых протоколов. Для примера, посмотрим на запрос к DHCP и увидим в теле сообщения запрашиваемые параметры:

В ответе DHCP сервера видим какие параметры ему предложили для работы в сети:

Ок, идём дальше. Посмотрим какие DNS использует ESP8266:

AT+CIPDNS_CUR — Задание пользовательских DNS серверов, настройки НЕ сохраняются во флеш-памяти

Команды: Query Command:
AT+CIPDNS_CUR?
Действие: показать текущие DNS сервера
Set Command:
AT+CIPDNS_CUR=<enable>[,<DNS server0>,<DNS server1>]
Действие: задать пользовательские DNS сервера
Отклик: [+CIPDNS_CUR:<DNS server0>]

[+CIPDNS_CUR:<DNS server1>]

OK

OK
Параметры:
  • <enable>:

    ‣ 0: отключает заданные пользователем DNS сервера;
    ‣ 1: включает заданные пользователем DNS сервера.

  • <DNS server0>: необязательный параметр, задание первого DNS сервера;
  • <DNS server1>: необязательный параметр, задание второго DNS сервера.
Примеры AT+CIPDNS_CUR=1,»208.67.220.220″
Замечания:
  • При команде: AT+CIPDNS_CUR=0 (отключает заданные пользователем DNS сервера), будет использован DNS сервер по умолчанию: «208.67.222.222». Так же DNS сервер может быть задан роутером при конфигурации через DHCP.
  • При команде: AT+CIPDNS_CUR=1 (включает заданные пользователем DNS сервера, но параметр <DNS server> не задан), будет использоваться сервер: «208.67.222.222» как DNS сервер по умолчанию.

AT+CIPDNS_DEF — Задание пользовательских DNS серверов, настройки сохраняются во флеш-памяти

Команды: Query Command:
AT+CIPDNS_DEF?
Действие: показать текущие DNS сервера
Set Command:
AT+CIPDNS_DEF=<enable>[,<DNS server0>,<DNS server1>]
Действие: задать пользовательские DNS сервера
Отклик: [+CIPDNS_DEF:]

[+CIPDNS_DEF:<DNS server1>]

OK

OK
Параметры:
  • <enable>:

    ‣ 0: отключает заданные пользователем DNS сервера;
    ‣ 1: включает заданные пользователем DNS сервера.

  • <DNS server0>: необязательный параметр, задание первого DNS сервера;
  • <DNS server1>: необязательный параметр, задание второго DNS сервера.
Примеры AT+CIPDNS_DEF=1,»208.67.220.220″
Замечания:
  • Конфигурация будет сохранена во флеш-памяти.
  • При команде: AT+CIPDNS_CUR=0 (отключает заданные пользователем DNS сервера), будет использован DNS сервер по умолчанию: «208.67.222.222». Так же DNS сервер может быть задан роутером при конфигурации через DHCP.
  • При команде: AT+CIPDNS_CUR=1 (включает заданные пользователем DNS сервера, но параметр <DNS server> не задан), будет использоваться сервер: «208.67.222.222» как DNS сервер по умолчанию.

Смотрим какие DNS используются по умолчанию:

AT+CIPDNS_CUR?
+CIPDNS_CUR:192.168.1.10
+CIPDNS_CUR:208.67.222.222

OK

Первый сервер — это шлюз, второй — это сервер проекта OpenDNS.

Задаем DNS яндекса:

AT+CIPDNS_CUR=1,"77.88.8.8","77.88.8.1"

OK
AT+CIPDNS_CUR?
+CIPDNS_CUR:77.88.8.8
+CIPDNS_CUR:77.88.8.1

OK

Проверяем:

AT+PING="ya.ru"
+35

OK

В tcpdump при этом появляются следующие строки:

07:34:35.982725 IP 192.168.1.11.4096 > 77.88.8.8.53: 43482+ A? ya.ru. (23)
07:34:36.014821 IP 77.88.8.8.53 > 192.168.1.11.4096: 43482 1/0/0 A 87.250.250.242 (39)
07:34:36.018460 IP 192.168.1.11 > 87.250.250.242: ICMP echo request, id 44975, seq 1, length 40
07:34:36.050192 IP 87.250.250.242 > 192.168.1.11: ICMP echo reply, id 44975, seq 1, length 40

Здесь, в первой строке идёт запрос к нашему DNS-серверу, чтобы тот предоставил IP адрес сервера «ya.ru». Во второй строке DNS сервер возвращает IP адрес: «87.250.250.242» . В третей строке идет сам ICMP запрос, а в четвёртой — ответ. Всё работает.

10) Получение даты и времени через сеть, используя NTP

Одним из наиболее очевидным способов применения ESP8266 в электронике, на мой взгляд, является синхронизация RTC по сетевому протоколу NTP. Даже если вы используете RTC повышенной точности, например: DS3231, это не избавляет вас от нудной процедуры подводки часов, которая зачастую упирается в удобство интерфейса. Не во всех устройствах рационально прикручивать кейпад, для коррекции даты и времени.

Для работы с NTP серверами имеются следующие AT-команды:

AT+CIPSNTPCFG — настройка SNTP

Команды: Query Command:
AT+CIPSNTPCFG?
Set Command:
AT+CIPSNTPCFG=<enable>[,<timezone>][,<SNTP server0>,<SNTP server1>,<SNTP server2>]
Отклик: +CIPSNTPCFG:<enable>,<timezone>,<SNTP server1>[,<SNTP server2>,<SNTP server3>]

OK

OK
Параметры:
  • <enable>:

    ‣ 0: SNTP отключён;
    ‣ 1: SNTP включён.

  • <timezone>: часовой пояс; допустимые значения: [-11,13]; Если SNTP отключено, то <timezone> не используется
  • <SNTP server0>: необязательный параметр, задаёт первый SNTP сервер;
  • <SNTP server1>: необязательный параметр, задаёт второй SNTP сервер;
  • <SNTP server2>: необязательный параметр, задаёт третий SNTP сервер.
Примеры AT+CIPSNTPCFG=1,8,»cn.ntp.org.cn»,»ntp.sjtu.edu.cn»,»us.pool.ntp.org»
Замечания: Если параметры <SNTP server> не заданы, то по умолчанию будут использоваться следующие сервера: будут использоваться по: «cn.ntp.org.cn»,»ntp.sjtu.edu.cn», и «us.pool.ntp.org».

AT+CIPSNTPTIME — получение текущей даты и времени по SNTP

Query Command: AT+CIPSNTPTIME?
Отклик: +CIPSNTPTIME:<time>

OK

Параметры отклика: <time>: SNTP time

Например:

+CIPSNTPTIME: Thu Aug 04 14:48:05 2016

OK

Примеры использования: AT+CWMODE=1 //установить WiFi режим клиента

AT+CWJAP=»DemoAP»,»password» //подключиться к роутеру

AT+CIPSNTPCFG=1,8 //задать часовой пояс

AT+CIPSNTPTIME? //получить текущее время

OpenWRT может выступать в качестве SNTP сервера поэтому я указываю его адрес в качестве сервера, после чего запрашиваю текущее время:

OK
AT+CIPSNTPCFG=1,4,"192.168.1.10"

OK
AT+CIPSNTPTIME?
+CIPSNTPTIME:Sun Nov 11 21:59:56 2018
OK

В tcpdump при этом появляются следующие строки:

21:59:09.411350 IP 192.168.1.11.4097 > 192.168.1.10.123: NTPv4, Client, length 48
21:59:09.434194 IP 192.168.1.10.123 > 192.168.1.11.4097: NTPv4, Server, length 48

Здесь первая срока — это запрос к серверу, а вторая — ответ сервера.

11) Связь ESP8266 с Web сервером на OpenWrt: настройка OpenWRT

Теперь рассмотрим вопрос организации связи ESP8266 с точкой доступа на OpenWRT. Допустим, программа или скрипт на OpenWRT ищет какую-либо информацию в интернет, и через ESP8266 её нужно вывести на дисплей. В составе OpenWRT имеется Web сервер uhttpd на котором крутится веб интерфейс LUCI, его и будем использовать. Север настраивается через конфиг /etc/config/uhttpd. LUCI мы трогать не будем, вместо этого создадим конфиг для нового сайта. Для этого, в конфиг: /etc/config/uhttpd добавим следующий раздел:

config uhttpd 'site'
        list listen_http '0.0.0.0:8010'
        list listen_http '[::]:8010'
        option home '/site'
        option rfc1918_filter '1'
        option max_requests '3'
        option max_connections '25'
        option cgi_prefix '/cgi-bin'
        option script_timeout '60'
        option network_timeout '30'
        option http_keepalive '20'
        option tcp_keepalive '1'
        option ubus_prefix '/ubus

Как не трудно догадаться, директорией для сайта будет папка: «/site», директорией CGI будет папка: «/site/cgi-bin», а рабочим портом: «8010». Структура папки «site» пусть пока будет такой:

$ tree site 

├── 
├── index.html
└── 
    └── weather.txt

2 directories, 2 files

Где index.html — обычная «заглушка»:

<?xml version="1.0" encoding="utf-8"?>

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
</head>
<body style="background-color: white">
<h3>Hello World!</h3>
</body>
</html>

После редактирования конфига и добавления директории «/site», перезапускаем web-сервер:

# /etc/init.d/uhttpd restart

Проверяем:

# netstat -l 
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       
tcp        0      0 0.0.0.0:8010            0.0.0.0:*               LISTEN      
tcp        0      0 0.0.0.0:www             0.0.0.0:*               LISTEN      
tcp        0      0 0.0.0.0:domain          0.0.0.0:*               LISTEN      
tcp        0      0 OpenWrt.lan:ssh         0.0.0.0:*               LISTEN      
netstat: /proc/net/tcp6: No such file or directory
udp        0      0 0.0.0.0:domain          0.0.0.0:*                           
udp        0      0 0.0.0.0:bootps          0.0.0.0:*                           
udp        0      0 0.0.0.0:ntp             0.0.0.0:*                           
netstat: /proc/net/udp6: No such file or directory
netstat: /proc/net/raw6: No such file or directory
Active UNIX domain sockets (only servers)
Proto RefCnt Flags       Type       State         I-Node Path
unix  2      [ ACC ]     STREAM     LISTENING        650 /var/run/ubus.sock

Видим, что открыт наш порт 8010. Теперь с локальной машины пробуем с помощью curl подать на Web-сервер GET-запрос:

$ curl alien:8010
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
</head>
<body style="background-color: white">
<h3>Hello World!</h3>
</body>
</html>

В ответ мы получили свою html страницу, и значит, здесь все ОК. Ради любопытства посмотрим, что нам скажет nmap:

$ nmap -sV alien

Starting Nmap 7.12 ( https://nmap.org ) at 2018-11-12 13:10 +04
Nmap scan report for alien (192.168.1.10)
Host is up (0.00067s latency).
Not shown: 996 closed ports
PORT     STATE SERVICE VERSION
22/tcp   open  ssh     Dropbear sshd 2011.54 (protocol 2.0)
53/tcp   open  domain  dnsmasq 2.62
80/tcp   open  http    LuCI Lua http config
8010/tcp open  http    BusyBox http 1.19.4
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 46.36 seconds

Здесь на 80-м порту висит LUCI, а на 8010 наш сайт. Теперь можно подключиться к нему через ESP8266. Но для этого нам нужно будет ознакомится с набором AT-команд для установления TCP/UDP соединения.

АТ-команды для установки TCP/UDP соединения

Прежде всего хочу коснуться терминологии. В ESP8266 имеется два режима TCP/UDP соединения: обычный нормальный режим, и режим «UART-Wi-Fi passthrough», который также называется прозрачным (transparent mode). Режим «UART-Wi-Fi passthrough» это мостовое соединение вида: «UART over WIFI», этакий UART по воздуху. Фактически это выглядит как чат на две персоны. Включается он командой: «AT+CIPMODE=1», а выключается последовательностью: «+++». Сейчас мы режима «UART-Wi-Fi passthrough» касаться не будем, но он часто упоминается в описании команд, поэтому я предварительно решил рассказать о нем.

AT+CIPMUX — включение или отключение режима нескольких подключений

Команды: Query Command:

AT+CIPMUX?

Set Command:

AT+CIPMUX=<mode>

Действие: установить тип соединения

Отклик: +CIPMUX:<mode>

OK

OK
Параметры: <mode>:

‣ 0: режим одиночного подключения
‣ 1: режим нескольких подключений

Замечения:
  • По умолчанию используется режим одиночного соединения
  • Режим нескольких подключений может быть включен только тогда, когда отключен прозрачный режим (AT+CIPMODE=0).
  • Этот режим может быть изменен только после отключения отключения всех активных соединений.
  • Если включен TCP сервер, то его следует отключить (AT+CIPSERVER=0) перед тем, как устанавливать режим одиночного соединения.
Пример: AT+CIPMUX=1

AT+CIPMODE — установить режим соединения

Команды: Query Command:

AT+CIPMODE?

Действие: возвращает текущий режим соединения.

Set Command:

AT+CIPMODE=<mode>

Действие: устанавливает режим соединения.

Отклик: +CIPMODE:<mode>

OK

OK
Параметры: <mode>:

‣ 0: нормальный режим соединения.
‣ 1: UART-Wi-Fi passthrough mode (прозрачный режим соединения), может быть установлен при использовании режима одиночного соединения или в UDP режиме, когда удалённые IP-адрес и порт не могут быть изменены.

Замечения:
  • Конфигурация не сохраняется во флеш-памяти.
  • Если в при режиме «UART-Wi-Fi passthrough» рвётся связь, то ESP8266 пытается восстановить ее переподключением, до тех пор пока, не получит символы +++ которые означают завершение режима «UART-Wi-Fi passthrough» и возврат к нормальному режиму. При дисконнекте в нормальном режиме, ESP8266 не будет пытаться переподключиться заново.
Пример: AT+CIPMODE=1

AT+CIPSTART — установка TCP соединения, UDP передачи или SSL соединения

Установка TCP соединения

Set Command: Одиночное соединение (когда +CIPMUX=0):

AT+CIPSTART=<type>,<remote IP>,<remote port>[,<TCP keep alive>]

Множественное соединение: (когда +CIPMUX=1):

AT+CIPSTART=<link ID>,<type>,<remote IP>,<remote port>[,<TCP keep alive>]

Отклик: OK

или

ERROR

Если соединение уже было установлено, то вернет: ALREADY CONNECTED

Параметры:
  • <link ID>: ID соединения: от 0 до 4. Применимо только для множественного режима соединения.
  • <type>: строковый параметр указывающий тип соединения: «TCP», «UDP» или «SSL».
  • <remote IP>: строковый параметр содержащий удалённый IP адрес.
  • <remote port>: удаленный порт.
  • [<TCP keep alive>]: определение времени удержания TCP соединения: «keep-alive»; по умолчанию выключено.

    ‣ 0: отключение TCP keep-alive.
    ‣ 1 ~7200: определение интервала в секундах.

Примеры: AT+CIPSTART=»TCP»,»iot.espressif.cn»,8000
AT+CIPSTART=»TCP»,»192.168.101.110″,1000

Для большей информации смотрите документ: ESP8266 AT Command Examples

Установка UDP соединения

Set Command: Одиночное соединение (когда +CIPMUX=0):

AT+CIPSTART=<type>,<remote IP>,<remote port>[,(<UDP local port>),(<UDP mode>)]

Множественное соединение: (когда +CIPMUX=1):

AT+CIPSTART=<link ID>,<type>,<remote IP>,<remote port>[,(<UDP local port>),(<UDP mode>)]

Отклик: OK

или

ERROR

Если соединение уже было установлено, то вернет: ALREADY CONNECTED

Параметры:
  • <link ID>: ID соединения: от 0 до 4. Применимо только для множественного режима соединения.
  • <type>: строковый параметр указывающий тип соединения: «TCP», «UDP» или «SSL».
  • <remote IP>: строковый параметр содержащий удалённый IP адрес.
  • <remote port>: удаленный порт.
  • [<UDP local port>]: необязательный параметр, указывает UDP порт ESP8266.
  • [<UDP mode>]: необязательный параметр, для прозрачной UDP передачи должен быть сброшен в ноль.
    ‣ 0: целевой объект UDP передачи не может быть изменен; это значение используется по умолчанию.
    ‣ 1: целевой объект UDP передачи может быть изменен один раз.
    ‣ 2: целевой объект UDP передачи возможно менять.

Замечание: <UDP local port> должен быть задан перед <UDP mode>.

Примеры: AT+CIPSTART=»UDP»,»192.168.101.110″,1000,1002,2

Для большей информации смотрите документ: ESP8266 AT Command Examples

Установка SSL соединения

Set Command: AT+CIPSTART=[<link ID>,]<type>,<remote IP>,<remote port>[,<TCP keep alive>]
Отклик: OK

или

ERROR

Если соединение уже было установлено, то вернет: ALREADY CONNECTED

Параметры:
  • <link ID>: ID соединения: от 0 до 4. Применимо только для множественного режима соединения.
  • <type>: строковый параметр указывающий тип соединения: «TCP», «UDP» или «SSL».
  • <remote IP>: строковый параметр содержащий удалённый IP адрес.
  • <remote port>: удаленный порт.
  • [<TCP keep alive>]: определение времени удержания TCP соединения: «keep-alive»; по умолчанию выключено.

    ‣ 0: отключение TCP keep-alive.
    ‣ 1 ~7200: определение интервала в секундах.

Замечания:
  • ESP8266 может устанавливать только одно SSL соединение.
  • SSL не поддерживает режим прозрачного соединения (UART-Wi-Fi passthrough mode).
  • SSL соединению необходим большой объем памяти, иначе это может привести к перезагрузке ESP8266. Память для SSL соединения можно выделить командой AT+CIPSSLSIZE=<size>, где size — размер буфера.
Примеры: AT+CIPSTART=»SSL»,»iot.espressif.cn»,8443

AT+CIPSEND — отправка данных

Команды: Set Command:

  1. Одиночное соединение: (при +CIPMUX=0)
    AT+CIPSEND=<length>
  2. Множественные соединения:(при +CIPMUX=1)
    AT+CIPSEND=<link ID>,<length>
  3. При UDP сессии может быть указан удаленный IP-адрес и порт:
    AT+CIPSEND=[<link ID>,]<length> [,<remote IP>,<remote port>]

Действие: задание длины данных в нормальном режиме передачи (не «UART-WIFI passthrough mode»).

Execute Command: AT+CIPSEND
Действие: объявлет начало передачи данных в прозрачном режиме.
Отклик: Отправка данных определенной длины. Возвращает значок > после передачи «Set Command». Значок означает, что можно начать передавать данные. Когда длина данных достигнет размера заданного в параметре <length>, данные начнут передаваться. Если соединение не удастся установить или оно будет прервано, то будет возвращенно:

ERROR

Если данные были переданны успешно, то будет возвращенно:

SEND OK

Если же это не удалось, то вернется:

SEND FAIL

Возвращает значок «>» после подачи команды. После этого, ESP8266 удерживает соединение посылая пакеты с интервалом 20 мс и максимальной длиной пакета 2048 байт. Когда будет получен пакет содержащий три последовательных символа плюс: «+++», то соединение разрывается и ESP8266 возвращается в обычный командный режим.

Команда может использоваться только в прозрачном режиме которе требует одиночного режима соединения(+CIPMUX=0)

Для UDP режима, значение <UDP mode> должно быть установлено в нуль, прежде чем подавать команду AT+CIPSTART.

Параметры:
  • <link ID>: ID соединения: от 0 до 4. Применимо для множественного режима соединения.
  • <length>: длина данных, максимальное значение: 2048 байта.
  • [<remote IP>]: удаленный IP адрес, может быть установлен для UDP сессии.
  • [<remote port>]: удаленный порт, может быть установлен для UDP сессии.
Примеры: Для большей информации смотрите документ ESP8266 AT Command Examples.

AT+CIPCLOSE — Закрытие TCP/UDP/SSL соединения

Команды: Set Command (используется только при множественном соединении):

AT+CIPCLOSE=<link ID>

Действие: закрывает TCP/UDP соединение.(Про закрытие SSL соединения в оригинале ничего не сказано. Прим переводчика.)

Execute Command (используется только при множественном соединении):

AT+CIPCLOSE

Отклик: OK
Параметры: <link ID>: где ID это номер закрываемого соединения (от 1 до 4). Когда ID равен 5, то это означает, что нужно закрыть все соединения. В режиме сервера, ID=5 не имеет какого-либо эффекта.

AT+CWQAP — отключение от точки доступа

Execute Command: AT+CWQAP
Отклик: OK
Параметры: отсутствуют.

13) Получение web-страницы или текстового файла от сервера на OpenWRT

Итак, попробуем получить html страницу которую мы разместили на веб-сервере OpenWRT.

Подключаемся к точке доступа:

AT+CWMODE_CUR=1

OK

AT+CWJAP="Alien","password"
WIFI CONNECTED
WIFI GOT IP

OK

Устанавливаем TCP-соединение:

AT+CIPSTART="TCP","192.168.1.10",8010
CONNECT

OK

Отправляем http запрос из 18 байт, где текст запроса составляет 14 байт, плюс четыре байта отводится на комбинацию завершения: «rnrn»

AT+CIPSEND=18

OK
> 

После того, как появится символ «>», нужно будет ввести команду:

GET / HTTP/1.0

После ввода команды нужно еще раз ввести пустой Enter. Если всё было сделано правильно, то вернется наша html страница:

>
Recv 18 bytes

SEND OK

+IPD,17:HTTP/1.0 200 OK

+IPD,450:Connection: close
ETag: "6004-111-5be409c1"
Last-Modified: Thu, 08 Nov 2018 10:02:41 GMT
Date: Thu, 15 Nov 2018 20:00:08 GMT
Content-Type: text/html
Content-Length: 273

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
</head>
<body style="background-color: white">
<h3>Hello World!</h3>
</body>
</html>
CLOSED

Если посмотреть запись TCP-сессии в wireshark, то можно увидеть наш GET-запрос:

И 200-й ответ сервера с содержанием html-страницы:

14) Получение лога погоды от сервера на OpenWRT

Теперь подумаем, для чего нужна html страница? HTML страницы открывают в браузерах которые переобразуют их в форматированный текст. В ESP8266 нет ресурсов чтобы парсить интернет. Зато эти ресурсы есть в OpenWRT.

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

$ elinks --dump http://realmeteo.ru/samara/1/current|sed -n "13p" |awk '{print $1}'
-9DEGC

Остается написать задание для cron, что бы он периодически запускал эту команду, еще добавить дату и время для справки, и получим погодный логер из старого роутера. Остается передать лог на ESP8266 чтобы он выводил этот лог на дисплей, т.е. получаем этакий Hi-Tech градусник. У кого обычный градусник летом постоянно нагревается солнцем, те оценят.

Файл с логом погоды разместим в директории сайта: «/site/pub/waether.txt». Чтобы нам получить этот файл от веб-сервера, в GET-запросе нужно будет указать имя файла, который нам нужно получить:

GET /pub/weather.txt HTTP/1.0

В результате получаем наш файл:

AT+CIPSTART="TCP","192.168.1.10",8010
CONNECT

OK
AT+CIPSEND=33

OK
> 
Recv 33 bytes

SEND OK

+IPD,17:HTTP/1.0 200 OK

+IPD,1460:Connection: close
ETag: "6006-545-5bede30f"
Last-Modified: Thu, 15 Nov 2018 21:20:15 GMT
Date: Thu, 15 Nov 2018 21:41:04 GMT
Content-Type: text/plain
Content-Length: 1349

[11-15-18 00:00:11] -5.8DEGC
[11-15-18 00:30:11] -5.9DEGC
[11-15-18 01:30:12] -6.4DEGC
[11-15-18 02:00:12] -6.4DEGC
[11-15-18 02:30:12] -6.6DEGC
[11-15-18 03:00:11] -6.6DEGC
[11-15-18 03:30:11] -6.8DEGC
[11-15-18 04:00:11] -7.1DEGC
[11-15-18 04:30:11] -7.2DEGC
[11-15-18 05:00:11] -7.4DEGC
[11-15-18 05:30:11] -7.6DEGC
[11-15-18 06:00:12] -8.1DEGC
[11-15-18 06:30:12] -8.1DEGC
[11-15-18 07:00:12] -9DEGC
[11-15-18 07:30:12] -9DEGC
[11-15-18 08:00:12] -9DEGC
[11-15-18 08:30:11] -9DEGC
[11-15-18 09:00:11] -9DEGC
[11-15-18 09:30:11] -7.9DEGC
[11-15-18 10:00:11] -7.9DEGC
[11-15-18 10:30:11] -6.7DEGC
[11-15-18 11:00:11] -6.1DEGC
[11-15-18 11:30:11] -5.4DEGC
[11-15-18 12:00:11] -5.2DEGC
[11-15-18 12:30:11] -5.2DEGC
[11-15-18 13:00:11] -4.3DEGC
[11-15-18 13:30:11] -4.2DEGC
[11-15-18 14:00:11] -3.8DEGC
[11-15-18 14:30:11] -3.4DEGC
[11-15-18 15:00:11] -3.4DEGC
[11-15-18 15:30:11] -3DEGC
[11-15-18 16:00:11] -3DEGC
[11-15-18 16:30:11] -2.8DEGC
[11-15-18 17:00:11] -2.8DEGC
[11-15-18 17:30:11] -2.7DEGC
[11-15-18 18:00:11] -2.7DEGC
[11-15-18 18:30:11] -2.6DEGC
[11-15-18 19:00:11] -2.4DEGC
[11-15-18 19:30:11] -2.4DEGC
[11-15-18 20:00:12] -2.4DEGC
[11-15-18 20:30:12] -2.7DEGC
[11-15-18 21:00:12] -2.7DEGC
[11-15-18 21:30:12] -2.7DEGC
[11-15-18 22:00:12] -2.7DEGC
[11-15-18 22:30:11]
+IPD,68: -2.7DEGC
[11-15-18 23:00:11] -2.7DEGC
[11-15-18 23:30:11] -2.5DEGC
CLOSED

15) Управление OpenWRT через ESP8266 посредством CGI интерфейса

Раньше, чтобы управлять роутером на OpenWRT, нужно было либо припаивать к нему «гребёнку» на UART интерфейс и тянуть провода к микроконтроллеру, посредством которого передавались бы ваши команды. Либо прикручивать к микроконтроллеру какой либо Ethernet чип и передавать команды через сеть Ethernet, что опять же подразумевает провода. С помощью ESP8266 вы сможете вычеркнуть из этого уравнения провода.

Т.к. сервер uhttpd поддерживает CGI интерфейс, мы можем связать наш ESP8266 с OpenWRT посредством этого интерфейса, который и заменит нам пресловутые провода. Скрипты cgi могут писаться на каких угодно языках, для примера я возьму самый очевидный вариант — язык shell скриптов. Я буду краток, но если вас заинтересует тема написания cgi скриптов на языке shell скриптов, то советую почитать книгу Дэвида Тейнсли: «Linux и UNIX: программирование в shell. Руководство разработчика», глава 29 «Сценарии cgi».

Для проверки работоспособности GCI интерфейса проведем небольшой тест. Для этого в каталоге «/site/cgi-bin/» создадим файл esp8266.cgi следующего содержания:

echo -en "Status: 200 OKrn"
echo -en "Content-type: text/htmlrnrn"
echo "<h1>test</h1>"

Установим на файл права:

# chmod 755 /site/cgi-bin/esp8266.cgi

Проверяем тут же в OpenWRT:

# curl localhost:8010/cgi-bin/esp8266.cgi
<h1>test</h1>

Работает. Теперь, допустим нам нужно получить текущую температуру. Приведем скрипт esp8266.cgi к такому виду:

echo -en "Status: 200 OKrn"
echo -en "Content-type: text/htmlrnrn"
echo "<h1>ESP8266 Weather</h1>"
temp=$(elinks --dump http://realmeteo.ru/samara/1/current|sed -n "13p" |awk '{print $1}'|sed "s/DEGC//")
echo "<p>"
echo -n "current temp= "
echo -n "$temp" 
echo "&deg;"
echo "</p>"

Проверяем из ESP8266:

Здесь после «AT+CIPSEND=37» нужно будет ввести: «GET /cgi-bin/esp8266.cgi HTTP/1.1», после чего два раза ввести Enter. Как можно видеть по вставкам вида: «+IDC:num», ответ от сервера приходит в формате Chunked transfer encoding, когда данные бьются на фрагменты.

16) Отправка данных от ESP8266 на web-сервер OpenWRT через GET запрос

Теперь нам нужно рассмотреть, как можно отправить данные с микроконтроллера, посредством ESP8266, на OpenWRT. В HTTP протоколе имеются два основных способа передачи данных от клиента серверу: а) через GET запрос; б) через POST запрос.

Первый способ несколько попроще, там данные передаются через строку адреса. Отсюда и главное ограничение такого способа: длина передаваемых данные не должна превышать максимальную длину URL. Кроме того, такие данные видны пользователю в строке веб-браузера, что тоже не всегда желательно. Но для того, чтобы передать несколько цифр полученных микроконтроллером от датчиков, GET запрос подходит как нельзя лучше.

GET запрос формируется добавлением к URL знака вопроса, после которого перечисляются данные и их значения:

?var1=value1&var2=value2&var3=value3

Данные разделяются символом амперсанда, пробелы и прочие непечатные символы передаются в шестнадцатеричном виде: %xy. Shell — скрипт получает данные от сервера через CGI интерфейс в виде встроенных переменных.

Приведем содержимое скрипта esp8266.cgi к следующему виду:

echo -en "Status: 200 OKrn"
echo -en "Content-type: text/htmlrnrn"
echo "<h1>ESP8266 -  GET Request Example</h1>"
echo "<p>"
echo -n "Request method= "
echo "$REQUEST_METHOD"
echo "<br>"
echo -n "Data: "
echo "$QUERY_STRING"
echo "</p>"

Проверяем:

# curl "localhost:8010/cgi-bin/esp8266.cgi?var1=value1&var2=value2&var3=value3"
<h1>ESP8266 -  GET Request Example</h1>
<p>
Request method= GET
<br>
Data: var1=value1&var2=value2&var3=value3
</p>

Как видно, данные были успешно приняты, нам осталось лишь распарсить переменную QUERY_STRING. У меня это получилось так:

echo -en "Status: 200 OKrn"
echo -en "Content-type: text/htmlrnrn"
echo "<h1>ESP8266 -  GET Request Example</h1>"
echo "<p>"
echo -n "Request method= "
echo "$REQUEST_METHOD"
echo "<br>"
echo -n "Data: "
echo "$QUERY_STRING"
echo "</p>"
line=$(echo "$QUERY_STRING"|sed "s/&/	/g")
for loop in $line
do
	name=$(echo $loop|awk -F = '{print $1}')
	type=$(echo $loop|awk -F = '{print $2}')
	var=$(printf "${name}=${type}")
	eval $(printf $var)
done

[ -z $var1 ] && exit || echo $var1
[ -z $var2 ] && exit || echo $var2
[ -z $var3 ] && exit || echo $var3

let "var1 += 10"
echo $var1

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

# curl "localhost:8010/cgi-bin/esp8266.cgi?var1=12&var2=bar&var3=foo"
<h1>ESP8266 -  GET Request Example</h1>
<p>
Request method= GET
<br>
Data: var1=12&var2=bar&var3=foo
</p>
12
bar
foo
22

17) Отправка данных от ESP8266 на web-сервер OpenWRT через POST запрос

Отправка данных через POST запрос несколько сложнее. У этого метода имеется заголовок, в котором следует указывать формат и длинну данных.

Для обработки POST запросов создадим скрипт: «/site/cgi-bin/post.cgi» следующего содержания:


if [ "$REQUEST_METHOD" = "POST" ]; then
QUERY_STRING=$(cat -)
fi

echo -en "Status: 200 OKrn"
echo -en "Content-type: text/htmlrnrn"
echo "<h1>ESP8266 -  POST Request Example</h1>"
echo "<p>"
echo -n "Request method= "
echo "$REQUEST_METHOD"
echo "<br>"
echo -n "Data: "
echo "$QUERY_STRING"
echo "</p>"

line=$(echo "$QUERY_STRING"|sed "s/&/	/g")
for loop in $line
do
	name=$(echo $loop|awk -F = '{print $1}')
	type=$(echo $loop|awk -F = '{print $2}')
	var=$(printf "${name}=${type}")
	eval $(printf $var)
done

[ -z $var1 ] && exit || echo $var1
[ -z $var2 ] && exit || echo $var2
[ -z $var3 ] && exit || echo $var3

let "var1 += 10"
echo $var1

Установим на него права:

# chmod 755 /site/cgi-bin/post.cgi

Проверяеем командой:

$ curl -d "var1=12&var2=bar&var3=foo" -X POST "192.168.1.10:8010/cgi-bin/post.cgi"

Или:

$ curl -d "var1=12&var2=bar&var3=foo" -H "Content-Type: application/x-www-form-urlencoded" -X POST "192.168.1.10:8010/cgi-bin/post.cgi"

Где «192.168.1.10» — это адрес роутера c OpenWRT.

В Wireshark можно посмотреть формат запроса:

Как можно видеть, заголовок запроса состоит из следующих строк:

POST /cgi-bin/post.cgi HTTP/1.1
Host: 192.168.1.10:8010
User-Agent: curl/7.59.0
Accept: */*
Content-Type: application/x-www-form-urlencoded
Content-Length: 25

После заголовка следует ДВА enter’а, т.е. последовательность: «rnrn». После этого идут данные.

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

Теперь подробнее, пошаговая инструкция.

Устанавливаем TCP-соединение:

AT+CIPSTART="TCP","192.168.1.10",8010
CONNECT

OK

Отправляем http запрос из 60 байт, где заголовок будет состоять из 31 байта, 4 байта будет занимать последовательность окончания заголовка: «rnrn», на остальные 25 байт приходятся сами данные.

AT+CIPSEND=60

OK
 

После того, как появится символ «>», нужно будет ввести запрос:

POST /cgi-bin/post.cgi HTTP/1.1

После ввода запроса нужно еще раз ввести пустой Enter. После этого, вводим наши данные:

var1=12&var2=bar&var3=foo

После ввода Enter, должен прийти ответ от сервера. На скриншоте показан наш POST запрос в программе Wireshark:

18) Управление Linux/OpenWRT используя режим «UART-WiFi passthrough»

В ESP8266 имеется режим «UART-WiFi passthrough» который в документации также называется прозрачным режимом (transparent). Этот режим можно назвать «UART через WIFI», т.к. он позволяет установить непрерывное соединение по TCP или UDP протоколу. Режим включается командой AT+CIPMODE=1, а выход из этого режима происходит посылкой последовательности трех плюсов подряд: «+++». Примеры с использованием данного режима приведены в следующем руководстве: ESP8266 AT Command Examples

Какие у этого может быть практическое применение? Думаю все знают о такой полезной утилите как nc или netcat, с помощью которой можно устраивать простенькие чаты. Одними чатами ее полезность не ограничена, мы можем также управлять компьютером c linux или Windows с её по помощью через ESP8266. Давайте посмотрим как это делается на примере OpenWRT.

Открываем backdoor на OpenWRT с помощью команды:

# nc -l -p 12345 -e /bin/ash

Запускаем ESP8266 и подключаемся к точке доступа:

AT+CWMODE_CUR=1

OK

AT+CWJAP="Alien","password"
WIFI CONNECTED
WIFI GOT IP

OK

Устанавливаем TCP-соединение:

AT+CIPSTART="TCP","192.168.1.10",12345
CONNECT

OK

Где 192.168.1.10 — адрес роутера с OpenWRT, на котором мы открыли порт. Далее даём команды:

AT+CIPMODE=1

и:

AT+CIPSEND

После этого появится значок «>». После этого, в терминале, знак окончания строки нужно будет сменить с «NL & CR» на «NL», и можно начинать вводить команды:

Для окончания сеанса, следует в терминале сменить знак окончания строки на: «нет окончания строки». После этого ввести три знака плюс. Затем знак окончания строки сменить на: «NL & CR».

Далее, для разрыва соединения вводится команды:

AT+CIPMODE=0

и:

AT+CIPCLOSE

Думаю, что стоит упомянуть, что: а) использовать такой способ следует только в защищённом участке интрасети, б) не следует предоставлять привилегированный доступ к . При необходимости следует использовать sudo.

19) Прошивка ESP32 в интерпретатор AT-команд

Плата ESP32 NodeMCU несколько более замороченная нежели свой аналог на ESP8266:

Плата немного шире чем ESP8266 NodeMCU, при установке в беспаячную макетку, свободным остается только один ряд. Т.е. пины на другой стороне становятся недоступными.

Для работы с платой в режиме AT-команд понадобится USB-UART преобразователь с логикой на 3.3 Вольт, а для прошивки придется нажимать кнопки. ESP32 имеет два интерфейса UART. Один используется для отладки, другой для работы с AT-интерпретатором. Микро-USB порт который имеется на плате используется для отладки и прошивки.

В терминале нужно будет выставить режим 115200 бод, и признак окончания строки: «NL & CR». При подключении только что купленного модуля, у меня в терминале пошел такой лог:

ets Jun  8 2016 00:22:57

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0x00
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0008,len:8
load:0x3fff0010,len:3480
load:0x40078000,len:7804
ho 0 tail 12 room 4
load:0x40080000,len:252
entry 0x40080034
^[[0;32mI (46) boot: ESP-IDF v2.0-3-gbef9896 2nd stage bootloader^[[0m
^[[0;32mI (46) boot: compile time 05:59:45^[[0m
^[[0;32mI (46) boot: Enabling RNG early entropy source...^[[0m
^[[0;32mI (65) boot: SPI Speed      : 40MHz^[[0m
^[[0;32mI (78) boot: SPI Mode       : DIO^[[0m
^[[0;32mI (90) boot: SPI Flash Size : 4MB^[[0m
^[[0;32mI (102) boot: Partition Table:^[[0m
^[[0;32mI (114) boot: ## Label            Usage          Type ST Offset   Length^[[0m
^[[0;32mI (136) boot:  0 phy_init         RF data          01 01 0000f000 00001000^[[0m
^[[0;32mI (160) boot:  1 otadata          OTA data         01 00 00010000 00002000^[[0m
^[[0;32mI (183) boot:  2 nvs              WiFi data        01 02 00012000 0000e000^[[0m
^[[0;32mI (206) boot:  3 at_customize     unknown          40 00 00020000 000e0000^[[0m
^[[0;32mI (229) boot:  4 ota_0            OTA app          00 10 00100000 00180000^[[0m
^[[0;32mI (253) boot:  5 ota_1            OTA app          00 11 00280000 00180000^[[0m
^[[0;32mI (276) boot: End of partition table^[[0m
^[[0;32mI (289) boot: Disabling RNG early entropy source...^[[0m
^[[0;32mI (306) boot: Loading app partition at offset 00100000^[[0m
^[[0;32mI (1482) boot: segment 0: paddr=0x00100018 vaddr=0x00000000 size=0x0ffe8 ( 65512) ^[[0m
^[[0;32mI (1482) boot: segment 1: paddr=0x00110008 vaddr=0x3f400010 size=0x1c5f0 (116208) map^[[0m
^[[0;32mI (1499) boot: segment 2: paddr=0x0012c600 vaddr=0x3ffb0000 size=0x0215c (  8540) load^[[0m
^[[0;32mI (1529) boot: segment 3: paddr=0x0012e764 vaddr=0x40080000 size=0x00400 (  1024) load^[[0m
^[[0;32mI (1552) boot: segment 4: paddr=0x0012eb6c vaddr=0x40080400 size=0x1b028 (110632) load^[[0m
^[[0;32mI (1631) boot: segment 5: paddr=0x00149b9c vaddr=0x400c0000 size=0x00034 (    52) load^[[0m
^[[0;32mI (1632) boot: segment 6: paddr=0x00149bd8 vaddr=0x00000000 size=0x06430 ( 25648) ^[[0m
^[[0;32mI (1648) boot: segment 7: paddr=0x00150010 vaddr=0x400d0018 size=0x7a56c (501100) map^[[0m
^[[0;32mI (1676) heap_alloc_caps: Initializing. RAM available for dynamic allocation:^[[0m
^[[0;32mI (1698) heap_alloc_caps: At 3FFBA6B8 len 00025948 (150 KiB): DRAM^[[0m
^[[0;32mI (1719) heap_alloc_caps: At 3FFE8000 len 00018000 (96 KiB): D/IRAM^[[0m
^[[0;32mI (1741) heap_alloc_caps: At 4009B428 len 00004BD8 (18 KiB): IRAM^[[0m
^[[0;32mI (1762) cpu_start: Pro cpu up.^[[0m
^[[0;32mI (1773) cpu_start: Single core mode^[[0m
^[[0;32mI (1786) cpu_start: Pro cpu start user code^[[0m
^[[0;32mI (1847) cpu_start: Starting scheduler on PRO CPU.^[[0m
^[[0;32mI (2016) uart: queue free spaces: 10^[[0m
Bin version:0.10.0^M
I (2017) wifi: wifi firmware version: c604573
I (2017) wifi: config NVS flash: enabled
I (2018) wifi: config nano formating: disabled
I (2027) wifi: Init dynamic tx buffer num: 32
I (2027) wifi: wifi driver task: 3ffc4eac, prio:23, stack:3584
I (2032) wifi: Init static rx buffer num: 10
I (2036) wifi: Init dynamic rx buffer num: 0
I (2040) wifi: Init rx ampdu len mblock:7
I (2044) wifi: Init lldesc rx ampdu entry mblock:4
I (2049) wifi: wifi power manager task: 0x3ffca254 prio: 21 stack: 2560
I (2055) wifi: wifi timer task: 3ffcb2d4, prio:22, stack:3584
^[[0;31mE (2060) phy_init: PHY data partition validated^[[0m
^[[0;32mI (2080) phy: phy_version: 329, Feb 22 2017, 15:58:07, 0, 0^[[0m
I (2081) wifi: mode : softAP (80:7d:3a:cb:66:b9)
I (2084) wifi: mode : sta (80:7d:3a:cb:66:b8) + softAP (80:7d:3a:cb:66:b9)
I (2087) wifi: mode : softAP (80:7d:3a:cb:66:b9)^M

Из любопытного. Последовательности: [[0;32mI и [[0m означат цветовую разметку вывода в Linux. Это означает, что мы можем подключиться к порту программной screen:

$ screen /dev/ttyUSB0 115200,cs8

Выглядит это так:

Из полезного, тут можно узнать версию AT-интерпретатора:

Bin version:0.10.0

Т.к. это ужас какая древняя версия, аж прошлого 2017-го года, скорее всего вам захочется ее обновить. Для этого нам снова придется обратится к программе esptool.py

Перед вводом команд esptool.py, необходимо: а) вначале нажать кнопку EN; б) после чего, удерживая кнопку EN, нажать конку BOOT; в) после чего, отпустить кнопку EN и удерживая кнопку BOOT ввести команду esptool.py.

Для начала проверим связь:

$ esptool.py --chip esp32 flash_id
esptool.py v2.3.1
Connecting....
Chip is ESP32D0WDQ6 (revision (unknown 0xa))
Features: WiFi, BT, Dual Core, VRef calibration in efuse
Uploading stub...
Running stub...
Stub running...
Manufacturer: c8
Device: 4016
Detected flash size: 4MB
Hard resetting via RTS pin...
$ esptool.py --chip esp32 chip_id
esptool.py v2.3.1
Connecting......
Chip is ESP32D0WDQ6 (revision (unknown 0xa))
Features: WiFi, BT, Dual Core, VRef calibration in efuse
Uploading stub...
Running stub...
Stub running...
Chip ID: 0xaa807d3acb66
Hard resetting via RTS pin...

Затем, вам возможно захочется сохранить существующую прошивку:

$  esptool.py --chip esp32 --port /dev/ttyUSB0 read_flash 0x00000 0x400000 ./esp32_firmware2.bin
esptool.py v2.3.1
Connecting.....
Chip is ESP32D0WDQ6 (revision (unknown 0xa))
Features: WiFi, BT, Dual Core, VRef calibration in efuse
Uploading stub...
Running stub...
Stub running...
4194304 (100 %)
4194304 (100 %)
Read 4194304 bytes at 0x0 in 380.7 seconds (88.1 kbit/s)...
Hard resetting via RTS pin...

Актуальную версию прошивки можно скачать с официального сайта: ESP32 Resources | Espressif Systems.

После распаковки архива, видим следующую структуру каталогов:

$ tree .
.
├── at_customize.bin
├── blank.bin
├── 
│   └── bootloader.bin
├── 
│   ├── ble_data.bin
│   ├── client_ca.bin
│   ├── client_cert.bin
│   ├── client_key.bin
│   ├── server_ca.bin
│   ├── server_cert.bin
│   └── server_key.bin
├── download.config
├── esp-at.bin
├── factory.bin
├── partitions_at.bin
└── phy_init_data.bin

Здесь нас будет интересовать содержимое файла download.config, к котором хранится опции прошивки для esptool.py:

--flash_mode dio --flash_freq 40m --flash_size detect 0x1000 bootloader/bootloader.bin 0x20000 at_customize.bin 0x21000 customized_partitions/ble_data.bin 0x24000 customized_partitions/server_cert.bin 0x26000 customized_partitions/server_key.bin 0x28000 customized_partitions/server_ca.bin 0x2a000 customized_partitions/client_cert.bin 0x2c000 customized_partitions/client_key.bin 0x2e000 customized_partitions/client_ca.bin 0xf000 phy_init_data.bin 0x100000 esp-at.bin 0x8000 partitions_at.bin

Не мудрствуя лукаво, прошиваем согласно предложенным рекомендациям:

$ esptool.py --chip esp32 --port /dev/ttyUSB0 write_flash --flash_mode dio --flash_freq 40m --flash_size detect 0x1000 bootloader/bootloader.bin 0x20000 at_customize.bin 0x21000 customized_partitions/ble_data.bin 0x24000 customized_partitions/server_cert.bin 0x26000 customized_partitions/server_key.bin 0x28000 customized_partitions/server_ca.bin 0x2a000 customized_partitions/client_cert.bin 0x2c000 customized_partitions/client_key.bin 0x2e000 customized_partitions/client_ca.bin 0xf000 phy_init_data.bin 0x100000 esp-at.bin 0x8000 partitions_at.bin

Процесс прошивки:

esptool.py v2.3.1
Connecting.....
Chip is ESP32D0WDQ6 (revision (unknown 0xa))
Features: WiFi, BT, Dual Core, VRef calibration in efuse
Uploading stub...
Running stub...
Stub running...
Configuring flash size...
Auto-detected Flash size: 4MB
Compressed 19424 bytes to 11458...
Wrote 19424 bytes (11458 compressed) at 0x00001000 in 1.0 seconds (effective 153.0 kbit/s)...
Hash of data verified.
Compressed 3072 bytes to 136...
Wrote 3072 bytes (136 compressed) at 0x00020000 in 0.0 seconds (effective 1372.2 kbit/s)...
Hash of data verified.
Compressed 5720 bytes to 347...
Wrote 5720 bytes (347 compressed) at 0x00021000 in 0.0 seconds (effective 1239.8 kbit/s)...
Hash of data verified.
Compressed 1284 bytes to 941...
Wrote 1284 bytes (941 compressed) at 0x00024000 in 0.1 seconds (effective 115.7 kbit/s)...
Hash of data verified.
Compressed 1692 bytes to 1322...
Wrote 1692 bytes (1322 compressed) at 0x00026000 in 0.1 seconds (effective 110.9 kbit/s)...
Hash of data verified.
Compressed 1276 bytes to 882...
Wrote 1276 bytes (882 compressed) at 0x00028000 in 0.1 seconds (effective 121.5 kbit/s)...
Hash of data verified.
Compressed 2536 bytes to 1534...
Wrote 2536 bytes (1534 compressed) at 0x0002a000 in 0.1 seconds (effective 142.9 kbit/s)...
Hash of data verified.
Compressed 3376 bytes to 2537...
Wrote 3376 bytes (2537 compressed) at 0x0002c000 in 0.2 seconds (effective 116.9 kbit/s)...
Hash of data verified.
Compressed 2544 bytes to 1460...
Wrote 2544 bytes (1460 compressed) at 0x0002e000 in 0.1 seconds (effective 150.8 kbit/s)...
Hash of data verified.
Compressed 144 bytes to 69...
Wrote 144 bytes (69 compressed) at 0x0000f000 in 0.0 seconds (effective 96.2 kbit/s)...
Hash of data verified.
Compressed 1119072 bytes to 704097...
Wrote 1119072 bytes (704097 compressed) at 0x00100000 in 62.5 seconds (effective 143.2 kbit/s)...
Hash of data verified.
Compressed 3072 bytes to 129...
Wrote 3072 bytes (129 compressed) at 0x00008000 in 0.0 seconds (effective 1446.2 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting via RTS pin...

Если после перепрошивки отладочный лог платы в порядке, то теперь для работы с AT-командами нужно будет подключить USB-UART адаптер с 3.3 вольтовой логикой на второй UART порт ESP32. Подключение USB-UART адаптера и ESP32: GND<—>GND(адаптера), RX2<—>TX(адаптера), TX2<—>RX(адаптера).

Работа с AT интерпретатором ESP32 по сути не отличается от ESP8266:

AT+GMR
AT version:1.1.2.0(f045c0c - Aug 30 2018 04:20:47)
SDK version:v3.0.3
compile time:Sep  4 2018 08:53:40
Bin version(Wroom32):1.1.2
OK

AT+SYSRAM?
+SYSRAM:131680
OK

AT+PING="ya.ru"
+PING:30

OK

AT+CIPDNS?
+CIPDNS:192.168.1.10

OK

Существенное отличие от ESP8266 — это наличие команд для работы с Bluetooth.

На этом пока всё. К сожалению не удалось осветить тему программирования ESP8266/ESP32 на Си и ассемблере. Для этого потребуется отдельная статья и возможно даже не одна. Так же остался за бортом Bluetooth, о сфере применения которого я пока гадаю. В руководстве ESP32 AT Instruction Set and Examples имеется пример сопряжения двух ESP32, но мне кажется более интересной тема связи с другими Bluetooth устройствами, например со смартфонами.

В этом уроке поговорим о микроконтроллере ESP8266 и платах на его основе. Как с ними работать и чем они отличаются от Arduino на базе МК AVR. ESP8266 – китайский микроконтроллер за 2 доллара с большим объемом памяти и WiFi связью на борту. Официальная документация:

  • https://github.com/esp8266/Arduino/blob/master/doc/reference.rst
  • https://arduino-esp8266.readthedocs.io/en/latest/

Купить на Aliexpress


Дёшево купить Wemos Mini можно тут: ссылка, ссылка, ссылка. Рекомендуется брать версию как слева на картинке выше, на базе полного чипа ESP-12.

Уроки по работе с esp8266


Конкретные уроки по работе с платой и WiFi библиотеками публикуются на сайте набора GyverKIT, так как уроки на этом сайте являются общими по программированию Arduino, без углубления в сторонние библиотеки.

Характеристики


  • Напряжение питания: 3.3V (2.5-3.6V)
  • Ток потребления: 300 мА при запуске и передаче данных, 35 мА во время работы, 80 мА в режиме точки доступа
  • Максимальный ток пина – 12 мА.
  • Flash память (память программы): 1 МБ
  • Flash память (файловое хранилище): 1-16 МБ в зависимости от модификации
  • EEPROM память: до 4 кБ
  • SRAM память: 82 кБ
  • Частота ядра: 80/160 МГц
  • GPIO: 11 пинов
  • ШИМ: 10 пинов
  • Прерывания: 10 пинов
  • АЦП: 1 пин
  • I2C: 1 штука (программный, пины можно назначить любые)
  • I2S: 1 штука
  • SPI: 1 штука
  • UART: 1.5 штуки
  • WiFi связь

Начало работы


Для работы с платами на основе esp8266 нужно установить ядро и драйвер.

  • Идём в Файл/Настройки/Дополнительные ссылки для менеджера плат. Вставляем ссылку https://arduino.esp8266.com/stable/package_esp8266com_index.json.
  • Инструменты/Плата/Менеджер плат…, ищем в поиске esp8266 и устанавливаем. В списке плат появится семейство плат на базе esp8266.
  • На большинстве плат стоит USB конвертер CH340, как на всех китайских Ардуинах. Если вы ещё не устанавливали драйвер – читать здесь.

Настройки платы


Для работы с любой платой (даже самодельной) можно выбрать пункт Generic esp8266, будет доступен полный набор настроек. Для работы с Wemos Mini выбираем LOLIN Wemos D1 R2 mini. Настроек станет меньше, а к пинам платы можно будет обращаться в программе по их подписям на плате (Dn). Основные настройки:

  • Upload speed: скорость загрузки прошивки. Можно смело поднимать до 921600.
  • CPU Frequency: частота тактирования процессора. Для большинства задач хватит стандартных 80 МГц. На 160 МГц будет работать шустрее, но могут быть сбои.
  • Flash Size: распределение памяти, настройка имеет вид xMB (FS:xMB OTA:~xKB). Размер памяти под программу не меняется – это всегда 1 МБ.
    • Первое число: полный объём микросхемы памяти (в основном 4MB, на Wemos и NodeMCU стоят такие).
    • Второе число: объём под файловое хранилище.
    • Третье число: объём под OTA (обновление по воздуху) – всегда меньше 1 МБ.
    • Что выбрать? У Wemos самый ходовой – первый вариант: 4MB (FS:2MB OTA:~1019KB).
  • Flash mode: режим загрузки во Flash память.
    • DOUT: медленный, но совместим со всеми модификациями esp8266.
    • QIO: более быстрый, но будет работать не на всех чипах.
  • Erase Flash: режим очистки памяти.
    • Only Sketch: стереть только программу.
    • Sketch + WiFi Settings: стереть программу и настройки WiFi (логин-пароль последнего подключения и т.д.).
    • All Flash Contents: полностью очистить память.
  • Порт: к какому порту подключена плата.

Нумерация пинов


У самого чипа esp8266 все выводы пронумерованы цифрами. На распиновке они подписаны как GPIOn, где n – номер. На плате (NodeMCU, Wemos Mini) пины подписаны как Dn и эти номера не совпадают с номерами GPIO! При работе например с Wemos можно использовать как нумерацию выводов GPIO (digitalWrite(5, LOW)), так и D-нумерацию пинов на плате (digitalWrite(D1, LOW)) – если выбрана плата Wemos. Новички очень часто в этом путаются, будьте внимательны. Также GPIO1 и GPIO3 подписаны на плате как TX и RX, по этим названиям к ним тоже можно обращаться (digitalWrite(TX, LOW)).

Особенности пинов


У esp8266 много системных пинов, с которыми нужно быть очень внимательным.

  • К целому ряду пинов подключена внешняя Flash память, в общем случае их использовать нельзя (если очень нужно – ищите информацию). На плате NodeMCU визуально гораздо больше пинов, чем на Wemos Mini, но по факту “безопасных” для использования пинов там ровно столько же.
  • С оставшимися пинами тоже не всё гладко: некоторые из них требуют наличия определенного логического уровня на момент включения микроконтроллера (подача питания, перезагрузка). Если к этим пинам подключить что-то, дающее противоположный сигнал – esp не запустится. Вот распиновка с нужным уровнем сигнала при запуске:
  • На плате (NodeMCU, Wemos и других) эти пины уже подтянуты резисторами к нужному напряжению, поэтому нужно несколько раз подумать, что вы к ним подключаете и как оно повлияет на напряжение на пине. Например, можно подключить энкодер, он прижмёт системный пин к GND и esp не запустится.
  • На GPIO16/D0 нельзя подключать прерывания (attachInterrupt()) и включать ШИМ сигнал (analogWrite()).
  • Максимальный ток с GPIO – 12 мА.
  • Светодиод LED_BUILTIN находится на пине GPIO2 и его поведение инвертировано: при подаче LOW он включается и наоборот.
  • При старте контроллера почти все пины делают скачок до высокого уровня, подробнее – в этой статье. Единственными “спокойными” пинами являются D1 (GPIO5) и D2 (GPIO4). Если контроллер управляет напрямую какими-то железками (реле, транзистор, или является “кнопкой” для другого устройства), то лучше использовать именно эти пины!
    • На этих же пинах сидит I2C, но шину можно переназначить на любые другие пины через Wire.begin(sda, scl).

Особенности работы WiFi


WiFi реализован синхронно, его обработчик должен постоянно вызываться во время работы программы не реже, чем каждые 20 мс (если WiFi используется в программе). Обработка WiFi происходит в следующих местах:

  • Автоматически в конце каждой итерации loop()
  • Внутри любого delay()
  • Внутри функции yield()

Если у вас есть участки программы, которые долго выполняются, то нужно разместить вызовы yield() до и после тяжёлых блоков кода. Также в чужих скетчах можно встретить delay(0), по сути это и есть yield().

По тем же причинам не рекомендуется использовать задержку delayMicroseconds() более чем на 20’000 мкс.

Отличия от AVR Arduino

Деление на 0


В отличие от AVR, деление на 0 приводит к критической ошибке и перезагрузке микроконтроллера. Стараемся этого избегать.

min() и max()


В ядре esp8266 функции min() и max() реализованы как функции, а не как макросы, поэтому должны использоваться с данными одного типа. Использование переменных разного типа приведёт к ошибке компиляции.

map()


В функции map(val, min, max, to min, to max) нет защиты от деления на 0, поэтому если min равен max – микроконтроллер зависнет и перезагрузится. Если min и max задаются какими-то внешними условиями – проверяйте их равенство вручную и исключайте вызов map() с такими аргументами.

Типы данных


  • Тип int является синонимом long (int32_t) и занимает 4 байта. В AVR int это int16_t, то есть 2 байта.
  • Тип char является синонимом byte– принимает значения 0.. 255 в отличие от -128.. 127 в AVR.
  • Тип double имеет полную двойную точность – 8 байт. В AVR это 4 байта.
  • Указатель занимает 4 байта, так как область памяти тут 32-битная. В AVR – 2 байта.

Функция analogRead()


ESP8266 имеет крайне убогий одноканальный АЦП.

  • Сам АЦП в esp8266 может измерять напряжение в диапазоне 0.. 1.0V. На платах (NodeMCU, Wemos Mini) стоит делитель напряжения, который расширяет диапазон до более удобных 3.3V.
  • Разрешение – 10 бит, т. е. значения 0.. 1023 как на Arduino
  • Частый вызов analogRead() замедляет работу WiFi. При вызовах чаще нескольких миллисекунд WiFi полностью перестаёт работать.
  • Результат analogRead() имеет кеширование до 5 мс, то есть полученные данные могут запаздывать на это время.
  • АЦП может использоваться для измерения напряжения питания МК: для этого нужно вызвать ADC_MODE(ADC_VCC); до void setup(), а само напряжение питания можно получить из ESP.getVcc().

Функция analogWrite()


  • Работает на всех пинах, кроме GPIO16.
  • Разрядность ШИМ по умолчанию 8 бит (0.. 255) на версиях ядра 3.x. На ранних версиях – 10 бит (0.. 1023). Скажем спасибо индусам за совместимость.
    • Разрядность можно настроить в analogWriteResolution(4...16 бит).
  • Частота ШИМ по умолчанию 1 кГц.
    • Частоту можно настроить в analogWriteFreq(100.. 40000 Гц).
  • ШИМ реализован программно, поэтому на повышенной частоте и разрядности будет тормозить выполнение программы!

Аппаратные прерывания


  • Настраиваются точно так же, через attachInterrupt().
  • Работают на всех пинах, кроме GPIO16.
  • Функция-обработчик должна быть объявлена с атрибутом IRAM_ATTR:
    void setup() {
      attachInterrupt(1, myIsr, RISING);
    }
    
    IRAM_ATTR void myIsr() {
    }

    Либо с ICACHE_RAM_ATTR (на старых версиях ядра), вот так:

    void ICACHE_RAM_ATTR myIsr() {
    }
    
    void setup() {
      attachInterrupt(1, myIsr, RISING);
    }
  • В обработчике нельзя использовать динамическое выделение и перераспределение памяти (new, malloc, realloc), соответственно менять String-строки тоже нельзя.
  • В прерывании нельзя использовать задержки.

Функция yield()


В реализации esp8266 функция yield() выполняет другую задачу и использовать её как на AVR не получится. Скажем спасибо индусам за совместимость

EEPROM


EEPROM в esp8266 является эмуляцией из Flash памяти, поэтому мы можем выбрать нужный размер.

  • Перед началом работы нужно вызвать EEPROM.begin(4.. 4096) с указанием размера области памяти в байтах.
  • Для применения изменений в памяти нужно вызвать EEPROM.commit().
  • В некоторых версиях SDK отсутствует EEPROM.update() и EEPROM.length().
  • У Flash памяти небольшой ресурс – всего около 10’000 перезаписей. У фирменной памяти Winbond (можно найти на некоторых моделях ESP-12 и прочих) – около 50’000 перезаписей.

В остальном работа с библиотекой EEPROM.h ничем не отличается.

Важно: EEPROM реализован следующим образом: после запуска EEPROM.begin(4.. 4096) содержимое EEPROM указанного размера дублируется в оперативной памяти. После любого изменения и вызова EEPROM.commit() стирается весь блок Flash памяти (4 кБ) и записывается заново. Таким образом ресурс “EEPROM” памяти у ESP вырабатывается довольно быстро и весь сразу, а не по ячейкам.

Serial (UART)


  • В отличие от реализации для AVR, можно изменить размер буфера на приём: Serial.setRxBufferSize(размер) в байтах. Вызывать перед Serial.begin(), по умолчанию 256 байт.
  • Можно настроить работу только на приём или только на отправку для освобождения пина: Serial.begin(скорость, SERIAL_8N1, режим), где режим:
    • SERIAL_TX_ONLY – только отправка
    • SERIAL_RX_ONLY – только приём
    • SERIAL_FULL – приём и отправка (по умолчанию)
  • Можно перенести Serial на другие пины при помощи Serial.swap(), вызывать после Serial.begin(). Пины переместятся на GPIO15/D8 (TX) и GPIO13/D7 (RX). Если вызвать ещё раз – переместятся обратно на GPIO1 (TX) и GPIO3 (RX). И так по кругу.
  • У esp8266 есть второй аппаратный UART, но его приёмная нога (RX) занята одним из пинов для работы с памятью и не выведена на плате Wemos Mini. Нога TX находится на GPIO2/D4, то есть можно работать только на отправку, но на практике и это может пригодиться. В программе просто работаем с объектом Serial1, настроив его только на отправку.

Полезные страницы


  • Набор GyverKIT – большой стартовый набор Arduino моей разработки, продаётся в России
  • Каталог ссылок на дешёвые Ардуины, датчики, модули и прочие железки с AliExpress у проверенных продавцов
  • Подборка библиотек для Arduino, самых интересных и полезных, официальных и не очень
  • Полная документация по языку Ардуино, все встроенные функции и макросы, все доступные типы данных
  • Сборник полезных алгоритмов для написания скетчей: структура кода, таймеры, фильтры, парсинг данных
  • Видео уроки по программированию Arduino с канала “Заметки Ардуинщика” – одни из самых подробных в рунете
  • Поддержать автора за работу над уроками
  • Обратная связь – сообщить об ошибке в уроке или предложить дополнение по тексту ([email protected])

Интернет вещей (Internet of Things) и автоматизация дома (Home Automation) в настоящее время стали одними из ведущих трендов в развитии микроэлектроники. Для начинающих радиолюбителей особенно волнительным является процесс создания какого либо устройства, способного подключаться к мировой всемирной паутине интернета (World Wide Web). Доступ к таким устройствам можно получить из любой точки земного шара, в которой есть подключение к сети Интернет.

Некоторые могут подумать, что создание своими руками электронного устройства с подключением к сети Интернет является достаточно сложной задачей. Отчасти да. Но с появлением таким замечательных (и при этом сравнительно недорогих) модулей как ESP8266 от компании Espressif Systems эта задача значительно упростилась.

Внешний вид проекта для изучения основ работы с модулем ESP8266

В данной статье мы рассмотрим основы работы с модулем ESP8266-01. Для программирования данного модуля вам понадобится программатор (адаптер) FTDI USB to TTL. Более подробно все эти процессы вы можете посмотреть на видео, представленном в конце статьи.

Большинство людей называют ESP8266 модулем Wi-Fi, но на самом деле это микроконтроллер. ESP8266 — это название микроконтроллера, разработанного компанией Espressif Systems, базирующейся в Шанхае. Данный микроконтроллер имеет возможность работы с технологией Wi-Fi, поэтому он широко используется в качестве модуля Wi-Fi.

Внешний вид модуля ESP8266

Существует множество типов модулей ESP8266, доступных в диапазоне от ESP8266-01 до ESP8266-12. В данной статье мы будем использовать модуль ESP8266-01 в связи с тем, что он самый дешевый.

Однако все модули ESP имеют только один тип процессора ESP и отличаются только типом используемого интерфейсного модуля. Интерфейсный модуль микроконтроллера ESP8266-01 имеет только 2 вывода GPIO, а другие модули ESP могут иметь большее количество выводов.

Назначение элементов на плате модуля ESP8266-01

Технические характеристики микроконтроллера ESP8266-01 приведены в следующей таблице.

Напряжение питания 3.3V
Потребление тока 10uA-170mA
Максимальный потребляемый ток во время программирования (прошивки) модуля 800mA
Флэш-память 16MB (512K normal)
Тип процессора Tensilica L106 32 bit
Тактовая частота процессора 80-160MHz
ОЗУ (RAM) 32K+80K
Число контактов GPIO 17 (большинство из них могут выполнять несколько функций)
АЦП 1 (с разрешением 10 бит)
Максимальное число соединений TCP 5

Хочется отметить, что в составе даже такого дешевого модуля как ESP8266-01 имеется аналого-цифровой преобразователь (АЦП), что позволяет подключать к нему различные аналоговые устройства. Также особенностью модуля является его очень большой потребляемый ток во время его прошивки (программирования) — 0,8 А.

Основы технологии Wi-Fi

Протокол управления передачей (Transfer Control Protocol, TCP), интернет-протокол (Internet Protocol, IP), протокол пользовательских дейтаграмм (User Datagram Protocol, UDP), точка доступа (Access Point, AP), станция (Station, Sta), идентификатор набора служб (Service Set Identifier, SSID), интерфейс прикладного программирования (Application Programming Interface, API), веб-сервер (Webserver). Знакомы ли вам эти термины? Если да, то можете пропустить данный раздел статьи и переходить сразу к следующему ее разделу. Если же нет – то желательно все же кратко познакомиться с этими терминами в данном разделе статьи.

Протокол управления передачей (TCP)

Протокол транспортного управления стека протоколов TCP/IP. Фактически, это набор правил, на основе которых работает Интернет. Wi-Fi – это технология, описывающая 1-й и 2-й уровни эталонной семиуровневой модели взаимодействия открытых систем (ЭМ ВОС), а чтобы выходить в сеть Интернет данная технология на более высоких уровнях ЭМ ВОС использует протокол IP (3-й уровень) и протоколы TCP или UDP на 4-м уровне. Вы можете настроить свой модуль ESP для работы по протоколу TCP/IP или протоколу UDP.

Протокол пользовательских дейтаграмм (UDP)

UDP также является еще одним типом интернет-протокола. Он обеспечивает более высокие скорости передачи данных чем TCP, но он менее точен (совершает больше ошибок при передаче). Причина в том, что протокол TCP использует подтверждение во время сеанса связи, а UDP – нет. TCP, в основном, используется в сетях, где требуется высокая надежность. UDP используется в местах, где скорость имеет более высокий приоритет, чем надежность. Например, UDP используется в видеоконференциях, потому что там, даже если некоторые пиксели не передаются (или передаются неправильно), то это не сильно повлияет на качество видео, но скорость соединения в видеоконференциях очень важна.

Большинство проектов и кодов ESP8266 работают по протоколам TCP/IP, протокол UDP используется значительно реже.

Точка доступа (AP) и станция (STA)

Как только вы начнете работать с модулем ESP, вы будете часто сталкиваться с этими двумя терминами. Допустим, вы и ваш друг хотели бы пользоваться Интернетом на своих смартфонах, но, поскольку у него нет активного подключения к Интернету, вы решаете включить свою точку доступа, и ваш друг подключается к ней и через нее получает доступ в сеть Интернет. Здесь ваш телефон, который обеспечивает подключение к Интернету, является точкой доступа (AP), а телефон вашего друга, который использует Интернет, называется станцией (STA).

Модуль ESP8266 может использоваться в трех режимах: режиме AP (точки доступа), режиме STA (станции) или как в режиме STA, так и в режиме AP (комбинированном).

Идентификатор набора служб/услуг (SSID)

Это достаточно простой термин. Наверняка все из вас пользовались Wi-Fi связью. Имя сети Wi-Fi называется ее SSID. Когда у нас есть несколько точек доступа для подключения станции, станция должна знать, к какой точке доступа она должна подключиться, поэтому каждой точке доступа (AP) присваивается идентификатор, который называется SSID.

Интерфейс прикладного программирования (API)

Проще говоря, API – это мессенджер, который принимает ваши запросы, обрабатывает их и возвращает вашей системе желаемый результат. Большинство действий, которые мы выполняем в сети Интернет, использует API, например, когда вы бронируете рейс, совершаете онлайн-покупку и т.д. Каждый веб-сайт связывает вас с API, где для вас выполняется определенная часть работы, такая как регистрация, оплата и т. д.

Микроконтроллер ESP8266 использует API для общения с миром Интернета. Например, если он хочет узнать время, погоду или что-то еще, то он должен запросить это в форме API на соответствующем веб-сайте. Этот веб-сайт получит запрос и вернет желаемый результат нашему модулю ESP.

Веб-сервер

Веб-сервер – это то, что отвечает за отображение содержимого веб-сайта. Все содержимое этого конкретного веб-сайта будет загружено на его веб-сервер. Существуют выделенные компьютеры, работа которых заключается только в том, чтобы выполнять функции веб-сервера. Мы также можем запрограммировать наш ESP8266 для работы в качестве веб-сервера и подключиться к нему из любой точки мира.

Способы программирования ESP8266

Существует два основных способа работы с модулем ESP8266. Первый – это использование AT команд. Второй – использование Arduino IDE. Давайте более подробно разберем эти способы.

Все модули ESP8266 поставляются с завода с заранее загруженной в них прошивкой (default firmware). Фактически, прошивка модуля – это набор SDK+API. Эта прошивка (встроенная программа) и позволяет производить программирование модуля ESP8266 с помощью AT команд.

Второй способ непосредственного программирования модуля ESP8266 – это использование интегрированной среды Arduino IDE (сама плата Arduino при этом не нужна) со всеми ее библиотеками.

Любой проект на ESP8266 можно реализовать с помощью любого из этих двух методов. Но если вы будете использовать Arduino IDE для программирования модуля ESP8266 вы, скорее всего, уже не сможете использовать AT команды потому что исходный SDK (software development kit, набор инструментальных средств разработки программного обеспечения) модуля может быть поврежден. В этом случае вы должны будете во время прошивки модуля ESP использовать настройки по умолчанию.

Аппаратное обеспечение для программирования модуля ESP8266

Модуль ESP8266 имеет 8 контактов. Его внешний вид и распиновка показаны на следующих рисунках.

Внешний вид модуля ESP8266

Распиновка модуля ESP8266

Назначение контактов модуля ESP8266:

  • 1 – земля, 8 – питание. По документации напряжение подается до 3,6 В – это важно учесть при работе с Ардуино, на которую обычно подают 5 В.
  • 6 – RST, нужна для перезагрузки микроконтроллера при подаче на него низкого логического уровня.
  • 4 – CP_PD, также используется для перевода устройства в энергосберегающий режим.
  • 7 и 0 – RXD0 и TXD0, это аппаратный UART (последовательный порт), необходимый для перепрошивки модуля.
  • 2 – TXD0, к этому контакту подключается светодиод, который загорается при низком логическом уровне на GPIO1 и при передаче данных по UART.
  • 5 – GPIO0, порт ввода и вывода, также позволяет перевести устройство в режим программирования (при подключении порта к низкому логическому уровню и подачи напряжения).
  • 3 – GPIO2, порт ввода и вывода.

К сожалению, модуль ESP8266 не является «дружественным» к макетной плате (breadboard friendly) и поэтому его нельзя на ней непосредственно закрепить. Также, в отличие от платы Arduino у него нет собственного драйвера для преобразования интерфейса USB в интерфейс последовательного порта (USB to Serial driver), следовательно, нам необходимо будет использовать FTDI USB to TTL Serial Adapter Module (модуль адаптера FTDI для преобразования USB в логику TTL) чтобы взаимодействовать с данным модулем. Прежде чем собирать схему нашего проекта убедитесь в том, что используемая вами плата FTDI может работать при напряжении 3.3V.

Внешний вид модуля (платы) FTDI

Итак, как мы знаем, наш модуль ESP8266 мы должны запитывать от напряжения 3.3V. Но поскольку во время загрузки программного обеспечения (прошивки) модуль может потреблять ток до 0.8A, то он может работать некорректно если мы запитаем его от платы адаптера FTDI, поэтому мы соберем отдельную цепь для его питания на основе регулятора напряжения LM317.

Необходимые компоненты

  1. Модуль ESP8266-01 (купить на AliExpress).
  2. Перфорированная плата.
  3. Плата адаптера FTDI (FTDI breakout Board) (купить на AliExpress).
  4. Регулятор напряжения LM317 (купить на AliExpress).
  5. Конденсатор 0,1 мкФ (купить на AliExpress).
  6. Конденсатор 10 мкФ (купить на AliExpress)
  7. Разъем типа Barrel Jack.
  8. Кнопка.
  9. Переключатель.
  10. Соединительные колодки «мама», «папа».
  11. Соединительные провода.
  12. Адаптер 12V для питания платы.

Схема проекта

Схема для программирования модуля ESP8266 представлена на следующем рисунке.

Схема для программирования модуля ESP8266Некоторые из вас, возможно, пытались запитывать ваш модуль ESP напрямую с вашей платы FTDI и заставить его работать (в частности, сейчас достаточно часто используется программирование модулей ESP с помощью использования платы Arduino в качестве платы FTDI как, например, продемонстрировано в данной статье), но ниже приведены причины для создания собственной схемы питания модуля ESP:

  1. Только некоторые из плат FTDI могут обеспечить достаточный ток для модуля ESP. При этом некоторые модули ESP могут потреблять больший ток, чем другие аналогичные модули, во время загрузки в них программы. Следовательно, всегда безопаснее иметь свой собственный источник (схему) питания для модуля ESP. Эту схему проще собрать на точечной плате, нежели на макетной плате.
  2. Перед загрузкой кода программы всегда необходимо сбрасывать модуль ESP. Создание собственной схемы питания модуля позволяет легко интегрировать в нее кнопку для осуществления сброса модуля.
  3. Вывод GPIO0 модуля ESP должен быть заземлен при программировании с помощью Arduino IDE и должен быть оставлен свободным (не подключенным) при использовании AT команд – это легко реализовать в нашей собственной схеме. Мы использовали переключатель для переключения между режимом AT команд и режимом программирования с помощью Arduino IDE.
  4. Программирование модуля ESP осуществляется с использованием последовательной связи – при использовании макетной платы некоторые ненадежно закрепленные контакты могут привести к ошибке в процессе последовательной передачи данных, тогда вам придется повторять процесс программирования модуля сначала.

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

Создание платы для программирования ESP8266

Итак, мы занимаемся созданием платы для программирования модуля ESP8266, которая имеет свою собственную схему питания ESP8266.

Как уже отмечалось, наш модуль потребляет ток примерно 800mA во время его программирования. Наш собственный блок для питания модуля мы собрали на основе микросхемы регулятора напряжения LM317, которая выдерживает ток до 1.2A. Входное напряжение на микросхему LM317 в нашем проекте подается 12V, его можно обеспечить с помощью простого адаптера 12V 2A. На выходе микросхемы LM317 мы получаем стабилизированное напряжение 3.3V с помощью резисторов сопротивлением 220 и 360 Ом.

Формула для расчета выходного напряжения микросхемы LM317 выглядит следующим образом:

Vout = 1.25*(1+ (R2/R1))

В нашем случае, R1= 220 Ом, R2= 360 Ом.

Схема подключения модуля ESP8266 к остальным элементам схемы нашего проекта представлена в следующей таблице.

Номер контакта Название контакта ESP8266 Куда подключен
1 Ground земля платы FTDI
2 GPIO2 оставлен не подключенным
3 GPIO0 переключение между режимами программирования
4 Rx Tx платы FTDI
5 Tx Rx платы FTDI
6 CH_PH 3.3V от LM317
7 Reset к кнопке сброса
8 Vcc 3.3V от LM317

Для быстрого переключения между режимами AT команд и программирования с помощью Arduino IDE мы использовали в схеме переключатель (jumper), который на подает на GPIO 0 модуля землю (ground) во время использования Arduino IDE и оставляет его «свободно висящим в воздухе» во время использования AT команд.

Кнопка в схеме используется для сброса модуля ESP – во время ее нажатия происходит замыкание контакта сброса модуля (RST pin) на землю. Каждый раз перед программированием модуля ESP мы должны сбрасывать его.

После сборки схемы проекта на перфорированной плате у нас получилась следующая конструкция проекта.

Собранная на перфорированной плате схема проекта

Вместо перфорированной платы вы можете использовать макетную плату.

После сборки схемы подайте на нее питание без подключения модуля ESP и платы FTDI и проверьте точно ли мы вы получаете напряжение 3.3V на выходе микросхемы LM317. Проверьте то, что ваша плата FTDI может работать от 3.3V, и после этого подключайте плату FTDI и модуль ESP в схему.

Когда на модуль ESP будет подано питание, на нем должен загореться светодиод красного цвета.

Горящий светодиод красного цвета свидетельствует о работоспособности модуля ESP

После этого подключите вашу плату FTDI к компьютеру используя кабель mini-USB to USB, откройте диспетчер устройств на компьютере и в нем вы должны обнаружить к какому COM порту компьютера подключилась ваша плата FTDI, как показано на следующем рисунке.

COM порт компьютера которому подключен наш модуль ESP8266

После этого можно приступать к программированию вашего модуля ESP8266. Можно начать с AT команд, а потом перейти к его программированию с помощью Arduino IDE.

Видео, демонстрирующее работу проекта

Источник статьи

Загрузка…

4 737 просмотров

11 июля 2019

Представляем пример быстрого развертывания IoT-проекта на основе контроллера ESP32 от Espressif и стеков технологий Mongoose OS и Cloud IoT Core.

Перед вами проект, цель которого – разработка устройства с автоматической калибровкой датчиков присутствия, вывода информации на удаленный индикатор, сбора статистики для проверки наличия людей в нескольких кабинках. В статьях этого цикла мы дадим пошаговое руководство по установке операционной системы Mongoose OS на контроллер семейства ESP32, подключению устройства к облачному сервису Google – Cloud IoT Core, сохранению и обработке данных в базе данных Firebase, передаче на устройство и на индикатор конфигурации и управляющих команд. Для определения присутствия человека используются инфракрасные дальномеры Sharp c аналоговыми выходами.

Начнем с того, почему для реализации выбраны именно эти компоненты.

Wi-Fi-контроллер ESP32

Чип ESP32 является преемником известного ESP8266 – одного из самых бюджетных Wi-Fi-контроллеров. По сравнению с предшественником, в контроллере была повышена тактовая частота до 240 МГц, добавлено второе ядро, размер ОЗУ увеличен до 520 кбайт, увеличено количество выводов GPIO (в том числе – добавлены входы 12-битного АЦП, 18 каналов), Bluetooth, возможность шифрования памяти, аппаратное криптографическое ускорение: AES, SHA-2, RSA, ECC, RNG. Для разработки был использован модуль ESP32-PICO-KIT V4, расположение выводов которого приведено на рисунке 1.

Рис. 1. Контроллер ESP32-PICO-KIT V4

Рис. 1. Контроллер ESP32-PICO-KIT V4

Этот чип был выбран по таким критериям как цена, большое количество портов ввода-вывода, в том числе – аналоговых входов, аппаратное криптографическое ускорение.

 Mongoose OS

Обычно разработка логики приложения занимает порядка 20% общего времени разработки программы. Остальное время уходит на обеспечение работы с сетью, управление устройством, OTA-обновление прошивки, обеспечение безопасности и так далее. Операционная система Mongoose OS позволяет, сосредоточившись только на логике, быстро разработать прототип приложения на Javascript (JS) (конечно, если вы предпочитаете семейство языков С/С++, то можно писать и на нем, но, возможно, это будет несколько дольше), предоставляя множество API-интерфейсов для конфигурирования, работы с таймерами, протоколом MQTT, обработчики событий, средства для доступа к аппаратным ресурсам контроллера, периферии. Кроме того, программа на Javascript в большой степени кроссплатформенная – ее можно будет загрузить и в другие контроллеры с поддержкой Mongoose OS: STM32L4, STM32F4, STM32F7, CC3220, CC3200, ESP32, ESP8266. Mongoose OS поставляется с инструментом разработки mos, позволяющим легко взаимодействовать с контроллером, загружать файлы, обновлять прошивку, осуществлять вызовы RPC-функций.

Google Cloud

Перед вами – обширная облачная экосистема, включающая в себя необходимые для реализации проекта компоненты: MQTT-брокер Cloud IoT Core, хранилища данных Firebase и Big Query, хостинг, облачные функции для реализации логики обработки сообщений, конфигурирования датчиков и многое другое. Ко всему есть готовые, хорошо документированные API, единая система контроля доступа IAM (Cloud Identity & Access Management) повышает безопасность приложения.

Датчик присутствия

В качестве датчика присутствия выбраны оптические датчики Sharp GP2Y0A710K0F с рабочим расстоянием 100…550 см (в зависимости от геометрии пространства, в котором нужно проводить измерения, датчик может быть заменен на любой аналогичный с требуемым диапазоном). В отличие от ультразвуковых дальномеров, этот датчик имеет относительно узкую апертуру, что исключает отражение от стен. Также, в отличие от пирометрических, данный датчик срабатывает, в том числе, на неподвижные объекты.

Расстояние до объекта датчик измеряет при помощи метода триангуляции. Инфракрасный светодиод излучает короткий импульс, который отражается (или не отражается) от препятствия. Угол падения отраженного импульса зависит от расстояния до объекта. Аналоговое напряжение, соответствующее расстоянию до объекта (зависимость совсем не линейная, но, поскольку нужно только ответить на вопрос наличия человека, то это не принципиально), подается на выход датчика.

Общее описание проекта

Блок датчиков состоит из ESP-32, трех аналоговых оптических дальномеров Sharp GP2Y0A710K0F и опционального датчика освещения. При изменении состояния одного из датчиков (выходе измеренного напряжения за заданные пределы или возврате в исходное состояние) в Cloud IoT Core отправляется сообщение по протоколу MQTT с текущим состоянием датчиков. В облачных функциях Firebase реализован триггер, срабатывающий при поступлении такого сообщения. По этому триггеру происходит сохранение данных в Google Sheet, Firebase, и Big Query (естественно, так много хранилищ данных в реальном проекте использовать не нужно, в этом проекте они используются в целях демонстрации).

В Firebase формируется и отправляется в Cloud IoT Core настройка для блока датчиков, которая загружается в устройство после его перезагрузки и подключения.

Схема устройства достаточно проста – нужно подключить датчики к аналоговым входам ESP32 и подать питание.

Обратите внимание на два момента: при работе Wi-Fi становится недоступен второй порт АЦП (видимо, проблема в SDK от Espressif). Многие модули с ESP32 требовательны к питанию и при использовании длинных тонких проводов и маломощных источников могут перезагружаться по Brownout.

Облачные технологии Google

Архитектура проекта на первом этапе будет аналогична проекту погодной станции (рисунок 2).

Рис. 2. Архитектура проекта

Рис. 2. Архитектура проекта

Блок датчиков публикует данные телеметрии по протоколу MQTT в Cloud IoT Core. Сервис Cloud Pub/Sub организует подписки и отправляет сообщения получателям. В Firebase функция-триггер, подписанная на сообщения, сохраняет данные во всех хранилищах.

Cloud IoT Core

Cloud IoT Core – это сервис облачной экосистемы Google Cloud Platform, в который каждое из зарегистрированных в нем устройств может отправлять данные датчиков. Отправка данных называется публикацией события телеметрии. В принципе, за каждое опубликованное событие Google может захотеть получить оплату, но для небольших проектов, обычно, достаточно бесплатной квоты. Кроме того, при подключении на счет кладется $300 бонусов, которые можно использовать в первый год работы.

MQTT

Публикация сообщений осуществляется по протоколу MQTT. Сообщение телеметрии публикуется устройством (в терминологии MQTT – «издателем») в Cloud IoT Core (MQTT bridge, брокер MQTT) в тему, имя которой должно соответствовать формату:


/devices/{device-id}/events

Публиковать сообщение можно не только в саму папку, но и в ее подпапки.

Идентификатор {device-id} должен быть уникален для каждого устройства. В случае использования Mongoose OS идентификатор создается из последних 3 байтов MAC-адреса контроллера ESP32, например esp32_ABCDEF.

 Качество обслуживания (QoS)

В спецификации MQTT описаны три уровня качества обслуживания (QoS), используемые при публикации сообщений:

  • QoS 0 – сообщение доставляется не более одного раза;
  • QoS 1 – сообщение доставляется как минимум один раз;
  • QoS 2 – сообщение доставляется ровно один раз.

Google IoT Core поддерживает QoS 0 и QoS 1. Уровень качества обслуживания можно указать при публикации сообщения.

Безопасность

Связь между устройством и Cloud IoT Core осуществляется через шифрованное соединение TLS, поэтому можно гарантировать, что устройство подключено к серверу Cloud IoT Core MQTT (сертификаты создаются и хранятся в файловой системе Mongoose OS), обмен данными защищен и целостность данных проверена. Аутентификация устройства в Cloud IoT Core выполняется с помощью открытого/закрытого ключа для каждого контроллера с использованием JSON Web Token (JWT). Контроллер подписывает JWT своим закрытым ключом, а Cloud IoT Core проверяет его, используя связанный открытый ключ. Ключи можно сгенерировать и опубликовать с помощью инструмента mos. Для исключения компрометации закрытого ключа память контроллера ESP32 может быть зашифрована.

Хранилище (registries)

 Хранилище – это условный способ объединения однотипных устройств. В хранилище задаются топики для публикации телеметрии.

Cloud Pub/Sub

Телеметрические данные со всех устройств, принадлежащих одному и тому же хранилищу, пересылаются в топик Cloud Pub/Sub (элемент экосистемы Google Cloud). Названия топиков (Cloud Pub/Sub topic) должны иметь следующий вид:


projects/ИМЯ_ПРОЕКТА/topics/ИМЯ_ТОПИКА

В общем случае, контроллер публикует сообщения телеметрии и статуса и получает сообщения конфигурации (если он, конечно, на них подписан). Функции Firebase получают сообщения телеметрии и публикуют новые конфигурации (или команды) для контроллера.

Хранение и визуализация данных

Рис. 3. Хранение и визуализация данных

Рис. 3. Хранение и визуализация данных

Публикация данных телеметрии в разделе Cloud Pub/Sub будет запускать облачную функцию Firebase, которая будет сохранять полученные результаты в выбранных базах данных: Firebase Realtime Database, Google Spread Sheet, BigQuery. Сайт, размещенный на хостинге Firebase, будет динамически отображать (рисунок 3) данные из базы данных Firebase Realtime Database (или другого источника).

BigQuery – альтернативный способ хранения данных. Это хранилище позволяет извлекать данные с помощью SQL-запросов. Вместе с Data Studio помогает быстро визуализировать необходимую информацию и оформить ее в профессионально выполненный dashboard.

Google SpreadSheet – доступный инструмент хранения табличных данных. В рабочем приложении, скорее всего, он не понадобится, но на этапе тестирования позволит легко, без дополнительного программирования просмотреть сохраненные данные и построить графики.

Сообщения «Config» и «State»

На диаграмме архитектуры проекта, приведенной на рисунке 1, помимо телеметрии, есть два дополнительных потока данных: Config и State (рисунок 4).

Рис. 4. Сообщения Config (Конфигурации) и State (Состояния)

Рис. 4. Сообщения Config (Конфигурации) и State (Состояния)

Это два служебных топика, существующих по умолчанию в каждом хранилище Cloud IoT Core. В некоторых других облачных сервисах аналогичную роль выполняет Shadow.

Если опубликовать сообщение в топике Config, то подписанное на этот топик устройство гарантированно получит это сообщение. Кроме того, сообщение конфигурации поступит на устройство и при его перезагрузке. Изменение параметров конфигурации полезно, когда необходимо, чтобы устройство перешло в новое состояние, например, чтобы изменить настройки одного из датчиков, период глубокого сна, положение серводвигателя и так далее.

Google рекомендует отправлять не более одного сообщения такого типа в секунду на устройство. Каждое сообщение может быть размером до 64 кбайт. Название темы конфигурации следующее:


/devices/{device-id}/config

После опубликования новой конфигурации вам наверняка захочется узнать, достигнут ли ожидаемый эффект. Проверить это можно с помощью сообщений состояния (State) – другой специальной темы, на которую автоматически подписывается Cloud IoT Core. Кроме всего прочего, сообщения состояния могут содержать информацию о сети, количестве доступной оперативной памяти, промежутке времени с момента последней перезагрузки, состоянии входов и прочем.

Как и в случае с конфигурацией, Google не рекомендует публиковать сообщения такого рода чаще чем раз в секунду для каждого устройства. Каждое сообщение может быть размером до 64 кбайт. Название темы состояния следующее:


/devices/{device-id}/state

Примечание. Кроме конфигурации и состояния, Cloud IoT Core предоставляет еще один служебный топик – Команды. Работа с ним аналогична работе с топиком конфигурации.

Установка ОС Mongoose на контроллер

Краткое описание Mongoose OS

Mongoose OS – это IoT-ориентированная операционная система, работающая на контроллерах STM32L4, STM32F4, STM32F7, CC3220, CC3200, ESP32, ESP8266. Mongoose OS имеет API к основным облачным сервисам IoT: Amazon AWS IoT, Google IoT Core, IBM Watson, Microsoft Azure IoT, Samsung Artik. Версия Mongoose OS Community Edition бесплатная и распространяется под лицензией Apache 2.0. Входящий в состав ОС инструмент разработки mos позволяет сформировать и загрузить прошивку, обновить файлы, подготовить устройство для работы с платформой IoT. Mos работает либо в пользовательском интерфейсе, либо в командной строке, либо в браузере. Mongoose OS имеет многочисленные API, упрощающие доступ к сетевым сервисам и датчикам. Программы для операционной системы можно писать как на C/C++, так и на JS (JS позволит быстро написать прототип приложения, а C/C++ обеспечат экономию памяти и более глубокий доступ к возможностям контроллера). Впрочем, в JS предусмотрен функционал для вызова функций C, и ничто не мешает обращаться из JS напрямую к Espressif SDK.

В экосистеме Mongoose есть облачное приложение для управления устройствами под названием mDash (с ограничением на три устройства с бесплатной лицензией; платная лицензия стоит около $2, интерес представляет возможность «коробочного» обновления прошивки «по воздуху» и изменения файлов) и еще несколько сервисов, доступных только при покупке платной лицензии.

Установка Mongoose на ESP32

Инструкция приведена на сайте Mongoose OS и занимает примерно 11 минут. Для наших целей выполнять шаги с 8 по 10 не требуется, так что время установки сократится до 6 минут (рисунок 5).

Рис. 5. Инструкция установки Mongoose на ESP32

Рис. 5. Инструкция установки Mongoose на ESP32

Последовательность установки операционной системы на контроллер:

1…3. Нужно скачать и запустить программу, подключить плату с контроллером и, при необходимости, для подключения к контроллеру установить драйвер;

  1. Создание тестового приложения в папке appTest. С помощью команды mos clone https://github.com/mongoose-os-apps/demo-js appTest тестовое приложение будет клонировано в папку appTest, и на эту же папку изменится рабочая папка приложения mos (рисунок 6).

Рис. 6. Создание тестового приложения в папке appTest

Рис. 6. Создание тестового приложения в папке appTest

В папке appTest/fs/ расположен исходный файл приложения с именем init.js. Приложение умеет взаимодействовать с различными платформами IoT (если они, конечно, сконфигурированы).

Примечание. Следующие шаги покажут, как собрать прошивку и загрузить ее в устройство.

  1. Для сборки прошивки в приложении mos нужно в выпадающем списке вверху выбрать целевую платформу (ESP32). Сборка запускается командой mos build (если вы работаете из терминала, добавьте ключ arch esp32 к этой строке). Сборка выполняется в облаке и занимает некоторое время. Если конфигурация программы не изменяется, то сборку больше выполнять не требуется. Достаточно будет только обновить файл в файловой системе контроллера (если вам необходимо выполнять сборку на локальном компьютере – воспользуйтесь инструкцией на сайте mongoose). Результатом выполнения этого шага будет создание множества файлов в папке appTest/. Один из созданных файлов – appTest/build/fw.zip – содержит прошивку микроконтроллера. На следующем шаге эта прошивка будет загружена в целевое устройство.
  2. Загрузка прошивки выполняется командой mos flash. Как и сборку, в большинстве случаев эту команду нужно выполнить только один раз. При изменении программы init.js или одного из рабочих файлов изменения можно будет загрузить командой mos put. Процесс прошивки отображается в консоли mos. После завершения прошивки контроллер автоматически перезагрузится (ход загрузки и возможные ошибки будут видны в терминале) и запустится скрипт init.js.

В терминале mos (или в любом другом терминале, подключенном на скорости 115 кбайт/с) каждую секунду будет появляться строка состояния.


[Jun 17 19:11:09.543] online: false
{ram_free”: 31200, “uptime”:6.516889, “btnCount”:0, “on”:false}
  1. Подключение к Wi-Fi выполняется командой:

mos wifi WIFI_NETWORK_NAME WIFI_PASSWORD

Контроллер сам попытается подключиться к сети, получит IP-адрес, выполнит синхронизацию времени. Если доступ к сети не сконфигурирован, контроллер по умолчанию будет работать в режиме точки доступа с запущенным веб-сервером, после подключения к этой точке доступа (пароль: Mongoose) страницу устройства, – файл appTest/fs/index.html, – можно открыть по адресу: 192.168.4.1. В дальнейшем для конфигурации беспроводной сети можно будет добавить на эту страницу форму для задания логина и пароля сети. Изменить имя точки доступа, пароль и ip-адрес можно, перезаписав конфигурацию в настройках приложения:


"wifi": {
	"ap": {
		"enable": true,        // Разрешение работы точки доступа
		"ssid": "Mongoose_??????",  // Имя SSID. Символы ?? заменяются MAC адресом
		"pass": "Mongoose",      // Пароль
		"hidden": false,       // Скрывать WiFi сеть
		"channel": 6,         // Канал WiFi
		"max_connections": 10,    // Максимальное количество подключений
		"ip": "192.168.4.1",     // Статический IP Адрес
		"netmask": "255.255.255.0",  // Маска подсети
		"gw": "192.168.4.1",     // Шлюз по умолчанию
	}
}

Управление конфигурацией подробно описано в документации. Обратите внимание, что после любого изменения конфигурации нужно заново собирать и загружать прошивку. Если не принять специальных мер, после загрузки прошивки будут сброшены настройки Wi-Fi, подключения к облаку и так далее. Узнать настройки конфигурации можно с помощью команды mos config-get KEY, а изменить – с помощью mos config-set KEY=VALUE. Команда получения настроек может вернуть JSON или значение конкретного ключа, командой установки можно задать только простые типы значений – строки, числа.

Из консоли mos с помощью вызовов RPC можно получить информацию об устройстве и узнать состояние подключения, например, IP-адрес. Делается это комбинацией клавиш CTRL + i в mos или командой mos call Sys.GetInfo.

В mos есть еще несколько полезных сочетаний клавиш, они видны в консоли команд приложения после загрузки.

Шаги 5…7 должны выполняться для каждого настраиваемого устройства. Конечно, для однотипных платформ, например, только для ESP32, шаг 5 повторять не нужно.

Hello, word

Теперь напишем тестовую программу, переключающую по таймеру состояние выхода контроллера и выводящую в терминал сообщения:



/*
 Мигание встроенным светодиодом и вывод на консоль
 Светодиод подключен к GPIO2.
 Управление таймером:
 - https://mongoose-os.com/docs/mos/api/core/mgos_timers.h.md
*/

load('api_config.js');
load('api_gpio.js');
load('api_timer.js');

let pin = 2; // вывод, к которому подключен светодиод

GPIO.set_mode(pin, GPIO.MODE_OUTPUT);

// вызов каждые две секунды
Timer.set(2000, Timer.REPEAT, function() {
	let value = GPIO.toggle(pin);
	print(value ? 'Tick' : 'Tack');
}, null);

Этот код нужно сохранить вместо загруженного ранее демоскрипта по адресу appTest/fs/init.js.

Для редактирования можно использовать любую IDE, поддерживающую язык JS. Из программы mos загрузим новый скрипт в файловую систему ОС Mongoose:


mos put fs/init.js

и выполним перезагрузку:


mos call Sys.Reboot

Светодиод должен мигать, а мы – должны увидеть сообщения Tick и Tack в консоли.

Подключение I2C-датчика

Для ряда популярных датчиков в Mongoose есть готовые библиотеки. Рассмотрим случай, когда готовой библиотеки нет. Вот что нужно сделать для подключения произвольного датчика:

  1. Проверить, что в состав прошивки включена библиотека I2С. Для этого нужно открыть файл конфигурации mos.yml и проверить наличие в разделе libs строки – origin: https://mongoose-os-libs/i2c. Если такой строки нет, то ее нужно добавить, и после этого заново собрать и загрузить прошивку.
  2. Проверить/создать/изменить конфигурацию выводов I2С. Конфигурация I2C должна выглядеть следующим образом:

 "i2c": {
  "unit_no": 0,
  "enable": true,
  "freq": 100000,
  "debug": false,
  "sda_gpio": 32,
  "scl_gpio": 33
 } 

Нужно обратить внимание на то, что работа I2C разрешена «enable»: true и на используемые номера портов для подключения устройств. Если что-то сконфигурировано неправильно, нужно это поправить в файле конфигурации mos.yml и обновить прошивку.

  1. Подключить библиотеку к скрипту. Для этого достаточно добавить строку load(‘api_i2c.js’); в начало файла fs/init.js.
  2. Инициализировать шину I2C и датчик. Для измерения освещенности использован датчик MAX44009. Инициализация шины и датчика выполняются командами:

let bus = I2C.get();

let result = I2C.writeRegB(bus, 0x4A, 0x02, 0x40);
  1. Добавить таймер для регулярного получения данных с датчика. Обработчик таймера должен считать данные из регистров 0x03 и 0x04.

Полностью код скрипта для регулярного опроса I2C-датчика следующий:



/*
 Опрос датчика MAX44009, вывод на консоль
 I2C: 
 - https://mongoose-os.com/docs/mongoose-os/api/core/i2c.md
*/
load('api_config.js');
load('api_timer.js');
load('api_i2c.js'); 

let bus = I2C.get(); 
let result = I2C.writeRegB(bus, 0x4A, 0x02, 0x40); 

// вызов каждые две секунды
Timer.set(2000, Timer.REPEAT, function() {
	let val = I2C.readRegB(bus, 0x4A, 0x03);
	let val1 = I2C.readRegB(bus, 0x4A, 0x04);
	let exponent = (val & 0xF0) >> 4;
	let mantissa = ((val & 0x0F) << 4) | (val1 & 0x0F);
	let lightLevel = Math.pow(2, exponent) * mantissa * 0.045;
	print(lightLevel);
}, null);

После сохранения файла нужно его загрузить в контроллер и перезагрузить устройство:


mos put fs/init.js
mos call Sys.Reboot

После этого в консоли появятся данные датчика:


[Jun 17 21:47:06.528] 142.560000

[Jun 17 21:47:08.521] 142.560000

[Jun 17 21:47:10.520] 143.280000

[Jun 17 21:47:12.521] 142.560000

Подключение аналогового датчика

Шаги аналогичны инструкции из предыдущего раздела, вы можете выполнить их самостоятельно.

Для информации:

  • библиотека – https://github.com/mongoose-os-libs/adc;
  • строка подключения – load(‘api_adc.js’);
  • инициализация порта – ADC.enable(port);
  • измерение ADC.read(port).

Обратите внимание: второй порт АЦП в принципе не работает одновременно с Wi-Fi; для уменьшения шума рекомендуется отключать Wi-Fi перед измерением.

 Публикация сообщений телеметрии (MQTT)

Объединим результаты двух предыдущих скриптов и добавим публикацию телеметрии в Google Cloud (или любом другом настроенном mqtt-сервере).

Топик для публикации задается шаблоном: /devices/{device-id}/events.

Сообщения публикуем в формате JSON, чтобы облегчить их дальнейшую обработку с помощью облачной функции Firebase, подписанной на эти сообщения:



/*
Простой датчик с отправкой данных в Google Cloud
 */

load('api_config.js');
load('api_timer.js');
load('api_sys.js');
load('api_i2c.js');
load('api_mqtt.js');
load('api_adc.js');

let bus = I2C.get();
let lightAdr = 0x4A; //I2C-адрес датчика освещенности
let port=35; 
let topic = '/devices/' + Cfg.get('device.id') + '/';
//добавить events | config | state для получения реального адреса

let Sensors = {
	lightLevel: 0,
	dist:0,
	report: function () {
		return {
			dst: this.dist,
			l: this.lightLevel
		};
	},
	// инициализация датчиков
	init: function () {
		ADC.enable(port);
		let result = I2C.writeRegB(bus, lightAdr, 0x02, 0x40);
        // ручной режим работы по запросу
		return;
	},
	// проведение измерения
	measure: function () {
		let tempDist = 0;
		for (let j = 0; j < 5; j++) {
                    tempDist += ADC.read(port);
                    Sys.usleep(17000);
        // задержка между измерениями в датчике расстояния
                }
                this.dist = tempDist / 5; // измерение освещенности
                let val = I2C.readRegB(bus, lightAdr, 0x03);
                let val1 = I2C.readRegB(bus, lightAdr, 0x04);
                let exponent = (val & 0xF0) >> 4;
		let mantissa = ((val & 0x0F) << 4) | (val1 & 0x0F);
		this.lightLevel = Math.pow(2, exponent) * mantissa * 0.045;
		return;
	}
};
// инициализация датчиков
Sensors.init();
// функция для отправки объекта в облако
let MQTTSend = function (suff, obj) {
	let msg = JSON.stringify(obj);
	if (MQTT.isConnected()) {
		let ok = MQTT.pub(topic + suff, msg, 1);
		print(ok, suff, msg);
	} else {
		print(suff + "= Not connected! ", msg);
	}
};

// таймер для запуска измерений и публикации в теме /devices/{device-id}/events
Timer.set(2000, Timer.REPEAT, function () {
	Sensors.measure();
	MQTTSend("events", Sensors.report());
}, null); 

После загрузки программы и перезапуска контроллера мы видим, что данные не отправляются (MQTT.isConnected()возвращает false):


[Jun 19 22:35:54.810] events= Not connected!

{“1”:1146.240000, “dst”:155.800000}

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

Настройка проекта в Google IoT Core

Установка Google Cloud SDK

Во-первых, нам нужно установить Google Cloud SDK, так как многие действия удобнее выполнять из терминала, вводя команды gcloud в командной строке. Скачать SDK можно со страницы загрузки Google Cloud SDK.

Для работы с Cloud IoT Core потребуются бета-версии gcloudкоманд. Их можно установить следующим образом:


gcloud components install beta

В принципе, большинство необходимых действий в Google IoT Core можно выполнить любым из трех способов:

  • с помощью Google Cloud Console;
  • с помощью API;
  • из командной строки командами gcloud.

Мы будем использовать последний способ, проверяя результат с помощью Google Cloud Console.

Настройка проекта Google Cloud

Последовательность настройки проекта Google Cloud приведена на сайте Mongoose OS:


# Приведенные ниже команды нужно выполнить всего один раз для настройки Google
# Cloud project! Они могут быть выполнены из любой папки

# Запрос авторизации в Google Cloud. В открывшемся окне нужно будет выбрать нужную
# учетную запись Google и разрешить доступ:

gcloud auth login

# Создание проекта. Например, выберем cabine-sensor-project как PROJECT_ID

gcloud projects create cabine-sensor-project

# Предоставление Cloud IoT Core прав на публикацию в Pub/Sub-теме:

gcloud projects add-iam-policy-binding cabine-sensor-project 
--member=serviceAccount:cloud-iot@system.gserviceaccount.com --role=roles/pubsub.publisher

# Установка проекта по умолчанию для gcloud:

gcloud config set project cabine-sensor-project

# Создание тем Pub/Sub для отправки телеметрии:

gcloud beta pubsub topics

create main-telemetry-topicgcloud beta pubsub topics create registry-topic

# Создание подписки Pub/Sub на созданную тему:

gcloud beta pubsub subscriptions create --topic main-telemetry-topic 
main-telemetry-subscription

# Создание хранилища для устройств (cabine-devices-registry)

# Определение топика Pub/Sub для публикации сообщений, в том числе для подпапки

# Запрет подключения по протоколу HTTP:

gcloud iot registries create cabine-devices-registry --project=cabine-sensor-project 
--region=europe-west1 --event-notification-config=topic=registry-topic,subfolder=registry 
--event-notification-config=topic=main-telemetry-topic --no-enable-http-config

# На запрос разрешения API нужно отвечать «да»

# Команда не будет работать, если на аккаунте не настроен биллинг

# В этом случае нужно перейти по ссылке, настроить биллинг и повторить команду

Регистрация устройства в проекте Cloud IoT Core

Программа mos предоставляет удобную команду для выполнения этой задачи. Следует просто набрать следующую команду с идентификатором проекта и именем регистра:


# Регистрация устройства в Cloud IoT Core (выполнить для каждого устройства!):
mos gcp-iot-setup --gcp-project cabine-sensor-project --gcp-region europe-west1 
--gcp-registry cabine-devices-registry

Эта команда сама, внутри программы mos, будет исполнять нужные gcloud-команды. Для выполнения команды требуется, чтобы регистрируемое устройство было подключено через последовательный порт к компьютеру, так как в результате выполнения команды на устройство будут загружены ключи, настроены адреса MQTT и так далее.

Результаты работы команды выводятся на консоль mos. В папке проекта появятся два ключа – закрытый и открытый. Закрытый ключ (xxx.key.pem) – для ESP32, а открытый (xxx.pub.pem) – для Google IoT Core (рисунок 7). Они будут использоваться во время процесса аутентификации с использованием JSON Web Token в Google IoT Core.

Рис. 7. Сгенерированная пара ключей

Рис. 7. Сгенерированная пара ключей

О безопасности ключей: закрытый ключ не должен храниться в виде текста во Flash-памяти контроллера. В инструкции на сайте Mongoose рассказано, как зашифровать память контроллера ESP32. Конечно, закрытый ключ не стоит хранить и в открытой папке на компьютере разработчика. По крайней мере, следует защитить доступ к нему с помощью пароля.

После перезагрузки устройства в консоли видно, что оно успешно подключается к Google MQTT-брокеру и публикует сообщения телеметрии (MQTT.pub()возвращает 1):


[Jun 19 22:36:01.913] events= Not connected! {“1”:1152, “dst”:434.600000}

[Jun 19 22:36:03.006] 1 events {“1”:1152, “dst”: 17.400000}

[Jun 19 22:36:05.081] 1 events {“1”:1152, “dst”: 4.600000}

[Jun 19 22:36:07.134] 1 events {“1”:1152, “dst”: 1.200000}

Проверка настроек проекта в Google Cloud Console

На панели управления Google Cloud можно убедиться, что все настроено правильно (рисунок 8).

Рис. 8. Создан проект, хранилище, топики для публикации сообщений

Рис. 8. Создан проект, хранилище, топики для публикации сообщений

При нажатии на идентификатор хранилища cabine-devices-registry откроется список подключенных к этому хранилищу устройств. Открыв одно из устройств, можно увидеть, когда это устройство загружало конфигурацию, обновляло состояние, передавало телеметрию (рисунок 9).

Рис. 9. Список устройств в хранилище

Рис. 9. Список устройств в хранилище

В меню Pub/Sub виден список топиков и созданных подписок (рисунок 10).

Рис. 10. Названия тем и связанных подписок в Google Cloud Console (Pub/Sub)

Рис. 10. Названия тем и связанных подписок в Google Cloud Console (Pub/Sub)

Просмотр данных телеметрии

Передаваемые данные можно посмотреть с помощью команды gcloud:


gcloud beta pubsub subscriptions pull --auto-ack main-telemetry-subscription --limit=2

Эта команда получает до двух сообщений Pub/Sub из подписки main-telemetry-subscription. На рисунке 11 видна полезная нагрузка в формате JSON и список атрибутов, в том числе идентификатор устройства.

Рис. 11. Результат извлечения телеметрических сообщений из подписки

Рис. 11. Результат извлечения телеметрических сообщений из подписки

Теперь можно перейти к следующему шагу – обработке и сохранению данных в Firebase.

Регистрация, хранение и визуализация данных в Firebase

Для реализации проекта нам потребуются несколько продуктов Firebase:

  • Облачные функции (Cloud Function for Firebase) реагируют на события (публикации в топике, запросы HTTP и так далее) и выполняют заданную логику (сохранение или извлечение данных, их обработка и передача).
  • База данных Firebase (Firebase Realtime Database) – NoSQL-хранилище для произвольной информации. Она позволяет сохранить или загрузить данные в произвольном формате, например JSON.

Примечание. тарификация в Firebase осуществляется за объем хранения и трафик. Поэтому будет разумно на рабочих приложениях использовать короткие наименования свойств передаваемых и сохраняемых объектов.

  • Хостинг (Firebase Hosting) хранит скрипты, используемые для формирования web-страниц для визуализации данных.

Конфигурация Firebase

Все продукты Google, в том числе и Firebase, объединяются в едином проекте. Чтобы начать пользоваться возможностями Firebase, включите его в созданном на прошлом этапе проекте cabine-sensor-project в консоли Firebase (рисунки 12 и 13).

Рис. 12. Firebase Console – Добавить проект

Рис. 12. Firebase Console – Добавить проект

Рис. 13. Выбор проекта из существующих

Рис. 13. Выбор проекта из существующих

Примечание. После подключения проекта от вас потребуется выбрать тарифный план Firebase. В большинстве случаев для небольших и тестовых проектов план Blaze с оплатой по факту использования ресурсов даст достаточно бесплатных квот.

Инициализация Firebase

Установите Node.js и инструменты Firebase.

Теперь нужно авторизоваться командой firebase login (откроется страница в браузере, где можно выбрать учетную запись Google) и выполнить команду инициализации firebase init из той папки, где расположен проект Firebase (файлы проекта находятся в общем репозитории в папке Firebase).

На первом шаге выберите продукты Firebase, которые будут использоваться (рисунок 14).

Рис. 14. Выбор продуктов Firebase

Рис. 14. Выбор продуктов Firebase

Второй шаг – установка проекта по умолчанию (рисунок 15) для текущей папки (cabine-sensor-project).

Рис. 15. Установка связи между проектом и папкой

Рис. 15. Установка связи между проектом и папкой

Примечание. Если проект не виден – попробуйте выйти из учетной записи Google firebase logout, а затем авторизоваться заново (firebase login).

Третий шаг – определение файла с правилами доступа к базе данных. Будем использовать наименование файла по умолчанию (рисунок 16).

Рис. 16. Правила базы данных по умолчанию

Рис. 16. Правила базы данных по умолчанию

Конфигурация облачных функций и хостинга показана на рисунке 17.

Рис. 17. Конфигурация облачных функций и хостинга

Рис. 17. Конфигурация облачных функций и хостинга

Обратите внимание: загруженные из репозитария GitHub файлы firebase/functions/index.js и firebase/public/index.html перезаписывать не нужно.

Триггер подписки на топик телеметрии

Firebase позволяет написать функцию-триггер для подписки на сообщения, публикуемые в топике Cloud Pub/Sub. Соответственно, в этой функции должна быть реализована вся логика по обработке и сохранению полученных данных.

Код функции следующий:



exports.detectTelemetryEvents = functions.pubsub.topic('main-telemetry-topic')
.onPublish((message, context) => {
	const l = message.json.l.toFixed(1);
	const dst = message.json.dst.toFixed(1);
	const deviceId = message.attributes.deviceId; 
	const timestamp = context.timestamp;
	// отправка лога в журнал:
	console.log(`Device=${deviceId}, light=${l}lux, distance=${dst},
                    Timestamp=${timestamp}`);
	const data = {
		t: timestamp,
		l: l,
		d: dst
	};
	// отправка в Firebase Realtime Database 
	return  db.ref(`devices-telemetry-simple/${deviceId}`).push(data);
});

Функция получает две переменные – полезную нагрузку сообщения message (содержащую в себе два объекта json с самим сообщением и attributes с его атрибутами) и контекст, содержащий свойства окружения – context.

Примечание. В журнал сообщений Google Cloud Firebase выводит информацию о запуске облачной функции и времени выполнения (и возникших ошибках). Эту информацию можно дополнить данными для отладки с помощью команды console.log(ИМЯ_ПЕРЕМЕННОЙ). Она создает сообщение в журналах облачных функций и позволяет контролировать их работу.

Еще одно важное замечание: в работе функций активно используется API Google. Это API по своей сути асинхронно, и для работы с ним удобно использовать Promise. Promise (обычно их так и называют – «промисы») предоставляют удобный способ организации асинхронного кода, позволяющий, в том числе, последовательно выполнить несколько асинхронных вызовов, передавая результаты из одного вызова в другой.

Развертывание облачной функции

Развертывание можно выполнить как для всего проекта командой firebase deploy, так и только для облачных функций (или даже одной функции):


firebase deploy --only functions

Проверка облачной функции

Для проверки работы функции нужно зайти в закладку «журналы» раздела «Облачные функции» консоли Firebase (рисунок 18).

Рис. 18. Firebase Console – Журналы облачных функций Firebase

Рис. 18. Firebase Console – Журналы облачных функций Firebase

Кроме того, в консоли Google Cloud, как показано на рисунке 19, можно не только посмотреть журналы функции, но и изменить код, протестировать функцию с заданными параметрами и удалить функцию (функции стоит удалять, так как производимый ими трафик и используемое для хранения место могут превысить бесплатные квоты).

Рис. 19. Google Cloud Console – облачные функции

Рис. 19. Google Cloud Console – облачные функции

В хранилище Firebase можно увидеть сохраненные данные телеметрии, путь сохранения (devices-telemetry-simple/${deviceId}) задан в функции detectTelemetryEvents (рисунок 20).

Рис. 20. Firebase Console – База данных в реальном времени

Рис. 20. Firebase Console – База данных в реальном времени

Примечание. Облачная функция имеет права администратора для доступа к базе данных, независимо от содержимого файла конфигурации database.rules.json. Для доступа из веб-приложения нужно прописать правила, но об этом ниже.

Веб-приложение для визуализации данных

В рамках этой статьи будет создано простое веб-приложение, умеющее только отображать график с показаниями датчиков. Возможности приложения можно будет расширить используя, например, Data Studio.

Для построения графиков будем использовать библиотеку plotly.

Для получения данных из Firebase используется следующий код:



// определение объекта базы данных:
const db = firebase.database();
// подписка на последние 100 записей по пути devices-telemetry/${devicesId}
db.ref(`devices-telemetry-simple/${devicesId}`).limitToLast(100).on('value', ts_measures => {
	// полезная нагрузка
});

Получать данные можно двумя способами: подписаться на обновления методом on() или извлечь их однократно методом once().

Чтобы скрипт смог извлечь данные из базы, нужно определить правила доступа в файле database.rules.json. Правила можно задать для конкретных узлов, в нашем случае для узла devices-telemetry-simple нужно дать разрешение на чтение:



{"rules": {"devices-telemetry-simple": { ".read": true, ".write": false}}}

Такая настройка дает права на чтение для веб-приложения. Права можно установить для узла любой степени вложенности и задать для конкретных пользователей. На доступ из консоли эти правила не распространяются – в консоли всегда администраторский доступ.

База Firebase устроена таким образом, что при запросе конкретного узла будут извлечены все данные из вложенных узлов. Поэтому не стоит читать корневой узел, это очень накладно (помним, что оплата идет за трафик). Данные телеметрии группируются по узлам с именами, совпадающими с именами устройств. Чтобы скрипт мог получить список устройств, на данном этапе создадим вручную в консоли Firebase узел devices-ids, в который занесем идентификаторы устройств. Скрипт веб-приложения предварительно прочитает этот узел и только потом начнет выгружать данные телеметрии для конкретного датчика. (В следующей статье будет рассказано, как сделать процесс добавления идентификаторов автоматическим и совместить его с конфигурированием вновь подключаемых устройств).

Соответственно, для узла devices-ids тоже нужно добавить правила в файл database.rules.json. В конечном итоге набор правил в файле должен стать таким:



{
	"rules": {
		"devices-ids": {
			".read": true,
			".write": false
		},
		"devices-telemetry-simple": {
			".read": true,
			".write": false
		}
	}
}

После редактирования и сохранения правила нужно развернуть с помощью команды:


firebase deploy --only database

Исходный код веб-приложения

Исходные коды скриптов веб-страниц находятся в папке firebase/public клонированного приложения. Там должно быть достаточно комментариев для понимания работы кода.

Локальное развертывание и тестирование

Для тестирования приложение Firebase можно запустить на локальном сервере:


firebase serve --only hosting

После развертывания по адресу http://localhost:5000 станет доступна страница с показаниями датчиков (рисунок 21).

Рис. 21. Данные датчика в реальном времени

Рис. 21. Данные датчика в реальном времени

Проверив, что все работает, можно перенести код на хостинг Firebase:


firebase deploy --only hosting

В результате работы этой команды мы получаем общедоступный URL-адрес веб-приложения, который можно увидеть в консоли Firebase на закладке Hosting (рисунок 22).

Рис. 22. Адреса приложения

Рис. 22. Адреса приложения

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

Заключение

В статье приведен пример быстрого развертывания жизнеспособного IoT-проекта на основе контроллера ESP32 и стека технологий Mongoose OS и Cloud IoT Core. В следующей статье этого цикла будет рассказано о генерации и обработке событий в Mongoose OS на ESP32, создании и вызове RPC-функций, шифровании памяти и обеспечении безопасности контроллера, автоматизации регистрации устройств в Firebase, их конфигурировании и отслеживании состояния, передаче состояния на удаленный индикатор. В облачные функции будет добавлен функционал сохранения данных в альтернативных хранилищах – Big Query и Google Sheet.

Дополнительные материалы для реализации проекта

  1. Погодная станция с Mongoose-os и Google Cloud IoT
  2. Быстрый запуск Mongoose
  3. Ограничения реализации JS в Mongoose
  4. Использование BigQuery и DataStudio
  5. Безопасность в Mongoose-OS
  6. Использование Promise в JS
  7. Файлы проекта на GitHub

•••

Руководство по ESP-NOW

В данном руководстве рассмотрим как использовать протокол беспроводной связи ESP-NOW для обмена короткими пакетами данных между платами ESP32.

title

Знакомство с ESP-NOW

ESP-NOW

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

ESP-NOW поддерживает следующие функции:

  • Зашифрованная и незашифрованная одноадресная передача;
  • Смешанные зашифрованные и незашифрованные одноранговые сети;
  • Полезная нагрузка может составлять до 250 байт ;
  • Выполнение обратных функций, которые могут служить для обратной связи.

Технология ESP-NOW также имеет следующие ограничения:

  • В режиме станции поддерживается не более 10 зашифрованных одноранговых узлов; Не более 6 в режиме SoftAP или SoftAP + Station;
  • Поддерживается несколько незашифрованных одноранговых узлов, однако их общее количество должно быть не больше 20, включая зашифрованные одноранговые узлы;
  • Полезная нагрузка ограничена 250 байтами.

Проще говоря, ESP-NOW – это протокол связи, который можно использовать для обмена небольшими сообщениями (до 250 байт) между платами ESP32.

Односторонняя связь ESP-NOW

Рассмотрим пример, когда плата ESP32 отправляет данные на другую плату ESP32.

Эту конфигурацию очень легко реализовать, и она отлично подходит для отправки данных с одной платы на другую, таких как показания датчиков или команды включения и выключения GPIO.

one-way-communication

Отправка данных по структуре one-master-multiple-slaves

Одна плата ESP32 отправляет команды на разные платы ESP32. Эта конфигурация идеальна для создания чего-то вроде пульта дистанционного управления. В доме может быть несколько плат ESP32, которые управляются одной основной платой ESP32.

one-master-multi-slave

Отправка данных по структуре one-slave-multi-master

Эта конфигурация подходит, если вы хотите собрать данные с нескольких плат на одну. Это может быть конфигурация веб – сервера для отображения данных из других плат, например:

one-slave-multi0mater

Примечание: в документации ESP-NOW нет такого понятия, как «sender/master» и «receiver/slave». Каждая плата может быть отправителем и получателем. Однако для ясности мы будем использовать термины «отправитель» и «получатель» или «master» и «slave».

Двусторонняя связь ESP-NOW

С ESP-NOW каждая плата может быть отправителем и получателем одновременно.

Например, у вас может быть две платы, взаимодействующие друг с другом.

two-way-communication

Вы можете добавить больше плат в эту конфигурацию и получить нечто похожее на сеть (все платы ESP32 будут взаимодействовать друг с другом).

many-esp-now

Таким образом, ESP-NOW также подходит для построения сети, в которой может быть несколько плат ESP32, обменивающихся данными друг с другом.

Получение MAC-адреса платы

Чтобы отправлять сообщения через ESP-NOW, вам нужно знать MAC-адреса плат. Каждая плата имеет уникальный MAC-адрес

Загрузите следующий код на каждую плату-приемник, чтобы получить их MAC-адреса.

#ifdef ESP32 

#include <WiFi.h>

#else 

#include <ESP8266WiFi.h>

#endifvoid

setup() { 

Serial.begin(115200); 

Serial.println(); 

Serial.print(«ESP Board MAC Address:  «); 

Serial.println(WiFi.macAddress());

}

void loop(){

}

После загрузки кода нажмите кнопку RST / EN, и MAC-адрес должен отобразиться в мониторе порта.

mac-seria-monitor

Стоит записать MAC-адрес платы на бирке, чтобы было удобнее идентифицировать каждую плату.

naming

Односторонняя связь «точка-точка»

Чтобы ознакомиться с принципом работы беспроводной связи ESP-NOW, создадим простой проект, который будет отправлять сообщение от одной ESP32 к другой. Одна ESP32 будет «отправителем», а другая – «получателем».

one-way-communication

Мы отправим переменные типа char , int , float , String и boolean . Поняв как это работает, вы сможете изменить код и отправлять любые типы переменных, подходящие для вашего проекта (например, показания датчиков или логические переменные для включения или выключения чего-либо).

Для лучшего понимания мы будем называть плату-отправителя номером 1 и получателя номером 2.

Вот что мы должны включить в скетч для платы №1:

  • Запуск протокола ESP-NOW;
  • Создание обратной функции OnDataSent, которая будет выполняться при отправке сообщения.;
  • Добавка MAC-адреса получателя.
  • Отправка сообщения.

Со стороны платы №2 в скетче должно быть:

  • Запуск протокола ESP-NOW;
  • Создание обратной функции OnDataRecv, которая будет выполняться при получении сообщения.;
  • Внутри этой функции должно быть реализовано сохранение сообщения в переменной, для выполнения задач с этой информацией.

ESP-NOW работает с обратными функциями, которые вызываются, когда устройство получает сообщение или когда сообщение отправлено.

Полезные функции ESP-NOW

Вот краткое о наиболее важных функциях ESP-NOW:

Функция Название и описание
esp_now_ init() Инициализирует ESP-NOW. Перед инициализацией ESP-NOW необходимо подключиться к Wi-Fi.
esp_now_add_ peer() Требуется, чтобы связать устройство и передать в качестве аргумента MAC-адрес устройства.
esp_now_ send() Отправляет данные с помощью ESP-NOW.
esp_now_register_send_ cb() Создает обратную функцию, которая вызывается при отправке данных. Когда сообщение отправлено, функция сообщает была ли доставка успешной.
esp_now_register_rcv_ cb() Создает обратную функцию, которая вызывается при получении данных. Когда сообщение получено, функция сообщает было ли получение успешным.

Для получения дополнительной информации об этих функциях прочтите документацию.

Скетч для платы-отправителя ESP32

Вот код для платы-отправителя. Скопируйте код в Arduino IDE, но пока не загружайте его. Вам нужно будет сделать несколько исправлений.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

/*

  Rui Santos

  Complete project details at https://RandomNerdTutorials.com/esp-now-esp32-arduino-ide/

  Permission is hereby granted, free of charge, to any person obtaining a copy

  of this software and associated documentation files.

  The above copyright notice and this permission notice shall be included in all

  copies or substantial portions of the Software.

*/

#include <esp_now.h>

#include <WiFi.h>

// ЗАМЕНИТЕ МАС-АДРЕСОМ ПЛАТЫ-ПОЛУЧАТЕЛЯ

uint8_t broadcastAddress[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};

// Структура в скетче платы-отправителя

// должна совпадать с оной для получателя

typedef struct struct_message {

  char a[32];

  int b;

  float c;

  String d;

  bool e;

} struct_message;

// Создаем структуру сообщения myData

struct_message myData;

// Обратная функция отправки

void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {

  Serial.print(«rnLast Packet Send Status:t»);

  Serial.println(status == ESP_NOW_SEND_SUCCESS ? «Delivery Success» : «Delivery Fail»);

}

void setup() {

  // Запускаем монитор порта

  Serial.begin(115200);

  // Выбираем режим WiFi

  WiFi.mode(WIFI_STA);

  // Запускаем протокол ESP-NOW

  if (esp_now_init() != ESP_OK) {

    Serial.println(«Error initializing ESP-NOW»);

    return;

  }

  // Регистрируем отправку сообщения

  esp_now_register_send_cb(OnDataSent);

  // Указываем получателя

  esp_now_peer_info_t peerInfo;

  memcpy(peerInfo.peer_addr, broadcastAddress, 6);

  peerInfo.channel = 0;  

  peerInfo.encrypt = false;

  if (esp_now_add_peer(&peerInfo) != ESP_OK){

    Serial.println(«Failed to add peer»);

    return;

  }

}

void loop() {

  // Указываем данные, которые будем отправлять

  strcpy(myData.a, «THIS IS A CHAR»);

  myData.b = random(1,20);

  myData.c = 1.2;

  myData.d = «Hello»;

  myData.e = false;

  // Отправляем сообщение

  esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));

  if (result == ESP_OK) {

    Serial.println(«Sent with success»);

  }

  else {

    Serial.println(«Error sending the data»);

  }

  delay(2000);

}

Как работает код?

Сначала подключаем библиотеки esp_now.h и WiFi.h.

В следующей строке мы должны вставить MAC-адрес получателя ESP32.

uint8_t broadcastAddress [] = {0x30, 0xAE, 0xA4, 0x07, 0x0D, 0x64};

В нашем случае MAC-адрес получателя: 30: AE: A4: 07: 0D: 64, но вам нужно будет заменить эту переменную своим собственным MAC-адресом.

Затем создаём структуру, содержащую тип данных, которые мы хотим отправить. Мы назвали эту структуру struct_message, и она содержит 5 различных типов переменных.

typedef struct struct_message {

char a[32];

int b;

float c;

String d;

bool e;

} struct_message;

Затем создаём новую переменную типа struct_message с именем myData, в которой будут храниться значения переменных.

Затем вводим функцию OnDataSent (). Она будет выполняться при отправке сообщения. В нашем случае эта функция просто выводит, было ли сообщение успешно доставлено.

void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {

Serial.print(«rnLast Packet Send Status:t»);

Serial.println(status == ESP_NOW_SEND_SUCCESS ? «Delivery Success» : «Delivery Fail»);

}

В функции setup () инициализируем монитор порта для отладки:

Устанавливаем режим Wi-Fi:

Запускаем ESP-NOW:

if (esp_now_init() != ESP_OK) {

Serial.println(«Error initializing ESP-NOW»);

return;

}

После успешной инициализации ESP-NOW вводим обратную функцию OnDataSent ().

esp_now_register_send_cb (OnDataSent);

После этого нам нужно выполнить сопряжение с другим устройством для отправки данных. Вот что мы делаем в следующих строках:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

// Зарегистрируем получателя

esp_now_peer_info_t peerInfo;

memcpy(peerInfo.peer_addr, broadcastAddress, 6);

peerInfo.channel = 0;

peerInfo.encrypt = false;

// Добавляем пира

if (esp_now_add_peer(&peerInfo) != ESP_OK){

Serial.println(«Failed to add peer»);

return;

}

В loop() мы будем отправлять сообщение через ESP-NOW каждые 2 секунды (вы можете изменить время задержки).

Сначала мы устанавливаем значения переменных следующим образом:

strcpy(myData.a, «THIS IS A CHAR»);

myData.b = random(1,20);

myData.c = 1.2;

myData.d = «Hello»;

myData.e = false;

Помните, что myData – это структура. Здесь мы назначаем значения, которые хотим отправить внутри структуры. Например, первая строка назначает char, вторая строка назначает случайное число Int, Float, String и логическую переменную.

Мы создаем такую структуру, чтобы показать, как отправлять наиболее распространенные типы переменных.

Наконец, отправляем сообщение следующим образом:

esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));

Проверяем, успешно ли было отправлено сообщение:

if (result == ESP_OK) {

Serial.println(«Sent with success»);

}

else {

Serial.println(«Error sending the data»);

}

loop () выполняется каждые 2000 миллисекунд (2 секунды).

Скетч для платы-получателя

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

/*

  Rui Santos

  Complete project details at https://RandomNerdTutorials.com/esp-now-esp32-arduino-ide/

  Permission is hereby granted, free of charge, to any person obtaining a copy

  of this software and associated documentation files.

  The above copyright notice and this permission notice shall be included in all

  copies or substantial portions of the Software.

*/

#include

#include

// Структура должна совпадать со структурой

// на плате-отправителе

typedef struct struct_message {

    char a[32];

    int b;

    float c;

    String d;

    bool e;

} struct_message;

// Создаем myData

struct_message myData;

// Обратная функция при получении

void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {

  memcpy(&myData, incomingData, sizeof(myData));

  Serial.print(«Bytes received: «);

  Serial.println(len);

  Serial.print(«Char: «);

  Serial.println(myData.a);

  Serial.print(«Int: «);

  Serial.println(myData.b);

  Serial.print(«Float: «);

  Serial.println(myData.c);

  Serial.print(«String: «);

  Serial.println(myData.d);

  Serial.print(«Bool: «);

  Serial.println(myData.e);

  Serial.println();

}

void setup() {

  // Запускаем монитор порта

  Serial.begin(115200);

  // Выставляем режим работы WiFi

  WiFi.mode(WIFI_STA);

ESP_

  // Запускаем протокол ESP-NOW

  if (esp_now_init() != ESP_OK) {

    Serial.println(«Error initializing ESP-NOW»);

    return;

  }

  // Получаем состояние отправки

  esp_now_register_recv_cb(OnDataRecv);

}

void loop() {

}

Как работает код?

Как и на отправителе, начинаем с подключения библиотек:

#include «esp_now.h»;

#include «WiFi.h»;

Создаем такую же как и на отправителе структуру.

typedef struct struct_message {

char a[32];

int b;

float c;

String d;

bool e;

} struct_message;

Создаем переменную myData.

Создаем обратную функцию onDataRecv () со следующими параметрами:

void OnDataRecv (const uint8_t * mac, const uint8_t * incomingData, int len) {

Копируем содержимое переменной данных incomingData в переменную myData.

memcpy (& myData, incomingData, sizeof (myData));

Теперь структура myData содержит несколько переменных со значениями, отправленными другой платой. Например, чтобы получить доступ к переменной a, нам нужно вызвать myData.a.

В этом примере мы просто выводим полученные данные.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

Serial.print(«Bytes received: «);

Serial.println(len);

Serial.print(«Char: «);

Serial.println(myData.a);

Serial.print(«Int: «);

Serial.println(myData.b);

Serial.print(«Float: «);

Serial.println(myData.c);

Serial.print(«String: «);

Serial.println(myData.d);

Serial.print(«Bool: «);

Serial.println(myData.e);

Serial.println();

}

В setup () запускаем монитор порта.

Выставляем режим работы WiFi

Запускаем ESP-NOW:

if (esp_now_init() != ESP_OK) {

Serial.println(«Error initializing ESP-NOW»);

return;

}

Используем функцию OnDataRecv (), которая была создана ранее.

esp_now_register_recv_cb (OnDataRecv);

Демонстрация

Загрузите скетчи на платы ESP32 отправителя, откройте два окна в среде Arduino. Один для получателя, а другой для отправителя. Откройте монитор порта для каждой платы. Для каждой платы должен быть свой COM-порт.

Это то, что вы должны получить на стороне отправителя.

serial-monitor

И это то, что вы должны получить на стороне приемника. Обратите внимание, что переменная Int изменяется при каждом запуске (потому что мы отправляем рандомное число).

serial-monitor-2

Заключение

Мы постарались сделать примеры максимально простыми, чтобы вы лучше понимали, как все работает. Есть много функций, связанных с ESP-NOW, которые могут быть полезны в ваших проектах, например: управление и удаление пиров, сканирование ведомых устройств и так далее Чтобы просмотреть их все в Arduino IDE перейдите Файл > Примеры > ESP32 > ESPNow и выберите один из скетчей.

Кроме того, с ESP-NOW каждая плата может быть отправителем и получателем одновременно, и одна плата может отправлять данные на несколько плат, а также получать данные с нескольких плат. Эти темы будут рассмотрены в будущих руководствах, так что следите за обновлениями.

Кстати, максимальное расстояние, при котором можно установить стабильное соединение между платами – 220 метров (без препятствий)

220-meter

Надеемся, вам понравилось.

Данный материал был переведен с сайта RandomNerdTutorials.com. Авторские права принадлежат ее автору — Rui Santos. Автор продает очень полезные и толковые курсы по ESP8266 / ESP32 (на английском языке), ознакомиться с которыми можно по ссылке.
Вопросы по прошивке и работе с кодом лучше писать напрямую автору в комментариях к статье (на англ. языке)

Вольтик — это слаженная команда амбициозных и заядлых инженеров. Мы создали этот проект с целью вовлечения вас, талантливых и начинающих профессионалов, в увлекательный мир мейкерской микроэлектроники!

Добрый день, уважаемый читатель! Продолжаем тему ESP-IDF, сегодня обсудим конфигурирование собственно самой Espressiff IoT Development Framework.

Делается это с помощью специального файла sdkconfig.h, в котором объявлено великое множество макросов препроцессора с различными настройками. Этот файл можно найти в каталоге /.pio/config и он доступен из любого файла ESP-IDF, и с помощью него можно, например, “включать” или “отключать” некоторые функции. Или изменять их поведение. Выглядит он примерно так:

Но, открыв этот файл в редакторе, мы сразу же видим предупреждение, что это “Автоматически сгенерированный файл. НЕ РЕДАКТИРОВАТЬ“. Всё правильно, редактировать его вручную бесполезно – всё равно все ваши изменения затрутся при следующей компиляции. То есть для нас он совершенно бесполезен.

Дело в том, что основой для этого файла служит другой файл, расположенный в “корне” проекта, называется он примерно так: sdkconfig.esp32dev, то есть расширением является целевая плата.

Но и здесь мы можем увидеть то же самое предупреждение – не редактировать.

По своему опыту могу сказать, что этот файл можно редактировать вручную, если нужно, но делать это нужно очень осторожно. Или например можно скопировать этот файл из другого проекта – и все настройки ESP-IDF будут перенесены.

Меню конфигурации проекта

Существует другой способ конфигурирования ESP-IDF – с помощью команды menuconfig. Если обратиться к справочной системе (кстати, рекомендую ознакомится), для вызова меню конфигурации проекта необходимо выполнить команду: idf.py menuconfig. Прямо из командной строки. Но, увы, в PlatformIO это не работает – вместо меню вы получите ошибку что-то вроде ““idf.py” не является внутренней или внешней командой, исполняемой программой или пакетным файлом.

В PlatformIO для вызова меню конфигурации (да и вообще любых команд, связанных с idf.py) существует своя: pio run -t menuconfig. То есть pio run -t вызывает тот самый idf.py неявным образом.

Можно попытаться сделать это прямо в терминале VSCode:

Но делать это неудобно, по двум причинам:

  • Во-первых, каждый раз приходится увеличивать высоту терминала, а после завершения восстанавливать обратно. Недолго, но напрягает.
  • На Windows 10 в терминале VSCode для навигации не работают клавиши со стрелками, увы, и приходится вместо них использовать клавиши J и K, постоянно путаешься.

Поэтому я рекомендую делать это по другому – через командную строку. Нажимаем клавиши Win+R, в открывшемся окошке вводим cmd (не спешите вводить pio run) и нажимаем Enter. Открывается черное окно терминала. Не спешим набирать команду, вначале нам нужно перейти в каталог проекта, например с помощью системной команды chdir, и только после этого набираем тайное заклинание:

Жмем Enter, и через несколько десятков секунд попадаем в заветное меню:

Меню конфигурации проекта

Меню конфигурации проекта

Теперь давайте разберем каждый из разделов более подробно.

Опций очень много, большинство из них я не изменял, да и не знаю их назначения. Я приведу только те опции, которые я использую сам, и в назначении которых я сумел разобраться на текущий момент. Если Вы используете другие и знаете их назначение – прошу в комментарии.

Итак.


SDK tool configuration

Тут по сути, ничего менять не требуется, сразу пропускаем

Build type

Здесь вы можете выбрать тип вашего приложения: bin-приложение с отдельным загрузчиком либо elf-файл, загружаемый в RAM. Я никогда не трогал, на ваш страх и риск.

Application manager

Тоже ничего менять не требуется, пропускаем

Bootloader config

Опции загрузчика. А вот здесь остановимся поподробнее.

  • Bootloader log verbosity – здесь лучше отключить понизить уровень отладки для загрузчика до уровня ERROR. На загрузчик все равно мы никак повлиять не можем, а размер загрузчика немного снизится.
  • Enable app rollback support – если в дальнейшем вы будете использовать OTA (обновления по воздуху / обновления через WiFi), то я рекомендую включить эту опцию сразу же. Эта опция позволяет задействовать механизм автоматического отката неудачной прошивки, когда при OTA что-то пошло не так, и устройство не смогло нормально загрузиться. “Потом” через OTA включить её не получится, так как при OTA сам загрузчик не обновляется, придется подключать устройство кабелем.
  • Bootloader optimization Level – рекомендую поставить уровень Size. Загрузчик используется один раз при старте, нет смысла оптимизировать его другими способами.

Остальные опции лучше не трогать, чтобы чего-нибудь не сломать случайно.

Security features

Опции безопасной загрузки. Я не использую, no comments.

Serial flasher config

Здесь находятся опции UART-порта и Flash-памяти. Здесь можно выбрать тип памяти (QIO / DIO), частоту SPI шины и ее размер. Параметры по умолчанию оптимальные, ничего менять не требуется.

Здесь же можно изменить скорость передачи текстовых логов в режиме монитора порта, по умолчанию 115200 бод, если это необходимо. Только не забудьте потом поменять настройки в platformio.ini

Partition Table

В этом меню вы можете выбрать свою таблицу разделов Flash-памяти. Об этом мы поговорим в другой раз, а пока пропускаем.

Compiler options

Опции компилятора. Здесь можно попробовать изменить уровень оптимизации компилятора или включить исключения. На ваш страх и риск.

Compatibility options

Да, да, я пока “перескочил” через одну строчку, оставим её на “вкусное”. Здесь же можно включить режим совместимости с предыдущими версиями ESP-IDF. Я не использую.


Component config

Основной и самый большой раздел. Отвечает за различные подсистемы и сервисы.

Чтобы не перегружать статью, я отмечу только те пункты, которыми я пользуюсь.

  • Log output → Default log verbosity – выберите уровень отладки “по умолчанию” для библиотеки esp_log.h

Системные настройки

  • ESP32-specific → CPU frequency – здесь вы можете выбрать частоту процессора 80 / 160 / 240 MHz. Всё как обычно – больше частота, больше производительность, но и больше потребление электроэнергии. Выбирайте то, что вам важнее в данный момент. По умолчанию 160, достаточно в большинстве случаев.
  • ESP32-specific → Support for external, SPI-connected RAM – если вы используете модуль WROVER, то в этом меню можно подключить внешнюю QSPI оперативную память.
  • ESP System Settings → Main task stack size – размер стека для главной задачи. Если вы используете app_main() только для запуска других задач, что вполне достаточно 2048. Если в app_main() у вас будет выполняться какая-то прикладная работа, подберите оптимальный размер самостоятельно.
  • ESP System Settings → Event loop task stack size – размер стека для цикла событий. Я увеличил размер стека до 3072, как как из цикла событий могут вызываться различные процедуры и функции. Что такое цикл событий, поговорим позже.
  • FreeRTOS → Enable FreeRTOS trace facility – включение этой опции позволяет включить функции для отладки списка задач. Полезно на начальном этапе разработки, чтобы подобрать оптимальный размер стека.
  • Heap memory debugging → Abort if memory allocation fails – если включить эту опцию, устройство перезагрузится при ошибке выделения памяти из кучи. Выделение памяти из кучи должно быть корректно обработано, если этого не сделать – это может привести к непредсказуемым последствиям. В этом случае установка этой опции может помочь. Но если Вы корректно обрабатываете запросы к памяти каждый раз – проблем быть не должно, и это опцию можно деактивировать.

Таймеры

  • High resolution timer (esp_timer) → High-resolution timer task stack size – здесь можно настроить размер стека для задачи, из которой выполняются программные таймеры.
  • High resolution timer (esp_timer) → Hardware timer to use for esp_timer – здесь вы можете выбрать, какой из аппаратных таймеров будет использоваться для программных таймеров

WiFi и сетевые службы

  • Wi-Fi → WiFi Task Core ID – выбираем, на каком ядре будет выполняться задача WiFi. Я использую 0
  • LWIP → Local netif hostname – сетевое имя устройства, которое вы увидите на роутере в списке подключенных устройств. Не должно быть длиннее 15 символов
  • LWIP → SNTP → Maximum number of NTP servers – я ставлю 5, и указываю 5 разных SNTP-серверов. ESP сама выберет нужный
  • mbedTLS → Memory allocation strategy – если вы используете WROVER с дополнительной памятью, здесь вы можете выбрать, где mbedTLS будет размещать свои данные
  • mbedTLS → Using dynamic TX/RX buffer – позволяет включить динамическое выделение памяти под mbedTLS буферы при каждом TLS-рукопожатии. Включение этой опции позволяет значительно сэкономить кучу, но может привести к её фрагментации при некоторых условиях.
  • mbedTLS → Certificate Bundle → Enable trusted root certificate bundle – если вам неохота возиться с подключением TLS-сертификатов к проекту, вы можете подключить сразу весь общедоступный пакет. Но памяти сожрет немеряно. Впрочем, есть опции, поговорим о них отдельно
  • ESP-MQTT Configurations – настройки MQTT клиента. Посмотрите на настройки самостоятельно, ничего сложного там нет, если знакомы с MQTT протоколом. Впрочем, это тоже обсудим позднее

Что интересно, я нигде не нашел параметра, отвечающего за размер стека WiFi службы. Ну ладно, не очень-то и хотелось.

Подробную информацию обо всех доступных опциях вы можете почерпнуть из справочной информации: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/kconfig.html

После того, как вы внесли какие-то изменения в конфигурацию, не забудьте сохранить её, нажав клавишу S.

Если у вас несколько похожих проектов, не обязательно выполнять одинаковые настройки для каждого из них отдельно. Вполне можно обойтись копированием файла sdkconfig.esp32dev (или аналогичного, который находится в корне проекта)

После изменения конфигурации sdkconfig PlatformIO скомпилирует все системные библиотеки заново, что занимает довольно продолжительное время. Именно по этой причине я не люблю добавлять пользовательские опции в “общий” файл конфигурации, ибо это сильно замедляет работу над проектом. Но такая возможность есть, давайте рассмотрим, как это сделать.


Пользовательские опции

SDK Config позволяет добавлять пользовательские опции в общее меню конфигурации проекта. То есть вы можете определять какие-либо произвольные опции и настройки и добавлять их в общее меню, чтобы создать единую систему настроек проекта. Очень часто этим пользуются разработчики сторонних библиотеках.

Для того, чтобы добавить свое меню в sdkconfig, вы должны создать текстовый UTF-8 файл с именем Kconfig.projbuild и поместить его в папку src проекта. Содержимое файла должно иметь примерно такую структуру:

menu "НАЗВАНИЕ МЕНЮ"
   config ПАРАМЕТР
      bool "Подсказка к параметру"
         depends on ЗАВИСИМОСТИ_ОТ_ДРУГОГО_МОДУЛЯ
   help
     Здесь вы можете написать краткую справку к параметру
endmenu

Разумеется, параметров может быть любое количество, а также можно сделать многоуровневое меню. Например, я в качестве примера сделал такой файл:

В результате в меню конфигурации появилось новое подменю с 2 уровнями вложенности:

Таким образом, вы можете добавить в общую систему параметров любые необходимые опции. Пример можно посмотреть или скачать по ссылке.

Я практически не пользовался таким способом добавления “своих” опций, поэтому я не владею этим в совершенстве.

Более подробную информацию о файла kconfig вы можете почерпнуть здесь https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/kconfig.html#project-configuration-menu или здесь: https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt

Полезные ссылки

  1. ESP-IDF :: Project Configuration
  2. Kconfig system

Наконец-то, по многочисленным просьбам мы начинаем знакомство, а впоследствии, как я думаю, и полноценную работу по программированию микроконтроллера ESP8266.

Данный контроллер является собственностью китайского производителя Espressif, и основную свою популярность среди программистов он снискал благодаря наличию беспроводного интерфейса Wi-Fi. Также немаловажным фактором является его очень низкая стоимость и также наличие на сегодняшний момент многочисленной документации, а также программного обеспечения, позволяющего самостоятельно писать для него программы на различных языках. О сфере использования данного контроллера в различных устройствах я вообще даже боюсь и говорить. Она очень многообразна: интернет вещей, сбор информации с различных датчиков и приборов, передача на другие устройства, где нет возможности протянуть к ним провода и т.д.

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

Вот это лишь некоторая часть из них

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

Также я много думал о том, с чего начать рубрику по данному контроллеру. Вообще, честно говоря, хотелось приступить сразу к написанию программ и их прошивке в модуль. Но, так как в данных модулях сразу имеется определённое прошитое ПО, позволяющее уже с ним работать по интерфейсу UART посредством AT-команд, и, так как просьб по работе с AT-командами данного контроллера было тоже немалое количество, то начнём мы именно с них. А дальше уже покажет обстановка.

Прежде чем приступить к практической работе с модулем, мы познакомимся поначалу с контроллером, а затем уже будем знакомиться с модулями, а вернее с самым простым из них — ESP-01.

Практически во всех модулях, построенных на контроллере ESP8266 имеется в наличии внешняя микросхема FLASH-памяти, так как у контроллера, к сожалению, внутренней FLASH-памяти на борту нет. Но зато в этом есть и плюсы, позволяющие установить данную память различного размера.

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

Основные технические характеристики контроллера ESP8266 (а точнее ESP8266EX), касающиеся передачи данных по Wi-FI:

  1. поддержка протокола 802.11 b/g/n,
  2. поддержка 802.11n (2.4 GHz), до 72.2 Mbps,
  3. дефрагментация,
  4. 2 виртуальных передатчика Wi-Fi,
  5. поддержка шифрования WPA/WPA2 WEP/TKIP/AES,
  6. выходная мощность +20 дБм в режиме 802.11b,
  7. WiFi режим — STA (станция), программная точка доступа, программная точка доступа + STA (станция).

Это лишь некоторые самые интересные характеристики по передаче данных.

Также приведу некоторые остальные характеристики:

  1. встроенный MCU 32-бит с низким энергопотреблением,
  2. встроенные блоки ФАПЧ и управления мощностью,
  3. встроенный стек протоколов TCP/IP с поддержкой протоколов передачи данных IPv4, TCP/UDP/HTTP
  4. интерфейсы SDIO 2.0, SPI, HSPI UART, I2C, I2S, IRDA, PWM, GPIO,
  5. поддержка различных режимов пониженного энергопотребления,
  6. диапазон рабочих температур –40°C ~ 125°C,
  7. загрузка (а также и выгрузка) ПО по интерфейсу UART,
  8. питание 2.5V ~ 3.6V (стабильная работа контроллера, как подтвердила практика, наблюдается при стабилизированном напряжении 3.3V).

Токи потребления контроллером в активном режиме при определённых режимах и скоростях передачи данных

А это токи потребления контроллером в различных режимах пониженного энергопотребления, а также что остаётся в данных режимах в работе

Находится микроконтроллер ESP8266 в 32-пинном QFN корпусе.

Вот основное назначение ножек (возможен REMAP)

А вот это блок-схема

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

Также об этом свидетельствует и вот этот пункт, в котором обозначены параметры подключаемого внешнего FLASH

Оперативной памяти в контроллере около 50 килобайт.

Процессор в контроллер ESP8266 встроен Xtensa L106 от компании Tensilica. Работает он на частоте до 80 мегагерц, возможен также негарантированный разгон до 160 МГц.

Вообщем, это пока всё, что я хотел сказать вам о контроллере ESP8266. В дальнейших уроках мы уже начнём знакомство с отдельными модулями, научимся управлять их работой сначала с помощью команд AT, а затем уже напишем свои прошивки, позволяющие работать с модулем самостоятельно и более гибко, а также впоследствии мы обязательно подключим данный контроллер к другому контроллеру общего назначения, в частности к STM32, к которому мы с вами уже так привыкли, что позволит ещё более профессионально организовать процессы передачи данных между устройствами без использования проводов.

Всем спасибо за внимание!

Программирование МК ESP8266 Следующий урок

Различные модули ЕSP8266 можно приобрести здесь Модули ЕSP8266

Смотреть ВИДЕОУРОК (нажмите на картинку)

ESP8266 Первое знакомство с контроллером ESP8266


Post Views:
3 738

Блок уроков по работе с платой ESP8266 состоящий, скорее всего не из уроков, а заметок по решению проблем, которые возникают у меня или моих подписчиков. А также небольшие уроки по подключению модулей, сенсоров, датчиков. И прочей полезной информации.

HTTP-сервер ESP8266. Выводим информацию HTML, Javascript и CSS

HTTP-сервер ESP8266. Выводим информацию HTML, Javascript и CSS

Цель этого урока — объяснить, как работать с HTML, Javascript и CSS на веб-сервере ESP8266 HTTP.

Важно учитывать, что HTML, Javascript и CSS — это языки, которые выполняются / отображаются на стороне клиента. Поскольку мы собираемся выполнять HTTP-запросы из веб-браузера, он будет отвечать за рендеринг HTML и CSS и выполнение Javascript.

Это означает, что мы узнаем, как интерпретировать HTML, CSS или Javascript.
Как увидим ниже, этот код будет храниться в строках, которые будут
возвращены в ответах HTTP, почти так же, как мы это делали бы для
возврата любого другого типа контента.

В этом простом примере мы
создадим главную страницу на HTML. Страницу с кодом Javascript на
которой будет запускаться окно предупреждения при нажатии кнопки. И
страницу с кнопкой, стилизованной с помощью CSS.

Урок ESP8266. Настройка простого HTTP веб-сервера.

Урок ESP8266. Настройка простого HTTP веб-сервера.

Цель этого урока — объяснить, как настроить веб-сервер HTTP на ESP8266 и делать к нему простые запросы с помощью веб-браузера.

В уроке будем использовать библиотеки ESP8266 для Arduino IDE. Как настроить Arduino IDE для поддержки ESP8266, узнать можно здесь.

Тесты проводились с использованием платы NodeMCU, очень дешевая и простая в использовании плата ESP8266.

Код простого HTTP веб-сервера на ESP8266.

Прежде всего, подключим библиотеку ESP8266WiFi, которая содержит необходимые функции для подключения ESP8266 к сети Wi-Fi. Вы можете прочитать более подробное описание того, как подключить ESP8266 к сети Wi-Fi в предыдущем уроке.

Урок ESP8266. Управление двигателем постоянного тока. NodeMCU + MX1508

Урок ESP8266. Управление двигателем постоянного тока. NodeMCU + MX1508

Цель этого урока — объяснить, как управлять двигателем постоянного тока и изменять скорость вращения, с помощью ESP8266 и драйвера MX1508. Подробное описание драйвера можно посчитать в моем уроке по подключению MX1508 к Arduino.

Поскольку
цифровые выводы микроконтроллера могут подавать только ограниченный ток
(в случае ESP8266, максимум 12 мА), мы не можем напрямую использовать
их для управления двигателем постоянного тока. Поэтому будем использовать драйвер MX1508, чтобы обеспечить ток, необходимый для вращения двигателя.

Схема подключения NodeMCU, MX1508 и двигатель постоянного тока.

Урок ESP8266. Использование широтно-импульсной модуляции (ШИМ).

Урок ESP8266. Использование широтно-импульсной модуляции (ШИМ).

Цель этого урока — объяснить, как использовать метод широтно-импульсной модуляции (ШИМ) с ESP8266 и основные отличия реализации от Arduino.

Широтно-импульсная модуляция — Pulse Width Modulation (PWM).

В
методе PWM мы создаем прямоугольную волну с контролируемым рабочим
циклом. Это означает, что мы можем контролировать для каждого периода
волны, сколько времени он находится в состоянии VCC (HIGH) или GND
(LOW). Таким образом, обычно рабочий цикл указывается как процент
времени, в течение которого находится в ВЫСОКОМ состоянии по отношению к
периоду.

Урок ESP8266. Подключение сдвигового регистра 74HC595.

Урок ESP8266. Подключение сдвигового регистра 74HC595.

Цель этого урока — объяснить, как подключить 8-битный сдвиговый регистр 74HC595 к ESP8266
для управления светодиодами. Также рассмотрим код позволяющий
осуществлять управление сдвиговым регистром. Как настроить работу с
платой ESP8266 в среде Arduino IDE, описано здесь.

Также у меня есть урок по подключению сдвигового регистра 74HC595 к Arduino, подробнее читайте тут.

Описание сдвигового регистра 74HC595.

ESP8266 уроки. Кодирование сообщений JSON — Encoding JSON messages.

ESP8266 уроки. Кодирование сообщений JSON - Encoding JSON messages.

Цель этого урока — объяснить, как кодировать сообщение JSON (Encoding JSON messages) при помощи ESP8266, используя библиотеку ArduinoJson. Предполагаем, что библиотеки ESP8266 для Arduino IDE были ранее установлены. Вы можете узнать, как это сделать, здесь.

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

Подключение библиотеки ArduinoJson.

ESP8266 уроки. Анализ массивов JSON.

ESP8266 уроки. Анализ массивов JSON.

В этом уроке ESP8266 создадим простую программу для анализа строки JSON, которая включает в себя массив целых чисел. Все необходимые библиотеки ESP8266 для Arduino IDE были ранее установлены в предыдущей статье, подробнее здесь.

Кроме того, объяснения, как использовать библиотеку анализа простых пар JSON «имя : значение», можно прочитать в предыдущим уроке.

Подготовка для анализа массива JSON.

ESP8266 уроки. Анализ JSON в среде Arduino IDE.

ESP8266 уроки. Анализ JSON в среде Arduino IDE.

В этом уроке ESP8266 создадим простую программу для синтаксического анализа строки JSON, имитирующей данные с датчика, и вывод полученных значений в последовательный порт. Для данного урока вам нужно установить библиотеки ESP8266 для Arduino IDE, о чем рассказывал здесь.

Чтобы избежать ручного декодирования строки в пригодные для использования значения, будем использовать библиотеку ArduinoJson, которая предоставляет простые в использовании классы и методы для синтаксического анализа JSON. С библиотекой и ее возможностями можно ознакомиться на GitHub.

Эта очень полезная библиотека позволяет, как кодировать, так и декодировать JSON, она очень эффективна и работает на ESP8266. Её можно установить через «менеджер библиотек» Arduino IDE, как показано на рисунке ниже.

ESP8266 уроки. HTTP-запрос POST

ESP8266 уроки. HTTP-запрос POST

Цель этого урока — объяснить, как выполнять запросы POST от ESP8266, используя Arduino IDE и библиотеки ESP8266. Все показанные здесь тесты, были выполнены на плате NodeMCU.

Для данного урока нужно подключить некоторые библиотеки, которые должны быть доступны после установки поддержки ESP8266 в среде Arduino IDE.

Нам понадобится ESP8266WiFi.h, чтобы была возможность подключить ESP8266 к сети Wi-Fi, и ESP8266HTTPClient.h, который делает доступными методы, необходимые для выполнения запроса POST.

ESP8266 уроки. HTTP-запрос GET

ESP8266 уроки. HTTP-запрос GET

Цель данного урока — объяснить, как выполнять HTTP-запрос GET с помощью ESP8266. Примеры из этого урока были выполнены с использованием NodeMCU – одна из недорогих плат и самая простая в использовании среди линейки ESP8266.

Описание скетча отправки GET запроса с помощью ESP8266.

Фото в бортжурнале Mercedes-Benz S-class (W221)

Всем привет!
Решил поделиться опытом, возможно кому-то будет полезно.
Периодически появлялась ошибка на приборке «ESP временно недоступна См.»Руководство»», подвеска авто переходила в аварийный режим и было просто невозможно передвигаться, как на буханке.
После перезапуска двигателя ошибка пропадала, могла не появляться 2 недели и потом опять.
В конечном итоге она появилась и не пропадала, также периодически менялась на «ESP не действует См.»Руководство»». поехал на диагностику.
Приговор: накрылся датчик положения рулевого колеса.
Предложили замену на новый с работой около 550$, решил что 550$ я смогу потратить на что-то более полезное, как минимум рассмотрю вариант покупки бу.
Для начала решил проверить возможно что-то можно сделать (как оказалось не зря).
После снятия руля, до датчика добраться не составило проблем.
После визуального осмотра ничего не обнаружилось, был только немного грязный диск по которому ходит игла.
Взяли ватку со спиртом протерли и обезжирили. Все собрали обратно, ошибка больше не беспокоила.
С тех пор проехал около 8000.
Будут вопросы уточняйте.
Стоимость ремонта 10$
1 диагностика ошибки 5$.
2 сброс ошибки после снятия подушки 5$.

Фото в бортжурнале Mercedes-Benz S-class (W221)

Фото в бортжурнале Mercedes-Benz S-class (W221)

Фото в бортжурнале Mercedes-Benz S-class (W221)

Фото в бортжурнале Mercedes-Benz S-class (W221)

Фото в бортжурнале Mercedes-Benz S-class (W221)

Пробег: 250 000 км

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

Понравилась статья? Поделить с друзьями:
  • Мама рино капли в нос инструкция по применению
  • Битрикс 24 руководство пользователя скачать
  • Ибупрофен вертекс гель инструкция по применению цена отзывы аналоги
  • Инструкции по судебному делопроизводству у мировых судей утверждаются
  • Love drops капли инструкция по применению