打印
[STC单片机]

关于MPU6050不同角度控制舵机不同角度的转动,请大神给予...

[复制链接]
3788|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
502650182|  楼主 | 2017-6-12 14:29 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我想通过MPU6050角度传感器来实现改变不同的角度从而控制舵机不同角度的转动,但在实际操作中遇到了问题,请各位大神指点。
在不加MPU6050时单独通过按键控制舵机没有问题,单独测试MPU6050得到的角度也没有问题。
把他们写到一块就有问题了。我通过示波器发现是中断时舵机的周期有问题。
定时器每隔20ms进一次中断,经测试,程序中的中断时间没有问题。舵机的周期也确实是20ms,我单独给2ms高电平,18ms低电平,也完全没有问题。
但是在中断中我通过给一个for循环来控制舵机的高电平就开始出现问题了。for循环中a是我通过MPU6050得到的角度换算的一个值,通过改变a来实现高电平的不同时间。一但加入这个for循环后,舵机的周期立刻从原来的20ms变为220ms左右,我没搞懂为什么会这样变化,请各位大神给我点指点、建议,谢谢。
#include<STC12C5A60S2.h>
#include<math.h>
#include<stdio.h>
#include<INTRINS.H>


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


signed int a;


/********功能模块头文件**********/
#include"MPU6050.h"
#include"lcd1602.h"


//******角度参数************
float Accel_ax;
float Accel_ay;
float Accel_az;             //X轴加速度值暂存
float Angle;         //小车最终倾斜角度


//******产生PWM参数************
sbit pwm = P2^2;


//*********************************************************
//延时
//*********************************************************
void delay10us(unsigned char a)//每10微秒误差-0.234375us
{
   unsigned char b,c;
   for(b=a;b>0;b--)
      for(c=2;c>0;c--);
}


void Delay100us()                //@11.0592MHz
{
        unsigned char i, j;


        i = 2;
        j = 15;
        do
        {
                while (--j);
        } while (--i);
}


void Delay2ms()                //@11.0592MHz
{
        unsigned char i, j;


        i = 22;
        j = 128;
        do
        {
                while (--j);
        } while (--i);
}


//*********************************************************
// 倾角计算
//*********************************************************


float Angle_Calcu(void)         
{
//        Accel_ax  = GetData(ACCEL_XOUT_H);          //读取X轴加速度
        Accel_ay  = GetData(ACCEL_YOUT_H);           //读取Y轴加速度
        Accel_az  = GetData(ACCEL_ZOUT_H);          //读取z轴加速度
//        Angle = (int)(atan(Accel_ax/Accel_az)*180/3.14);   //读取XZ平面角度
//        Angle = (int)(atan(Accel_ax/Accel_ay)*180/3.14);   //读取XY平面角度
        Angle = (int)(atan(Accel_ay/Accel_az)*180/3.14);   //读取YZ平面角度
        Angle=(int)(Angle+90.0);
    if(30<=(int)Angle<=90)
        {
            Angle=0.0029*Angle*Angle+1.1795*Angle-39.3514;  //实际角度值
        }
        else if(90<(int)Angle<=180)
        {
            Angle=(-0.0029)*Angle*Angle+2.2359*Angle-87.741;
        }
        return         Angle;                                                                                                          
}




//*********************************************************
//定时器0初始化
//*********************************************************
void Timer0_Init(void)                                //100微秒11.0592MHz
{
        AUXR &= 0x7F;                //定时器时钟12T模式
        TMOD &= 0xF0;                //设置定时器模式
        TMOD |= 0x01;            //设置定时器模式
    TL0 = 0x00;                //设置定时初值
        TH0 = 0xB8;                //设置定时初值
        EA = 1;             //开总中断
        ET0 =  1;                 //开T0中断
        TR0 = 1;                    //定时器0开始计时
}


//*********************************************************
//定时器0中断                                  //问题主要出在这一块,但我没想到什么好的方法,请各位大神给予指点,谢谢。
//*********************************************************
void Timer0(void)interrupt 1
{
    TL0 = 0x00;                //设置定时初值
        TH0 = 0xB8;                //设置定时初值   
        pwm = 1;
        for(;a>0;a--)                           
        {
            Delay100us();
        }
//    Delay2ms();
        pwm = 0;
}




//*********************************************************
//主函数
//*********************************************************
void main()
{        
    float jiaodu_1;
        int sj_jiaodu_1;
        delay(500);                //上电延时
    InitMPU6050();        //初始化MPU6050
        InitLcd();                //液晶初始化
        delay(150);
        Timer0_Init();
        pwm = 0;
        while(1)
        {       
                jiaodu_1=Angle_Calcu();
                sj_jiaodu_1 = (int)(0.00001*jiaodu_1*jiaodu_1+0.2021*jiaodu_1+4.7779);         
                a = (int)(0.64*sj_jiaodu_1+29);
                lcd_printf(dis,jiaodu_1);                        //转换数据显示
            DisplayListChar(2,0,dis,4);
//                DelayMS(100);DelayMS(100);DelayMS(100);DelayMS(100);DelayMS(100);DelayMS(100);
//                DelayMS(10);
                delay(1000);
        }
}

相关帖子

沙发
502650182|  楼主 | 2017-6-12 14:33 | 只看该作者
程序中定时时间是20ms,不是100us。备注的时候忘了改了。

使用特权

评论回复
板凳
kingTek| | 2017-6-12 17:49 | 只看该作者
*中断程序不得有延时 ,中断的体系结构不能这么写,中断要尽可能短小。
*a为整形变量,(;a>0;a--) ,不知会编译为什么样的实际代码,时序不乱是偶然,
控制舵机角度至于要动用角度传感器么,我们的舵机直接用原来的电位器,摘除原电路模块,换上我们自己开发升级的CPU主控板,基本上任何市售舵机都可以秒变数控总线舵机,
https://bbs.21ic.com/icview-1703968-1-1.html
可以看舵机的动作视频。

使用特权

评论回复
地板
xxdcq| | 2017-6-12 17:55 | 只看该作者
6050计算姿态角度是非常耗时间的,基本上都要好几ms的时间,是不是这个时间把你的20ms定时搞乱了

使用特权

评论回复
5
502650182|  楼主 | 2017-6-12 18:00 | 只看该作者
kingTek 发表于 2017-6-12 17:49
*中断程序不得有延时 ,中断的体系结构不能这么写,中断要尽可能短小。
*a为整形变量,(;a>0;a--) ,不知会 ...

哦哦,好的。谢谢。我是想通过角度传感器来控制舵机转动,有一个主从关系。

使用特权

评论回复
6
502650182|  楼主 | 2017-6-12 18:02 | 只看该作者
xxdcq 发表于 2017-6-12 17:55
6050计算姿态角度是非常耗时间的,基本上都要好几ms的时间,是不是这个时间把你的20ms定时搞乱了 ...

哦哦,好的,谢谢。我再想一想怎么写这个程序能完成我想要的结果。

使用特权

评论回复
7
@502650182    请问您改好了没?,想学习一下

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

4

主题

10

帖子

0

粉丝