一、前言

        本章主包将手把手带大家入门亚博公司的K210摄像头,包括开发环境搭建到固件下载到神经网络训练以及与下位机进行串口通信,本章节适用范围包括但不仅限于电子设计大赛、课设、毕设等,后续将带领大家实现更多的K210功能。本章节主要参考资料为亚博公司官网给出的教程:亚博官网介绍

二、K210模块介绍

        K210是基于RISC-V精简指令集的一款MCU,在众多特色中,芯片架构包含了一个自研的神经网络硬件加速器KPU属于最大特色,可以高性能地进行卷积神经网络运算。在MCU的AI计算方面,K210芯片的算力非常给力,根据嘉楠官网的描述,K210的KPU算力能够达到0.8TFLOPS,这相当于什么水平呢?举个例子,最新树莓派4B的算力不到0.1TFLOPS,而以神经网络处理为卖点的Jetson Nano拥有128个CUDA单元,算力也仅仅是0.47TFLOPS。
        本章节使用的K210开发板使用的是亚博公司的K210模块,之所以使用他们家的是因为相比于其它家的k210,亚博家的K210模块不仅外观做的好看最主要的是生态好,官方资料比较齐全,相关的例程demo也可以直接到官网上查找。
模块正面

在这里插入图片描述

序号说明
1.按键K1硬件连接到IO16,可自定义按键功能
2.RGB灯可编程显示红、绿、蓝、白等颜色
3.TF卡槽用于插入TF卡,金手指朝向模块,保存程序和模型等文件
4.固定铜柱总共四个固定铜柱,M3尺寸
5.K210核心模组包含K210芯片最小运行系统
6.摄像头采集图像
7.模组接口连接K210核心模组和底板
8.RST按键复位按键,用于重启K210芯片
9.外扩串口连接其他串口设备,输出自定义数据
10.microUSB接口下载固件、串口调试、连接IDE等
11.CH340芯片与microUSB接口连接,将USB信号转化成TTL信号

