Step 3: PID Logic
The PID is the heart of this code. The basic theory is that you consider three factors to figure out how much heat to apply to the system:
1] how far away are we from the target setting?
2] how fast are we getting there?
3] How much have we been consistently off?
OK, so first off, since this is an 8-bit micro that can handle a few 16 bit registers, we represent the temperatures as the temp multiplied by 64. This is called fixed point math, since we're just shifting the decimal point. A 64x multiplier lets me get a temp up to 1024 degrees with 5 bits of decimal points (1/64th per division). Since the temp sensor is giving us 2 bits of decimal, this is plenty of precision for what we're up to.
When we calculate how much to heat the space (The power demand), we begin with the proportional gain. To get this, we subtract the target temp from the current temp and multiply by the gain setting. As we get closer, we add less and less heat. Running this by itself will, however, leave us with an error. If the gain is too low, then the error will be nearly constant. Too high, and it will oscillate. It's important to make sure when you do this math that you be on the look out for overflows on the registers. If your gain is 1024 and your reading is 16C, the math works out to well over the 65,535 you're allowed to go. So be sure to limit all values to sane ones.
To prevent oscillation we add the Derivative portion. The derivative of the temperature is a measure of how much it's changing. So to do this we save the last reading and subtract it from the current one. Now, we multiply that by the derivative gain and get a measure of how much of the proportional gain we need to get rid of to prevent overshooting the target temp.
Finally, that little bit of error that will always be present when you use only P and D portions can be removed by adding a factor that comes from how far off you've been. While handy for holding the set point, it cannot be stressed enough that because it accumulates, the integral gain has the potential to cause problems faster than anything else. Think about it: You start the system and it's 82F, but you've set it for 225F. For the 45 minutes it takes to come up to temp it's piling on more gain.
We avoid most of this by two simple methods:
1] Limit the I portion to something small... no more than about 10% total available gain
2] Don't accumulate I gain if the temperature is moving in the correct direction.
The second bit there is not standard, but it seemed to work best in this application.
Once you have all the gain components added up, convert to an output value.