TMC Coolstep and how to make it works

Hi, I spent some time under the hood, klipper has a nice codebase.
So, I made TMC CoolStep work and also made some tools to measure live driver values (similar to ADXL345).



There are some graphs of XY.

A bit of explaining:

  • They are cumulative - no time here only value distribution
  • CS is the actual current scaler max value 31 (or IRUN)
  • SG is stall guard live measurements.

I had TMC5160 with ~48V power for reference, LDO 2504 & 1.768A RMS.
This is my Ratrig V-Core 3.1 400 mm.

What can I say for now:

  • It works, in my case with almost default registers.
  • I tuned it by sensorless homing and after by graphs above.
  • It is more or less reliable above 100 mm/s
  • Without aggressive tuning, looks like the current can be decreased by 20% may be.
    But I don’t measure it with real print for now.

10 min orca tolerance test print, but without filament for now.


Looks like under 150 mm/s is noisy and can be unreliable.


Extruder data, modern extruders often has small motors and plenty of power.
So it is possible that coolstep can allow run them cooler.
There is Orbiter 2.0 on TMC2209.
Gear Ration 7.5:1 and rotational distance 35.
Simplified to 4.67 mm per rotation.
Velocity to flow for that extruder is:

10.5 * (3.14 * (1.75/2)**2) = 25.24 # ~ 2 RPS


Graphs are much more stable and reproducible here.
After 2 RPS (10 mm/s or ~ 25 mm^3), the driver can regulate the current and downscale.

So, this is only will work for High Flow hot end or extruder with a higher gear ratio.


The topic will be updated if there is interest or if I have new interesting data.
fork with dirty patches (coolstep-manual branch): GitHub - nefelim4ag/klipper at coolstep-manual
Thanks

Developers

3 Likes

There are my testing macros, X, Y, and Extruder.

[force_move]
enable_force_move: True

[gcode_macro SG_LOOP_TEST_Y]
gcode:
    G28
    # Yes, I'm too lazy to use range()
    {% set vel = (25, 50, 75, 100, 125, 150, 175, 200, 225, 250, 275, 300, 325, 350, 375, 400, 425, 450, 475, 500, 525, 550, 575, 600, 625, 650, 675, 700, 725, 750, 775, 800, 825, 850, 875, 900) %} # set velocity values to be tested (mm/s)
    {% set min_x = printer.toolhead.axis_minimum.x|float +20 %}
    {% set max_x = printer.toolhead.axis_maximum.x|float -20 %}
    {% set min_y = printer.toolhead.axis_minimum.y|float +20 %}
    {% set max_y = printer.toolhead.axis_maximum.y|float -20 %}
    G90
    G0 X{ printer.toolhead.axis_maximum.x/2 } Y{ printer.toolhead.axis_maximum.y/2 } Z15 F7200
    MEASURE_STALLGUARD STEPPER=stepper_y
    # I have a 400x400 mm printer, you may want to reduce that
    {% set distance = {'value': 150} %}
    FORCE_MOVE STEPPER=stepper_y DISTANCE={distance.value//2 * -1} VELOCITY=100 ACCEL=20000
    {% for V in vel %}
        M117 velocity:{V}mm/s, accel:{A}mm/s^2
        FORCE_MOVE STEPPER=stepper_y DISTANCE={distance.value} VELOCITY={V} ACCEL=20000
        {% if distance.update({'value': distance.value * -1}) %} {% endif %}
    {% endfor %}
    MEASURE_STALLGUARD STEPPER=stepper_y
    G28 X Y

[gcode_macro SG_LOOP_TEST_X]
gcode:
    G28
    {% set vel = (25, 50, 75, 100, 125, 150, 175, 200, 225, 250, 275, 300, 325, 350, 375, 400, 425, 450, 475, 500, 525, 550, 575, 600, 625, 650, 675, 700, 725, 750, 775, 800, 825, 850, 875, 900) %} # set velocity values to be tested (mm/s)
    {% set min_x = printer.toolhead.axis_minimum.x|float +20 %}
    {% set max_x = printer.toolhead.axis_maximum.x|float -20 %}
    {% set min_y = printer.toolhead.axis_minimum.y|float +20 %}
    {% set max_y = printer.toolhead.axis_maximum.y|float -20 %}
    G90
    G0 X{ printer.toolhead.axis_maximum.x/2 } Y{ printer.toolhead.axis_maximum.y/2 } Z15 F7200
    MEASURE_STALLGUARD STEPPER=stepper_x
    {% set distance = {'value': 150} %}
    FORCE_MOVE STEPPER=stepper_x DISTANCE={distance.value//2 * -1} VELOCITY=100 ACCEL=20000
    {% for V in vel %}
        M117 velocity:{V}mm/s, accel:{A}mm/s^2
        FORCE_MOVE STEPPER=stepper_x DISTANCE={distance.value} VELOCITY={V} ACCEL=20000
        {% if distance.update({'value': distance.value * -1}) %} {% endif %}
    {% endfor %}
    MEASURE_STALLGUARD STEPPER=stepper_x
    G28 X Y

[gcode_macro SG_EXTRUDER]
gcode:
    # set flow values to be tested (mm/s)
    {% set flow = (10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40) %} 
    MEASURE_STALLGUARD STEPPER=extruder
    {% set distance = {'value': 25} %}
    {% set speed_devider = (3.14 * (1.75/2)*(1.75/2)) %}
    {% for F in flow %}
        G1 E{distance.value} F{F/speed_devider * 60}
        {% if distance.update({'value': distance.value * -1}) %} {% endif %}
    {% endfor %}
    MEASURE_STALLGUARD STEPPER=extruder

There is a script to generate graphs:

./scripts/calibrate_stallguard.py /tmp/stepper_y-20240512_010858.csv -o ~/klipper/stepper_y-20240512_010858.png
1 Like

There is cumulative data from real print ~1h18m, filtered by min 130 mm/s, max 1000 mm/s
with enabled CoolStep.

I need to filter everything above 1000 mm/s because for some reason (step compression?) driver sometimes sees almost zero latency between steps.

I use 150 mm/s as the start threshold for the CoolStep & allow a current reduction of up to half.



I tried to reduce it to 50 mm/s (I can use sensorless homing at that speed), but StallGuard output was pretty unstable at such low speeds and I skipped steps.

Same graphs, with the same filter but over time, extruder is a mess.
X and Y are pretty stable.



This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.