1. 项目概述:为特殊需求人群打造一个多感官互动站

在物理计算和辅助技术领域,我们常常思考如何用电子和代码去创造一些有温度、能切实帮助到人的东西。这次分享的项目——“水母感官站”,就是这样一个尝试。它源于我们在大学里的一门物理计算与辅助技术课程,最终落地于波士顿学院校园学校,旨在为有特殊需求的学生们提供一个安全、有趣且富有吸引力的多感官互动环境。

这个项目的核心,是借助一块小巧但功能强大的开发板——Adafruit Circuit Playground Bluefruit(后面简称CPB),去协调灯光、声音和触觉反馈,创造出一个按下按钮就会“活”过来的发光水母。它不仅仅是一个手工制品,更是一个融合了微控制器编程、基础电子焊接、简单木工和纺织工艺的综合性辅助技术装置。其价值在于,通过可控的视觉(LED动画)、听觉(环境音效)和触觉(多种纹理的织物)刺激,为使用者提供一个可以自我调节、探索和享受的平静角落,这在教育辅助和感官整合训练中非常有用。

如果你是一位教育工作者、治疗师、创客,或者只是对如何用技术做些有意义的项目感兴趣,这个案例会很有参考价值。它涉及从需求分析、材料选型、编程到动手制作的全流程。我会详细拆解我们是如何一步步把想法变成实物的,其中踩过的坑、总结的经验,都会毫无保留地分享出来。

2. 项目整体设计与核心思路拆解

2.1 需求分析与设计定位

任何辅助技术项目的起点都必须是用户需求,而不是炫酷的技术。在与校园学校的老师和治疗师多次沟通后,我们明确了几个关键点:

  1. 安全性至上 :装置必须坚固、稳定,无尖锐边角,所有电子部件需完全封闭,避免误触或吞咽风险。电线连接必须可靠,防止被拉扯脱落。
  2. 多感官整合 :目标用户可能对特定感官输入有不同需求或偏好。因此,装置应同时提供视觉(灯光)、听觉(声音)和触觉(不同材质)的反馈,且强度可控、可预测。
  3. 明确的因果交互 :交互逻辑必须极其简单、直观。我们选择了超大尺寸的街机按钮,因为它目标明显、按压力度反馈清晰,能明确建立“按压-响应”的因果关系。
  4. 美观与沉浸感 :装置本身应该是一个吸引人的“景点”,而不仅仅是功能的堆砌。水母的造型柔和、神秘,其发光和飘动的触须能营造一种平静、梦幻的氛围,有助于情绪安抚。

基于这些,我们确定了“立柱式感官站”的形态:一个稳定的木质底座,支撑起一个透明的亚克力管柱,管柱内是电子核心,顶部则是装饰成水母形态的互动头。用户按压底座上的大按钮,触发管柱内的LED灯带产生星光闪烁动画,并随机播放一段水环境声音。

2.2 核心硬件选型与原理

为什么是Adafruit Circuit Playground Bluefruit?这是本项目成功的关键决策之一。对于这类集成度要求高、功能需求明确的创意电子项目,像CPB这样的“一体化开发板”远比从零开始用Arduino Uno连接各种传感器模块要高效可靠。

Circuit Playground Bluefruit的核心优势

  • 高度集成 :一块板子上集成了10个可编程RGB NeoPixel LED、运动传感器、温度传感器、光线传感器、声音传感器、蜂鸣器,以及多个触摸感应引脚。这几乎囊括了我们所需的所有基础传感器和反馈器,极大简化了电路设计和焊接工作。
  • 内置蓝牙 :虽然本项目未使用,但Bluefruit系列内置的蓝牙低能耗(BLE)为未来升级留下了空间,例如可以通过手机应用远程控制或切换模式。
  • CircuitPython支持 :这是另一个决定性因素。CircuitPython是MicroPython的一个分支,针对Adafruit的硬件进行了优化。它让编程变得像在U盘里拖放文件一样简单,无需复杂的IDE设置和编译过程,特别适合快速原型开发和教育场景。
  • 充足的GPIO与专用音频引脚 :CPB提供了足够的通用输入输出引脚来连接外部按钮和LED灯带,并且有专用的模拟音频输出引脚,可以直接驱动小功率扬声器或连接功放,处理音频播放任务。

