加入星计划,您可以享受以下权益:

  • 创作内容快速变现
  • 行业影响力扩散
  • 作品版权保护
  • 300W+ 专业用户
  • 1.5W+ 优质创作者
  • 5000+ 长期合作伙伴
立即加入

开源一个自己做的小四旋翼工程,会有相关讲解

2016/08/24
35
服务支持:
技术交流群

完成交易后在“购买成功”页面扫码入群,即可与技术大咖们分享疑惑和经验、收获成长和认同、领取优惠和红包等。

虚拟商品不可退

当前内容为数字版权作品,购买后不支持退换且无法转移使用。

加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论
放大
方块图(2)
  • 方案介绍
  • 相关文件
  • 相关推荐
  • 电子产业图谱
申请入驻 产业图谱

1.

float q0q0 = q0*q0;

float q0q1 = q0*q1;

float q0q2 = q0*q2;

// float q0q3 = q0*q3;

float q1q1 = q1*q1;

// float q1q2 = q1*q2;

float q1q3 = q1*q3;

float q2q2 = q2*q2;

float q2q3 = q2*q3;

float q3q3 = q3*q3;

这段程序就是为了把需要用到的姿态矩阵的元素求出来给出的。

2.

vx = 2*(q1q3 - q0q2); /

vy = 2*(q0q1 + q2q3);

vz = q0q0 - q1q1 - q2q2 + q3q3 ;

可以看到vx,vy,vz为CRb的最后一列的三项,四元数矩阵带入(1)式得vx,vy,vz分别是axB,ayB,azB每一项g前的系数。且静止情况下vx,vy,vz组成向量模长基本可以认为为1.

3.

norm = sqrt(ax*ax + ay*ay + az*az); //acc数据归一化

ax = ax /norm;

ay = ay / norm;

az = az / norm;

以上已说,由四元数倒推回去的加速度,向量模长为1,为了比较误差进行归1化,算的由加计得出的向量。

4.

ex = (ay*vz - az*vy) ;

ey = (az*vx - ax*vz) ;

ez = (ax*vy - ay*vx) ;

接着可以通过叉乘(向量外积)计算误差

5.

exInt = exInt + ex * Ki;

eyInt = eyInt + ey * Ki;

ezInt = ezInt + ez * Ki;

对误差进行积分

6.

gx = gx + Kp*ex + exInt;

gy = gy + Kp*ey + eyInt;

gz = gz + Kp*ez + ezInt;

进行pi滤波,其实就是互补滤波

7.

q0 = q0 + (-q1*gx - q2*gy - q3*gz)*halfT;

q1 = q1 + (q0*gx + q2*gz - q3*gy)*halfT;

q2 = q2 + (q0*gy - q1*gz + q3*gx)*halfT;

q3 = q3 + (q0*gz + q1*gy - q2*gx)*halfT;

龙格库塔法。。。就是方程的数值解法。。近似解。。一阶解法

0736fac7228d4220f912874ee8cee5e5_21.png (0 Bytes, 下载次数: 0)

下载附件

2010-12-14 22:54 上传

这个跟四元数的微分方程对应有兴趣的看看书。。。。

8.

norm = sqrt(q0*q0 + q1*q1 + q2*q2 + q3*q3);

q0 = q0 / norm;

q1 = q1 / norm;

q2 = q2 / norm;

q3 = q3 / norm;

对四元数进行规范化,即化为模长为1 ,因为只有规范化的四元数才能表示刚体旋转。

9.

Q_ANGLE.Y = asin(-2 * q1 * q3 + 2 * q0* q2)* 57.3; // pitch

Q_ANGLE.X = atan2(2 * q2 * q3 + 2 * q0 * q1, -2 * q1 * q1 - 2 * q2* q2 + 1)* 57.3; // roll

仍旧一一对应关系发现2(q1q3 -q0q2)刚好跟欧拉角对应,由此利用自带库函数即可求得俯仰角,横滚角类似,偏航角由于没有罗盘进行校正求没有意义,控制中采用采用PD控制。

