Duet3D Logo Duet3D
    • Tags
    • Documentation
    • Order
    • Register
    • Login
    1. Home
    2. NineMile
    • Profile
    • Following 0
    • Followers 1
    • Topics 20
    • Posts 87
    • Best 28
    • Controversial 0
    • Groups 0

    NineMile

    @NineMile

    62
    Reputation
    13
    Profile views
    87
    Posts
    1
    Followers
    0
    Following
    Joined Last Online
    Website github.com/millenniummachines

    NineMile Unfollow Follow

    Best posts made by NineMile

    • MillenniumOS - A CNC "Operations System" for RRF 3.5+

      Circular-Bore_%05d.webp

      I thought I'd share something that I've been working on for a while (since October 😓) and made public earlier today - MillenniumOS, which is an "Operations System" for RRF 3.5+.

      There's further documentation for the system, and the operations it implements, on our (Millennium Machines) documentation site, and I made a video a while back (while developing it!) of how the system works in practice - I'll be making more of these now that the repository is public including example videos of each probing operation.

      MillenniumOS is a combination of 3 things:

      • A G-Code dialect
      • An RRF addon consisting of a set of custom G- and M- codes and system macros (tool change, pause, resume etc) that implement the gcode dialect and
      • Post-processors for Fusion360 and FreeCAD (Realthunder branch until FreeCAD releases a version packaging Python 3.11)

      This addon implements a bunch of CNC features designed to allow novice operators to approach their first cuts more safely and in a guided fashion, including:

      • Guided workpiece probing (Bore - shown above, Boss, Rectangle Block, Rectangle Pocket, Outside Corner, Vise Corner, Single Surface) using both a touch probe and manually with a datum tool. Includes touch probe deflection and radius compensation as well as datum tool radius compensation.
      • Protected moves when using a touchprobe so during travel moves, the machine will stop if an unexpected collision was detected.
      • Workpiece rotation calculation on certain probe cycle types which will be used in future to apply G68 transformations.
      • Tool changes with tool length compensation using a toolsetter, or re-triggering a z-probe on the workpiece if no toolsetter is enabled.
      • Parking in Z and optionally X/Y for easy access to the table.
      • Pause and resume with spindle control and delay.
      • Variable Spindle Speed Control, which adjusts the spindle RPM up and down within a range to avoid resonance between the tool and workpiece.
      • Configuration is handled using a Wizard process that runs on first-install, guiding operators through the process using RRF dialogs. Includes a guided procedure to measure touch probe deflection.
      • Probing cycles gather information required using RRF dialogs as well.

      The base design choice of this system is that all complex functionality is implemented as RRF meta gcode - there are some great post-processors for RRF but these all seem to take the approach of implementing rather complex functionality in the post-processor itself, rather than doing this directly in meta gcode.

      One of the benefits of taking the MillenniumOS approach is that the post-processors are relatively simple, and implementing wider post-processor support to target this gcode dialect is much quicker than re-implementing all of the functionality in a new post-processor to support a different CAM package.

      One thing I wanted to do with this was to make manual probing easier / safer. Not everyone has a toolsetter and touch probe, but the maths to calculate probing points and origins is the same whether using a touch probe or not - so MillenniumOS can guide the operator through manual probing in exactly the same way it would use a touch probe.

      The probing macro is actually the same, but runs different underlying macros to trigger either a touch probe move or a M291-dialog-driven manual move. This avoids the RRF jog window as much as possible as I've found it too easy to hit the wrong button - the manual probing will only ever move directly towards or away from the surface that needs to be probed - it won't accidentally move up or down, or along the wrong axis.

      You can see an example of how the probing cycles are the same between touch probe and manual probing in this video, and one of the early testers made a video of running through the installation and machining using the MillenniumOS post-processors and macros here!

      This addon is designed to work with our (Millennium Machines) open-design desktop CNC mill, the Milo, but it should work with any machine that has the axes configured in the same direction (i.e. Moving tables with Y max when the table is at the front, X max when the table is at the left, and Z min when the spindle is at its' lowest point). I'd be interested to hear from anyone who decides to try and use this on a machine that isn't the Milo.

      On machines that don't have the axes in the right direction (X and Y only, Z minimum must be the lowest spindle position), then certain settings like corner names or surface names will need to be changed as these would be back to front depending on which directions your axes move.

      I've found while developing this that I have been pushing the capabilities of RRF and some of the boards we've been testing on (specifically the stm32f407) so this has been a really fun project and a bunch of the Duet and Teamgloomy guys have been a great help in tracking down a bunch of issues, so if you guys are reading this thank you so much for your help - this is why I was coming up with all sorts of random questions and issues and everything else.

      My goal has been to reduce the learning curve for those just getting started with machining and hopefully what I've developed here helps with that - this is only a first public release and I'm hoping I'll be able to continue working on this more in future!

      posted in CNC
      NineMileundefined
      NineMile
    • RE: MillenniumOS - A CNC "Operations System" for RRF 3.5+

      I'm currently working towards v0.5.0 of MillenniumOS, which brings some pretty big changes along with it.

      I'm overhauling the probing system to more effectively account for probing surfaces that aren't aligned to the machine axes - this can help make G68 rotation compensation based off corner or rectangle block probes more accurate, due to the way that probe deflection changes when probing an unaligned surface. There's a video here covering it.

      The above video also covers protected probe moves, which I have implemented as part of a new MillenniumOS-UI plugin to Duet Web Control. The idea of this plugin is to expose the functionality of the MillenniumOS macros in an easier to use fashion, allowing operators to drive the probing macros directly via the DWC web interface rather than using the current dialog-driven system. It also changes the layout of the machine information shown at the top of DWC so it's a little bit more CNC focused. Here's some images of the current probing design:

      Select probe cycle

      mosui_select_cycle.png

      Configure chosen cycle

      mosui_configure_cycle.png

      Jog to position (currently the same interface as on the dashboard)

      mosui_jog_position.png

      Probe status once started

      mosui_probe_status.png

      I've been working on the probing interface for a little bit, but only enabled it to run probing cycles last week - demoing it live at SMRRF for the first time with the new Milo V2.0 we had there 😅 - luckily no broken probes or major issues and got some great feedback as well.

      There's also a couple of new features in the plugin, including a WCS Origins window on the right hand side that lets you type offsets into each WCS and tab between them - this is useful if you're not using a touch probe and just want to be able to set origins by hand.

      This new code is relying on some features from RRF v3.6 so won't be released before then, but thought an update was warranted as people have already seen this system in the wild.

      posted in CNC
      NineMileundefined
      NineMile
    • RE: Modbus Spindle Control

      Just wanted to update to say I've been using daemon.g to control my VFD over modbus for a while now and it feels like it's working well. The error messages not being suppressed when writing to a variable is a bit of a pain but aside from that, it feels like a relatively robust way to do it.

      For clarity, I still have the spindle configured to use enable / direction / PWM pins but these are not connected. I read the spindle state in daemon.g and send the relevant Modbus requests to start it and control the speed.

      I've had a 2 second comms timeout set on the VFD so if there's no Modbus status check within 2 seconds the VFD will stop automatically.

      There's a lot of functionality I could add to this to e-stop / pause / whatever if the VFD reports the spindle stopped or at high load or is completely unresponsive, but for the moment I'm pretty happy with the behaviour.

      posted in CNC
      NineMileundefined
      NineMile
    • RE: Modbus Spindle Control

      @dc42 Just wanted to confirm, someone on the RatRig discord has used M260.4 to communicate with a Huanyang HY02D223B which was one of those VFD's that looks like Modbus but implements its own command model.

      We compiled control examples for daemon.g for the Shihlin SL3 VFD and the Huanyang HY02 on this gist if anyone is interested.

      posted in CNC
      NineMileundefined
      NineMile
    • Return Values from Macros

      One of the features that I think would make RRF meta gcode more obviously powerful is an inbuilt way to return values from macros back to where they're called.

      At the moment this is possible using global variables, but requires writing handler code into every calling and called macro to handle those global vars, and if you don't use the same variable name(s) across all macros you can end up polluting the global namespace quite quickly (with the associated memory implications).

      I had a quick look this morning to see whether it would be possible to extend the M99 call so that it can pass values back to the caller, similar to how acknowledging an M291 dialog can put values back into the input variable, and I ended up with something that works like this:

      G901.g:

      ; Run child macro
      G902
      echo { "Returned Value: " ^ retval }
      

      G902.g:

      var testval = 902
      while { iterations < 5 }
          set var.testval = var.testval + iterations
      
      M99 R{ "Test", var.testval }
      

      M98 P"G901.g" prints the output Returned Value: {Test,912}.

      Is this something that has legs to be added to RRF itself?

      Has this been thought about already and rejected for reasons I'm unaware of? Would be grateful to hear any input on this front 🙂

      posted in Firmware developers
      NineMileundefined
      NineMile
    • RE: Protected Moves with a Touch Probe

      Implemented limit checks and machine position calculation so the moves work properly, this is how it works in practice: video

      posted in Duet Web Control
      NineMileundefined
      NineMile
    • Abort tool changes

      I'm using a particular tool number (T49) to identify a touch probe (for CNC purposes). Part of the tool change process (in tpre.g) is to detect the touch probe is plugged into the machine (because a lot of Aliexpress touch probes are normally open, it makes sense to confirm the touch probe is plugged in before potentially ramming it into the machine).

      I have a macro that looks for a status change on the touch probe in tpre.g, and runs abort {} when the touch probe is not detected. This successfully exits out of tpre.g but tpost.g is still executed, and the tool number is still successfully changed to T49. I've tried using M99 instead (same behaviour as abort {}) and running T-1 P0 inside the tool change macros themselves, but it doesn't seem possible right now to fully abort a tool change.

      I think it would be a useful safety feature, particularly for CNC purposes, to allow tool changes to be aborted - that way it would allow the currently selected tool number to act as a 'guard' - for example macros that need a touch probe check if the current tool number is the probe tool, and exit if not. In the current situation, the tool number is changed regardless of whether the tpre.g or tpost.g were aborted or not.

      E: I should probably add, this is likely safe inside a running gcode file because the abort{} will successfully cancel the "print" - but it still leaves T49 active even after the print is finished.

      posted in Firmware wishlist
      NineMileundefined
      NineMile
    • RE: MQL System with Diesel Heater Pump

      @gloomyandy said in MQL System with Diesel Heater Pump:

      @NineMile Have you tried doing 1-5Hz just using M950?

      I have a basic implementation of this now that uses M950 for anything equal to or over 1Hz, and then for anything lower I use daemon.g to run the on/off cycle, which seems to work nicely.

      posted in CNC
      NineMileundefined
      NineMile
    • RE: Meta gcode result variable inconsistent with docs

      @dc42 I've been looking at implementing this and I have the J2 functionality working as described - however this also means that a J2 message box that times out will also return -1 (as well as if the user clicks Cancel).

      I think this is the right behaviour, as in both cases it essentially means 'user did not supply a valid input', but I'd like to confirm that this is what you'd expect to happen as well.

      I've tested on my stm32 based board and it works well - I have a Mini 5+ here that I'll test on once I get the build repo working. Happy to submit a PR for this if you'd like to look at the approach I've taken and verify I'm on the right track 🙂

      posted in Documentation
      NineMileundefined
      NineMile
    • Protected Moves with a Touch Probe

      @chrishamm A feature I've had in MillenniumOS (probing macro package for RRF, for use with touch probes on CNC machines) is protected moves.

      The concept is pretty simple, rather than using G1 to move to calculated positions around the workpiece, every travel move is actually a probing move (using G38.3) as well - so if the touch probe hits something unexpected, like a clamp or vise then the move will stop instantly and mostly avoid any damage.

      However - we still use the DWC MovementPanel and Dialog Boxes for jogging to the probe starting location, which leaves a big 'unprotected' gap as these features only ever send a G1 command.

      I actually damaged my first probe by missing a Y- jog button and hitting the Z-25 button instead.

      I'd like to implement protected movements in DWC when in CNC mode, and I think this would take either 1 or 2 settings - a probe ID selector to pick the probe to watch during moves, and potentially a toggle to enable or disable protected moves (this could be done as 1 input where the probe ID is set to -1 if protected moves are disabled).

      Given that touch probes can be installed / removed, I think it's necessary to have the option to enable / disable protected moves via the movement panel and / or jog buttons in the dialog window directly, rather than it being in the machine settings page or something like that.

      I'm happy to implement this and submit it as a PR, but I'd like to know if:

      1. Would this be something you'd likely accept as a new feature to DWC?
      2. Do you have any particular feelings about where these settings should go, or any thoughts on how this behaviour should function?

      cc @jay_s_uk

      posted in Duet Web Control
      NineMileundefined
      NineMile

    Latest posts made by NineMile

    • RE: Modbus CNC Spindle Control (3.6 RC2) Shihlin SL3

      @Firky_CNC said in Modbus CNC Spindle Control (3.6 RC2) Shihlin SL3:

      Just an update to say, using the MillenniumMachines ArborCTL release 0.0.5, I am able to control a SL3 VFD using the RJ45 connector using a TLL to RS845 converter connected to UART (OI_1) on the mini 5+

      Unable to post a link. But it is on GitHub.

      https://github.com/MillenniumMachines/ArborCTL/releases/tag/v0.0.5

      <- Author

      It's a RRF addon written in a similar vein to MillenniumOS, the idea is to provide a framework around which Modbus spindle control implementations can be written for particular VFD types.

      Currently it configures and runs the Shihlin SL3 and has untested support for the HY02 VFDs. It is alpha quality so if you do use it, be careful and it is at your own risk.

      Help supporting more VFD types appreciated.

      posted in CNC
      NineMileundefined
      NineMile
    • RE: What useful things have you printed on a 3D printer?

      I 3D printed a motorcycle crank puller and a tool for installing gearbox lock rings when I was rebuilding my motorbike engine.

      I also used it to produce prototypes of an axial to radial caliper adapter to fit a radial motorcycle brake to my axial forks, before having the real bracket machined locally.

      Now it gets used to make parts and develop new machines for the Millennium Machines team.

      posted in General Discussion
      NineMileundefined
      NineMile
    • RE: Modbus Spindle Control

      @dc42 Just wanted to confirm, someone on the RatRig discord has used M260.4 to communicate with a Huanyang HY02D223B which was one of those VFD's that looks like Modbus but implements its own command model.

      We compiled control examples for daemon.g for the Shihlin SL3 VFD and the Huanyang HY02 on this gist if anyone is interested.

      posted in CNC
      NineMileundefined
      NineMile
    • RE: DSF Failed to serialize code

      @chrishamm said in DSF Failed to serialize code:

      @NineMile I think the messages from M291 are too long, so DSF cannot send them to RRF. The maximum length of a G-code is 256 bytes, which is exceeded by your logic, and depending on the number of parameters it's a bit lower in SBC mode due to the way G-codes are transferred. If you reduce the message length, it should work again.

      I'm going to change the error message in v3.6 to be more specfic.

      Gotcha, thanks for the clarification. It has definitely been fun trying to fit the M291 dialog contents into 256 bytes so yes, some of these could be right up against the limit (I know I pushed some over by adding the J2 parameter on some dialogs while testing with v3.6.

      I'll take another look at dialog lengths and see where these need to be sorted out.

      Thanks again 👍

      posted in DSF Development
      NineMileundefined
      NineMile
    • DSF Failed to serialize code

      Hi @chrishamm

      I had a user try to run the MillenniumOS config wizard yesterday on a new SBC setup of RRF 3.5.4 on a BTT Kraken board, and they received the following errors:

      1000039304.jpg

      I've not seen this before on a standalone setup, and this may well be the first person to try using SBC mode with MillenniumOS as I personally don't have an SBC setup to test with.

      We managed to narrow it down to MillenniumOS usage of html codes within the M291 dialog commands, the file being run to cause these errors is here: https://github.com/MillenniumMachines/MillenniumOS/blob/main/macro%2Fmovement%2FG8000.g

      I'm aware that this is problematic if used on something not-a-browser but MillenniumOS was always designed with browser usage in mind, and has been using HTML styling in dialog boxes since very early in development to make some of the information clearer.

      Do you think this is something that can be fixed? I assume special characters are limited for some reason but I have no context as to why that would be the case in DSF and not in standalone mode.

      1000039305.png

      posted in DSF Development
      NineMileundefined
      NineMile
    • RE: Trouble with a if statement decision tree using M291 K

      @Macgyver said in Trouble with a if statement decision tree using M291 K:

      set var.secondary_head = input("Enter your choice (1-4): ")

      Another thing that jumps out here is that input is a variable, not a function - with S4 when the message box returns, input is set to the index of the value you selected, so:

      M291 R"Choose Print Head" S4 K{"GS","GHF","GUF","GHR"}
      set var.secondary_head = { input }
      

      would result in the secondary head being set to 1 if you clicked GHF

      posted in Gcode meta commands
      NineMileundefined
      NineMile
    • RE: Macro return oddities

      @chrishamm sorry for all the questions but maybe you know the answer to this one too:

      I'm trying to do the following, which runs a Modbus discovery command on a set number of addresses. The idea is to loop within meta gcode, because if the M260.4 command is called directly by await this.sendCode() then the response variable is defined at top level and then exists for the lifetime of the HTTP gcode buffer.

      // Use a RRF meta gcode loop, so we can use the same response variable for M260.4
                      
                      await this.sendCode(`
                          if { !exists(global.modbusResult) }
                              global modbusResult = { null }
                      
                          set global.modbusResult = { vector(${this.maxAddressesPerDiscovery}, null) }
                      
                          while { iterations < ${this.maxAddressesPerDiscovery} }
                              G4 P100
                              M260.4 P${this.selectedPort} A{${this.addressStart} + iterations} B{0x08,0x00,0x00,0xBE,0xEF} R5 V"modbusResponse"
                              set global.modbusResult[iterations] = { var.modbusResponse }
                      `);
                      
                      const modbusResult = store.state.machine.model.global.get("modbusResult");
                      
      

      If I trigger the above code, I get an error that looks like the lines aren't formatted properly.

      dwc_error.png

      What's the correct way to send code like this with conditionals from DWC? Is there one? I think I've seen other plugins create a macro file temporarily and then execute it using M98 but that seems like a rather roundabout way to execute macro code directly.

      posted in Duet Web Control
      NineMileundefined
      NineMile
    • RE: Macro return oddities

      @NineMile said in Macro return oddities:

      So if I were to remove the echoed output from the macros (it's actually less important if I can load probing data directly into DWC) then it should work?

      Update: This does work, if the macros don't output any information via echo {} then the UI waits correctly for the command to run. Thanks @chrishamm 👍

      posted in Duet Web Control
      NineMileundefined
      NineMile
    • RE: MillenniumOS - A CNC "Operations System" for RRF 3.5+

      @audryhome said in MillenniumOS - A CNC "Operations System" for RRF 3.5+:

      @NineMile I have seen this thread , did not find him again , however this was in a corner of my memory for a while.
      I am refurbishing a Roland CAMM 3 trying to keep the control panel with 3 separate x y z jogs.

      Will test happily your work as soon the old panel is connected to the Duet6HC through a custom made board I am working on.

      Excellent - Feel free to message if you need help with configuration - depending on the machine configuration you might need some custom configuration to make sure the probing directions are correct. For what it's worth v0.5.0 won't be out for a while as it's a pretty big change to the existing codebase.

      posted in CNC
      NineMileundefined
      NineMile
    • RE: Modbus Spindle Control

      @dc42 said in Modbus Spindle Control:

      @audryhome @NineMile does anyone actually use M568 to control the spindle?

      I do 🙂

      I use it to vary the RPM set by M3 or M4 from daemon.g, to implement variable spindle speed. It adjusts the spindle RPM over a set period between a high and low point, to avoid potential resonance conditions between the tool and workpiece.

      I would say M568 isn't an issue though - it could be overridden in the same manner as M3, M4 or M5.

      This isn't as clear cut with Tool::Activate() and Tool::Standby() as it appears that they can be called outside of a GCodeBuffer context (see: MovementState::SelectTool / GCodes::SelectPrimaryTool)

      @dc42 said in Modbus Spindle Control:

      However, there is still a need to turn the spindle off and on during pause/resume. So perhaps it would be better to define one or more standard macros to control spindles and have them invoked by M3/4/5/568.

      Yes, agree. I think named macros for start / stop / rpm would work well. I'd prefer spindle details to be passed by parameter rather than part of the macro filename though.

      posted in CNC
      NineMileundefined
      NineMile