其他关键硬件解析

  1. 外部LED灯带 :CPB板载只有10个LED,且位于板子同一平面,光效不够立体。我们额外选用了20颗/米的WS2812B可寻址LED灯带(4英寸间距),将其盘绕在亚克力管内部,从底部向上照明,模拟深海中的光芒。WS2812B只需要一个数据引脚就能控制所有LED的颜色和亮度,与CPB的NeoPixel库完美兼容。
  2. 大尺寸街机按钮 :选择它不仅是出于美观和易用性,其内部通常采用微动开关,手感清晰,寿命长。在电路上,我们将其配置为“上拉输入”模式。简单来说,按钮一端接地(GND),另一端接CPB的输入引脚。当按钮未按下时,引脚通过内部上拉电阻连接到高电平(3.3V),读取为“True”或“1”;按下时,引脚直接接地,变为低电平(0V),读取为“False”或“0”。这种配置能有效防止引脚悬空产生误触发。
  3. 音频输出方案选择与教训 :原始项目中我们使用了一个小型放大器模块,但效果不佳。 这里是个重要的经验点 :CPB的模拟音频输出驱动能力有限,直接推动大尺寸扬声器音量会很小。更优的方案是选择一款“功放一体式”的小喇叭,或者一个带内置D类功放的小型扬声器模块。如果对音质有要求,可以使用I2S接口的数字音频模块,但这需要更复杂的编程和接线。对于本项目,一个3W左右的微型功放喇叭足矣。

2.3 软件与逻辑框架

整个装置的“大脑”是运行在CPB上的CircuitPython程序。逻辑流程非常清晰:

  1. 初始化 :程序启动后,初始化所有硬件——设置按钮引脚为上拉输入模式,初始化外部LED灯带对象,加载Adafruit LED动画库中的“Sparkle”(闪烁)动画,并配置音频输出。
  2. 主循环 :程序不断检查按钮引脚的状态。
  3. 触发判断 :一旦检测到按钮被按下(引脚值变为 False ),立即进入响应序列。
  4. 执行反馈
    • 灯光 :启动Sparkle动画,让20颗LED随机以紫色闪烁,模拟水母发光和海底星光。
    • 声音 :从一个预设的音频文件列表(如海浪声、气泡声、溪流声)中随机选择一个,通过音频接口播放。
  5. 同步与结束 :在音频播放期间,灯光动画持续更新。播放完毕后,系统回到等待按钮触发的状态。

这种“事件驱动”的模型非常高效,CPU只在事件发生时工作,大部分时间处于低功耗的等待状态,有利于电池续航。

3. 核心制作流程与实操详解

3.1 结构件制作:底座、顶盖与亚克力管

材料与工具准备

  • 木材 :1英寸厚的实木板或高质量胶合板,尺寸至少15x15英寸两块(用于底座和顶盖)。胶合板更不易开裂。
  • 亚克力管 :外径4英寸,高度12英寸的透明圆管。透明材质便于观察内部电子结构和灯光效果。
  • 主要工具 :台锯(或请木材店代裁)、曲线锯、电钻/台钻、砂光机(或不同目数砂纸)、卷尺、铅笔。

