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

"Virtual Axis" break stall detection?

Scheduled Pinned Locked Moved
Gcode meta commands
3
6
356
Loading More Posts
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • undefined
    garethky
    last edited by garethky 1 Mar 2021, 03:06 3 Jan 2021, 03:06

    People in this category have hinted that you can define an axis that you are not using and then hijack its offset to store a floating point number per-tool for use in expressions. The axis has to have limits define, it cant be hidden and needs to be homed. So, easy enough:

    M584 A ; Use the 'A' axis
    M208 A0:400 ; define travel limits from 0 to 400
    G92 A0 ; home it

    Then you can assign 'A' a value per-tool using its G10 offset:

    G10 P{state.currentTool} A240
    

    And wherever you need that value you can read it out of the current tool (assuming that A was the 5th axis to get defined):

    M109 S{tools[state.currentTool].offsets[4]}
    

    So the above works, but when I home my Core X/Y machine it refuses to detect a stall in the X axis! Y stall detect works just fine. Stall detection worked before I added the axis. Same motors and settings, nothing changed. 😲

    So I wondered if maybe I had to assign a drive to the axis and tried this:

    M584 A6              ; Use the 'A' axis
    

    Drive 6 does not exist, so I get an error in the console:

    Error: M584: Driver 0.6 does not exist

    Fair enough, but when I home the machine anyway everything is fine, just as it was before I added the axis. 😬 😏

    So I have no idea whats going on. The console error shows up in 3.2_RC2 but not 3.1.1. The stall detection failure happens on both versions if no drive number is given. Feels like a bug but I know I'm doing something pretty far outside the box. Anyone else run into this?

    (Duet 3, Pi SBC attached, 1 expansion board, running 3.2_RC2. E3D Tool Changer motion system.)

    1 Reply Last reply Reply Quote 0
    • undefined
      jay_s_uk
      last edited by 3 Jan 2021, 08:53

      You don't need to create another axis to store numbers.
      Use the workplace coordinates to store values. In 3d printing we only use the first one so there's another 8 sets of coordinates, one for each axis that can be used. Look at G54 to G59.3

      Owns various duet boards and is the main wiki maintainer for the Teamgloomy LPC/STM32 port of RRF. Assume I'm running whatever the latest beta/stable build is

      undefined 1 Reply Last reply 4 Jan 2021, 03:44 Reply Quote 1
      • undefined
        dc42 administrators
        last edited by 3 Jan 2021, 10:30

        My original suggestion was to use the G10 offsets of dummy tools, not extra axes.

        Duet WiFi hardware designer and firmware engineer
        Please do not ask me for Duet support via PM or email, use the forum
        http://www.escher3d.com, https://miscsolutions.wordpress.com

        undefined 1 Reply Last reply 4 Jan 2021, 03:04 Reply Quote 0
        • undefined
          garethky @dc42
          last edited by 4 Jan 2021, 03:04

          @dc42

          So the thing I'm trying to simulate is a variable that can be looked up by the tool's index. When we get variables I'm expecting to do something like this:

          var global.toolOffsetX = [302, 68, 125, 197]
          var global.toolOffsetY = [300, 301.0, 300.54, 300.3]

          then use a tool number to look that up:

          ; move to final docking position
          G1 X{global.toolOffsetX[state.currentTool]} Y {global.toolOffsetY[state.currentTool]} F{global.dockingSpeed}

          Until that day arrives its hacks all the time 😼

          I want to store this info for each tool:

          • Filament temp for loading/unloading and printing Z-calibration test patterns
          • Extrude speed for the filament for the above reasons.
          • Nozzle diameter for printing Z-calibration test patterns (to correct the flow rate) and checking that a prints expected nozzle diameter matches the one installed
          • Each tools X, Y and offsets in machine coordinates for docking

          So long as the above is going to work I don't really care how broken this is right now so long as I don't damage anything. I'm investigating the workplace coordinate options as a less hacky alternative.

          1 Reply Last reply Reply Quote 0
          • undefined
            garethky @jay_s_uk
            last edited by garethky 1 Apr 2021, 03:49 4 Jan 2021, 03:44

            @jay_s_uk Thank you for the suggestion!

            For my machine I think this will work, I have 4 tools and 4 axes, what are the odds? 😁

            Sorry if I'm being very pedantic beyond this point, I'm documenting how it works for the next person that wants to try it out:

            To make accessing the values easy I'm storing all of a tool's properties in a single axis, so X=Tool 0, Y=Tool 1, Z=Tool 2 and C=Tool 3. Lets say I want to record the nozzle diameter for each tool, that would looks like this:

            ; store tool nozzle diameters in coordinate system 5
            G10 L2 P5 X0.4 Y0.6 Z0.4 C0.8

            Then the object model makes retrieving the values by tool painless because the axes are in an array:

            echo "Current tool nozzle diameter is: ", {move.axes[state.currentTool].workplaceOffsets[4]}, "mm"
            

            You get from G10 L2 P2 to G10 L2 P9 to store stuff in, enough for 8 per-tool properties. G10 L2 P1 is G54 so that's already in use.

            For me its a drop in replacement for the axis hack and likely to be supported long term. If your machine has more tools than axes this wouldn't work out quite as well for you.

            1 Reply Last reply Reply Quote 1
            • undefined
              garethky
              last edited by 4 Jan 2021, 23:18

              This is really turning out to be the right answer. One of the benefits of using the work offsets is that they are one of the few things that can be stored with M500!

              (I thought I could store things from the object model by exploiting M28/M29. But no expressions between those commands gets evaluated, so you can't store the result of an expression.)

              So I explained above how to store things by writing gcode to a file you run on startup. But what if you want to store something in the work offsets during operation of the printer? You have a tool number, say 2, and you need to write a gcode expression with an axis letter, G10 L2 P5 Z.... How do you get that Z?

              Well, you can write an if block to do that but that code is pretty long and you wouldn't want that cluttering up your all your macros. So I wrapped that up into macro itself so I can re-use it everywhere I need to store something. The trick is we don't have a way to pass variables into macros yet. So I just write the tool #, value to store and desired coordinate system index into coordinate system #9. Basically coordinate system #9 is now the stack for my program:

              ; copy_var.g
              ;
              ; this macro copies a variable from the temporary variable slot and stores it in the requested slot for the specified tool:
              ;
              ; How To use:
              ;
              ; G10 L2 P9 X{state.currentTool} Y{value_to_store} Z{target_coordinate_system_index}
              ; M98 P"/macros/scripts/copy_var.g"
              ;
              ; Inputs:
              ;
              ; move.axes[0].workplaceOffsets[8] - tool number to store the value for
              ; move.axes[1].workplaceOffsets[8] - the value to store
              ; move.axes[2].workplaceOffsets[8] - the coordinate system number to store it in
              if move.axes[0].workplaceOffsets[8] == 0
              G10 L2 P{floor(move.axes[2].workplaceOffsets[8])} X{move.axes[1].workplaceOffsets[8]}
              elif move.axes[0].workplaceOffsets[8] == 1
              G10 L2 P{floor(move.axes[2].workplaceOffsets[8])} Y{move.axes[1].workplaceOffsets[8]}
              elif move.axes[0].workplaceOffsets[8] == 2
              G10 L2 P{floor(move.axes[2].workplaceOffsets[8])} Z{move.axes[1].workplaceOffsets[8]}
              elif move.axes[0].workplaceOffsets[8] == 3
              G10 L2 P{floor(move.axes[2].workplaceOffsets[8])} C{move.axes[1].workplaceOffsets[8]}
              else
              abort ; if you pass -1 you call at the wrong time!

              Now that is solved I can combine it with M500 and I give you per-tool baby stepping adjustment that persists between reboots:

              call this in tfreeN.g

              ; save_babystep.g
              ; writes the baby stepping value into the work offset 7 and then stores it with M500
              G10 L2 P9 X{state.currentTool} Y{move.axes[2].babystep} Z6
              M98 P"/macros/scripts/copy_var.g"
              M500

              and call this in tpostN.g

              ; restore_babystep.g
              ; restore the absolute babystepping value from its storage slot
              M290 R0 S{move.axes[state.currentTool].workplaceOffsets[5]}

              Then call M501 at startup before you write any config values as described in the post above.

              alt text

              😸 🍻

              1 Reply Last reply Reply Quote 1
              5 out of 6
              • First post
                5/6
                Last post
              Unless otherwise noted, all forum content is licensed under CC-BY-SA