三、开发环境搭建

        K210摄像头模块的开发环境主要用到了CanMV IDE这个软件,可以直接到亚博的官网进行下载:官方下载链接,选择下面红框中这个下载就行(如果打不开giyhub的话可以使用主包这个百度网盘:提取码12sd
在这里插入图片描述        下载完以后D盘找个空间一路下一步安装就行
在这里插入图片描述
下载完成以后打开的界面如图所示

在这里插入图片描述
将K210模块通过microUSB数据线连接到电脑USB口。然后点击CanMV IDE左下角连接按钮,绿色的按钮是运行按钮,需要等链接上模块以后再点击运行
在这里插入图片描述

四、固件烧录

这里需要用到两个固件,一个是亚博官方给出的固件
在这里插入图片描述
还有一个是maxipy给出的用于模型训练和部署的固件
在这里插入图片描述
可以使用kflash_gui进行烧录
在这里插入图片描述
烧录时候先进行擦除
在这里插入图片描述

然后切换到固件烧录模式,先烧录canmv_yahboom_v2.1.1.bin这个固件
在这里插入图片描述
然后这里注意!!!不要擦除直接在canmv_yahboom_v2.1.1.bin固件的基础上直接烧录maixpy_v0.5.1_106_g6d66d6e_minimum_with_ide_support.bin这个固件,这两个固件主包测试过了可以兼容

四、神经网络训练(以人脸检测为例)

K210神经网络训练主要使用的是Maixhub这个在线训练平台Maixhub这个平台可进行目标检测或者目标分类的任务训练,不过目前貌似只支持yolov2版本,这里主包以人脸识别目标检测任务为例,我们在训练前需要准备数据集,数据集的目录格式如下:
在这里插入图片描述
文件夹里要包含两个子文件夹,images用来存放图片
在这里插入图片描述
xml文件夹用来存放标注后的voc格式文件
在这里插入图片描述
images和xml文件夹里对应图片和标签文件的命名要一模一样!!,主包使用的标注软件是labelImg(这个网上教程很多随便找一个下载就行),把图片中的人脸都框出来,然后设置保存路径(一定要是VOC格式)
在这里插入图片描述
然后将两个文件夹压缩为.zip格式压缩包
在这里插入图片描述
然后打开maxihub这个网站,点击开始训练
在这里插入图片描述
然后点击新建数据集

在这里插入图片描述
然后选择以压缩包的形式上传数据集
在这里插入图片描述
maxihub网站上也可以进行数据标注,不过这里不推荐因为太卡了,还是建议在本地上标注完了再上传
现在就可以开始训练模型了!,返回首页以后点击新建训练
在这里插入图片描述
在这里插入图片描述
然后选择刚刚创建的数据集,点击确定
在这里插入图片描述
然后开始创建训练任务,选择nncase
在这里插入图片描述
训练完成后选择手动部署
在这里插入图片描述
下载模型后,我们只需要把下面两个文件放入到K210的sd卡中即可上电运行
在这里插入图片描述

五、和下位机串口通信

需要使用CH340模块连接模块的外置接口,引脚连接情况如下图所示。
在这里插入图片描述
K210模块提供的外置串口为串口1,RX为引脚6,TX为引脚7

from machine import UART
fm.register(7, fm.fpioa.UART1_TX, force=True)  # TX - P7
fm.register(6, fm.fpioa.UART1_RX, force=True)  # RX - P6
uart = UART(UART.UART1, 115200, timeout=1000)

可以通过类似下面的通信协议与单片机进行通信

packet = bytearray([0xF0, total, 0xFF])
uart.write(packet)

完整参考代码如下

import sensor, image, time, lcd
from maix import KPU
import gc
from machine import UART
from fpioa_manager import fm

# ---------- UART 初始化(按需修改引脚) ----------
def init_uart():
    # 默认示例将 UART1 TX -> 8, RX -> 6(可根据你的硬件修改)
    fm.register(8, fm.fpioa.UART1_TX, force=True)
    fm.register(6, fm.fpioa.UART1_RX, force=True)
    uart = UART(UART.UART1, 115200, 8, 0, 0, timeout=1000, read_buf_len=256)
    return uart

def send_detect_counts(uart, boxes, screen_width):
    # 只有检测到至少一个框时才发送报文
    if not boxes or len(boxes) == 0:
        return
    total = len(boxes)
    left = 0
    right = 0
    half = screen_width // 2  # 中线位置(中线算到右侧)
    for b in boxes:
        # b 的格式假设为 (x, y, w, h, ...),与原代码一致
        bx = int(b[0])
        bw = int(b[2])
        cx = bx + (bw // 2)
        if cx < half:
            left += 1
        else:
            right += 1
    # 限制为单字节(0-255)
    if left > 255: left = 255
    if right > 255: right = 255
    if total > 255: total = 255
    packet = bytearray([0xF0, left, right, total, 0xFF])
    try:
        uart.write(packet)
    except Exception as e:
        # 串口发送异常不要让程序崩溃,打印错误便于调试
        try:
            print("UART write error:", e)
        except:
            pass

# ---------- 相机与模型初始化 ----------
lcd.init()
sensor.reset()                      # Reset and initialize the sensor.
sensor.set_pixformat(sensor.RGB565) # Set pixel format to RGB565 (or GRAYSCALE)
sensor.set_framesize(sensor.QVGA)   # Set frame size to QVGA (320x240)
sensor.skip_frames(time = 1000)     # Wait for settings take effect.
clock = time.clock()                # Create a clock object to track the FPS.

# 用于 AI 输入的 image(和你原来一致)
od_img = image.Image(size=(320,256))

anchor_head_detect = (0.1074, 0.1458, 0.1367, 0.2137, 0.1758, 0.2824, 0.2441, 0.3333, 0.2188, 0.4167, 0.2969, 0.5000, 0.4102, 0.6667, 0.6094, 0.9722, 1.2364, 1.6915)
head_kpu = KPU()
print("ready load model")
head_kpu.load_kmodel("/sd/KPU/head_body_detect/head_detect_v1.kmodel")
head_kpu.init_yolo2(anchor_head_detect, anchor_num=9, img_w=320, img_h=240, net_w=320 , net_h=256 ,layer_w=10 ,layer_h=8, threshold=0.6, nms_value=0.2, classes=1)

# 初始化 UART
uart = init_uart()

# 屏宽(判断左右使用)。这里用网络输入宽度 320(与 net_w 保持一致)
SCREEN_WIDTH = 320

# ---------- 主循环 ----------
while True:
    gc.collect()
    clock.tick()                    # Update the FPS clock.
    img = sensor.snapshot()
    # 将 camera 图像贴到 od_img(AI 输入)
    od_img.draw_image(img, 0, 0)
    od_img.pix_to_ai()
    # 运行模型并获取结果
    head_kpu.run_with_output(od_img)
    head_boxes = head_kpu.regionlayer_yolo2()

    # 画框并统计(如果有)
    if head_boxes and len(head_boxes) > 0:
        # 画框
        for l in head_boxes:
            # l 的格式 (x, y, w, h, score?),按你原来写法画矩形
            img.draw_rectangle(int(l[0]), int(l[1]), int(l[2]), int(l[3]), color=(0, 255, 0))
        # 仅当检测到至少一个框时发送串口数据
        send_detect_counts(uart, head_boxes, SCREEN_WIDTH)

    # 显示 FPS
    fps = clock.fps()
    img.draw_string(0, 0, "%2.1ffps" % (fps), color=(0, 60, 128), scale=2.0)
    lcd.display(img)

# 程序退出时清理(通常不会到达)
head_kpu.deinit()

六、实验现象

在这里插入图片描述

七、文末

后续主包将带领大家做更多关于K210的项目,评论区可以留下你希望主包更新的方向,更多项目资料可查看主页(尽情期待)

更多推荐