feng741 发表于 2011-5-6 22:18:22

无刷电机转起来了,但是启动时常卡死,请大家谈下自己的启动策略和经验

首先非常感谢墨鸢大侠的电调攻略!
我的程序也是参考德国程序,做了精简。下面是启动函数和主函数。
void Anwerfen(unsigned char pwm)
{
    unsigned long timer = 300,i;
    DISABLE_SENSE_INT;//&关中断
    PWM = 50;
    SetPWM();
    Manuell();
    _delay_ms(200);
        PWM = pwm;
        SetPWM();
    while(1)
      {
                        for(i=0;i<timer; i++)
                        {
                                _delay_us(100);
                        }
                        timer-= timer/15+1;
                        if(timer < 25) return;

                        Manuell();
                        Phase++;
                        Phase %= 6;
                        if(SENSE)
                        {
                                PORTA ^= 0x80;
                        }
      }
}

int main (void)
{
        PortInit();
        TimerInit();

        ADCmpInit();
        ADMUX = 1;
        Anwerfen(10);
        Phase--;
        PWM=255;
        SetPWM();
        SENSE_TOGGLE_INT;
        ENABLE_SENSE_INT;
        sei();

        while(1);
}
启动的换向时间受PWM占空比、“timer-= timer/15+1;”、“_delay_us(100);”、“timer=300”和电机特性的影响。同样的程序换了个不同的电机就不一定能启动了。请问各位你们是怎么确定这些参数的,有什么经验,不要说完全的瞎试凑哦。或者有其他的好一点的启动方法不,我看了一些别的,好像是又复杂又没什么优势。有没有能够带任意负载启动的方法?谢谢了!我看到TI有篇文档用TMS320F240做的,在3.2.7节讲到启动算法,但得获得转动惯量和转矩等参数。看的有点不太懂,后边的程序是用汇编写的好长,我只会看C的,无奈。我传上来各位高手看先具体是怎么做的。
Implementation of a Sensorless Speed Controlled Brushless DC driveourdev_637716SO8K3D.pdf(文件大小:235K) (原文件名:bpra072.pdf)

feng741 发表于 2011-5-7 11:54:19

怎么没人回答啊,自己顶一个。

NE555 发表于 2011-5-7 11:59:32

不是那么简单吧。这程序。

feng741 发表于 2011-5-8 01:11:20

回复【2楼】NE555
-----------------------------------------------------------------------

完整程序在这里,改成了M16的。最精简版,去掉电流检测部分,只剩启动和运行两部分了。
环境:ATMEGA16,主频16M,编译器WINAVR。
新手入门电调的可以参考这个程序,不用上来就看那个庞大的程序了。

哪位路过的能不能顺便回复一下呗,发表下意见啊,这么问题应该不菜吧!谢谢了!
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>


#define PWM_C_ON{TCCR1A = 0x81; TCCR2= 0x41; PORTD &= ~(1<<7 | 1<<4);}
#define PWM_B_ON{TCCR1A = 0x21; TCCR2= 0x41; PORTD &= ~(1<<7 | 1<<5);}
#define PWM_A_ON{TCCR1A = 0x01; TCCR2= 0x61; PORTD &= ~(1<<5 | 1<<4);}
#define PWM_OFF   {TCCR1A = 0x01; TCCR2= 0x41; PORTD &= ~(1<<7 | 1<<5 | 1<<4);}

#defineSTEUER_A_H {PWM_A_ON}
#defineSTEUER_B_H {PWM_B_ON}
#defineSTEUER_C_H {PWM_C_ON}

#defineSTEUER_A_L {PORTB &= ~(1<<6 | 1<<7); PORTB |= 1<<5;}
#defineSTEUER_B_L {PORTB &= ~(1<<5 | 1<<7); PORTB |= 1<<6;}
#defineSTEUER_C_L {PORTB &= ~(1<<5 | 1<<6); PORTB |= 1<<7;}
#defineSTEUER_OFF {PORTB &= ~(1<<5 | 1<<6 | 1<<7); PWM_OFF;}

#define SENSE_A ADMUX = 0;
#define SENSE_B ADMUX = 1;
#define SENSE_C ADMUX = 2;

#define ClrSENSE            ACSR |= 0x10
#define SENSE               ((ACSR & 0x10))
#define SENSE_L             (!(ACSR & 0x20))
#define SENSE_H             ((ACSR & 0x20))
#define ENABLE_SENSE_INT    {CompInterruptFreigabe = 1;ACSR |= 0x0A; }
#define DISABLE_SENSE_INT   {CompInterruptFreigabe = 0; ACSR &= ~0x08; }


