esp32+ov7670wifi发射失败率过高debug记录

来源:互联网 发布:网络爬虫技术介绍 编辑:程序博客网 时间:2024/05/17 03:48


       采用esp32+0v7670做拍摄完图片之后,通过wifi实时传送至接收端的项目。我的做法是,camera采集一帧的图像后,放RAM中。然后将一帧的数据分成80个udp包连续通过for循环发送出去调用sendto发送出去。发送一帧的图片的部分代码如下:

for(int i=0;i<80;i++){
ret=sendto(sock,s_fb+i*720,1440,0,(struct sockaddr*)&toAddr,sizeof(toAddr));if(ret<0){perror("fail reason is :");}}
       所有代码写完之后,运行,发现发送失败率过高,失败原因是not enough memeory。于是开始排查。为缩小问题范围,写了一个不加camera只做wifi单独发送的程序。发现发送失败率很低。调查后发现,原来与数据存放的位置有关,wifi单独发送的程序中,数据被自动分配到的虚拟地址其物理地址对应flash,而加了camera的程序,数据所在的虚拟地址对应的物理地址是RAM中。调用sendto接口,数据会从上层向底层一层一层的送,直至送到wifi core。而lwip协议为其提供一个buffer来存放数据,当buffer中的数据通过wifi发送出去后,buffer就会被清空。如果上层一直不停的调用sendto,数据就会在buffer还没被清空就填入buffer,所以会提示not enough memory。(乐鑫不提供底层源码,很多都是靠自己猜)
      而当数据位于falsh时,失败率低,是因为cpu从flash获取数据比较慢,所以经常有充足的时间将buffer中的数据处理完。数据位于RAM中时,失败率高,就是因为cpu从RAM中读取数据太快,所以这段时间不足以将当前buffer中的数据处理完。
      于是在程序中加了,每发一包延时1ms,即等待buffer中的数据处理完成后再向buffer中填入数据。
        for(int i=0;i<80;i++){ret=sendto(sock,s_fb+i*720,1440,0,(struct sockaddr*)&toAddr,sizeof(toAddr));if(ret<0){perror("fail reason is :");}vTaskDelay(1/portTICK_RATE_MS);}

       发现失败率还是很高,于是加大延时时间,加大到10ms时,失败率才降下来。但是不应该这么久,因为测试过sendto消耗的时间。继续调查发现,是freertos的tickrate设的是100hz。也就是说freertos的tick一秒钟只震荡100次,所以精度只有10ms。于是设置将tick_rate设置为1000hz。发现失败率还是很高。于是深入freertos底层,看lwip协议。做过很多尝试都没解决。于是放弃在软件上debug。开始找硬件原因,供电是稳定的。之后又做了大量对照。将esp32的通过gpio输出的时钟,改为外部晶振输出时钟,最终解决了wifi发送失败率过高的稳定。我的解释是:esp32通过gpio输出时钟,加上camera,影响了供电稳定性,进而干扰到了射频发送。         这次debug的经历告诉我,bug可能是由多种原因产生的。做对照试验,控制变量一定要严谨。越是困难的问题,debug中就能学到越多。 遇到困难更应该兴奋。

原创粉丝点击