版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
⽤20块的摄像头(不带fifo的OV7670)做WiFi实时传图⼩车零、导读在这篇⽂章中,你将看到如下内容:1.OV7670QVGA配置的注意事项;2.将FPGA做成⼀个FIFO驱动不带FIFO的OV7670;3.libjpeg阉割库的使⽤;4.ESP8266传图给上位机的简单实现。5.ESP8266传图给OneNET,微信⼩程序的⽅案6.在开头的博客⾥有整个⼯程的GitHub链接(仅供参考)⼀、项⽬背景与吐槽该项⽬是⼤三下的嵌⼊式短学期,因为⼀些的原因做的不太⼀样,正常做的是⼀个STM32F103的WiFi上位机的项⽬,但为了玩地快乐我做了⼀个FPGA控制的⼩车,并且还兼备了WIFI传图,上位机/微信⼩程序显⽰与控制地功能。我在⽼师发布项⽬之后的三天内,使⽤STM32F1战舰开发板进⾏了测试(毕竟⼀下⼦玩的太⼤,怕失⼿),确定了初步⽅案,当时感觉是捡了⼀个⼤便宜,做了⼀个简单的任务,但当我看到FPGA的RTL图的时候,我⾃闭了。还有许多⼩模块没全部展现出来,特别是在sdramip中,害,⾃闭要往上⾯这个FPGA中动⼿脚是⽐较困难的。特别是在我对整个sdram存储的运⽤还不太熟练的情况下。吐槽:本来没打算做微信⼩程序的,结果在最后的实验验收要求上看到了安卓⼿机控制。阿这,这是我没想到的,只得硬着头⽪做完。。。⼆、项⽬设计⽅案回归正题,这次的任务的要求如下:基于FPGA⼩车、STM32最⼩系统、摄像头、⽆线模块等常⽤电⼦模块,实现⼀个远程可视的遥控⼩车。对此我的设计⽅案如下:系统框图
系统设计⽅案由系统框图所⽰,整个系统设计⽅案分成三个部分,分别是FPGA部分,STM32部分以及上位机/云端部分。1、FPGA部分使⽤⿊⾦的AX301来进⾏设计,FPGA在系统中的作⽤是获取图像、存储图像、传输图像以及控制⼩车。1.获取图像1.使⽤OV7670摄像头来进⾏图像获取,其中对摄像头的配置,采⽤QVGA、RGB565的格式输出,输出窗⼝设置为256*128的⼤⼩2.图像存储1.使⽤SRAM来进⾏图像的存储,同时采⽤乒乓操作,⼀边获取图像⼀边传输图像;3.图像的传输1.为了加快图像的传输速率,采⽤流⽔线,将RGB565的图像转换成灰度图,然后通过SPI作为从机进⾏图像的传输;4.⼩车控制1.根据获得的控制指令,输出1KHZ的PWM波驱动电桥控制电机从⽽控制⼩车,其中PWM的占空⽐可调,在进⾏转弯时为了增加驱动能⼒,适当提⾼PWM的占空⽐。2、STM32部分使⽤⾃制的STM32F407最⼩系统板,STM32在系统中的作⽤是与FPGA进⾏交互,对图像数据进⾏处理,与上位机/云端进⾏交互,是连接云端与底层的通道。1.与FPGA进⾏交互1.STM32使⽤硬件SPI作为主机,使⽤21M的速率与FPGA进⾏双向传输,即获取FPGA中存储的图像数据的同时,传达⼩车的⽅向控制指令。2.对图像数据进⾏处理1.根据计算,256*128的图像即使是作为灰度图仍然后32KB的⼤⼩,相对于ESP8266的115200的波特率来说图像还是太⼤,因此需要对图像进⾏jpeg压缩,在jpeg的压缩⽅⾯,借助了libjpeg的库。实测灰度图压缩为jpeg后图像⼤⼩压缩⾄1KB左右。⼤⼤加快了传输的速率。3.与上位机/云端进⾏交互1.STM32驱动ESP8266⼀⽅⾯可以与PC的上位机进⾏交互,传输图⽚到上位机上并获取来⾃上位机的⼩车控制指令,另⼀⽅⾯可以与OneNET进⾏交互,通过http协议post图像数据到OneNET上,并能通过get获取OneNET上的⼩车控制指令。3、上位机/云端部分
这⼀部分是最后的显⽰与控制终端,其中上位机部分采⽤C#进⾏编写,云端部分借助OneNET这个物联⽹开发平台存储数据,并通过微信⼩程序获得图像数据以及传达控制指令。三、项⽬具体实现与难点攻克1、有关FPGA的⽅案设计借助⿊⾦的OV7670_sdram的例程,进⾏修改。1、OV7670QVGA的配置这⾥我给出了三个输出窗⼝的配置,分别是128*64、320*240和256*128但需要注意的时,将OV7670配置成QVGA时,根据datasheet给出的波形图。我们可以看到他的输出速率是VGA模式的⼀半,表现在应⽤中,我发线他的PCLK输出变为原来的⼀半,即原来我是25M的PCLK,但我设置位QVGA时,他的输出变成了12.5M。这⾥必须安利⼀波singalTap,我本来没有注意这⼀点,然后他的输出数据⼀⽀不对,然后我就将OV7670的全部引脚全部放到singalTap上,然后就发现了他的PCLK变为原来的⼀半,这时候我才想到datasheet这个时序图的含义......他的这个时钟是会影响到后续的fifo等⼀系列操作。2、修改保存的图像的⼤⼩要改变图像⼤⼩,只需修改sdram_vga_top.v的最⼤地址⼤⼩NOTE:这⾥的地址⼤⼩最好是与wr_length和rd_length的整数倍,否则在显⽰图像的时候会出现图像会进⾏移动。注意:我在上⾯记录了OV7670的配置时给了320*240的图像⼤⼩,但我最后并没有使⽤,⼀⽅⾯是因为图像⼤了传输过慢,另⼀⽅⾯是因为建议图像的⼤⼩是他的wr_length以及rd_length的整数倍,否则显⽰图像的时候可能会出现图像的移动。3、FPGA与STM32的SPI通信为了实现⾼速率的传输,我设置了SPI通信为21M,需要注意的是⼀下⼏点:1.为了保证SPI和STM32的通信,⼀定要让STM32与FPGA共地2.SPI模块的时钟1.在FPGA这⾥经过测试发现SPI模块的时钟建议倍频到200M,⼀开始我设置了100M的时钟,发现SPI通信会发⽣错位,有时候还会紊乱,提⾼时钟的频率可以解决这个问题。3.SPI模块的CS1.⼀般SPI模块都会设计⼀个CS,然后⼜由于STM32的硬件SPI只有3个输出脚,我⾃⼰定义了⼀个CS,但实际的使⽤效果不佳,我查看SingalTap的时候发现,好⼏次SPI传输的时候这个CS脚会突然来⼀个⾼电平,导致我的数据出现问题,预计原因是STM32与FPGA之间的地还是不稳,因此我最后没有⽤32控制CS,⽽是引出来进⾏⼿动复位......4、将FPGA做成⼀个FIFO因为原来的程序中,摄像头的数据是存储在sdram中,使⽤了乒乓操作,⼀边读取⼀边存储,并且设计是考虑到VGA的时序,基本读取与存储是可以很好的同步的进⾏,但在我这个项⽬中,我对图像数据的处理明显时远远慢于OV7670图像数据的输出,因此我需要将FPGA做成⼀个保存数据的FIFO(吐槽⼀下:此处点题,20块的摄像头不带fifo就是这么真实,但凡他有⼀个fifo我可以简便不少.....)为了达到fifo的效果,我从sdban_switch⼊⼿修改了他的交换bank的条件case(state_write)3'd0:beginif(frame_write_done&&frame_read_done)//tobesuredatawiththesameimagehasbeenwrotestate_write<=3'd1;elsestate_write<=3'd0;end3'd1:beginwr_load<=1'b0;state_write<=3'd2;end3'd2:beginwr_load<=1'b1;state_write<=3'd3;end3'd3:beginwr_load<=1'b0;state_write<=3'd4;end3'd4:beginif(bank_switch_flag)state_write<=3'd5;elsestate_write<=3'd4;end3'd5:beginif(frame_write_done&&frame_read_done)//tobesuredatawiththesameimagehasbeenwrotebeginwr_bank<=~wr_bank;state_write<=3'd0;endelsebeginwr_bank<=wr_bank;state_write<=3'd4;endenddefault:;如上所⽰,在读取完并且写⼊完毕后才交换bank,以此来配合较慢的读取,但是相应的最终会导致显⽰的图像有延迟,延迟取决于传输时间、压缩时间等⼀系列因素。不过,其中的神来之笔是我将读取的时钟更换了,不再由pll锁相环提供,⽽是由SPI模块的读取完毕的信号来作为时钟,通过rtl图可以清楚的看到这⼀点这条时钟⼀⽅⾯是作为sdram读取fifo的时钟,另⼀⽅⾯是作为RGB565转换灰度图的时钟,因为这个转换是完全流⽔线结构,所以他的只需要经过3个时钟周期的时滞就可以8位流量的输出灰度值。5、⼩车的驱动⼩车的驱动主要是依靠PWM来进⾏驱动,但需要注意的是,转弯时的摩擦⼒⽐较⼤,需要更强的驱动能⼒,因此在收到转弯指令的时候可以适当提⾼PWM的占空⽐,提⾼驱动能⼒。2、有关STM32的设计1、libjpeg库的使⽤但他是RGB的压缩,我为了更进⼀步的压缩,把他修改成了灰度图的jpeg压缩,具体可以看我的代码,或者直接使⽤。这位⼤佬移植了libjpeg,不过貌似是⼀个⽐较旧的版本......压缩质量使⽤的还是浮点数,不过不影响使⽤。值得⼀提的是,如果去查看STM32Cube_FW_F4可以在其的Projects->STM32F429-Discovery->Application下可以看到LibJPEG,这个是官⽅的移植,不过他把整个LibJPEG给移植过来了,整个⼯程太⼤了,所以还是选择使⽤这个阉割版。。。。。。2、STM32与上位机通信在这⾥我设置了ESP8266作Client,上位机作为Server,ESP8266通过配置连接WIFI,然后访问我电脑的IP,就可以与上位机建⽴socket进⾏图⽚的传输。STM32与上位机机通信最好是要有⾃定的协议,要有帧头,校验位等,但这个数据量实在有点⼤,我就只设置了⼀个传输数据包⼤⼩的帧头,然后就粗暴的上传了,不过效果还蛮好的说效果如下:全损画质3、STM32与OneNET进⾏交互STM32对OneNET进⾏交互,OneNET官⽅给了许多的协议,例如MQTT,EDP和HTTP等,不过对于我来说,最快的还是直接使⽤API,⽤get获取数据点,⽤post上传图⽚。对于图像传输,这是我上传的数据POST/bindata?device_id=607169499&datastream_id=imageHTTP/1.1api-key:yourapi-keyHost:Content-Length:3493后⾯加上图像数据,图像数据可以是⽤上⾯链接给的⼀个⼩软件。在传输的时候需要注意的是,在传输末尾要加上两个换⾏符,这个很关键,没有这两个换⾏符数据上传就会有很多的问题。另外OneNET的Api-key建议直接使⽤Master-api-key在STM32的代码上,如下所⽰u8*p;intt=0;p=mymalloc(SRAMIN,32);//申请32字节内存sprintf((char*)p,"Content-Length:%d\r\n\r\n",pt_buf);u3_printf("POST/bindata?device_id=607169499&datastream_id=image&desc=testfileHTTP/1.1\r\n");u3_printf("api-key:yourapikey\r\n");u3_printf("Host:\r\n");u3_printf(p);for(t=0;t<pt_buf;t++){UART3_Send_Data(JPG_enc_buf[t]);}myfree(SRAMIN,p);同理,获取OneNET的数据点USART3_RX_STA=0;u3_printf("GET/devices/607169499/datastreams/directionHTTP/1.1\r\n");u3_printf("api-key:yourapikey\r\n");u3_printf("Host:\r\n\r\n");delay_ms(100);USART3_RX_STA=0;char*c1=strstr(USART3_RX_BUF,"current_value");return*(c1+16);这⾥对于收到的数据可以使⽤cJSON进⾏解析,但需要注意的是,收到的数据还有⼀个HTTP的头,需要将他除去,如下所⽰HTTP/1.1200OKDate:Wed,01Jul202015:23:14GMTContent-Type:application/jsonContent-Length:133Connection:keep-aliveServer:Apache-Coyote/1.1Pragma:no-cache因此为了⽅便使⽤,我直接使⽤了strstr函数,通过查找current_value来获取数据点的数据。4、上位机的编写上位机的编写我是⽤的是C#来进⾏编写,下列展⽰⼀下主要的代码voidTSReceive(){aimSocket=mySocket.Accept();//服务端监听到的Socket为服务端发送数据的⽬标socketinfoLabel.Text="连接成功";byte[]buffer=newbyte[4];while(true){try{aimSocket.Receive(buffer,buffer.Length,SocketFlags.None);intcontentLen=BitConverter.ToInt32(buffer,0);intsize=0;MemoryStreamms=newMemoryStream();while(size<contentLen){//分多次接收,每次接收256个字节,byte[]bits=newbyte[256];intr=aimSocket.Receive(bits,bits.Length,SocketFlags.None);//接收到监听的Socket的数据if(r==0){MessageBox.Show("连接断开");break;}ms.Write(bits,0,r);size+=r;}Imageimg=Image.FromStream(ms);picBox.Image=null;picBox.Image=img;}catch{}}}上述代码是TCPServer的线程,在该线程中,通过监听socket,获取数据然后将他显⽰到Image控件上。整体上位机布局在控制指令⽅⾯,我设置了⼀个帧头,byte[]CtrBuf=newbyte[2]{0xA3,0x20};虽然实际上并没有起到什么作⽤.......5、微信⼩程序的编写微信⼩程序⽅⾯,下图展⽰的获取图像数据并展⽰的代码。图像的转换是主要靠OneNET获取⽂件的api,获取图像的⼆进制流⽂件,然后将其转换成base64的类型,就可以显⽰图像了,这⾥主要要注意两点:1.在request的函数中加⼀个responseType:'arraybuffer',这样接收到的数据就是arraybuffer的形式,就可通过arrayBufferToBase64转换成base64的形式,然后加上data:image/jpg;base64,就可以直接显⽰图像了。2.使⽤OneNET获取⽂件的api的时候要使⽤master-api-key,否则可能会报错,我当时报的错是errno:3authfailed,为此我还问了OneNET客服呢。。。。。四、成果展⽰1、上位机接受图像2、⼿机端微信⼩程序界⾯做的简陋了⼀点。。。。。五、缺陷与提⾼部分本次实验最⼤的缺陷是延迟过⾼,⼀⽅⾯是因为受限于Jpeg压缩的效率太低,另⼀⽅⾯则是因
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年吉化总医院二院医护人员招聘考试备考试题及答案详解
- 2026年遵义市第一人民医院医护人员招聘考试参考题库及答案详解
- 2026年浙江省肿瘤医院浙江中医药大学附属肿瘤医院医护人员招聘笔试备考题库及答案详解
- 2026年温州医学院附属眼视光医院浙江省眼视光医院医护人员招聘考试参考题库及答案详解
- 2026年青岛市海慈医疗集团医护人员招聘笔试备考题库及答案详解
- 2026年通辽市传染病医院医护人员招聘笔试备考题库及答案详解
- 2026年嘉兴市妇幼保健院医护人员招聘考试备考试题及答案详解
- 2026年中国人民解放军第105医院医护人员招聘考试参考试题及答案详解
- 2026年解放军第九六零医院医护人员招聘考试参考试题及答案详解
- 2025年珠海市妇幼保健院(柠溪院区)医护人员招聘考试试题附答案详解
- 2025江苏苏州市城投集团第一批次招聘16人笔试历年参考题库附带答案详解
- 2026年绍兴市社区工作者(专职网格员)招聘考试试卷1含答案解析
- 2026年纪检监察考试题库(附参考答案)
- 第22课 《太空一日》课件(内嵌视频 ) 2025-2026学年统编版语文七年级下册
- GB/T 21186-2026傅立叶变换红外光谱仪
- 2025年事业单位预防医学岗《公卫知识》真题及答案解析
- 2025年度中国展览数据统计报告
- (完整版)企业商业秘密管理体系及保密措施
- 福建省特安安全技术服务中心有限公司招聘笔试题库2026
- 2026年高考(湖南卷)英语试题及答案
- 【期末】《国家安全概论》(西安交通大学)期末考试慕课答案
评论
0/150
提交评论