找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 5812|回復(fù): 1
收起左側(cè)

基于openmv與stm32的尋球小車(chē)制作 附代碼

[復(fù)制鏈接]
ID:519703 發(fā)表于 2020-2-25 16:13 | 顯示全部樓層 |閱讀模式
OPENMV和STM32的識(shí)別追蹤小車(chē)(詳細(xì)版)之OPENMV端
實(shí)現(xiàn):通過(guò)OPENMV識(shí)別Apriltags標(biāo)簽,STM32驅(qū)動(dòng)小車(chē)追蹤標(biāo)簽
博主通過(guò)一段時(shí)間的學(xué)習(xí),做了這個(gè)比較簡(jiǎn)單的以O(shè)PENMV為攝像傳感器STM32為控制器的尋物小車(chē),不多說(shuō),直接進(jìn)入正題!

材料準(zhǔn)備
小車(chē)底盤(pán)&&輪子
直流減速電機(jī)
杜邦線(xiàn)若干
7.2V電源
L298N模塊
STM32F407最小系統(tǒng)
OPENMV4 H7

程序設(shè)計(jì)思路
這里分兩個(gè)方面來(lái)說(shuō),一個(gè)是OPENMV的程序,另一個(gè)是STM32的程序。其中,最重要的地方是openmv與stm32的通信問(wèn)題,我也會(huì)著重講一下這個(gè)問(wèn)題。由于篇幅比較長(zhǎng),我將分兩篇文章講解。

一:首先說(shuō)一下OPENMV的介紹和程序
1.1(OPENMV介紹)
OpenMV攝像頭是一款小巧,低功耗,低成本的電路板,它幫助你很輕松的完成機(jī)器視覺(jué)(machine vision)應(yīng)用。它可以讓我們直接應(yīng)用具有人工智能的功能的攝像頭作為我們機(jī)器人的視覺(jué)傳感器。它可以識(shí)別出人臉,方塊,小球,標(biāo)簽等。
這里,我選擇用來(lái)識(shí)別Apriltags標(biāo)簽,OPENMV識(shí)別Apriltags標(biāo)簽可以計(jì)算出相對(duì)于相機(jī)的精確3D位置,方向和id。包括有6個(gè)自由度,三個(gè)位置,三個(gè)角度。這里我選擇X,Z軸的位置數(shù)據(jù)來(lái)進(jìn)行判斷。 Apriltags標(biāo)簽一共有6個(gè)家族,星瞳科技的例程里面默認(rèn)是TAG36H11家族,因?yàn)樗淖R(shí)別錯(cuò)誤率比較低,而我選擇TAG16H5,因?yàn)榭梢宰R(shí)別得比較遠(yuǎn)。

我的OPENMV4 H7是在星瞳科技買(mǎi)的,在星瞳科技官網(wǎng)有上手教程,其中有介紹到OPENMV的串口通信問(wèn)題。首先,OPENMV的控制芯片其實(shí)就是STM32H7,所以單片機(jī)與單片機(jī)之間肯定是可以通信的,這一點(diǎn)沒(méi)有問(wèn)題,看一下它的引腳圖

這里可以看到P4和P5是串口,P4是TX,P5是RX.(注意一定要看清楚選對(duì)引腳).這就是硬件上的連接,下面來(lái)講一下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')#
設(shè)置特定格式,以便于stm32分割取得數(shù)據(jù),這里設(shè)置的格式是精確到兩位小數(shù)特別代碼講解如下:在附件中
uart.init(115200,bits=8,parity=None,stop=1)
上面一行是OPENMV的波特率,數(shù)據(jù)數(shù),校驗(yàn)位,停止位的設(shè)置
print_args = (tag.x_translation(), tag.z_translation())上面一行是選擇要發(fā)送的數(shù)據(jù),Apriltags標(biāo)簽可以識(shí)別出三維坐標(biāo)以及偏移量的數(shù)值,這里我選擇了發(fā)送X軸和Z軸的參數(shù),也就是前后以及左右。
uart.write("x%.2fz%.2fe"% print_args+'\r\n')#設(shè)置特定格式,以便于stm32分割取得數(shù)據(jù)上面這一行是串口發(fā)送數(shù)據(jù)我所需要的格式,這里我是所要的保留兩位小數(shù)的格式。也就是說(shuō),比如X軸的數(shù)據(jù)為1,則發(fā)送的數(shù)據(jù)是1.00這種格式。Z軸也是如此。’\r\n’是回車(chē)換行的意思,這個(gè)回車(chē)換行也會(huì)被發(fā)送過(guò)去,到時(shí)候也作為STM32端的數(shù)據(jù)檢測(cè),講到STM32代碼的時(shí)候也會(huì)說(shuō)清楚。
51hei.png
這是OPENMV端的代碼
尋球小車(chē) 7.0(no_find優(yōu)化).7z (246.8 KB, 下載次數(shù): 123)

單片機(jī)源程序如下:
  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.                 //--------------------車(chē)位狀態(tài)判斷-----------------//
  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)//強(qiáng)制菜單
  45.                 {
  46.                         car_mode=stop;
  47.                 }
  48.                 //尋找小球的 色號(hào)(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;//正為正轉(zhuǎn)
  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. }
復(fù)制代碼


評(píng)分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

ID:713851 發(fā)表于 2020-3-23 10:02 | 顯示全部樓層
您好我買(mǎi)了個(gè)平衡小車(chē)想咨詢(xún)?cè)趺磁copenmv連接
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表