如何基于NodeMCU Lua通过SIM800C实现ESP32无WiFi连接云MQTT broker
基于NodeMCU ESP32 + SIM800C的无WiFi环境MQTT电机控制器实现方案
前置准备
- 硬件:ESP32 WROOM-32 DEVKIT V1、SIM800C模块(配GSM天线、开通2G GPRS业务的物联网卡,部署点需有2G信号覆盖)
- 固件:烧录ESP32版本支持Lua 5.1的NodeMCU固件,固件编译时勾选
uart、mqtt、tmr、gpio、wdt模块即可,无需勾选WiFi相关组件 - 接线要求:SIM800C必须独立供电(峰值电流2A,禁止直接从ESP32 3.3V引脚取电),接线如下:
- SIM800C TX 接 ESP32 GPIO16(UART2 RX)
- SIM800C RX 接 ESP32 GPIO17(UART2 TX,建议串1K电阻匹配电平)
- SIM800C GND 与 ESP32 GND 可靠共地
实现思路
不需要移植Arduino平台的C++库,直接通过AT指令控制SIM800C完成GPRS拨号、TCP连接到MQTT broker,进入透传模式后将串口收发逻辑和NodeMCU内置的MQTT客户端做适配即可,纯Lua代码实现,逻辑简单适合无人值守场景。断线恢复直接用节点重启的方式,可靠性远高于复杂的异常捕获逻辑。
完整实现代码
-- 硬件配置 local UART_ID = 2 local MOTOR_CTRL_PIN = 5 -- 电机控制引脚,根据实际接线修改 local REPORT_INTERVAL = 30000 -- 状态上报间隔,单位毫秒 local RECONNECT_DELAY = 10000 -- 重连等待时间,单位毫秒 -- 网络配置,根据实际情况修改 local APN = "CMNET" -- 移动卡填CMNET、联通填UNINET、电信填CTNET,物联网卡以运营商提供参数为准 local MQTT_HOST = "你的MQTT服务器地址" local MQTT_PORT = 1883 local MQTT_CLIENT_ID = "farm_motor_"..node.chipid() local MQTT_USER = "你的MQTT用户名" local MQTT_PWD = "你的MQTT密码" local SUB_TOPIC = "farm/motor/ctrl" local PUB_TOPIC = "farm/motor/status" -- 初始化串口 uart.setup(UART_ID, 9600, 8, uart.PARITY_NONE, uart.STOPBITS_1, 0) -- AT指令发送工具,带超时等待 local function at_send(cmd, expect, timeout_us) uart.write(UART_ID, cmd.."\r\n") local resp = "" local t_start = tmr.now() while tmr.now() - t_start < timeout_us do local len = uart.available(UART_ID) if len > 0 then resp = resp .. uart.read(UART_ID, len) if string.find(resp, expect, 1, true) then return true, resp end end tmr.delay(10000) end return false, resp end -- SIM800C初始化+GPRS联网 local function sim800c_init() -- 波特率同步 local ok = at_send("AT", "OK", 1000000) if not ok then return false end -- 关闭指令回显 at_send("ATE0", "OK", 1000000) -- 检测SIM卡 ok = at_send("AT+CPIN?", "READY", 5000000) if not ok then return false end -- 检测信号质量 at_send("AT+CSQ", "OK", 2000000) -- 配置APN ok = at_send(string.format("AT+CSTT=\"%s\"", APN), "OK", 3000000) if not ok then return false end -- 激活GPRS ok = at_send("AT+CIICR", "OK", 10000000) if not ok then return false end -- 验证IP获取成功 ok = at_send("AT+CIFSR", ".", 5000000) if not ok then return false end -- 配置单连接模式 ok = at_send("AT+CIPMUX=0", "OK", 1000000) return ok end -- MQTT连接与业务逻辑 local function mqtt_start() -- 清理旧连接 at_send("AT+CIPCLOSE", "OK", 2000000) -- 建立到MQTT服务器的TCP连接 local ok = at_send(string.format("AT+CIPSTART=\"TCP\",\"%s\",%d", MQTT_HOST, MQTT_PORT), "CONNECT OK", 15000000) if not ok then return false end -- 进入透传模式 ok = at_send("AT+CIPSEND", ">", 2000000) if not ok then return false end -- 初始化MQTT客户端 local mqtt_cli = mqtt.Client(MQTT_CLIENT_ID, 120, MQTT_USER, MQTT_PWD) -- 串口收到的数据喂给MQTT客户端解析 uart.on(UART_ID, "data", function(data) mqtt_cli:on_data(data) end, 0) -- MQTT客户端要发的数据通过串口透传给SIM800C mqtt_cli:on("send", function(payload) uart.write(UART_ID, payload) end) -- MQTT连接成功回调 mqtt_cli:on("connect", function() -- 订阅控制主题 mqtt_cli:subscribe(SUB_TOPIC, 0) -- 定时上报电机状态 tmr.create():alarm(REPORT_INTERVAL, tmr.ALARM_AUTO, function() local stat = gpio.read(MOTOR_CTRL_PIN) == 1 and "running" or "stopped" mqtt_cli:publish(PUB_TOPIC, stat, 0, 0) end) end) -- 处理控制指令 mqtt_cli:on("message", function(_, topic, payload) if topic ~= SUB_TOPIC then return end if payload == "on" then gpio.write(MOTOR_CTRL_PIN, gpio.HIGH) mqtt_cli:publish(PUB_TOPIC, "running", 0, 0) elseif payload == "off" then gpio.write(MOTOR_CTRL_PIN, gpio.LOW) mqtt_cli:publish(PUB_TOPIC, "stopped", 0, 0) end end) -- 离线重启恢复 mqtt_cli:on("offline", function() tmr.create():alarm(RECONNECT_DELAY, tmr.ALARM_SINGLE, node.restart) end) -- 发起MQTT连接 mqtt_cli:connect(MQTT_HOST, MQTT_PORT, false) return true end -- 主入口 gpio.config({gpio=MOTOR_CTRL_PIN, dir=gpio.OUTPUT}) wdt.setup(30) -- 开启看门狗,30秒喂狗超时自动重启 tmr.create():alarm(5000, tmr.ALARM_AUTO, function(boot_tmr) wdt.feed() if sim800c_init() then boot_tmr:unregister() if mqtt_start() then -- 主循环喂狗 tmr.create():alarm(10000, tmr.ALARM_AUTO, wdt.feed) else tmr.create():alarm(RECONNECT_DELAY, tmr.ALARM_SINGLE, node.restart) end end end)
部署调试要点
- 供电优先:SIM800C发射时电流波动大,必须用独立5V/2A以上电源供电,否则会出现随机掉线、GPRS附着失败的问题
- 信号验证:部署前在安装位置执行
AT+CSQ指令,返回的第一个参数值≥12才能稳定通信,低于10需更换高增益GSM天线 - 流量估算:按30秒上报一次状态计算,单设备每月流量消耗不超过5MB,用最低档的物联网卡即可满足需求
- 电平匹配:SIM800C的RX引脚默认是3.3V耐受,部分老版本模块是5V逻辑,建议ESP32 TX到SIM800C RX之间串1K电阻,避免烧引脚
内容的提问来源于stack exchange,提问作者Abhi
相关产品推荐
相关产品推荐

