☰
用树莓派Pico和OLED 0.96为脑卒中患者打造沟通辅助发声设备
2026/10/3 12:15:50 网站建设 项目流程

去年我去看望一位因中风住院的长辈,病房墙边挂着一块白板,上面写着“水”“疼”“尿”“谢谢”几个词。需要的时候,家里人会把白板递过去,让他用手指。这个方法确实管用,可一旦只有护工在,或者老人手没有力气抬不起来,白板就成了一种负担。回家以后我一直放不下这个画面:那些心里明白却说不出来的患者,真正需要的可能只是一个能替他们开口的小盒子。于是就有了这个项目——用树莓派Pico做一台脑卒中沟通辅助发声设备,配合0.96寸OLED显示屏、几个大按钮和一个小喇叭,让患者按一下就能说出想要的话。

这篇文章会从硬件选型、接线细节、MicroPython固件、实测翻车点,再到长期使用的改进方向,把我从原型到可上手使用的完整折腾过程写下来。如果你正准备做辅助沟通装置、康复护理玩具,或者单纯想用raspberry pi 2040加oled 0.96做点有人情味的东西,这篇应该能帮你少走不少弯路。先说清楚,它不是一个医疗器械,也不能替代康复治疗师,它能做的是在患者还能控制手指或头部的情况下,把“我想喝水”变成一句清晰的人声。

1. 为什么沟通板首选树莓派Pico而不是桌面派:从病房场景反推硬件选型

1.1 病房里真正需要的是什么

脑卒中后语言障碍主要分两类。一类是失语症,患者大脑语言中枢受损,听、说、读、写能力下降,心里明白但找不到词,或者听不懂别人说话;另一类是构音障碍,肌肉控制出问题,舌头嘴唇不听使唤,说话含糊不清。两类患者都可能出现“表达需求失败”的瞬间,然后变成急躁、拍床、甚至拒食。

在病房里观察两天就会发现,沟通需求其实可以被压缩成几大类:基本生理需求(喝水、吃饭、上厕所、冷热)、疼痛与不适(头疼、肚子疼、难受)、情绪表达(谢谢、想见家人、别担心)、医疗请求(叫护士、吃药)。患者需要的不是一个能上网、能跑App的平板,而是“看一眼、按一下、能出声”的确定性工具。

辅助沟通设备的核心要求其实是四个:直观,患者不用学就会用;可靠,每一次按键都有反馈;便携,床头柜和轮椅小桌板放得下;可维护,护工和家属能换短语、能充电。这四个要求直接排除了功能复杂的桌面设备。

1.2 为什么不是树莓派4、平板或Arduino

我在最初选型时列了一张表,逐个比过:

方案优点在病床场景的麻烦
树莓派4性能强、屏幕大、能跑语音识别开机慢、功耗大、怕系统更新后菜单变了,患者误触容易退出界面
安卓平板通用App多电容屏对手指不灵活的人太灵敏,误触率高,界面容易被弹窗打断
Arduino简单稳定、上电秒开flash太小,存不了几条录音,音频和菜单做起来繁琐
树莓派Pico RP2040上电秒开、microPython开发快、有大容量flash、硬件I2S需要自己接OLED、功放和喇叭,动手量稍大

我的结论是:沟通辅助这块,系统越简单越好。树莓派4和平板会带来很多“不必要的能力”,这些能力在患者手抖或误触时就变成了风险。Pico这种单片机没有操作系统、没有弹窗、没有待机唤醒,按一下就做一件事,反而最合适。Pico还有一个加分项:它的RP2040无论是用MicroPython还是C SDK,社区里驱动OLED 0.96的方案都非常成熟,事实上“raspberry pi 2040加oled 0.96”本来就是很多小型交互项目的第一步,素材和经验都好找。

1.3 硬件清单:从屏到喇叭都按“少而稳”选

最终确定的硬件清单如下:

