lcw_swust 发表于 2015-10-10 11:59:27

基于STM32与OV7670的简陋型光流模块

本帖最后由 lcw_swust 于 2015-10-10 15:42 编辑

首先上传电路和程序:


还有两个VB上位机用于调试:


---------------------------------------------------------------------------------------------
简介:
此模块是利用STM32F103CBT6驱动OV7670摄像头模组,可作简单的图像处理,打算用于四轴飞行器的悬停。
实际应用中可能会不理想,假如环境太单调,那效果就不好。
听说PX4FLOW做得挺好,查了下好像挺贵。
---------------------------------------------------------------------------------------------
OV7670驱动原理:
电源(DOVDD,AVDD)为2.5V左右(HT7333输出串1N4148降压,因为我没有HT7325),
DVDD采用OV7670内部的LDO(1.8V),外部只需接一只电容.
单片机为STM32F103CBT6,采用HSI时钟,PLL倍频到64MHz,可省去外部晶振.
由于只需要处理灰度图像,OV7670配置为YUV格式,Y在前,
TIM4_CH1的捕获分频设置为2分频,就可以只采集Y(亮度).
TIM3_CH3产生XCLK,(16MHz对应VSYNC约20HZ,实测最低约8MHZ)
TIM4_CH1检测PCLK(4MHz),下降沿捕获,滤波为1,二分频,触发DMA,采集PA0~PA7的数据至数组DMA_Buf.
TIM3_CH4检测VSYNC,下降沿捕获中断,控制DMA的关与开.
HREF忽略.

引脚连接:
PA12:                        LED
PA0~7:                        OV7670_D0~D7
PB0(TIM3_CH3):        OV7670_XCLK
PB1(TIM3_CH4):        OV7670_VSYNC
PB2:                        OV7670_RST
PB7(TIM4_CH2):        OV7670_HREF(可省略)
PB6(TIM4_CH1):        OV7670_PCLK
PB10:                        OV7670_SIO_C
PB11:                        OV7670_SIO_D
PB12:                        OV7670_PWDN

建议:
        为加快速度,SIO_C与SIO_D可加外部上拉电阻

注意:
        看了下SCCB时序,貌似与IIC略有区别,指定地址读数据时:
        OV7670:        ...IICWByte(add);IICACK(0);IICEnd();IICStart();...
        普通IIC:...IICWByte(add);IICACK(0);         IICStart();...
---------------------------------------------------------------------------------------------
图像处理:
上次图像中部区域(按STEP间隔)存入数组MID_Buf,在当前采集的
图像中遍历,寻找差值最小的位置,从而得到座标增量。

程序中配置摄像头为YUV格式,窗口为160*80像素,得到80*80的Y(亮度)数据;
中心区为40*40像素,STEP设置为5,也就成了8*8的稀疏点阵,处理一幅图像大约耗时45ms.
(由于接收图像还需要时间,所以程序中约100ms处理一次)
程序经KEIL3编译后:Code=12054 RO-data=358 RW-data=48 ZI-data=8608;
可以看出代码量和内存消耗都不大。

图像处理核心算法:
(注意,由于二维数组访问速度较低,真实的代码略有优化,详见附件)
//--------------------------------------------------
//变量定义
//--------------------------------------------------
U8         DMA_Buf;//本次采集的摄像头数据
U8         MID_Buf;//上次中部区域的数据
//--------------------------------------------------
//计算差值的绝对值
//--------------------------------------------------
__INLINE U8caldif(U8 v1,U8 v2)
{
        if(v1>v2)return v1-v2;
        return v2-v1;
}
//--------------------------------------------------
//图像处理:用上次图像中部区域去与当前采集图像(从x,y
//开始的区域)求差,寻找差值最小的位置,
//从而得到x增量(MovIncX)与y增量(MovIncY)
//--------------------------------------------------
void PicProcess(void)
{
        U16 i,j,x,y;
        U32 dif,min=0xffffffff;        //差值,最小值
        U16 minx,miny;                        //最小值处的左上角座标
        //--------遍历整个当前图像,查找与之前中部图像相差最小的位置       
        for(y=0;y<CAMHEIGHT-MIDHEIGHT;y++)//从上到下
        {
                for(x=0;x<CAMWIDTH-MIDWIDTH;x++)//从左到右
                {               
                        dif=0;//误差清0                       
                        for(i=0;i<MIDHEIGHT;i+=STEP)
                        {
                                for(j=0;j<MIDWIDTH;j+=STEP)
                                {//计算当前图像中的点与上次图像中部区域的点的差值
                                        dif+=caldif(DMA_Buf,MID_Buf);//误差累加       
                                }
                        }
                        if(min>dif)//误差小于当前最小值,则记最小值为当前值,且记下座标
                        {
                                min=dif;
                                minx=x;
                                miny=y;
                        }
                }
        }
        //------------------------------计算座标增量
        if(min>30000)min=30000;//此句可省,是为了便于串口发送该值
        if(min<15*(MIDHEIGHT/STEP)*(MIDWIDTH/STEP))//允许平均每个点15的误差
        {
                MovIncX=minx-MIDX;//x增量
                MovIncY=miny-MIDY;//y增量
                MovX+=MovIncX;//模拟成鼠标的绝对座标,便于查看
                MovY+=MovIncY;       
                if(MovX<-1000)MovX=-1000;//限幅
                if(MovX>1000)MovX=1000;       
                if(MovY<-1000)MovY=-1000;
                if(MovY>1000)MovY=1000;
        }       
        //------------------------------复制当前中部区域
        for(i=0;i<MIDHEIGHT;i+=STEP)
        {
                //memcpy(MID_Buf,DMA_Buf+MIDX,MIDWIDTH);
                for(j=0;j<MIDWIDTH;j+=STEP)
                {
                        MID_Buf=DMA_Buf;                       
                }
        }
        //------------------------------串口查看误差与座标
        UART1_SendByte(0xaa);
        UART1_SendByte(6);       
        UART1_SendByte(min>>8);
        UART1_SendByte(min);                       
        UART1_SendByte(MovX>>8);
        UART1_SendByte(MovX);       
        UART1_SendByte(MovY>>8);
        UART1_SendByte(MovY);
}

