找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 27206|回复: 32
打印 上一主题 下一主题
收起左侧

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

  [复制链接]
跳转到指定楼层
楼主
ID:72008 发表于 2015-1-12 14:26 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
/***********************************************************************
// 两轮自平衡车最终版控制程序(6轴MPU6050+互补滤波+PWM电机)
// 单片机STC12C5A60S2
// 晶振:20M
// 日期:2014.11.26 - ?
***********************************************************************/

#include <REG52.H>
#include <math.h>     
#include <stdio.h>   
#include <INTRINS.H>

typedef unsigned char  uchar;
typedef unsigned short ushort;
typedef unsigned int   uint;

//******功能模块头文件*******

#include "DELAY.H"    //延时头文件
//--------------------------------------------
#include "STC_ISP.H"    //程序烧录头文件
#include "SET_SERIAL.H"//串口头文件

#include "SET_PWM.H"//PWM头文件
#include "MOTOR.H"//电机控制头文件
#include "MPU6050.H"//MPU6050头文件
//-----------------这些文件---------------------------



//******角度参数************

float Gyro_y;        //Y轴陀螺仪数据暂存

//--------------加速度和角度的转化------------------


float Angle_gy;      //由角速度计算的倾斜角度
//陀螺仪直接反应角度

float Accel_x;     //X轴加速度值暂存
float Angle_ax;      //由加速度计算的倾斜角度 、

float Angle;         //小车最终倾斜角度
uchar value; //角度正负极性标记

//******PWM参数*************

int   speed_mr; //右电机  转速//这个的测量---------转盘
int   speed_ml; //左电机  转速
int   PWM_R;         //右轮PWM值计算
int   PWM_L;         //左轮PWM值计算
float PWM;           //综合PWM计算
float PWMI; //PWM积分值

//******电机参数*************

float speed_r_l;//电机转速
float speed;        //电机转速滤波
float position;    //位移

//******蓝牙遥控参数*************
uchar remote_char;
char  turn_need;
char  speed_need;

//*********************************************************
//定时器100Hz数据更新中断 T1定时器
//*********************************************************

void Init_Timer1(void)//10毫秒@20MHz,100Hz刷新频率
{
AUXR &= 0xBF;//定时器时钟12T模式
TMOD &= 0x0F;//设置定时器模式
TMOD |= 0x10;//设置定时器模式
TL1 = 0xE5;    //设置定时初值
TH1 = 0xBE;    //设置定时初值
TF1 = 0;    //清除TF1标志
TR1 = 1;    //定时器1开始计时
}



//*********************************************************
//中断控制初始化
//*********************************************************

void Init_Interr(void)
{
EA = 1;     //开总中断
    EX0 = 1;    //开外部中断INT0
    EX1 = 1;    //开外部中断INT1
    IT0 = 1;    //下降沿触发
    IT1 = 1;    //下降沿触发
ET1 = 1;    //开定时器1中断
}



//******卡尔曼参数************

float code Q_angle=0.001;  
float code Q_gyro=0.003;
float code R_angle=0.5;
float code dt=0.01;                  //dt为kalman滤波器采样时间;
char  code C_0 = 1;
float xdata Q_bias, Angle_err;
float xdata PCt_0, PCt_1, E;
float xdata K_0, K_1, t_0, t_1;
float xdata Pdot[4] ={0,0,0,0};
float xdata PP[2][2] = { { 1, 0 },{ 0, 1 } };

//*********************************************************
// 卡尔曼滤波
//*********************************************************

//Kalman滤波,20MHz的处理时间约0.77ms;