零件型号/规格数量选型理由
主控Raspberry Pi Pico 开发板(RP2040)1成本低、GPIO多、有硬件I2S
显示屏0.96寸OLED,SSD1306,I2C接口,128x641功耗低、对比度高、点阵驱动成熟
按钮大尺寸轻触开关,带键帽,直径12mm以上4~6患者手指动作精度差,需要大面积触发
音频功放MAX98357A模块(I2S输入,单声道)1三根信号线接好就能出声,自带DAC和功放
扬声器3W、8Ω、直径40mm内磁喇叭1体积小,装进外壳还有余量
电源5V 2A USB电源或10000mAh充电宝1充电宝便宜,内置过压保护
电容470uF电解电容 + 0.1uF瓷片电容各2解决播放时电源跌落导致重启

选OLED 0.96而不是LCD1602,是因为OLED没有背光,整体功耗低,黑色底加白色字在病房昏暗环境下反而更清楚。但它的缺点是分辨率只有128x64,一行塞不了太多字,所以菜单不能做深,两级最合适。这个限制反而是好事,逼着我把沟通动作控制在三次按键以内。

2. OLED、按钮和音频放大三件套的接线细节:引脚、电平和电源环境

2.1 引脚分配速查表

一套成熟的接线方案应该一开始就定死引脚,避免后面改线。我的分配如下:

功能Pico GPIO引脚外设端备注
OLED SDAGPIO0OLED SDAI2C0数据线,需要上拉
OLED SCLGPIO1OLED SCLI2C0时钟线
上一条GPIO2按钮到GND不用外部上拉,内部上拉即可
下一条GPIO3按钮到GND内部上拉
确认/播放GPIO4按钮到GND内部上拉
返回/长按返回GPIO5按钮到GND内部上拉
I2S BCLKGPIO18MAX98357A BCLK数字音频位时钟
I2S LRCGPIO19MAX98357A LRC左右声道时钟
I2S DINGPIO20MAX98357A DIN数字音频数据
MAX98357A电源+5V / GNDVIN / GND用5V供电,避免用3.3V

注意I2S的这三个引脚一定不能接错顺序,接反了不会烧,但会完全无声。我调试时踩过这个坑:BCLK和LRC接反后喇叭里只有电流底噪,检查了半天才发现是杜邦线插错位。

2.2 按钮接法:为什么用“按下接地加软件去抖”

Pico的GPIO可以开内部上拉,所以按钮的一端接到GPIO,另一端接GND,代码里把引脚配置为Pin.IN, Pin.PULL_UP。平时引脚被上拉到高电平,按下后变成低电平,程序读到低就是触发。

这个接法的好处是节省板子空间,不用每个按键都加外部10k电阻。但要注意两点:手边如果用的是长杜邦线,线缆容易感应噪声,那种情况下我会给每路再加上10k上拉电阻到3.3V,让电平更稳定;第二是Pico的部分GPIO在启动时不能直接接5V,所以按钮这一侧只能接GND,不要接3.3V以外的高电平。

机械开关都有抖动问题,按下去的一瞬间会有几毫秒的开闭震荡,不做处理会出现一次按键触发两三次。最省事的软件去抖是:

from machine import Pin import time def debounce(pin): if pin.value() == 0: time.sleep_ms(20) if pin.value() == 0: return True return False

这个函数在第一次检测到低电平后等20ms,再去读一次,如果还是低电平就确认是有效按键。20ms这个值对机械开关足够,又不会让人觉得迟钝。

2.3 OLED 0.96的I2C接线和上拉注意

市面上0.96寸OLED大多数是四脚模块:GND、VCC、SCL、SDA。VCC供电看模块说明,大多数支持3.3V到5V,但保险起见我都用3.3V。SCL接GPIO1,SDA接GPIO0,I2C地址一般是0x3C,如果屏幕没反应可以试0x3D。

有些模块板载了上拉电阻,有些没有。I2C总线上拉电阻范围是2.2k到10k,模块没有自带的话,我们在SCL和SDA上各接一个4.7k电阻到3.3V。Pico自己也可以启用引脚上拉,但软件上拉阻值偏大,在长线通信时不够稳,外接电阻更靠谱。

