LUNAROPS · OPERATIONAL UPLINK 100% UPTIME 1,247d POSTS 893 JEFF.MOON@LUNAROPS.DEV UTC --:--:--

Sous Vide Is Just a PID Loop

sous-videcontrol-theorypidfood-sciencediyesp32

A steak overcooks because heat does not know when to stop. Drop it in a 230 C pan and the surface races past well-done while the center is still raw, and the only tool a conventional cook has against that gradient is timing and nerve. Sous vide deletes the problem by changing the boundary condition: instead of applying a huge temperature difference and yanking the food out at the right instant, you submerge it in water held at exactly the doneness temperature you want and let the whole piece equilibrate. The food cannot overcook because there is nowhere hotter for it to go. The center asymptotically approaches the setpoint and stops. That is the entire idea, and it is not really a cooking technique — it is a closed-loop control problem with a tasty output.

Once you see it that way, every part of the practice becomes legible. The immersion circulator is a controller holding a setpoint against disturbances. The water bath is a thermal capacitor that makes the loop stable. The “cook chicken to 165 F” rule is a conservative shortcut around a logarithmic kill-rate equation. The thickness of the meat sets a diffusion time constant. And the sear at the end is a deliberately separate, high-rate process bolted on because the low-and-slow loop cannot produce the one thing it is structurally incapable of: a browned crust. Sous vide is what happens when you stop cooking by vibes and start cooking by control theory, and the surprising thing is how little of it is actually about food.


Water is the ideal medium because it has enormous thermal mass

The reason sous vide works at all is a property of water that has nothing to do with cooking: its volumetric heat capacity is gigantic compared to air. Water holds roughly 4.18 joules per gram per degree, and it is dense, so a bath of it stores an enormous quantity of thermal energy per degree of temperature. That stored energy is what makes the control loop stable, because thermal mass is the physical equivalent of a low-pass filter — it smooths disturbances and slows the rate at which the controlled variable can move.

Compare the media. A convection oven controls air, which has a specific heat per unit volume thousands of times lower than water; open the door and the temperature collapses, and the food’s surface sees wild swings. Water resists all of that. Drop a cold steak into a 56 C bath and the bath temperature barely flinches, because the steak’s heat capacity is small next to the bath’s. The disturbance the food represents is tiny relative to the energy reservoir it is perturbing, which is exactly the condition you want in a control system: a plant with large inertia and small disturbances is easy to hold at setpoint.

Water also transfers heat to the food far better than air. Its thermal conductivity is about 25 times that of air, and convective transfer in a stirred bath is better still, which is why circulators circulate — moving water breaks up the insulating boundary layer at the bag surface and keeps the food’s exterior pinned to the bath temperature. The combination is what gives sous vide its defining property: the food’s surface is held at the target, and heat flows inward purely by conduction through the food itself, so the final state is the entire piece sitting at one uniform temperature. The same large-thermal-mass-makes-a-stable-loop principle is why an aquarium behaves like a production system — a big water volume is a forgiving plant to control, in a fish tank or a stock pot.


What the PID loop actually does

Inside the immersion circulator is a controller running a PID loop, and understanding its three terms tells you exactly why good circulators feel effortless and cheap ones oscillate around the setpoint. PID stands for Proportional, Integral, Derivative, and it answers one question forty times a second: given where the temperature is now, how hard should I drive the heater?

 setpoint ──>(+)── error ──┬──> Kp * error ───────────┐
              ^            │                            │
              │            ├──> Ki * ∫error dt ─────────┼──>(+)──> heater PWM
              │            │                            │
              │            └──> Kd * d(error)/dt ───────┘
              │                                          
              └────────────── measured temp <── sensor <── water bath

The proportional term drives the heater in proportion to the error — far from setpoint, push hard; close to it, ease off. P alone cannot hold a setpoint, though: to keep the water warm against heat loss you need some steady heater output, but P produces output only when there is error, so a pure-P controller settles at a permanent offset below target. The integral term fixes this by accumulating error over time — the longer the bath sits below setpoint, the more I winds up and the harder it drives, until the steady-state error is eliminated. The derivative term looks at the rate of change and damps the approach, backing off as the temperature rushes toward setpoint so the system does not blow past it.