void Kalman_Filter(float Accel,float Gyro)  // 滤波,输出标准的方波驱动电机
{
Angle+=(Gyro - Q_bias) * dt; //先验估计陀螺角度


Pdot[0]=Q_angle - PP[0][1] - PP[1][0]; // Pk-先验估计误差协方差的微分

Pdot[1]=- PP[1][1];
Pdot[2]=- PP[1][1];
Pdot[3]=Q_gyro;

PP[0][0] += Pdot[0] * dt;   // Pk-先验估计误差协方差微分的积分
PP[0][1] += Pdot[1] * dt;   // =先验估计误差协方差
PP[1][0] += Pdot[2] * dt;
PP[1][1] += Pdot[3] * dt;

Angle_err = Accel - Angle;//zk-先验估计

PCt_0 = C_0 * PP[0][0];
PCt_1 = C_0 * PP[1][0];

E = R_angle + C_0 * PCt_0;

K_0 = PCt_0 / E;
K_1 = PCt_1 / E;

t_0 = PCt_0;
t_1 = C_0 * PP[0][1];

PP[0][0] -= K_0 * t_0; //后验估计误差协方差
PP[0][1] -= K_0 * t_1;
PP[1][0] -= K_1 * t_0;
PP[1][1] -= K_1 * t_1;

Angle+= K_0 * Angle_err; //后验估计
Q_bias+= K_1 * Angle_err; //后验估计
Gyro_y   = Gyro - Q_bias; //输出值(后验估计)的微分=角速度

}



//*********************************************************
// 倾角计算(卡尔曼融合)
//*********************************************************

void Angle_Calcu(void)
{
//------加速度--------------------------

//范围为2g时,换算关系:16384 LSB/g
//角度较小时,x=sinx得到角度(弧度), deg = rad*180/3.14
//因为x>=sinx,故乘以1.3适当放大

Accel_x  = GetData(ACCEL_XOUT_H);  //读取X轴加速度         存在ACCEL_XOUT_H 寄存器
Angle_ax = (Accel_x - 1100) /16384;   //去除零点偏移,计算得到角度(弧度)
Angle_ax = Angle_ax*1.2*180/3.14;     //弧度转换为度,


    //-------角速度-------------------------

//范围为2000deg/s时,换算关系:16.4 LSB/(deg/s)

Gyro_y = GetData(GYRO_YOUT_H);      //静止时角速度Y轴输出为  【-30】 左右
Gyro_y = -(Gyro_y + 30)/16.4;         //去除零点偏移,计算角速度值,  【负号为方向处理】
//Angle_gy = Angle_gy + Gyro_y*0.01;  //角速度积分得到倾斜角度.


//-------卡尔曼滤波融合-----------------------

Kalman_Filter(Angle_ax,Gyro_y);       //卡尔曼滤波计算倾角


/*//-------互补滤波-----------------------

//补偿原理是取当前倾角和加速度获得倾角差值进行放大,然后与
    //陀螺仪角速度叠加后再积分,从而使倾角最跟踪为加速度获得的角度
//0.5为放大倍数,可调节补偿度;0.01为系统周期10ms

Angle = Angle + (((Angle_ax-Angle)*0.5 + Gyro_y)*0.01);*/
  
}  



//*********************************************************
//电机转速和位移值计算
//*********************************************************

void Psn_Calcu(void)
{

speed_r_l =(speed_mr + speed_ml)*0.5;
speed *= 0.7;//上一次的                  //车轮速度滤波
speed += speed_r_l*0.3;
position += speed;                  //积分得到位移
position += speed_need;//加上蓝牙位移,等于总的移动
if(position<-6000) position = -6000;
if(position> 6000) position =  6000;


}


static float code Kp  = 9.0;       //PID参数
static float code Kd  = 2.6;    //PID参数
static float code Kpn = 0.01;      //PID参数
static float code Ksp = 2.0;    //PID参数

//*********************************************************
//电机PWM值计算
//*********************************************************

