⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pid.txt

📁 pid control of closed loop control system
💻 TXT
字号:
#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 Switching 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 High
	IOCON1bits.POLL		= 0;        // Low Output Polarity is active High 
	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 50 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 Cycle 
	PHASE1 = 0;                     // No staggering 
	FCLCON1 = 0x0003;				// Fault Input is disabled
	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/AN1 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 function 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 result from channel AN0 

	pidParams.error = 	pidParams.ReferenceSetpoint - pidParams.feedback; // This claculated the proportional error

	if ((pidParams.error > 2) || (pidParams.error < -2)) // If error is within 2 then do not do the PID Calculation.
	{

		if (pidParams.saturated == 0)      // If the PID controller is staurated 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 - pidParams.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 limits 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 register 

		LATEbits.LATE5 = 0;// Turn the LED OFF	

	}
}



⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -