BanananaPi上ov 5640カメラオートフォーカス機能の実現

7601 ワード

         ,    ov5640   ,            。

ov 5640はタブレットや携帯電話に使用されるカメラで、画素は500 Wで、この画素は現在では高くなく、中低端携帯電話の画素はこれより高いが、学習カメラ駆動開発には十分である.今回の主な開発と使用プラットフォーム式BananaPi---フル志A 20デュアルコアプロセッサに基づくプラットフォーム.使用するソフトウェアはlinux-sunxiコミュニティのLinuxシステムです.
sunxiのシステムにはov 5640の駆動コードがあるが、この駆動はov 540の多くの機能を去勢し、オートフォーカス(AutoFocus)機能は去勢された機能の列にある.ov 5640のデータマニュアルやその他のアプリケーションマニュアルから見ると、オートフォーカス機能の実現には以下のいくつかのステップが必要です.
1、電源を入れて初期化し、オートフォーカスファームウェア(firmware)に書き込む
2、制御レジスタに指定値を書き込み、オートフォーカスプロセスを開始する
3、オートフォーカスの終了を待ち、レンズを固定して次のフォーカスを待つ
4、電源が切れるまでレンズを一番遠くに固定する
ここでもう一つ注意しなければならない問題は、新しいカメラモジュールには保護フィルムがあり、中のモータを接着しているので、このフィルムを取り除いて焦点距離を調整する必要があります.
ov 5640とマザーボードを接続する方法はいろいろありますが、BananaPiのインタフェースはCSIインタフェース、CSIインタフェースはI 2 Cバスに掛かっているので、ov 5640のレジスタの読み書きはI 2 Cコマンドで行います.ドライバの分析と開発の詳細については、全志の説明ドキュメントを参照してください.http://download.csdn.net/detail/longhui173/8074173
ドライブパスはdrivers/media/video/sun 4 i_csi/device/ov5640.c
上の分析によると、主な修正点は初期化部分とsensor_s_ctrl関数セクション.初期化関数では、カメラモジュールに4 Kのレジスタ値を書き込む必要があります.レジスタの値はファームウェアドキュメントを参照してください.http://download.csdn.net/detail/longhui173/8074193.
初期化セクションは次のように変更されました.
static int sensor_init(struct v4l2_subdev *sd, u32 val)
{
	int ret;
	csi_dev_dbg("sensor_init
"); /*Make sure it is a target sensor*/ ret = sensor_detect(sd); if (ret) { csi_dev_err("chip found is not an target chip.
"); return ret; }
	ret = sensor_write_array(sd, afc_firmware,ARRAY_SIZE( afc_firmware));			//Simon edit 2014/10/13
	if(ret < 0)
	{
		csi_dev_err("write afc reg error!!
"); return ret; }
ret = sensor_write_array(sd, sensor_default_regs , ARRAY_SIZE(sensor_default_regs));if(ret < 0){csi_dev_err("write def array error!!");return ret;}csi_dev_print("start write auto focus register");return ret;}
 
  
afc_firmware 。

sensor_s_ctrl

static int sensor_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
{
	switch (ctrl->id) {
	case V4L2_CID_BRIGHTNESS:
		return sensor_s_brightness(sd, ctrl->value);
	case V4L2_CID_CONTRAST:
		return sensor_s_contrast(sd, ctrl->value);
	case V4L2_CID_SATURATION:
		return sensor_s_saturation(sd, ctrl->value);
	case V4L2_CID_HUE:
		return sensor_s_hue(sd, ctrl->value);
	case V4L2_CID_VFLIP:
		return sensor_s_vflip(sd, ctrl->value);
	case V4L2_CID_HFLIP:
		return sensor_s_hflip(sd, ctrl->value);
	case V4L2_CID_GAIN:
		return sensor_s_gain(sd, ctrl->value);
	case V4L2_CID_AUTOGAIN:
		return sensor_s_autogain(sd, ctrl->value);
	case V4L2_CID_EXPOSURE:
		return sensor_s_exp(sd, ctrl->value);
	case V4L2_CID_EXPOSURE_AUTO:
		return sensor_s_autoexp(sd,
				(enum v4l2_exposure_auto_type) ctrl->value);
	case V4L2_CID_DO_WHITE_BALANCE:
		return sensor_s_wb(sd,
				(enum v4l2_whiteblance) ctrl->value);
	case V4L2_CID_AUTO_WHITE_BALANCE:
		return sensor_s_autowb(sd, ctrl->value);
	case V4L2_CID_COLORFX:
		return sensor_s_colorfx(sd,
				(enum v4l2_colorfx) ctrl->value);
	case V4L2_CID_CAMERA_FLASH_MODE:
	  return sensor_s_flash_mode(sd,
	      (enum v4l2_flash_mode) ctrl->value);
	case V4L2_CID_FOCUS_AUTO:
		return sensor_s_single_af(sd,ctrl->value);
	}
	return -EINVAL;
}

しい も する があります:sensor_s_single_af();
static int sensor_s_single_af(struct v4l2_subdev *sd, int value)
{
	unsigned char i=0;
	int ret;
	struct sensor_info *info = to_state(sd);
	struct regval_list regs;	
	
	csi_dev_print("sensor_s_single_af
"); regs.reg_num[0] = 0x30; //Write 0x00 to 0x3000, enable the mcu regs.reg_num[1] = 0x0; regs.value[0] = 0x00; ret = sensor_write(sd,regs.reg_num,regs.value); if(ret < 0) { csi_dev_err("sensor_write err at start a single af
"); return ret; } regs.reg_num[0] = 0x30; //set 0x3004 BIT6=1,BIT5=1 regs.reg_num[1] = 0x04; ret = sensor_read(sd,regs.reg_num,regs.value); if(ret < 0) { csi_dev_err("sensor_read err at register 0x%x%x
",regs.reg_num[0],regs.reg_num[1]); return ret; } csi_dev_print("register 0x3004 = 0x%x
",regs.value[0]); regs.value[0] |= 0x01 <<5; regs.value[0] |= 0x01 <<6; ret = sensor_write(sd,regs.reg_num,regs.value); if(ret < 0) { csi_dev_err("sensor_write err at register 0x%x%x
",regs.reg_num[0],regs.reg_num[1]); return ret; } regs.reg_num[0] = 0x30; //set 0x3001 BIT6=0 regs.reg_num[1] = 0x01; ret = sensor_read(sd,regs.reg_num,regs.value); if(ret < 0) { csi_dev_err("sensor_read err at register 0x%x%x
",regs.reg_num[0],regs.reg_num[1]); return ret; } csi_dev_print("register 0x%x%x = 0x%2x
",regs.reg_num[0],regs.reg_num[1],regs.value[0]); regs.value[0] &= ~(0x01 <<6); ret = sensor_write(sd,regs.reg_num,regs.value); if(ret < 0) { csi_dev_err("sensor_write err at register 0x%x%x
",regs.reg_num[0],regs.reg_num[1]); return ret; } regs.reg_num[0] = 0x30; //set 0x3005 BIT6=1 regs.reg_num[1] = 0x05; ret = sensor_read(sd,regs.reg_num,regs.value); if(ret < 0) { csi_dev_err("sensor_read err at register 0x%x%x
",regs.reg_num[0],regs.reg_num[1]); return ret; } csi_dev_print("register 0x%x%x = 0x%x
",regs.reg_num[0],regs.reg_num[1],regs.value[0]); regs.value[0] |= 0x01 <<6; ret = sensor_write(sd,regs.reg_num,regs.value); if(ret < 0) { csi_dev_err("sensor_write err at register 0x%x%x
",regs.reg_num[0],regs.reg_num[1]); return ret; } regs.reg_num[0] = 0x30; //Write 0x03 to 0x3022, start singal af regs.reg_num[1] = 0x22; regs.value[0] = 0x03; ret = sensor_write(sd,regs.reg_num,regs.value); if(ret < 0) { csi_dev_err("sensor_write err at start a single af
"); return ret; } while(regs.value[0] !=0 && i < 50) { i++; msleep(100); ret = sensor_read(sd, regs.reg_num, regs.value); if (ret < 0) { csi_dev_err("sensor_read err at sensor_s_single_af!
"); return ret; } csi_dev_print("register 0x3022=0x%x
",regs.value[0]); } if( i >= 50) { csi_dev_print("write 0x03 to 0x3022 timeout!!
"); return -1; } i = 0; regs.reg_num[0] = 0x30; regs.reg_num[1] = 0x29; //regs.value[0] = 0x10; while(regs.value[0] != 0x10 && i < 200) { msleep(500); ret = sensor_read(sd,regs.reg_num,regs.value); if(ret < 0) { csi_dev_err("sensor_read err at sensor_s_single_af!
"); return -1; } csi_dev_print("register 0x3029=0x%x
",regs.value[0]); i++; } if(i >= 200) { csi_dev_err("sensor_s_single_af failed
"); return -1; } csi_dev_print("Single AF ok ,value = 0x10
"); regs.reg_num[0] = 0x30; regs.reg_num[1] = 0x22; regs.value[0] = 0x06; ret = sensor_write(sd,regs.reg_num,regs.value); if(ret < 0) { csi_dev_err("sensor_write err at pause af
"); return ret; } return 0; }

この の くのコードはデバッグのために されます.
アプリケーションで、オートフォーカスが な で を び します.
	    struct v4l2_ext_control  control;
        	CLEAR(control);
        	control.id = V4L2_CID_FOCUS_AUTO;//V4L2_CID_EXPOSURE_AUTO;
        	if (-1 == ioctl(fd, VIDIOC_S_CTRL, &control)) {
		perror("VIDIOC_S_CTRL");
		exit(EXIT_FAILURE);
        	
	}

これでov 5640のオートフォーカスが できます.