搜索
bottom↓
回复: 15

请教无刷的电路及驱动程序(无刷电机/48v)

[复制链接]

出0入0汤圆

发表于 2007-4-18 17:24:54 | 显示全部楼层 |阅读模式
我现在正在做一个无刷电机驱动电路和程序,但是以前没有作过类似的东西,希望那位大侠可以

提供点资料,小弟不胜感激.或发到我的邮箱lizq791003@126.com

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

 楼主| 发表于 2007-4-18 19:34:50 | 显示全部楼层
急,谢谢各位了...

出0入0汤圆

发表于 2007-4-18 19:49:49 | 显示全部楼层
给一个网上的无刷控制器C程序,看看原理吧.



/************************************************************************/



(PIC电动车双闭环程序)



#include    <pic.h>



//电动车双闭环程序,采用双闭环方式控制电机,以得到最好的zh转速性能,并且可以



//限制电机的最大电流。本应用程序用到两个CCP部件,其中CCP1用于PWM输出,以控



//制电机电压;CCP2用于触发AD,定时器TMR2、TMR1,INT中断,RB口电平变化中断,



//看门狗以及6个通用I/O口



#define AND  0xe0        //状态采集5,6,7位   



#define CURA 0X0a        //电流环比例和积分系数之和



#define CURB 0X09        //电流环比例系数



#define THL  0X6400      //电流环最大输出



#define FULLDUTY 0X0FF    //占空比为1时的高电平时间



#define SPEA 0X1d        //转速环比例和积分系数之和



#define SPEB 0X1c        //转速环比例系数



#define    GCURHILO 0X0330  //转速环最大输出



#define GCURH 0X33        //最大给定电流



#define GSPEH 0X67        //最大转速给定



#define TSON 0X38        //手柄开启电压1.1 V,TSON*2为刹车后手柄开启电压,即



                         //2.2 V



#define VOLON 0X4c        //低电压保护重开电压3.0 V即33 V



#define VOLOFF 0X49        //低电压保护关断电压2.86 V即31.5 V



volatile unsigned char DELAYH,DELAYL,oldstate,speed,



    speedcount,tsh,count_ts,count_vol,gcur,currenth,



    voltage;                    //寄存器定义



static bit sp1,spe,ts,volflag,spepid,lowpower,



    off,shutdown,curpid;     //标志位定义



static volatile unsigned char new[10]={0xaf,0xbe,0xff,0x7e,0xcf,



    0xff,0xd7,0x77,0xff,0xff};    //状态寄存器表



//------------PIC16F877初始化子程序------------



void INIT877()



{   



    PORTC=0X0FF;         //关断所有MOSFET



    TRISC=0X02;          //设置C口输出



   PIE1=0X00;            //中断寄存器初始化,关断所有中断



    TRISA=0XCF;          //设置RA4,RA5 输出



    TRISB=0XEF;          //RB 口高三位输入,采集电机三相的霍尔信号



    PORTC=new[(PORTB&AND)>>5];    //采集第一次霍尔信号,并输出相应的信号,导通



//两个MOS管



    T2CON=0X01;          //TMR2 4分频



    CCPR1L=0X0FF;        //初始时PWM输出全高



    CCP1CON=0X0FF;       //CCP1设置为PWM方式



    CCP2CON=0X0B;        //CCP2设置为特殊方式,以触发AD



    ADCON0=0X81;         //AD时钟为32分频,且AD使能,选择AN0通道采集手



//柄电压



   TMR2=0X00;            //TMR2寄存器初始化



    TMR1H=0X00;          //TMR1寄存器初始化



    TMR1L=0X00;



    T1CON=0X00;          //TMR1为1分频



    CCPR2H=0X08;



    CCPR2L=0X00;         //电流采样周期设置为TAD=512 μs



    PR2=0XC7;            //PWM频率设置为5 kHz



    ADCON1=0X02;         //AD结果左移



    OPTION=0XFB;         //INT上升沿触发



    TMR2ON=1;            //PWM开始工作



    INTCON=0XD8;         //中断设置GIE=1,PEIE=1,RBIE=1



    ADIE=1;             //AD中断使能



    speedcount=0x00;     //转速计数寄存器



    speed=0x7f;          //转速保持寄存器



    spe=1;              //低速标志位



    sp1=1;              //低速标志位



    oldstate=0x0ff;      //初始状态设置,区别于其他状态



    count_ts=0x08;       //电流采样8次,采集1次手柄



    count_vol=0x00;      //采样256次手柄,采集1次电池电压



    ts=1;               //可以采集手柄值的标志位



    ADGO=1;             //AD采样使能



    TMR1ON=1;            //CCP2部件开始工作



}



//------------延时子程序---------------



#pragma interrupt_level 1



void DELAY1(x)



char x;



{



    DELAYH=x;            //延时参数设置



#asm



DELAY2  MOVLW    0X06



    MOVWF    _DELAYL



DELAY1    DECFSZ    _DELAYL



    GOTO    DELAY1



    DECFSZ    _DELAYH



    GOTO    DELAY2



#endasm



}



