ESP32 连接 WiFi

本文介绍了使用ESP32-WROOM-32连接WiFi进行GET请求和NTP时间同步的实践。通过Arduino IDE配置开发环境,结合第三方库和官方API实现WiFi连接和时间同步功能,简化了原本需要外接实时时钟模块的需求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

(如有更新,见原文:https://blog.iyatt.com/?p=11891

1 前言

ESP32 买了快三个月了,当时用 Arduino IDE 配置好了开发环境,之后就开始吃灰。最近想起来,打算做个可以联网对时的时钟,所以开始学习探索了。

2 测试环境

2.1 硬件

  • ESP32-WROOM-32(只支持 2.4GHz 频段 WiFi)

2.2 软件

  • Arduino IDE 2.2.1
  • esp32 2.0.14(开发板)
  • NTP 1.7.0(NTP 时间同步):https://github.com/sstaub/NTP

3 探索

3.1 WiFi 连接

/**
 * WiFi 连接程序
 * 启动后自动尝试连接设置的 WiFi
 * 如果连接失败,最多尝试 20 次
 * 连接成功后可以短接 GND 和 D15 引脚使 WiFi 连接断开
 */
#include <WiFi.h>

const char* ssid = "IYATT-yx_2.4GHz"; // WiFi 名
const char* password = "esp32test"; // 密码

int pin = 15; // D15 引脚用于控制断开 WiFi
int state = false; // 引脚状态

void setup()
{
    Serial.begin(115200);
    delay(500);

    pinMode(pin, INPUT_PULLUP);

    Serial.println();
    Serial.print("[WiFi] 尝试连接到 ");
    Serial.println(ssid);

    WiFi.begin(ssid, password);

    // 失败尝试重连
    int try_delay = 1000; // 尝试间隔延时
    int number_of_tries = 20; // 尝试次数

    while (true)
    {
        // 检查 WiFi 连接状态
        switch(WiFi.status())
        {
            case WL_NO_SSID_AVAIL:
            {
                Serial.println("[WiFi] 没有找到 SSID");
                break;
            }
            case WL_CONNECT_FAILED:
            {
                Serial.print("[WiFi] 失败 - WiFi 未连接! 原因:");
                return;
            }
            case WL_CONNECTION_LOST:
            {
                Serial.println("[WiFi] 连接丢失");
                break;
            }
            case WL_SCAN_COMPLETED:
            {
                Serial.println("[WiFi] 扫描已完成");
                break;
            }
            case WL_CONNECTED:
            {
                Serial.println("[WiFi] 已连接!");
                Serial.print("[WiFi] IP 地址:");
                Serial.println(WiFi.localIP());
                return;
            }
            case WL_DISCONNECTED:
            {
                Serial.println("[WiFi] 连接已断开");
                break;
            }
            default:
            {
                Serial.print("[WiFi] WiFi 状态:");
                Serial.println(WiFi.status());
                break;
            }
        }
        delay(try_delay);

        if(number_of_tries <= 0)
        {
            Serial.print("[WiFi] 连接 WiFi 失败!");
            WiFi.disconnect();
            return;
        }
        else
        {
            --number_of_tries;
        }
    }
}

void loop()
{
    state = digitalRead(pin);

    if (state == LOW)
    {
        Serial.println("[WiFi] 正在断开连接!");
        if(WiFi.disconnect(true, false))
        {
        Serial.println("[WiFi] 已断开连接");
        }
        delay(1000);
    }
}

file

file

3.2 GET 请求

这里方便测试我就使用电脑上的 Python 运行 http 模块作为服务器端,下面是一个简易的 html 网页

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>hello</title>
</head>
<body>
    <h1>你好,世界!</h1>
</body>
</html>

命名保存为 index.html 文件

然后在这个文件所在的路径运行 http 服务(8080 端口)

python -m http.server 8080

file

同一局域网下的手机可以访问这个网页(电脑IP:8080 ),服务器这边就没啥问题了
file

然后是 ESP32 的代码

/**
 * GET 请求实现
 */
#include <WiFi.h>
#include <WiFiMulti.h>

WiFiMulti WiFiMulti; // 创建一个多 WiFi 实例,可以连接多个 WiFi

void setup()
{
    Serial.begin(115200);
    delay(10);

    WiFiMulti.addAP("IYATT-yx_2.4GHz", "esp32test"); // 首先连接到一个 WiFi,分别是名字和密码

    Serial.println();
    Serial.println();
    Serial.print("等待 WiFi 连接...... ");

    while(WiFiMulti.run() != WL_CONNECTED) // 连接失败时重试
    {
        Serial.print(".");
        delay(1000);
    }

    Serial.println("");
    Serial.println("WiFi 已连接");
    Serial.println("IP 地址: ");
    Serial.println(WiFi.localIP());

    delay(500);
}


void loop()
{
    const char * host = "192.168.1.249"; //  服务器地址
    const uint16_t port = 8080; // 服务器端口

    Serial.print("正在连接到 ");
    Serial.println(host);

    WiFiClient client; // 用于创建 TCP 连接

    if (!client.connect(host, port)) // 连接服务器
    {
        Serial.println("连接失败!");
        Serial.println("5 秒后重试......");
        delay(5000);
        return;
    }

    client.print("GET /index.html HTTP/1.1\n\n"); // 发送 GET 请求,获取 index.html 文件

    int maxloops = 0;

    // 等待服务器返回数据
    while (!client.available() && maxloops < 1000)
    {
        ++maxloops;
        delay(1);
    }

    if (client.available() > 0) // 如果有数据返回
    {
        String response = client.readString();
        Serial.println("服务器返回的内容:");
        Serial.println(response);
    }
    else
    {
        Serial.println("连接超时");
    }

    Serial.println("正在关闭连接。");
    client.stop();

    Serial.println("等待 5 秒后重试......");
    delay(5000);
}

运行后可以看到串口输出了请求到的内容
file

Python 这边也会显示 ESP32 的请求记录
file

3.3 NTP 时间同步

3.3.1 第三方库

源码

#include <WiFi.h>
#include <NTP.h>

const char * ssid = "IYATT-yx_2.4GHz";
const char * password = "esp32test";

WiFiUDP wifi_udp;
NTP ntp(wifi_udp);

void setup()
{
    const char * ntp_server = "ntp.aliyun.com"; // NTP 服务器,默认的感觉应该不如国内的稳定

    Serial.begin(115200);
    delay(100);

    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED)
    {
        Serial.println("正在尝试连接 WiFi ......");
        delay(1000);
    }
    Serial.println("WiFi 已连接");

    ntp.isDST(false); // 禁止夏令时
    ntp.timeZone(8); // 北京时间
    ntp.begin(ntp_server);
    Serial.println("开始同步时间:");
}