补充,由于陀螺仪会有零点漂移开始一定要进行补偿。这段是在mpu6050.c中程序,对直流偏执进行了补偿。

MPU6050_ACC_LAST.X=((((int16_t)mpu6050_buffer[0]) << 8) | mpu6050_buffer[1]) - ACC_OFFSET.X;

MPU6050_ACC_LAST.Y=((((int16_t)mpu6050_buffer[2]) << 8) | mpu6050_buffer[3]) - ACC_OFFSET.Y;

MPU6050_ACC_LAST.Z=((((int16_t)mpu6050_buffer[4]) << 8) | mpu6050_buffer[5]) - ACC_OFFSET.Z;

MPU6050_GYRO_LAST.X=((((int16_t)mpu6050_buffer[8]) << 8) | mpu6050_buffer[9]) - GYRO_OFFSET.X;

MPU6050_GYRO_LAST.Y=((((int16_t)mpu6050_buffer[10]) << 8) | mpu6050_buffer[11]) - GYRO_OFFSET.Y;

MPU6050_GYRO_LAST.Z=((((int16_t)mpu6050_buffer[12]) << 8) | mpu6050_buffer[13]) - GYRO_OFFSET.Z;

这里还要说一点,这里加速计的数据用的是滑动平均值滤波法,一定要有这个。。不然由于机械振动造成的影响非常大。。。

void repare_Data(void)

