|
1.前言
一直有想要寫些東西的想法正好最近比較閑以及大創(chuàng)項目和電賽備賽需要用到OpenMV所以就記錄一下學(xué)習(xí)過程。因為小白第一次寫文章有什么錯誤希望大家包含在評論區(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)與開發(fā)板的RX端連接即可。
2.2、STM32端
51hei圖片20220406000313.png (170.4 KB, 下載次數(shù): 62)
下載附件
2022-4-6 00:03 上傳
將開發(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", #格式為倆個字符倆個短整型(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ù)組,這個函數(shù)似乎不能發(fā)送單個字節(jié),必須得一次發(fā)送多個字節(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) #打印色塊中心點坐標(biāo)到串行終端便于數(shù)據(jù)核驗
sending_data(max_blob.cx(),max_blob.cy())#發(fā)送色塊框的中心點坐標(biāo)
#FH = bytearray([0x2C,0x12,blobs[0].cx(),blobs[0].cy(),0x5B])
#uart.write(FH)
else:
print('not found!')
sending_data(567,789)#如果沒有找到符合條件的色塊,那么發(fā)送一個不可能出現(xiàn)的坐標(biāo)
#FH = bytearray([0x2C,0x12,0x77,0x55,0x5B])
#uart.write(FH)
顏色識別:
這里只需要使用閾值編輯器,將想要識別的顏色調(diào)節(jié)到純白色如下圖所示,然后將下面的LAB閾值填入 red_threshold_01=() 即可。
51hei圖片20220406000457.png (137.89 KB, 下載次數(shù): 60)
下載附件
2022-4-6 00:05 上傳
獲取中心坐標(biāo):
blob.rect() 返回這個色塊的外框——矩形元組(x, y, w, h),可以直接在 image.draw_rectangle中使用。
blob.x() 返回色塊的外框的x坐標(biāo)(int),也可以通過blob[0]來獲取。
blob.y() 返回色塊的外框的y坐標(biāo)(int),也可以通過blob[1]來獲取。
blob.w() 返回色塊的外框的寬度w(int),也可以通過blob[2]來獲取。
blob.h() 返回色塊的外框的高度h(int),也可以通過blob[3]來獲取。
blob.pixels() 返回色塊的像素數(shù)量(int),也可以通過blob[4]來獲取。
blob.cx() 返回色塊的外框的中心x坐標(biāo)(int),也可以通過blob[5]來獲取。
blob.cy() 返回色塊的外框的中心y坐標(biāo)(int),也可以通過blob[6]來獲取。
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) //開始接收有效數(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ā)送的第一個數(shù)據(jù)的低八位,RxBuffer1[3]是openmv發(fā)送的第一個數(shù)據(jù)的高八位
Cy=(RxBuffer1[RxCounter1-2]<<8)+(RxBuffer1[RxCounter1-3]); //RxBuffer1[4]是openmv發(fā)送的第二個數(shù)據(jù)的低八位,RxBuffer1[5]是openmv發(fā)送的第二個數(shù)據(jù)的高八位
printf("X=%d,Y=%d\n",Cx,Cy);
delay_ms(300); //延時防止大量數(shù)據(jù)造成上位機卡頓
}
}
else if(RxState==3) //檢測是否接受到結(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 //接收錯誤
{
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ù)組清零
}
}
}
}
看到這里或許會存在疑問,為什么我們發(fā)送五個數(shù)據(jù)卻要定義一個七位的數(shù)據(jù)的接收數(shù)組呢?在OpenMV端的發(fā)送函數(shù)里面有一個"<bbhhb"的數(shù)據(jù)聲明,其中b表示C語言的signed char類型占一個字節(jié)八位二進(jìn)制數(shù),h表示C語言的short類型占兩個字節(jié)十六位二進(jìn)制數(shù)。而我們的OpenMV一次只能發(fā)送一個字節(jié)八位二進(jìn)制數(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ù)要使用兩個字節(jié),那是因為我們選擇的是QVGA即320*240大小的圖像,因此數(shù)據(jù)將會超過255即一個字節(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ù)。可以發(fā)現(xiàn)雖然延時導(dǎo)致部分?jǐn)?shù)據(jù)沒有被打印出來但是調(diào)試助手中的數(shù)據(jù)全部來自串行終端,所以代碼正確。
## 5.總結(jié)
代碼部分參考了[這篇文章]寫的很好很詳細(xì)。完整的工程代碼可以去[Gitee下載]。
|
評分
-
查看全部評分
|