3·ESP32 您所在的位置:网站首页 扫描wifi的软件 3·ESP32

3·ESP32

2024-07-17 09:35| 来源: 网络整理| 查看: 265

        对于物联网实战来说,wifi模块当属重中之重。今天有了学习的新思路,既然是入门学习,从整体入手,开始主要是按照模块化的角度去学习,从整体上认识每个模块的功能,然后在回顾部分再去梳理一遍流程、每个API调用的原理以及相关函数的知识。

       

目录

level1:从wifi scan模式入门wifi模块

最简单的方式实现wifi扫描

加入回调,采用扫描的方式

level2:打开热点&连接路由器

ap模式

sta模式

level3:一键智能配置smart config

例程使用

实现原理

回顾——esp32的WIFI实现流程

主程序

回调函数

流程图

小结 

        学习ESP32,少了wifi怎么行?这一篇先从扫描wifi信息开始光速入门,再一步步学习如何配置和连接wifi,到如何打开热点模式,最后进阶多种多样的配网方式,好好研究一下wifi板块的功能。

        前两篇中涉及到的一些概念和用法可能对学习WIFI以及理解一些函数的用法有帮助,也记录了我过程中esp32学习方法的变化,链接指路→从点灯开始,学习定时器和PWM控制和从按键入手,学习中断回调以及freertos的线程概念

        从本章起,我也将采用从模块化分析到API接口的方式,从整体到局部,去学习ESP32的WIFI功能(注意:ESP32只支持2.4GHz WiFi,还不支持5GHz WiFi)

level1:从wifi scan模式入门wifi模块 最简单的方式实现wifi扫描

       先从扫描wifi开始认识ESP32的wifi模块,这一部分实现起来还是比较容易的,调用的接口也不多,源码以及模块化总结如下。

#include #include "freertos/FreeRTOS.h" #include "freertos/event_groups.h" #include "esp_wifi.h" #include "esp_log.h" #include "esp_event.h" #include "nvs_flash.h" #define DEFAULT_SCAN_LIST_SIZE 16 static const char *TAG = "scan"; void wifi_scan_result(void) { uint16_t number = DEFAULT_SCAN_LIST_SIZE; uint16_t ap_count = 0; wifi_ap_record_t ap_info[DEFAULT_SCAN_LIST_SIZE]; memset(ap_info, 0, sizeof(ap_info)); esp_wifi_scan_get_ap_records(&number, ap_info); esp_wifi_scan_get_ap_num(&ap_count); ESP_LOGI(TAG, "Total APs scanned = %d", ap_count); for (int i = 0; (i < DEFAULT_SCAN_LIST_SIZE) && (i < ap_count); i++) { ESP_LOGI(TAG, "SSID \t\t%s", ap_info[i].ssid); ESP_LOGI(TAG, "RSSI \t\t%d", ap_info[i].rssi); ESP_LOGI(TAG, "Channel \t\t%d\n", ap_info[i].primary); } } void app_main(void) { esp_err_t ret = nvs_flash_init(); if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { nvs_flash_erase(); ret = nvs_flash_init(); } esp_netif_init(); esp_event_loop_create_default(); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); esp_wifi_init(&cfg); esp_wifi_set_mode(WIFI_MODE_STA); esp_wifi_start(); esp_wifi_scan_start(NULL, true); wifi_scan_result(); }

 运行结果如下: 

加入回调,采用扫描的方式

        在按键模块我就写过,将想要实现功能函数放到主函数中,虽然很好理解,除非只实现几个功能,不然对于一个复杂事件来说还是太笨了,功能实现的过程和顺序都会相互干扰。所以我们需要更进一步加入中断的学习。

         加入中断其实也比较容易实现,在前两篇文章中我有详细分析和讨论过,所以这里就不展开叙述了,源码以及模块化注释如下:

