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.
    • timschneiderundefined
      timschneider
      last edited by

      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 Reply Quote 4
      • T3P3Tonyundefined
        T3P3Tony administrators @timschneider
        last edited by

        @timschneider this is great! Thanks for sharing it 😁

        www.duet3d.com

        timschneiderundefined 1 Reply Last reply Reply Quote 0
        • timschneiderundefined
          timschneider @T3P3Tony
          last edited by

          @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 🙂

          timschneiderundefined 1 Reply Last reply Reply Quote 1
          • timschneiderundefined
            timschneider @timschneider
            last edited by

            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.

            timschneiderundefined 1 Reply Last reply Reply Quote 0
            • timschneiderundefined
              timschneider @timschneider
              last edited by

              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
              
              OwenDundefined 1 Reply Last reply Reply Quote 1
              • OwenDundefined
                OwenD @timschneider
                last edited by

                @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 🤔

                timschneiderundefined 1 Reply Last reply Reply Quote 0
                • o_lampeundefined
                  o_lampe
                  last edited by

                  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
                  • timschneiderundefined
                    timschneider @OwenD
                    last edited by

                    @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
                    • timschneiderundefined
                      timschneider
                      last edited by

                      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
                      
                      timschneiderundefined 1 Reply Last reply Reply Quote 0
                      • timschneiderundefined
                        timschneider @timschneider
                        last edited by timschneider

                        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
                        • AndyE3Dundefined
                          AndyE3D
                          last edited by

                          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.

                          timschneiderundefined 1 Reply Last reply Reply Quote 1
                          • timschneiderundefined
                            timschneider @AndyE3D
                            last edited by timschneider

                            @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