小MU视觉传感器

概述

打开智能时代,从视觉开始。一款内置深度学习引擎的图像识别传感器来了,拥有和四枚一元硬币大小相当的小巧体积,采用30W广角镜头,含有多种视觉算法,能够实现机器人自主智能(比如寻球投篮,沿着箭头指示走完规定路线等),让机器人面对环境中的随机事件时能自主触发适合的行为。 传感器可以识别多种目标物体,例如颜色检测,球体检测,人体检测,卡片识别等,检测结果可通过UART或I2C方式进行输出。内置算法均在本地处理,无需联网就可进行图像识别,而且通过板载USB串口即可实现传感器模块的参数设定和固件更新,支持UART,I2C,WIFI通讯方式。适用于Arduino及micro:bit嵌入式平台,提供图形化编程软件Mind+的支持,无论你是哪个平台的创客爱好者,我们都能让你体验到它的能力。 通过小MU视觉传感器可完成一些智能化应用,比如智能打印扫描小车、智能无人车、寻球投篮机器人等,可广泛应用于智能玩具、人工智能教具、创客产品等领域。 图像识别是对光源、色彩、背景、物体移动速度等因素十分敏感的技术,使用环境的差异会对图像检测结果将产生不同的影响,为了获取较好的识别结果:

  1. 避免在过暗、过亮、强逆光的环境下使用,比如昏暗的房间,具有强烈光亮差别的窗边等;
  2. 避免让灯光或强烈阳光直射目标物体,避免造成物体反光;
  3. 避免在彩色灯光或可变换的灯光下使用,稳定均匀的白色是最好的光源;
  4. 避免正对光源使用;
  5. 颜色敏感型算法不要在有近似颜色的背景下使用,比如绿色网球不要在绿色地毯上使用;
  6. 避免在有类似目标物体的环境下使用,避免误报,比如球体检测旁边有一个橙子;

⚠注意:本传感器支持Mind+图形化编程,详细教程见本页面后续章节。

特性

小MU视觉传感器具有如下优点:

  1. 能够做出丰富多样的视觉课程应用
    1. 智能打印扫描小车
    2. 智能无人车
    3. 寻球投篮机器人等
  2. 体积小巧,功耗极低
  3. 易于使用:支持UART,I2C,WIFI通讯方式,适用于Arduino及micro:bit嵌入式平台
  4. 应用广泛
  5. 安全可靠,无需网络:所有视觉识别算法都于本地进行处理,无须联网,不受网络状况所限制,无需担忧隐私泄露

产品参数

详细教程见如下文档: WIFI图传与运动轨迹检测.pdf

引脚说明

编号 功能描述
G 地(GND)
V 电源输入(兼容3.3V和5V)
TX 串口发送端
RX 串口接收端
SCL 控制线
SDA 数据线

分类标签

人体识别

无分类标签

球体识别

分类标签 目标物体
1 2
橙色乒乓球 绿色网球

颜色识别

分类标签 目标物体 分类标签 目标物体
1 黑色(深灰色) 2 白色(浅灰色)
3 红色 4 黄色(橙色)
5 绿色 6 青色(蓝绿色)
7 蓝色 8 紫色
0 未知 / /

卡片识别

图形卡片

分类标签 目标物体 分类标签 目标物体
1 对号图案 2 叉号图案
3 圆形图案 4 方形图案
5 三角形图案 0 无效

交通卡片

分类标签 目标物体 分类标签 目标物体
1 前进 2 左转
3 右转 4 掉头
5 停止 0 无效

数字卡片

分类标签 目标物体 分类标签 目标物体
1 数字1 2 数字2
3 数字3 4 数字4
5 数字5 6 数字6
7 数字7 8 数字8
9 数字9 0 数字0

输出模式及地址选择

传感器有UART和I2C两种输出模式,不同模式下需通过拨码开关进行调整,开关下方标有Output的为输出模式拨码开关 传感器有4种地址可选择,地址范围为0x60-0x63,该范围内的地址在两种模式下通用,不同地址需通过拨码开关进行调整,开关下方标有Address的为地址拨码开关

输出模式选择

采用 2 位拨码开关来选择信号输出类型,定义见下表:

拨码1 wifi开关 拨码2 信号输出类型
0 禁止使用Wifi功能* 0 UART通讯方式
1 允许使用Wifi功能* 1 I2C通讯方式

注1:*所示功能,当前版本尚不具备 注2:向上拨动为1,向下拨动为0

