App Lab 使用说明
Arduino App Lab 用于创建、运行和管理开发板上的应用(App)。一个 App 可包含 Arduino Sketch、Python 程序和 Bricks 功能模块。电脑连接模式下,电脑负责编辑和管理,应用仍在 VENTUNO Q 上运行。
从 Arduino 软件下载页 下载最新版 App Lab。电脑端与开发板上预装的 App Lab 分别更新;连接开发板后,根据界面提示完成软件更新。
| 部分 | 编辑位置与用途 |
|---|---|
| Arduino Sketch | sketch/sketch.ino,运行在 STM32 MCU 上,用于 I/O 与外设控制 |
| Python | python/main.py,运行在 Ubuntu / MPU 上,用于应用逻辑、网络及数据处理 |
| Bricks | 按需加入的功能模块,例如 Web 界面或模型处理;基础 I/O 示例不要求加入 AI 模块 |
完成 首次配置 和开发板更新后,即可使用 App Lab。
运行示例程序
- 连接并选择 VENTUNO Q。
- 在 "Examples" 或 "Inspirations" 中打开适用于本板的示例,查看示例说明和硬件要求。
- 点击右上角 "Run"。App Lab 会编译 Sketch、传输程序并启动应用,过程显示在底部 "Console" 中。首次运行可能需要联网下载运行环境。
- 等待启动过程结束,并根据示例说明观察硬件现象。入门可使用 Blink 示例;如果下载运行环境失败,可参考 FAQ。

创建与修改 App
复制官方示例
内置示例为只读内容。打开示例后,点击 "Copy and edit App",输入新名称并选择 "Create new",再编辑副本。
创建空白 App
- 在 "Apps" 中选择新建入口;旧版界面可能显示为 "My Apps" 或 "Create new app +"。
- 输入应用名称并创建。
- 在文件列表中打开
sketch/sketch.ino或python/main.py,根据需要编辑对应部分。只测试 MCU 时,保留工具生成的其他文件。 - 点击 "Run"。修改正在运行的代码后,停止并重新运行,使新代码生效。

查看控制台与停止应用
| 控制台标签 | 检查内容 |
|---|---|
| App launch | 编译、传输、启动过程;部分旧版可能显示为 Start-up |
| Python | Python 的 print() 输出和运行报错 |
| Serial Monitor | Sketch 的 Serial.print() 或 Monitor.print() 输出 |
| Brick 对应标签 | 使用相应 Brick 时出现的容器日志 |

启动过程中可能只显示 "App launch",启动完成后才出现其他标签。编译失败时先检查启动日志;应用已启动但行为异常时,再检查 Python、串口或相应 Brick 的日志。若 LED 已闪烁或点阵已显示,但启动日志仍在下载或出现错误,应继续检查启动过程,确认应用是否完整启动。
点击右上角 "Stop" 可停止应用。需要向 Sketch 输入文本时,在 "Serial Monitor" 底部输入框发送,程序可通过 Serial.read() 或 Monitor.read() 接收。
通过终端查看应用
在 开发板终端 中,可使用 App CLI 查看应用:
| 命令 | 用途 |
|---|---|
arduino-app-cli app list | 查看已创建或安装的应用 |
arduino-app-cli app list --examples | 查看内置示例 |
arduino-app-cli app ps | 查看应用运行状态 |
基础功能示例
每个示例分别创建 App,并替换 sketch/sketch.ino。输出信息在 "Serial Monitor" 中查看。
接外部元件前先断开电源,按本板引脚图核对位置。示例使用 3.3 V 接线;不要向 A0 等模拟输入施加 5 V。无需外接元件的练习见 板载 RGB LED 与 LED 点阵。
数字 I/O:按键控制 LED
接线: 准备一个按键、LED、限流电阻、面包板和跳线。按下图连接:按键接 D4 与 GND;D5 通过限流电阻连接 LED 阳极,LED 阴极接 GND。D4 使用内部上拉,按下为 LOW。

const int buttonPin = D4;
const int ledPin = D5;
void setup() {
pinMode(buttonPin, INPUT_PULLUP);
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
}
void loop() {
bool pressed = digitalRead(buttonPin) == LOW;
digitalWrite(ledPin, pressed ? HIGH : LOW);
Serial.println(pressed ? "Button pressed" : "Button released");
delay(100);
}
运行结果: 按住按键时 LED 点亮,松开后熄灭,串口显示相应状态。这里使用的是外接按键,不是板上的 User 按钮。
ADC:读取电位器
ADC(Analog-to-Digital Converter,模数转换器)将模拟电压转换为数字读数。
接线: 电位器两端分别接 3.3 V 和 GND,中间滑动端接 A0。

