Wednesday 16 December 2020

Tom Paterson's add-in for Fusion 360 post processing - FIXED

Still haven't figured out the root cause of the issues with Tim's post processor add-in. This requires some investigation.

The reply on his Github page gives some idea where the problem lies but certainly doesn't fix it. I need to do some digging of my own here.

There is clearly something causing G91 relative to be left on when his add-in creates a combined file containing several toolpaths.

Here's a typical section of g-code generated by the Fusion post processor before the shackles were put on the Free version. It covers the changeover between one section (and tool) and the next:

....
N225 G28 G91 Z0.  >>> Return to home height. G91 is the safest way to do this*...
N230 G90               >>> ...but it is critical to issue G90 to ensure return to absolute
(7003 Drill 7mm)
N235 M9                 >>> Coolant off
N240 M1                 >>> M1 Optional program stop - if activated in the controller
N245 T4 M6             >>> M6 Tool change
N250 T2
N255 S3500 M3       >>> Spindle start CW
N260 G54
N265 M8                 >>> Coolant back on
N275 G0 X117.2 Y50.85
N280 G43 Z10. H4   >>> Set tool length offset
N290 Z5.
....

*G28 G91 Z0 is not intuitive. You need to understand how G28 works - and it's not the way it looks - "why would you ask for a relative move of zero?" Well actually, with this approach the "intermediate point" used by G28 is the same as the initial position, no matter where that happens to be. The only alternative way to define an "intermediate point" G28 G90 X* Y* Z0 would require you to know and state the current tool position in X & Y, which isn't always possible or convenient.

The problem is that the "Free" restrictions prevent tool changes between operations within the same file. So instead, Tim Paterson's workaround generates g-code for each individual section, then comes back and stitches them together. The problem seems to be that we are ending up with the program ending block at the end of each section. 

Here's a typical end of program, with the home move highlighted:

....
N1515 X5.507 Y6.526 Z-18.739
N1520 X5.486 Y6.527 Z-18.621
N1525 X5.478 Z-18.5
N1530 Z15. F1500.
N1540 G28 G91 Z0.
N1545 M30
%

As each of those newly stitched together sections now includes an instance of the G28 G91 Z0 home sequence (without the G90!!), each following section is entered with G91 still active. That's rather unhelpful, as all the subsequent coordinates values are executed in G91 relative mode whereas they should be in G90 absolute mode. Doh. So instead of moving from one absolute coordinate to the next absolute coordinate, it executes them as relative moves. Not good.

Some useful and highly relevant info on cncsw's post processor info This is really insightful. Here's the interesting section in the context of this investigation:

Automatic Tool Changers

No post processor changes are strictly necessary in order to support machines with automatic tool changers. Just use M6 and a T code to change tools, as always.

On a machine with manual tool changing, the control will move Z home, stop the spindle and coolant, display a prompt ("Insert tool and press Cycle Start"), and wait for the Cycle Start key.

On a machine with automatic tool changing, the control will do whatever is required by the tool changer, as directed by its PLC and macro programming.

So perhaps the "N245 T4 M6" line (highlighted in red in the top example) may suffice on its own to achieve the tool change. But of course I would still need a program end section.

