当前位置:   article > 正文

OpenMv与STM32通信(数字识别)(最大色块)(OLED显示)_openmv与stm32连接

openmv与stm32连接

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、OpenMV如何与STM32进行通信
  • 二、具体实现
    • 数字识别
    • 将识别到的数字信息显示在与stm32通讯的oled上
  • 总结


前言

       笔者为参加 2024 年电赛控制类题目,意识到 OpenMV 图像识别极为关键,尤其是对于送药小车数字识别功能的实现。于是对 OpenMV 展开学习并上网找资料,特别关注 OpenMV 与 stm32 如何进行数据传输,看到资料后产生传输多种不同数据的想法,如单个字符和各种特定信息而非固定的几个值,经过努力尝试最终实现,期望把这段学习理解过程记录下来以助他人。

 最大色块的识别,可以去参考这个链接,具体实现了传输色块坐标并且将坐标信息打印在上位机。https://blog.csdn.net/m0_51661679/article/details/118936152

以及超详细OpenMV与STM32单片机通信 (有完整版源码)-CSDN博客

笔者想进一步实现送药小车的数字识别,经过更改程序,写出了传输不同数字信息的代码。并且对于stm32与openmv通信有了更深的理解。让识别到的信息实时显示到oled上,同时实现脱机运行,效果得到验证。

1.OpenMV如何与STM32进行通信?

        OpenMV和STM32之间可以通过多种方式进行通信,其中一种常见的方法是使用串口通信。

将openmv的RX与stm32的TX相连,TX与RX相连。即可实现串口通讯,同时配置要设定一致。

例如:

openmv端

  1. uart = UART(3, 115200)
  2. uart.init(115200, bits=8, parity=None, stop=1)

stm32端主要通过CubeMx配置串口,切记打开中断。如何打开的可以参考我放的链接的博客。

通过openmv打包数据包的格式发送到stm32,stm32收到后进行解析。

定义全局变量

  1. /* USER CODE BEGIN PV */
  2. uint8_t usart1_Rxbuff;
  3. /* USER CODE END PV */

主函数里面加上串口接受中断开启。

HAL_UART_Receive_IT(&huart1,(void *)&usart1_RXbuff,1);

然后进行回调函数的接收

  1. /* USER CODE BEGIN 4 */
  2. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
  3. {
  4. uint16_t temp;
  5. if(huart->Instance==UART1)
  6. {
  7. temp=uart1_rxbuff;
  8. Openmv_Receive_Data(temp);
  9. }
  10. HAL_UART_Receive_IT(&huart1,(void *)&uart1_Rxbuff,1);
  11. }
  12. /* USER CODE END 4 */

 在这段代码中,假设USART1_RXbuff是一个全局变量,用来存储接收到的数据。当接收到数据时,将其存储在temp变量中,然后调用Openmv_Receive_Data()函数进行处理。最后,通过调用HAL_UART_Receive_IT()再次启动串口接收中断,以便接收下一组数据。

2.具体实现

2.1 OpenMv端代码

2.1.1 (最大色块)

  1. from pyb import UART, LED
  2. import json, ustruct, sensor, time
  3. import lcd
  4. red_threshold = (1, 2, -73, 41, -72, 54)
  5. sensor.reset()
  6. sensor.set_pixformat(sensor.RGB565)
  7. sensor.set_framesize(sensor.QQVGA2)
  8. sensor.skip_frames(10)
  9. sensor.set_auto_whitebal(False)
  10. sensor.set_hmirror(True)
  11. sensor.set_vflip(True)
  12. clock = time.clock()
  13. uart = UART(3, 115200)
  14. uart.init(115200, bits=8, parity=None, stop=1)
  15. lcd.init()
  16. def find_max(blobs):
  17. max_size = 0
  18. for blob in blobs:
  19. if blob[2] * blob[3] > max_size:
  20. max_blob = blob
  21. max_size = blob[2] * blob[3]
  22. return max_blob
  23. def sending_data(cx, cy, cw, ch):
  24. global uart;
  25. data = ustruct.pack("<bbhhhhb",
  26. 0x2C,
  27. 0x12,
  28. int(cx),
  29. int(cy),
  30. int(cw),
  31. int(ch),
  32. 0x5B)
  33. uart.write(data);
  34. while(True):
  35. clock.tick()
  36. img = sensor.snapshot()
  37. blobs = img.find_blobs([red_threshold])
  38. if blobs:
  39. max_blob = find_max(blobs)
  40. img.draw_rectangle(max_blob.rect())
  41. img.draw_cross(max_blob.cx(), max_blob.cy())
  42. cx = max_blob[5]
  43. cy = max_blob[6]
  44. cw = max_blob[2]
  45. ch = max_blob[3]
  46. OUT_DATA = bytearray([0x2C, 0x12, cx, cy, cw, ch, 0x5B])
  47. uart.write(OUT_DATA)
  48. print(OUT_DATA)
  49. lcd.display(img)

 2.1.2数字识别

  1. import time, sensor, image
  2. from image import SEARCH_EX, SEARCH_DS
  3. from machine import UART
  4. import lcd
  5. sensor.reset()
  6. sensor.set_contrast(1)
  7. sensor.set_gainceiling(16)
  8. sensor.set_framesize(sensor.QQVGA2)
  9. sensor.set_pixformat(sensor.GRAYSCALE)
  10. sensor.set_hmirror(True)
  11. sensor.set_vflip(True)
  12. uart = UART(3, 115200)
  13. uart.init(115200, bits=8, parity=None, stop=1)
  14. templates = ["/1.1.pgm", "/1.pgm", "/2.pgm"]
  15. lcd.init() # 初始化 lcd 屏幕。
  16. clock = time.clock()
  17. while (True):
  18. clock.tick()
  19. img = sensor.snapshot()
  20. for t in templates:
  21. template = image.Image(t)
  22. r = img.find_template(template, 0.70, step=4, search=SEARCH_EX)
  23. if r:
  24. x, y, w, h = r
  25. if t == "/1.1.pgm" or t == "/1.pgm":
  26. cx=1
  27. cy=0
  28. cw=0
  29. ch=0
  30. img.draw_string(x, y, "1", color=(255, 255, 255))
  31. elif t == "/2.pgm":
  32. cx=2
  33. cy=0
  34. cw=0
  35. ch=0
  36. img.draw_string(x, y, "2", color=(255, 255, 255))
  37. img.draw_rectangle(r)
  38. OUT_DATA =bytearray([0x2C,0x12,cx,cy,cw,ch,0x5B])
  39. uart.write(OUT_DATA)
  40. print(cx,cy,cw,ch)
  41. lcd.display(img) # 拍照并在 lcd 上显示图像。

 在这里我的代码数据包与上面的雷同,其实主要是为了方便大家理解,我们主要识别图片1.1.pgm和1.pgm都是数字1,所以我们发送1 0 0 0,让32只接收第一个数据就好了或者说是只打印出来,2的原理一样。其他的数字我们可以同理扩展。

