[Switch to English]

快速上手视频

点击查看完整版:Mind+自定义用户库视频教程


优秀用户库列表

目前已支持的用户库有: Blynk、甲醛传感器、SHT20传感器、手势传感器、TM1637数码管、掌控板蓝牙、掌控板语音识别等。
详细清单及加载路径: 点击查看

----------

1-开发教程简介

MindPlus-用户库扩展-开发者文档

Mind+是一款基于Scratch3.0开发的青少年编程软件,支持arduino、micro:bit、掌控板等各种开源硬件,只需要拖动图形化程序块即可完成编程,还可以使用python/c/c++等高级编程语言,让大家轻松体验创造的乐趣。

提示:尽管用户库增加非常简单,但依然建议有一定代码基础的用户进行操作,若有需要增加的模块而不懂代码,依然可以给官方反馈需要增加的模块。

使用用户库请先升级Mind+到V1.6.2 RC2.0及以上版本。

----------

2-用户库文件结构

└─newExtensions                    // 项目名称
    │  config.json                 // 本用户库的配置文件
    │  LICENSE.TXT                 // 许可证说明
    │  README.md                   // 文档说明
    │
    └─arduinoC                     // arduino模式用户库根目录
        │  main.ts                 // 图形块描述文件
        │
        ├─libraries                // arduino库文件,列出本扩展库所有需要引用的.c或.h或.cpp文件
        │  └─oled12864
        │          oled12864.cpp
        │          oled12864.h
        │          qrcode.c
        │          qrcode.h
        │
        ├─_images                  // 图片文件
        │      featured.png        // MindPlus扩展库展示图片
        │      icon.svg            // MindPlus中图形块上的图标文件
        │
        ├─_locales                 // 翻译文件,支持多国语言
        │      zh-cn.json
        │      en.json
        │
        └─_menus                   // 下拉菜单参数,每个板子可以独立设置
                leonardo.json
                uno.json
                nano.json
                mega2560.json
                microbit.json
                mpython.json

扩展库文件架构图

----------

3-文件说明

3.1-config.json配置文件

{
    "name": {
        "zh-cn": "OLED-12864显示屏(测试)",
        "en": "OLED-12864 screen(Test)"
    },
    "description": {
        "zh-cn": "小体积显示屏,可用于智能穿戴设备的显示器",
        "en": "I2C OLED-2864 Display Module"
    },
    "author": "DFRobot",
    "email": "MindPlus@dfrobot.com",
    "license": "MIT",
    "isTest": false,"备注":"此字段已删除,自动判断,不需要"
    "isBoard": false,
    "id": "oled12864",
    "platform": ["win", "mac", "web"],
    "asset": {
        "arduinoC": {
            "dir": "arduinoC/",
            "version": "0.0.1",
            "board": ["microbit", "esp32"],
            "main": "main.ts",
            "files": ["备注":"此字段自动生成,调试时不需要填写"
                "_locales/zh-cn.json","备注":"此字段自动生成,不需要"
                "_images/icon.svg","备注":"此字段自动生成,不需要"
                "libraries/oled12864/oled12864.cpp","备注":"此字段自动生成,不需要"
                "libraries/oled12864/oled12864.h","备注":"此字段自动生成,不需要"
                "libraries/oled12864/qrcode.c","备注":"此字段自动生成,不需要"
                "libraries/oled12864/qrcode.h""备注":"此字段自动生成,不需要"
            ]
        }
    }
}

