当前位置:   article > 正文

OpenMV与STM32单片机串口通信,如何使用openmv连续发送多帧数据给单片机_openmv有通信协议吗

openmv有通信协议吗

首先,我使用STM 32单片机有2 年左右的时间了,但是openmv却不足一个月的时间,由于近几天问我关于两者之间如何进行通讯问题的人比较多,所以特地写这样一篇文章进行讲解。如果有什么讲的不对的地方,还请各位读者指正。

在开始的时候,我们得必须明白一件事,我们要干什么。我们先来梳理一下任务。

openmv与单片机通讯,大多数时候都不是只发送一两个字符或数字,一般都需要进行大量数据传输,将识别到的图像,位置,颜色信息通过转换为数字的方式发送给单片机。既然是很多数字,那么如何才能使数字能准确的传输而不发生错误和“错位”呢?我想,将数据以帧格式进行发送,是一种非常不错的选择。简单的说一下帧格式备用:

百度的解释太过于复杂,一般 我们常用到的帧格式为:

帧头+帧头+数据类型+数据量+数据....+校验和+结束标志。就像这样:

5A 5A 01  08 FF DD 00 1B 40 12 00 00  54 C0     (随意编的,不一定对)。需要说明的是,一帧数据不一定需要这里面的所以东西,最简单的一帧可以只有帧头和数据构成,就变成了这样:5A 5A  FF DD 00 1B 40 12 00 00。数据总不能省略吧。帧头也是不能省略的,如果没有帧头,那怎么能在一大串连续的数据中分辨出数据的开始呢,而且经验告诉我,用两个Byte的帧头很有必要的。接下来我就以最简单的方式来讲解如何发送一帧数据给单片机,大家后期可以根据自己的需求在添加上需要的帧段。

openmv如何配置串口,并且利用串口助手发送单个字符串给电脑相信大家都已经实现,网上教程也很多,这里就不再讲解。

openmv的一个while(true)循环,一般产生一帧数据

就像这样:这是一个颜色识别并输出色块中心点坐标的程序

  1. # Untitled - By: 小柱 - 周三 4月 17 2019
  2. import sensor, image, time
  3. from pyb import UART
  4. import json
  5. threshold = [(37, 67, 45, 84, 4, 68), #red
  6. (34, 67, -55, -22, 2, 41), #green
  7. (25, 67, -37, 26, -63, -26)] #blue
  8. #设置红色的阈值,括号里面的数值分别是L A B 的最大值和最小值(minL, maxL, minA,
  9. # maxA, minB, maxB),LAB的值在图像左侧三个坐标图中选取。如果是灰度图,则只需
  10. #设置(min, max)两个数字即可。
  11. sensor.reset()
  12. sensor.set_pixformat(sensor.RGB565)
  13. sensor.set_framesize(sensor.QVGA)
  14. sensor.skip_frames(time = 2000 )
  15. sensor.set_auto_whitebal(False)
  16. #关闭白平衡。白平衡是默认开启的,在颜色识别中,需要关闭白平衡。
  17. clock = time.clock()
  18. uart = UART(3, 115200)
  19. uart.init(115200, bits=8, parity=None, stop=1) #8位数据位,无校验位,1位停止位、
  20. while(True):
  21. clock.tick()
  22. img = sensor.snapshot()
  23. blob = img.find_blobs(threshold, area_threshold=300)
  24. if blob: #如果找到了目标颜色
  25. # print(blob)
  26. # uart.write("B3 B3 ") #一帧数据的帧头
  27. FH = bytearray([0xb3,0xb3])
  28. uart.write(FH)
  29. for b in blob:
  30. #迭代找到的目标颜色区域
  31. img.draw_rectangle(b[0:4]) # rect
  32. img.draw_cross(b[5], b[6]) # cx, cy
  33. x = b.cx()
  34. y = b.cy()
  35. print(x, y, end = ',')
  36. data = bytearray([x,y])
  37. uart.write(data)
  38. #uart.write("%x %x \r"%(x,y)) #以16进制的格式输出,(16进制不能这样输出啊,浪费了我两天的时间)
  39. #img.draw_circle((50, 50, 30), color = (250, 0, 0))
  40. print(clock.fps())

我们主要看while(true)。其中,uart.write(FH)输出的是帧头,uart.write(data)输出的是色块坐标位置信息。

          简单分析一下,while(true)是一个大循环,通常情况下,一个大循环才能完成一轮识别,产生一帧数据(这当然取决于你的代码怎么写)。所以会在识别到摄像头识别到颜色(if blob)后首先发送出帧头 0xb3 ,0xb3。然后进入for循环(for b in blob)当for循环完的时候,一帧数据中完整的数据量就产生了。这样就在openmv当中产生了完整的一帧数据,利用串口助手可以观察到

这就是在串口助手中看到的数据内容

 

特别注意:!!!!

一帧数据的每一个Byte必须要以字节的显示发送(data = bytearray([x,y])),而不能是用16进制发送(uart.write("%x %x \r"%(x,y))),他们两个函数在串口助手里面看到的内容是一样的(大小写的区别),但是后者是无法让单片机接收到的。如果采用后者发送方式,就会出现openmv和单片机分别于PC通讯没问题,但是二者之间却无法通讯的问题,我也是在这里浪费了很多的时间,希望读者特别小心这个问题。

再一个,以上程序数据不一定是6个!!!,当只识别到一个或者两个色块时,就只产生两个或者四个数据!!!!

 

现在openmv能产生一帧有效数据了。STM32该如何接收到呢?由于stm32串口接收是以中断的方式。

  1. void USART2_IRQHandler(void)
  2. {
  3. static uint8_t rebuf[8]={0},i=0;
  4. if(USART_GetITStatus(USART2,USART_IT_RXNE) != RESET)
  5. {
  6. rebuf[i++]=USART_ReceiveData(USART2);
  7. if(rebuf[0]!=0xb3)//帧头
  8. i=0;
  9. if((i==2)&&(rebuf[1]!=0xb3))//判断帧头
  10. i=0;
  11. if(i>=7)//代表一帧数据完毕
  12. {
  13. memcpy(OpenMV_Rx_BUF,rebuf,i);
  14. i = 0;
  15. }
  16. USART_ClearFlag(USART2,USART_FLAG_RXNE);
  17. }
  18. }

其中OpenMV_Rx_BUF是一个外部变量用于保存从openmv接收到的数据,中断子程序中,每当进入中断,会首先判断帧头,如果不是 帧头,会直接丢弃,直到等到帧头的到来。

值得注意的是,中断子程序每进入一次,只会接收一个Byte的数据。也就是说接收完一帧数据需要进入8次中断才行。这一点的理解也比较重要,需要多多体会才行。

当数据保存在OpenMV_Rx_BUF[]后,就可以调用来使用了(注意数据不一定是完整的)使用时最好加以判断。

  1. void Color_Blob_Show(void)
  2. {
  3. OLED_ShowNum(0,6,OpenMV_Rx_BUF[0],3,12);
  4. OLED_ShowNum(20,6,OpenMV_Rx_BUF[1],3,12);
  5. OLED_ShowNum(40,6,OpenMV_Rx_BUF[2],3,12);
  6. OLED_ShowNum(60,6,OpenMV_Rx_BUF[3],3,12);
  7. }

显示图像

 

这样,一帧数据的发送和接受就完成了。

最后我要特别感谢CSDN,给了我一个学习的平台,在这里我学习到了很多知识,解决了我很多问题,感谢各位前辈的无私奉献。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/503193
推荐阅读
相关标签
  

闽ICP备14008679号