Add docs/temp_control_calibration.md

Covers Smith predictor parameter identification (C, M, L, Td) from log
data, model-plant replay verification, and controller performance metrics.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NSo8R6GjoBQdStB3j67zSs
This commit is contained in:
2026-06-29 22:05:37 +02:00
co-authored by Claude Sonnet 4.6
parent 6ecfa2d38a
commit abcd011a9f
+119
View File
@@ -0,0 +1,119 @@
# Temperature controller calibration
## Controller overview
`components/pid/temp_controller_smith.py` implements a Smith predictor. Each tick it computes:
```
theta_ist = theta_ist_model + (theta_ist_plant theta_ist_model_delay)
```
`theta_ist_model` comes from a fast internal `Pot` (transport delay Td = 0);
`theta_ist_model_delay` from a second `Pot` with the full configured Td.
The correction term `(theta_ist_plant theta_ist_model_delay)` removes the dead
time from the feedback path.
The plant model (`components/plant/pot.py`) integrates:
```
temp += (delayed_power_in L·M·(temp theta_amb)) / (M·C) · dt
```
Four parameters must be calibrated:
| Parameter | Unit | Meaning |
|---|---|---|
| C | J/(kg·K) | Specific thermal capacity |
| M | kg | Mass of pot + water + grain |
| L | W/(kg·K) | Heat loss coefficient |
| Td | s | Transport (heater-to-sensor) delay |
## 1. Verify model-plant match: replay simulation
Feed the **recorded `power_eff`** from a log file into a fresh `Pot` instance
with the same parameters and compare the simulated temperature to `temp_ist`.
```python
from components.plant.pot import Pot
pot = Pot(dt=1.0)
pot.set_plant_params({'C': C, 'M': M, 'L': L, 'Td': Td})
pot.set_ambient_temperature(theta_amb)
pot.initial(samples[0]['temp_ist'])
sim_temp = []
for s in samples:
pot.set_power(s['power_eff'])
pot.process()
sim_temp.append(pot.get_temperature())
```
Plot `sim_temp` (model) against `temp_ist` (real) and the residual
`temp_ist sim_temp`. What divergence tells you:
| Symptom | Likely cause |
|---|---|
| Ramp slopes differ | C·M wrong |
| Phase shift between power step and temperature rise | Td wrong |
| Wrong equilibrium temperature during HOLD | L wrong |
| Residual grows over a long run | Model drift / L temperature-dependent |
## 2. Parameter identification from log data
### Td — transport delay
Cross-correlate `power_eff` with `temp_ist`. The lag at peak correlation is the
actual Td. Alternatively, find a sharp power step (start of a ramp) and measure
the visible delay before `temp_ist` begins rising.
### L — heat loss coefficient
At steady-state HOLD, `d(temp)/dt ≈ 0`, so all input power compensates losses:
```
P_hold = L · M · (T theta_amb)
→ L = P_hold / (M · (T theta_amb))
```
Repeat across hold phases at different temperatures and fit a line through
`(T theta_amb)` vs `P_hold` for a more robust estimate.
### C — specific heat capacity
During a ramp where heat loss is small relative to input power:
```
C ≈ power_eff / (M · rate_ist_K_per_s)
```
`rate_ist` in the log is K/min; divide by 60 to get K/s. Use a mid-ramp window
where `power_eff` and `rate_ist` are both stable.
## 3. Controller performance metrics
These can be read directly from the log without re-simulation:
| Metric | How to compute |
|---|---|
| Overshoot | `max(temp_ist) temp_soll` after each setpoint step |
| Settling time | First time `|temp_ist temp_soll| < threshold` is sustained after a step |
| Steady-state error | Mean of `temp_soll temp_ist` during HOLD phase |
| Rate tracking error | `rate_ist rate_soll` during RAMP |
### Smith predictor correction signal
The term `theta_ist_plant theta_ist_model_delay` is the Smith correction; a
growing correction signal indicates model drift. This is not currently written to
the log. To observe it, log `theta_ist_model` and `theta_ist_model_delay` from
`temp_controller_smith.py` alongside the existing fields.
## 4. Suggested addition to analyze_log.py
A replay panel added to `utils/analyze_log.py` would show:
- `temp_ist` (blue) vs `sim_temp` (red dashed) — model accuracy at a glance
- Residual `temp_ist sim_temp` in a separate subplot — reveals systematic
parameter errors vs noise floor