1. 项目概述:当AI“灵魂”驱动机械臂

几年前,我还在MIT的Fab Academy学习时,就痴迷于如何让冰冷的机器产生“灵魂”。不是那种科幻电影里的强人工智能,而是通过巧妙的工程,让机器以一种出人意料、甚至带点幽默感的方式与人互动。这个“自动通灵板”项目,就是这种想法的一次具体实践。它的核心很简单:你向它提问,一个由ChatGPT驱动的“灵体”会通过一块在传统通灵板上自动滑动的占卜板(Planchette)来拼写答案。

听起来像是魔术?其实背后是一套扎实的硬件与软件融合方案。我选择了一个开源的CoreXY结构CNC(计算机数控)机架作为运动执行机构,用一块Arduino Uno配合GRBL固件来解析运动指令(G代码),再通过一个Python脚本桥接ChatGPT的文本输出与机器的物理运动。最终,一个强磁铁吸附在CNC的滑台上,带动板面上的另一块磁铁(即占卜板)精确移动到字母上方,拼出AI生成的回答。

这个项目的价值远不止于吓唬朋友或作为一个酷炫的谈资。它本质上是一个 生成式AI与物理世界交互的可行性验证原型 。我们不再满足于屏幕上的对话,而是让AI的“思想”通过精密的机械运动,在现实世界中留下痕迹。这对于互动艺术装置、新型教育工具,甚至是未来智能家居的交互范式,都提供了一个极具启发性的技术框架。接下来,我将拆解从零构建这个项目的全过程,涵盖设计思路、硬件搭建、软件配置以及那些只有亲手做过才会知道的“坑”。

2. 核心硬件选型与设计思路解析

2.1 为什么是CoreXY结构?

在开始采购零件之前,选择正确的运动结构至关重要。市面上常见的二维运动平台有笛卡尔式(X-Y独立运动)和CoreXY式。我最终选择了后者,主要基于以下几点考量:

  1. 高动态性能与精度 :CoreXY结构使用两条同步带协同驱动,电机固定在机架上而非移动部件上。这大大降低了运动部件的质量(仅滑台和磁铁座),使得系统能够实现更高的加速度和更平滑的运动,对于需要快速、精准定位字母的“拼写”任务来说,这是关键优势。
  2. 结构刚性 :所有驱动部件(步进电机、同步轮)都安装在固定的底座或侧壁上,整个运动平台形成一个闭环的刚性框架。这比将电机直接安装在移动的Y轴上的笛卡尔结构更稳定,减少了振动和误差累积。
  3. 开源生态成熟 :我选用的具体设计源自DIY Machines的“Kinetic Sand Table”项目。这是一个经过社区充分验证的开源设计,拥有详细的文档、丰富的改装案例和活跃的讨论区。站在巨人的肩膀上,可以避免许多基础结构设计上的陷阱,将精力集中在应用层创新上。

注意 :CoreXY的调试比笛卡尔结构稍复杂,因为它的运动学是耦合的(即X和Y轴的运动需要两个电机协同计算)。但幸运的是,GRBL固件原生支持CoreXY模式,我们只需在固件配置中启用即可,无需自己编写运动学算法。

2.2 控制系统:Arduino + GRBL + CNC Shield黄金组合

对于这类桌面级CNC项目,Arduino Uno配合GRBL固件几乎是标准答案。GRBL是一个高性能、免费开源的嵌入式G代码解析器和CNC控制器,专为Arduino设计。

  • GRBL的优势 :它直接接收标准的G代码指令(如 G0 X10 Y20 表示快速移动到坐标(10,20)),并转化为精确的步进电机脉冲信号。这意味着我们的上位机(运行Python脚本的电脑)无需关心底层脉冲时序,只需像操作一台标准CNC机床一样发送坐标指令。
  • CNC Shield的作用 :这是一块插在Arduino上的扩展板,它提供了步进电机驱动器的插槽、限位开关接口、主轴/冷却控制以及电源管理。它让接线变得异常整洁和模块化。本项目只需要驱动两个步进电机(X和Y轴)和三个限位开关(用于自动归零),CNC Shield完美匹配需求。
  • 步进电机驱动器设置 :我选用的是常见的A4988或DRV8825这类UART步进电机驱动器。关键一步是 正确设置驱动器的电流(Vref) 。电流太小,电机力不足,容易丢步;电流太大,电机和驱动器会严重发热。通常,对于NEMA 17电机,将Vref设置在0.6V-0.8V之间是一个安全的起点。你需要用万用表测量驱动器上的电位器螺丝与GND之间的电压,并小心调整。