//-----------状态采集子程序----------------------



void sample()



{



    char state1,state2,state3,x;



    do  {



        x=1;



        state1=(PORTB&AND);      //霍尔信号采集



        DELAY1(x);



        state2=(PORTB&AND);



    }while(state1-state2);        //当三次采样结果不相同时继续采集状态



    if(state1-oldstate!=0)        //看本次采样结果是否与上次相同,不同



//则执行



     {oldstate=state1;            //将本次状态设置为旧状态



      state1=(oldstate>>5);



      PORTC=new[state1];           //C口输出相应的信号触发两个MOS管



      if(sp1==1){spe=1;sp1=0;}



      else  {                    //如果转速很低,则spe置1



spe=0;sp1=0;



        speedcount<<=1;



        state3=(TMR1H>>2);       //否则,spe=0,计转速



        speed=speedcount+state3;    //speed寄存器为每256 μs加1



      }



      speedcount=0;



    }



}



//-----------------AD采样子程序----------------------



void AD()



{



    char x;



    ADIF=0;                 //清AD中断标志位



    if(ts==1){               //如果为手柄采样,则采样手柄值



     CHS0=1;                    //选择电流采样通道



     count_vol=count_vol+1;    //电池采样计数寄存器



    spepid=1;                //置转速闭环运算标志



     ts=0;tsh=ADRESH;     //存手柄值



     if(count_vol==0) {   //如果电池采样时间到,则选择AN2通道,采集电池电压



        CHS0=0;CHS1=1;volflag=1;x=1;DELAY1(x);ADGO=1;



      }



    }



    else if(volflag==1) {           //电池采样完毕,进行相应的处理



       CHS1=0;CHS0=1;volflag=0;voltage=ADRESH;lowpower=1;



    }



    else    {                        //否则,中断为采样电流中断



      speedcount=speedcount+1;    //speedcount寄存器加1,作为测量转速用



      if(speedcount>0x3d)  sp1=1;    //如果转速低于1 000 000 μs/(512 μs*3eh*3)   



                                  // 则认为为低速状态



      currenth=ADRESH;



      curpid=1;



      count_ts=count_ts-1;



      if(count_ts==0) {            //如果手柄时间到,则转入手柄采样通道



          CHS0=0;count_ts=0x08;ts=1;x=1;DELAY1(x);ADGO=1;



        }



     }



}



//-------------刹车处理子程序------------------



void BREAKON()



{



    char x;



    off=0;                  //off清零,如果是干扰则不复位



    shutdown=0;



   if(RB0==1)    {           //如果刹车信号为真,则停止输出电压



    ADIE=0;              //关AD中断



        INTE=0;             //关刹车中断



        CCPR1L=FULLDUTY;     //输出电压0



        TMR1ON=0;            //关CCP2,不再触发AD



        for(;ADGO==1;)    continue;//如正在采样,则等待采样结束



        ADIF=0;             //ADIF位清零



        CHS0=0;             //选择通道0采样手柄



        CHS1=0;



        x=1;



DELAY1(x);



        do  {



            ADGO=1;



            for(;ADIF==0;)continue;



            ADIF=0;



            CCPR1L=FULLDUTY;



        asm("CLRWDT");



            tsh=(ADRESH>>1);



        }while(tsh>TSON||RB0==1); //当手柄值大于2.2 V或刹车仍旧继续时,执行以



                                 //上语句



       off=1;                    //置复位标志



  }



}



//---------欠保护子程序-------------------



void POWER()



{



    char x;



    lowpower=0;



    voltage>>=1;                 //电压值换为7位,以利于单字节运算



    if(voltage<VOLOFF) {         //电池电压小于3*k(V)时保护



    ADIE=0;



        INTE=0;



        TMR1ON=0;



        CCPR1L=FULLDUTY;



        for(;ADGO==1;)continue;



        ADIF=0;



        CHS0=0;CHS1=1;



        x=1;



DELAY1(x);



        do{ADGO=1;



            for(;ADIF==0;)continue;



            ADIF=0;



            voltage=(ADRESH>>1);



            CCPR1L=FULLDUTY;



         asm("CLRWDT");



         }while(voltage<VOLON);    //电池电压小于35 V时继续保护



       off=1;                    //置复位标志



    }



}



//------------电流环运算子程序-----------------



void CURPI()



