Magnetic Filament Monitor for Automatic E-Step Calibration
-
Hi folks,
I had the idea of a method for automatic e-step calibration. As it is not easy to get the e-step calibration right - in sense of how good the MFM is doing the measurement. So i thought, why not use the MFM in first place?
There are some requirements in order for the method to work, but these requirements are also positive for the MFM itself.
- The MFM must be tightly connected to the extruder (stiff and short)
- The initial calibration of the mm/rev of the MFM must be done by hand or math
That's it.
You only need around 500mm of Filament and you are good to go.
I use the following method
- set the L parameter of the MFM to your needs, I measured 8mm diameter of the sense wheel, so the circumference is about 25.13mm - I rounded it to 25.3
- set the min and max allowance values very tight, I use 98% and 102%
- set the reporting distance very small, I use 0.2mm
- now start printing a calibration file, where the file is basicly only extruding short chunks of 1mm filament with only 30 mm/min at your desired temperature, in the example 235° for petg carbon filled
- if the MFM is reporting tooLittleMovement, increase the e-steps
- if the MFM is reporting tooMuchMovement, decrease the e-steps
- store the latest reported e-steps in your filament config.
thats it - works like a charm, and the sporadic false tooLittleMovement error is gone
My g-code files for reference only, as they use other macros of our printers.
0:/gcodes/filament_monitor_calibration.gcode
if exists(global.mfmcalibration) set global.mfmcalibration = true else global mfmcalibration = true G10 P0 S235 ; sets the temperature M140 P0 S100 ; set bed temp M107 ; fan off M144 P0 S1 ; activate bed 1 heater T0 ; select tool 0 M98 P"0:/sys/meltingplot/home_if_necessary" ; check homing G29 S1 ; load stored hight map M83 ; use relative distances for extrusion G90 ; use absolute coordinates G21 ; set units to millimeters M116 ; wait for all heaters G11 ; unretract G1 Z300 ; raise z=20mm G53 G1 X50 Y50 F14400 ; move printhead to center G92 E0 ; reset e-steps M572 D0 S0.0 ; disable pressure advance M591 D0 P3 C"e1stop" S1 R98:102 E0.2 L25.3 ; enable MFM G4 S5 ; wait for restart of MFM G91 ; relative moves ; 500mm G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G1 X1 E1 F30 G10 ; retract G10 P0 R0 S0 ; disable hotend M140 S0 R0 ; set bed heater to 0° M140 P0 S-273.1 ; disable bed heater T-1 ; unselect tool set global.mfmcalibration = false
0:/sys/filament-error.g
; Parameter P description ; 2 = noDataReceived ; 3 = noFilament ; 4 = tooLittleMovement ; 5 = tooMuchMovement ; 6 = SensorError ; 7 = Magnet to weak ; 8 = Magnet to strong if param.P == 2 || param.P == 6 echo "Filament Sensor Error: " ^ param.P ^ " sensor : " ^ param.D ^ " - continue printing" M99 if param.P == 4 if !exists(global.mfmcalibration) || global.mfmcalibration == false echo "Filament Sensor " ^ param.D ^ ": Too little Filament movement - Possible Reasons: Filament empty, grinding or clogged nozzle." M291 P{"Filament Sensor " ^ param.D ^ ": Too little Filament movement - Possible Reasons: Filament empty, grinding or clogged nozzle."} S1 T0 M25 ; pause print else M92 E{move.extruders[0].stepsPerMm+0.1} echo "E-Steps: " ^ {move.extruders[0].stepsPerMm} ^ "" M99 ; leave macro if param.P == 5 if !exists(global.mfmcalibration) || global.mfmcalibration == false echo "Filament Sensor " ^ param.D ^ ": Too much Filament movement - Possible Reasons: Spool skipped or Filament pushed into PTFE tube." M291 P{"Filament Sensor " ^ param.D ^ ": Too much Filament movement - Possible Reasons: Spool skipped or Filament pushed into PTFE tube."} S1 T0 M25 ; pause print else M92 E{move.extruders[0].stepsPerMm-0.1} echo "E-Steps: " ^ {move.extruders[0].stepsPerMm} ^ "" M99 ; leave macro echo "Filament error: " ^ param.P ^ " on sensor " ^ param.D ^ " - paused" M291 P{"Filament Sensor " ^ param.D ^ ": " ^ param.S ^ " - Paused"} S1 T0 M25 ; pause
-
@timschneider this is great! Thanks for sharing it
-
@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
-
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 betweensensors.filamentMonitors[0].calibrated.totalDistance
andmove.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.gcodeif 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:
So i was able to correct the extrusion up to F300 with 2.85mm filament or up to 31.9mm³/s.
-
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
-
@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 -
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. -
@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
-
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
-
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
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
-