地址选择

采用 2 位拨码开关来选择信号输出类型,定义见下表:

拨码1 拨码2 设备地址
0 0 0x60
0 1 0x61
1 0 0x62
1 1 0x63

注1:UART模式下可使用0x00作为广播地址 注2:向上拨动为1,向下拨动为0

模块通讯协议

协议格式

1 2 3 4 5 6 7
START LEN ADDR CMD DATA CHK END

START:起始码,始终为0xFF LEN:长度,从起始码到结束码所有的字节数 ADDR:设备地址,范围0x60~0x63,初次使用默认地址为0x60,特别的:0x00为广播地址,所有设备都会接收 CMD:指令码/应答码 DATA:数据,详见各指令码介绍 CHK:校验码,从START至DATA所有字节累加求和 例:FF 08 60 01 20 03 8B ED 其中8B为校验码,0xFF+0x08+0x60+0x01+0x20+0x03 = 0x8B END:结束码,始终为0xED

应答码

应答正确 应答错误 未知错误 超时错误 校验错误 长度错误 指令错误 地址错误 参数错误 写入错误
0xE0 0xE1 0xE2 0xE3 0xE4 0xE5 0xE6 0xE7 0xE8 0xE9

指令码

写寄存器 读寄存器 数据报文 请求报文
0x01 0x02 0x11 0x12

以上均是发送指令的代码,操作成功或操作失败会返回相对应的应答码

使用说明

使用步骤

  1. 设置 Address 地址
  2. 设置 Output 模式
  3. 版本校验
  4. 配置硬件参数
  5. 配置算法参数
  6. 读取检测结果

设置地址

通过拨码开关来设定 MU 的设备地址,详见6.2地址选择

设置输出模式

通过拨码开关来设定通讯方式,详见6.1输出模式选择 注:需要在设定完 Address 和 Output 之后再上电,已经上电的则需要按 reset 重启

版本校验

查询 PROTOCOL_VER 和 FIRMWARE_VER 寄存器来判断固件是否与手册一致,不一致则可能导致寄存器功能不同或算法版本区别

设置硬件参数

根据实际应用场景和需求寄存器相应的寄存器参数,主要涉及 CAMERA_CONF1,LED1,LED2 寄存器。

设置算法参数

每个算法 VISION_ID 都具有相应的寄存器,在设置算法参数前需要先设置 VISION_ID(即选取识别对象类别)

读取检测结果

可通过UART或I2C读取检测结果

算法列表

  1. id:算法类型编号
  2. num:目标物体数量
  3. x:水平中心坐标
  4. y:垂直中心坐标
  5. width:物体边缘宽度
  6. height:物体边缘高度
  7. label:分类标签编号,部分算法适用,详见分类标签

UART模式下Arduino使用教程

准备

点击下载库文件库文件和示例

接线图

MU连线图.png

样例代码

/*!
 * @file getTargetPosition.ino
 * @brief Examples of get target position.
 * @copyright   Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com)
 * @license     The MIT license (MIT)
 * @author DFRobot
 * @version  V1.0
 * @date  2023-06-28
 * @https://github.com/DFRobot/DFRobot_MuVisionSensor
 */
#include <DFRobot_MuVisionSensor.h>
#include <Wire.h>
#include <SoftwareSerial.h>

/*
 * Choose communication mode define here:
 *    I2C_MODE    : I2C mode, default pin: MU_SDA <==> ARDUINO_SDA, MU_SCL <==> ARDUINO_SCL
 *    SERIAL_MODE : Serial mode, default pin: MU_TX <==> ARDUINO_PIN3, MU_RX <==> ARDUINO_PIN2
 */
#define I2C_MODE
//#define SERIAL_MODE

/*
 * Choose MU address here: 0x60, 0x61, 0x62, 0x63
 */
#define MU_ADDRESS    0x60

/*
 * Change vision type here, VISION_TYPE:VISION_COLOR_DETECT
 *                                      VISION_COLOR_RECOGNITION
 *                                      VISION_BALL_DETECT
 *                                      VISION_BODY_DETECT
 *                                      VISION_SHAPE_CARD_DETECT
 *                                      VISION_TRAFFIC_CARD_DETECT
 *                                      VISION_NUM_CARD_DETECT
 */
#define VISION_TYPE     VISION_BALL_DETECT

