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

    Magnetic Filament Monitor for Automatic E-Step Calibration

    Scheduled Pinned Locked Moved
    Filament Monitor
    5
    12
    2.2k
    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 @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