void PWM_Calcu(void)
{

if(Angle<-40||Angle>40)               //角度过大,关闭电机
{  
  CCAP0H = 0;
      CCAP1H = 0;
  return;
}
PWM  = Kp*Angle + Kd*Gyro_y;          //PID:角速度和角度
PWM += Kpn*position + Ksp*speed;      //PID:速度和位置
PWM_R = PWM + turn_need;
PWM_L = PWM - turn_need;   //蓝牙的倾斜,
PWM_Motor(PWM_L,PWM_R);

}




//*********************************************************
//手机蓝牙遥控
//*********************************************************

void Bluetooth_Remote(void)
{

remote_char = receive_char();   //接收蓝牙串口数据

if(remote_char ==0x02) speed_need = -80;   //前进
else if(remote_char ==0x01) speed_need = 80;   //后退
     else speed_need = 0;   //不动

    if(remote_char ==0x03) turn_need = 15;   //左转
else if(remote_char ==0x04) turn_need = -15;   //右转
     else turn_need = 0;   //不转

}


/*=================================================================================*/

//*********************************************************
//main
//*********************************************************
void main()
{

delaynms(500);   //上电延时
Init_PWM();       //PWM初始化
    Init_Timer0();     //初始化定时器0,作为PWM时钟源
Init_Timer1();     //初始化定时器1
Init_Interr();     //中断初始化
Init_Motor();   //电机控制初始化
Init_BRT();   //串口初始化(独立波特率)
InitMPU6050();     //初始化MPU6050
delaynms(500);   

while(1)
{
   
Bluetooth_Remote();

}
}


/*=================================================================================*/

//********timer1中断***********************

void Timer1_Update(void) interrupt 3
{

   TL1 = 0xE5;    //设置定时初值10MS
   TH1 = 0xBE;

   //STC_ISP();                    //程序下载
   Angle_Calcu();                  //倾角计算
   Psn_Calcu();                    //电机位移计算
   PWM_Calcu();                    //计算PWM值

   speed_mr = speed_ml = 0;

}


//********右电机中断***********************

void INT_L(void) interrupt 0
{

   if(SPDL == 1)  { speed_ml++; } //左电机前进
   else      { speed_ml--; } //左电机后退
   LED = ~LED;

}


//********左电机中断***********************

void INT_R(void) interrupt 2
{

   if(SPDR == 1)  { speed_mr++; } //右电机前进
   else      { speed_mr--; } //右电机后退
   LED = ~LED;

}

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏8 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:76321 发表于 2015-4-7 12:21 | 只看该作者
本帖最后由 安生 于 2015-4-7 12:24 编辑

楼主乃神人也:能给个电路图和完整软件吗?我退休在家,有时间,对单片机只知点毛皮,正在学习,想做一个玩玩。谢谢啦。dxq731@126.com
回复

使用道具 举报

板凳
ID:81109 发表于 2015-5-25 20:59 | 只看该作者
能帮我把蓝牙那部分的程序去掉吗?多了蓝牙那部分的程序,我就看不明白了,拜托了,谢谢了
如果弄出来后发到我邮箱1002831161@qq.com 好么?谢谢了,你很棒,我很需要你的帮助
回复

使用道具 举报

地板
ID:84102 发表于 2015-6-27 20:47 | 只看该作者
你好,现在我用51单片机做着自平衡车,不过到达pid调试的时候就不知怎么下手了,新手,希望楼主能给我一个完整资料参考一下吗?如果可以,那真是感激不尽
回复

使用道具 举报

5#
ID:84102 发表于 2015-6-27 20:49 | 只看该作者
回复

使用道具 举报

6#
ID:84102 发表于 2015-6-27 20:50 | 只看该作者
对了 我的qq邮箱是995709242@qq.com
回复

使用道具 举报

7#
ID:84229 发表于 2015-6-29 11:59 | 只看该作者
能把原理图共享一下,就更完美了,谢谢楼主的分享。尊敬、
回复

使用道具 举报

8#
ID:72399 发表于 2015-7-23 14:28 | 只看该作者
这个程序还没有完整把,你有角度传感器的资料和程序吗
回复