#include #include "freertos/FreeRTOS.h" #include "freertos/event_groups.h" #include "esp_wifi.h" #include "esp_log.h" #include "esp_event.h" #include "nvs_flash.h" #define DEFAULT_SCAN_LIST_SIZE 16 static const char *TAG = "scan"; uint16_t number = DEFAULT_SCAN_LIST_SIZE; uint16_t ap_count = 0; wifi_ap_record_t ap_info[DEFAULT_SCAN_LIST_SIZE]; void wifi_scan_result(void) { memset(ap_info, 0, sizeof(ap_info)); esp_wifi_scan_get_ap_records(&number, ap_info); esp_wifi_scan_get_ap_num(&ap_count); ESP_LOGI(TAG, "Total APs scanned = %d", ap_count); for (int i = 0; (i < DEFAULT_SCAN_LIST_SIZE) && (i < ap_count); i++) { ESP_LOGI(TAG, "SSID \t\t%s", ap_info[i].ssid); ESP_LOGI(TAG, "RSSI \t\t%d", ap_info[i].rssi); ESP_LOGI(TAG, "Channel \t\t%d\n", ap_info[i].primary); } } static void event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) { if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_SCAN_DONE) { wifi_event_sta_scan_done_t* scan_done = (wifi_event_sta_scan_done_t*) event_data; ESP_LOGE(TAG, "wifi scan done status = %d, number = %d", scan_done->status, scan_done->number); wifi_scan_result(); } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data; ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip)); } } void app_main(void) { esp_err_t ret = nvs_flash_init(); if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { nvs_flash_erase(); ret = nvs_flash_init(); } esp_netif_init(); esp_event_loop_create_default(); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); esp_wifi_init(&cfg); esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL, NULL); esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL, NULL); esp_wifi_set_mode(WIFI_MODE_STA); esp_wifi_start(); esp_wifi_scan_start(NULL, false); }

level2:打开热点&连接路由器

        level1可以算是小试牛刀,有了WiFi的相关概念之后,我们可以更近一步,学习如何配置wifi模块,更近一步打开物联网的大门。

        sta模式和ap模式ESP官网都给了例程,上手就可以直接用,所以这两部分的代码我就直接引用了,只需要在vscode中,contorl+shift+p,输入example,在里面找到wifi模块的get-start,选择创建文件夹,然后编译烧录就可以看到结果了~

ap模式

       上面的SCAN部分理解透了,AP部分直接光速拿下,由于是从被动扫描模式切换到了主动发射模式,所以需要自己DIY一些部分,总的来看还是非常好理解的,烧录好后,可以打开手机连接ESP的热点(虽然没有网络)。

sta模式

        sta模式其实和ap模式实现过程大体相似,只是模式选择和个别调用的接口不同,但是因为需要考虑的事件和情况更多,所以代码量会比ap模式多一些,在官方的例程中,可以直接调用和烧录,因为显示范围问题,我把截图分成了两部分。

        这里引入了事件的概念,下面有个方框没有备注上,是对上面事件信号的调用和监测,可以和上面那张图片对比着看。

         经过了按键和点灯的学习,我们可以举一反三,比较轻松的去学习WiFi环节的配置,但是想要联网,我们必须要在源代码中就要设置好网络的ID和密码,这样多少还是比较麻烦的。那么怎么样去做到可以实现随时随地就更换网络呢?esp提供了一个方案——smart config,我们只需要连接手机,就可以随时更换所想要的WiFi和密码。

level3:一键智能配置smart config 例程使用

        samrt config官方也给出了例程,我们只需要按照上述的方法即可创立例程。

        在使用这个例程之前,我们需要先进行一个APP的下载,链接指路→手机端的网络配置软件,会跳转到github,选择.apk的文件下载,然后我们只需要进行配置就好了。 

         

注意:ESP32只支持2.4GHz WiFi,还不支持5GHz WiFi,如果家里的网络多次配置失败的话,可以使用手机的热点,更容易成功。

实现原理

一键配网连接过程:

ESP32-C3 开启混杂模式监听所有网络数据包。手机连上 WiFi,开启 APP 软件,输入手机所在 WiFi 密码,请求配网。手机通过广播、组播循环发送路由 SSID 和 PASSWD 数据包,按一定格式加密。ESP32 通过 UDP 包(长度)获取配置信息捕捉到路由 SSID 和 PASSWD,连接路由器。

        Smart Config 采用的是 UDP 广播模式 (UDP 接收 IP 地址是 255.255.255.255) 。 WiFi 设备先 scan 环境下 AP, 得到 AP 的相关信息,如工作的 channel。然后配置 WiFi 芯片工作 scan 到的 channel 上去接收 UDP 包,如果没有接收到,继续配置工作在另外的 channel 上,如此循环,直到收到 UDP 包为止。

        这种办法的致命缺点是成功率只有 70%,而且有些路由器不支持;但优点是能一键完成配网

回顾——esp32的WIFI实现流程 主程序 nvs_flash_init  初始化默认NVS分区esp_netif_init  初始化底层TCP/IP堆栈esp_event_1oop_create_default  创建默认事件循环esp_netif_create_default_wifi_sta  使用默认WiFi Station配置创建esp_netif对象,将netif连 接到WiFi并注册默认WiFi处理程序 esp_wifi_init,为WiFi驱动初始化WiFi分配资源,如WiFi控制结构、RX/TX缓冲区、WiFi NVS结构等,这个WiFi也启动WiFi任务。必须先调用此API,然后才能调用所有其他WiFiAPIesp_event_handler_instance_register  监听WIFI_EVENTWiFi任意事件,触发事件后,进入回 调函数esp_event_handler_instance_register  监听IP_EVENT从连接的AP获得IP的事件,触发事件 后,进入回调函数esp_event_handler_instance_register  监听SC_EVENT从SmartConfig任意事件,触发事件后, 进入回调函数esp_wifi_set_mode  设置WiFi工作模式为station、soft-AP或station+soft-AP,默认模式为soft- AP模式。本程序设置为station esp_wifi_start  根据配置,启动WiFi 回调函数 WIFI_EVENT_STA_START  WiFi station模式启动时 【创建smartconfig_example_task 线程,开始SmartConfig】WIFI_EVENT_STA_DISCONNECTED WiFi station模式失去连接。 【清除CONNECTED_BIT标志位】IP_EVENT_STA_GOT_IP  WiFi station模式从连接的AP那获得IP 【设置CONNECTED_BIT标志位】SC_EVENT_SCAN_DONE SmartConfig扫描AP列表结束SC_EVENT_FOUND_CHANNEL  SmartConfig 从目标AP找到频道SC_EVENT_GOT_SSID_PSWD  SmartConfig 获得WiFi信息(SSID和密码)时, 【解析出WiFi的SSID和密码】【esp_wifi_disconnect断开当前WiFi连接】【esp_wifi_set_config WiFI配置,设置WIFI_IF_STA模式,设置WiFi的SSID和密码】【esp_wifi_connect WiFi连接】SC_EVENT_SEND_ACK_DONE  SmartConfig 给App发送完成ACK 【设置ESPTOUCH_DONE_BIT标志位】   流程图:

 

小结 

         WiFi部分是esp的优势所在,也是其在今天的物联网市场如此受欢迎的原因。官方给的例程和RAINMAKER以及ESP TOUCH的接口都非常方便,我们可以很轻易的在它的基础上拓展自己需要的功能,很多接口都可以直接调用,大大简化了我们需要的开发时间和步骤。

        还有一些部分因为时间安排原因,暂时没有展开写,比如像蓝牙部分、NVS实现过程,本地控制...但是从实战角度出发,这三篇穿插讲到的这些内容已经足够去让我们做一个比较小的实验demo了,还没有写到的内容会不断完善。

        当然,从实战的角度出发,光实现一个WiFi的连接,只是搭好了一座桥,怎么样让人们在桥上有秩序地行走,也就是数据如何在MCU和互联网之间传输信息,还需要更进一步。下一章咱们聊聊如何从本地控制到接入rainmaker,实现一个小的物联网控制模型。

        



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

      专题文章
        CopyRight 2018-2019 实验室设备网 版权所有