fengyiyu1006 发表于 2012-10-15 23:14:42

问关于四轴控制时间周期的问题。(已解决)

本帖最后由 fengyiyu1006 于 2012-10-16 11:43 编辑

请问轴友们:
    最近在做一个三轴6电机,控制周期上遇到了问题,请问四轴控制的周期一般多少合适啊?
    我在学校做智能车时学校提供例程,里面是用5ms的定时中断精确循环,于是我受到启发,在写程序时主函数是一个中断级别较低的接收机解码程序,然后用systick的高级别定时中断实现其他控制,另有最高级别的中断用于加速度计自由落体中断等。
    程序一块一块的写,刚开始没问题,但是当几块和在一起时,发现解码程序根本不执行了,用示波器看了一下,由于我的四个传感器全是iic接口,又用的是模拟iic,导致一个single_read()函数都需要执行283.33us,每个传感器数据读取平局耗时7.06ms,总共28.23ms。有点小担心啊,还计划用5ms中断,连一个传感器都读不完,跟别说后面的数据融合和控制了。
    加速度计是BMA020,陀螺仪是MPU3050,电子罗盘HMC5883L,气压计BMP085 。

    如果这样长的时间能保证控制精度的话,我就继续往下写,不然就要想办法精简算法了,后面的数据融合和控制算法都用的很庞大的东西。

    {:2_31:} 等高手指点啊》》》。。。


+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
问题已经解决:
    程序主要是iic读数据用的时间太长,后来检查时一句一句的读,其他的都注释掉,然后用示波器看时间,终于找到病因了。
    在读取BMP085的气压和温度的两个小函数里有长达5ms的延时,以前是为了保证读数准确,写飞控就直接拷过来了,注释掉后发现无影响,现在肉眼观察iic几乎不占时间。
    谢之前几位网友的提示指点。

   

john800422 发表于 2012-10-16 01:20:33

"每个传感器数据读取平局耗时7.06ms"
感觉太久了
不知是使用什么MCU?
目前STM32 400Hz取样加算法还很OK

fengyiyu1006 发表于 2012-10-16 10:05:45

john800422 发表于 2012-10-16 01:20 static/image/common/back.gif
"每个传感器数据读取平局耗时7.06ms"
感觉太久了
不知是使用什么MCU?


    用的确实是stm32f103rbt6,主要是模拟iic中的delay函数太多,用硬件iic的话感觉太麻烦,之前潜水听大家说stm32的硬件iic比较难搞
   400Hz的话周期是2毫秒多,看来程序有问题,我再改改
   {:3_48:} 谢了

40342zz 发表于 2012-10-16 11:22:33

IIC延时可以适当减少甚至去掉

fengyiyu1006 发表于 2012-10-16 11:29:51

40342zz 发表于 2012-10-16 11:22 static/image/common/back.gif
IIC延时可以适当减少甚至去掉

    我觉得可能是某些细节地方设置不对,现在函数是这样子的:
          void I2C_delay(void)
                  {
              __nop(); __nop();
                  }
    已经很简单了,但是还是那个问题,我正在检查...

