# Why is MPC better than PID for 3D printers, and (why) is it more useful for 'high-power heaters'?

The YouTube video 'PID vs MPC' from Mark Misin Engineering Ltd perfectly demonstrates that Model Predictive Temperature Control (MPC) is more powerful than Proportional-Integral-Derivative (PID). Marlin implemented MPC as described in Marlin's MPC documentation. The Marlin-based firmware version I use also describes MPC in the mriscoc MPC documentation and as follows:

In the latest releases, MPC is being incorporated in all versions. MPC has proven to be a better algorithm for keeping the nozzle temperature stable, and it is also very useful for high-power heaters.
Source: GitHub mriscoc repository for Ender 3 V2/S1

Since 3D printers, especially the heated parts (bed and nozzle), are relatively simple, with only simple control and sensor readings, why exactly is MPC a better choice than PID? And why is it more useful for 'high-power heaters'?

PID reacts only after the temperature changes are registered by the sensor. MPC instead calculates the expected heat loss before the temperature actually changes and then applies heat to prevent those changes.

Here's a graph comparing PID and MPC, created by Reddit user yelleck:

PID and its modifications1 is the duct-tape solution to the hotend temperature regulation problem2, and MPC is the engineering-PhD solution.

MPC is a predictive model that compensates before the temperature actually changes. It calculates a physical heat model (effectively a Thermal Resistance Circuit). Using this, it figures out how much heat energy (in Joules) will leave the hotend in a given time—through radiation, convection, and extruded molten plastic—and thus it knows exactly how much heat energy (again in Joules, or "Watts times Seconds") it has to put in to keep the temperature the same or move to a new temperature. The properties of this physical model (heat capacity, emissivity, etc.) can be obtained automatically with fairly good accuracy or looked up in a table (filament heat capacity per mm).

PID on the other hand is a reactive model that can only work after the temperature has already changed. It is more like a vigilant operator who stares only at the measured difference between the actual and desired temperature. If this temperature difference changes by just a tiny bit, or by a large step, it will immediately try to counteract that error by applying its three rules: P, I, and D.

The three PID coefficients can also be auto-tuned, but the results are... well, let's say there is a reason that there are dozens if not hundreds of PID tuning guides and forum questions out there. The coefficients are not linked to any distinct physical property of your hotend: The geometry, fan, heater power, silicone sock, and filament are all mushed together into three abstract numbers. So far I have tried a handful of times to get a deep, intuitive understanding of PID behavior and tuning, but have failed each time, and honestly, I don't consider it worth my time anymore. MPC just makes so much more sense.

The PID controller does not know or care why the temperature difference changed. It could be due to faster extrusion speed, switching on the fan, or a changed temperature setpoint (M104), for example. A PID controller has to react to any changes using the same rigid 3-rules-system1, although the three situations will in practice require different reactions. The MPC model, on the other hand, can figure out precisely how much each of those changes would influence the temperature and how it must react to prevent that.

So in a PID-based system, the temperature will always fluctuate a little by design. It needs those temperature changes in order to know how to react (unless you assume a completely static situation), because it is the only measurement it has. Consequently, a noisy temperature measurement, which looks like a lot of tiny, very fast changes, will force the PID controller to react to them, which leads to even more noticeable fluctuations because the system reacts to a change that isn't really there, since it's just noise. Alternatively, you could make it react slower to ignore these fast noise fluctuations, but that will make it... well... slower.

And why is it more useful for 'high-power heaters'?

As explained above, the PID controller must react to noise. With a high-power heater, even a tiny adjustment in the PWM can lead to a large increase in temperature. So the controller must react more slowly and carefully so as not to overshoot or oscillate. But by going more slowly, you are throwing away the main benefit of your high-power heater, namely: faster heating. Since MPC largely ignores noise, it won't oscillate. And since it knows your heater power in Watts and the exact amount of energy needed in Joules, it can just go "full throttle" when a higher temperature is needed3, stopping just in time to avoid overshooting. With a lower-powered heater, this problem is not so apparent, because it can only go slowly anyways.

1 Yes, Marlin has PID_FUNCTIONAL_RANGE, PID_EXTRUSION_SCALING, and PID_FAN_SCALING to work around these issues. Those are hacky, ad-hoc solutions that try to do the same thing as MPC, but without a correct and complete physical model underneath. It's rather like adding more duct tape to the problem instead of stepping back, understanding the situation, and engineering a proper solution. Also, each of these functions has its own configuration parameters, which require separate tuning, while the auto-tuning in MPC can take care of all of them together (except filament heat capacity, which you can look up or calculate using physics instead). So if you consider using those additional PID features, you are essentially using MPC, but without a solid theoretical foundation, so you could as well go all the way and just use MPC instead.

2 Don't get me wrong: PID control is a flexible and well-established tool that is for many, many different tasks everywhere. Just like duct tape. But it is not the best tool for every job. A well-tuned PID can control the hotend temperature within a few degrees with little overshoot. It just wasn't specifically designed for this case, and thus it is outperformed by tools that were.

3 Marlin PID tries to do the same thing with PID_FUNCTIONAL_RANGE: it goes full power when the temperature difference is greater than this configured value. But with a high-power heater, this is an additional value that you have to tune. And after the PID kicks in, it needs some time to "wind up", which is another time during which the heater is not using its full potential. Also, the PID coefficients have to be tuned for different, partially conflicting goals: heating up quickly, avoiding overshoots, and avoiding oscillations. Again, all are lumped together into three abstract numbers with no physical meaning.

• Welcome @Fritz and a very good and comprehensive answer. Thank you! Commented Dec 6, 2023 at 20:56