最近需要用到openmv进行追踪物体,所以在此做个小结,其中这些文章给我很大的帮助,建议可以去看超详细OpenMV与STM32单片机通信 以及星瞳科技官网
实验目的:openmv追踪物体颜色,将物体坐标发给32(为了 调试,顺便将32收到的数据传给上位机) 实验所需:openmv,STM32F103ZET6(正点原子)
一、openmv程序编写
import sensor, image, time
from pid import PID
from pyb import Servo
from pyb import UART,LED
import json
import ustruct
pan_servo=Servo(1)
tilt_servo=Servo(2)
pan_servo.calibration(500,2500,500)
tilt_servo.calibration(500,2500,500)
red_threshold = (2, 12, -56, 2, -75, 14)
pan_pid = PID(p=0.08, i=0, imax=90)
tilt_pid = PID(p=0.05, i=0, imax=90)
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QQVGA)
sensor.skip_frames(10)
sensor.set_auto_whitebal(False)
clock = time.clock()
uart = UART(3,115200)
uart.init(115200, bits=8, parity=None, stop=1)
def find_max(blobs):
max_size=0
for blob in blobs:
if blob[2]*blob[3] > max_size:
max_blob=blob
max_size = blob[2]*blob[3]
return max_blob
def sending_data(cx,cy,cw,ch):
global uart;
data = ustruct.pack("<bbhhhhb",
0x2C,
0x12,
int(cx),
int(cy),
int(cw),
int(ch),
0x5B)
uart.write(data);
while(True):
clock.tick()
img = sensor.snapshot()
blobs = img.find_blobs([red_threshold])
if blobs:
max_blob = find_max(blobs)
pan_error = max_blob.cx()-img.width()/2
tilt_error = max_blob.cy()-img.height()/2
img.draw_rectangle(max_blob.rect())
img.draw_cross(max_blob.cx(), max_blob.cy())
pan_output=pan_pid.get_pid(pan_error,1)/2
tilt_output=tilt_pid.get_pid(tilt_error,1)
pan_servo.angle(pan_servo.angle()+pan_output)
tilt_servo.angle(tilt_servo.angle()-tilt_output)
cx=max_blob[5]
cy=max_blob[6]
cw=max_blob[2]
ch=max_blob[3]
FH = bytearray([0x2C,0x12,cx,cy,cw,ch,0x5B])
uart.write(FH)
print(cx,cy,cw,ch)
二、stm32
1、cubeMX配置 时钟树这些基本配置掠过,然后需要配置串口4,串口1,以及两个led灯(方便调试),配置串口记得开中断,以及配置优先级 2、源码 (1).openmv.h
#ifndef __OpenMV_H
#define __OpenMV_H
#include "stm32f1xx.h"
void Openmv_Receive_Data(int16_t data);
#endif
(2).openmv.c
#include "OpenMV.h"
#include "stdio.h"
#include "usart.h"
static uint8_t Cx=0,Cy=0,Cw=0,Ch=0;
void Openmv_Receive_Data(int16_t com_data)
{
uint8_t i;
static uint8_t RxCounter1=0;
static uint16_t RxBuffer1[10]={0};
static uint8_t RxState = 0;
static uint8_t RxFlag1 = 0;
if(RxState==0&&com_data==0x2C)
{
RxState=1;
RxBuffer1[RxCounter1++]=com_data;
HAL_GPIO_WritePin(LED0_GPIO_Port, LED0_Pin, GPIO_PIN_RESET);
}
else if(RxState==1&&com_data==0x12)
{
HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET);
RxState=2;
RxBuffer1[RxCounter1++]=com_data;
}
else if(RxState==2)
{
RxBuffer1[RxCounter1++]=com_data;
if(RxCounter1>=10||com_data == 0x5B)
{
RxState=3;
RxFlag1=1;
Cx=RxBuffer1[RxCounter1-5];
Cy=RxBuffer1[RxCounter1-4];
Cw=RxBuffer1[RxCounter1-3];
Ch=RxBuffer1[RxCounter1-2];
printf("%d\r ",Cx);
printf("%d\r ",Cy);
printf("%d\r ",Cw);
printf("%d\r\n",Ch);
}
}
else if(RxState==3)
{
if(RxBuffer1[RxCounter1-1] == 0x5B)
{
RxFlag1 = 0;
RxCounter1 = 0;
RxState = 0;
}
else
{
RxState = 0;
RxCounter1=0;
for(i=0;i<10;i++)
{
RxBuffer1[i]=0x00;
}
}
}
else
{
RxState = 0;
RxCounter1=0;
for(i=0;i<10;i++)
{
RxBuffer1[i]=0x00;
}
}
}
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
return ch;
}
int fgetc(FILE *f)
{
uint8_t ch = 0;
HAL_UART_Receive(&huart1, &ch, 1, 0xffff);
return ch;
}
(3).主函数 先定义两个全局变量
uint8_t usart1_rxbuff;
uint8_t uart4_rxbuff;
主函数里面加上串口接受中断开启
HAL_UART_Receive_IT(&huart4,(void *)&uart4_rxbuff,1);
HAL_UART_Receive_IT(&huart1,(void *)&usart1_rxbuff,1);
中断回调函数(切记要加上接收中断开启)
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
uint16_t tem;
if(huart->Instance==UART4)
{
tem=uart4_rxbuff;
Openmv_Receive_Data(tem);
}
HAL_UART_Receive_IT(&huart4,(void *)&uart4_rxbuff,1);
}
**
三、实验现象
** 四、总结 其中出现了一个好蠢的问题,就是我一直检测不到0x2c之后的数据,以为是接受解码程序的问题。后来发现只是忘记在中断回调函数里面加接收中断,真的是大无语事件。
|