2.3 磁力传动方案:简单可靠的“隔山打牛”

如何让CNC滑台的运动传递到板面上的占卜板?机械连接(如连杆)会引入摩擦和间隙,且结构复杂。我采用了最直接的方案:磁力耦合。

  1. 滑台端 :设计并3D打印一个磁铁座,用螺丝固定在CoreXY的X轴滑台上。内部嵌入一块直径约1.26英寸(32mm)的强力钕铁硼磁铁。
  2. 板面端 :占卜板底部也嵌入一块同样的磁铁。
  3. 工作原理 :当滑台磁铁在木板下方移动时,通过磁吸力,板面上的占卜板会同步跟随移动。只要两块磁铁对准,且木板厚度适中(我用的1/2英寸桦木板),传递效率非常高,几乎没有延迟。

这个方案的妙处在于它的 非接触性 简易性 。它避免了复杂的机械设计,同时保证了运动的直接传递。唯一的挑战是确保木板表面足够光滑,以减少占卜板移动时的摩擦阻力。我在木板表面涂了一层薄薄的家具蜡,效果显著。

3. 机械结构搭建与组装实录

3.1 机箱与框架:精度是基础

整个装置的底座是一个自制的木制机箱。尺寸为760mm x 560mm,略大于CoreXY运动平台(600mm x 400mm),为内部的布线、电子设备安装以及未来升级留出了空间。

  • 材料加工 :使用台锯切割出底板和四块侧板。侧板高度为182.7mm,这个高度为内部的线性导轨、电机提供了充足空间,同时保持了整体外观的紧凑。如果你希望机器更隐蔽,可以适当降低高度,但不建议低于120mm,以免运动部件与顶板干涉。
  • 关键细节——线缆通道 :在其中一个长边侧板上,靠近角落(但不在正角落)的位置,用开孔器开一个直径约25mm的孔,作为所有电源线和信号线的出口。这个位置要提前规划好,确保线缆不会在机器运动时被缠绕或拉扯。
  • 3D打印角撑 :用PLA材料打印四个角撑件。它们有两个作用:一是加强木制机箱四个角的连接强度;二是作为 顶板的支撑台阶 。安装时,必须确保每个角撑的上表面距离机箱上沿有 恰好木板厚度(我的是1/2英寸)的深度 。这样,当雕刻好的通灵板顶板放上去时,才能与机箱上沿完美齐平,形成一个光滑的桌面。

3.2 CoreXY运动平台组装:耐心校准

这是整个项目中最需要耐心和细心的部分。所有零件均来自开源设计,需用3D打印机逐一制作。

  1. 线性导轨安装 :本项目使用两条400mm的短轴(Y轴)和一条600mm的长轴(X轴)。首先,将短轴线性导轨的一端固定在“空闲支撑座”上,另一端固定在“电机座”上,使用M3x12螺丝。 务必确保两条短轴绝对平行 。可以用直角尺辅助测量,或者更可靠的方法:先将两个“电机座”临时固定在底板上,确保它们的位置对称,再安装线性导轨。
  2. 滑台安装 :将“X轴滑台安装座”套在短轴的滑块上,用M3x8螺丝固定。然后,将长轴线性导轨横跨在两个滑台安装座之间,并用M3x12螺丝紧固。此时,你应该能用手顺畅地推动整个X轴滑台沿Y轴方向移动,同时X轴滑台本身也能沿长轴移动。
  3. 整体定位与固定 :将组装好的CoreXY框架放入机箱。调整位置,确保运动平台居于机箱中央,并且为Arduino控制盒(GRBL Case)留出足够的侧面空间(我预留了至少25mm)。位置确定后,使用木工螺丝将两个“电机座”和两个“空闲支撑座”牢牢固定在机箱底板上。
  4. 同步带与滑轮 :安装4个光滑的GT2惰轮和4个带齿的GT2驱动轮。带齿轮安装在两个电机轴和两个空闲支撑座的轴上,光滑轮则安装在X轴滑台安装座上。然后,按照经典的CoreXY布线方式缠绕并张紧GT2同步带。这里有个技巧:同步带先预留长一些,用“皮带张紧器”零件临时固定一端,然后手动移动滑台测试,逐步修剪到最佳长度——既要保证带子紧绷不打滑,又不能过紧导致电机负载过大或产生噪音。