The classic failure of cheap circulators is oscillation, and it is a tuning problem, not a hardware mystery. If the proportional gain is too high or the integral term winds up too aggressively, the controller overshoots the setpoint, then over-corrects downward, then overshoots again — a bath that reads 56.0, then 57.2, then 55.1, hunting back and forth instead of settling. This is identical to every other unstable feedback loop, including the alert systems that flap between firing and clearing because their thresholds and damping are wrong. The fix is the same: lower the gain, add damping, and accept a slightly slower approach in exchange for a stable steady state. A well-tuned circulator with good thermal coupling holds setpoint to within a tenth of a degree and never visibly hunts; that tight control is most of what you are paying for in a premium unit, and it is why “it heats water” wildly undersells what the device does.


The food-safety math is logarithmic, not a magic number

The single most misunderstood thing in cooking is the safe-temperature rule, because “cook chicken to 165 F” is presented as a threshold when the underlying reality is a rate equation. Pasteurization is not a temperature you reach; it is a number of bacteria you kill, and killing bacteria with heat is a logarithmic process governed by two parameters every food scientist knows: the D-value and the z-value.

The D-value is the time required to kill 90% of the target organism — a one-log (factor-of-ten) reduction — at a given temperature. For Salmonella, the D-value at 60 C (140 F) is about 5.5 minutes: hold the food at 60 C for 5.5 minutes and you kill 90% of the Salmonella; hold it for 11 minutes and you kill 99%; for 16.5 minutes, 99.9%. Each D-value interval removes another factor of ten. The z-value describes how the D-value changes with temperature — for Salmonella it is about 5.5 C, meaning every 5.5 C hotter cuts the required time by a factor of ten. Crank the temperature and the kill accelerates enormously.

The USDA’s safety target for poultry is a 7-log reduction (7D) — kill all but one in ten million organisms. Now the magic of 165 F dissolves. Here is the same 7-log Salmonella kill expressed across temperatures:

Bath temp Salmonella D-value Time for 7-log (7D) reduction
54.4 C / 130 F ~54.8 min ~6.4 hours
57.2 C / 135 F ~16.9 min ~2.0 hours
60.0 C / 140 F ~5.48 min ~38 min
62.8 C / 145 F ~1.7 min ~12 min
65.6 C / 150 F ~0.54 min ~3.8 min
73.9 C / 165 F ~0.1 min seconds (effectively instant)

The famous “165 F” is simply the temperature where 7D happens so fast it is instantaneous on the timescale of cooking — you reach temperature and you are already safe, so a single number suffices and no one has to think about holding time. But the table shows you can achieve the identical 7-log reduction at 60 C if you hold for 38 minutes, producing chicken that is safe by the exact same standard yet juicy and tender instead of dry. Sous vide trades the convenience of a single threshold for a time-temperature combination, and that trade is the whole reason it can make safe poultry that does not taste like a regret. This is the same D-value/log-reduction framework that governs fermentation as bioprocess control — food safety is a kill-rate calculation whether you are heating it or acidifying it.

One critical caveat: these times are holding times at temperature, and they begin only once the coldest part of the food reaches the bath temperature. Which brings us to the part most people get wrong.


Thickness sets the time constant, and it scales with the square

The most common sous vide mistake is thinking the cook time depends on weight. It does not. It depends on thickness, and it depends on thickness squared, because you are solving a heat-diffusion problem and the characteristic time of diffusion scales with the square of the distance heat has to travel.

The physics is the heat equation. Heat enters the food at the surface and conducts inward, and the time for the center to come within a fraction of a degree of the surface temperature goes as:

   t_center  proportional to  (thickness)^2 / thermal_diffusivity

   double the thickness  ->  4x the heating time
   triple the thickness  ->  9x the heating time
   (weight is irrelevant; a wide thin steak heats as fast as a small thin one)