void loop()
{
    ntp.update();
    Serial.println(ntp.formattedTime("%Y.%m.%d %A %T")); // 格式化规则同 strftime
    delay(1000);
}

file

3.3.2 官方 API

前面探索 NTP 时间同步的时候不知道 ESP32 内部有系统时间,也不知道官方有提供时间同步功能。本来的计划是 ESP32 还要外接一个实时时钟模块,结果在查阅资料的时候发现官方文档说内部有系统时间,那就大大地简化了。不过因为没有独立电源供电,一旦外接电源断开时钟就会丢失,而实时时钟模块自身是可以使用外部电池供电维持走时。

#include <WiFi.h>

void setup()
{
    const char * ssid = "IYATT-yx_2.4GHz";
    const char * password = "esp32test";
    const char * ntp_server = "ntp.aliyun.com"; // NTP 服务器
    const int gmt_offset = 8 * 60 * 60; // UTC/GMT+8,东 8 时区偏移量,单位秒
    const int daylight_offset = 0; // 夏令时偏移值,单位秒

    Serial.begin(115200);
    delay(1000);

    // 设置时区
    setenv("TZ", "CST-8", 1); // TZ 是时区环境变量,CST-8 是中国标准时间,1 表示覆盖旧值
    tzset(); // 作用时区变量

    // 连接 WiFi
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED)
    {
        Serial.println("正在尝试连接 WiFi ......");
        delay(1000);
    }
    Serial.println("WiFi 已连接");
    delay(1000);

    // 同步时间
    configTime(gmt_offset, daylight_offset, ntp_server);
    Serial.println("完成时间同步");
    delay(2000);
}

