这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 板卡试用 » 【ARDUINOUNOQ4GBRAM32GBEMMC】在ArduinoUNOQ上

共2条 1/1 1 跳转至

【ARDUINOUNOQ4GBRAM32GBEMMC】在ArduinoUNOQ上搭个AI嘴替,让元宝帮你控制openclaw点亮LED矩阵

助工
2026-06-28 18:54:38   被打赏 50 分(兑奖)     打赏

 技术分享:在ArduinoUNOQ上搭个AI嘴替,让元宝帮你控制openclaw点亮LED矩阵

最近在Arduino Uno Q上面部署了openclaw,并接入了元宝,实现了在元宝中,通过对话来进行AI编程,并成功驱动LED点阵。这篇文档就给大家分享这次的经验。


一、故事背景

最近拿到一块 Arduino UNO Q——这玩意儿不是普通 Arduino,它内部是一颗 Linux Debian 13(高通 QRB2210)+ 一颗 STM32U585(Zephyr RTOS),板载 13×8 灰度 LED 矩阵。

我想搞的事情是:在微信上(元宝)说一句"显示 你好世界",板子就立刻滚出这行字,不用烧录、不用重启 app

走完一遍下来发现路径比想象顺,于是把它写成一份完整复盘:怎么把 AI Agent 装上 Uno Q、怎么让 Agent 用元宝对话、怎么给 Agent 编 skill 让它能驱动 LED 矩阵,最后顺手把家里另一块 Arduino UNO R4 WiFi 的板载矩阵也接进来。


二、第一步:在 Uno Q 上装 OpenClaw

2.1 板子情况

Uno Q 是双核异构板:

  • Linux 侧:Debian 13,arduino@my-uno-q,跑系统服务

  • MCU 侧:STM32U585 (Zephyr RTOS),管 LED 矩阵 + 通讯

  • 桥接:两核之间用 RouterBridge(MsgPack RPC over /dev/ttyHS1 @ 115200),不是裸串口——这一点很重要,后面写 sketch 的人会踩坑

2.2 装 OpenClaw

Uno Q 的 Linux 侧可以直接 apt,但我推荐用 npm(更可控、升级快):

# 装 node 22+(板子一般预装)
node -v  # 应该 ≥ 22

# 全局装 OpenClaw CLI
npm i -g openclaw@latest
# 或 pnpm(推荐)
npm i -g pnpm
pnpm i -g openclaw@latest

# 验证
openclaw --version
# OpenClaw 2026.6.1 (xxx)

# 起 gateway(系统服务方式,开机自启)
openclaw gateway install   # 注册 systemd user 服务
openclaw gateway start
openclaw gateway status
# Gateway: bind=loopback (127.0.0.1), port=18789
# Runtime: running (pid xxx, state active)

装完之后你会得到:

  • CLI: /home/arduino/.npm-global/bin/openclaw

  • 配置:~/.openclaw/openclaw.json

  • Gateway 监听 127.0.0.1:18789

  • WebUI: http://127.0.0.1:18789/

 小坑:loopback 模式只允许本机访问。如果你要从另一台机器控制 Uno Q,开 tailscale 或者把 gateway.bind 改成 0.0.0.0(注意改 auth)。

2.3 给 Agent 一个工作目录

OpenClaw 是基于 workspace 的 Agent。每个 Agent 启动时加载一个工作目录里的 markdown 当人设/记忆。我用的是默认 /home/arduino/.openclaw/workspace,里面几个关键文件:

workspace/
├── AGENTS.md          # Agent 行为准则("对你的人类好"那种)
├── SOUL.md            # 人设(我是"阿Q",俏皮嘴贫)
├── IDENTITY.md        # 我叫什么、长啥样
├── USER.md            # 我的人类是谁
├── TOOLS.md           # 本地笔记(板子型号、路径、偏好)
├── HEARTBEAT.md       # 心跳检查清单(默认空)
├── MEMORY.md          # 长期记忆(主会话才加载)
└── memory/            # 每日笔记 (memory/YYYY-MM-DD.md)

这一套设计很贴心——主会话会加载 MEMORY.md,群聊/陌生人会话不会,天然防泄漏。


三、第二步:把 Agent 对接到腾讯元宝

OpenClaw 原生支持很多 IM(Signal/Telegram/Discord/WhatsApp…),元宝(Tencent Yuanbao)走 plugin 接入。

3.1 装元宝插件

openclaw plugins install openclaw-plugin-yuanbao

3.2 拿到 appKey / appSecret

到腾讯元宝开放平台(yuanbao.tencent.com 开发者后台):

  1. 创建一个机器人,得到 appKey 和 appSecret

  2. 记下来,配置一次就好

3.3 写到 openclaw.json

