100% found this document useful (3 votes)
512 views

PID Position Control Dspic 30f2020

This document contains code for a PID controller implementation on a microcontroller. It includes: 1. Initialization code to configure the microcontroller peripherals like PWM, ADC, interrupts. 2. Definition of a PID parameter struct to store PID constants, variables and registers. 3. Main function to initialize PID parameters and call setup function. 4. Setup function that configures ADC, PWM and interrupts for PID control loop updates at 20kHz rate. 5. ADC interrupt service routine that reads feedback, calculates PID output and updates duty cycle register every 50us.

Uploaded by

FREEDOMHOUSE
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
100% found this document useful (3 votes)
512 views

PID Position Control Dspic 30f2020

This document contains code for a PID controller implementation on a microcontroller. It includes: 1. Initialization code to configure the microcontroller peripherals like PWM, ADC, interrupts. 2. Definition of a PID parameter struct to store PID constants, variables and registers. 3. Main function to initialize PID parameters and call setup function. 4. Setup function that configures ADC, PWM and interrupts for PID control loop updates at 20kHz rate. 5. ADC interrupt service routine that reads feedback, calculates PID output and updates duty cycle register every 50us.

Uploaded by

FREEDOMHOUSE
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 4

#include "p30f2020.

h"
_FOSCSEL(PRIOSC_PLL) // This sets up the device for use with external
Crystal in PLL MODE
_FOSC(CSW_FSCM_OFF & HS) // This sets the Oscillator Source
_FWDT(FWDTEN_OFF) // This turns the Watchdog timer off
_FBS(BWRP_WRPROTECT_ON) // Boot Segment is Write Protected
_FGS(CODE_PROT_OFF) //Code Protection is OFF
// Define Global Variables
struct pidParameters
{
float Kp;
float Ki;
float Kd;
signed long int error;
signed long int output;
signed long int outmax;
signed long int ReferenceSetpoint;
signed long int feedback;
signed long int integral;
signed long int derivitive;
signed long int previous_error;
signed long int saturated;
} pidParams;
void setup(void) // Funtion definition for setup of the ADC AND Power PWM Module
.
{
PTCONbits.PTEN = 0; // This will disable the PWM Module
PTPER = 15992; // Sets the PWM Period to 16.667u secs (60KHz Switc
hing Frequency)Period Duration = (PTPER + 1) / 120MHz.
/* Initialize PWM Generator 1 */
IOCON1bits.PENH = 1; // PWM Module controls High output
IOCON1bits.PENL = 1; // PWM Module controls Low output
IOCON1bits.POLH = 0; // High Output Polarity is active Hi
gh
IOCON1bits.POLL = 0; // Low Output Polarity is active Hig
h
IOCON1bits.PMOD = 1; // Independant output mode
IOCON1bits.OVRENH = 0; // High Output Override disabled
IOCON1bits.OVRENL = 0; // Low Output Override disabled
PWMCON1bits.FLTSTAT = 0; // Clear Fault Interrupt flag
PWMCON1bits.CLSTAT = 0; // Clear Current Limit Interrupt flag
PWMCON1bits.TRGSTAT = 0; // Clear PWM Trigger Interrupt flag
PWMCON1bits.FLTIEN = 0; // Disable Fault Interrupt
PWMCON1bits.CLIEN = 0; // Disable Current Limit Interrupt
PWMCON1bits.TRGIEN = 0; // Disable Trigger Interrupt
PWMCON1bits.ITB = 0; // Time base is read from PTMR
PWMCON1bits.MDCS = 0; // Duty cycle is read from PDC
PWMCON1bits.DTC = 2; // No Dead Time
PWMCON1bits.XPRES = 0; // No extenal reset for PTMR
PWMCON1bits.IUE = 0; // Immediate update to PDC
TRGCON1bits.TRGDIV = 2; // Trigger on every 3rd event. That is 5
0 usecs between successive interations with the system
TRGCON1bits.TRGSTRT = 0; // Start the counting at the start
TRIG1 = 15992; // Trigger event at 16.667 usec from
// start of the PWM cycle
PDC1 = 0; // Initially start with with a 0% Duty C
ycle
PHASE1 = 0; // No staggering
FCLCON1 = 0x0003; // Fault Input is disabl
ed
PTCON = 0x8000; // Enable PWM Module
/* Initialize the ADC */
ADCONbits.ADSIDL = 0; // Operate in Idle Mode
ADCONbits.FORM = 0; // Output in Integer Format
ADCONbits.EIE = 1; // Enable Early Interrupt
ADCONbits.ORDER = 0; // Even channel first
ADCONbits.SEQSAMP = 1; // Sequential Sampling Enabled
ADCONbits.ADCS = 4; // Clock Divider is set up for Fadc/12
ADSTAT = 0; // Clear the ADSTAT register
ADPCFG = 0xFFC0; // AN0/AN1, AN2/AN3, AN4/AN5 are analog
inputs
ADCPC0bits.TRGSRC0 = 0x4; // Trigger conversion OF CHANNELS AN0/AN
1 on PWM#1 Trigger
ADCPC0bits.IRQEN0 = 1; // Enable the interrupt
ADCONbits.ADON = 1; // Start the ADC module
/* Set up the Interrupts */
IFS0bits.ADIF = 0; // Clear AD Interrupt Flag
IPC2bits.ADIP = 4; // ADC Interrupt Priority Is Set To 1
IEC0bits.ADIE = 1; // Enable the ADC Interrupt
}
int main(void)
{
pidParams.Kp = 0.4;
pidParams.Ki = 0;
pidParams.Kd = 0;
pidParams.outmax = 15992; // The Maximum PWM Value is a functio
n of frequency
//
Max Duty = (Percent * PTPER) / 100
pidParams.ReferenceSetpoint = 707; //Corresponds to 14.5Volts
pidParams.feedback = 0;
pidParams.integral = 0;
pidParams.derivitive = 0;
pidParams.previous_error = 0;
setup(); // Function Call to setup peripherals
while(1)
{
}
}
// Interrupt Service Routine will read ADC and Update the Duty Cycle Register
// The ISR is Invoked at a 20KHz rate. This 50usecs between updates of the Duty
Cycle Register.
void __attribute__((__interrupt__)) _ADCInterrupt()
{
TRISE = 0xffCf; //Set LED pins E4 and E5
as outputs
LATEbits.LATE5 = 1; // Turn LED ON
IFS0bits.ADIF = 0; // Clear ADC Interrupt Flag
ADSTATbits.P0RDY = 0; // Clear the ADSTAT bits
pidParams.feedback = ADCBUF0; // Get the conversion re
sult from channel AN0
pidParams.error = pidParams.ReferenceSetpoint - pidParams.feedback
; // This claculated the proportional error
if ((pidParams.error > 2) || (pidParams.error < -2)) // If error is with
in 2 then do not do the PID Calculation.
{
if (pidParams.saturated == 0) // If the PID controller is s
taurated the flag will be 1 and no
//
accumulation of integral/derivitive will be done.
{
if (pidParams.integral < 32000)
{
if (pidParams.integral > -32000)
pidParams.integral += pidParams.error;
}
pidParams.derivitive = pidParams.error - pidPara
ms.previous_error;
}
// NOW WE EXECUTE THE ACTUAL PID ALGORITHM
pidParams.output =(pidParams.Kp * pidParams.error
+ pidParams.Ki * pidParams.integral
+ pidParams.Kd * pidParams.derivitive);
// Perform boundary checks on the output of the PID algorithm. If the output lim
its are exceeded then, then set output to the limit
// and set flag.
if (pidParams.output > pidParams.outmax)
{
pidParams.saturated = 1;
pidParams.output = pidParams.outmax;
}
else if (pidParams.output < 0)
{
pidParams.saturated = 1;
pidParams.output = 0;
}
else
pidParams.saturated = 0;
pidParams.previous_error = pidParams.error;
PDC1 = pidParams.output; // Update the duty cycle re
gister
LATEbits.LATE5 = 0;// Turn the LED OFF
}
}

You might also like