• Tags
  • Documentation
  • Order
  • Register
  • Login
Duet3D Logo Duet3D
  • Tags
  • Documentation
  • Order
  • Register
  • Login

Magnetic Filament Monitor for Automatic E-Step Calibration

Scheduled Pinned Locked Moved
Filament Monitor
5
12
1.9k
Loading More Posts
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • undefined
    timschneider
    last edited by 19 Sept 2023, 20:50

    Hi folks,

    I had the idea of a method for automatic e-step calibration. As it is not easy to get the e-step calibration right - in sense of how good the MFM is doing the measurement. So i thought, why not use the MFM in first place?

    There are some requirements in order for the method to work, but these requirements are also positive for the MFM itself.

    • The MFM must be tightly connected to the extruder (stiff and short)
    • The initial calibration of the mm/rev of the MFM must be done by hand or math

    That's it.

    You only need around 500mm of Filament and you are good to go.

    I use the following method

    • set the L parameter of the MFM to your needs, I measured 8mm diameter of the sense wheel, so the circumference is about 25.13mm - I rounded it to 25.3
    • set the min and max allowance values very tight, I use 98% and 102%
    • set the reporting distance very small, I use 0.2mm
    • now start printing a calibration file, where the file is basicly only extruding short chunks of 1mm filament with only 30 mm/min at your desired temperature, in the example 235° for petg carbon filled
    • if the MFM is reporting tooLittleMovement, increase the e-steps
    • if the MFM is reporting tooMuchMovement, decrease the e-steps
    • store the latest reported e-steps in your filament config.

    thats it - works like a charm, and the sporadic false tooLittleMovement error is gone 🙂

    My g-code files for reference only, as they use other macros of our printers.

    0:/gcodes/filament_monitor_calibration.gcode

    if exists(global.mfmcalibration)
      set global.mfmcalibration = true
    else
      global mfmcalibration = true
    
    G10 P0 S235 ; sets the temperature
    M140 P0 S100 ; set bed temp
    
    M107                                        ; fan off
    M144 P0 S1                                  ; activate bed 1 heater
    T0                                          ; select tool 0
    M98 P"0:/sys/meltingplot/home_if_necessary" ; check homing
    G29 S1                                      ; load stored hight map
    
    M83 ; use relative distances for extrusion
    G90 ; use absolute coordinates
    G21 ; set units to millimeters
    
    M116                                        ; wait for all heaters
    
    G11 ; unretract
    
    G1 Z300                                      ; raise z=20mm
    
    G53 G1 X50 Y50 F14400                       ; move printhead to center
    
    G92 E0                                       ; reset e-steps
    
    M572 D0 S0.0                                 ; disable pressure advance
    
    M591 D0 P3 C"e1stop" S1 R98:102 E0.2 L25.3           ; enable MFM
    
    G4 S5 ; wait for restart of MFM
    
    G91 ; relative moves
    ; 500mm
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    G1 X1 E1 F30
    
    G10                                          ; retract
    G10 P0 R0 S0                        ; disable hotend
    M140 S0 R0                          ; set bed heater to 0°
    M140 P0 S-273.1                     ; disable bed heater
    T-1                                          ; unselect tool
    
    set global.mfmcalibration = false
    

    0:/sys/filament-error.g

    ; Parameter P description
    ; 2 = noDataReceived
    ; 3 = noFilament
    ; 4 = tooLittleMovement
    ; 5 = tooMuchMovement
    ; 6 = SensorError
    ; 7 = Magnet to weak
    ; 8 = Magnet to strong
    
    if param.P == 2 || param.P == 6
        echo "Filament Sensor Error: " ^ param.P ^ "  sensor : " ^ param.D ^ " - continue printing"
        M99
    
    if param.P == 4
        if !exists(global.mfmcalibration) || global.mfmcalibration == false
            echo "Filament Sensor " ^ param.D ^ ": Too little Filament movement - Possible Reasons: Filament empty, grinding or clogged nozzle."
            M291 P{"Filament Sensor " ^ param.D ^ ": Too little Filament movement - Possible Reasons: Filament empty, grinding or clogged nozzle."} S1 T0
            M25 ; pause print
        else
            M92 E{move.extruders[0].stepsPerMm+0.1}
            echo "E-Steps: " ^ {move.extruders[0].stepsPerMm} ^ ""
        M99 ; leave macro
    
    if param.P == 5
        if !exists(global.mfmcalibration) || global.mfmcalibration == false
            echo "Filament Sensor " ^ param.D ^ ": Too much Filament movement - Possible Reasons: Spool skipped or Filament pushed into PTFE tube."
            M291 P{"Filament Sensor " ^ param.D ^ ": Too much Filament movement - Possible Reasons: Spool skipped or Filament pushed into PTFE tube."} S1 T0
            M25 ; pause print
        else
            M92 E{move.extruders[0].stepsPerMm-0.1}
            echo "E-Steps: " ^ {move.extruders[0].stepsPerMm} ^ ""
        M99 ; leave macro
    
    echo "Filament error: " ^ param.P ^ " on sensor " ^ param.D ^ " - paused"
    M291 P{"Filament Sensor " ^ param.D ^ ": " ^ param.S ^ " - Paused"} S1 T0
    M25 ; pause
    
    T3P3Tonyundefined 1 Reply Last reply 21 Sept 2023, 18:13 Reply Quote 4
    • T3P3Tonyundefined
      T3P3Tony administrators @timschneider
      last edited by 21 Sept 2023, 18:13

      @timschneider this is great! Thanks for sharing it 😁

      www.duet3d.com

      undefined 1 Reply Last reply 27 Sept 2023, 10:55 Reply Quote 0
      • undefined
        timschneider @T3P3Tony
        last edited by 27 Sept 2023, 10:55

        @T3P3Tony
        I was even able to push it a little further. The most pain four our customers is the non-linear-extrusion calibration.

        And what should I say, it is even possible to do that with the MFM 🙂

        non_linear_extrusion_calibration.gcode

        if exists(global.nlecalibration)
          set global.nlecalibration = true
        else
          global nlecalibration = true
        
        G10 P0 S235 ; sets the temperature
        M140 P0 S90 ; set bed temp
        
        M107                                        ; fan off
        M144 P0 S1                                  ; activate bed 1 heater
        T0                                          ; select tool 0
        M98 P"0:/sys/meltingplot/home_if_necessary" ; check homing
        G29 S1                                      ; load stored hight map
        
        M83 ; use relative distances for extrusion
        G90 ; use absolute coordinates
        G21 ; set units to millimeters
        
        M116                                        ; wait for all heaters
        
        G11 ; unretract
        
        G1 Z300                                      ; raise z=20mm
        
        G53 G1 X50 Y50 F14400                       ; move printhead to center
        
        G92 E0                                       ; reset e-steps
        
        M572 D0 S0.0                                 ; disable pressure advance
        M592 D0 A0.0 B0.0                            ; disable non-linear-extrusion
        
        M591 D0 P3 C"e1stop" S0 R98:102 E0.2 L25.3           ; enable MFM, but do not trigger event
        
        G4 S5 ; wait for restart of MFM
        
        G91 ; relative moves
        ; 15mm
        G1 X1 E1 F30
        G1 X1 E1 F30
        G1 X1 E1 F30
        G1 X1 E1 F30
        G1 X1 E1 F30
        G1 X1 E1 F30
        G1 X1 E1 F30
        G1 X1 E1 F30
        G1 X1 E1 F30
        G1 X1 E1 F30
        G1 X1 E1 F30
        G1 X1 E1 F30
        G1 X1 E1 F30
        G1 X1 E1 F30
        G1 X1 E1 F30
        
        ; the mfm should be calibrated now
        
        if sensors.filamentMonitors[0].calibrated == null
        	echo "Cannot calibrate filament monitor within 15mm - error!"
        	M99
        
        G4 S1 ; wait for filament monitor send timeout
        
        var totalCommandedBase = move.extruders[0].rawPosition
        var totalDistanceBase = sensors.filamentMonitors[0].calibrated.totalDistance
        
        G1 X50 E50 F60
        G1 X50 E50 F60
        
        G4 S1 ; wait for filament monitor send timeout
        echo "F60 " ^ {(1.0-((sensors.filamentMonitors[0].calibrated.totalDistance-var.totalDistanceBase)/(move.extruders[0].rawPosition-var.totalCommandedBase)))*100.0} ^ "% error."
        
        set var.totalCommandedBase = move.extruders[0].rawPosition
        set var.totalDistanceBase = sensors.filamentMonitors[0].calibrated.totalDistance
        
        G1 X50 E50 F90
        G1 X50 E50 F90
        
        G4 S1 ; wait for filament monitor send timeout
        echo "F90 " ^ {(1.0-((sensors.filamentMonitors[0].calibrated.totalDistance-var.totalDistanceBase)/(move.extruders[0].rawPosition-var.totalCommandedBase)))*100.0} ^ "% error."
        
        set var.totalCommandedBase = move.extruders[0].rawPosition
        set var.totalDistanceBase = sensors.filamentMonitors[0].calibrated.totalDistance
        
        G1 X50 E50 F120
        G1 X50 E50 F120
        
        G4 S1 ; wait for filament monitor send timeout
        echo "F120 " ^ {(1.0-((sensors.filamentMonitors[0].calibrated.totalDistance-var.totalDistanceBase)/(move.extruders[0].rawPosition-var.totalCommandedBase)))*100.0} ^ "% error."
        
        set var.totalCommandedBase = move.extruders[0].rawPosition
        set var.totalDistanceBase = sensors.filamentMonitors[0].calibrated.totalDistance
        
        G1 X50 E50 F150
        G1 X50 E50 F150
        
        G4 S1 ; wait for filament monitor send timeout
        echo "F150 " ^ {(1.0-((sensors.filamentMonitors[0].calibrated.totalDistance-var.totalDistanceBase)/(move.extruders[0].rawPosition-var.totalCommandedBase)))*100.0} ^ "% error."
        
        set var.totalCommandedBase = move.extruders[0].rawPosition
        set var.totalDistanceBase = sensors.filamentMonitors[0].calibrated.totalDistance
        
        G1 X-50 E50 F180
        G1 X-50 E50 F180
        
        G4 S1 ; wait for filament monitor send timeout
        echo "F180 " ^ {(1.0-((sensors.filamentMonitors[0].calibrated.totalDistance-var.totalDistanceBase)/(move.extruders[0].rawPosition-var.totalCommandedBase)))*100.0} ^ "% error."
        
        set var.totalCommandedBase = move.extruders[0].rawPosition
        set var.totalDistanceBase = sensors.filamentMonitors[0].calibrated.totalDistance
        
        G1 X-50 E50 F210
        G1 X-50 E50 F210
        
        G4 S1 ; wait for filament monitor send timeout
        echo "F210 " ^ {(1.0-((sensors.filamentMonitors[0].calibrated.totalDistance-var.totalDistanceBase)/(move.extruders[0].rawPosition-var.totalCommandedBase)))*100.0} ^ "% error."
        
        set var.totalCommandedBase = move.extruders[0].rawPosition
        set var.totalDistanceBase = sensors.filamentMonitors[0].calibrated.totalDistance
        
        G1 X-50 E50 F240
        G1 X-50 E50 F240
        
        G4 S1 ; wait for filament monitor send timeout
        echo "F240 " ^ {(1.0-((sensors.filamentMonitors[0].calibrated.totalDistance-var.totalDistanceBase)/(move.extruders[0].rawPosition-var.totalCommandedBase)))*100.0} ^ "% error."
        
        set var.totalCommandedBase = move.extruders[0].rawPosition
        set var.totalDistanceBase = sensors.filamentMonitors[0].calibrated.totalDistance
        
        G1 X-50 E50 F270
        G1 X-50 E50 F270
        
        G4 S1 ; wait for filament monitor send timeout
        echo "F270 " ^ {(1.0-((sensors.filamentMonitors[0].calibrated.totalDistance-var.totalDistanceBase)/(move.extruders[0].rawPosition-var.totalCommandedBase)))*100.0} ^ "% error."
        
        set var.totalCommandedBase = move.extruders[0].rawPosition
        set var.totalDistanceBase = sensors.filamentMonitors[0].calibrated.totalDistance
        
        G1 X50 E50 F300
        G1 X50 E50 F300
        
        G4 S1 ; wait for filament monitor send timeout
        echo "F300 " ^ {(1.0-((sensors.filamentMonitors[0].calibrated.totalDistance-var.totalDistanceBase)/(move.extruders[0].rawPosition-var.totalCommandedBase)))*100.0} ^ "% error."
        
        set var.totalCommandedBase = move.extruders[0].rawPosition
        set var.totalDistanceBase = sensors.filamentMonitors[0].calibrated.totalDistance
        
        G1 X50 E50 F330
        G1 X50 E50 F330
        
        G4 S1 ; wait for filament monitor send timeout
        echo "F330 " ^ {(1.0-((sensors.filamentMonitors[0].calibrated.totalDistance-var.totalDistanceBase)/(move.extruders[0].rawPosition-var.totalCommandedBase)))*100.0} ^ "% error."
        
        set var.totalCommandedBase = move.extruders[0].rawPosition
        set var.totalDistanceBase = sensors.filamentMonitors[0].calibrated.totalDistance
        
        G1 X50 E50 F360
        G1 X50 E50 F360
        
        G4 S1 ; wait for filament monitor send timeout
        echo "F360 " ^ {(1.0-((sensors.filamentMonitors[0].calibrated.totalDistance-var.totalDistanceBase)/(move.extruders[0].rawPosition-var.totalCommandedBase)))*100.0} ^ "% error."
        
        set var.totalCommandedBase = move.extruders[0].rawPosition
        set var.totalDistanceBase = sensors.filamentMonitors[0].calibrated.totalDistance
        
        G10                                          ; retract
        G10 P0 R0 S0                        ; disable hotend
        M140 S0 R0                          ; set bed heater to 0°
        M140 P0 S-273.1                     ; disable bed heater
        T-1                                          ; unselect tool
        
        set global.nlecalibration = false
        

        The variable nlecalibration is for further use.

        non_linear_extrusion_check.gcode

        if exists(global.nlecheck)
          set global.nlecheck= true
        else
          global nlecheck= true
        
        G10 P0 S235 ; sets the temperature
        M140 P0 S90 ; set bed temp
        
        M107                                        ; fan off
        M144 P0 S1                                  ; activate bed 1 heater
        T0                                          ; select tool 0
        M98 P"0:/sys/meltingplot/home_if_necessary" ; check homing
        G29 S1                                      ; load stored hight map
        
        M83 ; use relative distances for extrusion
        G90 ; use absolute coordinates
        G21 ; set units to millimeters
        
        M116                                        ; wait for all heaters
        
        G11 ; unretract
        
        G1 Z300                                      ; raise z=20mm
        
        G53 G1 X50 Y50 F14400                       ; move printhead to center
        
        G92 E0                                       ; reset e-steps
        
        M572 D0 S0.0                                 ; disable pressure advance
        M592 D0 A0.003 B0.011 L0.2                   ; enable non-linear-extrusion
        
        M591 D0 P3 C"e1stop" S0 R98:102 E0.2 L25.3           ; enable MFM, but do not trigger event
        
        G4 S5 ; wait for restart of MFM
        
        G91 ; relative moves
        ; 15mm
        G1 X1 E1 F30
        G1 X1 E1 F30
        G1 X1 E1 F30
        G1 X1 E1 F30
        G1 X1 E1 F30
        G1 X1 E1 F30
        G1 X1 E1 F30
        G1 X1 E1 F30
        G1 X1 E1 F30
        G1 X1 E1 F30
        G1 X1 E1 F30
        G1 X1 E1 F30
        G1 X1 E1 F30
        G1 X1 E1 F30
        G1 X1 E1 F30
        
        ; the mfm should be calibrated now
        
        if sensors.filamentMonitors[0].calibrated == null
        	echo "Cannot calibrate filament monitor within 15mm - error!"
        	M99
        
        G4 S1 ; wait for filament monitor send timeout
        
        var totalCommandedBase = move.extruders[0].rawPosition
        var totalDistanceBase = sensors.filamentMonitors[0].calibrated.totalDistance
        
        G1 X50 E50 F60
        G1 X50 E50 F60
        
        G4 S1 ; wait for filament monitor send timeout
        echo "F60 " ^ {(1.0-((sensors.filamentMonitors[0].calibrated.totalDistance-var.totalDistanceBase)/(move.extruders[0].rawPosition-var.totalCommandedBase)))*100.0} ^ "% error."
        
        set var.totalCommandedBase = move.extruders[0].rawPosition
        set var.totalDistanceBase = sensors.filamentMonitors[0].calibrated.totalDistance
        
        G1 X50 E50 F90
        G1 X50 E50 F90
        
        G4 S1 ; wait for filament monitor send timeout
        echo "F90 " ^ {(1.0-((sensors.filamentMonitors[0].calibrated.totalDistance-var.totalDistanceBase)/(move.extruders[0].rawPosition-var.totalCommandedBase)))*100.0} ^ "% error."
        
        set var.totalCommandedBase = move.extruders[0].rawPosition
        set var.totalDistanceBase = sensors.filamentMonitors[0].calibrated.totalDistance
        
        G1 X50 E50 F120
        G1 X50 E50 F120
        
        G4 S1 ; wait for filament monitor send timeout
        echo "F120 " ^ {(1.0-((sensors.filamentMonitors[0].calibrated.totalDistance-var.totalDistanceBase)/(move.extruders[0].rawPosition-var.totalCommandedBase)))*100.0} ^ "% error."
        
        set var.totalCommandedBase = move.extruders[0].rawPosition
        set var.totalDistanceBase = sensors.filamentMonitors[0].calibrated.totalDistance
        
        G1 X50 E50 F150
        G1 X50 E50 F150
        
        G4 S1 ; wait for filament monitor send timeout
        echo "F150 " ^ {(1.0-((sensors.filamentMonitors[0].calibrated.totalDistance-var.totalDistanceBase)/(move.extruders[0].rawPosition-var.totalCommandedBase)))*100.0} ^ "% error."
        
        set var.totalCommandedBase = move.extruders[0].rawPosition
        set var.totalDistanceBase = sensors.filamentMonitors[0].calibrated.totalDistance
        
        G1 X-50 E50 F180
        G1 X-50 E50 F180
        
        G4 S1 ; wait for filament monitor send timeout
        echo "F180 " ^ {(1.0-((sensors.filamentMonitors[0].calibrated.totalDistance-var.totalDistanceBase)/(move.extruders[0].rawPosition-var.totalCommandedBase)))*100.0} ^ "% error."
        
        set var.totalCommandedBase = move.extruders[0].rawPosition
        set var.totalDistanceBase = sensors.filamentMonitors[0].calibrated.totalDistance
        
        G1 X-50 E50 F210
        G1 X-50 E50 F210
        
        G4 S1 ; wait for filament monitor send timeout
        echo "F210 " ^ {(1.0-((sensors.filamentMonitors[0].calibrated.totalDistance-var.totalDistanceBase)/(move.extruders[0].rawPosition-var.totalCommandedBase)))*100.0} ^ "% error."
        
        set var.totalCommandedBase = move.extruders[0].rawPosition
        set var.totalDistanceBase = sensors.filamentMonitors[0].calibrated.totalDistance
        
        G1 X-50 E50 F240
        G1 X-50 E50 F240
        
        G4 S1 ; wait for filament monitor send timeout
        echo "F240 " ^ {(1.0-((sensors.filamentMonitors[0].calibrated.totalDistance-var.totalDistanceBase)/(move.extruders[0].rawPosition-var.totalCommandedBase)))*100.0} ^ "% error."
        
        set var.totalCommandedBase = move.extruders[0].rawPosition
        set var.totalDistanceBase = sensors.filamentMonitors[0].calibrated.totalDistance
        
        G1 X-50 E50 F270
        G1 X-50 E50 F270
        
        G4 S1 ; wait for filament monitor send timeout
        echo "F270 " ^ {(1.0-((sensors.filamentMonitors[0].calibrated.totalDistance-var.totalDistanceBase)/(move.extruders[0].rawPosition-var.totalCommandedBase)))*100.0} ^ "% error."
        
        set var.totalCommandedBase = move.extruders[0].rawPosition
        set var.totalDistanceBase = sensors.filamentMonitors[0].calibrated.totalDistance
        
        G1 X50 E50 F300
        G1 X50 E50 F300
        
        G4 S1 ; wait for filament monitor send timeout
        echo "F300 " ^ {(1.0-((sensors.filamentMonitors[0].calibrated.totalDistance-var.totalDistanceBase)/(move.extruders[0].rawPosition-var.totalCommandedBase)))*100.0} ^ "% error."
        
        set var.totalCommandedBase = move.extruders[0].rawPosition
        set var.totalDistanceBase = sensors.filamentMonitors[0].calibrated.totalDistance
        
        G1 X50 E50 F330
        G1 X50 E50 F330
        
        G4 S1 ; wait for filament monitor send timeout
        echo "F330 " ^ {(1.0-((sensors.filamentMonitors[0].calibrated.totalDistance-var.totalDistanceBase)/(move.extruders[0].rawPosition-var.totalCommandedBase)))*100.0} ^ "% error."
        
        set var.totalCommandedBase = move.extruders[0].rawPosition
        set var.totalDistanceBase = sensors.filamentMonitors[0].calibrated.totalDistance
        
        G1 X50 E50 F360
        G1 X50 E50 F360
        
        G4 S1 ; wait for filament monitor send timeout
        echo "F360 " ^ {(1.0-((sensors.filamentMonitors[0].calibrated.totalDistance-var.totalDistanceBase)/(move.extruders[0].rawPosition-var.totalCommandedBase)))*100.0} ^ "% error."
        
        set var.totalCommandedBase = move.extruders[0].rawPosition
        set var.totalDistanceBase = sensors.filamentMonitors[0].calibrated.totalDistance
        
        G10                                          ; retract
        G10 P0 R0 S0                        ; disable hotend
        M140 S0 R0                          ; set bed heater to 0°
        M140 P0 S-273.1                     ; disable bed heater
        T-1                                          ; unselect tool
        
        set global.nlecheck = false
        

        We have a tool which takes the values from that script and will aproximate the A and B factors of the non-linear-extrusion - but it can be done with excel as well. It will safe you alot of measurements 🙂

        undefined 1 Reply Last reply 6 Oct 2023, 20:16 Reply Quote 1
        • undefined
          timschneider @timschneider
          last edited by 6 Oct 2023, 20:16

          ok, the above code is not correct.

          I thought that sensors.filamentMonitors[0].calibrated.totalDistance is the total measured distance, but in fact, it is just the total commanded distance and the difference between sensors.filamentMonitors[0].calibrated.totalDistance and move.extruders[0].rawPosition is for example the non linear extrusion correction.

          I think it is possible to get the current measured distance in mm with the following line:

          (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
          

          and the new code looks like the following:
          0:/gcodes/non_linear_extrusion_calibration.gcode

          if exists(global.nlecalibration)
            set global.nlecalibration = true
          else
            global nlecalibration = true
          
          G10 P0 S235 ; sets the temperature
          M140 P0 S90 ; set bed temp
          
          M107                                        ; fan off
          M144 P0 S1                                  ; activate bed 1 heater
          T0                                          ; select tool 0
          M98 P"0:/sys/meltingplot/home_if_necessary" ; check homing
          G29 S1                                      ; load stored hight map
          
          M83 ; use relative distances for extrusion
          G90 ; use absolute coordinates
          G21 ; set units to millimeters
          
          M116                                        ; wait for all heaters
          
          G11 ; unretract
          
          G1 Z300 F3600                               ; raise z=20mm
          
          G53 G1 X50 Y50 F14400                       ; move printhead to center
          
          G92 E0                                       ; reset e-steps
          
          M572 D0 S0.0                                 ; disable pressure advance
          M592 D0 A0.0 B0.0                            ; disable non-linear-extrusion
          
          M591 D0 P3 C"e1stop" S0 R98:102 E0.2 L25.3           ; enable MFM, but do not trigger event
          
          G4 S5 ; wait for restart of MFM
          
          G91 ; relative moves
          ; 15mm
          G1 X1 E1 F30
          G1 X1 E1 F30
          G1 X1 E1 F30
          G1 X1 E1 F30
          G1 X1 E1 F30
          G1 X1 E1 F30
          G1 X1 E1 F30
          G1 X1 E1 F30
          G1 X1 E1 F30
          G1 X1 E1 F30
          G1 X1 E1 F30
          G1 X1 E1 F30
          G1 X1 E1 F30
          G1 X1 E1 F30
          G1 X1 E1 F30
          
          ; the mfm should be calibrated now
          
          if sensors.filamentMonitors[0].calibrated == null
          	echo "Cannot calibrate filament monitor within 15mm - error!"
          	M99
          
          G4 S1 ; wait for filament monitor send timeout
          
          ; sensors.filamentMonitors[0].calibrated.totalDistance is including extrusion correction like pressure advance, non linear extrusion and so on ...
          ; move.extruders[0].rawPosition is the extrusion without correction values
          ; sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev is the number of measured revolutions
          
          var totalCommandedBase = sensors.filamentMonitors[0].calibrated.totalDistance
          var totalDistanceBase = (var.totalCommandedBase / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
          
          G1 X50 E50 F60
          G1 X50 E50 F60
          
          G4 S1 ; wait for filament monitor send timeout
          
          var currentCommanded = sensors.filamentMonitors[0].calibrated.totalDistance
          var currentMeasured = (var.currentCommanded / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
          
          echo "F60 " ^ {(1.0-((var.currentMeasured-var.totalDistanceBase)/(var.currentCommanded-var.totalCommandedBase)))*100.0} ^ "% error."
          
          set var.totalCommandedBase = sensors.filamentMonitors[0].calibrated.totalDistance
          set var.totalDistanceBase = (var.totalCommandedBase / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
          
          G1 X50 E50 F90
          G1 X50 E50 F90
          
          G4 S1 ; wait for filament monitor send timeout
          
          set var.currentCommanded = sensors.filamentMonitors[0].calibrated.totalDistance
          set var.currentMeasured = (var.currentCommanded / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
          
          echo "F90 " ^ {(1.0-((var.currentMeasured-var.totalDistanceBase)/(var.currentCommanded-var.totalCommandedBase)))*100.0} ^ "% error."
          
          set var.totalCommandedBase = sensors.filamentMonitors[0].calibrated.totalDistance
          set var.totalDistanceBase = (var.totalCommandedBase / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
          
          G1 X50 E50 F120
          G1 X50 E50 F120
          
          G4 S1 ; wait for filament monitor send timeout
          
          set var.currentCommanded = sensors.filamentMonitors[0].calibrated.totalDistance
          set var.currentMeasured = (var.currentCommanded / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
          
          echo "F120 " ^ {(1.0-((var.currentMeasured-var.totalDistanceBase)/(var.currentCommanded-var.totalCommandedBase)))*100.0} ^ "% error."
          
          set var.totalCommandedBase = sensors.filamentMonitors[0].calibrated.totalDistance
          set var.totalDistanceBase = (var.totalCommandedBase / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
          
          G1 X50 E50 F150
          G1 X50 E50 F150
          
          G4 S1 ; wait for filament monitor send timeout
          
          set var.currentCommanded = sensors.filamentMonitors[0].calibrated.totalDistance
          set var.currentMeasured = (var.currentCommanded / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
          
          echo "F150 " ^ {(1.0-((var.currentMeasured-var.totalDistanceBase)/(var.currentCommanded-var.totalCommandedBase)))*100.0} ^ "% error."
          
          set var.totalCommandedBase = sensors.filamentMonitors[0].calibrated.totalDistance
          set var.totalDistanceBase = (var.totalCommandedBase / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
          
          G1 X-50 E50 F180
          G1 X-50 E50 F180
          
          G4 S1 ; wait for filament monitor send timeout
          
          set var.currentCommanded = sensors.filamentMonitors[0].calibrated.totalDistance
          set var.currentMeasured = (var.currentCommanded / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
          
          echo "F180 " ^ {(1.0-((var.currentMeasured-var.totalDistanceBase)/(var.currentCommanded-var.totalCommandedBase)))*100.0} ^ "% error."
          
          set var.totalCommandedBase = sensors.filamentMonitors[0].calibrated.totalDistance
          set var.totalDistanceBase = (var.totalCommandedBase / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
          
          G1 X-50 E50 F210
          G1 X-50 E50 F210
          
          G4 S1 ; wait for filament monitor send timeout
          
          set var.currentCommanded = sensors.filamentMonitors[0].calibrated.totalDistance
          set var.currentMeasured = (var.currentCommanded / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
          
          echo "F210 " ^ {(1.0-((var.currentMeasured-var.totalDistanceBase)/(var.currentCommanded-var.totalCommandedBase)))*100.0} ^ "% error."
          
          set var.totalCommandedBase = sensors.filamentMonitors[0].calibrated.totalDistance
          set var.totalDistanceBase = (var.totalCommandedBase / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
          
          G1 X-50 E50 F240
          G1 X-50 E50 F240
          
          G4 S1 ; wait for filament monitor send timeout
          
          set var.currentCommanded = sensors.filamentMonitors[0].calibrated.totalDistance
          set var.currentMeasured = (var.currentCommanded / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
          
          echo "F240 " ^ {(1.0-((var.currentMeasured-var.totalDistanceBase)/(var.currentCommanded-var.totalCommandedBase)))*100.0} ^ "% error."
          
          set var.totalCommandedBase = sensors.filamentMonitors[0].calibrated.totalDistance
          set var.totalDistanceBase = (var.totalCommandedBase / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
          
          G1 X-50 E50 F270
          G1 X-50 E50 F270
          
          G4 S1 ; wait for filament monitor send timeout
          
          set var.currentCommanded = sensors.filamentMonitors[0].calibrated.totalDistance
          set var.currentMeasured = (var.currentCommanded / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
          
          echo "F270 " ^ {(1.0-((var.currentMeasured-var.totalDistanceBase)/(var.currentCommanded-var.totalCommandedBase)))*100.0} ^ "% error."
          
          set var.totalCommandedBase = sensors.filamentMonitors[0].calibrated.totalDistance
          set var.totalDistanceBase = (var.totalCommandedBase / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
          
          G1 X50 E50 F300
          G1 X50 E50 F300
          
          G4 S1 ; wait for filament monitor send timeout
          
          set var.currentCommanded = sensors.filamentMonitors[0].calibrated.totalDistance
          set var.currentMeasured = (var.currentCommanded / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
          
          echo "F300 " ^ {(1.0-((var.currentMeasured-var.totalDistanceBase)/(var.currentCommanded-var.totalCommandedBase)))*100.0} ^ "% error."
          
          set var.totalCommandedBase = sensors.filamentMonitors[0].calibrated.totalDistance
          set var.totalDistanceBase = (var.totalCommandedBase / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
          
          G1 X50 E50 F330
          G1 X50 E50 F330
          
          G4 S1 ; wait for filament monitor send timeout
          
          set var.currentCommanded = sensors.filamentMonitors[0].calibrated.totalDistance
          set var.currentMeasured = (var.currentCommanded / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
          
          echo "F330 " ^ {(1.0-((var.currentMeasured-var.totalDistanceBase)/(var.currentCommanded-var.totalCommandedBase)))*100.0} ^ "% error."
          
          set var.totalCommandedBase = sensors.filamentMonitors[0].calibrated.totalDistance
          set var.totalDistanceBase = (var.totalCommandedBase / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
          
          G1 X50 E50 F360
          G1 X50 E50 F360
          
          G4 S1 ; wait for filament monitor send timeout
          
          set var.currentCommanded = sensors.filamentMonitors[0].calibrated.totalDistance
          set var.currentMeasured = (var.currentCommanded / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
          
          echo "F360 " ^ {(1.0-((var.currentMeasured-var.totalDistanceBase)/(var.currentCommanded-var.totalCommandedBase)))*100.0} ^ "% error."
          
          set var.totalCommandedBase = sensors.filamentMonitors[0].calibrated.totalDistance
          set var.totalDistanceBase = (var.totalCommandedBase / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
          
          G10                                          ; retract
          G10 P0 R0 S0                        ; disable hotend
          M140 S0 R0                          ; set bed heater to 0°
          M140 P0 S-273.1                     ; disable bed heater
          T-1                                          ; unselect tool
          
          set global.nlecalibration = false
          

          The output looks like the following:
          aca1f04f-371f-44d6-873e-b21694201da4-grafik.png

          bff69de6-3c6d-44b4-8e4c-56825d384124-grafik.png

          So i was able to correct the extrusion up to F300 with 2.85mm filament or up to 31.9mm³/s.

          undefined 1 Reply Last reply 6 Oct 2023, 20:16 Reply Quote 0
          • undefined
            timschneider @timschneider
            last edited by 6 Oct 2023, 20:16

            and the code of

            0:/gcodes/non_linear_extrusion_check.gcode

            if exists(global.nlecheck)
              set global.nlecheck = true
            else
              global nlecheck = true
            
            G10 P0 S240 ; sets the temperature
            M140 P0 S90 ; set bed temp
            
            M107                                        ; fan off
            M144 P0 S1                                  ; activate bed 1 heater
            T0                                          ; select tool 0
            M98 P"0:/sys/meltingplot/home_if_necessary" ; check homing
            G29 S1                                      ; load stored hight map
            
            M83 ; use relative distances for extrusion
            G90 ; use absolute coordinates
            G21 ; set units to millimeters
            
            M116                                        ; wait for all heaters
            
            G11 ; unretract
            
            G1 Z300 F3600                               ; raise z=20mm
            
            G53 G1 X50 Y50 F14400                       ; move printhead to center
            
            G92 E0                                       ; reset e-steps
            
            M572 D0 S0.0                                 ; disable pressure advance
            M592 D0 A0.0 B0.0035 L0.2                       ; enable non-linear-extrusion
            
            M591 D0 P3 C"e1stop" S0 R98:102 E0.2 L25.3           ; enable MFM, but do not trigger event
            
            G4 S5 ; wait for restart of MFM
            
            G91 ; relative moves
            ; 15mm
            G1 X1 E1 F30
            G1 X1 E1 F30
            G1 X1 E1 F30
            G1 X1 E1 F30
            G1 X1 E1 F30
            G1 X1 E1 F30
            G1 X1 E1 F30
            G1 X1 E1 F30
            G1 X1 E1 F30
            G1 X1 E1 F30
            G1 X1 E1 F30
            G1 X1 E1 F30
            G1 X1 E1 F30
            G1 X1 E1 F30
            G1 X1 E1 F30
            
            ; the mfm should be calibrated now
            
            if sensors.filamentMonitors[0].calibrated == null
            	echo "Cannot calibrate filament monitor within 15mm - error!"
            	M99
            
            G4 S1 ; wait for filament monitor send timeout
            
            ; sensors.filamentMonitors[0].calibrated.totalDistance is including extrusion correction like pressure advance, non linear extrusion and so on ...
            ; move.extruders[0].rawPosition is the extrusion without correction values
            ; sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev is the number of measured revolutions
            
            var totalCommandedBase = move.extruders[0].rawPosition
            var totalDistanceBase = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
            
            G1 X50 E50 F60
            G1 X50 E50 F60
            
            G4 S1 ; wait for filament monitor send timeout
            
            var currentCommanded = move.extruders[0].rawPosition
            var currentMeasured = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
            
            echo "F60 " ^ {(1.0-((var.currentMeasured-var.totalDistanceBase)/(var.currentCommanded-var.totalCommandedBase)))*100.0} ^ "% error."
            
            set var.totalCommandedBase = move.extruders[0].rawPosition
            set var.totalDistanceBase = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
            
            G1 X50 E50 F90
            G1 X50 E50 F90
            
            G4 S1 ; wait for filament monitor send timeout
            
            set var.currentCommanded = move.extruders[0].rawPosition
            set var.currentMeasured = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
            
            echo "F90 " ^ {(1.0-((var.currentMeasured-var.totalDistanceBase)/(var.currentCommanded-var.totalCommandedBase)))*100.0} ^ "% error."
            
            set var.totalCommandedBase = move.extruders[0].rawPosition
            set var.totalDistanceBase = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
            
            G1 X50 E50 F120
            G1 X50 E50 F120
            
            G4 S1 ; wait for filament monitor send timeout
            
            set var.currentCommanded = move.extruders[0].rawPosition
            set var.currentMeasured = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
            
            echo "F120 " ^ {(1.0-((var.currentMeasured-var.totalDistanceBase)/(var.currentCommanded-var.totalCommandedBase)))*100.0} ^ "% error."
            
            set var.totalCommandedBase = move.extruders[0].rawPosition
            set var.totalDistanceBase = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
            
            G1 X50 E50 F150
            G1 X50 E50 F150
            
            G4 S1 ; wait for filament monitor send timeout
            
            set var.currentCommanded = move.extruders[0].rawPosition
            set var.currentMeasured = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
            
            echo "F150 " ^ {(1.0-((var.currentMeasured-var.totalDistanceBase)/(var.currentCommanded-var.totalCommandedBase)))*100.0} ^ "% error."
            
            set var.totalCommandedBase = move.extruders[0].rawPosition
            set var.totalDistanceBase = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
            
            G1 X-50 E50 F180
            G1 X-50 E50 F180
            
            G4 S1 ; wait for filament monitor send timeout
            
            set var.currentCommanded = move.extruders[0].rawPosition
            set var.currentMeasured = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
            
            echo "F180 " ^ {(1.0-((var.currentMeasured-var.totalDistanceBase)/(var.currentCommanded-var.totalCommandedBase)))*100.0} ^ "% error."
            
            set var.totalCommandedBase = move.extruders[0].rawPosition
            set var.totalDistanceBase = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
            
            G1 X-50 E50 F210
            G1 X-50 E50 F210
            
            G4 S1 ; wait for filament monitor send timeout
            
            set var.currentCommanded = move.extruders[0].rawPosition
            set var.currentMeasured = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
            
            echo "F210 " ^ {(1.0-((var.currentMeasured-var.totalDistanceBase)/(var.currentCommanded-var.totalCommandedBase)))*100.0} ^ "% error."
            
            set var.totalCommandedBase = move.extruders[0].rawPosition
            set var.totalDistanceBase = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
            
            G1 X-50 E50 F240
            G1 X-50 E50 F240
            
            G4 S1 ; wait for filament monitor send timeout
            
            set var.currentCommanded = move.extruders[0].rawPosition
            set var.currentMeasured = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
            
            echo "F240 " ^ {(1.0-((var.currentMeasured-var.totalDistanceBase)/(var.currentCommanded-var.totalCommandedBase)))*100.0} ^ "% error."
            
            set var.totalCommandedBase = move.extruders[0].rawPosition
            set var.totalDistanceBase = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
            
            G1 X-50 E50 F270
            G1 X-50 E50 F270
            
            G4 S1 ; wait for filament monitor send timeout
            
            set var.currentCommanded = move.extruders[0].rawPosition
            set var.currentMeasured = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
            
            echo "F270 " ^ {(1.0-((var.currentMeasured-var.totalDistanceBase)/(var.currentCommanded-var.totalCommandedBase)))*100.0} ^ "% error."
            
            set var.totalCommandedBase = move.extruders[0].rawPosition
            set var.totalDistanceBase = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
            
            G1 X50 E50 F300
            G1 X50 E50 F300
            
            G4 S1 ; wait for filament monitor send timeout
            
            set var.currentCommanded = move.extruders[0].rawPosition
            set var.currentMeasured = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
            
            echo "F300 " ^ {(1.0-((var.currentMeasured-var.totalDistanceBase)/(var.currentCommanded-var.totalCommandedBase)))*100.0} ^ "% error."
            
            set var.totalCommandedBase = move.extruders[0].rawPosition
            set var.totalDistanceBase = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
            
            G1 X50 E50 F330
            G1 X50 E50 F330
            
            G4 S1 ; wait for filament monitor send timeout
            
            set var.currentCommanded = move.extruders[0].rawPosition
            set var.currentMeasured = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
            
            echo "F330 " ^ {(1.0-((var.currentMeasured-var.totalDistanceBase)/(var.currentCommanded-var.totalCommandedBase)))*100.0} ^ "% error."
            
            set var.totalCommandedBase = move.extruders[0].rawPosition
            set var.totalDistanceBase = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
            
            G1 X50 E50 F360
            G1 X50 E50 F360
            
            G4 S1 ; wait for filament monitor send timeout
            
            set var.currentCommanded = move.extruders[0].rawPosition
            set var.currentMeasured = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
            
            echo "F360 " ^ {(1.0-((var.currentMeasured-var.totalDistanceBase)/(var.currentCommanded-var.totalCommandedBase)))*100.0} ^ "% error."
            
            set var.totalCommandedBase = move.extruders[0].rawPosition
            set var.totalDistanceBase = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
            
            G10                                          ; retract
            G10 P0 R0 S0                        ; disable hotend
            M140 S0 R0                          ; set bed heater to 0°
            M140 P0 S-273.1                     ; disable bed heater
            T-1                                          ; unselect tool
            
            set global.nlecheck = false
            
            undefined 1 Reply Last reply 6 Oct 2023, 20:50 Reply Quote 1
            • undefined
              OwenD @timschneider
              last edited by 6 Oct 2023, 20:50

              @timschneider
              Nice work 👍
              The only issue I can imagine is if at higher speeds the change in the extrusion is due to the extruder skipping steps rather than just changes in extrusion efficiency that M592 is attempting to compensate for.
              That problem exists no matter if you measure with a tape or using the filament monitor, but I think using your automatic system users are less likely to pay close attention and will just accept the readings on face value.
              It probably doesn't matter as you'll get bad results when printing above the extruders max flow rate.
              Maybe just a warning to the user if the error rate is above X% that the max flow rate may have been exceeded or the nozzle is jammed?
              I've always wondered on the value of the MFM because I see a few people struggling with them, but this has me thinking it's time to throw out my simple switch 🤔

              undefined 1 Reply Last reply 7 Oct 2023, 09:48 Reply Quote 0
              • undefined
                o_lampe
                last edited by 7 Oct 2023, 07:36

                Over at the simpleFOC forum, we also use the 'AS5xxx' mag sensors a lot and there we struggle with a dead-zone around the turning point (0-360°) where the sensor has an hiccup.
                I wonder if RRF has the same issue and found a way to deal with it?
                In simpleFOC dev-branch we are experimenting with an interpolating smoothingSensor module, also because the I2C sensor is pretty slow /lags behind.
                That's maybe not so relevant for slow extruder moves, though.

                1 Reply Last reply Reply Quote 0
                • undefined
                  timschneider @OwenD
                  last edited by 7 Oct 2023, 09:48

                  @OwenD said in Magnetic Filament Monitor for Automatic E-Step Calibration:

                  The only issue I can imagine is if at higher speeds the change in the extrusion is due to the extruder skipping steps rather than just changes in extrusion efficiency that M592 is attempting to compensate for.

                  That is exactly what happened with the F360 values. My rule of thumb is: try to compensate up to about 10%, because that means the extruder has to push at least 10% more, but in reality it's more like 15-20% more.

                  As for your other thoughts. I use a different technique to make the sensor more robust, as explained here

                  1 Reply Last reply Reply Quote 0
                  • undefined
                    timschneider
                    last edited by 30 Oct 2023, 13:09

                    The above code will only work in standalone mode firmware 3.4.6.

                    It seems that the G4 S1 is somehow breaking the var scope from time to time (it will stop working at F150 for the first time with unknown variable ) @dc42

                    so I use global variables for sbc setup.

                    if exists(global.nlecheck)
                      set global.nlecheck = true
                    else
                      global nlecheck = true
                    
                    G10 P0 S245 ; sets the temperature
                    M140 P0 S90 ; set bed temp
                    
                    M107                                        ; fan off
                    M144 P0 S1                                  ; activate bed 1 heater
                    T0                                          ; select tool 0
                    M98 P"0:/sys/meltingplot/home_if_necessary" ; check homing
                    G29 S1                                      ; load stored hight map
                    
                    M83 ; use relative distances for extrusion
                    G90 ; use absolute coordinates
                    G21 ; set units to millimeters
                    
                    M116                                        ; wait for all heaters
                    
                    G11 ; unretract
                    
                    G1 Z300 F3600                               ; raise z=20mm
                    
                    G53 G1 X50 Y50 F14400                       ; move printhead to center
                    
                    G92 E0                                       ; reset e-steps
                    
                    M572 D0 S0.0                                 ; disable pressure advance
                    M592 D0 A0 B0                       ; disable non-linear-extrusion
                    
                    M591 D0 P3 C"io3.in" S0 R98:102 E0.2 L25.3           ; enable MFM, but do not trigger event
                    
                    G4 S5 ; wait for restart of MFM
                    
                    G91 ; relative moves
                    ; 15mm
                    G1 X1 E1 F30
                    G1 X1 E1 F30
                    G1 X1 E1 F30
                    G1 X1 E1 F30
                    G1 X1 E1 F30
                    G1 X1 E1 F30
                    G1 X1 E1 F30
                    G1 X1 E1 F30
                    G1 X1 E1 F30
                    G1 X1 E1 F30
                    G1 X1 E1 F30
                    G1 X1 E1 F30
                    G1 X1 E1 F30
                    G1 X1 E1 F30
                    G1 X1 E1 F30
                    
                    ; the mfm should be calibrated now
                    
                    if sensors.filamentMonitors[0].calibrated == null
                    	echo "Cannot calibrate filament monitor within 15mm - error!"
                    	M99
                    
                    M400
                    G4 S1 ; wait for filament monitor send timeout
                    
                    ; sensors.filamentMonitors[0].calibrated.totalDistance is including extrusion correction like pressure advance, non linear extrusion and so on ...
                    ; move.extruders[0].rawPosition is the extrusion without correction values
                    ; sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev is the number of measured revolutions
                    
                    global totalCommandedBase = move.extruders[0].rawPosition
                    global totalDistanceBase = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
                    
                    G1 X50 E50 F60
                    G1 X50 E50 F60
                    
                    M400
                    G4 S1 ; wait for filament monitor send timeout
                    
                    global currentCommanded = move.extruders[0].rawPosition
                    global currentMeasured = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
                    
                    echo "F60 " ^ {(1.0-((global.currentMeasured-global.totalDistanceBase)/(global.currentCommanded-global.totalCommandedBase)))*100.0} ^ "% error."
                    
                    set global.totalCommandedBase = move.extruders[0].rawPosition
                    set global.totalDistanceBase = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
                    
                    G1 X50 E50 F90
                    G1 X50 E50 F90
                    
                    M400
                    G4 S1 ; wait for filament monitor send timeout
                    
                    set global.currentCommanded = move.extruders[0].rawPosition
                    set global.currentMeasured = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
                    
                    echo "F90 " ^ {(1.0-((global.currentMeasured-global.totalDistanceBase)/(global.currentCommanded-global.totalCommandedBase)))*100.0} ^ "% error."
                    
                    set global.totalCommandedBase = move.extruders[0].rawPosition
                    set global.totalDistanceBase = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
                    
                    G1 X50 E50 F120
                    G1 X50 E50 F120
                    
                    M400
                    G4 S1 ; wait for filament monitor send timeout
                    
                    set global.currentCommanded = move.extruders[0].rawPosition
                    set global.currentMeasured = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
                    
                    echo "F120 " ^ {(1.0-((global.currentMeasured-global.totalDistanceBase)/(global.currentCommanded-global.totalCommandedBase)))*100.0} ^ "% error."
                    
                    set global.totalCommandedBase = move.extruders[0].rawPosition
                    set global.totalDistanceBase = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
                    
                    G1 X50 E50 F150
                    G1 X50 E50 F150
                    
                    M400
                    G4 S1 ; wait for filament monitor send timeout
                    
                    set global.currentCommanded = move.extruders[0].rawPosition
                    set global.currentMeasured = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
                    
                    echo "F150 " ^ {(1.0-((global.currentMeasured-global.totalDistanceBase)/(global.currentCommanded-global.totalCommandedBase)))*100.0} ^ "% error."
                    
                    set global.totalCommandedBase = move.extruders[0].rawPosition
                    set global.totalDistanceBase = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
                    
                    G1 X-50 E50 F180
                    G1 X-50 E50 F180
                    
                    M400
                    G4 S1 ; wait for filament monitor send timeout
                    
                    set global.currentCommanded = move.extruders[0].rawPosition
                    set global.currentMeasured = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
                    
                    echo "F180 " ^ {(1.0-((global.currentMeasured-global.totalDistanceBase)/(global.currentCommanded-global.totalCommandedBase)))*100.0} ^ "% error."
                    
                    set global.totalCommandedBase = move.extruders[0].rawPosition
                    set global.totalDistanceBase = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
                    
                    G1 X-50 E50 F210
                    G1 X-50 E50 F210
                    
                    M400
                    G4 S1 ; wait for filament monitor send timeout
                    
                    set global.currentCommanded = move.extruders[0].rawPosition
                    set global.currentMeasured = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
                    
                    echo "F210 " ^ {(1.0-((global.currentMeasured-global.totalDistanceBase)/(global.currentCommanded-global.totalCommandedBase)))*100.0} ^ "% error."
                    
                    set global.totalCommandedBase = move.extruders[0].rawPosition
                    set global.totalDistanceBase = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
                    
                    G1 X-50 E50 F240
                    G1 X-50 E50 F240
                    
                    M400
                    G4 S1 ; wait for filament monitor send timeout
                    
                    set global.currentCommanded = move.extruders[0].rawPosition
                    set global.currentMeasured = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
                    
                    echo "F240 " ^ {(1.0-((global.currentMeasured-global.totalDistanceBase)/(global.currentCommanded-global.totalCommandedBase)))*100.0} ^ "% error."
                    
                    set global.totalCommandedBase = move.extruders[0].rawPosition
                    set global.totalDistanceBase = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
                    
                    G1 X-50 E50 F270
                    G1 X-50 E50 F270
                    
                    M400
                    G4 S1 ; wait for filament monitor send timeout
                    
                    set global.currentCommanded = move.extruders[0].rawPosition
                    set global.currentMeasured = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
                    
                    echo "F270 " ^ {(1.0-((global.currentMeasured-global.totalDistanceBase)/(global.currentCommanded-global.totalCommandedBase)))*100.0} ^ "% error."
                    
                    set global.totalCommandedBase = move.extruders[0].rawPosition
                    set global.totalDistanceBase = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
                    
                    G1 X50 E50 F300
                    G1 X50 E50 F300
                    
                    M400
                    G4 S1 ; wait for filament monitor send timeout
                    
                    set global.currentCommanded = move.extruders[0].rawPosition
                    set global.currentMeasured = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
                    
                    echo "F300 " ^ {(1.0-((global.currentMeasured-global.totalDistanceBase)/(global.currentCommanded-global.totalCommandedBase)))*100.0} ^ "% error."
                    
                    set global.totalCommandedBase = move.extruders[0].rawPosition
                    set global.totalDistanceBase = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
                    
                    G1 X50 E50 F330
                    G1 X50 E50 F330
                    
                    M400
                    G4 S1 ; wait for filament monitor send timeout
                    
                    set global.currentCommanded = move.extruders[0].rawPosition
                    set global.currentMeasured = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
                    
                    echo "F330 " ^ {(1.0-((global.currentMeasured-global.totalDistanceBase)/(global.currentCommanded-global.totalCommandedBase)))*100.0} ^ "% error."
                    
                    set global.totalCommandedBase = move.extruders[0].rawPosition
                    set global.totalDistanceBase = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
                    
                    G1 X50 E50 F360
                    G1 X50 E50 F360
                    
                    M400
                    G4 S1 ; wait for filament monitor send timeout
                    
                    set global.currentCommanded = move.extruders[0].rawPosition
                    set global.currentMeasured = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
                    
                    echo "F360 " ^ {(1.0-((global.currentMeasured-global.totalDistanceBase)/(global.currentCommanded-global.totalCommandedBase)))*100.0} ^ "% error."
                    
                    set global.totalCommandedBase = move.extruders[0].rawPosition
                    set global.totalDistanceBase = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
                    
                    G10                                          ; retract
                    G10 P0 R0 S0                        ; disable hotend
                    M140 S0 R0                          ; set bed heater to 0°
                    M140 P0 S-273.1                     ; disable bed heater
                    T-1                                          ; unselect tool
                    
                    set global.nlecheck = false
                    
                    undefined 1 Reply Last reply 23 Apr 2024, 14:21 Reply Quote 0
                    • undefined
                      timschneider @timschneider
                      last edited by timschneider 23 Apr 2024, 14:21

                      ok it took me a little longer to get this up, but this is my current version of the initial automatic filament calibration script.
                      It will automatically calibrate the e-steps and the non linear extrusion.

                      It will only run in 3.5 and as a macro.

                      The copyright of the script is

                      Tim Schneider
                      Meltingplot GmbH
                      CC BY-SA
                      

                      content of 0:/macros/meltingplot/filament-extrusion-calibration

                      if !exists(global.ignoreMFMevents)
                        global ignoreMFMevents = true
                      else
                        set global.ignoreMFMevents = true
                      
                      var filamentMonitorPin = "e1stop"
                      var filamentMonitorCircumference = 25.3
                      
                      var extrusionDistance = 20                  ; distance for e-step calibration
                      
                      ; speeds in mm/s for NLE to test
                      var extrusionSpeeds = {0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 6.0}
                      
                      M107                                        ; fan off
                      T0                                          ; select tool 0
                      M98 P"0:/sys/meltingplot/home_if_necessary" ; check homing
                      G29 S1                                      ; load stored hight map
                      
                      M83 ; use relative distances for extrusion
                      G90 ; use absolute coordinates
                      G21 ; set units to millimeters
                      
                      var currentTool = state.currentTool
                      var currentHeater = tools[0].heaters[var.currentTool]
                      var currentTemp = heat.heaters[var.currentHeater].active
                      
                      if var.currentTemp < 180 || var.currentTemp > 355
                        set var.currentTemp = 180 
                      
                      M291 P"Please set desired filament temperature" R"Filament Temp" S6 L180 H355 F{var.currentTemp}
                      set var.currentTemp = input
                      G10 P0 S{var.currentTemp}
                      
                      M116                                        ; wait for all heaters
                      
                      G11 ; unretract
                      
                      G1 Z300 F3600                               ; raise z=20mm
                      
                      G53 G1 X50 Y50 F14400                       ; move printhead to center
                      
                      G92 E0                                       ; reset e-steps
                      
                      M220 S100                                    ; Set speed factor override percentage
                      M221 S100                                    ; Set extrude factor override percentage
                      M572 D0 S0.0                                 ; disable pressure advance
                      M592 D0 A0.0 B0.0                            ; disable non-linear-extrusion
                      
                      M591 D0 P0
                      G4 S1
                      M591 D0 P3 C{var.filamentMonitorPin} S2 R98:102 E0.2 L{var.filamentMonitorCircumference}    ; enable MFM on all moves
                      
                      G4 S5 ; wait for restart of MFM
                      
                      G91 ; relative moves
                      ; 15mm
                      G1 X1 E1 F30
                      G1 X1 E1 F30
                      G1 X1 E1 F30
                      G1 X1 E1 F30
                      G1 X1 E1 F30
                      G1 X1 E1 F30
                      G1 X1 E1 F30
                      G1 X1 E1 F30
                      G1 X1 E1 F30
                      G1 X1 E1 F30
                      G1 X1 E1 F30
                      G1 X1 E1 F30
                      G1 X1 E1 F30
                      G1 X1 E1 F30
                      G1 X1 E1 F30
                      
                      ; the mfm should be calibrated now
                      
                      if sensors.filamentMonitors[0].calibrated == null
                        echo "Cannot calibrate filament monitor within 15mm - error!"
                        set global.ignoreMFMevents = false
                        M99
                      
                      G4 S1 ; wait for filament monitor send timeout
                      
                      ; start e-step calibration
                      var totalDistanceBase = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
                      
                      G1 X{var.extrusionDistance} E{var.extrusionDistance} F30
                      
                      G4 S1 ; wait for filament monitor send timeout
                      
                      var currentMeasured = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
                      
                      var newESteps = {floor(move.extruders[0].stepsPerMm / ((var.currentMeasured-var.totalDistanceBase)/var.extrusionDistance)*100)/100}
                      
                      set var.totalDistanceBase = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
                      
                      G1 X{var.extrusionDistance} E{var.extrusionDistance} F30
                      
                      G4 S1 ; wait for filament monitor send timeout
                      
                      set var.currentMeasured = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
                      
                      set var.newESteps = var.newESteps + {floor(move.extruders[0].stepsPerMm / ((var.currentMeasured-var.totalDistanceBase)/var.extrusionDistance)*100)/100}
                      
                      set var.totalDistanceBase = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
                      
                      G1 X{var.extrusionDistance} E{var.extrusionDistance} F30
                      
                      G4 S1 ; wait for filament monitor send timeout
                      
                      set var.currentMeasured = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
                      
                      echo "Current E-Steps: " ^ {move.extruders[0].stepsPerMm}
                      set var.newESteps = (var.newESteps + {floor(move.extruders[0].stepsPerMm / ((var.currentMeasured-var.totalDistanceBase)/var.extrusionDistance)*100)/100})
                      set var.newESteps = floor(var.newESteps / 3.0 * 100)/100
                      echo "New E-Steps: " ^ var.newESteps
                      
                      echo >{"0:/filaments/" ^ {move.extruders[0].filament} ^ "/config-auto-esteps.g"} "; calibration temperature: " ^ var.currentTemp
                      echo >>{"0:/filaments/" ^ {move.extruders[0].filament} ^ "/config-auto-esteps.g"} "M92 E" ^ var.newESteps
                      
                      M92 E{var.newESteps} ; activate new e-steps
                      
                      ; start non linear calibration
                      
                      G92 E0                                       ; reset e-steps
                      
                      ; https://www.bragitoff.com/2018/06/polynomial-fitting-c-program/
                      ; speed to test
                      var x = var.extrusionSpeeds
                      ; number of data points
                      var N = #var.x
                      ; degree of polynomial
                      var n = 2
                      ; echo "x: " ^ var.x
                      ; echo "N: " ^ var.N
                      ; echo "n: " ^ var.n
                      
                      ; array to store the y-axis data points
                      var y = vector(var.N, 0.0)
                      
                      ; gather y data points
                      ;set var.y = {0.0, 0.0, 0.0118, 0.0207, 0.0247, 0.0356, 0.0507, 0.0613, 0.0751, 0.0922, 0.1234, 0.1438}
                      
                      M591 D0 P0
                      G4 S1
                      M591 D0 P3 C{var.filamentMonitorPin} S2 R98:102 E0.2 L{var.filamentMonitorCircumference}    ; enable MFM on all moves
                      
                      G4 S5 ; wait for restart of MFM
                      
                      G91 ; relative moves
                      ; 15mm
                      G1 X1 E1 F30
                      G1 X1 E1 F30
                      G1 X1 E1 F30
                      G1 X1 E1 F30
                      G1 X1 E1 F30
                      G1 X1 E1 F30
                      G1 X1 E1 F30
                      G1 X1 E1 F30
                      G1 X1 E1 F30
                      G1 X1 E1 F30
                      G1 X1 E1 F30
                      G1 X1 E1 F30
                      G1 X1 E1 F30
                      G1 X1 E1 F30
                      G1 X1 E1 F30
                      
                      ; the mfm should be calibrated now
                      
                      if sensors.filamentMonitors[0].calibrated == null
                        echo "Cannot calibrate filament monitor within 15mm - error!"
                        set global.ignoreMFMevents = false
                        M99
                      
                      G4 S1 ; wait for filament monitor send timeout
                      
                      ; sensors.filamentMonitors[0].calibrated.totalDistance is including extrusion correction like pressure advance, non linear extrusion and so on ...
                      ; move.extruders[0].rawPosition is the extrusion without correction values
                      ; sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev is the number of measured revolutions
                      
                      var i = 0
                      
                      var first = true
                      var check = false
                      var nle_a = 0
                      var nle_b = 0
                      var nn = var.n
                      var success = false
                      var mean_error = 0.0
                      var min_error = 100.0
                      var max_error = 0.0
                      var s = 0.0
                      
                      while true
                        ; gather y-values for the compensated x-values
                        set var.i = 0
                        set var.n = var.nn
                        set var.mean_error = 0.0
                        set var.min_error = 100.0
                        set var.max_error = 0.0
                        var errors = vector(var.N, 0.0)
                      
                        while {var.i < var.N}
                          set var.totalDistanceBase = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
                          var comp_f = var.x[var.i] * 60
                          if var.check == false && var.first == false
                            set var.comp_f = var.comp_f * (1 + var.y[var.i])
                          
                          var currentCommanded = 100
                          G1 X{mod(var.i,2)=0?100:-100} E{var.currentCommanded} F{var.comp_f}
                          
                          G4 S1 ; wait for filament monitor send timeout
                          
                          set var.currentMeasured = (sensors.filamentMonitors[0].calibrated.totalDistance / sensors.filamentMonitors[0].calibrated.mmPerRev * sensors.filamentMonitors[0].configured.mmPerRev)
                        
                          var error = (1.0-((var.currentMeasured-var.totalDistanceBase)/var.currentCommanded))
                          set var.min_error = min(var.min_error, var.error)
                          set var.max_error = max(var.max_error, var.error)
                          set var.errors[var.i] = var.error
                      
                          echo "F" ^ {var.comp_f} ^ ": " ^ {var.error*100.0} ^ "% error."
                      
                          if var.comp_f < 60 && var.error >= 0.1
                            echo "The filament error exceeds the expected value at low speed. This may be due to grinding. Repeating!"
                            G1 E-10 F60 ; backoff some filament
                            G1 E15 F60 ; extrude some material to get pass the grinding
                            continue
                      
                          if var.check == false
                            set var.y[var.i] = var.error
                            if var.y[var.i] < 0.01
                              if var.first == true && var.i < 1 && var.y[var.i] < -0.01
                                echo "Calibrate E-Steps first."
                                M99
                              set var.y[var.i] = 0.01
                      
                            ; if the error is larger than 10% or more than twice as the previous value - stop 
                            if var.y[var.i] > 0.1 || ( var.i > 0 && var.y[var.i-1] > 0.025 && var.y[var.i] > (var.y[var.i-1] * 2))
                              if var.first == true && var.i < 1
                                echo "Calibrate E-Steps first."
                                M99
                              set var.N = var.i
                              echo "New N: " ^ var.N
                              break
                      
                          set var.i = var.i + 1
                        
                        set var.first = false
                      
                        var k = 0
                        while {var.k < var.N}
                          set var.mean_error = var.mean_error + var.errors[var.k]
                          set var.k = var.k + 1
                      
                        set var.mean_error = var.mean_error / var.N
                        echo "mean error:" ^ var.mean_error
                      
                        set var.k = 0
                        set var.s = 0.0
                      
                        while {var.k < var.N}
                          set var.s = pow(var.errors[var.k] - var.mean_error, 2.0)
                          set var.k = var.k + 1
                      
                        set var.s = sqrt(var.s / var.N)
                        echo "standard deviation: " ^ var.s
                      
                        if var.check
                          set var.check = false
                          if var.s <= 0.005
                            set var.success = true
                            break
                          elif var.s > 0.005 && var.s < 0.25
                            M592 D0 A0 B0
                            continue
                          else
                            set var.success = false
                            break
                      
                        ; echo "y: " ^ var.y
                        
                        ; an array of size 2*n+1 for storing N, Sig xi, Sig xi^2, ...
                        var X = vector(2*var.n+1, 0.0)
                        ; echo "X: " ^ var.X
                        
                        set var.i = 0
                        while {var.i <= (2*var.n)}
                          var j = 0
                          while {var.j < var.N}
                            set var.X[var.i] = var.X[var.i] + pow(var.x[var.j], var.i)
                            set var.j = var.j + 1
                          set var.i = var.i + 1
                        ; echo "X: " ^ var.X
                        
                        ; the normal argumented matrix
                        
                        var B = vector(var.n+1, vector(var.n+2, 0.0))
                        var Y = vector(var.n+1, 0.0)
                        ; echo "B: " ^ var.B
                        ; echo "Y: " ^ var.Y
                        
                        set var.i = 0
                        while {var.i <= var.n}
                          var j = 0
                          while {var.j < var.N}
                            set var.Y[var.i] = var.Y[var.i] + pow(var.x[var.j], var.i) * var.y[var.j]
                            set var.j = var.j + 1
                          set var.i = var.i + 1
                        ; echo "Y: " ^ var.Y
                        
                        set var.i = 0
                        while {var.i <= var.n}
                          var j = 0
                          while {var.j <= var.n}
                            set var.B[var.i][var.j] = var.X[var.i+var.j]
                            set var.j = var.j + 1
                          set var.i = var.i + 1
                        ; echo "B: " ^ var.B
                        
                        set var.i = 0
                        while {var.i <= var.n}
                          set var.B[var.i][var.n+1] = var.Y[var.i]
                          set var.i = var.i + 1
                        ; echo "B: " ^ var.B
                        
                        var A = vector(var.n+1, 0.0)
                        ; echo "A: " ^ var.A
                        
                        ; gaussEliminationLS
                        
                        var m = var.n + 1
                        set var.n = var.n + 2
                        
                        set var.i = 0
                        while {var.i < (var.m-1)}
                          ;Partial Pivoting
                          set var.k = var.i + 1
                          while {var.k < var.m}
                            ;If diagonal element(absolute vallue) is smaller than any of the terms below it
                            if abs(var.B[var.i][var.i]) < abs(var.B[var.k][var.i])
                              ;Swap the rows
                              var j = 0
                              while {var.j < var.n}
                                var temp = var.B[var.i][var.j]
                                set var.B[var.i][var.j] = var.B[var.k][var.j]
                                set var.B[var.k][var.j] = var.temp
                                set var.j = var.j + 1
                            set var.k = var.k + 1
                        
                          ;Begin Gauss Elimination
                          set var.k = var.i + 1
                          while {var.k < var.m}
                            var term = var.B[var.k][var.i] / var.B[var.i][var.i]
                            var j = 0
                            while {var.j < var.n}
                              set var.B[var.k][var.j] = var.B[var.k][var.j] - var.term * var.B[var.i][var.j]
                              set var.j = var.j + 1
                            set var.k = var.k + 1
                          set var.i = var.i + 1
                        
                        ;Begin Back-substitution
                        set var.i = var.m - 1
                        while {var.i >= 0}
                          set var.A[var.i] = var.B[var.i][var.n-1]
                          var j = var.i + 1
                          while {var.j < (var.n - 1)}
                            set var.A[var.i] = var.A[var.i] - var.B[var.i][var.j] * var.A[var.j]
                            set var.j = var.j + 1
                        
                          set var.A[var.i] = var.A[var.i] / var.B[var.i][var.i]
                          set var.i = var.i - 1
                        
                        set var.nle_a = var.A[1]
                        set var.nle_b = var.A[2]
                      
                        M592 D0 A{var.A[1]} B{var.A[2]} L0.2
                        echo "Test: M592 D0 A" ^ var.nle_a ^ " B" ^ var.nle_b ^ " L0.2"
                        set var.check = true
                      
                      if var.success
                        echo "NLE calibration finished!"
                        echo "M592 D0 A" ^ var.nle_a ^ " B" ^ var.nle_b ^ " L0.2"
                        echo >{"0:/filaments/" ^ {move.extruders[0].filament} ^ "/config-auto-nle.g"} "; max F" ^ var.x[var.N-1] * 60 ^ " mm/min or " ^ var.x[var.N-1] * 6.38 ^ "mm³/s"
                        echo >>{"0:/filaments/" ^ {move.extruders[0].filament} ^ "/config-auto-nle.g"} "; temp: " ^ var.currentTemp ^ " °C"
                        echo >>{"0:/filaments/" ^ {move.extruders[0].filament} ^ "/config-auto-nle.g"} "; mean error: " ^ var.mean_error
                        echo >>{"0:/filaments/" ^ {move.extruders[0].filament} ^ "/config-auto-nle.g"} "; min error: " ^ var.min_error
                        echo >>{"0:/filaments/" ^ {move.extruders[0].filament} ^ "/config-auto-nle.g"} "; max error: " ^ var.max_error
                        echo >>{"0:/filaments/" ^ {move.extruders[0].filament} ^ "/config-auto-nle.g"} "; standard deviation: " ^ var.s
                        echo >>{"0:/filaments/" ^ {move.extruders[0].filament} ^ "/config-auto-nle.g"} "M592 D0 A" ^ var.nle_a ^ " B" ^ var.nle_b ^ " L0.2"
                      else
                        echo "NLE calibration falied!"
                      
                      ; end calibration
                      
                      G10                                          ; retract
                      G10 P0 R0 S0                                 ; disable hotend
                      M140 S0 R0                                   ; set bed heater to 0°
                      M144 P0                                      ; disable bed heater
                      T-1                                          ; unselect tool
                      
                      M591 D0 P0                                   ; reset filament sensor
                      M98 P"0:/sys/meltingplot/machine-override"              ; Load Machine specific overrides
                      
                      set global.ignoreMFMevents = false
                      

                      add the following lines to your 0:/sys/filament-error.g

                      if exists(global.ignoreMFMevents) && global.ignoreMFMevents == true
                        M99
                      

                      and the following to your filament config

                      if fileexists({"0:/filaments/" ^ {move.extruders[0].filament} ^ "/config-auto-esteps.g"})
                        M98 P{"0:/filaments/" ^ {move.extruders[0].filament} ^ "/config-auto-esteps.g"}
                      
                      if fileexists({"0:/filaments/" ^ {move.extruders[0].filament} ^ "/config-auto-nle.g"})
                        M98 P{"0:/filaments/" ^ {move.extruders[0].filament} ^ "/config-auto-nle.g"}
                      

                      the macro M98 P"0:/sys/meltingplot/machine-override" will reset the filament monitor to its default, so you need to adapt this.

                      sample output

                      f834b0ec-b3a6-44b4-9e31-29079ebb4f11-grafik.png

                      85c20172-2903-4854-9ef2-2a2c7b67160e-grafik.png

                      b743d441-5edc-4105-a7b4-79453b3df13c-grafik.png

                      Another thing I would like to add is pressure advance calibration, as I think, it should be possible to determine the stiffness of the filament with the filament monitor and predict the pressure advance value. Maybe somesome can help here?

                      Btw. this script helped me to write a simple adaptive temp control in correlation to the extrusion speed, which will crank up the extrusion flow rate upto 30% and make the NLE look linear. Maybe something for the firmware @dc42

                      content of daemon.g

                      while true
                        if exists(global.initial_temp) == false
                          global initial_temp = 0
                      
                        if !exists(global.compensated_temp)
                          global compensated_temp = 0
                      
                        if !exists(global.is_compensated)
                          global is_compensated = false
                      
                        if !exists(global.filament_extrusion_temp_compensation_factor)
                          global filament_extrusion_temp_compensation_factor = 1
                      
                        if exists(global.filament_extrusion_temp_compensation) && global.filament_extrusion_temp_compensation
                          if ( {move.currentMove.extrusionRate} > 0 )
                            if global.initial_temp == 0 || global.compensated_temp != {heat.heaters[1].active}
                              set global.initial_temp = {heat.heaters[1].active}
                      
                            set global.compensated_temp = global.initial_temp + min({move.currentMove.extrusionRate} * global.filament_extrusion_temp_compensation_factor, 100)
                            G10 P0 S{global.compensated_temp} R{global.initial_temp-50}
                            set global.is_compensated = true
                          elif (global.initial_temp != 0 && {heat.heaters[1].active} != 0 && global.is_compensated)
                            G10 P0 S{global.initial_temp} R{global.initial_temp-50}
                            set global.is_compensated = false
                      

                      if you want to use the temp compensation add the following to your filament config and rerun the auto filament calibration

                      set global.filament_extrusion_temp_compensation_factor = 8
                      
                      if !exists(global.filament_extrusion_temp_compensation)
                        global filament_extrusion_temp_compensation = true
                      
                      1 Reply Last reply Reply Quote 4
                      • T3P3Tonyundefined T3P3Tony referenced this topic 1 May 2024, 19:51
                      • undefined
                        AndyE3D
                        last edited by 29 Nov 2024, 11:45

                        I created this macro to use the mfm to calibrate non linear extrusion. Have done nearly no print tests to see if it actually have a print quality improvement though so feedback would also be appreciated.

                        ; Inputs
                        var tool = param.T
                        var maxSpeed = exists(param.S) ? param.S : 20
                        var dist = exists(param.D) ? param.D : 20
                        var minExtrusionThreshold = exists(param.E) ? param.E : 0.85
                        
                        var force = exists(param.F) ? param.F : 0   ; if > 0, will run macro without confirming with user
                        
                        ; Configuration
                        var baseSpeed = 1
                        var debug = false
                        
                        ; Internal variables
                        var originalTool = state.currentTool
                        var speeds = {1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1}
                        var speedInc = var.maxSpeed / #var.speeds
                        while (iterations < #var.speeds)
                            set var.speeds[iterations] = var.speedInc * (iterations + 1)
                        
                        var drive = tools[var.tool].filamentExtruder
                        var flows = var.speeds ; must be same length as var.speeds
                        var eMulti = var.speeds ; must be same length as var.speeds
                        var numMeasurements = 0
                        
                        ; Check with user
                        if (var.force <= 0)
                            var msg = "Would you like to calibrate non linear extrusion for T"^{var.tool}^"? Current coefficients: Base="^move.extruders[var.drive].factor * 100^"%, A="^move.extruders[var.drive].nonlinear.a^", B="^move.extruders[var.drive].nonlinear.b
                            M291 S4 R{"Calibrating Extrusion: T"^var.tool} P{var.msg} K{"Yes", "No", "Reset Coefficients"}
                        
                            if (input == 1)
                                M99                         ; exit
                            if (input == 2)
                                M221 D{var.drive} S100
                                M592 D{var.drive} A0 B0
                                M99                         ; exit
                        
                        ; Calibrate default extrusion percentage
                        if (#var.speeds != #var.eMulti)
                            abort "var.speeds must have the same length as var.eMulti"
                        
                        echo "Calibrating extrusion rate for T"^var.tool^" using filament \""^move.extruders[tools[var.tool].filamentExtruder].filament^"\""
                        echo "Settings: distance = "^var.dist^"mm, base speed = "^var.baseSpeed^"mm/s, min extrusion threshold = "^{var.minExtrusionThreshold * 100}^"%"
                        echo "Speeds: "^var.speeds^" mm/s"
                        
                        if (sensors.filamentMonitors[var.drive].type != "rotatingMagnet")
                            abort "Must be a rotating magnet encoder"
                        if (sensors.filamentMonitors[var.drive].enableMode != 2)
                            abort "Encoder mode must be S2"
                        if (sensors.filamentMonitors[var.drive].configured.allMoves != true)
                            abort "Encoder must be active for all moves (A2)"
                        
                        T-1
                        T{var.tool} P0      ; don't run tpre, tfree, tpost
                        M703
                        if (tools[var.tool].active[0] == 0)
                            M568 P{var.tool} S{global.defaultFilamentTemperature}
                        M116 P{var.tool}
                        M220 S100                   ; reset speed
                        ; M221 D{var.drive} S100      ; reset base extrusion
                        M592 D{var.drive} A0 B0     ; reset non linear extrusion
                        ; G1 X334 Y100 F30000
                        M591 D{var.drive} S2 A1  ; set magnetic encoder to record during all moves
                        M400
                        G1 E{var.dist} F{var.baseSpeed * 60}
                        M400
                        var flow = sensors.filamentMonitors[var.drive].lastPercentage / 100
                        var baseFlowModifier = {100 / var.flow}
                        echo "Setting base extrusion factor override for drive "^var.drive^" = "^var.baseFlowModifier
                        M221 D{var.drive} S{var.baseFlowModifier}
                        
                        ; Collect non linear data
                        while iterations < #var.speeds
                            ; clear encoder data
                            M591 D{var.drive} S0
                            M591 D{var.drive} S2
                        
                            G1 E{var.dist} F{var.speeds[iterations] * 60}
                            M400
                            set var.flow = sensors.filamentMonitors[var.drive].lastPercentage / 100
                            set var.flows[iterations] = var.flow
                            set var.eMulti[iterations] = 1 / var.flow
                            echo "Flow at "^var.speeds[iterations]^"mm/s = "^{var.flow * 100}^"%, requires extrusion multiplier of "^{var.eMulti[iterations] * 100}^"%"
                        
                            set var.numMeasurements = iterations + 1
                            if (var.flow < var.minExtrusionThreshold)
                                break
                        
                        echo "Number of measurements = "^var.numMeasurements
                        echo "Flows: "^var.flows
                        echo "Required extrusion multipliers: "^var.eMulti
                        
                        ; Quadratic regression
                        ; https://www.statisticshowto.com/quadratic-regression/
                        var x = 0
                        var y = 1
                        var x2 = 0
                        var x3 = 0
                        var x4 = 0
                        var xy = 0
                        var x2y = 0
                        
                        while (iterations < var.numMeasurements)
                            set var.x = var.x + var.speeds[iterations]
                            set var.y = var.y + var.eMulti[iterations]
                            set var.x2 = var.x2 + (var.speeds[iterations] * var.speeds[iterations])
                            set var.x3 = var.x3 + (var.speeds[iterations] * var.speeds[iterations] * var.speeds[iterations])
                            set var.x4 = var.x4 + (var.speeds[iterations] * var.speeds[iterations] * var.speeds[iterations] * var.speeds[iterations])
                            set var.xy = var.xy + (var.speeds[iterations] * var.eMulti[iterations])
                            set var.x2y = var.x2y + (var.speeds[iterations] * var.speeds[iterations] * var.eMulti[iterations])
                        
                        if var.debug
                            echo "x = "^var.x
                            echo "y = "^var.y
                            echo "x2 = "^var.x2
                            echo "x3 = "^var.x3
                            echo "x4 = "^var.x4
                            echo "xy = "^var.xy
                            echo "x2y = "^var.x2y
                        
                        ; add 100% flow at 0 speed
                        set var.numMeasurements = var.numMeasurements + 1
                        
                        ; a*var.x4 + b*var.x3 + c*var.x2 = var.x2y
                        ; a*var.x3 + b*var.x2 + c*var.x = var.xy
                        ; a*var.x2 + b*var.x + c*var.numMeasurements = var.y
                        
                        ; Because we have normalised the base extrusion multiplier with a slow extrusion rate
                        ; c ~= 1
                        var c = 1
                        
                        ; Therefore
                        ; a*var.x4 + b*var.x3 = var.x2y - var.x2
                        ; a*var.x3 + b*var.x2 = var.xy - var.x
                        ; a*var.x2 + b*var.x = var.y - var.numMeasurements
                        
                        ; a = (var.y - var.numMeasurements - b*var.x) / var.x2
                        
                        ; ((var.y - var.numMeasurements - b*var.x) / var.x2)*var.x3 + b*var.x2 = var.xy - var.x
                        ; ((var.y - var.numMeasurements - b*var.x)*var.x3 / var.x2) + b*var.x2 = var.xy - var.x
                        
                        var b = ((var.xy - var.x) - (((var.y - var.numMeasurements)*var.x3)/var.x2))/(var.x2 - ((var.x * var.x3)/var.x2))
                        var a = ((var.y - var.numMeasurements) - (var.b * var.x))/var.x2
                        
                        if var.debug
                            echo "a = "^var.a
                            echo "b = "^var.b
                            echo "c = "^var.c
                        
                        ; Note var.a and var.b are flipped because M592 uses the equation (1 + min(L, Av + Bv^2)) which has different coefficients to that uses to solve the quadratic regression
                        echo "Setting non linear extrusion multiplier with: M592 D"^var.drive^" A"^var.b^" B"^var.a
                        M592 D{var.drive} A{var.b} B{var.a}
                        
                        T-1 P0
                        T{var.originalTool}
                        
                        ; M591 D{var.drive} S1 A1  ; only monitor filament during prints
                        

                        The main issue I have identified, which I don't think can easily be solved, is that it doesn't account for how much the filament expands coming out of the nozzle from die swell and foaming. So the extruder might be moving the correct quantity of filament, but the filament becomes a lower density once it leaves the nozzle which effectively produces overextrusion. I think a visual based method would be the most comprehensive way to measure this.

                        undefined 1 Reply Last reply 29 Nov 2024, 19:42 Reply Quote 1
                        • undefined
                          timschneider @AndyE3D
                          last edited by timschneider 29 Nov 2024, 19:42

                          @AndyE3D
                          Hi, thank you for sharing this alternative method for calibrating the non-linear extrusion with the MFM based on quadratic regression. In any case, your macro looks quite clean and well thought out.

                          It seems that the macro collects the errors only once, without reevaluating the applied coefficients. Based on my experience, I can say that this approach is insufficient to achieve good values that result in an error of less than 1% across the entire speed range. That’s why I follow this process with my macro:

                          • The minimum extrusion distance for the measurements should be at least twice as long as the melting zone.
                          • First, I collect the errors.
                          • I discard speeds with errors greater than 10%, as corrections would require at least a 20% adjustment, which is not feasible due to slip and grinding.
                          • I calculate the coefficients using least squares.
                          • I apply the coefficients.
                          • I test whether the errors are within acceptable limits.
                          • If the errors are within limits, I finish.
                          • If not, I adjust the speed values based on the corrected errors (e.g., an error of 2.5% at 2 mm/sec).
                          • I recollect errors with the adjusted speeds (e.g., 2.05 mm/sec).
                          • I recalculate the coefficients.
                          • I apply the coefficients again.
                          • I test if the errors are within limits.
                          • If the errors are within limits, I finish.
                          • If not, I drop the fastest speed and repeat the process.

                          Regarding your concerns about die swell or foaming, I can clarify that this is simply an extrusion multiplier in the slicer or filament profile when the non-linear extrusion is calculated using that method.

                          I am excited to see where the development of the MFM will lead.

                          Btw. you can find the latest macro of my MFM calibration at https://github.com/Meltingplot/BigPrint/blob/duet-3.5.3-sbc/duet-config/macros/meltingplot/filament-extrusion-calibration

                          1 Reply Last reply Reply Quote 2
                          • First post
                            Last post
                          Unless otherwise noted, all forum content is licensed under CC-BY-SA