PIC Vietnam

PIC Vietnam (http://www.picvietnam.com/forum/index.php)
-   dsPIC - Bộ điều khiển tín hiệu số 16-bit (http://www.picvietnam.com/forum/forumdisplay.php?f=29)
-   -   dsPIC30F4011 điều khiển động cơ BLDC (http://www.picvietnam.com/forum/showthread.php?t=3241)

nvtri 03-12-2008 11:42 AM

dsPIC30F4011 điều khiển động cơ BLDC
 
Mình đang điều khiển động cơ BLDC 3 phase có cảm biến Hall, đây là đoạn code của minh cung với sơ đồ mạch, không hiểu sao chẳng có tín hiệu PWM ra gì cả, mong mọi người đọc và chỉ giúp, minh dung con IR2101S để kích cho Mosfet:

Code:

#include<p30f4011.h>
        _FOSC(CSW_FSCM_OFF & XT_PLL4);
        _FWDT(WDT_OFF);
        _FBORPOR(PBOR_OFF & MCLR_EN);
        _FGS(CODE_PROT_OFF);


#define FCY  10000000          // xtal =10 Mhz; PLLx4
#define MILLISEC FCY/10000  // 1 mSec delay constant
#define FPWM 39000
#define POLEPAIRS          5            // number of pole pairs of the motor
#define INDEX        1          // Hall sensor position index
#define RPMConstant 60*(FCY/256)    // bang 2343750 (Voi FCY = 10000000)
#define S2        !PORTCbits.RC14    // nut S2 duoc nhan thi se co gia tri bang 0
#define S3        !PORTCbits.RC13    // nut S3 duoc nhan thi se co gia tri bang 0

#define CR        0x0D        // 14
#define LF        0x0A        // 10
#define BAUD  19200            // set baud rate to 19200
#define SPEEDMULT  2343750  // factor used to calculate speed
#define OFFSET 8                  // offset in InData to load speed values
#define POTMULT 4          // pot to speed ratio

#define Kps        750        // Kp and Ks terms need to be adjusted as per
#define Kis        20        // the motor and load


void InitADC10(void);
void AverageADC(void);
void DelayNmSec(unsigned int N);
void InitMCPWM(void);
void InitUART(void);
void SendSpeed(void);
void InitTMR3(void);
void SendMsg(void);
void CalculateDC(void);



struct {
                        unsigned RunMotor :        1; 
                        unsigned CalSpeed :        1; 
                        unsigned CheckRX  :        1; 
                        unsigned SendTX  :        1; 
                        unsigned unused    :          12; 
                }        Flags;

unsigned int HallValue;   
unsigned int timer3value; 
unsigned int timer3avg;   
unsigned char polecount;   
unsigned char *TXPtr;       
unsigned char *RXPtr;     
int DesiredSpeed;         
int ActualSpeed;           
int SpeedError;           
int DutyCycle;             
int SpeedIntegral;         
unsigned char InData[] = {"000000"};
unsigned char OutData[] = {"Speed = 00000 rpm\r\n"}; 

unsigned int StateTable[] = {0x0000, 0x0210, 0x2004, 0x0204,
                                                                        0x0801, 0x0810, 0x2001, 0x0000};

/*************************************************************
        Low side driver table is as below.  In the StateLoTableClk,
        the Low side driver is a PWM while the high side driver is
        either on or off. 
*************************************************************/

unsigned int StateLoTableClk[] = {0x0000, 0x0210, 0x2004, 0x0204,
                                                                        0x0801, 0x0810, 0x2001, 0x0000};
unsigned int StateLoTableAntiClk[] = {0x0000, 0x2001, 0x0810, 0x0801,
                                                                        0x0204, 0x2004, 0x0210, 0x0000};

/****************************************************************
Interrupt vector for Change Notification CN5, 6 and 7 is as below.
When a Hall sensor changes states, an interrupt will be
caused which will vector to the routine below
The program then reads PORTB, mask bits 3, 4 and 5,
shift and adjust the value to read as 1, 2 ... 6.  This
value is then used as an offset in the lookup table StateLoTableClk
or StateLoTableAntiClk to determine the value loaded in the OCDCON
register.  This routine also reads the Hall sensors and counts
up to the POLEPAIRS to determine the time for one mechanical
revolution using the fact that 1 mech rev = POLEPAIR*(1 elect. rev)
*****************************************************************/
void __attribute__((__interrupt__)) _CNInterrupt(void)
{
        IFS0bits.CNIF = 0;                                // clear flag
        HallValue = PORTB & 0x0038;            // mask RB3,4 & 5
        HallValue = HallValue >> 3;            // shift right 3 times
        OVDCON = StateLoTableAntiClk[HallValue];
// The code below is uses TMR3 to calculate the speed of the rotor
// Khi khoi lenh chi gom mot cau lenh thi co the bo qua cac dau ngoac nhon dau"{" va cuoi"}"
        if (HallValue == INDEX)            // has the same position been sensed?
                if (polecount++ == POLEPAIRS)  // has one mech rev elasped?
                {                                                                // yes then read timer 3
                timer3value = TMR3;
                TMR3 = 0;
                timer3avg = ((timer3avg + timer3value) >> 1);
                polecount = 1;
                }
}
//---------------------------------------------------------------------
// Below are the interrupt vectors for the serial receive and transmit
//---------------------------------------------------------------------
void __attribute__((__interrupt__)) _U1TXInterrupt(void)
{
        IFS0bits.U1TXIF = 0;        // clear interrupt flag
}

void __attribute__((__interrupt__)) _U1RXInterrupt(void)
{
        IFS0bits.U1RXIF = 0;        // clear interrupt flag
        *RXPtr = U1RXREG;
        if (*RXPtr == CR)
                {Flags.CheckRX = 1;RXPtr = &InData[0];}
        else *RXPtr++;
}
 


/*********************************************************************
The ADC interrupt reads the demand pot value.

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

void __attribute__((__interrupt__)) _ADCInterrupt(void)
{
        IFS0bits.ADIF = 0;       
        DesiredSpeed = ADCBUF0;
        Flags.CalSpeed = 1;                // after every adc read,  do a PI calculation
}

int main(void)
{
        LATE  = 0x0000;
        TRISE = 0xFFC0;                // PWMs are outputs
        CNEN1 = 0x00E0;                // CN5,6 and 7 enabled
        CNPU1 = 0x00E0;                // enable internal pullups
        IFS0bits.CNIF = 0;                    // clear CNIF
        IEC0bits.CNIE = 1;                  // enable CN interrupt
        InitMCPWM();
        InitADC10();
        InitUART();
        InitTMR3();
        timer3avg = 0;
        while(1)
        {               
                while (!S2);        // wait for start key hit
                while (S2)        // wait till key is released
                        DelayNmSec(10);
                // read hall position sensors on PORTB
                HallValue = PORTB & 0x0038;  // mask RB3,4 & 5
                HallValue = HallValue >> 3;          // shift right to get value = 1, 2 ... 6
                OVDCON = StateLoTableAntiClk[HallValue];  // Load the overide control register
                PWMCON1 = 0x0777;    // enable PWM outputs
                Flags.RunMotor = 1;      // set running flag
                T3CONbits.TON = 1;    // start tmr3
                polecount = 1;
                DelayNmSec(100);
                while (Flags.RunMotor)  // while motor is running
                        {
                        if (S2)        // if S2 is pressed, stop                                                                                     
                                {
                                PWMCON1 = 0x0700; // disable PWM outputs
                                  OVDCON  = 0x0000;  // overide PWM low.
                                Flags.RunMotor = 0;  // reset run flag
                                while (S2)      // wait for key release                                       
                                        DelayNmSec(10);
                                }
                        if (Flags.CalSpeed)                // if calculate flag set then
                                {
                                SendSpeed();        // send present speed serially
                                CalculateDC();      // calculate new dutycycle using PI
                                Flags.CalSpeed = 0;  // clear flag
                                }
                        }
        }        // end of while (1)
       

}        // end of main
       
/*******************************************************************
                Below is the code required to setup the ADC registers for :
                1. 1 channel conversion (in this case RB2/AN2)
                2. PWM trigger starts conversion
                3. Pot is connected to CH0 and RB2
                4. AD interrupt is set and buffer is read in the interrupt
                                                                                                                               
*********************************************************************/
void InitADC10(void)
{

 ADPCFG = 0xFFF8;        // all PORTB = Digital;RB0 to RB2 = analog
 ADCON1 = 0x0064;        // PWM starts conversion
 ADCON2 = 0x0200;        // simulataneous sample 4 channels                                                                       
 ADCHS  = 0x0002;                // Connect RB2/AN2 as CH0 = pot 
 ADCON3 = 0x0080;        // Tad = internal RC (4uS)
 IFS0bits.ADIF = 0;
 IEC0bits.ADIE = 1;

 ADCON1bits.ADON = 1;        // turn ADC ON
}

/********************************************************************
InitMCPWM, intializes the Motor PWM as follows:
1. FPWM = 39000 hz at 10Mips
2. Independant PWMs
3. Control outputs using OVDCON
4. Init Duty Cycle with a value = 100
5. Set ADC to be triggered by PWM special trigger
*********************************************************************/

void InitMCPWM(void)
{
        PTPER = FCY/FPWM - 1; // set the pwm period register (PTPER = 255)

        PWMCON1 = 0x0700;    // disable PWMs
        OVDCON  = 0x0000;      // allow control using OVD register
        PDC1 = 100;              // init PWM DC 1, 2 and 3 to 100
        PDC2 = 100;      // tuc la chu ki nhiem vu la ((100/2)/PTPER)*100% = 19.6%
        PDC3 = 100;
        SEVTCMP = PTPER;    // set ADC to trigeer at ...
        PWMCON2 = 0x0F;      // 16 PWM values (0000 1111 0000 0000)
        PTCON  = 0x8000;            // start PWM however output ...
                                // is enabled by OVDCON which is OFF
       
}

/************************************************************************
Tmr3 is used to determine the rotor speed so it is set to count using Tcy/256

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

void InitTMR3(void)
{
        T3CON = 0x0030;// internal Tcy/256 clock (0000 0000 0011 0000); tat Timer3
        TMR3 = 0;        // 16-bits timer count register (o day bat dau dem tu 0)
        PR3 = 0xFFFF;    // 16-bits Period Register
}

void InitUART(void)
{
//---------------------------------------------------------------------
// Initialize the UART1 for BAUD = 19,200 
 U1MODE = 0x8000;
 U1STA  = 0x0000;
 U1BRG  = ((FCY/16)/BAUD) - 1; // set baud to 19200
 IEC0bits.U1RXIE = 1;            // enable RX interrupt
 RXPtr = &InData[0];            // point to first char in receive buffer
 Flags.CheckRX = 0;            // clear RX and TX flags
 Flags.SendTX = 0;

 U1STAbits.UTXEN = 1;          // Initiate transmission
}

//------------------------------------------------------------------------
// SendSpeed sends the speed information on the uart at 19200 baud
void SendSpeed()
{
unsigned int k;
unsigned char c;
       
        k = SPEEDMULT/timer3avg;  // 2343750/timer3avg
        c = k/10000;
        if (c > 0)
                k = k - c*10000;
        OutData[OFFSET] = (c + 0x30);
        c = k/1000;
        if (c > 0)
                k = k - c*1000;
        OutData[OFFSET+1] = (c + 0x30);
        c = k/100;
        if (c > 0)
                k = k - c*100;
        OutData[OFFSET+2] = (c + 0x30);
        c = k/10;
        if (c > 0)
                k = k - c*10;
        OutData[OFFSET+3] = (c + 0x30);
        OutData[OFFSET+4] = (char)(k + 0x30);
        TXPtr = &OutData[0];
        SendMsg();
        Flags.CalSpeed = 0;
}

void SendMsg(void)
{
while (*TXPtr)
        {
        while (U1STAbits.UTXBF);
        U1TXREG = *TXPtr++;
        }
}


/*****************************************************************************
CalculateDC, uses the PI algorithm to calculate the new DutyCycle value which
will get loaded into the PDCx registers.

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

void CalculateDC(void)
{
        ActualSpeed = SPEEDMULT/timer3avg;        // Toc do thuc
        DesiredSpeed = DesiredSpeed*POTMULT;      // Toc do yeu cau
        SpeedError = DesiredSpeed - ActualSpeed;  // Sai so toc do
                        SpeedIntegral += SpeedError;
        DutyCycle = (((long)Kps*(long)SpeedError + (long)Kis*(long)SpeedIntegral) >> 16);
        PDC1 = PDC1 + DutyCycle;       
        if (PDC1 < 50)
                {PDC1 = 50;SpeedIntegral = 0;}
        if (PDC1 > 512)
                {PDC1 = 512;SpeedIntegral = 0;}
        PDC2 = PDC1;
        PDC3 = PDC1;

}


//---------------------------------------------------------------------
// This is a generic 1ms delay routine to give a 1mS to 65.5 Seconds delay
// For N = 1 the delay is 1 mS, for N = 65535 the delay is 65,535 mS.
// Note that FCY is used in the computation.  Please make the necessary
// Changes(PLLx4 or PLLx8 etc) to compute the right FCY as in the define
// statement above.

void DelayNmSec(unsigned int N)
{
unsigned int j;
while(N--)
        for(j=0;j < MILLISEC;j++);
}


kenvin_vo 18-05-2013 04:30 PM

a co file mo phong + mach in khong a,e dang lam de tai nay ma bi wa.mail cua em:duongvodinh@gmail.com

phidohuu 18-11-2013 02:55 PM

Trích:

Nguyên văn bởi kenvin_vo (Post 81913)
a co file mo phong + mach in khong a,e dang lam de tai nay ma bi wa.mail cua em:duongvodinh@gmail.com

bạn hoàn thành đề tài này chưa. mình bgio đang làm mà bí quá.

mroscar 09-01-2014 11:58 PM

anh em co the giup minh k??? minh viet tren mikro pro for dspic ma minh viet no k ngat! hic
unsigned int i,truoc,sau,trai,phai;
unsigned int struoc,ssau,strai,sphai;
void
void khaibaoPLL(){
// 7.3728MHz/2*32/2 7.3728*8= 58.9824/4 =14.7456 1/14.7456= 0.068
//1/58.9824=0.017
RCONbits.SWDTEN = 0; // disable watchdog timer
while(OSCCONbits.LOCK != 1) ; //wait PLL to lock
}
void khoitaotimer1 (){
T1CON.T1IE=1;
T1CON.T1IF=0;
TMR1=65533; //10us
T1CON=0x8000;//prescale 1:1
}
void Timer1Int () iv IVT_ADDR_T1INTERRUPT {
if(T1IF){
T1IF_bit=0;
TMR1=65533;
i++;
if(i>2000){
i=0;
LATD=0xff;
}
if(i>=truoc){RD0_bit=0;}
if(i>=sau){RD1_bit=0;}
if(i>=trai){RD2_bit=0;}
if(i>=phai){RD3_bit=0;}
}
}
void capnhat(){
struoc= truoc-truoc;
ssau= truoc-sau;
strai= truoc-trai;
sphai= truoc-phai;
}
void len(){
truoc=truoc++;
sau= truoc+ssau;
trai= truoc+strai;
phai= truoc+sphai;
}

void main () {
ADPCFG = 0xFFFF;

khoitaotimer1();
khaibaoPLL();
TRISD=0x00;
LATD=0xFF;
truoc = 100; sau=100;trai=100;phai=100;

//capnhat();
//len();

}
code minh viet anh xem dum sai cho nao chi e vs


Múi giờ GMT. Hiện tại là 01:31 PM.

Tên diễn đàn: vBulletin Version 3.8.11
Được sáng lập bởi Đoàn Hiệp.
Copyright © PIC Vietnam