点亮SSD1306的MicroPython代码很简单:

from machine import Pin, I2C import ssd1306 i2c = I2C(0, scl=Pin(1), sda=Pin(0)) oled = ssd1306.SSD1306_I2C(128, 64, i2c) oled.text("Hello", 0, 0) oled.show()

跑通这一步,等于把这块小屏作为项目的“脸”先立起来了。

2.4 选择I2S功放而不是PWM直推喇叭

Pico可以仅用GPIO的PWM模拟音频输出,接一个低通滤波和喇叭也能响,但这种方式有两个麻烦:PWM音频对CPU实时性要求高,菜单刷新和文件读取稍微慢一点,声音就会嘶哑;而且输出的功率很小,推到3W喇叭基本只能自己听见。所以我在项目里直接用MAX98357A,它是专门为I2S数字音频设计的单声道D类功放,支持3.2V到5.5V供电,3W输出,芯片内部自带DAC和解码,把Pico的I2S信号直接变成能驱动喇叭的模拟输出。

MAX98357A模块上有一个重要的GAIN引脚,它决定功放增益:

GAIN引脚连接增益
GAIN接VIN3dB
GAIN悬空15dB
GAIN接GND9dB

我第一次直接把GAIN悬空,结果音量最大,声音一响电池供电的Pico立刻重启。后来改成GAIN接VIN也就是3dB,音量调到中等,整个系统才稳定下来。经验是:辅助沟通设备不需要震天响,3dB增益加上外壳共鸣腔完全够病房里听清,宁可留音量余量也不要一开始就拉满。

接线时一定要把MAX98357A的电源接到5V而不是Pico的3.3V,因为播放瞬间电流会突然增加,3.3V稳压扛不住。同时在VIN和GND之间并上470uF电解电容和0.1uF瓷片电容,这个组合能吸收大部分瞬态跌落。

2.5 供电规划:充电宝比电池更适合原型

原型阶段最省心的供电方式是直接插一个5V 2A的充电宝,而不是自己做锂电池。Pico的VBUS脚接5V,MAX98357A的VIN也接5V,GND共地。充电宝自带电量显示和保护板,电压输出足够稳定,唯一要注意的是USB线要尽量短,线材电阻太大在播放瞬间会造成压降。

如果后面要把设备做成便携版,就需要一个3.7V锂电池加5V升压模块,再加TP4056充电板。但这里有个坑:播放瞬间电流可能到400mA甚至更高,升压模块的动态响应如果不好,电压会瞬间跌到4V以下,Pico虽然是3.3V逻辑也会跟着复位。所以在便携版里,音频功放和大电容要尽量靠近升压模块输出端,地线用粗线单独拉,不能和OLED这些低速器件共一根细地线。

3. 两级菜单的MicroPython实现:从JSON短语表到按钮状态机

3.1 用MicroPython的原因

Pico官方支持C SDK,性能上更好,但我的项目要频繁调整短语,录音文件也要重新生成,C编译一次来回至少十分钟。MicroPython的好处是直接改文件就能跑,短语列表可以放在JSON文件里,连程序都不用动,只改数据。对于一台辅助沟通设备来说,这种“数据与逻辑分离”的设计非常实用。

最终固件用MicroPython,主循环里做三件事:处理按钮、刷新OLED、按下确认键时用I2S播放WAV文件。菜单交互响应要求不高,按钮轮询频率50Hz足够。

3.2 短语表组织:JSON设计

短语表我放在phrases.json里,结构是二级目录:一级分类,二级具体短语。

{ "categories": [ { "label": "吃饭喝水", "items": ["我想喝水", "我想吃点东西", "我还不饿", "今天吃什么"] }, { "label": "身体不适", "items": ["我不舒服", "我头疼", "我肚子疼", "帮我把枕头垫高"] }, { "label": "情绪交流", "items": ["谢谢你", "我想见家人", "别担心", "我有点着急"] }, { "label": "医护人员", "items": ["请叫护士", "我需要吃药", "我要量体温", "请帮我翻身"] } ] }