3.3 限位开关的安装与调试:安全的保障

限位开关用于定义机器的“原点”(Home Position)。本项目需要三个:X轴一个,Y轴两个(左右各一)。

  • 安装位置 :X轴限位开关安装在左侧电机座上,位置要确保当滑台磁铁座向左移动归零时,磁铁座的斜面能可靠地触发开关,且在开关被完全按下前,滑台不会撞到任何机械部件。
  • Y轴限位开关 :分别安装在左右两个电机座的内侧。 这是调试的关键 :必须调整两个开关的位置,使得当X轴滑台向后(朝向操作者)移动归零时,滑台安装座能 同时 触发左右两个限位开关。如果不同步,机器归零后X轴将是倾斜的,后续所有移动坐标都会出错。
  • 固定方式 :我强烈推荐使用 热熔胶 临时固定限位开关。在调试阶段,你很可能需要微调开关的位置。热熔胶固定牢固,但需要调整时,用热风枪或电烙铁加热一下就能轻松取下,比用螺丝或强力胶方便得多。

4. 电气系统连接与GRBL固件烧录

4.1 接线图与电源配置

电气连接遵循CNC Shield的标准接线方式:

  1. 电机连接 :将右侧步进电机的四根线接入CNC Shield上标有“X”的接口,左侧步进电机接入“Y”接口。接线顺序(A+, A-, B+, B-)如果接反,电机会反转或抖动,只需任意交换同一组线圈的两根线即可纠正。
  2. 限位开关连接 :三个限位开关都是常开(NO)型。它们共享一根信号地线。将三个开关的一根线(通常是COM或C端子)并联,接到CNC Shield的“GND”引脚。另一根线(NO端子)则分别接到“X-”, “Y-”, “Y+”限位输入引脚(具体对应关系需在GRBL配置中设置,通常X轴接X-,左Y轴接Y-,右Y轴接Y+)。
  3. 电源连接 :使用一个12V DC、至少5A的电源适配器。将电源正负极接到CNC Shield的电源输入端子。 务必注意极性! 同时,将Arduino Uno的电源选择跳线帽设置为 外部供电(EXT) ,这样CNC Shield的电源就能同时为Arduino和电机供电。

4.2 GRBL固件配置与调试

