ESP32 - IOT应用

WIFI

ESP32 支持三种 Wi-Fi 模式:Station (STA)Access Point (AP)Station + Access Point (STA+AP)。每种模式都有其特定的应用场景和使用建议。下面将详细介绍这三种模式的异同点,并给出相应的使用建议。


1. Station (STA) 模式

定义
  • 在 Station 模式下,ESP32 作为客户端连接到现有的 Wi-Fi 网络(接入点)。它类似于手机或电脑连接到家庭路由器的方式。
特点
  • 功能:可以连接到现有的 Wi-Fi 网络,获取 IP 地址,访问互联网或其他网络资源。
  • 应用场景
    • 当你需要让 ESP32 连接到一个已有的 Wi-Fi 网络,并通过该网络进行数据传输时使用。
    • 例如,智能家居设备连接到家庭 Wi-Fi 网络以实现远程控制或数据上传。
优缺点
  • 优点
    • 可以利用现有 Wi-Fi 网络基础设施,无需额外配置。
    • 能够访问互联网,便于数据上传或与云端服务通信。
  • 缺点
    • 需要预先知道 SSID 和密码。
    • 如果没有可用的 Wi-Fi 网络,则无法连接到网络。
使用建议
  • 如果你的项目需要通过 Wi-Fi 网络与外界通信(如云服务器、其他设备等),则应选择 Station 模式。
  • 确保在代码中正确配置 SSID 和密码,并处理可能的断开重连逻辑。
wifi_config_t wifi_config = {
    .sta = {
    	//编译器优化了,所以可以将字符串赋值给数组类型
        .ssid = "your-SSID",
        .password = "your-PASSWORD",
        .threshold.authmode = WIFI_AUTH_WPA2_PSK,
    },
};

2. Access Point (AP) 模式

定义
  • 在 Access Point 模式下,ESP32 本身充当无线接入点,允许其他设备(如手机、电脑)直接连接到 ESP32 的 Wi-Fi 网络。
特点
  • 功能:创建一个独立的 Wi-Fi 网络,供其他设备连接。
  • 应用场景
    • 当你希望直接与 ESP32 设备交互而不需要外部 Wi-Fi 网络时使用。
    • 例如,在设备初始配置阶段,用户可以通过手机连接到 ESP32 的 AP,设置 Wi-Fi 凭证。
优缺点
  • 优点
    • 不依赖外部 Wi-Fi 网络,适用于临时或无网络环境下的设备配置。
    • 允许设备直接与 ESP32 通信,适合本地调试或配置。
  • 缺点
    • 不能直接访问互联网。
    • 通常仅用于短时间内的配置或调试,不适合长期运行。
使用建议
  • 使用 AP 模式进行设备初始化配置,尤其是在设备首次启动时需要输入 Wi-Fi 凭证的情况下。
  • 确保为 AP 设置一个唯一的 SSID 和强密码,避免与其他网络冲突。
wifi_config_t wifi_config = {
    .ap = {
        .ssid = "ESP32_AP",
        .password = "12345678",
        .authmode = WIFI_AUTH_WPA2_PSK,
        .max_connection = 4, // 最大连接数
        .ssid_hidden = 0, // 是否隐藏SSID
    },
};

3. Station + Access Point (STA+AP) 模式

定义
  • 在 STA+AP 模式下,ESP32 同时作为 Station 和 Access Point 工作。这意味着它可以连接到一个外部 Wi-Fi 网络,同时也可以被其他设备连接。
特点
  • 功能:既可以连接到外部 Wi-Fi 网络,又可以提供自己的 Wi-Fi 网络供其他设备连接。
  • 应用场景
    • 当你需要让 ESP32 同时连接到外部网络并允许其他设备直接与其通信时使用。
    • 例如,智能家居设备既需要连接到家庭 Wi-Fi 网络以实现远程控制,又需要允许本地设备直接连接进行配置或调试。
优缺点
  • 优点
    • 提供了更大的灵活性,既能够连接到外部网络,又能接受本地设备的直接连接。
    • 适合需要远程和本地交互的复杂应用场景。
  • 缺点
    • 增加了功耗和资源占用。
    • 实现较为复杂,需要注意管理两个网络接口之间的冲突。