分类控制在4个,每个分类下4到6条短语,这样从开机到发声最少两次按键,最多三次。OLED只有128x64,一行显示16x16的汉字最多8个,但为了看清我会把字号放大到实际能用的程度,一行最多显示四五个字,所以短语务必短。

3.3 菜单状态机和按键处理代码

程序状态我定义成三个:STATE_CATEGORY(在一级菜单)、STATE_ITEM(在二级菜单)、STATE_PLAYING(正在播放语音)。用两个变量cat_idx和item_idx记录当前位置。

import json, time from machine import Pin, I2C import ssd1306 i2c = I2C(0, scl=Pin(1), sda=Pin(0)) oled = ssd1306.SSD1306_I2C(128, 64, i2c) BTN_UP = Pin(2, Pin.IN, Pin.PULL_UP) BTN_DOWN = Pin(3, Pin.IN, Pin.PULL_UP) BTN_CONFIRM = Pin(4, Pin.IN, Pin.PULL_UP) BTN_BACK = Pin(5, Pin.IN, Pin.PULL_UP) STATE_CATEGORY = 0 STATE_ITEM = 1 STATE_PLAYING = 2 state = STATE_CATEGORY cat_idx = 0 item_idx = 0 def debounce(pin): if pin.value() == 0: time.sleep_ms(20) if pin.value() == 0: return True return False def draw_menu(categories, state, cat_idx, item_idx): oled.fill(0) if state == STATE_CATEGORY: start = cat_idx for i, cat in enumerate(categories): y = i * 16 if i == cat_idx: oled.text('>', 0, y) oled.text(cat["label"], 12, y) elif state == STATE_ITEM: items = categories[cat_idx]["items"] for i, item in enumerate(items): y = i * 16 if i == item_idx: oled.text('>', 0, y) oled.text(item, 12, y) oled.show() with open("phrases.json", "r") as f: phrases = json.load(f) while True: draw_menu(phrases["categories"], state, cat_idx, item_idx) if state == STATE_CATEGORY: if debounce(BTN_UP): cat_idx = max(0, cat_idx - 1) if debounce(BTN_DOWN): cat_idx = min(len(phrases["categories"]) - 1, cat_idx + 1) if debounce(BTN_CONFIRM): state = STATE_ITEM item_idx = 0 elif state == STATE_ITEM: if debounce(BTN_UP): item_idx = max(0, item_idx - 1) if debounce(BTN_DOWN): items = phrases["categories"][cat_idx]["items"] item_idx = min(len(items) - 1, item_idx + 1) if debounce(BTN_CONFIRM): state = STATE_PLAYING if debounce(BTN_BACK): state = STATE_CATEGORY elif state == STATE_PLAYING: # 播放完成后回到二级菜单 state = STATE_ITEM

这段逻辑很直白:一级菜单用上下选择分类,确认后进入二级;二级再选具体短语,确认后播放。播放完自动回到二级菜单,方便患者连续说多句话。注意debounce函数处理的是低电平有效的按键。

3.4 长按返回和播放中锁键

在中风患者里,很多人手抖或者无法精准控制手指,需要额外的防误触设计。我在STATE_PLAYING时只处理“长按返回”这一个操作,其他按钮全部忽略,防止患者无意间连按,一次发出好几句话。

“长按返回”是一个安全出口:无论患者在哪一层菜单,只要按住返回键超过1秒,就回到一级菜单首页。这个设计比做一个单独的“取消”按钮更合适,因为取消按钮可能被误触,而长按需要人主动持续压住,误触概率小很多。

def wait_short_or_long(pin): t0 = time.ticks_ms() while pin.value() == 0: if time.ticks_diff(time.ticks_ms(), t0) > 1000: return "long" time.sleep_ms(10) return "short"

