IOT项目------ESP8266无线开关
ESP8266无线开关实现方案
系统概述
本系统基于ESP8266模组构建一个无线开关控制系统,通过Wi-Fi连接实现远程设备控制。系统包含:
- ESP8266作为主控制器
- 继电器模块控制电器开关
- 本地按钮用于手动控制
- 云端/局域网通信
- PyQt上位机界面显示状态
硬件介绍
所需组件
- ESP8266开发板 (NodeMCU或Wemos D1 Mini)
- 继电器模块 (5V/10A)
- 面包板和跳线
- LED指示灯 (可选)
- 按钮开关
- 电源适配器
电路连接
ESP8266 继电器模块
GPIO5 --> IN引脚
3.3V --> VCC
GND --> GND
ESP8266 按钮
GPIO4 --> 一端
3.3V --> 另一端(通过10K上拉电阻)
软件介绍
VSCode开发环境配置
- 安装PlatformIO插件
- 创建新项目,选择ESP8266平台
- 添加必要的库依赖:
- ArduinoJson (用于数据解析)
- PubSubClient (MQTT通信,可选)
主要代码结构
cpp
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <ArduinoJson.h>
// WiFi配置
const char* ssid = "Your_WiFi_SSID";
const char* password = "Your_WiFi_Password";
// 引脚定义
const int relayPin = 5; // GPIO5控制继电器
const int buttonPin = 4; // GPIO4连接按钮
// 状态变量
bool switchState = false;
bool lastButtonState = HIGH;
ESP8266WebServer server(80);
void setup() {
Serial.begin(115200);
// 初始化引脚
pinMode(relayPin, OUTPUT);
pinMode(buttonPin, INPUT_PULLUP);
digitalWrite(relayPin, LOW);
// 连接WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi...");
}
Serial.println("WiFi connected");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
// 设置Web服务器路由
server.on("/", handleRoot);
server.on("/switch", handleSwitch);
server.on("/status", handleStatus);
server.begin();
Serial.println("HTTP server started");
}
void loop() {
server.handleClient();
// 按钮检测
bool currentButtonState = digitalRead(buttonPin);
if (currentButtonState == LOW && lastButtonState == HIGH) {
toggleSwitch();
delay(200); // 防抖
}
lastButtonState = currentButtonState;
}
void handleRoot() {
String html = "<html><body>";
html += "<h1>ESP8266 Wireless Switch</h1>";
html += "<p>Current State: " + String(switchState ? "ON" : "OFF") + "</p>";
html += "<a href='/switch?state=1'><button>Turn ON</button></a>";
html += "<a href='/switch?state=0'><button>Turn OFF</button></a>";
html += "</body></html>";
server.send(200, "text/html", html);
}
void handleSwitch() {
if (server.hasArg("state")) {
switchState = server.arg("state").toInt();
digitalWrite(relayPin, switchState);
server.send(200, "application/json", "{\"status\":\"success\",\"state\":" + String(switchState) + "}");
} else {
server.send(400, "application/json", "{\"status\":\"error\",\"message\":\"Missing state parameter\"}");
}
}
void handleStatus() {
String json = "{\"state\":" + String(switchState) + "}";
server.send(200, "application/json", json);
}
void toggleSwitch() {
switchState = !switchState;
digitalWrite(relayPin, switchState);
}
示例演示
操作步骤
- 将代码上传到ESP8266
- 打开串口监视器查看IP地址
- 在浏览器中输入ESP8266的IP地址
- 点击网页按钮控制开关
- 物理按钮也可用于切换状态
API接口
GET /- 显示控制网页GET /switch?state=0/1- 控制开关状态GET /status- 获取当前状态(JSON格式)
优化建议
1. 增加PyCharm PyQt上位机界面
使用PyCharm创建PyQt5应用程序来监控和控制ESP8266开关:
python
import sys
import requests
from PyQt5.QtWidgets import (QApplication, QMainWindow, QVBoxLayout,
QHBoxLayout, QPushButton, QLabel, QWidget,
QMessageBox)
from PyQt5.QtCore import QTimer, Qt
class SwitchController(QMainWindow):
def __init__(self):
super().__init__()
self.esp_ip = "192.168.1.100" # 替换为ESP8266的IP
self.initUI()
self.setupTimer()
def initUI(self):
self.setWindowTitle('ESP8266 Switch Controller')
self.setGeometry(300, 300, 300, 200)
# 中央窗口部件
central_widget = QWidget()
self.setCentralWidget(central_widget)
# 布局
layout = QVBoxLayout()
# 状态显示
self.status_label = QLabel('状态: 未知')
self.status_label.setAlignment(Qt.AlignCenter)
self.status_label.setStyleSheet("font-size: 16px; font-weight: bold;")
layout.addWidget(self.status_label)
# 控制按钮
button_layout = QHBoxLayout()
self.on_button = QPushButton('打开')
self.on_button.clicked.connect(self.turn_on)
self.on_button.setStyleSheet("background-color: green; color: white;")
button_layout.addWidget(self.on_button)
self.off_button = QPushButton('关闭')
self.off_button.clicked.connect(self.turn_off)
self.off_button.setStyleSheet("background-color: red; color: white;")
button_layout.addWidget(self.off_button)
layout.addLayout(button_layout)
# 连接状态
self.connection_label = QLabel('连接状态: 未连接')
layout.addWidget(self.connection_label)
central_widget.setLayout(layout)
def setupTimer(self):
# 定时器用于定期更新状态
self.timer = QTimer()
self.timer.timeout.connect(self.update_status)
self.timer.start(2000) # 每2秒更新一次
def update_status(self):
try:
response = requests.get(f"http://{self.esp_ip}/status", timeout=3)
if response.status_code == 200:
data = response.json()
state = data.get('state', 0)
status_text = "ON" if state else "OFF"
color = "green" if state else "red"
self.status_label.setText(f'状态: {status_text}')
self.status_label.setStyleSheet(f"font-size: 16px; font-weight: bold; color: {color};")
self.connection_label.setText('连接状态: 已连接')
self.connection_label.setStyleSheet("color: green;")
else:
self.connection_label.setText('连接状态: 响应错误')
self.connection_label.setStyleSheet("color: orange;")
except Exception as e:
self.connection_label.setText(f'连接状态: 连接失败 - {str(e)}')
self.connection_label.setStyleSheet("color: red;")
def turn_on(self):
self.send_switch_command(1)
def turn_off(self):
self.send_switch_command(0)
def send_switch_command(self, state):
try:
response = requests.get(f"http://{self.esp_ip}/switch?state={state}", timeout=3)
if response.status_code == 200:
QMessageBox.information(self, "成功", f"开关已{'打开' if state else '关闭'}")
self.update_status()
else:
QMessageBox.warning(self, "错误", "控制命令发送失败")
except Exception as e:
QMessageBox.critical(self, "错误", f"连接失败: {str(e)}")
if __name__ == '__main__':
app = QApplication(sys.argv)
controller = SwitchController()
controller.show()
sys.exit(app.exec_())
3. 其他优化建议
ESP8266端优化:
- 添加OTA(空中下载)功能,便于远程更新固件
- 实现MQTT协议,支持更灵活的物联网平台集成
- 添加看门狗定时器,提高系统稳定性
- 实现EEPROM存储,保存开关状态以防断电丢失
PyQt上位机增强功能:
- 添加多个设备管理功能
- 实现历史记录和日志功能
- 添加定时任务和场景模式
- 支持设备发现和自动配置
- 添加数据图表显示
安全优化:
- 添加Web界面密码保护
- 实现HTTPS加密通信
- 添加设备身份验证
这个完整的方案提供了从硬件到软件,再到图形界面的完整无线开关解决方案,可以根据实际需求进一步扩展功能。