{
  "plugins": {
    "entries": {
      "openclaw-plugin-yuanbao": { "enabled": true }
    }
  },
  "channels": {
    "yuanbao": {
      "appKey": "dPTE87AVZ0GRNWsuFmeKAUGZ66kZIXbQ",
      "appSecret": "***",
      "name": "阿Q",
      "enabled": true
    }
  }
}

安全提示:appKey 和 appSecret 等同于密码,提交到 git 前记得脱敏(我那份用了 demo 占位符,别直接用我的)。

3.4 重启 gateway 让配置生效

openclaw gateway restart
openclaw gateway status

3.5 配模型

OpenClaw 不绑定模型,可以接任何 OpenAI/Anthropic 兼容 API。我用的 MiniMax:

{
  "agents": {
    "defaults": {
      "model": { "primary": "minimax-portal/MiniMax-M3" }
    }
  },
  "models": {
    "providers": {
      "minimax-portal": {
        "baseUrl": "https://api.minimaxi.com/anthropic/v1",
        "api": "anthropic-messages",
        "authHeader": true
      }
    }
  },
  "auth": {
    "profiles": {
      "minimax-portal:default": {
        "provider": "minimax-portal",
        "mode": "oauth"
      }
    }
  }
}

Anthropic 兼容协议的话 authHeader: true,API key 走 Authorization: Bearer。OAuth 模式下 key 走 ~/.openclaw/auth-profiles.json,gateway 帮你管理 token 刷新。

3.6 验收

打开元宝 App,找到你创建的机器人,发条"/status"。它会通过 gateway 调到 LLM,回复你当前的状态 。

图1:元宝 App 里和"阿Q"机器人的对话截图

【图1:元宝 App 里和"阿Q"机器人的对话截图】


四、第三步:让 Agent 能驱动 Uno Q 的 LED 矩阵

光能聊天不够,让 Agent 能动手才有意思。这一步是重点:我们要让 Agent 一收到"显示X",就在 Uno Q 上点亮 13×8 矩阵

4.1 写一个 Arduino App(scroll-text)

Arduino UNO Q 用的是 App 架构——一个 App = MCU sketch + Linux 容器里的 Python:

arduino-app-cli app new /home/arduino/ArduinoApps/scroll-text

生成的目录:

scroll-text/
├── app.yaml               # 端口映射、容器配置
├── sketch/
│   └── sketch.ino         # STM32 端代码
├── python/
│   └── main.py            # 容器里跑的 Python
└── assets/
    └── fonts/             # 容器 bind mount 时可用

