Add exposure control for all sensors (#292)

* Textual register cleanup.

No functional changes.

* Add exposure control support.

You can now set the exposure for the camera in microseconds (versus an
opaque unknown value previously). First, we have a new method called
get_exposure_us() which will get the expsoure time in microseconds. This
let's you determine what the auto exposure algorithm set the exposure
time to. Second, the previously implmented set_auto_exposure() method
which allows you to turn aec off and on accepts a exposure_us keyword
argument when you turn aec off to manually control the exposure.

The next commit will add support for other sensor types.

* Cleanup register formatting.

No functional changes.

* Add exposure control support for the OV2640.

Register access for this chip is a PITA.

* Formatting Cleanup.

No functional changes.

* Add exposure control for ov9650.

Just doing it for all sensors.

* Add missing 2 factor.

* Added exposure control for the MT9V034.

* Add exposure control example.

Works well on the OV7725.
This commit is contained in:
Kwabena W. Agyeman 2017-12-30 08:56:11 -05:00 committed by Ibrahim Abd Elkader
parent c78a269f5a
commit 7be0a7a182
12 changed files with 477 additions and 148 deletions

View File

@ -95,6 +95,13 @@
#define MT9V034_AGC_ENABLE (1 << 1)
#define MT9V034_THERMAL_INFO (0xC1)
#define MT9V034_WINDOW_HEIGHT_A (0x03)
#define MT9V034_WINDOW_WIDTH_A (0x04)
#define MT9V034_HORIZONTAL_BLANKING_A (0x05)
#define MT9V034_VERTICAL_BLANKING_A (0x06)
#define MT9V034_COARSE_SHUTTER_WIDTH_TOTAL_A (0x0B)
#define MT9V034_FINE_SHUTTER_WIDTH_TOTAL_A (0xD5)
static int reset(sensor_t *sensor)
{
// NOTE: TODO This doesn't reset register configuration.
@ -199,9 +206,41 @@ static int set_auto_gain(sensor_t *sensor, int enable, int gain)
return 0;
}
static int set_auto_exposure(sensor_t *sensor, int enable, int exposure)
static int set_auto_exposure(sensor_t *sensor, int enable, int exposure_us)
{
return 0;
uint16_t reg, row_limit_0, row_limit_1, row_time_0, row_time_1;
int ret = cambus_readw(sensor->slv_addr, MT9V034_AEC_AGC_ENABLE, &reg);
ret |= cambus_writew(sensor->slv_addr, MT9V034_AEC_AGC_ENABLE, (reg & (~MT9V034_AEC_ENABLE)) | ((enable != 0) & MT9V034_AEC_ENABLE));
if ((enable == 0) && (exposure_us >= 0)) {
ret |= cambus_readw(sensor->slv_addr, MT9V034_WINDOW_HEIGHT_A, &row_limit_0);
ret |= cambus_readw(sensor->slv_addr, MT9V034_VERTICAL_BLANKING_A, &row_limit_1);
ret |= cambus_readw(sensor->slv_addr, MT9V034_WINDOW_WIDTH_A, &row_time_0);
ret |= cambus_readw(sensor->slv_addr, MT9V034_HORIZONTAL_BLANKING_A, &row_time_1);
int exposure = exposure_us * (27000000 / 1000000);
int row_time = row_time_0 + row_time_1;
int coarse_time = IM_MIN((exposure / row_time), (row_limit_0 + row_limit_1));
int fine_time = exposure % row_time;
ret |= cambus_writew(sensor->slv_addr, MT9V034_COARSE_SHUTTER_WIDTH_TOTAL_A, coarse_time);
ret |= cambus_writew(sensor->slv_addr, MT9V034_FINE_SHUTTER_WIDTH_TOTAL_A, fine_time);
}
return ret;
}
static int get_exposure_us(sensor_t *sensor, int *exposure_us)
{
uint16_t int_rows, int_pixels, row_time_0, row_time_1;
int ret = cambus_readw(sensor->slv_addr, MT9V034_COARSE_SHUTTER_WIDTH_TOTAL_A, &int_rows);
ret |= cambus_readw(sensor->slv_addr, MT9V034_FINE_SHUTTER_WIDTH_TOTAL_A, &int_pixels);
ret |= cambus_readw(sensor->slv_addr, MT9V034_WINDOW_WIDTH_A, &row_time_0);
ret |= cambus_readw(sensor->slv_addr, MT9V034_HORIZONTAL_BLANKING_A, &row_time_1);
*exposure_us = ((int_rows * (row_time_0 + row_time_1)) + int_pixels) / (27000000 / 1000000);
return ret;
}
static int set_auto_whitebal(sensor_t *sensor, int enable, int r_gain, int g_gain, int b_gain)
@ -229,7 +268,6 @@ static int set_lens_correction(sensor_t *sensor, int enable, int radi, int coef)
return 0;
}
int mt9v034_init(sensor_t *sensor)
{
// Initialize sensor structure.
@ -248,6 +286,7 @@ int mt9v034_init(sensor_t *sensor)
sensor->set_colorbar = set_colorbar;
sensor->set_auto_gain = set_auto_gain;
sensor->set_auto_exposure = set_auto_exposure;
sensor->get_exposure_us = get_exposure_us;
sensor->set_auto_whitebal = set_auto_whitebal;
sensor->set_hmirror = set_hmirror;
sensor->set_vflip = set_vflip;

View File

@ -14,6 +14,7 @@
#include "ov2640.h"
#include "systick.h"
#include "ov2640_regs.h"
#include "omv_boardconfig.h"
#define SVGA_HSIZE (800)
#define SVGA_VSIZE (600)
@ -619,22 +620,96 @@ static int set_auto_gain(sensor_t *sensor, int enable, int gain)
return cambus_writeb(sensor->slv_addr, COM8, reg) | ret;
}
static int set_auto_exposure(sensor_t *sensor, int enable, int exposure)
static int set_auto_exposure(sensor_t *sensor, int enable, int exposure_us)
{
uint8_t reg;
/* Switch to SENSOR register bank */
int ret = cambus_writeb(sensor->slv_addr, BANK_SEL, BANK_SEL_SENSOR);
/* Update COM8 */
int ret = cambus_readb(sensor->slv_addr, BANK_SEL, &reg);
ret |= cambus_writeb(sensor->slv_addr, BANK_SEL, reg | BANK_SEL_SENSOR);
ret |= cambus_readb(sensor->slv_addr, COM8, &reg);
ret |= cambus_writeb(sensor->slv_addr, COM8, COM8_SET_AEC(reg, (enable != 0)));
if (enable) {
reg |= COM8_AEC_EN;
} else {
reg &= ~COM8_AEC_EN;
if ((enable == 0) && (exposure_us >= 0)) {
ret |= cambus_readb(sensor->slv_addr, COM7, &reg);
int t_line = 0;
if (COM7_GET_RES(reg) == COM7_RES_UXGA) t_line = 1600 + 322;
if (COM7_GET_RES(reg) == COM7_RES_SVGA) t_line = 800 + 390;
if (COM7_GET_RES(reg) == COM7_RES_CIF) t_line = 400 + 195;
ret |= cambus_readb(sensor->slv_addr, CLKRC, &reg);
int pll_mult = (reg & CLKRC_DOUBLE) ? 2 : 1;
int clk_rc = ((reg & CLKRC_DIVIDER_MASK) + 1) * 2;
ret |= cambus_readb(sensor->slv_addr, BANK_SEL, &reg);
ret |= cambus_writeb(sensor->slv_addr, BANK_SEL, reg & (~BANK_SEL_SENSOR));
ret |= cambus_readb(sensor->slv_addr, IMAGE_MODE, &reg);
int t_pclk = 0;
if (IMAGE_MODE_GET_FMT(reg) == IMAGE_MODE_YUV422) t_pclk = 2;
if (IMAGE_MODE_GET_FMT(reg) == IMAGE_MODE_RAW10) t_pclk = 1;
if (IMAGE_MODE_GET_FMT(reg) == IMAGE_MODE_RGB565) t_pclk = 2;
int exposure = IM_MAX(IM_MIN(((exposure_us*(((OMV_XCLK_FREQUENCY/clk_rc)*pll_mult)/1000000))/t_pclk)/t_line,0xFFFF),0x0000);
ret |= cambus_readb(sensor->slv_addr, BANK_SEL, &reg);
ret |= cambus_writeb(sensor->slv_addr, BANK_SEL, reg | BANK_SEL_SENSOR);
ret |= cambus_readb(sensor->slv_addr, REG04, &reg);
ret |= cambus_writeb(sensor->slv_addr, REG04, (reg & 0xFC) | ((exposure >> 0) & 0x3));
ret |= cambus_readb(sensor->slv_addr, AEC, &reg);
ret |= cambus_writeb(sensor->slv_addr, AEC, (reg & 0x00) | ((exposure >> 2) & 0xFF));
ret |= cambus_readb(sensor->slv_addr, REG04, &reg);
ret |= cambus_writeb(sensor->slv_addr, REG04, (reg & 0xC0) | ((exposure >> 10) & 0x3F));
}
return cambus_writeb(sensor->slv_addr, COM8, reg) | ret;
return ret;
}
static int get_exposure_us(sensor_t *sensor, int *exposure_us)
{
uint8_t reg, aec_10, aec_92, aec_1510;
int ret = cambus_readb(sensor->slv_addr, BANK_SEL, &reg);
ret |= cambus_writeb(sensor->slv_addr, BANK_SEL, reg | BANK_SEL_SENSOR);
ret |= cambus_readb(sensor->slv_addr, COM8, &reg);
if (reg & COM8_AEC_EN) {
ret |= cambus_writeb(sensor->slv_addr, COM8, reg & (~COM8_AEC_EN));
}
ret |= cambus_readb(sensor->slv_addr, REG04, &aec_10);
ret |= cambus_readb(sensor->slv_addr, AEC, &aec_92);
ret |= cambus_readb(sensor->slv_addr, REG45, &aec_1510);
if (reg & COM8_AEC_EN) {
ret |= cambus_writeb(sensor->slv_addr, COM8, reg | COM8_AEC_EN);
}
ret |= cambus_readb(sensor->slv_addr, COM7, &reg);
int t_line = 0;
if (COM7_GET_RES(reg) == COM7_RES_UXGA) t_line = 1600 + 322;
if (COM7_GET_RES(reg) == COM7_RES_SVGA) t_line = 800 + 390;
if (COM7_GET_RES(reg) == COM7_RES_CIF) t_line = 400 + 195;
ret |= cambus_readb(sensor->slv_addr, CLKRC, &reg);
int pll_mult = (reg & CLKRC_DOUBLE) ? 2 : 1;
int clk_rc = ((reg & CLKRC_DIVIDER_MASK) + 1) * 2;
ret |= cambus_readb(sensor->slv_addr, BANK_SEL, &reg);
ret |= cambus_writeb(sensor->slv_addr, BANK_SEL, reg & (~BANK_SEL_SENSOR));
ret |= cambus_readb(sensor->slv_addr, IMAGE_MODE, &reg);
int t_pclk = 0;
if (IMAGE_MODE_GET_FMT(reg) == IMAGE_MODE_YUV422) t_pclk = 2;
if (IMAGE_MODE_GET_FMT(reg) == IMAGE_MODE_RAW10) t_pclk = 1;
if (IMAGE_MODE_GET_FMT(reg) == IMAGE_MODE_RGB565) t_pclk = 2;
uint16_t exposure = ((aec_1510 & 0x3F) << 10) + ((aec_92 & 0xFF) << 2) + ((aec_10 & 0x3) << 0);
*exposure_us = (exposure*t_line*t_pclk)/(((OMV_XCLK_FREQUENCY/clk_rc)*pll_mult)/1000000);
return ret;
}
static int set_auto_whitebal(sensor_t *sensor, int enable, int r_gain, int g_gain, int b_gain)
@ -708,6 +783,7 @@ int ov2640_init(sensor_t *sensor)
sensor->set_colorbar = set_colorbar;
sensor->set_auto_gain = set_auto_gain;
sensor->set_auto_exposure = set_auto_exposure;
sensor->get_exposure_us = get_exposure_us;
sensor->set_auto_whitebal = set_auto_whitebal;
sensor->set_hmirror = set_hmirror;
sensor->set_vflip = set_vflip;

View File

@ -5,61 +5,64 @@
*
* OV2640 register definitions.
*/
#ifndef __REG_REGS_H__
#define __REG_REGS_H__
/* DSP register bank FF=0x00*/
#define QS 0x44
#define HSIZE 0x51
#define VSIZE 0x52
#define XOFFL 0x53
#define YOFFL 0x54
#define VHYX 0x55
#define DPRP 0x56
#define TEST 0x57
#define ZMOW 0x5A
#define ZMOH 0x5B
#define ZMHH 0x5C
#define BPADDR 0x7C
#define BPDATA 0x7D
#define SIZEL 0x8C
#define HSIZE8 0xC0
#define VSIZE8 0xC1
#define CTRL1 0xC3
#define MS_SP 0xF0
#define SS_ID 0xF7
#define SS_CTRL 0xF7
#define MC_AL 0xFA
#define MC_AH 0xFB
#define MC_D 0xFC
#define P_CMD 0xFD
#define P_STATUS 0xFE
#define CTRLI 0x50
#define CTRLI_LP_DP 0x80
#define CTRLI_ROUND 0x40
#define QS 0x44
#define HSIZE 0x51
#define VSIZE 0x52
#define XOFFL 0x53
#define YOFFL 0x54
#define VHYX 0x55
#define DPRP 0x56
#define TEST 0x57
#define ZMOW 0x5A
#define ZMOH 0x5B
#define ZMHH 0x5C
#define BPADDR 0x7C
#define BPDATA 0x7D
#define SIZEL 0x8C
#define HSIZE8 0xC0
#define VSIZE8 0xC1
#define CTRL1 0xC3
#define MS_SP 0xF0
#define SS_ID 0xF7
#define SS_CTRL 0xF7
#define MC_AL 0xFA
#define MC_AH 0xFB
#define MC_D 0xFC
#define P_CMD 0xFD
#define P_STATUS 0xFE
#define CTRL0 0xC2
#define CTRL0_AEC_EN 0x80
#define CTRL0_AEC_SEL 0x40
#define CTRL0_STAT_SEL 0x20
#define CTRL0_VFIRST 0x10
#define CTRL0_YUV422 0x08
#define CTRL0_YUV_EN 0x04
#define CTRL0_RGB_EN 0x02
#define CTRL0_RAW_EN 0x01
#define CTRLI 0x50
#define CTRLI_LP_DP 0x80
#define CTRLI_ROUND 0x40
#define CTRL2 0x86
#define CTRL2_DCW_EN 0x20
#define CTRL2_SDE_EN 0x10
#define CTRL2_UV_ADJ_EN 0x08
#define CTRL2_UV_AVG_EN 0x04
#define CTRL2_CMX_EN 0x01
#define CTRL0 0xC2
#define CTRL0_AEC_EN 0x80
#define CTRL0_AEC_SEL 0x40
#define CTRL0_STAT_SEL 0x20
#define CTRL0_VFIRST 0x10
#define CTRL0_YUV422 0x08
#define CTRL0_YUV_EN 0x04
#define CTRL0_RGB_EN 0x02
#define CTRL0_RAW_EN 0x01
#define CTRL3 0x87
#define CTRL3_BPC_EN 0x80
#define CTRL3_WPC_EN 0x40
#define R_DVP_SP 0xD3
#define R_DVP_SP_AUTO_MODE 0x80
#define CTRL2 0x86
#define CTRL2_DCW_EN 0x20
#define CTRL2_SDE_EN 0x10
#define CTRL2_UV_ADJ_EN 0x08
#define CTRL2_UV_AVG_EN 0x04
#define CTRL2_CMX_EN 0x01
#define CTRL3 0x87
#define CTRL3_BPC_EN 0x80
#define CTRL3_WPC_EN 0x40
#define R_DVP_SP 0xD3
#define R_DVP_SP_AUTO_MODE 0x80
#define R_BYPASS 0x05
#define R_BYPASS_DSP_EN 0x00
@ -73,6 +76,7 @@
#define IMAGE_MODE_RGB565 0x08
#define IMAGE_MODE_HREF_VSYNC 0x02
#define IMAGE_MODE_LBYTE_FIRST 0x01
#define IMAGE_MODE_GET_FMT(x) ((x)&0xC)
#define RESET 0xE0
#define RESET_MICROC 0x40
@ -98,13 +102,18 @@
#define BANK_SEL_SENSOR 0x01
/* Sensor register bank FF=0x01*/
#define GAIN 0x00
#define COM1 0x03
#define REG_PID 0x0A
#define REG_VER 0x0B
#define COM4 0x0D
#define AEC 0x10
#define CLKRC 0x11
#define CLKRC_DOUBLE 0x80
#define CLKRC_DIVIDER_MASK 0x3F
#define COM10 0x15
#define HSTART 0x17
#define HSTOP 0x18
@ -168,6 +177,7 @@
#define COM7_RES_CIF 0x20 /* CIF */
#define COM7_ZOOM_EN 0x04 /* Enable Zoom */
#define COM7_COLOR_BAR 0x02 /* Enable Color Bar Test */
#define COM7_GET_RES(x) ((x)&0x70)
#define COM8 0x13
#define COM8_DEFAULT 0xC0
@ -175,6 +185,7 @@
#define COM8_AGC_EN 0x04 /* AGC Auto/Manual control selection */
#define COM8_AEC_EN 0x01 /* Auto/Manual Exposure control */
#define COM8_SET(x) (COM8_DEFAULT|x)
#define COM8_SET_AEC(r,x) (((r)&0xFE)|((x)&1))
#define COM9 0x14 /* AGC gain ceiling */
#define COM9_DEFAULT 0x08
@ -196,4 +207,5 @@
#define REG32_UXGA 0x36
#define REG32_SVGA 0x09
#define REG32_CIF 0x00
#endif //__REG_REGS_H__

View File

@ -369,24 +369,87 @@ static int set_auto_gain(sensor_t *sensor, int enable, int gain)
return ret;
}
static int set_auto_exposure(sensor_t *sensor, int enable, int exposure)
static int set_auto_exposure(sensor_t *sensor, int enable, int exposure_us)
{
uint8_t reg;
int ret = cambus_readb(sensor->slv_addr, COM8, &reg);
ret |= cambus_writeb(sensor->slv_addr, COM8, COM8_SET_AEC(reg, (enable != 0)));
// Set AEC on/off
reg = COM8_SET_AEC(reg, enable);
ret |= cambus_writeb(sensor->slv_addr, COM8, reg);
if ((enable == 0) && (exposure_us >= 0)) {
ret |= cambus_readb(sensor->slv_addr, COM7, &reg);
if (enable == 0 && exposure >= 0) {
// Set value manually.
ret |= cambus_writeb(sensor->slv_addr, AEC, (exposure&0xFF));
ret |= cambus_writeb(sensor->slv_addr, AECH, ((exposure>>8)&0xFF));
int t_line = (reg & COM7_RES_QVGA) ? (320 + 256) : (640 + 144);
int t_pclk = (COM7_GET_FMT(reg) == COM7_FMT_P_BAYER) ? 1 : 2;
ret |= cambus_readb(sensor->slv_addr, COM4, &reg);
int pll_mult = 0;
if (COM4_GET_PLL(reg) == COM4_PLL_BYPASS) pll_mult = 1;
if (COM4_GET_PLL(reg) == COM4_PLL_4x) pll_mult = 4;
if (COM4_GET_PLL(reg) == COM4_PLL_6x) pll_mult = 6;
if (COM4_GET_PLL(reg) == COM4_PLL_8x) pll_mult = 8;
ret |= cambus_readb(sensor->slv_addr, CLKRC, &reg);
int clk_rc = 0;
if (reg & CLKRC_NO_PRESCALE) {
clk_rc = 1;
} else {
clk_rc = ((reg & CLKRC_PRESCALER) + 1) * 2;
}
int exposure = IM_MAX(IM_MIN(((exposure_us*(((OMV_XCLK_FREQUENCY/clk_rc)*pll_mult)/1000000))/t_pclk)/t_line,0xFFFF),0x0000);
ret |= cambus_writeb(sensor->slv_addr, AEC, ((exposure >> 0) & 0xFF));
ret |= cambus_writeb(sensor->slv_addr, AECH, ((exposure >> 8) & 0xFF));
}
return ret;
}
static int get_exposure_us(sensor_t *sensor, int *exposure_us)
{
uint8_t reg, aec_l, aec_h;
int ret = cambus_readb(sensor->slv_addr, COM8, &reg);
if (reg & COM8_AEC_EN) {
ret |= cambus_writeb(sensor->slv_addr, COM8, COM8_SET_AEC(reg, 0));
}
ret |= cambus_readb(sensor->slv_addr, AEC, &aec_l);
ret |= cambus_readb(sensor->slv_addr, AECH, &aec_h);
if (reg & COM8_AEC_EN) {
ret |= cambus_writeb(sensor->slv_addr, COM8, COM8_SET_AEC(reg, 1));
}
ret |= cambus_readb(sensor->slv_addr, COM7, &reg);
int t_line = (reg & COM7_RES_QVGA) ? (320 + 256) : (640 + 144);
int t_pclk = (COM7_GET_FMT(reg) == COM7_FMT_P_BAYER) ? 1 : 2;
ret |= cambus_readb(sensor->slv_addr, COM4, &reg);
int pll_mult = 0;
if (COM4_GET_PLL(reg) == COM4_PLL_BYPASS) pll_mult = 1;
if (COM4_GET_PLL(reg) == COM4_PLL_4x) pll_mult = 4;
if (COM4_GET_PLL(reg) == COM4_PLL_6x) pll_mult = 6;
if (COM4_GET_PLL(reg) == COM4_PLL_8x) pll_mult = 8;
ret |= cambus_readb(sensor->slv_addr, CLKRC, &reg);
int clk_rc = 0;
if (reg & CLKRC_NO_PRESCALE) {
clk_rc = 1;
} else {
clk_rc = ((reg & CLKRC_PRESCALER) + 1) * 2;
}
*exposure_us = (((aec_h<<8)+(aec_l<<0))*t_line*t_pclk)/(((OMV_XCLK_FREQUENCY/clk_rc)*pll_mult)/1000000);
return ret;
}
static int set_auto_whitebal(sensor_t *sensor, int enable, int r_gain, int g_gain, int b_gain)
{
uint8_t reg;
@ -457,7 +520,6 @@ static int set_lens_correction(sensor_t *sensor, int enable, int radi, int coef)
return ret;
}
int ov7725_init(sensor_t *sensor)
{
// Initialize sensor structure.
@ -476,6 +538,7 @@ int ov7725_init(sensor_t *sensor)
sensor->set_colorbar = set_colorbar;
sensor->set_auto_gain = set_auto_gain;
sensor->set_auto_exposure = set_auto_exposure;
sensor->get_exposure_us = get_exposure_us;
sensor->set_auto_whitebal = set_auto_whitebal;
sensor->set_hmirror = set_hmirror;
sensor->set_vflip = set_vflip;

View File

@ -3,18 +3,20 @@
* Copyright (c) 2013/2014 Ibrahim Abdelkader <i.abdalkader@gmail.com>
* This work is licensed under the MIT license, see the file LICENSE for details.
*
* OV2640 register definitions.
* OV7725 register definitions.
*/
#ifndef __REG_REGS_H__
#define __REG_REGS_H__
#define GAIN 0x00 /* AGC Gain control gain setting */
#define BLUE 0x01 /* AWB Blue channel gain setting */
#define RED 0x02 /* AWB Red channel gain setting */
#define GREEN 0x03 /* AWB Green channel gain setting */
#define BAVG 0x05 /* U/B Average Level */
#define GAVG 0x06 /* Y/Gb Average Level */
#define RAVG 0x07 /* V/R Average Level */
#define AECH 0x08 /* Exposure Value AEC MSBs */
#define GAIN 0x00 /* AGC - Gain control gain setting */
#define BLUE 0x01 /* AWB - Blue channel gain setting */
#define RED 0x02 /* AWB - Red channel gain setting */
#define GREEN 0x03 /* AWB - Green channel gain setting */
#define BAVG 0x05 /* U/B Average Level */
#define GAVG 0x06 /* Y/Gb Average Level */
#define RAVG 0x07 /* V/R Average Level */
#define AECH 0x08 /* Exposure Value - AEC MSBs */
#define COM2 0x09 /* Common Control 2 */
#define COM2_SOFT_SLEEP 0x10 /* Soft sleep mode */
@ -26,28 +28,32 @@
#define PID 0x0A /* Product ID Number MSB */
#define VER 0x0B /* Product ID Number LSB */
#define COM3 0x0C /* Common Control 3 */
#define COM3_VFLIP 0x80 /* Vertical flip image ON/OFF selection */
#define COM3_MIRROR 0x40 /* Horizontal mirror image ON/OFF selection */
#define COM3_SWAP_BR 0x20 /* Swap B/R output sequence in RGB output mode */
#define COM3_SWAP_YUV 0x10 /* Swap Y/UV output sequence in YUV output mode */
#define COM3_SWAP_MSB 0x08 /* Swap output MSB/LSB */
#define COM3_TRI_CLOCK 0x04 /* Tri-state option for output clock at power-down period */
#define COM3_TRI_DATA 0x02 /* Tri-state option for output data at power-down period */
#define COM3_COLOR_BAR 0x01 /* Sensor color bar test pattern output enable */
#define COM3 0x0C /* Common Control 3 */
#define COM3_VFLIP 0x80 /* Vertical flip image ON/OFF selection */
#define COM3_MIRROR 0x40 /* Horizontal mirror image ON/OFF selection */
#define COM3_SWAP_BR 0x20 /* Swap B/R output sequence in RGB output mode */
#define COM3_SWAP_YUV 0x10 /* Swap Y/UV output sequence in YUV output mode */
#define COM3_SWAP_MSB 0x08 /* Swap output MSB/LSB */
#define COM3_TRI_CLOCK 0x04 /* Tri-state option for output clock at power-down period */
#define COM3_TRI_DATA 0x02 /* Tri-state option for output data at power-down period */
#define COM3_COLOR_BAR 0x01 /* Sensor color bar test pattern output enable */
#define COM3_SET_CBAR(r, x) ((r&0xFE)|((x&1)<<0))
#define COM3_SET_MIRROR(r, x) ((r&0xBF)|((x&1)<<6))
#define COM3_SET_FLIP(r, x) ((r&0x7F)|((x&1)<<7))
#define COM3_GET_CBAR(r) ((r>>0)&1)
#define COM3_GET_MIRROR(r) ((r>>6)&1)
#define COM3_GET_FLIP(r) ((r>>7)&1)
#define COM4 0x0D /* Common Control 4 */
#define COM4_PLL_BYPASS 0x00 /* Bypass PLL */
#define COM4_PLL_4x 0x40 /* PLL frequency 4x */
#define COM4_PLL_6x 0x80 /* PLL frequency 6x */
#define COM4_PLL_8x 0xc0 /* PLL frequency 8x */
#define COM4_PLL_8x 0xC0 /* PLL frequency 8x */
#define COM4_AEC_FULL 0x00 /* AEC evaluate full window */
#define COM4_AEC_1_2 0x10 /* AEC evaluate 1/2 window */
#define COM4_AEC_1_4 0x20 /* AEC evaluate 1/4 window */
#define COM4_AEC_2_3 0x30 /* AEC evaluate 2/3 window */
#define COM4_GET_PLL(r) (r&0xC0)
#define COM5 0x0E /* Common Control 5 */
#define COM5_AFR 0x80 /* Auto frame rate control ON/OFF selection (night mode) */
@ -65,7 +71,10 @@
#define COM6_AUTO_WINDOW 0x01 /* Auto window setting ON/OFF selection when format changes */
#define AEC 0x10 /* AEC[7:0] (see register AECH for AEC[15:8]) */
#define CLKRC 0x11 /* Internal Clock */
#define CLKRC_NO_PRESCALE 0x40 /* Use external clock directly */
#define CLKRC_PRESCALER 0x3F /* Internal clock pre-scaler */
#define COM7 0x12 /* Common Control 7 */
#define COM7_RESET 0x80 /* SCCB Register Reset */
@ -83,9 +92,10 @@
#define COM7_FMT_R_BAYER 0x03 /* Output format Bayer RAW */
#define COM7_SET_FMT(r, x) ((r&0xFC)|((x&0x3)<<0))
#define COM7_SET_RES(r, x) ((r&0xBF)|(x))
#define COM7_GET_FMT(r) (r&0x03)
#define COM8 0x13 /* Common Control 8 */
#define COM8_FAST_AUTO 0x80 /* Enable fast AGC/AEC algorithm */
#define COM8 0x13 /* Common Control 8 */
#define COM8_FAST_AUTO 0x80 /* Enable fast AGC/AEC algorithm */
#define COM8_STEP_VSYNC 0x00 /* AEC - Step size limited to vertical blank */
#define COM8_STEP_UNLIMIT 0x40 /* AEC - Step size unlimited step size */
#define COM8_BANDF_EN 0x20 /* Banding filter ON/OFF */
@ -124,13 +134,14 @@
#define REG16 0x16 /* Register 16 */
#define REG16_BIT_SHIFT 0x80 /* Bit shift test pattern options */
#define HSTART 0x17 /* Horizontal Frame (HREF column) Start 8 MSBs (2 LSBs are at HREF[5:4]) */
#define HSIZE 0x18 /* Horizontal Sensor Size (2 LSBs are at HREF[1:0]) */
#define VSTART 0x19 /* Vertical Frame (row) Start 8 MSBs (1 LSB is at HREF[6]) */
#define VSIZE 0x1A /* Vertical Sensor Size (1 LSB is at HREF[2]) */
#define PSHFT 0x1B /* Data Format - Pixel Delay Select */
#define MIDH 0x1C /* Manufacturer ID Byte High */
#define MIDL 0x1D /* Manufacturer ID Byte Low */
#define MIDH 0x1C /* Manufacturer ID Byte - High */
#define MIDL 0x1D /* Manufacturer ID Byte - Low */
#define LAEC 0x1F /* Fine AEC Value - defines exposure value less than one row period */
#define COM11 0x20 /* Common Control 11 */
@ -146,8 +157,8 @@
#define HOUTSIZE 0x29 /* Horizontal Data Output Size MSBs (2 LSBs at register EXHCH[1:0]) */
#define EXHCH 0x2A /* Dummy Pixel Insert MSB */
#define EXHCL 0x2B /* Dummy Pixel Insert LSB */
#define VOUTSIZE 0x2C /* Vertical Data Output Size MSBs (LSB at register EXHCH[2]) */
#define ADVFL 0x2D /* LSB of Insert Dummy Rows in Vertical Sync (1 bit equals 1 row) */
#define VOUTSIZE 0x2C /* Vertical Data Output Size MSBs (LSB at register EXHCH[2]) */
#define ADVFL 0x2D /* LSB of Insert Dummy Rows in Vertical Sync (1 bit equals 1 row) */
#define ADVFH 0x2E /* MSB of Insert Dummy Rows in Vertical Sync */
#define YAVE 0x2F /* Y/G Channel Average Value */
#define LUMHTH 0x30 /* Histogram AEC/AGC Luminance High Level Threshold */
@ -163,6 +174,7 @@
#define OFF_R 0x3A /* AD Offset Compensation Value for R Channel */
#define OFF_GB 0x3B /* AD Offset Compensation Value for GB Channel */
#define OFF_GR 0x3C /* AD Offset Compensation Value for GR Channel */
#define COM12 0x3D /* DC offset compensation for analog process */
#define COM13 0x3E /* Common Control 13 */
@ -174,10 +186,10 @@
#define COM14 0x3F /* Common Control 14 */
#define COM15 0x40 /* Common Control 15 */
#define COM16 0x41 /* Common Control 16 */
#define TGT_B 0x42 /* BLC Blue Channel Target Value */
#define TGT_R 0x43 /* BLC Red Channel Target Value */
#define TGT_GB 0x44 /* BLC Gb Channel Target Value */
#define TGT_GR 0x45 /* BLC Gr Channel Target Value */
#define TGT_B 0x42 /* BLC Blue Channel Target Value */
#define TGT_R 0x43 /* BLC Red Channel Target Value */
#define TGT_GB 0x44 /* BLC Gb Channel Target Value */
#define TGT_GR 0x45 /* BLC Gr Channel Target Value */
#define LC_CTR 0x46 /* Lens Correction Control */
#define LC_CTR_RGB_COMP_1 0x00 /* R, G, and B channel compensation coefficient is set by LC_COEF (0x49) */
@ -219,11 +231,11 @@
#define DSP_CTRL1_BLACK_EN 0x02 /* Black defect auto correction ON/OFF */
#define DSP_CTRL1_WHITE_EN 0x01 /* White defect auto correction ON/OFF */
#define DSP_CTRL2 0x65 /* DSP Control Byte 2 */
#define DSP_CTRL2_VDCW_EN 0x08 /* Vertical DCW enable */
#define DSP_CTRL2_HDCW_EN 0x04 /* Horizontal DCW enable */
#define DSP_CTRL2_VZOOM_EN 0x02 /* Vertical zoom out enable */
#define DSP_CTRL2_HZOOM_EN 0x01 /* Horizontal zoom out enable */
#define DSP_CTRL2 0x65 /* DSP Control Byte 2 */
#define DSP_CTRL2_VDCW_EN 0x08 /* Vertical DCW enable */
#define DSP_CTRL2_HDCW_EN 0x04 /* Horizontal DCW enable */
#define DSP_CTRL2_VZOOM_EN 0x02 /* Vertical zoom out enable */
#define DSP_CTRL2_HZOOM_EN 0x01 /* Horizontal zoom out enable */
#define DSP_CTRL3 0x66 /* DSP Control Byte 3 */
#define DSP_CTRL3_UV_EN 0x80 /* UV output sequence option */
@ -234,13 +246,11 @@
#define DSP_CTRL3_INTRP_PWDN 0x01 /* Interpolation module power down control */
#define DSP_CTRL3_SET_CBAR(r, x) ((r&0xDF)|((x&1)<<5))
#define DSP_CTRL4 0x67 /* DSP Control Byte 4 */
#define DSP_CTRL4_YUV_RGB 0x00 /* Output selection YUV or RGB */
#define DSP_CTRL4_RAW8 0x02 /* Output selection RAW8 */
#define DSP_CTRL4_RAW10 0x03 /* Output selection RAW10 */
#define AWB_BIAS 0x68 /* AWB BLC Level Clip */
#define AWB_CTRL1 0x69 /* AWB Control 1 */
#define AWB_CTRL2 0x6A /* AWB Control 2 */
@ -309,14 +319,14 @@
#define FIFODLYM 0xA3 /* FIFO Manual Mode Delay Control */
#define FIFODLYA 0xA4 /* FIFO Auto Mode Delay Control */
#define SDE 0xA6 /* Special Digital Effect Control */
#define SDE_NEGATIVE_EN 0x40 /* Negative image enable */
#define SDE_GRAYSCALE_EN 0x20 /* Gray scale image enable */
#define SDE_V_FIXED_EN 0x10 /* V fixed value enable */
#define SDE_U_FIXED_EN 0x08 /* U fixed value enable */
#define SDE_CONT_BRIGHT_EN 0x04 /* Contrast/Brightness enable */
#define SDE_SATURATION_EN 0x02 /* Saturation enable */
#define SDE_HUE_EN 0x01 /* Hue enable */
#define SDE 0xA6 /* Special Digital Effect Control */
#define SDE_NEGATIVE_EN 0x40 /* Negative image enable */
#define SDE_GRAYSCALE_EN 0x20 /* Gray scale image enable */
#define SDE_V_FIXED_EN 0x10 /* V fixed value enable */
#define SDE_U_FIXED_EN 0x08 /* U fixed value enable */
#define SDE_CONT_BRIGHT_EN 0x04 /* Contrast/Brightness enable */
#define SDE_SATURATION_EN 0x02 /* Saturation enable */
#define SDE_HUE_EN 0x01 /* Hue enable */
#define USAT 0xA7 /* U Component Saturation Gain */
#define VSAT 0xA8 /* V Component Saturation Gain */
@ -330,6 +340,6 @@
#define DSPAUTO_EDGE_EN 0x20 /* Sharpness (edge enhancement) auto strength control */
#define DSPAUTO_UV_EN 0x10 /* UV adjust auto slope control */
#define DSPAUTO_SCAL0_EN 0x08 /* Auto scaling factor control (register SCAL0 (0xA0)) */
#define DSPAUTO_SCAL1_EN 0x04 /* Auto scaling factor control (registers SCAL1 (0xA1 and SCAL2 (0xA2))*/
#define SET_REG(reg, x) (##reg_DEFAULT|x)
#define DSPAUTO_SCAL1_EN 0x04 /* Auto scaling factor control (registers SCAL1 (0xA1 and SCAL2 (0xA2)) */
#endif //__REG_REGS_H__

View File

@ -14,6 +14,7 @@
#include "ov9650.h"
#include "systick.h"
#include "ov9650_regs.h"
#include "omv_boardconfig.h"
#define NUM_BR_LEVELS 7
@ -320,23 +321,6 @@ static int set_brightness(sensor_t *sensor, int level)
return 0;
}
//static int set_exposure(sensor_t *sensor, int exposure)
//{
// uint8_t val;
// val = cambus_readb(sensor->slv_addr, REG_COM1);
// /* exposure [1:0] */
// cambus_writeb(sensor->slv_addr, REG_COM1, val | (exposure&0x03));
// /* exposure [9:2] */
// cambus_writeb(sensor->slv_addr, REG_AECH, ((exposure>>2)&0xFF));
// /* exposure [15:10] */
// cambus_writeb(sensor->slv_addr, REG_AECHM, ((exposure>>10)&0x3F));
// return 0;
//}
static int set_gainceiling(sensor_t *sensor, gainceiling_t gainceiling)
{
/* Write gain ceiling register */
@ -355,15 +339,73 @@ static int set_auto_gain(sensor_t *sensor, int enable, int gain)
return 0;
}
static int set_auto_exposure(sensor_t *sensor, int enable, int exposure)
static int set_auto_exposure(sensor_t *sensor, int enable, int exposure_us)
{
uint8_t val;
cambus_readb(sensor->slv_addr, REG_COM8, &val);
uint8_t reg;
int ret = cambus_readb(sensor->slv_addr, REG_COM8, &reg);
ret |= cambus_writeb(sensor->slv_addr, REG_COM8, (reg & (~REG_COM8_AEC)) | ((enable != 0) & REG_COM8_AEC));
cambus_writeb(sensor->slv_addr, REG_COM8,
enable ? (val | REG_COM8_AEC) : (val & ~REG_COM8_AEC));
if ((enable == 0) && (exposure_us >= 0)) {
ret |= cambus_readb(sensor->slv_addr, REG_COM7, &reg);
int t_line = 0, t_pclk = (reg & REG_COM7_RGB) ? 2 : 1;
if (reg & REG_COM7_VGA) t_line = 640 + 160;
if (reg & REG_COM7_CIF) t_line = 352 + 168;
if (reg & REG_COM7_QVGA) t_line = 320 + 80;
if (reg & REG_COM7_QCIF) t_line = 176 + 84;
ret |= cambus_readb(sensor->slv_addr, REG_CLKRC, &reg);
int pll_mult = (reg & REG_CLKRC_DOUBLE) ? 2 : 1;
int clk_rc = ((reg & REG_CLKRC_DIVIDER_MASK) + 1) * 2;
return 0;
int exposure = IM_MAX(IM_MIN(((exposure_us*(((OMV_XCLK_FREQUENCY/clk_rc)*pll_mult)/1000000))/t_pclk)/t_line,0xFFFF),0x0000);
ret |= cambus_readb(sensor->slv_addr, REG_COM1, &reg);
ret |= cambus_writeb(sensor->slv_addr, REG_COM1, (reg & 0xFC) | ((exposure >> 0) & 0x3));
ret |= cambus_readb(sensor->slv_addr, REG_AECH, &reg);
ret |= cambus_writeb(sensor->slv_addr, REG_AECH, (reg & 0x00) | ((exposure >> 2) & 0xFF));
ret |= cambus_readb(sensor->slv_addr, REG_AECHM, &reg);
ret |= cambus_writeb(sensor->slv_addr, REG_AECHM, (reg & 0xC0) | ((exposure >> 10) & 0x3F));
}
return ret;
}
static int get_exposure_us(sensor_t *sensor, int *exposure_us)
{
uint8_t reg, aec_10, aec_92, aec_1510;
int ret = cambus_readb(sensor->slv_addr, REG_COM8, &reg);
if (reg & REG_COM8_AEC) {
ret |= cambus_writeb(sensor->slv_addr, REG_COM8, reg & (~REG_COM8_AEC));
}
ret |= cambus_readb(sensor->slv_addr, REG_COM1, &aec_10);
ret |= cambus_readb(sensor->slv_addr, REG_AECH, &aec_92);
ret |= cambus_readb(sensor->slv_addr, REG_AECHM, &aec_1510);
if (reg & REG_COM8_AEC) {
ret |= cambus_writeb(sensor->slv_addr, REG_COM8, reg | REG_COM8_AEC);
}
ret |= cambus_readb(sensor->slv_addr, REG_COM7, &reg);
int t_line = 0, t_pclk = (reg & REG_COM7_RGB) ? 2 : 1;
if (reg & REG_COM7_VGA) t_line = 640 + 160;
if (reg & REG_COM7_CIF) t_line = 352 + 168;
if (reg & REG_COM7_QVGA) t_line = 320 + 80;
if (reg & REG_COM7_QCIF) t_line = 176 + 84;
ret |= cambus_readb(sensor->slv_addr, REG_CLKRC, &reg);
int pll_mult = (reg & REG_CLKRC_DOUBLE) ? 2 : 1;
int clk_rc = ((reg & REG_CLKRC_DIVIDER_MASK) + 1) * 2;
uint16_t exposure = ((aec_1510 & 0x3F) << 10) + ((aec_92 & 0xFF) << 2) + ((aec_10 & 0x3) << 0);
*exposure_us = (exposure*t_line*t_pclk)/(((OMV_XCLK_FREQUENCY/clk_rc)*pll_mult)/1000000);
return ret;
}
static int set_auto_whitebal(sensor_t *sensor, int enable, int r_gain, int g_gain, int b_gain)
@ -411,6 +453,7 @@ int ov9650_init(sensor_t *sensor)
sensor->set_gainceiling = set_gainceiling;
sensor->set_auto_gain = set_auto_gain;
sensor->set_auto_exposure = set_auto_exposure;
sensor->get_exposure_us = get_exposure_us;
sensor->set_auto_whitebal = set_auto_whitebal;
sensor->set_hmirror = set_hmirror;
sensor->set_vflip = set_vflip;

View File

@ -5,8 +5,10 @@
*
* OV9650 register definitions.
*/
#ifndef __REG_REGS_H__
#define __REG_REGS_H__
#define REG_GAIN 0x00
#define REG_BLUE 0x01
#define REG_RED 0x02
@ -110,7 +112,9 @@
#define REG_COM26 0xA5
#define REG_GGAIN 0xA6
#define REG_VGAST 0xA7
/* register bits */
#define REG_COM1_QQCIF (1<<5)
#define REG_COM1_QQVGA (1<<5)
#define REG_COM1_SKIP2 (1<<2)
@ -125,4 +129,7 @@
#define REG_COM8_AEC (1<<0)
#define REG_MVFP_HMIRROR (1<<5)
#define REG_MVFP_VFLIP (1<<4)
#define REG_CLKRC_DOUBLE (1<<8)
#define REG_CLKRC_DIVIDER_MASK (0x3F)
#endif //__REG_REGS_H__

View File

@ -354,12 +354,19 @@ static mp_obj_t py_sensor_set_auto_gain(uint n_args, const mp_obj_t *args, mp_ma
}
static mp_obj_t py_sensor_set_auto_exposure(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
int enable = mp_obj_get_int(args[0]);
int value = py_helper_lookup_int(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_value), -1);
if (sensor_set_auto_exposure(enable, value) != 0) {
return mp_const_false;
int exposure_us = py_helper_lookup_int(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_exposure_us), -1);
if (sensor_set_auto_exposure(mp_obj_get_int(args[0]), exposure_us) != 0) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Sensor control failed!"));
}
return mp_const_true;
return mp_const_none;
}
static mp_obj_t py_sensor_get_exposure_us() {
int exposure_us;
if (sensor_get_exposure_us(&exposure_us) != 0) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Sensor control failed!"));
}
return mp_obj_new_int(exposure_us);
}
static mp_obj_t py_sensor_set_auto_whitebal(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
@ -444,6 +451,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_sensor_set_quality_obj, py_sensor_se
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_sensor_set_colorbar_obj, py_sensor_set_colorbar);
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_sensor_set_auto_gain_obj, 1,py_sensor_set_auto_gain);
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_sensor_set_auto_exposure_obj,1,py_sensor_set_auto_exposure);
STATIC MP_DEFINE_CONST_FUN_OBJ_0(py_sensor_get_exposure_us_obj, py_sensor_get_exposure_us);
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_sensor_set_auto_whitebal_obj,1,py_sensor_set_auto_whitebal);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_sensor_set_hmirror_obj, py_sensor_set_hmirror);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_sensor_set_vflip_obj, py_sensor_set_vflip);
@ -520,6 +528,7 @@ STATIC const mp_map_elem_t globals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_set_colorbar), (mp_obj_t)&py_sensor_set_colorbar_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_set_auto_gain), (mp_obj_t)&py_sensor_set_auto_gain_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_set_auto_exposure), (mp_obj_t)&py_sensor_set_auto_exposure_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_get_exposure_us), (mp_obj_t)&py_sensor_get_exposure_us_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_set_auto_whitebal), (mp_obj_t)&py_sensor_set_auto_whitebal_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_set_hmirror), (mp_obj_t)&py_sensor_set_hmirror_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_set_vflip), (mp_obj_t)&py_sensor_set_vflip_obj },

View File

@ -223,6 +223,8 @@ Q(set_quality)
Q(set_colorbar)
Q(set_auto_gain)
Q(set_auto_exposure)
Q(exposure_us)
Q(get_exposure_us)
Q(set_auto_whitebal)
Q(set_hmirror)
Q(set_vflip)

View File

@ -536,11 +536,22 @@ int sensor_set_auto_gain(int enable, int gain)
return 0;
}
int sensor_set_auto_exposure(int enable, int exposure)
int sensor_set_auto_exposure(int enable, int exposure_us)
{
/* call the sensor specific function */
if (sensor.set_auto_exposure == NULL
|| sensor.set_auto_exposure(&sensor, enable, exposure) != 0) {
|| sensor.set_auto_exposure(&sensor, enable, exposure_us) != 0) {
/* operation not supported */
return -1;
}
return 0;
}
int sensor_get_exposure_us(int *exposure_us)
{
/* call the sensor specific function */
if (sensor.get_exposure_us == NULL
|| sensor.get_exposure_us(&sensor, exposure_us) != 0) {
/* operation not supported */
return -1;
}

View File

@ -136,7 +136,8 @@ typedef struct _sensor {
int (*set_quality) (sensor_t *sensor, int quality);
int (*set_colorbar) (sensor_t *sensor, int enable);
int (*set_auto_gain) (sensor_t *sensor, int enable, int gain);
int (*set_auto_exposure) (sensor_t *sensor, int enable, int exposure);
int (*set_auto_exposure) (sensor_t *sensor, int enable, int exposure_us);
int (*get_exposure_us) (sensor_t *sensor, int *exposure_us);
int (*set_auto_whitebal) (sensor_t *sensor, int enable, int r_gain, int g_gain, int b_gain);
int (*set_hmirror) (sensor_t *sensor, int enable);
int (*set_vflip) (sensor_t *sensor, int enable);
@ -203,7 +204,10 @@ int sensor_set_colorbar(int enable);
int sensor_set_auto_gain(int enable, int gain);
// Enable auto exposure or set value manually.
int sensor_set_auto_exposure(int enable, int exposure);
int sensor_set_auto_exposure(int enable, int exposure_us);
// Get the exposure value.
int sensor_get_exposure_us(int *get_exposure_us);
// Enable auto white balance or set value manually.
int sensor_set_auto_whitebal(int enable, int r_gain, int g_gain, int b_gain);

View File

@ -0,0 +1,53 @@
# Sensor Exposure Control
#
# This example shows off how to cotnrol the camera sensor's
# exposure manually versus letting auto exposure control run.
import sensor, image, time
# Change this value to adjust the exposure. Try 10.0/0.1/etc.
EXPOSURE_TIME_SCALE = 1.0
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)
# Print out the initial exposure time for comparison.
print("Initial exposure == %d" % sensor.get_exposure_us())
sensor.skip_frames(time = 2000) # Wait for settings take effect.
clock = time.clock() # Create a clock object to track the FPS.
# You have to turn automatic gain control and automatic white blance off
# otherwise they will change the image gains to undo any exposure settings
# that you put in place...
sensor.set_auto_gain(False)
sensor.set_auto_whitebal(False)
current_exposure_time_in_microseconds = sensor.get_exposure_us()
print("Current Exposure == %d" % current_exposure_time_in_microseconds)
# Auto exposure control (AEC) is enabled by default. Calling the below function
# disables sensor auto exposure control. The additionally "exposure_us"
# argument then overrides the auto exposure value after AEC is disabled.
sensor.set_auto_exposure(False, \
exposure_us = int(current_exposure_time_in_microseconds * EXPOSURE_TIME_SCALE))
print("New exposure == %d" % sensor.get_exposure_us())
# sensor.get_exposure_us() returns the exact camera sensor exposure time
# in microseconds. However, this may be a different number than what was
# commanded because the sensor code converts the exposure time in microseconds
# to a row/pixel/clock time which doesn't perfectly match with microseconds...
# If you want to turn auto exposure back on do: sensor.set_auto_exposure(True)
# Note that the camera sensor will then change the exposure time as it likes.
# Doing: sensor.set_auto_exposure(False)
# Just disables the exposure value update but does not change the exposure
# value the camera sensor determined was good.
while(True):
clock.tick() # Update the FPS clock.
img = sensor.snapshot() # Take a picture and return the image.
print(clock.fps()) # Note: OpenMV Cam runs about half as fast when connected
# to the IDE. The FPS should increase once disconnected.