
1. 这个项目到底在做什么StackChan、NFC 与 AI 的边界1.1 StackChan 是什么如果你之前没有接触过 StackChan可以先把它理解成一个摆在你桌面上、大概 20 厘米高度的迷你机器人伙伴。它通常由 3D 打印外壳、树莓派 Zero 或 ESP32 主控、若干舵机、麦克风、扬声器和摄像头组成。头部可以左右转动身体可以轻微摇摆看起来就像一个小型“桌宠”。StackChan 是一个开源项目社区中很多玩家会自己打印外壳、接线、写程序再把它接入语音助手、大语言模型或者其他智能服务实现语音聊天、表情显示、动作交互等功能。在我的实际使用体验中StackChan 最大的价值不是“做一个玩具”而是它提供了一个非常友好的硬件扩展平台。你可以把各种传感器、屏幕、舵机、通信模块叠加到现有结构上。本文要讲的“NFC 智能换装”就是其中一个不错的扩展方向给机器人增加 NFC 读卡能力让它可以识别不同的标签再借助 AI 能力自动匹配对应的配饰或外观模式。1.2 NFC 在“换装”场景中的定位NFCNear Field Communication近场通信是一种短距离高频无线通信技术工作频率通常是 13.56 MHz有效通信距离大概在 4 厘米以内。我们在门禁卡、公交卡、手机支付、电子标签等场景中经常用到它。对开发者来说NFC 更像是一个“触达触发口”只要把卡片或贴纸靠近读卡器系统就会在极短时间内读到卡片 UID、存储文本或 NDEF 数据。在 StackChan 换装场景中NFC 的作用非常明确它是一个物理触发开关。用户不需要通过键盘输入指令也不需要打开手机 App只需要把一枚贴了 NFC 标签的道具靠近机器人身体上的读卡器机器人就能感知到“用户想切换配饰”。相比按钮、App 遥控这些方案NFC 的好处是触发方式自然贴近实体交互。每张卡片或贴纸可以写入不同的内容。可以复用市面上常见的 NTag215、Mifare Classic 等标签。读卡模块体积小方便隐藏在机器人外壳里。这里需要说明一下正常情况下我们讨论 NFC 开发是指读写自己购买的、合法的空白标签或者在获得设备授权的前提下做个人实验。不能把 NFC 技术用于复制门禁卡、读取他人卡片信息、绕过安全认证等场景。本文所有示例都是基于“自己制作标签、自己控制读卡器”的合法前提。1.3 AI 如何参与“自动匹配”既然已经有了一枚 NFC 标签为什么还要引入 AI最简单的做法是每张标签存一个编号系统查询编号并把对应的配饰配置读取出来。但这样做缺少一点“智能感”而且可扩展性不够高。引入 AI 后交互方式会变成这样用户在 NFC 标签里写入一段自然语言描述比如“我想变成夜行忍者”“戴上魔法帽进入法师模式”“切换成西部牛仔风格”。机器人读到这段文本后把文本发给大语言模型接口。大语言模型结合本地的配饰清单解析出用户意图返回一个结构化的配饰配置 JSON。机器人根据 JSON 控制舵机做出动作、切换 LED 颜色、通过语音播报结果。这样做的好处是不需要预先为每张标签固定绑定某一种配饰。标签只是触发入口真正的“匹配决策”由 AI 完成。即使未来你新增了大量配饰也不用重新写标签只需要更新配饰库和 Prompt 描述即可。2. 硬件选型与整体架构设计2.1 硬件清单首先是主控。如果你使用的是官方或社区常见的 StackChan 方案主控一般是树莓派 Zero 2 W 或树莓派 4B。树莓派的好处是 Python 生态完善可以直接使用大量的 GPIO 库、NFC 库和网络库。如果你手上是 ESP32也可以做类似实现但代码会偏向 C 或 MicroPython本文以树莓派 Python 为例讲解。然后是 NFC 读卡模块。比较常见的有两款RC522基于 MFRC522 芯片使用 SPI 接口价格便宜适合学习。PN532支持 I2C / SPI / UART 三种接口功能更强也能在树莓派上通过 libnfc 使用。如果只是做“读标签文本 写标签”的基础功能RC522 足够用了。我建议新手从 RC522 开始等熟悉接线和协议后再切换到 PN532 做更复杂的 NFC 开发。本文示例以 RC522 SPI 接口为例但代码思路也适用于 PN532。除了主控和 NFC 模块还需要以下硬件StackChan 3D 打印外壳与舵机支架。2 到 4 个舵机通常用于控制头部左右转动、点头和身体摆动。PCA9685 舵机驱动板方便通过 I2C 同时控制多个舵机。一枚或多个空白 NFC 标签或卡片建议选择 NTag215容量足够写入描述文本。LED 灯或 RGB 灯珠用于展示配饰颜色。麦克风与扬声器用于语音交互播报。若干杜邦线、面包板和电源模块。2.2 软件与开发环境软件层面树莓派建议使用 Raspberry Pi OS64 位作为操作系统。需要提前安装 Python 3.9并且开启 SPI 和 I2C 接口。你可以在终端执行以下命令进入树莓派配置界面开启这些接口sudo raspi-config在Interface Options菜单中分别打开 SPI 和 I2C。开启后重启系统。后续需要安装的 Python 库主要有mfrc522用于 RC522 读写器控制。adafruit-circuitpython-servokit用于 PCA9685 舵机驱动板控制。requests用于调用大语言模型接口。python-dotenv用于管理环境变量和 API Key。安装命令如下pip install mfrc522 adafruit-circuitpython-servokit requests python-dotenv不同版本的树莓派内核和 Python 环境可能会对依赖版本有影响如果你在执行时遇到版本冲突可以根据报错信息单独安装指定版本。这里给你一个原则不要盲目升级所有库优先保证mfrc522和adafruit-circuitpython-servokit能正常导入即可。2.3 系统架构拆解整个系统可以拆成三层感知层NFC 读卡器负责读取标签中的文本内容这是整个交互的触发入口。决策层本地的 FastAPI 小服务或者脚本通过 HTTP 调用大语言模型接口将 NFC 文本输入给模型模型返回配饰 JSON。执行层树莓派根据 JSON 控制舵机、LED 和语音模块完成“换装”动作。这三层之间通过 Python 函数调用或 HTTP 请求衔接。为了便于后续扩展我在项目里会把 NFC 读取、AI 匹配、舵机控制分别封装成独立模块。每个模块只负责一件事这样以后想替换 AI 服务、更换舵机驱动方式都只需要修改对应模块不需要重写整个项目。3. 让 StackChan 具备 NFC 读取能力3.1 NFC 模块接线RC522 一共有 8 个引脚在树莓派上通过 SPI 与主控通信。建议按照下面的表格接线RC522 引脚树莓派引脚SDAGPIO8 (CE0)SCKGPIO11 (SCLK)MOSIGPIO10 (MOSI)MISOGPIO9 (MISO)IRQ不接GNDGNDRSTGPIO253.3V3.3V接线时需要注意RC522 必须使用 3.3V 供电不能接 5V否则可能烧坏模块。RST 引脚可以选择任意空闲 GPIO本文以 GPIO25 为例你也可以根据实际布局调整为其他引脚。连接好之后可以先用一个最简单的代码验证模块是否被系统识别。3.2 安装依赖库前面已经给出了安装命令这里再做一次说明。mfrc522库会依赖spidev和RPi.GPIO如果你在纯净系统上安装失败可以先手动安装sudo apt update sudo apt install python3-pip python3-dev sudo pip install spidev RPi.GPIO mfrc522安装完成后可以先写一个短小的脚本测试模块能否读到卡片 UID。需要注意的是读取时卡片要贴近模块线圈距离太远会无法识别。3.3 编写 NFC 标签读取程序下面创建一个nfc_reader.py文件用来封装读取 NFC 标签的功能。核心逻辑很简单实例化SimpleMFRC522调用read()阻塞等待卡片靠近函数返回卡片 UID 和存储文本。# 文件路径project/nfc_reader.py from mfrc522 import SimpleMFRC522 class NFCReader: def __init__(self): self.reader SimpleMFRC522() def read(self): 阻塞读取一张 NFC 标签。 返回值为 (uid, text)。 uid: 标签唯一标识。 text: 标签内写入的文本内容。 uid, text self.reader.read() return uid, text.strip() def write(self, text): 向一张空白 NFC 标签写入文本。 注意这个操作会覆盖标签中原有的内容。 self.reader.write(text)SimpleMFRC522的read()方法会一直等待直到检测到一张卡片靠近。在 StackChan 场景中这相当于一个阻塞式的触发点。你也可以把读取逻辑放进线程避免阻塞主程序的舵机控制。不过为了演示简单我们先用同步方式。3.4 编写写标签工具你可能需要先给标签写入内容才能让机器人读到文本。这里创建一个独立的写标签脚本# 文件路径project/write_tag.py from nfc_reader import NFCReader def main(): reader NFCReader() text input(请输入要写入 NFC 标签的文本内容) print(请将空白 NFC 标签靠近读卡器...) reader.write(text) print(写入完成) if __name__ __main__: main()运行这个脚本后在终端输入“我想变成夜行忍者”然后把标签贴近读卡器等待写入完成。4. 设计配饰数据与 NFC 标签编码4.1 配饰数据模型为了让 AI 能够“理解”有哪些配饰可用我们需要在项目里维护一个配饰清单。这个清单可以是 JSON 文件也可以是 Python 字典。每个配饰建议包含以下字段id配饰唯一标识。name配饰显示名称。category配饰分类例如“头饰”“手持道具”“披风”。keywords关键词列表用于辅助 AI 判断。motion匹配成功后机器人的动作配置。led_color匹配成功后 LED 灯的颜色。下面是一个示例配饰库{ accessories: [ { id: ninja_hood, name: 忍者头巾, category: 头饰, keywords: [忍者, 夜行, 刺客, ninja], motion: nod, led_color: #2C3E50 }, { id: wizard_hat, name: 魔法帽, category: 头饰, keywords: [魔法, 法师, 巫师, wizard], motion: bow, led_color: #8E44AD }, { id: cowboy_hat, name: 牛仔帽, category: 头饰, keywords: [牛仔, 西部, cowboy], motion: swing, led_color: #D35400 } ] }4.2 NFC 标签文本设计NFC 标签中的文本不需要很复杂它可以是一句自然语言描述。比如“我想变成夜行忍者”“戴上魔法帽进入法师模式”“切换成西部牛仔风格”AI 会从这句话中提取关键词然后与配饰库中的keywords字段做语义匹配选出最合适的配饰配置。如果你的标签容量很小也可以只写入“忍者”“魔法帽”这类短词效果类似但对语义识别的宽容度会稍低一些。4.3 从标签读出的原始数据当用户把写好的标签贴近机器人时NFCReader.read()会返回类似下面的数据UID: 123456789 TEXT: 我想变成夜行忍者其中 UID 是卡片的物理唯一标识不同厂家、不同批次的卡片 UID 格式会不同。我们主要关注 TEXT 字段它会作为 AI 匹配的输入。5. AI 自动匹配服务实现5.1 AI 服务选择与调用方式AI 匹配服务可以选用云端大模型接口也可以选择本地部署的私有化模型。国内开发者通常会使用兼容 OpenAI 接口的服务这样代码结构统一。选择模型时要注意阅读服务提供方的使用条款不要将个人数据发送到未授权的第三方。本文不绑定某一个具体模型品牌示例代码使用 OpenAI 兼容接口格式。你需要准备一个api_key和模型名称并且建议通过.env环境变量管理不要把密钥硬编码在代码里。下面创建.env文件# 文件路径project/.env MODEL_API_KEYyour_api_key_here MODEL_BASE_URLhttps://api.example.com/v1 MODEL_NAMEyour-model-name5.2 编写 AI 匹配模块接下来创建ai_matcher.py这个模块负责与模型接口通信。为了让 AI 稳定输出 JSON我们在 Prompt 中明确要求它只返回 JSON不输出多余解释。# 文件路径project/ai_matcher.py import json import os import requests from dotenv import load_dotenv load_dotenv() API_KEY os.getenv(MODEL_API_KEY) BASE_URL os.getenv(MODEL_BASE_URL) MODEL_NAME os.getenv(MODEL_NAME) class AIMatcher: def __init__(self, accessory_library): self.accessory_library accessory_library def match(self, text): 将 NFC 标签文本发送给大语言模型。 返回解析后的配饰配置字典。 prompt self._build_prompt(text) try: response requests.post( f{BASE_URL}/chat/completions, headers{ Authorization: fBearer {API_KEY}, Content-Type: application/json, }, json{ model: MODEL_NAME, messages: [ {role: system, content: 你是一个智能配饰匹配助手。}, {role: user, content: prompt}, ], temperature: 0.2, }, timeout30, ) response.raise_for_status() data response.json() content data[choices][0][message][content] return self._parse_json(content) except Exception as e: print(f[AI Matcher] 请求失败: {e}) return None def _build_prompt(self, text): accessory_json json.dumps(self.accessory_library, ensure_asciiFalse) return ( 用户通过 NFC 标签输入了一段文本请结合配饰库选择最合适的配饰。\n f配饰库{accessory_json}\n f用户文本{text}\n 请只返回 JSON格式为 {id: 配饰id, name: 配饰名称, reason: 匹配理由} ) def _parse_json(self, content): try: return json.loads(content) except json.JSONDecodeError: # 某些模型会在 JSON 外包一层 json ... 这里做简单清理 cleaned content.strip() if cleaned.startswith(): cleaned cleaned.split(\n, 1)[1] cleaned cleaned.rsplit(, 1)[0] return json.loads(cleaned)5.3 返回格式校验与容错大模型返回内容最大的不确定点是格式。即使 Prompt 里明确要求只返回 JSON也可能出现多余的说明文字。因此在_parse_json中我们做了两重处理先尝试直接json.loads。如果失败尝试去掉 Markdown 代码块标记后再解析。另外建议在实际项目中增加一个校验步骤确认返回结果中的id确实存在于配饰库中。如果模型返回了一个不存在的配饰 id就直接返回默认配饰避免程序崩溃。6. StackChan 控制联动与换装效果6.1 舵机动作控制StackChan 通常使用 2 到 4 个舵机。这里以 PCA9685 舵机驱动板为例创建一个stackchan_control.py模块。它需要支持基本的点头、摇头、摆动动作。# 文件路径project/stackchan_control.py from adafruit_servokit import ServoKit import time class StackChanController: def __init__(self, channels16): self.kit ServoKit(channelschannels) # 假设舵机 0 控制头部左右舵机 1 控制头部上下舵机 2 控制身体左右 self.head_pan_channel 0 self.head_tilt_channel 1 self.body_pan_channel 2 def reset(self): self.kit.servo[self.head_pan_channel].angle 90 self.kit.servo[self.head_tilt_channel].angle 90 self.kit.servo[self.body_pan_channel].angle 90 def nod(self): self.kit.servo[self.head_tilt_channel].angle 70 time.sleep(0.3) self.kit.servo[self.head_tilt_channel].angle 110 time.sleep(0.3) self.kit.servo[self.head_tilt_channel].angle 90 time.sleep(0.2) def bow(self): self.kit.servo[self.head_tilt_channel].angle 140 time.sleep(0.5) self.kit.servo[self.head_tilt_channel].angle 90 time.sleep(0.3) def swing(self): for angle in [70, 110, 70, 110, 90]: self.kit.servo[self.body_pan_channel].angle angle time.sleep(0.2)舵机角度范围会根据你的舵机型号和机械结构而变化。这里的角度只是示例实际项目中你需要手动测试并调整防止舵机堵转损坏。6.2 状态显示与语音播报匹配完成后机器人最好能通过 LED 颜色或语音反馈结果。下面创建一个简单的灯光和语音模块# 文件路径project/feedback.py import subprocess class Feedback: def set_led(self, hex_color): 将 RGB LED 设置为指定颜色。 这里以控制树莓派 GPIO 外接 RGB LED 为例具体引脚按实际接线调整。 print(f[LED] 颜色已切换为 {hex_color}) def speak(self, message): 使用系统 TTS 能力播报消息。 树莓派上可以使用 espeak 或其它 TTS 引擎。 print(f[语音] {message}) subprocess.run([espeak, message])这里没有绑定具体的 LED 驱动库因为不同接线方式差异较大。你可以根据自己使用的 LED 类型替换为RPi.GPIO、board库或 WS2812 灯带库。6.3 整合为一个 main.py现在把 NFC 读取、AI 匹配和 StackChan 控制串联起来。主循环的逻辑是初始化各模块。等待 NFC 卡片靠近。读取标签文本。调用 AI 匹配配饰。根据返回结果执行动作、切换 LED、语音播报。回到等待状态。# 文件路径project/main.py import json import time from nfc_reader import NFCReader from ai_matcher import AIMatcher from stackchan_control import StackChanController from feedback import Feedback def load_accessory_library(pathaccessories.json): with open(path, r, encodingutf-8) as f: return json.load(f) def apply_outfit(controller, feedback, outfit): motion outfit.get(motion, nod) led outfit.get(led_color, #FFFFFF) if hasattr(controller, motion): getattr(controller, motion)() feedback.set_led(led) feedback.speak(f已切换为{outfit.get(name, 未知配饰)}模式) def main(): library load_accessory_library() reader NFCReader() matcher AIMatcher(library) controller StackChanController() feedback Feedback() controller.reset() print( StackChan NFC 智能换装系统已启动 ) while True: try: print(等待 NFC 标签靠近...) uid, text reader.read() print(f读取到标签 UID: {uid}, 内容: {text}) matched matcher.match(text) if not matched: print(AI 匹配失败请检查模型服务或网络) continue outfit_id matched.get(id) if not any(item[id] outfit_id for item in library[accessories]): print(f配饰 {outfit_id} 不存在使用默认动作) matched {id: default, name: 默认, motion: nod, led_color: #FFFFFF} print(fAI 匹配结果: {matched}) apply_outfit(controller, feedback, matched) except KeyboardInterrupt: print(系统退出) break except Exception as e: print(f发生异常: {e}) time.sleep(1) if __name__ __main__: main()7. 完整实战演示7.1 启动流程在这个章节我会把整个项目的运行流程串联起来让你知道每一步应该在什么时候执行。首先创建项目目录并整理文件。一个建议的项目结构如下stackchan-nfc-outfit/ ├── .env ├── accessories.json ├── nfc_reader.py ├── write_tag.py ├── ai_matcher.py ├── stackchan_control.py ├── feedback.py └── main.py确认所有文件就绪后先运行写标签工具把标签写入一段自然语言描述python write_tag.py然后启动主程序python main.py如果你已经安装了espeak和其他依赖系统会输出类似下面的日志 StackChan NFC 智能换装系统已启动 等待 NFC 标签靠近... 读取到标签 UID: 123456789, 内容: 我想变成夜行忍者 AI 匹配结果: {id: ninja_hood, name: 忍者头巾, reason: 用户提到忍者} [LED] 颜色已切换为 #2C3E50 [语音] 已切换为忍者头巾模式7.2 预期运行效果当用户把写有“我想变成夜行忍者”的 NFC 标签靠近机器人身体上的读卡器模块时StackChan 会在 2 秒内完成以下动作舵机执行“点头”动作代表它已经收到指令。LED 灯变成深灰色体现忍者主题。语音模块播报“已切换为忍者头巾模式”。如果用户换成另一张写着“戴上魔法帽进入法师模式”的标签AI 会匹配到wizard_hat机器人做出“鞠躬”动作LED 变成紫色语音播报对应内容。7.3 演示中的关键日志说明日志是整个系统的排错核心。我建议在你的代码中保留类似上面的打印信息尤其是 AI 匹配结果它可以帮助你快速判断是 NFC 读取失败、AI 请求失败还是舵机执行失败。在真实项目中不要在生产环境直接使用print输出日志。建议改用logging标准库将日志同时输出到控制台和文件方便回溯问题。8. 常见问题与排查思路8.1 NFC 模块无法识别问题现象常见原因解决思路执行NFCReader时报错说不存在模块未安装mfrc522或依赖库重新执行pip install mfrc522 spidev RPi.GPIO读卡时一直卡住没有任何提示读卡器接线不正确或供电不足检查 SDA、SCK、MOSI、MISO 接线确认使用 3.3V 供电模块发热且读不到卡接了 5V 电源断电后重新按表格接线避免损坏模块如果换用 PN532需要额外检查接口模式I2C 还是 SPI。PN532 的板载拨码开关必须和代码一致否则通信会失败。8.2 读到的 UID 不稳定某些低价 RC522 模块在弱供电环境下会出现 UID 读取不稳定。排查思路是检查 3.3V 与 GND 是否连接可靠。尝试缩短 SPI 数据线的长度杜邦线长度建议控制在 20 厘米以内。在 RC522 的 3.3V 与 GND 之间并联一个 10uF 电解电容帮助稳定供电。8.3 AI 返回 JSON 格式错误大语言模型返回不稳定是常见情况。你可以通过下面几个方式降低出错概率在 Prompt 中给出严格的 JSON 格式示例。将temperature调低到 0.2 以下。在代码中对返回内容做二次清理。如果模型始终输出额外文本考虑使用支持函数调用或返回结构化输出的模型服务。8.4 舵机响应抖动如果你发现舵机在转动过程中抖动或者卡在某个角度发出“嗡嗡”声大概率是以下原因PCA9685 舵机驱动板的电源功率不足。舵机堵转角度超过机械限位。舵机频率与型号不匹配。建议使用独立的 5V 电源给舵机供电并且把舵机驱动的 GND 与主控 GND 连接在一起形成共地。测试动作时角度变化幅度不要太大先用小范围角度验证。9. 最佳实践与工程建议9.1 NFC 标签与硬件安全在做 NFC 开发时有一点必须强调所有读写实验都要在自己购买、拥有控制权的标签和设备上进行。不要尝试复制门禁卡、读取他人卡片、破解或绕过任何安全认证系统这是不合法且存在风险的行为。从工程角度来说NFC 标签的选型也很重要。如果标签贴纸贴在金属表面读卡距离会明显缩短因为金属会吸收部分射频能量。这种情况下可以选择带有铁氧体隔离层的 NFC 标签贴纸或者调整读卡器位置避免贴纸正对金属壳。另外读卡器模块应该固定在机器人外壳内部尽量避开电机、舵机排线和大块金属物体减少电磁干扰。走线时注意不要把 GPIO 排线扎成与电源线并行的长线否则可能出现 SPI 通信异常。9.2 AI Prompt 与模型选择AI 匹配服务的稳定性很大程度上取决于 Prompt 设计。一个清晰的 Prompt 应当包含角色设定告诉模型它是“智能配饰匹配助手”。可用的配饰清单模型无法凭空知道你有哪些配饰。输入文本用户到底说了什么。输出格式要求返回 JSON 结构。尽量把配饰库放在 Prompt 中而不是让模型自行发挥。配饰库如果很长可以先在本地做一次关键词粗筛再把候选结果传给 AI这样既能降低 Token 消耗也能提高匹配准确率。关于模型选择建议优先使用你业务环境允许的私有化模型或经过授权的商用模型。涉及个人信息和自定义数据时不要轻易发送到不受信任的第三方服务。如果项目只是学习用途使用常见大模型 API 即可如果用于商业产品务必确认数据安全边界和成本。9.3 生产环境下的稳定性如果想把这套方案从 demo 变成稳定运行的小产品有几点值得注意。第一NFC 读取是阻塞式的在主循环里直接执行reader.read()会导致其他任务被卡住。生产环境建议使用独立线程或异步方式处理 NFC 读取读取结果通过队列传给主业务线程。第二AI 请求可能超时或失败系统必须具备降级策略。当 AI 服务不可用时可以回退到基于关键词的本地匹配保证机器人在离线状态下也有基本响应。我的建议是维护一个简单的本地关键词映射表AI 成功时用 AI 结果AI 失败时用本地结果。第三舵机动作要配置限位保护。不同舵机、不同机械结构的活动范围不同不要直接写死极限角度。可以把每个动作的最小角度、最大角度、速度抽成配置项便于后期调整。还要在代码里记录当前舵机状态防止多个动作并发执行时互相打架。第四日志和监控不能少。建议记录每一次 NFC 读取记录、AI 匹配耗时、匹配结果、舵机执行状态。这些数据不仅用于排错也能帮助你优化 Prompt 和动作参数。10. 总结与扩展方向到这里你已经完成了 StackChan NFC AI 的“智能换装”最小闭环系统。从 NFC 标签读取文本到大语言模型解析用户意图再到舵机执行动作和语音反馈整个链路并不复杂但它展示了硬件交互与 AI 能力结合的典型方式。后续你可以从这几个方向继续扩展把 AI 匹配服务改造成 FastAPI 接口让机器人状态和配饰配置可以远程查看。增加表情屏幕通过 OLED 或 LCD 显示配饰对应的图案。在配饰库中加入音频素材切换配饰时播放对应背景音效。将多张 NFC 标签组合使用比如一张标签代表“忍者”另一张代表“红色”组成组合配饰。接入更强大的语音模型让机器人不仅能识别配饰意图还能主动和用户聊天。如果你在实际复现中遇到了问题建议先缩小排查范围单独测试 NFC 读取单独测试 AI 接口单独测试舵机动作确认每个环节没有问题后再组合运行。硬件调试最忌讳的就是多个模块一起报错时同时改动多个地方这样很难定位根因。把握好“读写自有标签、使用授权接口、控制合法边界”这几个原则这套方案还可以延伸到很多有趣的桌面机器人应用场景。如果本文对你有帮助可以收藏备用后续我也准备再写一篇关于 StackChan 接入语音模型和表情屏幕的实现笔记届时可以继续关注。