跳转至

7 excamera-摄像头控制

作者:陈取德 | 最后修改:2026-05-19

一、概述

excamera 扩展库主要特点是简化摄像头业务的复杂业务流程,将异步业务逻辑简化为同步业务逻辑,将复杂的拍照/扫码流程优化为线性的操作流程,只需要开启、拍照/扫码、关闭即可完成整个拍照/扫码流程。

注意事项

使用 excamera 扩展库时需注意:

Air780系列、Air8000系列、Air700系列

1、仅支持一路SPI摄像头;

2、仅支持gc032a、gc0310、bf30a2这三款摄像头;

3、目前,在LuatOS的默认lib中,包含了:

  • excamera.lua(excamera扩展库脚本文件);

  • gc032a.lua(gc032a摄像头配置脚本文件);

  • gc0310.lua(gc0310摄像头配置脚本文件);

  • bf30a2.lua(bf30a2摄像头配置脚本文件);

  • 一共四个脚本文件;

  • 用户使用excamera扩展库开发摄像头应用时,只需要在main.lua中根据自己使用的摄像头型号,加载对应的摄像头脚本配置文件和excamera脚本文件即可;

  • 以使用摄像头型号gc032a为例,在main.lua编写如下两行代码:

require "gc032a"
require "excamera"

4、gc032a、gc0310、bf30a2的实际操作应用和DEMO请跳转对应型号链接;

Air8101系列

1、仅支持一路DVP/USB摄像头,实际操作应用和DEMO请跳转对应型号链接;

2、Air8101系列模组搭配usb或者dvp摄像头使用时,支持录制视频保存到本地、rtmp推流、预览三种模式,三种模式不能同时工作,每次只能使用其中的一种模式,这三种工作模式下的性能参数如下:

  • 录制视频保存到本地模式:支持分辨率1280x720,视频录制帧率,usb摄像头最大13fps,dvp摄像头最大15fps;
  • rtmp推流模式:支持分辨率1280x720,推流帧率,usb和dvp摄像头最大都是10fps;
  • 预览模式:支持分辨率1280x720,预览画面帧率,usb和dvp摄像头最大都是12fps;

二、核心示例

1、核心示例是指:使用本库文件提供的核心 API,开发的基础业务逻辑的演示代码;

2、核心示例的作用是:帮助开发者快速理解如何使用本库,所以核心示例的逻辑都比较简单;

3、更加完整和详细的 demo,请参考 LuatOS 仓库 中各个产品目录下的相关示例:demo/camera:

-- zbuff/文件路径存储单张拍照DEMO

require "gc032a"
local excamera = require "excamera"

sys.taskInit(function()
    local result
    while true do
        local spi_camera_param = {
            id= "gc032a",  -- SPI摄像头仅支持"gc03a"、"gc0320"、"bf30a2",请带引号填写
            i2c_id = 1,             -- 模块上使用的I2C编号
            work_mode = 0,          -- 工作模式,0为拍照模式,1为扫描模式
            save_path = "zbuff",    -- 拍照结果存储路径,可用"zbuff"交由excamera库内部管理
            camera_pwr = 2 ,        -- 摄像头使能管脚,填写GPIO号即可,无则填nil
            camera_pwdn = 5 ,       -- 摄像头pwdn开关脚,填写GPIO号即可,无则填nil
            camera_light = 25       -- 摄像头补光灯控制管脚,填写GPIO号即可,无则填nil
        }

        -- local usb_camera_param = {
        --     id= camera_type,       -- 摄像头类型,默认camera.USB
        --     sensor_width = width,                   -- 摄像头像素宽度,根据摄像头实际参数填写数值
        --     sensor_height = height,                 -- 摄像头像素高度,根据摄像头实际参数填写数值
        --     usb_port = usb_port              -- USB端口号
        -- }

        -- local dvp_camera_param = {
        --     id= camera_type,       -- 摄像头类型,默认camera.DVP
        --     sensor_width = width,                   -- 摄像头像素宽度,根据摄像头实际参数填写数值
        --     sensor_height = height,                 -- 摄像头像素高度,根据摄像头实际参数填写数值
        --     i2c_id = 1                              -- 模块上使用的I2C编号,默认值为1
        -- }
        sys.waitUntil("ONCE_CAPTURE")
        result = excamera.open(spi_camera_param)
        log.info("初始化状态", result)
        result ,path = excamera.photo()
        log.info("拍完了",data)
        excamera.close()
    end
end)