另外模拟iic程序是淘宝买东西附带的,百度也有:(能读数,就是太慢,我正在看时钟配置对不对)
bool I2C_Start(void)            
{                                                                                                                                                               
        SDA_H;
        SCL_H;
        I2C_delay();
        if(!SDA_read)return FALSE;                         //SDA线为低电平则总线忙,退出
        SDA_L;
        I2C_delay();
        if(SDA_read) return FALSE;                         //SDA线为高电平则总线出错,退出
        SDA_L;
        I2C_delay();
        return TRUE;
}
void I2C_Ack(void)
{       
        SCL_L;
        I2C_delay();
        SDA_L;
        I2C_delay();
        SCL_H;
        I2C_delay();
        SCL_L;
        I2C_delay();
}
void I2C_NoAck(void)
{       
        SCL_L;
        I2C_delay();
        SDA_H;
        I2C_delay();
        SCL_H;
        I2C_delay();
        SCL_L;
        I2C_delay();
}
bool I2C_WaitAck(void)                                      //返回为:=1有ACK,=0无ACK
{
        SCL_L;
        I2C_delay();
        SDA_H;                       
        I2C_delay();
        SCL_H;
        I2C_delay();
        if(SDA_read)
        {
      SCL_L;
          I2C_delay();
      return FALSE;
        }
        SCL_L;
        I2C_delay();
        return TRUE;
}
void I2C_SendByte(u8 SendByte)                           //数据从高位到低位
{
    u8 i=8;
    while(i--)
    {
      SCL_L;
      I2C_delay();
      if(SendByte&0x80)
      SDA_H;
      else
      SDA_L;   
      SendByte<<=1;
      I2C_delay();
                SCL_H;
      I2C_delay();
    }
    SCL_L;
}
unsigned char I2C_RadeByte(void)                           //数据从高位到低位
{
    u8 i=8;
    u8 ReceiveByte=0;

    SDA_H;                               
    while(i--)
    {
      ReceiveByte<<=1;      
      SCL_L;
      I2C_delay();
          SCL_H;
      I2C_delay();       
      if(SDA_read)
      {
      ReceiveByte|=0x01;
      }
    }
    SCL_L;
    return ReceiveByte;
}
bool Single_Write(unsigned char SlaveAddress,unsigned char REG_Address,unsigned char REG_data)
{
        if(!I2C_Start())return FALSE;
    I2C_SendByte(SlaveAddress);   //发送设备地址+写信号//I2C_SendByte(((REG_Address & 0x0700) >>7) | SlaveAddress & 0xFFFE);//设置高起始地址+器件地址
    if(!I2C_WaitAck()){I2C_Stop(); return FALSE;}
    I2C_SendByte(REG_Address );                                             //设置低起始地址      
    I2C_WaitAck();       
    I2C_SendByte(REG_data);
    I2C_WaitAck();   
    I2C_Stop();
    delay5ms();
    return TRUE;
}
unsigned char Single_Read(unsigned char SlaveAddress,unsigned char REG_Address)
{   unsigned char REG_data;          
        if(!I2C_Start())return FALSE;
    I2C_SendByte(SlaveAddress); //I2C_SendByte(((REG_Address & 0x0700) >>7) | REG_Address & 0xFFFE);//设置高起始地址+器件地址
    if(!I2C_WaitAck()){I2C_Stop();test=1; return FALSE;}
    I2C_SendByte((u8) REG_Address);                            //设置低起始地址      
    I2C_WaitAck();
    I2C_Start();
    I2C_SendByte(SlaveAddress+1);
    I2C_WaitAck();

        REG_data= I2C_RadeByte();
    I2C_NoAck();
    I2C_Stop();
    //return TRUE;
        return REG_data;

}

40342zz 发表于 2012-10-16 11:38:53

告诉你个秘密你下的程序是用在51上的{:titter:}51两个空指令2usSTM32是多少?目测WaitAck等待时间也太短用硬件仿真或者示波器看看吧

fengyiyu1006 发表于 2012-10-16 11:46:41

40342zz 发表于 2012-10-16 11:38 static/image/common/back.gif
告诉你个秘密你下的程序是用在51上的51两个空指令2usSTM32是多少?目测WaitAck等待时间 ...

    嗯,这个在stm32上也能用,这里的__nop();不追求准确,只是为了小延时一下,经测试传感器数据读取正常。另外的延时函数也是用的这个(systick中断用作控制周期定时了),那里我就是用示波器调的,还是挺准的。

enthier 发表于 2012-10-16 14:10:38

用硬件吧,没什么问题,一直用。

fengyiyu1006 发表于 2012-10-16 22:40:25

enthier 发表于 2012-10-16 14:10 static/image/common/back.gif
用硬件吧,没什么问题,一直用。

    开始时试了一下,一是不会,学一句,写一句;另外中断太多,配置的iic不运行。

john800422 发表于 2012-10-17 00:37:37

fengyiyu1006 发表于 2012-10-16 22:40 static/image/common/back.gif
开始时试了一下,一是不会,学一句,写一句;另外中断太多,配置的iic不运行。 ...

可以是看我之前改写的
http://www.amobbs.com/thread-5492852-1-1.html
下面有完整测试程序

或许会有帮助

fengyiyu1006 发表于 2012-10-17 12:01:56

40342zz 发表于 2012-10-16 11:38 static/image/common/back.gif
告诉你个秘密你下的程序是用在51上的51两个空指令2usSTM32是多少?目测WaitAck等待时间 ...

等待时间确实不够,已经改成5次i--循环了

__@ 发表于 2012-10-17 12:08:52

果断用硬件I2CDMA方式读取
直接无视采样时间,控制周期就看你自己随便了

fengyiyu1006 发表于 2012-10-17 12:33:23

__@ 发表于 2012-10-17 12:08 static/image/common/back.gif
果断用硬件I2CDMA方式读取
直接无视采样时间,控制周期就看你自己随便了

嗯,正在尝试
前面有“john800422 ”的代码范例,我正在学习
页: [1]
查看完整版本: 问关于四轴控制时间周期的问题。(已解决)