Thursday, November 29, 2007

PID code for Arduino

Here is my PID code for Arduino or other microcontroller.  It is unfinished and untested in this exact state, but it used to work on a PIC, so it cant be that broken, right?  Once I get a chance to get it uploaded to my espresso machine and tested IRL, I'll publish it on the arduino wiki. If you use this and especially if you change it, please drop a quick comment. (license at bottom) thanks!

float iState = 0;
float lastTemp = 0;

#define PGAIN_ADR 0
#define IGAIN_ADR 4
#define DGAIN_ADR 8


float loadfloat(int address) {
// must be written
// this function return the float from EEPROM storage.
// This is used for the P,I, and D_GAIN settings.
// These are three values that need to be tuned after
// the machine up and running to make the PID loop
// work right.

float UpdatePID(float targetTemp, float curTemp)
// these can be cut out if memory is an issue,
// but they make it more readable
float pTerm, iTerm, dTerm;

float error;
float windupGaurd;

// determine how badly we are doing
error = targetTemp - curTemp;

// the pTerm is the view from now, the pgain judges
// how much we care about error we are this instant.
pTerm = loadfloat(PGAIN_ADR) * error;

// iState keeps changing over time; it's
// overall "performance" over time, or accumulated error
iState += error;

// to prevent the iTerm getting huge despite lots of
// error, we use a "windup guard"
// (this happens when the machine is first turned on and
// it cant help be cold despite its best efforts)

// not necessary. this makes windup guard values
// relative to the current iGain
windupGaurd = WINDUP_GUARD_GAIN / loadfloat(IGAIN_ADR);

if (iState > windupGaurd)
iState = windupGaurd;
else if (iState < -windupGaurd)
iState = -windupGaurd;
iTerm = loadfloat(IGAIN_ADR) * iState;

// the dTerm, the difference between the temperature now
// and our last reading, indicated the "speed,"
// how quickly the temp is changing. (aka. Differential)
dTerm = (loadfloat(DGAIN_ADR)* (curTemp - lastTemp));

// now that we've use lastTemp, put the current temp in
// our pocket until for the next round
lastTemp = curTemp;

// here comes the juicy magic feedback bit
return pTerm + iTerm - dTerm;

Creative Commons License

This work is licensed under a
Creative Commons Attribution-Noncommercial 3.0 Unported License.

No comments: