CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Anyone written a simple PID routine for a PIC???

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Carlos Barberis
Guest







Anyone written a simple PID routine for a PIC???
PostPosted: Sun Feb 17, 2002 4:19 am     Reply with quote

HI
I am looking for a simple pid routine to control a small heater using the pwm output of the pic. Any hints would be appreciated.
___________________________
This message was ported from CCS's old forum
Original Post ID: 2637
Eric Minbiole
Guest







Re: Anyone written a simple PID routine for a PIC???
PostPosted: Sun Feb 17, 2002 7:04 am     Reply with quote

:=I am looking for a simple pid routine to control a small heater using the pwm output of the pic. Any hints would be appreciated.

I recently finished a project that leviated a metal ball using an electromagnet. It used a PIC to control a PID loop which kept the ball floating stabily.

Here's the code for my PID loop. I'm sure it's not the best PID code out there, but it should give you a starting point to work from. The only tricky part of the code is in calculating the differential term. Rather than taking the difference of two adjacent samples, I averaged 4 old samples, and 4 new samples, and took the difference between the averages. This made the loop more immune to noisy samples.

Hope it helps!


// control loop constants
float Kp; // proportional gain
float Ki; // integral gain
float Kd; // differential gain

// terms
float Tp; // proportional term
float Ti; // integral term
float Td; // differential term