void setup() {
Serial.begin(9600);
analogReadResolution(12);
}
void loop() {
int value = analogRead(A0);
Serial.println(value);
delay(100);
}
运行结果: 旋转电位器时,串口数值随输入电压变化。本例将读数分辨率设置为 12 位,数值范围为 0~4095。
DAC:输出固定模拟量
DAC(Digital-to-Analog Converter,数模转换器)用于输出模拟电压。本板的 DAC0 对应 A0,DAC1 对应 A1。
接线: 先断开前一个 ADC 示例的电位器,再使用高阻电压测量仪器测量 A0 相对 GND 的输出。
void setup() {
analogWriteResolution(12);
analogWrite(DAC0, 2048);
}
void loop() {
}
运行结果: 预期测得稳定的模拟输出;实际电压应通过测量确认。12 位设置的数字范围为 0~4095,2048 约为半量程。普通 PWM 引脚调用 analogWrite() 输出的是脉冲,不能与 DAC 输出混为一谈。
PWM:调节占空比
PWM(Pulse Width Modulation,脉宽调制)通过改变高电平时间比例控制输出。
接线: 沿用 A0 电位器接线,在 D3 输出 PWM;用示波器或逻辑分析仪观察 D3 与 GND。
void setup() {
analogReadResolution(12);
analogWriteResolution(8);
}
void loop() {
int value = analogRead(A0);
int duty = map(value, 0, 4095, 0, 255);
analogWrite(D3, duty);
delay(10);
}
运行结果: 旋转电位器时,D3 输出的占空比改变。本例将 PWM 设置为 8 位,对应 0~255;不要把 PWM 数值范围与 ADC 读数范围混用。
UART:发送文本
UNO 排针的硬件串口使用 Serial1,TX 为 D1,RX 为 D0;Serial 用于 App Lab 的串口输出。
接线: 将 D1 连接到支持 3.3 V 逻辑的串口接收端 RX,并连接 GND。在接收端设置 115200 波特率查看文本。本例只发送数据,不需要连接 D0。
void setup() {
Serial1.begin(115200);
}
void loop() {
Serial1.println("Hello VENTUNO Q");
delay(1000);
}
运行结果: 外部接收端约每秒收到一行文本。此接线不是 JCTL 调试串口。
I2C:选择总线并扫描地址
UNO 排针的 SDA、SCL 使用 Wire;Qwiic 接口使用 Wire1。
接线: 确认模块的 3.3 V 供电、GND、SDA、SCL 及所需上拉条件,再运行下列扫描示例。
#include <Wire.h>
// 改为 Wire1 可扫描 Qwiic 接口。
#define SCAN_BUS Wire
void setup() {
Serial.begin(9600);
SCAN_BUS.begin();
}
void loop() {
Serial.println("Scanning I2C...");
for (int address = 0x08; address <= 0x77; address++) {
SCAN_BUS.beginTransmission(address);
if (SCAN_BUS.endTransmission() == 0) {
Serial.print("Found address: 0x");
Serial.println(address, HEX);
}
}
delay(2000);
}
运行结果: 有设备应答时,串口输出对应的 I2C 地址。连接多个设备时,注意避免地址冲突。
SPI:初始化与接线
接线: 默认 UNO SPI 引脚为 D10/SS、D11/MOSI、D12/MISO、D13/SCK。连接外设时还需共同连接 GND,并根据外设资料确认供电、时钟模式、速率及片选电平。
以下为初始化代码,片选保持高电平,暂不发送设备相关指令:
#include <SPI.h>
const int chipSelect = D10;
void setup() {
pinMode(chipSelect, OUTPUT);
digitalWrite(chipSelect, HIGH);
SPI.begin();
}
void loop() {
}
代码作用: 以上代码完成 SPI 初始化。读写外设时,在 loop() 中添加目标器件规定的 SPI 参数、指令和数据处理。
Python 与 MCU 通信:Bridge
Bridge 通过远程过程调用(RPC,Remote Procedure Call)连接 Linux 与 MCU。下面用 Python 发送递增数字,MCU 收到后向串口监视器输出,不需要外接元件。

此示例使用 Arduino_RouterBridge 库。先确认已安装包含 VENTUNO Q 定义的 Arduino Zephyr core,并单独创建此 App。Zephyr core 的版本号与 App Lab 不同;如果找不到开发板定义,可参考 FAQ 排查步骤。
Sketch(sketch/sketch.ino):
#include "Arduino_RouterBridge.h"
void printValue(int value) {
Monitor.print("MCU received value: ");
Monitor.println(value);
}
void setup() {
Bridge.begin();
Monitor.begin();
Bridge.provide_safe("print_value", printValue);
}
void loop() {
}
Python(python/main.py):
from arduino.app_utils import App, Bridge
import time
counter = 0
def loop():
global counter
time.sleep(2)
counter += 1
Bridge.call("print_value", counter)
print("Sent:", counter)
App.run(user_loop=loop)
点击 "Run" 后,在 "Python" 中应看到 Sent: 1 等输出,在 "Serial Monitor" 中应看到 MCU received value: 1 等输出,约每两秒增加一次。
print_value 必须在两端保持一致,参数类型也需与 C++ 函数匹配。这里采用 Bridge.provide_safe(),使包含 Monitor 操作的函数在安全上下文执行;不要直接改成普通 Bridge.provide() 后在回调内进行嵌套同步调用。
设置开机运行
- 打开自己创建的 App 或官方示例副本。
- 点击应用名称旁的下拉箭头。
- 启用 "Run at startup"。

重新供电后,检查 App 日志与硬件现象,确认开机运行结果。