12浏览
查看: 12|回复: 0

[项目] Arduino UNO Q 之“马到成功”

[复制链接]
本帖最后由 云天 于 2026-2-5 11:48 编辑

       最近在 DF 创客商城入手了刚上架的Arduino UNO Q,开箱上手、调试编程的整个过程充满惊喜,不仅系统学习了 Linux 嵌入式、边缘 AI、双核心协同等前沿知识,还解锁了从传统单片机控制到智能视觉、语音识别的全新创作路径,无数创意点子在脑海里迸发。这块集经典兼容、Linux 系统、本地 AI、实时控制于一体的全能开发板,彻底打破了传统 Arduino 的性能边界,成为我手边又一件高效、好用、潜力无限的创客制作利器,未来的智能小车、环境监测站、交互装置、AI 小机器人都有了更强大的硬件底座!
【Arduino UNO Q 简介】
       Arduino UNO Q是 Arduino 新一代高性能全能型开发板,专为创客、学生、开发者打造,既保留经典 UNO 的易用性,又搭载 “双大脑”,一步迈入 Linux 与边缘 AI 时代,是新手进阶、老玩家升级的首选主力板。
  • 双核心 “神仙组合”
    一边是STM32U585 实时单片机,精准控灯、舵机、传感器,延迟极低、稳如老狗;另一边是高通四核处理器,跑完整 Debian Linux,能跑 Python、跑 AI 模型、连 WiFi / 蓝牙,相当于把 “微型电脑 + 经典 Arduino” 焊在一块板上。
  • 自带 Linux 系统,不用外接电脑也能开发
    板载 2GB/4GB 内存 + 16GB/32GB 存储,预装 Linux 系统,可直接在板上运行 Arduino IDE、写代码、跑程序,接显示器鼠标就能当迷你开发机用,外出调试超方便。
  • 原生支持边缘 AI,本地就能做人脸 / 物体识别
    不用上云、不依赖服务器,本地直接跑目标检测、图像分类、关键词识别,做智能门禁、跟随机器人、语音交互装置门槛大幅降低。
  • 完美兼容经典 UNO 生态
    保留标准 UNO 接口尺寸,你手里现有的传感器、扩展板、模块直接插就能用,老项目无缝迁移,新项目直接起飞。
  • 接口现代、联网齐全
    标配USB-C(支持 PD 供电)、Qwiic 快连接口、高速 GPIO,自带WiFi 5 + 蓝牙 5.1,物联网、远程控制、无线传输一步到位。
       它是能跑 Linux、能玩 AI、能精准控制硬件、兼容所有 UNO 配件的下一代 Arduino,从小白入门到高阶智能创作,一块板全覆盖,是当前最值得入手的创客全能神器。

Arduino UNO Q 之“马到成功”图1

Arduino UNO Q 之“马到成功”图2

Arduino UNO Q 之“马到成功”图3





【Arduino IDE】
       Arduino UNO Q 兼容标准 Arduino IDE,可使用你熟悉的 Arduino 语言与生态系统对开发板进行编程。(Arduino UNO Q 搭载双处理器:Arduino IDE 只能编程其中的 STM32 微控制器;如果要开发高通处理器部分,可使用 Arduino App Lab 。)
Arduino UNO Q 之“马到成功”图4

       测试:使用点阵屏播放“Bad Apple”
       1.安装 UNO Q 开发板核心
       手动添加安装包啦。操作步骤:打开「文件」>「首选项」,把下面这个链接粘贴到「附加开发板管理器网址」的输入框里:
  1. https://downloads.arduino.cc/packages/package_zephyr_index.json
复制代码
      2.程序代码

       使用UNO Q的”Arduino_LED_Matrix”——“video”示例
  1. #include "Arduino_LED_Matrix.h"
  2. #include "bad_apple.h"
  3. Arduino_LED_Matrix matrix;
  4. void setup() {
  5.   matrix.begin();
  6.   matrix.setGrayscaleBits(8);
  7. }
  8. void loop() {
  9.   matrix.playVideo(bad_apple, bad_apple_len);
  10. }
复制代码

       3.演示视频

Arduino App Lab
       Arduino App Lab 是一款一站式开发工具,把咱们熟悉的 Arduino 玩法拓展到了高性能计算领域。用它可以把 Arduino 代码、Python 脚本和 Linux 容器应用完美融合,全程开发不用来回切换工具。
       它自带「Bricks(代码积木)」、现成的 AI 模型,以及集成化的任务编排功能,能做出从简单小原型到高算力复杂应用的各种作品,新手也能轻松上手。
Arduino UNO Q 之“马到成功”图5

       根据官网操作文档,下载Arduino App Lab,安装并连接UNO Q。
       踩坑指南
       1.Arduino App Lab卡在“检查更新”界面,这可能是由开发板固件版本过低引起的。
       按照官方指南使用arduino-flasher-cli工具重刷最新固件。
       2.准备硬件时需要用一个母对母跳线短接两个特定引脚,其目的是让UNO Q进入特殊的刷机模式(类似“下载模式”或“恢复模式”),以便后续连接电脑刷写固件。