#ifdef SERIAL_MODE
#define TX_PIN 2
#define RX_PIN 3
SoftwareSerial mySerial(RX_PIN, TX_PIN);
#endif
DFRobot_MuVisionSensor Mu(MU_ADDRESS);

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  delay(500);

#ifdef I2C_MODE
  Wire.begin();
  Mu.begin(&Wire);              // initialized MU on I2C port
#elif defined SERIAL_MODE
  mySerial.begin(9600);
  Mu.begin(&mySerial);          // initialized MU on soft serial port
#endif

  Mu.visionBegin(VISION_TYPE);  // enable vision

  if (VISION_TYPE == VISION_COLOR_DETECT
      || VISION_TYPE == VISION_COLOR_RECOGNITION) {
    Mu.cameraSetAwb(kLockWhiteBalance); // lock AWB
    if (VISION_TYPE == VISION_COLOR_RECOGNITION) {
      Mu.write(VISION_TYPE, kXValue, 50);
      Mu.write(VISION_TYPE, kYValue, 50);
      Mu.write(VISION_TYPE, kWidthValue, 5);
      Mu.write(VISION_TYPE, kHeightValue, 5);
    }
  }
}

void loop() {
  // put your main code here, to run repeatedly:
  long timeStart = millis();

  // read result
  if (Mu.getValue(VISION_TYPE, kStatus)) {
    Serial.println("vision detected:");
    switch (VISION_TYPE) {
      case VISION_BALL_DETECT:
      case VISION_BODY_DETECT:
      case VISION_SHAPE_CARD_DETECT:
      case VISION_TRAFFIC_CARD_DETECT:
      case VISION_NUM_CARD_DETECT:
      case VISION_COLOR_DETECT:
        Serial.print("x = ");
        Serial.println(Mu.getValue(VISION_TYPE, kXValue));
        Serial.print("y = ");
        Serial.println(Mu.getValue(VISION_TYPE, kYValue));
        Serial.print("width = ");
        Serial.println(Mu.getValue(VISION_TYPE, kWidthValue));
        Serial.print("height = ");
        Serial.println(Mu.getValue(VISION_TYPE, kHeightValue));
        if (VISION_TYPE != VISION_COLOR_DETECT) {
          Serial.print("label = ");
          Serial.println(Mu.getValue(VISION_TYPE, kLabel));
        } else {
          Serial.print("color = ");
          Serial.println(Mu.getValue(VISION_TYPE, kLabel));
        }
        break;
      case VISION_COLOR_RECOGNITION:
        Serial.print("r = ");
        Serial.println(Mu.getValue(VISION_TYPE, kRValue));
        Serial.print("g = ");
        Serial.println(Mu.getValue(VISION_TYPE, kGValue));
        Serial.print("b = ");
        Serial.println(Mu.getValue(VISION_TYPE, kBValue));
        Serial.print("color = ");
        Serial.println(Mu.getValue(VISION_TYPE, kLabel));
        break;
      default:
        break;
    }
  } else {
    Serial.println("vision undetected.");
  }
  Serial.print("fps = ");
  Serial.println(1000/(millis()-timeStart));
  Serial.println();
}

输出结果:识别颜色时可输出颜色的RGB值及颜色分类标签;识别其它目标时输出其中心坐标值和其所围成的区域大小 上述程序识别的是交通卡片,串口输出信息为卡片中心坐标,卡片外框大小及分类标签(即和识别卡片的下方label数值保持一致),识别其它类型需在程序#define VISION_TYPE处更换识别种类,方能识别其它物体。

I2C模式下Arduino使用教程

准备

接线图

MU连线图1.png

识别球体样例代码(乒乓球和网球)

/*!
 * @file ball.ino
 * @brief Examples of identifying ball.
 * @copyright   Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com)
 * @license     The MIT license (MIT)
 * @author [WWZ](Wenzheng.wang@dfrobot.com)
 * @version  V1.0
 * @date  2023-06-28
 * @https://github.com/DFRobot/DFRobot_MuVisionSensor
 */
#include <Wire.h>

#define MU_ADDRESS    0x60
#define PROTOCOL_VER  0x03
#define VISION_ID     0x03      // ball

