Submitted by dave on

A while back I built a controller for doing home Sous Vide (write up to come...). It controls a hotplate under a pan of water and uses a digital temperature sensor to attempt to maintain a constant, precise temperature. I hacked together a simple control system, and found that it worked very badly for controlling a system with so much lag. I tried a bit of tweaking, but it was still not very good - a tendency to overshoot massively, and take a long time to cool down. So, I looked into hooking up a PID controller - a good, solid engineering solution if you don't have knowledge that something else is better.

PID stands for proportional, integrative, derivative. The controller has these three parts, which act over the error between a desired and current state, to give a control level; that is, the control level is the sum of terms based on

* the current error

* the integral of the current error

* the differential of the current error (or output - the differential is the same)

There's a nice Arduino library to do this at: http://www.arduino.cc/playground/Code/PIDLibrary. Setting it up and using sensible defaults from the article gave a fairly poor performance. This is because it needs to be tuned for my particular hardware. In particular, I suspect my response times are a couple of orders of magnitude slower than usual circuits. The lag term is especially problematic.

This article at MBED: http://mbed.org/cookbook/PID gives a really nice introduction to PID, and tuning it for a particular system. As a first approximation (because it takes a really long time to work out properly) I'm going to follow it through using partly remembered and made up values - hopefully, this will get a reasonable response, and I can tune more later.

The controller takes three parameters:

* [tex]K_c[/tex], for proportional control,

* [tex]\tau_I[/tex], for the integral component

* [tex]\tau_D[/tex] for the derivative component.

Here, I'm just going to set up a PI controller (no D) for simplicity.

== Step Response ==

The first part is based on the step response - the way that the sensed variable changes in response to a step in the output of the controller. There are three parameters here:

* Process Gain ([tex]K_p[/tex]): how much the control variable changes for a given step in output. My output is between 0 and 32 (controlling duty cycle for the hotplate). I think it's around 5C change for a step of 2, but I'm not sure - I'll revisit this later. For the constant, we have:

[equation]K_p=\frac{\Delta PV}{\Delta CO} \approx 5/6 \approx 1[/equation]

* Process Time ([tex]T_p[/tex]): how long the output takes to reach 63% of its final value after the change becomes visible. I'm going to estimate this at 5 minutes: [equation]T_p=300s[/equation]

* Dead Time ([tex]\theta_p[/tex]): how long before the output starts to respond. I think this is about 2 minutes: [tex]\theta_p=120s[/tex]

According to MBED, there's one more component, [tex]T_c[/tex] which controls how aggressive the system is. Due to problems in the past with overshoot, I'll go for a moderate value:

[equation]T_c=max(T_p, 8 * \theta_p) = max(300, 960) = 960[/equation]

Now putting this together we get:

[equation]K_c = \frac{1}{K_p}(\frac{T_p}{\theta_p+T_c}) = \frac{1}{1}\frac{300}{120+960} = 0.25[/equation]

we need this as a percentage, so we scale by 32/100 to get [tex]K_c=0.08[/tex]

Apparently we set [tex]\tau_i=\T_p=300s[/tex].

Running this gave a bit of a slow response, with a fair bit of overshoot. For the sous-vide, overshoot is a problem, as some bits of the food will end up overcooked. So, after doing a bit more reading of [http://www.controlguru.com/wp/p78.html controlguru], it looks like adding the derivative component doesn't need any more parameters. The IMC tuning parameters are:

[equation] K_c=\frac{1}{K_p}(\frac{T_p+0.5\theta_p}{T_c+0.5\theta_p});

T_i=T_p+0.5\theta_P; T_d=\frac{T_p\theta_p}{2T_p+\theta_p}[/equation]

[equation] K_c=\frac{1}{1}(\frac{300+30}{960+30}); T_i=330+60; T_d=\frac{300*120}{600+120}[/equation]

[equation] K_c=0.33; T_i=390; T_d=50;[/equation]