123下一页

[经验] 【Kinetis MK10】一起DIY四轴飞行器

  [复制链接]
发表于 2015-3-13 10:21:16   6683 查看 45 回复 显示全部楼层 倒序浏览
分享
网上看到一个四轴飞行器的视频深深吸引了我,然而我是一个Kinetis的忠实粉丝,就想尝试一下用Kinetis MK10去做一个四轴飞行器!!!

期间因为很多事情,让这个项目断断续续,但是很高兴我能坚持下来。

当然,尽管现在也还未能成功起飞,但是最起码,有了新的进展,在这里,我分享一下我的Kinetis四轴心得。

也算是我自己的一个学习记录吧。

首先是main函数:
  1.     int main(void)
  2.     {
  3.         uint32_t i;
  4.         uint8_t ret;
  5.         uint32_t counter = 0;
  6.         imu_float_euler_angle_t angle;
  7.         SYSTICK_DelayInit(); //Init Delay
  8.         UART_QuickInit(UART1_RX_PC03_TX_PC04, 115200);  //Init UART and printf
  9.         GPIO_QuickInit(HW_GPIOA, 1 , kGPIO_Mode_OPP);   //Init LED
  10.         //Blink LED to indicate system is running
  11.         for(i = 0; i < 10; i++)
  12.         {
  13.             GPIO_ToggleBit(HW_GPIOA, 1);
  14.             DelayMs(50);
  15.         }
  16.         //init sensor
  17.         ret = InitSensor();
  18.         if(ret)
  19.         {
  20.             printf("Sensor init failed! code:%d\r\n", ret);
  21.         }
  22.         // install imu interface function
  23.         imu_io_install(&IMU_IOInstallStruct1);
  24.         // install trans uart for send data
  25.         trans_io_install(&TRANS_IOInstallStruct1);
  26.       
  27.         trans_user_data_t send_data;
  28.         while(1)
  29.         {
  30.             imu_get_euler_angle(&angle);
  31.     //              通过串口将姿态的数据发送出去,串口速度为115200               
  32.     //        printf("%05d %05d %05d\r", (int16_t)angle.imu_pitch, (int16_t)angle.imu_roll, (int16_t)angle.imu_yaw);
  33.             
  34.                             //以下函数用于发送数据帧,传输飞控需要的数据帧
  35.             send_data.trans_pitch = (int16_t)angle.imu_pitch*100;
  36.             send_data.trans_roll = (int16_t)angle.imu_roll*100;
  37.             send_data.trans_yaw = (int16_t)angle.imu_yaw*10;
  38.             trans_send_pactket(send_data);  //发送一帧数据
  39.                             //结束
  40.             //blink the LED
  41.             counter++;
  42.             counter %= 10;
  43.             if(!counter)
  44.             {
  45.                 GPIO_ToggleBit(HW_GPIOA, 1);   //LED运行灯闪烁
  46.             }
  47.         }
  48.     }
复制代码
main函数就是飞控一开始执行的代码,主要的一些外设的初始化工作。比如IIC啦,UART啦,SPI啦等等。

InitSensor();其实就是MPU6050   hmc5883 的初始化函数。代码如下:
  1.     uint8_t InitSensor(void)
  2.     {
  3.         static int init = 0;
  4.         uint8_t ret = 0;
  5.         if(!init)
  6.         {
  7.             ret += mpu6050_init(&mpu6050_device1, IMU_TEST_I2C_MAP, "mpu6050", 96000);
  8.             ret += hmc5883_init(&hmc_device, IMU_TEST_I2C_MAP, "hmc5883", 96000);
  9.          //   ret += bmp180_init(&bmp180_device1, IMU_TEST_I2C_MAP, "bmp180", 96000);
  10.             init = 1;
  11.         }
  12.         if(ret)
  13.         {
  14.             return ret;
  15.         }
  16.         return 0;
  17.     }
