《记忆相机-阿尔兹海默症提醒器》

2026-11-105

作品说明

一、背景分析与设计要求

摘要:本项目是一台针对阿尔兹海默症(Alzheimer's disease)患者设计的「记忆相机」。它以 Arduino UNO 为控制核心,把二哈(HUSKYLENS)人工智能摄像头、串口 MP3 语音模块、DS1307 实时时钟模块和扬声器装进一个相机造型的激光切割外壳里,实现两项核心功能:一是认人播报——摄像头识别到已录入的家人面孔时,用家属录制的语音播报对方身份,帮患者「记住这是谁」;二是定时提醒——到点自动循环播放用药、检查、活动的提醒语音,帮患者「记住该做什么」。整个装置做成相机外形并配上可调节背带,是为了让它看起来像一件随身小物,而不是一台冷冰冰的监护设备。

关键词:阿尔兹海默症;人脸识别;HUSKYLENS;Arduino UNO;串口 MP3 语音模块;DS1307 实时时钟;激光切割结构

1.1 背景与问题提出

阿尔兹海默症是老龄化社会绕不开的一道坎。按照本作品创作说明中引用的数据,我国目前大约有 600 万~800 万名阿尔兹海默症患者;随着世界人口老龄化加剧,该病的患病率还在持续升高。

患者最先失去的往往是「近事记忆」:刚放下的东西找不到,刚说过的话记不住,忘记日常要做什么;病情加重后,甚至会把最亲密的人也忘掉,出现失语、失用、失认的现象。创作说明里写下的是一个很朴素的判断——目前的医疗技术还不能实现阿尔兹海默症的治愈。既然治不好,那能做的事情就变成了:尽量延缓认知障碍带来的生活困难,让患者的日子好过一点。

带着这个判断,小组把目光收窄到两个具体的、每天都会发生的小麻烦上:

  • 认不出家人。患者看着站在面前的人,知道「我应该认识这个人」,却叫不出名字、想不起来是什么关系。这种挫败感会让他逐渐回避交流。
  • 忘记按时用药和日常活动。吃药、常规检查、日常运动这些事都有固定时间点,患者自己记不住,家属又不可能时时刻刻在旁边盯着。

这两件事都不是靠「多提醒几遍」能解决的——提醒的人不在的时候,问题依然存在。于是项目的目标被明确下来:做一台能随身带着、能认人、能准点开口的提醒器。

1.2 主体结构与工作流程

本作品整体做成相机外形,配一条可调节背带;内部由 UNO 主控板、二哈 AI 摄像头、语音模块、时钟模块和喇叭组成。摄像头装在正面,负责「看」;语音模块和喇叭负责「说」;时钟模块负责「记时间」;UNO 负责把这三件事串起来。

整机的工作流程可以概括成一句话:摄像头看人脸,时钟看时间,两路信息都交给 UNO 判断,再由喇叭把结果说出来。具体分成两条并行的支线,它们在程序的主循环里交替执行:

支线触发条件装置的动作解决的问题
认人播报二哈摄像头在画面中检测到人脸方框,且该人脸的 ID 为已录入的 1 号或 2 号播放与该 ID 对应的家人语音,播完保持一段时间不重复打扰患者认不出眼前的人时,听到熟悉的声音说出身份
定时提醒DS1307 读到的「时」与「分」命中了程序里预设的时刻连续重复播放 3 次提醒语音,每次间隔 8 秒到点提醒吃药、做检查、做日常运动

两条支线共用一个喇叭,因此程序里需要处理「谁先说话」的问题——这也是后面编程流程分析中要重点交代的一处细节:当画面里没有家人面孔时,程序会主动把语音播放模式置为「结束播放」,避免上一段语音还没播完、下一段又被塞进去。

1.3 设计要求

1.3.1 功能要求

功能要求来自创作说明里列出的功能设想,逐条整理如下:

编号功能要求本作品的实现方式
F1识别家人身份并语音播报HUSKYLENS 切换至「人脸识别」算法,对家人人脸进行学习并保存;再次识别到时按 ID 播放对应语音
F2定时语音提醒DS1307 提供当前时间,程序在预设时刻触发语音提醒
F3语音内容亲切、熟悉语音由家属录制,内容尽量模仿患者熟悉、亲近的语气
F4便于携带、不易丢失相机造型配可调节背带,做成随身小物的样子
F5不需要患者操作上电即自动运行,患者全程不需要按任何按键

其中 F3 是这份作品比较特别的一条要求。它不是技术指标,而是一条情感指标:创作说明里写得很清楚——「语音内容尽量模仿使患者熟悉、亲近的语气。在实现功能的同时,让患者保持愉悦的心情。」换句话说,装置发出的声音不能是一段机械的电子提示音,而应该是女儿、儿子、老伴的声音。

1.3.2 工程结构要求

项目要求本作品的处理
外形亲切、不引起抵触做成相机造型,患者把它当相机而不是监护仪
携带可随身佩戴或挎带配备可调节背带
结构板件拼装、边角安全SketchUp 建模后由 LaserMaker 输出激光切割板件拼装
安装模块位置固定、连线可靠主控与扩展板居中,摄像头正面开孔,喇叭出声孔在正面下方
供电与运行上电即用、无需操作通电后程序自动进入初始化并进入主循环
工艺外壳厚度均匀、装配到位板材切割后按槽位插接,模块用螺丝/扎带固定

需要如实说明一处:申报材料中没有给出整机的具体外形尺寸与板材厚度,因此本文不填写这两项数据,只描述结构与装配关系。

二、设计思维导图

整个项目从需求出发,沿「硬件方案—软件功能—结构设计—制作与验证—应用场景」五条线同时展开,最终收拢到「记忆相机」这一台装置上。下面这张思维导图把小组的设计思路完整摊开:

记忆相机需求分析阿尔兹海默症人群上升近事记忆减退 · 认人困难按时用药容易遗忘硬件方案Arduino UNO 主控二哈 AI 摄像头(I2C)串口 MP3 + 扬声器DS1307 实时时钟结构设计相机造型降低抵触感激光切割板件拼装可调节背带便于携带软件功能人脸识别 → 语音播报身份定时到点 → 语音提醒音量与结束播放控制应用场景居家养老陪伴社区日间照料中心创客与人工智能课程制作与验证SketchUp 结构建模LaserMaker 激光切割真人录入 · 现场演示

图 2-1 记忆相机设计思维导图

从导图可以看出,这个项目有两条并行的主线:一条是感知与发声(摄像头看、喇叭说),另一条是时间与提醒(时钟计时、到点开口)。两条主线共用一块主控板和一个发声器件,这也是后面硬件选型时最需要权衡的地方。

三、硬件选用与连接

3.1 硬件选型与清单

选型的总体思路是「稳定优先、模块化拼装、不自己画电路板」,所有功能模块都选用现成的开源硬件,用杜邦线连接。创作说明中对此有一句直接的表态:「选择 arduino UNO 主板做控制板,稳定,故障率低。」

序号器材型号 / 规格数量作用
1主控板Arduino UNO1读取传感器数据、判断条件、控制语音模块
2扩展板DFRobot I/O Expansion Shield V71把 UNO 的 D0–D13、A0–A5 引出为排针,方便接多个模块
3AI 摄像头Gravity HUSKYLENS 人工智能摄像头(SEN0305)1人脸识别,输出画面中的人脸方框与 ID
4语音模块Gravity UART 串口 MP3 语音模块(DFR0534)1读取 TF 卡中的语音文件并按编号播放
5时钟模块I2C DS1307 RTC 实时时钟模块(DFR0151)1提供年、月、日、时、分、秒,供定时判断使用
6扬声器无源喇叭1把语音模块的音频信号放出来
7存储卡TF 卡1存放家属录制的语音文件
8结构板材激光切割板材若干拼装相机外形外壳
9背带可调节背带1便于患者随身携带

关于金额:申报材料(作品登记表、创作说明、讲解稿)只写了作品名称、大小与所用软件环境,没有逐项列出采购单价与合计金额,因此本表只列名称、型号与数量,不填写金额,也不做估算。

需要说明的是,表中第 3、4、5 项的型号SEN0305、DFR0534、DFR0151均来自作品创作说明「参考资源」一栏中列出的官方产品页链接,不是推测;第 2 项扩展板型号来自作品附带的硬件连接图(图上印有 I/O Expansion Shield V7 字样)。

外观结构上还有一个容易忽略的细节:连接图里的扩展板带了一排彩色电源/信号排针(VCC 红、GND 黑、D0–D13 绿、A0–A5 蓝),这套颜色约定在后面的接线环节里起到了防呆作用——红找红、黑找黑,插反的可能性大大降低。

3.2 硬件连接

连接关系并不复杂,四类模块各自接到主控上,其中三个走总线、一个走串口、一个走模拟音频线。整体连接关系如下:

图 3-1 硬件连接关系总览:哈仕奇 AI 摄像头与 DS1307 时钟模块走 IIC 总线,MP3 模块走串口数据线,扬声器接 MP3 模块的 SP+/SP−

图 3-1 硬件连接关系总览:哈仕奇 AI 摄像头与 DS1307 时钟模块走 IIC 总线,MP3 模块走串口数据线,扬声器接 MP3 模块的 SP+/SP−

图 3-2 主控部分:Arduino UNO 插在 DFRobot I/O Expansion Shield V7 扩展板上,扩展板把 D0–D13 与 A0–A5 全部引出

图 3-2 主控部分:Arduino UNO 插在 DFRobot I/O Expansion Shield V7 扩展板上,扩展板把 D0–D13 与 A0–A5 全部引出

各模块与主控的具体连接关系整理如下:

模块接口类型接到主控的引脚说明
HUSKYLENS 二哈摄像头I2CSDA = A4,SCL = A5,器件地址 0x32程序中「HuskyLens 初始化引脚为」的设置项里明确选择了 I2C 方式,并给出地址 0x32 与 A4/A5 两根信号线
串口 MP3 语音模块软串口(Software Serial)Rx(绿)= 3,Tx(蓝)= 4程序中「初始化串口 MP3 模块」设置为软串口,Rx 接 3 号、Tx 接 4 号
DS1307 实时时钟模块I2CSDA = A4,SCL = A5连接图上该模块标注为 IIC 接口,与摄像头共用同一条 I2C 总线
扬声器模拟音频接 MP3 模块的 SP+ / SP−不做数据通信,只负责把音频电流变成声音
供电板载电源扩展板 5V / GND 排针三个模块均由扩展板统一供电

⚠️ 一处必须交代的素材差异:作品附带的硬件连接图上,MP3 模块的数据线标注为 D11 与 D10;而 Mind+ 程序里「初始化串口 MP3 模块」这一块填的是Rx = 3、Tx = 4。两者对不上。按「以程序为准」的原则,本文的引脚表采用 Rx = 3 / Tx = 4,并以程序截图作为依据(见第六章图 6-2)。连接图上出现 D10/D11 标注,推测是画图阶段的早期方案或版式遗留,这里如实写出差异,不做取舍性改写——动手复现时请以程序中的设置为准。

3.3 分模块参数与选型理由

各模块的关键参数与选用理由如下:

模块关键参数选型理由
Arduino UNOATmega328P 主控;数字口 D0–D13、模拟口 A0–A5;USB 供电与下载生态成熟、资料多、稳定性好,是入门级开源硬件里故障率最低的选择之一
I/O 扩展板 V7引出全部 D0–D13 与 A0–A5 排针;板载 5V/3.3V 与 GND 汇流排;另有 SERVO_PWR 独立供电口UNO 原生排针数量有限,接三个模块后接线拥挤;扩展板把引脚分成整齐的排针列,接线更清楚,也减少插错
HUSKYLENS(SEN0305)2.0 寸屏;内置多种视觉算法,人脸识别模式可学习并保存多个人脸,输出方框与 ID;支持 I2C / UART 两种通信方式摄像头自带屏幕和算法,识别结果直接以「方框 + ID」给出,主控只需读结果,不必在 UNO 上跑图像处理——这对算力有限的 UNO 来说是关键
串口 MP3 模块(DFR0534)UART 控制;支持 TF 卡;可设置音量与播放模式,支持按编号点播语音文件放在 TF 卡里,家属自己录、随时换;按编号点播正好对应「1 号人脸播 01 首、2 号人脸播 02 首」的逻辑
DS1307 时钟模块(DFR0151)I2C 接口;提供年月日时分秒;带纽扣电池座,断电后继续走时定时提醒必须有一个「不会因为主控断电就归零」的时间源;DS1307 走 I2C,与摄像头共用两根线,不占额外引脚
无源扬声器接 SP+/SP−作品创作说明中明确使用无源喇叭,由 MP3 模块内置功放直接驱动

三个核心模块的外观与接口如下,可与上面的参数表对照查看:

图 3-3 Gravity HUSKYLENS 人工智能摄像头(SEN0305):自带 2.0 寸显示屏与多种视觉算法,底部为 IIC 接口(与主控的 A4/A5 相连)

图 3-3 Gravity HUSKYLENS 人工智能摄像头(SEN0305):自带 2.0 寸显示屏与多种视觉算法,底部为 IIC 接口(与主控的 A4/A5 相连)

图 3-4 串口 MP3 语音模块(DFR0534):左侧为 UART 接口的 VCC/GND/RX/TX 四线,右侧 SP+/SP− 接扬声器。注意图中数据线旁标注的 D11 / D10 与程序中的 Rx=3、Tx=4 不一致,以程序为准

图 3-4 串口 MP3 语音模块(DFR0534):左侧为 UART 接口的 VCC/GND/RX/TX 四线,右侧 SP+/SP− 接扬声器。注意图中数据线旁标注的 D11 / D10 与程序中的 Rx=3、Tx=4 不一致,以程序为准

图 3-5 I2C DS1307 RTC 实时时钟模块(DFR0151):右侧为 IIC 接口(与摄像头共用同一条 I2C 总线),板上有纽扣电池座

图 3-5 I2C DS1307 RTC 实时时钟模块(DFR0151):右侧为 IIC 接口(与摄像头共用同一条 I2C 总线),板上有纽扣电池座

图 3-6 无源扬声器:两根线接到 MP3 模块的 SP+/SP−,由模块内置功放直接驱动

图 3-6 无源扬声器:两根线接到 MP3 模块的 SP+/SP−,由模块内置功放直接驱动

这套选型里最值得说的一点,是把「识别」这件事完全交给了摄像头模块。UNO 是 8 位单片机,跑不动人脸识别;而 HUSKYLENS 自带处理器和算法,把「谁的脸、在画面哪个位置」直接算成两个数字(ID 与方框)交给 UNO。让专业的模块干专业的事,是这份作品能在入门级主控上跑通 AI 功能的关键。

四、结构安装与制作过程

4.1 外观设计

外观设计是这份作品里最容易被当成「装饰」、实际上最有想法的一环。创作说明里对原创部分的第一条描述就是外形:「整体呈相机外形配有调节背带,更加美观方便便于携带,不易丢失。」

为什么是相机?把这句话拆开看,背后是三层考虑:

  1. 心理层面。如果装置做成长方体盒子、贴着「提醒器」「监护仪」的标签,患者很容易产生被当成病人看待的抵触感,进而不愿意随身带着。做成相机,它首先是一件「物件」,其次才是一件「工具」。
  2. 功能层面。摄像头必须朝前对着人,而相机的形态天然就是「一个朝前的镜头 + 一个握持机身」,镜头开孔的位置不需要额外解释。
  3. 携带层面。相机本来就配挂绳背带,把背带变成整机的一部分,比另外设计一个佩戴方案更自然。

从结构建模图可以看到具体的外观处理:机身为竖长方形的小盒,正面左上位置开了一个圆形大孔,用来露出摄像头的镜头;正面下方开了一个矩形出声孔,让喇叭的声音透出来;机身右侧留了一条橙色的竖条作为视觉分割,顶部有挂绳的穿绳孔。配色上机身主体用绿色、镜头环与分割条用橙色,两种颜色反差明显,让这台小装置看起来更像一件玩具、而不是医疗器械。

图 4-1 外观设计:SketchUp 建立的三维模型(机身绿色、镜头环与侧面分割条橙色,正面下方为喇叭出声孔,顶部留挂绳孔)

图 4-1 外观设计:SketchUp 建立的三维模型(机身绿色、镜头环与侧面分割条橙色,正面下方为喇叭出声孔,顶部留挂绳孔)

图 4-2 早期手绘设计草图:相机机身、背带与屏幕位置的最初设想

图 4-2 早期手绘设计草图:相机机身、背带与屏幕位置的最初设想

把手绘草图(图 4-2)和最终的三维模型(图 4-1)放在一起看,能看出一次明显的方案调整:草图阶段画的是一个横置的传统相机——大镜头居中、顶部有取景结构、还画了一根粗背带;而到三维建模阶段,机身改成了竖置、镜头缩小并移到左上方,正面腾出的空间留给了出声孔。竖置的好处是单手握持时手掌能整个包住机身,出门挂绳时机器是竖着贴在胸前的,镜头方向依然朝前。

这里需要如实说明一处:讲解稿里提到过「屏幕显示文字」的功能设想,但在最终提交的 Mind+ 程序里并没有出现任何显示屏相关的积木,也不存在独立的显示模块。程序与连接图里唯一的屏幕是 HUSKYLENS 摄像头自带的2.0 寸屏(用于显示识别框与 ID)。因此本作品的实际提示方式是纯语音,正文按程序与连接图呈现,不写屏幕文字显示功能。

4.2 结构建模

外壳用 SketchUp 2019 建模,先确定外形,再把内部模块的位置倒推出来。建模阶段要解决的几个问题是:

  • 镜头开孔的圆心位置要正好落在摄像头模块的镜头上,孔径既不能大到露出模块外壳,也不能小到挡住视野;
  • 出声孔要开在喇叭正前方,且开孔总面积要够大,否则声音会被闷在盒子里;
  • 机身内部要给 UNO + 扩展板留出高度,扩展板插上 UNO 之后是一个「双层汉堡」结构,比单块 UNO 高不少;
  • 顶部要留挂绳孔,孔的直径要能穿过背带的绳扣。

建模完成后再把机身拆成一圈侧板、一块面板、一块底板,转成平面图纸交给激光切割软件。

4.3 激光切割下料

切割环节使用 LaserMaker,把 SketchUp 拆解出的板件轮廓导入后排版下料。作品创作说明在「制作用软件及运行环境」里列出的正是这一套组合:建模用 SketchUp 2019、激光切割用 LaserMaker、编程用 Mind+ V1.7.3 RC1.0、运行环境 Windows 10。

图 4-3 在 LaserMaker 里排版下料的板件图:机身面板、侧板与卡槽按轮廓排布,模拟造物确认无误后再开始切割

图 4-3 在 LaserMaker 里排版下料的板件图:机身面板、侧板与卡槽按轮廓排布,模拟造物确认无误后再开始切割

排版时有两条基本规则:一是同一块板上的零件尽量紧凑排布,省料;二是卡槽宽度要与板材厚度一致,太松装不住、太紧插不进。作品没有留下切割参数(速度、功率)的记录,因此本文不填写具体数值。

4.4 装配

装配按「先装模块、再装线路、最后合壳」的顺序进行:

  1. 固定主控。把 UNO 插到 I/O 扩展板上,再把这一组固定到机身内部底板上;
  2. 装摄像头。把二哈摄像头贴到前面板内侧,调整位置让镜头正对面板上的圆形开孔;
  3. 装喇叭。把扬声器贴在面板内侧出声孔的位置,用胶固定,避免震动时移位;
  4. 接时钟。DS1307 模块接到 I2C 排针上,注意与摄像头共用同一条总线;
  5. 接语音模块并插卡。串口 MP3 模块按软串口接好数据线,装上存有语音文件的 TF 卡;
  6. 合壳、穿背带。确认所有连线没有压在板件接缝上,合上前板后从顶部孔穿过背带。

装配过程中最容易出问题的环节是线材的收纳。三个模块加一个喇叭共有一大把杜邦线,如果随手塞进盒子里,合壳时会顶住面板、也可能把排针压弯。实际处理办法是把连线沿机身侧壁盘绕,再用扎带固定在底板上的走线槽位置,让线束贴着壳体走而不是悬在中间。

4.5 成品与实测

图 4-4 成品实物:浅色激光切割外壳,正面左侧为摄像头开孔、右下为喇叭出声孔格栅,顶部为挂绳孔

图 4-4 成品实物:浅色激光切割外壳,正面左侧为摄像头开孔、右下为喇叭出声孔格栅,顶部为挂绳孔

图 4-5 另一视角的成品实物:可以看清出声孔格栅与一侧的数据线出口

图 4-5 另一视角的成品实物:可以看清出声孔格栅与一侧的数据线出口

从实物图可以看出,成品与三维模型在整体思路上是一致的——竖长方形机身、正面一个镜头孔、下方一片出声孔格栅、顶部挂绳。结构板材的浅色与建模图里的绿色配色不同,这一点需要说明:SketchUp 模型里的绿色/橙色是方案阶段的配色效果示意,实物外壳使用的是浅色板材(表面未做二次上色)。

功能验证分成两个部分,都由学生在现场演示中完成:

验证项操作观察到的结果
人脸录入对着二哈摄像头完成人脸学习,把家人的面孔录入并保存摄像头屏幕上为人脸分配编号(1 号、2 号)
认人播报让已录入的人出现在镜头前装置识别出人脸并按编号播出对应的家人语音
定时提醒把装置的时间设到预设时刻(演示时设为早上 8 点半)装置连续播出 3 次提醒语音,间隔 8 秒,语音内容为提醒吃药

 

五、编程流程分析

程序用 Mind+ V1.7.3 RC1.0 编写,工程文件名为 HM-UNO.mp。整体采用了「主程序 + 三个自定义块」的结构,这样安排的好处是主程序一眼就能看懂,复杂的判断逻辑各自封装起来,修改定时时刻时只需要打开「定时」这一块。

5.1 主程序结构

主程序只有四步,非常短:

  1. 调用自定义块「初始化」——把摄像头和语音模块都配置好;
  2. 进入「循环执行」;
  3. 在循环里先调用「人脸识别」;
  4. 紧接着调用「定时」,然后回到循环顶部继续下一轮。

Arduino UNO 通电 · 程序启动自定义块:初始化HuskyLens 初始化引脚为 · 直到成功切换到 人脸识别 算法 · 直到成功MP3 软串口 Rx=3(绿) Tx=4(蓝)· 音量 100%循环执行(无限)自定义块:人脸识别请求一次结果 → 判断画面方框与 ID命中 1 号 / 2 号人脸时播放对应语音自定义块:定时读取 DS1307 的「时」与「分」命中预设时刻 → 重复播放提醒语音返回循环顶部

图 5-1 主程序执行流程:初始化一次,之后在循环中交替执行「人脸识别」与「定时」两个自定义块

把「人脸识别」和「定时」放进同一个循环里轮流执行,是一个很实际的取舍:一台 UNO 没法同时做两件事,但两个功能的响应要求都不高——人脸识别慢一点没关系(人站在面前总会停一会儿),定时判断慢一点也没关系(提醒晚个一两秒不影响)。轮流执行是这类单核主控最常见、也最省事的方案。

5.2 初始化:把两个模块调起来

「初始化」块要完成四件事,程序截图里可以看到完整的四行积木(见第六章图 6-2):

顺序积木参数作用
1HuskyLens 初始化引脚为I2C 方式,地址 0x32,SDA=A4,SCL=A5;积木后缀为「直到成功」等待摄像头握手成功。直到成功意味着如果接触不良,程序会一直重试而不是带着错误往下跑
2HuskyLens 切换到「人脸识别」算法算法 = 人脸识别(faceRecognition);后缀同样为「直到成功」告诉摄像头用哪一种识别算法。摄像头支持多种算法,必须显式切换
3初始化串口 MP3 模块接口 = 软串口;Rx(绿) = 3,Tx(蓝) = 4用两个普通数字口模拟出一路串口,专门跟 MP3 模块通信
4设置串口 MP3 模块的音量为100 %把音量拉满。患者多有听力衰退,音量留小了等于没提醒

其中「直到成功」这个后缀值得单独说一句:它让初始化变成了一个带有等待性质的步骤——没成功就不往下走。对于一台给老人用的设备来说,这比「初始化失败也照样跑」要安全得多。

5.3 人脸识别:从「看到方框」到「知道是谁」

这个自定义块的逻辑是一条典型的判断链,一共三层:

  1. 第一层:请求数据。「HuskyLens 请求一次数据存入结果」——让摄像头做一次识别,把结果取回本地;
  2. 第二层:判断画面里有没有人。「从结果中获取 方框 是否在画面中?」——注意取的是方框(box)而不是别的对象,这一句决定了画面里到底有没有检测到人脸;
  3. 第三层:判断是谁。「从结果中获取靠近中心 方框 的 ID」与 1、2 比较——取的是最靠近画面中心的那个人脸,这样避免了远处背景里有人脸时被误判。

进入「人脸识别」HuskyLens 请求一次数据存入结果从结果中获取「方框」是否在画面中?结束播放设置播放模式为:结束播放否是从结果中获取靠近中心的方框 ID = ?ID = 1播放第 01 首语音等待 8 秒ID = 2播放第 02 首语音等待 6 秒1 号人脸2 号人脸

图 5-2 「人脸识别」自定义块流程:先判断画面是否有方框,再按靠近中心的方框 ID 分派到 1 号或 2 号语音

判断结果装置的动作等待时长
画面中没有方框把 MP3 播放模式置为「结束播放」不等待
方框 ID = 1播放第 01 首语音8 秒
方框 ID = 2播放第 02 首语音6 秒

这里有两个细节是学生自己加的、很值得肯定的处理:

  • 「结束播放」这条兜底分支。当画面里没有人脸时,程序主动让语音模块停下来。如果不写这一句,上一段播报还没结束、下一轮循环又发了一条新指令,语音就会互相打断、变成一片嘈杂。
  • 不同的等待时长。1 号语音等 8 秒、2 号语音等 6 秒。两个数字不同,说明学生是按实际语音文件的长度分别设的——等待时间必须不短于语音长度,否则话说到一半就被下一轮循环打断。

5.4 定时:把时间点写进条件里

「定时」块用「获取 DS1307 时间」取出时分,再跟预设值比较。整个块是一条四分支的级联判断加一条兜底分支:

进入「定时」· 读取 DS1307 时间如果时 = 8 且 分 = 30执行重复 3 次:播放第 04 首语音 → 等待 8 秒否则如果时 = 13执行重复 3 次:播放第 04 首语音 → 等待 8 秒否则如果时 = 21执行重复 3 次:播放第 04 首语音 → 等待 8 秒否则如果时 = 16执行重复 3 次:播放第 05 首语音 → 等待 8 秒否则以上四个时刻都不满足执行设置播放模式为:结束播放

图 5-3 「定时」自定义块流程:四个时刻分别触发对应语音,其余情况让语音模块停止播放

分支判断条件执行的动作用对应场景(依据演示讲解)
1时 = 8 且 分 = 30重复 3 次:播放第 04 首语音,等待 8 秒演示中明确说明「设置的时间是早上的八点半」,播报内容为提醒吃药
2时 = 13重复 3 次:播放第 04 首语音,等待 8 秒中午时段的提醒(讲解中提到还会设置做检查的语音播报)
3时 = 21重复 3 次:播放第 04 首语音,等待 8 秒晚间时段的提醒
4时 = 16重复 3 次:播放第 05 首语音,等待 8 秒下午时段,使用另一段语音
兜底以上都不满足设置播放模式为「结束播放」非提醒时段保持安静

关于这一块,有三点必须如实指出:

  • 只有第一个分支同时判断了「时」和「分」。8 点 30 分那个分支用了「与」把两个条件连起来,而 13 点、21 点、16 点三个分支只判断了「时」,没有判断「分」。这意味着后三个分支只要到了那个小时就会触发,相当于「每小时提醒一次」。这是程序的真实状态,本文照实呈现,并在第九章的改进方向里提出来的。本文不做善意修补式的改写。
  • 重复 3 次是为了「叫得住」。每个分支都用「重复执行 3 次」把语音连播三遍、每遍之间等 8 秒。对于记性不好的患者,说一遍很容易被忽略,连说三遍的提醒强度明显更高。
  • 「否则」分支同样是「结束播放」。和「人脸识别」块里的兜底逻辑一样,非提醒时段主动让语音停下来,避免残留播放。两处兜底说明学生在调试中确实被「语音乱响」坑过。

5.5 两个功能之间的配合

把两个自定义块放在一起看,会发现它们共享同一个喇叭,因此必须回答「谁先说话」这个问题。程序给出的答案是约定式的互斥:任一分支判定为「不需要说话」时,都主动发送「结束播放」。这样无论上一轮是哪条支线在发声,只要本轮的条件不满足,声音就会被立刻收住。

这种做法简单、够用,但也有代价:人脸识别与定时提醒可能互相打断——如果患者在提醒语音播到一半时出现在镜头前,人脸播报会插进来。这一点在第九章的改进方向里会具体说明。

六、参考代码

6.1 图形化程序原貌

本作品是用 Mind+ 的图形化方式编写的,没有手写代码文件。下面三张截图是工程 HM-UNO.mp 的程序全貌,按「自定义块」分组呈现,可以直接与第五章的流程分析对照着看。

图 6-1 主程序与「人脸识别」自定义块:Uno 主程序里先调「初始化」,再进入循环交替调用「人脸识别」与「定时」;人脸识别块内按靠近中心的方框 ID 分派到 01、02 两段语音

图 6-1 主程序与「人脸识别」自定义块:Uno 主程序里先调「初始化」,再进入循环交替调用「人脸识别」与「定时」;人脸识别块内按靠近中心的方框 ID 分派到 01、02 两段语音

图 6-2 「初始化」自定义块:HuskyLens 初始化引脚(直到成功)、切换到人脸识别算法(直到成功)、初始化串口 MP3 模块(软串口,Rx=3 / Tx=4)、音量 100%

图 6-2 「初始化」自定义块:HuskyLens 初始化引脚(直到成功)、切换到人脸识别算法(直到成功)、初始化串口 MP3 模块(软串口,Rx=3 / Tx=4)、音量 100%

图 6-3 「定时」自定义块:四个时刻的分支判断与兜底分支,每个命中分支都重复播放 3 次、每次等待 8 秒

图 6-3 「定时」自定义块:四个时刻的分支判断与兜底分支,每个命中分支都重复播放 3 次、每次等待 8 秒

从截图右上角可以确认软件版本与工程名:Mind+ V1.7.3 RC1.0,工程 HM-UNO.mp;截图右下角的系统时间为 2023/2/18,与登记表上填写的日期一致。

6.2 等价的 Arduino C 参考代码

图形化程序最终也是要编译成 C++ 烧进 UNO 的。为了便于理解程序结构、也方便后来者在纯代码环境下复现,下面按图形化程序的逻辑整理出一份等价的 Arduino C 参考代码,并逐行加上中文注释。

⚠️ 代码出处说明:以下代码是依据本作品 Mind+ 图形化程序的功能逻辑整理而成,不是工程文件里导出的原始代码。其中 DS1307 与二哈摄像头的调用采用对应开源库的公开接口,串口 MP3 模块的三个操作(初始化、设音量、按编号点播)在 Mind+ 里由「串口 MP3」扩展提供,不同版本扩展的函数命名可能不同,这里按功能语义命名并标明用途。复现时请以 Mind+ 对应扩展生成的代码为准。

/* =========================================================
 *  记忆相机 - 阿尔兹海默症提醒器
 *  主控:Arduino UNO + DFRobot I/O Expansion Shield V7
 *  本代码依据 Mind+ 图形化工程的逻辑整理,供理解程序结构使用
 * ========================================================= */

#include <Wire.h>                  // I2C 总线,二哈摄像头与 DS1307 都挂在上面
#include "HUSKYLENS.h"             // 二哈 AI 摄像头库
#include "DFRobot_DS1307.h"        // DS1307 实时时钟库
#include <SoftwareSerial.h>        // 软串口:用两个普通数字口模拟一路串口给 MP3 用

/* ---------- 引脚定义(与图形化程序中的设置一致) ---------- */
#define MP3_RX_PIN   3             // MP3 模块的 Rx(绿线)接 UNO 的 3 号口
#define MP3_TX_PIN   4             // MP3 模块的 Tx(蓝线)接 UNO 的 4 号口
// 二哈摄像头走 I2C:SDA = A4、SCL = A5,器件地址 0x32(硬件固定,不需在此定义)

/* ---------- 语音编号约定(对应 TF 卡中的语音文件) ---------- */
#define VOICE_FACE_1      1        // 1 号人脸  -> 第 01 首语音(家属 A)
#define VOICE_FACE_2      2        // 2 号人脸  -> 第 02 首语音(家属 B)
#define VOICE_REMIND_A    4        // 用药提醒  -> 第 04 首语音
#define VOICE_REMIND_B    5        // 检查提醒  -> 第 05 首语音

/* ---------- 等待时长(毫秒):不得短于对应语音的实际长度 ---------- */
#define WAIT_LONG   8000UL         // 8 秒:用于播报较长的人脸语音与用药提醒
#define WAIT_SHORT  6000UL         // 6 秒:用于 2 号人脸的语音

/* ---------- 对象实例化 ---------- */
SoftwareSerial  mp3Serial(MP3_RX_PIN, MP3_TX_PIN);   // MP3 模块专用软串口
HUSKYLENS       huskylens;                            // 二哈摄像头
DFRobot_DS1307  ds1307;                               // DS1307 时钟

/* =========================================================
 *  串口 MP3 模块的三个操作(由 Mind+ 的「串口 MP3」扩展提供)
 *  下面的写法按功能语义命名,实际函数名以所用扩展生成的代码为准
 * ========================================================= */
void mp3Init() {                       // 对应积木:初始化串口MP3模块
  mp3Serial.begin(9600);               // 软串口波特率
  delay(200);                          // 给模块上电留出握手时间
}

void mp3SetVolume(uint8_t vol) {       // 对应积木:设置串口MP3模块的音量为 100%
  // vol 取值 0~100,这里传 100:患者多有听力衰退,音量留小等于没提醒
  mp3SetVolumeImpl(vol);
}

void mp3PlayIndex(uint16_t index) {    // 对应积木:设置串口MP3模块播放第 N 首歌曲
  mp3PlayIndexImpl(index);             // 按 TF 卡中的文件编号点播
}

void mp3Stop() {                       // 对应积木:设置串口MP3模块播放模式为 结束播放
  mp3StopImpl();
}

/* =========================================================
 *  初始化 —— 对应自定义块「初始化」
 * ========================================================= */
void initAll() {
  Serial.begin(9600);                  // 串口调试用,便于观察运行状态

  /* --- 1. 二哈摄像头初始化,并且"直到成功" --- */
  Wire.begin();                        // 打开 I2C 总线(A4 = SDA,A5 = SCL)
  while (!huskylens.begin(Wire)) {     // 握手失败就一直重试,绝不带着错误往下跑
    Serial.println(F("HuskyLens 未就绪,重试中..."));
    delay(300);
  }

  /* --- 2. 把摄像头切到「人脸识别」算法,同样"直到成功" --- */
  // 摄像头支持多种算法,必须显式切换,否则读到的结果不是人脸
  while (!huskylens.writeAlgorithm(ALGORITHM_FACE_RECOGNITION)) {
    delay(300);
  }

  /* --- 3. 初始化串口 MP3 模块(软串口 Rx=3、Tx=4) --- */
  mp3Init();

  /* --- 4. 音量拉满,保证老人听得见 --- */
  mp3SetVolume(100);
}

/* =========================================================
 *  人脸识别 —— 对应自定义块「人脸识别」
 * ========================================================= */
void faceRecognition() {
  huskylens.request();                 // 让摄像头做一次识别,把结果取回本地

  // ---- 判断画面中是否存在人脸方框 ----
  if (!huskylens.available()) {        // 画面里没有方框
    mp3Stop();                         // 兜底:主动停播,避免上一段语音残留
    return;                            // 直接返回,本轮不做任何播报
  }

  // ---- 找出"最靠近画面中心"的那张人脸 ----
  // 用画面中心与各人脸方框中心的距离做比较,取距离最小者,
  // 这样可以避免背景远处的人脸被误判成"眼前的人"
  int    bestId   = 0;                 // 命中人脸的编号,0 表示尚未命中
  long   bestDist = 0x7FFFFFFF;        // 初始距离设为极大值

  while (huskylens.available()) {      // 逐个读取本轮识别到的所有人脸
    HUSKYLENSResult r = huskylens.read();

    long dx     = (long)r.xCenter - 160;   // 画面中心横坐标按 320x240 估
    long dy     = (long)r.yCenter - 120;   // 画面中心纵坐标
    long dist   = dx * dx + dy * dy;       // 用距离平方比较即可,不必开方

    if (dist < bestDist) {                 // 找到更靠近中心的人脸
      bestDist = dist;
      bestId   = r.ID;                     // 记下它的编号
    }
  }

  // ---- 按编号分派到对应的家人语音 ----
  if (bestId == 1) {                   // 1 号人脸
    mp3PlayIndex(VOICE_FACE_1);        // 播放第 01 首语音
    delay(WAIT_LONG);                  // 等 8 秒,让语音播完
  } else if (bestId == 2) {            // 2 号人脸
    mp3PlayIndex(VOICE_FACE_2);        // 播放第 02 首语音
    delay(WAIT_SHORT);                 // 等 6 秒
  } else {                             // 识别到了人脸但编号不是 1、2
    mp3Stop();                         // 同样兜底停播
  }
}

/* =========================================================
 *  定时提醒 —— 对应自定义块「定时」
 *  读取 DS1307 的「时」与「分」,命中预设时刻就循环播放提醒语音
 * ========================================================= */
void timerRemind() {
  uint8_t hour   = ds1307.getHour();       // 读取当前"时"
  uint8_t minute = ds1307.getMinute();     // 读取当前"分"

  if (hour == 8 && minute == 30) {         // 分支一:早上 8 点 30 分
    for (int i = 0; i < 3; i++) {          // 重复 3 次,连说三遍才叫得住
      mp3PlayIndex(VOICE_REMIND_A);        // 播放第 04 首(用药提醒)
      delay(WAIT_LONG);                    // 每次间隔 8 秒
    }
  } else if (hour == 13) {                 // 分支二:下午 1 点(只判"时")
    for (int i = 0; i < 3; i++) {
      mp3PlayIndex(VOICE_REMIND_A);
      delay(WAIT_LONG);
    }
  } else if (hour == 21) {                 // 分支三:晚上 9 点(只判"时")
    for (int i = 0; i < 3; i++) {
      mp3PlayIndex(VOICE_REMIND_A);
      delay(WAIT_LONG);
    }
  } else if (hour == 16) {                 // 分支四:下午 4 点(只判"时")
    for (int i = 0; i < 3; i++) {
      mp3PlayIndex(VOICE_REMIND_B);        // 播放第 05 首(检查提醒)
      delay(WAIT_LONG);
    }
  } else {                                 // 兜底:非提醒时段
    mp3Stop();                             // 保持安静,并清掉可能残留的播放
  }
}

/* =========================================================
 *  主程序 —— 对应图形化里的「Uno 主程序」
 *  Arduino 的 loop() 本身就是无限循环,正好对应"循环执行"
 * ========================================================= */
void setup() {
  initAll();                           // 上电后只初始化一次
}

void loop() {
  faceRecognition();                   // 先看"人"
  timerRemind();                       // 再看"时间"
}                                      // 回到 loop 顶部继续下一轮

这份代码里有三处地方,是把图形化积木「翻译」成 C 代码时必须留心的地方,也正好是嵌入式编程里最常踩的坑:

  • 循环与延时。图形化里的「循环执行」直接对应 Arduino 的 loop() 函数,不需要自己写 while(1)。而「等待 8 秒」对应的是 delay(),它会把整个 CPU 卡住 8 秒——这意味着在此期间摄像头不会被读取。这是图形化方案天生的局限,改进办法见第九章。
  • 「靠近中心」需要自己算。图形化里「从结果中获取靠近中心的方框」是一个现成积木,翻译成 C 代码就得自己遍历所有识别结果、算出每个方框中心到画面中心的距离再取最小值。
  • 「结束播放」是两条支线共用的安全阀。代码里 mp3Stop() 出现在三个不同的分支中(没有人脸、识别到未知人脸、非提醒时段),它的作用都是同一件事:把喇叭收住,避免两路功能互相打断。

七、作品创新点

7.1 把「认人」这件最难的事交给 AI 摄像头

阿尔兹海默症患者最痛苦的症状之一是认不出亲人。本作品用二哈摄像头的人脸识别算法,把「这个人是谁」变成了一个可以直接读到的编号(ID),再把这个编号翻译成一段家人自己的声音。整个过程中,一台 8 位单片机不需要做任何图像处理——这是让低算力主控跑通 AI 功能的关键取舍。

这个做法对同类项目有直接参考价值:凡是「识别类」需求,都可以先找带算力的成熟模块,把主控从繁重的计算里解放出来。

7.2 语音由家属录制,输入的是「声音」而不只是「信息」

作品的 F3 要求写得很清楚:语音内容尽量模仿患者熟悉、亲近的语气。这条要求的落点不在技术,而在把播报的声音从「机器提示音」换成「家人的声音」。对一位认不出女儿的患者来说,听到女儿的声音说出自己的身份,与听到一段电子合成音说「这是您的女儿」,效果完全不同。

语音文件存在 TF 卡里按编号点播,这个设计也让「换声音」变得极其简单——重新录一段放进去重新编号就行,不用改程序、不用重新烧录。

7.3 相机造型:把医疗器械伪装成一件随身物件

这是这份作品最容易被忽略、但完成度最高的一处创新。硬件功能是「识别 + 播报」,而与患者每天打交道的其实是那层外壳。小组把外壳做成相机,还配上背带,让装置从「需要被照顾的证据」变成了「一件想带着的小玩意儿」。在这种面向特殊人群的作品里,外形设计的权重和功能设计一样高。

7.4 一套硬件、两路功能,靠「兜底停播」实现互斥

人脸识别与定时提醒共用同一个喇叭,程序里没有复杂的任务调度,而是用「不满足条件就结束播放」这个统一约定来处理冲突:三处兜底分支写法一致,逻辑上很干净。对于一份面向中学生的作品来说,这种「用简单规则解决冲突」的思路,比硬套一个复杂的状态机更值得肯定。

7.5 全开源硬件、全模块化,复现门槛低

整机没有一块自制电路板,全部使用市售开源模块加杜邦线连接,外壳用激光切割板材拼装。这意味着任何一所普通中学的创客空间都能照着做出来,不需要采购贴片设备、也不需要焊接功底。作品的价值不只在于它本身能用,更在于它是一份可复制的方案。

八、项目应用拓展

本作品的两项核心能力——认人播报与定时语音提醒——并不局限于阿尔兹海默症这一个场景。把硬件稍作调整、把语音内容换掉,同一套方案可以迁移到不少相近的需求上:

应用场景需要做的改造能解决的问题
轻度认知障碍老人的居家陪伴增加更多人脸录入(可扩展到多位家属),并按时间段调整提醒内容减少家属反复解释「我是谁」的负担
社区日间照料中心为每位老人配置一个独立的语音编号组,工作人员统一录入与管理一个中心可同时照护多位服务对象
术后康复与慢性病用药管理把提醒语音改为具体药名与剂量,增加语音确认(如按键或语音回应)降低漏服、错服的风险
视障人士的方向与物件提示把摄像头换成物体识别算法,语音内容改为「这是水杯」「门在左边」用听觉替代视觉获取关键信息
养老院护理提醒加入护理项目清单,按班次切换提醒内容把护理流程变成可听、可追溯的提醒
中小学人工智能与开源硬件课程拆成「人脸识别入门—串口语音模块—I2C 时钟」三个课时任务让学生在一件完整作品中同时接触 AI、通信与结构设计
家庭教育场景把提醒对象换成学生自己,语音换成家长的鼓励话语用熟悉的声音做学习与作息提醒

需要说明的是:以上拓展方向中,本作品实际实现并验证的只有「认人播报」与「定时提醒」两项,其余属于方案层面的延伸设想,列出它们是为了说明这套技术路线的可迁移性,不代表已完成验证。

九、小结

9.1 制作历程

这个项目从「想到一个问题」开始,到「做出一台能演示的装置」结束,大致走过了这样一条路径:

  1. 问题聚焦。从阿尔兹海默症这个大话题里,收窄到「认不出人」与「忘记按时做事」两个具体麻烦;
  2. 画出样子。先手绘相机造型的草图,确定机身、背带与镜头的大致关系;
  3. 定下方案。确定用 UNO + 扩展板做控制核心,把识别交给二哈摄像头、把发声交给串口 MP3、把时间交给 DS1307;
  4. 建出模型。用 SketchUp 2019 建立三维模型,确定各模块在机内的位置与开孔位置;
  5. 切成板件。用 LaserMaker 排版下料,激光切割出外壳板件;
  6. 装上模块。把主控、摄像头、喇叭、时钟、语音模块逐个固定并接线;
  7. 写下程序。在 Mind+ 里用「主程序 + 三个自定义块」的方式完成逻辑;
  8. 录入人脸、现场验证。对着摄像头学入家人面孔,实测认人播报与定时提醒两项功能,并完成演示讲解的录制。

一路做下来,感受最深的一点是:真正难的从来不是「让灯亮起来」,而是「让它一直亮着、并且亮得合适」。程序第一次跑通只花了一小会儿,而后面反复调整的,是音量够不够大、等待时间够不够长、语音会不会互相打断这些琐碎但决定成败的细节。

9.2 不足与改进方向

作品的不足,创作说明的最后一段写得很坦率:「MP3 存储空间小,不能即时录音,定制个性化提示语音,音量不能调节等;问题还很多,希望有时间不断探究改进。」本章在此基础上,把材料中已经暴露出来的问题与程序里可改进的地方一并整理如下:

类别现存问题改进方向
硬件MP3 模块的存储依赖 TF 卡,空间有限;不能即时录音,换语音必须拔卡插电脑重新拷文件;音量固定为 100%,在夜间或安静环境下可能显得过响改用带录音功能的语音模块或板载 Flash 语音芯片;增加一个旋钮或按键用来现场调节音量
程序四个定时分支中有三个只判断了「时」,没有判断「分」,到了那个小时就会整点触发一次,时间精度不够补齐「分」的判断,让每个提醒点都精确到分钟;或者把提醒时刻做成一张表,用循环遍历,方便增删
程序用 delay() 等待语音播完,等待期间摄像头不会被读取;人脸播报与定时提醒可能互相打断改用 millis() 记录时间戳做非阻塞延时,并给两条支线加优先级:提醒正在播报时暂停人脸播报
功能只能录入有限的几张人脸,且录入操作需要在摄像头上手动完成,患者本人无法自行添加增加手机端或电脑端的录入辅助工具,让家属能远程维护人脸库与语音内容
结构外壳采用板材拼装,长期使用后接缝处可能松动;作品未记录整机尺寸与板材厚度参数补充结构图纸与参数记录;接缝处增加卡扣或螺丝固定
验证仅完成功能演示,未做过长时间连续运行测试,也未在真实患者身上试用做 24 小时以上连续运行测试,记录误识别率与漏报率;在专业医护人员指导下开展小范围试用

其中「三个定时分支只判断了小时」这一条,是本文在逐块核对程序时发现的,属于程序的真实状态,不是推测。这里把它列出来,是因为它恰好是一处很好的教学素材:同样的一个小时数,判断到「时」和判断到「分」,对使用者来说是完全不同的体验。

9.3 参考文献

  1. DFRobot. Gravity HUSKYLENS 人工智能摄像头(SKU: SEN0305)产品文档. wiki.dfrobot.com.cn
  2. DFRobot. MP3 语音模块(SKU: DFR0534)产品文档. wiki.dfrobot.com.cn
  3. DFRobot. I2C DS1307 RTC 实时时钟模块 V1.0(SKU: DFR0151)产品文档. wiki.dfrobot.com.cn
  4. 《记忆相机-阿尔兹海默症提醒器》作品创作说明、推荐作品登记表与演示讲解稿(参赛申报材料,2023 年 2 月)
  5. 作品 Mind+ 工程文件 HM-UNO.mp、硬件连接图与结构建模文件(同上)

说明:本作品引用的阿尔兹海默症患者数量(我国约 600 万~800 万名)来自作品创作说明原文,本文照录并标注出处,未做二次核证。

创作许可协议

本项目采用 CC BY(署名) 进行许可。

评论(0)
- 没有更多了 -