|
1.前言
一直有想要寫(xiě)些東西的想法正好最近比較閑以及大創(chuàng)項(xiàng)目和電賽備賽需要用到OpenMV所以就記錄一下學(xué)習(xí)過(guò)程。因?yàn)樾“椎谝淮螌?xiě)文章有什么錯(cuò)誤希望大家包含在評(píng)論區(qū)指正。
2.硬件連接
2.1、Openmv端
XDY~JN544R(L5VONC`HZQ~I.png (207.97 KB, 下載次數(shù): 59)
下載附件
2022-4-6 00:02 上傳
這里OpenMV端僅作為數(shù)據(jù)的發(fā)送端,所以只需要共地,以及OpenMV的TX(P4)與開(kāi)發(fā)板的RX端連接即可。
2.2、STM32端
51hei圖片20220406000313.png (170.4 KB, 下載次數(shù): 62)
下載附件
2022-4-6 00:03 上傳
將開(kāi)發(fā)板連接STM芯片RX端與轉(zhuǎn)串口TX端的跳帽取下,再將OpenMV的TX端(P4)與STM的RX連接。如果使用USB轉(zhuǎn)TTL則將TTL的RX端與STM的TX端連接,STM的RX端與OpenMV的TX端(P4)連接,然后共地,這樣就可以在串口調(diào)試助手中查看數(shù)據(jù)的傳輸情況了。
3.代碼
3.1、OpenMV端
# Blob Detection and uart transport
import sensor, image, time, math, pyb
from pyb import UART
import json
import ustruct
# For color tracking to work really well you should ideally be in a very, very,
# very, controlled enviroment where the lighting is constant...A
yellow_threshold = (8, 22, -60, -3, 127, -128)
# You may need to tweak the above settings for tracking green things...
# Select an area in the Framebuffer to copy the color settings.
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA) #設(shè)置圖像大小QVGA大小為320*240,所以中心坐標(biāo)應(yīng)該是(160,120)
sensor.skip_frames(time = 2000)
sensor.set_auto_gain(False) # must be turned off for color tracking
sensor.set_auto_whitebal(False) # must be turned off for color tracking
red_threshold_01=(66, 31, -58, -24, 127, -128)
clock = time.clock()
uart = UART(3, 115200)
uart.init(115200, bits=8, parity=None, stop=1) # OpenMV端初始化與STM端配置一樣即可。
#**************************傳輸數(shù)據(jù)的函數(shù)************************************
def sending_data(cx,cy):
global uart;
#frame=[0x2C,18,cx%0xff,int(cx/0xff),cy%0xff,int(cy/0xff),0x5B];
#data = bytearray(frame)
data = ustruct.pack("<bbhhb", #格式為倆個(gè)字符倆個(gè)短整型(2字節(jié))
0x2C, #幀頭1
0x12, #幀頭2
int(cx), # up sample by 4 #數(shù)據(jù)1
int(cy), # up sample by 4 #數(shù)據(jù)2
0x5B)
uart.write(data); #必須要傳入一字節(jié)的數(shù)組,這個(gè)函數(shù)似乎不能發(fā)送單個(gè)字節(jié),必須得一次發(fā)送多個(gè)字節(jié)
#**************************************************************************
#**************************找到最大的色塊函數(shù)*******************************#
def find_max(blobs):
max_size=0
for blob in blobs:
if blob.pixels() > max_size:
max_blob=blob
max_size = blob.pixels()
return max_blob
#**************************************************************************#
while(True):
img = sensor.snapshot() # Take a picture and return the image.
blobs = img.find_blobs([yellow_threshold])
if blobs:
max_blob=find_max(blobs)
#print('sum :', len(blobs))
img.draw_rectangle(max_blob.rect())
img.draw_cross(max_blob.cx(), max_blob.cy())
output_str="[%d,%d]" % (max_blob.cx(),max_blob.cy())
print('you send:',output_str) #打印色塊中心點(diǎn)坐標(biāo)到串行終端便于數(shù)據(jù)核驗(yàn)
sending_data(max_blob.cx(),max_blob.cy())#發(fā)送色塊框的中心點(diǎn)坐標(biāo)
#FH = bytearray([0x2C,0x12,blobs[0].cx(),blobs[0].cy(),0x5B])
#uart.write(FH)
else:
print('not found!')
sending_data(567,789)#如果沒(méi)有找到符合條件的色塊,那么發(fā)送一個(gè)不可能出現(xiàn)的坐標(biāo)
#FH = bytearray([0x2C,0x12,0x77,0x55,0x5B])
#uart.write(FH)
顏色識(shí)別:
這里只需要使用閾值編輯器,將想要識(shí)別的顏色調(diào)節(jié)到純白色如下圖所示,然后將下面的LAB閾值填入 red_threshold_01=() 即可。
51hei圖片20220406000457.png (137.89 KB, 下載次數(shù): 60)
下載附件
2022-4-6 00:05 上傳
獲取中心坐標(biāo):
blob.rect() 返回這個(gè)色塊的外框——矩形元組(x, y, w, h),可以直接在 image.draw_rectangle中使用。
blob.x() 返回色塊的外框的x坐標(biāo)(int),也可以通過(guò)blob[0]來(lái)獲取。
blob.y() 返回色塊的外框的y坐標(biāo)(int),也可以通過(guò)blob[1]來(lái)獲取。
blob.w() 返回色塊的外框的寬度w(int),也可以通過(guò)blob[2]來(lái)獲取。
blob.h() 返回色塊的外框的高度h(int),也可以通過(guò)blob[3]來(lái)獲取。
blob.pixels() 返回色塊的像素?cái)?shù)量(int),也可以通過(guò)blob[4]來(lái)獲取。
blob.cx() 返回色塊的外框的中心x坐標(biāo)(int),也可以通過(guò)blob[5]來(lái)獲取。
blob.cy() 返回色塊的外框的中心y坐標(biāo)(int),也可以通過(guò)blob[6]來(lái)獲取。
3.2、STM32端
void DEBUG_USART_IRQHandler(void)
{
uint8_t com_data;
uint8_t i;
static uint8_t RxCounter1=0;
static uint16_t RxBuffer1[7]={0};
static uint8_t RxState = 0;
// static uint8_t RxFlag1 = 0;
if( USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET) //接收中斷
{
USART_ClearITPendingBit(USART1,USART_IT_RXNE); //清除中斷標(biāo)志
com_data = USART_ReceiveData(DEBUG_USARTx );
if(RxState==0&&com_data==0x2C) //0x2c幀頭
{
RxState=1;
RxBuffer1[RxCounter1++]=com_data; //RxBuffer1[0]==0x2c RxCounter1==1
}
else if(RxState==1&&com_data==0x12) //0x12幀頭
{
RxState=2;
RxBuffer1[RxCounter1++]=com_data; //RxBuffer1[0]==0x12 RxCounter1==2
}
else if(RxState==2) //開(kāi)始接收有效數(shù)據(jù)
{
RxBuffer1[RxCounter1++]=com_data; //全部接收完,RxCounter1==7
if(RxCounter1>=7||com_data == 0x5B) //RxBuffer1接受滿了,接收數(shù)據(jù)結(jié)束
{
RxState=3;
// RxFlag1=1;
Cx=(RxBuffer1[RxCounter1-4]<<8)+(RxBuffer1[RxCounter1-5]); //RxBuffer1[2]是openmv發(fā)送的第一個(gè)數(shù)據(jù)的低八位,RxBuffer1[3]是openmv發(fā)送的第一個(gè)數(shù)據(jù)的高八位
Cy=(RxBuffer1[RxCounter1-2]<<8)+(RxBuffer1[RxCounter1-3]); //RxBuffer1[4]是openmv發(fā)送的第二個(gè)數(shù)據(jù)的低八位,RxBuffer1[5]是openmv發(fā)送的第二個(gè)數(shù)據(jù)的高八位
printf("X=%d,Y=%d\n",Cx,Cy);
delay_ms(300); //延時(shí)防止大量數(shù)據(jù)造成上位機(jī)卡頓
}
}
else if(RxState==3) //檢測(cè)是否接受到結(jié)束標(biāo)志
{
if(RxBuffer1[RxCounter1-1] == 0x5B)
{
USART_ITConfig(DEBUG_USARTx,USART_IT_RXNE,DISABLE);//關(guān)閉DTSABLE中斷
// if(RxFlag1)
// {
//
// OLED_ShowNum(0,0,Cx,3,1,2);
// OLED_ShowNum(0,2,Cy,3,1,2);
//
// }
// RxFlag1 = 0;
RxCounter1 = 0;
RxState = 0;
USART_ITConfig(DEBUG_USARTx,USART_IT_RXNE,ENABLE);
}
else //接收錯(cuò)誤
{
RxState = 0;
RxCounter1=0;
for(i=0;i<7;i++)
{
RxBuffer1[ i]=0xff; //將存放數(shù)據(jù)數(shù)組清零
}
}
}
else //接收異常
{
RxState = 0;
RxCounter1=0;
for(i=0;i<7;i++)
{
RxBuffer1[ i]=0xff; //將存放數(shù)據(jù)數(shù)組清零
}
}
}
}
看到這里或許會(huì)存在疑問(wèn),為什么我們發(fā)送五個(gè)數(shù)據(jù)卻要定義一個(gè)七位的數(shù)據(jù)的接收數(shù)組呢?在OpenMV端的發(fā)送函數(shù)里面有一個(gè)"<bbhhb"的數(shù)據(jù)聲明,其中b表示C語(yǔ)言的signed char類型占一個(gè)字節(jié)八位二進(jìn)制數(shù),h表示C語(yǔ)言的short類型占兩個(gè)字節(jié)十六位二進(jìn)制數(shù)。而我們的OpenMV一次只能發(fā)送一個(gè)字節(jié)八位二進(jìn)制數(shù),因此實(shí)際傳輸?shù)臄?shù)據(jù)為:數(shù)據(jù)幀1->數(shù)據(jù)幀2->數(shù)據(jù)1的低八位->數(shù)據(jù)1的高八位->數(shù)據(jù)2的低八位->數(shù)據(jù)2的高八位->數(shù)據(jù)幀3。至于為什么數(shù)據(jù)要使用兩個(gè)字節(jié),那是因?yàn)槲覀冞x擇的是QVGA即320*240大小的圖像,因此數(shù)據(jù)將會(huì)超過(guò)255即一個(gè)字節(jié)八位二進(jìn)制數(shù)。
4.查看結(jié)果
51hei圖片20220406000730.png (173.84 KB, 下載次數(shù): 60)
下載附件
2022-4-6 00:07 上傳
左邊是OpenMV IDE串行終端的數(shù)據(jù),右邊是調(diào)試助手中的數(shù)據(jù)?梢园l(fā)現(xiàn)雖然延時(shí)導(dǎo)致部分?jǐn)?shù)據(jù)沒(méi)有被打印出來(lái)但是調(diào)試助手中的數(shù)據(jù)全部來(lái)自串行終端,所以代碼正確。
## 5.總結(jié)
代碼部分參考了[這篇文章]寫(xiě)的很好很詳細(xì)。完整的工程代碼可以去[Gitee下載]。
|
評(píng)分
-
查看全部評(píng)分
|