Tool/software: Code Composer Studio
Hi all,
I am trying to control velocity of DC motor using PID, but i am have trouble to stabilize it any desired velocity, and also the derivative terms stays zero all the time.
/* DC Motor Velocity */ #include "Config.h" #define PERIOD_PWM 1250 // 2ms time period is equal to 1250 ticks #define GET_MAG(X) (X > 0 ? X : -X) #ifndef DEGPS_RPM #define DEGPS_RPM 0.16667 #endif float encdrRdShldr, rotDirShldr, dpsShldr, rpmShldr, errVelShldr, intgErrShldr, dErrShldr, pidVelShldr, prevErrVelShldr; float desVelShldr, kpVelShldr, kiVelShldr, kdVelShldr, pwm,D; float scaledOutVelShldr; float accErrVelShldr; int a; int main ( void ) { SysCtlClockSet ( SYSCTL_SYSDIV_2|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHZ ) ; // 400/2=200MHz (2 is default divider), 200/5=40MHz (System Clock become 40MHz), tmr0IntrptConfig(); // Call timer 0 interrupt Configuration encdrShldrConfig(); // Call Shoulder Motor encoder Configuration pwmShldrConfig(); // Call PWM Shoulder Configuration initlzVarConfig(); kpVelShldr = 1.5; kiVelShldr = 1; kdVelShldr = 2; /* Direction PINS */ SysCtlPeripheralEnable ( SYSCTL_PERIPH_GPIOB ) ; GPIOPinTypeGPIOOutput ( GPIO_PORTB_BASE, ( GPIO_PIN_0 | GPIO_PIN_1|GPIO_PIN_2 ) ) ; mag = 99; a = 0; } void Timer0IntHandler(void) { encdrRdShldr = QEIVelocityGet(QEI0_BASE); rotDirShldr = QEIDirectionGet(QEI0_BASE); if(rotDirShldr == 1) //CCW { dpsShldr = -1*(encdrRdShldr * 0.1124); rpmShldr = dpsShldr * DEGPS_RPM; } else if(rotDirShldr == -1) //CW { dpsShldr = (encdrRdShldr * 0.1124); rpmShldr = dpsShldr * DEGPS_RPM; } if(desVelShldr > 60) { desVelShldr = 60; } else if(desVelShldr < -60) { desVelShldr = -60; } errVelShldr = desVelShldr - rpmShldr; intgErrShldr = (accErrVelShldr) * 0.0001; dErrShldr = (errVelShldr - prevErrVelShldr) * 10000; pwm = desVelShldr * 1.35; // pwm according to desired velociety pidVelShldr = (kpVelShldr * errVelShldr + kiVelShldr * intgErrShldr + kdVelShldr * dErrShldr)+pwm; D= kdVelShldr * dErrShldr; accErrVelShldr += errVelShldr; if(pidVelShldr >= 0) { if(pidVelShldr >= 254) pidVelShldr = 254; if(pidVelShldr <= 1) pidVelShldr = 1; } else if(pidVelShldr < 0) { if(pidVelShldr <= -254) pidVelShldr = -254; if(pidVelShldr >= -1) pidVelShldr = -1; } if(pidVelShldr >= 0) { //Set direction bits to rotate motor CW GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_0, GPIO_PIN_0); GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_1, 0x00); } else { //Set direction bits to rotate motor CCW GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_0, 0x00); GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_1, GPIO_PIN_1); } scaledOutVelShldr = GET_MAG(pidVelShldr) * 5.0; if(scaledOutVelShldr > 1250) {scaledOutVelShldr = 1250;} PWMPulseWidthSet ( PWM1_BASE, PWM_OUT_7, scaledOutVelShldr); a++; if(a == 1){ GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_2, GPIO_PIN_2); }if(a == 2){ GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_2, 0x00); a = 0;} prevErrVelShldr = errVelShldr; TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);// Clear the timer interrupt }
and this is code for Config.c source file
#include "Config.h"
float mag;
void initlzVarConfig (void)
{
mag = 0.0;
}
void encdrShldrConfig (void)
{
SysCtlPeripheralEnable ( SYSCTL_PERIPH_GPIOD ) ;
//Unlock GPIOD7
HWREG (GPIO_PORTD_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
HWREG (GPIO_PORTD_BASE + GPIO_O_CR) |= 0x80;
HWREG (GPIO_PORTD_BASE + GPIO_O_AFSEL) &= ~0x80;
HWREG (GPIO_PORTD_BASE + GPIO_O_DEN) |= 0x80;
HWREG (GPIO_PORTD_BASE + GPIO_O_LOCK) = 0;
SysCtlPeripheralEnable ( SYSCTL_PERIPH_QEI0 ) ; // Enable QEI Peripherals
//Set Pins to be PHA0 and PHB0
GPIOPinConfigure(GPIO_PD6_PHA0); //GPIOPinConfigure ( 0x00031806 ) ; //0x00031806 =>GPIO_PD6_PHA0
GPIOPinConfigure(GPIO_PD7_PHB0); //GPIOPinConfigure ( 0x00031C06 ) ; // 0x00031C06 => GPIO_PD7_PHB0
GPIOPinTypeQEI(GPIO_PORTD_BASE, (GPIO_PIN_6 | GPIO_PIN_7)) ; //Set GPIO pins for QEI
// Configure quadrature encoder, use an arbitrary top limit of 2000 and enable QEI
QEIConfigure (QEI0_BASE, (QEI_CONFIG_CAPTURE_A | QEI_CONFIG_RESET_IDX | QEI_CONFIG_QUADRATURE | QEI_CONFIG_NO_SWAP) ,640000) ;
QEIEnable(QEI0_BASE);
//Configure and enable velocity
QEIVelocityConfigure(QEI0_BASE, QEI_VELDIV_1, SysCtlClockGet()) ; // Divide by clock speed to get counts/sec
QEIVelocityEnable(QEI0_BASE);
}
void tmr0IntrptConfig (void)
{
SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0) ;
TimerConfigure(TIMER0_BASE, TIMER_CFG_A_PERIODIC) ;
uint32_t InterruptPeriod = SysCtlClockGet() * 0.0001;
TimerLoadSet(TIMER0_BASE, TIMER_A, InterruptPeriod - 1) ;
IntEnable(INT_TIMER0A);
TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
IntMasterEnable();
TimerEnable(TIMER0_BASE, TIMER_A) ;
}
void pwmShldrConfig (void)
{
// Enable the peripherals used by this program.
SysCtlPeripheralEnable ( SYSCTL_PERIPH_PWM1 ) ;
while(!SysCtlPeripheralReady(SYSCTL_PERIPH_PWM1));
SysCtlPeripheralEnable ( SYSCTL_PERIPH_GPIOF ) ;
GPIOPinTypePWM ( GPIO_PORTF_BASE, GPIO_PIN_3 ) ; // Configure PF3 Pins as PWM
GPIOPinConfigure ( GPIO_PF3_M1PWM7 ) ;
SysCtlPWMClockSet ( SYSCTL_PWMDIV_64 ) ; // 40/64=0.625 MHz, 625KHz
PWMDeadBandDisable ( PWM1_BASE,PWM_GEN_3 ) ;
PWMGenConfigure ( PWM1_BASE, PWM_GEN_3, PWM_GEN_MODE_DOWN | PWM_GEN_MODE_NO_SYNC ) ; //Configure PWM Options
uint32_t PWMPeriod=1250; //PWM_GEN_2 Covers M1PWM4 and M1PWM5
PWMGenPeriodSet ( PWM1_BASE, PWM_GEN_3, PWMPeriod ) ; //PWM_GEN_3 Covers M1PWM6 and M1PWM7
PWMOutputState ( PWM1_BASE, PWM_OUT_7_BIT, true ) ; //Turn on the Output pins
PWMGenEnable ( PWM1_BASE, PWM_GEN_3 ) ; //Enable the PWM generator
}