OPENMV和STM32的识别追踪小车(详细版)之OPENMV端

2 篇文章 5 订阅
2 篇文章 7 订阅

OPENMV和STM32的识别追踪小车(详细版)之OPENMV端

实现:通过OPENMV识别Apriltags标签,STM32驱动小车追踪标签

博主通过一段时间的学习,做了这个比较简单的以OPENMV为摄像传感器STM32为控制器的寻物小车,不多说,直接进入正题!

材料准备

小车底盘&&轮子
直流减速电机
杜邦线若干
7.2V电源
L298N模块
STM32F407最小系统
OPENMV4 H7

程序设计思路

这里分两个方面来说,一个是OPENMV的程序,另一个是STM32的程序。其中,最重要的地方是openmv与stm32的通信问题,我也会着重讲一下这个问题。由于篇幅比较长,我将分两篇文章讲解。

一:首先说一下OPENMV的介绍和程序

1.1(OPENMV介绍)

OpenMV摄像头是一款小巧,低功耗,低成本的电路板,它帮助你很轻松的完成机器视觉(machine vision)应用。它可以让我们直接应用具有人工智能的功能的摄像头作为我们机器人的视觉传感器。它可以识别出人脸,方块,小球,标签等。
这里,我选择用来识别Apriltags标签,OPENMV识别Apriltags标签可以计算出相对于相机的精确3D位置,方向和id。包括有6个自由度,三个位置,三个角度。这里我选择X,Z轴的位置数据来进行判断。 Apriltags标签一共有6个家族,星瞳科技的例程里面默认是TAG36H11家族,因为它的识别错误率比较低,而我选择TAG16H5,因为可以识别得比较远。

我的OPENMV4 H7是在星瞳科技买的,在星瞳科技官网有上手教程,其中有介绍到OPENMV的串口通信问题。首先,OPENMV的控制芯片其实就是STM32H7,所以单片机与单片机之间肯定是可以通信的,这一点没有问题。
我们来看一下它的引脚图

在这里插入图片描述
这里可以看到P4和P5是串口,P4是TX,P5是RX.(注意一定要看清楚选对引脚).这就是硬件上的连接,下面来讲一下OPENMV代码。

1.2(OPENMV代码)

先贴出代码

import sensor, image, time, math,pyb
from pyb import UART

sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QQVGA) # we run out of memory if the resolution is much bigger...
sensor.skip_frames(time = 2000)
sensor.set_auto_gain(False)  # must turn this off to prevent image washout...
sensor.set_auto_whitebal(False)  # must turn this off to prevent image washout...
clock = time.clock()
uart = UART(3, 115200)#串口波特率
uart.init(115200,bits=8,parity=None,stop=1)


f_x = (2.8 / 3.984) * 160 # find_apriltags defaults to this if not set
f_y = (2.8 / 2.952) * 120 # find_apriltags defaults to this if not set
c_x = 160 * 0.5 # find_apriltags defaults to this if not set (the image.w * 0.5)
c_y = 120 * 0.5 # find_apriltags defaults to this if not set (the image.h * 0.5)

def degrees(radians):
    return (180 * radians) / math.pi

while(True):
    clock.tick()
    img = sensor.snapshot()

    for tag in img.find_apriltags(families=image.TAG16H5,fx=f_x, fy=f_y, cx=c_x, cy=c_y): # defaults to TAG16H5
        img.draw_rectangle(tag.rect(), color = (255, 0, 0))
        img.draw_cross(tag.cx(), tag.cy(), color = (0, 255, 0))
        print_args = (tag.x_translation(), tag.z_translation())
        uart.write("x%.2fz%.2fe"% print_args+'\r\n')#设置特定格式,以便于stm32分割取得数据,这里设置的格式是精确到两位小数

特别代码讲解如下:

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

上面一行是OPENMV的波特率,数据数,校验位,停止位的设置

  print_args = (tag.x_translation(), tag.z_translation())

上面一行是选择要发送的数据,Apriltags标签可以识别出三维坐标以及偏移量的数值,这里我选择了发送X轴和Z轴的参数,也就是前后以及左右。

uart.write("x%.2fz%.2fe"% print_args+'\r\n')#设置特定格式,以便于stm32分割取得数据

上面这一行是串口发送数据我所需要的格式,这里我是所要的保留两位小数的格式。也就是说,比如X轴的数据为1,则发送的数据是1.00这种格式。Z轴也是如此。’\r\n’是回车换行的意思,这个回车换行也会被发送过去,到时候也作为STM32端的数据检测,讲到STM32代码的时候也会说清楚。

这是OPENMV端的代码,下一篇文章,我将写一下STM32端的代码以及讲解~
OpenMVSTM32都是常用于嵌入式系统开发的工具,其中OpenMV是一款基于Python编程语言的开源嵌入式视觉开发平台,而STM32是一种基于ARM Cortex-M处理器内核的单片机OpenMVSTM32可以结合使用,实现各种应用,例如追踪小车控制。 具体实现方法如下: 1.在OpenMV上进行图像处理,通过OpenMV的摄像头获取图像数据,使用Python代码进行图像处理,识别小车的位置和方向等信息。 2.将处理后的数据通过串口传输到STM32上,STM32根据接收到的数据控制小车运动。 3.STM32根据接收到的数据调整小车的运动方向和速度,使其朝向目标位置运动。 以下是参考代码: OpenMV部分: ```python import sensor, image, time, pyb, ustruct from pyb import UART #初始化串口 uart = UART(3, 115200) #初始化摄像头 sensor.reset() sensor.set_pixformat(sensor.RGB565) sensor.set_framesize(sensor.QVGA) sensor.skip_frames(time = 2000) sensor.set_auto_whitebal(False) def find_blobs(): #寻找小车颜色区域 for i in range(10): img = sensor.snapshot() blobs = img.find_blobs([(0, 100, -128, 127, -128, 127)], pixels_threshold=100, area_threshold=100) if blobs: #找到颜色区域后计算中心点坐标和面积 max_blob = max(blobs, key=lambda b: b.pixels()) x = max_blob.cx() y = max_blob.cy() w = max_blob.w() h = max_blob.h() return (x,y,w,h) while(True): blobs_data = find_blobs() if blobs_data: #将数据打包发送到串口 uart.write(ustruct.pack("<hhhh", blobs_data, blobs_data, blobs_data, blobs_data[3])) time.sleep(10) ``` STM32部分: ```c #include "stm32f4xx.h" #include "stm32f4xx_gpio.h" #include "stm32f4xx_rcc.h" #include "misc.h" #define BUF_SIZE 8 GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; uint8_t buf[BUF_SIZE]; void USART3_IRQHandler(void) { if (USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) { static uint8_t i = 0; buf[i++] = USART_ReceiveData(USART3); if (i >= BUF_SIZE) { i = 0; int16_t x,y,w,h; memcpy(&x, buf, 2); memcpy(&y, buf+2, 2); memcpy(&w, buf+4, 2); memcpy(&h, buf+6, 2); //根据接收到的数据调整小车运动方向和速度 } } } int main(void) { RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_USART3); GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_USART3); USART_InitStructure.USART_BaudRate = 115200; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART3, &USART_InitStructure); NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); USART_Cmd(USART3, ENABLE); while(1) { } } ```
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值