OPENMV结合PIX飞控实现四轴定点 循迹 2017电赛

article/2025/10/9 3:53:56

本文章代码已上传Github:
https://github.com/Kevincoooool/2017_Follow
有兴趣的可以加个STAR

自从17年国赛之后,自己做了openmv,加了很多群,也了解到很多人都在想着这个题。
第一版
这里写图片描述
第二版
这里写图片描述
第三版
这里写图片描述
这里写图片描述
我们做国赛的时候实现了全部功能,找了下题目,这篇文章就以这道题来讲吧。

题目:
这里写图片描述
这里写图片描述
看到题相信大家都送了口气,不是巡线,不用去思考怎么识别直线、曲线、直角、起点圆啊这些,因为在赛前我们队一直在想着怎么用OV7670或者OV2640来实现这些东西的识别,那段时间也确实找到了段资料:
http://blog.csdn.net/hello_world12138/article/details/51974092
这位大佬写的相当详细,大家也可以参考下来写自己的识别算法。

而我们采用的方案是OpenMV+PixHawk+STM32F4
这种方案就是最省事,不需要自己写飞控,不需要去调姿态的PID,对于玩过PIX的人来说最方便。
这里写图片描述

OPENMV负责图像的采集和处理,PIX负责飞机的基础稳定飞行和定高,STM32负责控制PIX怎么飞,也就是用32来模拟了一个遥控器,输出PWM波后经过PPM编码器转换成PPM信号给pix就能用32控制pix啦。

一、OPENMV的设计
当时我们是买的官方代理的OPENMV3,价格388呢,还好能报销哈哈,用openmv实现了对地面黑点的检测,然后通过串口3把黑点的坐标值传回给STM32。
这里写图片描述

OPENMV寻找黑点串口输出程序

# 寻找黑点串口输出程序 - By: Kevincoooool - 周四 11月 23 2017
import sensor,time,pyb,math
from pyb import Pin, Timer, LED, UART
#黑色点阈值
black_threshold = [(0, 64)]
#xy平面误差数据
err_x = 0
err_y = 0
#发送数据
uart_buf = bytearray([0x55,0xAA,0x00,0x00,0x00,0x00,0xAA])#串口三配置
uart = UART(3, 115200)
uart.init(115200, bits=8, parity=None, stop=1)sensor.reset()
sensor.set_pixformat(sensor.RGB565)#设置灰度信息
sensor.set_framesize(sensor.QQVGA)#设置图像大小
sensor.skip_frames(20)#相机自检几张图片
sensor.set_auto_whitebal(False)#关闭白平衡
clock = time.clock()#打开时钟
while(True):clock.tick()img = sensor.snapshot()#寻找blobblobs = img.find_blobs(black_threshold)if blobs:most_pixels = 0largest_blob = 0for i in range(len(blobs)):#目标区域找到的颜色块可能不止一**重点内容**个,找到最大的一个if blobs[i].pixels() > most_pixels:most_pixels = blobs[i].pixels()largest_blob = i#位置环用到的变量err_x = int(60 - blobs[largest_blob].cy())err_y = int(blobs[largest_blob].cx() - 80)img.draw_cross(blobs[largest_blob].cx(),blobs[largest_blob].cy())#调试使用img.draw_rectangle(blobs[largest_blob].rect())else:err_x = 0err_y = 0#数组中数据写入uart_buf = bytearray([0x55,err_x>>8,err_x,err_y>>8,err_y,0xAA])print(err_x,err_y)uart.write(uart_buf)

二、STM32控制端程序设计
既然我们用的是STM32模拟遥控器,那我们就要先初始化两个定时器来输出八路PWM波,电调的频率基本上都是50hz,刚刚把代码贴上来了,但是想了想大家都是有基础的,这些初始化肯定会的。
一个串口用来读取OPENMV的数据,一个串口用来读取超声波模块的高度。
两个定时器用来模拟50hz的PWM波。

恩 ,对,然后就没了,最后还需要个PID控制函数来对OPENMV传回的黑点坐标值进行PID运算,转化为PIX能识别的‘遥控器’控制量即可实现定点。
对于怎么知道模拟出来的PWM波对应的遥控器的哪个通道值,大家只有拿着遥控器一个一个对应调了,记得做好记录。