-- 文件路径存储多张拍照DEMO
require "gc032a"
local excamera = require "excamera"
local count = 1
local path = "/ram/" .. count .. "abc.jpg"

sys.taskInit(function()
    local result
    while true do
        local spi_camera_param = {
            id= "gc032a",
            i2c_id = 1,
            work_mode = 0,
            save_path = path,
            camera_pwr = 2,
            camera_pwnd = 5,
            camera_light = 25
        }
        log.debug("摄像头拍照")
        sys.waitUntil("ONCE_CAPTURE")
        result = excamera.open(spi_camera_param)
        log.info("初始化状态", result)
        local result, data = excamera.photo()
        local count_before = count - 1
        local path_before = "/ram/" .. count_before .. "abc.jpg"
        log.info("拍完了", path, count, io.fileSize(path), "上一张照片大小:", path_before, io.fileSize(path_before))
        count = count + 1
        path = "/ram/" .. count .. "abc.jpg"
        excamera.close()
    end
end)

三、常量详解

核心库常量,顾名思义是由合宙 LuatOS 内核固件中定义的、不可重新赋值或修改的固定值,在脚本代码中不需要声明,可直接调用;

合宙LuatOS内核固件中定义的核心库常量,和此扩展库功能有关,所以也会放到本文描述。

3.1 camera.USB

常量含义:摄像头接口类型为USB的摄像头
数据类型:number
适用产品:Air8101系列
示例代码:-- USB摄像头初始化示例
         local usb_camera_param = {
               id= camera.USB,       
               sensor_width = 640,                 
               sensor_height = 480,              
               usb_port = 1             
          }
         local result = excamera.open(usb_camera_param)
         log.info("摄像头初始化结果:",result)

3.2 camera.DVP

常量含义:摄像头接口类型为DVP的摄像头
数据类型:number
适用产品:Air8101系列
示例代码:-- DVP摄像头初始化示例
         local dvp_camera_param = {
               id= camera.DVP,       
               sensor_width = 640,                 
               sensor_height = 480,   
               i2c_id = 1              
          }
         local result = excamera.open(dvp_camera_param )
         log.info("摄像头初始化结果:",result)

四、函数详解

4.1 excamera.open(camera_param)

功能

  1. 摄像头业务整体配置,包含摄像头初始化、供电、开关、补光灯、存储路径管理;
  2. 配置照片存储路径,支持自动管理 zbuff;
  3. 配置摄像头电源、开关、补光灯控制管脚;

注意事项

  • 此接口只能在 task 中运行;

  • 此接口如果返回 false,需要主动调用 excamera.close()释放资源;

  • 如果对照片的大小有要求时,不要修改摄像头配置表中的像素参数,会造成摄像头初始化错误,初始化不会报错,但是回调会收不到任何信息。如需较小的照片结果请直接使用excamera.photo(x, y, w, h)接口的裁切功能,直接输出裁切好的照片即可!

参数

camera_param

