自平衡小车控制(stc12+mpu6050程序)

自平衡小车控制(stc12+mpu6050程序)

 
  1. /***********************************************************************
  2. // 两轮自平衡车最终版控制程序(6轴MPU6050+互补滤波+PWM电机)
  3. // 单片机STC12C5A60S2
  4. // 晶振:20M
  5. // 日期:2014.11.26 - ?
  6. ***********************************************************************/
  7.  
  8. #include <REG52.H>
  9. #include <math.h>     
  10. #include <stdio.h>   
  11. #include <INTRINS.H>
  12.  
  13. typedef unsigned char  uchar;
  14. typedef unsigned short ushort;
  15. typedef unsigned int   uint;
  16.  
  17. //******功能模块头文件*******
  18.  
  19. #include "DELAY.H"    //延时头文件
  20. //--------------------------------------------
  21. #include "STC_ISP.H"    //程序烧录头文件
  22. #include "SET_SERIAL.H"//串口头文件
  23.  
  24. #include "SET_PWM.H"//PWM头文件
  25. #include "MOTOR.H"//电机控制头文件
  26. #include "MPU6050.H"//MPU6050头文件
  27. //-----------------这些文件---------------------------
  28.  
  29.  
  30.  
  31. //******角度参数************
  32.  
  33. float Gyro_y;        //Y轴陀螺仪数据暂存
  34.  
  35. //--------------加速度和角度的转化------------------
  36.  
  37.  
  38. float Angle_gy;      //由角速度计算的倾斜角度
  39. //陀螺仪直接反应角度
  40.  
  41. float Accel_x;     //X轴加速度值暂存
  42. float Angle_ax;      //由加速度计算的倾斜角度 、
  43.  
  44. float Angle;         //小车最终倾斜角度
  45. uchar value; //角度正负极性标记
  46.  
  47. //******PWM参数*************
  48.  
  49. int   speed_mr; //右电机  转速//这个的测量---------转盘
  50. int   speed_ml; //左电机  转速
  51. int   PWM_R;         //右轮PWM值计算
  52. int   PWM_L;         //左轮PWM值计算
  53. float PWM;           //综合PWM计算
  54. float PWMI; //PWM积分值
  55.  
  56. //******电机参数*************
  57.  
  58. float speed_r_l;//电机转速
  59. float speed;        //电机转速滤波
  60. float position;    //位移
  61.  
  62. //******蓝牙遥控参数*************
  63. uchar remote_char;
  64. char  turn_need;
  65. char  speed_need;
  66.  
  67. //*********************************************************
  68. //定时器100Hz数据更新中断 T1定时器
  69. //*********************************************************
  70.  
  71. void Init_Timer1(void)//10毫秒@20MHz,100Hz刷新频率
  72. {
  73. AUXR &= 0xBF;//定时器时钟12T模式
  74. TMOD &= 0x0F;//设置定时器模式
  75. TMOD |= 0x10;//设置定时器模式
  76. TL1 = 0xE5;    //设置定时初值
  77. TH1 = 0xBE;    //设置定时初值
  78. TF1 = 0;    //清除TF1标志
  79. TR1 = 1;    //定时器1开始计时
  80. }
  81.  
  82.  
  83.  
  84. //*********************************************************
  85. //中断控制初始化
  86. //*********************************************************
  87.  
  88. void Init_Interr(void)
  89. {
  90. EA = 1;     //开总中断
  91.     EX0 = 1;    //开外部中断INT0
  92.     EX1 = 1;    //开外部中断INT1
  93.     IT0 = 1;    //下降沿触发
  94.     IT1 = 1;    //下降沿触发
  95. ET1 = 1;    //开定时器1中断
  96. }
  97.  
  98.  
  99.  
  100. //******卡尔曼参数************
  101.  
  102. float code Q_angle=0.001;  
  103. float code Q_gyro=0.003;
  104. float code R_angle=0.5;
  105. float code dt=0.01;                  //dt为kalman滤波器采样时间;
  106. char  code C_0 = 1;
  107. float xdata Q_bias, Angle_err;
  108. float xdata PCt_0, PCt_1, E;
  109. float xdata K_0, K_1, t_0, t_1;
  110. float xdata Pdot[4] ={0,0,0,0};
  111. float xdata PP[2][2] = { { 1, 0 },{ 0, 1 } };
  112.  
  113. //*********************************************************
  114. // 卡尔曼滤波
  115. //*********************************************************
  116.  
  117. //Kalman滤波,20MHz的处理时间约0.77ms;
  118.  
  119. void Kalman_Filter(float Accel,float Gyro)  // 滤波,输出标准的方波驱动电机
  120. {
  121. Angle+=(Gyro - Q_bias) * dt; //先验估计陀螺角度
  122.  
  123.  
  124. Pdot[0]=Q_angle - PP[0][1] - PP[1][0]; // Pk-先验估计误差协方差的微分
  125.  
  126. Pdot[1]=- PP[1][1];
  127. Pdot[2]=- PP[1][1];
  128. Pdot[3]=Q_gyro;
  129.  
  130. PP[0][0] += Pdot[0] * dt;   // Pk-先验估计误差协方差微分的积分
  131. PP[0][1] += Pdot[1] * dt;   // =先验估计误差协方差
  132. PP[1][0] += Pdot[2] * dt;
  133. PP[1][1] += Pdot[3] * dt;
  134.  
  135. Angle_err = Accel - Angle;//zk-先验估计
  136.  
  137. PCt_0 = C_0 * PP[0][0];
  138. PCt_1 = C_0 * PP[1][0];
  139.  
  140. E = R_angle + C_0 * PCt_0;
  141.  
  142. K_0 = PCt_0 / E;
  143. K_1 = PCt_1 / E;
  144.  
  145. t_0 = PCt_0;
  146. t_1 = C_0 * PP[0][1];
  147.  
  148. PP[0][0] -= K_0 * t_0; //后验估计误差协方差
  149. PP[0][1] -= K_0 * t_1;
  150. PP[1][0] -= K_1 * t_0;
  151. PP[1][1] -= K_1 * t_1;
  152.  
  153. Angle+= K_0 * Angle_err; //后验估计
  154. Q_bias+= K_1 * Angle_err; //后验估计
  155. Gyro_y   = Gyro - Q_bias; //输出值(后验估计)的微分=角速度
  156.  
  157. }
  158.  
  159.  
  160.  
  161. //*********************************************************
  162. // 倾角计算(卡尔曼融合)
  163. //*********************************************************
  164.  
  165. void Angle_Calcu(void)
  166. {
  167. //------加速度--------------------------
  168.  
  169. //范围为2g时,换算关系:16384 LSB/g
  170. //角度较小时,x=sinx得到角度(弧度), deg = rad*180/3.14
  171. //因为x>=sinx,故乘以1.3适当放大
  172.  
  173. Accel_x  = GetData(ACCEL_XOUT_H);  //读取X轴加速度         存在ACCEL_XOUT_H 寄存器
  174. Angle_ax = (Accel_x - 1100) /16384;   //去除零点偏移,计算得到角度(弧度)
  175. Angle_ax = Angle_ax*1.2*180/3.14;     //弧度转换为度,
  176.  
  177.  
  178.     //-------角速度-------------------------
  179.  
  180. //范围为2000deg/s时,换算关系:16.4 LSB/(deg/s)
  181.  
  182. Gyro_y = GetData(GYRO_YOUT_H);      //静止时角速度Y轴输出为  【-30】 左右
  183. Gyro_y = -(Gyro_y + 30)/16.4;         //去除零点偏移,计算角速度值,  【负号为方向处理】
  184. //Angle_gy = Angle_gy + Gyro_y*0.01;  //角速度积分得到倾斜角度.
  185.  
  186.  
  187. //-------卡尔曼滤波融合-----------------------
  188.  
  189. Kalman_Filter(Angle_ax,Gyro_y);       //卡尔曼滤波计算倾角
  190.  
  191.  
  192. /*//-------互补滤波-----------------------
  193.  
  194. //补偿原理是取当前倾角和加速度获得倾角差值进行放大,然后与
  195.     //陀螺仪角速度叠加后再积分,从而使倾角最跟踪为加速度获得的角度
  196. //0.5为放大倍数,可调节补偿度;0.01为系统周期10ms
  197.  
  198. Angle = Angle + (((Angle_ax-Angle)*0.5 + Gyro_y)*0.01);*/
  199.   
  200. }  
  201.  
  202.  
  203.  
  204. //*********************************************************
  205. //电机转速和位移值计算
  206. //*********************************************************
  207.  
  208. void Psn_Calcu(void)
  209. {
  210.  
  211. speed_r_l =(speed_mr + speed_ml)*0.5;
  212. speed *= 0.7;//上一次的                  //车轮速度滤波
  213. speed += speed_r_l*0.3;
  214. position += speed;                  //积分得到位移
  215. position += speed_need;//加上蓝牙位移,等于总的移动
  216. if(position<-6000) position = -6000;
  217. if(position> 6000) position =  6000;
  218.  
  219.  
  220. }
  221.  
  222.  
  223. static float code Kp  = 9.0;       //PID参数
  224. static float code Kd  = 2.6;    //PID参数
  225. static float code Kpn = 0.01;      //PID参数
  226. static float code Ksp = 2.0;    //PID参数
  227.  
  228. //*********************************************************
  229. //电机PWM值计算
  230. //*********************************************************
  231.  
  232. void PWM_Calcu(void)
  233. {
  234.  
  235. if(Angle<-40||Angle>40)               //角度过大,关闭电机
  236. {  
  237.   CCAP0H = 0;
  238.       CCAP1H = 0;
  239.   return;
  240. }
  241. PWM  = Kp*Angle + Kd*Gyro_y;          //PID:角速度和角度
  242. PWM += Kpn*position + Ksp*speed;      //PID:速度和位置
  243. PWM_R = PWM + turn_need;
  244. PWM_L = PWM - turn_need;   //蓝牙的倾斜,
  245. PWM_Motor(PWM_L,PWM_R);
  246.  
  247. }
  248.  
  249.  
  250.  
  251.  
  252. //*********************************************************
  253. //手机蓝牙遥控
  254. //*********************************************************
  255.  
  256. void Bluetooth_Remote(void)
  257. {
  258.  
  259. remote_char = receive_char();   //接收蓝牙串口数据
  260.  
  261. if(remote_char ==0x02) speed_need = -80;   //前进
  262. else if(remote_char ==0x01) speed_need = 80;   //后退
  263.      else speed_need = 0;   //不动
  264.  
  265.     if(remote_char ==0x03) turn_need = 15;   //左转
  266. else if(remote_char ==0x04) turn_need = -15;   //右转
  267.      else turn_need = 0;   //不转
  268.  
  269. }
  270.  
  271.  
  272. /*=================================================================================*/
  273.  
  274. //*********************************************************
  275. //main
  276. //*********************************************************
  277. void main()
  278. {
  279.  
  280. delaynms(500);   //上电延时
  281. Init_PWM();       //PWM初始化
  282.     Init_Timer0();     //初始化定时器0,作为PWM时钟源
  283. Init_Timer1();     //初始化定时器1
  284. Init_Interr();     //中断初始化
  285. Init_Motor();   //电机控制初始化
  286. Init_BRT();   //串口初始化(独立波特率)
  287. InitMPU6050();     //初始化MPU6050
  288. delaynms(500);   
  289.  
  290. while(1)
  291. {
  292.    
  293. Bluetooth_Remote();
  294.  
  295. }
  296. }
  297.  
  298.  
  299. /*=================================================================================*/
  300.  
  301. //********timer1中断***********************
  302.  
  303. void Timer1_Update(void) interrupt 3
  304. {
  305.  
  306.    TL1 = 0xE5;    //设置定时初值10MS
  307.    TH1 = 0xBE;
  308.  
  309.    //STC_ISP();                    //程序下载
  310.    Angle_Calcu();                  //倾角计算
  311.    Psn_Calcu();                    //电机位移计算
  312.    PWM_Calcu();                    //计算PWM值
  313.  
  314.    speed_mr = speed_ml = 0;
  315.  
  316. }
  317.  
  318.  
  319. //********右电机中断***********************
  320.  
  321. void INT_L(void) interrupt 0
  322. {
  323.  
  324.    if(SPDL == 1)  { speed_ml++; } //左电机前进
  325.    else      { speed_ml--; } //左电机后退
  326.    LED = ~LED;
  327.  
  328. }
  329.  
  330.  
  331. //********左电机中断***********************
  332.  
  333. void INT_R(void) interrupt 2
  334. {
  335.  
  336.    if(SPDR == 1)  { speed_mr++; } //右电机前进
  337.    else      { speed_mr--; } //右电机后退
  338.    LED = ~LED;
  339.  
  340. }
复制代码

 
 
 

文件到原文下载,原文出自:https://bbs.usoftchina.com/thread-203198-1-1.html

  • 7
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值