{

static uint8_t filter_cnt=0;

int32_t temp1=0,temp2=0,temp3=0;

uint8_t i;

MPU6050_Read();

MPU6050_Dataanl();

ACC_X_BUF[filter_cnt] = MPU6050_ACC_LAST.X;

ACC_Y_BUF[filter_cnt] = MPU6050_ACC_LAST.Y;

ACC_Z_BUF[filter_cnt] = MPU6050_ACC_LAST.Z;

for(i=0;i<FILTER_NUM;i++)

{

temp1 += ACC_X_BUF;

temp2 += ACC_Y_BUF;

temp3 += ACC_Z_BUF;

}

选择716电机,720的转速跟716的差不多,注意电机孔直径一定要大一点。。不然塞不进去。。然后补充一下MPU6050的摆放位置没有关系。。同一坐标系下测的的加速度角速度都是没有关系的。。。

关于电源还有QFN的芯片。。。注意这个其实很好焊,用烙铁沾点锡加点焊锡膏在对准的引脚上拖焊就行。。可以拿个灯照着看反光比较容易对准。

关于软件最关建的说说。。只有姿态解算部分。。PID部分我的算法还得改。。。。这个网上有开源的就是串机PID。。。额。。本人菜鸟。。还没看懂。。大二还没学自控。。回去会看的。。。注意这里MPU最好用硬件IIc,因为小四轴的姿态更新频率是1000HZ比较快,这里的IIC只是一个器件。。目前还没出什么问题。
这里有一部分是我之前写的总结

(1)欧拉角法静止状态,或者总加速度只是稍微大于g时,由加计算出的值比较准确。

使用欧拉角表示姿态,令Φ,θ和Φ代表ZYX 欧拉角,分别称为偏航角、俯仰角和横滚角 。 载体坐标系下的 加 速 度(axB,ayB,azB)和参考坐标系下的加速度(axN, ayN, azN)之间的关系可表示为(1)。其中 c 和 s 分别代表 cos 和 sin。axB,ayB,azB就是mpu读出来的三个值。

这个矩阵就是三个旋转矩阵相乘得到的,因为矩阵的乘法可以表示旋转。

这是程序

void IMUupdate(float gx, float gy, float gz, float ax, float ay, float az)

{

float norm;

// float hx, hy, hz, bx, bz;

float vx, vy, vz;// wx, wy, wz;

float ex, ey, ez;

// 先把这些用得到的值算好

float q0q0 = q0*q0;

float q0q1 = q0*q1;

float q0q2 = q0*q2;

// float q0q3 = q0*q3;

float q1q1 = q1*q1;

// float q1q2 = q1*q2;

float q1q3 = q1*q3;

float q2q2 = q2*q2;

float q2q3 = q2*q3;

float q3q3 = q3*q3;

if(ax*ay*az==0)

return;

norm = sqrt(ax*ax + ay*ay + az*az); //acc数据归一化

ax = ax /norm;

ay = ay / norm;

az = az / norm;

// estimated direction of gravity and flux (v and w)

vx = 2*(q1q3 - q0q2); //四元素中xyz的 vy = 2*(q0q1 + q2q3);

vz = q0q0 - q1q1 - q2q2 + q3q3 ;

// error is sum of cross product between reference direction of fields and direction measured by sensors

ex = (ay*vz - az*vy) ; //向量外积在相减得到差分就是误差

ey = (az*vx - ax*vz) ;

ez = (ax*vy - ay*vx) ;

exInt = exInt + ex * Ki; //对误差进行积分

eyInt = eyInt + ey * Ki;

ezInt = ezInt + ez * Ki;

// adjusted gyroscope measurements

gx = gx + Kp*ex + exInt; //将误差PI后补偿到陀螺仪,即补偿零点漂移

gy = gy + Kp*ey + eyInt;

gz = gz + Kp*ez + ezInt; //这里的gz由于没有观测者进行矫正会产生漂移,表现出来的就是积分自增或自减

// integrate quaternion rate and normalise //四元素的微分方程

q0 = q0 + (-q1*gx - q2*gy - q3*gz)*halfT;

q1 = q1 + (q0*gx + q2*gz - q3*gy)*halfT;

q2 = q2 + (q0*gy - q1*gz + q3*gx)*halfT;

q3 = q3 + (q0*gz + q1*gy - q2*gx)*halfT;

// normalise quaternion

norm = sqrt(q0*q0 + q1*q1 + q2*q2 + q3*q3);

q0 = q0 / norm;

q1 = q1 / norm;

q2 = q2 / norm;

q3 = q3 / norm;

//Q_ANGLE.Yaw = atan2(2 * q1 * q2 + 2 * q0 * q3, -2 * q2*q2 - 2 * q3* q3 + 1)* 57.3; // yaw

Q_ANGLE.Y = asin(-2 * q1 * q3 + 2 * q0* q2)* 57.3; // pitch

Q_ANGLE.X = atan2(2 * q2 * q3 + 2 * q0 * q1, -2 * q1 * q1 - 2 * q2* q2 + 1)* 57.3; // roll

}

1.

float q0q0 = q0*q0;

float q0q1 = q0*q1;

float q0q2 = q0*q2;

// float q0q3 = q0*q3;

float q1q1 = q1*q1;

// float q1q2 = q1*q2;

float q1q3 = q1*q3;

float q2q2 = q2*q2;

float q2q3 = q2*q3;

float q3q3 = q3*q3;

这段程序就是为了把需要用到的姿态矩阵的元素求出来给出的。

2.

vx = 2*(q1q3 - q0q2); /

vy = 2*(q0q1 + q2q3);

vz = q0q0 - q1q1 - q2q2 + q3q3 ;

可以看到vx,vy,vz为CRb的最后一列的三项,四元数矩阵带入(1)式得vx,vy,vz分别是axB,ayB,azB每一项g前的系数。且静止情况下vx,vy,vz组成向量模长基本可以认为为1.

3.

norm = sqrt(ax*ax + ay*ay + az*az); //acc数据归一化

ax = ax /norm;

ay = ay / norm;

az = az / norm;

以上已说,由四元数倒推回去的加速度,向量模长为1,为了比较误差进行归1化,算的由加计得出的向量。

4.

ex = (ay*vz - az*vy) ;

ey = (az*vx - ax*vz) ;

ez = (ax*vy - ay*vx) ;

接着可以通过叉乘(向量外积)计算误差

5.

exInt = exInt + ex * Ki;

eyInt = eyInt + ey * Ki;

ezInt = ezInt + ez * Ki;

对误差进行积分

6.

gx = gx + Kp*ex + exInt;

gy = gy + Kp*ey + eyInt;

gz = gz + Kp*ez + ezInt;

进行pi滤波,其实就是互补滤波

7.

q0 = q0 + (-q1*gx - q2*gy - q3*gz)*halfT;

q1 = q1 + (q0*gx + q2*gz - q3*gy)*halfT;

q2 = q2 + (q0*gy - q1*gz + q3*gx)*halfT;

q3 = q3 + (q0*gz + q1*gy - q2*gx)*halfT;

龙格库塔法。。。就是方程的数值解法。。近似解。。一阶解法

这个跟四元数的微分方程对应有兴趣的看看书。。。。

8.

norm = sqrt(q0*q0 + q1*q1 + q2*q2 + q3*q3);

q0 = q0 / norm;

q1 = q1 / norm;

q2 = q2 / norm;

q3 = q3 / norm;

对四元数进行规范化,即化为模长为1 ,因为只有规范化的四元数才能表示刚体旋转。

9.

Q_ANGLE.Y = asin(-2 * q1 * q3 + 2 * q0* q2)* 57.3; // pitch

Q_ANGLE.X = atan2(2 * q2 * q3 + 2 * q0 * q1, -2 * q1 * q1 - 2 * q2* q2 + 1)* 57.3; // roll

仍旧一一对应关系发现2(q1q3 -q0q2)刚好跟欧拉角对应,由此利用自带库函数即可求得俯仰角,横滚角类似,偏航角由于没有罗盘进行校正求没有意义,控制中采用采用PD控制。

补充,由于陀螺仪会有零点漂移开始一定要进行补偿。这段是在mpu6050.c中程序,对直流偏执进行了补偿。

MPU6050_ACC_LAST.X=((((int16_t)mpu6050_buffer[0]) << 8) | mpu6050_buffer[1]) - ACC_OFFSET.X;

MPU6050_ACC_LAST.Y=((((int16_t)mpu6050_buffer[2]) << 8) | mpu6050_buffer[3]) - ACC_OFFSET.Y;

MPU6050_ACC_LAST.Z=((((int16_t)mpu6050_buffer[4]) << 8) | mpu6050_buffer[5]) - ACC_OFFSET.Z;

MPU6050_GYRO_LAST.X=((((int16_t)mpu6050_buffer[8]) << 8) | mpu6050_buffer[9]) - GYRO_OFFSET.X;

MPU6050_GYRO_LAST.Y=((((int16_t)mpu6050_buffer[10]) << 8) | mpu6050_buffer[11]) - GYRO_OFFSET.Y;

MPU6050_GYRO_LAST.Z=((((int16_t)mpu6050_buffer[12]) << 8) | mpu6050_buffer[13]) - GYRO_OFFSET.Z;

这里还要说一点,这里加速计的数据用的是滑动平均值滤波法,一定要有这个。。不然由于机械振动造成的影响非常大。。。

void repare_Data(void)

{

static uint8_t filter_cnt=0;

int32_t temp1=0,temp2=0,temp3=0;

uint8_t i;

MPU6050_Read();

MPU6050_Dataanl();

ACC_X_BUF[filter_cnt] = MPU6050_ACC_LAST.X;

ACC_Y_BUF[filter_cnt] = MPU6050_ACC_LAST.Y;

ACC_Z_BUF[filter_cnt] = MPU6050_ACC_LAST.Z;

for(i=0;i<FILTER_NUM;i++)

{

temp1 += ACC_X_BUF;

temp2 += ACC_Y_BUF;

temp3 += ACC_Z_BUF;

}




  • 四轴第三版-改.SchDoc
    描述:四轴第三版
  • 四轴飞行第三版-改.PcbDoc
    描述:四轴飞行第三版
  • 基于PI_PD控制器的四旋翼姿态控制_唐健杰.pdf
    描述:论文
  • 小四旋翼.rar
    描述:参考资料等

相关推荐

电子产业图谱