ESP32的Wi-Fi和蓝牙到底怎么用?一个实战项目带你搞懂连接、配网和数据传输(附完整代码)
ESP32无线通信实战:从配网到数据传输的完整解决方案
在物联网设备开发中,ESP32凭借其出色的无线通信能力成为众多开发者的首选。这款芯片不仅价格亲民,更重要的是集成了Wi-Fi和蓝牙功能,让智能设备开发变得前所未有的简单。本文将带你深入ESP32的无线通信核心功能,通过一个完整的"无线环境监测器"项目,掌握Wi-Fi连接、蓝牙数据传输等关键技术。
1. 项目概述与环境搭建
我们的目标是构建一个能够实时监测环境温湿度并通过无线方式传输数据的设备。这个项目将涵盖ESP32最核心的两种无线通信方式:Wi-Fi用于连接网络上传数据,蓝牙用于近距离与手机交互。
1.1 硬件准备
需要准备以下组件:
- ESP32开发板(推荐使用ESP32-WROOM-32)
- DHT22温湿度传感器
- 面包板和连接线
- 微型USB数据线
接线示意图:
| ESP32引脚 | 传感器引脚 |
|---|---|
| 3.3V | VCC |
| GND | GND |
| GPIO4 | DATA |
1.2 开发环境配置
- 安装Arduino IDE(1.8.x或更高版本)
- 在首选项中添加ESP32开发板管理URL:
https://dl.espressif.com/dl/package_esp32_index.json - 通过开发板管理器安装"esp32"平台
- 安装必要的库:
- WiFi.h(内置)
- BluetoothSerial.h(内置)
- DHT sensor library(通过库管理器安装)
提示:首次使用ESP32时,可能需要安装CP210x或CH340驱动程序,具体取决于开发板使用的USB转串口芯片。
2. Wi-Fi连接与配网实现
ESP32支持两种基本的Wi-Fi工作模式:STA(站点)模式和AP(接入点)模式。在我们的项目中,主要使用STA模式连接现有无线网络。
2.1 基础Wi-Fi连接
以下是建立Wi-Fi连接的基本代码框架:
#include <WiFi.h> const char* ssid = "your_SSID"; const char* password = "your_PASSWORD"; void setup() { Serial.begin(115200); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); } void loop() { // 主程序代码 }这种方法虽然简单,但存在明显缺点:SSID和密码硬编码在程序中,更换网络时需要重新烧录固件。下面我们介绍更实用的配网方案。
2.2 智能配网方案
2.2.1 Web配网
通过创建一个配置页面,让用户可以通过手机或电脑浏览器来配置Wi-Fi信息:
#include <WiFi.h> #include <WebServer.h> WebServer server(80); void handleRoot() { String html = "<form action='/config' method='POST'>"; html += "SSID: <input type='text' name='ssid'><br>"; html += "Password: <input type='password' name='password'><br>"; html += "<input type='submit' value='Connect'>"; html += "</form>"; server.send(200, "text/html", html); } void handleConfig() { String ssid = server.arg("ssid"); String password = server.arg("password"); // 保存到EEPROM或文件系统 // 然后尝试连接 server.send(200, "text/plain", "Connecting..."); } void setup() { WiFi.softAP("ESP32-Config"); server.on("/", handleRoot); server.on("/config", handleConfig); server.begin(); }2.2.2 SmartConfig技术
SmartConfig是乐鑫提供的一种便捷配网方式,允许通过手机APP发送Wi-Fi凭证:
#include <WiFi.h> void setup() { Serial.begin(115200); WiFi.beginSmartConfig(); while (!WiFi.smartConfigDone()) { delay(500); Serial.print("."); } Serial.println("SmartConfig received"); // 等待连接建立 while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } }注意:SmartConfig需要配合乐鑫的官方APP或兼容的第三方APP使用。
3. 蓝牙通信实现
ESP32支持经典蓝牙和低功耗蓝牙(BLE)两种模式。对于我们的环境监测器,BLE是更合适的选择,因为它功耗更低,适合与手机等移动设备通信。
3.1 BLE服务与特征定义
首先,我们需要定义BLE服务和特征:
#include <BLEDevice.h> #include <BLEServer.h> #include <BLEUtils.h> #include <BLE2902.h> BLEServer* pServer; BLEService* pService; BLECharacteristic* pTempCharacteristic; BLECharacteristic* pHumidCharacteristic; #define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b" #define TEMP_CHAR_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8" #define HUMID_CHAR_UUID "1bc68a2e-36e1-4688-b7f5-ea07361b26a9" void setupBLE() { BLEDevice::init("ESP32_EnvMonitor"); pServer = BLEDevice::createServer(); pService = pServer->createService(SERVICE_UUID); pTempCharacteristic = pService->createCharacteristic( TEMP_CHAR_UUID, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY ); pHumidCharacteristic = pService->createCharacteristic( HUMID_CHAR_UUID, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY ); pTempCharacteristic->addDescriptor(new BLE2902()); pHumidCharacteristic->addDescriptor(new BLE2902()); pService->start(); BLEAdvertising* pAdvertising = BLEDevice::getAdvertising(); pAdvertising->addServiceUUID(SERVICE_UUID); pAdvertising->setScanResponse(true); pAdvertising->setMinPreferred(0x06); pAdvertising->setMinPreferred(0x12); BLEDevice::startAdvertising(); }3.2 数据更新与通知
在读取传感器数据后,通过BLE通知机制将数据推送到已连接的客户端:
void updateBLEData(float temperature, float humidity) { char tempStr[8]; char humidStr[8]; dtostrf(temperature, 6, 2, tempStr); dtostrf(humidity, 6, 2, humidStr); pTempCharacteristic->setValue(tempStr); pTempCharacteristic->notify(); pHumidCharacteristic->setValue(humidStr); pHumidCharacteristic->notify(); }4. 完整项目集成与优化
现在我们将Wi-Fi、蓝牙和传感器功能整合到一个完整的项目中。
4.1 主程序架构
#include <WiFi.h> #include <BLEDevice.h> #include <DHT.h> #define DHTPIN 4 #define DHTTYPE DHT22 DHT dht(DHTPIN, DHTTYPE); void setup() { Serial.begin(115200); dht.begin(); setupWiFi(); // 实现Wi-Fi连接 setupBLE(); // 初始化BLE // 其他初始化代码 } void loop() { static unsigned long lastReadTime = 0; if (millis() - lastReadTime > 2000) { // 每2秒读取一次 float h = dht.readHumidity(); float t = dht.readTemperature(); if (!isnan(h) && !isnan(t)) { updateBLEData(t, h); sendToServer(t, h); // 通过Wi-Fi发送到服务器 } lastReadTime = millis(); } // 处理其他任务 }4.2 电源管理优化
为了延长电池供电时的使用时间,我们可以利用ESP32的低功耗特性:
void enterDeepSleep() { // 配置唤醒源 esp_sleep_enable_timer_wakeup(30 * 1000000); // 30秒后唤醒 // 进入深度睡眠 esp_deep_sleep_start(); } void loop() { // 读取传感器数据并传输 // 进入低功耗模式 if (batteryPowered) { enterDeepSleep(); } else { delay(2000); } }4.3 常见问题排查
Wi-Fi连接不稳定:
- 检查天线连接(如果使用外置天线)
- 尝试降低Wi-Fi功率:
WiFi.setTxPower(WIFI_POWER_19_5dBm) - 确保电源稳定,Wi-Fi工���时电流需求较大
BLE连接断开:
- 检查设备是否超出有效范围(通常10米内)
- 确保没有其他2.4GHz设备干扰
- 增加连接间隔:
BLEDevice::setMTU(517)可提高吞吐量
传感器读数异常:
- 检查接线是否正确
- 确保供电电压稳定(DHT22需要3.3V)
- 添加适当的去抖动延迟
5. 进阶应用与扩展
掌握了基础功能后,我们可以考虑以下扩展方向:
5.1 多协议协同工作
ESP32可以同时运行Wi-Fi和蓝牙,我们可以利用这一特性实现更复杂的应用场景:
void setup() { // 初始化Wi-Fi和蓝牙 WiFi.mode(WIFI_STA); BLEDevice::init("ESP32_DualMode"); // 同时运行两种协议 xTaskCreatePinnedToCore( wifiTask, /* 任务函数 */ "WiFiTask", /* 任务名称 */ 10000, /* 堆栈大小 */ NULL, /* 参数 */ 1, /* 优先级 */ NULL, /* 任务句柄 */ 0 /* 核心 */ ); xTaskCreatePinnedToCore( bleTask, /* 任务函数 */ "BLETask", /* 任务名称 */ 10000, /* 堆栈大小 */ NULL, /* 参数 */ 1, /* 优先级 */ NULL, /* 核心 */ 1 /* 核心 */ ); }5.2 云端数据集成
将传感器数据上传到物联网平台:
void sendToCloud(float temp, float humid) { WiFiClient client; if (client.connect("api.iotplatform.com", 80)) { String postData = "temperature=" + String(temp) + "&humidity=" + String(humid); client.println("POST /data HTTP/1.1"); client.println("Host: api.iotplatform.com"); client.println("Content-Type: application/x-www-form-urlencoded"); client.print("Content-Length: "); client.println(postData.length()); client.println(); client.println(postData); delay(10); client.stop(); } }5.3 OTA固件更新
实现无线固件更新功能:
#include <HTTPClient.h> #include <Update.h> void performOTA() { HTTPClient http; http.begin("http://your-server.com/firmware.bin"); int httpCode = http.GET(); if (httpCode == HTTP_CODE_OK) { WiFiClient* stream = http.getStreamPtr(); if (Update.begin(stream->available())) { Update.writeStream(*stream); if (Update.end()) { Serial.println("OTA update complete, restarting..."); ESP.restart(); } } } http.end(); }在实际项目中,我发现同时使用Wi-Fi和蓝牙时,合理的任务调度和优先级设置对系统稳定性至关重要。特别是在处理传感器数据的同时维护无线连接,需要仔细平衡各个任务的执行时间。
