ESP-12E连PIC16F887,无树莓派通过MQTT实现安卓APP远程控继电器并查状态
Hey, 刚好折腾过类似的无树莓派MQTT远程控制方案,给你一步步捋清楚,从硬件到代码再到APP全流程:
一、硬件连接细节
先把各个模块的接线理清楚,重点注意电平兼容(ESP-12E是3.3V,PIC16F887是5V,必须加电平转换器):
1. ESP-12E ↔ PIC16F887 连接
- ESP的
GPIO1(TXD)→ 电平转换器3.3V端 → PIC的RC7(RXD)(5V端) - ESP的
GPIO0(RXD)→ 电平转换器3.3V端 → PIC的RC6(TXD)(5V端) - ESP的
GND↔ PIC的GND(共地是通信稳定的关键!) - 若需给PIC供电,从ESP外接的3.3V转5V模块输出接PIC的
VDD(注意电流要足够驱动PIC)
2. ESP-12E ↔ 继电器模块连接
- 继电器的
IN引脚 → ESP的GPIO4(可任选可用GPIO,这里举例子) - 继电器的
VCC→ 外接5V电源(ESP的3.3V带不动继电器,必须独立供电) - 继电器的
GND↔ ESP的GND
二、ESP-12E的MQTT固件开发(用Arduino IDE)
先准备环境:安装Arduino IDE,添加ESP8266开发板支持,再安装PubSubClient库(MQTT客户端必备)。
下面是核心代码,我做了详细注释,你直接改参数就能用:
#include <ESP8266WiFi.h> #include <PubSubClient.h> // WiFi配置 const char* ssid = "你的WiFi名称"; const char* password = "你的WiFi密码"; // MQTT公共Broker(不用自己搭建,直接用EMQX的免费服务器) const char* mqtt_server = "mqtt.emqx.io"; const int mqtt_port = 1883; const char* mqtt_client_id = "esp_relay_001"; // 唯一设备ID,随便设 const char* mqtt_topic_control = "home/relay/control"; // 订阅的控制主题 const char* mqtt_topic_status = "home/relay/status"; // 发布状态的主题 // 硬件引脚定义 const int relayPin = 4; WiFiClient espClient; PubSubClient client(espClient); void setup() { pinMode(relayPin, OUTPUT); digitalWrite(relayPin, LOW); // 默认继电器断开 Serial.begin(9600); // 和PIC通信的串口 setupWiFi(); client.setServer(mqtt_server, mqtt_port); client.setCallback(callback); // 设置MQTT消息回调 } void setupWiFi() { delay(10); Serial.println(); Serial.print("Connecting to "); Serial.println(ssid); 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()); } // MQTT消息回调:处理APP发来的控制指令 void callback(char* topic, byte* payload, unsigned int length) { Serial.print("Message arrived ["); Serial.print(topic); Serial.print("] "); String payloadStr = ""; for (int i = 0; i < length; i++) { payloadStr += (char)payload[i]; } Serial.println(payloadStr); // 执行继电器控制 if (payloadStr == "ON") { digitalWrite(relayPin, HIGH); client.publish(mqtt_topic_status, "ON"); // 上报状态到MQTT Serial.println("ON"); // 同步状态给PIC } else if (payloadStr == "OFF") { digitalWrite(relayPin, LOW); client.publish(mqtt_topic_status, "OFF"); // 上报状态到MQTT Serial.println("OFF"); // 同步状态给PIC } } // MQTT重连逻辑:掉线自动重连 void reconnect() { while (!client.connected()) { Serial.print("Attempting MQTT connection..."); if (client.connect(mqtt_client_id)) { Serial.println("connected"); client.subscribe(mqtt_topic_control); // 订阅控制主题 // 上线先主动上报一次当前状态 String status = digitalRead(relayPin) ? "ON" : "OFF"; client.publish(mqtt_topic_status, status.c_str()); } else { Serial.print("failed, rc="); Serial.print(client.state()); Serial.println(" try again in 5 seconds"); delay(5000); } } } void loop() { if (!client.connected()) { reconnect(); } client.loop(); // 读取PIC发来的指令(如果需要PIC主动控制继电器) if (Serial.available() > 0) { String picMsg = Serial.readStringUntil('\n'); picMsg.trim(); if (picMsg == "ON" || picMsg == "OFF") { digitalWrite(relayPin, picMsg == "ON" ? HIGH : LOW); client.publish(mqtt_topic_status, picMsg.c_str()); // 同步状态到MQTT } } }
三、PIC16F887代码(可选,若需PIC参与控制/读取状态)
用MPLAB X IDE编写,核心是串口通信,实现和ESP的状态同步:
#include <xc.h> #define _XTAL_FREQ 8000000 void UART_Init() { TRISC6 = 1; // RX引脚设为输入 TRISC7 = 1; // TX引脚设为输入 SPBRG = 51; // 9600波特率@8MHz BRGH = 1; SYNC = 0; SPEN = 1; CREN = 1; TXEN = 1; } void UART_Write(char data) { while(!TRMT); TXREG = data; } void UART_Write_String(char *text) { int i; for(i=0;text[i]!='\0';i++) UART_Write(text[i]); } char UART_Read() { while(!RCIF); return RCREG; } void main() { UART_Init(); while(1) { // 读取ESP发来的继电器状态 if(RCIF) { char status = UART_Read(); // 示例:根据状态点亮PIC的LED(RD0引脚) TRISD0 = 0; RD0 = (status == 'O') ? 1 : 0; } // 示例:PIC按键控制继电器(RB0为按键) TRISB0 = 1; if(RB0 == 0) { __delay_ms(20); // 按键消抖 if(RB0 == 0) { UART_Write_String("ON\n"); // 给ESP发送控制指令 while(RB0 == 0); // 等待按键释放 } } } }
四、安卓APP实现(两种方式)
方式1:用现成APP快速验证(适合测试)
比如MQTT Dash或IoT MQTT Panel,安装后配置:
- Broker地址:
mqtt.emqx.io - 端口:1883
- 客户端ID:随便设(别和ESP的重复)
- 订阅主题:
home/relay/status(查看继电器状态) - 发布主题:
home/relay/control(发送ON/OFF指令)
方式2:自定义安卓APP(用Android Studio)
核心是集成org.eclipse.paho.android.service库,步骤如下:
- 在
build.gradle添加依赖:
dependencies { implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.5' implementation 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1' }
- 在
AndroidManifest.xml配置权限和服务:
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <service android:name="org.eclipse.paho.android.service.MqttService" />
- 核心代码(连接MQTT、发送指令、监听状态):
import org.eclipse.paho.android.service.MqttAndroidClient; import org.eclipse.paho.client.mqttv3.*; // 初始化MQTT客户端 String clientId = MqttClient.generateClientId(); MqttAndroidClient client = new MqttAndroidClient(this, "tcp://mqtt.emqx.io:1883", clientId); MqttConnectOptions options = new MqttConnectOptions(); options.setMqttVersion(MqttConnectOptions.MQTT_VERSION_3_1_1); try { IMqttToken token = client.connect(options); token.setActionCallback(new IMqttActionListener() { @Override public void onSuccess(IMqttToken asyncActionToken) { // 连接成功,订阅状态主题 try { client.subscribe("home/relay/status", 0); } catch (MqttException e) { e.printStackTrace(); } } @Override public void onFailure(IMqttToken asyncActionToken, Throwable exception) { // 连接失败处理 } }); } catch (MqttException e) { e.printStackTrace(); } // 设置消息回调,更新继电器状态到UI client.setCallback(new MqttCallback() { @Override public void connectionLost(Throwable cause) {} @Override public void messageArrived(String topic, MqttMessage message) throws Exception { String status = new String(message.getPayload()); // 这里更新APP的UI显示,比如切换按钮状态 } @Override public void deliveryComplete(IMqttDeliveryToken token) {} }); // 发送控制指令的方法 public void sendControlCommand(String command) { try { MqttMessage message = new MqttMessage(command.getBytes()); message.setQos(0); client.publish("home/relay/control", message); } catch (MqttException e) { e.printStackTrace(); } }
五、踩坑提醒
- 电平兼容:ESP是3.3V,PIC是5V,必须加电平转换器(比如TXS0108),直接连会烧ESP引脚!
- 继电器供电:ESP的3.3V输出电流极小,继电器必须外接5V电源,否则无法吸合。
- MQTT主题唯一性:如果有多个设备,给每个设备设置唯一的主题前缀(比如
home/relay/001/control),避免指令混乱。 - 网络稳定性:家庭网络要确保ESP能稳定连接WiFi,信号弱的话加个WiFi放大器。
内容的提问来源于stack exchange,提问作者HM_
相关产品推荐
相关产品推荐