操作步骤与关键细节

  1. 切割与成型

    • 用台锯将木板裁切成15英寸x15英寸的正方形作为底座。再裁切一块稍大的木板,用曲线锯或圆规锯切出一个直径15英寸的圆形作为顶盖。圆形边缘用砂光机仔细打磨至光滑,消除所有木刺。
    • 安全第一 :操作台锯等电动工具时,务必使用推把,佩戴护目镜和防尘口罩。
  2. 钻孔与开槽

    • 核心定位 :这是确保立柱垂直稳固的关键。在底座正方形中心和顶盖圆形的中心,用开孔器或台钻钻一个直径比亚克力管外径小约1-2毫米的圆孔。例如,管外径101.6mm(4英寸),可钻100mm的孔。需要耐心测试,目标是让亚克力管能够紧紧“塞入”或“卡入”,依靠摩擦力初步固定,而不是松松垮垮。
    • 走线孔 :在顶盖圆盘上,距离中心一定距离(确保不影响结构强度)再钻一个直径约1英寸(25mm)的孔,用于将所有电子线缆从亚克力管内部引到顶盖之上。
    • 亚克力管开孔 :在亚克力管靠近底部的位置,同样开一个1英寸的孔。这个孔是 外部按钮和电池盒电源线的入口 。所有电子设备主体(CPB、灯带、喇叭)都密封在管内,只有按钮和电池盒放在管外便于操作和更换。
  3. 打磨与处理

    • 所有木制部件的边角都必须用砂纸打磨成圆角,特别是顶盖的边缘和底座的棱边。
    • 可以根据喜好给木头上清漆或环保水性漆,增加美观度和耐用性。务必在通风良好处进行,并等待漆面完全干透固化后再进行组装。

注意 :在这一步, 绝对不要 进行任何永久性粘合(如胶水)或焊接。务必保持所有部件可分离,以便后续的电子部分安装和调试。我们当时就曾差点把管子提前粘死,导致后续穿线困难。

3.2 电子系统搭建与编程

电路连接示意图(文字描述)

  1. 电源总线 :将3节AAA电池盒的正极(+)输出线连接到CPB的 VOUT 引脚(或 3.3V 引脚,具体看板子标注),负极(-)连接到CPB的 GND 引脚。这为整个系统供电。
  2. 外部LED灯带 :将灯带的 VCC (+5V)接至CPB的 VOUT (如果灯带是5V的,CPB的 VOUT 引脚在USB供电时是5V,电池供电时是电池电压,需确认灯带工作电压范围), GND 接CPB的 GND DIN (数据输入)接CPB的 A1 引脚(或其他任何支持PWM/数字输出的引脚)。
  3. 大按钮 :按钮的一个端子接CPB的 GND ,另一个端子接CPB的 A4 引脚(配置为上拉输入)。
  4. 扬声器/功放 :如果使用无源扬声器+功放模块,将功放的音频输入接CPB的 A0 (模拟音频输出),功放的电源接CPB的 VOUT GND 。如果使用一体式有源喇叭,通常直接连接 A0 GND 即可。

编程实战(CircuitPython) : 首先,你需要将最新的CircuitPython固件刷写到CPB上(从Adafruit官网下载 .uf2 文件,按住板子上的复位键,通过USB连接电脑,出现 CPLAYBTBOOT 磁盘后,将固件文件拖入即可)。

然后,在你的代码.py文件所在目录,需要安装必要的库文件(通过 circup 工具或手动从Adafruit GitHub库下载):

  • adafruit_led_animation
  • 对应的 neopixel.mpy

以下是增强和注释后的核心代码:

# jellyfish_sensory_stand.py
import time
import board
import digitalio
import neopixel
import random
from audiocore import WaveFile
from adafruit_led_animation.animation.sparkle import Sparkle
from adafruit_led_animation.color import PURPLE  # 使用预定义颜色

# 1. 初始化大按钮 (配置为上拉输入)
big_button = digitalio.DigitalInOut(board.A4)  # 使用A4引脚,根据实际接线修改
big_button.direction = digitalio.Direction.INPUT
big_button.pull = digitalio.Pull.UP  # 启用内部上拉电阻

# 2. 初始化外部NeoPixel灯带
NUM_PIXELS = 20  # 灯带上LED的数量
PIXEL_PIN = board.A1  # 数据线连接的引脚
pixels = neopixel.NeoPixel(PIXEL_PIN, NUM_PIXELS, brightness=0.5, auto_write=False)
# brightness建议从0.3开始测试,太亮可能刺眼。auto_write=False允许我们批量更新LED状态,效率更高。