下面是一些照片:
模块电路和照片:








将采集的图像发送出来用上位机查看:

将误差和座标发送出来用上位机查看:

8*8点阵去匹配当前图像的效果图,为避免GIF太大,只做了前5行的效果:

发送座标时的GIF图:


---------------------------------------------------------------------------------------------
补充一下:
测了下工作电流,约47mA
“处理一幅图像大约耗时10ms",这里写错了,应为45ms.
忘了传OV7670的资料了:

houyusheng 发表于 2015-10-10 12:09:21

做的不错,学习了

elecfun 发表于 2015-10-10 12:23:54

不明觉厉

2013的弹子球 发表于 2015-10-10 12:35:07

{:lol:}{:lol:}{:lol:}好棒

astankvai 发表于 2015-10-10 13:01:07

楼主V5,标记一下。

wind_zlc 发表于 2015-10-10 13:59:43

先收藏了,谢谢楼主

完美幸 发表于 2015-10-10 14:00:20

牛X啊。。。

ICPACHONG 发表于 2015-10-10 14:11:49

可以测移动方向,但没加测距的无法实现测量位移距离吧

lcw_swust 发表于 2015-10-10 14:38:10

ICPACHONG 发表于 2015-10-10 14:11
可以测移动方向,但没加测距的无法实现测量位移距离吧

是啊,所以一般要配合超声波模块。

ICPACHONG 发表于 2015-10-10 14:42:57

lcw_swust 发表于 2015-10-10 14:38
是啊,所以一般要配合超声波模块。

这个程序很有参考价值,感谢分享

lionsg 发表于 2015-10-10 15:03:53

STM32与OV7670的简陋型光流.可以配个超声波定高

default 发表于 2015-10-10 15:47:44

很不错,我们之前使用过鼠标芯片来做光流。有些鼠标芯片还提供了初始化固件,让里面的DSP能有光流的算法处理。

venus5712 发表于 2015-10-10 17:53:41

涨姿势了!!


老魏 发表于 2015-10-10 18:01:32

强帖,学习!

lcw_swust 发表于 2015-10-13 16:00:17

这两天找了下BUG:
MIDHEIGHT/STEP应改为(MIDHEIGHT+STEP-1)/STEP,宽度的同理
y<CAMHEIGHT-MIDHEIGHT应改为y<CAMHEIGHT-MIDHEIGHT+1,x同理
DMA可以一直工作不需停止.
OV7670的配置略有改动.
目前遗留的问题:
OV7670易丢帧(有VSYNC但无PCLK),特别是在光线剧烈变化的时候,估计是配置的问题

上位机改用C++builder编写,能支持更高的波特率,因为VB太过占用CPU。


天下乌鸦一般黑 发表于 2015-10-20 20:09:19

这个厉害。stm32 ov7670 跟随电路 mark

liaihua1997 发表于 2015-10-20 21:44:03

非常好,无敌了

atg525 发表于 2015-10-20 22:04:48

楼主太牛了

njhying 发表于 2015-10-20 22:51:48


楼主学习了 自制PCB很棒