详细说明:

  • name: 名称。模块显示在扩展库中的标题名称。
  • description: 描述。模块显示在扩展库中的描述。
  • author: 作者名。请使用英文字母表示。
  • email: 邮箱。当版本更新需要修改用户库或用户反馈,将通过邮件通知开发者(预留功能)
  • license: 许可证类型。参考链接
  • isTest: 调试模式。True打开测试模式:每次编译都会重新构建静态文件(用于调试);False关闭测试模式:只会在第一次编译才会构建静态文件。建议开发者在调试过程中设置为True,在导出发布时设置为False。 注:从1.6.2RC2.0开始删除此字段,根据加载库方法自动判断模式(从本地解压导入config.json为调试模式则有调试标志及刷新按钮,以zip或从网络加载为非调试模式则无标志及按钮)。
  • isBoard: 主控。当前扩展是否为主控(预留功能,统一为false)
  • id: 模块区分号。同一作者的不同模块需要设置不同的id,建议使用英文和数字符号命名。
  • platform: 支持平台。有三个选项:"win", "mac", "web",分别表示Mind的windows桌面版,mac桌面版,网页版,当前仅支持win。
  • asset: 各模式配置。当前仅支持上传模式的arduino C模式。
  • dir: 指定模式路径。/不能遗漏,例如:"dir": "arduinoC/",不建议修改。
  • version: 版本信息。三个数字,从小到大,例如:"0.0.1",建议每次发布都增加一位小数,依次从小到大增加(版本控制功能预留)。
  • board: 指定支持的主控,主控对应字段见下文“主控列表”。请确认测试通过后添加对应支持主控。若当前主控板不支持或模式不支持,则用户库右上角会显示“不可用”
  • main: block描述文件的文件名。需要是ts后缀文件,名称自定义,需要在对应路径下,例如:main.ts
  • files: 包含所需文件的路径,以便加载。 注:从1.6.2RC2.0开始删除此字段,编译和导出库时自动添加相关文件。

主控列表

主控 类型 名称
UNO 主控 arduino
Nano 主控 arduinonano
Leonardo 主控 leonardo
Micro:Bit 主控 microbit
掌控 主控 esp32
Mega2560 主控 mega2560
Vortex 套件 vortex
Romeo 套件 romeo
UNOR3 套件 arduinounor3
Max:Bot 套件 maxbot
麦昆 套件 maqueen
Max 套件 max

----------

3.2-main.ts描述文件总述

文件内容结构


enum xxxx {
   //% 引脚描述内容定义,需要翻译的菜单项需要定义到menu文件中
   //% 引脚生成代码定义
}


//% color="#xxxx"   整个扩展block的外观定义,通过 //% 后的描述内容定义
namespace xxxx {  

    //% block="xxx [xxx]" blockType="xxx" 第一个block的外观定义描述内容  
    //% block其他描述内容 
    export function xxxx(parameter: any, block: any) {  //单个block的生成代码定义,通过函数描述生成代码的位置及内容
        //生成的代码位置及内容描述
    }

    //% block="xxx [xxx]" blockType="xxx" 第二个block的外观定义描述内容 
    //% block其他描述内容 
    export function xxxx(parameter: any, block: any) {
       //生成的代码位置及内容描述
    }

    //% block="xxx [xxx]" blockType="xxx" 第N个block的外观定义描述内容
    //% block其他描述内容 
    export function xxxx(parameter: any, block: any) {
       //生成的代码位置及内容描述
    }

}

以一个block的定义为例说明

main.ts中的代码如下:

//% block="when press [BUTTON]" blockType="hat"
//% BUTTON.shadow="dropdown" BUTTON.options="BTN" BUTTON.defl="BTN.A"
export function myBlock(parameter: any, block: any) {
    let button = parameter.BUTTON.code;
    Generator.addInclude('Mylibraray', '#include <Mylibraray.h>');
    Generator.addObject(`libraray`, `MY_Libraray`, `libraray;`);
    Generator.addEvent("functionName", "String", "functionName", "String message, int8_t error", true);
    Generator.addSetup("libraray.begin", `libraray.begin(${button});`);
    Generator.addSetup(`libraray.callback`, `libraray.callback(functionName);`);
    Generator.addCode('libraray.start();')
}

效果:

  • 生成的block:
    生成block示例
  • 生成的代码:
/*!
 * MindPlus
 * microbit
 *
 */
#include <Mylibraray.h>

// 函数声明
String functionName(String message, int8_t error);
// 创建对象
MY_Libraray libraray;


// 主程序开始
void setup() {
    libraray.begin(A);
    libraray.callback(functionName);
    libraray.start();
}
void loop() {

}

// 事件回调函数
String functionName(String message, int8_t error) {

}

3.2.1-block外观定义

描述规则

描述命令必须包含在//%描述符后。