// circular queue vars
int i = 0;
signed long error_history[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
int8 queue_pos = 0;
int8 temp_pos;
signed long prev_ave;
signed long cur_ave;

signed long error;
signed long DeDt; // change in error over time
signed int32 error_sum = 0; // sum of errors, for integral term
signed long desired_power;
int8 power;
int8 setpoint;
float temp_float;

// **** set the loop constants (Kp, Ki, Kd) to something useful

// main control loop
while (1)
{
// calculate the raw error
// negative = disc too low
error = (signed long)read_adc() - setpoint;

// calculate the proportional term
Tp = -Kp * error;

// calculate the integral term
error_sum = error_sum + (signed int32)error;
temp_float = error_sum;
Ti = Ki * temp_float;

// use a circular queue to save a history of the last 8 samples
// this will be used to calculate the differential term
error_history[queue_pos] = error;
queue_pos++;
queue_pos &= 0x07; // keep in 0..7 range
temp_pos = queue_pos;

// calculate the average for the 4 oldest samples
for (i = 0, prev_ave = 0; i < 4; i++)
{
prev_ave += error_history[temp_pos];
temp_pos++;
temp_pos &= 0x07;
}

// calculate the average for the 4 most recent samples
for (i = 0, cur_ave = 0; i < 4; i++)
{
cur_ave += error_history[temp_pos];
temp_pos++;
temp_pos &= 0x07;
}

// calculate the differential term
DeDt = prev_ave - cur_ave;
Td = Kd * DeDt;

// calculate the desired power
desired_power = (signed long)(Tp + Td + Ti);

// set the correct power
if (desired_power < 0)
power = 0;
else if (desired_power > 255)
power = 255;
else
power = desired_power;
set_output_power(power); // this could be pwm duty, etc

// wait between samples
delay_ms(2);
}
___________________________
This message was ported from CCS's old forum
Original Post ID: 2639
Neutone



Joined: 08 Sep 2003
Posts: 839
Location: Houston

View user's profile Send private message

Re: Anyone written a simple PID routine for a PIC???
PostPosted: Mon Feb 18, 2002 6:29 am     Reply with quote

This is turned out to be a really easy way to impliment a PID control. It works good if it's tuned right. I use this to heat a heat exchanger with a variable heat load. My pulse width is 20 seconds and sampel rate is 5 times per pulse. Any of the number can be changed.

All variables are floats
//PID PWM calculation routine for SupplyTemperature

errorNOW = Setpoint - SupplyTemperature;
PWMonTIME = PWMonTIME + (PWMp * errorNOW ) + (PWMi * (errorNOW - (PWMd * (errorNOW - errorLAST))));
errorLAST = errorNOW;
if (PWMon > 190) PWMon = 190; //maximum on time
if (PWMon < 10) PWMon =10; //minimum on time
PWMoff = 200 - PWMon;



:=HI
:=I am looking for a simple pid routine to control a small heater using the pwm output of the pic. Any hints would be appreciated.
___________________________
This message was ported from CCS's old forum
Original Post ID: 2658
future



Joined: 14 May 2004
Posts: 330

View user's profile Send private message

PostPosted: Wed Dec 22, 2004 9:14 pm     Reply with quote

Are PWMp, PWMi and PWMd values from 0 to 1?

I want to use PID to control a stepper motor, so it has to know how many steps and direction to apply to correct the error.
Neutone



Joined: 08 Sep 2003
Posts: 839
Location: Houston

View user's profile Send private message

PostPosted: Fri Dec 24, 2004 1:30 pm     Reply with quote

future wrote:
Are PWMp, PWMi and PWMd values from 0 to 1?

I want to use PID to control a stepper motor, so it has to know how many steps and direction to apply to correct the error.


I can't remember but looking at the formula it looks like between -1 and 1.
sonicdeejay



Joined: 20 Dec 2005
Posts: 112

View user's profile Send private message

PostPosted: Sat Feb 04, 2006 8:26 am     Reply with quote

thx guys...been looking for this too...I will study the code...
sonicdeejay



Joined: 20 Dec 2005
Posts: 112

View user's profile Send private message

Re: Anyone written a simple PID routine for a PIC???
PostPosted: Sun Feb 05, 2006 8:09 pm     Reply with quote

Eric Minbiole wrote:
:=I am looking for a simple pid routine to control a small heater using the pwm output of the pic. Any hints would be appreciated.

I recently finished a project that leviated a metal ball using an electromagnet. It used a PIC to control a PID loop which kept the ball floating stabily.

Here's the code for my PID loop. I'm sure it's not the best PID code out there, but it should give you a starting point to work from. The only tricky part of the code is in calculating the differential term. Rather than taking the difference of two adjacent samples, I averaged 4 old samples, and 4 new samples, and took the difference between the averages. This made the loop more immune to noisy samples.

Hope it helps!


// control loop constants
float Kp; // proportional gain
float Ki; // integral gain
float Kd; // differential gain

// terms
float Tp; // proportional term
float Ti; // integral term
float Td; // differential term

// circular queue vars
int i = 0;
signed long error_history[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
int8 queue_pos = 0;
int8 temp_pos;
signed long prev_ave;
signed long cur_ave;

signed long error;
signed long DeDt; // change in error over time
signed int32 error_sum = 0; // sum of errors, for integral term
signed long desired_power;
int8 power;
int8 setpoint;
float temp_float;

// **** set the loop constants (Kp, Ki, Kd) to something useful

// main control loop
while (1)
{
// calculate the raw error
// negative = disc too low
error = (signed long)read_adc() - setpoint;

// calculate the proportional term
Tp = -Kp * error;

// calculate the integral term
error_sum = error_sum + (signed int32)error;
temp_float = error_sum;
Ti = Ki * temp_float;

// use a circular queue to save a history of the last 8 samples
// this will be used to calculate the differential term
error_history[queue_pos] = error;
queue_pos++;
queue_pos &= 0x07; // keep in 0..7 range
temp_pos = queue_pos;

// calculate the average for the 4 oldest samples
for (i = 0, prev_ave = 0; i < 4; i++)
{
prev_ave += error_history[temp_pos];
temp_pos++;
temp_pos &= 0x07;
}

// calculate the average for the 4 most recent samples
for (i = 0, cur_ave = 0; i < 4; i++)
{
cur_ave += error_history[temp_pos];
temp_pos++;
temp_pos &= 0x07;
}

// calculate the differential term
DeDt = prev_ave - cur_ave;
Td = Kd * DeDt;

// calculate the desired power
desired_power = (signed long)(Tp + Td + Ti);

// set the correct power
if (desired_power < 0)
power = 0;
else if (desired_power > 255)
power = 255;
else
power = desired_power;
set_output_power(power); // this could be pwm duty, etc

// wait between samples
delay_ms(2);
}
___________________________
This message was ported from CCS's old forum
Original Post ID: 2639



hi there...

seem like the code isn't totally complete...

Isn't it suppose to include looping code rite??


can u post the complete code?




thx


sonic
andibaciu



Joined: 06 Feb 2006
Posts: 6

View user's profile Send private message

PostPosted: Fri Feb 23, 2007 6:51 am     Reply with quote

@Eric Minbiole
can you put the principle how to set the Kp, Ki, Kd ???

any help is good ....
newguy



Joined: 24 Jun 2004
Posts: 1903

View user's profile Send private message

PostPosted: Fri Feb 23, 2007 8:55 am     Reply with quote

andibaciu wrote:
@Eric Minbiole
can you put the principle how to set the Kp, Ki, Kd ???

any help is good ....


Read Tim Westcott's excellent article, PID Without a PhD: http://www.embedded.com/2000/0010/0010feat3.htm
kilarn
Guest







PID values
PostPosted: Thu Apr 02, 2009 10:08 am     Reply with quote

A good place to start for values is to do a quick search for the Ziegler-Nichols Decay ratio technique... this is only a starting place though...

The best method I have found is to use Root Locus with a program like MATLAB... but this again depends on how well you have modeled your design.

Also to find the Kp you can use a Routh Array and/or what is called the Magnitude condition.

These all come from classical control theory.

Hope this helps.
mmprestine



Joined: 13 Jan 2004
Posts: 29
Location: Green Bay, Wisconsin

View user's profile Send private message

PostPosted: Thu Apr 02, 2009 1:16 pm     Reply with quote

here is what was posted in the past. try the search.

http://www.ccsinfo.com/forum/viewtopic.php?t=32995&highlight=
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group