void loop()
{
    time_t now = 0;
    struct tm time_info;
    char strftime_buf[64] = {'\0'};

    time(&now);
    localtime_r(&now, &time_info);
    strftime(strftime_buf, sizeof(strftime_buf), "%Y.%m.%d %A %T", &time_info);
    Serial.println(strftime_buf);
    delay(1000);
}

file

### ESP32连接WiFi的示例代码及配置方法 以下是基于不同开发环境下的ESP32 WiFi连接示例及其配置说明。 #### 使用Arduino框架实现ESP32 WiFi连接 以下是一个简单的Arduino代码示例,用于将ESP32设备连接到Wi-Fi网络: ```cpp #include <WiFi.h> const char* ssid = "Your_SSID"; // 替换为您的Wi-Fi名称 const char* password = "Your_PASSWORD"; // 替换为您的Wi-Fi密码 void setup() { Serial.begin(115200); WiFi.begin(ssid, password); // 开始尝试连接指定SSID和密码 while (WiFi.status() != WL_CONNECTED) { // 循环直到成功连接 delay(1000); Serial.println("Connecting to WiFi..."); } Serial.println("Connected to the WiFi network"); Serial.print("IP Address: "); Serial.println(WiFi.localIP()); // 打印分配给ESP32的本地IP地址 } void loop() { } ``` 上述代码通过`WiFi.begin()`函数实现了基本的Wi-Fi连接功能[^1]。需要注意的是,在实际部署前应确认目标路由器的工作频段是否兼容ESP32(仅支持2.4GHz),否则可能导致无法正常连接的情况发生[^3]。 #### 基于ESP-IDF框架实现WiFi STA模式连接 对于更底层控制需求的应用场景,推荐采用Espressif提供的ESP-IDF工具链来完成相应操作。下面展示了一个典型的初始化过程片段: ```c #include "esp_wifi.h" #include "esp_event.h" 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_STA_START){ esp_wifi_connect(); }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; printf("Got IP:%s\n",inet_ntoa(event->ip_info.ip)); } } void wifi_init_sta(){ tcpip_adapter_init(); ESP_ERROR_CHECK(esp_event_loop_create_default()); wifi_init_config_t cfg={}; cfg.nvs_enable=false;cfg.modem_sleep_disable=true; ESP_ERROR_CHECK(esp_wifi_init(&cfg)); ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT,-1,event_handler,NULL)); ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT,IP_EVENT_STA_GOT_IP,event_handler,NULL)); wifi_config_t wifi_config={ .sta={ .ssid="your_ssid", .password="your_password" }, }; ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA,&wifi_config)); ESP_ERROR_CHECK(esp_wifi_start()); } ``` 此部分代码定义了事件处理程序以及具体的无线网卡参数设置逻辑,并最终调用了`esp_wifi_start()`启动服务[^2]。 #### MicroPython环境下ESP32 Wi-Fi连接实例 如果倾向于脚本化快速原型设计,则可考虑运用MicroPython简化流程如下所示: ```python import network wlan=network.WLAN(network.STA_IF) wlan.active(True) if not wlan.isconnected(): print('connecting to network...') wlan.connect('your_ssid','your_password') while not wlan.isconnected(): pass print('Network config:', wlan.ifconfig()) ``` 该脚本同样完成了从激活接口至获取当前网络状态的一系列动作。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IYATT yx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值