NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Microcontroller Programming » How would i create a PID controller method?

March 03, 2012
by RevMoses
RevMoses's Avatar

Some example code would be great. for a general definition of what i'm attempting to achieve: http://en.wikipedia.org/wiki/PID_controller

Assuming i have ADCinput and PWMoutput

March 03, 2012
by RevMoses
RevMoses's Avatar

P is the easy part. Its just gain...so ADCinput * GainFactor However I and D are a bit more...uh unfriendly

March 03, 2012
by esoderberg
esoderberg's Avatar

Rev,

Here is code for a linear servo. As you can see, it's essentially a P controller, without the ID parts of the full PID. With the gearing on most linear actuators, you get a system that effectively has very low inertia, meaning the below code gives rather accurate and precise results without the need for the I or D elements. I tried them and found no improvement at all with D feedback included, but I may yet still go back and implement an I element if I find I'm getting stuck with unacceptable steady state error. The first function sets up the PWM, the second controls an H-bridge and sets the actual PWM depending on demanded position and actual position(measured elsewhere in code via ADC).

void pwm_init() {
  // setup Timer1 for Fast PWM mode, 16-bit
  // COM1B1 -- for non-inverting output on OC1B (PB2) for tilt lock servo input
  // COM1A1 -- for non-inverting output on OC1A (PB1) (Digital Pin 9)for steer servo input
  // WGM13, WGM12, WGM11 -- for Fast PWM with ICR1 as TOP value
  // CS11 -- for CLK/8 prescaling

  //ICR1 = 40000;   // sets PWM to repeat pulse every 20.0ms for RC servo mode
  ICR1 = 1000;//set PWM for MC mode OCR1A will now be 0-1000 --- 5 usec minimum on time with PWM freq of 2k 
  TCCR1A = (1<<COM1A1) | (1<<WGM11) | (1<<COM1B1); //***1A0/1B0 will make it inverting
  TCCR1B = (1<<WGM13) | (1<<WGM12) | (1<<CS11);}

///////////////////////////////////////////////

void MC1(int16_t steer, int16_t MC1FB) {//(where you want,      where you are)

//steer in percent of radians
x = 100*(steer-MC1FB);// for PID control scheme.  
//As set, will saturate at 10% of full steer

//max output to OCR1 is 1000

if (x>=0) {//move forward HL and LR on********HR and LL off
if (x>1000) x=1000;//can't do more than 100%

 //HR off via PD2
 PORTD &= ~(1<<PD2);
//Turn off LL
OCR1A = 0;

//HL on via PD3
PORTD |= (1<<PD3);
//LR on with PWM

if (x>0) OCR1B = x;//Turn on LR
else OCR1B=0;

}

////////////////////////

if (x<0){//move backward  HL and LR off********HR and LL on
if (x<-1000) x = -1000;//can't do more than 100%

 //HL off via PD3
 PORTD &= ~(1<<PD3);
//Turn off LR
OCR1B = 0;

//HR on via PD2

PORTD |= (1<<PD2);
//LL on with PWM

OCR1A = -x;
                }
}

Post a Reply

Please log in to post a reply.

Did you know that binary numbers use base 2 to represent numbers, and these are important for understanding microcontroller registers? Learn more...