查看: 3677|回复: 8

[其他] 开源制作小四旋翼全过程

[复制链接]
  • TA的每日心情
    奋斗
    2017-2-13 08:29
  • 签到天数: 20 天

    连续签到: 1 天

    [LV.4]偶尔看看III

    531

    主题

    2048

    帖子

    0

    中级会员

    Rank: 3Rank: 3

    积分
    210
    最后登录
    2018-8-14
    发表于 2016-7-21 10:35:21 | 显示全部楼层 |阅读模式
    开源制作小四旋翼全过程.jpg
    开源制作小四旋翼全过程2.jpg
    开源制作小四旋翼全过程3.jpg
    开源制作小四旋翼全过程4.png




    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;

    }


    电路图文件:

    四轴飞行第三版-改.PcbDoc (6.96 MB, 下载次数: 24)
    签到 签到
    回复

    使用道具 举报

  • TA的每日心情
    奋斗
    2017-2-13 08:29
  • 签到天数: 20 天

    连续签到: 1 天

    [LV.4]偶尔看看III

    531

    主题

    2048

    帖子

    0

    中级会员

    Rank: 3Rank: 3

    积分
    210
    最后登录
    2018-8-14
     楼主| 发表于 2016-7-21 13:11:47 | 显示全部楼层
    stary666 发表于 2016-7-21 11:24
    小九,验证过吗??

    亲测啊
    签到 签到
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2017-5-9 08:12
  • 签到天数: 6 天

    连续签到: 1 天

    [LV.2]偶尔看看I

    34

    主题

    801

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    2375
    最后登录
    2021-8-11
    发表于 2016-7-21 13:37:33 | 显示全部楼层
    要开搞麽?
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2018-8-30 16:02
  • 签到天数: 5 天

    连续签到: 1 天

    [LV.2]偶尔看看I

    36

    主题

    1065

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    1851
    最后登录
    2019-11-19
    发表于 2016-7-21 18:41:47 | 显示全部楼层
    墙裂收藏
    哎...今天够累的,签到来了~
    回复

    使用道具 举报

    该用户从未签到

    0

    主题

    3

    帖子

    0

    新手上路

    Rank: 1

    积分
    8
    最后登录
    1970-1-1
    发表于 2016-8-10 09:59:01 | 显示全部楼层
    学习一下啦
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    难过
    2019-9-19 08:55
  • 签到天数: 269 天

    连续签到: 1 天

    [LV.8]以坛为家I

    28

    主题

    2424

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    2785
    最后登录
    2019-11-29
    发表于 2016-8-10 10:17:38 | 显示全部楼层
    6666666666666
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    难过
    2019-9-19 08:55
  • 签到天数: 269 天

    连续签到: 1 天

    [LV.8]以坛为家I

    28

    主题

    2424

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    2785
    最后登录
    2019-11-29
    发表于 2016-8-10 10:18:27 | 显示全部楼层
    虽然看不懂  不明觉厉 呱唧呱唧
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    2018-11-8 23:27
  • 签到天数: 1 天

    连续签到: 1 天

    [LV.1]初来乍到

    9

    主题

    74

    帖子

    0

    中级会员

    Rank: 3Rank: 3

    积分
    309
    最后登录
    2025-1-22
    发表于 2016-10-13 10:04:21 | 显示全部楼层
    谢谢分享,代码略乱啊
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2017-12-26 12:04
  • 签到天数: 43 天

    连续签到: 1 天

    [LV.5]常住居民I

    4

    主题

    253

    帖子

    0

    高级会员

    Rank: 4

    积分
    620
    最后登录
    2018-7-6
    发表于 2016-11-28 12:04:14 | 显示全部楼层
    看着好高深
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /3 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2025-9-11 08:21 , Processed in 0.121785 second(s), 30 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表