参数含义:摄像头业务信息配置表;
数据类型:table;
是否必选:必须传入此参数;
注意事项:Air780系列、Air8000系列、Air700系列仅支持SPI摄像头;
Air8101系列仅支持DVP/USB摄像头;
因为各型号摄像头的信息参数不同,所以需要分为三种配置表,详见参数示例;
参数示例:
SPI摄像头配置表
spi_camera_param
{
参数含义:SPI摄像头型号;
数据类型:string;
取值范围:"gc032a"、"gc0310"、"bf30a2";
是否必选:必选;
注意事项:当前合宙SPI摄像头仅支持"gc032a"、"gc0310"、"bf30a2"这三款型号;
参数示例: "gc032a"
参数名称: spi_camera_param.id

参数含义:I2C编号;
数据类型:number;
取值范围:0-1;
是否必选:必选;
注意事项:这是向摄像头发送配置信息的I2C接口,对应CAMERA_SDA、CAMERA_SCL这两个接口的所使用的I2C编号;
参数示例: 1
参数名称: spi_camera_param.i2c_id

参数含义:摄像头工作模式;
数据类型:number;
取值范围:0-1;
是否必选:必选;
注意事项:SPI摄像头有两种工作模式,0为拍照模式,1为扫描模式;
参数示例: 0
参数名称: spi_camera_param.work_mode

参数含义:照片保存路径;
数据类型:string;
取值范围:暂无;
是否必选:必选;
注意事项:填写"ZBUFF"表示将图片存储到ram中,需要的内存由excamera扩展库自动申请;
填写其他字符串,表示将图片存储到字符串路径所表示的文件中;
文件所在的目录必须已经创建,如果没有创建,由用户在自己的应用程序中创建;
拍照业务是以覆盖写入的形式存储照片到ram或者文件中的,
所以在执行第二次拍照前一定要将上一次拍照的照片处理好再进行下一次拍照,否则将会被覆盖;
在excamera.close()时会将"ZBUFF"时使用的ram释放,请务必管理好每次拍照的照片后再关闭摄像头;
在excamera.close()时不会自动删除存储的照片文件,用户根据自己的项目业务需求,
在应用程序中自行控制是否需要使用os.remove(path)接口删除照片文件;
参数示例: "ZBUFF"表示将图片存储到ram中;
"/ram/abc.jpg"表示将图片存储到文件/ram/abc.jpg中
参数名称: spi_camera_param.save_path

参数含义:控制摄像头供电使能的GPIO ID;
数据类型:number;
取值范围:所使用模组的GPIO号/nil;
是否必选:必选;
注意事项:如果是由模组控制摄像头供电时,可填入对应的控制GPIO号交由excamera自动管理,
excamera内部会控制输出高电平控制打开供电,输出低电平控制关闭供电,如果是外部给摄像头供电时,填nil;
参数示例: 2
参数名称: spi_camera_param.camera_pwr

参数含义:控制摄像头复位的GPIO ID;
数据类型:number; 取值范围:所使用模组的GPIO号/nil;
是否必选:必选;
注意事项:对应摄像头的PWDN管脚,在摄像头使用外部供电或者不需要低功耗的场景下,可以在保持供电时关闭摄像头,
在需要使用时打开,与供电开关的差异是PWDN的开关更快,因为并没有断电,
首次初始化发送的配置信息可以不用再发送,打开即可拍照,如果由外部控制则填nil;
参数示例: 5
参数名称: spi_camera_param.camera_pwdn

参数含义:控制补光灯的GPIO ID;
数据类型:number;
取值范围:所使用模组的GPIO号/nil;
是否必选:必选;
注意事项:因为excamera是自动管理拍照业务的,可以将补光灯的管脚控制交由excamera管理,
excamera内部会控制输出高电平控制打开补光灯,输出低电平控制关闭补光灯。将补光时间控制在拍照的那个瞬间,
如果由外部控制,无法准确把控补光的时机。没有补光灯则填nil;
参数示例: 25
参数名称: spi_camera_param.camera_light

}

