You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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库,步骤如下:

  1. 在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'
}
  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" />
  1. 核心代码(连接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();
    }
}
五、踩坑提醒
  1. 电平兼容:ESP是3.3V,PIC是5V,必须加电平转换器(比如TXS0108),直接连会烧ESP引脚!
  2. 继电器供电:ESP的3.3V输出电流极小,继电器必须外接5V电源,否则无法吸合。
  3. MQTT主题唯一性:如果有多个设备,给每个设备设置唯一的主题前缀(比如home/relay/001/control),避免指令混乱。
  4. 网络稳定性:家庭网络要确保ESP能稳定连接WiFi,信号弱的话加个WiFi放大器。

内容的提问来源于stack exchange,提问作者HM_

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 12:18:13