Other Parts Discussed in Thread: TIGER
Hi all,
I'm trying to get my DC motor run like a cruise control system, by means of a PID controller. I managed to get it to work, but when I started tuning my PID parameters, I noticed it was having a neglible affect on the PWM signal.
This is what I had at that time in terms of my PID controller.
int
updatePID(int targetRPM, int currentRPM)
{
int error;
static int last_error;
static int integrated_error;
float pTerm, iTerm, dTerm;
/* Calculate error and proportional value.*/
error = targetRPM - currentRPM;
pTerm = i32Kp * error;
/* Calculate error and intergral value.*/
integrated_error += error;
iTerm = i32Ki * constrain(integrated_error, -1, 1);
/* Calculate deriviative value and reset error.*/
dTerm = i32Kd * (error - last_error);
last_error = error;
/* Return the PID controlled duty cycle value. */
return constrain((i32K*(pTerm + dTerm)), -1, 1);
}
Within this function, is the constrain function, which is shown below.
int
constrain(int x, int a, int b)
{
if(x < a)
{
return a;
}
if(b < x)
{
return b;
}
else
{
return x;
}
}
The constrain function was to ensure the dutycycle never exceed 100%, but I quickly noticed this wasn't working as I intended, as the dutycycle is the value of clockticks, thus when configuring the PWM signal to work at a frequency of 24kHz when the system clock is running at 120MHz, the loaded value is 624. The code for this configuration is shown below.
void
InitPWM(void)
{
/* Enable PWM clock.*/
PWMClockSet(PWM0_BASE,PWM_SYSCLK_DIV_8);
/* Configure the GPIO pins.*/
GPIOPinConfigure(GPIO_PF0_M0PWM0);
GPIOPinConfigure(GPIO_PF1_M0PWM1);
GPIOPinConfigure(GPIO_PF2_M0PWM2);
GPIOPinConfigure(GPIO_PF3_M0PWM3);
/* Configure the GPIO pins as PWM pins.*/
GPIOPinTypePWM(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3);
/* Calculate period and duty cycle.*/
ui32PWMClockFreq = (ui32SysClkFreq / 8); //(120000000 / 8 = 15000000
ui32PWMLoad = ((ui32PWMClockFreq / PWM_FREQUENCY) -1); //15000000 / 24000 = 624
//ui32PWMDutyCycle = ui32PWMLoad;
/* Configure the PWMs to count-down, and sync with each other.*/
PWMGenConfigure(PWM0_BASE, PWM_GEN_0, PWM_GEN_MODE_DOWN | PWM_GEN_MODE_SYNC);// | PWM_GEN_MODE_GEN_SYNC_GLOBAL | PWM_GEN_MODE_DB_SYNC_GLOBAL);
PWMGenConfigure(PWM0_BASE, PWM_GEN_1, PWM_GEN_MODE_DOWN | PWM_GEN_MODE_SYNC);// | PWM_GEN_MODE_GEN_SYNC_GLOBAL | PWM_GEN_MODE_DB_SYNC_GLOBAL);
/* Set the periods.*/
PWMGenPeriodSet(PWM0_BASE, PWM_GEN_0, ui32PWMLoad);
PWMGenPeriodSet(PWM0_BASE, PWM_GEN_1, ui32PWMLoad);
/* Set the duty-cycle.*/
PWMPulseWidthSet(PWM0_BASE, PWM_OUT_0, ui32PWMLoad*0.1);
PWMPulseWidthSet(PWM0_BASE, PWM_OUT_2, ui32PWMLoad*0.1);
/* Enable the dead-time.*/
//PWMDeadBandEnable(PWM0_BASE, PWM_GEN_0, deadTime, deadTime); //15 pulses is roughly 1 us.
//PWMDeadBandEnable(PWM0_BASE, PWM_GEN_1, deadTime, deadTime);
/* Enable all of the PWM signal outputs.*/
PWMOutputState(PWM0_BASE, PWM_OUT_0_BIT, true);//PF0 - PWM
PWMOutputState(PWM0_BASE, PWM_OUT_1_BIT, false);//PF1 - \PWM
PWMOutputState(PWM0_BASE, PWM_OUT_2_BIT, true);//PF2 - PWM
PWMOutputState(PWM0_BASE, PWM_OUT_3_BIT, false);//PF3 - \PWM
/* Enable the sync.*/
PWMSyncTimeBase(PWM0_BASE, PWM_GEN_0_BIT | PWM_GEN_1_BIT);
PWMSyncUpdate(PWM0_BASE, PWM_GEN_0_BIT | PWM_GEN_1_BIT);
/* Enable the PWM gens.*/
PWMGenEnable(PWM0_BASE, PWM_GEN_0);
PWMGenEnable(PWM0_BASE, PWM_GEN_1);
}
e
I figured that my tuning was neglible, because I'm sending only a fraction of the dutycycle due to the constrain until -1 and 1 when it should in reality be 0 and 624. However, when I implement these methods, the dutycycle goes crazy as the value it loads to PWMPulseWidthSet() is in the thousands, causing the dutycyle to be a 100% at all times, rendering the whole controller useless.
I figured this was because I was dealing with the unsigned vs. signed values incorrectly, therefore I changed it once to allow for larger numbers and make them all signed, but this still provided crazy numbers.
What I dont understand is that my constrain function should prevent this from happening, and even though the dutycycle wants to be 10,000 because I set my Kp, Ki, Kd values really high, it should still only return the value between 0 and 624 due to the constrain function.
Anybody know what might be causing this irregularity in the numbers?