What algorithm is being used for smoothing by the pid controller?

what algorithm is being used here? My degree is in computational physics/math, but i don’t recognize this algorithm.

Some related discussion here:

I was also confused by this line, but I believe that it is simply a first order low-pass filter.

1 Like

It’s a “modified moving average” - see Moving average - Wikipedia and Moving average - Wikipedia



I see this has been in the code base since the very beginning, can you speak to why this is being used? Was this an attempt at getting a more accurate derivative?

I ask, because I’m rewriting the ControlPID class. I stripped this, and the temp_integ_max bits out, as well as fixed a logic error. I’m now getting substantially better control for the same kp, ki, & kd values.

I was just getting ready to do a second pass, and switch to trapezoidal integration as its substantially more accurate than the right hand method currently being used. so I could fairly easily add this back in, if it yielded a benefit.

Yes - it is intended to reduce the impact of noise on the derivative calculation.


you are already dealing with noise pretty well in the adc controller via oversampling.

What looks like noise in the derivative data is just the fact the ‘backward Euler method’ (what temp_diff / time_diff is) is the simplest way to numerically calculate a derivative, but that also makes it the least accurate. its error is on the order of O(h), so to get a more accurate answer, temp updates would need to happen 10 to 100 times more often (not realistic).

The moving average is’t really helping, as it averaging data that’s already been averaged at the adc level. its adding lag/delay that looks like smoothing.

if the data truly needed to be smoothed, the temp readings feed into temperature_update would need to be smoothed using something like a Savitzky Golay filter, and then the derivative calculated based on the smoothed temperature values.

In my opinion what is needed, is not smoothing but a derivative algorithm with error on the order of O(h^2) or O(h^3). I’m looking at that now, and then i will post something to be reviewed/tested by others, or i will just putt it all in a pr.

Just for reference: Klipper with MPC
Dunno if there are any real world advantages or just added complexity, at least it sounds nice at the first impression.
This is the corresponding Marlin PR: https://github.com/MarlinFirmware/Marlin/pull/23751 (and MPC tuning improvements by tombrazier · Pull Request #23984 · MarlinFirmware/Marlin · GitHub)

I’ve seen those, but they add a lot of extra parameters, that can cause issues. For example 3 big ones that jump out at me, are the model looks at ambient temperature, filament, and fan speed. Those are variables that are constantly changing, thus throwing of the model to varying degrees.

what I’m working on is making the current pid controller, better without adding any new parameters.

A “low pass filter” to reduce noise in the derivative calculation is a common feature of PIDs.

It might be useful to change the default to zero as we have seen that it can lead to oscillations on some boards. (It used to default to 2 seconds; it was changed to 1 second after reports of oscillations.)


Imo, that’s because a lot of them are using the backward Euler method. The method only works well when h is really small. Thus, even an insignificant amount of noise, or lack of precision in your data, can causes large oscillations.

Take a look at the attached spreadsheet, it compares the different numerical derivative methods to the analytical derivative.

y’(x) is the analytical derivative, “back euler” and “Mod mov avg” is what is being used now.

finite diff 3,4,5,6 are using the finite difference concept to calculate the derivative. finite diff 3 uses the current value and 2 previous ones. finite diff 4 uses the current value and 3 previous ones. The more points you use the more accurate the answer will be.

keep in mind I’m using an exponential here as its basically a worse case scenario for numerical differentiation.

y(x) = 2.5x + e^x

dif.zip (8.6 KB)

I think this might be a better example.

for the function y(x) =-2 * e^(-0.1x) * cos(.4x) the plot shows the actual derivative, the euler approximation, and moving average approximation.

Out of curiosity, have you tried feeding real thermistor or RTD data from a printer through this algorithm? I can dig out some 0.3s resolution raw data from my previous smoothing tests with a thermistor and I could attempt to generate some more data from my current PT1000 configuration. The PT1000 appears more noisy when looking at the temperature input and the PID PWM drive, but this could be just the inherently lower ADC resolution with the ~1000 Ohm probe.

It is worth noting though that my printer is likely in the upper percentile bracket in terms of ADC signal quality - I use a Duet3 Mini and am quite cognizant of wiring electro-magnetic coupling, etc.

I’ve looked at some, but it’s not super useful, other than to see how much noise you are dealing with. as I’ve improved the algorithm, noise has started to become the limiting factor, so i’m looking into how best to mitigate that now. I want to try and avoid the delay as much as possible.

My thoughts would be that characterizing the boundaries of noise amplitude in different printer installations and configurations would shed light on the required degree of derivative “smoothing”…

Since I am not a native speaker, sorry for my poor English.
But anyway, I have tried mpctemp and it works great. The model requires ambient temperature only when calibrating. For me, it only takes me around 3min to calibrate by simply send the command ‘M306 T’ without specific target temp. And the result is amazing, there is NO OVERSHOOT even if I tune the target temp or fan speed down and up. Speak of the heat capacity of filament, I think as long as someone are not using a werid material, this parameter could remain the same without changing.