ESP8266 Урок 21. FreeRTOS. Wi-Fi. Режим STA



Продолжаем учиться писать код для микроконтроллера ESP8266 с использованием операционной системы реального времени FREEFTOS.

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

С таким режимом мы уже работали в уроке 14, но только без использования операционной системы, в автономном режиме.

А с использованием операционной системы работа с таким режимом несколько отличается, так как нам нужно учитывать определённые требования FREERTOS, а также работу мы ведём с использованием другого комплекта SDK.

Схема у нас остаётся прежней — отладочная плата, подключенная к USB компьютера

 

 

А проект мы за основу возьмём из урока 19 с именем UART_TX_RTOS и дадим ему имя WIFI_STA_RTOS.

Откроем наш проект в Eclipse и первым делом в файле main.c исправим в функции user_rf_cal_sector_set вот эту циферку

 

rf_cal_sec = 128 - 5;

 

Удалим объявление структуры с переменными

 

typedef struct

{

  unsigned char num_task;

  unsigned short del;

} pData;

pData dt1, dt2;

 

В функции user_init удалим инициализацию переменных и создание двух задач

 

dt1.del = 1000; dt1.num_task = 1;

dt2.del = 900; dt2.num_task = 2;

xTaskCreate(task1, «task1», 256, (void *) &dt1, 1, NULL);

xTaskCreate(task1, «task2», 256, (void *) &dt2, 1, NULL);

 

Вместо этого произведём инициализацию ножки, к которой подключен синий светодиод, и создадим задачу без параметров

 

 

В функции задачи task1 удалим код инициализации, оставим только бесконечный цикл, в котором будем лишь время от времени выводить версию SDK для того, чтобы видеть, что у нас работает операционная система и ничего не повисло. После этого функция примет вот такой вид

 

 

В заголовочном файле user_config.h объявим две константы с именем точки доступа, к которой мы будем подключаться и с паролем

 

 

Так как работа с режимом станции Wi-Fi не такая простая, давайте для этого создадим ещё один модуль в виде двух файлов wifi.c и wifi.h, которые будут иметь пока вот такое содержимое

 

wifi.h:

 

wifi.c:

 

Подключим также данный модуль в main.h

 

 

В файле wifi.c добавим функцию инициализации wifi

 

 

Создадим на данную функцию прототип в заголовочном файле wifi.h и вызовем её в main.c

 

 

В файле wifi.h объявим два типа указателей на функции (с указателями на функции мы знакомы из уроков по C, а именно из урока 30)

 

 

В файле wifi.c создадим несколько указателей таких типов и объявим, что они пока никуда не указывают

 

 

Объявим также две глобальные переменные булевого типа и пока проинициализируем их в false

 

 

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

 

 

И ниже добавим такую функцию, в которой пока выведем в терминальную программу соответствующее сообщение

 

 

В функции инициализации вызовем функцию назначения указателя функции и передадим ей в параметре имя функции

 

 

Добавим статическую переменную для программного таймера

 

 

Добавим функцию, которую мы будем вызывать при соединении с точкой доступа, в которой выйдем из функции, если переменная состояния соединения ещё не получила значения true

 

 

Затем узнаем текущий режим

 

 

Если там не присутствует режим STA, то также выйдем из функции с результатом false

 

 

Ну а дальше, если мы не вышли из функции, узнаем состояние соединения

 

 

Путём некоторого логического сбора информации о состояниях соединения присвоим нашей булевской переменной новое значение и вернём его

 

 

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

 

 

Далее в условии вызовем нашу функцию, которую мы только что написали, и если результат будет true, то выведем в терминальную программу соответствующее сообщение

 

 

 

В противном случае отправим в терминальную программу сообщение об ожидании 2 секунд и вызовем инициализацию таймера повторно и данная функция вызовется рекурсивно, так как в параметре инициализации таймера будет её имя, а затем запустим таймер

 

 

Также нам надо запустить таймер первоначально. Это мы проделаем в функции on_wifi_connect

 

 

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

Для этого мы также добавим функцию для присвоения реального указателя функции ниже функции set_on_station_connect

 

 

А ниже функции on_wifi_connect добавим функцию, в которой мы будем только выводить сообщение в терминальную программу о том, что у нас пропало соединение, с указанием идентификатора причины разъединения, которые можно посмотреть в библиотеке в соответствующем перечисляемом типе, больше мы в данной функции ничего делать не будем

 

 

Вызовем функцию для присвоения указателя в функции инициализации init_esp_wifi

 

 

Добавим обработчик событий соединения Wi-Fi, в котором сбросим переменную состояния в false

 

 

В функции инициализации init_esp_wifi с помощью специальной библиотечной функции назначим данную функцию обработчиком событий

 

 

Добавим глобальный макрос для ножки светодиода

 

 

В обработчике wifi_event_handler_cb, если вдруг событие ведёт вникуда, то вернёмся из функции

 

 