在主循环里,如果是长按,就把state重置为STATE_CATEGORY,两个索引都清零。

3.5 预录真人声和WAV播放

沟通辅助设备的语音,我坚持用真人预录而不是文字转语音。原因很简单:病房里响起一句陌生的机器合成声,患者和家人都会有距离感;如果是患者老伴录的“我想喝水”,听起来就像家里人在说话,情绪的安抚作用远比清晰度重要。

录音用手机或电脑麦克风,先录成48kHz 16bit单声道,再用Audacity压成22050Hz 16bit单声道WAV。采样率降到22050是因为Pico的处理器和I2S功放都够用,而且文件体积小一半。一段两秒的WAV大约88KB,Pico的2MB flash去掉固件和字库图片,放15句常用短语完全够。

播放前要处理WAV文件头部。简单做法是直接跳过前44字节:

from machine import I2S, Pin import struct audio_out = I2S(0, sck=Pin(18), ws=Pin(19), sd=Pin(20), mode=I2S.TX, bits=16, format=I2S.MONO, rate=22050, ibuf=8192) def play_wav(filename, volume=0.7): with open(filename, "rb") as f: f.seek(44) while True: chunk = f.read(4096) if not chunk: break chunk = chunk[:len(chunk) - (len(chunk) % 2)] if chunk: samples = bytearray(chunk) for i in range(0, len(samples), 2): raw = struct.unpack_from("<h", samples, i)[0] raw = int(raw * volume) raw = max(-32768, min(32767, raw)) struct.pack_into("<h", samples, i, raw) audio_out.write(samples)

这里用struct模块把每两个字节当成一个16bit有符号数,乘以音量后写回缓冲,再整块交给I2S。音量控制放在播放端而不是录音端,是为了以后能用按键实时调整。实际使用中,0.75左右的音量在病房最合适,既能唤醒注意力,又不会把隔床病人吓着。

3.6 中文显示避坑:别用MicroPython内置字体硬刚中文

SSD1306库里自带的oled.text()只支持ASCII字符,中文直接传入会显示乱码或空白。这是很多新手第一次做中文菜单卡住的地方。绕开办法有三个:

一是用拼音或英文标签,但面向老年人不够友好;二是在电脑上把每一条菜单预渲染成128x64的1bit位图,存成字节数组,运行时用oled.blit()整块显示;三是烧录一个GB2312点阵字库,用文件偏移方式访问,工作量比较大。

我最终选的是位图方案。在电脑上用Python的Pillow库生成:

from PIL import Image, ImageDraw, ImageFont font = ImageFont.truetype("simhei.ttf", 16) img = Image.new("1", (128, 64), 0) draw = ImageDraw.Draw(img) draw.text((12, 24), "我想喝水", font=font, fill=1) img.save("want_water.bin")

生成后的want_water.bin体积只有1KB,几行字也就几KB,塞进Pico的flash没有任何压力。运行时:

with open("want_water.bin", "rb") as f: oled.blit(f.read(), 0, 0) oled.show()

这样做的好处是“所见即所得”,我在电脑上想用什么字体、什么排版,就在电脑上排好,设备端不做任何文字渲染。

3.7 死机保护:看门狗和异常兜底

辅助沟通设备最怕“无声死机”,患者按了没反应,家属会以为设备坏了。MicroPython虽然稳定,但我在程序里加了看门狗,要求主循环必须定期喂狗:

try: from machine import WDT wdt = WDT(timeout=8000) while True: # 主循环 wdt.feed() except Exception: import machine machine.reset()

WDT超时设为8秒,即使主循环卡死,设备也会自动重启。另外用try/except接住所有异常,出错后直接调用machine.reset()复位,保证最多8秒内恢复可用。这功能平时没有存在感,但在长期使用中非常重要。

4. 实测阶段最容易翻车的三件事:播放重启、中文乱码和误触

4.1 播放瞬间整个设备重启

