基于CRICKIT与CPX的交互式电子展板:从传感器到执行器的完整原型开发指南
1. 项目概述打造一个会“思考”和“反应”的电子展板如果你对Arduino或树莓派这类微控制器项目感兴趣但又觉得从零开始连接电机、灯带、传感器还要处理复杂的电源和信号问题过程太过繁琐和容易出错那么这个项目可能就是为你准备的。我最近用Adafruit的CRICKIT扩展板和Circuit Playground ExpressCPX主控板搭建了一个集成了八种不同交互方式的电子展板。它就像一个微缩的“游乐场”通过按下按钮、旋转旋钮、触摸金属条、改变光照等简单动作就能控制电磁铁敲钟、舵机转动、电机加速、灯带跑马灯等一系列炫酷的物理反馈。整个过程我几乎没有动用电烙铁大部分连接靠的是螺丝端子和杜邦线编程则使用了对新手极其友好的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 CPXCRICKIT是“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, brightness0.3, auto_writeFalse) # 定义一个炫彩追逐动画函数 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: # --- 第一部分按钮控制螺线管和电磁铁 --- # 读取按钮状态当按下时被拉低到GNDdigital_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固定在纸板背面。确保不会晃动且散热不受影响。美化与标识用标签纸打印或手写一些简单的标识贴在按钮旁边如“敲钟”、“吸铁石”、电位器旁画一个角度刻度、触摸带旁画一个手指图标。这能极大提升展板的可玩性和教育性。实操心得模块化测试与故障隔离。不要等到所有东西都装好了再第一次上电测试。我的策略是“装一个测一个”。固定好按钮就接上线测试按钮功能贴上灯带就测试触摸触发。这样如果最终某个功能失效你很容易就能定位问题是出在新安装的部件、其连接线还是因为安装过程导致了短路或接触不良。另外在纸板内部走线时可以用胶带将线缆固定在板子上防止它们因重力下垂或互相缠绕。