使用建议
  • 在需要同时支持远程和本地交互的场景下使用 STA+AP 模式。
  • 注意合理分配资源,确保不会因为双模式运行导致性能下降或不稳定。
wifi_config_t wifi_config_sta = {
    .sta = {
        .ssid = "your-SSID",
        .password = "your-PASSWORD",
        .threshold.authmode = WIFI_AUTH_WPA2_PSK,
    },
};

wifi_config_t wifi_config_ap = {
    .ap = {
        .ssid = "ESP32_STA_AP",
        .password = "12345678",
        .authmode = WIFI_AUTH_WPA2_PSK,
        .max_connection = 4,
        .ssid_hidden = 0,
    },
};

// 启用 STA+AP 模式
esp_wifi_set_mode(WIFI_MODE_STA_AP);
esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config_sta);
esp_wifi_set_config(ESP_IF_WIFI_AP, &wifi_config_ap);

总结与对比

特性/模式Station (STA)Access Point (AP)Station + Access Point (STA+AP)
功能描述连接到已有 Wi-Fi 网络创建独立的 Wi-Fi 网络同时连接到外部网络并创建本地网络
应用场景数据上传、远程控制设备配置、调试远程和本地交互
是否需外部网络
资源占用较低中等较高
适用场景需要联网的 IoT 设备设备初次配置复杂应用,需兼顾远程和本地通信

使用建议

  1. Station (STA) 模式

    • 适用于大多数需要连接到外部 Wi-Fi 网络的 IoT 设备。
    • 确保在网络配置时提供正确的 SSID 和密码,并处理好断开重连机制。
  2. Access Point (AP) 模式

    • 主要用于设备的初次配置或调试阶段,让用户可以直接与设备通信。
    • 确保 AP 的 SSID 和密码简单易记,但也要保证一定的安全性。
  3. Station + Access Point (STA+AP) 模式

    • 适用于需要同时支持远程和本地交互的复杂应用场景。
    • 注意优化资源管理,避免因双模式运行导致的性能问题。

根据具体需求选择合适的 Wi-Fi 模式,可以使你的项目更加高效和稳定。

STA模式实现

#include <stdio.h>
#include <string.h>
#include "nvs_flash.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_err.h"

#define MY_SSID        "your ssid"
#define MY_PASSWORD    "your password"

#define MAX_RETRY_COUNT 5  // 最大重连次数

static int retry_count = 0;  // 重连计数器

/*
 * @brief 处理 Wi-Fi 断开连接事件的原因,并打印相关日志信息。
 *
 * 该函数解析 WIFI_EVENT_STA_DISCONNECTED 事件中的断开原因,
 * 并根据不同的原因打印详细的错误日志,帮助用户或开发者快速定位问题。
 *
 * @param event_data 事件数据指针,指向触发事件时传递的数据。
 *                   对于 WIFI_EVENT_STA_DISCONNECTED 事件,event_data 是一个 wifi_event_sta_disconnected_t 类型的结构体。
 */
void wifi_disconnected_reason(void* event_data)
{
    // 将 event_data 转换为 wifi_event_sta_disconnected_t 类型的指针
    wifi_event_sta_disconnected_t *disconnected_event = (wifi_event_sta_disconnected_t *)event_data;

    // 打印断开连接的原因编号(reason 字段)
    ESP_LOGE("sta", "Disconnected from AP. Reason: %d", disconnected_event->reason);

    // 判断断开原因是否为认证失败(例如密码错误)
    if (disconnected_event->reason == WIFI_REASON_AUTH_FAIL) {
        // 认证失败时打印错误日志,提示用户检查 SSID 和密码
        ESP_LOGE("sta", "Authentication failed. Check SSID and password.");
    }
    // 判断断开原因是否为未找到目标接入点(AP)
    else if (disconnected_event->reason == WIFI_REASON_NO_AP_FOUND) {
        // 未找到 AP 时打印错误日志,提示用户检查 SSID 是否正确
        ESP_LOGE("sta", "AP not found. Check SSID.");
    }
    // 如果断开原因是未知原因,则打印具体的断开原因编号
    else {
        ESP_LOGE("sta", "Disconnected due to unknown reason: %d", disconnected_event->reason);
    }
}