# 3. 创建闪烁动画实例
sparkle_animation = Sparkle(pixels, speed=0.05, color=PURPLE, num_sparkles=5)
# speed: 闪烁速度(值越小越快), num_sparkles: 同时闪烁的LED数量。可调整以获得最佳视觉效果。

# 4. 音频输出初始化(兼容不同板卡)
try:
    from audioio import AudioOut
except ImportError:
    try:
        from audiopwmio import PWMAudioOut as AudioOut
    except ImportError:
        print("此开发板不支持AudioOut")
        pass

# 启用板载音频放大器(如果板子有的话)
speaker_enable = digitalio.DigitalInOut(board.SPEAKER_ENABLE)
speaker_enable.direction = digitalio.Direction.OUTPUT
speaker_enable.value = True

audio = AudioOut(board.SPEAKER)  # 使用板载扬声器引脚
SOUNDS_DIR = "/sounds/"  # 声音文件存放在CPB存储盘的/sounds/目录下

def play_random_sound():
    """播放随机选择的一个水声文件"""
    sound_files = ["waves.wav", "bubbles.wav", "stream.wav"]
    chosen_sound = random.choice(sound_files)
    file_path = SOUNDS_DIR + chosen_sound

    try:
        with open(file_path, "rb") as wave_file:
            wave = WaveFile(wave_file)
            audio.play(wave)
            print(f"正在播放: {chosen_sound}")
            # 在播放声音的同时,更新灯光动画
            while audio.playing:
                sparkle_animation.animate()  # 更新动画帧
                time.sleep(0.01)  # 短暂延时,避免循环过紧
    except OSError as e:
        print(f"无法播放声音文件 {file_path}: {e}")

# 5. 主循环
print("水母感官站已启动,等待按钮按下...")
last_button_state = True  # 记录上一次按钮状态,用于消抖

while True:
    current_button_state = big_button.value  # 读取当前按钮状态
    # 消抖处理:检测到从“未按下”(True)到“按下”(False)的下降沿
    if last_button_state and not current_button_state:
        print("按钮被按下!")
        play_random_sound()
    last_button_state = current_button_state  # 更新状态
    time.sleep(0.05)  # 主循环延时,降低CPU占用并进一步消抖

音频文件准备要点

  • 来源 :从 bigsoundbank.com freesound.org 等网站寻找免版税的水声、自然声WAV文件。
  • 处理 :使用Audacity(免费开源软件)进行处理:
    1. 导入文件。
    2. 裁剪长度 :将声音裁剪到5-10秒,过长的文件会占用大量存储空间并导致播放延迟。
    3. 转换格式 :导出时选择“WAV (Microsoft) signed 16-bit PCM”格式,这是CircuitPython audiocore 模块广泛支持的格式。
    4. 降低采样率 :将采样率降至22050 Hz或甚至16000 Hz,可以显著减小文件体积,且对于环境音效质量损失不大。
    5. 单声道 :确保导出为单声道(Mono),而非立体声。
  • 存放 :将处理好的 .wav 文件直接拷贝到CPB存储盘上新建的 sounds 文件夹内。

3.3 焊接、组装与总装

焊接工序的惨痛教训 : 这是整个项目中最容易出错的一环。我们的黄金法则是: 先穿线,后焊接;先测试,后固定

  1. 规划走线 :在焊接任何一根线之前,用记号笔或胶带标出所有线缆从电路板到最终目的地的路径。特别是要穿过亚克力管上那个1英寸孔的电线(按钮线和电池盒线)。
  2. 预穿线 务必 先将这些需要过孔的线缆穿过亚克力管上的孔,并留出足够长的余量,然后再焊接它们到CPB或灯带上。我们当时就是先焊好了按钮,结果发现插头太大穿不过孔,不得不剪断重焊。
  3. 焊接技巧
    • 使用焊台,温度设置在350°C左右。
    • 焊接前先给焊盘和线头“上锡”。
    • 焊接时使用助焊剂,让焊点圆润光亮。
    • 为每个焊点套上热缩管,用热风枪或打火机(小心)加热收缩,实现绝缘和保护。最后再用电工胶布整体包裹线束,既美观又安全。
  4. 系统测试 :将所有部件(电池、CPB、灯带、按钮、喇叭)连接好,但先不要固定在任何结构上。上电,测试按钮功能、灯光效果、声音播放是否全部正常。这是修复问题的最后黄金时间。