题目分析:

基础一:把飞机放在黑点上方,需要一键自动起飞到指定高度,我们采用的方法:
按键按下模式1后,先模拟遥控器对PIX解锁、然后开始起飞,油门逐渐增加,增加的同时当高度高于20cm就开启定点,当飞机高度到达指定高度后开启定高模式,因为PIX的气压计定高不是很准,所以我们人为加了定高的修正,高度大于目标值就拉低油门,低于目标值就拉高油门,定高的同时也在定点,然后开始计时,到达指定时间,大幅拉低油门,自动降落。
主函数

int main(void)
{ 	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2delay_init(168);  //初始化延时函数uart_init(115200);//初始化串口波特率为115200uart2_init(9600);uart3_init(115200);LED_Init();KEY_Init();IIC_Init();       //IIC初始化OLED_Init();OLED_Clear();TIM3_PWM_Init(20000-1,84-1);	//84M/84=1Mhz的计数频率,重装载值20000,所以PWM频率为 1M/20000=50hz.    TIM4_PWM_Init(20000-1,84-1);	//84M/84=1Mhz的计数频率,重装载值20000,所以PWM频率为 1M/20000=50hz. 	TIM2_Int_Init(10-1,8400-1);while(1){Fly_Mode = 0;OLED_Clear();while(!Fly_Mode){Fly_Mode=KEY_Scan();OLED_ShowNum(0, 2, Fly_Mode, 1, 16);OLED_ShowUnNum(0, 0, hight, 3, 16);}OLED_ShowNum(0, 2, Fly_Mode, 1, 16);LED = 0;delay_ms(200);LED = 1;switch (Fly_Mode){case 1:Take_off();Start_Fixed_high();while(1){					if(PID_flag == 1){PID_flag = 0;PositionPID();High_fix();}	SStart_flag = 1;if(S_flag == 1){S_flag = 0;i++;}if(i == 300){i = 0;SStart_flag = 0;Land_down();break;}}break;case 2:Take_off();Start_Fixed_high();while(1){					if(PID_flag == 1){PID_flag = 0;PositionPID();High_fix();}	SStart_flag = 1;//1s开始计时if(S_flag == 1){S_flag = 0;i++;}//计时盲飞if(i == 100){mang_flag = 1;}//忙飞结束if(i == 120){mang_flag = 0;	}//计时降落if(i == 200){i = 0;SStart_flag = 0;Land_down();break;}}break;case 3:break;case 4:break;case 5:break;default:Land_down();break;		}}
}

串口解析OPENMV数据函数

void Vision_datadeal(void)
{int tmp, tmp1, tmp2;USART_SendData(USART2, 0x55);  //向串口2发送数据PID_flag = 1;if(USART3_RX_BUF[0]==0x55 && USART3_RX_BUF[5]==0xAA){		/*接收视觉模块发来的信息*/if(USART3_Flage){	USART3_Flage=0;tmp=((int)USART2_RX_BUF[0]<<8) + USART2_RX_BUF[1];hight=tmp/10; //除以 1000 转化为单位 M{/*  Target_Roll */tmp1=((int16_t)USART3_RX_BUF[1]<<8) + USART3_RX_BUF[2];tmp1 = Median_filer1(tmp1);if(tmp1>=32768){tmp1 = tmp1-0xffff;}					else{tmp1 =tmp1;}pixX = tmp1;/*  Target_Pitch */tmp2=((int16_t)USART3_RX_BUF[3]<<8) + USART3_RX_BUF[4];tmp2 = Median_filer2(tmp2);if(tmp2>=32768){tmp2 = tmp2-0xffff;}else{tmp2 = tmp2;}pixY = tmp2;if(Fly_Mode == 2 && mang_flag == 1){if(pixY_last == 0 && pixY - pixY_last < -50){mang_flag = 0;}else{pixY = -23;}TIM_SetCompare1(TIM3,1540); 	//Pitch		CH1 PB4 TIM_SetCompare3(TIM3,1530);		//Roll		CH3 PB0 }pixY_last = pixY;}							}	}
}