I think I may create a short dummy g-code file and experiment to see if the G28 is required for tool change (doesn't seem so) and if the Swissi post processor will allow me to include the G28 line as the program end block. Failing that, I could edit the post processor to generate what I need.

This works - edit the post processor to remove / suppress the "G28 G91 Z0" and insert an M25 instead:

function onClose() {

  onCommand(COMMAND_COOLANT_OFF);
  writeBlock(mFormat.format(25)); // go to Z home
  zOutput.reset();
  setWorkPlane(new Vector(0, 0, 0)); // reset working plane
  onImpliedCommand(COMMAND_END);
  onImpliedCommand(COMMAND_STOP_SPINDLE);
  writeBlock(mFormat.format(30)); // stop program, spindle stop, coolant off
  writeln("%");
}

This works nicely and here's an example of what we get:
...
N21590 X141.293 Y-22.114 Z-1.557
N21595 X141.3 Y-22.11 Z-1.4
N21600 G00 Z15.0 (Changed from: "Z15.")
N21605 M25

(2207 Drill1)
N21610 T14 M6
(2.1mm drill)
N21615 S4000 M3
N21620 G54
N21625 G0 X126.5 Y-27.628
N21630 G43 Z10. H14
N21635 Z5.
N21640 G98 G83 X126.5 Y-27.628 Z-11. R2. Q3. P0. F40.
N21645 X146.5
N21650 X282.55
N21655 X302.55
N21660 G80
N21665 Z10.
N21670 M25

(2208 Drill2)
N21675 T21 M6
(3.3mm drill)
N21680 S4000 M3
N21685 G54
N21690 G0 X289. Y16.372
N21695 G43 Z10. H21
N21700 Z5.
N21705 G98 G83 X289. Y16.372 Z-22.5 R-7.5 Q3. P0. F50.
N21710 X296.
N21715 G80
N21720 Z10.
N21725 M25
N21730 M30
%

There are now no G91s to mess things up, which is fine for Centroid. The "Tx" takes care of that.

However, we actually get a superfluous M25 (Z retract) at the end of each section, whether or not there is actually a tool change. I suppose I could live with that for now, although it requires you to press cycle start to continue. However, at least it shows that there are legs on this solution.

Let's not leave it there though. A better solution would be to edit Tom's add-in to spit out both an M25 and an M30 at the end of the file - clearly he only generates an M30, having stripped them out from each subsection. There must be a way to do this.

Looking at Tim's Python code, I haven't much of a clue about the detail. My minimal involvement in writing software has been the Fortran > Pascal > C > Arduino strand, with bits of VHDL, Javascript (post processors etc) etc along the way. I find Python syntax completely incomprehensible but in places I can just about discern some insight into what's going on. Perhaps the code gods might smile on me.

Aha - I found this bit, which is looking for the "tail" of the code from each section. The plan is that the tails are stripped out from the end of each section and finally one of them is added back on to the very end of the combined file, once the main bodies have been concatenated. What is being looked for? 

 # Parse the gcode. We expect a header like this:
            #
            # % <optional>
            # (<comments>) <0 or more lines>
            # (<Txx tool comment>) <optional>
            # <comments or G-code initialization, up to Txx>
            #
            # This header is stripped from all files after the first,
            # except the tool comment is put in a list at the top.
            # The header ends when we find the body, which starts with:
            #
            # Txx ...   (optionally preceded by line number Nxx)
            #
            # We copy all the body, looking for the tail. The start
            # of the tail is marked by one of these:
            # M30 - end program
            # M5 - stop spindle
            # M9 - stop coolant
            # The tail is stripped until the last operation is done.

So - the start of tail is considered to be where the first occurrence of those the M codes (M30, M5 or M9) are spotted. So if I want to add a bit of code to be added to the end of the file, it doesn't want to happen before the first occurrence of any of those. As Tim noted, I don't see any M9 (stop coolant), so it's probably best to rely on the M30 instead. M30 doesn't actually do anything but is often used as a harmless "end of job" marker. So the solution may be to simply add an "M25" immediately after the "M30". That way, Tim's add-in will strip each instance out from each section and replace one instance at the very end. Which is what I want.

Modify the post processor like this:

}
function onClose() {
  onCommand(COMMAND_COOLANT_OFF);
  zOutput.reset();
  setWorkPlane(new Vector(0, 0, 0)); // reset working plane
  onImpliedCommand(COMMAND_END);
  onImpliedCommand(COMMAND_STOP_SPINDLE);
  writeBlock(mFormat.format(30)); // stop program, spindle stop, coolant off
  writeBlock(mFormat.format(25)); // muzzer - add M25
  writeln("%");
}

That seems to work. Here's what I get when I post process a setup with multiple tools:

....
N21560 X141.293 Y-22.114 Z-1.557
N21565 X141.3 Y-22.11 Z-1.4
N21570 G00 Z15.0 (Changed from: "Z15.")

(2207 Drill1)
N21575 T14 M6
(2.1mm drill)
N21580 S4000 M3
N21585 G54
N21590 G0 X126.5 Y-27.628
N21595 G43 Z10. H14
N21600 Z5.
N21605 G98 G83 X126.5 Y-27.628 Z-11. R2. Q3. P0. F40.
N21610 X146.5
N21615 X282.55
N21620 X302.55
N21625 G80
N21630 Z10.

(2208 Drill2)
N21635 T21 M6
(3.3mm drill)
N21640 S4000 M3
N21645 G54
N21650 G0 X289. Y16.372
N21655 G43 Z10. H21
N21660 Z5.
N21665 G98 G83 X289. Y16.372 Z-22.5 R-7.5 Q3. P0. F50.
N21670 X296.
N21675 G80
N21680 Z10.
N21685 M30
N21690 M25
%

Looks like a good result for now! No retracts unless a tool change is actually required but a Z home move at the end of the file. Bargain buckets.

No comments:

Post a Comment

Final assembly and test of the spindle nose adaptor - RESULT!!

After the recent distraction caused by the 3D scanner, resurrecting the 3D printer and buggering about with the throttle bodies for my Honda...