// register define
#define REG_PROTOCOL_VER  0x01
#define REG_LED1_CONF     0x06
#define REG_LED2_CONF     0x07
#define REG_LED_LEVEL     0x08
#define REG_CAMERA_CONF1  0x10
#define REG_FRAME_CNT     0x1F
#define REG_VISION_ID     0x20
#define REG_VISION_CONF1  0x21
#define REG_PARAM_VALUE5  0x29
#define RESULT_NUM        0x34
#define RESULT_DATA1      0x40
#define RESULT_DATA2      0x41
#define RESULT_DATA3      0x42
#define RESULT_DATA4      0x43
#define RESULT_DATA5      0x44
// color
#define MU_COLOR_BLACK                0x01U
#define MU_COLOR_WHITE                0x02U
#define MU_COLOR_RED                  0x03U
#define MU_COLOR_YELLOW               0x04U
#define MU_COLOR_GREEN                0x05U
#define MU_COLOR_CYAN                 0x06U
#define MU_COLOR_BLUE                 0x07U
#define MU_COLOR_PURPLE               0x08U

int i2cRead8(uint8_t reg) {
  Wire.beginTransmission(MU_ADDRESS);
  Wire.write(reg);
  Wire.endTransmission();

  Wire.requestFrom(MU_ADDRESS, 1);
  return Wire.read();
}
void i2cWrite8(const uint8_t reg, const uint8_t value) {
  Wire.beginTransmission(MU_ADDRESS);
  Wire.write(reg);
  Wire.write(value);
  Wire.endTransmission();
}

uint8_t reg[][2] = {
    { REG_VISION_ID,      VISION_ID }, // set vision type = vision_detect
    { REG_VISION_CONF1,   0x21 }, // vision begin
};
uint8_t frameCountLast = 0;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Wire.begin();
  delay(500);

  if (i2cRead8(REG_PROTOCOL_VER) == PROTOCOL_VER) {
    Serial.println("device initialized.");
  } else {
    Serial.println("fail to initialize device! Please check protocol version.");
  }
  for (uint32_t i = 0; i < sizeof(reg)/2; ++i) {
    i2cWrite8(reg[i][0], reg[i][1]);
  }
}

void loop() {
  // put your main code here, to run repeatedly:
  long timeStart = millis();
  int frameCount = 0;
  // waiting for update
  do {
    frameCount = i2cRead8(REG_FRAME_CNT);
  } while(frameCount == frameCountLast);
  frameCountLast = frameCount;

  i2cWrite8(REG_VISION_ID, VISION_ID);
  // read result
  if (i2cRead8(RESULT_NUM) > 0) {
    Serial.println("ball detected:");
    Serial.print("x = ");
    Serial.println(i2cRead8(RESULT_DATA1));
    Serial.print("y = ");
    Serial.println(i2cRead8(RESULT_DATA2));
    Serial.print("width = ");
    Serial.println(i2cRead8(RESULT_DATA3));
    Serial.print("height = ");
    Serial.println(i2cRead8(RESULT_DATA4));
    Serial.print("label = ");
    switch(i2cRead8(RESULT_DATA5)) {
      case 1:
        Serial.println("Ping-Pong ball");
        break;
      case 2:
        Serial.println("Tennis");
        break;
      default:
        break;
    }
  } else {
    Serial.println("ball undetected.");
  }
  Serial.print("fps = ");
  Serial.println(1000/(millis()-timeStart));
  Serial.println();
}

输出结果:可识别目标球体,通过串口可观察到球体的中心坐标,球体外边框大小,分类标签

识别人体样例代码(依据上半身轮廓)

/*!
 * @file body.ino
 * @brief Examples of identifying body.
 * @copyright   Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com)
 * @license     The MIT license (MIT)
 * @author DFRobot
 * @version  V1.0
 * @date  2023-06-28
 * @https://github.com/DFRobot/DFRobot_MuVisionSensor
 */
#include <Wire.h>

#define MU_ADDRESS    0x60
#define PROTOCOL_VER  0x03
#define VISION_ID     0x05      // body

// register define
#define REG_PROTOCOL_VER  0x01
#define REG_LED1_CONF     0x06
#define REG_LED2_CONF     0x07
#define REG_LED_LEVEL     0x08
#define REG_CAMERA_CONF1  0x10
#define REG_FRAME_CNT     0x1F
#define REG_VISION_ID     0x20
#define REG_VISION_CONF1  0x21
#define REG_PARAM_VALUE5  0x29
#define RESULT_NUM        0x34
#define RESULT_DATA1      0x40
#define RESULT_DATA2      0x41
#define RESULT_DATA3      0x42
#define RESULT_DATA4      0x43
#define RESULT_DATA5      0x44
// color
#define MU_COLOR_BLACK                0x01U
#define MU_COLOR_WHITE                0x02U
#define MU_COLOR_RED                  0x03U
#define MU_COLOR_YELLOW               0x04U
#define MU_COLOR_GREEN                0x05U
#define MU_COLOR_CYAN                 0x06U
#define MU_COLOR_BLUE                 0x07U
#define MU_COLOR_PURPLE               0x08U