PIX加锁函数

void lock(void)
{TIM_SetCompare1(TIM3,1500); 	//Pitch		CH1 PB4 TIM_SetCompare2(TIM3,1000);		//Throttle	CH2 PB5TIM_SetCompare3(TIM3,1500);		//Roll		CH3 PB0 TIM_SetCompare4(TIM3,1000);		//Yaw		CH4 PB1TIM_SetCompare1(TIM4,1000);		//			CH5 PD12TIM_SetCompare2(TIM4,1000);		//			CH6 PD13TIM_SetCompare3(TIM4,1000);		//			CH7 PD14TIM_SetCompare4(TIM4,1000);		//			CH8 PD15delay_ms(3000);
}

解锁函数

void Unlock(void)
{TIM_SetCompare1(TIM3,1500); 	//Pitch		CH1 PA6 TIM_SetCompare2(TIM3,1000);		//Throttle	CH2 PA7TIM_SetCompare3(TIM3,1500);		//Roll		CH3 PB0 TIM_SetCompare4(TIM3,2000);		//Yaw		CH4 PB1TIM_SetCompare1(TIM4,1000);		//			CH5 PB6TIM_SetCompare2(TIM4,1000);		//			CH6 PB7TIM_SetCompare3(TIM4,1000);		//			CH7 PB8TIM_SetCompare4(TIM4,1000);		//			CH8 PB9delay_ms(4000);TIM_SetCompare4(TIM3,1500);		//Yaw		CH4 PB1delay_ms(1000);TIM_SetCompare2(TIM3,1300);		//Throttle	CH2 PA7		delay_ms(500);TIM_SetCompare2(TIM3,1000);		//Throttle	CH2 PA7
}

起飞函数