This is why a 2 cm steak reaches core temperature in roughly 45 minutes while a 4 cm roast of the same meat takes around three hours — not double, quadruple, because the heat has to diffuse twice as far and diffusion time goes as distance squared. Douglas Baldwin’s widely-used tables tabulate exactly this: heat-up time as a function of thickness and starting temperature, for slab, cylinder, and sphere geometries. The practical rule is to measure the thickest dimension of your food, not its mass, and look up the heating time from that.

The total time in the bath is therefore two stages added together: the heat-up time (thickness-driven, gets the core to temperature) plus the pasteurization hold (temperature-driven, from the table above). For a thin chicken breast at 60 C, the heat-up might be 40 minutes and the hold 38 minutes — but conveniently, much of the kill happens during the final approach as the core climbs through the lethal zone, so the table values already bake in conservative assumptions. Starting from frozen simply adds heat-up time; you cannot under-cook by leaving it in longer, because the food cannot exceed the setpoint, which is the entire safety margin of the method. The failure mode is pulling food too early — before the core has reached temperature — and it is invisible without a probe, which is the same lesson as any debugging problem where the bug is a state you did not measure rather than one you can see.


Searing is a separate, high-rate process

Here is the structural limitation sous vide cannot escape: the browned, savory crust everyone wants comes from the Maillard reaction, and the Maillard reaction runs meaningfully only above about 140-150 C — more than double the boiling point of water. A water bath physically cannot get there. So the crust is not part of the sous vide loop at all; it is a second, deliberately separate process running at a completely different operating point, applied for a deliberately short time at the very end.

This two-stage architecture is the actual technique: a long, low-rate, tightly-controlled equilibration to set doneness, followed by a short, high-rate, uncontrolled blast to brown the surface without raising the interior. The reason you sous vide first and sear second is thermal: a quick, brutally hot sear — a ripping-hot cast iron pan, a torch, a few seconds per side — browns the exterior faster than the heat can diffuse inward, so the gray “overcooked band” beneath the crust stays paper-thin. Sear too long or too cool and the heat soaks in, ruining the uniform interior the bath worked to create. The sear is a high-Péclet-number process: surface reaction fast, inward diffusion slow, and you exploit the gap.

The honest tradeoff is that this is two pieces of equipment and two steps for what a skilled cook does in one pan. A restaurant line cook can take a steak from raw to perfectly-rested with a crust using nothing but a pan, heat, and judgment, in a fraction of the wall-clock time. Sous vide’s advantage is not speed and not fewer tools; it is reproducibility and parallelism — it removes the judgment, so the result is identical every time and you can hold a dozen portions at perfect doneness simultaneously, then sear on demand. That is a genuine win for a dinner party or a restaurant and close to pointless for a single weeknight steak.


DIY: an ESP32 and an SSR versus buying a circulator

Because sous vide is just a PID loop driving a heater, it is one of the most satisfying control projects you can build, and the build teaches you more about feedback control than any amount of reading. The bill of materials is small: a temperature probe, a microcontroller running PID, a solid-state relay to switch the heater, a heating element (a cheap immersion heater or a rice cooker), and a pump or a stir mechanism to break the boundary layer.

A canonical build is an ESP32 with a waterproof DS18B20 probe reading the bath, running a PID loop in firmware, driving a solid-state relay (SSR) that switches a mains heating element. The SSR is the key component: a mechanical relay clicking on and off many times a minute would wear out in days, but an SSR switches silently at the zero-crossing of the AC waveform with no moving parts, so the controller can pulse the heater with PWM-like duty cycling indefinitely. (An SSR is just a triac or back-to-back thyristors gated by an opto-isolated LED — solid-state switching all the way down, the same family of semiconductor physics that runs everything else.) The same ESP32/MicroPython homelab toolchain that drives your other sensors handles this directly, and you can wire the whole rig into Home Assistant for setpoints, history, and a “core has reached temperature” notification.