总装步骤

  1. 电子部分入管 :将CPB主板、盘绕好的LED灯带(发光面朝向管壁)、小喇叭用尼龙扎带或双面泡沫胶固定在亚克力管内部。确保线缆整齐,避免杂乱。
  2. 密封管底 :用一块切割好的圆形亚克力板或厚实的不织布,配合硅胶或热熔胶,将亚克力管底部密封,防止灰尘进入。
  3. 安装顶盖 :将顶盖木圆盘套在亚克力管顶端。此时,从管侧孔引出的按钮线和电池盒线,以及从顶盖中心孔引出的灯带/喇叭线,都在顶盖上方了。
  4. 连接与固定外部部件 :将大按钮安装在底座木板预先开好的孔位上(孔位需匹配按钮螺母),电池盒也用胶或魔术贴固定在底座侧面。将对应的线缆连接好。
  5. 最终结构整合 :将亚克力管插入底座中心的孔中,调整垂直度后,可以从底座下方打入少量木工胶或使用法兰盘固定。将顶盖与亚克力管顶端粘合。 再次强调,确保所有电子功能测试无误后再进行永久粘合!

3.4 水母触须与外观制作

这是赋予项目灵魂的艺术环节。

  1. 制作伞盖
    • 用黑色不织布或帆布,裁剪出7-8个长条三角形(底边约15cm,高约30-40cm)。
    • 用缝纫机将这些三角形的长边缝合在一起,形成一个圆锥体,这就是水母的“伞盖”。
    • 在伞盖的内侧或边缘,缝上或粘上各种触觉材料:毛茸茸的绒球缎带、光滑的亮片缎带、沙沙作响的网纱布料。创造丰富的触觉对比。
  2. 集成灯光
    • 在顶盖木圆盘上,围绕中心走线孔,将LED灯带(从亚克力管中伸出的部分)用胶水或小钉子固定成一圈,确保LED朝向伞盖内部。
    • 将水母伞盖套在顶盖圆盘上,让灯光能从布料中透出。用填充棉适量塞入伞盖顶部,使其看起来饱满。
    • 用热熔胶或手工针线将伞盖的底部固定在顶盖圆盘边缘。
  3. 制作触须
    • 剪出长度不一的黑色、半透明纱带或丝带。
    • 将这些触须粘在伞盖内侧边缘,垂落下来。
    • 可以在部分触须上粘上小铃铛或更小的亮片,增加动态感和听觉细节。
  4. 最终装饰 :用剩余的亮片布、缎带装饰亚克力管柱和底座,遮盖可能不美观的接缝和线缆。

4. 调试、优化与问题排查实录

即使规划得再周密,实际制作中总会遇到问题。以下是我们在项目中和后续反思中总结的“避坑指南”。

4.1 常见问题与解决方案速查表