#define SENSE_FALLING_INT    ACSR &= ~0x01
#define SENSE_RISING_INT    ACSR |= 0x03
#define SENSE_TOGGLE_INT    ACSR &= ~0x03

volatile unsigned char Phase = 0,ShadowTCCR1A = 0;
volatile unsigned char CompFreigabeTimer = 100;
volatile unsigned char CompInterruptFreigabe = 0;
volatile unsigned char PWM=0;




void PortInit()
{
        DDRA=0xf0;
        PORTA=0xf0;
        DDRB=0xe0;
        PORTB=0xfb;
        DDRD=0xb2;
        PORTD=0xff;       

        PORTB &= ~((1<<5) | (1<<6) | (1<<7));//初始化置低N管电平引脚
        PORTD &= ~((1<<7) | (1<<5) | (1<<4));//初始化置低P管PWM引脚
        PORTA |= 0xf0;//PORTA高4位接测试用LED
}
void TimerInit()
{
        //TCCR2=0x69;//8位相频修正,32KHz
        TCCR2=1<<WGM20 | 0<<WGM21 | 1<<CS20;//1<<COM21 | 0<<COM20 | ;
        TCNT2=0;
        OCR2=0;
        TCCR1A=0<<WGM11 | 1<<WGM10;//1<<COM1A1 | <<COM1A0 | 1<<COM1B1 | <<COM1B0
        TCCR1B=0<<WGM13 | 0<<WGM12 | 0<<CS12 | 0<<CS11 | 1<<CS10;
        TCNT1=0;
        OCR1A=0;
        OCR1B=0;
}

void ADCmpInit()
{
        SFIOR=1<<ACME;
}


SIGNAL(SIG_COMPARATOR)
{
unsigned char sense = 0;
PORTA &= ~(1<<6);
do
{
if(SENSE_H) sense = 1; else sense = 0;
switch(Phase)
{
   case 0:
         STEUER_A_H;
         if(sense)
            {
                      STEUER_C_L;
            TCNT2 = 1;
            SENSE_FALLING_INT;
            SENSE_B;
            Phase++;
             }
                       else
             {
            STEUER_B_L;
             }
          break;
   case 1:
             STEUER_C_L;
         if(!sense)
            {
            STEUER_B_H;
            TCNT2 = 1;
            SENSE_A;
            SENSE_RISING_INT;
            Phase++;
             }
             else
             {
               STEUER_A_H;
             }

          break;
   case 2:
         STEUER_B_H;
         if(sense)
            {
                         STEUER_A_L;
            TCNT2 = 1;
            SENSE_C;
            SENSE_FALLING_INT;
            Phase++;
             }
             else
             {
            STEUER_C_L;
             }
            
          break;
   case 3:
               STEUER_A_L;
         if(!sense)
            {
                         STEUER_C_H;
            TCNT2 = 1;
            SENSE_B;
            SENSE_RISING_INT;
            Phase++;
             }
             else
             {
            STEUER_B_H;
             }
            

          break;
   case 4:
               STEUER_C_H;
         if(sense)
            {
                         STEUER_B_L;
            TCNT2 = 1;
            SENSE_A;                           
            SENSE_FALLING_INT;
            Phase++;
             }
                        else
             {
            STEUER_A_L;
             }
            
          break;
   case 5:
                 STEUER_B_L;
         if(!sense)
            {
                         STEUER_A_H;
            TCNT2 = 1;
            SENSE_C;
            SENSE_RISING_INT;
            Phase = 0;
             }
             else
             {
            STEUER_C_H;
             }
          break;
}
}
while((SENSE_L && sense) || (SENSE_H && !sense));
}


void Manuell(void)
{
switch(Phase)
{
   case 0:
         STEUER_A_H;
                   STEUER_B_L;
         SENSE_C;
         SENSE_RISING_INT;
          break;
   case 1:
         STEUER_A_H;
                   STEUER_C_L;
         SENSE_B;
         SENSE_FALLING_INT;
          break;
   case 2:
         STEUER_B_H;
                   STEUER_C_L;
         SENSE_A;
         SENSE_RISING_INT;
          break;
   case 3:
         STEUER_B_H;
                   STEUER_A_L;
         SENSE_C;
         SENSE_FALLING_INT;
          break;
   case 4:
         STEUER_C_H;
                   STEUER_A_L;
         SENSE_B;
         SENSE_RISING_INT;
          break;
   case 5:
         STEUER_C_H;
                   STEUER_B_L;
         SENSE_A;
         SENSE_FALLING_INT;
          break;
}
}


void SetPWM()
{
        unsigned char tmp_pwm;
        tmp_pwm=PWM;
        OCR1A=tmp_pwm;
        OCR1B=tmp_pwm;
        OCR2=tmp_pwm;
}


