跳转至内容
BakeHub 工科开源社群

社区讨论

项目复盘

4主题 5帖子

复盘项目过程、决策与结果

此版块可通过开放社交网络使用标识符 announcements@127.0.0.1:14581 关注

  • 1赞同
    1帖子
    21浏览
    本文是 shaojiec932-web/CCD 项目的开源分享帖,原 README 同步搬运过来,方便社群同学在 BakeHub 内直接讨论。仓库整理了 2026 嵌入式芯片应用赛道(乐鑫科技赛道)参赛过程中三个核心 ESP32-S3 节点工程:主控节点端、图传视觉端、门牌节点端。主控与图传端基于小智开源框架二次开发,门牌端用 Arduino 实现。致敬虾哥 xiaozhi。 TrackDock 室内智能感知运载平台 基于 ESP32-S3、小智开源框架、MQTT、RFID、UWB、图传视觉与本地运动控制构建的室内智能运载与感知系统。 本仓库整理了本项目中三个核心 ESP32-S3 节点工程,分别为:主控节点端、图传视觉端和可编辑门牌节点端。其中主控节点端与图传视觉端均基于小智开源代码框架进行二次开发,在原有语音交互、联网通信和设备框架基础上,扩展了面向室内运载场景的本地实时控制、MCP 工具服务、MQTT 数据同步、RFID 货物识别、UWB 区域定位、串口屏交互和摄像头图传等能力。门牌节点端采用 Arduino 框架实现,用于室内区域标识与 MQTT 配置同步。 项目背景 在医院、养老院、仓库、图书馆、教学楼和实验室等复杂室内环境中,药品、文件、器材、样本、工具和日常物资需要频繁流转。传统方式主要依赖人工搬运、人工登记和人工核对,容易出现效率低、定位难、状态不可追踪、错拿错送、远程感知不足等问题。 TrackDock 的目标是通过低成本嵌入式节点与多端协同系统,将"任务发起、语音理解、货物识别、区域定位、远程图传、运动执行、状态反馈"打通,形成一套面向室内场景的智能运载与感知原型平台。 工程目录 嵌入式大赛/ ├─ ESP32-S3主控节点端/ │ ├─ application.cc │ ├─ application.h │ ├─ mcp_server.cc │ ├─ mcp_server.h │ └─ bread-compact-wifi-lcd/ │ ├─ compact_wifi_board_lcd.cc │ ├─ config.h │ ├─ mcp_rfid_cargo_manager.cc │ ├─ mcp_serial_display.cc │ ├─ mcp_stm32_motor_control.cc │ ├─ mcp_storage_lid.cc │ ├─ mcp_uwb_navigation.cc │ ├─ trackdock_mqtt_client.cc │ └─ trackdock_scene.cc │ ├─ ESP32-S3图传视觉端/ │ └─ lichuang-dev/ │ ├─ config.h │ ├─ lichuang_dev_board.cc │ ├─ mcp_uart_tools.cc │ └─ mcp_uart_tools.h │ └─ ESP32-S3门牌节点端/ ├─ NumberIP.ino └─ 门牌.txt 1. ESP32-S3 主控节点端 主控节点端是系统的核心控制节点,基于小智开源框架进行二次开发,主要负责语音交互接入、本地 MCP 工具注册、外设数据解析、串口屏交互、货物识别、UWB 定位接口、MQTT 状态同步以及底盘控制指令转发。 主要功能 基于小智框架接入语音交互能力,支持语音触发任务。 扩展 MCP 本地工具服务,将大模型意图映射为本地硬件操作。 通过 RFID 模块完成货物标签识别与货物信息采集。 通过 UWB 模块接口实现室内定位与目标区域导航能力预留。 通过串口屏实现本地人机交互,包括状态显示、按钮控制、音量调节等。 通过 UART 与 STM32 底盘控制端通信,实现前进、后退、左转、右转、停止等运动控制。 通过 MQTT 与客户端进行数据同步,实现远程控制、运行状态反馈和场景切换。 支持收纳盖控制、场景模式管理和任务状态记录。 关键文件说明 文件 说明 application.cc / application.h 小智应用层逻辑扩展,承载语音状态、任务流程和系统初始化相关逻辑。 mcp_server.cc / mcp_server.h MCP 工具服务核心文件,用于注册和管理本地可调用工具。 compact_wifi_board_lcd.cc 主控板级初始化与硬件资源配置。 config.h 主控端 IO、串口、SPI、I2C、外设参数配置。 mcp_rfid_cargo_manager.cc RFID 货物扫描、标签读取、货物信息反馈。 mcp_serial_display.cc 串口屏数据解析、控件同步、指令接收与显示输出。 mcp_stm32_motor_control.cc STM32 底盘运动指令封装与串口发送。 mcp_uwb_navigation.cc UWB 定位、目标点、导航状态与路径指令接口。 trackdock_mqtt_client.cc MQTT 客户端连接、订阅、发布与远程控制同步。 trackdock_scene.cc 多场景模式切换与场景语义管理。 2. ESP32-S3 图传视觉端 图传视觉端基于立创实战派 ESP32-S3 开发板方案和小智开源框架进行二次开发,主要用于摄像头图像采集、JPEG 编码、MQTT 图传发布和远程视觉控制台显示。该节点作为独立视觉感知节点,不承担主控运动决策,重点提供远程观察与辅助驾驶能力。 主要功能 基于 ESP32-S3 摄像头接口采集实时图像。 将图像压缩为 JPEG 数据并通过 MQTT 上传。 客户端可实时显示视觉画面,用于远程观察和辅助控制。 可配合主控端完成室内运行状态监控、路径观察和物品识别辅助展示。 保留小智框架的基础联网和设备初始化能力,并扩展图传任务循环。 关键文件说明 文件 说明 lichuang_dev_board.cc 图传视觉端核心实现,包含摄像头初始化、图像采集、MQTT 发布和任务循环。 config.h 摄像头、板级 IO 和基础参数配置。 mcp_uart_tools.cc / mcp_uart_tools.h 原框架中的 UART 工具能力,保留用于后续扩展。 3. ESP32-S3 门牌节点端 门牌节点端用于构建可编辑的室内区域标识系统。该节点采用 Arduino 框架实现,便于快速开发和部署。门牌节点通过 Wi-Fi 和 MQTT 与客户端同步,客户端可远程配置门牌名称,例如"仓库""收纳区""充电区""病房区"等,节点本地屏幕显示当前门牌信息。 主要功能 支持 Wi-Fi 连接与 MQTT 通信。 支持客户端远程修改门牌名称。 支持本地 TFT/OLED 屏幕显示区域名称。 可作为 UWB 室内定位系统中的空间语义节点。 可与主控端运动任务结合,实现"目标区域名称"和"定位参考点"的对应关系。 关键文件说明 文件 说明 NumberIP.ino 门牌节点主程序,包含 Wi-Fi、MQTT、屏幕显示和门牌配置逻辑。 门牌.txt 门牌端说明、配置记录或辅助资料。 系统总体链路 用户语音 / 客户端 / 串口屏 ↓ ESP32-S3 主控节点 ↓ 小智语音交互 + MCP 本地工具调用 ↓ RFID 货物识别 / UWB 区域定位 / STM32 底盘控制 / 收纳盖控制 ↓ MQTT 状态同步 ↓ 电脑端、手机端、视觉控制端、门牌节点 图传视觉端作为独立感知节点持续上传摄像头画面,门牌节点作为空间语义节点提供区域标识,主控节点负责语音理解后的本地执行和多端状态同步。三个节点共同构成室内智能运载平台的基础闭环。 二次开发说明 本项目主控节点端和图传视觉端基于小智开源框架进行二次开发,主要扩展方向包括: 面向室内运载场景的 MCP 工具接口。 面向硬件外设的本地实时控制逻辑。 面向客户端的 MQTT 数据同步链路。 面向串口屏的人机交互协议。 面向 RFID、UWB、STM32、摄像头等模块的板级适配。 面向多场景应用的任务状态与场景语义管理。 开源时请保留原小智项目相关版权与许可证说明,并在仓库中注明本项目是在其基础上进行的场景化二次开发。 技术栈 主控框架:Espressif ESP-IDF、小智开源框架 主控芯片:ESP32-S3 图传节点:ESP32-S3 摄像头开发板 门牌节点:ESP32-S3 + Arduino 框架 通信方式:Wi-Fi、MQTT、UART、SPI、I2C、GPIO 识别模块:RFID RC522 定位模块:UWB / DW1000 系列模块接口 执行控制:STM32F103C8T6 底盘控制端 交互方式:语音、串口屏、电脑端客户端、手机端客户端 适用场景 医院药品、样本、护理用品转运 养老院照护用品配送 仓储货物转运与盘点辅助 实验室器材和样本流转 图书馆资料搬运与区域配送 教学楼、办公楼内的低成本智能配送 后续扩展方向 将主控、图传、门牌和底盘控制进一步集成化,减少分散模块数量。 优化机械结构,使车体更接近真实运载平台。 完善 UWB 多基站定位解算,提高室内定位精度。 增强视觉识别能力,支持货物外观识别和障碍检测。 完善客户端任务管理,实现多车、多门牌、多任务调度。 增加电源管理和安全保护,提高系统稳定性。 开源说明 本仓库为 TrackDock 室内智能感知运载平台的嵌入式端工程整理版本,包含主控节点端、图传视觉端和门牌节点端三个部分。项目用于嵌入式系统开发、物联网多节点协同、智能运载平台原型验证和比赛展示。 其中涉及小智开源框架的部分为基于原项目的二次开发与场景化扩展,建议开源时同步附带原项目许可证、二次开发说明和本项目新增功能说明。 仓库地址:https://github.com/shaojiec932-web/CCD 欢迎在评论区交流硬件选型、MCP 工具注册、UWB 定位解算、MQTT 图传带宽优化等细节问题。
  • STM32超频开源项目合集

    1
    1赞同
    1帖子
    70浏览
    项目概述 本项目收集整理了GitHub上三个优秀的STM32超频开源项目,覆盖STM32F103、STM32F303、STM32F37x三个系列,从极限挑战到实用工程模板都有涉及,适合喜欢折腾硬件超频的爱好者参考学习。 项目一:stm32-overclocking-challenge(蓝药丸极限超频竞赛) GitHub地址: https://github.com/m3y54m/stm32-overclocking-challenge 目标芯片: STM32F103C8T6(BluePill蓝药丸开发板) 项目特点 专门针对STM32F103的极限超频挑战项目 使用汇编语言编写时钟配置代码,追求极致性能 支持测试不同PLL配置下的极限频率 包含GPIO翻转速度测试,直观验证超频效果 附带稳定性测试代码 玩法亮点 STM32F103官方标称最高72MHz,但很多板子实际能跑到128MHz甚至更高。这个项目就像一场硅片体质抽奖,不同芯片的极限频率差异很大,用示波器看GPIO翻转波形就能直观感受到超频效果。 项目二:stm32f303k8-template(F303超频工程模板) GitHub地址: https://github.com/dimtass/stm32f303k8-template 目标芯片: STM32F303 Nucleo开发板 项目特点 完整的STM32F303超频工程模板,开箱即用 稳定超频至128MHz(官方标称72MHz) 已配置好Flash等待周期,系统运行稳定 完整Makefile工程,适合直接用于实际开发 支持Nucleo开发板,硬件门槛低 实用价值 F303系列自带硬件浮点单元(FPU),超频后DSP运算性能提升明显。这个项目不是单纯的极限超频demo,而是真正可用于实际项目的工程模板,外设都能正常工作。 项目三:overclocking-STM32F37x_16(F37x时钟魔改) GitHub地址: https://github.com/qidfpv/overclocking-STM32F37x_16 目标芯片: STM32F37x系列 项目特点 修改系统时钟配置文件system_stm32f37x.c 从官方72MHz超频到80MHz,约11%性能提升 超频幅度保守,稳定性有保障 直接替换时钟文件即可完成超频 适合新手入门MCU超频 适合人群 这种"甜点频率"超频基本所有芯片都能稳住,不需要挑体质,风险低成就感高,非常适合第一次玩MCU超频的新手。 超频注意事项 失去质保:超频超出芯片官方规格,会失去原厂质保 功耗发热:超频后功耗和发热会明显增加,注意散热 Flash等待周期:必须根据频率调整Flash等待周期,否则直接HardFault 外设时钟:UART/SPI/I2C等外设时钟会变化,通信波特率可能错乱 芯片体质:同型号芯片极限频率差异很大,不要盲目追求高频 风险提示:极限超频有烧坏芯片的风险,请做好电流监控和散热措施 技术标签 STM32 单片机超频 PLL时钟配置 嵌入式开发 硬件DIY
  • 51单片机+ESP8266连接mqtt的智能火灾报警系统设计与实现

    1
    0赞同
    1帖子
    47浏览
    <p>声明:本项目为自研,(前端是小伙伴帮忙做的)开发不易,大家点点赞支持一下主播吧(目前网上没有看到基于51的mqtt相关项目,感觉51搞这些太容易超内存了,并且大佬都在搞32)</p><p>本博客不包含emqx的搭建教程,不会搭建emqx的可以先看这个博主的视频: <span><a href="http:// https://b23.tv/fuq6wbk" target="_blank" rel="noopener noreferrer">https://b23.tv/fuq6wbk</a></span></p><p>结尾附网盘链接</p><h2>项目概述</h2><p>本项目基于STC89C52RC单片机,结合ESP8266  WiFi模块、DHT11温湿度传感器、MQ-2气体传感器等硬件,设计并实现了一个智能火灾报警系统。系统能够实时监测环境温湿度和可燃气体浓度,通过MQTT协议将数据上传到云平台,并支持远程报警和阈值设置。</p><p> <span>​<img src="/assets/uploads/files/1785077888776-image.png" alt="image.png" data-size="large" /></span></p><h2>系统架构</h2><h3>硬件组成</h3><ul><li><p><strong>主控芯片</strong>:STC89C52RC单片机</p></li><li><p><strong>通信模块</strong>:ESP8266 WiFi模块(ESP-01S)</p></li><li><p><strong>传感器</strong>:</p><ul><li><p>DHT11温湿度传感器</p></li><li><p>MQ-2气体浓度传感器</p></li></ul></li><li><p><strong>AD/DA转换模块</strong>:PCF8591转换模块</p></li><li><p><strong>显示模块</strong>:LCD1602液晶显示屏</p></li><li><p><strong>报警模块</strong>:蜂鸣器、LED报警灯</p></li></ul><h3>软件架构</h3><ul><li><p><strong>开发环境</strong>:Keil C51</p></li><li><p><strong>通信协议</strong>:MQTT</p></li><li><p><strong>数据格式</strong>:JSON</p></li></ul><h2><strong>PCB设计</strong></h2><p><span></span></p><p>1.原理图</p><p><img src="/assets/uploads/files/1785077910964-image.png" alt="image.png" data-size="large" /></p><p>2.PCB</p><p><img src="/assets/uploads/files/1785078011677-image.png" alt="image.png" data-size="large" /></p><p><span>​</span></p><h2>核心功能实现</h2><h3>1. 传感器数据采集</h3><p>1.mq2烟雾传感器</p> <blockquote><code><span></span></code><code><span><span></span></span></code><span>#include "mq2.h''<br /></span><p><span><strong>#include "i2c.h"</strong></span><strong><span></span></strong></p><p><strong><span>#define PCF8591_ADDR  0x90</span><span> </span><span>// PCF8591 I2C地址</span><span></span></strong></p><p><strong><span> </span></strong></p><p><strong><span>// 读取PCF8591指定通道的模拟值(MQ2接通道0)</span><span></span></strong></p><p><strong><span>unsigned char MQ2_ReadByte(unsigned char Channel)</span><span></span></strong></p><p><strong><span>{</span><span></span></strong></p><p><strong><span> </span><span>unsigned char Data;</span><span></span></strong></p><p><strong><span> </span><span>I2C_Start();</span><span></span></strong></p><p><strong><span> </span><span>I2C_SendByte(PCF8591_ADDR);</span><span> </span><span> </span></strong><span><strong>// </strong><strong>写地址</strong></span><span></span></p><p><span></span></p><p><span></span></p></blockquote><p><span></span><span></span><span></span></p> <p><span></span></p><p>2.dht11温湿度传感器</p> <pre><code><span>#<span>include</span> <span>"dht11.h"</span></span> <span>#<span>include</span> <span><intrins.h></span></span> <span>// 30us延时</span> <span><span>void</span> <span>DHT11_Delay30us</span><span>(<span>void</span>)</span> </span>{ <span>unsigned</span> <span>char</span> i; i = <span>12</span>; <span>while</span> (--i); } <span>// 40us延时</span> <span><span>void</span> <span>DHT11_Delay40us</span><span>(<span>void</span>)</span> </span>{ <span>unsigned</span> <span>char</span> i; i = <span>17</span>; <span>while</span> (--i); } <span><span>uint8_t</span> <span>DHT11_Init</span><span>(<span>void</span>)</span> </span>{ DHT11_DQ = <span>1</span>; DHT11_DQ = <span>0</span>; <span>Delay_xms</span>(<span>20</span>); <span>// 至少给18ms</span> DHT11_DQ = <span>1</span>; <span>DHT11_Delay30us</span>(); <span>if</span>(DHT11_DQ == <span>0</span>) { <span>while</span>(DHT11_DQ == <span>0</span>); <span>while</span>(DHT11_DQ == <span>1</span>); <span>return</span> <span>0</span>; } <span>return</span> <span>1</span>; } <span><span>uint8_t</span> <span>DHT11_ReceiveByte</span><span>(<span>void</span>)</span> </span>{ <span>uint8_t</span> i, Byte = <span>0x00</span>; <span>for</span>(i=<span>0</span>; i<<span>8</span>; i++) { Byte <<= <span>1</span>; <span>while</span>(DHT11_DQ == <span>0</span>); <span>DHT11_Delay40us</span>(); <span>if</span>(DHT11_DQ == <span>1</span>) Byte |= <span>0x01</span>; <span>while</span>(DHT11_DQ == <span>1</span>); } <span>return</span> Byte; } <span><span>uint8_t</span> <span>DHT11_GetData</span><span>(<span>uint8_t</span> *Humi_H, <span>uint8_t</span> *Humi_L, <span>uint8_t</span> *Temp_H, <span>uint8_t</span> *Temp_L)</span> </span>{ <span>uint8_t</span> i, Buffer[<span>5</span>]; <span>if</span>(<span>DHT11_Init</span>() == <span>0</span>) { <span>for</span>(i=<span>0</span>; i<<span>5</span>; i++) Buffer[i] = <span>DHT11_ReceiveByte</span>(); <span>if</span>(Buffer[<span>0</span>] + Buffer[<span>1</span>] + Buffer[<span>2</span>] + Buffer[<span>3</span>] == Buffer[<span>4</span>]) { *Humi_H = Buffer[<span>0</span>]; *Humi_L = Buffer[<span>1</span>]; *Temp_H = Buffer[<span>2</span>]; *Temp_L = Buffer[<span>3</span>]; <span>return</span> <span>0</span>; } } <span>return</span> <span>1</span>; } </code></pre> <p><span></span> </p><pre><code><span>#<span>ifndef</span> DHT11_H</span> <span>#<span>define</span> DHT11_H</span> <span>#<span>include</span> <span><reg52.h></span></span> <span>#<span>include</span> <span>"delay.h"</span></span> <span>typedef</span> <span>unsigned</span> <span>char</span> <span>uint8_t</span>; sbit DHT11_DQ = P2^<span>0</span>; <span>// 引脚设置</span> <span><span>uint8_t</span> <span>DHT11_Init</span><span>(<span>void</span>)</span></span>; <span><span>uint8_t</span> <span>DHT11_ReceiveByte</span><span>(<span>void</span>)</span></span>; <span><span>uint8_t</span> <span>DHT11_GetData</span><span>(<span>uint8_t</span> *Humi_H, <span>uint8_t</span> *Humi_L, <span>uint8_t</span> *Temp_H, <span>uint8_t</span> *Temp_L)</span></span>; <span>#<span>endif</span></span> </code></pre> <p><span></span></p><h3>2. ESP8266 MQTT通信</h3><p>注意:客户端ID随意但是必须唯一,用户名称和密码就是自己在emqx上设置的</p><p> <span>​<img src="/assets/uploads/files/1785078045468-image.png" alt="image.png" data-size="large" /></span></p><p>注意:mqtt的IP地址用ipconfig查看不了,可以用网络调试助手等软件看,不知道是哪个可以先用串口调试ESP8266,发送AT指令连接尝试:(串口发送AT指令记得末尾加上换行)</p><blockquote><p>AT+CWMODE=1</p><p>AT+CWJAP="WiFi名","WiFi密码"</p><p>AT+MQTTUSERCFG=0,1,"客户端ID","用户名","密码",0,0,""</p><p>AT+MQTTCONN=0,"mqtt的IP地址",1883,0</p></blockquote><p><span></span></p><p>网络调试助手:</p><p><img src="/assets/uploads/files/1785078101073-image.png" alt="image.png" data-size="large" /></p><p><span>​</span></p><p>esp8266.c</p> <pre><code><span>#<span>include</span> <span>"esp8266.h"</span></span> <span>#<span>include</span> <span><reg52.h></span></span> <span>#<span>include</span> <span>"lcd1602.h"</span></span> <span>#<span>include</span> <span>"usart.h"</span></span> <span>#<span>include</span> <span>"delay.h"</span></span> <span>#<span>include</span> <span>"time.h"</span></span> <span>// 硬件引脚定义</span> sbit WIFI_RST = P1^<span>7</span>; <span>// ESP8266复位</span> sbit Bee = P1^<span>6</span>; <span>// 蜂鸣器</span> sbit ALARM_LED= P1^<span>5</span>; <span>// 报警灯</span> <span>// 全局变量:传感器数据</span> <span>unsigned</span> <span>char</span> Humi_H, Temp_H, Gas; <span>unsigned</span> <span>char</span> Threshold = <span>29</span>; <span>// 温度报警阈值</span> <span>// ESP8266初始化连接MQTT(使用AT指令)</span> <span><span>void</span> <span>ESP_conect_sev</span><span>(<span>void</span>)</span> </span>{ <span>// ESP8266复位</span> WIFI_RST = <span>0</span>; <span>Delay_xms</span>(<span>1000</span>); WIFI_RST = <span>1</span>; <span>Delay_xms</span>(<span>1000</span>); <span>// 本地MQTT AT指令配置</span> <span>uart1_sendstring</span>(<span>"AT+CWMODE=1\r\n"</span>); <span>Delay_xms</span>(<span>1000</span>); <span>uart1_sendstring</span>(<span>"AT+CWJAP=\"WiFi名\",\"密码\"\r\n"</span>); <span>// 连接WiFi</span> <span>Delay_xms</span>(<span>2000</span>); <span>uart1_sendstring</span>(<span>"AT+MQTTUSERCFG=0,1,\"客户端ID\",\"用户名\",\"密码\",0,0,\"\"\r\n"</span>); <span>// MQTT用户配置</span> <span>Delay_xms</span>(<span>1000</span>); <span>uart1_sendstring</span>(<span>"AT+MQTTCONN=0,\"IP地址\",1883,0\r\n"</span>); <span>// 连接MQTT服务器</span> <span>Delay_xms</span>(<span>2000</span>); } <span>// 数字转字符串(发送数据用)</span> <span><span>void</span> <span>num_to_str</span><span>(<span>unsigned</span> <span>char</span> num, <span>unsigned</span> <span>char</span> *num_str1)</span> </span>{ <span>if</span>(num != <span>0</span>) { <span>unsigned</span> <span>int</span> num_temp = num; <span>unsigned</span> <span>char</span> cnt = <span>0</span>; <span>while</span>(num_temp) { cnt++; num_temp /= <span>10</span>; } num_temp = num; <span>while</span>(cnt) { cnt--; num_str1[cnt] = (num_temp % <span>10</span>) + <span>48</span>; num_temp /= <span>10</span>; } } <span>else</span> { num_str1[<span>0</span>] = <span>'0'</span>; } } <span>// 发送第一个传感器数据(湿度)</span> <span><span>void</span> <span>first_data</span><span>(<span>unsigned</span> <span>char</span> *str2, <span>unsigned</span> <span>char</span> num)</span> </span>{ <span>unsigned</span> <span>char</span> str1[<span>3</span>] = {<span>0</span>}; <span>// MQTT发布主题:testtopic/1,保留JSON数据格式</span> <span>uart1_sendstring</span>(<span>"AT+MQTTPUB=0,"testtopic/1","{\""</span>); <span>uart1_sendstring</span>(str2); <span>uart1_sendstring</span>(<span>"\":"</span>); <span>num_to_str</span>(num, str1); <span>uart1_sendstring</span>(str1); } <span>// 追加传感器数据(温度、气体浓度)</span> <span><span>void</span> <span>add_data</span><span>(<span>unsigned</span> <span>char</span> *str2, <span>unsigned</span> <span>char</span> num)</span> </span>{ <span>unsigned</span> <span>char</span> str1[<span>3</span>] = {<span>0</span>}; <span>uart1_sendstring</span>(<span>"\,\""</span>); <span>uart1_sendstring</span>(str2); <span>uart1_sendstring</span>(<span>"\":"</span>); <span>num_to_str</span>(num, str1); <span>uart1_sendstring</span>(str1); } <span>// 每秒发送传感器数据到MQTT</span> <span><span>void</span> <span>ESP_send_data</span><span>(<span>void</span>)</span> </span>{ <span>if</span>(time0_ms > <span>1000</span>) <span>// 1秒发送一次</span> { <span>first_data</span>(APP_Humi, Humi_H); <span>// 湿度</span> <span>add_data</span>(APP_Temp, Temp_H); <span>// 温度</span> <span>add_data</span>(APP_Gas, Gas); <span>// 气体浓度</span> <span>uart1_sendstring</span>(<span>"}",0,0\r\n"</span>); <span>Delay_xms</span>(<span>200</span>); <span>uart1_sendstring</span>(<span>"AT+MQTTPUB=0,"订阅主题名",""</span>); <span>if</span>(Gas > <span>50</span> || Temp_H > Threshold) { <span>uart1_sendstring</span>(<span>"fire"</span>); <span>// 报警发送fire</span> } <span>else</span> { <span>uart1_sendstring</span>(<span>"normal"</span>);<span>// 正常发送normal</span> } <span>uart1_sendstring</span>(<span>"",0,0\r\n"</span>); <span>Delay_xms</span>(<span>200</span>); time0_ms = <span>0</span>; <span>// 重置定时器</span> } } <span>// 字符串比较</span> <span>bit <span>str_cmp</span><span>(<span>char</span> *str1, <span>char</span> *str2, <span>char</span> len)</span> </span>{ <span>char</span> *str3 = str1; <span>char</span> *str4 = str2; <span>while</span>(len) { <span>if</span>(*str3 != *str4) <span>return</span> <span>0</span>; len--; str3++; str4++; } <span>return</span> <span>1</span>; } <span>// 字符串转数字</span> <span><span>int</span> <span>str_to_num</span><span>(<span>char</span> *str1)</span> </span>{ <span>unsigned</span> <span>char</span> num = <span>0</span>; <span>while</span>(*str1 >= <span>'0'</span> && *str1 <= <span>'9'</span>) { num += (*str1) - <span>48</span>; str1++; <span>if</span>(!(*str1 >= <span>'0'</span> && *str1 <= <span>'9'</span>)) <span>break</span>; num *= <span>10</span>; } <span>return</span> num; } <span>// 处理本地MQTT下发指令</span> <span>unsigned</span> <span>char</span> Deliver_num; <span><span>void</span> <span>Proces_distribut_data</span><span>(<span>void</span>)</span> </span>{ <span>unsigned</span> <span>char</span> i; <span>// C89:提前声明循环变量,修复语法错误</span> <span>if</span>(RX_ok) <span>// 接收完成</span> { Deliver_num = <span>str_to_num</span>(Deliver_data); <span>// 解析指令数值</span> <span>// 仅保留温度阈值修改逻辑(可扩展其他本地指令)</span> <span>if</span>(<span>str_cmp</span>(Deliver_identifier, APP_Threshold, <span>8</span>)) { Threshold = Deliver_num; } <span>// 清空接收缓存</span> <span>for</span>(i=<span>0</span>; i&lt;<span>6</span>; i++) { Deliver_identifier[i] = <span>0</span>; } <span>for</span>(i=<span>0</span>; i&lt;<span>4</span>; i++) { Deliver_data[i] = <span>0</span>; } Deliver_cnt = <span>0</span>; Deliver_data_cnt = <span>0</span>; RX_ok = <span>0</span>; } } <span>// 传感器报警逻辑(气体浓度/温度过高)</span> <span><span>void</span> <span>Alarm_Check</span><span>(<span>void</span>)</span> </span>{ <span>if</span>(Gas > <span>50</span> || Temp_H > Threshold) <span>// 气体浓度>阈值 或 温度>阈值</span> { <span>LCD_ShowString</span>(<span>2</span>, <span>7</span>, <span>"fire!"</span>); Bee = <span>0</span>; <span>// 蜂鸣器响</span> ALARM_LED = <span>1</span>; <span>// 报警灯亮</span> } <span>else</span> { <span>LCD_ShowString</span>(<span>2</span>, <span>7</span>, <span>" "</span>); Bee = <span>1</span>; <span>// 蜂鸣器关</span> ALARM_LED = <span>0</span>; <span>// 报警灯灭</span> } } </code></pre> <p><span></span></p><p>esp8266.h</p> <pre><code><span>#<span>ifndef</span> ESP8266_H</span> <span>#<span>define</span> ESP8266_H</span> <span>#<span>include</span> <span><reg52.h></span></span> <span>#<span>include</span> <span>"usart.h"</span></span> <span>#<span>include</span> <span>"time.h"</span></span> <span>// 传感器数据宏定义</span> <span>#<span>define</span> APP_Humi <span>"Humi"</span> <span>// 湿度</span></span> <span>#<span>define</span> APP_Temp <span>"Temp"</span> <span>// 温度</span></span> <span>#<span>define</span> APP_Gas <span>"Gas"</span> <span>// 气体浓度</span></span> <span>#<span>define</span> APP_Threshold <span>"Threshold"</span> <span>// 温度阈值</span></span> <span>extern</span> <span>unsigned</span> <span>char</span> Humi_H, Temp_H, Gas; <span>extern</span> <span>unsigned</span> <span>char</span> Threshold; <span><span>void</span> <span>ESP_conect_sev</span><span>(<span>void</span>)</span></span>; <span><span>void</span> <span>ESP_send_data</span><span>(<span>void</span>)</span></span>; <span><span>void</span> <span>num_to_str</span><span>(<span>unsigned</span> <span>char</span> num, <span>unsigned</span> <span>char</span> *num_str1)</span></span>; <span>bit <span>str_cmp</span><span>(<span>char</span> *str1, <span>char</span> *str2, <span>char</span> len)</span></span>; <span><span>int</span> <span>str_to_num</span><span>(<span>char</span> *str1)</span></span>; <span><span>void</span> <span>Proces_distribut_data</span><span>(<span>void</span>)</span></span>; <span><span>void</span> <span>Alarm_Check</span><span>(<span>void</span>)</span></span>; <span><span>void</span> <span>first_data</span><span>(<span>unsigned</span> <span>char</span> *str2, <span>unsigned</span> <span>char</span> num)</span></span>; <span><span>void</span> <span>add_data</span><span>(<span>unsigned</span> <span>char</span> *str2, <span>unsigned</span> <span>char</span> num)</span></span>; <span>#<span>endif</span></span> </code></pre> <p><span></span></p><h2>关键技术点</h2><h3>1. 数据格式转换</h3><p>由于51的时钟频率差异(11.0592MHz相比32性能相差数十倍,所以数字转换算法必须极度优化,我在这个问题上卡了两天,后面查到一种比较好的轻量级数字转换算法</p> <pre><code><span><span>void</span> <span>num_to_str</span><span>(<span>unsigned</span> <span>char</span> num, <span>unsigned</span> <span>char</span> *num_str1)</span> </span>{ <span>if</span>(num != <span>0</span>) { <span>unsigned</span> <span>int</span> num_temp = num; <span>unsigned</span> <span>char</span> cnt = <span>0</span>; <span>while</span>(num_temp) { cnt++; num_temp /= <span>10</span>; } num_temp = num; <span>while</span>(cnt) { cnt--; num_str1[cnt] = (num_temp % <span>10</span>) + <span>48</span>; num_temp /= <span>10</span>; } } <span>else</span> { num_str1[<span>0</span>] = <span>'0'</span>; } }</code></pre> <p><span></span></p><h3>2. JSON数据构造</h3><p>由于51单片机内存限制,无法使用标准库,需要采用手动构造JSON格式数据:</p> <pre><code><span><span>void</span> <span>first_data</span><span>(<span>unsigned</span> <span>char</span> *str2, <span>unsigned</span> <span>char</span> num)</span> </span>{ <span>unsigned</span> <span>char</span> str1[<span>3</span>] = {<span>0</span>}; <span>// MQTT发布主题:testtopic/1,保留JSON数据格式</span> <span>uart1_sendstring</span>(<span>"AT+MQTTPUB=0,"testtopic/1","{\""</span>); <span>uart1_sendstring</span>(str2); <span>uart1_sendstring</span>(<span>"\":"</span>); <span>num_to_str</span>(num, str1); <span>uart1_sendstring</span>(str1); }</code></pre> <p><span></span></p><h3>3. 中断处理的能力限制</h3><p>51单片机中断向量少,响应慢。32则有着丰富的中断源,NVIC优先级管理</p> <pre><code><span><span>void</span> <span>UART1_IRQ_Handle</span><span>(<span>void</span>)</span> interrupt 4 <span>using</span> 1 </span>{ <span>if</span> (TI) { TI = <span>0</span>; uart1_busy = <span>0</span>; <span>// 只做标志位操作</span> } <span>if</span> (RI) { <span>Pro_deliver_data</span>(); <span>// 立即处理,不缓存</span> RI = <span>0</span>; } }</code></pre> <p><span></span></p><h2>系统特点</h2><ol> <li> <p><strong>实时监测</strong>:持续监控环境参数</p> </li> <li> <p><strong>双重报警</strong>:本地声光报警 + 远程状态推送</p> </li> <li> <p><strong>远程控制</strong>:支持通过MQTT修改报警阈值</p> </li> <li> <p><strong>稳定可靠</strong>:采用工业级传感器和成熟的通信协议</p> </li> <li> <p><strong>低成本</strong>:基于廉价硬件组件</p> </li> </ol><h2>应用场景</h2><ul> <li> <p>家庭火灾预警</p> </li> <li> <p>仓库环境监控</p> </li> <li> <p>实验室安全监测</p> </li> <li> <p>工业生产环境监控</p> </li> </ul><h2>总结</h2><p>本系统成功实现了基于51单片机和ESP8266的智能火灾报警功能,展示了如何将传统单片机与现代物联网技术相结合。系统具有良好的实用性和扩展性,为小型化、低成本的智能安防系统开发提供了参考方案。</p><hr /><p><strong>网盘链接:</strong> <span><a href="https://pan.baidu.com/s/1cfd2bHt5SNVlaVzUCct9XQ " target="_blank" rel="noopener noreferrer">https://pan.baidu.com/s/1cfd2bHt5SNVlaVzUCct9XQ </a></span>提取码: sdjw<br /> 欢迎在评论区或群留言讨论!</p>
  • MimiClaw - 5美元芯片上的口袋AI助手

    2
    2赞同
    2帖子
    113浏览
    @KongChar 佬