You are on page 1of 6

CCS :: View topic - Anyone written a simple PID routine for a P... http://ccsinfo.com/forum/viewtopic.php?t=9048&highlight=int&...

FAQ Forum Help Official CCS Support Search Register

Profile Log in to check your private messages Log in

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

CCS Forum Index -> General CCS C Discussion

View previous topic :: View next topic

Author Message

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


Guest Posted: Sun Feb 17, 2002 4:19 am

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 Re: Anyone written a simple PID routine for a PIC???
Guest Posted: Sun Feb 17, 2002 7:04 am

:=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;

1 от 6 01.3.2007 г. 09:14
CCS :: View topic - Anyone written a simple PID routine for a P... http://ccsinfo.com/forum/viewtopic.php?t=9048&highlight=int&...

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)

2 от 6 01.3.2007 г. 09:14
CCS :: View topic - Anyone written a simple PID routine for a P... http://ccsinfo.com/forum/viewtopic.php?t=9048&highlight=int&...

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 Re: Anyone written a simple PID routine for a PIC???


Posted: Mon Feb 18, 2002 6:29 am

Joined: 08 Sep 2003 This is turned out to be a really easy way to impliment a PID control. It works good if it's tuned
Posts: 1104
Location: Houston 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 Posted: Wed Dec 22, 2004 9:14 pm

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


Joined: 14 May 2004
Posts: 270
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 Posted: Fri Dec 24, 2004 1:30 pm

future wrote:
Joined: 08 Sep 2003
Posts: 1104 Are PWMp, PWMi and PWMd values from 0 to 1?
Location: Houston
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 Posted: Sat Feb 04, 2006 8:26 am

thx guys...been looking for this too...I will study the code...
Joined: 20 Dec 2005
Posts: 110

3 от 6 01.3.2007 г. 09:14
CCS :: View topic - Anyone written a simple PID routine for a P... http://ccsinfo.com/forum/viewtopic.php?t=9048&highlight=int&...

sonicdeejay Re: Anyone written a simple PID routine for a PIC???


Posted: Sun Feb 05, 2006 8:09 pm

Joined: 20 Dec 2005 Eric Minbiole wrote:


Posts: 110
:=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++;

4 от 6 01.3.2007 г. 09:14
CCS :: View topic - Anyone written a simple PID routine for a P... http://ccsinfo.com/forum/viewtopic.php?t=9048&highlight=int&...

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 Posted: Fri Feb 23, 2007 6:51 am

@Eric Minbiole
Joined: 06 Feb 2006
Posts: 4 can you put the principle how to set the Kp, Ki, Kd ???

any help is good ....

newguy Posted: Fri Feb 23, 2007 8:55 am

andibaciu wrote:
Joined: 24 Jun 2004
Posts: 557 @Eric Minbiole
Location: Edmonton AB can you put the principle how to set the Kp, Ki, Kd ???
Canada
any help is good ....

5 от 6 01.3.2007 г. 09:14
CCS :: View topic - Anyone written a simple PID routine for a P... http://ccsinfo.com/forum/viewtopic.php?t=9048&highlight=int&...

Read Tim Westcott's excellent article, PID Without a PhD:


http://www.embedded.com/2000/0010/0010feat3.htm

Display posts from previous: All Posts Oldest First Go

All times are GMT - 6 Hours


CCS Forum Index -> General CCS C Discussion

Page 1 of 1

Jump to: General CCS C Discussion Go

You can post new topics in this forum


You can 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

6 от 6 01.3.2007 г. 09:14

You might also like