Azuresky 发表于 2015-10-20 23:40:45

牛!强力顶起!支持开源

735953120@qq.co 发表于 2015-10-21 00:11:40

楼主霸气,前几天也是和楼主的想法相近,我的想法是stm32采集视频数据,然后将采集的数据发送给FPGA用于进行图像处理原本想做70帧最有改到30帧,还是苦于不知传输速率如何解决一直没开工,楼主有何见解可以给讲讲吗

hemeizhi 发表于 2015-10-21 08:28:03

用407或者427不是更方便

ZYBing 发表于 2015-10-21 08:49:38

不错,图片里的是楼主吗?

lcw_swust 发表于 2015-10-21 09:05:35

ZYBing 发表于 2015-10-21 08:49
不错,图片里的是楼主吗?

是啊,相素较低,看起来没那么帅

cxh321 发表于 2015-11-2 15:12:38

很不错!

chengying 发表于 2015-11-10 09:05:53

厉害!            

Dragontan 发表于 2015-11-10 09:12:59

楼主很厉害呀

ly8008csko 发表于 2015-11-10 09:34:10

做的不错,支持一个

videofun 发表于 2015-11-15 10:52:16

做的不错,学习了

vivi_cq1982 发表于 2015-11-17 17:08:49

正在找相关的资料,谢谢楼主

acchkr 发表于 2015-11-17 18:06:01

做的不错 多谢楼主分享~

2201 发表于 2015-12-25 11:33:22

串口呢?

lcw_swust 发表于 2015-12-25 12:05:46

2201 发表于 2015-12-25 11:33
串口呢?

若想达到高于115200的波特率,建议用USB转TTL模块。

wangjiawu187 发表于 2015-12-25 16:50:35

做的不错,学习学习!!

joelin97 发表于 2015-12-25 18:19:18

学习学习!

HYLG 发表于 2016-1-15 11:57:14

楼主板子做得非常漂亮。好玩的东西。

Hyzilla01 发表于 2016-1-18 02:04:49

好东西啊,学习学习

黄瓜 发表于 2016-1-19 16:13:10

本帖最后由 黄瓜 于 2016-1-19 16:14 编辑

楼主做得不错。
可以考虑移植下APM的光流算法。

qrytian 发表于 2016-1-21 09:10:39

好呀,研究的很透彻,说明的清晰,好资料,当时要是能看到,OV7670也不至于摆弄那么长时间了

笑对人生Zzz 发表于 2016-1-21 21:03:11

不错,楼主可以外接一个晶振,倍频到128M试一试呀,主频提高一倍,处理速度和响应速度就快了一倍,效果应该会更好些!

midjus 发表于 2016-1-22 16:14:17

学习中,有应用前景。

Yvan 发表于 2016-3-3 22:14:11

楼主牛人!!!!

snow1107 发表于 2016-5-14 13:11:15

我的天哪,都可以做成武器的自动瞄准了,厉害!!

redchina 发表于 2016-6-17 09:25:10

学习中,有应用前景。

Flyhome 发表于 2016-7-18 20:17:36

太牛了!!!

智涅 发表于 2016-7-25 20:35:15

牛人mark一个

yuqilala 发表于 2016-7-25 20:56:25

标记,以后有可能用到

warrenyan7251 发表于 2016-8-9 08:45:21

做的非常好,谢谢分享

shiyuzuxia1111 发表于 2016-8-30 09:58:48

从楼主发帖,回复,制板和焊接看出,楼主大牛,很严谨的一个人{:lol:}

newphj 发表于 2016-11-12 23:02:36

夹子很强大。。。

小管 发表于 2016-11-14 09:26:26

很强大,牛人一个

vsdcjs 发表于 2016-11-15 11:10:18

不错很好的东西

Jacky.Qiu 发表于 2016-11-15 13:23:31


不错很好的东西

vivi_cq1982 发表于 2016-11-15 18:01:46

顶楼主,很好的东西

qd118118 发表于 2016-11-15 20:01:36

牛!建议搞个套件出来,大家一起整整

tianyime 发表于 2016-11-15 20:25:27

厉害了楼主,谢谢分享。

dull20112011 发表于 2017-12-15 14:32:21

学习一下,也做一个

newphj 发表于 2018-5-6 20:45:20

大神,太厉害了。

lgy1025 发表于 2018-5-12 20:42:13

学习了。谢谢。

NanceMichael 发表于 2019-10-14 17:53:49

这个要给赞,真的太牛了。

liubo_zhao 发表于 2021-5-14 07:57:27

学习一下,LZ厉害{:victory:}
页: [1]
查看完整版本: 基于STM32与OV7670的简陋型光流模块