Duet3D Logo Duet3D
    • Tags
    • Documentation
    • Order
    • Register
    • Login
    1. Home
    2. timschneider
    3. Best
    • Profile
    • Following 0
    • Followers 0
    • Topics 31
    • Posts 193
    • Best 46
    • Controversial 0
    • Groups 0

    Best posts made by timschneider

    • 3.5.2 Closed loop SBC Setup Duet3 6HC 2x1HCL+Magnetic Encoder

      @dc42 @chrishamm @T3P3Tony and the whole Duet3D Team! Thank you!

      3.5.2 Closed loop SBC Setup Duet3 6HC 2x 1HCL with Magnetic Encoder on NEMA 17 1.8° LDO Motor

      I have the Closed Loop System running for a week now and have been printing continuously 24/7 on a job that I had to abort six times before. Without the Closed Loop System, I would not be able to print the job!

      Thanks a lot for this! After initial difficulties in tuning the system, because the instructions were written for quadrature shaft encoders, I was able to achieve a high-performance tuning. The Closed Loop System even has a better print quality e.g. because the backlash is compensated. I can run the steppers at full current, higher accelerations, higher speeds and the steppers are even cooler.

      Btw. the printer is loosing the position about every 15 minutes on that print, due to the material. It's our PA6 CF HT which is very stiff and strong, so even the smallest amount of residues will stop/crash the print head. The print takes around 5.5 kg, where the material is around 89€/kg.

      Please find attached a picture in which you can hardly see the misalignments. 2024-10-04-16-58-03-364.jpg

      Chris, after the hard work you put in the SBC setup it runs pretty stable now 🙂 not rock solid, as I can still crash it - but mostly solid 😉

      Keep up the great work!

      posted in General Discussion
      timschneiderundefined
      timschneider
    • Simplyprint.io (unoffical) Duet Connector

      Hi, I came across Simplyprint.io and thought it would be nice to control our printers with Duet control via the interface. It is a cloud based remote / off-side print management tool.
      They do not offer a connector to duet at the moment, so I wrote a connector that allows easy monitoring and control of the printers. Maybe someone here is interested in it.
      You can find it on github and you can run it on a RPi.
      I know it is tempting to use the SBC for that, but you need python >= 3.8 to run it, so either bookworm or bulleseye - buster will not work.

      Some screenshots from my setup:

      db9118a1-42c2-4781-8114-c188fbacb57c-grafik.png
      d0b9e557-c400-4962-9f90-97da387e6be8-grafik.png

      posted in Third-party software
      timschneiderundefined
      timschneider
    • RE: [3.5.0-rc.3+5] [bug] nested while job Illegal para letter '.'

      @chrishamm
      Thanks for the great patch! Your work is outstanding! It's impressive to see the passion and dedication you and the duet3d team put into the software and hardware!

      Now that all the show-stoppers are out of the way, we are going to switch completely to duet3 in the sbc setup. Starting with 4 closed loop steppers with 4 1HCL and 4 open loop steppers directly on the 6HC. Also two filament monitors and two IR probes per machine. This will be followed at a later stage by two tool boards and a distribution board per machine. I am excited to see the results.

      posted in DSF Development
      timschneiderundefined
      timschneider
    • 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
      
      posted in Filament Monitor
      timschneiderundefined
      timschneider
    • Howto make the filament monitor more robust

      Hi,

      we sometimes face the problem, that the filamentsensor is producing "false" errors. They are actually true from the MFM perspective resulting in 0% extrusion or even minus values, but only minor in nature e.g. due to friction or some sort of untangling of the filament spool and will not affect the print result at all.
      So the current range will not work on these kind of errors.

      In order to reduce these "false" alarms and resulting print pause, I came up with the idea of some kind of a backoff counter.

      It works the following:

      • count the filament errors
      • if the count will go above a threshold, pause the print.
      • reduce the count if there was no filament error within a relaxe duration e.g. 60s

      reduce the check distance in order not to loose resultion. e.g. from

      M591 D0 P3 C"e1stop" S1 R70:120 E6 L25.3
      

      to

      M591 D0 P3 C"e1stop" S1 R70:120 E2 L25.3
      

      with a counter of 3.

      the output looks like the following below the threshold:
      5fc41dd3-2b6b-4faa-9a6f-a88428e74b4b-grafik.png

      and above the threshold:
      0dcc5144-4509-480b-a54e-7e6902a0229a-grafik.png

      The code 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 !exists(global.mfmbackoff)
        global mfmbackoff = 3
      
      if !exists(global.lastMFMBackoffCheck)
        global lastMFMBackoffCheck = state.upTime
      
      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 == true
              M92 E{move.extruders[0].stepsPerMm+0.1}
              echo "E-Steps: " ^ {move.extruders[0].stepsPerMm} ^ ""
          else
              echo "Filament Sensor " ^ param.D ^ ": Too little Filament movement - Possible Reasons: Filament empty, grinding or clogged nozzle."
              
              set global.lastMFMBackoffCheck = state.upTime
      
              if global.mfmbackoff == 0
                  set global.mfmbackoff = 3
                  M291 P{"Filament Sensor " ^ param.D ^ ": Too little Filament movement - Possible Reasons: Filament empty, grinding or clogged nozzle."} S1 T0
                  M25 ; pause print
              else
                  set global.mfmbackoff = global.mfmbackoff - 1
                  echo "Filament Sensor Backoffcounter: " ^ global.mfmbackoff ^ ""
              
          M99 ; leave macro
      
      if param.P == 5
          if exists(global.mfmcalibration) && global.mfmcalibration == true
              M92 E{move.extruders[0].stepsPerMm-0.1}
              echo "E-Steps: " ^ {move.extruders[0].stepsPerMm} ^ ""
          else
              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
              
          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
      

      0:/sys/daemon.g:

      if exists(global.mfmbackoff) && exists(global.lastMFMBackoffCheck) && global.mfmbackoff < 3 && ((global.lastMFMBackoffCheck + 60) < state.upTime)
          set global.mfmbackoff = global.mfmbackoff + 1
          set global.lastMFMBackoffCheck = state.upTime
      
      posted in Filament Monitor
      timschneiderundefined
      timschneider
    • RE: Magnetic Filament Monitor for Automatic E-Step Calibration

      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
      
      posted in Filament Monitor
      timschneiderundefined
      timschneider
    • Indicate that a Command is added to the Movement Queue

      The behaviour of some G and M Codes in relation to the movement queue has silently changed in the past.

      This is for example the reason why I only add a single line of code M112 in the emergency stop trigger, even if I would add more commands to it - if a customer is updating the firmware, it may break the script.

      In the recent days, I saw other people getting in touch with the behaviour of the movment queue and it is kind of a pitfall if you don't know it.

      So in order to make people aware of it, I would like to propose a small icon next to the G-Code Command in the Docs to indicate, that the command is added to the movement queue. The Icon is linked to a page explaining the movement queue and show examples on how to get around the queue, e.g. use expressions at the moment.

      f7781860-e4b5-452b-939a-8c334582f614-grafik.png

      what do you think about it?

      the icon shown is from flaticon, but that is not important.

      posted in Documentation
      timschneiderundefined
      timschneider
    • Automated compiling to perform CD/CI

      Hello,
      i recently stumpled over some minor problems or wanted improvements with the RRF in different locations -> e.g. M200 SafeState on power down, heater power consumption / limiter, virtual endstops to map events like heaterfault to trigger#.g ... and while doing so I needed to compile the firmware to check quick fixed. Then I thought, that it would be usefull to automate the firmware creation for RRF with github actions, so that every push or merge request is automaticly checked against the current dev of the project and no one really needs to care about the dev environment anymore.
      I'm currently on the Duet2 Ethernet, thats why I startet there and following the build instructions, one should start with the CoreNG, so did I. Following the variants/duetNG/build_gcc make file and logic, I copied that build logic to all dependencies to simplify maintainance.

      I will upload all the modificaitions I did to my github today, but as a starting point the RRFLibraries in dev branch are already up.

      c571f6a3-edd5-4af8-a48d-55d18ea10f59-grafik.png
      https://github.com/timschneider/RRFLibraries/commit/2a6808c4c2c5ab9cbae5b86d237f57f1491634a4/checks?check_suite_id=399291871

      So to conclude what I did:

      • changed the build scripts in variants/duetNG/build_gcc of CoreNG to perform like the Eclipse Build logic, e.g. with recursion and exlusion logic
      • copied that build scripts to every project (CoreNG, FreeRTOS, RRFLibraries, RepRapFirmware, DuetWiFiSocketServer (not yet))
      • adapted the build scripts according to the .cproject files of each project to behave similar to eclipse auto makefile generation
      • put the different dependencies in the github actions file (WIP)

      This allows me to make a change to the code and get the newly build firmware right from github in an automated fashion.

      what do you think about it? should we continue to work on that?

      Tim

      0 timschneider committed to timschneider/RRFLibraries
      Update ccpp.yml
      posted in Firmware developers
      timschneiderundefined
      timschneider
    • RE: [3.5.0-rc.3] M122 causing Lost connection to Duet (Timeout

      I've added corresponding issue and pull request on Github.
      https://github.com/Duet3D/RepRapFirmware/pull/955

      The Binary for MB6HC
      Duet3Firmware_MB6HC.bin

      That solved the problem for me.

      1f1a35c0-1c06-40dd-9ae8-88f7ff7dce52-grafik.png

      timschneider opened this pull request in Duet3D/RepRapFirmware

      closed Fix M122 StuckInSpinLoop, Gcodes spinning #955

      posted in DSF Development
      timschneiderundefined
      timschneider
    • RE: Movement after M112 E-Stop!

      @dc42

      I think it is a success!

      without the IterateDrivers fix there is a small delay 1.34s in the step generation shut down, but the drivers are not re-enabled.

      SDS00007.png

      with both patches 'no' delay at all.
      SDS00008.png

      posted in CNC
      timschneiderundefined
      timschneider
    • RE: Magnetic Filament Monitor for Automatic E-Step Calibration

      @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

      posted in Filament Monitor
      timschneiderundefined
      timschneider
    • RE: [3.6.0-beta.3] DWC connection issues Duet2 / Duex5

      @chrishamm
      ok, checked it and indeed reducing the clients to one DWC session helped to mitigate the problem - or to say I was not able to trigger it via DWC with repeating M122 gcodes. But, i took the chance to rush down the rabbit hole and was able to trigger it with M122 M122 M122 as one command.

      HTTP connection accepted<\n>
      Found responder<\n>
      Received 466 bytes<\n>
      HTTP req, command words { GET /rr_gcode HTTP/1.0 }, parameters { gcode=M122 M122 M122 M122 }<\n>
      Sending JSON reply, length 12<\n>
      New conn on socket 0 for local port 80<\n>
      HTTP connection accepted<\n>
      Found responder<\n>
      Received 431 bytes<\n>
      Peer disconnected on socket 0<\n>
      New conn on socket 0 for local port 80<\n>
      HTTP connection accepted<\n>
      Found responder<\n>
      Received 431 bytes<\n>
      Peer disconnected on socket 0<\n>
      New conn on socket 0 for local port 80<\n>
      HTTP connection accepted<\n>
      Found responder<\n>
      Received 431 bytes<\n>
      Released gcodeReply, free buffers=26<\n>
      Peer disconnected on socket 0<\n>
      New conn on socket 0 for local port 80<\n>
      HTTP connection accepted<\n>
      Found responder<\n>
      Received 458 bytes<\n>
      HTTP req, command words { GET /rr_connect HTTP/1.0 }, parameters { password=meltingplot time=2025-1-27T15:33:25 sessionKey=yes }<\n>
      Sending JSON reply, length 94<\n>
      New conn on socket 0 for local port 80<\n>
      HTTP connection accepted<\n>
      Found responder<\n>
      
      
      { GET /rr_gcode HTTP/1.0 }, parameters { gcode=m122 }Bad recv status sizeError: failed to retrieve WiFi status message: another SPI transfer is pendingBad recv status sizeBad recv status sizeError: failed to retrieve WiFi status message: another SPI transfer is pendingBad recv status sizeError: failed to retrieve WiFi status message: SPI timeoutError: failed to retrieve WiFi status message: SPI timeoutBad recv status sizeError: failed to retrieve WiFi status message: SPI timeoutBad recv status sizeError: failed to retrieve WiFi status message: SPI timeoutBad recv status sizeError: failed to retrieve WiFi status message: SPI timeoutBad recv status sizeError: failed to retrieve WiFi status message: SPI timeoutBad recv status sizeError: failed to retrieve WiFi status message: SPI timeoutBad recv status sizeError: failed to retrieve WiFi status message: SPI timeoutBad recv status sizeError: failed to retrieve WiFi status message: SPI timeoutBad recv status sizeError: failed to retrieve WiFi status message: SPI timeoutBad recv status sizeError: failed to retrieve WiFi status message: SPI timeoutBad recv status sizeError: failed to retrieve WiFi status message: SPI timeoutBad recv status sizeError: failed to retrieve WiFi status message: SPI timeoutBad recv status sizeError: failed to retrieve WiFi status message: SPI timeoutBad recv status sizeError: failed to retrieve WiFi status message: SPI timeoutBad recv status sizeError: failed to retrieve WiFi status message: SPI timeoutBad recv status sizeError: failed to retrieve WiFi status message: SPI timeoutBad recv status sizeError: failed to retrieve WiFi status message: SPI timeoutBad recv status sizeError: failed to retrieve WiFi status message: SPI timeoutBad recv status sizeError: failed to retrieve WiFi status message: SPI timeoutBad recv status sizeError: failed to retrieve WiFi status message: SPI timeoutBad recv status sizeError: failed to retrieve WiFi status message: SPI timeoutBad recv status sizeError: failed to retrieve WiFi status message: SPI timeoutBad recv status sizeError: failed to retrieve WiFi status message: SPI timeoutBad recv status sizeError: failed to retrieve WiFi status message: SPI timeoutBad recv status sizeError: failed to retrieve WiFi status message: SPI timeoutBad recv status sizeError: failed to retrieve WiFi status message: SPI timeoutBad recv status sizeError: failed to retrieve WiFi status message: SPI timeoutBad recv status sizeError: failed to retrieve WiFi status message: SPI timeoutBad recv status sizeError: failed to retrieve WiFi status message: SPI timeoutBad recv status sizeError: failed to retrieve WiFi status message: SPI timeoutBad recv status sizeError: failed to retrieve WiFi status message: SPI timeoutBad recv status sizeError: failed to retrieve WiFi status message: SPI timeoutBad recv status sizeError: failed to retrieve WiFi status message: SPI timeoutBad recv status sizeError: failed to retrieve WiFi status message: SPI timeoutBad recv status sizeError: failed to retrieve WiFi status message: SPI timeoutBad recv status sizeError: failed to retrieve WiFi status message: SPI timeoutBad recv status sizeReleased gcodeReply, free buffers=26Error: failed to retrieve WiFi status message: SPI timeoutBad recv status size
      

      don't know if this is somehow related, just catched it as a by-catch.

      OK, lesson learned - teach the bot to query rr_reply every second, just in case. But still there is some problem with memory management and error handling.

      posted in Beta Firmware
      timschneiderundefined
      timschneider
    • RE: Movement after M112 E-Stop!

      @timschneider
      I think the problem is in the IterateDrivers Function in the Platform.cpp

      the following code snippets are based on the 3.4-dev branch

      The else if branch will disable all extruders, but the problem is, that it will start working from GetTotalAxes() to MaxAxesPlusExtruders. But there are only MaxExtruders allowed.
      That means in numbers for the MB6XD

      MaxAxesPlusExtruders = 25
      GetTotalAxes() = 3 in this case XYZ
      MaxExtruders  = 16
      

      So from 3 - 24 it will work with the else if branch

      size_t LogicalDriveToExtruder(size_t drive) noexcept { return MaxAxesPlusExtruders - 1 - drive; }
      
      25 - 1 - 3 = 21
      25 - 1 - 4 = 20
      ...
      25 - 1 - 24 = 0
      
      DriverId extruderDrivers[MaxExtruders] -> array of 16 elements
      
      so the following code will read some random data for the elements from 3 - 8
      const DriverId id = extruderDrivers[LogicalDriveToExtruder(axisOrExtruder)];
      
      and this code will sometimes end up in the remoteFunc e.g. in our case send can message and wait for a reply
      
      if (id.IsLocal())
      {
      	localFunc(id.localDriver);
      }
      else
      {
      	remoteFunc(id);
      }
      
      but there will be no reply and this will delay the e-stop (stop step generation and clear the movement system) around 3 - 3.5 sec
      

      I've changed the IterateDrivers the following:

      // Function to identify and iterate through all drivers attached to an axis or extruder
      void Platform::IterateDrivers(size_t axisOrExtruder, function_ref<void(uint8_t)> localFunc, function_ref<void(DriverId)> remoteFunc) noexcept
      {
      	if (axisOrExtruder < reprap.GetGCodes().GetTotalAxes())
      	{
      		for (size_t i = 0; i < axisDrivers[axisOrExtruder].numDrivers; ++i)
      		{
      			const DriverId id = axisDrivers[axisOrExtruder].driverNumbers[i];
      			if (id.IsLocal())
      			{
      				localFunc(id.localDriver);
      			}
      			else
      			{
      				remoteFunc(id);
      			}
      		}
      	}
      	else if (axisOrExtruder >= (MaxAxesPlusExtruders - MaxExtruders) && axisOrExtruder < MaxAxesPlusExtruders)
      	{
      		const DriverId id = extruderDrivers[LogicalDriveToExtruder(axisOrExtruder)];
      		if (id.IsLocal())
      		{
      			localFunc(id.localDriver);
      		}
      		else
      		{
      			remoteFunc(id);
      		}
      	}
      }
      

      But this will only address the delay - I think this is a good time to add a secondary layer to prevent the EnableSignale from getting high again. (Because of the delay, prepare moves where re-enableing the drivers again)

      platform.cpp

       src/Platform/Platform.cpp | 7 ++++---
       1 file changed, 4 insertions(+), 3 deletions(-)
      
      diff --git a/src/Platform/Platform.cpp b/src/Platform/Platform.cpp
      index c8f7793c..fdd6f2d3 100644
      --- a/src/Platform/Platform.cpp
      +++ b/src/Platform/Platform.cpp
      @@ -424,7 +424,7 @@ Platform::Platform() noexcept :
       #if HAS_MASS_STORAGE
       	logger(nullptr),
       #endif
      -	board(DEFAULT_BOARD_TYPE), active(false), errorCodeBits(0),
      +	board(DEFAULT_BOARD_TYPE), active(false), preventDriverEnable(true), errorCodeBits(0),
       	nextDriveToPoll(0),
       	lastFanCheckTime(0),
       #if SUPPORT_PANELDUE_FLASH
      @@ -861,6 +861,7 @@ void Platform::Init() noexcept
       	DuetExpansion::DueXnTaskInit();								// must initialise interrupt priorities before calling this
       #endif
       	active = true;
      +	preventDriverEnable = false;
       }
       
       // Reset the min and max recorded voltages to the current values
      @@ -2439,7 +2440,7 @@ void Platform::IterateDrivers(size_t axisOrExtruder, function_ref<void(uint8_t)>
       			}
       		}
       	}
      -	else if (axisOrExtruder < MaxAxesPlusExtruders)
      +	else if (axisOrExtruder >= (MaxAxesPlusExtruders - MaxExtruders) && axisOrExtruder < MaxAxesPlusExtruders)
       	{
       		const DriverId id = extruderDrivers[LogicalDriveToExtruder(axisOrExtruder)];
       		if (id.IsLocal())
      @@ -2572,7 +2573,7 @@ void Platform::DisableOneLocalDriver(size_t driver) noexcept
       // Enable the local drivers for a drive. Must not be called from an ISR, or with interrupts disabled.
       void Platform::EnableDrivers(size_t axisOrExtruder, bool unconditional) noexcept
       {
      -	if (unconditional || driverState[axisOrExtruder] != DriverStatus::enabled)
      +	if (unconditional || (driverState[axisOrExtruder] != DriverStatus::enabled && !preventDriverEnable))
       	{
       		driverState[axisOrExtruder] = DriverStatus::enabled;
       		const float requiredCurrent = motorCurrents[axisOrExtruder] * motorCurrentFraction[axisOrExtruder];
      

      platform.h

       src/Platform/Platform.h | 5 ++++-
       1 file changed, 4 insertions(+), 1 deletion(-)
      
      diff --git a/src/Platform/Platform.h b/src/Platform/Platform.h
      index c3f006b4..4f2b2196 100644
      --- a/src/Platform/Platform.h
      +++ b/src/Platform/Platform.h
      @@ -528,7 +528,7 @@ public:
       
       	uint32_t GetSteppingEnabledDrivers() const noexcept { return steppingEnabledDriversBitmap; }
       	void DisableSteppingDriver(uint8_t driver) noexcept { steppingEnabledDriversBitmap &= ~StepPins::CalcDriverBitmap(driver); }
      -	void EnableAllSteppingDrivers() noexcept { steppingEnabledDriversBitmap = 0xFFFFFFFFu; }
      +	void EnableAllSteppingDrivers() noexcept { if (!preventDriverEnable) { steppingEnabledDriversBitmap = 0xFFFFFFFFu; } }
       
       #ifdef DUET3_MB6XD
       	bool HasDriverError(size_t driver) const noexcept;
      @@ -643,6 +643,8 @@ public:
       	const GpInputPort& GetGpInPort(size_t gpinPortNumber) const noexcept
       		pre(gpinPortNumber < MaxGpInPorts) 	{ return gpinPorts[gpinPortNumber]; }
       
      +	void SetPreventDriverEnable() noexcept { preventDriverEnable = true; }
      +
       #if MCU_HAS_UNIQUE_ID
       	const UniqueId& GetUniqueId() const noexcept { return uniqueId; }
       	uint32_t Random() noexcept;
      @@ -742,6 +744,7 @@ private:
       #endif
       
       	bool active;
      +	bool preventDriverEnable;
       	uint32_t errorCodeBits;
       
       	void InitialiseInterrupts() noexcept;
      
      

      RepRap.cpp

       src/Platform/RepRap.cpp | 1 +
       1 file changed, 1 insertion(+)
      
      diff --git a/src/Platform/RepRap.cpp b/src/Platform/RepRap.cpp
      index 5d5a28aa..168619c4 100644
      --- a/src/Platform/RepRap.cpp
      +++ b/src/Platform/RepRap.cpp
      @@ -1004,6 +1004,7 @@ void RepRap::EmergencyStop() noexcept
       	else
       #endif
       	{
      +		platform->SetPreventDriverEnable(); // prevent any conditional call to EnableDrivers
       		platform->DisableAllDrivers();				// disable all local and remote drivers - need to do this to ensure that any motor brakes are re-engaged
       
       		switch (gCodes->GetMachineType())
      

      With these changes, there will be no delay at all after the estop is pressed in DWC and processed by RRF.

      SDS00041.png

      posted in CNC
      timschneiderundefined
      timschneider
    • RE: List of RRF compatible post-processors

      @MaxGyver

      this is our current post (fusion360) based on the reprap from autodesk, but I guess you need to modify it to fit your machine.

      meltingplot-ekka.cps

      posted in CNC
      timschneiderundefined
      timschneider
    • [bug] System.NotSupportedException: Specified method is

      While checking the log of the printer that crashes in sbc setup sometimes I found the following.

      The error occured while hammering the DSF<->Duet3 SPI interface with requests via large printjob simulation and quering DSF via DWC to execute M122.

      Jan 04 17:51:15 Meltingplot-MBL-480-vaswsq DuetWebServer[1321]: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[3] Route matched with {action = "DoCode", controller = "Machine"}. Executing controller action with signature System.Threading.Tasks.Task`1[Microsoft.AspNetCore.Mvc.IActionResult] DoCode(DuetWebServer.Singletons.ISessionStorage, Boolean) on controller DuetWebServer.Controllers.MachineController (DuetWebServer).
      Jan 04 17:51:15 Meltingplot-MBL-480-vaswsq DuetWebServer[1321]: DuetWebServer.Singletons.SessionStorage[0] Session a0b7b52e95b74569b4fcd0fc45803587 started a long-running request
      Jan 04 17:51:15 Meltingplot-MBL-480-vaswsq DuetWebServer[1321]: DuetWebServer.Controllers.MachineController[0] [DoCode] Executing code 'M122'
      Jan 04 17:51:15 Meltingplot-MBL-480-vaswsq DuetControlServer[744]: [error] HTTP: Failed to process code in stage Executed
      Jan 04 17:51:15 Meltingplot-MBL-480-vaswsq DuetControlServer[744]:    System.NotSupportedException: Specified method is not supported.
      Jan 04 17:51:15 Meltingplot-MBL-480-vaswsq DuetControlServer[744]:    at System.Threading.Channels.ChannelReader`1.get_Count()
      Jan 04 17:51:15 Meltingplot-MBL-480-vaswsq DuetControlServer[744]:    at DuetControlServer.Codes.Pipelines.PipelineBase.Diagnostics(StringBuilder builder) in /home/runner/work/DuetSoftwareFramework/DuetSoftwareFramework/src/DuetControlServer/Codes/Pipelines/PipelineBase.cs:line 103
      Jan 04 17:51:15 Meltingplot-MBL-480-vaswsq DuetControlServer[744]:    at DuetControlServer.Codes.ChannelProcessor.Diagnostics(StringBuilder builder) in /home/runner/work/DuetSoftwareFramework/DuetSoftwareFramework/src/DuetControlServer/Codes/ChannelProcessor.cs:line 87
      Jan 04 17:51:15 Meltingplot-MBL-480-vaswsq DuetControlServer[744]:    at DuetControlServer.Codes.Processor.Diagnostics(StringBuilder builder) in /home/runner/work/DuetSoftwareFramework/DuetSoftwareFramework/src/DuetControlServer/Codes/Processor.cs:line 48
      Jan 04 17:51:15 Meltingplot-MBL-480-vaswsq DuetControlServer[744]:    at DuetControlServer.Codes.Handlers.MCodes.Diagnostics(Message result) in /home/runner/work/DuetSoftwareFramework/DuetSoftwareFramework/src/DuetControlServer/Codes/Handlers/MCodes.cs:line 1069
      Jan 04 17:51:15 Meltingplot-MBL-480-vaswsq DuetControlServer[744]:    at DuetControlServer.Codes.Handlers.MCodes.CodeExecuted(Code code) in /home/runner/work/DuetSoftwareFramework/DuetSoftwareFramework/src/DuetControlServer/Codes/Handlers/MCodes.cs:line 1033
      Jan 04 17:51:15 Meltingplot-MBL-480-vaswsq DuetControlServer[744]:    at DuetControlServer.Codes.Pipelines.Executed.ProcessCodeAsync(Code code) in /home/runner/work/DuetSoftwareFramework/DuetSoftwareFramework/src/DuetControlServer/Codes/Pipelines/Executed.cs:line 44
      Jan 04 17:51:15 Meltingplot-MBL-480-vaswsq DuetControlServer[744]:    at DuetControlServer.Codes.Pipelines.PipelineStackItem.<>c__DisplayClass0_0.<<-ctor>b__0>d.MoveNext() in /home/runner/work/DuetSoftwareFramework/DuetSoftwareFramework/src/DuetControlServer/Codes/Pipelines/PipelineStackItem.cs:line 64
      Jan 04 17:51:30 Meltingplot-MBL-480-vaswsq DuetWebServer[1321]: DuetWebServer.Singletons.SessionStorage[0] Session f0e11673864a49f68e1373ccbb7b2557 finished a long-running request
      Jan 04 17:51:30 Meltingplot-MBL-480-vaswsq DuetWebServer[1321]: DuetWebServer.Controllers.MachineController[0] [DoCode] DCS is not started
      Jan 04 17:51:30 Meltingplot-MBL-480-vaswsq DuetWebServer[1321]: Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor[1] Executing ObjectResult, writing value of type 'System.String'.
      Jan 04 17:51:30 Meltingplot-MBL-480-vaswsq DuetWebServer[1321]: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[2] Executed action DuetWebServer.Controllers.MachineController.DoCode (DuetWebServer) in 236398.3322ms
      Jan 04 17:51:30 Meltingplot-MBL-480-vaswsq DuetWebServer[1321]: Microsoft.AspNetCore.Routing.EndpointMiddleware[1] Executed endpoint 'DuetWebServer.Controllers.MachineController.DoCode (DuetWebServer)'
      Jan 04 17:51:30 Meltingplot-MBL-480-vaswsq DuetWebServer[1321]: Microsoft.AspNetCore.Hosting.Diagnostics[2] Request finished HTTP/1.1 POST http://192.168.172.110/machine/code text/plain;charset=UTF-8 4 - 503 - text/plain;+charset=utf-8 236402.9347ms
      Jan 04 17:51:38 Meltingplot-MBL-480-vaswsq DuetWebServer[1321]: DuetWebServer.Singletons.SessionStorage[0] Session f0e11673864a49f68e1373ccbb7b2557 expired
      

      M122 at the moment DCS crashed from the eventlog

      2024-01-04 17:51:15 === Diagnostics ===
      RepRapFirmware for Duet 3 MB6HC version 3.5.0-rc.2 (2023-12-14 10:32:22) running on Duet 3 MB6HC v1.02 or later (SBC mode)
      Board ID: 08DJM-9P63L-DJ3T8-6JKD4-3SJ6K-9A77A
      Used output buffers: 1 of 40 (29 max)
      === RTOS ===
      Static ram: 154844
      Dynamic ram: 88272 of which 4072 recycled
      Never used RAM 95036, free system stack 119 words
      Tasks: SBC(2,nWait,6.6%,404) HEAT(3,nWait,0.0%,324) Move(4,nWait,42.8%,213) CanReceiv(6,nWait,0.0%,942) CanSender(5,nWait,0.0%,334) CanClock(7,delaying,0.0%,342) TMC(4,nWait,5.5%,61) MAIN(1,running,45.0%,103) IDLE(0,ready,0.0%,30), total 100.0%
      Owned mutexes: HTTP(MAIN)
      === Platform ===
      Last reset 01:18:38 ago, cause: power up
      Last software reset at 2024-01-03 15:51, reason: OutOfMemory, Gcodes spinning, available RAM 428, slot 0
      Software reset code 0x41c3 HFSR 0x00000000 CFSR 0x00000000 ICSR 0x00435000 BFAR 0x00000000 SP 0x2041b9a0 Task MAIN Freestk 2054 ok
      Stack: 2041808c 00419f61 00000103 2043229c 2043c740 0044659f 00000003 00000000 0000007c 01000003 ffffffff 00000000 00000253 2041bccc 2042bb20 204251b0 204251b0 00471301 00000000 00497caf 0000000a 00000000 00000000 00000000 00000000 00000000 004aea70
      Error status: 0x00
      MCU temperature: min 31.7, current 31.8, max 31.9
      Supply voltage: min 24.1, current 24.1, max 24.1, under voltage events: 0, over voltage events: 0, power good: yes
      12V rail voltage: min 12.0, current 12.2, max 12.6, under voltage events: 0
      Heap OK, handles allocated/used 99/5, heap memory allocated/used/recyclable 2048/188/40, gc cycles 0
      Events: 0 queued, 0 completed
      Driver 0: standstill, SG min n/a, mspos 200, reads 2920, writes 0 timeouts 0
      Driver 1: standstill, SG min n/a, mspos 808, reads 2919, writes 0 timeouts 0
      Driver 2: standstill, SG min n/a, mspos 744, reads 2919, writes 0 timeouts 0
      Driver 3: standstill, SG min n/a, mspos 584, reads 2919, writes 0 timeouts 0
      Driver 4: standstill, SG min n/a, mspos 584, reads 2920, writes 0 timeouts 0
      Driver 5: standstill, SG min n/a, mspos 4, reads 2920, writes 0 timeouts 0
      Date/time: 2024-01-04 17:51:14
      Slowest loop: 24.27ms; fastest: 0.06ms
      === Storage ===
      Free file entries: 20
      SD card 0 not detected, interface speed: 37.5MBytes/sec
      SD card longest read time 0.0ms, write time 0.0ms, max retries 0
      === Move ===
      DMs created 125, segments created 38, maxWait 3ms, bed compensation in use: mesh, height map offset -0.015, max steps late 0, ebfmin 0.00, ebfmax 0.00
      no step interrupt scheduled
      Moves shaped first try 78, on retry 4, too short 3, wrong shape 4601, maybepossible 0
      === DDARing 0 ===
      Scheduled moves 2252258, completed 2252233, hiccups 0, stepErrors 0, LaErrors 0, Underruns [0, 0, 0], CDDA state -1
      === DDARing 1 ===
      Scheduled moves 0, completed 0, hiccups 0, stepErrors 0, LaErrors 0, Underruns [0, 0, 0], CDDA state -1
      === Heat ===
      Bed heaters 0 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1, chamber heaters -1 -1 -1 -1, ordering errs 0
      === GCodes ===
      Movement locks held by null, null
      HTTP* is doing "M122" in state(s) 0
      Telnet is idle in state(s) 0
      File* is doing "G1 X560.140991 Y121.342003 E0.064190" in state(s) 0
      USB is idle in state(s) 0
      Aux is idle in state(s) 0
      Trigger* is idle in state(s) 0
      Queue is idle in state(s) 0
      LCD is idle in state(s) 0
      SBC is idle in state(s) 0
      Daemon* is idle in state(s) 0 0, running macro
      Aux2 is idle in state(s) 0
      Autopause is idle in state(s) 0
      File2* is idle in state(s) 0
      Queue2 is idle in state(s) 0
      Q0 segments left 0, axes/extruders owned 0x80000007
      Code queue 0 is empty
      Q1 segments left 0, axes/extruders owned 0x0000000
      Code queue 1 is empty
      === Filament sensors ===
      check 0 clear 41551178
      Extruder 0: pos 2160.00, errs: frame 0 parity 0 ovrun 0 pol 0 ovdue 0
      === CAN ===
      Messages queued 8, received 0, lost 0, errs 3722, boc 0
      Longest wait 0ms for reply type 0, peak Tx sync delay 0, free buffers 50 (min 50), ts 4/0/0
      Tx timeouts 0,0,4,0,0,4 last cancelled message type 30 dest 127
      === SBC interface ===
      Transfer state: 5, failed transfers: 0, checksum errors: 0
      RX/TX seq numbers: 63584/63584
      SPI underruns 0, overruns 0
      State: 5, disconnects: 0, timeouts: 0 total, 0 by SBC, IAP RAM available 0x258a4
      Buffer RX/TX: 2896/1136-4096, open files: 0
      

      after DCS restarted

      M122
      === Diagnostics ===
      RepRapFirmware for Duet 3 MB6HC version 3.5.0-rc.2 (2023-12-14 10:32:22) running on Duet 3 MB6HC v1.02 or later (SBC mode)
      Board ID: 08DJM-9P63L-DJ3T8-6JKD4-3SJ6K-9A77A
      Used output buffers: 1 of 40 (29 max)
      === RTOS ===
      Static ram: 154844
      Dynamic ram: 88272 of which 4072 recycled
      Never used RAM 95036, free system stack 119 words
      Tasks: SBC(2,ready,3.8%,404) HEAT(3,nWait,0.0%,324) Move(4,nWait,16.8%,213) CanReceiv(6,nWait,0.0%,942) CanSender(5,nWait,0.0%,334) CanClock(7,delaying,0.0%,342) TMC(4,nWait,6.9%,61) MAIN(2,running,72.4%,103) IDLE(0,ready,0.0%,30), total 100.0%
      Owned mutexes: HTTP(MAIN)
      === Platform ===
      Last reset 01:30:01 ago, cause: power up
      Last software reset at 2024-01-03 15:51, reason: OutOfMemory, Gcodes spinning, available RAM 428, slot 0
      Software reset code 0x41c3 HFSR 0x00000000 CFSR 0x00000000 ICSR 0x00435000 BFAR 0x00000000 SP 0x2041b9a0 Task MAIN Freestk 2054 ok
      Stack: 2041808c 00419f61 00000103 2043229c 2043c740 0044659f 00000003 00000000 0000007c 01000003 ffffffff 00000000 00000253 2041bccc 2042bb20 204251b0 204251b0 00471301 00000000 00497caf 0000000a 00000000 00000000 00000000 00000000 00000000 004aea70
      Error status: 0x00
      MCU temperature: min 31.6, current 32.1, max 32.3
      Supply voltage: min 24.0, current 24.1, max 24.2, under voltage events: 0, over voltage events: 0, power good: yes
      12V rail voltage: min 11.7, current 12.2, max 13.0, under voltage events: 0
      Heap OK, handles allocated/used 99/4, heap memory allocated/used/recyclable 2048/188/84, gc cycles 0
      Events: 0 queued, 0 completed
      Driver 0: standstill, SG min n/a, mspos 200, reads 58753, writes 0 timeouts 0
      Driver 1: standstill, SG min n/a, mspos 808, reads 58753, writes 0 timeouts 0
      Driver 2: standstill, SG min n/a, mspos 744, reads 58753, writes 0 timeouts 0
      Driver 3: standstill, SG min n/a, mspos 584, reads 58753, writes 0 timeouts 0
      Driver 4: standstill, SG min n/a, mspos 584, reads 58752, writes 0 timeouts 0
      Driver 5: standstill, SG min n/a, mspos 4, reads 58752, writes 0 timeouts 0
      Date/time: 2024-01-04 18:02:38
      Slowest loop: 34.87ms; fastest: 0.05ms
      === Storage ===
      Free file entries: 20
      SD card 0 not detected, interface speed: 37.5MBytes/sec
      SD card longest read time 0.0ms, write time 0.0ms, max retries 0
      === Move ===
      DMs created 125, segments created 38, maxWait 54ms, bed compensation in use: mesh, height map offset -0.015, max steps late 0, ebfmin 0.00, ebfmax 0.00
      no step interrupt scheduled
      Moves shaped first try 36298, on retry 13009, too short 24420, wrong shape 1424794, maybepossible 4988
      === DDARing 0 ===
      Scheduled moves 4235707, completed 4235707, hiccups 0, stepErrors 0, LaErrors 0, Underruns [0, 0, 0], CDDA state -1
      === DDARing 1 ===
      Scheduled moves 0, completed 0, hiccups 0, stepErrors 0, LaErrors 0, Underruns [0, 0, 0], CDDA state -1
      === Heat ===
      Bed heaters 0 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1, chamber heaters -1 -1 -1 -1, ordering errs 0
      === GCodes ===
      Movement locks held by null, null
      HTTP* is doing "M122" in state(s) 0
      Telnet is idle in state(s) 0
      File* is idle in state(s) 0
      USB is idle in state(s) 0
      Aux is idle in state(s) 0
      Trigger* is idle in state(s) 0
      Queue is idle in state(s) 0
      LCD is idle in state(s) 0
      SBC is idle in state(s) 0
      Daemon* is idle in state(s) 0 0, running macro
      Aux2 is idle in state(s) 0
      Autopause is idle in state(s) 0
      File2* is idle in state(s) 0
      Queue2 is idle in state(s) 0
      Q0 segments left 0, axes/extruders owned 0x80000003
      Code queue 0 is empty
      Q1 segments left 0, axes/extruders owned 0x0000000
      Code queue 1 is empty
      === Filament sensors ===
      check 0 clear 46345336
      Extruder 0: pos 2160.00, errs: frame 0 parity 0 ovrun 0 pol 0 ovdue 0
      === CAN ===
      Messages queued 6149, received 0, lost 0, errs 3242235, boc 0
      Longest wait 0ms for reply type 0, peak Tx sync delay 0, free buffers 50 (min 50), ts 3416/0/0
      Tx timeouts 0,0,3416,0,0,2733 last cancelled message type 4514 dest 127
      === SBC interface ===
      Transfer state: 5, failed transfers: 0, checksum errors: 0
      RX/TX seq numbers: 2616/2616
      SPI underruns 0, overruns 0
      State: 5, disconnects: 0, timeouts: 0 total, 0 by SBC, IAP RAM available 0x258a4
      Buffer RX/TX: 0/0-0, open files: 0
      === Duet Control Server ===
      Duet Control Server version 3.5.0-rc.2 (2023-12-18 12:42:49)
      Failed to deserialize the following properties:
      - MoveSegmentation -> Int32 from 2.0
      Daemon:
      >> Doing macro daemon.g, started by system
      Code buffer space: 4096
      Configured SPI speed: 8000000Hz, TfrRdy pin glitches: 0
      Full transfers per second: 198.67, max time between full transfers: 64.9ms, max pin wait times: 43.0ms/33.7ms
      Codes per second: 741.41
      Maximum length of RX/TX data transfers: 7392/3356
      

      1a3b9480-63c7-486d-9cd8-9edc56ceb2c7-grafik.png

      posted in DSF Development
      timschneiderundefined
      timschneider
    • RE: Reboots/crashes - RRF ≤3.5.0-rc1

      @dc42
      Hi david, I'm reading this thread as bystander. I asked myself if it is possible that the error occurs when the connection is interrupted but the socket is not closed and RRF is running in an timeout?

      Maybe I'm totally off, but as far as I know the RRF is opening an DMA channel to the WiFi/Network stack and the socket handling is done over there.

      What will happen if a client is sending a partially delayed http header like

      GET /rr_model?flags=d99fno HTTP/1.1\r\n
          Host: 192.168.10.x\r\n
          Connection: keep-alive\r\n
          X-Session-Key: 4102879531\r\n
          User-Agent: BBL-Slicer/v01.07.07.89 (dark) Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 Edg/107.0.1418.52\r\n
          Accept: */*\r\n
          Referer: http://192.168.10.x/\r\n
      <VERY LONG DELAY>
          Accept-Encoding: gzip, deflate\r\n
          Accept-Language: nb,no;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6\r\n
      \r\n
      

      The socket will stay open and later on run into an timeout, but the DMA channel is still open and partially written. The buffer gets freed (on stack), but the client or WiFi/Network stack keeps writing to that address via the opened DMA after the <very long delay>.

      Maybe the idea is totally off, then just ignore it.

      I was just thinking about another behaviour I observed when using DWC over an VPN tunnel, sometimes the RRF just stopped after I checked the status of the print and disconnected the VPN.

      Edit:

      • No timeout in the Network stack
      • Timeout in the RRF
      • Open DMA channel
      posted in Beta Firmware
      timschneiderundefined
      timschneider
    • RE: Indicate that a Command is added to the Movement Queue

      @droftarts
      the informations are now available in the docs.

      https://docs.duet3d.com/en/User_manual/Reference/Gcodes#command-queueing

      this thread can be marked as solved.

      posted in Documentation
      timschneiderundefined
      timschneider
    • RE: Movement after M112 E-Stop!

      @dc42 I was able to reproduce this behaviour with an brand new of the shelf 6XD WD32096 v1.01 firmware 3.4.6 reflashed to be sure. In standalone mode.

      Enable Jumper in active Enable.

      Following config.g

      ; Enable network
      M552 P0.0.0.0 S1
          
      ;CNC Mode
      M453                            ; Select CNC device mode
      M669 K0 S2 T1
      
      M569 R0 P0.4 S0 T3:3:6:0       ; physical drive 0.4 goes backwards
      M569 R0 P0.5 S0 T3:3:6:0       ; driver 5 requires an active high enable, 2.5us minimum step pulse, 2.5us minimum step interval, 5us DIR setup time and no hold time
      M569 R0 P0.3 S0 T3:3:6:0       ; driver 5 requires an active high enable, 2.5us minimum step pulse, 2.5us minimum step interval, 5us DIR setup time and no hold time
      
      M569 P0.0 S0 R0 T5:5:9:0       ; physical drive 0.0 goes backwards
      M569 P0.1 S1                    ; physical drive 0.1 goes forwards
      M569 P0.2 S1                    ; physical drive 0.2 goes forwards
      
      M584 X0.3 Y0.4:0.5 Z0.0             ; set drive mapping
      
      M92 X160.00 Y320.00 Z640.00     ; set steps per mm
      M566 X1800.00 Y180.00 Z120.00     ; set maximum instantaneous speed changes (mm/min)
      M203 X15000.00 Y12000.00 Z5000.00 I5  ; set maximum speeds (mm/min)
      M201 X400.00 Y200.00 Z200.00        ; set accelerations (mm/s^2)
      
      ;M564 H0                         ; Allow stepper movement before homing
      ; Axis Limits
      M208 X0 Y0 Z0 S1                ; set axis minima
      M208 X600 Y1200 Z170 S0         ; set axis maxima
      
      ;Machine Initialization
      M18                          ; disable all steppers
      M17                          ; enable z stepper so it doesn't fall
      

      test_movement.gcode

      G90
      G21
       
       
      G1 Y500 F4000
      G1 Y600 F4000
       
      G1 Y500 F4000
      G1 Y600 F4000
       
      G1 Y500 F4000
      G1 Y600 F4000
       
      G1 Y500 F4000
      G1 Y600 F4000
       
      G1 Y500 F4000
      G1 Y600 F4000
      

      M122
      Screenshot 2023-11-03 at 12-03-32 My Duet.png

      EmergencyStop pressed mid job via DWC

      Channel 1 (yellow) is STEP-
      Channel 2 (pink) is ENABLE-
      SDS00004.png

      there is a ENABLE low, when the Emergency Stop is pressed, then high again, then low, high, low again (low is off in this setup). I've tried it also the other was around with R1 - it just inverts the curve.

      The Setup:
      2023-11-03-12-03-03-888.jpg
      2023-11-03-12-03-08-248.jpg

      posted in CNC
      timschneiderundefined
      timschneider
    • RE: [bug] Error: in job file (channel File2) variable already exists

      @chrishamm thank you for checking it that fast, and I respectfully see your response, but the underlaying bug in it is not addressed.
      There is some initialize/reset bug in the dsf which is causing all kind of trouble, but this is a minimal working example on how to reproduce it very easy. You will come back to that bug later on, even if you do not see the bug now.

      In sbc mode, channel 0 and 2 are sometimes mixed up, which will lead to unexpected behaviour of the machine - even after a fresh hard reboot.

      the following execution order is not possible with normal behaviour.

      9a8720fc-194c-404d-817c-8d5321b72b6a-grafik.png

      another example
      9880b3c5-fb9b-48a8-a7e2-025903753a87-grafik.png
      g-code used to produce it

      content of 0:/gcodes/job-variable.gcode

      echo {state.thisInput}
      
      if {state.thisInput == 2}
        if {exists(global.TestVar1)}
          echo "before set: " ^ { global.TestVar1 }
          set global.TestVar1 = true
        else
          global TestVar1 = true
      
      
        echo global.TestVar1
      
      G4 S5
      
      if {state.thisInput == 2}
        M999
        ;M112
      

      content of 0:/sys/stop.g

      ; stop.g
      ; called when M0 (Stop) is run (e.g. when a print from SD card is cancelled)
      ;
      
      echo "0:/sys/stop.g"
      ;M98 P"0:/sys/meltingplot/print_end"
      

      if conditional gcode in job files is not supported, the machine should output an error message.

      posted in DSF Development
      timschneiderundefined
      timschneider
    • RE: Reboots/crashes - RRF ≤3.5.0-rc1

      @dc42
      I was looking at the code and found your ocmment about the failed assert.

      // Look at the response
      #if SAME5x	//TEMP DEBUG
      	CheckStackValue(9, ra);			//***** This is the check that occasionally fails ******
      #endif
      

      looking backwards from here it will reset the spi and disable the dma channel. There is a comment about the disabling of the dma channel on SAME5x.

      // Disable a channel. Also clears its status and disables its interrupts.
      // On the SAME5x it is sometimes impossible to disable a channel. So we now return true if disabling it succeeded, false it it is still enabled.
      bool DmacManager::DisableChannel(const uint8_t channel) noexcept
      {
      

      but the return value is not checked in the function:

      static inline void spi_rx_dma_disable() noexcept
      

      From here I've looked in the datasheet of the chip to check the dma function and found the following:
      83600302-3976-4571-9819-4324e39204d8-grafik.png

      So it is possible that a DMA transfer is already scheduled but not processed and this will block/prevent the gracefull disable from taking place.

      posted in Beta Firmware
      timschneiderundefined
      timschneider