moggieuk / Happy-Hare

MMU software driver for Klipper (ERCF, Tradrack, Box Turtle, Night Owl, Angry Beaver, 3MS, ...)
GNU General Public License v3.0
501 stars 126 forks source link

`_MMU_POST_LOAD` does not re-engage synced movement #178

Closed himanshugoel2797 closed 9 months ago

himanshugoel2797 commented 9 months ago

I call a purge macro as part of the post load routine:

[gcode_macro _MMU_POST_LOAD]
description: Optional post load routine for filament change
gcode:
    SAVE_GCODE_STATE NAME=MMU_POST_LOAD_state

    # A good place to implement custom purging logic and/or nozzle cleaning
    # Also move back to original saved position in _MMU_PRE_UNLOAD/_MMU_POST_FORM_TIP
    # Doing it hear rather than leaving it to Happy Hare ensures control
    # of movement and speed
    PURGE_NOZZLE
    _MMU_RESTORE_POSITION

    RESTORE_GCODE_STATE NAME=MMU_POST_LOAD_state

It just does:

[gcode_macro BRUSH_NOZZLE]
# heat nozzle for best results
variable_brushpos_x: -12
variable_brushpos_y: 37
variable_brushwidth: 0
variable_brushheight: 10
variable_z1: 2 #z value for pushing the nozzle into the brush
variable_safe_z: 40
gcode:
    M400  ;wait for buffer to clear
    {% if "xy" not in printer.toolhead.homed_axes %}
        G28         ;home axes before travel moves
    {% endif %}

    G90
    G1 X{brushpos_x} Y{brushpos_y} F5000  ;left position

    RESPOND MSG="Brushing Nozzle"
    G1 X{brushpos_x + brushwidth / 2} Y{brushpos_y + brushheight / 2} F5000
    G1 X{brushpos_x - brushwidth / 2} Y{brushpos_y - brushheight / 2} F2000
    G1 X{brushpos_x + brushwidth / 2} Y{brushpos_y + brushheight / 2} F2000
    G1 X{brushpos_x - brushwidth / 2} Y{brushpos_y - brushheight / 2} F2000
    G1 X{brushpos_x + brushwidth / 2} Y{brushpos_y + brushheight / 2} F2000
    RESPOND MSG="Nozzle Cleaned"

[gcode_macro PURGE_NOZZLE]
description: Purges filament into bucket
variable_purge_amount: 150
gcode:
    G1 X-12 Y65 F6000;move to bucket
    G1 E{purge_amount} F600
    BRUSH_NOZZLE

But the G1 E{purge_amount} isn't actually able to work, because the servo is engaged and the gear isn't moving, so the extruder is just grinding rather than purging the filament. I'm using the given custom MMU_LOAD_SEQUENCE for stallguard 'home to nozzle' if that might matter.

Looking in mmu.log, I see:

21:29:14 Unload of -729.2mm filament successful (encoder measured 719.0mm)
21:29:14 - - TRACE: Running macro: _MMU_ACTION_CHANGED ACTION='Idle' OLD_ACTION='Unloading'
21:29:14 - - TRACE: Running macro: _MMU_POST_UNLOAD
21:29:14 - DEBUG: Loading tool T0...
21:29:14 - - TRACE: Running macro: _MMU_PRE_LOAD
21:29:14 - DEBUG: Selecting tool T0 on gate #0...
21:29:14 - - TRACE: Running macro: _MMU_ACTION_CHANGED ACTION='Selecting' OLD_ACTION='Idle'
21:29:14 - DEBUG: Setting servo to move (filament hold) position at angle: 150
21:29:14 - - TRACE: Attempting selector 'touch' movement
21:29:15 - - TRACE: Truing selector 0.7mm to 0.0mm
21:29:15 - - TRACE: Setting gear motor rotation distance: 22.960040 (ratio: 1.000000)
21:29:15 - - TRACE: Running macro: _MMU_ACTION_CHANGED ACTION='Idle' OLD_ACTION='Selecting'
21:29:15 Tool T0 enabled
21:29:15 Loading filament...
21:29:15 - - TRACE: (toolhead sensor does not detect filament)
21:29:15 [T0] > En ......... [Ex .. (t) .. Nz] UNLOADED 0.0mm (e:0.0mm)
21:29:15 - - TRACE: Running macro: _MMU_ACTION_CHANGED ACTION='Loading' OLD_ACTION='Idle'
21:29:15 - DEBUG: Calling external user defined loading sequence macro
21:29:15 - - TRACE: Running macro: _MMU_LOAD_SEQUENCE FILAMENT_POS=0 LENGTH=615.9 FULL=1 HOME_EXTRUDER=0 SKIP_EXTRUDER=0 EXTRUDER_ONLY=0
21:29:15 - DEBUG: Setting servo to down (filament drive) position at angle: 80
21:29:18 - - TRACE: Initial load into encoder. Stepper: 'gear' moved 70.0mm, encoder measured 41.4mm (delta 28.6mm). Pos: @70.0, (41.4mm)
21:29:18 - - TRACE: (toolhead sensor does not detect filament)
21:29:18 [T0] > En >........ [Ex .. (t) .. Nz] 41.4mm (e:41.4mm)
21:29:18 - DEBUG: Loading bowden tube
21:29:21 - - TRACE: Course loading move into bowden. Stepper: 'gear' moved 574.5mm, encoder measured 574.5mm (delta -0.0mm). Pos: @615.9, (615.9mm)
21:29:21 - - TRACE: (toolhead sensor does not detect filament)
21:29:21 [T0] > En >>>>>>>>> [Ex .. (t) .. Nz] 615.9mm (e:615.9mm)
21:29:21 - DEBUG: Homing 'gear+extruder' motor to 'mmu_ext_touch' endstop, up to 100.0mm...
21:29:28 - - TRACE: User defined step homing move. Stepper: 'gear+extruder' homed after moving 98.0mm (of max 100.0mm), encoder measured 94.5mm (delta 3.6mm). Pos: @713.9, (710.4mm)
21:29:28 - - TRACE: (toolhead sensor detects filament)
21:29:28 [T0] > En >>>>>>>>> [Ex >> (*) >> Nz] LOADED 713.9mm (e:710.4mm)
21:29:28 Load of 713.9mm filament successful (encoder measured 710.4mm)
21:29:28 - - TRACE: Running macro: _MMU_ACTION_CHANGED ACTION='Idle' OLD_ACTION='Loading'
21:29:28 - - TRACE: Running macro: _MMU_POST_LOAD
21:29:44 MMU Last Print Statistics:
         3 swaps completed
         41 seconds spent loading (average: 13 seconds)
         39 seconds spent unloading (average: 13 seconds)
         0 seconds spent paused (total pauses: 0)

         Gate Statistics:
         #0: Good, #1: Great, #2: Marginal, #3: Perfect, #4: Perfect, #5: Perfect
21:29:46 - DEBUG: Syncing gear stepper and extruder
21:29:46 - - TRACE: Updated sync multiplier: 1.0000
21:29:46 - - TRACE: Setting gear motor rotation distance: 22.960040 (ratio: 1.000000)
21:29:46 Modifying MMU gear stepper run current to 50% for extruder syncing

the 'Syncing gear stepper and extruder' coming after 'Running macro: _MMU_POST_LOAD' makes me think that the sync is being disabled during the post load macro.

I'm thinking this is related to the home-to-nozzle functionality, I had initially encountered this error:

An issue with the MMU has been detected. Print paused.
Reason: Load sequence failed: Error running _MMU_LOAD_SEQUENCE: Valid motor names are 'gear', 'extruder', 'gear+extruder'.

