找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5035|回复: 1
打印 上一主题 下一主题
收起左侧

基于openmv与stm32的寻球小车制作 附代码

[复制链接]
跳转到指定楼层
楼主
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代码。

.2(OPENMV代码)
先贴出代码
mport 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端的代码
寻球小车 7.0(no_find优化).7z (246.8 KB, 下载次数: 122)

单片机源程序如下:
  1. #include "my_include.h"

  2. extern CAR_STATUS_e car_mode;
  3. extern moty_duty run_duty;
  4. extern u8 control_data[MAX_DATA_LENS];
  5. extern float C_P; //cameraP
  6. extern float C_D; //cameraD
  7. extern int16 ser_duty;
  8. extern int16 x_error;
  9. extern int16 last_x_error;
  10. extern uint8 ball_colcor;
  11. extern uint8 BEEP_ON_OFF;

  12. extern uint8 out_edge;//出界

  13. void Car_mode_control()
  14. {

  15.                 if(control_data[3]<50 && control_data[3]!=0) //左出界
  16.                 {
  17.                         out_edge=Left;
  18.                 }
  19.                 else if(control_data[3]>110 && control_data[3]!=0) //右出界
  20.                 {
  21.                         out_edge=Right;
  22.                 }

  23.                
  24.                 //--------------------车位状态判断-----------------//
  25.                 if(out_edge==Left && control_data[4]==0 && control_data[5]==0)
  26.                 {
  27.                         car_mode=finding_L;
  28.                 }
  29.                 else if(out_edge==Right && control_data[4]==0 && control_data[5]==0)
  30.                 {
  31.                         car_mode=finding_R;
  32.                 }
  33.                 else if (control_data[3]>0 && control_data[4]>0 && control_data[5]>0)
  34.                 {
  35.                         car_mode=run;
  36.                 }
  37.                 if(control_data[5]<=12 && control_data[5]>=3)
  38.                 {
  39.                                 LED1=0;
  40.                                 car_mode=stop;
  41.                 }
  42.                 else {LED1=1;}
  43.                
  44.                 if(Boma4==0)//强制菜单
  45.                 {
  46.                         car_mode=stop;
  47.                 }
  48.                 //寻找小球的 色号(0为红,1为绿)        

  49.                 if(Boma3==0)
  50.                 {
  51.                         BEEP_ON_OFF=OFF;
  52.                 }
  53.                 else {BEEP_ON_OFF=ON;}
  54. }


  55. void FTM_updata()
  56. {

  57.                 if(car_mode == run)
  58.                 {
  59.                                 TIM_SetCompare1(TIM1,run_duty.Speed_Duty_R);        //右为  TIM1  CH1
  60.                                 TIM_SetCompare4(TIM1,run_duty.Speed_Duty_L);  //左为  TIM1  CH4
  61.                 }
  62.                 else if(car_mode == finding_R)
  63.                 {
  64.                                 TIM_SetCompare1(TIM1,1400);        //右为  TIM1  CH1
  65.                                 TIM_SetCompare4(TIM1,1400); //左为  TIM1  CH4
  66.                 }
  67.                 else if(car_mode == finding_L)
  68.                 {
  69.                                 TIM_SetCompare1(TIM1,1500);        //右为  TIM1  CH1
  70.                                 TIM_SetCompare4(TIM1,1500); //左为  TIM1  CH4
  71.                 }
  72.           else if(car_mode == stop)
  73.                 {
  74.                                 TIM_SetCompare1(TIM1,0);        //右为  TIM1  CH1
  75.                                 TIM_SetCompare4(TIM1,0);  //左为  TIM1  CH4
  76.                 }
  77. }




  78. void PD_control()
  79. {

  80.         last_x_error=x_error;
  81.         x_error=control_data[3]-80;
  82.         ser_duty = C_P*x_error-C_D*(last_x_error-x_error);

  83.         run_duty.Speed_Duty_R=1550-ser_duty;//正为正转
  84.         run_duty.Speed_Duty_L=1350-ser_duty;
  85.         //左边FTM波//限幅        
  86.         run_duty.Speed_Duty_L=run_duty.Speed_Duty_L<1300?1300:run_duty.Speed_Duty_L;
  87.         run_duty.Speed_Duty_L=run_duty.Speed_Duty_L>1600?1600:run_duty.Speed_Duty_L;
  88.         //右边FTM波//限幅        
  89.   run_duty.Speed_Duty_R=run_duty.Speed_Duty_L<1300?1300:run_duty.Speed_Duty_R;
  90.         run_duty.Speed_Duty_R=run_duty.Speed_Duty_L>1600?1600:run_duty.Speed_Duty_R;

  91.         
  92.         
  93. }
复制代码


评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏3 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:713851 发表于 2020-3-23 10:02 | 只看该作者
您好我买了个平衡小车想咨询怎么与openmv连接
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表