void Anwerfen(unsigned char pwm)
{
    unsigned long timer = 300,i;
    DISABLE_SENSE_INT;//&关中断
    PWM = 50;
    SetPWM();
    Manuell();
    _delay_ms(200);
        PWM = pwm;
        SetPWM();
    while(1)
      {
                        for(i=0;i<timer; i++)
                        {
                                _delay_us(100);
                        }
                        timer-= timer/15+1;
                        if(timer < 25) return;

                        Manuell();
                        Phase++;
                        Phase %= 6;
                        if(SENSE)
                        {
                                PORTA ^= 0x80;
                        }
      }
}

int main (void)
{
        PortInit();
        TimerInit();

        ADCmpInit();
        ADMUX = 1;
        Anwerfen(10);
        Phase--;
        PWM=255;
        SetPWM();
        SENSE_TOGGLE_INT;
        ENABLE_SENSE_INT;
        sei();

        while(1);
}
点击此处下载 ourdev_638198OT15K3.rar(文件大小:1K) (原文件名:main.rar)

feng741 发表于 2011-5-8 01:24:54

ATMEGA16接线图,用的现成的最小系统版,没画protel了,H桥和德国的一样的N、P管的。
http://cache.amobbs.com/bbs_upload782111/files_39/ourdev_638200NIK4AC.jpg
(原文件名:QQ截图未命名3.jpg)

vague2010 发表于 2011-5-9 23:14:21

就我现在的理解,起动想不经过测试用一个程序起动不同的负载或是不同电机,不 同电压,还无法做到。

无刷无感在起动时是完全的盲操作,基本不知道电机处于一个什么位置。

MK的Anwerfen()我想也应该是经过测试的,用于他们的那个电机估计效果应该不错。

但我现在应用在硬盘电机,基本不管用。

要自己写测试的程序,测试电机。反正也挺麻烦的。
我现在也有许多问题搞不错。

NE555 发表于 2011-5-9 23:25:39

谢谢楼主的程序。
可以说也是很长的。
估计有三百行啦。
如果是自己写还可以理解。别人写的就有点困难啦。
可否苛求楼主编写一点注释。
最好写出流程。
一来方便这里的新手。
二来方便楼主维护程序。
因为小弟真的看不懂。

lg2911 发表于 2011-5-11 22:20:29

不知道商业电调是怎么能适应不同电机启动的

好像现在国内杂牌电调的启动适应性也已经很好了

vague2010 发表于 2011-5-11 22:58:58

电路上都是外在的应该没有太多问题
我想主要还是在软件上
起动这一块是个关键啊!

现在我也在想不同的起动方法,不过还没有什么好的思路

tian179587568 发表于 2011-5-16 14:52:13

如果开环启动正常,进入闭环卡死,我是这样理解的。开环的时候效率低,转速也低,进入闭环稳定后的转速在相同占空比下相对开环是比较高的。那么从开环进入闭环就会有一个加速的过程。实际上上从开环进入闭环的加速度是一定的,如果开环与闭环的速度相差太大,那么对应的加速度也就会很大,当这个加速度超过实际加速度时久会出现失步的情况,甚至是卡死。这个时候往往你用手帮一把电机,他就会进入闭环。解决问题的办法我觉得有两个,一个是开环启动时,把换相延时设得低一些;另一个就是将进入闭环后的PWM占空比设得相对开环时低一些。    我也是正在学习无刷的驱动,也不知道怎么解释,希望对你有帮助。

feng741 发表于 2011-5-19 22:56:43

谢谢楼上几位的回答。但都没给出使用的方法。希望对无传感器无刷电机的启动有深入研究的老师能发表下想法。我更想了解除了三步法之外的算法。谢谢了!

jayzah 发表于 2011-10-17 13:19:04

mark

zcp17521 发表于 2011-12-22 11:35:23

请问楼主的问题解决了吗?

talangxue 发表于 2012-1-6 22:30:49

我也碰到同样的问题啊,哎,同问为什么商业电调能适应那么多电机啊

guoreny 发表于 2012-1-25 21:43:30

按个爪印

banjiaoshi 发表于 2012-5-13 23:05:33

发一个论文,希望对lz有用,也希望大家共同解决~

AsMap 发表于 2012-5-15 08:22:08

无刷电机控制有速度环和电流环,我觉得可以在电流上做点文章。。。

hgy_tom 发表于 2013-1-16 15:04:40

mark!!!学习
页: [1]
查看完整版本: 无刷电机转起来了,但是启动时常卡死,请大家谈下自己的启动策略和经验