void wifi_event_handle(void* event_handler_arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
{
    if(event_base == WIFI_EVENT)
    {
        switch (event_id)
        {
        case WIFI_EVENT_STA_START:      //WIFI以STA模式启动后触发此事件//启动STA工作模式
            retry_count = 0;            // 启动时重置重连计数器        
            esp_wifi_connect();         //启动WIFI连接
            break;
        case WIFI_EVENT_STA_CONNECTED:  //WIFI连上路由器后,触发此事件
            retry_count = 0;            // 连接上wifi后重置重连计数器
            ESP_LOGI("sta", "esp32 connetced to ap!");
            break;
        case WIFI_EVENT_STA_DISCONNECTED:   //WIFI从路由器断开连接后触发此事件
            wifi_disconnected_reason(event_data);
            if (retry_count < MAX_RETRY_COUNT) 
            {
                retry_count++;
                vTaskDelay(pdMS_TO_TICKS(2000));  // 延迟 2 秒后重连
                esp_wifi_connect();
                ESP_LOGI("sta", "esp32 connect the ap failed! retry %d/%d", retry_count, MAX_RETRY_COUNT);
            } 
            else 
            {
                ESP_LOGE("sta", "Max retry count reached. Connection failed.");
            }
            break;
        default:
            break;
        }
    }
    else if(event_base == IP_EVENT)                  //IP相关事件
    {
        switch (event_id)
        {
        case IP_EVENT_STA_GOT_IP:           //只有获取到路由器分配的IP,才认为是连上了路由器
            ESP_LOGI("sta", "esp32 get ip address");
            break;
        default:
            break;
        }
    }
}

void app_main(void)
{
    ESP_ERROR_CHECK(nvs_flash_init());  // 初始化 NVS 存储(用于保存 Wi-Fi 配置等数据)
    ESP_ERROR_CHECK(esp_netif_init());  //用于初始化tcp/ip协议栈
    ESP_ERROR_CHECK(esp_event_loop_create_default());       //创建一个默认系统事件调度循环,之后可以注册回调函数来处理系统的一些事件
    esp_netif_create_default_wifi_sta();    //使用默认配置创建STA对象

    //初始化WIFI
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();    // 使用默认配置初始化 Wi-Fi
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));
    
    //注册事件
    ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, wifi_event_handle, NULL)); // 注册 Wi-Fi 事件处理函数
    ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, wifi_event_handle, NULL));// 注册 IP 事件处理函数

    //WIFI配置
    wifi_config_t wifi_config = {
        .sta.threshold.authmode = WIFI_AUTH_WPA2_PSK,//设置加密方式
        .sta.pmf_cfg.capable = true, //是否使用保护管理帧
        .sta.pmf_cfg.required = false, //是否之和有保护管理帧功能的设备通信
    };
    /* 不直接在结构体内对ssid和password赋值的原因是:
    wifi_config.sta.ssid和wifi_config.sta.password是固定长度的数组类型,而不是指针类型,C 语言不允许直接将字符串赋值给数组*/
    memset(wifi_config.sta.ssid, 0, sizeof(wifi_config.sta.ssid));
    memcpy(wifi_config.sta.ssid, MY_SSID, strlen(MY_SSID));
    memset(wifi_config.sta.password, 0, sizeof(wifi_config.sta.password));
    memcpy(wifi_config.sta.password, MY_PASSWORD, strlen(MY_PASSWORD));

    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));         //设置工作模式为STA
    ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));   //设置wifi配置
    ESP_ERROR_CHECK(esp_wifi_start());                         //启动WIFI

    ESP_LOGI("sta", "wifi_init_sta finished!");

    while(1)
    {
        vTaskDelay(pdMS_TO_TICKS(500));
    }
    ESP_LOGI("err", "project faild!");
    return;
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值