int i2cRead8(uint8_t reg) {
  Wire.beginTransmission(MU_ADDRESS);
  Wire.write(reg);
  Wire.endTransmission();

  Wire.requestFrom(MU_ADDRESS, 1);
  return Wire.read();
}
void i2cWrite8(const uint8_t reg, const uint8_t value) {
  Wire.beginTransmission(MU_ADDRESS);
  Wire.write(reg);
  Wire.write(value);
  Wire.endTransmission();
}

uint8_t reg[][2] = {
    { REG_VISION_ID,      VISION_ID }, // set vision type = vision_detect
    { REG_VISION_CONF1,   0x21 }, // vision begin
};
uint8_t frameCountLast = 0;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Wire.begin();
  delay(500);

  if (i2cRead8(REG_PROTOCOL_VER) == PROTOCOL_VER) {
    Serial.println("device initialized.");
  } else {
    Serial.println("fail to initialize device! Please check protocol version.");
  }
  for (uint32_t i = 0; i < sizeof(reg)/2; ++i) {
    i2cWrite8(reg[i][0], reg[i][1]);
  }
}

void loop() {
  // put your main code here, to run repeatedly:
  long timeStart = millis();
  int frameCount = 0;
  // waiting for update
  do {
    frameCount = i2cRead8(REG_FRAME_CNT);
  } while(frameCount == frameCountLast);
  frameCountLast = frameCount;

  i2cWrite8(REG_VISION_ID, VISION_ID);
  // read result
  if (i2cRead8(RESULT_NUM) > 0) {
    Serial.println("body detected:");
    Serial.print("x = ");
    Serial.println(i2cRead8(RESULT_DATA1));
    Serial.print("y = ");
    Serial.println(i2cRead8(RESULT_DATA2));
    Serial.print("width = ");
    Serial.println(i2cRead8(RESULT_DATA3));
    Serial.print("height = ");
    Serial.println(i2cRead8(RESULT_DATA4));
  } else {
    Serial.println("body undetected.");
  }
  Serial.print("fps = ");
  Serial.println(1000/(millis()-timeStart));
  Serial.println();
}

输出结果:可识别人体,通过串口可观察到人体的中心坐标和所围成的大小,无分类标签

识别颜色样例代码

/*!
 * @file colorRecognition.ino
 * @brief Examples of color recognition.
 * @copyright   Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com)
 * @license     The MIT license (MIT)
 * @author DFRobot
 * @version  V1.0
 * @date  2023-06-28
 * @https://github.com/DFRobot/DFRobot_MuVisionSensor
 */
#include <Wire.h>

#define MU_ADDRESS    0x60
#define PROTOCOL_VER  0x03
#define VISION_ID     0x02

// register define
#define REG_PROTOCOL_VER  0x01
#define REG_LED1_CONF     0x06
#define REG_LED2_CONF     0x07
#define REG_LED_LEVEL     0x08
#define REG_CAMERA_CONF1  0x10
#define REG_FRAME_CNT     0x1F
#define REG_VISION_ID     0x20
#define REG_VISION_CONF1  0x21
#define REG_PARAM_VALUE1  0x25
#define REG_PARAM_VALUE2  0x26
#define REG_PARAM_VALUE3  0x27
#define REG_PARAM_VALUE4  0x28
#define RESULT_NUM        0x34
#define RESULT_DATA1      0x40
#define RESULT_DATA2      0x41
#define RESULT_DATA3      0x42
#define RESULT_DATA5      0x44
// color
#define MU_COLOR_BLACK                0x01U
#define MU_COLOR_WHITE                0x02U
#define MU_COLOR_RED                  0x03U
#define MU_COLOR_YELLOW               0x04U
#define MU_COLOR_GREEN                0x05U
#define MU_COLOR_CYAN                 0x06U
#define MU_COLOR_BLUE                 0x07U
#define MU_COLOR_PURPLE               0x08U

