由於之前接觸openmv的時候是用庫函數寫的代碼,在網上發現用hal庫寫接收代碼的例子並不多,於是就想重新用cubemx寫一次openmv與stm32通訊的代碼,把之前寫好的顏色識別返回座標的Python代碼運用一次。
所需要的元器件
- stm32單片機
- usb-ttl模塊
- stlink
- openmv
- 導線若干
整體思路
- 先編寫openmv的代碼,實現特定顏色識別,並把座標值通過串口發送出去;
- 之後在cube上配置相關stm32的初始化設置,並生成代碼;
- 在keil裏編寫串口中斷接收函數,將串口1用於接收openmv發送來的數據,並通過串口2將接收到的數據通過串口發送給電腦;
- 燒錄程序實現效果,並改進出現的問題。
接線方式
- stm32通過uart1與openmv連接
- stm32通過sw與stlink連接
- stm32通過uart2與usb-ttl連接
完成效果
openmv識別特定顏色的物體,並把其座標發送給stm32,單片機讀取後通過ttl在pc上顯示。
Cube配置
代碼解析
- openmv顏色識別及座標發送
import sensor, image, time
from pyb import UART
import json
threshold = [(6, 16, 19, 63, 4, 25)]
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.skip_frames(time = 2000 )
sensor.set_auto_whitebal(False)
clock = time.clock()
uart = UART(3, 115200)
uart.init(115200, bits=8, parity=None, stop=1) #8位數據位,無校驗位,1位停止位、
while(True):
clock.tick()
img = sensor.snapshot()
blob = img.find_blobs(threshold, area_threshold=300)
if blob: #如果找到了目標顏色
FH = bytearray([0xb3,0xb4])
uart.write(FH)
for b in blob:
#迭代找到的目標顏色區域
img.draw_cross(b[5], b[6]) # cx, cy
img.draw_edges(b.min_corners(), color=(0,255,0))
x = b.cx()
y = b.cy()
data = bytearray([x,y])
uart.write(data)
end = bytearray([0x01,0x01,0xb5,0xb6])
uart.write(end)
- stm32串口中斷接收
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) //opmv-receive
{
if(huart==&huart1)
{
HAL_UART_Receive_IT(&huart1,&my_re_buf1[++pt_w1],1);
trans(my_re_buf1[pt_w1]);
}
}
- stm32接收數據處理
while(pt_r1<pt_w1 )
{
while(pt_r1<pt_w1)
{
pt_r1++;
}
}
if(pt_r1>=pt_w1)
{
pt_w1=pt_r1=0;
HAL_UART_AbortReceive_IT(&huart1);
HAL_UART_Receive_IT(&huart1,my_re_buf1,1);
}
- 發送數據函數
void measure(void)
{
int x,y;
x=opmvdata[2];
y=opmvdata[3];
printf("x: %d \r ,",x);
printf("y: %d \r\n",y);
}
- 數據判斷部分
static int state = 0;
if(state==0&&data==0xb3)
{
state=1;
opmvdata[0]=data;
}
else if(state==1&&data==0xb4)
{
state=2;
opmvdata[1]=data;
}
- 數據不符清除部分
else if(data != 0xb6)
{
state = 0;
for(i=0;i<8;i++)
{
opmvdata[i]=0x00;
}
}
遇到的問題
剛開始的時候openmv的發送數據總是會在stm32上漏掉一些,或者多出來一些,後來發現數據不能發送\r\n這樣的數據,會打亂數據的結構。並且發送的時候一定要開啓16進制顯示,這樣調試的時候才能看到數據是否滿足需求。
其次,stm32的接收函數一定要判斷髮送的數據串的幀頭是否爲openmv上設置的預設值,滿足後方可把數據存入數組。
在數據處理中,記得把16進制的數據轉化爲10進制,否則數據格式會不容易讀懂。
總結
寫代碼是個有趣的過程,遇到問題多在csdn上找答案。