Remove the 300ms heater control delay?

Following on to the powerful heaters PID tuning impossible route.
All heaters have a hard coded 300ms control delay in the form of the sensor.get_report_time_delta().

I assume this is there to mitigate “Missed scheduling of next digital out event” when scheduling PWM frequency change.

My (untested) suspicion is that a tight control loop is way more accurate than precisely timed control loop. And we are talking about 300 vs 5 ms round-trip times on one side and 0.1 vs 2 ms timing variance on the other side.

Thecnically that would be adding a non-queued version of queue_digital_out oid=%c clock=%u on_ticks=%u?
There is already a update_digital_out oid=%c value=%c for basic 1/0 operations, so a update_digital_out_pwm oid=%c on_ticks=%u should be straightforward.

Edit: On a related note, would be nice to replace next_clock in analog_in_state with actual measurement clock. And get rid of having the Python code guesstimate when the actual measurement took place.

Edit2: Proof of concept: Comparing Klipper3d:master...viesturz:queueless_gpio_pwm · Klipper3d/klipper · GitHub

1 Like

How much variation in temperature do you have now? I had a lot of variation on the E1. It turned out to be a hardware problem.
Look here.

1 Like

Bambu hotend. Stock about 4 degrees oscillation, 1 degrees after tuning the update speed.
Def not a hw problem. It’s well known that fast heaters have a hard time stabilizing the temp on Klipper. Rapido generally gets within the 1 deg stability window with stock params, Bambu has the sensor right next to the heat plate leading to a very fast temp reaction.

1 Like

By tuning update speed I mean smooth_time: 0.2, not this topic.

My E1 extruder is 60 watts. What is yours?
When I test with these macros on a “cold” printer, I get delta temperatures typically lower than 0.1 degrees Celsius. Can you test and see what you get?
Test with L400. The test takes about 30 seconds. Feel free to test several times.

[gcode_macro L400] 
gcode:
    {% for i in range(200) %}
	    M105
	    L401
	    G4 P150
    {% endfor %}
    L402

[gcode_macro L401] 
gcode:
    {% if printer.extruder.temperature < printer["gcode_macro L402"].e0min %}
      SET_GCODE_VARIABLE MACRO=L402 VARIABLE=e0min VALUE={printer.extruder.temperature}
    {% endif %}
    {% if printer.extruder.temperature > printer["gcode_macro L402"].e0max %}
      SET_GCODE_VARIABLE MACRO=L402 VARIABLE=e0max VALUE={printer.extruder.temperature}
    {% endif %}

[gcode_macro L402] 
variable_e0min: 400.0
variable_e0max: 0.0
gcode:
    M118 Extruder0 Min {printer["gcode_macro L402"].e0min
    } Max {printer["gcode_macro L402"].e0max
    } Delta {printer["gcode_macro L402"].e0max - printer["gcode_macro L402"].e0min}
1 Like

A rapido is 115 wats, a Bambu is 48w but tiny thermal mass.
Thanks for the instructions, however I would like to focus on the concept of shortening the control loop, not troubleshooting a random hotend.

  • has this been tried before?
  • is there some research around PID loop duration?
  • does this look technically feasible to try? Any caveats to look out for?
1 Like

Looking at the basic math - Shannon’s theorem says you need at least twice the sampling frequency of the oscillation you want to cancel.

Here are all the times affecting the temp PID loop:

  • single measurement time: 8 milliseconds
  • measurement interval: 300ms
  • temp smooth time: 1 second (tunable in config)
  • pwm scheduling delay: 300ms
  • serial comms delay: none, because control is scheduled via the MCU clock.
  • code time: <1ms

On the surface this is a 300ms loop.
But because the actuation is delayed, it’s actually a 600ms loop:

8ms measure, report, update target PWM, send command, 292 ms wait, 300ms heat

And this corresponds precisely to what I’m seeing in my temperature graph: ~1.2 second oscillations

Here are some links that I found. It doesn’t look like the developers are very interested in this.

The reason I ask is that on my motherboard, the ADC is only 9 bits, i.e. 0 to 1023. This, combined with a very non-linear NTC, makes temperature measurement for high temperatures very inaccurate. (If you have something better, this does not apply to you.) I do not know if it is measured several times to improve this.
If there is noise/inaccurate temperature measurements, (change in) software can help. But it is perhaps better/easier to improve hardware. I got improved temperature stability very much, probably 10 times better, or more.

1 Like

I don’t know if you have found a solution that you are happy with. But anyway, I ask you to visit my thread.
A struggle and a solution with unstable temperature
Download and try the macros for one Extruder and post the result there.

1 Like

Not sure if you are aware or if it materially affects anything you are doing but PTC heaters do not have a linear power output. The rapido may be 115w at 20C but the power output rapidly drops as it reaches print temps. We’ve had a good review and discussion of this when Model Predictive Control (MPC) was ported over to DangerKlipper.

For reference here our power output charts for various PTC heaters.

If you are interested in reading up on MPC as the better replacement for PID here is a link to the user guide in Danger Klipper: Danger_Klipper_Docs/docs/MPC.md at master · YanceyA/Danger_Klipper_Docs · GitHub

Right - the main reason for scheduling these events in the future is to ensure there is a sufficient round-trip-time from sensor reading to PWM update.

I’m sure it is possible, but I don’t think it would be straight-forward. The challenge is ensuring the safety checks remain in place (in particular the maximum duration checks). For what it is worth, I view the heater PWM pins as “critical to be set correctly” and I’d be a little leery of the mcu processing simple “turn yourself on” commands without a more explicit context (such as a timestamp). I do understand your concern with the timing of the feedback loop though.

Cheers,
-Kevin

Just in case, you can basically try to tune:

./klippy/extras/adc_temperature.py:
REPORT_TIME = 0.300 -> 0.1

That should increase control frequency.
I am not sure about long-term stability, you can check if there are actual differences.

Other things to play with:

./klippy/extras/heaters.py:
abs(value - self.last_pwm_value) < 0.05):

This is basically a filter, so if you decrease 0.05 → 0.01 PWM will be updated more ‘preciese’.

From my limited testing, with my homemade rapido UHF (CHC Pro + Nut).
The filter has more importance. But I’m talking about +0.2C vs +0.1C

Another way, you can also try to decrease the max power of your hotend, which should also help stabilize it, if that is what you want.

I think this is more or less a proper fix for eliminating delay:

1 Like