Системный администратор, программист
0,0
рейтинг
24 ноября 2014 в 22:36

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

В прошлой статье мы рассмотрели первоначальную настройку и работу модуля 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, стандартные примеры прошивок, а так же мои собственные примеры прошивок.

Итак приступим:
1. Cкачиваем (148Mb) и устанавливаем мой комплект Espressif-ESP8266-DevKit-v2.2.1-x86.exe (актуален на 15.11.2016)
2. Скачиваем и устанавливаем Java Runtime x86 или x64 (Например: jre-8u111-windows-x64.exe для Windows x64)
3. Скачиваем и устанавливаем Eclipse Neon x86 или Eclipse Neon x64 для разработки на С++. Распаковываем архив в корень диска С.
4. Скачиваем и устанавливаем MinGW. Запускаем mingw-get-setup.exe, в процессе установки выберите режим без GUI, то есть уберите галочку "...also install support for the graphical user interface".
5. Скачиваем набор моих скриптов для автоматизации установки доп.модулей для MinGW. (актуален на 15.10.2016)
6. Запустите из моего набора файл install-mingw-package.bat. Он скачает с моего сайта закэшированые архивы пакетов для mingw, примерно 90 Mb и установит основные модули для MinGW. Скачивание заранее готового набора файлов пакетов для MinGW гарантирует, что все они будут установлены, иногда сервера, где лежат пакеты MinGW становятся недоступными и необходимые пакеты не ставятся и поэтому сборка прошивок может проходить с разного рода фокусами.
7. Запустите Eclipse из каталога c:\eclipse\eclipse.exe
8. В Eclipse выберите меню File -> Import -> General -> Existing Project into Workspace, в строке Select root directory выберите каталог C:\Espressif\examples\ESP8266 и импортируйте рабочие проекты.
Далее справа в Make Target выберите нужный проект, например hello-world и запустите цель all на сборку,
при этом в окне Console должен отобразиться ход сборки, если все сделано правильно, то будет примерно такая картина:

17:00:00 **** Build of configuration Default for project hello-world ****
mingw32-make.exe -f C:/Espressif/examples/ESP8266/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:\Espressif\examples\hello-world\firmware
Для прошивки ESP8266 используйте цель flash, предварительно отредактировав файл сборки проекта Makefile, строка
ESPPORT ?= COM2
, где после COM цифра 2 указывает номер COM-порта к которому подключена плата с ESP8266.

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

Видео с демонстрацией создания нового проекта в Eclipse.

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

ВНИМАНИЕ! В моей текущей сборке Unofficial Development Kit for Espressif ESP8266 утилита esptool уже содержит эти доработки, поэтому дополнительно патчить ничего не нужно.

Так же я подправил утилиту esptool.py в процедуре connect
Так же я подправил утилиту 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...'

Таким легким финтом ушами я решил проблему ручного перехода в режим обновления прошивки.


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


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

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

Часть 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:\Espressif\examples\
Типичная структуры папок в любом проекте для 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

Открываем файл user\user_main.c

Основная процедура, которая выполняется при старте прошивке это
//Init function 
void ICACHE_FLASH_ATTR
user_init()
{
}

В начало файла user\user_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:\Espressif\ESP8266_SDK\include\
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...\r\n");
	#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...\r\n");
		#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: %s\r\n",
			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!\r\n");
	#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...\r\n");
			#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 connected\r\n");
        #endif
		#ifdef PLATFORM_DEBUG
	        uart0_sendStr("Start TCP connecting...\r\n");
        #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 password\r\n");
			#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 found\r\n");
			#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 fail\r\n");
			#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...\r\n");
			#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 failed\r\n");
		#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 ":%d\r\n",
		   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 connect\r\n");
	#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 ",%s\r\n", 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 callback\r\n");
	#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 callback\r\n");
	#endif
}

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

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

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

Подробнее
Реклама

Самое читаемое