Покажем в терминальной программе идентификатор события

 

 

Затем, используя оператор вариантов, подготовим ветви для обработки различных событий соединения Wi-Fi

 

 

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

 

 

Создадим указатель на тип структуры состояния разрыва и присвоим ей адрес соответствующего поля указателя на переменную структуры из параметра функции

 

 

Если функция события разъединения не ведёт вникуда, то вызовем её, передав ей в параметре идентификатор причины разъединения

 

 

Далее обработаем событие соединения, в соответствующем кейсе которого выведем в терминальную программу сообщение о том, что у нас статическая адресация, если это действительно так

 

 

Установим в true нашу переменную состояния соединения

 

 

Если подобная переменная, только локальная, не установлена в true, то мы её тоже установим

 

 

 

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

 

 

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

 

 

Далее обработаем условие ожидания присвоения адреса от сервера DHCP, в котором мы сбросим нашу переменную состояния в false, если она в true

 

 

Затем вызовем функцию разрыва соединения при условии её существования, а она у нас есть, передав ей идентификатор причины UNSPECIFIED

 

 

Следующее событие — событие успешного присвоения адреса DHCP-сервером нашему модулю, в котором мы установим нашу переменную в true

 

 

Зажжем наш светодиод

 

 

Также в true установим и локальную переменную

 

 

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

 

 

Выйдя из обоих условий, вызовем функцию соединения

 

 

Обработаем также событие соединения в случае настройки нашего модуля в режиме точки доступа

 

 

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

Аналогично обработаем событие разъединения с клиентом в случае настройки в режиме точки доступа

 

 

Ниже функции on_wifi_disconnect добавим функцию установки режима работы модуля Wi-Fi

 

 

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

В функции инициализации init_esp_wifi установим режим по умолчанию, узнав его предварительно с помощью определённой библиотечной функции

 

 

Ниже функции wifi_set_mode добавим функцию отключения режима точки доступа

 

 

В теле данной функции мы сначала узнаем режим работы модуля и занесём его в соответствующую переменную, в которой впоследствии сбросим бит точки доступа, и затем установим режим со сброшенным битом. В случае неудачи установки выведем соответствующее сообщение в терминальную программу и возвратимся со статусом false, а в случае удачи — true.

Вызовем данную функцию в функции инициализации init_esp_wifi и вернём режим

 

 

Ниже функции wifi_set_mode добавим функцию старта соединения с параметрами имени точки доступа и пароля доступа к ней, в теле которой мы сначала узнаем текущий режим работы модуля Wi-Fi

 

 

Затем в теле данной функции, если в режиме бит станции не установлен, то установим его сначала в переменной

 

 

Попытаемся установить новый режим, если будет неудача, то выведем соответствующее сообщение в терминальную программу и выйдем из функции с статусом false

 

 

Выйдя из тел обоих условий, проверим условие наличия переданного SSID, если он пустой то также выведем соответствующее сообщение и выйдем из функции со статусом false

 

 

Выйдя из этого условия, создадим переменную структуры конфигурации соединения, в которой сначала память, выделенную под её поля, очистим полностью, а затем занесём в соответствующее поле имя точки доступа

 

 

Если пароль непустой, также присвоим его соответствующему полю переменной структуры

 

 

Вызовем функцию занесения полей в модуль, если неудача, то возвратимся с результатом false

 

 

Включим режим полноправной работы модуля (режим без ограничения энергопотребления)

 

 

Включим режим DHCP Client, при неудаче выходим из функции со статусом false

 

 

Включим самую большую поддерживаемую скорость (протокол 802.11N)

 

 

Вызовем функцию соединения с точкой доступа и вернём статус

 

 

В функции user_init файла main.c вызовем данную функцию, не забыв перед этим добавить её прототип в заголовочном файле

 

 

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

 

 

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

 

 

Также попробуем послать пинги нашему модулю

 

 

Модуль отлично откликается.

Итак, на данном уроке нам удалось настроить модуль Wi-Fi нашего контроллера ESP8266 в режиме станции, используя при этом операционную систему реального времени FREERTOS.

Всем спасибо за внимание!

 

 

Предыдущий урок Программирование МК ESP8266 Следующий урок

 

Исходный код

 

 

Модуль ESP NodeMCU можно купить здесь: Модуль ESP NodeMCU

Различные модули ЕSP8266 можно приобрести здесь Модули ЕSP8266

Переходник USB to TTL можно приобрести здесь ftdi ft232rl

Многофункциональный переходник JTAG UART FIFO SPI I2C можно приобрести здесь CJMCU FT232H USB к JTAG UART FIFO SPI I2C

Логический анализатор 16 каналов можно приобрести здесь

 

 

Смотреть ВИДЕОУРОК (нажмите на картинку)

 

ESP8266 FreeRTOS. Wi-Fi. Режим STA

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*