复制代码
然后在while(1)里,就是最重要的姿态解算函数了。
imu_get_euler_angle(&angle);就是姿态解算函数,并把得到的结果保存到angle变量里。
代码如下:

  1.     uint32_t imu_get_euler_angle(imu_float_euler_angle_t * angle)
  2.     {
  3.         uint8_t err = 0;
  4.         int16_t ax,ay,az,gx,gy,gz,mx,my,mz;
  5.         imu_raw_data_t raw_data;
  6.     //    imu_raw_data_t filter_data;
  7.         imu_float_data_t float_data;
  8.         err += gpIOInstallStruct->imu_get_accel(&ax, &ay, &az);
  9.         err += gpIOInstallStruct->imu_get_gyro(&gx, &gy, &gz);
  10.         err += gpIOInstallStruct->imu_get_mag(&mx, &my, &mz);
  11.         if(err >0)
  12.         {
  13.           return 1;
  14.         }
  15.         raw_data.ax = ax;
  16.         raw_data.ay = ay;
  17.         raw_data.az = az;
  18.         raw_data.gx = gx;
  19.         raw_data.gy = gy;
  20.         raw_data.gz = gz;
  21.         raw_data.mx = mx;
  22.         raw_data.my = my;
  23.         raw_data.mz = mz;
  24.     #if 0
  25.         //I need rawdata I give you filtered data
  26.         imu_sliding_filter(raw_data, &filter_data);
  27.     #endif
  28.         // I need filtered data I give you float data
  29.         imu_format_data(raw_data, &float_data);
  30.         //I need float data I give you euler angles
  31.         updateAHRS( float_data.gx * Gyro_Gr,
  32.                     float_data.gy * Gyro_Gr,
  33.                     float_data.gz * Gyro_Gr,
  34.                     float_data.ax,
  35.                     float_data.ay,
  36.                     float_data.az,
  37.                     float_data.mx,
  38.                     float_data.my,
  39.                     float_data.mz,
  40.                     angle);
  41.         return 0;
  42.     }
复制代码
得到飞控的姿态,就可以做很多事情了。

在四轴飞行器里,我们需要使用姿态来做PID控制
常用的是单级PID算法,高级的就是串级PID。
我在尝试使用串级PID
串级PID的代码如下:

  1.     //飞行器姿态外环控制
  2.     void ANO_FlyControl::Attitude_Outter_Loop(void)
  3.     {
  4.             int32_t        errorAngle[2];
  5.             Vector3f Gyro_ADC;
  6.             
  7.             //计算角度误差值
  8.             errorAngle[ROLL] = constrain_int32((rc.Command[ROLL] * 2) , -((int)FLYANGLE_MAX), +FLYANGLE_MAX) - imu.angle.x * 10;
  9.             errorAngle[PITCH] = constrain_int32((rc.Command[PITCH] * 2) , -((int)FLYANGLE_MAX), +FLYANGLE_MAX) - imu.angle.y * 10;
  10.             
  11.             //获取角速度
  12.             Gyro_ADC = mpu6050.Get_Gyro() / 4;
  13.             
  14.             //得到外环PID输出
  15.             RateError[ROLL] = pid[PIDLEVEL].get_p(errorAngle[ROLL]) - Gyro_ADC.x;
  16.             RateError[PITCH] = pid[PIDLEVEL].get_p(errorAngle[PITCH]) - Gyro_ADC.y;
  17.             RateError[YAW] = ((int32_t)(yawRate) * rc.Command[YAW]) / 32 - Gyro_ADC.z;               
  18.     }
复制代码
  1.     //飞行器姿态内环控制
  2.     void ANO_FlyControl::Attitude_Inner_Loop(void)
  3.     {
  4.             int32_t PIDTerm[3];
  5.             
  6.             for(u8 i=0; i<3;i++)
  7.             {
  8.                     //当油门低于检查值时积分清零,重新积分  
  9.                     if ((rc.rawData[THROTTLE]) < RC_MINCHECK)        
  10.                             pid[i].reset_I();
  11.                   
  12.                     //得到内环PID输出
  13.                     PIDTerm[i] = pid[i].get_pid(RateError[i], PID_INNER_LOOP_TIME);
  14.             }
  15.             
  16.             PIDTerm[YAW] = -constrain_int32(PIDTerm[YAW], -300 - abs(rc.Command[YAW]), +300 + abs(rc.Command[YAW]));        
  17.                   
  18.             //PID输出转为电机控制量
  19.             motor.writeMotor(rc.Command[THROTTLE], PIDTerm[ROLL], PIDTerm[PITCH], PIDTerm[YAW]);
  20.     }        
复制代码
分为外环控制 和 内环控制两部分。

PID算法完成,当然是输出给PWM控制电机了。
代码如下:

  1. //四轴X模式
  2.         motorPWM[0] = throttle - pidTermRoll + pidTermPitch - pidTermYaw; //后右
  3.         motorPWM[1] = throttle - pidTermRoll - pidTermPitch + pidTermYaw; //前右
  4.         motorPWM[2] = throttle + pidTermRoll + pidTermPitch + pidTermYaw; //后左
  5.         motorPWM[3] = throttle + pidTermRoll - pidTermPitch - pidTermYaw; //前左
复制代码
这样,一个基本能飞的四轴飞控系统就差不多完成了。