【示例体验】
       1.“UNO Q Pin Toggle”
       你可通过简洁的交互式开发板可视化界面,在浏览器中控制 Arduino UNO Q 的每一个引脚。拨动开关即可切换引脚的通断状态,且所有状态变化会实时反馈显示。本示例展示了一套简洁易用的实时控制面板,你可在此基础上扩展为功能更丰富的监控仪表盘与自动化控制系统。
Arduino UNO Q 之“马到成功”图6

Arduino UNO Q 之“马到成功”图7

       2.“Weather forecast on LED matrix”
       修改示例ino文件,在原单一显示程序中指定的城市天气,实现通过按钮切换多个城市天气显示。
Arduino UNO Q 之“马到成功”图8

  1. // SPDX-FileCopyrightText: Copyright (C) ARDUINO SRL ([url]http://www.arduino.cc[/url])
  2. //
  3. // SPDX-License-Identifier: MPL-2.0
  4. #include <Arduino_LED_Matrix.h>
  5. #include <Arduino_RouterBridge.h>
  6. #include "weather_frames.h"
  7. // 1. 定义7个中国主要城市列表(拼音,适配open-meteo API)
  8. String cities[] = {"Zhangjiakou","Beijing", "Shanghai", "Guangzhou", "Shenzhen", "Chengdu", "Chongqing"};
  9. // 当前选中的城市索引(初始为0,对应张家口)
  10. int currentCityIndex = 0;
  11. // 城市总数
  12. const int cityCount = sizeof(cities) / sizeof(cities[0]);
  13. // 按钮相关定义
  14. const int BUTTON_PIN = 4;    // 按钮接引脚4
  15. bool lastButtonState = LOW; // 上一次按钮状态(初始低电平)
  16. unsigned long lastDebounceTime = 0; // 消抖时间记录
  17. const unsigned long debounceDelay = 50; // 消抖延时(50ms)
  18. Arduino_LED_Matrix matrix;
  19. void setup() {
  20.   // 初始化LED点阵屏
  21.   matrix.begin();
  22.   matrix.clear();
  23.   // 初始化Bridge通信
  24.   Bridge.begin();
  25.   // 初始化按钮引脚(上拉输入模式,无需外接上拉电阻)
  26.   pinMode(BUTTON_PIN, INPUT_PULLUP);
  27.   
  28.   // 启动时显示第一个城市(张家口)的天气
  29.   updateWeatherForecast();
  30. }
  31. void loop() {
  32.   // 检测按钮按下并切换城市
  33.   checkButtonPress();
  34.   // 持续播放当前城市的天气动画(无需频繁调用API,避免限流)
  35.   matrix.playSequence();
  36. }
  37. // 检测按钮按下(带消抖),切换城市并更新天气
  38. void checkButtonPress() {
  39.   // 读取当前按钮状态(INPUT_PULLUP模式下,按下为HIGH,松开为LOW)
复制代码
Arduino UNO Q 之“马到成功”图9


Arduino UNO Q 之“马到成功”图10


【马到成功】
       新年“马上”就要到了,马年祝大家,事事顺意,马到成功。
       1.“LED Matrix Painter”
       LED 矩阵绘制器示例提供了一个基于网页的交互界面,可实时绘制、制作动画并控制 Arduino UNO Q 内置的 LED 点阵屏。该工具具备像素编辑功能(支持 3 位色深 / 0-7 级亮度调节)、设计方案的数据库存储功能,还内置代码生成器,可将你设计的帧动画导出为可直接使用的 C++ 代码。
Arduino UNO Q 之“马到成功”图11

       该应用支持你直接在浏览器中为 8×13 LED 点阵屏设计视觉效果。它借助 web_ui 功能模块搭建了一个图形化编辑器,你可在其中绘制单个像素点、调节像素亮度,还能对图案执行翻转、旋转等变换操作。你在浏览器中做出的每一处修改,都会即时同步到物理开发板上呈现。
Arduino UNO Q 之“马到成功”图12

       演示视频

       2.修改示例,实现一键“平移动画生成器”
       它会根据当前编辑的图案,自动生成从左到右移动的多帧动画。
       1) 首先在 HTML 中添加按钮index.html 文件中的 animation-options 部分添加一个新按钮:
  1. <button id="generate-horizontal" class="anim-option-btn" title="生成水平移动动画">    <img src="img/arrow-right.svg" alt="水平移动" style="width: 16px; height: 16px;">
  2. </button>
复制代码
      2)在 CSS 中添加样式
       在 style.css 中添加按钮样式:
  1. /* 为生成动画按钮添加样式 */
  2. #generate-horizontal {
  3.     border: 1px solid #C9D2D2;
  4.     border-radius: 8px;
  5.     padding: 6px;
  6.     background-color: transparent;
  7.     cursor: pointer;
  8.     display: flex;
  9.     align-items: center;
  10.     justify-content: center;
  11.     color: #2C353A;
  12. }
  13. #generate-horizontal:hover {
  14.     background-color: rgba(0, 129, 132, 0.08);
  15. }
  16. #generate-horizontal img {
  17.     width: 16px;
  18.     height: 16px;
  19. }
