标题:
STM32F407飞控源码 超声波定高与循迹功能
[打印本页]
作者:
jljlyzp
时间:
2018-4-13 10:58
标题:
STM32F407飞控源码 超声波定高与循迹功能
STM32F407单片机的超声波定高循迹飞控
0.jpg
(38.66 KB, 下载次数: 46)
下载附件
2018-4-13 16:00 上传
APB1 42m
APB2 84m
TIMx clk = APBx *2
中断优先级:
第0组:所有4位用于指定响应优先级;
第1组:最高1位用于指定抢占式优先级,最低3位用于指定响应优先级;
第2组:最高2位用于指定抢占式优先级,最低2位用于指定响应优先级;
第3组:最高3位用于指定抢占式优先级,最低1位用于指定响应优先级;
第4组:所有4位用于指定抢占式优先级。
|先抢占,再响应|
1)如果指定的抢占式优先级别或响应优先级别超出了选定的优先级分组所限定的范围,将可能得到意想不到的结果;
2)抢占式优先级别相同的中断源之间没有嵌套关系;
3)如果某个中断源被指定为某个抢占式优先级别,又没有其它中断源处于同一个抢占式优先级别,则可以为这个中断源指定任意有效的响应优先级别。
事件记录,beta0.4开始。
2015.5.18
beta 0.4 修复各种bug。
2015.5.19
beta 0.5 完善摇杆识别。
beta 0.6 pwm_in优化
beta 0.7 修复bug,优化rc,添加mapping
beta 0.9 起飞成功
beta 1.0 修复控制周期bug
beta 1.1 添加部分注释
beta 1.2 优化整定参数,修改bug
beta 1.3 完成flash存储,上位机HID通信
beta 1.35 增加磁力计纠正航向
beta 1.36 增加磁力计校准时灯管提示
beta 1.37 增加mpu6050,ak8975,ms5611自检,未通过的LED状态分别是:间隔连续闪烁1次;间隔连续闪烁2次;间隔连续闪烁3次
beta 1.37.1 增加滑动窗口平均滤波函数,增加ks103超声波读取,该版备份。
beta 1.37.2 添加user数据,上位机显示波形,串口超声波改发送中断。
beta 1.37.3 添加部分注释,修改部分变量名,增加ano_private.lib。
beta 1.38 添加超声波控制代码(注意!暂未测试),修改磁力计纠正算法(重要更新),消除磁力计纠正YAW时对姿态的干扰。删除ano_pribate.lib
beta 1.39 修复上一版数据传输一个小bug,添加环形缓存。
beta 1.39.1 超声波直接控制高度,还有问题。
beta 1.40 超声波定高ok,暂没优化参数,没加上位机调参。可改惯导竖直方向速率控制。
beta 1.40.1
#define CTRL_HEIGHT 1 //0失能,1使能
#define HEIGHT_MODE 1 //0,无,1惯性控制高度,2气压计控制(空),3超声波控制高度
beta 1.41 修复磁力计纠正的一个bug。
beta 1.42 us100超声波定高稳定
beta 1.43
1.模式0(呼吸白,解锁绿长),普通,油门直接输出。模式1(呼吸浅绿,解锁浅绿长),垂直速率控制(下一步改为气压定高)。模式2(呼吸紫,解锁紫长),超声波定高。
2.飞行时,只能向模式0切换,其他切换无效。
3.只有插上超声波,模式3才有效。(这个未优化,比如临时拔下超声波,也能进入该模式。)
beta 1.44
修复定高控制中积分的bug,优化超声波定高,优化高度设定值调节速度。增加超声波最大高度,可达到到1.5米比较稳定(高度越低越稳定)。
beta 1.46
气压计定高,测试版(无高度静差修正)。
beta 1.47
气压计定高,测试版(无高度静差修正)。改进磁力计纠正算法,解决磁力计纠正时对姿态的干扰,修正磁力计纠正中180度的一个错误。
beta 1.48
修复气压计速率的一个bug,并调整可控制的速率。
beta 1.48.1
注释掉while(1);
beta 1.49 电赛版本,完善通信协议中串口接收通道数据部分。
beta 1.49.2 修改气压计定高速率环积分部分,优化定高效果。
beta 1.49.3 滤波算法测试。
beta 1.50 修改磁力计纠正方法
beta 1.50.2 增加罗盘倾斜纠正,修复数据传输一个bug。
beta 1.51 修改气压计融合,定高控制等几处小bug
beta 1.52 修改超声波定高一个小bug
beta 1.6 细节优化&新参数
beta 1.6.2 修正罗盘原始数据的一个错误。
beta 1.6.2_fix 上版漏掉一句代码,导致解锁后yaw混乱,I'm sorry。。。
beta 1.6.3 新融合策略,解决加速度零点漂移(水平姿态)。
STM32F407单片机源程序如下:
/****************************************************************
@本程序只供学习使用,未经作者许可,不得用于其它任何用途
+编者:普哥
+描述:飞控核心控制程序(PID控制)
+编写日期:2017/3/10
+版权所有,盗版必纠。
****************************************************************/
#include "ctrl.h"
#include "height_ctrl.h"
#include "search.h"
ctrl_t ctrl_1;//内环,角速度控制结构体
ctrl_t ctrl_2;//外环,角度(姿态)控制结构体
/*-----------------------------------------------
+实现功能:恢复默认控制幅度
-------------------------------------------------*/
void Ctrl_Para_Init() //设置默认参数
{
/* 微分控制幅度*/
ctrl_1.PID[PIDROLL].kdamp = 1;
ctrl_1.PID[PIDPITCH].kdamp = 1;
ctrl_1.PID[PIDYAW].kdamp = 1;
/* 角速度的偏差权重比例系数*/
ctrl_1.FB = 0.20; //外 0<fb<1
}
xyz_f_t except_A = {0,0,0};//遥控控制期望姿态角度
xyz_f_t ctrl_angle_offset = {0,0,0};//期望姿态角度偏移
xyz_f_t compensation;
/*----------------------------------------------------------
+ 实现功能:姿态PID控制角速度 由任务调度调用周期5ms
+ 调用参数:两次调用间隔
----------------------------------------------------------*/
void CTRL_2(float T) //外环 角度控制
{
/* 期望角度 遥控器控制量中心死区30 单位 微秒*/
except_A.x = MAX_CTRL_ANGLE *( my_deathzoom( ( CH_filter[ROL]) ,30 )/500.0f );
except_A.y = MAX_CTRL_ANGLE *( my_deathzoom( (-CH_filter[PIT]) ,30 )/500.0f );
if( Thr_Low == 0 )//遥控器控制量的油门拉起
{
/* 期望航向姿态由遥控器航向控制积分*/
except_A.z += (s16)( MAX_CTRL_YAW_SPEED *( my_deathzoom_2( (CH_filter[YAW]) ,40 )/500.0f ) ) *T ;
}
else //遥控器控制量的油门低
{
except_A.z += 1 *3.14 *T *( Yaw - except_A.z );//期望航向姿态为当前姿态
}
except_A.z = To_180_degrees(except_A.z);//角度范围控制在+-180角度
/* 得到角度误差 为姿态自稳 与 遥控器控制量 之和 */
ctrl_2.err.x = To_180_degrees( ctrl_angle_offset.x + except_A.x - Roll );
ctrl_2.err.y = To_180_degrees( ctrl_angle_offset.y + except_A.y - Pitch );
ctrl_2.err.z = To_180_degrees( ctrl_angle_offset.z + except_A.z - Yaw );
/* 计算角度误差权重 */
ctrl_2.err_weight.x = ABS(ctrl_2.err.x)/ANGLE_TO_MAX_AS;
ctrl_2.err_weight.y = ABS(ctrl_2.err.y)/ANGLE_TO_MAX_AS;
ctrl_2.err_weight.z = ABS(ctrl_2.err.z)/ANGLE_TO_MAX_AS;
/* 角度误差微分(跟随误差曲线变化)*/
ctrl_2.err_d.x = 10 *ctrl_2.PID[PIDROLL].kd *(ctrl_2.err.x - ctrl_2.err_old.x) *( 0.005f/T ) *( 0.65f + 0.35f *ctrl_2.err_weight.x );
ctrl_2.err_d.y = 10 *ctrl_2.PID[PIDPITCH].kd *(ctrl_2.err.y - ctrl_2.err_old.y) *( 0.005f/T ) *( 0.65f + 0.35f *ctrl_2.err_weight.y );
ctrl_2.err_d.z = 10 *ctrl_2.PID[PIDYAW].kd *(ctrl_2.err.z - ctrl_2.err_old.z) *( 0.005f/T ) *( 0.65f + 0.35f *ctrl_2.err_weight.z );
/* 角度误差积分 */
ctrl_2.err_i.x += ctrl_2.PID[PIDROLL].ki *ctrl_2.err.x *T;
ctrl_2.err_i.y += ctrl_2.PID[PIDPITCH].ki *ctrl_2.err.y *T;
ctrl_2.err_i.z += ctrl_2.PID[PIDYAW].ki *ctrl_2.err.z *T;
/* 角度误差积分分离 */
ctrl_2.eliminate_I.x = Thr_Weight *CTRL_2_INT_LIMIT;
ctrl_2.eliminate_I.y = Thr_Weight *CTRL_2_INT_LIMIT;
ctrl_2.eliminate_I.z = Thr_Weight *CTRL_2_INT_LIMIT;
/* 角度误差积分限幅 */
ctrl_2.err_i.x = LIMIT( ctrl_2.err_i.x, -ctrl_2.eliminate_I.x,ctrl_2.eliminate_I.x );
ctrl_2.err_i.y = LIMIT( ctrl_2.err_i.y, -ctrl_2.eliminate_I.y,ctrl_2.eliminate_I.y );
ctrl_2.err_i.z = LIMIT( ctrl_2.err_i.z, -ctrl_2.eliminate_I.z,ctrl_2.eliminate_I.z );
/* 对用于计算比例项输出的角度误差限幅 */
ctrl_2.err.x = LIMIT( ctrl_2.err.x, -90, 90 );
ctrl_2.err.y = LIMIT( ctrl_2.err.y, -90, 90 );
ctrl_2.err.z = LIMIT( ctrl_2.err.z, -90, 90 );
/* 角度PID输出 */
ctrl_2.out.x = ctrl_2.PID[PIDROLL].kp *( ctrl_2.err.x + ctrl_2.err_d.x + ctrl_2.err_i.x ); //rol
ctrl_2.out.y = ctrl_2.PID[PIDPITCH].kp *( ctrl_2.err.y + ctrl_2.err_d.y + ctrl_2.err_i.y ); //pit
ctrl_2.out.z = ctrl_2.PID[PIDYAW].kp *( ctrl_2.err.z + ctrl_2.err_d.z + ctrl_2.err_i.z );
/* 记录历史数据 */
ctrl_2.err_old.x = ctrl_2.err.x;
ctrl_2.err_old.y = ctrl_2.err.y;
ctrl_2.err_old.z = ctrl_2.err.z;
}
xyz_f_t except_AS;//期望角速度
float g_old[ITEMS];//记录的陀螺仪数据
/*----------------------------------------------------------
+ 实现功能:角速度电机输出量 由任务调度调用周期2ms
+ 调用参数:两次调用间隔
----------------------------------------------------------*/
void CTRL_1(float T) //x roll,y pitch,z yaw内环 角速度控制
{
xyz_f_t EXP_LPF_TMP;//期望角速度
/* 给期望(目标)角速度 */
EXP_LPF_TMP.x = MAX_CTRL_ASPEED *(ctrl_2.out.x/ANGLE_TO_MAX_AS);
EXP_LPF_TMP.y = MAX_CTRL_ASPEED *(ctrl_2.out.y/ANGLE_TO_MAX_AS);
EXP_LPF_TMP.z = MAX_CTRL_ASPEED *(ctrl_2.out.z/ANGLE_TO_MAX_AS);
/* 期望角速度*/
except_AS.x = EXP_LPF_TMP.x;
except_AS.y = EXP_LPF_TMP.y;
except_AS.z = EXP_LPF_TMP.z;
/* 期望角速度限幅 */
except_AS.x = LIMIT(except_AS.x, -MAX_CTRL_ASPEED,MAX_CTRL_ASPEED ); //-300到300之间
except_AS.y = LIMIT(except_AS.y, -MAX_CTRL_ASPEED,MAX_CTRL_ASPEED );
except_AS.z = LIMIT(except_AS.z, -MAX_CTRL_ASPEED,MAX_CTRL_ASPEED );
/* 角速度直接微分(角加速度),负反馈可形成角速度的阻尼(阻碍角速度的变化)*/
ctrl_1.damp.x = ( mpu6050.Gyro_deg.x - g_old[A_X]) *( 0.002f/T );
ctrl_1.damp.y = (-mpu6050.Gyro_deg.y - g_old[A_Y]) *( 0.002f/T );
ctrl_1.damp.z = (-mpu6050.Gyro_deg.z - g_old[A_Z]) *( 0.002f/T );
/* 角速度误差 */
ctrl_1.err.x = ( except_AS.x - mpu6050.Gyro_deg.x ) *(300.0f/MAX_CTRL_ASPEED);
ctrl_1.err.y = ( except_AS.y + mpu6050.Gyro_deg.y ) *(300.0f/MAX_CTRL_ASPEED); //-y
ctrl_1.err.z = ( except_AS.z + mpu6050.Gyro_deg.z ) *(300.0f/MAX_CTRL_ASPEED); //-z
/* 角速度误差权重 */
ctrl_1.err_weight.x = ABS(ctrl_1.err.x)/MAX_CTRL_ASPEED;
ctrl_1.err_weight.y = ABS(ctrl_1.err.y)/MAX_CTRL_ASPEED;
ctrl_1.err_weight.z = ABS(ctrl_1.err.z)/MAX_CTRL_YAW_SPEED;
/* 角速度微分 */
ctrl_1.err_d.x = ( ctrl_1.PID[PIDROLL].kd *( -10 *ctrl_1.damp.x) *( 0.002f/T ) );
ctrl_1.err_d.y = ( ctrl_1.PID[PIDPITCH].kd *( -10 *ctrl_1.damp.y) *( 0.002f/T ) );
ctrl_1.err_d.z = ( ctrl_1.PID[PIDYAW].kd *( -10 *ctrl_1.damp.z) *( 0.002f/T ) );
/* 角速度误差积分 */
ctrl_1.err_i.x += ctrl_1.PID[PIDROLL].ki *(ctrl_1.err.x - ctrl_1.damp.x) *T;
ctrl_1.err_i.y += ctrl_1.PID[PIDPITCH].ki *(ctrl_1.err.y - ctrl_1.damp.y) *T;
ctrl_1.err_i.z += ctrl_1.PID[PIDYAW].ki *(ctrl_1.err.z - ctrl_1.damp.z) *T;
/* 角速度误差积分分离 */
ctrl_1.eliminate_I.x = Thr_Weight *CTRL_1_INT_LIMIT ;
ctrl_1.eliminate_I.y = Thr_Weight *CTRL_1_INT_LIMIT ;
ctrl_1.eliminate_I.z = Thr_Weight *CTRL_1_INT_LIMIT ;
/* 角速度误差积分限幅 */
ctrl_1.err_i.x = LIMIT( ctrl_1.err_i.x, -ctrl_1.eliminate_I.x,ctrl_1.eliminate_I.x );
ctrl_1.err_i.y = LIMIT( ctrl_1.err_i.y, -ctrl_1.eliminate_I.y,ctrl_1.eliminate_I.y );
ctrl_1.err_i.z = LIMIT( ctrl_1.err_i.z, -ctrl_1.eliminate_I.z,ctrl_1.eliminate_I.z );
/* 角速度PID输出 */
ctrl_1.out.x = 3 *( ctrl_1.FB *LIMIT((0.45f + 0.55f*ctrl_2.err_weight.x),0,1)*except_AS.x + ( 1 - ctrl_1.FB ) *ctrl_1.PID[PIDROLL].kp *( ctrl_1.err.x + ctrl_1.err_d.x + ctrl_1.err_i.x ) );
ctrl_1.out.y = 3 *( ctrl_1.FB *LIMIT((0.45f + 0.55f*ctrl_2.err_weight.y),0,1)*except_AS.y + ( 1 - ctrl_1.FB ) *ctrl_1.PID[PIDPITCH].kp *( ctrl_1.err.y + ctrl_1.err_d.y + ctrl_1.err_i.y ) );
ctrl_1.out.z = 3 *( ctrl_1.FB *LIMIT((0.45f + 0.55f*ctrl_2.err_weight.z),0,1)*except_AS.z + ( 1 - ctrl_1.FB ) *ctrl_1.PID[PIDYAW].kp *( ctrl_1.err.z + ctrl_1.err_d.z + ctrl_1.err_i.z ) );
Thr_Ctrl(T);// 电机油门量控制
All_Out(ctrl_1.out.x,ctrl_1.out.y,ctrl_1.out.z);//角速度控制量转换到电机转速的输出量
/* 记录角速度误差积分*/
ctrl_1.err_old.x = ctrl_1.err.x;
ctrl_1.err_old.y = ctrl_1.err.y;
ctrl_1.err_old.z = ctrl_1.err.z;
/* 记录角速度数据*/
g_old[A_X] = mpu6050.Gyro_deg.x ;
g_old[A_Y] = -mpu6050.Gyro_deg.y ;
g_old[A_Z] = -mpu6050.Gyro_deg.z ;
}
float thr_value;//油门赋值
u8 Thr_Low;//低油门信号判断
float Thr_Weight; //滤波后油门数据
/*----------------------------------------------------------
+ 实现功能:油门信号控制
+ 调用参数:两次调用间隔
----------------------------------------------------------*/
void Thr_Ctrl(float T)
{
static float thr;//油门值
static float Thr_tmp;//滤波后的油门值
thr = 500 + CH_filter[THR]; //油门值范围 0 ~ 1000
Thr_tmp += 10 *3.14f *T *(thr/400.0f - Thr_tmp); //低通滤玻,油门数据积分滤波
Thr_Weight = LIMIT(Thr_tmp,0,1);// 滤波后油门数据限幅,后边多处分离数据会用到这个值
if( thr < 100 )//低油门信号判断
{
Thr_Low = 1;
}
else
{
Thr_Low = 0;
}
/* 允许高度控制*/
#if(CTRL_HEIGHT)
Height_Ctrl(T,thr);//油门控制高度
thr_value = Thr_Weight *height_ctrl_out; //油门赋值
#else
thr_value = thr; //实际使用值
#endif
thr_value = LIMIT(thr_value,0,10 *MAX_THR *MAX_PWM/100);//油门限幅
}
float motor[MAXMOTORS];//电机数量
float posture_value[MAXMOTORS];//姿态作用于电机位置的控制量
float curve[MAXMOTORS];//姿态对电机的实际控制量
/*----------------------------------------------------------
+ 实现功能:角速度控制量 转换到电机转速的输出量
+ 调用参数:角速度控制量
----------------------------------------------------------*/
void All_Out(float out_roll,float out_pitch,float out_yaw)
{
s16 motor_out[MAXMOTORS];
u8 i;//循环计数变量
float posture_value[MAXMOTORS];//姿态作用于电机位置的控制量
float curve[MAXMOTORS];//姿态对电机的实际控制量
float Line_Out=0,Line_LR_Out=0;//寻线PID输出
float Point_X=0,Point_Y=0;//定点PID输出
/* 允许循迹控制*/
#if(CTRL_SEARCH)
Line_Out = Line_ctrl_out; //循迹偏移PID输出
Line_LR_Out = Line_LR_ctrl_out; //循迹偏移PID输出
Point_X = Point_X_ctrl_out; //左右定点PID输出
Point_Y = Point_Y_ctrl_out; //前后定点PID输出
#else
Line_Out = 0
Line_LR_Out = 0
Point_X = 0
Point_Y = 0
#endif
/* 航向的角速度控制量限幅 防止动力不足*/
out_yaw = LIMIT( out_yaw , -5*MAX_THR ,5*MAX_THR ); //50%
/*默认是四旋翼X模式,CCW是从上方向下看逆时针选择,CW与CCW刚好相反,
注意前方偏右是连接1号电机电调,逆时针顺序依次是2开始
CW2 1CCW
\ /
/ \
CCW3 4CW */
posture_value[0] = - out_roll + out_pitch + out_yaw - Line_Out -Point_X -Point_Y -Line_LR_Out ;//右前方,CCW
posture_value[1] = + out_roll + out_pitch - out_yaw + Line_Out +Point_X -Point_Y -Line_LR_Out ;//左前方,CW
posture_value[2] = + out_roll - out_pitch + out_yaw + Line_Out +Point_X +Point_Y +Line_LR_Out;//左后方,CCW
posture_value[3] = - out_roll - out_pitch - out_yaw - Line_Out -Point_X +Point_Y +Line_LR_Out ;//右后方,CW
for(i=0;i<4;i++)//作用于电机位置的控制量
{
posture_value[i] = LIMIT(posture_value[i], -1000,1000 );//姿态作用于电机位置的控制量限幅
}
/* 姿态对电机的实际控制量*/
curve[0] = (0.55f + 0.45f *ABS(posture_value[0])/1000.0f) *posture_value[0] ;
curve[1] = (0.55f + 0.45f *ABS(posture_value[1])/1000.0f) *posture_value[1] ;
curve[2] = (0.55f + 0.45f *ABS(posture_value[2])/1000.0f) *posture_value[2] ;
curve[3] = (0.55f + 0.45f *ABS(posture_value[3])/1000.0f) *posture_value[3] ;
/* 单个电机的总控制量*/
motor[0] = thr_value + Thr_Weight *curve[0] ;
motor[1] = thr_value + Thr_Weight *curve[1] ;
motor[2] = thr_value + Thr_Weight *curve[2] ;
motor[3] = thr_value + Thr_Weight *curve[3] ;
/* 是否解锁 */
if(fly_ready)//已经解锁
{
if( !Thr_Low ) //遥控器的控制量油门拉起
{
for(i=0;i<4;i++)
{
/* 保证大于在电机最小起转转速*/
motor[i] = LIMIT(motor[i], (10 *READY_SPEED),(10*MAX_PWM) );
}
}
else //遥控器控制量的油门低
{
for(i=0;i<4;i++)
{
motor[i] = LIMIT(motor[i], 0,(10*MAX_PWM) );
}
}
}
else//未解锁
{
for(i=0;i<4;i++)//电机停转
{
motor[i] = 0;
}
}
/* int16到float数据类型转换*/
……………………
…………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
F407_FC_ANO - 超声波定高_循迹.rar
(2.15 MB, 下载次数: 108)
2018-4-13 16:02 上传
点击文件名下载附件
下载积分: 黑币 -5
作者:
plyl
时间:
2018-5-16 16:16
收藏一波,楼主666
作者:
阿斯顿马丁
时间:
2018-6-24 20:01
学习!!!!!!!!!!!!!1
作者:
wuxishun
时间:
2018-6-25 06:13
有电路原理图吗?
作者:
丿维灬纳
时间:
2019-4-1 16:08
不是寻迹的
作者:
1320081644
时间:
2019-5-20 11:19
楼主,这个上位机软件能分享下不?
作者:
810780579
时间:
2019-8-7 08:47
来学习下,需要资料
作者:
happynocn
时间:
2019-8-7 09:03
谢谢分享,下载收藏了。
作者:
zhukm
时间:
2019-12-27 10:53
谢谢分享,下载收藏
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1