{   static int curep=0x00,curek=0x00,curuk=0x00;



    union data{int pwm;



        char a[2];}b;            //定义电流环运算寄存器



    curpid=0;                    //清电流运算标志



    curep=curek*CURB;            //计算上一次偏差与比例系数的积



    if(currenth<2)currenth=2;     //如果采样电流为零,则认为有一个小电流以利于



//使转速下降



    currenth>>=1;



    curek=gcur-currenth;         //计算本次偏差



    curuk=curuk+curek*CURA-curep;     //按闭环PI运算方式得到本次输出结果,下



//面对结果进行处理



    if(curuk<0x00) {             //如果输出小于零,则认为输出为零



      curuk=0;CCPR1L=FULLDUTY;CCP1X=0;CCP1Y=0;   



      }



else if(curuk-THL>=0) {    //如果输出大于限幅值,则输出最大电压



            curuk=THL;CCPR1L=0;CCP1X=0;CCP1Y=0;



        }



else    {               //否则,按比例输出相应的高电平时间到CCPR1寄存器



            b.pwm=THL-curuk;



            b.pwm<<=1;



           CCPR1L=b.a[1];     //CCPR1L=(b.pwm>>8)&0x0ff;将PWM寄存器的高半字节



           if(b.pwm&0x80!=0) CCP1X=1;



           else CCP1X=0;



           if(b.pwm&0x40!=0) CCP1Y=1;



           else CCP1Y=0;



    }



}



//---------------转速环运算子程序-----------------------



void SPEPI()



{   static int speep=0x00,speek=0x00,speuk=0x00;



    int tsh1,speed1;                //转速寄存器定义



    spepid=0;                    //清转速运算标志        



   if(spe==1)    speed1=0x00;     //若转速太低,则认为转速为零



    else speed1=0x7f-speed;       //否则计算实际转速



    if(speed1<0) speed1=0;



    speep=speek*SPEB;



    tsh1=tsh-0x38;               //得到计算用的手柄值



    speek=tsh1-speed1;



   if(tsh1<0) {speuk=0;gcur=0;}    //当手柄值低于1.1 V时,则认为手柄给定为零



    else {                      //否则,计算相应的转速环输出



        if(tsh1>=GSPEH)          //限制最大转速



        tsh1=GSPEH;



    speuk=speuk+speek*SPEA-speep;    //计算得转速环输出



        if(speuk<=0X00) {speuk=0x00;gcur=0x00;}//转速环输出处理



        else if(speuk>GCURHILO)   {    //转速环输出限制,即限制最大电流约12 A



            speuk=GCURHILO;gcur=GCURH;}



        else        {                   //调速状态时的输出



            gcur=(speuk>>4)&0x0ff;



        }



    }



}



//-----------主程序-------------------------



main()



{



for(;;){



       INIT877();                //单片机复位后,先对其进行初始化



       off=0;                    //清复位标志



        for(;off==0;)    {       //复位标志为零,则执行下面程序,否则复位



        if(curpid==1) CURPI();    //电流PI运算



        else if(spepid==1)    SPEPI();    //转速PI运算



        else if(lowpower==1)  POWER();



        else if(shutdown==1)    BREAKON();



        asm("CLRWDT");



    }



  }



}



//---------中断服务子程序---------------------



#pragma interrupt_level 1



void interrupt INTS(void)



{   



    if(RBIF==1)    {RBIF=0;sample();}



    else if(ADIF==1)    AD();



    else if(INTF==1)    {shutdown=1;INTF=0;}    //刹车中断来,置刹车标志



}

出0入0汤圆

 楼主| 发表于 2007-4-19 13:25:57 | 显示全部楼层
谢谢.

谁有原理图呀,最好是avr单片机的.

出0入0汤圆

 楼主| 发表于 2007-4-19 15:54:41 | 显示全部楼层
XDM帮帮忙吧.

出0入0汤圆

 楼主| 发表于 2007-4-20 08:36:50 | 显示全部楼层
XDM帮帮忙吧.

出0入0汤圆

发表于 2007-4-20 09:40:50 | 显示全部楼层
偶也想要!

出0入0汤圆

 楼主| 发表于 2007-4-20 13:17:17 | 显示全部楼层
XDM帮帮忙吧.

出0入0汤圆

 楼主| 发表于 2007-4-20 16:25:58 | 显示全部楼层
我现在正在做一个无刷电机驱动电路和程序,但是以前没有作过类似的东西,希望那位大侠可以

提供点资料,小弟不胜感激.或发到我的邮箱lizq791003@126.com

出0入0汤圆

 楼主| 发表于 2007-4-21 15:04:01 | 显示全部楼层
XDM帮帮忙吧

出0入0汤圆

发表于 2007-4-22 22:39:46 | 显示全部楼层
学习中,顶。。。

出0入0汤圆

发表于 2012-1-28 18:45:52 | 显示全部楼层
MARK

出0入0汤圆

发表于 2012-3-6 19:32:50 | 显示全部楼层
mark

出0入0汤圆

发表于 2013-3-10 02:51:16 | 显示全部楼层
mark.....

出0入0汤圆

发表于 2013-4-16 16:37:42 | 显示全部楼层
fzdz =PIC电动车双闭环程序=要得

出0入0汤圆

发表于 2014-8-13 14:47:59 | 显示全部楼层
MARK。。。。我也刚发了个贴,想要找云台用无刷电机的驱动,貌似没人有,估计有也不愿意分享吧
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-23 12:24

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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