使用道具 举报

9#
ID:78573 发表于 2015-7-28 18:13 | 只看该作者
感谢,这位牛人
回复

使用道具 举报

10#
ID:58502 发表于 2015-8-1 13:11 | 只看该作者
头文件呢
回复

使用道具 举报

11#
ID:86621 发表于 2015-8-7 18:58 | 只看该作者
能给完整资料吗
回复

使用道具 举报

12#
ID:88333 发表于 2015-8-14 16:04 | 只看该作者
楼主,能给我头文件吗?QQ邮箱979690676。
回复

使用道具 举报

13#
ID:89055 发表于 2015-8-29 14:35 来自手机 | 只看该作者
能提供下完整程序吗?我邮箱是857047534@qq. com
回复

使用道具 举报

14#
ID:89553 发表于 2015-9-7 10:59 | 只看该作者
求完整资料,谢谢楼主了
回复

使用道具 举报

15#
ID:89553 发表于 2015-9-7 11:00 | 只看该作者
求完整程序,谢楼主了。2841208412@qq.com
回复

使用道具 举报

16#
ID:79544 发表于 2015-11-2 13:00 | 只看该作者
值得尊敬,谢谢分享。能把头文件也分享大家都可以做出来啦。
回复

使用道具 举报

17#
ID:70736 发表于 2016-3-1 10:31 | 只看该作者
楼主共享的资料可否打包一下!!!
回复

使用道具 举报

18#
ID:104472 发表于 2016-3-1 16:21 | 只看该作者
分享,可以不发原文件,但希望楼主积极和大家交流
回复

使用道具 举报

19#
ID:124330 发表于 2016-7-16 22:53 来自手机 | 只看该作者
楼主可以给个完整程序吗?1543921814@qq.com   谢谢哦
回复

使用道具 举报

20#
ID:137079 发表于 2016-8-18 20:16 | 只看该作者
楼主可以给个完整程序吗?2428784068@qq.com   谢谢楼主
回复

使用道具 举报

21#
ID:143094 发表于 2016-10-17 18:35 | 只看该作者
求完整文件,谢谢伟大楼主,10247451532@qq.com
回复

使用道具 举报

22#
ID:146045 发表于 2016-11-14 13:33 | 只看该作者
资料不错
回复

使用道具 举报

23#
ID:139660 发表于 2017-2-26 18:33 | 只看该作者
楼主,我想看看子程序是怎么写的。邮箱:876623863@163.com
谢谢楼主!
回复

使用道具 举报

24#
ID:230689 发表于 2017-9-3 23:43 | 只看该作者
楼主可以给个完整程序吗 1374679043@qq.com谢谢!
回复

使用道具 举报

25#
ID:221145 发表于 2017-10-16 10:11 | 只看该作者
感谢分享,借鉴
回复

使用道具 举报

26#
ID:256390 发表于 2017-12-3 08:15 | 只看该作者
感谢楼主
回复

使用道具 举报

27#
ID:253767 发表于 2017-12-24 08:55 | 只看该作者
大家都很渴求,谢谢分享
回复

使用道具 举报

28#
ID:380389 发表于 2018-10-14 23:04 | 只看该作者
能帮我把蓝牙那部分的程序去掉吗?多了蓝牙那部分的程序,我就看不明白了,拜托了,谢谢了
如果弄出来后发到我邮箱2797231135@qq.com 好么?谢谢了,你很棒,我很需要你的帮助
回复

使用道具 举报

29#
ID:380389 发表于 2018-12-21 17:04 | 只看该作者
请楼主分享完整程序
回复

使用道具 举报

30#
ID:780742 发表于 2021-3-17 22:59 | 只看该作者
楼主有其他头文件的代码吗?求完整代码
回复

使用道具 举报

31#
ID:780742 发表于 2021-3-17 23:27 | 只看该作者
感谢楼主,求proteus仿真原理图
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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