Продолжаем программирование микроконтроллера ESP8266 с использованием операционной системы реального времени FREEFTOS.
На данном уроке мы также продолжим тему беспроводной передачи данных и попробуем настроить наш модуль в режиме программной точки доступа (SOFTAP). После этого мы можем создавать подключение с узлами, настроенными в режиме станции, пытающимися подключиться к нашему модулю. Также мы попытаемся с помощью настройки DHCP раздать нашим станциям IP-адреса.
Схема наша остаётся без изменений – отладочная плата, подключенная к USB компьютера
Проект за основу мы возьмём с прошлого занятия с именем WIFI_STA_RTOS и присвоим ему новое имя WIFI_AP_RTOS.
Откроем наш проект в среде Eclipse и в файле конфигурации user_config.h добавим имя нашей точки доступа, пароль подключения к ней, её сетевой адрес, шлюз, сетевую маску, а также начало и окончание пула адресов, выделяемых подключаемым станциям
1 2 3 4 5 6 7 8 |
#define WIFI_CLIENTPASSWORD "12345678" #define WIFI_APSSID "ESP8266_AP" #define WIFI_APPASSWORD "12345678" #define WIFI_AP_IP "192.168.0.1" #define WIFI_AP_GW "192.168.0.1" #define WIFI_AP_NETMASK "255.255.255.0" #define WIFI_AP_IP_CLIENT_START "192.168.0.100" #define WIFI_AP_IP_CLIENT_END "192.168.0.105" |
Данные станции мы удалять не будем, так как наш проект будет универсальным и сможет работать как в режиме станции, так и точки доступа.
В файле wifi.c ниже функции set_on_station_disconnect добавим функции, получающие указатели на функции соединения станции с нашей точкой доступа, а также разрыва соединения
1 2 3 4 5 6 7 8 9 10 |
//------------------------------------------------ void ICACHE_FLASH_ATTR set_on_client_connect(wifi_state_cb_t cb){ on_client_connect = cb; } //------------------------------------------------ void ICACHE_FLASH_ATTR set_on_client_disconnect(wifi_state_cb_t cb) { on_client_disconnect = cb; } //------------------------------------------------ |
Ниже функции on_wifi_disconnect добавим функцию-обработчик соединения станции с нашей точкой доступа
1 2 3 4 5 6 7 8 9 |
//------------------------------------------------ LOCAL void ICACHE_FLASH_ATTR on_wifi_client_connect() { os_printf("on_wifi_client_connect();\n"); uint32 station_num = wifi_softap_get_station_num(); os_printf("number station: %d\n", station_num); GPIO_OUTPUT_SET(GPIO_LED, 0); } //------------------------------------------------ |
В данной функции мы выведем соответствующее сообщение в терминальную программу, затем узнаем количество подключенных станций, впоследствии также выведя об этом соответствующее сообщение в терминальную программу и зажжём наш светодиод.
Ниже этой функции добавим функцию-обработчик разъединения станции с точкой доступа
1 2 3 4 5 6 7 8 9 |
//------------------------------------------------ LOCAL void ICACHE_FLASH_ATTR on_wifi_client_disconnect() { os_printf("client disconnect\n"); uint32 station_num = wifi_softap_get_station_num(); os_printf("number station: %d\n", station_num); if (!station_num) GPIO_OUTPUT_SET(GPIO_LED, 1); } //------------------------------------------------ |
Данная функция подобна предыдущей, только выводит она уже сообщение в терминальную программу об отсоединении станции, и если у нас подсоединённых станций не осталось, то есть их количество равно 0, то мы погасим светодиод.
Из тела функции инициализации init_esp_wifi удалим данные строки
set_on_station_connect(on_wifi_connect);
set_on_station_disconnect(on_wifi_disconnect);
А вместо них мы зарегистрируем наши 2 функции, которые мы только что добавили
1 2 |
set_on_client_connect(on_wifi_client_connect); set_on_client_disconnect(on_wifi_client_disconnect); |
В функции-обработчике событий wifi-соединения wifi_event_handler_cb исправим ошибку в кейсе EVENT_SOFTAPMODE_STACONNECTED, так как мы там вместо on_client_connect проверяли on_station_connect
Ниже функции старта станции start_wifi_station добавим функцию старта точки доступа, в теле которой для начала объявим переменную типа структуры ip_info, также целочисленную переменную для адреса и два символьных массива для IP-адреса и MAC-адреса
1 2 3 4 5 6 7 8 9 |
//------------------------------------------------ bool ICACHE_FLASH_ATTR start_wifi_ap(const char * ssid, const char * pass) { struct ip_info ipinfo; uint32_t ip; char ip_char[15]; char macaddress[17]; } //------------------------------------------------ |
Добавим символьный массив для MAC-адреса
1 2 |
struct ip_info ipinfo; uint8 macadr[6]; |
Попытаемся установить режим точки доступа, если не получится, то выйдем из функции со статусом false
1 2 3 4 5 6 |
uint8 macadr[6]; if(!wifi_set_mode(SOFTAP_MODE)) { os_printf("Failed to enable Access Point mode!\n"); return false; } |
Объявим переменную типа указателя на структуру и выделим для такой переменной память
1 2 3 |
return false; } struct softap_config *config = (struct softap_config *)zalloc(sizeof(struct softap_config)); |
Вернёмся в функцию start_wifi_ap и получим MAC-адрес модуля, а затем запишем его в переменную
1 2 |
struct softap_config *config = (struct softap_config *)zalloc(sizeof(struct softap_config)); wifi_get_macaddr(SOFTAP_IF, macaddr); |
Запросим данные о состоянии точки доступа и сохраним их в переменную структуры
1 2 |
wifi_get_macaddr(SOFTAP_IF, macaddr); wifi_softap_get_config(config); |
Очистим память в данной переменной под имя точки доступа и запишем туда данное имя
1 2 3 |
wifi_softap_get_config(config); memset(config->ssid, 0, sizeof(config->ssid)); sprintf(config->ssid, WIFI_APSSID); |
Аналогично поступим и с паролем
1 2 3 |
sprintf(config->ssid, WIFI_APSSID); memset(config->password, 0, sizeof(config->password)); sprintf(config->password, WIFI_APPASSWORD); |
Проверим, что у нас включился режим точки доступа, и если это так, то сначала выведем соответствующее сообщение в терминальную программу
1 2 3 4 5 |
sprintf(config->password, WIFI_APPASSWORD); if (wifi_get_opmode() == SOFTAP_MODE) { os_printf("SOFTAP_MODE\n"); } |
Не выходя из тела данного условия, проинициализируем также номер канала, на котором будет работать наша точка доступа, режим шифрования, максимальное количество подключаемых станций, а также режим видимости, и затем запишем наши настройки в модуль с помощью специальной функции, передав ей нашу переменную типа структуры в качестве параметра
1 2 3 4 5 6 |
os_printf("SOFTAP_MODE\n"); config->authmode = AUTH_WPA_WPA2_PSK; config->channel = 7; config->max_connection = 255; config->ssid_hidden = 0; wifi_softap_set_config(config); |
Выйдем из условия и ещё раз убедимся, что у нас режим точки доступа и, если это так, то заберём конфигурацию опять в нашу переменную config
1 2 3 4 5 6 |
wifi_softap_set_config(config); } if (wifi_get_opmode() == SOFTAP_MODE) { wifi_softap_get_config(config); } |
Также в теле данного условия выведем наши настройки в терминальную программу
1 2 3 4 5 6 7 8 |
wifi_softap_get_config(config); os_printf("OPMODE: %u, SSID: %s, PASSWORD: %s, CHANNEL: %d, AUTHMODE: %d, MACADDRESS: %02x:%02x:%02x:%02x:%02x:%02x\n", wifi_get_opmode(), config->ssid, config->password, config->channel, config->authmode, macadr[0],macadr[1],macadr[2],macadr[3],macadr[4],macadr[5]); |
Выйдя из тела условия, освободим память, выделенную под переменную структуры
1 2 3 |
macaddress); } free(config); |
Включим полноправный режим без пониженного энергопотребления
1 2 |
free(config); wifi_set_sleep_type(NONE_SLEEP_T); |
Остановим DHCP-сервер
1 2 |
wifi_set_sleep_type(NONE_SLEEP_T); wifi_softap_dhcps_stop(); |
Занесём в переменную структуры ipinfo значения IP-адреса, шлюза и сетевой маски нашего DHCP-сервера
1 2 3 4 5 6 7 8 9 10 |
wifi_softap_dhcps_stop(); snprintf(ip_char, sizeof(ip_char), "%s", WIFI_AP_IP); ip = ipaddr_addr(ip_char); memcpy(&ipinfo.ip, &ip, 4); snprintf(ip_char, sizeof(ip_char), "%s", WIFI_AP_GW); ip = ipaddr_addr(ip_char); memcpy(&ipinfo.gw, &ip, 4); snprintf(ip_char, sizeof(ip_char), "%s", WIFI_AP_NETMASK); ip = ipaddr_addr(ip_char); memcpy(&ipinfo.netmask, &ip, 4); |
Сохраним всё это в модуль
1 2 |
memcpy(&ipinfo.netmask, &ip, 4); wifi_set_ip_info(SOFTAP_IF, &ipinfo); |
Аналогичным образом настроим пул адресов для станций
1 2 3 4 5 6 7 8 9 |
wifi_set_ip_info(SOFTAP_IF, &ipinfo); struct dhcps_lease dhcp_lease; snprintf(ip_char, sizeof(ip_char), "%s", WIFI_AP_IP_CLIENT_START); ip = ipaddr_addr(ip_char); memcpy(&dhcp_lease.start_ip, &ip, 4); snprintf(ip_char, sizeof(ip_char), "%s", WIFI_AP_IP_CLIENT_END); ip = ipaddr_addr(ip_char); memcpy(&dhcp_lease.end_ip, &ip, 4); wifi_softap_set_dhcps_lease(&dhcp_lease); |
Запустим DHCP-сервер, установим режим с максимальной скоростью передачи данных и вернём true
1 2 3 4 5 |
wifi_softap_set_dhcps_lease(&dhcp_lease); wifi_softap_dhcps_start(); if(wifi_get_phy_mode() != PHY_MODE_11N) wifi_set_phy_mode(PHY_MODE_11N); return true; |
Ниже функции stop_wifi_ap добавим аналогичную функцию остановки станции
1 2 3 4 5 6 7 8 9 10 11 12 13 |
//------------------------------------------------ bool ICACHE_FLASH_ATTR stop_wifi_station() { WIFI_MODE mode = wifi_get_opmode(); mode &= ~STATION_MODE; if(!wifi_set_mode(mode)) { os_printf("Failed to disable STA mode!\n"); return false; } return true; } //------------------------------------------------ |
Тело функции подобно телу предыдущей функции, только отключаем мы режим станции.
В функции инициализации удалим следующую строку
stop_wifi_ap();
Вместо неё остановим станцию
1 |
stop_wifi_station(); |
В файле main.c в функции user_init удалим вот эту строку
start_wifi_station(WIFI_CLIENTSSID, WIFI_CLIENTPASSWORD);
Вместо неё запустим режим точки доступа, не забыв предварительно добавить на данную функцию прототип в заголовочном файле
1 |
start_wifi_ap(WIFI_APSSID, WIFI_APPASSWORD); |
Соберём код, прошьём контроллер и попытаемся соединиться с нашей точкой доступа со смартфона
Светодиод загорелся
Также в терминальной программе мы видим, что станция с точкой доступа соединилась и количество станций теперь 1
Попробуем соединиться с точкой доступа с другого смартфона
Почему-то, независимо от настройки пула, адреса назначились начальные – 2 и 3. Ну это не страшно и некритично.
Светодиод продолжает светиться и количество станций теперь 2
Отсоединимся в одном сматрфоне, количество станций теперь 1
Отключим второй, количество соединений – 0 и светодиод не светится
Итак, на данном занятии нам удалось настроить наш модуль в режиме точки доступа, используя при этом операционную систему FreeRTOS.
Всем спасибо за внимание!
Предыдущий урок Программирование МК ESP8266 Следующий урок
Модуль ESP NodeMCU можно купить здесь: Модуль ESP NodeMCU
Различные модули ЕSP8266 можно приобрести здесь Модули ЕSP8266
Переходник USB to TTL можно приобрести здесь ftdi ft232rl
Многофункциональный переходник CJMCU FT232H USB к JTAG UART FIFO SPI I2C можно приобрести здесь ftdi ft232rl
Логический анализатор 16 каналов можно приобрести здесь
Смотреть ВИДЕОУРОК (нажмите на картинку)
Добавить комментарий