物联网云平台数据库选型与搭建全指南(NRF52840, CH585M,ESP32-S3的硬件资源要求选型对比、方案设计、搭建步骤)
物联网云平台数据库选型与搭建全指南(适配LoRaWAN场景)
一、物联网云平台主流数据库对比(含流行度+LoRaWAN适配性)
1. 核心数据库类型对比表
| 数据库类型 | 代表产品 | 流行度 | LoRaWAN适配场景 | 优势 | 劣势 | 部署成本(中小规模) |
|---|---|---|---|---|---|---|
| 时序数据库 | InfluxDB(开源)、TDengine(国产)、TimescaleDB | ★★★★★ | 核心:传感器时序数据(温湿度/电量/信号强度)高频写入、时间范围查询 | 1. 高并发写入(10万+ TPS);2. 时间维度查询极快;3. 按时间自动分片压缩 | 1. 非时序查询能力弱;2. 事务支持差 | 低(单机部署<500元/月) |
| 关系型数据库 | PostgreSQL、MySQL/MariaDB | ★★★★☆ | 辅助:设备配置、用户信息、网关参数、LoRaWAN网络配置(DevEUI/AppEUI) | 1. 事务强一致性;2. SQL生态成熟;3. 复杂关联查询;4. ChirpStack默认配置库 | 1. 时序数据写入性能差;2. 海量数据存储成本高 | 低(云托管RDS 300-800元/月) |
| 文档型NoSQL | MongoDB | ★★★★☆ | 扩展:非结构化设备属性、JSON格式上报数据、多协议设备兼容 | 1. 数据模型灵活(无需预定义表结构);2. 支持嵌套文档;3. 云托管成熟 | 1. 时序查询效率低;2. 写入性能弱于时序库 | 中(云托管MongoDB 500-1500元/月) |
| 键值型NoSQL | Redis | ★★★★★ | 缓存:LoRaWAN网关实时状态、设备在线状态、高频查询数据 | 1. 毫秒级读写;2. 支持过期策略;3. 分布式部署 | 1. 持久化成本高;2. 不适合海量历史数据 | 低(单机Redis 200-500元/月) |
| 云原生时序库 | AWS Timestream、阿里云TSDB | ★★★☆☆ | 大规模LoRaWAN网络(10万+设备)、跨地域部署 | 1. 弹性扩缩容;2. 免运维;3. 与云服务无缝集成 | 1. 成本高;2. 厂商锁定;3. 小规模部署不划算 | 高(按用量计费 1000-5000元/月) |
2. 核心结论
-
物联网云平台最流行:时序数据库(InfluxDB/TDengine)+ 关系型数据库(PostgreSQL)+ 缓存(Redis)的组合(90%以上物联网平台采用);
-
LoRaWAN专属选型:
-
中小规模(<1万设备):InfluxDB(时序)+ PostgreSQL(配置)+ Redis(缓存);
-
大规模(1万+设备):TDengine(分布式时序)+ PostgreSQL(配置)+ Redis Cluster(缓存);
-
云托管优先:AWS Timestream/阿里云TSDB + 云RDS PostgreSQL。
-
二、自建物联网云平台数据库选型指导(分场景)
1. 选型核心原则
| 决策维度 | 优先级 | 选型依据 |
|---|---|---|
| 数据类型 | 最高 | 90% LoRaWAN数据为时序数据→优先时序库;10%为结构化配置数据→关系库 |
| 设备规模 | 高 | <1万设备:单机时序库;1万-10万:分布式时序库;>10万:云原生时序库 |
| 技术栈匹配 | 中 | 熟悉SQL→TimescaleDB;熟悉国产技术→TDengine;轻量化部署→InfluxDB |
| 运维成本 | 中 | 小团队→免运维云托管;有运维团队→开源单机/分布式部署 |
| 成本预算 | 低 | <1000元/月→开源单机;>1000元/月→云托管/分布式开源 |
2. 分场景选型方案
| 场景 | 数据库组合 | 部署方式 | 适用场景 |
|---|---|---|---|
| 入门测试(<100设备) | InfluxDB(单机)+ SQLite(替代PostgreSQL) | 本地服务器/虚拟机 | 实验室验证、LoRaWAN原型开发 |
| 中小规模商用(<1万设备) | InfluxDB + PostgreSQL + Redis(单机) | 云服务器(4核8G) | 园区/楼宇LoRaWAN物联网 |
| 大规模商用(1万-10万设备) | TDengine(集群)+ PostgreSQL(主从)+ Redis Cluster | 云服务器集群(8核16G×3) | 城市级LoRaWAN网络 |
| 云原生部署 | AWS Timestream + RDS PostgreSQL + ElastiCache Redis | 公有云托管 | 跨地域LoRaWAN部署、免运维 |
三、自建物联网云平台数据库搭建详细步骤(中小规模:InfluxDB+PostgreSQL+Redis)
前置准备
-
硬件/云服务器:Linux(Ubuntu 22.04)、4核8G、500G SSD(时序数据占比高);
-
软件:Docker + Docker Compose(推荐容器化部署,简化运维);
-
LoRaWAN网络服务器:ChirpStack(开源,默认适配PostgreSQL+InfluxDB)。
步骤1:环境初始化(Ubuntu 22.04)
Bash
步骤2:容器化部署PostgreSQL(LoRaWAN配置库)
1. 创建配置文件
Bash
2. 启动PostgreSQL
Bash
步骤3:容器化部署InfluxDB(LoRaWAN时序库)
1. 创建配置文件
Bash
2. 启动InfluxDB
Bash
步骤4:容器化部署Redis(缓存)
1. 创建配置文件
Bash
2. 启动Redis
Bash
步骤5:对接LoRaWAN网络服务器(ChirpStack)
1. 部署ChirpStack
Bash
2. 验证数据流转
-
访问ChirpStack Web界面:http://服务器IP:8080(默认账号:admin,密码:admin);
-
添加LoRaWAN设备(DevEUI/AppEUI配置);
-
设备上报数据后,验证数据存储:
Bash
步骤6:数据库基础运维(必做)
1. 数据备份
Bash
2. 时序数据清理(避免磁盘满)
Bash
四、核心例程(数据读写操作)
1. InfluxDB时序数据读写(Python例程)
Python
2. PostgreSQL设备配置读写(Python例程)
Python
五、选型与搭建关键点总结
1. 选型核心
-
LoRaWAN场景优先时序数据库(InfluxDB/TDengine)存储传感器数据,关系库存储配置数据;
-
中小规模优先容器化开源部署 ,大规模优先分布式时序库+云托管;
-
必须搭配Redis缓存提升设备状态查询效率。
2. 搭建关键
-
容器化部署简化运维,优先采用Docker Compose;
-
时序数据库需设置数据保留策略,避免磁盘占满;
-
定期备份配置数据(PostgreSQL)和时序数据(InfluxDB);
-
对接LoRaWAN网络服务器(如ChirpStack)时,确保数据库连接参数一致。
3. 进阶优化
-
设备规模>1万:将InfluxDB替换为TDengine集群,PostgreSQL配置主从复制;
-
需可视化:部署Grafana对接InfluxDB/TDengine,实现LoRaWAN数据大屏;
-
云原生改造:迁移到K8s部署,配合Prometheus监控数据库状态。
六、one_channel_hub硬件搭建物料清单与核心调试步骤速查表
6.1 硬件搭建物料清单(面包板原型验证)
| 物料类别 | 具体物料 | 规格参数 | 数量 | 用途说明 |
|---|---|---|---|---|
| 核心芯片 | CH585M芯片 | QFN28封装,RISC-V架构 | 1片 | 网关主控,负责协议解析、数据转发 |
| 核心芯片 | SX1278 LoRa模块 | 支持470/868/915MHz,UART接口 | 1个 | LoRa信号调制解调,实现无线通信 |
| 供电模块 | AMS1117-3.3V | 线性稳压芯片,输入5V/输出3.3V | 1片 | 为CH585M、SX1278提供稳定3.3V供电 |
| 供电模块 | CH340G芯片 | USB转串口,支持5V供电 | 1片 | USB转UART,用于程序下载和调试 |
| 供电模块 | TP4056芯片 | 锂电池充电管理 | 1片 | 适配锂电池供电场景,实现充电管理 |
| 被动器件 | 晶振 | 12MHz(主时钟)、32.768KHz(RTC) | 各1个 | 为CH585M提供时钟信号,保证系统运行 |
| 被动器件 | 电容 | 0.1μF(陶瓷电容)、10pF(陶瓷电容) | 若干 | 去耦、滤波,稳定电源和时钟信号 |
| 被动器件 | 电阻 | 1KΩ、10KΩ(碳膜电阻) | 若干 | LED限流、GPIO上拉/下拉 |
| 辅助器件 | LED灯 | 直插式,任意颜色 | 2个 | 电源状态指示、LoRa通信状态指示 |
| 辅助器件 | 按键 | 轻触按键,4脚 | 1个 | 系统唤醒、复位控制 |
| 辅助器件 | 锂电池 | 3.7V,容量≥1000mAh | 1块 | 备用供电,适配移动场景 |
| 辅助器件 | USB-TYPE-C接口 | 母座,支持数据+供电 | 1个 | USB供电和数据传输接口 |
| 连接器件 | 面包板 | 半尺寸 | 1个 | 搭建临时电路,方便调试和修改 |
| 连接器件 | 杜邦线 | 公对公、公对母,40P套装 | 1套 | 面包板与器件、器件之间的电路连接 |
| 调试工具 | WCH-Link调试器 | 支持CH58x系列芯片 | 1个 | CH585M程序下载和在线调试 |
| 调试工具 | 万用表 | 支持电压、通断测量 | 1台 | 检测电路通断、电压是否正常 |
6.2 核心调试步骤速查表
| 调试阶段 | 核心步骤 | 操作要点 | 验证标准 | 常见问题与解决办法 |
|---|---|---|---|---|
| 1. 硬件供电调试 | 1. 搭建供电电路;2. 接入电源;3. 测量关键电压 | 1. 注意电源正负极,避免接反;2. 先接USB供电测试,再测试锂电池供电;3. 测量AMS1117输出端电压 | AMS1117输出3.3V±0.1V;电源灯(PB2)正常亮起 | 问题:电源灯不亮 |
| 解决:1. 检查USB线是否接触良好;2. 用万用表测量供电电路通断;3. 更换AMS1117芯片 | ||||
| 2. CH585M最小系统调试 | 1. 完成最小系统搭建;2. 连接WCH-Link调试器;3. 下载测试程序 | 1. 确保晶振、复位电路连接正确;2. WCH-Link接CH585M的SWDIO、SWCLK引脚;3. 测试程序选择简单GPIO翻转程序 | 程序下载成功;测试LED可按设定频率闪烁 | 问题:程序下载失败 |
| 解决:1. 检查WCH-Link驱动是否安装;2. 确认SWD引脚连接正确;3. 检查CH585M复位电路是否正常 | ||||
| 3. UART通信调试 | 1. 搭建UART0(调试)电路;2. 初始化UART0;3. 发送调试信息 | 1. CH340G TX接CH585M PA0,CH340G RX接CH585M PA1;2. 配置UART0波特率115200;3. 打开串口助手接收数据 | 串口助手能正常接收"sys init ok!"调试信息 | 问题:无调试信息输出 |
| 解决:1. 检查CH340G驱动是否安装;2. 核对UART引脚连接;3. 确认波特率与串口助手一致 | ||||
| 4. LoRa模块调试 | 1. 搭建LoRa模块对接电路;2. 复位SX1278;3. 发送AT指令配置;4. 测试数据收发 | 1. SX1278 TX接CH585M PA8,SX1278 RX接CH585M PA9;2. 先执行LoRa复位操作;3. AT指令波特率9600;4. 用另一LoRa模块作为终端测试 | 1. 配置后串口助手接收"lora config ok!";2. 能正常接收终端发送的LoRa数据;3. 发送数据时LoRa状态灯(PB3)闪烁 | 问题:LoRa配置失败/无法收发数据 |
| 解决:1. 检查LoRa模块供电电压;2. 核对UART1波特率;3. 检查SX1278 RST引脚连接;4. 调整LoRa频段与终端一致 | ||||
| 5. 低功耗功能调试 | 1. 配置RTC定时唤醒;2. 编写休眠函数;3. 测试唤醒功能 | 1. RTC配置10秒唤醒;2. 无数据时进入休眠模式;3. 分别测试定时唤醒和按键唤醒 | 1. 休眠时电流≤10μA;2. 10秒后能自动唤醒;3. 按下唤醒按键能立即唤醒 | 问题:无法唤醒/唤醒不及时 |
| 解决:1. 检查RTC晶振连接;2. 核对RTC中断配置;3. 检查按键中断引脚配置 | ||||
| 6. 整体功能联调 | 1. 连接LoRa终端设备;2. 启动网关和终端;3. 验证数据流转 | 1. 终端配置与网关一致(频段、SF、带宽);2. 终端发送传感器数据;3. 查看上位机接收数据 | 1. 网关能接收终端数据并上传至上位机;2. 上位机下发数据能被终端接收;3. 整个链路无丢包(测试100条数据丢包率<3%) | 问题:数据丢包严重 |
| 解决:1. 调整LoRa模块发射功率(提升至17dBm);2. 减小扩频因子;3. 确保网关与终端之间无遮挡 |
6.3 关键参数速记
-
CH585M系统时钟:48MHz;RTC时钟:32.768KHz
-
UART0(调试):波特率115200,引脚PA0(RX)、PA1(TX)
-
UART1(LoRa对接):波特率9600,引脚PA8(RX)、PA9(TX)
-
LoRa模块默认配置:470MHz频段、SF7扩频因子、125KHz带宽、17dBm发射功率
-
休眠唤醒配置:RTC定时10秒唤醒,按键下降沿中断唤醒
七、one_channel_hub LoRa单通道网关MCU选型补充(新增ESP32-S3)
7.1 新增ESP32-S3后的核心参数对比表
| 对比维度 | NRF52840 | CH585M | ESP32-S3 | one_channel_hub适配性评分(★/5) |
|---|---|---|---|---|
| 核心架构 | ARM Cortex-M4F | RISC-V RV32IMAC | Xtensa LX7(双核) | NRF52840:★4.5;CH585M:★4;ESP32-S3:★4.5 |
| 主频 | 64MHz | 48MHz | 240MHz(双核) | ESP32-S3:★5;NRF52840:★4.5;CH585M:★4(均满足需求) |
| Flash/RAM | 1MB Flash + 256KB RAM | 64KB Flash + 16KB RAM | 8MB Flash + 512KB RAM(最小配置) | ESP32-S3:★5;NRF52840:★5;CH585M:★3.5 |
| 通信接口 | 4路UART、3路SPI、2路I2C、BLE 5.0、NFC | 2路UART、1路SPI、1路I2C、BLE 5.0 | 4路UART、4路SPI、2路I2C、BLE 5.0、Wi-Fi 6、USB OTG | ESP32-S3:★5;NRF52840:★5;CH585M:★4 |
| 低功耗性能 | 休眠电流≈2.7μA(仅RTC) | 休眠电流≈1.2μA(仅RTC) | 休眠电流≈5μA(仅RTC) | CH585M:★5;NRF52840:★4.5;ESP32-S3:★4 |
| 封装与成本 | QFN48(7x7mm),单价≈18元 | QFN28(4x4mm),单价≈8元 | QFN56(7x7mm),单价≈15元 | CH585M:★5;ESP32-S3:★4;NRF52840:★3.5 |
| 开发支持 | Nordic SDK、Zephyr OS,LoRa驱动完善 | WCH SDK、RT-Thread,国产支持及时 | ESP-IDF、Arduino,Wi-Fi/BLE生态成熟,LoRa驱动丰富 | ESP32-S3:★5;NRF52840:★4.5;CH585M:★4 |
| 扩展能力 | 支持多协议融合(LoRa+BLE) | 基础单通道需求,扩展受限 | 支持LoRa+Wi-Fi+BLE三协议融合、本地AI处理、大屏扩展 | ESP32-S3:★5;NRF52840:★4.5;CH585M:★3 |
| 供电电压 | 1.7V-3.6V | 2.0V-3.6V | 2.7V-3.6V | 三者均★5(适配锂电池供电) |
7.2 补充ESP32-S3后的选型结论
结合one_channel_hub单通道网关的核心需求(轻量化、成本、功能适配)及三款MCU特性,新增细分场景选型:
-
极致成本/低功耗场景:优先CH585M
理由:单价最低(8元),休眠电流最小(1.2μA),封装小巧,满足纯单通道数据收发核心需求,无功能冗余,适合批量低成本部署场景(如简易数据采集网关)。
-
扩展功能场景(无Wi-Fi需求):优选NRF52840
理由:Flash/RAM充足(1MB+256KB),支持LoRa+BLE融合通信,开发社区成熟,无Wi-Fi模块的冗余功耗,适合需要本地数据存储、多外设扩展的场景(如对接多个传感器的网关)。
-
多协议融合/云对接场景:优选ESP32-S3
理由:自带Wi-Fi 6+BLE 5.0,可直接实现LoRa数据通过Wi-Fi上传至云平台,无需额外添加Wi-Fi模块;双核240MHz算力充足,支持后续功能迭代(如本地数据解析、边缘计算),适合需要直接对接物联网云平台的场景。
后续补充基于ESP32-S3的方案设计、搭建步骤及例程,与原有CH585M、NRF52840方案形成互补。
7.3 基于三款MCU的one_channel_hub方案设计(补充NRF52840)
7.3.1 核心功能定位(分MCU)
-
NRF52840方案:实现LoRa单通道数据收发+BLE辅助调试/本地数据交互,支持多外设扩展(如传感器、SD卡本地存储),适配无Wi-Fi环境、需本地数据处理的单通道网关场景。
-
CH585M方案:实现LoRa单通道数据收发核心功能,极简设计,适配低成本、低功耗、无扩展需求的批量部署场景。
-
ESP32-S3方案:实现LoRa单通道数据收发+Wi-Fi云对接+BLE调试,支持多协议融合,适配需直接上云、功能迭代的场景。
实现LoRa单通道数据收发,通过Wi-Fi直接对接物联网云平台(如阿里云、腾讯云),支持BLE调试、本地数据缓存、设备状态监控及低功耗模式,适配需要直接上云的单通道网关场景。
7.3.2 硬件方案设计(核心原理图框架-分MCU)
7.3.2.1 NRF52840硬件方案
- 核心供电模块
- 输入:5V USB供电 或 3.7V锂电池供电;
- 稳压:采用AMS1117-3.3V稳压芯片,输出3.3V给NRF52840、LoRa模块、BLE天线供电;
- 电源管理:TP4056充电管理芯片(适配锂电池),电源开关+电源指示灯。
- NRF52840核心电路
- 最小系统:外接64MHz晶振(主时钟)、32.768KHz晶振(RTC时钟);
- 复位电路:采用RC复位电路,搭配复位按键;
- 下载接口:SWD调试接口(SWDIO、SWCLK引脚),搭配WCH-Link调试器。
- LoRa模块接口电路(对接SX1278)
- 通信接口:NRF52840的UART1(GPIO24-TX、GPIO25-RX)对接SX1278的UART接口;
- 控制接口:GPIO26作为SX1278复位引脚,GPIO27作为SX1278状态指示引脚;
- 电源:3.3V供电,添加0.1μF去耦电容。
- BLE与调试接口
- BLE接口:NRF52840自带BLE 5.0模块,外接2.4G BLE天线;
- UART调试:UART0(GPIO6-TX、GPIO8-RX)对接CH340G USB转串口芯片,用于程序下载和调试。
- 扩展功能电路
- 状态指示:2个LED灯(GPIO13-电源灯,GPIO14-LoRa通信状态灯);
- 按键:2个功能按键(GPIO15-复位按键,GPIO16-配置按键);
- 扩展接口:SPI接口(GPIO19-SCK、GPIO20-MOSI、GPIO21-MISO),可对接SD卡模块实现本地数据存储。
7.3.2.2 CH585M硬件方案(沿用原有)
- 核心供电模块
- 输入:5V USB供电 或 3.7V锂电池供电;
- 稳压:采用AMS1117-3.3V稳压芯片,输出3.3V给CH585M、SX1278模块供电;
- 电源管理:TP4056充电管理芯片(适配锂电池),电源开关+电源指示灯。
- CH585M核心电路
- 最小系统:外接12MHz晶振(主时钟)、32.768KHz晶振(RTC时钟);
- 复位电路:采用RC复位电路,搭配复位按键;
- 下载接口:SWD调试接口,搭配WCH-Link调试器。
- LoRa模块接口电路(对接SX1278)
- 通信接口:CH585M的UART1(PA8-TX、PA9-RX)对接SX1278的UART接口;
- 控制接口:GPIO4作为SX1278复位引脚;
- 电源:3.3V供电,添加0.1μF去耦电容。
- 调试接口
- UART调试:UART0(PA0-RX、PA1-TX)对接CH340G USB转串口芯片,用于程序调试。
- 辅助功能电路
- 状态指示:2个LED灯(PB2-电源灯,PB3-LoRa通信状态灯);
- 按键:1个复位按键。
7.3.2.3 ESP32-S3硬件方案(沿用原有)
- 核心供电模块
- 输入:5V USB供电 或 3.7V锂电池供电;
- 稳压:采用AMS1117-3.3V稳压芯片,输出3.3V给ESP32-S3、LoRa模块供电;
- 电源管理:TP4056充电管理芯片(适配锂电池),电源开关+电源指示灯。
- ESP32-S3核心电路
- 最小系统:外接40MHz晶振(主时钟)、32.768KHz晶振(RTC时钟);
- 复位电路:采用RC复位电路,搭配复位按键;
- 下载接口:USB Type-C接口(直接用于程序下载和调试,无需额外USB转串口芯片)。
- LoRa模块接口电路(对接SX1278)
- 通信接口:ESP32-S3的UART2(GPIO17-TX、GPIO16-RX)对接SX1278的UART接口;
- 控制接口:GPIO4作为SX1278复位引脚,GPIO5作为SX1278状态指示引脚;
- 电源:3.3V供电,添加0.1μF去耦电容。
- 云对接与调试接口
- Wi-Fi接口:ESP32-S3自带Wi-Fi模块,无需额外电路,通过天线座外接2.4G Wi-Fi天线;
- BLE调试:利用ESP32-S3自带BLE功能,支持手机APP调试;
- 备用UART调试:UART0(GPIO1-TX、GPIO3-RX),可外接CH340G用于串口调试。
- 辅助功能电路
- 状态指示:2个LED灯(GPIO2-电源灯,GPIO15-LoRa通信状态灯);
- 按键:2个功能按键(GPIO0-复位按键,GPIO14-配置按键,用于Wi-Fi配网)。
- 核心供电模块
- 输入:5V USB供电 或 3.7V锂电池供电;
- 稳压:采用AMS1117-3.3V稳压芯片,输出3.3V给ESP32-S3、LoRa模块供电;
- 电源管理:TP4056充电管理芯片(适配锂电池),电源开关+电源指示灯。
- ESP32-S3核心电路
- 最小系统:外接40MHz晶振(主时钟)、32.768KHz晶振(RTC时钟);
- 复位电路:采用RC复位电路,搭配复位按键;
- 下载接口:USB Type-C接口(直接用于程序下载和调试,无需额外USB转串口芯片)。
- LoRa模块接口电路(对接SX1278)
- 通信接口:ESP32-S3的UART2(GPIO17-TX、GPIO16-RX)对接SX1278的UART接口;
- 控制接口:GPIO4作为SX1278复位引脚,GPIO5作为SX1278状态指示引脚;
- 电源:3.3V供电,添加0.1μF去耦电容。
- 云对接与调试接口
- Wi-Fi接口:ESP32-S3自带Wi-Fi模块,无需额外电路,通过天线座外接2.4G Wi-Fi天线;
- BLE调试:利用ESP32-S3自带BLE功能,支持手机APP调试;
- 备用UART调试:UART0(GPIO1-TX、GPIO3-RX),可外接CH340G用于串口调试。
- 辅助功能电路
- 状态指示:2个LED灯(GPIO2-电源灯,GPIO15-LoRa通信状态灯);
- 按键:2个功能按键(GPIO0-复位按键,GPIO14-配置按键,用于Wi-Fi配网)。
7.3.3 软件方案设计(核心流程-分MCU)
7.3.3.1 NRF52840软件方案
- 系统初始化流程
- 上电复位后,初始化NRF52840核心外设:时钟(64MHz)、UART1(LoRa对接)、UART0(调试)、GPIO(LED/按键)、RTC、BLE;
- 初始化LoRa模块:通过UART1发送AT指令,配置LoRa频段、扩频因子、带宽等参数;
- BLE初始化:配置BLE广播名称,设置数据收发服务和特征值,支持手机APP连接调试。
- 数据收发与本地交互流程
- 接收流程:NRF52840通过UART1接收SX1278的LoRa数据,解析后通过BLE发送至手机APP,同时可通过SPI接口将数据存储至SD卡(可选);
- 发送流程:手机APP通过BLE下发指令,NRF52840接收后通过UART1发送至SX1278,由SX1278调制为LoRa信号发送,发送完成后向APP反馈状态。
- 低功耗流程
- 无数据收发时,NRF52840进入低功耗模式(仅保留RTC和BLE广播);
- 定时唤醒:RTC定时10秒唤醒,检查LoRa数据和BLE连接状态;
- 按键唤醒:配置按键触发外部中断唤醒系统。
7.3.3.2 CH585M软件方案(沿用原有)
- 系统初始化流程
- 上电复位后,初始化CH585M核心外设:时钟(48MHz)、UART1(LoRa对接)、UART0(调试)、GPIO(LED/按键)、RTC;
- 初始化LoRa模块:通过UART1发送AT指令,配置LoRa频段、扩频因子、带宽等参数。
- 数据收发流程
- 接收流程:CH585M通过UART1接收SX1278的LoRa数据,解析后通过UART0发送至上位机;
- 发送流程:上位机通过UART0下发指令,CH585M接收后通过UART1发送至SX1278,由SX1278调制为LoRa信号发送。
- 低功耗流程
- 无数据收发时,CH585M进入休眠模式(仅保留RTC);
- 定时唤醒:RTC定时10秒唤醒,检查LoRa数据;
- 按键唤醒:配置按键触发外部中断唤醒系统。
7.3.3.3 ESP32-S3软件方案(沿用原有)
- 系统初始化流程
- 上电复位后,初始化ESP32-S3核心外设:时钟(240MHz)、UART2(LoRa对接)、GPIO(LED/按键)、RTC、Wi-Fi、BLE;
- 初始化LoRa模块:通过UART2发送AT指令,配置LoRa频段、扩频因子、带宽等参数;
- Wi-Fi配网:支持AirKiss配网或按键触发配网,连接指定Wi-Fi热点。
- 数据收发与云对接流程
- 接收流程:ESP32-S3通过UART2接收SX1278的LoRa数据,解析后通过Wi-Fi上传至云平台,同时本地缓存数据(防止网络中断);
- 发送流程:云平台下发指令,ESP32-S3接收后通过UART2发送至SX1278,由SX1278调制为LoRa信号发送,发送完成后向云平台反馈状态。
- 低功耗流程
- 无数据收发时,ESP32-S3进入轻度休眠模式(仅保留RTC和Wi-Fi心跳);
- 定时唤醒:RTC定时10秒唤醒,检查LoRa数据和Wi-Fi连接状态;
- 按键唤醒:配置按键触发外部中断唤醒系统。
- 系统初始化流程
- 上电复位后,初始化ESP32-S3核心外设:时钟(240MHz)、UART2(LoRa对接)、GPIO(LED/按键)、RTC、Wi-Fi、BLE;
- 初始化LoRa模块:通过UART2发送AT指令,配置LoRa频段、扩频因子、带宽等参数;
- Wi-Fi配网:支持AirKiss配网或按键触发配网,连接指定Wi-Fi热点。
- 数据收发与云对接流程
- 接收流程:ESP32-S3通过UART2接收SX1278的LoRa数据,解析后通过Wi-Fi上传至云平台,同时本地缓存数据(防止网络中断);
- 发送流程:云平台下发指令,ESP32-S3接收后通过UART2发送至SX1278,由SX1278调制为LoRa信号发送,发送完成后向云平台反馈状态。
- 低功耗流程
- 无数据收发时,ESP32-S3进入轻度休眠模式(仅保留RTC和Wi-Fi心跳);
- 定时唤醒:RTC定时10秒唤醒,检查LoRa数据和Wi-Fi连接状态;
- 按键唤醒:配置按键触发外部中断唤醒系统。
7.4 基于三款MCU的one_channel_hub搭建详细步骤
7.4.1 NRF52840搭建步骤(面包板原型验证)
- 前置准备物料
- 核心芯片:NRF52840开发板、SX1278 LoRa模块;
- 通信器件:2.4G BLE天线(IPEX接口)、64MHz晶振、32.768KHz晶振;
- 辅助器件:AMS1117-3.3V、TP4056、CH340G、LED、按键、SD卡模块(可选);
- 连接器件:面包板、杜邦线(公对公、公对母);
- 调试工具:WCH-Link调试器、万用表。
-
分步搭建与测试
-
搭建供电电路
- AMS1117-3.3V输入接5V(USB或锂电池经TP4056),输出3.3V;
- 3.3V分别给NRF52840开发板、SX1278模块、CH340G供电;
- 接入电源,测试电源灯(GPIO13)亮,供电稳定。
- 搭建调试接口电路
- CH340G TX接NRF52840 GPIO6(UART0_RX),CH340G RX接NRF52840 GPIO8(UART0_TX);
- 安装CH340G驱动,打开串口助手,配置波特率115200。
- 搭建LoRa模块对接电路
- SX1278 VCC接3.3V,GND接GND;
- SX1278 TX接NRF52840 GPIO25(UART1_RX),SX1278 RX接NRF52840 GPIO24(UART1_TX);
- SX1278 RST接NRF52840 GPIO26,SX1278 DIO0接NRF52840 GPIO27;
- 连接BLE天线至NRF52840开发板的IPEX接口。
- 搭建扩展功能电路(可选)
- SD卡模块VCC接3.3V,GND接GND;
- SD卡模块 SCK接NRF52840 GPIO19,MOSI接GPIO20,MISO接GPIO21,CS接GPIO22;
- 配置按键(GPIO16)串联10K上拉电阻接3.3V,另一端接GND。
- 硬件自检
- 接通电源,电源灯亮;
- 按下复位按键,NRF52840正常启动,无异常发热;
- 串口助手接收"sys init ok!"调试信息。
7.4.2 NRF52840软件搭建步骤(基于Nordic SDK)
- 开发环境搭建
- 下载并安装Nordic SDK v17.0.2:访问https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/gs_installing.html,按指南安装环境;
- 安装SEGGER Embedded Studio(SES):用于NRF52840程序开发和调试;
- 新建项目:在SES中新建"nrf52840_xxaa"项目,选择Nordic SDK模板。
- 核心代码开发与调试
- 初始化外设:编写uart_init.c、ble_init.c、lora_init.c,分别初始化UART0(调试)、UART1(LoRa)、BLE、LoRa模块;
- 数据收发逻辑:编写lora_comm.c,实现LoRa数据收发与BLE数据交互;
- 扩展功能开发(可选):编写sdcard.c,实现SD卡本地数据存储;
- 下载调试:通过WCH-Link将程序下载到NRF52840,利用SES查看调试信息,通过手机APP连接BLE验证数据交互。
7.4.3 CH585M与ESP32-S3搭建步骤(沿用原有)
CH585M搭建步骤参考原有2. 硬件搭建物料清单与核心调试步骤速查表;ESP32-S3搭建步骤参考原有7.4 基于ESP32-S3的one_channel_hub搭建详细步骤。
7.4.1 硬件搭建步骤(面包板原型验证)
- 前置准备物料(新增/调整部分)
- 核心芯片:ESP32-S3-DevKitC-1开发板(替代裸芯片,简化开发)、SX1278 LoRa模块;
- 辅助器件:2.4G Wi-Fi天线(IPEX接口)、40MHz晶振、32.768KHz晶振;
- 其他物料:与CH585M方案通用(AMS1117、TP4056、LED、按键等)。
-
分步搭建与测试
-
搭建供电电路
- 同CH585M方案,AMS1117-3.3V输出3.3V,分别给ESP32-S3开发板、SX1278模块供电;
- 接入锂电池,测试TP4056充电功能,确保供电稳定。
- 搭建LoRa模块对接电路
- SX1278 VCC接3.3V,GND接GND;
- SX1278 TX接ESP32-S3 GPIO16(UART2_RX),SX1278 RX接ESP32-S3 GPIO17(UART2_TX);
- SX1278 RST接ESP32-S3 GPIO4,SX1278 DIO0接ESP32-S3 GPIO5;
- 连接Wi-Fi天线至ESP32-S3开发板的IPEX接口。
- 搭建辅助功能电路
- LED灯:GPIO2接电源灯(串联1K电阻),GPIO15接LoRa状态灯(串联1K电阻);
- 按键:GPIO14接配置按键(串联10K上拉电阻),复位按键使用开发板自带按键。
- 硬件自检
- 接通电源,电源灯亮;
- 按下复位按键,ESP32-S3正常启动,无异常发热。
7.4.2 软件搭建步骤(基于ESP-IDF)
- 开发环境搭建
- 下载并安装ESP-IDF v5.0及以上版本:访问https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32s3/get-started/index.html,按指南安装环境;
- 新建项目:在ESP-IDF中新建项目,选择"esp32s3_devkitc_1"开发板;
- 添加组件:添加UART、Wi-Fi、LoRa相关组件,配置组件参数。
- 核心代码开发与调试
- 初始化外设:编写uart_init.c、wifi_init.c、lora_init.c,分别初始化UART2、Wi-Fi、LoRa模块;
- 云对接开发:编写mqtt_client.c,实现通过MQTT协议对接物联网云平台;
- 数据收发逻辑:编写lora_comm.c,实现LoRa数据收发与云平台数据交互;
- 下载调试:通过USB Type-C将程序下载到ESP32-S3,利用ESP-IDF Monitor查看调试信息。
7.5 基于三款MCU的核心例程代码
7.5.1 NRF52840核心例程(UART+LoRa+BLE)
Plain
#include "nrf_drv_uart.h"
#include "nrf_drv_gpiote.h"
#include "ble_nus.h"
#include "nrf_delay.h"
#include <string.h>
// 引脚定义
#define LORA_RST_PIN 26
#define LORA_DIO0_PIN 27
#define LED_LORA_PIN 14
#define LED_POWER_PIN 13
#define KEY_CONFIG_PIN 16
// UART1配置(对接SX1278,9600波特率)
#define UART_LORA_INSTANCE 1
#define UART_TX_PIN 24
#define UART_RX_PIN 25
#define UART_BUF_SIZE 128
// BLE相关定义
#define BLE_DEVICE_NAME "LoRa_Gateway_NRF52840"
static ble_nus_t m_nus;
static uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID;
// UART句柄
static const nrf_drv_uart_t uart_lora = NRF_DRV_UART_INSTANCE(UART_LORA_INSTANCE);
static uint8_t uart_rx_buf[UART_BUF_SIZE];
static uint8_t uart_tx_buf[UART_BUF_SIZE];
static uint16_t uart_rx_len = 0;
// GPIO初始化
static void gpio_init(void)
{
ret_code_t err_code;
// 初始化GPIOTE驱动
err_code = nrf_drv_gpiote_init();
APP_ERROR_CHECK(err_code);
// LED引脚:推挽输出
nrf_drv_gpiote_out_config_t out_config = NRF_DRV_GPIOTE_OUT_CONFIG_INIT_HIGH(false);
err_code = nrf_drv_gpiote_out_init(LED_POWER_PIN, &out_config);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_gpiote_out_init(LED_LORA_PIN, &out_config);
APP_ERROR_CHECK(err_code);
nrf_drv_gpiote_out_clear(LED_LORA_PIN); // LoRa灯灭
// LoRa复位引脚:推挽输出
err_code = nrf_drv_gpiote_out_init(LORA_RST_PIN, &out_config);
APP_ERROR_CHECK(err_code);
nrf_drv_gpiote_out_set(LORA_RST_PIN); // 默认不复位
// 配置按键:上拉输入,下降沿中断
nrf_drv_gpiote_in_config_t in_config = NRF_DRV_GPIOTE_IN_CONFIG_INIT(NRF_GPIOTE_POLARITY_HITOLO, NRF_GPIO_PIN_PULLUP);
err_code = nrf_drv_gpiote_in_init(KEY_CONFIG_PIN, &in_config, NULL);
APP_ERROR_CHECK(err_code);
nrf_drv_gpiote_in_enable(KEY_CONFIG_PIN);
}
// UART事件回调函数
static void uart_event_handler(nrf_drv_uart_event_t const * p_event, void * p_context)
{
switch (p_event->type)
{
case NRF_DRV_UART_EVT_RX_DONE:
uart_rx_len = p_event->data.rx.length;
// 接收LoRa数据,通过BLE发送
if (m_conn_handle != BLE_CONN_HANDLE_INVALID)
{
ble_nus_data_send(&m_nus, uart_rx_buf, &uart_rx_len, m_conn_handle);
nrf_drv_gpiote_out_set(LED_LORA_PIN);
nrf_delay_ms(100);
nrf_drv_gpiote_out_clear(LED_LORA_PIN);
}
// 继续接收
nrf_drv_uart_rx(&uart_lora, uart_rx_buf, UART_BUF_SIZE);
break;
case NRF_DRV_UART_EVT_TX_DONE:
break;
default:
break;
}
}
// UART初始化
static void uart_init(void)
{
ret_code_t err_code;
nrf_drv_uart_config_t uart_config = NRF_DRV_UART_DEFAULT_CONFIG;
uart_config.pseltx = UART_TX_PIN;
uart_config.pselrx = UART_RX_PIN;
uart_config.baudrate = NRF_UART_BAUDRATE_9600;
err_code = nrf_drv_uart_init(&uart_lora, &uart_config, uart_event_handler, NULL);
APP_ERROR_CHECK(err_code);
// 启用接收
nrf_drv_uart_rx(&uart_lora, uart_rx_buf, UART_BUF_SIZE);
}
// LoRa模块复位
static void lora_reset(void)
{
nrf_drv_gpiote_out_clear(LORA_RST_PIN);
nrf_delay_ms(100);
nrf_drv_gpiote_out_set(LORA_RST_PIN);
nrf_delay_ms(100);
}
// LoRa模块配置(AT指令)
static void lora_config(void)
{
lora_reset();
nrf_delay_ms(500);
// SX1278 AT指令配置(470MHz,SF7,125KHz)
const char *at_cmds[] = {
"AT+FREQ=470000000\r\n",
"AT+SF=7\r\n",
"AT+BW=125\r\n",
"AT+CR=4\r\n",
"AT+POWER=17\r\n",
"AT+MODE=1\r\n",
"AT+SAVE\r\n"
};
for (int i = 0; i < sizeof(at_cmds)/sizeof(at_cmds[0]); i++)
{
strcpy((char*)uart_tx_buf, at_cmds[i]);
nrf_drv_uart_tx(&uart_lora, uart_tx_buf, strlen(at_cmds[i]));
nrf_delay_ms(200);
}
// 发送初始化完成标识
const char *init_ok = "LoRa module config ok!\r\n";
strcpy((char*)uart_tx_buf, init_ok);
nrf_drv_uart_tx(&uart_lora, uart_tx_buf, strlen(init_ok));
}
// BLE连接事件回调函数
static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
{
ret_code_t err_code;
switch (p_ble_evt->header.evt_id)
{
case BLE_GAP_EVT_CONNECTED:
m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
break;
case BLE_GAP_EVT_DISCONNECTED:
m_conn_handle = BLE_CONN_HANDLE_INVALID;
break;
case BLE_GATTS_EVT_WRITE:
// 接收BLE下发指令,通过LoRa发送
nrf_drv_uart_tx(&uart_lora, p_ble_evt->evt.gatts_evt.params.write.data, p_ble_evt->evt.gatts_evt.params.write.len);
nrf_drv_gpiote_out_set(LED_LORA_PIN);
nrf_delay_ms(100);
nrf_drv_gpiote_out_clear(LED_LORA_PIN);
break;
default:
break;
}
}
// BLE初始化
static void ble_init(void)
{
ret_code_t err_code;
ble_stack_init_t init = {0};
ble_gap_conn_params_t gap_conn_params = {0};
ble_gap_sec_params_t gap_sec_params = {0};
// 初始化BLE协议栈
err_code = ble_stack_init(&init);
APP_ERROR_CHECK(err_code);
// 设置BLE事件回调
NRF_SDH_BLE_OBSERVER(m_ble_observer, NRF_SDH_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
// 初始化NUS服务(Nordic UART Service)
ble_nus_init_t nus_init = {0};
nus_init.data_handler = NULL;
err_code = ble_nus_init(&m_nus, &nus_init);
APP_ERROR_CHECK(err_code);
// 配置GAP参数
memset(&gap_conn_params, 0, sizeof(gap_conn_params));
gap_conn_params.min_conn_interval = NRF_BLE_GAP_MIN_CONN_INTERVAL;
gap_conn_params.max_conn_interval = NRF_BLE_GAP_MAX_CONN_INTERVAL;
gap_conn_params.slave_latency = 0;
gap_conn_params.conn_sup_timeout = NRF_BLE_GAP_CONN_SUP_TIMEOUT;
err_code = sd_ble_gap_ppcp_set(&gap_conn_params);
APP_ERROR_CHECK(err_code);
// 设置设备名称
err_code = sd_ble_gap_device_name_set(&(ble_gap_device_name_t){.name = (uint8_t*)BLE_DEVICE_NAME, .len = strlen(BLE_DEVICE_NAME)});
APP_ERROR_CHECK(err_code);
// 启动BLE广播
err_code = sd_ble_gap_adv_start(&(ble_gap_adv_params_t){.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED, .interval = NRF_BLE_GAP_ADV_INTERVAL});
APP_ERROR_CHECK(err_code);
}
// 系统初始化入口
void sys_init(void)
{
// 初始化GPIO
gpio_init();
// 初始化UART
uart_init();
// 初始化BLE
ble_init();
// 初始化LoRa模块
lora_config();
}
// 主函数入口
int main(void)
{
// 系统初始化
sys_init();
// 进入主循环
while (1)
{
nrf_delay_ms(1000);
}
}
7.5.1 外设初始化例程(UART+LoRa+Wi-Fi)
Plain
#include "esp_err.h"
#include "esp_log.h"
#include "driver/uart.h"
#include "driver/gpio.h"
#include "wifi.h"
#include <string.h>
// 引脚定义
#define LORA_RST_PIN GPIO_NUM_4
#define LORA_DIO0_PIN GPIO_NUM_5
#define LED_LORA_PIN GPIO_NUM_15
#define LED_POWER_PIN GPIO_NUM_2
#define KEY_CONFIG_PIN GPIO_NUM_14
// UART2配置(对接SX1278,9600波特率)
#define UART_NUM_LORA UART_NUM_2
#define UART_TX_PIN GPIO_NUM_17
#define UART_RX_PIN GPIO_NUM_16
#define BUF_SIZE 1024
static const char *TAG = "lora_gateway";
// GPIO初始化
void gpio_init(void)
{
// LED引脚:推挽输出
gpio_reset_pin(LED_POWER_PIN);
gpio_reset_pin(LED_LORA_PIN);
gpio_set_direction(LED_POWER_PIN, GPIO_MODE_OUTPUT);
gpio_set_direction(LED_LORA_PIN, GPIO_MODE_OUTPUT);
gpio_set_level(LED_POWER_PIN, 1); // 电源灯亮
gpio_set_level(LED_LORA_PIN, 0); // LoRa灯灭
// LoRa复位引脚:推挽输出
gpio_reset_pin(LORA_RST_PIN);
gpio_set_direction(LORA_RST_PIN, GPIO_MODE_OUTPUT);
gpio_set_level(LORA_RST_PIN, 1); // 默认不复位
// 配置按键:上拉输入
gpio_reset_pin(KEY_CONFIG_PIN);
gpio_set_direction(KEY_CONFIG_PIN, GPIO_MODE_INPUT);
gpio_set_pull_mode(KEY_CONFIG_PIN, GPIO_PULLUP_ONLY);
}
// UART初始化
void uart_init(void)
{
const uart_config_t uart_config = {
.baud_rate = 9600,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_APB,
};
// 配置UART参数
uart_param_config(UART_NUM_LORA, &uart_config);
// 设置UART引脚
uart_set_pin(UART_NUM_LORA, UART_TX_PIN, UART_RX_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
// 安装UART驱动
uart_driver_install(UART_NUM_LORA, BUF_SIZE * 2, 0, 0, NULL, 0);
}
// LoRa模块复位
void lora_reset(void)
{
gpio_set_level(LORA_RST_PIN, 0);
vTaskDelay(pdMS_TO_TICKS(100));
gpio_set_level(LORA_RST_PIN, 1);
vTaskDelay(pdMS_TO_TICKS(100));
}
// LoRa模块配置(AT指令)
void lora_config(void)
{
lora_reset();
vTaskDelay(pdMS_TO_TICKS(500));
// SX1278 AT指令配置(470MHz,SF7,125KHz)
const char *at_cmds[] = {
"AT+FREQ=470000000\r\n",
"AT+SF=7\r\n",
"AT+BW=125\r\n",
"AT+CR=4\r\n",
"AT+POWER=17\r\n",
"AT+MODE=1\r\n",
"AT+SAVE\r\n"
};
for (int i = 0; i < sizeof(at_cmds)/sizeof(at_cmds[0]); i++) {
uart_write_bytes(UART_NUM_LORA, at_cmds[i], strlen(at_cmds[i]));
vTaskDelay(pdMS_TO_TICKS(200));
// 接收模块响应,验证配置结果
uint8_t buf[64];
int len = uart_read_bytes(UART_NUM_LORA, buf, sizeof(buf)-1, pdMS_TO_TICKS(100));
if (len > 0) {
buf[len] = '\0';
ESP_LOGI(TAG, "LoRa config response: %s", buf);
}
}
ESP_LOGI(TAG, "LoRa module config ok!");
}
// 系统初始化入口
void sys_init(void)
{
// 初始化GPIO
gpio_init();
// 初始化UART
uart_init();
// 初始化Wi-Fi(配网)
wifi_init_sta(); // 自定义Wi-Fi STA模式初始化函数
// 初始化LoRa模块
lora_config();
ESP_LOGI(TAG, "System init ok!");
}
7.5.2 LoRa数据收发与Wi-Fi云上传例程(MQTT协议)
Plain
#include "esp_err.h"
#include "esp_log.h"
#include "driver/uart.h"
#include "mqtt_client.h"
#include "string.h"
static const char *TAG = "lora_cloud";
static esp_mqtt_client_handle_t client;
// MQTT连接配置(对接阿里云示例)
#define MQTT_BROKER_URL "mqtt://xxx.iot-as-mqtt.cn-shanghai.aliyuncs.com:1883"
#define MQTT_CLIENT_ID "xxx|securemode=3,tlsVersion=1,signmethod=hmacsha1|"
#define MQTT_USERNAME "xxx&xxx"
#define MQTT_PASSWORD "xxx"
#define MQTT_PUB_TOPIC "/sys/xxx/xxx/thing/event/property/post"
// MQTT事件回调函数
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
esp_mqtt_event_handle_t event = event_data;
switch (event->event_id) {
case MQTT_EVENT_CONNECTED:
ESP_LOGI(TAG, "MQTT connected!");
break;
case MQTT_EVENT_DISCONNECTED:
ESP_LOGI(TAG, "MQTT disconnected!");
break;
case MQTT_EVENT_DATA:
ESP_LOGI(TAG, "Received MQTT data: %.*s", event->data_len, event->data);
// 接收云平台下发指令,通过LoRa发送
uart_write_bytes(UART_NUM_LORA, event->data, event->data_len);
gpio_set_level(LED_LORA_PIN, 1);
vTaskDelay(pdMS_TO_TICKS(100));
gpio_set_level(LED_LORA_PIN, 0);
break;
default:
break;
}
}
// MQTT客户端初始化
void mqtt_client_init(void)
{
const esp_mqtt_client_config_t mqtt_config = {
.uri = MQTT_BROKER_URL,
.client_id = MQTT_CLIENT_ID,
.username = MQTT_USERNAME,
.password = MQTT_PASSWORD,
};
client = esp_mqtt_client_init(&mqtt_config);
esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
esp_mqtt_client_start(client);
}
// LoRa数据接收与云上传任务
void lora_cloud_task(void *pvParameters)
{
uint8_t lora_buf[128];
while (1) {
// 读取LoRa数据
int len = uart_read_bytes(UART_NUM_LORA, lora_buf, sizeof(lora_buf)-1, pdMS_TO_TICKS(1000));
if (len > 0) {
lora_buf[len] = '\0';
ESP_LOGI(TAG, "Received LoRa data: %s", lora_buf);
// 构造MQTT上传数据(JSON格式)
char pub_buf[256];
snprintf(pub_buf, sizeof(pub_buf),
"{\"method\":\"thing.event.property.post\",\"params\":{\"lora_data\":\"%s\"}}",
lora_buf);
// 上传至云平台
int ret = esp_mqtt_client_publish(client, MQTT_PUB_TOPIC, pub_buf, 0, 1, 0);
if (ret > 0) {
ESP_LOGI(TAG, "MQTT publish success, msg_id: %d", ret);
gpio_set_level(LED_LORA_PIN, 1);
vTaskDelay(pdMS_TO_TICKS(100));
gpio_set_level(LED_LORA_PIN, 0);
} else {
ESP_LOGE(TAG, "MQTT publish failed");
}
}
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
// 主函数入口
void app_main(void)
{
// 系统初始化
sys_init();
// MQTT客户端初始化
mqtt_client_init();
// 创建LoRa数据收发与云上传任务
xTaskCreate(lora_cloud_task, "lora_cloud_task", 4096, NULL, 5, NULL);
}
Plain
#include "esp_err.h"
#include "esp_log.h"
#include "driver/uart.h"
#include "driver/gpio.h"
#include "wifi.h"
#include <string.h>
// 引脚定义
#define LORA_RST_PIN GPIO_NUM_4
#define LORA_DIO0_PIN GPIO_NUM_5
#define LED_LORA_PIN GPIO_NUM_15
#define LED_POWER_PIN GPIO_NUM_2
#define KEY_CONFIG_PIN GPIO_NUM_14
// UART2配置(对接SX1278,9600波特率)
#define UART_NUM_LORA UART_NUM_2
#define UART_TX_PIN GPIO_NUM_17
#define UART_RX_PIN GPIO_NUM_16
#define BUF_SIZE 1024
static const char *TAG = "lora_gateway";
// GPIO初始化
void gpio_init(void)
{
// LED引脚:推挽输出
gpio_reset_pin(LED_POWER_PIN);
gpio_reset_pin(LED_LORA_PIN);
gpio_set_direction(LED_POWER_PIN, GPIO_MODE_OUTPUT);
gpio_set_direction(LED_LORA_PIN, GPIO_MODE_OUTPUT);
gpio_set_level(LED_POWER_PIN, 1); // 电源灯亮
gpio_set_level(LED_LORA_PIN, 0); // LoRa灯灭
// LoRa复位引脚:推挽输出
gpio_reset_pin(LORA_RST_PIN);
gpio_set_direction(LORA_RST_PIN, GPIO_MODE_OUTPUT);
gpio_set_level(LORA_RST_PIN, 1); // 默认不复位
// 配置按键:上拉输入
gpio_reset_pin(KEY_CONFIG_PIN);
gpio_set_direction(KEY_CONFIG_PIN, GPIO_MODE_INPUT);
gpio_set_pull_mode(KEY_CONFIG_PIN, GPIO_PULLUP_ONLY);
}
// UART初始化
void uart_init(void)
{
const uart_config_t uart_config = {
.baud_rate = 9600,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_APB,
};
// 配置UART参数
uart_param_config(UART_NUM_LORA, &uart_config);
// 设置UART引脚
uart_set_pin(UART_NUM_LORA, UART_TX_PIN, UART_RX_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
// 安装UART驱动
uart_driver_install(UART_NUM_LORA, BUF_SIZE * 2, 0, 0, NULL, 0);
}
// LoRa模块复位
void lora_reset(void)
{
gpio_set_level(LORA_RST_PIN, 0);
vTaskDelay(pdMS_TO_TICKS(100));
gpio_set_level(LORA_RST_PIN, 1);
vTaskDelay(pdMS_TO_TICKS(100));
}
// LoRa模块配置(AT指令)
void lora_config(void)
{
lora_reset();
vTaskDelay(pdMS_TO_TICKS(500));
// SX1278 AT指令配置(470MHz,SF7,125KHz)
const char *at_cmds[] = {
"AT+FREQ=470000000\r\n",
"AT+SF=7\r\n",
"AT+BW=125\r\n",
"AT+CR=4\r\n",
"AT+POWER=17\r\n",
"AT+MODE=1\r\n",
"AT+SAVE\r\n"
};
for (int i = 0; i < sizeof(at_cmds)/sizeof(at_cmds[0]); i++) {
uart_write_bytes(UART_NUM_LORA, at_cmds[i], strlen(at_cmds[i]));
vTaskDelay(pdMS_TO_TICKS(200));
// 接收模块响应,验证配置结果
uint8_t buf[64];
int len = uart_read_bytes(UART_NUM_LORA, buf, sizeof(buf)-1, pdMS_TO_TICKS(100));
if (len > 0) {
buf[len] = '\0';
ESP_LOGI(TAG, "LoRa config response: %s", buf);
}
}
ESP_LOGI(TAG, "LoRa module config ok!");
}
// 系统初始化入口
void sys_init(void)
{
// 初始化GPIO
gpio_init();
// 初始化UART
uart_init();
// 初始化Wi-Fi(配网)
wifi_init_sta(); // 自定义Wi-Fi STA模式初始化函数
// 初始化LoRa模块
lora_config();
ESP_LOGI(TAG, "System init ok!");
}
7.5.2 ESP32-S3核心例程(UART+LoRa+Wi-Fi)
Plain
#include "CH58x_common.h"
#include "CH58x_uart.h"
#include "CH58x_gpio.h"
#include <string.h>
// 引脚定义
#define LORA_RST_PIN GPIO_Pin_4
#define LED_LORA_PIN GPIO_Pin_3
#define LED_POWER_PIN GPIO_Pin_2
// UART1配置(对接SX1278,9600波特率)
#define UART_LORA UART1
#define UART_TX_PIN GPIO_Pin_8
#define UART_RX_PIN GPIO_Pin_9
#define UART_BUF_SIZE 128
uint8_t uart_rx_buf[UART_BUF_SIZE];
uint8_t uart_tx_buf[UART_BUF_SIZE];
uint16_t uart_rx_len = 0;
// GPIO初始化
void gpio_init(void)
{
// 配置LED引脚为推挽输出
GPIO_InitTypeDef gpio_init_struct = {0};
gpio_init_struct.GPIO_Pin = LED_POWER_PIN | LED_LORA_PIN;
gpio_init_struct.GPIO_Mode = GPIO_ModeOut_PP;
gpio_init_struct.GPIO_Speed = GPIO_Speed10MHz;
GPIO_Init(GPIOA, &gpio_init_struct);
GPIO_SetBits(GPIOA, LED_POWER_PIN); // 电源灯亮
GPIO_ResetBits(GPIOA, LED_LORA_PIN); // LoRa灯灭
// 配置LoRa复位引脚为推挽输出
gpio_init_struct.GPIO_Pin = LORA_RST_PIN;
GPIO_Init(GPIOB, &gpio_init_struct);
GPIO_SetBits(GPIOB, LORA_RST_PIN); // 默认不复位
}
// UART初始化
void uart_init(void)
{
UART_InitTypeDef uart_init_struct = {0};
// 配置UART引脚
GPIO_InitTypeDef gpio_init_struct = {0};
gpio_init_struct.GPIO_Pin = UART_TX_PIN;
gpio_init_struct.GPIO_Mode = GPIO_ModeOut_PP;
gpio_init_struct.GPIO_Speed = GPIO_Speed10MHz;
GPIO_Init(GPIOA, &gpio_init_struct);
gpio_init_struct.GPIO_Pin = UART_RX_PIN;
gpio_init_struct.GPIO_Mode = GPIO_ModeIN_FLOATING;
GPIO_Init(GPIOA, &gpio_init_struct);
// 配置UART参数
uart_init_struct.UART_BaudRate = 9600;
uart_init_struct.UART_WordLength = UART_WordLength_8b;
uart_init_struct.UART_StopBits = UART_StopBits_1;
uart_init_struct.UART_Parity = UART_Parity_No;
uart_init_struct.UART_HardwareFlowControl = UART_HardwareFlowControl_None;
uart_init_struct.UART_Mode = UART_Mode_Tx_Rx;
UART_Init(UART_LORA, &uart_init_struct);
// 启用接收中断
UART_ITConfig(UART_LORA, UART_IT_RXNE, ENABLE);
NVIC_EnableIRQ(UART1_IRQn);
}
// UART中断服务函数
__INTERRUPT void UART1_IRQHandler(void)
{
if (UART_GetITStatus(UART_LORA, UART_IT_RXNE) != RESET)
{
uart_rx_buf[uart_rx_len++] = UART_ReceiveData(UART_LORA);
if (uart_rx_len >= UART_BUF_SIZE - 1 || uart_rx_buf[uart_rx_len - 1] == '\n')
{
// 接收完成,通过UART0发送至上位机
UART_SendData(UART0, uart_rx_buf, uart_rx_len);
GPIO_SetBits(GPIOA, LED_LORA_PIN);
DelayMs(100);
GPIO_ResetBits(GPIOA, LED_LORA_PIN);
uart_rx_len = 0;
}
UART_ClearITPendingBit(UART_LORA, UART_IT_RXNE);
}
}
// LoRa模块复位
void lora_reset(void)
{
GPIO_ResetBits(GPIOB, LORA_RST_PIN);
DelayMs(100);
GPIO_SetBits(GPIOB, LORA_RST_PIN);
DelayMs(100);
}
// LoRa模块配置(AT指令)
void lora_config(void)
{
lora_reset();
DelayMs(500);
// SX1278 AT指令配置(470MHz,SF7,125KHz)
const char *at_cmds[] = {
"AT+FREQ=470000000\r\n",
"AT+SF=7\r\n",
"AT+BW=125\r\n",
"AT+CR=4\r\n",
"AT+POWER=17\r\n",
"AT+MODE=1\r\n",
"AT+SAVE\r\n"
};
for (int i = 0; i < sizeof(at_cmds)/sizeof(at_cmds[0]); i++)
{
strcpy((char*)uart_tx_buf, at_cmds[i]);
UART_SendData(UART_LORA, uart_tx_buf, strlen(at_cmds[i]));
DelayMs(200);
}
// 发送初始化完成标识
const char *init_ok = "LoRa module config ok!\r\n";
strcpy((char*)uart_tx_buf, init_ok);
UART_SendData(UART_LORA, uart_tx_buf, strlen(init_ok));
}
// 系统初始化入口
void sys_init(void)
{
SetSysClock(CLK_SOURCE_PLL_60MHz);
// 初始化GPIO
gpio_init();
// 初始化UART0(调试)
UART0_Init(115200);
// 初始化UART1(LoRa)
uart_init();
// 初始化LoRa模块
lora_config();
}
// 主函数入口
int main(void)
{
sys_init();
while (1)
{
DelayMs(1000);
}
}
7.5.3 CH585M核心例程(UART+LoRa)
7.6 基于三款MCU的硬件物料与调试步骤补充速查表
7.6.1 ESP32-S3方案硬件物料补充表
| 物料类别 | 具体物料 | 规格参数 | 数量 | 用途说明 |
|---|---|---|---|---|
| 核心芯片 | ESP32-S3-DevKitC-1开发板 | Xtensa LX7双核,8MB Flash,512KB RAM | 1块 | 网关主控,负责LoRa数据处理、Wi-Fi云对接 |
| 通信器件 | 2.4G Wi-Fi天线 | IPEX接口,增益2dBi | 1个 | 增强Wi-Fi信号,确保稳定连接云平台 |
| 核心芯片 | SX1278 LoRa模块 | 支持470/868/915MHz,UART接口 | 1个 | LoRa信号调制解调 |
| 其他物料 | AMS1117-3.3V、TP4056、电容、电阻等 | 同CH585M方案规格 | 若干 | 供电、辅助功能实现 |
7.6.2 ESP32-S3方案核心调试步骤补充表
7.6.1 三款MCU方案硬件物料对比表
| 调试阶段 | 核心步骤 | 操作要点 | 验证标准 | 常见问题与解决办法 |
|---|---|---|---|---|
| 1. Wi-Fi配网调试 | 1. 初始化Wi-Fi STA模式;2. 触发配网;3. 连接指定Wi-Fi | 1. 确保Wi-Fi天线连接良好;2. 通过按键或APP触发AirKiss配网;3. 配置正确的Wi-Fi名称和密码 | ESP32-S3成功连接Wi-Fi;串口输出Wi-Fi IP地址 | 问题:Wi-Fi连接失败 |
| 解决:1. 检查Wi-Fi名称和密码是否正确;2. 确认Wi-Fi为2.4G频段(不支持5G);3. 检查Wi-Fi天线连接 | ||||
| 2. MQTT云对接调试 | 1. 配置MQTT参数;2. 初始化MQTT客户端;3. 测试数据上传 | 1. 正确填写MQTT Broker地址、客户端ID、用户名密码;2. 确保云平台设备已注册;3. 测试前关闭防火墙 | MQTT连接成功;LoRa数据可正常上传至云平台;云平台下发指令可接收 | 问题:MQTT连接失败 |
| 解决:1. 核对MQTT参数是否正确;2. 检查网络是否能ping通MQTT Broker;3. 确认云平台设备证书有效 | ||||
| 3. LoRa与云协同调试 | 1. 启动LoRa数据收发;2. 测试数据云上传;3. 测试云指令下发 | 1. 确保LoRa模块配置与终端一致;2. 观察串口调试信息;3. 查看云平台数据接收状态 | LoRa终端发送的数据可在云平台查看;云平台下发的指令可通过LoRa发送至终端 | 问题:数据上传延迟/丢包 |
| 解决:1. 优化Wi-Fi信号强度;2. 增加本地数据缓存机制;3. 调整MQTT重连策略 |
7.6.2 三款MCU方案核心调试步骤对比表
| 物料类别 | NRF52840方案 | CH585M方案 | ESP32-S3方案 |
|---|---|---|---|
| 核心芯片 | NRF52840开发板、SX1278 LoRa模块 | CH585M芯片、SX1278 LoRa模块 | ESP32-S3-DevKitC-1开发板、SX1278 LoRa模块 |
| 通信器件 | 2.4G BLE天线、64MHz晶振、32.768KHz晶振 | 12MHz晶振、32.768KHz晶振 | 2.4G Wi-Fi天线、40MHz晶振、32.768KHz晶振 |
| 供电与调试 | AMS1117-3.3V、TP4056、CH340G、WCH-Link | AMS1117-3.3V、TP4056、CH340G、WCH-Link | AMS1117-3.3V、TP4056、USB Type-C线 |
| 辅助器件 | LED、按键、SD卡模块(可选)、电阻电容 | LED、按键、电阻电容 | LED、按键、电阻电容 |
| 核心成本(估算) | ≈36元(NRF52840+SX1278+天线) | ≈16元(CH585M+SX1278) | ≈45元(ESP32-S3+SX1278+天线) |
| 调试阶段 | |||
| --- | --- |
7.7 三款MCU方案核心差异总结
| 对比维度 | CH585M方案 | NRF52840方案 | ESP32-S3方案 |
|---|---|---|---|
| 核心优势 | 成本最低、功耗最小、封装小巧 | 开发成熟、无冗余功耗、扩展灵活 | 自带Wi-Fi+BLE、算力强、直接上云 |
| 核心劣势 | Flash/RAM小、扩展受限 | 无Wi-Fi、上云需额外模块 | 成本较高、功耗略大 |
| 适用场景 | 批量低成本、纯单通道数据收发 | 无Wi-Fi需求、多外设扩展 | 直接上云、多协议融合、功能迭代 |
| 硬件成本(核心器件) | ≈16元(CH585M+SX1278) | ≈36元(NRF52840+SX1278) | ≈45元(ESP32-S3+SX1278+天线) |