int i2cRead8(uint8_t reg) {
  Wire.beginTransmission(MU_ADDRESS);
  Wire.write(reg);
  Wire.endTransmission();

  Wire.requestFrom(MU_ADDRESS, 1);
  return Wire.read();
}
void i2cWrite8(const uint8_t reg, const uint8_t value) {
  Wire.beginTransmission(MU_ADDRESS);
  Wire.write(reg);
  Wire.write(value);
  Wire.endTransmission();
}

uint8_t reg[][2] = {
//    { REG_LED_LEVEL,      0x00 }, // LED will be closed automatically in this vision type.
//    { REG_LED1_CONF,      0x00 }, // LED1 color
//    { REG_LED2_CONF,      0x00 }, // LED2 color
    { REG_CAMERA_CONF1,   0x30 }, // lock AWB
    { REG_VISION_ID,      VISION_ID }, // set vision type = vision_recognition
    { REG_PARAM_VALUE1,   50 }, // x
    { REG_PARAM_VALUE2,   50 }, // y
//    { REG_PARAM_VALUE3,   5 }, // width
//    { REG_PARAM_VALUE4,   5 }, // height
    { REG_VISION_CONF1,   0x21 }, // vision begin
};
uint8_t frameCountLast = 0;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Wire.begin();
  delay(500);

  if (i2cRead8(REG_PROTOCOL_VER) == PROTOCOL_VER) {
    Serial.println("device initialized.");
  } else {
    Serial.println("fail to initialize device! Please check protocol version.");
  }
  for (uint32_t i = 0; i < sizeof(reg)/2; ++i) {
    i2cWrite8(reg[i][0], reg[i][1]);
  }
  delay(1000); // waiting for AWB lock.
}

void loop() {
  // put your main code here, to run repeatedly:
  long timeStart = millis();
  int frameCount = 0;
  // waiting for update
  do {
    frameCount = i2cRead8(REG_FRAME_CNT);
  } while(frameCount == frameCountLast);
  frameCountLast = frameCount;

  i2cWrite8(REG_VISION_ID, VISION_ID);
  // read result
  if (i2cRead8(RESULT_NUM) > 0) {
    Serial.println("color detected:");
    Serial.print("color = (");
    Serial.print(i2cRead8(RESULT_DATA1));
    Serial.print(",");
    Serial.print(i2cRead8(RESULT_DATA2));
    Serial.print(",");
    Serial.print(i2cRead8(RESULT_DATA3));
    Serial.print(")\nlabel = ");
    switch (i2cRead8(RESULT_DATA5)) {
      case 0:
        Serial.println("unknow color");
        break;
      case 1:
        Serial.println("black");
        break;
      case 2:
        Serial.println("white");
        break;
      case 3:
        Serial.println("red");
        break;
      case 4:
        Serial.println("yellow");
        break;
      case 5:
        Serial.println("green");
        break;
      case 6:
        Serial.println("cyan");
        break;
      case 7:
        Serial.println("blue");
        break;
      case 8:
        Serial.println("violet");
        break;
      default:
        break;
    }
  } else {
    Serial.println("color undetected.");
  }
  Serial.print("fps = ");
  Serial.println(1000/(millis()-timeStart));
  Serial.println();
}

输出结果:可识别相对应的颜色,通过串口可观察到目标区域的颜色 R,G,B 的平均值(0~255)及分类标签

识别卡片样例代码(仅限20张定制卡片)

/*!
 * @file card.ino
 * @brief Examples of identifying card.
 * @copyright   Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com)
 * @license     The MIT license (MIT)
 * @author DFRobot
 * @version  V1.0
 * @date  2023-06-28
 * @https://github.com/DFRobot/DFRobot_MuVisionSensor
 */
#include <Wire.h>

#define MU_ADDRESS    0x60
#define PROTOCOL_VER  0x03
#define VISION_ID     0x06      // shape card
//#define VISION_ID     0x07      // traffic card
//#define VISION_ID     0x08      // number card

// register define
#define REG_PROTOCOL_VER  0x01
#define REG_LED1_CONF     0x06
#define REG_LED2_CONF     0x07
#define REG_LED_LEVEL     0x08
#define REG_CAMERA_CONF1  0x10
#define REG_FRAME_CNT     0x1F
#define REG_VISION_ID     0x20
#define REG_VISION_CONF1  0x21
#define REG_PARAM_VALUE5  0x29
#define RESULT_NUM        0x34
#define RESULT_DATA1      0x40
#define RESULT_DATA2      0x41
#define RESULT_DATA3      0x42
#define RESULT_DATA4      0x43
#define RESULT_DATA5      0x44
// color
#define MU_COLOR_BLACK                0x01U
#define MU_COLOR_WHITE                0x02U
#define MU_COLOR_RED                  0x03U
#define MU_COLOR_YELLOW               0x04U
#define MU_COLOR_GREEN                0x05U
#define MU_COLOR_CYAN                 0x06U
#define MU_COLOR_BLUE                 0x07U
#define MU_COLOR_PURPLE               0x08U

