故障排查

东西不太对劲?按顺序一步步来,先搞清楚问题到底出在哪里。

东西不太对劲的时候,最快解决问题的办法不是急着去"修",而是先搞清楚问题到底出在哪:是板子本身、电脑上的软件,还是两者之间的连接。下面每一步都是建立在前一步的基础上,所以就算你大概猜到问题出在哪,也建议按顺序走一遍。

不知道从哪开始?

你看到的情况去看
灯完全不亮,没有任何反应第 1 步
颜色不对、闪烁,或者亮的 LED 不对第 3.5 步
灯亮着,但卡在错误的颜色上第 4 步
andon-light 命令本身就报错第 2 步
之前好好的,拔插一次之后就坏了第 1 步

第 1 步:板子在运行固件吗?

在终端里运行:

lsusb | grep -i "2e8a"
你看到的内容含义怎么办
2e8a:0003 Raspberry Pi RP2 Boot板子处于"引导加载"模式:这是专门用来烧录新固件的特殊模式,不是正常使用时的状态,这个模式下 LED 不会有反应。打开 Arduino IDE 点击上传:它会自动识别这个状态并完成烧录。
出现包含 Waveshare 或 RP2040 Zero 的一行很好:固件在正常运行。继续看第 2 步。
什么都没显示板子没插上,或者数据线不支持传数据。换一根 USB-C 线试试,确认插紧了。

也可以直接检查引导加载模式下出现的那个文件传输盘:

find /media /run/media /mnt -maxdepth 3 -iname "*RPI*" 2>/dev/null

如果打印出了路径,说明板子处于引导加载模式:解决办法同上。

第 2 步:电脑上的软件能看到板子吗?

andon-light doctor
你看到的内容含义
Found device on /dev/ttyACM0(或类似内容)软件能看到板子,权限也没问题。继续看第 3 步。
No device found板子没有在运行固件。回到第 1 步。
[Errno 13] Permission denied权限问题,仅出现在 Linux 上:参见下面的打开端口时提示权限被拒绝。

第 3 步:是不是有别的东西占着这个连接?

andon-light set idle
你看到的内容含义
没有任何输出,正常退出电脑和板子之间的连接是通的。如果 LED 还是没变化,去看第 3.5 步,或者试试重新烧录(第 1 步)。
andon-light: serial error: ... Device or resource busy有别的程序占着这个连接:几乎总是后台还开着的 Arduino IDE 串口监视器。关掉它再试一次。

如果不确定命令到底成功没有,直接看退出码:

andon-light set idle; echo "exit code: $?"

退出码是 0 就说明成功了。

第 3.5 步:闪烁、颜色不对,或者部分点亮看起来怪怪的

可寻址 LED 既需要数据信号的精确时序,也需要足够的供电。连接不稳定就可能导致看得见的异常,哪怕"技术上"其实是通的。

先排除一个不算问题的情况: 按设计,同一时间只会有 3 颗 LED 亮起(加上那颗常亮的状态灯)。看到大部分灯带是暗的、只有绿色那组亮着,这是正常现象。具体细节见 LED 的排列方式。下面要讲的问题不一样:是应该亮的那一组里面有 LED 不对,或者亮的样子完全不符合任何一种正常状态。

在成品电路板上,芯片和 LED 在同一块板子上,没有线缆可以检查,所以"信号问题"几乎总是意味着虚焊。在面包板上,通常是接线的问题。下面两种情况都会讲到。

你看到的情况可能的原因可以试试
该亮的那组里,有些 LED 暗着或者不对,其他的正常数据线连接不稳定:某处连接不牢,会导致后面的 LED 失去同步成品电路板: 检查芯片引脚有没有虚焊。面包板: 把信号线剪短一点,检查连接器压接是否牢固,或者加一个物料清单里可选的电平转换器。
颜色偏暗、颜色不对,或者灯一亮板子就像重启了一样供给 LED 的电不够成品电路板: 确认 USB-C 线既能传数据又能供电,检查电源部分有没有虚焊。面包板: 确认 V 接的是 5V 而不是 3V3:见组装指南。
完全不亮(连第 1 颗都不亮)但 andon-light set idle 执行成功固件预期的数据引脚和实际接线对不上成品电路板: 确认 kDataPin 和板子设计的走线一致:默认应该是 GPIO1。面包板: 检查你接的那根引脚是不是和 kDataPin 一致。如果第 1 颗 LED 能亮,但 2-10 号完全没反应,那是第 3 步的问题,不是这里。
亮的颜色对不上该亮的 LED(比如"工作中"点亮了不该亮的那组)LED 灯带是从错误的一端接入数据的成品电路板: 这种情况一般说明板子设计或生产有问题:先和一块正常工作的板子对比看看。面包板: 检查灯带上哪一端印着是数据输入端,确认 S 接的是那一端。

如果还是没解决,确认 Arduino IDE 里确实装了 Adafruit NeoPixel 库(工具 → 管理库 → 搜索 "Adafruit NeoPixel")。库没装通常会报编译错误,而不是上面这些症状,但还是值得排查一下。

第 4 步:Claude Code 的 hook 设置对吗?

cat ~/.claude/settings.json

