Работа с ESP8266: Собираем компилятор и пишем первую прошивку

в 19:36, , рубрики: diy или сделай сам

В прошлой статье мы рассмотрели первоначальную настройку и работу модуля ESP-01 с базовой AT-прошивкой. Возможности данной прошивки достаточно ограничены и использовать её для каких-то повседневных задач достаточно сложно. Как я писал в первой статье, для ESP8266 можно написать свою прошивку с нужным функционалом и тем самым сделать плату ESP-01 самодостаточным устройством. Всем кому это интересно, прошу под хабракат.

Как известно, SoC ESP8266 построен на базе процессора Xtensa LX106 фирмы Tensilica, если кому-то интересно, то в сети есть статья про конфигурируемые процессоры этой фирмы. Компания Espressif предоставляет полную документацию, а так же компилятор и среду разработки для SoC ESP8266 только после подписания партнерского соглашения и не со всеми подряд, на мое письмо они так и не ответили. Немного погуглив можно найти утекший в сеть официальный компилятор, среду разработки, основанную на Eclipse, множество документации и лицензии, но это не наш путь. Мы будем использовать неофициальный компилятор на основе Crosstool-NG

В этой статье я расскажу как собрать компилятор под Ubuntu Linux, а так же мы попробуем написать простейшую прошивку. Основной упор я сделаю на работу с компилятором под Windows, а так же настройку среды Eclipse для написания прошивок для ESP8266.

Часть 1: Сборка компилятора под Ubuntu Linux, настройка SDK, сборка стандартных примеров и прошивок.

Установка среды сборки

Для 32-разрядной Debian (Linux) выполняем:

apt-get install git autoconf build-essential gperf bison flex texinfo libtool libncurses5-dev wget gawk libc6-dev-amd64 python-serial libexpat-dev

Для 64-разрядной Debian (Linux) выполняем:

apt-get install git autoconf build-essential gperf bison flex texinfo libtool libncurses5-dev wget gawk libc6-dev-i386 python-serial libexpat-dev

Далее:
USER меняем на логин текущего пользователя.

sudo mkdir /opt/Espressif
sudo chown USER:root /opt/Espressif
cd /opt/Espressif
git clone -b lx106 git://github.com/jcmvbkbc/crosstool-NG.git 
cd crosstool-NG
./bootstrap && ./configure --prefix=`pwd` && make && make install
./ct-ng xtensa-lx106-elf
./ct-ng build
PATH=$PWD/builds/xtensa-lx106-elf/bin:$PATH

После этого можно откинуться на спинку кресла минут на 40-50 и попить кофе. Если все завершится без ошибок, то можно двигаться дальше.

Установка SDK

