第一步:环境准备
-
安装 ESP-IDF:确保你已正确安装 ESP-IDF 环境,并且已支持 ESP8266。
- 官方安装指南:ESP-IDF 获取和安装
- 重要:ESP8266 支持需要 IDF 版本 v4.4 或更高。安装时通常需要手动添加 ESP8266 支持:
bashcd $IDF_PATH ./install.sh esp8266 # 在安装时添加目标,或者使用 install.bat (Windows) . ./export.sh # 激活环境 (Linux/macOS),或 export.bat (Windows)
-
确认环境:打开终端(或 ESP-IDF Command Prompt),运行以下命令确认 ESP8266 已就绪:
cssidf.py --version idf.py --list-targets | grep esp8266 # 应该能看到 esp8266 在列表中
第二步:创建项目
我们将从一个简单的示例项目开始修改。
-
创建项目目录:
bashmkdir ~/esp/esp8266_relay_control cd ~/esp/esp8266_relay_control
-
复制示例项目 (推荐从
hello_world
开始):bashcp -r $IDF_PATH/examples/get-started/hello_world/* .
-
初始化项目为 ESP8266:
arduinoidf.py set-target esp8266
这个命令会创建必要的配置文件,并将项目目标设置为 ESP8266。
第三步:编写代码
修改 main/hello_world_main.c
文件,将其重命名为 main/relay_control.c
并替换为以下代码:
c
#include <stdio.h>
#include <string.h>
#include "esp_system.h"
#include "esp_netif.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "protocol_examples_common.h"
#include "lwip/err.h"
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include "lwip/netdb.h"
#include "driver/gpio.h"
// 项目配置(这些将在 menuconfig 中设置)
#define RELAY_GPIO CONFIG_RELAY_GPIO
#define PORT CONFIG_TCP_PORT
static const char *TAG = "relay_control";
// 继电器控制函数
static void relay_init(void) {
gpio_config_t io_conf = {};
io_conf.intr_type = GPIO_INTR_DISABLE; // 禁用中断
io_conf.mode = GPIO_MODE_OUTPUT; // 设置为输出模式
io_conf.pin_bit_mask = (1ULL << RELAY_GPIO); // 指定GPIO引脚
io_conf.pull_down_en = 0; // 禁用下拉
io_conf.pull_up_en = 0; // 禁用上拉
gpio_config(&io_conf);
// 初始状态:关闭继电器
gpio_set_level(RELAY_GPIO, 0);
ESP_LOGI(TAG, "Relay initialized on GPIO %d", RELAY_GPIO);
}
static void set_relay_state(int state) {
gpio_set_level(RELAY_GPIO, state);
ESP_LOGI(TAG, "Relay set to: %s", state ? "ON" : "OFF");
}
// TCP服务器任务
static void tcp_server_task(void *pvParameters) {
char rx_buffer[128];
int addr_family = AF_INET;
int ip_protocol = IPPROTO_IP;
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(PORT);
int sock = socket(addr_family, SOCK_STREAM, ip_protocol);
if (sock < 0) {
ESP_LOGE(TAG, "Unable to create socket");
vTaskDelete(NULL);
return;
}
// 绑定socket
if (bind(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
ESP_LOGE(TAG, "Socket bind failed");
close(sock);
vTaskDelete(NULL);
return;
}
// 开始监听
if (listen(sock, 5) < 0) {
ESP_LOGE(TAG, "Socket listen failed");
close(sock);
vTaskDelete(NULL);
return;
}
ESP_LOGI(TAG, "TCP server started on port %d", PORT);
while (1) {
struct sockaddr_in client_addr;
socklen_t client_addr_len = sizeof(client_addr);
int client_sock = accept(sock, (struct sockaddr *)&client_addr, &client_addr_len);
if (client_sock < 0) {
ESP_LOGE(TAG, "Unable to accept connection");
continue;
}
ESP_LOGI(TAG, "Client connected");
// 向客户端发送欢迎消息
char welcome_msg[] = "ESP8266 Relay Controller. Commands: 'ON', 'OFF'\r\n";
send(client_sock, welcome_msg, strlen(welcome_msg), 0);
while (1) {
int len = recv(client_sock, rx_buffer, sizeof(rx_buffer) - 1, 0);
if (len < 0) {
ESP_LOGE(TAG, "Receive failed");
break;
} else if (len == 0) {
ESP_LOGI(TAG, "Connection closed");
break;
} else {
rx_buffer[len] = '\0'; // 添加字符串结束符
ESP_LOGI(TAG, "Received: %s", rx_buffer);
// 处理命令
if (strstr(rx_buffer, "ON")) {
set_relay_state(1);
send(client_sock, "Relay turned ON\r\n", 17, 0);
} else if (strstr(rx_buffer, "OFF")) {
set_relay_state(0);
send(client_sock, "Relay turned OFF\r\n", 18, 0);
} else {
send(client_sock, "Unknown command\r\n", 17, 0);
}
}
}
shutdown(client_sock, 0);
close(client_sock);
}
}
void app_main(void) {
// 初始化NVS
ESP_ERROR_CHECK(nvs_flash_init());
// 初始化TCP/IP栈
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
// 连接WiFi(使用示例组件中的通用函数)
ESP_ERROR_CHECK(example_connect());
// 初始化继电器GPIO
relay_init();
// 创建TCP服务器任务
xTaskCreate(tcp_server_task, "tcp_server", 4096, NULL, 5, NULL);
ESP_LOGI(TAG, "Relay control application started");
}
同时,需要修改 main/CMakeLists.txt
:
erlang
idf_component_register(SRCS "relay_control.c"
INCLUDE_DIRS "."
REQUIRES esp_netif lwip)
第四步:项目配置 (idf.py menuconfig
)
这是最关键的一步,配置项目参数。
-
打开配置菜单:
idf.py menuconfig
-
配置串口烧录参数:
- 导航到
Serial flasher config
- 设置
Default serial port
(你的串口设备,如/dev/ttyUSB0
或COM3
) - 根据你的模块设置
Flash Size
(通常为2MB
或4MB
)
- 导航到
-
配置项目参数:
- 导航到
Example Configuration
(如果不存在,需要先创建main/Kconfig.projbuild
文件) - 设置
WiFi SSID
(你的WiFi名称) - 设置
WiFi Password
(你的WiFi密码) - 设置
Relay GPIO number
(控制继电器使用的GPIO号,如2
) - 设置
TCP port number
(TCP服务器端口,如3333
)
- 导航到
-
保存并退出:
- 按
S
保存配置 - 按
Enter
确认文件名 - 按
Q
退出
- 按
创建 main/Kconfig.projbuild
文件(如果不存在):
arduino
menu "Example Configuration"
config ESP_WIFI_SSID
string "WiFi SSID"
default "myssid"
help
SSID (network name) to connect to.
config ESP_WIFI_PASSWORD
string "WiFi Password"
default "mypassword"
help
WiFi password (WPA or WPA2).
config RELAY_GPIO
int "Relay GPIO number"
range 0 16
default 2
help
GPIO number (IOxx) to connect RELAY module.
config TCP_PORT
int "TCP port number"
range 1024 65535
default 3333
help
TCP port number for the server.
endmenu
第五步:编译项目
idf.py build
编译成功后会显示类似信息:
arduino
Project build complete. To flash, run this command:
../../../components/esptool_py/esptool/esptool.py -p (PORT) -b 460800...
第六步:烧录固件
-
硬件准备:
- 将 ESP8266 模块连接到电脑(通过 USB-TTL 转换器)
- 确保 GPIO0 接地以进入下载模式
- 给模块上电
-
执行烧录 (将
PORT
替换为你的实际串口):bashidf.py -p /dev/ttyUSB0 flash # Linux idf.py -p COM3 flash # Windows
-
重置模块:
- 烧录完成后,断开 GPIO0 与地的连接
- 重启模块(或重新上电)
第七步:监视运行和测试
-
打开串口监视器:
bashidf.py -p /dev/ttyUSB0 monitor # Linux idf.py -p COM3 monitor # Windows
-
观察日志:你应该能看到:
- 继电器初始化信息
- WiFi 连接过程
- 获取到的 IP 地址
- TCP 服务器启动信息
-
测试控制:
- 使用网络调试工具(如 NetAssist、TCP/UDP 调试助手)
- 连接到 ESP8266 的 IP 地址和配置的端口(如
192.168.1.100:3333
) - 发送
ON
打开继电器,发送OFF
关闭继电器
一键编译烧录监视:
bash
idf.py -p /dev/ttyUSB0 flash monitor
这样就完成了整个 ESP8266 继电器控制项目的创建、配置、编译和烧录流程!
核心网络设计模式概览
模式 | 协议/技术 | 特点 | 适用场景 | ESP 芯片 |
---|---|---|---|---|
直接连接云 | Wi-Fi + MQTT/HTTP | 响应快,依赖网络和云服务 | 大家电、智能插座、摄像头 | ESP32, ESP8266 |
局域网中心 | Wi-Fi + LAN MQTT | 响应极快,网络中断仍可用 | 本地自动化(灯光、开关) | ESP32, ESP8266 |
混合模式 | Wi-Fi + 双MQTT | 兼顾本地速度与远程控制 | 绝大多数智能家居设备 | ESP32, ESP8266 |
低功耗传感 | Wi-Fi + ESP-NOW | 低功耗,星型网络,简单 | 电池供电传感器 | ESP32, ESP8266 |
Mesh 覆盖 | Wi-Fi Mesh | 自组网,无缝覆盖,高可靠性 | 大户型全屋智能 | ESP32 (ESP-WIFI-MESH) |
蓝牙辅助 | BLE + Wi-Fi | 低功耗配网,近距离控制 | 设备配网、传感器 | ESP32 |
网络我暂时用 局域网中心 和 蓝牙辅助 , 稳定后考虑混合模式 与低功耗传感 , 最后考虑Mesh 覆盖