Here is the heart of it — a minimal PID step, the same handful of lines whether it runs on an ESP32 or a commercial circulator’s MCU:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
class PID:
    def __init__(self, kp, ki, kd, setpoint):
        self.kp, self.ki, self.kd = kp, ki, kd
        self.setpoint = setpoint
        self.integral = 0.0
        self.prev_err = 0.0

    def step(self, measured, dt):
        err = self.setpoint - measured
        self.integral += err * dt
        # anti-windup: clamp the integral so it can't overshoot wildly
        self.integral = max(min(self.integral, 50.0), -50.0)
        deriv = (err - self.prev_err) / dt
        self.prev_err = err
        output = self.kp * err + self.ki * self.integral + self.kd * deriv
        return max(0.0, min(1.0, output))   # heater duty cycle 0..1

# tune by hand: raise kp until it oscillates, back off, add ki to kill
# steady-state offset, add a little kd to damp the overshoot
pid = PID(kp=0.8, ki=0.02, kd=4.0, setpoint=56.0)
duty = pid.step(measured=bath_temp_c, dt=1.0)

The honest comparison: a commercial circulator costs less than the parts-plus-time of a good DIY build, holds tighter tolerance out of the box, is waterproof and safe by design, and you can buy one this afternoon. The DIY rig wins on exactly two axes — it is a phenomenal learning project that makes PID viscerally real, and it integrates into a homelab so you can log every cook to Prometheus and Grafana and compare batches. If you want dinner, buy the circulator; if you want to understand the circulator, build one.


Where it genuinely wins, and where it is nerd theater

Sous vide is neither a miracle nor a gimmick, and the engineer’s job is to know which problems it actually solves. It wins decisively wherever the conventional method forces a painful tradeoff between safety and quality, or wherever reproducibility matters more than speed.

It genuinely beats conventional technique for: thick steaks and chops cooked edge-to-edge at one doneness with no gray band; chicken breast that is both safe and juicy (impossible by the 165 F threshold, trivial by the 60-C-for-38-minutes path); tough cuts held for long enough that collagen converts to gelatin at a temperature below the one that squeezes out all the water — a 36-hour short rib at 60 C is a thing no other method can produce; eggs cooked to a custard texture that lives in a one-degree window; and any situation where you need a dozen portions at identical doneness on demand. These are not preferences; they are results the physics of conventional cooking cannot reach.

It is nerd theater for: a single thin weeknight steak (a pan is faster and as good); anything where the bag-then-sear two-step costs more time and cleanup than it saves; green vegetables (which want temperatures above water’s useful sous vide range and gain nothing); and any dish where a skilled cook’s pan judgment already nails it. There is also a real downside ledger — long cook times measured in hours, plastic bags and the associated questions, the inability to brown without a second step, and a meaningful equipment footprint for what is sometimes a marginal gain. The method’s superpower is removing variance, so its value is highest exactly when variance is your enemy: cooking for a crowd, cooking an unforgiving cut, or cooking something whose safe-and-good window is too narrow to hit by feel.


Verdict

Sous vide is control theory you can eat, and seeing it that way explains everything the recipes leave out. Water is the medium because its enormous thermal mass turns the cook into a stable feedback loop with large inertia and small disturbances — the easiest kind of plant to hold at setpoint. The circulator is a PID controller, and the difference between a great one and a cheap one is tuning: oscillation around the setpoint is the same instability that makes any feedback loop hunt, and the cure is the same lower-gain, more-damping fix. The safe-temperature rule is not a threshold but a logarithmic kill-rate governed by D-values and a 7-log target, which is why you can pasteurize chicken at 60 C held for 38 minutes and get the identical safety of 165 F with none of the dryness. Cook time depends on thickness squared, not weight, because it is a heat-diffusion problem, and the only way to under-cook is to pull the food before its core reaches temperature — a state you cannot see without a probe. The sear is a separate high-rate process precisely because water cannot reach Maillard temperatures, so the real technique is a slow controlled equilibration followed by a fast uncontrolled browning. Build the rig from an ESP32 and an SSR if you want PID to become viscerally real; buy the circulator if you just want dinner. And deploy it where it actually wins — thick cuts, safe-and-juicy poultry, long collagen conversions, and feeding a crowd at identical doneness — while skipping the cases where a hot pan and a little judgment already win. The crock-pot futurists oversold it as magic. It is better than magic: it is a well-behaved control loop, and control loops are predictable, which in a kitchen is the rarest luxury of all.


Sources

Comments