我第一版原型装好后,遇到一个非常头疼的问题:按下确认键,喇叭刚响一下,OLED屏幕闪白,整机重启。用万用表测,MAX98357A在播放瞬间电流从30mA跳到300mA以上,如果供电线又细又长,Pico VBUS端的电压会被拉低到复位阈值以下。

排查路径大概这样:先用示波器或万用表测Pico的VBUS电压,播放瞬间如果有明显凹陷,就说明电源不够硬。接下来做三件事解决:

  1. 给MAX98357A的VIN和GND之间并上470uF电解电容,位置尽量靠近功放引脚;
  2. 把GAIN引脚从悬空改成接VIN,把增益从15dB降到3dB,播放电流峰值立刻小了;
  3. 换一条粗短USB线,充电宝到设备之间的线材电阻不能忽视。

改完之后播放电流峰值控制在200mA以内,连续循环播放十句也没有再重启过。这个教训说明:软件写得再稳,电源设计有问题,一切都白搭。

4.2 声音播放有咔哒断续声

第一次加入OLED刷新后,播放WAV时“咔哒咔哒”的断续声特别明显。原因有两个:一是I2S的缓冲区太小,只有4096字节,文件读取稍微卡顿就断流;二是我在播放过程中还在同时调用oled.show()刷新菜单,I2C虽然只占几毫秒,但刚好打断了连续写入I2S的节奏。

解决办法是把ibuf从4096提高到8192,播放语音前先停掉LED和OLED的无效刷新,保留最后一张菜单画面不重绘,等播放完成后再恢复刷新。这个改法很简单,但声音明显连续了很多。凡是遇到I2S有杂音,优先查“谁在抢总线时间”。

4.3 OLED中文乱码和显示不全

接好OLED第一次运行就把我整懵了,菜单上显示的“吃饭喝水”变成了每一位象。后来查明白,SSD1306自带字库只覆盖ASCII,中文字节被拆开,自然全是乱码。我没有在设备端做字库,而是提前把每条菜单渲染成128x64的位图存到flash里。

这个方案要付出一点劳动:每条短语生成一个bin文件,并在JSON里加上对应的文件名。菜单表就变成:

{ "label": "吃饭喝水", "image": "menu_eat.bin", "items": [ {"text": "我想喝水", "sound": "want_water.wav", "image": "item_water.bin"}, {"text": "我想吃点东西", "sound": "want_food.wav", "image": "item_food.bin"} ] }

菜单显示时先根据下标读取对应的bin文件,用oled.blit()显示,确认键触发时播放对应的WAV文件。虽然多一步预处理,但中文显示效果非常干净,字体和排版可以自由控制。

4.4 手抖患者的误触

“误触”这件事在我做真实样机以前完全没概念。面包板阶段我用普通轻触开关,测试的是健康人手指,按键精准、反应快。但当我拿给一位手部控制不太好的试用者时,手指搭在按键上轻微抖动,机器就一连串说了一堆话,场面一度很尴尬。

最终方案是给所有按钮加“触发持续时间”判断:按下后必须持续0.4秒才确认触发,而不是检测到低电平就立刻响应。0.4秒对正常人来说几乎感知不到延迟,但能过滤掉大部分抖动和扫过按钮的误触。敏感短语后面再加一层确认,患者按完确认键,屏幕显示“确定要播放这句话吗”,再按一次确认才出声。

对于手抖得特别厉害的人,还有更极端方案:把“敏感项”放到一个需要长按才能进入的隐藏菜单里,平时主菜单只有最基本的喝水、进食、叫护士这些需求。这项改动是临床试验反馈后的最优解,强烈建议大家在做类似辅助项目时提前和真实使用者聊一聊。

5. 从原型到能长期使用的设备:外壳、紧急呼叫与数据记录

5.1 外壳设计:让按键放得稳,让声音传得出来