2.2.stm32端代码

2.2.1 openmv.c(openmv接收信息处理函数)

主要步骤为OpenMv发送数据包,stm32接受数据包并且处理打印到电脑上或者显示在oled上。(笔者用的是显示在OLED上)

openmv处理

  1. #include "openmv.h"
  2. #include <stdio.h>
  3. #include "usart.h"
  4. #include "oled.h"
  5. static uint8_t Cx=0;
  6. //static uint8_t Cy=0,Cw=0,Ch=0;
  7. uint8_t display_buf[20];
  8. void Openmv_Receive_Data(int16_t Com_Data)
  9. {
  10. uint8_t i;
  11. static uint8_t RxCounter1=0;//
  12. static uint16_t RxBuffer1[10]={0};
  13. static uint8_t RxState = 0;
  14. static uint8_t RxFlag1 = 0;
  15. if(RxState==0&&Com_Data==0x2C) //0x2c
  16. {
  17. RxState=1;
  18. RxBuffer1[RxCounter1++]=Com_Data;
  19. HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);
  20. }
  21. else if(RxState==1&&Com_Data==0x12) //0x12
  22. {
  23. RxState=2;
  24. RxBuffer1[RxCounter1++]=Com_Data;
  25. }
  26. else if(RxState==2)
  27. {
  28. RxBuffer1[RxCounter1++]=Com_Data;
  29. if(RxCounter1>=10||Com_Data == 0x5B)
  30. {
  31. RxState=3;
  32. Cx=RxBuffer1[RxCounter1-5];
  33. // Cy=RxBuffer1[RxCounter1-4];
  34. // Cw=RxBuffer1[RxCounter1-3];
  35. // Ch=RxBuffer1[RxCounter1-2];
  36. }
  37. }
  38. else if(RxState==3)//
  39. {
  40. if(RxBuffer1[RxCounter1-1] == 0x5B)
  41. {
  42. if(RxFlag1==0)
  43. {
  44. OLED_Clear();
  45. }
  46. RxFlag1++;
  47. RxCounter1 = 0;
  48. RxState = 0;
  49. OLED_ShowString(0,0,"Success",16);
  50. OLED_ShowNum(0,2,Cx,1,16);
  51. }
  52. else
  53. {
  54. RxState = 0;
  55. RxCounter1=0;
  56. for(i=0;i<10;i++)
  57. {
  58. RxBuffer1[i]=0x00; //
  59. }
  60. }
  61. }
  62. else
  63. {
  64. RxState = 0;
  65. RxCounter1=0;
  66. for(i=0;i<10;i++)
  67. {
  68. RxBuffer1[i]=0x00; //
  69. }
  70. }
  71. }

主要初始化代码

切记要先开中断,将数据读入缓冲区。

  1. /* USER CODE BEGIN 2 */
  2. OLED_Init();
  3. OLED_Clear();
  4. OLED_ShowString(0,0,"Waiting...",16);
  5. HAL_UART_Receive_IT(&huart1,(void *)&USART1_RXbuff,1);
  6. HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,GPIO_PIN_SET);
  7. /* USER CODE END 2 */

led灯其实还是为了方便调试。 

总结

其实看了上面的以及那些详细的博客之后大家基本都会对stm32与openmv的通信有所了解了,对于刚开始接触openmv与stm32通信的我们来说这感到很神奇,我们会好奇两个MCU之间是如何传输信息的呢?经过更多的了解之后相信大家会对串口通信有更深的了解以及理解。笔者在网上看到各种openmv向stm32发送最大色块坐标信息的博客,因此想扩展一下2023年送药小车的识别,为此进行扩展了数字识别传输信息。但是这还是很基础,后面的内容以及更优秀的数据传输方式仍然等待笔者去学习。希望可以对正在学习以及备赛电赛的人有所帮助。

同时笔者的openmv端代码加上了lcd显示功能,可以实现脱机运行的同时更好的实时得到摄像头的反馈信息。并且我们可以低成本制作lcd扩展屏。具体可以参考这篇博客。https://blog.csdn.net/nnxiaowoniu/article/details/133972872

这是笔者进行改造的,回头设计个pcb就不用飞这么多线了哈哈哈哈哈哈。

祝愿大家可以在电赛取得好成绩,我们的学习将会继续!

相关代码已经开源到gitee。

OpenMv数字识别: OpenMv实现数字识别,且将信息通过串口发送到STM32,实时显示到oled上。

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

闽ICP备14008679号