基于AIR32与ESP01S的智能药盒离线提醒、云端监控与微信小程序联动全解析大家好我是老张一个在嵌入式行业摸爬滚打了十几年的工程师。最近帮朋友做了一个给家里老人用的智能药盒从硬件选型、电路设计到软件开发和云端对接完整地走了一遍。今天我就把这个项目的实战经验掰开揉碎了分享给大家。无论你是刚入门的嵌入式爱好者还是想做一个完整物联网项目的创客相信这篇手把手的教程都能给你带来不少启发。这个智能药盒的核心功能很明确离线也能可靠提醒联网后子女能远程查看。它基于合宙的AIR32单片机搭配ESP01S Wi-Fi模块、DS1302时钟芯片、OLED屏和红外传感器实现了从本地声光报警到云端数据同步的全链路。下面咱们就从硬件到软件从原理到代码一步步来看这个项目是怎么做出来的。1. 项目核心功能与硬件选型思路做项目第一步永远是明确需求。这个药盒要解决的核心问题是老人容易忘记吃药子女在外不放心。所以功能必须围绕“可靠提醒”和“远程监护”来设计。1.1 功能拆解与实现方案根据需求我把功能拆解成了几个核心模块并确定了实现方案本地定时提醒这是基础断网也得能用。需要一个可靠的实时时钟RTC来计时到点就用蜂鸣器和LED发出声光报警。服药行为检测不能光提醒还得知道老人有没有真的打开药盒取药。这里我用的是红外对管传感器取药时手指会遮挡红外线从而触发检测。信息直观显示老人需要一眼就能看到下次吃药的时间、药品种类等信息。一块清晰、低功耗的OLED屏幕是最佳选择。联网与数据同步这是实现“智能”和“远程”的关键。需要将服药记录是否按时、剩余药量上传到云端方便子女通过手机查看。远程设置与管理子女应该能远程为老人设置或修改服药时间。开发一个手机App成本太高所以选择了微信小程序无需安装打开就用。1.2 主控与关键外设选型定好方案接下来就是选“演员”了。主控MCU合宙AIR32我选择了合宙的AIR32。它是一颗基于ARM Cortex-M3内核的32位单片机性能对于这个项目绰绰有余。关键是它性价比高生态特别是Arduino兼容库也不错能大大加快开发速度。它的GPIO、定时器、串口等资源完全满足驱动屏幕、传感器、时钟芯片和Wi-Fi模块的需求。“离线大脑”DS1302时钟芯片为什么不用单片机自带的RTC为了绝对可靠。DS1302是一颗独立的实时时钟芯片自带电池备份引脚。即使主控断电只要给它接上一颗纽扣电池它就能一直走时确保定时提醒功能永不失效。我们通过简单的3线SPI接口和它通信获取精准的年月日时分秒。“联网网关”ESP-01S Wi-Fi模块让AIR32直接处理Wi-Fi和TCP/IP协议栈比较麻烦。所以我选择了经典的ESP-01S模块它核心是ESP8266自带Wi-Fi功能和完整的网络协议栈。我们让AIR32通过串口UART以AT指令的方式指挥ESP-01S让它去连接路由器、连接云服务器这样主控的开发负担就小了很多。“眼睛”和“嘴巴”OLED屏与蜂鸣器OLED屏我用的是一块0.96寸的128x64单色OLED通过I2C接口驱动。它自发光的特性使得在任何光线下都清晰可见而且显示静态内容时功耗极低非常适合这种长期通电的设备。蜂鸣器选用了一个有源蜂鸣器。有源的意思是给它一个高电平信号它就会持续响驱动非常简单用单片机的一个GPIO口就能直接控制发出响亮的提醒音。“行为侦探”红外对管传感器检测药盒是否被打开取药我用了槽型光电开关红外对管。它有一个凹槽一边发射红外光另一边接收。当药片或手指穿过凹槽时光线被遮挡接收端的电平就会变化。单片机检测这个电平变化就知道有一次取药动作发生从而减少剩余药量计数。把这些器件组合起来就构成了系统的硬件基石。接下来咱们看看它们是如何协同工作的。2. 系统软件设计与工作流程硬件是躯体软件才是灵魂。这个项目的软件逻辑清晰是一个典型的“初始化-主循环-中断响应”的嵌入式架构。2.1 主程序逻辑框架系统上电后的工作流程我用下面这个流程图来概括大家一看就懂上电启动 | V 初始化所有硬件 (AIR32 GPIO、串口、I2C、SPI...) | V ESP01S联网获取网络时间 | V 将网络时间写入DS1302芯片 | V ESP01S连接阿里云物联网平台 | V 进入主循环 1. 从DS1302读取当前时间 2. 在OLED上显示时间、药量等信息 3. 检查是否到达预设的服药时间 ├── 是启动声光报警蜂鸣器LED ├── 否继续等待 4. 检查红外传感器状态 ├── 检测到取药减少剩余药量上传记录到云端 ├── 未检测到继续监控 5. 检查串口处理来自ESP01S的云端消息或用户按键指令这个流程确保了核心的离线提醒功能依赖DS1302绝对可靠而联网功能依赖ESP01S则在此基础上增加了远程监控的便利性。2.2 时间管理与解析项目的“心跳”时间是本项目的核心。我们有两个时间源DS1302本地可靠和网络时间云端精准。系统启动时会先让ESP01S联网获取一次精准的网络时间用来校准DS1302之后就以DS1302的时间为准。从云端服务器获取的时间通常是JSON格式的字符串我们需要从中解析出具体的时、分、秒。原始文章里给出了一个解析函数的示例我把它整理得更清晰一些// 假设从服务器收到的JSON时间数据存储在 Time_buff 数组中 // 数据格式可能类似于{datetime_1: 2023-10-27 14:30:45} void cJSON_Time_Parse(void) { char *data_pt; char hour_string[3] {0}; char minute_string[3] {0}; char second_string[3] {0}; int hour, minute; // 1. 在收到的数据中查找时间字段的起始位置 // 例如查找 datetime_1 这个关键词 data_pt strstr((const char *)Time_buff, datetime_1); // 2. 通过调试串口打印原始数据方便排查问题 UsartPrintf(USART_DEBUG, 收到原始时间数据: %s\r\n, Time_buff); if(data_pt ! NULL) { // 3. 根据已知的JSON格式计算时、分、秒字符的地址 // 假设2023-10-27 14:30:45时间部分从第11个字符开始索引从0算 // 更健壮的做法是使用cJSON库解析这里演示指针偏移的思路 hour_string[0] *(data_pt 24); // 小时十位例如 1 hour_string[1] *(data_pt 25); // 小时个位例如 4 hour_string[2] \0; // 字符串结束符 minute_string[0] *(data_pt 27); // 分钟十位例如 3 minute_string[1] *(data_pt 28); // 分钟个位例如 0 minute_string[2] \0; // 4. 将字符串转换为整数 hour atoi(hour_string); minute atoi(minute_string); UsartPrintf(USART_DEBUG, 解析成功时间: %d:%d\r\n, hour, minute); // 5. 这里可以将hour和minute写入DS1302芯片 // DS1302_SetTime(hour, minute, ...); } else { UsartPrintf(USART_DEBUG, 错误未在数据中找到时间字段\r\n); } }注意上面的代码是示例逻辑实际偏移量24、27需要根据你服务器返回的具体JSON字符串格式来调整。在实际项目中强烈推荐使用cJSON这类库来解析更安全、更灵活。解析出时间后就可以调用DS1302的驱动函数将其设置为芯片的当前时间。之后在主循环里不断读取DS1302的时间并与用户设定的3组服药闹钟时间进行比较从而触发提醒。2.3 云端通信与微信小程序联动物联网的精髓在于数据互通。我选择了阿里云物联网平台作为云端中枢因为它对MQTT协议支持友好并且与微信小程序对接比较方便。通信流程如下设备端AIR32ESP01SESP01S通过AT指令连接家庭Wi-Fi然后作为MQTT客户端连接到阿里云物联网平台指定的服务器地址和端口。发布Publish当药盒被打开取药红外传感器触发或者到达服药时间但未取药时AIR32会格式化一条消息如{event:medicine_taken, box:1, time:14:30}通过串口发送给ESP01S再由ESP01S通过MQTT协议发布Publish到阿里云上该设备对应的Topic主题中。订阅Subscribe同时设备也订阅了另一个Topic用于接收来自云端的指令。微信小程序子女手机上的微信小程序也通过阿里云提供的SDK连接到同一个物联网平台。小程序订阅了设备发布消息的Topic因此能实时收到服药状态更新。反之当子女在小程序上修改服药时间时小程序会向云端发送指令云端再通过设备订阅的Topic将新时间下发给药盒完成远程设置。这样一个双向的、实时的通信链路就建立起来了。微信小程序无需自己搭建复杂的服务器利用成熟的物联网平台大大降低了开发难度。3. 关键代码实现与驱动要点理解了整体框架我们深入几个关键的代码实现细节。3.1 OLED显示驱动OLED显示是给用户最直接的反馈。我们需要显示当前时间、下次服药时间、剩余药量等。显示的核心是字库。对于英文和数字我们可以直接使用编译器自带或简单的点阵字库。对于中文则需要提取中文字模。原始工程中提供了几个显示函数的示意图其核心思想是将屏幕缓冲区一个数组对应到OLED的每一个像素点。根据要显示的数字或汉字查找到对应的点阵数据字模。将这些点阵数据按位设置到屏幕缓冲区的特定位置。最后调用OLED_Refresh()之类的函数将整个缓冲区一次性更新到OLED硬件上。例如显示一个两位的小时数“14”// 伪代码展示思路 void Show_Hour(int hour) { int tens_digit hour / 10; // 获取十位数1 int ones_digit hour % 10; // 获取个位数4 // 假设数字字模是8x16像素 int pos_x 0; // 起始X坐标 int pos_y 0; // 起始Y坐标 // 在屏幕缓冲区(pos_x, pos_y)位置绘制数字‘1’的点阵 Draw_Char(tens_digit, pos_x, pos_y); // 在(pos_x8, pos_y)位置绘制数字‘4’的点阵 Draw_Char(ones_digit, pos_x8, pos_y); // 刷新到OLED屏幕 OLED_Refresh(); }在实际项目中你可以使用u8g2、Adafruit_SSD1306等成熟的OLED驱动库它们已经封装好了这些底层操作你只需要调用print函数即可效率高得多。3.2 红外传感器检测与防抖红外传感器的检测逻辑相对简单但防抖处理至关重要。因为机械开关或红外检测可能存在瞬间的抖动导致一次动作被误判为多次。// 检测药盒取药动作假设低电平表示被遮挡 #define MEDICINE_TAKEN_PIN GPIO_Pin_0 #define MEDICINE_TAKEN_PORT GPIOA uint8_t Check_Medicine_Taken(void) { static uint32_t last_detect_time 0; uint32_t current_time Get_SystemTick(); // 获取系统滴答时钟 // 1. 读取红外传感器引脚电平 if(GPIO_ReadInputDataBit(MEDICINE_TAKEN_PORT, MEDICINE_TAKEN_PIN) 0) { // 2. 检测到低电平遮挡进行防抖判断 // 如果距离上一次有效检测时间太短比如300毫秒内认为是抖动忽略 if((current_time - last_detect_time) 300) { last_detect_time current_time; // 3. 执行取药成功后的操作减少药量、上传记录等 Reduce_Medicine_Count(); Upload_Record_To_Cloud(); return 1; // 返回1表示一次有效的取药动作 } } return 0; // 返回0表示未检测到有效动作 }在主循环中定期比如每50ms调用这个函数就能稳定可靠地检测取药行为。3.3 微信小程序时间选择器子女端的小程序核心功能之一是设置服药时间。这里用到了微信小程序的picker-view组件来实现一个滚轮式的时间选择器体验很好。关键思路是创建一个独立的组件如scrollSelecter.vue在里面定义好小时和分钟的滚动数据。在添加服药计划的页面引入这个组件并通过bindChange事件监听用户滚动选择的值将其存储起来最终在保存时通过MQTT下发到设备。4. 硬件设计与调试心得4.1 PCB与结构设计双层堆叠设计为了紧凑和模块化我采用了双层PCB设计。底层PCB放置红外传感器模块和ESP-01S Wi-Fi模块顶层PCB则是AIR32主控、DS1302、OLED屏和蜂鸣器等。两层之间通过铜柱和排针连接结构清晰也便于单独调试。供电整个系统通过Type-C接口供电方便通用。注意要在DS1302的备用电池引脚上连接一个纽扣电池座确保断电时时钟不停。外壳使用3D打印如嘉立创三维猴制作外壳将PCB、药盒仓整合在一起成为一个完整的产品。4.2 调试技巧与常见问题ESP-01S连接不稳定问题有时连不上Wi-Fi或频繁断开。解决确保AT固件版本较新给ESP-01S的电源引脚并联一个100uF以上的电容提供瞬间大电流检查路由器信道尽量使用2.4GHz频段。DS1302时间不准问题走时一段时间后偏差较大。解决检查外部晶振通常是32.768kHz的负载电容是否匹配确保备用电池电压充足软件上可以增加每天一次联网同步网络时间的功能。OLED显示乱码问题显示汉字或特殊字符时出现乱码。解决确认使用的字库编码GB2312/UTF-8与程序中的编码一致检查字模数据提取是否正确确认I2C通信速率是否过高尝试降低速率。红外传感器误触发问题没有取药时也计数。解决除了软件防抖可以调整红外对管的灵敏度如果有电位器或者增加遮挡物的检测阈值判断比如持续遮挡超过一定时间才算有效。这个项目从构思到实现涉及了嵌入式硬件设计、单片机编程、物联网通信和微信小程序开发是一个非常好的全栈式学习案例。我把核心的嵌入式代码和微信小程序代码都开源了遵循GPL 3.0协议链接在原始文章末尾。你可以直接参考使用也可以在此基础上增加更多功能比如语音提醒、多药盒管理、用药报告生成等。希望这篇详细的解析能帮你少走弯路做出属于自己的智能硬件产品。