面包板版本没法放到病床边上,芯片裸露、按钮歪斜,家属看了也不敢用。后期我用3D打印做了一个小盒子,尺寸定成120mm长、80mm宽、30mm高,内部刚好放Pico、MAX98357A和40mm喇叭。盒子的设计要点有三个:面板向上倾斜30度,OLED嵌在斜面上,患者躺着也能看到;四个按钮用大号圆形按钮帽,间距至少20mm,防止胖手指一次碰到两个;喇叭开口开在前面板下方,而不是底面,否则放在床单上声音会被捂住。

如果没有3D打印机,可以用木盒或亚克力粘一个。但要注意按键背面的固定柱,轻触开关的引脚要焊接牢固,长期按压下松脱是很常见的故障。

5.2 短语列表必须让康复师参与

我个人做技术出身,一开始列菜单时想的都是“我饿了”“我疼”这种抽象描述,结果康复师一句点醒了我:患者说“我不舒服”,家属根本不知道是哪里不舒服。后来我把短语表改了,按康复思维分成更具体的项:

一级类别典型短语使用场景
基本需求我想喝水、我想上厕所、我冷、我热最高频,放首位
疼痛不适我头疼、我肚子疼、我肩膀疼、帮我把枕头垫高要描述部位,最好配图
情绪社交谢谢你、我想见家人、别担心、我有点着急缓解沟通挫败感
医疗请求请叫护士、我需要吃药、我要量体温、请帮我翻身紧急情况下能快速触发

身体部位描述对失语症患者特别重要,因为我发现很多人能听懂“哪里疼”,但说不清“哪个位置”。如果OLED空间允许,应该把疼痛类短语做成“身体部位图加对应按钮”,不过这就属于第二版迭代了。

5.3 紧急呼叫按钮和自动记录

长期使用后我发现,最常用的其实不是“我想喝水”这种日常短语,而是一句“请叫护士”。所以我专门在机器侧面加了一个红色大按钮,和普通菜单完全独立,红色按钮通过单独GPIO接到一个独立中断处理函数里。无论设备在哪个状态,只要红色按钮被按下并保持1秒,就立即播放急促的“我需要帮助,请叫护士”,同时驱动一个小LED闪烁。

我还在程序里到所有播放行为都记时间戳,简单存储在CSV文件里:

def log_play(tag): with open("log.csv", "a") as f: f.write("{},{}\n".format(time.localtime(), tag))

这条记录对康复师评估患者的表达意愿很有参考价值。比如全天只按过三次,说明患者沟通需求不多,或者按钮位置不合适,护理人员可以依据这个调整设备摆放和菜单内容。

5.4 长期使用的三个维护细节

长期放在病房的设备,会面临一些原型阶段想不到的维护问题。经验总结下来有三条:

  1. 开机音量固定为中等档位,不要把上次调节的音量存为默认,否则有人试过音量调最大后,下一位患者被吓一跳;
  2. 电源采用USB适配器固定供电时,要加一个防脱落的固定夹,病人翻身时扯掉电源,设备失灵会非常糟糕;
  3. 语音文件重新录制后,所有WAV统一过一遍响度标准化,不要一条响亮一条微弱,切换播放时体验会差很多。

这三个细节看着小,但在护理现场都会变成“这个设备不好用”的直接原因。做辅助设备,最怕的就是“能用”和“好用”之间的缝隙。

如果让我重做一遍这个项目,我会先把大按钮买回来,用硬纸板做一个比真实尺寸略大的模型,推到目标使用者的床头试摆两天。沟通辅助的瓶颈从来不是树莓派解码语音的速度,也不是OLED显示汉字的方案,而是按钮大小、颜色、位置、按压反馈这些最土的事情。技术上的路我已经踩平了:Pico驱动OLED 0.96很成熟,I2S功放接好电源就稳定,MicroPython的菜单状态机几个小时就能写完。真正让设备从原型变成“有人愿意用”的,是尽可能早地让患者、家属、护工参与进来。一句由家人提前录好的“我想喝水”,比任何高端语音合成都更接近“沟通”的本意。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询