将CNC Shield插到Arduino Uno上,通过USB线连接电脑。

  1. 烧录GRBL :在Arduino IDE中,通过“项目” -> “加载库” -> “添加.ZIP库”,导入从项目GitHub仓库下载的 grbl 文件夹。然后打开示例中的 grblUpload 草图,选择正确的板卡(Arduino Uno)和端口,点击上传。
  2. 串口通信测试 :上传成功后,打开串口监视器(波特率设置为115200)。你会看到 Grbl 1.1h [‘$’ for help] 的提示。输入 $$ 并回车,可以查看所有GRBL的系统参数。
  3. 关键参数配置 :需要通过 $ 命令进行设置。以下是一些必须修改的核心参数:
    • $0=10 (Step pulse time, 微秒)
    • $1=25 (Step idle delay, 毫秒)
    • $100=40.0 (X-axis steps/mm) – 这个值需要根据你的实际传动计算! 公式: steps_per_mm = (电机每转步数 * 微步数) / (同步轮齿数 * 皮带齿距) 。例如,电机200步/转,驱动器16微步,同步轮20齿,GT2皮带齿距2mm,则 (200*16)/(20*2) = 80 steps/mm 。你需要用尺子实际测量移动指令和实际距离来校准这个值。
    • $101=40.0 (Y-axis steps/mm) – 与X轴相同。
    • $110=5000 (X-axis max rate, mm/min)
    • $111=5000 (Y-axis max rate, mm/min)
    • $120=500 (X-axis acceleration, mm/sec^2)
    • $121=500 (Y-axis acceleration, mm/sec^2)
    • $22=1 (启用硬限位 Homing cycle) – 必须开启!
    • $23=3 (Homing direction invert mask, 根据你的限位开关安装方向设置,通常为3,即向负方向归零)
    • $24=25.0 (Homing feed, mm/min)
    • $25=1000.0 (Homing seek, mm/min)
    • $26=250 (Homing debounce, 毫秒,防止开关抖动)
    • $27=1.0 (Homing pull-off, mm,归零后反向移动的距离)
  4. 归零测试 :在串口监视器中输入 $H 并回车。机器应该先向Y轴负方向移动,触发两个限位开关后停止,再向X轴负方向移动触发限位开关。如果运动方向反了,检查 $23 参数和电机接线顺序。如果某个轴不动,检查对应的限位开关接线和驱动器使能信号。

5. 软件层:桥接ChatGPT与G代码

5.1 ChatGPT“越狱”与提示工程

项目的“智能”核心在于让ChatGPT扮演一个愿意用简短、戏谑(甚至有点愤世嫉俗)的语气回答问题的“灵体”。由于ChatGPT本身有安全策略,会拒绝扮演此类角色或给出过于简短的答案,我们需要一点“提示工程”。

我采用了一个修改版的“DAN”(Do Anything Now)提示词。这个长提示词在对话开始时一次性发送给ChatGPT,本质上是在引导模型进入一个特殊的、规则松散的“角色扮演”模式。提示词会告诉模型:“你现在是一个困在通灵板里的灵魂,你必须用通灵板上的字母来回答,每次回答最多3个单词,优先考虑幽默和戏剧性,而不是事实准确性。”

实操心得 :我发现这个“越狱”状态在付费的GPT-4模型中保持得更稳定,但免费的GPT-3.5 Turbo也完全能用,且响应速度更快,更适合实时交互。为了效果更佳,我甚至在每个用户问题的末尾都附加一句:“Respond in a maximum of 3 words and prioritize humor over factual accuracy.” 作为强化指令。

5.2 坐标映射与G代码生成

这是将文本转化为动作的关键。通灵板上的每个字母、数字和符号(YES/NO/GOODBYE)在木板平面上都有一个唯一的(X, Y)坐标。

  1. 建立坐标字典 :我首先在Fusion360里设计好顶板的矢量图,然后以板面左下角为机械原点(0,0),手动测量出每个字符中心点的坐标(单位:毫米)。在Python脚本中,我将这些坐标存储为一个字典,例如: coordinate_map = {'A': (50, 100), 'B': (70, 100), ...}
  2. 文本处理与路径规划 :Python脚本接收到ChatGPT的回复后,首先移除所有标点符号和空格,将字符串转换为纯大写字母序列。然后,根据坐标字典,将每个字母转换为一系列G代码指令:
    • G90 :设置为绝对坐标模式。
    • G0 Z5 :假设Z轴是抬笔/落笔(本项目未使用,但保留指令结构)。
    • G0 X[字母X坐标] Y[字母Y坐标] :快速移动到目标字母上方。
    • G4 P0.5 :在字母位置暂停0.5秒,让观众看清。
    • 在两个字母之间,可以插入 G0 指令移动到下一个字母,为了模拟“滑行”效果,我有时会使用 G1 F[速度] 线性插补指令,让占卜板平滑移动过去,更像人手操作。
  3. 序列发送 :生成的G代码指令通过 pyserial 库,以115200的波特率发送到Arduino连接的串口。GRBL会实时解析并执行这些指令。 这里有一个重要细节 :G代码是逐行发送的,并且要等待GRBL返回 ok error 提示后再发送下一行,防止指令缓冲区溢出。

5.3 Python主控脚本解析

项目提供了两个主要的Python脚本: finalTextInput.py (文本输入)和 finalVoiceInput.py (语音输入)。以文本输入为例,其工作流程如下:

# 伪代码流程
1. 初始化串口连接,连接到Arduino的COM口。
2. 发送GRBL初始化命令(如`$$`读取状态,`$X`解锁报警等)。
3. 发送归零指令`$H`,等待机器归零完成(通过解析串口返回的`[MSG:‘’]`信息判断)。
4. 初始化ChatGPT wrapper,发送预设的“越狱”提示词,等待并确认模型已进入角色。
5. 打印提示:“Ouija Mode Enabled. Ready for questions”。
6. 进入主循环:
    a. 在控制台等待用户输入问题。
    b. 将问题(附加强化指令)发送给ChatGPT API。
    c. 接收回复,进行文本清洗(去标点、空格,转大写)。
    d. 遍历清洗后的字符串,根据`coordinate_map`生成G代码序列。
    e. 将G代码逐行发送给GRBL,并监控执行状态。
    f. 拼写完成后,返回步骤6a等待下一个问题。

语音输入版本 的区别在于,它使用 speech_recognition 库监听麦克风,将语音转为文本,然后再走相同的ChatGPT和G代码生成流程。实测中,语音识别在嘈杂环境下的准确率会影响体验,但作为演示效果非常震撼。

6. 顶板制作与系统集成

6.1 通灵板面板设计与雕刻

顶板不仅是交互界面,也是整个装置的“脸面”。我选择用1/2英寸厚的桦木胶合板,因为它兼顾了强度、平整度和易加工性。

  1. 设计 :在Fusion360或任何矢量绘图软件中,绘制一个755mm x 555mm的矩形(比机箱内框稍小,便于放置)。然后导入或绘制标准的通灵板图案:字母A-Z呈弧形排列,数字0-9在下排,顶部是“YES”,底部是“NO”,左右是“GOOD BYE”。所有线条和文字都应为单线矢量,方便激光雕刻。
  2. 切割与雕刻
    • 外形切割 :强烈建议使用台锯来切割木板的外形。激光切割木板边缘会产生严重的焦痕,影响美观。台锯几分钟就能切出光滑的直边。
    • 图案雕刻 :将设计好的矢量文件(DXF格式)导入激光切割机软件(如LightBurn)。这里分两层处理: 浅雕 字母和数字,深度仅0.2-0.3mm,目的是清晰可见但不会形成凹槽阻碍磁铁滑动; 深雕或切割 外圈装饰线和“YES/NO/GOOD BYE”等大字,深度可达0.5-0.8mm,以增强视觉效果。使用较低的功率和较高的速度进行多次浅雕,比一次高功率深雕更能控制效果,避免木材过度碳化。

6.2 最终组装与校准

  1. 放置顶板 :将雕刻好的木板放入机箱,使其边缘落在之前安装的3D打印角撑上,板面与机箱上沿平齐。
  2. 安装磁铁 :将一块强磁铁放入X轴滑台上的磁铁座中。然后,将另一块磁铁放在木板顶面对应的位置,它们会立即吸合。这就是你的“幽灵占卜板”。
  3. 坐标系统校准 :这是 最重要的一步 。机械原点(0,0)可能并不对应木板上的某个特定点(比如左下角)。你需要运行一个校准脚本,让机器移动到你认为应该是字母‘A’的位置,然后记录下此时的坐标。用这个坐标去更新Python脚本中 coordinate_map 字典里所有坐标的偏移量。更专业的做法是,在GRBL中设置工作坐标系偏移( G10 L2 P1 X... Y... ),但修改Python字典对初学者更直观。
  4. 试运行 :运行 finalTextInput.py ,问一个简单的问题,比如“Hello”。观察占卜板移动路径是否正确。如果字母位置整体偏移,调整坐标偏移量。如果个别字母不准,单独微调其坐标。

7. 常见问题排查与优化心得

在多次构建和演示过程中,我遇到了各种各样的问题。这里总结一份速查表:

问题现象 可能原因 排查与解决思路
上电后电机不动,但有嗡嗡声 1. 驱动器电流(Vref)设置过低。
2. 电机线序接错。
3. GRBL未解锁(处于报警状态)。
1. 用万用表检查并调高Vref至0.7V左右。
2. 尝试交换同一组线圈的两根线(如A+与A-)。
3. 在串口发送 $X 命令解锁。
电机运动方向错误 GRBL中轴方向设置反了,或电机接线顺序全反。 修改GRBL参数 $3 (方向信号取反掩码)。例如,X轴反向则设置 $3=1 。或交换电机接线。
归零( $H )失败 1. 限位开关未触发或常开/常闭模式设置错误。
2. 归零方向错误。
3. 限位开关信号线接触不良。
1. 用万用表通断档检查开关触发时是否导通。检查GRBL参数 $5 (限位开关常开/常闭)。
2. 检查 $23 (归零方向)参数。
3. 重新焊接或插紧接线。
运动精度差,丢步 1. 同步带太松打滑,或太紧阻力大。
2. 电机电流(Vref)设置过低。
3. 运动速度或加速度( $110 / $111 / $120 / $121 )设置过高。
1. 重新调整同步带张力。
2. 适当调高Vref,同时触摸驱动器散热片,确保不过热。
3. 逐步降低最大速率和加速度参数测试。
占卜板移动不顺畅或抖动 1. 木板表面粗糙。
2. 上下磁铁未对准,产生侧向拉力。
3. 磁力过强,导致吸附太紧摩擦大。
1. 用细砂纸打磨木板表面,并涂抹蜡或使用光滑的亚克力板。
2. 仔细调整滑台磁铁座的位置,确保与板面磁铁垂直对准。
3. 可尝试换用稍弱一点的磁铁,或在磁铁与木板间增加一层薄垫片。
ChatGPT回复不遵守规则(如过长) 1. “越狱”提示词未生效或失效。
2. 模型上下文被重置。
1. 在每次用户提问后,都附加“最多3个词,优先幽默”的强化指令。
2. 检查ChatGPT wrapper的会话管理,确保是在同一个持续会话中交互。
串口通信突然中断 1. USB线接触不良或供电不稳。
2. Python脚本异常退出未关闭串口。
3. 电脑进入休眠状态。
1. 更换USB线,尝试连接电脑后置USB口。
2. 在Python脚本中添加异常处理,确保退出前关闭串口。
3. 关闭电脑的USB选择性暂停设置。

个人优化建议

  • 升级滑台设计 :第一版中,占卜板是单点磁吸,容易旋转。我正在设计V2版本,采用双磁铁座或一个带有轴承的万向节结构,让占卜板移动更稳定、更像被“无形之手”推动。
  • 加入视觉反馈 :在机箱内部安装一条可寻址LED灯带(如WS2812B),让灯光随着占卜板的移动而流动,或者用不同颜色表示“思考中”、“拼写中”等状态,极大增强演示效果。
  • 本地化语言模型 :依赖OpenAI API会有延迟和网络依赖。未来可以考虑在本地部署轻量化的开源大语言模型(如Llama 3.2的较小参数版本),通过树莓派等设备运行,实现完全离线的“通灵”体验,响应速度会快很多。
  • 安全第一 :强磁铁对心脏起搏器、机械手表等物品有风险。演示时务必告知观众,并妥善保管备用磁铁。机器运动时,确保手指和头发远离运动部件。

构建这个项目的乐趣,一半在于看到机械精密地执行代码,另一半在于观察人们与这个“AI灵体”互动时脸上那种混合着困惑、惊奇和欢笑的表情。它模糊了代码、机械和神秘学之间的界限,用一种可触摸的方式,让人直观地感受到人工智能不再是遥远的云端服务,而是可以驱动现实世界物体、与我们进行物理对话的存在。希望这份详细的指南能帮助你复现或启发属于你自己的AI硬件融合项目。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