赞
踩
最近需要用到openmv进行追踪物体,所以在此做个小结,其中这些文章给我很大的帮助,建议可以去看超详细OpenMV与STM32单片机通信
以及星瞳科技官网
实验目的:openmv追踪物体颜色,将物体坐标发给32(为了 调试,顺便将32收到的数据传给上位机)
实验所需:openmv,STM32F103ZET6(正点原子)
# Untitled - By:阿布 - 周日 7月 19 2021 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 = (13, 49, 18, 61, 6, 47) red_threshold = (2, 12, -56, 2, -75, 14)#测试所用,白色,懒得该名称 pan_pid = PID(p=0.08, i=0, imax=90) #脱机运行或者禁用图像传输,使用这个PID tilt_pid = PID(p=0.05, i=0, imax=90) #脱机运行或者禁用图像传输,使用这个PID #pan_pid = PID(p=1, i=0, imax=90)#在线调试使用这个PID #tilt_pid = PID(p=1, i=0, imax=90)#在线调试使用这个PID sensor.reset() # Initialize the camera sensor. sensor.set_pixformat(sensor.RGB565) # use RGB565. sensor.set_framesize(sensor.QQVGA) # use QQVGA for speed. sensor.skip_frames(10) # Let new settings take affect. sensor.set_auto_whitebal(False) # turn this off. clock = time.clock() # Tracks FPS. uart = UART(3,115200) #定义串口3变量 uart.init(115200, bits=8, parity=None, stop=1) # init with given parameters 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; #frame=[0x2C,18,cx%0xff,int(cx/0xff),cy%0xff,int(cy/0xff),0x5B]; #data = bytearray(frame) data = ustruct.pack("<bbhhhhb", #格式为俩个字符俩个短整型(2字节) 0x2C, #帧头1 0x12, #帧头2 int(cx), # up sample by 4 #数据1 int(cy), # up sample by 4 #数据2 int(cw), # up sample by 4 #数据1 int(ch), # up sample by 4 #数据2 0x5B) uart.write(data); #必须要传入一个字节数组 while(True): clock.tick() # Track elapsed milliseconds between snapshots(). img = sensor.snapshot() # Take a picture and return the image. 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 #print("pan_error: ", pan_error) img.draw_rectangle(max_blob.rect()) # rect img.draw_cross(max_blob.cx(), max_blob.cy()) # cx, cy pan_output=pan_pid.get_pid(pan_error,1)/2 tilt_output=tilt_pid.get_pid(tilt_error,1) #print("pan_output",pan_output) 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)
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) //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) //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) //RxBuffer1接受满了,接收数据结束 { 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); // if(RxState==1) // { // HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET); // } // else if(RxState!=1&&RxState!=0) // { // HAL_GPIO_WritePin(LED0_GPIO_Port, LED0_Pin, GPIO_PIN_RESET); // } } } 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; //将存放数据数组清零 } } } /** * 函数功能: 重定向c库函数printf到DEBUG_USARTx * 输入参数: 无 * 返 回 值: 无 * 说 明:无 */ int fputc(int ch, FILE *f) { HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff); return ch; } /** * 函数功能: 重定向c库函数getchar,scanf到DEBUG_USARTx * 输入参数: 无 * 返 回 值: 无 * 说 明:无 */ int fgetc(FILE *f) { uint8_t ch = 0; HAL_UART_Receive(&huart1, &ch, 1, 0xffff); return ch; }
(3).主函数
先定义两个全局变量
/* USER CODE BEGIN PV */
uint8_t usart1_rxbuff;
uint8_t uart4_rxbuff;
/* USER CODE END PV */
主函数里面加上串口接受中断开启
HAL_UART_Receive_IT(&huart4,(void *)&uart4_rxbuff,1);
HAL_UART_Receive_IT(&huart1,(void *)&usart1_rxbuff,1);
中断回调函数(切记要加上接收中断开启)
/* USER CODE BEGIN 4 */
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);
}
/* USER CODE END 4 */
**
**
四、总结
其中出现了一个好蠢的问题,就是我一直检测不到0x2c之后的数据,以为是接受解码程序的问题。后来发现只是忘记在中断回调函数里面加接收中断,真的是大无语事件。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。