两轴舵机云台的一点实践
- 效果演示
- 硬件使用情况
- 定时器中断代码
- 计算机体系下的云台角代码
- 舵机控制代码
- 工程源码下载
简介:
为了学习姿态解算相关知识,最近做了一个作品,模仿炮塔跟随系统,用陀螺仪使两个舵机指向空间中的某一特定方向,实际上用欧拉角旋转矩阵法只完成了功能,然后针对舵机延迟问题做了一个微分控制。但由于欧拉角不能解算全姿态,实际能稳定的角度并不大,
将旋转矩阵换成四元数来表示之后解算结果不对,不知道是小弟哪里弄错了?东西很多纯属瞎扯,望大佬们轻喷。
效果演示
视频: 两轴舵机云台
![作品一览](https://img-blog.csdnimg.cn/20190731125519658.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzIxODk2OA==,size_16,color_FFFFFF,t_70)
硬件使用情况
陀螺仪:MPU6050 *1
舵机:MG996R *2
主控芯片:STM32F103C8T6 *1
定时器中断代码
这部分代码使用TIM2定时器中断提供100Hz的控制频率,并且针对舵机位置控制延迟的问题,对舵机位置做了一个微分比例补偿控制,提高了响应速度。这部分代码在 main.c 里面。
float pitch,roll,yaw;
float q0=1.0f,q1=0.0f,q2=0.0f,q3=0.0f;
float hy=0,hp=0;
float by,bp,br;
float bhy=0,bhp=0,bhr=0;
float Kd1=10.0;
float Kd2=10.0;
void TIM2_IRQHandler(void)
{
static int t=0;
u8 button;
float bhylast=0, bhplast=0;
float bhyincre=0, bhpincre=0;
float bhycomp = 0, bhrcomp = 0;
if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
{ TIM_ClearITPendingBit(TIM2, TIM_IT_Update );
bhylast=bhy, bhplast=bhp;
if(mpu_dmp_get_data(&roll,&pitch,&yaw)==0)
{
yaw=-yaw, pitch=-pitch, roll=-roll;
CalHeadDegree();
bhyincre = bhy - bhylast;
bhpincre = bhp - bhplast;
bhycomp = Kd1*bhyincre;
bhrcomp = Kd2*bhpincre;
HeadTurnToXY(bhy+bhycomp ,bhp+bhrcomp);
t++;
if(t>=10)t=0, LED0=!LED0;
}
}
}
计算机体系下的云台角代码
这个函数将云台在参考坐标系内的指向向量旋转到机体系去,并且化为机体系下的云台角,注释掉的部分是用四元数表示的旋转矩阵,此部分放在 servo.c 里面。
void CalHeadDegree(void)
{
const float DEG2RAD = 0.0174533;
const float RAD2DEG = 57.29578 ;
float xn=cos(hy*DEG2RAD)*cos(hp*DEG2RAD);
float yn=sin(hy*DEG2RAD)*cos(hp*DEG2RAD);
float zn=sin(hp*DEG2RAD);
float xb,yb,zb,normalizer;
float cby,sby,cbp,sbp,cbr,sbr;
normalizer = invSqrt(xn*xn + yn*yn +zn*zn);
xn *= normalizer;
yn *= normalizer;
zn *= normalizer;
bp=pitch,br=roll,by=yaw;
cby=cos(by*DEG2RAD),sby=sin(by*DEG2RAD);
cbp=cos(bp*DEG2RAD),sbp=sin(bp*DEG2RAD);
cbr=cos(br*DEG2RAD),sbr=sin(br*DEG2RAD);
xb = cbp*cby*xn + cbp*sby*yn -sbp*zn;
yb = (sbr*sbp*cby - cbr*sby)*xn + (sbr*sbp*sby + cbr*cby)*yn + sbr*cbp*zn;
zb = (cbr*sbp*cby + sbr*sby)*xn + (cbr*sbp*sby - sbr*cby)*yn + cbr*cbp*zn;
normalizer = invSqrt(xb*xb + yb*yb +zb*zb);
xb *= normalizer;
yb *= normalizer;
zb *= normalizer;
bhp = asin(zb)*RAD2DEG;
bhy = acos( xb*invSqrt(xb*xb+yb*yb) )*RAD2DEG;
bhp = -bhp;
if(yb<0) bhy=-bhy;
}
舵机控制代码
以下函数用来控制舵机,使它们指向机体系下的一个方向 (hby,hbp)
水平角hby:-90°~90° 俯仰角hbp: 0°~180° ,放在 servo.c 里面。
void Servo1RunToDegree(float degree)
{
float pwm;
if(degree>=-120 && degree<=120){
pwm = 1.0394*degree + 1848.55;
TIM_SetCompare2(TIM3,pwm);
}
}
void Servo2RunToDegree(float degree)
{
float pwm;
if(degree>=-30 && degree<=210){
pwm = -1.0306*degree + 1939.10;
TIM_SetCompare1(TIM4,pwm);
}
}
void HeadTurnToXY(float x,float y)
{
Servo1RunToDegree(x);
Servo2RunToDegree(y);
}
工程源码下载
链接:https://pan.baidu.com/s/1f9QcTQm-TCXQcAJTKidhYg
提取码:rggw
参考资料: 四元数姿态解算 (来源网络,侵权请联系我删除,感谢作者整理)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)