基于CRICKIT与CPX的交互式电子展板:从传感器到执行器的完整原型开发指南
1. 项目概述:打造一个会“思考”和“反应”的电子展板
如果你对Arduino或树莓派这类微控制器项目感兴趣,但又觉得从零开始连接电机、灯带、传感器,还要处理复杂的电源和信号问题,过程太过繁琐和容易出错,那么这个项目可能就是为你准备的。我最近用Adafruit的CRICKIT扩展板和Circuit Playground Express(CPX)主控板,搭建了一个集成了八种不同交互方式的电子展板。它就像一个微缩的“游乐场”,通过按下按钮、旋转旋钮、触摸金属条、改变光照等简单动作,就能控制电磁铁敲钟、舵机转动、电机加速、灯带跑马灯等一系列炫酷的物理反馈。整个过程,我几乎没有动用电烙铁,大部分连接靠的是螺丝端子和杜邦线,编程则使用了对新手极其友好的CircuitPython。
这个项目的核心价值在于,它完美诠释了“扩展板”在硬件原型开发中的意义。CRICKIT本质上是一个强大的“外设管家”和“动力放大器”。CPX主控板负责“思考”(运行程序逻辑),而CRICKIT则负责“执行”和“感知”,它提供了统一的电源管理、电机驱动、大电流输出和信号调理接口。这种分工让你能摆脱繁琐的底层电路搭建,比如不用再担心驱动电机需要额外的H桥电路,或者连接多个舵机时电流不足的问题。你可以把全部精力集中在“我想实现什么交互逻辑”上。对于教育、艺术装置原型或者快速验证产品交互概念的场景来说,这种组合的效率提升是巨大的。接下来,我会从物料准备、电路原理、代码解析到机械组装,毫无保留地分享整个制作过程,以及我趟过的一些坑和总结出的实用技巧。
2. 核心硬件选型与功能解析
在动手之前,理解你手中的“武器”至关重要。这个项目的灵魂是两件硬件:作为大脑的Circuit Playground Express和作为四肢与感官的CRICKIT扩展板。它们的组合,让复杂交互变得简单。
2.1 大脑核心:Circuit Playground Express (CPX)
Circuit Playground Express不是一块普通的微控制器板。你可以把它看作一个高度集成、开箱即用的传感器套件。它内置了温度传感器、光线传感器、运动传感器(加速度计)、麦克风、蜂鸣器,甚至还有10个可编程的RGB NeoPixel LED。这意味着在连接任何外部设备之前,它本身就能完成许多感知和反馈任务。在这个项目中,我们就利用了其内置的光线传感器来控制直流电机的速度。
CPX通过其边缘的“鳄鱼夹友好型”大焊盘和标准引脚,与外部世界通信。它运行CircuitPython,这是一种基于Python的语言,其最大优势是有一个交互式串行终端(REPL),你可以像在电脑上使用Python命令行一样,实时测试代码、读取传感器数值,这对于调试和学习来说体验极佳。选择CPX而非更基础的板子(如Arduino Uno),是因为它极大地降低了入门门槛,省去了额外购买和连接多个传感器的成本和麻烦。
2.2 外设中枢:Adafruit CRICKIT for CPX
CRICKIT是“Creative Robotics and Interactive Construction Kit”的缩写。它的设计初衷就是为CPX这类板子补足驱动大电流、高功率设备的能力。简单来说,CPX的引脚输出电流很小(约20mA),无法直接驱动电机、螺线管或一整条LED灯带。CRICKIT解决了这个问题。
它通过一个叫Seesaw的协处理器芯片,使用I2C协议与CPX通信。这意味着CPX只用两个数据引脚(SDA, SCL)就能控制CRICKIT上所有的丰富资源:
- 4路舵机输出:提供稳定的5V电源和PWM信号,可直接驱动标准舵机。
- 2路直流电机驱动:内置双H桥电路,可以控制电机的正反转和速度(通过PWM调速)。
- 4路大电流“驱动”输出:可以理解为4个独立的数字开关,能提供高达500mA的电流,完美驱动螺线管、电磁铁、继电器或大功率LED。
- 8路信号输入/输出口:可以连接按钮、开关、电位器(作为模拟输入)等。
- 4路电容触摸输入:无需直接接触金属,就能检测人体触摸,非常适合做非接触式开关。
- 1路NeoPixel专用输出:为LED灯带提供数据和电源。
- 1路音频放大输出:连接扬声器,可以播放声音或简单的音调。
更重要的是,CRICKIT自带一个5V/2A的电源输入接口和一个电源开关。你可以用一个5V/2A的墙插电源同时为整个系统(包括CPX、CRICKIT和所有外设)供电,这比单纯依赖USB供电要稳定和强大得多,尤其是在同时驱动多个电机时。
2.3 外设清单与功能对应
根据项目总览,我们需要准备以下核心外设,每一件都对应一种经典的交互模式:
- 2个街机按钮:提供最直接、最可靠的物理输入。我们将用它来触发“瞬时动作”,比如让螺线管敲一下钟。
- 1个电位器:经典的模拟输入设备。旋转它,可以线性地、连续地控制一个输出量,比如舵机的角度。
- 导电胶带:作为电容触摸传感器。这是一种优雅的输入方式,手指轻触即可触发,我们将用它来启动一个LED灯带的动画效果。
- 30颗NeoPixel灯带:可单独寻址的RGB LED。用于提供丰富的视觉反馈,如流水灯、颜色变化等。
- 3W扬声器:提供音频反馈。当同时按下两个按钮时,播放一段简单的音阶,增加交互的趣味性和惊喜感。
- TT直流减速电机(带轮子):将电信号转换为持续的旋转运动。我们用CPX内置的光线传感器数值来控制它的转速,光线越亮,转得越快。
- 5V螺线管:将电信号转换为短促的直线撞击运动。按下按钮,它就会迅速弹出一小段,可以用来敲击一个小铃铛。
- 5V电磁铁:通电产生磁性,断电磁性消失。另一个按钮控制它,可以吸起或释放一个金属重物,直观展示“电生磁”现象。
- 180度微型舵机:将电信号转换为精确的角度位置。由电位器控制,旋钮转多少度,舵机臂就转多少度。
注意:电源是关键。务必使用规格为5V、至少2A的直流电源适配器(中心正极)为CRICKIT供电。USB供电通常无法满足电机和灯带同时工作的峰值电流,可能导致板子重启或工作不稳定。我最初尝试用电脑USB供电,在同时点亮灯带和启动电机时,系统就出现了间歇性复位。
3. 电路连接详解与信号流分析
在把东西装进盒子前,强烈建议先在桌面上完成所有电路的连接和测试。这能确保每个部件都是好的,并且你理解了每一根线的作用。盲目组装后再调试,会是一场噩梦。
3.1 供电与核心连接
首先,将Circuit Playground Express通过其背面的插槽,严丝合缝地插入CRICKIT扩展板。确保所有引脚都对齐并插到底。这是两者通信的物理基础。然后,将5V/2A电源适配器插入CRICKIT的DC电源接口,并将开关拨到“ON”。此时,CPX和CRICKIT都应被点亮。
3.2 数字输入:按钮的连接
两个街机按钮的连接最简单。每个按钮有两根线(不分正负)。我们将它们分别连接到CRICKIT上“Signal I/O”区域的Signal 1和Signal 2端口。
- 具体操作:取两根公-公杜邦线,一端插入按钮的接线端子,另一端插入CRICKIT上标有“1”和“GND”的螺丝端子孔内(对于第一个按钮)。信号线(如橙色)接“1”,另一根线(如棕色)接旁边的“GND”。第二个按钮同理接在“2”和“GND”上。
- 内部原理:在代码中,我们将这两个信号引脚设置为“上拉输入”。当按钮未按下时,引脚通过内部电阻连接到3.3V(高电平)。按下按钮时,引脚被短接到GND(低电平)。程序通过检测这个从高到低的跳变来判定按钮动作。
3.3 模拟输入:电位器的连接
电位器有三个引脚:两端的固定端和一个中间的滑动端。我们需要为它提供电压,并读取滑动端的分压值。
- 具体操作:使用三根带鳄鱼夹的测试线。左边引脚接CRICKIT上Signal 8端口的“3.3V”,右边引脚接“GND”,中间引脚接“Signal”。这样,就在电位器两端建立了一个3.3V的电压差。旋转旋钮,中间引脚的电压会在0V到3.3V之间线性变化。
- 信号流:CRICKIT内部的Seesaw芯片会通过ADC(模数转换器)将这个0-3.3V的模拟电压,转换成一个0-1023的数字值,并通过I2C发送给CPX。代码中的
map_range函数将这个0-1023的值映射到舵机的0-180度。
3.4 电容触摸:导电胶带的连接
这是最有趣的部分之一。电容触摸不需要形成电流回路,它检测的是因手指触摸而引起的微小电容变化。
- 具体操作:将导电胶带(或铝箔)贴在纸箱表面,形成一条触摸带。用一根带鳄鱼夹的测试线,一端夹住胶带裸露的末端,另一端连接到CRICKIT“Capacitive Touch”区域的“1”号端口。
- 工作原理:CRICKIT会向该引脚发送一个高频信号,并监测其充放电时间。当手指(一个导电体)靠近或触摸胶带时,相当于增加了一个电容,充放电时间会变长。芯片检测到这个时间变化,并输出一个相应的原始数值。在代码中,我们设置一个阈值(如800),当读取值超过该阈值时,就判定为“触摸”。
3.5 输出设备:执行器与指示器的连接
输出设备的连接主要关注电源和信号方向。
- NeoPixel灯带:灯带有三根线:5V(红色)、GND(白色或黑色)、Data(绿色)。分别用带鳄鱼夹的线连接到CRICKIT“NeoPixel”端口的对应位置。注意:数据线(Data)必须连接到标有“>”符号的端口,顺序不能错。
- 扬声器:两根线不分正负,直接插入CRICKIT的“Speaker”端口。
- 直流电机:两根线不分正负(控制方向由程序决定),插入“Motor 1”端口。
- 螺线管与电磁铁:它们都是两线设备。将其中一根线(通常是红色或不分颜色)接到“Drive”区域的“5V”螺丝端子上。将另一根线分别接到“Drive 1”(螺线管)和“Drive 2”(电磁铁)。这样,当程序将对应的Drive端口设置为高电平时,电流从5V流经设备到达Drive端口(此时在芯片内部切换到GND),形成回路,设备工作。
- 舵机:这是一个三线设备:电源(红色,+5V)、地线(棕色或黑色,GND)、信号线(橙色或黄色,Signal)。CRICKIT的“Servo”端口已经排列好顺序,按照“棕色在内侧(靠近板子中心)”的方向插入“Servo 1”端口即可。
实操心得:理线与标识。在测试阶段,虽然线路杂乱,但一定要用标签纸或彩色胶带为每一组线做好标记。例如,用红黄胶带标记按钮1的线,用蓝白胶带标记电位器的线。这在你后续排查“某个功能为什么不工作”时,能节省大量时间。我曾经因为两根颜色相近的电机线接反了方向,调试了半小时电机为什么不转。
4. CircuitPython代码深度剖析与编写
硬件连接是骨架,代码才是灵魂。这个项目的代码结构清晰,是学习事件驱动编程和传感器融合的绝佳范例。我们使用Mu Editor作为代码编辑器和串口终端。
4.1 开发环境搭建与库安装
首先,确保你的CPX已经烧录了支持CRICKIT的特殊版本CircuitPython固件。这是因为标准版固件不包含与CRICKIT的Seesaw芯片通信的底层驱动。你需要从Adafruit官网下载名为“adafruit-circuitpython-circuitplayground_express_crickit-xx.bin”的文件,并将其拖入出现的“CPLAYBOOT”磁盘中来完成烧录。
烧录成功后,电脑上会出现一个名为“CIRCUITPY”的磁盘。接下来,需要安装必要的库。从Adafruit的CircuitPython库包中,找到adafruit_crickit.mpy和simpleio.mpy这两个文件。在“CIRCUITPY”磁盘根目录下,创建一个名为lib的文件夹(如果不存在),将这两个.mpy文件复制进去。这样,你的代码才能调用控制CRICKIT和进行数值映射的函数。
4.2 主程序逻辑逐行解读
我们将核心代码code.py拆解开来分析:
# SPDX-FileCopyrightText: 2019 Dano Wall for Adafruit Industries # SPDX-License-Identifier: MIT """ Crickit Exhibit 交互式展板主程序 """ import time from adafruit_crickit import crickit # 导入CRICKIT控制库 import board import neopixel from analogio import AnalogIn from simpleio import map_range, tone # 导入数值映射和发声函数 # 定义一些常用的RGB颜色元组,方便调用 RED = (255, 0, 0) YELLOW = (255, 150, 0) GREEN = (0, 255, 0) CYAN = (0, 255, 255) BLUE = (0, 0, 255) PURPLE = (180, 0, 255) # 初始化与CRICKIT上Seesaw协处理器的通信接口 ss = crickit.seesaw # 初始化两个按钮,设置为内部上拉输入模式 BUTTON_1 = crickit.SIGNAL1 BUTTON_2 = crickit.SIGNAL2 ss.pin_mode(BUTTON_1, ss.INPUT_PULLUP) ss.pin_mode(BUTTON_2, ss.INPUT_PULLUP) # 设置螺线管(Drive 1)和电磁铁(Drive 2)的PWM频率为1000Hz # 频率影响驱动设备的响应速度和噪音,1000Hz是一个常用值 crickit.drive_1.frequency = 1000 crickit.drive_2.frequency = 1000 # 初始化NeoPixel灯带:30颗灯,亮度30%,连接在CPX的A1引脚 num_pixels = 30 pixels = neopixel.NeoPixel(board.A1, num_pixels, brightness=0.3, auto_write=False) # 定义一个炫彩追逐动画函数 def color_chase(color, wait): for i in range(num_pixels): pixels[i] = color # 设置当前LED颜色 time.sleep(wait) # 等待一段时间,产生流动效果 pixels.show() # 将颜色数据发送到灯带 time.sleep(0.5) # 初始化电位器,连接到CRICKIT的Signal 8 pot = crickit.SIGNAL8 # 初始化CPX板载光线传感器 light_in = AnalogIn(board.LIGHT) # 主循环开始 while True: # --- 第一部分:按钮控制螺线管和电磁铁 --- # 读取按钮状态,当按下时(被拉低到GND),`digital_read`返回`False` if not ss.digital_read(BUTTON_1): print("按钮1按下") crickit.drive_1.fraction = 1.0 # 螺线管全力开启 time.sleep(0.01) # 保持10毫秒,产生一个短脉冲 crickit.drive_1.fraction = 0.0 # 关闭螺线管 time.sleep(0.5) # 防抖延时,防止误触发 else: crickit.drive_1.fraction = 0.0 # 确保未按时保持关闭 # 按钮2控制电磁铁,逻辑类似,但保持时间更长以观察磁性 if not ss.digital_read(BUTTON_2): print("按钮2按下") crickit.drive_2.fraction = 1.0 time.sleep(0.5) # 电磁铁保持吸合0.5秒 else: crickit.drive_2.fraction = 0.0 # --- 第二部分:电容触摸控制NeoPixel动画 --- touch_raw_value = crickit.touch_1.raw_value if touch_raw_value > 800: # 触摸阈值,可根据实际环境调整 print("检测到触摸,启动流光效果") color_chase(PURPLE, 0.1) # 紫色流光,每灯间隔0.1秒 else: pixels.fill((0, 0, 0)) # 无触摸时,关闭所有LED pixels.show() # --- 第三部分:电位器控制舵机角度 --- # 读取电位器原始值(0-1023),并映射到舵机角度(180-0) # 注意映射是反的:电位器最小值对应舵机180度,最大值对应0度 # 这是因为电位器安装方向可能相反,这样映射更符合直觉(顺时针旋转,舵机顺时针转) angle = map_range(ss.analog_read(pot), 0, 1023, 180, 0) crickit.servo_1.angle = angle # 设置舵机角度 # --- 第四部分:环境光控制直流电机速度 --- # 读取光线传感器值(范围很广,约几百到几万) # 将光线值映射到电机油门值(0-1,即停止到全速) # 3000和62000这两个阈值需要根据实际环境光照校准 peak = map_range(light_in.value, 3000, 62000, 0, 1) crickit.dc_motor_1.throttle = peak # 设置电机速度 # --- 第五部分:组合键触发声音 --- # 当两个按钮同时被按下时 if not ss.digital_read(BUTTON_1) and not ss.digital_read(BUTTON_2): print("按钮1和2同时按下") # 播放一个从C4到C5的八度音阶 for f in (262, 294, 330, 349, 392, 440, 494, 523): tone(board.A0, f, 0.25) # 在A0引脚输出频率为f的声音,持续0.25秒 time.sleep(0.1) # 音符间间隔0.1秒4.3 代码优化与调试技巧
上面的代码是基础版本,完全可用。但在实际制作中,我做了几点优化:
- 阈值校准:电容触摸的
800和光线传感器的(3000, 62000)这两个阈值不是绝对的。在你的环境中,需要通过REPL实时打印这些值来校准。在Mu编辑器中点击“串口”按钮,打开REPL,然后添加几行调试代码,比如print(touch_raw_value)和print(light_in.value),观察在触摸/未触摸、亮/暗环境下的数值范围,然后调整阈值。 - 消除舵机抖动:舵机在到达目标角度时可能会轻微抖动。可以在设置角度后增加一个极短的延时,如
time.sleep(0.05),或者使用crickit.servo_1.angle = angle后,不频繁地更新角度,只有当电位器变化超过一定幅度时才更新。 - 电机死区处理:直流电机在低速时可能无法启动。可以给
peak值设置一个最小启动阈值,例如:如果peak < 0.2,则设置throttle = 0;否则,按原值设置。这样可以避免电机在暗处发出嗡嗡声却不转动。
常见问题排查表:
现象 可能原因 解决方案 按下按钮无反应 1. 按钮线未接好或接错(如两端都接了信号)
2. 代码中引脚定义错误
3. 未启用内部上拉电阻1. 检查接线是否为“信号-GND”组合。
2. 核对代码BUTTON_1是否对应crickit.SIGNAL1。
3. 确认pin_mode设置了INPUT_PULLUP。电位器控制舵机方向反了 电位器接线方向或映射范围反了 交换电位器两端子(3.3V和GND)的接线,或者交换 map_range函数中最后两个参数(180, 0)的顺序。触摸胶带不灵敏 1. 触摸阈值设置过高
2. 胶带接触不良或面积太小
3. 环境干扰大1. 在REPL中打印触摸值,调低阈值(如从800调到500)。
2. 确保鳄鱼夹与胶带接触紧密,增大胶带面积。
3. 让触摸线远离电源等干扰源。NeoPixel灯带部分不亮或颜色错乱 1. 数据流方向接反
2. 电源电流不足
3. 灯带中有一颗LED损坏1. 检查数据线(Din)是否接在CRICKIT的“>”标志端。
2. 确保使用5V/2A外接电源,而非USB供电。
3. 尝试跳过前几颗灯,从后面的灯开始点亮测试。电机/电磁铁不工作 1. CRICKIT电源开关未打开
2. 未使用外接电源
3. Drive端口设置错误1. 确认CRICKIT上小开关拨到了“ON”。
2.必须使用5V/2A外接电源。
3. 确认代码中控制的是正确的Drive端口(如drive_1)。
5. 展板结构设计与组装实战
代码和电路测试无误后,就可以开始打造它的“身体”了。一个设计良好的外壳不仅能保护电路,更能提升交互体验和展示效果。
5.1 布局规划与开孔设计
找一个足够大的硬纸箱(比如电脑显示器包装箱),将其展开成一个平面。将所有电子元件在纸板上摆开,进行布局规划。核心原则是:用户体验优先,走线方便其次。
- 交互区域:将需要用户操作的部件(两个按钮、电位器旋钮、触摸胶带)放在前方或中央显眼位置。
- 反馈区域:将用于展示效果的部件(NeoPixel灯带、转动的电机、摆动的舵机、被敲击的铃铛、被吸起的金属块)放在操作区域周围,确保观众能清晰看到。
- 核心板卡:将CRICKIT和CPX固定在板子背面或侧面不显眼但通风的位置,并确保所有接线孔朝向正确,方便走线。
- 走线考虑:在规划每个部件位置时,同步考虑其连线到CRICKIT的路径。尽量让线缆从部件背面直接进入纸板背面,减少正面凌乱。
用铅笔在纸板上轻轻勾勒出每个部件需要开孔的位置和形状:
- 按钮和电位器:需要开圆孔。用卡尺测量其安装直径,通常按钮是30mm,电位器是8mm。
- 舵机:需要开一个矩形孔,让舵机的方形主体能穿过,而边缘的安装耳留在背面固定。
- 电机、螺线管、扬声器:规划好固定位置,可能需要开小孔用于螺丝固定或穿线。
- 线缆通道:在CRICKIT附近,开几个较大的方孔或圆孔,作为所有线缆汇总并连接到板子背面的通道。
5.2 安全切割与部件固定
使用美工刀或笔刀进行切割。安全第一,建议使用切割垫,并佩戴防护手套。
- 圆孔:先用锥子或螺丝刀在圆心扎一个孔,然后用笔刀沿画好的圆慢慢切割。对于按钮的大圆孔,可以分多次切割,不要试图一刀完成。
- 方孔:用直尺辅助,先切割四条边,然后取下中间的废料。舵机的方孔要略小于其主体,这样它才能卡住。
- 固定方式:
- 按钮和电位器:它们通常自带螺母,从纸板正面放入,在背面用配套的螺母拧紧固定。
- 舵机:可以使用热熔胶从背面将其粘牢。注意不要将胶涂到齿轮或转轴上。
- 电机、螺线管、扬声器:优先使用螺丝固定。如果纸板太软,可以在背面粘贴一小块木片或塑料片作为加强筋,再将螺丝拧在上面。双面泡沫胶也是一个快速的临时固定方案。
- NeoPixel灯带:沿着规划好的路径,用双面泡沫胶或布基胶带粘贴。
- 导电胶带:直接撕下背胶,粘贴在预设的触摸区域。确保末端留出一小段用于夹鳄鱼夹。
5.3 内部走线与最终集成
这是组装中最考验耐心和条理的一步。
- 分组布线:将连接到同一区域(如Signal I/O区、Drive区)的线缆用扎带或扭绳捆在一起。
- 长度预留:留出适当的线缆余量,避免拉扯过紧,但也不要过长导致杂乱。多余的线可以盘成小圈用扎带固定。
- 顺序连接:按照之前测试时的连接图,将所有部件的线缆连接到CRICKIT对应的端子上。务必在断电状态下操作!每连接好一组,可以上电进行一次快速功能测试,确保在组装后依然工作。
- 固定主板:用尼龙柱或厚厚的双面泡沫胶将CRICKIT和CPX固定在纸板背面。确保不会晃动,且散热不受影响。
- 美化与标识:用标签纸打印或手写一些简单的标识,贴在按钮旁边(如“敲钟”、“吸铁石”)、电位器旁(画一个角度刻度)、触摸带旁(画一个手指图标)。这能极大提升展板的可玩性和教育性。
实操心得:模块化测试与故障隔离。不要等到所有东西都装好了再第一次上电测试。我的策略是“装一个,测一个”。固定好按钮,就接上线测试按钮功能;贴上灯带,就测试触摸触发。这样,如果最终某个功能失效,你很容易就能定位问题是出在新安装的部件、其连接线,还是因为安装过程导致了短路或接触不良。另外,在纸板内部走线时,可以用胶带将线缆固定在板子上,防止它们因重力下垂或互相缠绕。
