W80X(W800/W801)使用OV7670和OV2640摄像头 扫码 识物 监控
时间:2023年05月01日 人气:...

N年前的一天,在淘宝上偶然看到一款ov7670的摄像头模块,九块包邮,瞬间就买了一块,反正便宜,管他用不用、能不能用。结果这一吃灰就是好几年,但我一直觉得mcu玩摄像头挺好玩的,总想着找机会试一下,这次就准备在w801上试试。

先来个试验完成的视频,供阅读本文的人决定要不要再看下面的内容。

之所以选择w801,是因为stm32和esp32使用ov7670的教程已经烂大街了,而w80x系列却没见到有人做摄像头的,所以选择一个没有研究资料的可以在研究过程中学到更多东西。

在找资料的过程中,我发现原来ov7670有两款类型的模块,一种就是便宜的几块钱的,另一种是比较贵的。贵的这种是多了一个fifo,目的就是为了降低mcu采集图像难度,这样看来有fifo版本才是初学摄像头玩家的良配,于是我就又购买了一块有fifo的ov7670模块。等拿到手一看,发现这两块都是骑飞电子出的,网上好像还有正点原子版本的、普中的等等,这些的引脚都不大相同,调试时还是得区分清楚。

然后得再购买两块w801,淘宝上同样还是九块钱包邮,但是为了省事,这次我选择了焊接好插针的版本,多花了十块钱。等拿到手一看,这次倒是比上一篇买的w806做工好了很多,电源和gnd引脚也挺多,这才是适合人用的mcu嘛。但是,我还是泪流满面:

    1. 明明多花了十块钱说好的焊接好插针,咋还有两边各3共6根插针没焊,可能我没理解全焊这个词的含义吧

    2. 串口不支持SecureCRT工具直接打开使用,我推测可能把串口和复位电路连起来导致的,咱也不是很明白为啥同类的esp32可以完美打开使用,所以还需要特殊的一番配置才能用起来这工具(手动修改配置文件将"DTR Flow Control"和"RTS Flow Control"改为全0即可);

为了方便观看效果,又选择了俩屏幕,一块st7789,另一块ili9341,虽然都是320*240分辨率的,但是这俩屏的性能却不一样,我又踩坑了:ili9341至少可以支持60MHZ时钟,但是st7789却最高只能到50MHZ。

现在摄像头、w801、屏幕已经齐活了,就可以开工了。


一. ov7670摄像头的基础知识

ov7670这款摄像头,引脚看着挺多,其实,一共可以分为这么几组/类:

    1. sioc和siod(或叫scl和sda),这个用的sccb协议,和i2c很相似,具体差异可以看网上分析,咱这里不详细解释,只是说明,它俩就是用来对摄像头进行各项参数配置的,如查询版本号、配置白平衡等等。它既可以在用拍照前配好,也可以在中途再去修改某些配置,所以它就是用来做配置控制功能的。

    2. d0-d7,这是8根数据线,拍照的数据就是用这8根线传递的。

    3. rst和pwdn用来控制复位和电源的,上电初始化时rst应该先拉低保持一段时间然后拉高。正常工作时,pwdn应该拉低,rst拉高。

    4. 其它的引脚就是信号和时钟类型的,如无fifi版本xclk就是ov7670摄像头的时钟,如果没有它,这摄像头基本上就是不工作的了。vsync就是用来通知mcu,我这一帧准备好了你可以取照片数据了;href和vsync类似,vsycn是一帧,而href只是指示这一行的数据好了。fifo版本少了些引脚,多了些fifo的控制脚。

ov7670的配置参数超级多,很多还是需要懂图像知识的,但是一般直接用店家提供的例程中的参数就没啥太大问题。

调试时,我建议的步骤为先读id,判断sccb流程是否可以正常工作;

sccb可以直接使用io模拟法方式实现最为简单,也就是说初始化之后读取0xa寄存器,判断值是不是0x76就可以知道是否正常工作。如果不正常,调试方法也非常简单,用逻辑分析仪直接抓,用i2c协议解析数据,很容易就能判断问题出在哪。

当sccb工作正常后,就可以抓图了,但是也不要直接就来抓拍实际照片,因为这样不好判断问题,可以配成生成八色图(也就是摄像头固定输出8条彩色图),通过观察这个画面判断是否抓图流程存在异常。

实际效果就是可以稳定的出现这样的画面:

简单说就是把0x71寄存器改成0xB5,当能出现八色图后改成0x35即可回复正常模式。

在我调试中发现,这俩寄存器的配置对调试影响是最大的,一般画面不稳定基本上就是这俩配的不对:

通常这个需要按照自己mcu情况来改着试了,不好说有啥固定值,如fifo版本我就用的默认值0x80和0x0a。