USB摄像头配置表
usb_camera_param
{
参数含义:摄像头型号;
数据类型:number;
取值范围:camera.USB;
是否必选:必选;
注意事项:仅Air8101支持,使用USB摄像头时直接填写camera.USB常量即可;
参数示例: camera.USB
参数名称: usb_camera_param.id

参数含义:摄像头实际宽度参数,单位:像素;
数据类型:number;
取值范围:根据摄像头实际参数填写数值;
是否必选:必选;
注意事项:参考所使用的USB摄像头规格书;
参数示例: 640
参数名称: usb_camera_param.sensor_width

参数含义:摄像头实际高度参数,单位:像素;
数据类型:number;
取值范围:根据摄像头实际参数填写数值;
是否必选:必选;
注意事项:参考所使用的USB摄像头规格书;
参数示例: 480
参数名称: usb_camera_param.sensor_height

参数含义:USB端口号;
数据类型:number;
取值范围:1;
是否必选:必选;
注意事项:excamera支持多USB摄像头轮切拍照业务,如需使用多USB轮切拍照,
请参考合宙标准配件 AirCAMERA _1030 使用说明
参数示例: 1
参数名称: usb_camera_param.usb_port

参数含义:录制视频或推流的帧率;
数据类型:number;
取值范围:暂无,8101底层默认此值为15;
是否必选:可选;
注意事项:暂无;
参数示例: 15
参数名称: usb_camera_param.fps

参数含义:H.264编码的初始量化参数;
数据类型:number;
取值范围:0-40,8101底层默认此值为25;
是否必选:可选;
注意事项:暂无;
参数示例: 25
参数名称: usb_camera_param.h264_qp_init

参数含义:H.264编码的I帧最大量化参数;
数据类型:number;
取值范围:0-51,8101底层默认此值为51;
是否必选:可选;
注意事项:暂无;
参数示例: 51
参数名称: usb_camera_param.h264_qp_i_max

参数含义:H.264编码的P帧最大量化参数;
数据类型:number;
取值范围:0-51,8101底层默认此值为51;
是否必选:可选;
注意事项:暂无;
参数示例: 51
参数名称: usb_camera_param.h264_qp_p_max

参数含义:I帧比特率控制参数;
数据类型:number;
取值范围:0-256,8101底层默认此值为80;
是否必选:可选;
注意事项:暂无;
参数示例: 80
参数名称: usb_camera_param.h264_imb_bits
参数含义:P帧比特率控制参数;
数据类型:number;
取值范围:0-256,8101底层默认此值为35;
是否必选:可选;
注意事项:暂无;
参数示例: 35
参数名称: usb_camera_param.h264_pmb_bits

参数含义:每间隔 多少 个 P 帧插入 1 个 I 帧;
数据类型:number;
取值范围:0-1023,8101底层默认此值为123;
是否必选:可选;
注意事项:暂无;
参数示例: 123
参数名称: usb_camera_param.h264_pframe_nums

}

DVP摄像头配置表
dvp_camera_param
{
参数含义:摄像头型号;
数据类型:number;
取值范围:camera.DVP;
是否必选:必选;
注意事项:仅Air8101支持,使用DVP摄像头时直接填写camera.DVP常量即可;
参数示例: camera.DVP
参数名称: dvp_camera_param.id

参数含义:摄像头实际宽度参数,单位:像素;
数据类型:number;
取值范围:根据摄像头实际参数填写数值;
是否必选:必选;
注意事项:参考所使用的DVP摄像头规格书;
参数示例: 640
参数名称: dvp_camera_param.sensor_width

参数含义:摄像头实际高度参数,单位:像素;
数据类型:number;
取值范围:根据摄像头实际参数填写数值;
是否必选:必选;
注意事项:参考所使用的DVP摄像头规格书;
参数示例: 480
参数名称: dvp_camera_param.sensor_height

参数含义:I2C编号;
数据类型:number;
取值范围:0-1;
是否必选:可选;
注意事项:这是向摄像头发送配置信息的I2C接口,对应CAMERA_SDA、CAMERA_SCL这两个接口的所使用的I2C编号,默认值为1;
参数示例: 1
参数名称: dvp_camera_param.i2c_id

参数含义:录制视频或推流的帧率;
数据类型:number;
取值范围:暂无,8101底层默认此值为15;
是否必选:可选;
注意事项:暂无;
参数示例: 15
参数名称: dvp_camera_param.fps

参数含义:H.264编码的初始量化参数;
数据类型:number;
取值范围:0-40,8101底层默认此值为25;
是否必选:可选;
注意事项:暂无;
参数示例: 25
参数名称: dvp_camera_param.h264_qp_init

参数含义:H.264编码的I帧最大量化参数;
数据类型:number;
取值范围:0-51,8101底层默认此值为51;
是否必选:可选;
注意事项:暂无;
参数示例: 51
参数名称: dvp_camera_param.h264_qp_i_max

参数含义:H.264编码的P帧最大量化参数;
数据类型:number;
取值范围:0-51,8101底层默认此值为51;
是否必选:可选;
注意事项:暂无;
参数示例: 51
参数名称: dvp_camera_param.h264_qp_p_max

参数含义:I帧比特率控制参数;
数据类型:number;
取值范围:0-256,8101底层默认此值为80;
是否必选:可选;
注意事项:暂无;
参数示例: 80
参数名称: dvp_camera_param.h264_imb_bits
参数含义:P帧比特率控制参数;
数据类型:number;
取值范围:0-256,8101底层默认此值为35;
是否必选:可选;
注意事项:暂无;
参数示例: 35
参数名称: dvp_camera_param.h264_pmb_bits

参数含义:每间隔 多少 个 P 帧插入 1 个 I 帧;
数据类型:number;
取值范围:0-1023,8101底层默认此值为123;
是否必选:可选;
注意事项:暂无;
参数示例: 123
参数名称: dvp_camera_param.h264_pframe_nums

span>
}

