diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6884a80..b286822 100755 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -174,7 +174,7 @@ build web docs: deploy production: stage: deploy - image: ai.b-bug.org:5000/python:web-docs-v2 + image: ai.b-bug.org:5000/huangziyi/deploy:v1 dependencies: - build web docs rules: @@ -186,7 +186,7 @@ deploy production: url: https://developer.canaan-creative.com/k230_canmv/dev/index.html retry: 2 script: - - scp -P 52522 -O -C -r _build/* huangziyi@40.73.58.120:/data/webapp/k230_canmv/ + - scp -P $AWS_PORT -C -r _build/* $AWS/data/webapp/k230_canmv/ # sync dev branch to main branch diff --git "a/zh/CanMV-K230_SDK_nncase\347\211\210\346\234\254\345\257\271\345\272\224\345\205\263\347\263\273.md" "b/zh/CanMV-K230_SDK_nncase\347\211\210\346\234\254\345\257\271\345\272\224\345\205\263\347\263\273.md" index 2106947..088ff6d 100755 --- "a/zh/CanMV-K230_SDK_nncase\347\211\210\346\234\254\345\257\271\345\272\224\345\205\263\347\263\273.md" +++ "b/zh/CanMV-K230_SDK_nncase\347\211\210\346\234\254\345\257\271\345\272\224\345\205\263\347\263\273.md" @@ -47,3 +47,5 @@ | 0.2.0 | 1.1.0 | 2.4.0 | - | | 0.3.0 | 1.1.0 | 2.4.0 | - | | 0.4.0 | 1.3.0 | 2.7.0 | - | +| 0.5.0 | 1.4.0 | 2.8.0 | - | +| 0.6.0 | 1.5.0 | 2.8.1 | - | diff --git "a/zh/CanMV-K230\347\211\210\346\234\254\350\257\264\346\230\216.md" "b/zh/CanMV-K230\347\211\210\346\234\254\350\257\264\346\230\216.md" index 111a034..91edf72 100755 --- "a/zh/CanMV-K230\347\211\210\346\234\254\350\257\264\346\230\216.md" +++ "b/zh/CanMV-K230\347\211\210\346\234\254\350\257\264\346\230\216.md" @@ -51,6 +51,7 @@ | K230 CanMV | V0.3.0 | 2023-12-28 | | K230 CanMV | V0.4.0 | 2024-01-26 | | K230 CanMV | V0.5.0 | 2024-03-15 | +| K230 CanMV | V0.6.0 | 2024-04-30 | ## 2. 支持的硬件 @@ -89,6 +90,9 @@ K230平台支持CanMV-K230等主板 | 21 | V0.5.0 | 虚拟U盘 | 支持虚拟U盘的功能 | | | 22 | V0.5.0 | 外设模块 | 根据micropython官方重新整理fpioa、adc、uart、spi、i2c、rtc、timer模块的API | | | 23 | V0.5.0 | MCM | 支持多摄像头,添加2sensors,3sensors demo | | +| 24 | V0.6.0 | sensor | 增加sensor类 | | +| 25 | V0.6.0 | lcd | 增加lcd类 | | +| 25 | V0.6.0 | HDMI | 添加720P、480P分辨率 | | ### 4.2 AI Demo diff --git a/zh/api/image_video.rst b/zh/api/image_video.rst index 988ee55..e0c7dc3 100644 --- a/zh/api/image_video.rst +++ b/zh/api/image_video.rst @@ -5,7 +5,9 @@ mpp/K230_CanMV_Audio模块API手册.md mpp/K230_CanMV_Camera模块API手册.md + mpp/K230_CanMV_Sensor模块API手册.md mpp/K230_CanMV_Display模块API手册.md + mpp/K230_CanMV_Lcd模块API手册.md mpp/K230_CanMV_Media模块API手册.md mpp/K230_CanMV_MP4模块API手册.md mpp/K230_CanMV_VDEC模块API手册.md diff --git "a/zh/api/machine/K230_CanMV_TOUCH\346\250\241\345\235\227API\346\211\213\345\206\214.md" "b/zh/api/machine/K230_CanMV_TOUCH\346\250\241\345\235\227API\346\211\213\345\206\214.md" new file mode 100755 index 0000000..ddcb450 --- /dev/null +++ "b/zh/api/machine/K230_CanMV_TOUCH\346\250\241\345\235\227API\346\211\213\345\206\214.md" @@ -0,0 +1,126 @@ +# K230 CanMV TOUCH 模块API手册 + +![cover](../images/canaan-cover.png) + +版权所有©2023北京嘉楠捷思信息技术有限公司 + +
+ +## 免责声明 + +您购买的产品、服务或特性等应受北京嘉楠捷思信息技术有限公司(“本公司”,下同)及其关联公司的商业合同和条款的约束,本文档中描述的全部或部分产品、服务或特性可能不在您的购买或使用范围之内。除非合同另有约定,本公司不对本文档的任何陈述、信息、内容的正确性、可靠性、完整性、适销性、符合特定目的和不侵权提供任何明示或默示的声明或保证。除非另有约定,本文档仅作为使用指导参考。 + +由于产品版本升级或其他原因,本文档内容将可能在未经任何通知的情况下,不定期进行更新或修改。 + +## 商标声明 + +![logo](../images/logo.png)、“嘉楠”和其他嘉楠商标均为北京嘉楠捷思信息技术有限公司及其关联公司的商标。本文档可能提及的其他所有商标或注册商标,由各自的所有人拥有。 + +**版权所有 © 2023北京嘉楠捷思信息技术有限公司。保留一切权利。** +非经本公司书面许可,任何单位和个人不得擅自摘抄、复制本文档内容的部分或全部,并不得以任何形式传播。 + +
+ +## 目录 + +[TOC] + +## 前言 + +### 概述 + +本文档主要介绍machine模块下的TOUCH类API。 + +### 读者对象 + +本文档(本指南)主要适用于以下人员: + +- 技术支持工程师 +- 软件开发工程师 + +### 缩略词定义 + +| 简称 | 说明 | +| ---- | ---- | +| | | + +### 修订记录 + +| 文档版本号 | 修改说明 | 修改者 | 日期 | +| ---------- | -------- | ---------- | ---------- | +| V1.0 | 初版 | 软件部 | 2024-04-20 | + +## 1. 概述 + +触摸模块基于rtt的触摸框架,支持单点多点电容触摸屏、电阻触摸屏。 + +## 2. API描述 + +TOUCH类位于machine模块下 + +### 示例 + +```python +from machine import TOUCH +# 实例化TOUCH设备0 +tp = TOUCH(0) +# 获取TOUCH数据 +p = tp.read() +print(p) +# print(p[0].x) +# print(p[0].y) +# print(p[0].event) +``` + +### 构造函数 + +```python +touch = TOUCH(index) +``` + +【参数】 + +- index: TOUCH设备号,取值:[0,9],实际取决于有几个触摸设备 + +### read + +```python +TOUCH.read([count]) +``` + +获取触摸数据 + +【参数】 + +- count: 最多读取多少个触摸点,取值:[0:10],默认为0,读取全部触摸点 + +【返回值】 + +返回触摸点数据,类型为tuple,([tp[,tp...]]),每个tp都是一个touch_info类 + +### deinit + +```python +TOUCH.deinit() +``` + +释放TOUCH资源 + +【参数】 + +无 + +【返回值】 + +无 + +## 3. TOUCH_INFO 类 + +TOUCH_INFO类存储了触摸点的信息,用户可通过相关属性(只读)去访问 + +- event,事件码 +- track_id,触点id,用于多点触摸 +- width,触点width +- x,触点x坐标 +- y,触点y坐标 +- timestamp,触点时间辍 diff --git "a/zh/api/mpp/K230_CanMV_Camera\346\250\241\345\235\227API\346\211\213\345\206\214.md" "b/zh/api/mpp/K230_CanMV_Camera\346\250\241\345\235\227API\346\211\213\345\206\214.md" index 822ec7a..d211393 100755 --- "a/zh/api/mpp/K230_CanMV_Camera\346\250\241\345\235\227API\346\211\213\345\206\214.md" +++ "b/zh/api/mpp/K230_CanMV_Camera\346\250\241\345\235\227API\346\211\213\345\206\214.md" @@ -54,6 +54,8 @@ ## 1. 概述 +`该模块将在V1.0版本后废弃,请使用sensor模块` + ​ K230 CanMV平台Camera模块负责图像采集处理任务。本模块提供了一系列Highe Levl的API,应用开发者可以不用关注底层硬件细节,仅通过该模块提供的API即可获取不同格式和尺寸的图像。 ​ K230 CanMV平台Camera模块包括三个独立的能力完全相同的camera设备,每个camera设备均可独立完成图像数据采集捕获处理,并可以同时输出3路图像数据。如下图所示: diff --git "a/zh/api/mpp/K230_CanMV_Display\346\250\241\345\235\227API\346\211\213\345\206\214.md" "b/zh/api/mpp/K230_CanMV_Display\346\250\241\345\235\227API\346\211\213\345\206\214.md" index f2cfd8b..f2592cf 100755 --- "a/zh/api/mpp/K230_CanMV_Display\346\250\241\345\235\227API\346\211\213\345\206\214.md" +++ "b/zh/api/mpp/K230_CanMV_Display\346\250\241\345\235\227API\346\211\213\345\206\214.md" @@ -53,6 +53,8 @@ ## 1. 概述 +`该模块将在V1.0版本后废弃,请使用lcd模块` + 此文档介绍CanMV Display模块,用以指导开发人员如何调用Micro Python API实现图像输出功能。 ## 2. API描述 @@ -297,8 +299,14 @@ def deinit() | 成员名称 | 描述 | |---------|---------------------------------| -| HX8377_1080X1920_30FPS | VO和DSI模块输出1080X1920_30FPS时序到LCD | -| LT9611_1920X1080_30FPS | VO和DSI模块输出1920X1080_30FPS时序到HDMI | +| HX8377_1080X1920_30FPS | VO和DSI模块输出1080X1920 30FPS时序到LCD | +| ST7701_V1_MIPI_2LAN_480X800_30FPS | VO和DSI模块输出480x800 30FPS时序到LCD | +| LT9611_1920X1080_30FPS | VO和DSI模块输出1920X1080 30FPS时序到HDMI | +| LT9611_MIPI_4LAN_1920X1080_60FPS | VO和DSI模块输出1920X1080 60FPS时序到HDMI | +| LT9611_MIPI_4LAN_1280X720_60FPS | VO和DSI模块输出1280x720 60FPS时序到HDMI | +| LT9611_MIPI_4LAN_1280X720_50FPS | VO和DSI模块输出1280x720 50FPS时序到HDMI | +| LT9611_MIPI_4LAN_1280X720_30FPS | VO和DSI模块输出1280x720 30FPS时序到HDMI | +| LT9611_MIPI_4LAN_640X480_60FPS | VO和DSI模块输出640x480 30FPS时序到HDMI | 【注意事项】 diff --git "a/zh/api/mpp/K230_CanMV_Lcd\346\250\241\345\235\227API\346\211\213\345\206\214.md" "b/zh/api/mpp/K230_CanMV_Lcd\346\250\241\345\235\227API\346\211\213\345\206\214.md" new file mode 100755 index 0000000..f1e1eff --- /dev/null +++ "b/zh/api/mpp/K230_CanMV_Lcd\346\250\241\345\235\227API\346\211\213\345\206\214.md" @@ -0,0 +1,455 @@ +# K230 CanMV Lcd模块API手册 + +![cover](../images/canaan-cover.png) + +版权所有©2023北京嘉楠捷思信息技术有限公司 + +
+ +## 免责声明 + +您购买的产品、服务或特性等应受北京嘉楠捷思信息技术有限公司(“本公司”,下同)及其关联公司的商业合同和条款的约束,本文档中描述的全部或部分产品、服务或特性可能不在您的购买或使用范围之内。除非合同另有约定,本公司不对本文档的任何陈述、信息、内容的正确性、可靠性、完整性、适销性、符合特定目的和不侵权提供任何明示或默示的声明或保证。除非另有约定,本文档仅作为使用指导参考。 + +由于产品版本升级或其他原因,本文档内容将可能在未经任何通知的情况下,不定期进行更新或修改。 + +## 商标声明 + +![logo](../images/logo.png)、“嘉楠”和其他嘉楠商标均为北京嘉楠捷思信息技术有限公司及其关联公司的商标。本文档可能提及的其他所有商标或注册商标,由各自的所有人拥有。 + +**版权所有 © 2023北京嘉楠捷思信息技术有限公司。保留一切权利。** +非经本公司书面许可,任何单位和个人不得擅自摘抄、复制本文档内容的部分或全部,并不得以任何形式传播。 + +
+ +## 目录 + +[TOC] + +## 前言 + +### 概述 + +此文档介绍CanMV lcd模块,用以指导开发人员如何调用MicroPython API实现图像输出功能。 + +### 读者对象 + +本文档(本指南)主要适用于以下人员: + +- 技术支持工程师 +- 软件开发工程师 + +### 缩略词定义 + +| 简称 | 说明 | +| ---- | ---- | +| VO | Video Output | +| DSI | Display Serial Interface | + +### 修订记录 + +| 文档版本号 | 修改说明 | 修改者 | 日期 | +| ---------- | -------- | ---------- | ---------- | +| V1.0 | 初版 | 赵忠祥 | 2024-04-25 | + +## 1. 概述 + +此文档介绍CanMV lcd模块,用以指导开发人员如何调用Micro Python API实现图像输出功能。 + +## 2. API描述 + +### 2.1 lcd.init + +【描述】 + +初始化整个lcd通路,包括VO模块、DSI模块、LCD/HDMI + +【语法】 + +```python +lcd.init(type) +``` + +【参数】 + +| 参数名称 | 描述 | 输入/输出 | +|-----------------|-------------------------------|-----------| +| type | 输出接口参数 | 输入 | + +【返回值】 + +| 返回值 | 描述 | +|---------|---------------------------------| +| 0 | 成功。 | +| 非 0 | 失败,其值为\[错误码\] | + +【注意】 + +无 + +【举例】 + +无 + +【相关主题】 + +无 + +### 2.2 lcd.set_backlight + +【描述】 + +设置LCD背光 + +【语法】 + +```python +lcd.set_backlight(level) +``` + +【参数】 + +| 参数名称 | 描述 | 输入/输出 | +|-----------------|-------------------------------|-----------| +| level | 0:关闭LCD背光;1:打开LCD背光 | 输入 | + +【返回值】 + +| 返回值 | 描述 | +|---------|---------------------------------| +| 0 | 成功。 | +| 非 0 | 失败,其值为\[错误码\] | + +【注意】 + +set_backlight仅适用于LCD输出 + +【举例】 + +无 + +【相关主题】 + +无 + +### 2.3 lcd.set_plane + +【描述】 + +设置VO通道参数,set_plane方法主要用来设置和Camera、vdec、DPU、AI2D绑定的VO通道 + +【语法】 + +```python +lcd.set_plane(x, y, width, height, pixelformat, rotate, chn, mirror) +``` + +【参数】 + +| 参数名称 | 描述 | 输入/输出 | +|-----------------|-------------------------------|-----------| +| x | 起始坐标的x值 | 输入 | +| y | 起始坐标的y值 | 输入 | +| width | 宽度 | 输入 | +| height | 高度 | 输入 | +| pixelformat | 像素格式 | 输入 | +| rotate | 顺时针旋转功能 | 输入 | +| chn | VO通道 | 输入 | +| mirror | 翻转功能 | 输入 | + +【返回值】 + +| 返回值 | 描述 | +|---------|---------------------------------| +| 0 | 成功。 | +| 非 0 | 失败,其值为\[错误码\] | + +【注意】 + +只有DISPLAY_CHN_VIDEO1通道支持rotate功能和mirror功能 + +【举例】 + +无 + +【相关主题】 + +无 + +### 2.4 lcd.display + +【描述】 + +输出image到VO通道 + +【语法】 + +```python +lcd.display(image, x, y, chn) +``` + +【参数】 + +| 参数名称 | 描述 | 输入/输出 | +|-----------------|-------------------------------|-----------| +| image | 待输出的图像 | 输入 | +| x | 起始坐标的x值 | 输入 | +| y | 起始坐标的y值 | 输入 | +| chn | VO通道 | 输入 | + +【返回值】 + +| 返回值 | 描述 | +|---------|---------------------------------| +| 0 | 成功。 | +| 非 0 | 失败,其值为\[错误码\] | + +【注意】 + +无 + +【举例】 + +无 + +【相关主题】 + +无 + +### 2.5 lcd.disable_plane + +【描述】 + +关闭VO通道 + +【语法】 + +```python +lcd.disable_plane(chn) +``` + +【参数】 + +| 参数名称 | 描述 | 输入/输出 | +|-----------------|-------------------------------|-----------| +| chn | VO通道 | 输入 | + +【返回值】 + +| 返回值 | 描述 | +|---------|---------------------------------| +| 0 | 成功。 | +| 非 0 | 失败,其值为\[错误码\] | + +【注意】 + +通过disable_plane方法关闭的VO通道,可以通过set_plane方法或者display方法重新打开 + +【举例】 + +无 + +【相关主题】 + +无 + +### 2.6 lcd.deinit + +【描述】 + +执行反初始化,deinit方法会关闭整个lcd通路,包括VO模块、DSI模块、LCD/HDMI + +【语法】 + +```python +lcd.deinit() +``` + +【返回值】 + +| 返回值 | 描述 | +|---------|---------------------------------| +| 0 | 成功。 | +| 非 0 | 失败,其值为\[错误码\] | + +【注意】 + +无 + +【举例】 + +无 + +【相关主题】 + +无 + +## 3. 数据结构描述 + +### 3.1 type + +【说明】 + +输出接口参数 + +【定义】 + +【成员】 + +| 成员名称 | 描述 | +|---------|---------------------------------| +| HX8377_1080X1920_30FPS | VO和DSI模块输出1080X1920 30FPS时序到LCD | +| ST7701_V1_MIPI_2LAN_480X800_30FPS | VO和DSI模块输出480x800 30FPS时序到LCD | +| LT9611_1920X1080_30FPS | VO和DSI模块输出1920X1080 30FPS时序到HDMI | +| LT9611_MIPI_4LAN_1920X1080_60FPS | VO和DSI模块输出1920X1080 60FPS时序到HDMI | +| LT9611_MIPI_4LAN_1280X720_60FPS | VO和DSI模块输出1280x720 60FPS时序到HDMI | +| LT9611_MIPI_4LAN_1280X720_50FPS | VO和DSI模块输出1280x720 50FPS时序到HDMI | +| LT9611_MIPI_4LAN_1280X720_30FPS | VO和DSI模块输出1280x720 30FPS时序到HDMI | +| LT9611_MIPI_4LAN_640X480_60FPS | VO和DSI模块输出640x480 30FPS时序到HDMI | + +【注意事项】 + +无 + +### 3.2 chn + +【说明】 + +VO通道 + +【定义】 + +【成员】 + +| 成员名称 | 描述 | +|---------|---------------------------------| +| DISPLAY_CHN_VIDEO1 | VO模块video 1 通道,支持DISPLAY_OUT_NV12输出 | +| DISPLAY_CHN_VIDEO2 | VO模块video 2 通道,支持DISPLAY_OUT_NV12输出 | +| DISPLAY_CHN_OSD0 | VO模块OSD 0 通道,支持DISPLAY_OUT_ARGB8888、DISPLAY_OUT_RGB888、DISPLAY_OUT_RGB565输出 | +| DISPLAY_CHN_OSD1 | VO模块OSD 1 通道,支持DISPLAY_OUT_ARGB8888、DISPLAY_OUT_RGB888、DISPLAY_OUT_RGB565输出 | +| DISPLAY_CHN_OSD2 | VO模块OSD 2 通道,支持DISPLAY_OUT_ARGB8888、DISPLAY_OUT_RGB888、DISPLAY_OUT_RGB565输出 | +| DISPLAY_CHN_OSD3 | VO模块OSD 3 通道,支持DISPLAY_OUT_ARGB8888、DISPLAY_OUT_RGB888、DISPLAY_OUT_RGB565输出 | + +【注意事项】 + +只有DISPLAY_CHN_VIDEO1通道支持rotate功能和mirror功能 + +### 3.3 pixelformat + +【说明】 + +像素格式 + +【定义】 + +【成员】 + +| 成员名称 | 描述 | +|---------|---------------------------------| +| DISPLAY_OUT_NV12 | 输出NV12 | +| DISPLAY_OUT_ARGB8888 | 输出ARGB8888 | +| DISPLAY_OUT_RGB888 | 输出RGB888 | +| DISPLAY_OUT_RGB565 | 输出RGB565 | + +【注意事项】 + +无 + +### 3.4 mirror + +【说明】 + +水平方向和垂直方向镜像翻转功能 + +【定义】 + +【成员】 + +| 成员名称 | 描述 | +|---------|---------------------------------| +| DISPLAY_ROTATE_0 | 不进行旋转 | +| DISPLAY_ROTATE_90 | 顺时针旋转90度 | +| DISPLAY_ROTATE_180 | 顺时针旋转180度 | +| DISPLAY_ROTATE_270 | 顺时针旋转270度 | +| DISPLAY_MIRROR_NONE | 不进行翻转 | +| DISPLAY_MIRROR_HOR | 水平方向翻转180度 | +| DISPLAY_MIRROR_VER | 垂直方向翻转180度 | +| DISPLAY_MIRROR_BOTH | 水平方向和垂直方向都翻转180度 | + +【注意事项】 + +无 + +## 4. 示例程序 + +例程 + +```python + +from media.lcd import * +from media.media import * +import time, os, urandom, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 + +def lcd_test(): + print("lcd test") + # use hdmi for lcd + lcd.init(LT9611_1920X1080_30FPS) // 实始化lcd + # config vb for osd layer + config = k_vb_config() // 配置内存 + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + + # create image for drawing + img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888) + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + lcd.display(osd_img, 0, 0, DISPLAY_CHN_OSD0) // 显示 + try: + while True: + img.clear() + for i in range(10): + x = (urandom.getrandbits(11) % img.width()) + y = (urandom.getrandbits(11) % img.height()) + r = (urandom.getrandbits(8)) + g = (urandom.getrandbits(8)) + b = (urandom.getrandbits(8)) + # If the first argument is a scaler then this method expects + # to see x, y, and text. Otherwise, it expects a (x,y,text) tuple. + # Character and string rotation can be done at 0, 90, 180, 270, and etc. degrees. + img.draw_string(x, y, "Hello World!", color = (r, g, b), scale = 2, mono_space = False, + char_rotation = 0, char_hmirror = False, char_vflip = False, + string_rotation = 0, string_hmirror = False, string_vflip = False) // 绘图 + img.copy_to(osd_img) + time.sleep(1) + os.exitpoint() + except KeyboardInterrupt as e: + print("user stop: ", e) + except BaseException as e: + sys.print_exception(e) + + # deinit lcd + lcd.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # deinit media buffer + media.buffer_deinit() + +if __name__ == "__main__": + os.exitpoint(os.EXITPOINT_ENABLE) + lcd_test() + +``` diff --git "a/zh/api/mpp/K230_CanMV_Sensor\346\250\241\345\235\227API\346\211\213\345\206\214.md" "b/zh/api/mpp/K230_CanMV_Sensor\346\250\241\345\235\227API\346\211\213\345\206\214.md" new file mode 100755 index 0000000..00dfd8c --- /dev/null +++ "b/zh/api/mpp/K230_CanMV_Sensor\346\250\241\345\235\227API\346\211\213\345\206\214.md" @@ -0,0 +1,518 @@ +# K230 CanMV Sensor 模块API手册 + +![cover](../images/canaan-cover.png) + +版权所有©2023北京嘉楠捷思信息技术有限公司 + +
+ +## 免责声明 + +您购买的产品、服务或特性等应受北京嘉楠捷思信息技术有限公司(“本公司”,下同)及其关联公司的商业合同和条款的约束,本文档中描述的全部或部分产品、服务或特性可能不在您的购买或使用范围之内。除非合同另有约定,本公司不对本文档的任何陈述、信息、内容的正确性、可靠性、完整性、适销性、符合特定目的和不侵权提供任何明示或默示的声明或保证。除非另有约定,本文档仅作为使用指导参考。 + +由于产品版本升级或其他原因,本文档内容将可能在未经任何通知的情况下,不定期进行更新或修改。 + +## 商标声明 + +![logo](../images/logo.png)、“嘉楠”和其他嘉楠商标均为北京嘉楠捷思信息技术有限公司及其关联公司的商标。本文档可能提及的其他所有商标或注册商标,由各自的所有人拥有。 + +**版权所有 © 2023北京嘉楠捷思信息技术有限公司。保留一切权利。** +非经本公司书面许可,任何单位和个人不得擅自摘抄、复制本文档内容的部分或全部,并不得以任何形式传播。 + +
+ +## 目录 + +[TOC] + +## 前言 + +### 概述 + +本文档主要介绍K230 CanMV平台Camera模块 API使用说明及应用示例。 + +### 读者对象 + +本文档(本指南)主要适用于以下人员: + +- 技术支持工程师 +- 软件开发工程师 + +### 缩略词定义 + +| 简称 | 说明 | +|--------------------|--------------------------------------------------------| +| VICAP | Video Input Capture,图像输入采集模块 | +| MCM | Multi Camera Management ,多摄像头管理 | + +### 修订记录 + +| 文档版本号 | 修改说明 | 修改者 | 日期 | +| ---------- | -------- | ---------- | ---------- | +| V1.0 | 初版 | 赵忠祥 | 2024-04-24 | + +## 1. 概述 + +K230 CanMV平台sensor模块负责图像采集处理任务。本模块提供了一系列Highe Levl的API,应用开发者可以不用关注底层硬件细节,仅通过该模块提供的API即可获取不同格式和尺寸的图像。 + +K230 CanMV平台sensor模块包括三个独立的能力完全相同的sensor设备,每个sensor设备均可独立完成图像数据采集捕获处理,并可以同时输出3路图像数据。如下图所示: + +![cover](../images/k230-canmv-camera-top.png) + +sensor 0,sensor 1,sensor 2表示三个图像传感器;Camera Device 0,Camera Device 1,Camera Device 2表示三个sensor设备;output channel 0,output channel 1,output channel 2表示sensor设备的三个输出通道。三个图像传感器可以通过软件配置映射到不同的sensor 设备。 + +## 2. API描述 + +K230 CanMV平台sensor模块提供sensor静态类,该类提供以下章节描述的方法。 + +### 2.1 sensor.reset + +【描述】 + +根据指定的sensor设备和sensor类型执行初始化 + +【语法】 + +```python +sensor.reset(dev_num, type) +``` + +【参数】 + +| 参数名称 | 描述 | 输入/输出 | +|-----------------|-------------------------------|-----------| +| dev_num | sensor设备号 | | +| sensor_type | sensor类型,CanMV平台定义的已经支持的各类sensor | 输入 | + +【返回值】 + +| 返回值 | 描述 | +|---------|---------------------------------| +| 0 | 成功。 | +| 非 0 | 失败,其值为\[错误码\] | + +sensor_type: + +CAM_DEFAULT_SENSOR/OV_OV5647_MIPI_CSI0_1920X1080_30FPS_10BIT_LINEAR + +CAM_OV5647_1920X1080_CSI1_30FPS_10BIT_USEMCLK_LINEAR/OV_OV5647_MIPI_CSI1_1920X1080_30FPS_10BIT_LINEAR + +CAM_OV5647_1920X1080_CSI2_30FPS_10BIT_USEMCLK_LINEAR/OV_OV5647_MIPI_CSI2_1920X1080_30FPS_10BIT_LINEAR + +【注意】 +这是使用sensor模块需要调用的第一个方法。 + +用户不调用该方法,默认初始化sensor设备0及sensor OV5647 + +【举例】 + +```python +# 初始化sensor设备0以及sensor OV5647 +sensor.reset(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) +``` + +【相关主题】 + +无 + +### 2.2 sensor.set_framesize + +【描述】 + +设置指定sensor设备和通道的输出图像尺寸 + +【语法】 + +```python +sensor.set_framesize(dev_num, chn_num, width, height) +``` + +【参数】 + +| 参数名称 | 描述 | 输入/输出 | +| -------- | ---------------- | --------- | +| dev_num | sensor设备号 | 输入 | +| chn_num | sensor输出通道号 | 输入 | +| width | 输出图像宽度 | 输入 | +| height | 输出图像高度 | 输入 | + +【返回值】 + +| 返回值 | 描述 | +| ------ | ---------------------- | +| 0 | 成功。 | +| 非 0 | 失败,其值为\[错误码\] | + +【注意】 + +输出图像尺寸不能超过输入图像尺寸。 + +不同输出通道最大可输出图像尺寸由硬件限制。 + +用户不调用该方法,默认输出图像尺寸与输入图像一致。 + +【举例】 + +```python +# 配置sensor设备0,输出通道0, 输出图尺寸为640x480 +sensor.set_framesize(CAM_DEV_ID_0, CAM_CHN_ID_0, 640, 480) + +# 配置sensor设备0,输出通道1, 输出图尺寸为320x240 +sensor.set_framesize(CAM_DEV_ID_0, CAM_CHN_ID_1, 320, 240) +``` + +【相关主题】 + +无 + +### 2.3 sensor.set_pixformat + +【描述】 + +设置指定sensor设备和通道的输出图像格式 + +【语法】 + +```python +sensor.set_pixformat(dev_num, chn_num, pix_format) +``` + +【参数】 + +| 参数名称 | 描述 | 输入/输出 | +| ---------- | ---------------- | --------- | +| dev_num | sensor设备号 | 输入 | +| chn_num | sensor输出通道号 | 输入 | +| pix_format | 输出图像格式 | 输入 | + +pix_format: + +sensor.YUV420SP: NV12 + +sensor.RGB888: RGB888 interleave + +sensor.RGB888P: RGB888 planer + +【返回值】 + +| 返回值 | 描述 | +| ------ | ---------------------- | +| 0 | 成功。 | +| 非 0 | 失败,其值为\[错误码\] | + +【注意】 +用户不调用方法,将使用默认配置。 + +【举例】 + +```python +# 配置sensor设备0,输出通道0, 输出NV12格式 +sensor.set_pixformat(CAM_DEV_ID_0, CAM_CHN_ID_0, sensor.YUV420SP) + +# 配置sensor设备0,输出通道1, 输出RGB888格式 +sensor.set_pixformat(CAM_DEV_ID_0, CAM_CHN_ID_1, sensor.RGB888) +``` + +【相关主题】 + +无 + +### 2.4 sensor.start_stream + +【描述】 + +启动sensor数据流 + +【语法】 + +```python +sensor.start_stream() +``` + +【参数】 + +【返回值】 + +| 返回值 | 描述 | +| ------ | ---------------------- | +| 0 | 成功。 | +| 非 0 | 失败,其值为\[错误码\] | + +【举例】 + +```python +# 启动sensor设备输出数据流 +sensor.start_stream() +``` + +【相关主题】 + +无 + +### 2.5 sensor.stop_stream + +【描述】 + +停止sensor数据流 + +【语法】 + +```python +sensor.stop_stream() +``` + +【参数】 + +【返回值】 + +| 返回值 | 描述 | +| ------ | ---------------------- | +| 0 | 成功。 | +| 非 0 | 失败,其值为\[错误码\] | + +【举例】 + +```python +# 停止sensor设备0输出数据流 +sensor.stop_stream(CAM_DEV_ID_0) +``` + +【相关主题】 + +无 + +### 2.6 sensor.snapshot + +【描述】 + +从指定sensor设备的支持输出通道中捕获一帧图像数据 + +【语法】 + +```python +sensor.snapshot(dev_num, chn_num) +``` + +【参数】 + +| 参数名称 | 描述 | 输入/输出 | +| -------- | ---------------- | --------- | +| dev_num | sensor设备号 | 输入 | +| chn_num | sensor输出通道号 | | + +【返回值】 + +| 返回值 | 描述 | +| --------- | ---- | +| image对象 | 成功 | +| 其他 | 失败 | + +【注意】 + +该方法捕获的图像格式由set_outfmt方法指定。 + +【举例】 + +```python +# 从sensor设备0的通道0输出捕获一帧图像数据 +sensor.snapshot(CAM_DEV_ID_0, CAM_CHN_ID_0) +``` + +【相关主题】 + +无 + +## 3. 数据结构描述 + +K230 CanMV平台Camera模块包含如下描述的各个数据定义。 + +### 3.1 sensor类型 + +【说明】 + +下面是目前Canmv-K230板micropython支持的Sensor。 +其中CSI1/2是可以使用树莓派的ov5647模组,如果使用Canmv-K230 V1.0/1.1版的板子,要修改该模组的电压。 + +【定义】 + +```python +CAM_IMX335_2LANE_1920X1080_30FPS_12BIT_USEMCLK_LINEAR # Imx335 CSI0 +CAM_OV5647_1920X1080_30FPS_10BIT_USEMCLK_LINEAR # OV5647 CSI0 +CAM_OV5647_1920X1080_CSI1_30FPS_10BIT_USEMCLK_LINEAR # OV5647 CSI1 +CAM_OV5647_1920X1080_CSI2_30FPS_10BIT_USEMCLK_LINEAR # OV5647 CSI2 +# the default sensor type +CAM_DEFAULT_SENSOR = CAM_OV5647_1920X1080_30FPS_10BIT_USEMCLK_LINEAR # 默认的sensor使用OV5647 CSI0 +``` + +【注意事项】 + +Canmv-K230 V1.0/1.1版的板子外设接口为1.8V,不能直接使用树莓派的ov5647模组,必须修改电压为1.8V。 + +![ov5647_v1.8](../../images/ov5647_v1.8.jpg) + +【相关数据类型及接口】 + +### 3.2 输出图像尺寸 + +【说明】 + +定义各个输出通道能够支持的输出图像最大尺寸和最小尺寸 + +【定义】 + +```python +CAM_CHN0_OUT_WIDTH_MAX = 3072 +CAM_CHN0_OUT_HEIGHT_MAX = 2160 + +CAM_CHN1_OUT_WIDTH_MAX = 1920 +CAM_CHN1_OUT_HEIGHT_MAX = 1080 + +CAM_CHN2_OUT_WIDTH_MAX = 1920 +CAM_CHN2_OUT_HEIGHT_MAX = 1080 + +CAM_OUT_WIDTH_MIN = 64 +CAM_OUT_HEIGHT_MIN = 64 +``` + +【注意事项】 + +无 + +【相关数据类型及接口】 + +## 4. 示例程序 + +### 例程 + +```python +# 本示例程序包括以下内容: +# 1. 配置sensor设备0同时输出三路图像数据 +# 2. 通道0输出YUV格式用于预览显示,通道1、2输出RGB888P +# 3. 抓取三路输出的图像各100张 +# + +from media.sensor import * #导入sensor模块,使用sensor相关接口 +from media.display import * #导入display模块,使用display相关接口 +from media.media import * #导入media模块,使用meida相关接口 +from time import * #导入time模块,使用time相关接口 +import time +import image #导入image模块,使用image相关接口 + +def canmv_sensor_test(): + print("canmv_sensor_test") + + #初始化HDMI显示 + display.init(LT9611_1920X1080_30FPS) + + #初始化默认sensor配置(OV5647) + sensor.reset(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + + out_width = 1920 + out_height = 1080 + # 设置输出宽度16字节对齐 + out_width = ALIGN_UP(out_width, 16) + + #设置通道0输出尺寸 + sensor.set_framesize(CAM_DEV_ID_0, CAM_CHN_ID_0, out_width, out_height) + #设置通道0输出格式 + sensor.set_pixformat(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + + #创建媒体数据源设备 + media_source = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + #创建媒体数据接收设备 + media_sink = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + #创建媒体链路,数据从源设备流到接收设备 + media.create_link(media_source, media_sink) + #设置显示输出平面的属性 + display.set_plane(0, 0, out_width, out_height, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + + out_width = 640 + out_height = 480 + out_width = ALIGN_UP(out_width, 16) + + #设置通道1输出尺寸 + sensor.set_framesize(CAM_DEV_ID_0, CAM_CHN_ID_1, out_width, out_height) + #设置通道1输出格式 + sensor.set_pixformat(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + + #设置通道2输出尺寸 + sensor.set_framesize(CAM_DEV_ID_0, CAM_CHN_ID_2, out_width, out_height) + #设置通道2输出格式 + sensor.set_pixformat(CAM_DEV_ID_0, CAM_CHN_ID_2, PIXEL_FORMAT_RGB_888_PLANAR) + + #初始化媒体缓冲区 + ret = media.buffer_init() + if ret: + print("canmv_sensor_test, buffer init failed") + return ret + + #启动摄像头数据流 + sensor.start_stream(CAM_DEV_ID_0) + time.sleep(15) + + capture_count = 0 + while capture_count < 100: + time.sleep(1) + for dev_num in range(CAM_DEV_ID_MAX): + if not sensor.cam_dev[dev_num].dev_attr.dev_enable: + continue + + for chn_num in range(CAM_CHN_ID_MAX): + if not sensor.cam_dev[dev_num].chn_attr[chn_num].chn_enable: + continue + + print(f"canmv_sensor_test, dev({dev_num}) chn({chn_num}) capture frame.") + #从指定设备和通道捕获图像 + img = sensor.capture_image(dev_num, chn_num) + if img == -1: + print("sensor.capture_image failed") + continue + + if img.format() == image.YUV420: + suffix = "yuv420sp" + elif img.format() == image.RGB888: + suffix = "rgb888" + elif img.format() == image.RGBP888: + suffix = "rgb888p" + else: + suffix = "unkown" + + filename = f"/sdcard/dev_{dev_num:02d}_chn_{chn_num:02d}_{img.width()}x{img.height()}_{capture_count:04d}.{suffix}" + print("save capture image to file:", filename) + + with open(filename, "wb") as f: + if f: + img_data = uctypes.bytearray_at(img.virtaddr(), img.size()) + # save yuv data to sdcard. + #f.write(img_data) + else: + print(f"capture_image, open dump file failed({filename})") + + time.sleep(1) + #释放捕获的图像数据 + sensor.release_image(dev_num, chn_num, img) + + capture_count += 1 + + #停止摄像头输出 + sensor.stop_stream(CAM_DEV_ID_0) + + #去初始化显示设备 + display.deinit() + + #销毁媒体链路 + media.destroy_link(media_source, media_sink) + + time.sleep(1) + #去初始化媒体缓冲区资源 + ret = media.buffer_deinit() + if ret: + print("sensor test, media_buffer_deinit failed") + return ret + + print("sensor test exit") + return 0 + + +canmv_sensor_test() +``` diff --git a/zh/example/lvgl/lvgl_touch.md b/zh/example/lvgl/lvgl_touch.md new file mode 100644 index 0000000..d19eea0 --- /dev/null +++ b/zh/example/lvgl/lvgl_touch.md @@ -0,0 +1,174 @@ +# lvgl_touch - lvgl_touch例程 + +本示例程序用于对 CanMV 开发板进行一个lvgl触摸的功能展示。 + +```python +from media.display import * +from media.media import * +import time, os, sys, gc +import lvgl as lv +from machine import TOUCH + +DISPLAY_WIDTH = ALIGN_UP(480, 16) +DISPLAY_HEIGHT = 800 + +def display_init(): + # use hdmi for display + display.init(2) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # media buffer init + media.buffer_init() + # request media buffer for osd image + buffer = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # create image for osd + globals()["buffer"] = buffer + osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + globals()["osd_img"] = osd_img + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + +def display_deinit(): + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # deinit media buffer + media.buffer_deinit() + +def disp_drv_flush_cb(disp_drv, area, color): + if disp_drv.flush_is_last() == True: + osd_img = globals()["osd_img"] + osd_img.copy_from(color.__dereference__(osd_img.size())) + disp_drv.flush_ready() + +class touch_screen(): + def __init__(self): + self.x = 0 + self.y = 0 + self.state = lv.INDEV_STATE.RELEASED + + self.indev_drv = lv.indev_create() + self.indev_drv.set_type(lv.INDEV_TYPE.POINTER) + self.indev_drv.set_read_cb(self.callback) + self.touch = TOUCH(0) + + def callback(self, driver, data): + x, y, state = self.x, self.y, lv.INDEV_STATE.RELEASED + tp = self.touch.read(1) + if len(tp): + x, y, event = tp[0].x, tp[0].y, tp[0].event + if event == 2 or event == 3: + state = lv.INDEV_STATE.PRESSED + data.point = lv.point_t({'x': x, 'y': y}) + data.state = state + +def lvgl_init(): + lv.init() + disp_drv = lv.disp_create(DISPLAY_WIDTH, DISPLAY_HEIGHT) + disp_drv.set_flush_cb(disp_drv_flush_cb) + buf1 = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888) + buf2 = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888) + disp_drv.set_draw_buffers(buf1.bytearray(), buf2.bytearray(), buf1.size(), lv.DISP_RENDER_MODE.DIRECT) + globals()["buf1"] = buf1 + globals()["buf2"] = buf2 + tp = touch_screen() + +def lvgl_deinit(): + lv.deinit() + del globals()["buf1"] + del globals()["buf2"] + +def btn_clicked_event(event): + btn = lv.btn.__cast__(event.get_target()) + label = lv.label.__cast__(btn.get_user_data()) + if "on" == label.get_text(): + label.set_text("off") + else: + label.set_text("on") + +def user_gui_init(): + res_path = "/sdcard/app/tests/lvgl/data/" + + font_montserrat_16 = lv.font_load("A:" + res_path + "font/montserrat-16.fnt") + ltr_label = lv.label(lv.scr_act()) + ltr_label.set_text("In modern terminology, a microcontroller is similar to a system on a chip (SoC).") + ltr_label.set_style_text_font(font_montserrat_16,0) + ltr_label.set_width(310) + ltr_label.align(lv.ALIGN.TOP_MID, 0, 0) + + font_simsun_16_cjk = lv.font_load("A:" + res_path + "font/lv_font_simsun_16_cjk.fnt") + cz_label = lv.label(lv.scr_act()) + cz_label.set_style_text_font(font_simsun_16_cjk, 0) + cz_label.set_text("嵌入式系统(Embedded System),\n是一种嵌入机械或电气系统内部、具有专一功能和实时计算性能的计算机系统。") + cz_label.set_width(310) + cz_label.align(lv.ALIGN.BOTTOM_MID, 0, 0) + + anim_imgs = [None]*4 + with open(res_path + 'img/animimg001.png','rb') as f: + anim001_data = f.read() + + anim_imgs[0] = lv.img_dsc_t({ + 'data_size': len(anim001_data), + 'data': anim001_data + }) + anim_imgs[-1] = anim_imgs[0] + + with open(res_path + 'img/animimg002.png','rb') as f: + anim002_data = f.read() + + anim_imgs[1] = lv.img_dsc_t({ + 'data_size': len(anim002_data), + 'data': anim002_data + }) + + with open(res_path + 'img/animimg003.png','rb') as f: + anim003_data = f.read() + + anim_imgs[2] = lv.img_dsc_t({ + 'data_size': len(anim003_data), + 'data': anim003_data + }) + + animimg0 = lv.animimg(lv.scr_act()) + animimg0.center() + animimg0.set_src(anim_imgs, 4) + animimg0.set_duration(2000) + animimg0.set_repeat_count(lv.ANIM_REPEAT_INFINITE) + animimg0.start() + + btn = lv.btn(lv.scr_act()) + btn.align(lv.ALIGN.CENTER, 0, lv.pct(25)) + label = lv.label(btn) + label.set_text('on') + btn.set_user_data(label) + btn.add_event(btn_clicked_event, lv.EVENT.CLICKED, None) + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + display_init() + lvgl_init() + try: + user_gui_init() + while True: + time.sleep_ms(lv.task_handler()) + except BaseException as e: + sys.print_exception(e) + lvgl_deinit() + display_deinit() + gc.collect() + +if __name__ == "__main__": + main() + +``` + +具体接口定义请参考 [lvgl](../../api/lvgl/lvgl.md) diff --git a/zh/example/machine/touch/touch.md b/zh/example/machine/touch/touch.md new file mode 100755 index 0000000..65284eb --- /dev/null +++ b/zh/example/machine/touch/touch.md @@ -0,0 +1,18 @@ +# TOUCH - TOUCH例程 + +本示例程序用于对 CanMV 开发板进行一个TOUCH的功能展示。 + +```python +from machine import TOUCH + +# 实例化TOUCH设备0 +tp = TOUCH(0) +# 获取TOUCH数据 +p = tp.read() +print(p) +# print(p[0].x) +# print(p[0].y) +# print(p[0].event) +``` + +具体接口定义请参考 [TOUCH](../../../api/machine/K230_CanMV_TOUCH模块API手册.md)