ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

基于微信小程序与STM32的智能药盒管理系统

基于微信小程序与STM32的智能药盒管理系统 简介一套结合微信小程序与STM32的智能药盒管理系统完整方案以小程序作为交互入口、STM32作为控制核心构成端云联动的物联网用药管理方案。主要面向嵌入式开发者、物联网爱好者及医疗健康产品设计人员解决传统用药管理依赖人工提醒、易漏服错服以及监护人无法实时掌握服药情况的问题。压缩包共8个文件大小约71.02MB主要包含硬件PCB设计、STM32固件源码、小程序前端源码和项目结构说明另附README与许可证文件rar工程分模块打包便于按需选用和二次开发。已有76人下载学习。资源完整覆盖从硬件电路、嵌入式逻辑到移动端交互的全链路实现药盒定时开启精确控制、用药数据采集上传与远程监护可作为毕业设计、课程项目或智能医疗产品原型参考。 做这个项目的起因是去年回老家时看到奶奶的药盒上贴满胶布早中晚的药还是经常吃重或漏吃。市面上号称“智能药盒”的产品不少但要么贵得离谱要么必须装专用App老人根本用不来。后来我决定自己动手做一套用微信小程序作为交互端用STM32作为药盒主控做成一套基于微信小程序和STM32的智能药盒管理系统。核心目标就三个用药计划可管理、智能硬件可连接、监护人能远程监护。这套方案我已经跑通了完整链路从硬件选型到小程序联调都有可复现的细节这次一次性整理出来。1. 需求拆解药盒为什么要拆成“小程序STM32”两级架构1.1 真正需要解决的四个用药场景先说场景不然容易做成“为了智能而智能”。我在社区里看到过不少同类项目最后都变成蓝牙控制舵机转一圈的花架子。真实的用药痛点其实集中在四件事上漏服老人独居或者子女白天上班没有人到点提醒。药盒需要主动发声、发光而不是靠老人自己看。重复服药不少老人会“觉得今天好像没吃”然后补吃一次危险系数很高。药盒需要记录每次实际取出药品的动作。子女不知道服药情况很多老人不愿意承认自己忘了吃电话里都说“吃了吃了”。子女需要一份客观的、可查询的服药记录。药品种类和时间经常变慢性病老人一个月要调整几次药量今天加一片明天减一片。药盒设置必须简单到子女远程就能改。所以这个系统不是“硬件遥控器”而是一套完整的用药管理闭环计划由小程序维护到点由硬件执行结果自动回传监护人随时查看。这个定位决定了后面所有技术选型。1.2 为什么是微信小程序 STM32而不是纯App或纯云方案我在项目中常被问到为什么不用手机App直接连蓝牙为什么不上一个带WiFi的板子直接把数据传到云端我的答案是要看这个设备的使用者是谁。微信小程序的核心优势是“免安装”。给老人用的东西无论是iOS还是Android打开微信扫一下就能用子女在异地也能帮老人设置计划。对老人来说不需要教他们怎么装App、怎么注册账号点开小程序直接看到今天的药格子就行。这个体验是普通App给不了的。STM32这边则负责“真正动起来”的部分。药盒需要控制舵机开锁、驱动蜂鸣器、读取门控状态这些操作对时序要求高而且不能因为手机蓝牙断连就罢工。用STM32做主控一是实时性和稳定性有保障二是功耗低、成本可控三是整个方案里你能完全掌控硬件逻辑不会像某些家用路由器刷开源固件那样受限。为什么不走“纯云WiFi模块”方案我其实试验过如果药盒直接依赖WiFi模块接收云端指令一旦家里断网或者路由器重启整个药盒就处于“哑巴”状态连本地出药都做不了。而用蓝牙直连方案手机是临时网关药盒本体有独立工作能力断网时只要手机蓝牙还连着照样能按时出药。系统真正需要的云端能力是“远程查看记录”而不是“远程实时控制”的强依赖。这个取舍在老人场景下非常重要。2. 硬件方案从药格到主控板的实操选型2.1 主控与外设清单我的硬件清单如下都是从常用元件库里能直接买到的型号不搞稀缺料模块型号/规格作用主控MCUSTM32F103C8T6处理蓝牙指令、控制舵机和传感器蓝牙透传模块JDY-23 BLE 4.2 / 5.0与微信小程序建立BLE连接舵机MG90S 金属齿轮舵机 × 6控制6个药格锁扣药格状态检测微动开关 × 6检测药格是否被打开/关回蜂鸣器有源蜂鸣器 5V到点提醒、异常报警显示屏0.96寸OLED I2C显示时间、今日服药状态电源管理AMS1117-3.3 7.4V锂电池给MCU和舵机供电为什么用MG90S小舵机而不是步进电机我对比过。步进电机优点是定位精确但驱动需要驱动芯片药盒这场景本质上不是“分度定位”而是“把锁扣拉开一个角度”舵机最合适。MG90S堵转电流约200-300mA六路不会同时动作一个独立电源完全扛得住。如果你用大扭力舵机比如MG995就需要单独考虑电源了。2.2 电路连接与供电细节硬件连接上容易翻车的点主要是供电和电平匹配。STM32的GPIO是3.3V电平JDY-23蓝牙模块的串口电平通常兼容3.3V可以直接连但我不建议直接共地后把模块VCC接到板子的5V上就不管了。稳妥做法是BLE模块VCC接3.3VTXD接STM32的PA10(USART1_RX)RXD接PA9(USART1_TX)GND共地。这样收发不会出现电平“半高不高”的问题。舵机供电要单独给。MG90S的堵转瞬间可能把5V电源拉低如果和MCU共用同一个电源轻则屏幕闪烁重则单片机直接复位。我的方案是7.4V锂电池直接给舵机电源端再通过AMS1117降压到3.3V给STM32供电舵机VCC接5V的独立DCDC模块信号线接MCU的PA0、PA1等PWM输出引脚。实际接线时每个舵机的电源线最好加一个100uF电容滤波能明显减少瞬时压降。药格打开状态的检测我用的是微动开关安装在药格门锁位置门关上时开关被压住门弹开后开关释放。STM32的GPIO配置为输入上拉开关闭合时读到低电平打开时读到高电平。如果用的是常开型传感器就要在代码里反过来处理。这里有个顺序问题安装时先把微动开关固定在盒体上再装舵机锁扣否则容易出现“门关上了但锁扣压不住开关”的物理错位。3. 小程序端用药计划、BLE通信与远程监护闭环3.1 页面结构和云开发数据模型小程序整体结构很简单一共四个主要页面首页显示设备连接状态、今日用药计划的卡片列表。计划编辑添加/修改药品名称、剂量、提醒时间。记录页按天查看服药记录区分“已确认”“未确认”“已漏服”。监护端绑定家庭成员后查看被监护人的实时服药记录和剩余药量。数据存储我用了微信云开发省去了自建服务器。云数据库里建三个集合就够了users用户信息包含openid、家庭绑定关系。devices设备信息包含deviceId、绑定人ownerId、当前药格数量。plans用药计划包含userId、deviceId、drugName、dosage、reminderTimes、enabled。records我不建议单独建集合数据量大了之后查询很麻烦。我直接把每日服药记录嵌套在plans文档里以数组形式保存每次取当天记录时只查一次plans集合性能足够逻辑也清晰。3.2 微信小程序蓝牙通信的几个关键封装微信小程序连BLE模块核心流程是wx.openBluetoothAdapter({}) // 初始化蓝牙适配器 wx.startBluetoothDevicesDiscovery({ allowDuplicatesKey: true }) // 过滤名称包含 MedBox_ 的设备 wx.createBLEConnection({ deviceId }) wx.getBLEDeviceServices({ deviceId }) wx.getBLEDeviceCharacteristics({ deviceId, serviceId }) // 然后通过 writeBLECharacteristicValue 下发指令这里有三个实际会遇到的问题值得单独提醒。第一发现设备后不要马上就createBLEConnection要过滤设备名否则会把周围十几台蓝牙设备都尝试连一遍。我的做法是在onBluetoothDeviceFound回调里判断device.name是否包含MedBox_匹配后才执行连接。第二iOS和Android对蓝牙权限的处理不同。iOS上如果用户没有打开“定位服务”蓝牙扫描可能拿不到任何设备这个坑不实际踩一次很难想到。小程序初始化蓝牙前最好先用接口判断一下系统版本如果检测到iOS就先引导用户打开定位权限再走蓝牙流程。第三写数据时要考虑分包。微信BLE接口一次写入的最大长度通常在20字节左右我的协议帧只有6个字节完全没问题。如果你要扩展功能比如下一条较长的配置指令就必须把数据拆成多段每次写完后等待writeBLECharacteristicValue成功回调再写下一段。同时写操作要加防抖不能在极短时间内连续写否则手机会提示“连接不稳定”。3.3 监护人远程监护的数据流远程监护的数据流是这样的被监护人的手机小程序和药盒保持BLE连接当药盒检测到某个药格被打开并关回后会通过BLE回传一条确认帧小程序收到后调用云函数写入服药记录。监护人打开小程序时后台根据家庭绑定关系查对应被监护人的plans和records页面展示当日服药状态。这里有一个权限问题要提前设计微信云开发默认只允许用户读写自己的数据监护人怎么读取被监护人的数据我的方案是在用户表里维护一个family字段{ _openid: 被监护人的openid, ownerId: 被监护人openid, family: [ { openid: 监护人openid, role: child } ] }云函数里根据当前登录用户的openid查找ownerId等于该用户或family数组中包含该用户的设备再返回对应的计划与记录。这样权限关系依然清晰不会出现任何人能查别人数据的问题。如果监护人想主动提醒不使用蓝牙直连因为他在异地我用了微信订阅消息被监护人在小程序里授权“服药提醒”消息模板监护端点击“提醒服药”时通过云函数调用微信推送接口向被监护人发送一条订阅消息。注意订阅消息一次授权只能推送一次所以我做了一个“连续授权”引导在用户首次进入计划页时弹窗申请多次授权。这个设计在真机测试中有效但不要指望它像短信一样强制只能作为提醒增强。4. STM32端状态机与自定义BLE协议一条指令怎样变成一颗药4.1 自定义BLE指令帧格式与解析BLE透传模块传输的是裸串口字节直接传字符串也不是不能做但项目一旦复杂就会很痛苦。我自定义了一套极简二进制协议每个指令固定6字节字节定义说明第1字节帧头固定0xAA第2字节命令字0x01出药、0x02查询状态、0x03复位第3字节参数药格编号0~5第4字节保留固定0x00第5字节校验和低8位前4字节累加和的低8位第6字节帧尾固定0x55举个例子下发“打开第2格药”指令就是AA 01 02 00 AD 55因为前四个字节0xAA 0x01 0x02 0x00 0xAD所以校验码是0xAD。STM32端收到后先判断帧头和帧尾再验证累加和校验通过才执行。这个协议看起来简单但好处是不依赖字符串解析不会出现换行符干扰、大小写混淆的问题也方便以后扩展命令字。4.2 STM32主状态机与出药逻辑STM32端的核心不是怎么写串口中断而是怎么把“收到一条指令”变成“一次稳定的出药动作”。我这里用了一个简单的状态机四个状态IDLE空闲等待BLE指令。POPPING舵机正在转动等待到达指定角度。WAIT_CONFIRM药格已弹开等待药格被取走并关闭。MISSED超时未关闭执行提醒并上报。核心逻辑大概是这样的switch (state) { case IDLE: if (ble_rx.cmd CMD_POP) { pop_drug(ble_rx.arg); // 控制对应舵机转动 state WAIT_CONFIRM; } break; case WAIT_CONFIRM: if (door_sensor_closed(ble_rx.arg)) { send_status(STATUS_TAKEN); state IDLE; } else if (tick 15000) { buzzer_beep(3); send_status(STATUS_MISSED); state IDLE; } break; }这里有两个细节。第一个是舵机转动的时间MG90S从0度转到90度约120ms我在pop_drug里先让蜂鸣器短响一声再控制舵机转到对应角度防止老人被突然弹出的药格吓到。第二个是状态机里不要阻塞式等待用定时器中断维护一个毫秒级的tick主循环只做状态判断。如果直接写HAL_Delay(120)在延时期间蓝牙指令来了也处理不了体验会差很多。4.3 掉电保护与误弹出设计药盒最怕的就是掉电后状态丢失或者误触发导致药格弹开。针对这两个问题我做了三个处理。第一在STM32的Flash里保存一个“当前已弹开药格”的状态位。每次上电初始化时读取这个状态如果发现某个药格在掉电前是“已弹开未确认”蜂鸣器会持续鸣叫并上报一条待确认记录提示用户检查。这里用STM32F103的FLASH操作其实只需要擦写一个扇区不存在什么难度注意不要在运行时频繁写Flash就行。第二BLE指令执行前加一个“二次校验”逻辑。出药这种动作不能收到一帧就执行万一飘来一个CRC碰巧校验通过呢实际项目中我设置了同一个指令3秒内最多执行一次并且指令必须连续收到两次且内容一致才真正触发。用户在小程序端点一次“出药”小程序会自动发两帧相同的指令间隔200ms。这样即使BLE偶尔丢包也不会造成误操作。第三药格的状态检测要消抖。微动开关在机械动作瞬间会有一连串的电平抖动如果直接读GPIO判断可能会把一个开合动作识别成多次。我在代码里加了一个简单的软件消抖GPIO状态变化后延时20ms再读一次一致才确认变化。如果用定时器中断做轮询效果更好但要注意别在中断里做延时否则会拖慢主循环。5. 联调实测与踩坑记录从点击“出药”到药格弹开5.1 实测链路延迟与稳定性整个链路跑通之后我做了一轮比较完整的实测数据如下测试项目结果打开小程序到蓝牙连接成功平均耗时2.3秒iOS1.8秒Android下发“出药”指令到药格弹开平均耗时180ms药格状态回传到小程序显示平均耗时480ms连续操作10次指令丢失次数0次同一楼层环境蓝牙距离大于8米后丢包率明显上升实测下来用户点击“出药”后的实际体感是非常快的几乎感觉不到延迟。真正影响体验的反而是“打开小程序连蓝牙”这个过程。后来我在小程序首页加了一个自动重连逻辑如果检测到上次连接的设备ID就跳过设备扫描直接用createBLEConnection去连连接速度从2秒多降到1秒以内。5.2 我踩过的三个坑这里必须把几个印象深刻的坑单独拿出来说因为不踩一次很多问题看教程根本发现不了。坑一舵机供电不足导致STM32频繁复位。最初我把五块面包板接到同一个5V降压模块上按下出药按键的瞬间屏幕直接白屏串口打印全是乱码。后来用万用表量舵机电源端瞬间跌落到了3.8V而STM32的3.3V供电又是从同一个5V降压出来的在低压瞬间直接复位。解决方案就是前面说的舵机独立供电STM32通过AMS1117单独降压。这个教训让我明白在机电一体项目里供电规划比代码优先级更高。坑二微信小程序拿到的BLE服务UUID是“动态”的。JDY-23模块出厂默认有一套Service UUID和Characteristic UUID但不同固件版本返回的UUID并不一致甚至在重新上电后可能变化。我开始按照说明书硬编码UUID结果换了一块模块就连不上。后来改成了动态获取连接设备后先调用getBLEDeviceServices拿到所有服务再从中筛选出包含“写入”和“通知”权限的特征值不再依赖固定值。这样无论模块固件怎么变都能找到可用的通道。坑三微动开关抖动导致药格状态误报。一开始我直接按GPIO电平跳变判断“门被打开”结果发现老人轻轻关门时开关会连续抖动记录上显示“打开-关闭-打开-关闭”了好几次。我折腾半天后加了软件消抖还在小程序端增加了“状态变化后500ms内不再接受反向变化”的辅助逻辑最终记录稳定很多。这种事情调试时很难复现但装上电池放在家里第二天数据统计就开始出问题。所以凡是读取机械传感器的地方都别省消抖逻辑。5.3 可以继续扩展的方向这套系统的硬件和软件底座都搭好了后续扩展其实非常自然。我目前已经验证过几个方向离线语音播报加一个SYN6288语音合成模块到点直接播报“请服用阿司匹林一片”比蜂鸣器好用太多。语音模块通过串口和STM32通信协议类似AT指令非常成熟。用药数据导出云函数定期把每周服药依从性汇总成一个PDF通过小程序让用户下载或分享给家庭医生。这个我已经用云开发的generateUrl做了简单版能生成临时链接后续可以接文件存储。多设备家庭管理把devices集合改成数组支持一位用户绑定多个药盒比如老家一台、自己家一台。小程序首页按设备分组展示计划监护人端查看不同设备时也能按家庭维度过滤。最后分享一个我实际用下来最管用的小技巧给药盒的每颗药格编号在盒体上刻数字然后在微信小程序计划编辑页里让用户拍照绑定“第3格对应哪种药”。这个功能看着不起眼但老人实际使用时眼睛看着盒体编号再扫一眼手机几乎不会放错药。很多同类项目败在功能复杂但“不好用”上如果把交互细节做到这种程度整个系统才真正有了长期被使用的价值。本文还有配套的精品资源点击获取
返回列表