Комментарии (55)

  • 0
    Не нашел сходу характеристики контроллера (производительность/ОЗУ/ПЗУ), чтобы понять хоть качественно, на что способен контроллер…
    • +1
      В статье есть ссылка на спецификацию чипа, там все характеристики. И это не контроллер, это система на кристале (SoC).
  • 0
    Где можно скачать ехпрессифный девелоперкит под 32х разрядную винду?
    • +1
      Только если собирать самому. У меня на работе и дома x64, я не могу собрать под x86 версию, собирать на виртуалке — это гиблое дело. Попробую собрать на x86 на неделе на другом рабочем ПК, но не факт что получится.
      • 0
        ну так может проще было выложить это в виде архива, без всяческого стремного виндовсинсталятора?
        • 0
          А смысл? Компилятор будет работать только под x64.
          Перевыложил инсталлятор Espressif-ESP8266-DevKit-v0.9.3.exe, теперь он не проверяет разрадность Windows и поставится даже на x86, но скомпилировать под x86 Вы ничего не сможите!
          • 0
            всмысле xtensa на x64?
            • 0
              нет, просто компилятор не заработает — ругнется при запуске на неверную версию виндовс и умоет руки.
    • 0
      Вот тут имеется инструкция как собрать комплиятор под win x86. Сам не собирал — для меня не актуально.
      Про характеристики можно добавить, что размер ПЗУ зависит от того какой чип flash памяти стоит на плате. Обычно там установлен чип на 4мбита т.е. 512кбайт.

      Вообще, по моим наблюдениям SDK и/или компилятор не сильно допилены — иногда бывают необъяснимые глюки в работе собранных прошивок.
      Недавно вышел SDK 0.9.3, но на его я ещё не перешел.
      • 0
        Не. парнишка пишет следующее:
        Its made by mobyfab from esp8266.com
        These are apperently x64 binaries so no hope for you if you are using 32 bit machine
        .
      • 0
        иногда бывают необъяснимые глюки в работе собранных прошивок

        Если есть подозрения на компилятор, пожалуйста, рапортуйте о них в этом топике: www.esp8266.com/viewtopic.php?f=9&t=224
        Я посмотрю.
  • +1
    Последняя версия esptool поддерживает все операции — и создание образов, и прошивку, поэтому пользоваться 2мя esptool'ами необязательно. (Откуда взялось 2 тулзы с одним названием — загадка, но esptool.py появился в первые дни после начала хаканья ESP8266.)

    И в последней версии esptool позволяет шить сразу несколько сегментов за раз, без перезагрузки между ними, поэтому городить DTR'ы для автоматизации тоже опционально.
    • +1
      pfalcon а как Вы собираетесь зайти в режим загрузчика без перезагрузки платы? Вот именно для этого и сгорожены RTS и DTR.

      P.S. Я в курсе, что последняя версия esptool.py позволяет шить срузу 2 сегмента и собирать прошивку, в моих Makefile'ах как раз шьется именно 2 сегмента за раз.
      • 0
        А, ну да, передернуть питание сложно конечно. Но я пока делаю так. У меня GPIO0 вообще постоянно на GND в последнее время — перезагрузились, и можно шиться. Не нужно шиться в этот раз? В esptool.py теперь есть команда «run», которая запустит пользовательское приложение из бутлоадера.
        • 0
          на самом деле питанию не дергаю совсем: слишком сложная цепочка тулчеинов в паре виртуальных машин и маппинга компорта. Для прошивки/работы достаточно перетнкнуть пин на единицу/ноль и ножку RST коротко воткнуть на ноль. Принцип тот же, только руками. И времени много не занимает.
        • 0
          Да, бывает питание сложно передернуть, особенно если плата на другом конце города на работе, а я дома и по rdp сижу и пишу прошивку ;)
          • 0
            Ситуации разные бывают, да. Как например есть много USB-UART модулей, где только TXD/RXD выведены. Ну, пытливый читатель теперь будет знать, что все варианты под контролем ;-).
  • 0
    Добавлю пару ссылок.

    Посмотрел исходные коды с китайского сайта, некоторые китайцы, возможно, пользуются этим компилятором и IDE keil

    А в Англии студенты используют отладочную плату и красивый визуальный 3D интерфейс для проекта с ESP8266: www.rs-online.com/designspark/electronics/eng/blog/internet-of-things-made-simple-sensor-monitoring-the-flowcode-way
    • +1
      Самое интересное же! Удалось ли кому-то прочитать DS18B20 из ESP8266? Нашел пару примеров, но пока железки едут проверить не могу. Мне кажется это очень важная связка, ибо получается супердешевый wifi-термометр который можно раскидать где угодно по дому.
      • 0
        Вот тут можно вопрос задать, но только на чистом китайском :-). Если я понял правильно через перевод google, китайцы подключили DS18B20 к ESP8266. Это китайский пример с русскими комментариями для ESP8266 и DS18B20, надеюсь поможет в работе. Я сам пример не запускал.
        • +1
          Этот пример DS18B20 для работы на каком-то м/к через АТ команды. Сам лично пробовал переписывать код чтения DS18B20 под ESP8266, но пока ничего не вышло… Возможно проблема в точности пауз и наличия мешающих прерываний. Успешно запущены датчики DHT22 и BMP085/180. Даже готова прошивка отправки данных на сайт narodmon.ru
      • 0
        А я очень сильно жду появления у китайцев датчика BME280 — это универсальный датчик температуры, влажности, давления (работает по I2C,SPI), имееет хорошую точность и быстродействие.
        • 0
          Сейчас есть у них. Правда пока только 5шт по 220р\шт. Не покупали ещё? У меня уже есть желание заказать — они ж идеальны для автономных мини-метеостанций. Только код для ESP ещё никто не написал :)
          • 0
            Не заказывал еще, есть подозрение, что это не финальная партия от Bosch Sensortec, а некая экспериментальная которую Bosch рассылали для тестирования в январе 2015.
            В драйвера уже есть github.com/BoschSensortec/BME280_driver
  • 0
    А кто-то из владельцев модуля может протестить, реально ли связать два модуля между собой, переведя один из них в режим AP?
    • 0
      Через пару недель приедут 5 модулей ESP-07, тогда попробую провести эксперимент, но вообще проблем быть не должно.
    • 0
      Да, вполне реально.
    • 0
      два модуля с собой не связывал, зако тестировал по полной для компа. В модулях есть реализация dhcp сервера. умолчательный адрес AP 192.168.4.1. Каждому клиенту выделяется следующий адрес. Тестировал до трех клиентов — адреса получали точно, была возможность что либо послать — проблем не возникало.
  • 0
    github.com/espressif/esp8266_at/tree/master/at
    Дождались, исходники прошивки ESP8266. 17 часов назад выложил автор.
    • 0
      Исходники AT-прошивки давно доступны, просто они версии 0.9.1 были и не из оф.репа (см. мою сборку, они там есть), а тут вроде как все официально, хотя эти исходники интересны как пример прошивки, чтобы написать свою.
  • 0
    Сегодня обновил мои комплекты Espressif ESP8266 DevKit, что нового:
    1. Доступен компилятор под Windows x86, качаем programs74.ru/get.php?file=EspressifESP8266DevKitX86
    2. Для Windows x64 качаем этот programs74.ru/get.php?file=EspressifESP8266DevKitX64
    3. Теперь для работы DevKit не требуется Python
    4. В комплекты были добавлены новые примеры: 1wire_ds18b20, analog_dht22, blinky, blinky2, i2c_24xx16, i2c_htu21d и др.
    • 0
      Нельзя изменить при инсталяции папку установки C:\Espressif
      • 0
        Вы можете перенести папку Espressif куда нужно после установки, но тогда Вам нужно будет установить Python 2.7, исправить путь к папке Espressif в исходниках утилит C:\Espressif\utils\esptool.py и C:\Espressif\utils\gen_appbin.py и C:\Espressif\utils\gen_appbin_old.py и скомпилировать их через C:\Espressif\utils\py2exe_*.cmd файлы
  • 0
    Никто не делал настроек для notepad++ для компиляции\заливки прошивок?
    В идеале с поддержкой файлов-проектов, но хотя бы просто компиляцию осилить…
    На моем старом нубуке эклипс это нечто монстроподобное и практически не шевелящееся :(
    • 0
      В теории это не сложно сделать, Makefile из DevKit устроены так, что могут собирать прошивку из командной строки MinGW и без Eclipse.
      • 0
        Да, разобрался. Меня ввели в заблуждение ошибки при попытке сборки с командной строки. Оказалось просто системная PATH не содержала путей к bin MSYS и MinGW. Добавил c:\MinGW\msys\1.0\bin\ и c:\MinGW\bin\ и все заработало. Команда проста, выполняется с директории с Makefile:
        c:\MinGW\bin\mingw32-make.exe -f Makefile
  • 0
    Попробовал повторить финт
    Так же я подправил утилиту esptool.py в процедуре connect для того, чтобы при запуске происходил сброс платы по сигналу RTS и вход в режим загрузчика по сигналу DTR.

    Файл esptool.py видимо уже подправлен и от цитаты в статье не отличается.
    COM порт 2.
    При Make Target Build Flash сообщение об ошибке:
    Description Resource Path Location Type
    mingw32-make.exe: *** [flash] Error 255 hello_world C/C++ Problem
    recipe for target 'flash' failed Makefile /hello_world line 313 C/C++ Problem

    В какую сторону копать?
    • 0
      В DevKit esptool.py уже исправлен, я же писал относительно оригинального esptool.py, его я и исправлял.

      Копать в сторону переустановки MinGW по моей инструкции, скорее всего Вы не установили нужные пакеты.
      • 0
        Спасибо. Как то пропустил шаг.
        Понял после поиска и нахождения статьи с подробным пошаговым описанием:
        Step 5: Mikhail Grigoriev made some awesome scripts to automate the installation of additional modules in MinGW which are needed for compiling. You can download his package here, extract it somewhere and then run install-mingw-package.bat.
        • 0
          Финт с RTS-DTR чудесен. Проработал модуль 2-е суток и умер. При включении иногда сыпет в консоль мусор.
          Попытался перепрошивать флешерами с замыканием GPIO, с выключением, включением — не шился по обычной инструкции. Вспомнил о этой статье и прошился из eclipse. Чем-то лучше этот метод, чем ручные переключения ресет и gpio.

          Остается только вопрос почему умерла прошивка. Может флеш-память 25Q40 глючная.
          • 0
            Смотря что делала Ваша прошивка, если она писала во flash, то может не в ту область записала и потерла что-то.
            У меня таких чудес не было ни разу.
            • 0
              NodeMCU 0.9.5
              Почти по статье скрипт для отправки thingspeak
              habrahabr.ru/post/252481

              Работа модуля не стабильна. Несколько раз работал по часов 5 — затем перезагружался. Буду дальше смотреть на стабильность работы. Пока надежность не устраивает. Нельзя оставить устройство и забыть.
              • 0
                Скорее всего утечка памяти в прошивке NodeMCU, через N часов память заканчивается и все виснет.
          • 0
            Так удалось прошивку восстановить? У меня уже три таких модуля загубленных модуля. Времени особо найти не могу на поиск инфы, как их можно вернуть к жизни.

            Интересно то, что неважно в каком режиме, идет работа с тнрминалом АТ. Только ни одна команда не реагирует — сообщает об ошибке.
            • 0
              По описанному методу прошивается и работает.

              Модуль с самого начала не реагировал на команды, только при включении питания выдавал в консоль web адрес.

              Пока больше не повторялось. Гоняю в температуру с него в thingspeak.com и записываю его перезагрузки — чаще всего раз в сутки и чаще перегружается.

            • 0
              В августе опять прошивка умерла. Только сейчас появилось желание что-то опять прошить. Но уже обновилось EspressifESP8266DevKitAddon и по этой инструкции Sleuthhound скомпилировать и прошить пока не получается. Хотелось бы оставить возможность прошивать с RTS-DTR — очень удобно.
              • 0
                Возможность прошивать с RTS-DTR в DevKit есть, в комплект DevKit уже входит рабочий esptool.py (esptool.exe)
                • 0
                  Проблема в том, что по описанной инструкции уже настроить не получилось, например, нет такого файла — «Запустите из моего набора файл install-mingw-package.bat.». Сейчас выясняю как поправить ошибки Eclipse на компилятор.
                  • 0
                    Скорее всего проблема в том, что Вы невнимательно прочитали статью:

                    5. Скачиваем (84Mb) набор моих скриптов для автоматизации установки доп.модулей для MinGW.

                    Вот как раз в этом файле и есть install-mingw-package.bat
  • 0
    А как отключить вайфай? У меня модуль раз в час дергает интернет, в остальное время ему нужно тихо сидеть и не отсвечивать. Я сделал
    void ICACHE_FLASH_ATTR wifi_disconnect() {
    	wifi_station_disconnect();
    	wifi_station_dhcpc_stop();
    	wifi_station_set_auto_connect(0);
    	connState = WIFI_CONNECTING_ERROR;
    }
    
    , но он, похоже, сразу после отключения переключается в режим точки и вовсю ждет подключения. То ли это из-за того, что я connState в WIFI_CONNECTING_ERROR устанавливаю, то ли надо как-то хитро отключать вай-фай. По докам не понял…
    • 0
      У меня для проверки WiFi запускается таймер WiFiLinker, в user_init() см.
      os_timer_disarm(&WiFiLinker);
      os_timer_setfn(&WiFiLinker, (os_timer_func_t *)wifi_check_ip, NULL);
      os_timer_arm(&WiFiLinker, 1000, 0);

      После того, как вы делаете wifi_disconnect, нужно его останавливать, переводить esp в глубокий сон на N минут, а далее все по кругу.
      Если ESP не нужно переводить в глубокий сон, то просто останавливаете таймер WiFiLinker, запускаете свой таймер с тем интервалом с каким нужно переподключаться к WiFi, после сработки этого таймера запускаете установку wi-fi соединения, стопите ваш таймер, запускаете таймер WiFiLinker и так по кругу.
      Но лучше использовать режим deep sleep, там значительно ниже энергопотребление, чем если вы будите гонять вхолостую таймеры.
      • 0
        Так это для проверки вай-фая же wifi_check_ip? Т.е. если я дисконнектнул, он просто будет каждую секунду проверять, не установился ли коннект. Или он при отсутствии коннекта запускает режим АП, вот я чего не пойму? С дипслипом играться лень — не охота паяльником лезть в модуль. И он мне не особо нужен, не батареешная тема :-)
      • +1
        Все оказалось намного прозаичнее. Не заметил, что модуль может быть одновременно и точкой и станцией. Соответственно в конфиге стоял режим stationap…
  • 0
    Я еще доработал esptool.py по инструкции www.esp8266.com/wiki/doku.php?id=setup-windows-compiler-esp8266
    Теперь запускаешь Termie, когда начинаешь шить из эклипса, терминал отдает порт автоматом среде, а после перепрошивки опять забирает

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