实物图:
1.jpg

2.jpg

评分

参与人数 1积分 +10 收起 理由
zhou2sheng + 10 您的帖子很精彩,期待您分享的下一个帖子!.

查看全部评分

标签:DIY

实习生

发表于 2015-3-13 11:00:37  
楼主好厉害,继续加油!
回复

举报

技术员

发表于 2015-3-13 19:10:23  

PCB在线计价下单

板子大小:

cm
X
cm

层数:

2

板子数量:

10

厚度:

1.6
不错 哦,大师级别哦。
回复

举报

实习生

发表于 2015-3-13 19:58:13  
好啊    我想学学  做一个玩玩
回复

点赞 举报

实习生

发表于 2015-4-21 12:45:27  
一直想做四轴,但没经验,要多多学习呀!
回复

点赞 举报

实习生

发表于 2015-4-21 13:56:22  
记号学习学习。。。
回复

举报

高级工程师

发表于 2015-5-8 09:41:16  
牛逼!!!!!!!!!!!!!
回复

举报

等待验证会员

发表于 2015-6-9 11:03:35  
好,,好,,好,,好
回复

举报

技术员

发表于 2015-7-2 11:31:04  
不错 哦,看看学习一下。。。
回复

举报

技术员

发表于 2015-7-7 19:04:53  
好啊    我想学学  做一个玩玩
回复

点赞 举报

技术员

发表于 2015-7-8 10:35:24  
谢谢楼主分享,好好学习
回复

点赞 举报

实习生

发表于 2015-7-19 11:44:32  
楼主好厉害,有电路图吗参考
回复

点赞 1 举报

实习生

发表于 2015-7-23 01:27:19  
很牛逼啊,真心感谢楼主这么大公无私的奉献出来啦 哈哈
回复

点赞 举报

实习生

发表于 2015-8-11 17:01:09  

想试着做 慢慢学习
回复

举报

实习生

发表于 2015-8-13 00:15:34  
谢谢楼主分享。。。。
回复

举报

实习生

发表于 2015-8-13 00:15:50  
谢谢楼主分享。。。。
回复

举报

实习生

发表于 2015-8-13 02:21:58  
本帖最后由 雷锦锯 于 2017-3-29 13:37 编辑

推荐,谢谢分享
回复

点赞 举报

技术员

发表于 2015-8-27 17:27:43  
收藏了,谢谢分享。。。。。。。。。。。。。
回复

举报

实习生

发表于 2015-8-28 07:54:05  
非常厉害的楼主
回复

举报

实习生

发表于 2015-9-20 15:52:20  
学习了,可惜没原理图。
回复

举报

123下一页
高级模式
您需要登录后才可以回帖 登录 | 注册

关闭

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

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

推荐专区

技术干货集中营

专家问答

用户帮助┃咨询与建议┃版主议事

我的提问

工程师杂谈

工程师创意

工程师职场

论坛电子赛事

社区活动专版

发烧友活动

-

嵌入式论坛

ARM技术论坛

Android论坛

Linux论坛

单片机/MCU论坛

FPGA|CPLD|ASIC论坛

DSP论坛

嵌入式系统论坛

-

电源技术论坛

电源技术论坛

无线充电技术

-

硬件设计论坛

PCB设计论坛

电路设计论坛

电子元器件论坛

控制|传感

总线技术|接口技术

-

测试测量论坛

LabVIEW论坛

Matlab论坛

测试测量技术专区

仪器仪表技术专区

-

EDA设计论坛

multisim论坛

PADS技术论坛

Protel|AD|DXP论坛

Allegro论坛

proteus论坛|仿真论坛

EasyEDA-中国人自已的EDA工具

Orcad论坛

-

综合技术与应用

电机控制

智能电网

光电及显示

参考设计中心

汽车电子技术论坛

医疗电子论坛

-

开源硬件

-

无线通信论坛

无线通信技术专区

天线|RF射频|微波|雷达技术

-

IC设计论坛

芯片测试与失效分析

Mixed Signal/SOC[数模混合芯片设计]

Analog/RF IC设计

设计与制造封装测试

-

厂商专区

TI论坛

TI Deyisupport社区

-

检测技术与质量

电磁兼容(EMC)设计与整改

安规知识论坛

检测与认证

-

消费电子论坛

手机技术论坛

平板电脑/mid论坛

音视/视频/机顶盒论坛

-

电子论坛综合区

聚丰众筹官方社区

新人报道区

聚丰供应链

-

论坛服务区

-

供求信息发布

供需广告

招聘┃求职发布区

电子展览展会专区