命令 含义 作用位置 可选参数
color 设置颜色 namespace及block 24位真彩色
iconWidth icon图标宽度 namespace 默认40
iconHeight icon图标高度 namespace 默认40
board 指定当前图形块支持的主控或套件
多个用逗号隔开
block arduino、leonardo、microbit、esp32、arduinonano、mega2560、vortex、romeo、 arduinounor3、maxbot、maqueen、max
block block描述 block 自定义 例如:xxx[A]xxx
blockType block类型 block hat:帽子形 command:方形 reporter:圆形 boolean:菱形
shadow 输入框类型 输入框 string:文本 dropdown:下拉不可拖入 dropdownRound:下拉可拖入 boolean:布尔 range:范围 number:数字
defl 设置默认值 输入框 自定义
params.min 设置最小值 range型输入框 自定义
params.max 设置最大值 range型输入框 自定义
options 指定下拉菜单内容 菜单型输入框 自定义

描述内容限制

  • block的描述中有些是必选的,有些是可选的参数描述,详情参考下表:
    ● 表示必需有此参数
    ⭕ 表示此参数为可选
    \ 表示此无需此参数
参数字段 namespace
命名空间
block
积木定义
string
文本输入框
number
数字输入框
range
数字范围输入框
boolean
布尔输入框
dropdown
下拉菜单
dropdownRound
可拖入下拉菜单
color \ \ \ \ \ \ \
iconWidth \ \ \ \ \ \ \
iconHeight \ \ \ \ \ \ \
block \ \ \ \ \ \ \
blockType \ \ \ \ \ \ \
shadow \ \
defl \ \
params.min \ \ \ \ \ \ \
params.max \ \ \ \ \ \ \
options \ \ \ \ \ \
block \ \ \ \ \ \ \

namespace命名空间

在namespace前面的描述词可以指定整个用户库的颜色和icon信息,所有的block定义都需要在namespace大括号中。

//% color="#AA278D" iconWidth=50 iconHeight=40
namespace module {
    ...
}

创建一个TypeScript命名空间,所有的图形块都写在里面,还可以设置模块的整体颜色以及icon的尺寸,对于图形风格设置应该包含在//%描述符中。所有的风格设置不是必须的,如果没有设置这些参数,系统将会按照默认的风格展示,//%所包含的内容可以写在一行或多行。

  • color: 设置图形块颜色,RGB24位真彩。
  • iconWidth: 设置icon显示宽度。
  • iconHeight: 设置icon显示高度,icon要求svg格式,图片应该放在_images文件夹根目录。

blockType

积木类型

通过blockType关键词可以设置block的整体外观。

//% block="set the line width to [WIDTH] pixels" blockType="command"
export function setBrightness(parameter: any, block: any) {
    ...
}

定义一个方形的图形块,//%所包含的内容可以写在一行或多行。

  • block: 一个图形块的完整描述,也是这个图形块的默认显示语言,[]所包含的内容为输入框的名称。
  • blockType: 设置外观形状,可选参数有hat,command,boolean,reporter
block外观 blockType值 外观
hat 帽子型
command 方形
reporter 圆形
boolean 菱形

shadow输入框

  • 输入框由shadow关键词定义,总共有7种类型:string:文本 dropdown:下拉不可拖入 dropdownRound:下拉可拖入 boolean:布尔 range:范围 number:数字
  • 如下代码使用一个block展示所有输入类型。
  • defl关键词指定默认显示的参数。
  • options关键词指定下拉菜单选项,在ts文件中定义一个枚举,如果需要区分主控,则需要将引脚定义放在_menus文件夹的根目录。
  • 在range型输入框种可指定 params.min: 最小值 和 params.max: 最大值。
//% block="所有输入库类型测试:文本型:[SS] 数字型 [SN]  布尔型:[SB] 范围型 [SR] 下拉不可拖入型:[SD] 下拉可拖入型:[SDR] "  blockType="command"
//% SS.shadow="string"   SS.defl="mind+"
//% SN.shadow="number"   SN.defl="123"
//% SB.shadow="boolean"  
//% SR.shadow="range"   SR.params.min=0    SR.params.max=10    SR.defl=5
//% SD.shadow="dropdown"   SD.options="BTN"     SD.defl="BTN.B"
//% SDR.shadow="dropdownRound"   SDR.options="LINE"     SDR.defl="LINE.1"