int i2cRead8(uint8_t reg) {
  Wire.beginTransmission(MU_ADDRESS);
  Wire.write(reg);
  Wire.endTransmission();

  Wire.requestFrom(MU_ADDRESS, 1);
  return Wire.read();
}
void i2cWrite8(const uint8_t reg, const uint8_t value) {
  Wire.beginTransmission(MU_ADDRESS);
  Wire.write(reg);
  Wire.write(value);
  Wire.endTransmission();
}

uint8_t reg[][2] = {
    { REG_VISION_ID,      VISION_ID }, // set vision type = vision_detect
    { REG_VISION_CONF1,   0x21 }, // vision begin
};
uint8_t frameCountLast = 0;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Wire.begin();
  delay(500);

  if (i2cRead8(REG_PROTOCOL_VER) == PROTOCOL_VER) {
    Serial.println("device initialized.");
  } else {
    Serial.println("fail to initialize device! Please check protocol version.");
  }
  for (uint32_t i = 0; i < sizeof(reg)/2; ++i) {
    i2cWrite8(reg[i][0], reg[i][1]);
  }
}

void loop() {
  // put your main code here, to run repeatedly:
  long timeStart = millis();
  int frameCount = 0;
  // waiting for update
  do {
    frameCount = i2cRead8(REG_FRAME_CNT);
  } while(frameCount == frameCountLast);
  frameCountLast = frameCount;

  i2cWrite8(REG_VISION_ID, VISION_ID);
  // read result
  if (i2cRead8(RESULT_NUM) > 0) {
    Serial.println("card detected:");
    Serial.print("x = ");
    Serial.println(i2cRead8(RESULT_DATA1));
    Serial.print("y = ");
    Serial.println(i2cRead8(RESULT_DATA2));
    Serial.print("width = ");
    Serial.println(i2cRead8(RESULT_DATA3));
    Serial.print("height = ");
    Serial.println(i2cRead8(RESULT_DATA4));
    Serial.print("label = ");
    Serial.println(i2cRead8(RESULT_DATA5));
  } else {
    Serial.println("card undetected.");
  }
  Serial.print("fps = ");
  Serial.println(1000/(millis()-timeStart));
  Serial.println();
}

输出结果:可识别目标卡片,通过串口可观察到卡片中心坐标,卡片外框大小,分类标签

Mind+(基于Scratch3.0)图形化编程

  1. 下载及安装软件V1.5.6及以上版本。下载地址:https://mindplus.cc 详细教程:Mind+基础wiki教程-软件下载安装
  2. 切换到“上传模式”。 详细教程:Mind+基础wiki教程-上传模式编程流程
  3. “扩展”中选择“主控板”或“套件”中的“micro:bit”“掌控板”“麦昆”等你的产品。在“传感器”中搜索“摄像头”,加载“SEN0314 视觉摄像头” 。详细教程:Mind+基础wiki教程-加载扩展库流程
  1. 根据自己选择的产品,进行编程,如下图以micro:bit为例实现数字识别。
  1. 菜单“连接设备”,“上传到设备”
  2. 程序上传完毕后,使用配套的数字卡片对准摄像头,即可看到效果。 注意:output开关拨到1下2上,address开关拨到1下2 下。

更多图形化编程教程

DF创客社区用户提供了大量项目可供大家参考:

常见问题

如何升级固件?

Q1:为什么找不到教程中的“颜色检测”?

 A:从V1.6.0开始,原“颜色检测”的描述改为“色块检测”,因此使用“色块检测”即可。

Q2:上传完程序之后摄像头模块为什么没有任何反应?

A:如果使用了“恢复默认设置”可以尝试在这条程序后面跟一条“等待1秒”的程序以使恢复完成,上传完毕之后同时按下主控板和摄像头模块上的复位键复位。

更多问题及有趣的应用,可以 访问论坛 进行查阅或发帖!

更多

DFshopping_car1.png DFRobot商城购买链接