返回值

local result = excamera.open(camera_param)

此处有一个返回值 result

result

含义说明:摄像头业务配置是否成功;
数据类型:boolean
取值范围:true/false
注意事项:创建成功返回true,失败则返回false
         当返回false时,需要主动调用excamera.close()释放资源;
返回示例:true

示例

-- SPI摄像头初始化示例
local spi_camera_param = {
     id= "gc032a",  
     i2c_id = 1,         
     work_mode = 0,        
     save_path = "zbuff",  
     camera_pwr = 2 ,    
     camera_pwdn = 5 ,   
     camera_light = 25   
}
local result = excamera.open(spi_camera_param)
log.info("摄像头初始化结果:",result)

-- USB摄像头初始化示例
local usb_camera_param = {
      id= camera.USB,       
      sensor_width = 640,                 
      sensor_height = 480,              
      usb_port = 1             
 }
local result = excamera.open(usb_camera_param)
log.info("摄像头初始化结果:",result)

-- DVP摄像头初始化示例
local dvp_camera_param = {
      id= camera.DVP,       
      sensor_width = 640,                 
      sensor_height = 480,              
      i2c_id = 1              
 }
local result = excamera.open(dvp_camera_param )
log.info("摄像头初始化结果:",result)

4.2 excamera.photo(x, y, w, h)

功能

摄像头拍照功能函数,执行一次后即可得到拍照动作是否正常执行和一张照片的保存路径结果;

支持拍照时直接裁切照片,控制照片体积大小;

注意事项

如需较小的照片结果请使用裁切功能,计算好x、y、w、h参数,直接输出裁切好的照片即可!

参数

x

参数含义:裁剪起始横坐标;
数据类型:number
取值范围:根据所使用摄像头实际支持的像素尺寸决定;
是否必选:不填写则默认按照摄像头初始化时的像素原尺寸输出;
注意事项:X参数为从左开始的横向裁切宽度
         例如X为10,则裁切掉左边10列像素;
参数示例:--如下方所示,第1个参数为输出的照片结果裁切掉左边10列像素;
         local result , path = excamera.photo(1015 , 310 , 465)

y

参数含义:裁剪起始纵坐标;
数据类型:number
取值范围:根据所使用摄像头实际支持的像素尺寸决定;
是否必选:不填写则默认按照摄像头初始化时的像素原尺寸输出;
注意事项:y参数为从最下开始向上的纵向裁切高度
         例如y为15,则裁切掉最下面15行像素;
参数示例:--如下方所示,第2个参数为输出的照片结果裁切掉下面15行像素;
         local result , path = excamera.photo(1015 , 310 , 465)

w

参数含义:裁剪后的宽度;
数据类型:number
取值范围:根据所使用摄像头实际支持的像素尺寸决定;
是否必选:不填写则默认按照摄像头初始化时的像素原尺寸输出;
注意事项:w参数为照片裁切后的宽度
         例如w为310,则保留310宽的像素信息;
参数示例:--如下方所示,第3个参数为输出保留310列像素宽的照片;
         local result , path = excamera.photo(1015 , 310 , 465)

h

参数含义:裁剪后的高度;
数据类型:number
取值范围:根据所使用摄像头实际支持的像素尺寸决定;
是否必选:不填写则默认按照摄像头初始化时的像素原尺寸输出;
注意事项:h参数为照片裁切后的高度
         例如h为465,则保留465高的像素信息;
参数示例:--如下方所示,第4个参数为输出保留465行像素高的照片;
         local result , path = excamera.photo(1015 , 310 , 465)

返回值

local result , path = excamera.photo(x, y, w, h)

此处有 2 个返回值

result

含义说明:拍照的结果;
数据类型:boolean
取值范围:成功时返回true,失败时返回false
注意事项:拍照动作会存在以下失败的情况:
         1、摄像头初始化失败:打印"摄像头初始化失败,请重新确认软硬件配置"
         2、拍照执行失败:打印"拍照失败,请重试"
         3、摄像头初始化成功,但是拍照完成后无照片数据返回:打印"拍照成功,无照片生成"
            这种情况一般是照片保存路径内存溢出导致,需检查存储照片容器的内存信息;
返回示例:true

path

含义说明:照片保存的文件路径或者zbuff内存数据
数据类型:string或zbuff
取值范围:使用文件路径保存照片时,取值范围为string
         使用zbuff保存照片时,取值范围为zbuff
注意事项:拍照业务是以覆盖写入的形式存储照片的,所以在执行第二次拍照前一定要将上一次拍照的照片处理好再进行下一次拍照,否则将会被覆盖;
返回示例:
        使用zbuff时返回示例
        zbuff: 0C1A0988
        使用文件路径时返回示例:
        /ram/abc.jpg

示例

-- 拍照动作执行示例
local result , path = excamera.photo(1015 , 310 , 465)
log.info("拍照执行状态:", result, "照片保存在:", path)

4.3 excamera.scan(ms)

功能

摄像头扫描功能函数,可以配置一次扫描的时长,在扫描时长内扫描出结果时即可返回扫描结果,超时未扫描到结果返回 false;

参数

ms

参数含义:扫描时长,单位:毫秒;
数据类型:number
取值范围:大于等于1,小于等于0x7FFFFFFF,之间的所有正整数;最大时长0x7FFFFFFF毫秒  596小时  24.85天;
是否必选:必选;
注意事项:扫描时模组会实时处理摄像头返回的预览视频流,gc032a和gc0310的内存占用在600K以上,所以需要通过扫描时长限制摄像头打开的周期,避免造成内存溢出死机等问题;
参考示例:--如下方所示,执行一次5秒钟的扫描,5秒后返回执行结果和扫描的结果;
         local  result , data = excamera.scan(5000)

返回值

local result , data = excamera.scan(ms)

此处有 2 个返回值

result

含义说明:扫描动作执行结果;
数据类型:boolean
取值范围:成功时返回true,失败时返回false
注意事项:扫描动作会存在以下失败的情况:
         1、摄像头初始化失败:打印"摄像头初始化失败,请重新确认软硬件配置"
         2、扫描执行失败:打印"ms秒内未扫描成功,请将摄像头对准二维码"
返回示例:true

data

含义说明:扫描的结果;
数据类型:string或nil
取值范围:扫描成功返回扫描结果;
         扫描失败返回nil
注意事项:扫描结果会直接赋值给data变量,并不会做存储,所以每次扫描后请保存好扫描结果再执行下一次扫描;
返回示例:"Air780EPM.cn"

示例

-- 扫描动作执行示例
local  result , data = excamera.scan(5000)
log.info("扫描执行状态:", result, "扫描结果:", data )

4.4 excamera.video(file_path, duration)

功能

使用指定摄像头录制视频存储到指定路径下;

注意事项

视频录制通常存储在sd卡当中,模组存储空间有限,请注意存储空间是否充足;

参数

file_path

参数含义:保存视频的路径;
数据类型:string
取值范围:暂无;
是否必选:必选;
注意事项:文件尾缀必须以.mp4结尾
参考示例:local  result , path = excamera.video("/sd/video.mp4", 5000)

duration

参数含义:录制视频时长,单位:毫秒;
数据类型:number
取值范围:至少大于1000毫秒,小于等于0x7FFFFFFF,之间的所有正整数;最大时长0x7FFFFFFF毫秒  596小时  24.85天;
是否必选:必选;
注意事项:暂无;
参考示例:local  result , path = excamera.video("/sd/video.mp4", 5000)

返回值

local result , path = excamera.video(file_path, duration)

result

含义说明:录制视频结果;
数据类型:boolean
取值范围:成功时返回true,失败时返回false
注意事项:暂无:
返回示例:true

path

含义说明:录制视频存放路径;
数据类型:string
取值范围:应与参数中的file_path设置的路径一致
注意事项:只有录制视频成功了才会返回视频存放路径:
返回示例: "/sd/video.mp4"

示例

-- 录制视频示例
excamera.video("/sd/video.mp4", 5000)

4.5 excamera.rtmp()

功能

启动摄像头为RTMP推流做准备;

参数

nil

返回值

local result = excamera.rtmp()

result