export function myBlock(parameter: any, block: any) {

}


3.2.2-Generator代码定义

Generator是提供生成代码的工具,它被内置在mindplus解释器中,通过Generator.来调用以控制生成代码的规范。

Generator.addInclude(id, code, cover)

在全局区添加include.

  • id: 标识符,
  • code: 代码
  • cover: 是否覆盖具有相同id的代码, 默认值为False。此参数可以实现多个block之间的联动,例如串口输出没有使用初始化block会默认生成波特率9600的代码,当使用了初始化波特率为115200时block会生成波特率115200的代码.

例如:

  • main.ts:Generator.addInclude("Mylibraray", "Mylibraray.h", True);
  • arduino.ino:#include <Mylibraray.h>"

Generator.addObject(id, type, code, cover)

在全局区添加对象

  • id: 标识符
  • type: class名称
  • code: 对象名称
  • cover: 是否覆盖具有相同id的代码, 默认值为false

例如:

  • main.ts代码:Generator.addObject(`libraray`, `MY_Libraray`, `libraray;`);
  • arduino.ino代码:MY_Libraray ibraray;

Generator.addSetup(id, code, cover)

在setup中添加代码。

  • id: 标识符
  • code: 代码
  • cover: 是否覆盖具有相同id的代码, 默认值为false

Generator.addCode(code)

在setup或者loop中添加代码,没有返回值的代码添加(一般为方形,帽子形)。

  • code: 代码。

Generator.addCode([code, level])