void Take_off(void)
{int Throttle=1000,Throttle_Increase=25,Hight_Last;OLED_ShowString(0,4,"Start",16);delay_ms(3000);OLED_ShowString(0,4,"Unlock",16);Unlock();Hight_Last=hight;while (hight<25){TIM_SetCompare2(TIM3,Throttle);Throttle+=Throttle_Increase;if(Throttle>=1800)Throttle=1800;delay_ms(100);if (hight-Hight_Last>1){Throttle_Increase=0;Throttle-=10;}if(hight>25){PositionPID();		}Hight_Last=hight;TIM_SetCompare1(TIM3,1540); 	//Pitch		CH1 PB4 TIM_SetCompare3(TIM3,1530);		//Roll		CH3 PB0 }
//	TIM_SetCompare1(TIM3,1500); 	//Pitch		CH1 PB4 
//	TIM_SetCompare3(TIM3,1500);		//Roll		CH3 PB0 
}

开启定高模式函数

void Start_Fixed_high(void)
{OLED_ShowString(0,4,"Highfix",16);TIM_SetCompare1(TIM4,1500);		//			CH5 PD12delay_ms(5);TIM_SetCompare2(TIM3,1500);		//Throttle	CH2 PB5TIM_SetCompare2(TIM3,1300);delay_ms(15);TIM_SetCompare2(TIM3,1500);
}

降落函数

void Land_down(void)
{OLED_ShowString(0,4,"Land_down",16);int j = 0;while(j <= 200){j++;TIM_SetCompare2(TIM3,1280);		//Throttle	CH2 PB5delay_ms(20);PositionPID();}lock();
}

PID控制函数:

/*黑点悬停控制*/
void PositionPID(void)
{static float lastVxErro,lastVyErro;static float pidVx_pOut,pidVx_dOut,pidVx_iOut;static float pidVy_pOut,pidVy_dOut,pidVy_iOut;static float pidVx_value,pidVy_value;static unsigned char flag_Y,flag_X;/***************X轴PID参数**ROLL************/float Vxkp=0.086f;//float Vxki=0.0004f;//0.001f;float Vxkd=0.027f;//-0.000531;/***************Y轴PID参数*PITCH*************/float Vykp=0.086f;float Vyki=0.0004f;//0.001f;float Vykd= 0.024f;/*X轴位移速度调整*/float vxErro=(float)(0.0f-(-pixX*hight/100));float vxErroDelta=(vxErro-lastVxErro)/0.016f;lastVxErro=vxErro;/*X轴积分分离处理*/if(vxErro <= 50.0f&&vxErro >= -50.0f){flag_X = 0;}else{flag_X = 1;}pidVx_pOut=Vxkp * vxErro;pidVx_dOut=Vxkd * vxErroDelta;pidVx_iOut+=Vxki * vxErro;if(pidVx_iOut>2.5f)//1.5pidVx_iOut=2.5f;if(pidVx_iOut<-2.5f)pidVx_iOut=-2.5f;pidVx_value=pidVx_pOut+pidVx_dOut+flag_X*pidVx_iOut;if(pidVx_value>10)pidVx_value=10;if(pidVx_value<-10)pidVx_value=-10;pidVx_value*=22;/***************Y轴PID调节***************/	/*X轴位移速度调整*/float vyErro=(float)(0.0f-(-pixY*hight/100));float vyErroDelta=(vyErro-lastVyErro)/0.016f;lastVyErro=vyErro;/*Y轴积分分离处理*/if(vyErro <= 50.0f&&vyErro >= -50.0f){flag_Y = 0;}else{flag_Y = 1;}pidVy_pOut=Vykp * vyErro;pidVy_dOut=Vykd * vyErroDelta;pidVy_iOut+=Vyki * vyErro;/*Y轴积分限幅处理*/if(pidVy_iOut>2.5f)pidVy_iOut=2.5f;if(pidVy_iOut<-2.5f)pidVy_iOut=-2.5f;pidVy_value=pidVy_pOut+pidVy_dOut+flag_Y*pidVy_iOut;/*Y轴输出限幅处理*/if(pidVy_value>10)pidVy_value=10;if(pidVy_value<-10)pidVy_value=-10;pidVy_value*=22;/************PWM赋值***************/	TIM_SetCompare1(TIM3,1500+pidVx_value); 	//Pitch		CH1 PB4 TIM_SetCompare3(TIM3,1500+pidVy_value);		//Roll		CH3 PB0 			TIM_SetCompare4(TIM3,1505);					//Yaw		CH4 PB1}

基础二:这道题是检测两个物体间的空间距离,我们用的ESP8266来做的,它可以读出附近热点的信号值,但是这种做法精度极低。最后到比赛场地时才发现居然有人用超声波测距??而且居然没扣分,很神奇了。

基础三:对于这道题,和第一道题类似,但是需要往前飞一段时间,那么我们就可以先完成基础一,计时到了一定时间,人为的把OPENMV传回来的黑点值修改为定值,那么就可以往前飞了,但是这样掌握不好要往前飞多久才会到达小车的正上方,对于这种情况,解决办法一是去试那个时间,多试下会试出来的,二是判断坐标值的突变,也就是在往前飞的时候,OPENMV传回来的黑点的水平坐标是大致不会变的,而黑点的垂直方向的值会发生突变,一种情况是飞到小车和黑点中间丢失了黑点,这种情况是垂直坐标从最大值变成0再变为最小值。还有一种情况是飞机有点高,往前飞的时候小车也进入了摄像头视野,因为OPENMV找的是视野中面积最大的色块,那么OPENMV得到的黑点值就发生了突变,这时就可以开始取消人为给值,开始正常的定点计时到一定时间自动降落。

发挥一:这个题和基础三类似,修改一下第三阶段定点的时间就可以了。
发挥二:这个题和基础三类似,修改一下第三阶段定点的时间就可以了。

有问题的可以加Q97354734
可以提供能力之内的帮助
本人小店:

https://shop110563242.taobao.com/index.htm?spm=2013.1.w5002-16371582764.2.fo0MiW


http://chatgpt.dhexx.cn/article/U9r4oodx.shtml

相关文章

飞行控制器Pixhawk简介

作者&#xff1a;华清远见讲师 Pixhawk是一款由PX4开源项目设计并由3DR公司制造生产的高级自动驾驶仪系统。其前身是APM&#xff0c;由于APM的处理器已经接近满负荷&#xff0c;没有办法满足更复杂的运算处理&#xff0c;所以硬件厂商采用了目前最新标准的32位ARM处理器&#x…

pixhawk飞控解锁方法

1. pixhawk飞控解锁方法是&#xff1a;油门(throttl)拉到最低,偏航角&#xff08;yaw&#xff09;拉到最右边。

如何用开源飞控PIXHAWK进行二次开发?

著作权归作者所有。 商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处。 作者&#xff1a;我是肉包子 链接&#xff1a;http://www.zhihu.com/question/38874663/answer/84239995 来源&#xff1a;知乎 以下所描述的都是针对px4原生固件&#xff0c;此外&#xff0…

APM和PIX飞控日志分析入门贴

我们在飞行中&#xff0c;经常会碰到各种各样的问题&#xff0c;经常有模友很纳闷&#xff0c;为什么我的飞机会这样那样的问题&#xff0c;为什么我的飞机会炸机&#xff0c;各种问题得不到答案是一件非常不爽的问题&#xff0c;在APM和PIX飞控中&#xff0c;都有记录我们整个…

开源飞控APM与PIXHAWK

一 APM 官网地址&#xff1a;http://ardupilot.org/ APM&#xff08;ArduPilotMega&#xff09; 是在2007年由DIY无人机社区&#xff08;DIY Drones&#xff09;推出的飞控产品&#xff0c;是当今最为成熟的开源硬件项目。APM基于Arduino的开源平台&#xff0c;对多处硬件做出了…

Mission Planner初学者安装调试教程指南(APM或PIX飞控)1——下载与版本

目录 1.概述 2.下载与版本 3.关于 ArduPilot wquav 1.概述 Misson Planner简称MP&#xff0c;图标为黑底大写白色字体MP加一个绿色固定翼飞机&#xff0c;是可以调试APM或者PIX飞控的地面站软件&#xff0c;可以运行在windows系统和Linux系统&#xff08;非直接安装&#x…

Pix4飞控常见问题解决方法(二)

一、无法解锁&#xff08;黄灯闪烁&#xff09; 无法解锁的原因会有多种&#xff0c;请按照如下步骤进行检查&#xff1a; 1、初始设置是否全部完成 a、机架类型选择是否正确&#xff0c;或者你根本就没有选择&#xff1f; 注意&#xff0c;新版本的飞控固件在默认参数情况下&…

Pix4飞控硬件平台框架(一)

硬件平台简介 本文只是为了让大家简单入门为主&#xff0c;所以我选择的硬件学习平台是Pixhawk系列的mRoPixhawk&#xff0c;兼容原始版本Pixhawk1&#xff0c;基于Pixhawk-project FMUv3开源硬件设计&#xff0c;修正了将原始版本flash限制在1MB这个bug&#xff0c;需要深入学…

Mission Planner中级应用(APM或PIX飞控)3——APM飞控安装双GPS测试 APM双GPS

目录 1.未得到答案和技术指导 2.第一次实验失败 3.完全废掉了解锁功能 4.调整RX/TX位置 5.成功解锁 6.广阔室外的探索 山重水复疑无路&#xff0c;柳暗花明又一村 ——Mission Planner中级应用&#xff08;APM或PIX飞控&#xff09;3——APM飞控安装双GPS测试 APM双GPS。…

Mission Planner初学者安装调试教程指南(APM或PIX飞控)4——校准加速度计、指南针、遥控器、设置飞行模式

目录 1.加速度计校准。 2.指南针校准。 3.遥控器校准。 安装完固件后&#xff0c;无人机并不能马上解锁起飞&#xff0c;必须进行校准加速度计、指南针、遥控器&#xff0c;下面就逐一进行校准&#xff0c;该环境使用的是APM2.8、Mission Planner1.3.70地面站软件。 1.加速…

每天读一点儿APM(PIX)代码之三:飞行控制

本期话题以ArduPlane代码为例分析了Ardupilot飞控体系对飞行器的反馈控制过程,并在实例中添加了一个直接易用的固定翼起飞辅助模式,供大家参考。 姿态控制是飞控的核心功能,不论固定翼还是多旋翼,都需要维持飞行器本身的稳定。ArduPilot采用反馈修正的方式进行姿态控制,以…

PixHawk飞控 配置参数

PixHawk飞控 PixHawk是著名飞控厂商3DR推出的新一代独立、开源、高效的飞行控制器&#xff0c;前身为APM飞控&#xff0c;不仅提供了丰富的外设模块和可靠的飞行体验&#xff0c;有能力的爱好者还可在其基础上进行二次开发。第一次使用需要多方查阅资料&#xff0c;摸索前行&a…

Mission Planner初学者安装调试教程指南(APM或PIX飞控)7——多旋翼无人机APM(PIX)飞控ardupilot missionplanner扩展调参、基本调参(PID调参)

目录 1 APM(PIX)飞控ardupilot missionplanner扩展调参、基本调参默认值 2 Copter Home 3 调参各部分的解析示意图 4 在飞行中调roll和pitch&#xff08;以遥控输入第六通道调参为例&#xff09; https://ardupilot.org/copter/index.html P ID到底是个什么东西&#xff…

Web自动化测试怎么做呢?好!接下来我们就开始Web网页测试针对性的流程解析啦!!!

前言 测试行业现在70%是以手工测试为主&#xff0c;那么只有20%是自动化测试&#xff0c;剩下的10%是性能测试。 有人可能会说&#xff0c;我现在做手工&#xff0c;我为什么要学自动化呢&#xff1f;我去学性能更好性能的人更少&#xff1f; 其实&#xff0c;性能的要求比自动…

Web自动化测试流程:从入门到精通,帮你成为测试专家

B站首推&#xff01;2023最详细自动化测试合集&#xff0c;小白皆可掌握&#xff0c;让测试变得简单、快捷、可靠https://www.bilibili.com/video/BV1ua4y1V7Db 目录 摘要&#xff1a; 步骤一&#xff1a;选取测试工具 步骤二&#xff1a;编写测试用例 步骤三&#xff1a;编…

Web测试流程图

Web测试侧重流程图&#xff1a; 项目开发-测试双v模型&#xff1a; 常见问题&#xff1a; 1、给你项目&#xff0c;你会从哪方面着手测试&#xff1f; 【分析需求&#xff0c;明确测试任务&#xff0c;分析测试范围&#xff0c;制定测试计划和测试用例。】 2、冒烟测试过不…

web自动化测试流程的总结及关注点

目录 一、立项后测试需要拿到的文档 二、需求评审 三、用例编写&#xff08;同时根据开发计划编写测试计划&#xff09; 四、用例评审 五、测试执行 六、测试报告及操作手册 项目的测试流程大只包含的几个阶段&#xff1a;立项、需求评审、用例评审、测试执行、测试报告文…

Web网页测试全流程解析论Web自动化测试

1、功能测试 web网页测试中的功能测试&#xff0c;主要测试网页中的所有链接、数据库连接、用于在网页中提交或获取用户信息的表单、Cookie 测试等。 &#xff08;1&#xff09;查看所有链接&#xff1a; 测试从所有页面到被测特定域的传出链接。 测试所有内部链接。 测试链…

【2023最全教程】Web自动化测试怎么做?Web自动化测试的详细流程和步骤

一、什么是web自动化测试 自动化&#xff08;Automation&#xff09;是指机器设备、系统或过程&#xff08;生产、管理过程&#xff09;在没有人或较少人的直接参与下&#xff0c;按照人的要求&#xff0c;经过自动检测、信息处理、分析判断、操纵控制&#xff0c;实现预期的目…

web-自动化测试流程

1. 自动化测试流程 (1) 需求分析 (2) 挑选适合做自动化测试的功能 (3) 设计测试用例 (4) 搭建自动化测试环境 [可选] (5) 设计自动化测试项目的架构 [可选] (6) 编写代码 (7) 执行测试用例 (8) 生成测试报告并分析结果 2、自动化项目框架自动化框架 ① 顺序&#xf…