二. 有fifo版ov7670

这个真是超级简单,因为淘宝买的摄像头,店家提供例程的,还是好几种例程。我就照着stm32的io例程,翻译成w801的代码,唯独屏显方式不一样,我是rgb565,所以修改了下配置参数,一把就跑出了稳定的八色图。

然后就是改成正常模式,来看拍照效果。第一次用这个,发现镜头竟然需要手动调焦距,使劲拧就行,一直拧出来大半截画面就清晰了,效果可以看视频里的演示(视频先是用有fifo版本,接着是无fifo版本,然后接下来就是应用测试)。

整理了一份调试通的源码,供感兴趣的朋友参考   --->   w800_ov7670_with_fifo.7z (只支持cdk编译)

三. 无fifo版ov7670

这个难就难在xclk的模拟上,如果没有xclk时钟,这摄像头基本上就是不工作的,既不能配置也不能抓图,读id也是不行的。如果模拟不出高频时钟,那执行配置的速度就能慢如蜗牛,光一个初始化就能你放弃使用。虽然店家也是提供了stm32的例程,除了xclk其它的翻译成w801的代码也是非常容易,但就这个xclk还真是让人费脑筋。

通过琢磨stm32使用的思路,我对xclk的模拟考虑可以使用如下几种:

    1. 用定时器周期来翻转io模拟时钟,w801的硬件时钟精度是1us;

    2. 用pwm来输出时钟,w801的pwm在极限配置下可以输出20MHZ;

    3. 用psram的时钟来干这事,psram时钟最高80MHZ还可以往低配;

    4. 用sdio host时钟来干这是,sdio host时钟也是可配的,最高可达120MHZ;

因为ov7670最高可输出30fps,能达到的时钟24MHZ,但是w801可不好产生这个频率的时钟,而用硬件定时器时钟还是比较慢的所以就选择用w801能容易输出的20MHZ时钟来用,于是就选择简单易用的pwm玩一把了。

需注意,这个xclk时钟并不是一直以这一种方式工作。它在读d0-d7数据时还是要用io模拟方式,拉低拉高一次才能读一次数据。读完数据之后,就需要以高速方式模拟,等待vsync信号产生后,再次进入读图环节用io来模拟,如此反复。

最后也是成功读到八色图,然后实际抓图观察,因为我使用了有fifo版本的参数对其进行配置的,而这俩摄像头的版本并不是完全一致的,所以并没有把照片的颜色调好匹配,但也能正常运行观看效果了,懒得再调那堆天书一样的寄存器和参数了。无fifo版本运行效果如视频所示。

我发现无fifo版本的抗干扰性要比有fifo版本差,有fifo版本的用杜邦线连接的,拍照刷屏非常清晰毫无干扰。但是无fifo的就不是这样了,画面动一下线就对画面影响比较大,所以使用时推荐要按类别把杜邦线捆一起,如数据线捆一起、信号线捆一起、控制线捆一起。

整理了一份调试通的源码,供感兴趣的朋友参考   --->   w800_ov7670_without_fifo.7z (只支持cdk编译)

四. 这能干啥

这个问题,其实我是想在摄像头调通之后研究一下人脸识别、识物类应用的,再不齐也可以用个扫码吧,但是还没了解目前开源的识别框架有啥可以适合嵌入式的,等后面研究了再来补充吧。

倒是在github上发现了一个stm32做的车牌识别系统,于是我就移植到w801上简单测试了一下,果然对燃油车车牌识别还是挺灵敏的,可玩性不错,效果可以看视频的演示。

整理了一份调试通的源码,供感兴趣的朋友参考   --->   w800_ov7670_with_fifo_license_plate_recognition.7z (只支持cdk编译)

五. OV2640

在淘宝上看到一块仿正点原子的ov2640模组,看着使用简单,价格也便宜,于是又进行了一番探索。

这个使用也是非常简单,把原子哥的源码翻译成w801的即可,仅仅是io部分的修改和一个delay_ms适配。

ov2640支持jpg输出,图片最大可达1600X1200分辨率,这里显然只能输出到pc观看,所以原子哥也是提供了个uart的接收工具用来显示jpg图片,可以理论计算uart使用2M波特率传送,这速率也是不够看的,帧率应该还是没法流畅看,仅仅是给上位机一个抓图的意思了。

所以,我还是将图片输出到lcd上显示娱乐了一把,效果也还凑合,可以观看视频效果:

ov2640是可以做神经网络识别的,如esp-cam方案,这里咱目前还不了开源识别框架有啥可以在这种mcu上用的,待后续研究了再来拓展和深入优化用法,有了解的朋友也不妨留言指点一下。

热门评论