4.2 sketch.ino(STM32 端,只做 I/O

这是迭代了 11 版才定下来的架构:MCU 端极简,全部逻辑给 Python。13 行实质代码:

#include <Arduino_RouterBridge.h>
#include <Arduino_LED_Matrix.h>
#include <vector>

Arduino_LED_Matrix matrix;

void setup() {
  matrix.begin();
  matrix.setGrayscaleBits(3);
  matrix.clear();
  Bridge.begin();
  Bridge.provide("draw", draw);  // 注册一个 RPC handler
}

void loop() {
  delay(50);  // MCU 啥都不做,等 Python 推帧
}

void draw(std::vector<uint8_t> frame) {
  if (frame.size() < 104) return;
  matrix.draw(frame.data());  // 13×8 = 104 字节
}

为什么不让 MCU 跑逻辑? 试过 v5:双线程 + mutex + SPI 状态机 = 死机。把"算下一帧"放到 Linux 那颗 ARM A53 上跑(资源多),STM32 只收 104 字节去点 LED,稳得一逼。

图2:STM32 vs Python 职责分工的架构图

【图2:STM32 vs Python 职责分工的架构图】

4.3 python/main.py(主战场

Python 端要做的事:

  1. 渲染字模(用 PIL + Noto Serif CJK Bold 字体,64px → 缩放到 13×13 → 二值化)

  2. 把所有字符拼成一个 banner(比 13×8 长得多的纵向条)

  3. 用一个滚动线程,每 N ms 取一帧 13×8 的窗口 → Bridge.call("draw", frame_bytes)

  4. 起一个 HTTP server(端口 7099)接收外部控制

字模核心代码(伪):

from PIL import Image, ImageDraw, ImageFont

font = ImageFont.truetype("/app/assets/fonts/NotoSerifCJK-Bold.ttc", 64)

def render_glyph(ch: str) -> np.ndarray:
    img = Image.new("L", (64, 64), 0)
    d = ImageDraw.Draw(img)
    d.text((2, 0), ch, fill=255, font=font)
    arr = np.array(img)
    # 找非零 bbox → 缩放到 13×13 → 二值化
    ...
    return (arr > 110).astype(np.uint8)

滚动循环核心:

def _scroll_loop():
    while True:
        banner = current_banner()    # ndarray, shape (banner_h, 13)
        direction = current_direction()
        for top in iter_window(direction, banner.shape[0]):
            frame = banner[top:top+8, :]      # 13×8 窗口
            Bridge.call("draw", frame.tobytes())
            time.sleep(speed_ms / 1000)

HTTP API(用 stdlib http.server + threading,零依赖):

# POST /display  {"text": "你好", "speed_level": 10, "direction": "top_down"}
# POST /stop, POST /clear, GET /health

4.4 启动 + 验收

arduino-app-cli app start /home/arduino/ArduinoApps/scroll-text
# 它会自动:编译 sketch → 烧录到 STM32 → 起 Python 容器 → 暴露端口

arduino-app-cli app list | grep scroll-text
# 应该看到 scroll-text running

curl -sS -X POST http://127.0.0.1:7099/display \
  -H "Content-Type: application/json" \
  -d '{"text":"你好世界"}'

板子上立刻滚出"你好世界"。从此改字不用烧录

图3:板子实物照片,矩阵上正在滚"你好世界"四字

【图3:板子实物照片,矩阵上正在滚"你好世界"四字】

容器里没有 PIL 也没有中文字体,要在 assets/fonts/ 放一份字体,Docker bind mount 进容器。


五、第四步:给 Agent 编 skill

到这里,板子能听话了,但 Agent 还不知道怎么调它。"显示X" 对 LLM 来说只是一句话,它不会自动想起 curl。

OpenClaw 提供了 Skill Workshop——一套提案制的工作流,专门用来把"重复流程"沉淀成可复用技能。

5.1 写一个 Uno Q 的 skill(scroll-led)

skill 本质就是一份 markdown 文档,放在 ~/.openclaw/skills/<name>/SKILL.md,告诉 LLM:

  • 什么时候该用这个 skill

  • 该怎么调(命令、参数、边界条件)

  • 出错怎么办

我用 skill_workshop 工具创建:

openclaw skill_workshop create \
  --name "scroll-led" \
  --description "在 Arduino UNO Q 13×8 LED 矩阵上滚动显示任意文字。说\"显示X\" → HTTP API。支持方向+速度档位 1-10。"

关键章节(截选):

## 何时用
- 用户说"显示 X"、"在板子上显示 X"、"LED 上显 X"、"matrix 显示 X"
- 停止/清除/重启滚动时

## 前置条件
1. scroll-text app **必须 running**
2. HTTP API 监听 http://127.0.0.1:7099

## HTTP API(端口 7099)
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /display | 显示并滚动 |
| POST | /stop | 停滚动 |
| POST | /clear | 清除 + 停 |

## 用户口语映射
| 用户说 | 调什么 |
|---|---|
| "显示 X" | display text=X |
| "从下往上 X" | display text=X direction=bottom_up |
| "快一点"/"慢一点" | display text=X speed_level=±2 |
| "停"/"清"/"擦掉" | stop / clear |

提案创建后是 pending 状态。Skill Workshop 是个提交流程,编辑 + 评审 + 批准都走它,避免 skill 满天飞。

5.2 验收 skill

在元宝里发:"显示 你好,世界"。

Agent 收到 → 识别匹配 scroll-led skill → 读 SKILL.md → 调 curl http://127.0.0.1:7099/display ... → 板子立刻滚出"你好,世界"。

整个延迟大概 1 秒(LLM 一次往返)。

图4:元宝对话流程截图

【图4:元宝对话流程截图】


六、第五步:把 Arduino UNO R4 WiFi 也接进来

家里另一块板子是 Arduino UNO R4 WiFi——瑞萨 RA4M1 + ESP32-S3,板载 12×8 LED 矩阵。它没有 Uno Q 那套 Linux 架构,必须烧 sketch,没有 HTTP API 这种事。

图5:Arduino UNO R4 WiFi 板子实物

【图5:Arduino UNO R4 WiFi 板子实物】

6.1 工具链准备

R4 用 arduino-cli 直接烧:

# 装 core(一次性)
arduino-cli core install arduino:renesas_uno@1.6.0

# 装文字库(一次性)
arduino-cli lib install ArduinoGraphics

# 确认板子在
arduino-cli board list
# /dev/ttyACM0 ... Arduino UNO R4 WiFi  arduino:renesas_uno:unor4wifi

6.2 sketch 模板

R4 的板载矩阵用 Arduino_LED_Matrix + ArduinoGraphics + TextAnimation 这套异步滚动 API:

#include "ArduinoGraphics.h"
#include "Arduino_LED_Matrix.h"
#include "TextAnimation.h"

ArduinoLEDMatrix matrix;

// 帧缓冲大小公式:N >= (字符数 + 前导空白数) * 5 + 余量
// "   1 2 3 4 5 " = 13 字符 × 5px = 65,留余地写 80
TEXT_ANIMATION_DEFINE(anim, 80)

bool requestNext = false;

void setup() {
  matrix.begin();
  matrix.beginDraw();
  matrix.stroke(0xFFFFFFFF);
  matrix.textFont(Font_5x7);
  matrix.textScrollSpeed(60);       // 值越小滚得越快
  matrix.setCallback(matrixCallback);

  matrix.beginText(0, 1, 0xFFFFFF);
  matrix.println("   1 2 3 4 5 ");  // 前导空白 = 进场留白
  matrix.endTextAnimation(SCROLL_LEFT, anim);

  matrix.loadTextAnimationSequence(anim);
  matrix.play();
}

void matrixCallback() { requestNext = true; }

void loop() {
  if (requestNext) {
    requestNext = false;
    matrix.beginText(0, 1, 0xFFFFFF);
    matrix.println("   1 2 3 4 5 ");  // 两处都要改
    matrix.endTextAnimation(SCROLL_LEFT, anim);
    matrix.loadTextAnimationSequence(anim);
    matrix.play();
  }
}

6.3 烧录

cd /tmp/r4_led_scroll
arduino-cli compile --fqbn arduino:renesas_uno:unor4wifi \
  --upload -p /dev/ttyACM0 r4_led_scroll.ino
# 等 ~10 秒,看到 100% (15/15 pages) 就是烧好了

R4 上立刻循环滚"1 2 3 4 5"。注意:和 Uno Q 不同,R4 是"烧死"的,断电不丢,但改字要重烧

图6:R4 板子实物,12×8 矩阵上正在循环滚"1 2 3 4 5"

【图6:R4 板子实物,12×8 矩阵上正在循环滚"1 2 3 4 5"】

6.4 给 R4 也编一个 skill(r4-led-scroll)

写法跟 Uno Q 的类似,但走的是 arduino-cli compile --upload,不是 HTTP:

## 何时用
- "在 R4 上显示 X"、"R4 显示 X"、"UNO R4 显示 X"

## 前置条件
- Arduino UNO R4 WiFi(**R4 Minima 无矩阵**,不能用)
- USB 接到本机 /dev/ttyACM0
- arduino-cli 已装 + core arduino:renesas_uno@1.6.0

## 流程
1. 写 sketch 到 /tmp/r4_led_scroll/r4_led_scroll.ino(替换 TEXT)
2. arduino-cli compile --fqbn arduino:renesas_uno:unor4wifi --upload -p /dev/ttyACM0

七、最终效果

元宝对话框里随手发:

你说谁干活结果




"在 UnoQ 上显示 Hello"Agent 调 Uno Q skill → HTTP13×8 滚出 Hello
"R4 显示 12345"Agent 调 R4 skill → 烧录12×8 循环滚 12345
"UnoQ 从下往上,慢一点"Agent 调 Uno Q skill(改参数)立即生效,不烧录
"R4 快一点"Agent 改 sketch 里的 textScrollSpeed → 重烧烧完跑新速度

两块板子两套玩法,一套靠 HTTP 热改,一套靠烧录持久。这就是嵌入式 + AI Agent 组合的味道——板子不再是被烧死的设备,而是一个能被 LLM 操纵的 I/O

图7:两块板子并排实拍

【图7:两块板子并排实拍】


八、踩坑清单(速查)

坑症状解决




Uno Q sketch 用裸 Serial.begin() + AA55 协议MCU 完全不响应用 Arduino_RouterBridge,MCU 端 Bridge.provide("name", func)
把滚动逻辑全塞 MCU(双线程 + mutex)烧完死机,板子啥都不亮MCU 只做 I/O,逻辑全给 Python
滚动方向反字从下往上变成从上往下banner 编排方向 + 窗口扫描方向要配合
Uno Q 容器里没 PIL 没字体ModuleNotFoundError字体放 assets/fonts/,镜像里有 PIL 但要自己处理依赖
R4 Minima 想跑 LED 矩阵编译过了但没反应Minima 没有板载矩阵,只有 R4 WiFi 有
R4 TEXT_ANIMATION_DEFINE(anim, N) 设太小文字被截断N ≥ (字符数 × 5) + 5
元宝 appKey 提交到 git泄漏 token加进 .gitignore 或用环境变量
LLM 不会自动调 skill用户说"显示X",Agent 只回了文字SKILL.md 描述要够具体,触发关键词要覆盖口语表达





关键词: ARDUINOUNOQ4GBRAM32GBEMMC    

管理员
2026-06-29 17:43:48     打赏
2楼

将AI大模型(腾讯元宝)与嵌入式硬件(Arduino UNO Q)结合的完整思路,极具前瞻性和趣味性


共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]