问题现象 可能原因 排查步骤与解决方案
上电后无任何反应 1. 电池没电或装反。
2. 电源线虚焊或断开。
3. CPB未正确启动。
1. 用万用表检查电池电压,确保正负极正确。
2. 检查CPB板载红色电源LED是否亮起。不亮则检查电源焊接点。
3. 重新按一下CPB上的复位键。
按下按钮无反应 1. 按钮接线错误(特别是上拉模式)。
2. 代码中引脚定义错误。
3. 按钮内部接触不良。
1. 用万用表通断档,测按钮按下时两引脚是否导通。
2. 在代码中添加 print(big_button.value) ,观察串口输出,按下时应从 True False
3. 检查代码中 if not big_button.value: 逻辑是否正确。
LED灯带不亮或部分不亮 1. 电源功率不足(特别是LED全白时)。
2. 数据线(DIN)接触不良或接反。
3. 灯带中某个LED损坏导致信号中断。
1. 尝试降低代码中的 brightness 值(如从0.8降至0.3)。
2. 检查数据线焊接点。用单独程序测试灯带(如让所有灯亮红色)。
3. 如果部分不亮,检查该LED前后焊接点,或绕过该LED焊接数据线。
有灯光但无声音 1. 扬声器或功放未接电或损坏。
2. 音频文件格式不正确。
3. 音量设置过低或硬件静音。
1. 检查喇叭/功放与CPB的连线(电源、地、信号)。
2. 确认 .wav 文件是单声道、16位PCM格式,且已放入正确的文件夹。
3. 尝试用一段简单的代码测试蜂鸣器(如果CPB有)看音频系统是否正常。
声音播放卡顿或灯光动画掉帧 1. 音频文件过大或采样率过高。
2. 主循环中有阻塞操作。
3. 电源电压下降。
1. 用Audacity重新处理音频文件,缩短时长、降低采样率。
2. 确保在 audio.playing 循环中调用了 sparkle.animate() ,并留有短暂 time.sleep
3. 更换新电池,或考虑使用容量更大的锂电池组。
按钮响应不灵或连发 1. 机械抖动。
2. 主循环扫描速度过快。
1. 在代码中实现“消抖”,如检测下降沿并延时。上文代码已包含此逻辑。
2. 在主循环中增加 time.sleep(0.05)

4.2 项目优化与扩展思路

完成基础版本后,可以考虑以下升级,让装置更具交互性和适应性:

  1. 多模式切换 :增加一个旋钮开关或第二个按钮,用于切换不同的“场景模式”。例如:

    • 模式A :紫色闪烁+水声(基础模式)。
    • 模式B :缓慢呼吸的蓝绿色光+轻柔的海浪白噪音。
    • 模式C :随着环境声音(如拍手)大小而改变亮度或颜色的互动模式(利用CPB的麦克风)。
    • 实现方法:在代码中增加一个 mode 变量,通过另一个输入设备改变其值,在主循环中根据 mode 执行不同的灯光和声音例程。
  2. 增加传感器互动 :利用CPB板载的丰富传感器。

    • 光线传感器 :根据环境光自动调节LED亮度,在暗环境中降低亮度避免刺眼。
    • 加速度计 :轻轻拍打或摇晃底座,可以触发不同的灯光效果,提供另一种交互方式。
    • 电容触摸 :将一些金属亮片或锡纸连接到CPB的触摸引脚上,当用户触摸这些“触须”时,可以触发特定的反馈。
  3. 提升音频体验

    • 使用更高质量的I2S音频DAC模块和扬声器。
    • 实现音频的淡入淡出效果,避免声音突然开始和结束。
    • 播放更长的、循环的环境音轨,而按钮按下时触发一个短促的“点缀音效”。
  4. 结构与美学优化

    • 使用激光切割亚克力板来制作更精致、有图案的底座和顶盖。
    • 在亚克力管内部加入一些漫射材料(如磨砂贴膜或乳白色亚克力管),让LED光线更柔和均匀。
    • 为整个装置设计一个可拆卸的、易于清洗的外罩。

这个“水母感官站”项目从构思到落地的全过程,深刻地体现了辅助技术项目的核心——技术是手段,关怀与适用才是目的。它不需要多么高深的技术,但需要周全的考虑、耐心的调试和用心的制作。最大的收获不是做出了一个会发光发声的玩具,而是在测试时看到一位学生被绚烂的光影和舒缓的水声吸引,专注地探索不同纹理的触须,那一刻,所有焊接时烫到的手指、调试代码时的抓狂都值了。如果你也想尝试,不妨就从一块Circuit Playground开始,从一个明确的小需求出发,最重要的是,保持动手和分享的热情。

更多推荐