含义说明:启动摄像头为RTMP推流做准备的结果
数据类型:boolean
取值范围:成功时返回true,失败时返回false
注意事项:暂无:
返回示例:true

示例

local result = excamera.rtmp()
log.info("启动摄像头结果:",result )

4.6 excamera.close()

功能

关闭摄像头业务;

在 excamera 扩展库内部,会自动处理以下逻辑:

拉低摄像头供电使能管脚;

拉高摄像头 PWDN 管脚,摄像头进入待机状态;

如果使用了 zbuff,释放相关资源;

关闭 I2C 配置传输接口;

调用该接口时会关闭一切摄像头的管脚,释放摄像头占用管脚,让这些管脚可以复用给其他业务使用;

参数

boolean

参数含义:是否保留ZBUFF
数据类型:boolean
取值范围:true/nil
是否必选:可选;
注意事项:使用ZBUFF为存储方式时才传true,其他存储方式nil即可
参考示例:excamera.close(true)

返回值

示例

-- 关闭摄像头,释放资源
-- 使用ZBUFF存储方式时,close传入true后,excamera内部创建的ZBUFF会缩减至0字节,放出内存但是不释放ZBUFF,便于下次拍照时调用;
-- 重复申请和释放ZBUFF会导致垃圾内存堆积,影响系统内存;
excamera.close(true)

五、exexcamera应用参考

在当前合宙所有SOC上,摄像头一直是一个负担较重的业务,内存的管理不当,极容易造成摄像头初始化失败、拍照成功但没有照片、甚至拍照失败的情况。在有摄像头需求的产品上,照片是整个产品至关重要的核心,无法确保拍照业务正常执行,那产品失去灵魂。所以为了确保拍照功能的稳定性,在使用excamera时,我们提供了下述的应用参考。

常规模式循环拍照

在长供电场景下,摄像头可以一直稳定上电,为了确保摄像头业务的正常执行,只需要做一次摄像头初始化,后续重复调用excamera.photo获取照片结果即可,原理是将摄像头业务执行时所使用的内存区域占好,确保摄像头业务正常执行,根据照片保存路径不同,会有以下内存使用差异:

ZBUFF or RAM路径存储

这个路径是将照片结果存放在sys ram中,差异是使用ZBUFF方式存储时,excamera会将预占用足够存储照片的空间,确保照片可以输出,RAM路径存储可能会因为其他业务的内存占用导致照片输出异常。因为两个方式都是存在内存中,所以直接使用ZBUFF即可。内存占用大小计算方式为: ( 摄像头像素高 X 摄像头像素宽 X 3.5 ) GC032A举例:像素高为640,像素宽为480,则 ( 640 X 480 X 3.5 )= 1075200 (B) ≈ 1MB 在使用GC032A,ZBUFF方式存储照片结果的环境下,当调用 excamera.open() 后,sys ram 就会被占用1MB。后续只需要循环调用excamera.photo()获取照片即可,这 1MB 内存占用不会变大,当出现拍照报错时,再调用关闭接口重新初始化,参考代码如下:

-- 引入excamera扩展库模块
local excamera = require "excamera"

-- 定义照片存储路径
local save_method = "ZBUFF"
-- local save_method = "/ram/test.jpg"

function camera_func()

    -- 出现异常后重新初始化
    while true do
        -- 配置gc032a摄像头参数表
        local spi_camera_param = {
            id = "gc032a", -- SPI摄像头仅支持"gc032a"、"gc0310"、"bf30a2",请带引号填写
            i2c_id = 1, -- 模块上使用的I2C编号
            work_mode = 0, -- 工作模式,0为拍照模式,1为扫描模式
            save_path = nil, -- 扫描结果为字符串返回,使用变量赋值既可
            camera_pwr = 2, -- 摄像头使能管脚,填写GPIO号即可,无则填nil
            camera_pwdn = 5, -- 摄像头pwdn开关脚,填写GPIO号即可,无则填nil
            camera_light = nil -- 摄像头补光灯控制管脚,填写GPIO号即可,无则填nil
        }

        -- 初始化摄像头,传入配置参数
        result = excamera.open(spi_camera_param)
        -- 记录摄像头初始化状态
        log.info("初始化状态", result)

        -- 循环触发拍照任务
        while result do
            -- 执行拍照操作
            result, data = excamera.photo()
            -- 判断拍照任务正常则上传,错误则重新初始化摄像头
            if result then
                -- 执行照片上传
                -- (upload...)
            end
        end
        -- 关闭摄像头,重新初始化
        excamera.close(true)
    end
end

sys.taskInit(camera_func)

文件系统存储

使用外挂SD卡或SOC内的FLASH来存储照片时,因为 excamera.photo() 是直接将照片结果输出到路径的,内存不需要存储照片结果,所以 excamera.open() 初始化后,只会占用摄像头业务所需要的内存,计算方式为: ( 摄像头像素高 X 摄像头像素宽 X 2 ) GC032A举例:像素高为640,像素宽为480,则 ( 640 X 480 X 2 )= 614400 (B) ≈ 620KB 参考代码如上,只是路径将路径修改为文件路径,参考代码如下:

-- 定义照片存储路径
local save_method = "/SD/ABC.jpg"

低功耗模式循环拍照

在低功耗应用中,为了将功耗降到最低,都会在拍摄任务完成后将摄像头完全关断,等待下次唤醒后再上电重新初始化应用。这种场景下为了确保摄像头业务能够正常执行,就必须要有足够的连续内存。因为脚本各类功能持续的工作,内存被反复占用和释放后,即便此时内存有足够的余量,也没有连续的内存能够给摄像头使用,所以此时的最优解是重启设备,把内存刷新,并且在刚开机的时候就将摄像头初始化完成,让摄像头业务先占用好足够的内存空间。以便后续业务随时调用摄像头使用。参考代码如下:

-- 引入excamera扩展库模块
local excamera = require "excamera"

-- 定义照片存储路径
local save_method = "ZBUFF"
-- local save_method = "/ram/test.jpg"

function camera_func()

    -- 配置gc032a摄像头参数表
    local spi_camera_param = {
        id = "gc032a", -- SPI摄像头仅支持"gc032a"、"gc0310"、"bf30a2",请带引号填写
        i2c_id = 1, -- 模块上使用的I2C编号
        work_mode = 0, -- 工作模式,0为拍照模式,1为扫描模式
        save_path = nil, -- 扫描结果为字符串返回,使用变量赋值既可
        camera_pwr = 2, -- 摄像头使能管脚,填写GPIO号即可,无则填nil
        camera_pwdn = 5, -- 摄像头pwdn开关脚,填写GPIO号即可,无则填nil
        camera_light = nil -- 摄像头补光灯控制管脚,填写GPIO号即可,无则填nil
    }

    -- 初始化摄像头,传入配置参数
    local result = excamera.open(spi_camera_param)

    if not result then
        -- 记录摄像头初始化状态
        log.info("已无足够连续内存用于拍照业务执行,重启刷新内存后重试", result)
        reboot()
    end

    -- 执行拍照操作
    result, data = excamera.photo()
    -- 判断拍照任务正常则上传,错误则重新初始化摄像头
    if result then
        -- 执行照片上传
        -- (upload...)
    end
    -- 关闭摄像头,重新初始化
    excamera.close(true)
end

sys.taskInit(camera_func)

拍照需要裁切照片

当调用 excamera.photo(x,y,w,h) 需要使用 x,y,w,h 参数裁切照片时,内存会额外占用 ( 摄像头像素高 X 摄像头像素宽 X 1.5 )的空间,这个内存额外占用仅在执行 excamera.photo(x,y,w,h) 期间,当获取到照片结果时就会被释放掉,根据实际拍照应用需求,预备足够的内存余量再执行拍照业务。

拍照方案最优解

根据上述的应用参考,假设使用 GC032A 时,内存会有 1MB - 1.5MB 被占用,在Air780EPM这类小内存的SOC上,sys ram 分配只有 2.3MB ,基本占用了一大半,剩余 1MB 左右可以给其他业务使用,极易造成内存爆满的情况,所以当有摄像头需求时,选择Air8000系列、Air780EHM/EHV/EGH、Air700ECH这类 8MB + 8MB 大内存的SOC才是最优解。结合上述的应用参考,在脚本中增加足够的保护机制,就可以让摄像头业务稳定执行,增加产品的稳定性和更长的使用生命周期。

六、产品支持说明

支持 LuatOS 开发的 Air780 系列,Air8000 系列,Air8101 系列 产品都支持 excamera 库。