To 'fix' this, I had changed the stepper from 'extruder+gear' to 'gear+extruder', looking into it further I realize that's not right, as 'extruder+gear' is supposed to be the equivalent of 'synced'. However, https://github.com/moggieuk/Happy-Hare/blob/a3a23c0e1acddf670475ef23a4a6c2d9123be22e/extras/mmu.py#L4592 shows that, as also indicated by the error message, 'synced' is not an option for homing moves.

So, which is the intended behavior here for the post load sequence?

  1. Manually enable syncing in the post load macro
  2. The servo should move to the 'up' position and the gear not used for the post load macro
  3. 'synced' added to the options for homing moves I see this is explicitly prevented at https://github.com/moggieuk/Happy-Hare/blob/a3a23c0e1acddf670475ef23a4a6c2d9123be22e/extras/mmu.py#L4360
  4. Something else

Similarly, how should the home-to-nozzle load sequence be changed to fix the current error regarding 'extruder+gear'?

moggieuk commented 9 months ago

Hi. Very detailed report, thank you! I know there was a bug that meant syncing was not restored when restarting print but I thought that was fixed and only effected a 24h period. It would be good to confirm that you are completely up-to-date first.

Each "step" of the unload/load process will alter the servo state based on needs and will perform a combination of synced and non-synced moves. The reason is (obviously) not all moves can be synced. Each "step" will correct the servo and sync based on needs and leave it in a non-deterministic state. Well, not strictly non-deterministic, but there isn't any attention paid to the state it is in on exit because the next "step" in the sequence will set appropriately.

FYI that all movement by the "steps" would be equivalent to MOTOR= extruder or gear or gear+extruder based on need. None are synced which is what would be used in a print.

To be clear: "extruder+gear" means your are sending movement to the extruder and the gear is following along. "gear+extruder" means you are driving the gear stepper rail and the extruder is temporarily placed on the same rail to follow the movement. The former is what is used in-print.

moggieuk commented 9 months ago

The "DEBUG: Syncing gear stepper and extruder" is the restoration of syncing by happy hair before the print resumes and thus after the _MMU_POST_LOAD. You are correct that ANY HH initiated move will disable the automatic syncing so all the "step" functions would do so.

The use of MMU_LOAD_SEQUENCE is another wrinkle that I haven't tried for a while, but really the default I ship is calling the same sequence of "steps" that are coded within Happy Hare so shouldn't make a difference

moggieuk commented 9 months ago

So to summerize. In MMU_POST_LOAD which is called after the load_extruder() "step" I'd expect the servo to be down because that last movements would have been synced moves by using the equivalent of "gear+extruder" movement. Thus to do some extruder driven movement in POST_LOAD, you would want to use "MOTOR=synced" Or you could move the servo up and use "MOTOR=extruder". But these are HH driven movement not general g-code.

You could also run MMU_SYNC_GEAR_MOTOR ... then just do extruder movement as you are in your example. This would reengage the gear to follow the extruder (as in a print). It will also take care of the servo position if necessary

It's arguable that extruder syncing should be re-enabled before these call out macros but I think that could/would lead to a lot of servo flutter. I think it is better that the user re-engages the syncing.

Let me know how it goes ... there aren't many folks doing creative things. Also when you get it all working let me know what additions I should make to the doc ..

himanshugoel2797 commented 9 months ago

Thanks for the very detailed response! I had been busy dealing with some other printer issues, so I hadn't been able to get around to checking things and responding.

I think I had updated after the 24-hour period you mentioned, so I don't think that's involved. My takeaway from your explanation is that this isn't a bug and it would be proper for me to just call MMU_SYNC_GEAR_MOTOR in the purge macro as needed. This is what I ended up doing, and with it, the purge macro is working as expected.

I think documentation wise, a simple purge macro example could be added somewhere to clarify that calls to MMU_SYNC_GEAR_MOTOR may be needed in gcode customization. I can look around the documentation and suggest a good place for it (or maybe it already is somewhere and I missed it, so I can verify that :P ).

I'm really enjoying tinkering around with all this more 'creative' functionality :)

This issue can probably be closed for now, I'll reopen and/or submit a pull request when I have something to add regarding documentation.