cd /opt/Espressif
mkdir ESP8266_SDK
cd ESP8266_SDK
wget http://bbs.espressif.com/download/file.php?id=72 -O esp_iot_sdk_v0.9.3_14_11_21.zip
wget http://bbs.espressif.com/download/file.php?id=73 -O esp_iot_sdk_v0.9.3_14_11_21_patch1.zip
unzip esp_iot_sdk_v0.9.3_14_11_21.zip && rm esp_iot_sdk_v0.9.3_14_11_21.zip
rm esp_iot_sdk_v0.9.3/lib/libpp.a
unzip esp_iot_sdk_v0.9.3_14_11_21_patch1.zip && rm esp_iot_sdk_v0.9.3_14_11_21.zip
mv esp_iot_sdk_v0.9.3/* . && rm -r esp_iot_sdk_v0.9.3/

Добавляем библиотеки libc, libhal и заголовочные файлы в SDK

cd /opt/Espressif/ESP8266_SDK
wget -O lib/libc.a https://github.com/esp8266/esp8266-wiki/raw/master/libs/libc.a
wget -O lib/libhal.a https://github.com/esp8266/esp8266-wiki/raw/master/libs/libhal.a
wget -O include.tgz https://github.com/esp8266/esp8266-wiki/raw/master/include.tgz
tar -xvzf include.tgz && rm include.tgz

Установка ESP image tool

ESP tool можно собрать из исходников,
для Linux можно скачать здесь
для Debian/Ubuntu здесь
Готовый пакет для Ubuntu качаем отсюда

cd /opt/Espressif/
wget https://github.com/esp8266/esp8266-wiki/raw/master/deb/esptool_0.0.2-1_i386.deb
sudo dpkg -i esptool_0.0.2-1_i386.deb && rm esptool_0.0.2-1_i386.deb

Установка ESP upload tool

cd /opt/Espressif
git clone https://github.com/themadinventor/esptool esptool-py
sudo ln -s $PWD/esptool-py/esptool.py crosstool-NG/builds/xtensa-lx106-elf/bin/
sudo ln -s $PWD/esptool-py/esptool.py /usr/sbin/

Сборка примеров прошивок

Для начала откройте файл /opt/Espressif/ESP8266_SDK/include/osapi.h и закомментируйте строку #include «user_config.h»

Скачиваем и собираем примеры blinky и basic_example:

cd /opt/Espressif/ESP8266_SDK/examples/
wget https://github.com/esp8266/source-code-examples/archive/master.zip && unzip master.zip && rm -r master.zip
mv source-code-examples-master/* . && rm -r source-code-examples-master
cd blinky
make

Если все шаги были сделаны правильно, то сборка пройдет без ошибок и в каталоге firmware появятся 2 файла прошивки 0x00000.bin и 0x40000.bin

Скачиваем и собираем пример базовой прошивки AT:

cd /opt/Espressif/ESP8266_SDK/examples/
wget -O at_v0.19_14_10_30.zip http://bbs.espressif.com/download/file.php?id=13
unzip at_v0.19_14_10_30.zip && rm at_v0.19_14_10_30.zip
cd at_v0.19_on_SDKv0.9.2/
rm Makefile && cp ../example.Makefile . && mv example.Makefile Makefile

Для правильной сборки AT прошивки необходимо отредактировать базовый Makefile в строке
LIBS = c gcc hal pp phy net80211 lwip wpa main
добавить линковку библиотеки upgrade, итоговая строка будет выглядеть так
LIBS = c gcc hal pp phy net80211 lwip wpa upgrade main
после этого прошивку можно собрать командой make

Cобираем пример прошивки IoT:

cd /opt/Espressif/ESP8266_SDK/examples/IoT_Demo/
rm Makefile && cp ../example.Makefile . && mv example.Makefile Makefile

Так же как и для AT прошивки, для правильной сборки IoT прошивки необходимо отредактировать базовый Makefile в строку
MODULES = driver user
нужно добавить дополнительные модули, итоговая строка будет выглядеть так
MODULES = driver user json ssl upgrade lwip
а в строку
LIBS = c gcc hal pp phy net80211 lwip wpa main
добавить линковку библиотеки json, итоговая строка будет выглядеть так
LIBS = c gcc hal pp phy net80211 lwip wpa main json
после этого прошивку можно собрать командой make

Для того чтобы прошить плату ESP-01 нужно использовать команду make flash
Не забываем, что для переключения в режим обновления прошивки нужно подать низкий уровень на GPIO0 и высокий на CH_PD.
Чтобы понять, что делает make flash стоит открыть любой Makefile и найти строку flash:
после подстановки всех аргументов получаем команду прошивки SoC:

esptool.py --port /dev/ttyUSB0 write_flash 0x00000 firmware/0x00000.bin 0x40000 firmware/0x40000.bin

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

Часть 2: Установка компилятора под Windows, настройка SDK, сборка стандартных примеров и прошивок.

Т.к. моя основная ОС под которой я работаю 90% времени это Windows, то разработка в Linux меня не сильно интересовала.
Ниже я расскажу, как установить и настроить компилятор и SDK в Windows, а так же как настроить среду разработки Eclipse для комфортной разработки прошивок в ней.
Рассматривать процесс сборки компилятора под Windows я не буду, т.к. это довольно сложная процедура, она намного сложнее сборки в Linux.
Дабы избавить Вас от всех тонкостей и нюансов, я подготовил рабочий комплект Espressif DevKit, включающий в себя компилятор, последнюю версию SDK, стандартные примеры прошивок, а так же мои собственные примеры прошивок.

Внимание! Мой комплект Espressif DevKit собран и работает только под 64-разрядной версией Windows

Итак приступим:
1. Скачиваем (67Mb) и устанавливаем мой комплект Espressif-ESP8266-DevKit-v0.9.3.exe
2. Скачиваем и устанавливаем Python v2.7.8. Python необходимо установить в корень диска С как он предлагает по-умолчанию, то есть в C:Python27.
3. Скачиваем и устанавливаем Java Runtime x86 (jre-7u72-windows-i586.exe)
4. Скачиваем и устанавливаем Eclipse Luna x86 для разработки на С++ (eclipse-cpp-luna-SR1-win32.zip). Распаковываем архив в корень диска С.
5. Скачиваем и устанавливаем MinGW. Запускаем mingw-get-setup.exe, в процессе установки выберите режим без GUI, то есть уберите галочку "...also install support for the graphical user interface".
6. Скачиваем (52Mb) набор моих скриптов для автоматизации установки доп.модулей для Python и MinGW.
7. Запустите из моего набора файл install-pip.bat.
Он установит доп. модули для Python, установка должна пройти без ошибок.
8. Запустите из моего набора файл install-mingw-package.bat.
Он установит основные модули для MinGW, установка должна пройти без ошибок.
9. Запустите Eclipse Luna из каталога c:eclipseeclipse.exe
10. В Eclipse выберите меню File -> Import -> General -> Existing Project into Workspace, в строке Select root directory выберите каталог C:Espressifexamples и импортируйте рабочие проекты.
Далее справа в Make Target выберите нужный проект, например hello-world и запустите цель all на сборку,
при этом в окне Console должен отобразиться ход сборки, если все сделано правильно, то будет примерно такая картина:

17:00:00 **** Build of configuration Default for project hello-world ****
mingw32-make.exe -f C:/Espressif/examples/hello-world/Makefile all 
CC driver/uart.c
CC user/user_main.c
AR build/app_app.a
LD build/app.out
FW firmware/0x00000.bin
FW firmware/0x40000.bin
17:00:04 Build Finished (took 3s.740ms)

Это значит, что прошивка для ESP8266 собрана и находится в каталоге C:Espressifexampleshello-worldfirmware
Для прошивки ESP8266 используйте цель flash, предварительно отредактировав файл сборки проекта Makefile, строка
ESPPORT ?= COM2
, где после COM цифра 2 указывает номер COM-порта к которому подключена плата с ESP8266.

Видео с демонстрацией подключения проектов в Eclipse, сборкой и прошивкой ESP8266.

Как было сказано выше, для переключения в режим обновления прошивки нужно подать низкий уровень на GPIO0 и высокий на CH_PD, после этого либо передернуть питание платы, либо выполнить Сброс, подачей низкого уровня на GPIO5 (он же RESET). Выполнять эти действия постоянно очень неудобно. Немного подумав, я изменил схему подключения платы ESP-01 к преобразователю USB-to-RS232, смысл изменений сводится к подключению вывода RTS преобразователя USB-to-RS232 к выводу GPIO5 (он же RESET) платы ESP-01 и вывода DTR преобразователя USB-to-RS232 к выводу GPIO0 платы ESP-01. Так же я подправил утилиту esptool.py в процедуре connect для того, чтобы при запуске происходил сброс платы по сигналу RTS и вход в режим загрузчика по сигналу DTR.

Изменения в esptool.py

    def connect(self):
	print 'Entering bootloader...'
	self._port.setRTS(True)			#RTS
	self._port.setDTR(True)			#GPIO0
	time.sleep(0.25)
	self._port.setRTS(False)
	self._port.setDTR(True)
	time.sleep(0.25)
	self._port.setRTS(False)
	self._port.setDTR(False)
	print 'Connecting...'

Итоговая схема подключения:

Работа с ESP8266: Собираем компилятор и пишем первую прошивку - 1

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

Но в связи с этим финтом ушами пришлось поискать нормальную программу Terminal, т.к. то же Putty уже не подходил, в нем нельзя управлять линиями RTS и DTR и более того, сразу после подключения к COM-порту через Putty, он ставил линию DTR в низкий уровень, что приводило к постоянному входу в режим загрузчика. Удобная и в то же время богатая функционалам программа Terminal легко нашлась, она находится в каталоге C:Espressifutils

Часть 3: Написание простейших прошивок.

Для того, чтобы начать писать прошивки нужно изучить документацию на сам чип ESP8266 и на SDK, я не стал включать документацию в состав своей сборки Espressif-ESP8266-DevKit, дабы не нарушать разного рода лицензионных соглашений, все таки вся документация идет с пометкой confidential. Тем не менее, в интернете есть масса источников, где её можно раздобыть, например:
Спецификация на чип ESP8266
Описание SDK ESP8266 — это основной документ, который нам понадобится.

В прошлой статье на примере AT-прошивки мы подключались к Wi-Fi точке доступа и запускали TCP-сервер (TCP-клиент) на ESP8266, а так же отправляли тестовые данные на ПК. Как я писал ранее, данный способ не совсем удобен, т.к. для выполнения AT-команд по запуску TCP-сервера (TCP-клиента) требуется отдельный контроллер. Ниже мы рассмотрим пример написания простейшей прошивки для ESP8266, которая реализует все это без внешнего контроллера.
Итак задание:
1. Плата ESP-01 должна переключаться в режим STA (Wi-Fi клиента), устанавливать соединение с нашей AP.
2. После установки соединения с AP необходимо установить TCP-соединение с ПК и отправить тестовую строку.
3. К GPIO0 подключаем кнопку, при замыкании отправляем текстовую строку.
3. Процедуру отправки повторять каждые 5 сек.

Открываем в Eclipse пример wifi-sta-tcp-client из C:Espressifexamples
Типичная структуры папок в любом проекте для ESP8266 примерно такая:

wifi-sta-tcp-client
|-Makefile
|-driver
   |-uart.c
|-include
|-user
   |-user_main.c
   |-user_config.h

, где
— файл Makefile — это набор инструкций для программы make, которая помогает собирать наш проект
— каталог driver — содержит драйвера для различных устройств, пока у нас там только файл uart.c, для работы с портом rs232 чипа ESP8266, в принципе там могут быть драйвера для работы с gpio, i2c, spi, pwm и др., смотрите пример IoT_Demo, там более наглядно видно что может быть.
— каталог include — содержит вспомогательные заголовочные файлы, пока там только файлы для работы с портом rs232
— каталог user — основной каталог, в нем находятся основные файлы прошивки, файл user_main.c и user_config.h

Могут присутствовать и другие каталоги, все зависит от модели и принципов разработки, но Makefile настроен именно на такую структуру, и если Вы начнете что-то менять, то придется переписывать инструкции Makefile'а.
В текущем виде для того чтобы добавить доп. каталог с исходниками в сборку достаточно в Makefile в строку
MODULES = driver user
добавить наш новый каталог, например ssl и он будет участвовать в сборке прошивки.
Для добавления доп. библиотек в Makefile'е нужно дополнить строку
LIBS = c gcc hal phy pp net80211 lwip wpa main
нужными нам библиотеками, например если нам нужна в проекте библиотека по работе с json, то пишем
LIBS = c gcc hal phy pp net80211 lwip wpa main json

Открываем файл useruser_main.c

Основная процедура, которая выполняется при старте прошивке это

//Init function 
void ICACHE_FLASH_ATTR
user_init()
{
}

В начало файла useruser_main.c добавляем заголовочные файлы:

#include "ets_sys.h"
#include "osapi.h"
#include "os_type.h"
#include "user_interface.h"
#include "driver/uart.h"
#include "espconn.h"
#include "mem.h"
#include "gpio.h"
#include "user_config.h"

Данные файлы, за исключением user_config.h и driver/uart.h находятся C:EspressifESP8266_SDKinclude
ets_sys.h — спецефичные структуры и определения для работы с событиями и таймерами
osapi.h — таймеры и некоторые системные функции, например os_strcat, os_memcpy, os_delay_us и т.п.
os_type.h — мапинг структур из ets_sys.h
user_interface.h — множество вспомогательных структур и процедур API, в частности для работы с wi-fi, процедуры system_restart, system_deep_sleep и т.д.
espconn.h — основной файл API со структурами и процедурами по работе с TCP и UDP соединениями
mem.h — работа с памятью, os_malloc, os_free и т.п.
gpio.h — вспомогательные структуры и процедуры API для работы с GPIO

Итак пишем в user_init() следующее:

	// Инициализация uart0 и uart1 со скоростью 115200
	uart_init(BIT_RATE_115200, BIT_RATE_115200);
	// Ждем 100 мсек.
	os_delay_us(100);
	#ifdef PLATFORM_DEBUG
	// Вывод строки в uart о начале запуска, см. определение PLATFORM_DEBUG в user_config.h
	uart0_sendStr("ESP8266 platform starting...rn");
	#endif
	// Структура с информацией о конфигурации STA (в режиме клиента AP)
	struct station_config stationConfig;
	char info[150];
	// Проверяем если платы была не в режиме клиента AP, то переводим её в этот режим
	// В версии SDK ниже 0.9.2 после wifi_set_opmode нужно было делать system_restart
	if(wifi_get_opmode() != STATION_MODE)
	{
		#ifdef PLATFORM_DEBUG
		uart0_sendStr("ESP8266 not in STATION mode, restarting in STATION mode...rn");
		#endif
		wifi_set_opmode(STATION_MODE);
	}
	// Если плата в режиме STA, то устанавливаем конфигурацию, имя AP, пароль, см. user_config.h
	// Дополнительно читаем MAC адрес нашей платы для режима AP, см. wifi_get_macaddr(SOFTAP_IF, macaddr);
	// В режиме STA у платы будет другой MAC адрес, как у клиента, но мы для себя читаем адрес который у неё был если бы она выступала как точка доступа
	if(wifi_get_opmode() == STATION_MODE)
	{
		wifi_station_get_config(&stationConfig);
		os_memset(stationConfig.ssid, 0, sizeof(stationConfig.ssid));
		os_memset(stationConfig.password, 0, sizeof(stationConfig.password));
		os_sprintf(stationConfig.ssid, "%s", WIFI_CLIENTSSID);
		os_sprintf(stationConfig.password, "%s", WIFI_CLIENTPASSWORD);
		wifi_station_set_config(&stationConfig);
		wifi_get_macaddr(SOFTAP_IF, macaddr);
	}
	// Для отладки выводим в uart данные о настройке режима STA
	#ifdef PLATFORM_DEBUG
	if(wifi_get_opmode() == STATION_MODE)
	{
		wifi_station_get_config(&stationConfig);
		os_sprintf(info,"OPMODE: %u, SSID: %s, PASSWORD: %srn",
			wifi_get_opmode(),
			stationConfig.ssid,
			stationConfig.password);
		uart0_sendStr(info);
	}
	#endif

	// Запускаем таймер проверки соединения по Wi-Fi, проверяем соединение раз в 1 сек., если соединение установлено, то запускаем TCP-клиент и отправляем тестовую строку.
	os_timer_disarm(&WiFiLinker);
	os_timer_setfn(&WiFiLinker, (os_timer_func_t *)wifi_check_ip, NULL);
	os_timer_arm(&WiFiLinker, 1000, 0);
	// Инициализируем GPIO, 
	BtnInit();
	// Выводим сообщение о успешном запуске
	#ifdef PLATFORM_DEBUG
	uart0_sendStr("ESP8266 platform started!rn");
	#endif

Процедура инициализации GPIO

void BtnInit() {
	PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0);
	// Выключаем подтягивающий резистор на - (pull down)
	PIN_PULLDWN_DIS(PERIPHS_IO_MUX_GPIO0_U);
	// Включаем подтягивающий резистор на + (pull up)
	PIN_PULLUP_EN(PERIPHS_IO_MUX_GPIO0_U);  
	// Переводим GPIO0 на ввод
	gpio_output_set(0, 0, 0, BIT0);
	// Запуск таймера проверки GPIO
	os_timer_disarm(&BtnTimer);
	os_timer_setfn(&BtnTimer, BtnTimerCb, NULL);
	os_timer_arm(&BtnTimer, 500, 1);
}

Процедура проверки сделана в лоб, без какого либо устранения дребезга контактов, по уму нужно делать иначе, так же ниже будет видно, что в senddata не идет никакой проверки на поднятие интерфейса wi-fi, что тоже следует учитывать.

Процедура проверки GPIO

static void ICACHE_FLASH_ATTR BtnTimerCb(void *arg)
{
	if (!GPIO_INPUT_GET(BTNGPIO))
	{
		GPIO_Time_Active++;
	} else {
		if (GPIO_Time_Active != 0)
		{
			#ifdef PLATFORM_DEBUG
			uart0_sendStr("Start sending data...rn");
			#endif
			// Отправляем данные
			senddata();
		}
		GPIO_Time_Active = 0;
	}
}

Процедура проверки Wi-Fi подключения (вызывается по таймеру)

static void ICACHE_FLASH_ATTR wifi_check_ip(void *arg)
{
	// Структура с информацией о полученном, ip адресе клиента STA, маске подсети, шлюзе.
	struct ip_info ipConfig;
	// Отключаем таймер проверки wi-fi
	os_timer_disarm(&WiFiLinker);
	// Получаем данные о сетевых настройках
	wifi_get_ip_info(STATION_IF, &ipConfig);
	// Проверяем статус wi-fi соединения и факт получения ip адреса
	if (wifi_station_get_connect_status() == STATION_GOT_IP && ipConfig.ip.addr != 0)
	{
		// Соединения по wi-fi установлено
		connState = WIFI_CONNECTED;
		#ifdef PLATFORM_DEBUG
	        uart0_sendStr("WiFi connectedrn");
        #endif
		#ifdef PLATFORM_DEBUG
	        uart0_sendStr("Start TCP connecting...rn");
        #endif
		connState = TCP_CONNECTING;
		// Отправляем данные на ПК
		senddata();
		// Запускаем таймер проверки соединения и отправки данных уже раз в 5 сек, см. тех.задание
		os_timer_setfn(&WiFiLinker, (os_timer_func_t *)wifi_check_ip, NULL);
		os_timer_arm(&WiFiLinker, 5000, 0);
	}
	else
	{
		// Неправильный пароль
		if(wifi_station_get_connect_status() == STATION_WRONG_PASSWORD)
		{
			connState = WIFI_CONNECTING_ERROR;
			#ifdef PLATFORM_DEBUG
			uart0_sendStr("WiFi connecting error, wrong passwordrn");
			#endif
			os_timer_setfn(&WiFiLinker, (os_timer_func_t *)wifi_check_ip, NULL);
			os_timer_arm(&WiFiLinker, 1000, 0);
		}
		// AP не найдены
		else if(wifi_station_get_connect_status() == STATION_NO_AP_FOUND)
		{
			connState = WIFI_CONNECTING_ERROR;
			#ifdef PLATFORM_DEBUG
			uart0_sendStr("WiFi connecting error, ap not foundrn");
			#endif
			os_timer_setfn(&WiFiLinker, (os_timer_func_t *)wifi_check_ip, NULL);
			os_timer_arm(&WiFiLinker, 1000, 0);
		}
		// Ошибка подключения к AP
		else if(wifi_station_get_connect_status() == STATION_CONNECT_FAIL)
		{
			connState = WIFI_CONNECTING_ERROR;
			#ifdef PLATFORM_DEBUG
			uart0_sendStr("WiFi connecting failrn");
			#endif
			os_timer_setfn(&WiFiLinker, (os_timer_func_t *)wifi_check_ip, NULL);
			os_timer_arm(&WiFiLinker, 1000, 0);
		}
		// Другая ошибка
		else
		{
			os_timer_setfn(&WiFiLinker, (os_timer_func_t *)wifi_check_ip, NULL);
			os_timer_arm(&WiFiLinker, 1000, 0);
			connState = WIFI_CONNECTING;
			#ifdef PLATFORM_DEBUG
			uart0_sendStr("WiFi connecting...rn");
			#endif
		}
	}
}

Процедура отправки данных на ПК

static void ICACHE_FLASH_ATTR
senddata()
{
	char info[150];
	char tcpserverip[15];
	struct espconn *pCon = (struct espconn *)os_zalloc(sizeof(struct espconn));
	if (pCon == NULL)
	{
		#ifdef PLATFORM_DEBUG
		uart0_sendStr("TCP connect failedrn");
		#endif
		return;
	}
	pCon->type = ESPCONN_TCP;
	pCon->state = ESPCONN_NONE;
	// Задаем адрес TCP-сервера, куда будем отправлять данные
	os_sprintf(tcpserverip, "%s", TCPSERVERIP);
	uint32_t ip = ipaddr_addr(tcpserverip);
	pCon->proto.tcp = (esp_tcp *)os_zalloc(sizeof(esp_tcp));
	pCon->proto.tcp->local_port = espconn_port();
	// Задаем порт TCP-сервера, куда будем отправлять данные
	pCon->proto.tcp->remote_port = TCPSERVERPORT;
	os_memcpy(pCon->proto.tcp->remote_ip, &ip, 4);
	// Регистрируем callback функцию, вызываемую при установки соединения
	espconn_regist_connectcb(pCon, at_tcpclient_connect_cb);
	// Можно зарегистрировать callback функцию, вызываемую при реконекте, но нам этого пока не нужно
	//espconn_regist_reconcb(pCon, at_tcpclient_recon_cb);
	// Вывод отладочной информации
	#ifdef PLATFORM_DEBUG
	os_sprintf(info,"Start espconn_connect to " IPSTR ":%drn",
		   IP2STR(pCon->proto.tcp->remote_ip),
		   pCon->proto.tcp->remote_port);
	uart0_sendStr(info);
	#endif
	// Установить соединение с TCP-сервером
	espconn_connect(pCon);
}

callback функция, вызываемая после установки соединения

static void ICACHE_FLASH_ATTR
at_tcpclient_connect_cb(void *arg)
{
	struct espconn *pespconn = (struct espconn *)arg;
	#ifdef PLATFORM_DEBUG
	uart0_sendStr("TCP client connectrn");
	#endif
	// callback функция, вызываемая после отправки данных
	espconn_regist_sentcb(pespconn, at_tcpclient_sent_cb);
	// callback функция, вызываемая после отключения
	espconn_regist_disconcb(pespconn, at_tcpclient_discon_cb);
	char payload[128];
	// Подготавливаем строку данных, будем отправлять MAC адрес ESP8266 в режиме AP и добавим к нему строку ESP8266
	os_sprintf(payload, MACSTR ",%srn", MAC2STR(macaddr), "ESP8266");
	#ifdef PLATFORM_DEBUG
	uart0_sendStr(payload);
	#endif
	// Отправляем данные
	espconn_sent(pespconn, payload, strlen(payload));
}

callback функции, вызываемые после отправки данных и после отключения


static void ICACHE_FLASH_ATTR
at_tcpclient_sent_cb(void *arg) {
	#ifdef PLATFORM_DEBUG
	uart0_sendStr("Send callbackrn");
	#endif
	// Данные отправлены, отключаемся от TCP-сервера
	struct espconn *pespconn = (struct espconn *)arg;
	espconn_disconnect(pespconn);
}

static void ICACHE_FLASH_ATTR
at_tcpclient_discon_cb(void *arg) {
	struct espconn *pespconn = (struct espconn *)arg;
	// Отключились, освобождаем память
	os_free(pespconn->proto.tcp);
	os_free(pespconn);
	#ifdef PLATFORM_DEBUG
	uart0_sendStr("Disconnect callbackrn");
	#endif
}

И в заключении видео, с демонстрацией работы этой прошивки

Как Вы уже заметили, плата на чипе Espressif ESP8266 обладает достаточно внушительным потенциалом для написания собственных прошивок.
В следующей статье я приведу пример работы ESP8266 в связке с модулем передатчика nooLite MT1132 и мы попробуем управлять освещением в реальной квартире. Возможно в этой же статье мы разберем работу простейшего Web-сервера для ESP8266.

P.S. Если у Вас возникли вопросы и пожелания, то я буду рад их выслушать, но ввиду низкой кармы я не смогу отвечать оперативно в комментариях, поэтому пишите в ПМ или на email.

Автор: Sleuthhound

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js