赞
踩
对于物联网实战来说,wifi模块当属重中之重。今天有了学习的新思路,既然是入门学习,从整体入手,开始主要是按照模块化的角度去学习,从整体上认识每个模块的功能,然后在回顾部分再去梳理一遍流程、每个API调用的原理以及相关函数的知识。
目录
学习ESP32,少了wifi怎么行?这一篇先从扫描wifi信息开始光速入门,再一步步学习如何配置和连接wifi,到如何打开热点模式,最后进阶多种多样的配网方式,好好研究一下wifi板块的功能。
前两篇中涉及到的一些概念和用法可能对学习WIFI以及理解一些函数的用法有帮助,也记录了我过程中esp32学习方法的变化,链接指路→从点灯开始,学习定时器和PWM控制和从按键入手,学习中断回调以及freertos的线程概念
从本章起,我也将采用从模块化分析到API接口的方式,从整体到局部,去学习ESP32的WIFI功能(注意:ESP32只支持2.4GHz WiFi,还不支持5GHz WiFi)
先从扫描wifi开始认识ESP32的wifi模块,这一部分实现起来还是比较容易的,调用的接口也不多,源码以及模块化总结如下。
- #include <string.h>
- #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 <string.h>
- #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);
- }
level1可以算是小试牛刀,有了WiFi的相关概念之后,我们可以更近一步,学习如何配置wifi模块,更近一步打开物联网的大门。
sta模式和ap模式ESP官网都给了例程,上手就可以直接用,所以这两部分的代码我就直接引用了,只需要在vscode中,contorl+shift+p,输入example,在里面找到wifi模块的get-start,选择创建文件夹,然后编译烧录就可以看到结果了~
上面的SCAN部分理解透了,AP部分直接光速拿下,由于是从被动扫描模式切换到了主动发射模式,所以需要自己DIY一些部分,总的来看还是非常好理解的,烧录好后,可以打开手机连接ESP的热点(虽然没有网络)。
sta模式其实和ap模式实现过程大体相似,只是模式选择和个别调用的接口不同,但是因为需要考虑的事件和情况更多,所以代码量会比ap模式多一些,在官方的例程中,可以直接调用和烧录,因为显示范围问题,我把截图分成了两部分。
这里引入了事件的概念,下面有个方框没有备注上,是对上面事件信号的调用和监测,可以和上面那张图片对比着看。
经过了按键和点灯的学习,我们可以举一反三,比较轻松的去学习WiFi环节的配置,但是想要联网,我们必须要在源代码中就要设置好网络的ID和密码,这样多少还是比较麻烦的。那么怎么样去做到可以实现随时随地就更换网络呢?esp提供了一个方案——smart config,我们只需要连接手机,就可以随时更换所想要的WiFi和密码。
samrt config官方也给出了例程,我们只需要按照上述的方法即可创立例程。
在使用这个例程之前,我们需要先进行一个APP的下载,链接指路→手机端的网络配置软件,会跳转到github,选择.apk的文件下载,然后我们只需要进行配置就好了。
注意:ESP32只支持2.4GHz WiFi,还不支持5GHz WiFi,如果家里的网络多次配置失败的话,可以使用手机的热点,更容易成功。
一键配网连接过程:
Smart Config 采用的是 UDP 广播模式 (UDP 接收 IP 地址是 255.255.255.255) 。 WiFi 设备先 scan 环境下 AP, 得到 AP 的相关信息,如工作的 channel。然后配置 WiFi 芯片工作 scan 到的 channel 上去接收 UDP 包,如果没有接收到,继续配置工作在另外的 channel 上,如此循环,直到收到 UDP 包为止。
这种办法的致命缺点是成功率只有 70%,而且有些路由器不支持;但优点是能一键完成配网
WiFi部分是esp的优势所在,也是其在今天的物联网市场如此受欢迎的原因。官方给的例程和RAINMAKER以及ESP TOUCH的接口都非常方便,我们可以很轻易的在它的基础上拓展自己需要的功能,很多接口都可以直接调用,大大简化了我们需要的开发时间和步骤。
还有一些部分因为时间安排原因,暂时没有展开写,比如像蓝牙部分、NVS实现过程,本地控制...但是从实战角度出发,这三篇穿插讲到的这些内容已经足够去让我们做一个比较小的实验demo了,还没有写到的内容会不断完善。
当然,从实战的角度出发,光实现一个WiFi的连接,只是搭好了一座桥,怎么样让人们在桥上有秩序地行走,也就是数据如何在MCU和互联网之间传输信息,还需要更进一步。下一章咱们聊聊如何从本地控制到接入rainmaker,实现一个小的物联网控制模型。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。