# ESP32 WiFi开发与物联网应用
ESP32是一款功能强大的WiFi和蓝牙双模微控制器,为物联网项目提供了理想的解决方案。本文将全面介绍ESP32的WiFi开发技术,从基础连接到高级物联网应用。
## ESP32 WiFi基础
ESP32内置WiFi模块,支持802.11 b/g/n协议,可以工作在Station模式、AP模式或混合模式。
### 开发环境设置
```cpp
// 必要的库文件
#include <WiFi.h>
#include <WebServer.h>
#include <ArduinoJson.h>
#include <PubSubClient.h>
```
### WiFi连接基础
```cpp
const char* ssid = "your_wifi_name";
const char* password = "your_wifi_password";
void setup() {
Serial.begin(115200);
// 初始化WiFi
WiFi.begin(ssid, password);
// 等待连接
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("连接WiFi中...");
}
Serial.println("WiFi连接成功");
Serial.print("IP地址: ");
Serial.println(WiFi.localIP());
}
void loop() {
// 检查连接状态
if (WiFi.status() != WL_CONNECTED) {
Serial.println("WiFi连接丢失,尝试重连...");
WiFi.reconnect();
}
delay(5000);
}
```
## Web服务器开发
### 基础Web服务器
```cpp
#include <WiFi.h>
#include <WebServer.h>
const char* ssid = "your_wifi_name";
const char* password = "your_wifi_password";
WebServer server(80);
void setup() {
Serial.begin(115200);
// 连接WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("连接中...");
}
Serial.println("WiFi连接成功");
Serial.print("IP地址: ");
Serial.println(WiFi.localIP());
// 设置路由
server.on("/", handleRoot);
server.on("/api/status", handleStatus);
server.on("/api/control", handleControl);
// 启动服务器
server.begin();
Serial.println("Web服务器启动");
}
void loop() {
server.handleClient();
}
void handleRoot() {
String html = "<!DOCTYPE html><html><head><title>ESP32控制面板</title></head>";
html += "<body><h1>ESP32控制面板</h1>";
html += "<p>状态: <span id='status'>获取中...</span></p>";
html += "<button onclick='toggleLED()'>切换LED</button>";
html += "<script>";
html += "function toggleLED() {";
html += " fetch('/api/control?action=toggle')";
html += " .then(response => response.json())";
html += " .then(data => document.getElementById('status').innerHTML = data.status);";
html += "}";
html += "</script></body></html>";
server.send(200, "text/html", html);
}
void handleStatus() {
StaticJsonDocument<200> doc;
doc["status"] = "online";
doc["uptime"] = millis();
doc["free_heap"] = ESP.getFreeHeap();
String response;
serializeJson(doc, response);
server.send(200, "application/json", response);
}
void handleControl() {
String action = server.arg("action");
if (action == "toggle") {
// 切换LED状态
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
StaticJsonDocument<200> doc;
doc["status"] = digitalRead(LED_BUILTIN) ? "LED开启" : "LED关闭";
String response;
serializeJson(doc, response);
server.send(200, "application/json", response);
} else {
server.send(400, "text/plain", "无效的操作");
}
}
```
### 高级Web服务器功能
```cpp
#include <WiFi.h>
#include <WebServer.h>
#include <SPIFFS.h>
WebServer server(80);
void setup() {
Serial.begin(115200);
// 初始化SPIFFS文件系统
if (!SPIFFS.begin(true)) {
Serial.println("SPIFFS初始化失败");
return;
}
// 连接WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("连接中...");
}
// 设置路由
server.on("/", handleRoot);
server.on("/api/sensors", handleSensors);
server.on("/api/config", HTTP_GET, handleGetConfig);
server.on("/api/config", HTTP_POST, handlePostConfig);
server.onNotFound(handleNotFound);
// 启用CORS
server.enableCORS(true);
server.begin();
Serial.println("Web服务器启动");
}
void handleRoot() {
// 从SPIFFS读取HTML文件
File file = SPIFFS.open("/index.html", "r");
if (!file) {
server.send(404, "text/plain", "文件未找到");
return;
}
server.streamFile(file, "text/html");
file.close();
}
void handleSensors() {
StaticJsonDocument<500> doc;
// 模拟传感器数据
doc["temperature"] = random(20, 30);
doc["humidity"] = random(40, 80);
doc["light"] = random(100, 1000);
doc["timestamp"] = millis();
String response;
serializeJson(doc, response);
server.send(200, "application/json", response);
}
void handleGetConfig() {
File file = SPIFFS.open("/config.json", "r");
if (!file) {
server.send(404, "text/plain", "配置文件未找到");
return;
}
server.streamFile(file, "application/json");
file.close();
}
void handlePostConfig() {
if (server.hasArg("plain")) {
String config = server.arg("plain");
File file = SPIFFS.open("/config.json", "w");
if (file) {
file.print(config);
file.close();
server.send(200, "application/json", "{\"status\":\"success\"}");
} else {
server.send(500, "application/json", "{\"status\":\"error\"}");
}
} else {
server.send(400, "application/json", "{\"status\":\"bad_request\"}");
}
}
void handleNotFound() {
server.send(404, "text/plain", "页面未找到");
}
```
## MQTT通信
### MQTT客户端实现
```cpp
#include <WiFi.h>
#include <PubSubClient.h>
const char* ssid = "your_wifi_name";
const char* password = "your_wifi_password";
const char* mqtt_server = "broker.hivemq.com";
const int mqtt_port = 1883;
WiFiClient espClient;
PubSubClient client(espClient);
void setup() {
Serial.begin(115200);
// 连接WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("连接WiFi中...");
}
// 设置MQTT服务器
client.setServer(mqtt_server, mqtt_port);
client.setCallback(mqttCallback);
// 连接MQTT
connectMQTT();
}
void loop() {
if (!client.connected()) {
connectMQTT();
}
client.loop();
// 发布传感器数据
publishSensorData();
delay(5000);
}
void connectMQTT() {
while (!client.connected()) {
Serial.print("连接MQTT服务器...");
if (client.connect("ESP32Client")) {
Serial.println("连接成功");
// 订阅主题
client.subscribe("esp32/commands");
client.subscribe("esp32/settings");
} else {
Serial.print("连接失败,错误代码: ");
Serial.print(client.state());
Serial.println(" 5秒后重试");
delay(5000);
}
}
}
void mqttCallback(char* topic, byte* payload, unsigned int length) {
String message = "";
for (int i = 0; i < length; i++) {
message += (char)payload[i];
}
Serial.print("收到消息 [");
Serial.print(topic);
Serial.print("]: ");
Serial.println(message);
// 处理不同的主题
if (String(topic) == "esp32/commands") {
handleCommand(message);
} else if (String(topic) == "esp32/settings") {
handleSettings(message);
}
}
void handleCommand(String command) {
if (command == "led_on") {
digitalWrite(LED_BUILTIN, HIGH);
client.publish("esp32/status", "LED开启");
} else if (command == "led_off") {
digitalWrite(LED_BUILTIN, LOW);
client.publish("esp32/status", "LED关闭");
} else if (command == "restart") {
client.publish("esp32/status", "重启中...");
ESP.restart();
}
}
void handleSettings(String settings) {
StaticJsonDocument<200> doc;
deserializeJson(doc, settings);
if (doc.containsKey("update_interval")) {
int interval = doc["update_interval"];
// 更新发送间隔
Serial.println("更新间隔设置为: " + String(interval) + "ms");
}
}
void publishSensorData() {
StaticJsonDocument<200> doc;
doc["temperature"] = random(20, 30);
doc["humidity"] = random(40, 80);
doc["timestamp"] = millis();
String payload;
serializeJson(doc, payload);
client.publish("esp32/sensors", payload.c_str());
}
```
### 高级MQTT功能
```cpp
class MQTTManager {
private:
PubSubClient* client;
String deviceId;
String baseTopic;
unsigned long lastReconnectAttempt = 0;
const unsigned long reconnectInterval = 5000;
public:
MQTTManager(PubSubClient* mqttClient, String id) {
client = mqttClient;
deviceId = id;
baseTopic = "devices/" + deviceId;
}
bool connect() {
if (client->connected()) {
return true;
}
unsigned long now = millis();
if (now - lastReconnectAttempt > reconnectInterval) {
lastReconnectAttempt = now;
if (client->connect(deviceId.c_str())) {
Serial.println("MQTT连接成功");
// 订阅设备特定主题
client->subscribe((baseTopic + "/commands").c_str());
client->subscribe((baseTopic + "/settings").c_str());
// 发布设备上线消息
publishStatus("online");
return true;
} else {
Serial.print("MQTT连接失败,错误代码: ");
Serial.println(client->state());
}
}
return false;
}
void publishStatus(String status) {
StaticJsonDocument<100> doc;
doc["status"] = status;
doc["timestamp"] = millis();
doc["uptime"] = millis();
String payload;
serializeJson(doc, payload);
client->publish((baseTopic + "/status").c_str(), payload.c_str());
}
void publishSensorData(float temperature, float humidity, float light) {
StaticJsonDocument<200> doc;
doc["temperature"] = temperature;
doc["humidity"] = humidity;
doc["light"] = light;
doc["timestamp"] = millis();
String payload;
serializeJson(doc, payload);
client->publish((baseTopic + "/sensors").c_str(), payload.c_str());
}
void loop() {
if (!client->connected()) {
connect();
} else {
client->loop();
}
}
};
```
## 物联网项目实战
### 智能环境监测系统
```cpp
#include <WiFi.h>
#include <WebServer.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <DHT.h>
// 传感器定义
#define DHT_PIN 4
#define DHT_TYPE DHT22
#define LDR_PIN 34
#define PIR_PIN 2
// WiFi和MQTT配置
const char* ssid = "your_wifi_name";
const char* password = "your_wifi_password";
const char* mqtt_server = "broker.hivemq.com";
// 全局对象
DHT dht(DHT_PIN, DHT_TYPE);
WiFiClient espClient;
PubSubClient mqttClient(espClient);
WebServer webServer(80);
MQTTManager mqttManager(&mqttClient, "env_monitor_001");
// 传感器数据结构
struct SensorData {
float temperature;
float humidity;
float light;
bool motion;
unsigned long timestamp;
};
// 配置参数
struct Config {
int updateInterval = 5000;
bool mqttEnabled = true;
bool webServerEnabled = true;
float tempThreshold = 25.0;
float humidityThreshold = 70.0;
};
Config config;
void setup() {
Serial.begin(115200);
// 初始化传感器
dht.begin();
pinMode(PIR_PIN, INPUT);
// 连接WiFi
connectWiFi();
// 设置MQTT
mqttClient.setServer(mqtt_server, 1883);
mqttClient.setCallback(mqttCallback);
// 设置Web服务器
setupWebServer();
Serial.println("智能环境监测系统启动完成");
}
void loop() {
// 处理MQTT
if (config.mqttEnabled) {
mqttManager.loop();
}
// 处理Web服务器
if (config.webServerEnabled) {
webServer.handleClient();
}
// 读取传感器数据
static unsigned long lastUpdate = 0;
if (millis() - lastUpdate >= config.updateInterval) {
SensorData data = readSensors();
processSensorData(data);
lastUpdate = millis();
}
delay(100);
}
void connectWiFi() {
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("连接WiFi中...");
}
Serial.println("WiFi连接成功");
Serial.print("IP地址: ");
Serial.println(WiFi.localIP());
}
SensorData readSensors() {
SensorData data;
data.temperature = dht.readTemperature();
data.humidity = dht.readHumidity();
data.light = analogRead(LDR_PIN) * 100.0 / 4095.0; // 转换为百分比
data.motion = digitalRead(PIR_PIN);
data.timestamp = millis();
return data;
}
void processSensorData(const SensorData& data) {
// 打印到串口
Serial.println("=== 传感器数据 ===");
Serial.printf("温度: %.2f°C\n", data.temperature);
Serial.printf("湿度: %.2f%%\n", data.humidity);
Serial.printf("光照: %.1f%%\n", data.light);
Serial.printf("运动: %s\n", data.motion ? "检测到" : "无");
Serial.println("================");
// 检查阈值
if (data.temperature > config.tempThreshold) {
Serial.println("警告:温度过高!");
if (config.mqttEnabled) {
mqttClient.publish("env_monitor_001/alerts", "高温警告");
}
}
if (data.humidity > config.humidityThreshold) {
Serial.println("警告:湿度过高!");
if (config.mqttEnabled) {
mqttClient.publish("env_monitor_001/alerts", "高湿警告");
}
}
// 发布到MQTT
if (config.mqttEnabled) {
mqttManager.publishSensorData(data.temperature, data.humidity, data.light);
}
}
void mqttCallback(char* topic, byte* payload, unsigned int length) {
String message = "";
for (int i = 0; i < length; i++) {
message += (char)payload[i];
}
Serial.print("收到MQTT消息 [");
Serial.print(topic);
Serial.print("]: ");
Serial.println(message);
// 处理配置更新
if (String(topic) == "devices/env_monitor_001/settings") {
updateConfig(message);
}
}
void updateConfig(String configJson) {
StaticJsonDocument<200> doc;
deserializeJson(doc, configJson);
if (doc.containsKey("update_interval")) {
config.updateInterval = doc["update_interval"];
}
if (doc.containsKey("temp_threshold")) {
config.tempThreshold = doc["temp_threshold"];
}
if (doc.containsKey("humidity_threshold")) {
config.humidityThreshold = doc["humidity_threshold"];
}
Serial.println("配置已更新");
}
void setupWebServer() {
webServer.on("/", handleRoot);
webServer.on("/api/data", handleApiData);
webServer.on("/api/config", HTTP_GET, handleGetConfig);
webServer.on("/api/config", HTTP_POST, handlePostConfig);
webServer.begin();
Serial.println("Web服务器启动");
}
void handleRoot() {
String html = "<!DOCTYPE html><html><head><title>环境监测系统</title>";
html += "<meta name='viewport' content='width=device-width, initial-scale=1'>";
html += "<style>";
html += "body { font-family: Arial, sans-serif; margin: 20px; }";
html += ".card { background: #f0f0f0; padding: 20px; margin: 10px 0; border-radius: 5px; }";
html += ".value { font-size: 24px; font-weight: bold; color: #333; }";
html += "</style></head><body>";
html += "<h1>智能环境监测系统</h1>";
html += "<div class='card'>";
html += "<h3>实时数据</h3>";
html += "<p>温度: <span class='value' id='temp'>--</span>°C</p>";
html += "<p>湿度: <span class='value' id='humidity'>--</span>%</p>";
html += "<p>光照: <span class='value' id='light'>--</span>%</p>";
html += "<p>运动: <span class='value' id='motion'>--</span></p>";
html += "</div>";
html += "<script>";
html += "function updateData() {";
html += " fetch('/api/data')";
html += " .then(response => response.json())";
html += " .then(data => {";
html += " document.getElementById('temp').textContent = data.temperature.toFixed(1);";
html += " document.getElementById('humidity').textContent = data.humidity.toFixed(1);";
html += " document.getElementById('light').textContent = data.light.toFixed(1);";
html += " document.getElementById('motion').textContent = data.motion ? '检测到' : '无';";
html += " });";
html += "}";
html += "setInterval(updateData, 2000);";
html += "updateData();";
html += "</script></body></html>";
webServer.send(200, "text/html", html);
}
void handleApiData() {
SensorData data = readSensors();
StaticJsonDocument<200> doc;
doc["temperature"] = data.temperature;
doc["humidity"] = data.humidity;
doc["light"] = data.light;
doc["motion"] = data.motion;
doc["timestamp"] = data.timestamp;
String response;
serializeJson(doc, response);
webServer.send(200, "application/json", response);
}
void handleGetConfig() {
StaticJsonDocument<200> doc;
doc["update_interval"] = config.updateInterval;
doc["temp_threshold"] = config.tempThreshold;
doc["humidity_threshold"] = config.humidityThreshold;
doc["mqtt_enabled"] = config.mqttEnabled;
doc["web_server_enabled"] = config.webServerEnabled;
String response;
serializeJson(doc, response);
webServer.send(200, "application/json", response);
}
void handlePostConfig() {
if (webServer.hasArg("plain")) {
String configJson = webServer.arg("plain");
updateConfig(configJson);
webServer.send(200, "application/json", "{\"status\":\"success\"}");
} else {
webServer.send(400, "application/json", "{\"status\":\"error\"}");
}
}
```
## 性能优化与最佳实践
### 电源管理
```cpp
#include "esp_sleep.h"
void enterDeepSleep(int seconds) {
Serial.println("进入深度睡眠模式");
esp_sleep_enable_timer_wakeup(seconds * 1000000);
esp_deep_sleep_start();
}
void enterLightSleep() {
Serial.println("进入轻度睡眠模式");
esp_light_sleep_start();
}
```
### 内存管理
```cpp
void printMemoryInfo() {
Serial.printf("可用堆内存: %d bytes\n", ESP.getFreeHeap());
Serial.printf("最大分配块: %d bytes\n", ESP.getMaxAllocHeap());
Serial.printf("最小可用堆: %d bytes\n", ESP.getMinFreeHeap());
}
```
### 错误处理与恢复
```cpp
void handleWiFiDisconnect() {
if (WiFi.status() != WL_CONNECTED) {
Serial.println("WiFi连接丢失,尝试重连...");
WiFi.disconnect();
WiFi.begin(ssid, password);
int attempts = 0;
while (WiFi.status() != WL_CONNECTED && attempts < 20) {
delay(1000);
attempts++;
Serial.print(".");
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println("WiFi重连成功");
} else {
Serial.println("WiFi重连失败,重启设备");
ESP.restart();
}
}
}
```
## 总结
ESP32的WiFi功能为物联网项目提供了强大的基础。通过合理使用Web服务器、MQTT通信和传感器集成,可以构建出功能完整的智能设备。关键要点:
1. **稳定的网络连接**:实现自动重连和错误恢复机制
2. **高效的数据传输**:使用JSON格式和适当的压缩
3. **安全的通信**:考虑使用TLS加密和身份验证
4. **电源优化**:合理使用睡眠模式延长电池寿命
5. **用户体验**:提供直观的Web界面和实时数据更新
继续学习更多高级主题,如OTA更新、设备管理和云端集成,将帮助你构建更完善的物联网解决方案。