在setup或者loop中添加代码,有返回值的代码添加(一般为圆形,菱形)。

  • code:需要注册的代码。
  • level:运算符优先级,为代码添加括号。建议默认设置为Generator.ORDER_UNARY_POSTFIX。 例如:Generator.addCode([libraray.read()", Generator.ORDER_UNARY_POSTFIX]);

Generator.addEvent(id, type, nam, args, cover)

全局区定义一个回调函数

  • id: 标识符
  • type: 返回值类型,遵从C++语言规范。
  • name: 函数名,遵从C++语言规范。
  • args: 函数参数,遵从C++语言规范。
  • cover: 是否覆盖具有相同id的代码, 默认值为false 例如:Generator.addEvent("addEvent", "void", "function", "int x,int y");

运算符优先级

命令 级别 适用范围
Generator.ORDER_UNARY_POSTFIX 1 expr++ expr-- () [] .
Generator.ORDER_UNARY_PREFIX 2 -expr !expr ~expr ++expr --expr
Generator.ORDER_MULTIPLICATIVE 3 * / % ~/
Generator.ORDER_ADDITIVE 4 + -
Generator.ORDER_SHIFT 5 << >>
Generator.ORDER_RELATIONAL 6 >= > <= <
Generator.ORDER_EQUALITY 7 == != === !==
Generator.ORDER_BITWISE_AND 8 &
Generator.ORDER_BITWISE_XOR 9 ^
Generator.ORDER_BITWISE_OR 10 |
Generator.ORDER_LOGICAL_AND 11 &&
Generator.ORDER_LOGICAL_OR 12 ||
Generator.ORDER_CONDITIONAL 13 expr ? expr : expr
Generator.ORDER_ASSIGNMENT 14 = *= /= ~/= %= += -= <<= >>= &= ^=
* 数字越小级别越高

Generator.board

此代码可以返回当前选择的主控板型号,根据此可以实现同一block在不同主控板生成不同代码。

例如:

if(Generator.board === 'arduino'){//如果是arduinouno板,生成如下代码
     Generator.addSetup("GTSerialSetup",`${ser}.begin(9600);`);
}else if(Generator.board === 'esp32'){//如果是掌控板,生成如下代码
    Generator.addSetup("GTSerialSetup",`${ser}.begin(9600,${rx}, ${tx});`);
}

主控列表

主控 类型 返回字段
UNO 主控 arduino
Nano 主控 arduinonano
Leonardo 主控 leonardo
Micro:Bit 主控 microbit
掌控 主控 esp32
Mega2560 主控 mega2560
Vortex 套件 vortex
Romeo 套件 romeo
UNOR3 套件 arduinounor3
Max:Bot 套件 maxbot
麦昆 套件 maqueen
Max 套件 max

3.2.3-parameter传入参数

parameter是shadow传入参数,它被内置在mindplus解释器中,通过parameter.来调用获取shadow动态传入的参数。

例如:

    //% block="show [STR] on the [LINE] line" blockType="command"
    //% STR.shadow="string" STR.defl=hello
    //% LINE.shadow="dropdownRound" LINE.options="LINE" LINE.defl="LINE.1"
    export function println(parameter: any, block: any) {
        let str = parameter.STR.code
        let line = parameter.LINE.code
        Generator.addInclude('oled12864', '#include <oled12864.h>');
        Generator.addObject(`myoled`, `OLED_12864`, `myoled;`);
        Generator.addSetup(`myoled.begin`, `myoled.begin();`);
        Generator.addCode(`myoled.setCursorLine(${line});\n\tmyoled.printLine(${str});`);
    }

其中,parameter.STR.code即可获取STR这个输入框输入的内容。

目前parameter有四个输入参数可选,根据此4个参数,可以灵活调整生成的代码。

  1. code : 生成的代码
  2. parType : 传入参数类型
  3. codeType : 生成代码的数据类型
  4. checkType : 拖入参数类型限制

----------

3.3-资源文件夹

3.3.1-_images

此文件可放置图片类的资源文件。

  • featured.png 扩展库界面图片,名称不可修改,600*374分辨率的png图片。
  • icon.svg block上显示的图标文件,名称不可修改,svg格式矢量图,内容尽量精简,推荐白色icon。
    建议使用inkscape或AI等软件制作,也可从阿里巴巴矢量图标库iconfont等现成的图标库下载。

3.3.1-_locales

  • 根据文件名对应不同的语言,若没有对应语言的翻译文件则以main.ts中block描述代码中的内容直接显示。
  • 此文件夹下需要用到的文件路径需要在config.json中的file字段下填写。 注:从1.6.2RC2.0开始删除files字段,编译和导出库时自动添加相关文件,可以无需手动添加。
    "files": [
                  "_locales/zh-cn.json",
                  "_images/icon.svg",
                  "libraries/oled12864/oled12864.cpp",
                  "libraries/oled12864/oled12864.h",
                  "libraries/oled12864/qrcode.c",
                  "libraries/oled12864/qrcode.h"
              ]
  • block及menu都可以定义。
  • json格式,每一行格式为:
    "用户库名称.函数名|block":"翻译内容[菜单项]",
    或菜单项则为:
    "用户库名称.菜单名.菜单项|menu":"翻译内容",
语言文件名 对应语言
zh-cn.json 简体中文
es-419.json 西班牙文(南美)
fr.json 法文
ko.json 韩文
th.json 泰文
tr.json 土耳其文
mn.json 蒙文

3.3.1-_menus

  • 此文件夹中放置各种不同板子对应的下拉菜单内容。

  • 此文件夹下需要用到的文件路径需要在config.json中的file字段下填写。 注:从1.6.2RC2.0开始删除files字段,编译和导出库时自动添加相关文件,可以无需手动添加。

    "files": [
                  "_locales/zh-cn.json",
                  "_images/icon.svg",
                  "libraries/oled12864/oled12864.cpp",
                  "libraries/oled12864/oled12864.h",
                  "libraries/oled12864/qrcode.c",
                  "libraries/oled12864/qrcode.h"
              ]
  • 每个主控板一个json文件,文件名以板子命名,不可修改,格式为json格式。

  • menu字段对应菜单项:["下拉block中显示的内容","生成代码获得的内容"]

  • default_函数名_下拉字段名称 可以设置默认下拉引脚

  • 以下为OLED12864示例库中的microbit.json内容:

    {
      "PINX": {
          "menu":    [["P0", "0"], ["P1", "1"], ["P2", "2"]],
          "default_setBrightness_TXPIN": "1",
          "default_setBrightness_RXPIN": "2"
      },
      "MENU": {
          "menu":    [["A", "0"], ["B", "1"], ["C", "2"]],
          "default_setMenu_MENU":"2",
      }
    }

3.3.1-libraries

  • 此文件放置生成代码需要调用的arduino库文件,如果不需要库文件,需要将libraries文件夹删除。

----------

4-第一个用户库示例

目标

完成一个OLED显示库,实现高级功能。

准备

  • 文本编辑器:推荐VS Code。
  • libraris:如果需要用到库则需要准备。
  • block设计:根据功能先预想block应该如何呈现。
  • 图片设计:准备一张600*372像素的png图片。
  • icon设计: 可以去网上搜索免费的icon,也可以使用inkscape或AI等软件自行设计。

扩展库文件架构图

步骤

(详情内容参考示例库: https://gitee.com/dfrobot/ext-oled12864.git )

  1. 编辑config.json配置文件。配置扩展库信息。参考本文档的“3.1-config.json配置文件”部分进行配置。
  2. 编辑main.ts描述文件。配置block外观。参考本文档的“3.2.1-block外观定义”部分进行配置。
  3. 编辑main.ts描述文件。配置block生成的代码。参考本文档的“3.2.2-Generator代码定义”部分进行配置。
  4. 根据main.ts的需要编辑_menus、_locales菜单文件。参考本文档的“3.2.1-block外观定义”部分进行配置。
  5. 将对应文件放入_images,librires文件。参考本文档的“3.2.1-block外观定义”部分进行配置。

测试

  1. 功能测试(通过本地加载config.json可以更新库),查看生成的block是否符合预期,查看生成的代码是否符合预期,查看编译是否通过。
  2. 调整config.json的主板支持类型,测试不同主控板下的适应性(注意需要编译通过)。

导出分享

  1. 调试完成后,编写README.md文件(以markdown格式编辑本扩展库的教程)。
  2. 右键扩展库导出用户库为.mpext文件,如果上传git,文件名不要修改否则会出错。
  3. 分享(推荐分享到 Mind+社区):
    • 本地加载:直接分享给其他用户加载.mpext(注意不要解压从本地上传,否则是调试模式,从本地应该直接选择.mpext加载打开)。
    • 网络加载:将.mpext文件导出到与config.json同级目录下,通过git将整个文件夹上传到github或者gitee(码云) (gith教程),将git链接分享给其他用户加载。

** 注:通过git分享时,1.6.2RC2.0需要将导出的.mpext文件(可以zip解压提取)中的config.json和libraries.zip放到开发文件夹对应位置,然后上传git,否则会导致加载出错。(后续版本将直接加载mpext文件无需此操作,注意上传git时mpext文件名不要修改) **

加载方式

----------

5-常见问题

常见问题
问题描述: 用户库显示“不可用” :
解决办法: 说明当前用户库不支持当前所在的模式(上传/实时)、代码(arduinoC/micropython),或主控板。

常见问题
问题描述: 下拉菜单切换,生成代码无法切换是为何?
解决办法: 使用字符串拼接符号${}符号实现下拉菜单生成代码的切换。

常见问题
问题描述: 需要控制一个函数代码生成在setup中,参数根据用户选择的下拉可以生成多条,但是setup同一个id只能生成一条代码?
解决办法: 可以将下拉菜单的输入项作为id,这样选择不同的下拉就是不同的id,实现生成多条代码。

常见问题
问题描述: main.ts的block没有错误,导入之后输入框阴影无法输入。
解决办法: 检查namespace命名是否与config中模块id相同,尝试删除用户库,再重新导入。

常见问题
问题描述: main.ts的block没有错误,导入之后输入框阴影无法输入。
解决办法: 检查namespace是否与config用户id相同,尝试删除用户库,再重新导入。

常见问题
问题描述: Arduino的Cpp库中如何根据microbit、掌控板、arduino区分生成代码?
解决办法: 使用宏定义区分,如下:
#if   defined(NRF5)
//主控板选择microbit时编译器编译的代码
#elif defined (ESP_PLATFORM)
//主控板选择掌控板时编译器编译的代码
#else
//主控板为其他板时编译器编译的代码
#endif

如有问题,可以加入我们的官方QQ群或通过论坛、邮件反馈问题。