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

如何基于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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 00:27:24