复制代码
      3) 在 JavaScript 中实现核心功能
       在 app.js 中添加以下代码:
  1. // 获取生成水平移动动画的按钮
  2. const generateHorizontalBtn = document.getElementById('generate-horizontal');
  3. // 生成水平移动动画的函数
  4. async function generateHorizontalAnimation() {
  5.     if (loadedFrameId === null) {
  6.         showError('请先选择一个帧作为基础图案');
  7.         setTimeout(hideError, 3000);
  8.         return;
  9.     }
  10.     // 询问用户要生成多少帧
  11.     const frameCountInput = prompt('请输入要生成的帧数(建议 13-39 帧,数字越大动画越流畅):', '26');
  12.     if (!frameCountInput) return;
  13.    
  14.     const count = parseInt(frameCountInput, 10);
  15.     if (isNaN(count) || count < 5) {
  16.         showError('请输入至少 5 帧');
  17.         setTimeout(hideError, 3000);
  18.         return;
  19.     }
  20.     try {
  21.         // 获取当前帧的图案
  22.         const currentGrid = collectGridBrightness();
  23.         
  24.         // 计算动画参数
  25.         // 图案宽度为 COLS (13列)
  26.         // 为了让图案从左侧外出现到右侧外消失,总共需要移动 COLS + 当前帧宽度步数
  27.         // 但实际上我们让图案从左侧外完全看不到,到完全进入,再到完全出去
  28.         const patternWidth = COLS; // 图案宽度
  29.         const totalMovement = patternWidth + COLS; // 完全进入 + 完全出去需要的步数
  30.         
  31.         // 创建保存所有新帧的数组
  32.         const newFrames = [];
  33.         
  34.         // 生成每一帧
  35.         for (let i = 0; i < count; i++) {
  36.             // 计算当前帧的偏移量
  37.             // 从完全在左侧外(-COLS)开始,到完全在右侧外(+COLS)结束
  38.             const progress = i / (count - 1); // 0 到 1 的进度
  39.             const offset = Math.floor(-COLS + progress * (2 * COLS));
  40.             
  41.             // 创建新帧的图案
  42.             const newRows = [];
  43.             for (let r = 0; r < ROWS; r++) {
  44.                 const newRow = [];
  45.                 for (let c = 0; c < COLS; c++) {
  46.                     // 计算图案中对应的列
  47.                     const sourceCol = c - offset;
  48.                     
  49.                     // 如果源列在图案范围内,则使用图案的值,否则为0
  50.                     if (sourceCol >= 0 && sourceCol < patternWidth) {
  51.                         newRow.push(currentGrid[r][sourceCol]);
  52.                     } else {
  53.                         newRow.push(0);
  54.                     }
  55.                 }
  56.                 newRows.push(newRow);
  57.             }
  58.             
  59.             // 添加新帧到数组
  60.             newFrames.push({
  61.                 rows: newRows,
  62.                 name: `水平移动 ${i + 1}/${count}`,
  63.                 duration_ms: Math.max(30, Math.floor(1000 / count)) // 根据帧数计算合适的时长
  64.             });
  65.         }
  66.         
  67.         // 批量保存所有新帧
  68.         for (let i = 0; i < newFrames.length; i++) {
  69.             const frame = newFrames[i];
  70.             await fetchWithHandling('/persist_frame', {
  71.                 method: 'POST',
  72.                 headers: {'Content-Type': 'application/json'},
  73.                 body: JSON.stringify({
  74.                     rows: frame.rows,
  75.                     name: frame.name,
  76.                     duration_ms: frame.duration_ms,
  77.                     brightness_levels: BRIGHTNESS_LEVELS
  78.                 })
  79.             }, 'json', `保存第 ${i + 1} 帧`);
  80.         }
  81.         
  82.         // 刷新帧列表
  83.         await refreshFrames();
  84.         
  85.         // 加载第一帧
  86.         if (sessionFrames.length > 0) {
  87.             // 找到最新创建的帧(最后保存的那个)
  88.             const latestFrame = sessionFrames[sessionFrames.length - 1];
  89.             // 但我们需要找到水平移动动画的第一帧
  90.             const horizontalFrames = sessionFrames.filter(f => f.name.startsWith('水平移动'));
  91.             if (horizontalFrames.length > 0) {
  92.                 await loadFrameIntoEditor(horizontalFrames[0].id);
  93.             }
  94.         }
  95.         
  96.         showError(`成功生成 ${count} 帧水平移动动画!`);
  97.         setTimeout(hideError, 3000);
  98.         
  99.     } catch (error) {
  100.         console.error('生成水平移动动画失败:', error);
  101.         showError('生成动画失败: ' + error.message);
  102.         setTimeout(hideError, 5000);
  103.     }
  104. }
  105. // 为按钮添加事件***
  106. if (generateHorizontalBtn) {
  107.     generateHorizontalBtn.addEventListener('click', generateHorizontalAnimation);
  108. }
复制代码
       4)演示视频







您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4 备案 沪公网安备31011502402448

© 2013-2026 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail