mcpField
M
matlab-create-custom-arduino-library

matlab-create-custom-arduino-library

github.com/matlab开发1.2k51 次安装1 天前更新
代码仓库

关于 matlab-create-custom-arduino-library

这是一个帮助 MATLAB 用户为 Arduino 传感器或外设创建自定义库的技能指南,通过 MATLAB 类和 Arduino C++ 代码建立接口。指南先检查原生支持和 MathWorks File Exchange 资源,再说明库的搭建与验证流程。

主要功能

  1. 01检查 Arduino 原生库支持
  2. 02查找 MathWorks 贡献的扩展
  3. 03生成自定义扩展模板
  4. 04编写 MATLAB 类和 C++ 头文件
  5. 05验证库注册及设备连接

适用场景

  1. 01从 MATLAB 读取未原生支持的传感器
  2. 02通过 MATLAB 控制外接外设
  3. 03将现有 Arduino C++ 库接入 MATLAB
  4. 04为定制硬件创建 Arduino 扩展

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/matlab/matlab-agentic-toolkit --skill matlab-create-custom-arduino-library

安装后在 Claude Code 中输入/matlab-create-custom-arduino-library确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

manifest.yaml
references/
bus-conflicts.md
common-errors.md
cpp-patterns.md

详细介绍

创建自定义 Arduino 库

通过创建自定义 Arduino 库,在 MATLAB 与 Arduino C++ 代码之间搭建桥梁,帮助用户通过 MATLAB 使用 Arduino 传感器或外围设备。

适用场景

  • 用户想要读取原生不支持的传感器(DHT11、DHT22、IMU、空气质量传感器)
  • 用户想要控制原生不支持的外围设备(OLED 显示屏、电机驱动器、NeoPixels)
  • 用户询问“如何通过 MATLAB 使用 Arduino 上的 [传感器/执行器/外围设备]?”
  • 用户想要封装现有的 Arduino C++ 库,以便在 MATLAB 中使用
  • 用户提到 LibraryBase、arduinoioaddons 或创建自定义插件

不适用场景

  • 外围设备已原生支持(使用 listArduinoLibraries 检查)
  • 用户需要发现或连接 Arduino 板(请参阅 matlab-connect-arduino)
  • 用户需要通用 I2C/SPI 通信(内置支持)
  • 用户想要部署独立运行的 Arduino 代码(不连接 MATLAB)
  • 用户想要部署 Simulink Arduino 程序(工作流不同)
  • 用户想要修复 Arduino 硬件设置界面

工作流

强制检查步骤 — 不可跳过,但应快速完成:

创建自定义插件之前,必须先执行以下第 0 步和第 1 步。这些检查很简单(运行一条 MATLAB 命令,并用一句话说明 File Exchange 的搜索结果),无需深入研究。用 1–2 行报告结果,然后继续。如果存在原生支持或社区插件,则停止;否则立即进入第 2 步。

第 0 步:检查原生支持(始终首先执行)
listArduinoLibraries

如果列表中有该外围设备,请告知用户并停止。不要继续执行第 2 步或后续步骤。不要生成自定义库代码。常见的内置支持包括: I2C、SPI、Serial、Servo、RotaryEncoder、Ultrasonic、ShiftRegister

第 1 步:搜索 File Exchange(仅限 MathWorks 贡献内容)

搜索 MathWorks MATLAB Hardware Team 贡献的现有插件:

  • 搜索:site:mathworks.com/matlabcentral/fileexchange Arduino <peripheral>
  • 查找包含 +arduinoioaddons 文件夹结构的软件包
  • 仅使用由 MathWorks 编写的搜索结果——按作者“MathWorks Hardware Team”或“MathWorks”筛选。不要推荐来自未知第三方的社区贡献。

如果找到 MathWorks 贡献的插件,请指导用户完成安装:

  1. 下载并解压插件包
  2. 对包含 +arduinoioaddons 的文件夹运行 addpath
  3. 使用 arduinoio.customLibrary.downloadLibrary 安装第三方 Arduino 库
  4. 使用 listArduinoLibraries 验证

如果找到 MathWorks 插件,请在此处停止——不要继续执行第 2 步或后续步骤。

第 2 步:收集所需输入

创建自定义库之前,用户必须提供:

  1. 自定义库名称(例如,MyDHT22)
  2. 第三方 Arduino 库名称(如果要封装现有库;例如,DHT22、U8g2)
  3. MATLAB 插件文件的目标输出目录

在提供所有必需输入之前,不要继续执行后续步骤。如果缺少任何一项,请明确询问用户并等待回复。

第 3 步:安装第三方 Arduino 库
% R2025a+ — use downloadLibrary (preferred)
arduinoio.customLibrary.downloadLibrary("<ArduinoLibraryName>")

% Accepts: library name, name@version, GitHub URL, or local .zip path
% Examples:
arduinoio.customLibrary.downloadLibrary("DHT22")
arduinoio.customLibrary.downloadLibrary("U8g2")
arduinoio.customLibrary.downloadLibrary("https://github.com/olikraus/u8g2")

验证安装:

dir(fullfile(arduinoio.CLIRoot, 'user', 'libraries'))

对于 R2024a–R2024b(没有 downloadLibrary):手动将库压缩包解压到 fullfile(arduinoio.CLIRoot, 'user', 'libraries', '<LibName>')。

对于 R2024a 之前的版本(没有 CLIRoot):使用 arduinoio.IDERoot 代替 arduinoio.CLIRoot。

第 4 步:搭建插件框架
% R2025a+ — use createLibraryTemplate (preferred)
arduinoio.customLibrary.createLibraryTemplate("<CustomLibraryName>")

这会在**当前工作目录(pwd)**中创建文件夹结构,并自动添加路径。调用后,生成的文件位于:

<pwd>/+arduinoioaddons/+<CustomLibraryName>Folder/<CustomLibraryName>.m
<pwd>/+arduinoioaddons/+<CustomLibraryName>Folder/src/<CustomLibraryName>.h

不要搜索其他位置——文件始终位于 pwd 中。

命名:createLibraryTemplate("X") 会创建 +XFolder/X.m——它会自动在包名称后追加“Folder”。生成的 setup() 中包含占位注释——请清空函数体(不要调用 .begin())。生成的 loop() 未使用,可以删除。

对于 R2025a 之前的版本:手动创建文件夹结构:

<targetDir>/+arduinoioaddons/+<FolderName>/<ClassName>.m
<targetDir>/+arduinoioaddons/+<FolderName>/src/<HeaderName>.h

然后注册:

addpath('<targetDir>');
savepath;
步骤 5:配置 MATLAB 类

更新生成的 .m 文件。具体取值请参阅下文的“MATLAB 类属性规则”。

在生成的 .m 文件中添加简要注释,方便用户理解:

  • 文件级注释块,说明类的用途及其封装的外设
  • 为不明显的属性值添加简短注释(例如,说明 DependentLibraries 为空的原因)
  • 在每个公共方法上方添加一行注释,说明其作用
步骤 6:编写 C++ 头文件

更新生成的 .h 文件。请参阅下文的“C++ 头文件规则”,并阅读 references/cpp-patterns.md 中的模板。

在生成的 .h 文件中添加简要注释,方便用户理解:

  • 文件级注释,说明插件名称及其支持的外设
  • 在每个命令 ID #define 上方添加一行注释,说明该命令的作用
  • 在 commandHandler 中为每个 case 添加简短注释,说明其作用
步骤 7:验证
listArduinoLibraries  % Must show your library name
a = arduino("<port>", "<board>", "Libraries", "<FolderName>/<ClassName>");
obj = addon(a, "<FolderName>/<ClassName>", <args>);

MATLAB 类属性规则

属性格式示例备注
LibraryName'FolderName/ClassName''Adafruit/DHT22'必须与命名空间匹配
DependentLibrariesMATLAB 插件名称组成的单元格数组{} 或 {'I2C'}请参阅下方的决策表
LibraryHeaderFiles'<ArduinoLibFolder>/<header.h>''DHT/DHT.h'CLIRoot 中的文件夹名称 + 头文件名
CppHeaderFilefullfile(arduinoio.FilePath(mfilename('fullpath')), 'src', '<Name>.h')—始终使用此格式
CppClassName必须与 C++ 类名匹配'DHT22Base'必须完全匹配
DependentLibraries 决策表
场景值原因
仅使用 GPIO 的外设(DHT、NeoPixel){}不依赖 MATLAB 总线
使用 SW_I2C 的 I2C 设备(显示屏、大多数传感器){}软件 I2C 绕过 MATLAB 总线
将 I2C 操作交由 MATLAB I2C 基础设施处理的 I2C 设备{'I2C'}MATLAB 管理 Wire 初始化和引脚
SPI 设备{}MATLAB 不拥有 SPI 总线
使用另一个自定义插件{'OtherAddon/Name'}链式依赖
LibraryHeaderFiles 格式

格式:'<FolderNameInCLIRoot>/<HeaderFilename>'

% GOOD — folder name matches what's in CLIRoot/user/libraries/
LibraryHeaderFiles = {'DHT/DHT.h'}
LibraryHeaderFiles = {'U8g2/U8g2lib.h'}
LibraryHeaderFiles = {'Adafruit_Motor_Shield_V2_Library/Adafruit_MotorShield.h'}

% BAD — just filename without folder
LibraryHeaderFiles = {'DHT.h'}

% BAD — subdirectory path (NEVER include src/ even if the file physically lives there)
LibraryHeaderFiles = {'U8g2/src/U8g2lib.h'}

% BAD — Arduino library name (Wire is not in CLIRoot/user/libraries)
LibraryHeaderFiles = {'Wire/Wire.h'}

Arduino 构建系统会自动在库文件夹下的 src/ 子目录中查找,因此切勿在此路径中包含 src/。这是最常见的错误:尽管 U8g2lib.h 等头文件实际位于 <LibFolder>/src/ 中,但必须写成 'U8g2/U8g2lib.h',而不是 'U8g2/src/U8g2lib.h'。

C++ 头文件规则

完整模板请阅读 references/cpp-patterns.md。关键规则:

  1. setup() 绝不能初始化硬件——在 setup() 中调用 .begin()、Wire.begin()、 SPI.begin() 等会导致“内部错误:服务器代码的初始化不正确。” 简单的变量赋值(例如 cursorRow = 0)是安全的。
  2. 使用延迟初始化——通过专用的 INIT 命令,在首次收到命令时初始化硬件
  3. sendResponseMsg 必须至少发送 1 个字节——sendResponseMsg(cmdID, 0, 0) 会导致 ARM 开发板(UNO R4、ESP32)崩溃
  4. 绝不能在插件头文件中 #include <Wire.h>——这会与 MATLAB 造成 I2C 总线冲突。 代码中绝不能出现这一行。第三方库可能在内部包含它(这没有问题,因为你无法控制其代码),但你的 .h 文件中绝不能包含它。
  5. #include <SPI.h> 是安全的——MATLAB 不拥有 SPI
  6. 第三方头文件使用尖括号:#include <U8g2lib.h>
  7. 成员对象使用构造函数初始化列表,不要在类内初始化
I2C 总线冲突 — 阅读 references/bus-conflicts.md

MATLAB 拥有硬件 I2C 总线(Wire)。如果外设使用 I2C:

  • **首选:**使用软件 I2C 构造函数(例如 U8G2_..._SW_I2C),并设置 DependentLibraries = {}
  • 不要直接调用 Wire.begin()
  • 不要在自己的插件头文件中 #include <Wire.h>

如果第三方库需要硬件 I2C(例如 SGP30、电机扩展板):设置 DependentLibraries = {'I2C'},并让 MATLAB 管理总线。第三方库可能会在内部包含 Wire.h——这是安全的,因为 MATLAB 已经初始化了 Wire。 你的 C++ 代码不得调用 Wire.begin(),因为 MATLAB 已经完成了初始化。

常见错误

错误错误原因正确做法
DependentLibraries = {'Wire'}Wire 不在 listArduinoLibraries 中使用 {} 或 {'I2C'}
将第三方库放入 +arduinoioaddons/src/位置错误;构建时无法找到arduinoio.CLIRoot/user/libraries/
LibraryHeaderFiles = {'U8g2lib.h'}缺少文件夹前缀{'U8g2/U8g2lib.h'}
U8G2_..._HW_I2C 构造函数与 MATLAB 的 Wire 管理冲突使用 _SW_I2C 构造函数
在 setup() 中调用 .begin()服务端握手失败通过命令初始化硬件;变量赋值可以
sendResponseMsg(cmdID, 0, 0)会导致 ARM 开发板崩溃(nullptr)始终发送至少 1 个字节
在插件头文件中 #include <Wire.h>与 MATLAB I2C 服务冲突省略;使用 SW_I2C 或 DependentLibraries = {'I2C'}
通过 Arduino IDE 库管理器安装MATLAB 使用自己的 CLIRoot 路径使用 downloadLibrary()
创建插件后未调用 addpathlistArduinoLibraries 将无法找到它使用 addpath + savepath

约定

  • 始终先检查原生支持,再检查 File Exchange,最后才自行创建
  • 对第三方库,始终使用 downloadLibrary(R2025a+)或手动复制到 CLIRoot
  • 注册后始终使用 listArduinoLibraries 验证
  • 不要在 setup() 中调用 .begin() 或初始化硬件——使用专用命令进行延迟初始化
  • 在 sendResponseMsg 中始终发送至少 1 个字节
  • 不要在自己的代码中包含 <Wire.h>——使用软件 I2C 或依赖 {'I2C'}
  • 不要将第三方 Arduino 库放入 +arduinoioaddons
  • 优先使用 createLibraryTemplate(R2025a+),而非手动创建文件夹

备用方案:自动步骤失败或耗时过长时

如果 listArduinoLibraries 挂起、File Exchange 搜索耗时过长、downloadLibrary 失败,或 createLibraryTemplate 失败——请改用 R2025a 之前的手动方法:

  1. **手动安装库:**下载第三方 Arduino 库的 .zip 文件,并将其解压到 fullfile(arduinoio.CLIRoot, 'user', 'libraries', '<LibName>')。
  2. 手动创建文件夹结构:
    <targetDir>/+arduinoioaddons/+<FolderName>/<ClassName>.m
    <targetDir>/+arduinoioaddons/+<FolderName>/src/<HeaderName>.h
    
  3. 手动注册:addpath('<targetDir>'); savepath;
  4. 从第 5 步继续(照常配置 MATLAB 类和 C++ 头文件)。

不要反复重试失败的命令。改为手动创建并继续。

故障排除

部署或使用期间发生错误时,请阅读相应的参考文档:

  • 编译错误或“找不到源文件”错误 → 阅读 references/common-errors.md
  • 运行时错误(“无法接收数据”、“服务端代码不正确”) → 阅读 references/common-errors.md
  • 总线冲突(I2C/SPI/UART) → 阅读 references/bus-conflicts.md
  • C++ 代码模式(延迟初始化、响应格式、包含项) → 阅读 references/cpp-patterns.md

版权所有 2026 The MathWorks, Inc.


评论

支持 Markdown