按下面的清单逐项检查:

  • 是合法的 JSON 吗? 运行:

    python3 -c "import json, os; json.load(open(os.path.expanduser('~/.claude/settings.json'))); print('VALID JSON')"

    如果报错,说明文件里某处有个小的语法错误(通常是漏了逗号或括号)。在修好之前,Claude Code 很可能会直接忽略整个 hooks 配置。

  • 每条 hook 命令是不是都以 || true 结尾? 如果没有,任何小问题(比如板子被拔掉了)都会在 Claude Code 里以显眼的错误形式冒出来。这和"安静地待在后台"的状态灯设计初衷不符。有一点要注意:Claude Code 自己的 hook 日志有时会显示"执行成功",即使背后真正调用的 andon-light 其实失败了:如果怀疑是这种情况,把 || true 去掉直接运行命令,看看真实的退出码。

  • hook 命令是不是没有标记 "async": true? 异步执行可能导致命令完成的顺序被打乱,让灯卡在一个过时的颜色上。

  • 编辑完这个文件之后,重启 Claude Code 了吗? hook 配置只在会话开始时读取:已经在运行的会话不会感知到配置变化。这是"改了却没反应"最常见的原因。

第 5 步:手动试一遍

这个方法能帮你分清楚问题是出在"灯和 CLI 这边",还是"Claude Code 的 hook 这边"。自己手动运行一遍 hook 会执行的那些命令:

andon-light set working    # LED 2-4 常亮绿色(除 1 号外其余熄灭)
andon-light set waiting    # LED 5-7 常亮黄色(除 1 号外其余熄灭)
andon-light set idle       # LED 8-10 常亮红色(除 1 号外其余熄灭)
andon-light set compacting # LED 2-10 依次点亮模式

如果这四条手动执行都正常,但实际 Claude Code 会话中灯没有反应,问题出在 hook 设置(第 4 步),或者 Claude Code 还没读到最新的配置(试试重启它)。不是硬件或 CLI 的问题。

Linux 专属说明

打开端口时提示权限被拒绝

ls -la /dev/ttyACM0

看一下分组那一列:应该显示 dialout。

用 id 检查,不要用 groups $USER。 这两个命令给出的答案可能不一样,而真正反映"正在运行的程序实际拥有什么权限"的是 id。

id

这里有个不太直观的地方:不带参数的 id 显示的是当前这个终端实际拥有的分组权限,这正是 andon-light 打开端口时系统会检查的东西。而 groups $USER 每次都是重新查一遍账号本身的设置,跟当前有没有程序在运行没关系。所以可能出现这种情况:groups $USER 显示已经有 dialout 了,但包括新开的终端在内,所有终端的 id 里都还没有。因为分组权限是在会话最初启动的那一刻就定下来的,单纯在桌面环境里登出重登一次,并不能保证让所有进程都刷新这个状态。

如果 id 里没有 dialout:

解决办法有效范围命令
马上能用仅当前终端newgrp dialout
彻底解决所有程序,保证生效sudo reboot
临时应急每次拔插都要重新执行sudo chmod 666 /dev/ttyACM0

从终端启动 Arduino IDE 失败

Arduino IDE 的 AppImage 有时会因为 FUSE 相关的错误(dlopen(): error loading libfuse.so.2 或 Cannot mount AppImage)启动失败。如果双击打不开,可以试试从终端启动,能完全绕开 FUSE 挂载这一步:

cd ~/Downloads
./arduino-ide_2.3.10_Linux_64bit.AppImage --appimage-extract-and-run

(文件名根据你下载的具体版本调整。)解压启动需要几秒钟,之前打开的项目和标签页应该会自动恢复。

一切正常时应该是什么样子

$ lsusb | grep 2e8a
Bus 005 Device 010: ID 2e8a:0003 Raspberry Pi RP2 Boot      # 这一行代表引导加载模式(如果不是刚烧录完看到这个,要留意)

# 固件正常运行时,lsusb 不会单独显示"RP2 Boot"这一行。
# 改用 udevadm 检查:
$ udevadm info -a -n /dev/ttyACM0 | grep -iE "manufacturer|product"
ATTRS{manufacturer}=="Waveshare"
ATTRS{product}=="RP2040 Zero"

$ andon-light doctor
Found device on /dev/ttyACM0

$ andon-light set working; echo "exit=$?"
exit=0

Windows 专属说明

"Windows 已保护你的电脑"警告

安装程序和这个工具本身都没有数字签名,所以不管运行哪一个,Windows 第一次都会弹出这个警告,某些杀毒软件也可能会报警。

这是这类小型未签名工具打包方式的副作用,恰好和某些恶意软件的行为有点像。这不代表任何东西坏了。

要继续运行: 点"更多信息",然后点"仍要运行"。

装完之后找不到 andon-light

打开一个新的终端窗口(安装之前就开着的终端不会感知到更新后的 PATH)。

卸载之后 PATH 里还留着东西

如果你装的是修复这个问题之前的旧版本,它的卸载程序可能不会清理掉自己加的那条 PATH。手动检查方法:系统属性 → 环境变量 → Path(用户变量)→ 看看有没有残留的 AndonLight 条目,有的话删掉。

为什么电脑上的软件完全不需要知道 LED 硬件长什么样

命令行工具只是把每种状态映射成一个字符(工作中是 G,等待是 Y,以此类推),然后把这一个字符发到找到的那个端口上。它根本不知道另一端接了几颗 LED、怎么接的,甚至不知道那是不是可寻址 LED:所有这些逻辑完全在固件里处理,在 USB 连接的另一端。这也是为什么设备的自动识别不管接的是哪个版本的 LED 硬件都一样好用:它认的是单片机本身,不是后面接的东西。