GRBL new post processor with drill cycles G81..G83
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
Be nice to others! Respect the FreeCAD code of conduct!
Re: GRBL new post processor with drill cycles G81..G83
Yes, a post processor preferences and options panel is a good idea.
I've solved the situation for my case by modifying the source since I'm building it. But a more general solution would be good.
@+.
I've solved the situation for my case by modifying the source since I'm building it. But a more general solution would be good.
@+.
Re: GRBL new post processor with drill cycles G81..G83
I'm not entirely sure what you are meaning by that comment but it sounds like you are saying what Gautier suggested is already present.
He was suggesting an options panel ( presumably a kind of checkbox thing for the binary choice options ) . At the moment, all there is an edit box where you can type in kind of command line option. You need to continually configure this every time you create a job which is quite a drag.
I even find continually needing to select my post processor on every single job a drag. There is little chance I'm flipping constantly from one machine to another needing different PPs each time. Pre-filling the choice with the last used PP would be a nice trivial feature mod that would make the work flow easier. If any typed options could also be made persistent that would get around some of the need for a panel ( though not having to dig around to find the exact text required would still be a plus for a gui approach ).
Re: GRBL new post processor with drill cycles G81..G83
If you would have cared to open up the preferences before getting on your soap box you might have noticed the path output section. But I guess that's too much to ask for these days. Also, I have pointed at the job templates several times before which can also specify the post processor - which can also be set in the preferences. Can't help ya if ya ain't using what's there.freman wrote: ↑Sat Oct 26, 2019 7:04 pmI'm not entirely sure what you are meaning by that comment but it sounds like you are saying what Gautier suggested is already present.
He was suggesting an options panel ( presumably a kind of checkbox thing for the binary choice options ) . At the moment, all there is an edit box where you can type in kind of command line option. You need to continually configure this every time you create a job which is quite a drag.
I even find continually needing to select my post processor on every single job a drag. There is little chance I'm flipping constantly from one machine to another needing different PPs each time. Pre-filling the choice with the last used PP would be a nice trivial feature mod that would make the work flow easier. If any typed options could also be made persistent that would get around some of the need for a panel ( though not having to dig around to find the exact text required would still be a plus for a gui approach ).
Re: GRBL new post processor with drill cycles G81..G83
I would second the usage of templates. Invest these 13:25 to watch sliptonic's video or start at least at 5:15 where the templates start. Well prepared templates with tools, filenames, postprocessors including parameters, will save you, let's say, save 1 minute per job. That means that you are on the gaining side after 10 jobs only, That's a fantastic return on investment. And you will make less mistakes.
A Sketcher Lecture with in-depth information is available in English, auf Deutsch, en français, en español.
Re: GRBL new post processor with drill cycles G81..G83
Thanks Chris, that video is a good guide to where to find all this stuff. I will definitely look into setting up templates for toolcontrollers, that is another thing I'm constantly doing repetitively which wastes a lot of time.
Re: GRBL new post processor with drill cycles G81..G83
I was not "getting on my soapbox" I was trying to make a useful suggestion where I thought improvements could be made. I did look at prefs but due to screen size ( I only have 1780x 1240 available ) and poor layout I only see General and Geometry with two thirds of the tab window empty below it. It seems pretty clear that this is all there is on that page.mlampert wrote: ↑Sat Oct 26, 2019 9:58 pm
If you would have cared to open up the preferences before getting on your soap box you might have noticed the path output section. But I guess that's too much to ask for these days. Also, I have pointed at the job templates several times before which can also specify the post processor - which can also be set in the preferences. Can't help ya if ya ain't using what's there.
Having watched Siptonic's video , I realise there should be other content and for some reason the other two tabs are "displayed" out of sight below the 2/3 of empty grey space !!
I guess that this is not the way it is designed and may display better or other platforms or different versions of qt.
If users are not finding this stuff it may be more productive to ask why not rather than shouting a people. It may be that the interface which has evolved piecemeal over time is not optimal, or that modified code is never getting tested properly before getting merged.
The recent breakage of the toolcontroller code which means that default build of FC no longer work at all for Path, is one example which comes to mind.
Re: GRBL new post processor with drill cycles G81..G83
Having used the preference page for Path to set a few options I find this in report view. ( Options do seem to have stuck AFAICT ).
OS: Linux (LXDE/LXDE)
Word size of OS: 64-bit
Word size of FreeCAD: 64-bit
Version: 0.19.17672 (Git)
Build type: Unknown
Branch: (HEAD detached at ffb4aa5dc)
Hash: ffb4aa5dcfc0f0b6fb37161fd1c820ade167eb04
Python version: 2.7.16
Qt version: 4.8.7
Coin version: 4.0.0a
OCC version: 7.3.0
Locale: English/UnitedKingdom (en_GB)
Code: Select all
Traceback (most recent call last):
File "~/freecad-master-build/Mod/Path/PathScripts/PathPreferencesPathJob.py", line 262, in setProcessorListTooltip
self.setPostProcessorTooltip(self.form.postProcessorList, item.text(), '')
File "~/freecad-master-build/Mod/Path/PathScripts/PathPreferencesPathJob.py", line 255, in setPostProcessorTooltip
processor = self.getPostProcessor(name)
File "~/freecad-master-build/Mod/Path/PathScripts/PathPreferencesPathJob.py", line 249, in getPostProcessor
processor = PostProcessor.load(name)
File "~/freecad-master-build/Mod/Path/PathScripts/PathPostProcessor.py", line 49, in load
exec("import %s as current_post" % postname, namespace) # pylint: disable=exec-used
File "<string>", line 1, in <module>
File "~/freecad-master-build/Mod/Path/PathScripts//post/centroid_post.py", line 82, in <module>
'''.format(__name__, FreeCAD.ActiveDocument.FileName, str(now))
AttributeError: 'NoneType' object has no attribute 'FileName'
Traceback (most recent call last):
File "~/freecad-master-build/Mod/Path/PathScripts/PathPreferencesPathJob.py", line 262, in setProcessorListTooltip
self.setPostProcessorTooltip(self.form.postProcessorList, item.text(), '')
File "~/freecad-master-build/Mod/Path/PathScripts/PathPreferencesPathJob.py", line 255, in setPostProcessorTooltip
processor = self.getPostProcessor(name)
File "~/freecad-master-build/Mod/Path/PathScripts/PathPreferencesPathJob.py", line 249, in getPostProcessor
processor = PostProcessor.load(name)
File "~/freecad-master-build/Mod/Path/PathScripts/PathPostProcessor.py", line 49, in load
exec("import %s as current_post" % postname, namespace) # pylint: disable=exec-used
File "<string>", line 1, in <module>
File "~/freecad-master-build/Mod/Path/PathScripts//post/centroid_post.py", line 82, in <module>
'''.format(__name__, FreeCAD.ActiveDocument.FileName, str(now))
AttributeError: 'NoneType' object has no attribute 'FileName'
Traceback (most recent call last):
File "~/freecad-master-build/Mod/Path/PathScripts/PathPreferencesPathJob.py", line 262, in setProcessorListTooltip
self.setPostProcessorTooltip(self.form.postProcessorList, item.text(), '')
File "~/freecad-master-build/Mod/Path/PathScripts/PathPreferencesPathJob.py", line 255, in setPostProcessorTooltip
processor = self.getPostProcessor(name)
File "~/freecad-master-build/Mod/Path/PathScripts/PathPreferencesPathJob.py", line 249, in getPostProcessor
processor = PostProcessor.load(name)
File "~/freecad-master-build/Mod/Path/PathScripts/PathPostProcessor.py", line 49, in load
exec("import %s as current_post" % postname, namespace) # pylint: disable=exec-used
File "<string>", line 1, in <module>
File "~/freecad-master-build/Mod/Path/PathScripts//post/centroid_post.py", line 82, in <module>
'''.format(__name__, FreeCAD.ActiveDocument.FileName, str(now))
AttributeError: 'NoneType' object has no attribute 'FileName'
Traceback (most recent call last):
File "~/freecad-master-build/Mod/Path/PathScripts/PathPreferencesPathJob.py", line 262, in setProcessorListTooltip
self.setPostProcessorTooltip(self.form.postProcessorList, item.text(), '')
File "~/freecad-master-build/Mod/Path/PathScripts/PathPreferencesPathJob.py", line 255, in setPostProcessorTooltip
processor = self.getPostProcessor(name)
File "~/freecad-master-build/Mod/Path/PathScripts/PathPreferencesPathJob.py", line 249, in getPostProcessor
processor = PostProcessor.load(name)
File "~/freecad-master-build/Mod/Path/PathScripts/PathPostProcessor.py", line 49, in load
exec("import %s as current_post" % postname, namespace) # pylint: disable=exec-used
File "<string>", line 1, in <module>
File "~/freecad-master-build/Mod/Path/PathScripts//post/centroid_post.py", line 82, in <module>
'''.format(__name__, FreeCAD.ActiveDocument.FileName, str(now))
AttributeError: 'NoneType' object has no attribute 'FileName'
Traceback (most recent call last):
File "~/freecad-master-build/Mod/Path/PathScripts/PathPreferencesPathJob.py", line 262, in setProcessorListTooltip
self.setPostProcessorTooltip(self.form.postProcessorList, item.text(), '')
File "~/freecad-master-build/Mod/Path/PathScripts/PathPreferencesPathJob.py", line 255, in setPostProcessorTooltip
processor = self.getPostProcessor(name)
File "~/freecad-master-build/Mod/Path/PathScripts/PathPreferencesPathJob.py", line 249, in getPostProcessor
processor = PostProcessor.load(name)
File "~/freecad-master-build/Mod/Path/PathScripts/PathPostProcessor.py", line 49, in load
exec("import %s as current_post" % postname, namespace) # pylint: disable=exec-used
File "<string>", line 1, in <module>
File "~/freecad-master-build/Mod/Path/PathScripts//post/centroid_post.py", line 82, in <module>
'''.format(__name__, FreeCAD.ActiveDocument.FileName, str(now))
AttributeError: 'NoneType' object has no attribute 'FileName'
OS: Linux (LXDE/LXDE)
Word size of OS: 64-bit
Word size of FreeCAD: 64-bit
Version: 0.19.17672 (Git)
Build type: Unknown
Branch: (HEAD detached at ffb4aa5dc)
Hash: ffb4aa5dcfc0f0b6fb37161fd1c820ade167eb04
Python version: 2.7.16
Qt version: 4.8.7
Coin version: 4.0.0a
OCC version: 7.3.0
Locale: English/UnitedKingdom (en_GB)
Re: GRBL new post processor with drill cycles G81..G83
My bad, I thought this thread was about grbl.
-
- Posts: 1
- Joined: Thu Dec 19, 2019 4:54 pm
Re: GRBL new post processor with drill cycles G81..G83
Hi, first post so please go easy. I have been very pleased with my transition from Fusion360 to FreeCAD on the CAM front - really well done to all the contributors and thank you.
I'm trying to use a relatively flexible (as opposed to rigid) DIY CNC router controlled with grbl and ugcs to make holes in some 15mm and 20mm alu plates as part of a "reprap" style upgrade to the frame. I have profile cut alu with a 3mm 2 fluted endmill before but I didn't do enough to dial in feeds/speeds, just enough to say my machine could do it!
The upgrade involves cutting a couple of hundred 5mm through holes in several plates, for the rails, linear bearing carriages, ball nut traps and bearing blocks etc. I knew that my 3mm endmill would not be a good choice for pocket/profile or helix cutting these, especially as when I cut out my proof parts (using Fusion, over a year ago) the scariest noises happened during the (slow) plunging.
So I tried a 5mm stub drill with manual gcode sent through the ugcs console and the noise/vibration was horrible. Chips were like fine dust, even at slower speeds (I promise I was doing some proper calcs but I don't think the "500W" spindle I have is going to live very long at high torque low rpm drilling operations). Then I went and found some people had success reducing vibration using a 3 flute endmill for alu drilling operations with smaller machines. I received the 3 flute 5mm endmill with a 45 degree flute today and tried it with some manual gcode and the sound was really quite acceptable, vibration was low and the chips were like coarse sand. So far so good.
So I would like to generate gcode from Path (which I have successfully done with profile and helix operations already during test cuts on MDF with the 3mm endmill) using a canned drilling cycle for 60 holes in one of my plates. I realise I need the grbl_g81 postprocessor to do this but the output has two elements that I wasn't expecting.
Firstly, I have set a single hole, pecking 0.3mm, retracting 0.1mm and dwelling 1.0 (second?). This is the resultant gcode from the normal grbl_post:
But I appear to lose the dwell and retract in grbl_81_post:
There's also the matter of me not having set the start height right (Z = 19mm, which is the clearance height, rather than 15mm which is the stock surface) but I will find that out without bothering you now.
I understand it's sensible to post FreeCAD version details so mine are:
OS: Windows 10
Word size of OS: 64-bit
Word size of FreeCAD: 64-bit
Version: 0.18.4 (GitTag)
Build type: Release
Branch: releases/FreeCAD-0-18
Hash: 980bf9060e28555fecd9e3462f68ca74007b70f8
Python version: 3.6.6
Qt version: 5.6.2
Coin version: 4.0.0a
OCC version: 7.3.0
Locale: English/UnitedKingdom (en_GB)
Thanks for any help you can give.
EDIT: so I have managed to see that G98 means the retract will go to the original Z height at which drilling commenced. When I change to G99 (that took me a while to find), grbl_81 post processor results in:
Which isn't what I expected or wanted. I think I will have a look at the grbl_81_post.py and see if I can make the necessary changes there.
ANOTHER UPDATE: I have managed to get the output that I wanted. I had to change the code in grbl_81_post.py (which I named grbl_83_post.py and here's the pecking with a retract that suits what I understand G99 to be
I'll have a look on Github to see if I can submit a PR for the changes which now handle G99 and G83 a bit better.
By the way, can anyone tell me how we'd get the drill to rapid to the start drilling height specified in the Path "Start Depth"? At the moment, these post processors seem to be starting the canned cycles (let alone unpacked versions) from the clearance or safe height.
EDIT: the merged version of grbl_post on Github looks significantly different to the version of grbl_81_post that shipped with my version of FreeCAD (details above in this post), so I'll just leave the code here in case anyone wants to incorporate or test for themselves:
I'm trying to use a relatively flexible (as opposed to rigid) DIY CNC router controlled with grbl and ugcs to make holes in some 15mm and 20mm alu plates as part of a "reprap" style upgrade to the frame. I have profile cut alu with a 3mm 2 fluted endmill before but I didn't do enough to dial in feeds/speeds, just enough to say my machine could do it!
The upgrade involves cutting a couple of hundred 5mm through holes in several plates, for the rails, linear bearing carriages, ball nut traps and bearing blocks etc. I knew that my 3mm endmill would not be a good choice for pocket/profile or helix cutting these, especially as when I cut out my proof parts (using Fusion, over a year ago) the scariest noises happened during the (slow) plunging.
So I tried a 5mm stub drill with manual gcode sent through the ugcs console and the noise/vibration was horrible. Chips were like fine dust, even at slower speeds (I promise I was doing some proper calcs but I don't think the "500W" spindle I have is going to live very long at high torque low rpm drilling operations). Then I went and found some people had success reducing vibration using a 3 flute endmill for alu drilling operations with smaller machines. I received the 3 flute 5mm endmill with a 45 degree flute today and tried it with some manual gcode and the sound was really quite acceptable, vibration was low and the chips were like coarse sand. So far so good.
So I would like to generate gcode from Path (which I have successfully done with profile and helix operations already during test cuts on MDF with the 3mm endmill) using a canned drilling cycle for 60 holes in one of my plates. I realise I need the grbl_g81 postprocessor to do this but the output has two elements that I wasn't expecting.
Firstly, I have set a single hole, pecking 0.3mm, retracting 0.1mm and dwelling 1.0 (second?). This is the resultant gcode from the normal grbl_post:
Code: Select all
(Exported by FreeCAD)
(Post Processor: grbl_post)
(Output Time:2020-01-06 12:13:27.479520)
(begin preamble)
G17 G90
G21
(begin operation: T1: 5mm_3flute_endmill_45degree)
(Path: T1: 5mm_3flute_endmill_45degree)
(T1: 5mm_3flute_endmill_45degree)
(begin toolchange)
; M6 T2
M3 S1500.0000
(finish operation: T1: 5mm_3flute_endmill_45degree)
(begin operation: Drilling)
(Path: Drilling)
(Drilling)
(Begin Drilling)
G0 Z19.0000
G90
; G98
G83 X7.5000 Y6.5000 Z0.0000 F6.00 Q0.3000 R0.1000
; G80
G0 Z19.0000
(finish operation: Drilling)
(begin postamble)
M5
G17 G90
; M2
Code: Select all
(Exported by FreeCAD)
(Post Processor: grbl_G81_post)
(Output Time:2020-01-06 12:41:29.001765)
(begin preamble)
G17 G90
G21
(begin operation: T1: 5mm_3flute_endmill_45degree)
(Path: T1: 5mm_3flute_endmill_45degree)
(T1: 5mm_3flute_endmill_45degree)
(begin toolchange)
(M6 T2.0)
M3 S1500.000
(finish operation: T1: 5mm_3flute_endmill_45degree)
(begin operation: Drilling)
(Path: Drilling)
(Drilling)
(Begin Drilling)
G0 Z19.000
G90
(G98)
(G83 X7.500 Y6.500 Z0.000 F6.00 Q0.300 R0.100)
G0 X7.500 Y6.500
G1 Z18.700 F6.00
G0 Z19.000
G1 Z18.400 F6.00
G0 Z19.000
G1 Z18.100 F6.00
G0 Z19.000
G1 Z17.800 F6.00
G0 Z19.000
G1 Z17.500 F6.00
G0 Z19.000
G1 Z17.200 F6.00
G0 Z19.000
G1 Z16.900 F6.00
G0 Z19.000
G1 Z16.600 F6.00
G0 Z19.000
G1 Z16.300 F6.00
G0 Z19.000
G1 Z16.000 F6.00
G0 Z19.000
G1 Z15.700 F6.00
...
I understand it's sensible to post FreeCAD version details so mine are:
OS: Windows 10
Word size of OS: 64-bit
Word size of FreeCAD: 64-bit
Version: 0.18.4 (GitTag)
Build type: Release
Branch: releases/FreeCAD-0-18
Hash: 980bf9060e28555fecd9e3462f68ca74007b70f8
Python version: 3.6.6
Qt version: 5.6.2
Coin version: 4.0.0a
OCC version: 7.3.0
Locale: English/UnitedKingdom (en_GB)
Thanks for any help you can give.
EDIT: so I have managed to see that G98 means the retract will go to the original Z height at which drilling commenced. When I change to G99 (that took me a while to find), grbl_81 post processor results in:
Code: Select all
G17 G90
G21
(begin operation: T1: 5mm_3flute_endmill_45degree)
(Path: T1: 5mm_3flute_endmill_45degree)
(T1: 5mm_3flute_endmill_45degree)
(begin toolchange)
(M6 T2.0)
M3 S1500.000
(finish operation: T1: 5mm_3flute_endmill_45degree)
(begin operation: Drilling)
(Path: Drilling)
(Drilling)
(Begin Drilling)
G0 Z19.000
G90
G99
(G83 X7.500 Y6.500 Z0.000 F6.00 Q0.300 R0.100)
G0 X7.500 Y6.500
G0 Z19.000
G1 Z0.000 F6.00
G0 Z0.100
(G80)
G0 Z19.000
(finish operation: Drilling)
(begin postamble)
M5
G17 G90
M2
ANOTHER UPDATE: I have managed to get the output that I wanted. I had to change the code in grbl_81_post.py (which I named grbl_83_post.py and here's the pecking with a retract that suits what I understand G99 to be
Code: Select all
(Exported by FreeCAD)
(Post Processor: grbl_G83_post)
(Output Time:2020-01-07 00:38:33.770124)
(begin preamble)
G17 G90
G21
(begin operation: T1: 5mm_3flute_endmill_45degree)
(Path: T1: 5mm_3flute_endmill_45degree)
(T1: 5mm_3flute_endmill_45degree)
(begin toolchange)
(M6 T2.0)
M3 S1500.000
(finish operation: T1: 5mm_3flute_endmill_45degree)
(begin operation: Drilling)
(Path: Drilling)
(Drilling)
(Begin Drilling)
G0 Z19.000
G90
(G99)
(G83 X7.500 Y6.500 Z0.000 F6.00 Q0.300 R0.100)
G0 X7.500 Y6.500
G1 Z18.700 F6.00
G0 Z18.800
G1 Z18.400 F6.00
G0 Z18.500
G1 Z18.100 F6.00
G0 Z18.200
G1 Z17.800 F6.00
G0 Z17.900
G1 Z17.500 F6.00
G0 Z17.600
G1 Z17.200 F6.00
G0 Z17.300
By the way, can anyone tell me how we'd get the drill to rapid to the start drilling height specified in the Path "Start Depth"? At the moment, these post processors seem to be starting the canned cycles (let alone unpacked versions) from the clearance or safe height.
EDIT: the merged version of grbl_post on Github looks significantly different to the version of grbl_81_post that shipped with my version of FreeCAD (details above in this post), so I'll just leave the code here in case anyone wants to incorporate or test for themselves:
Code: Select all
# -*- coding: utf-8 -*-
#***************************************************************************
#* (c) Gauthier Briere - 2018 *
#* (c) Simon Merrett - 2020 *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2.1 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENSE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Lesser General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with This program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************/
TOOLTIP='''
Generate g-code from a Path that is compatible with the grbl controller.
import grbl_post
grbl_post.export(object, "/path/to/file.ncc")
'''
import FreeCAD
import PathScripts.PostUtils as PostUtils
import argparse
import datetime
import shlex
#*********************************************************************************************************
# Globals set customization preferences
#*********************************************************************************************************
# Default values for command line arguments:
OUTPUT_COMMENTS = True # default output of comments in output gCode file
OUTPUT_HEADER = True # default output header in output gCode file
OUTPUT_LINE_NUMBERS = False # default doesn't output line numbers in output gCode file
SHOW_EDITOR = True # default show the resulting file dialog output in GUI
PRECISION = 3 # Default precision for metric (see http://linuxcnc.org/docs/2.7/html/gcode/overview.html#_g_code_best_practices)
TRANSLATE_DRILL_CYCLES = True # If true, G81, G82 & G83 are translated in G0/G1 moves
PREAMBLE = '''G17 G90
''' # default preamble text will appear at the beginning of the gCode output file.
POSTAMBLE = '''M5
G17 G90
M2
''' # default postamble text will appear following the last operation.
# Customisation with no command line argument
MODAL = False # if true commands are suppressed if the same as previous line.
LINENR = 100 # line number starting value
LINEINCR = 10 # line number increment
OUTPUT_TOOL_CHANGE = False # default don't output M6 tool changes (comment it) as grbl currently does not handle it
DRILL_RETRACT_MODE = 'G98' # Default value of drill retractations (CURRENT_Z) other possible value is G99
MOTION_MODE = 'G90' # G90 for absolute moves, G91 for relative
UNITS = 'G21' # G21 for metric, G20 for us standard
SPEED_MULTIPLIER = 60 # *60 convert FreeCAD's mm/s to mm/mn
PRE_OPERATION = '''''' #Pre operation text will be inserted before every operation
POST_OPERATION = '''''' #Post operation text will be inserted after every operation
TOOL_CHANGE = '''''' #Tool Change commands will be inserted before a tool change
#*********************************************************************************************************
# End of customization
#*********************************************************************************************************
# Parser arguments list & definition
parser = argparse.ArgumentParser(prog='grbl_G81', add_help=False)
parser.add_argument('--comments', action='store_true', help='output comment (default)')
parser.add_argument('--no-comments', action='store_true', help='suppress comment output')
parser.add_argument('--header', action='store_true', help='output headers (default)')
parser.add_argument('--no-header', action='store_true', help='suppress header output')
parser.add_argument('--line-numbers', action='store_true', help='prefix with line numbers')
parser.add_argument('--no-line-numbers', action='store_true', help='don\'t prefix with line numbers (default)')
parser.add_argument('--show-editor', action='store_true', help='pop up editor before writing output (default)')
parser.add_argument('--no-show-editor', action='store_true', help='don\'t pop up editor before writing output')
parser.add_argument('--precision', default='3', help='number of digits of precision, default=3')
parser.add_argument('--translate_drill', action='store_true', help='translate drill cycles G81, G82 & G83 in G0/G1 movements (default)')
parser.add_argument('--no-translate_drill', action='store_true', help='don\'t translate drill cycles G81, G82 & G83 in G0/G1 movements')
parser.add_argument('--preamble', help='set commands to be issued before the first command, default="G17 G90"')
parser.add_argument('--postamble', help='set commands to be issued after the last command, default="M5\nG17 G90\n;M2"')
TOOLTIP_ARGS=parser.format_help()
#*********************************************************************************************************
# Internal global variables
MOTION_COMMANDS = ['G0', 'G00', 'G1', 'G01', 'G2', 'G02', 'G3', 'G03'] # Motion gCode commands definition
RAPID_MOVES = ['G0', 'G00'] # Rapid moves gCode commands definition
SUPPRESS_COMMANDS = ['G99', 'G98', 'G80'] #COMMIT DOCS added 'G99' to SUPPRESS_COMMANDS to fix error in unfolding G83 cycle # These commands are ignored by commenting them out
COMMAND_SPACE = " "
CURRENT_X = 0 # Global variable storing current position
CURRENT_Y = 0
CURRENT_Z = 0
#*********************************************************************************************************
# to distinguish python built-in open function from the one declared below
if open.__module__ in ['__builtin__','io']:
pythonopen = open
def processArguments(argstring):
global OUTPUT_HEADER
global OUTPUT_COMMENTS
global OUTPUT_LINE_NUMBERS
global SHOW_EDITOR
global PRECISION
global PREAMBLE
global POSTAMBLE
global TRANSLATE_DRILL_CYCLES
try:
args = parser.parse_args(shlex.split(argstring))
if args.no_header:
OUTPUT_HEADER = False
if args.header:
OUTPUT_HEADER = True
if args.no_comments:
OUTPUT_COMMENTS = False
if args.comments:
OUTPUT_COMMENTS = True
if args.no_line_numbers:
OUTPUT_LINE_NUMBERS = False
if args.line_numbers:
OUTPUT_LINE_NUMBERS = True
if args.no_show_editor:
SHOW_EDITOR = False
if args.show_editor:
SHOW_EDITOR = True
PRECISION = args.precision
if args.preamble is not None:
PREAMBLE = args.preamble
if args.postamble is not None:
POSTAMBLE = args.postamble
if args.no_translate_drill:
TRANSLATE_DRILL_CYCLES = False
if args.translate_drill:
TRANSLATE_DRILL_CYCLES = True
except:
return False
return True
# For debug...
def dump(obj):
for attr in dir(obj):
print("obj.%s = %s" % (attr, getattr(obj, attr)))
def export(objectslist, filename, argstring):
if not processArguments(argstring):
return None
global UNITS
global MOTION_MODE
print("Post Processor: " + __name__ +" postprocessing...")
gcode = ""
# write header
if OUTPUT_HEADER:
gcode += linenumber() + "(Exported by FreeCAD)\n"
gcode += linenumber() + "(Post Processor: " + __name__ +")\n"
gcode += linenumber() + "(Output Time:"+str(datetime.datetime.now())+")\n"
# Write the preamble
if OUTPUT_COMMENTS:
gcode += linenumber() + "(begin preamble)\n"
for line in PREAMBLE.splitlines(True):
gcode += linenumber() + line
# verify if PREAMBLE have changed MOTION_MODE or UNITS
if 'G90' in PREAMBLE:
MOTION_MODE = 'G90'
elif 'G91' in PREAMBLE:
MOTION_MODE = 'G91'
else:
gcode += linenumber() + MOTION_MODE + "\n"
if 'G21' in PREAMBLE:
UNITS = 'G21'
elif 'G20' in PREAMBLE:
UNITS = 'G20'
else:
gcode += linenumber() + UNITS + "\n"
for obj in objectslist:
# Debug...
#print("\n" + "*"*70)
#dump(obj)
#print("*"*70 + "\n")
if not hasattr(obj,"Path"):
print("The object " + obj.Name + " is not a path. Please select only path and Compounds.")
return
# do the pre_op
if OUTPUT_COMMENTS: gcode += linenumber() + "(begin operation: " + obj.Label + ")\n"
for line in PRE_OPERATION.splitlines(True):
gcode += linenumber() + line
# Parse the op
gcode += parse(obj)
# do the post_op
if OUTPUT_COMMENTS: gcode += linenumber() + "(finish operation: " + obj.Label + ")\n"
for line in POST_OPERATION.splitlines(True):
gcode += linenumber() + line
#do the post_amble
if OUTPUT_COMMENTS: gcode += linenumber() + "(begin postamble)\n"
for line in POSTAMBLE.splitlines(True):
gcode += linenumber() + line
#show the gCode result dialog
if FreeCAD.GuiUp and SHOW_EDITOR:
dia = PostUtils.GCodeEditorDialog()
dia.editor.setText(gcode)
result = dia.exec_()
if result:
final = dia.editor.toPlainText()
else:
final = gcode
else:
final = gcode
print("done postprocessing.")
#write the file
gfile = pythonopen(filename,"w")
gfile.write(gcode)
gfile.close()
def linenumber():
global LINENR
global LINEINCR
if OUTPUT_LINE_NUMBERS == True:
s = "N" + str(LINENR) + " "
LINENR += LINEINCR
return s
return ""
def format_outstring(strTbl):
global COMMAND_SPACE
# construct the line for the final output
s = ""
for w in strTbl:
s += w + COMMAND_SPACE
s = s.strip()
return s
def parse(pathobj):
global DRILL_RETRACT_MODE
global MOTION_MODE
global CURRENT_X
global CURRENT_Y
global CURRENT_Z
out = ""
lastcommand = None
precision_string = '.' + str(PRECISION) +'f'
params = ['X','Y','Z','A','B','C','I','J','K','F','S','T','Q','R','L','P']
if hasattr(pathobj,"Group"): # We have a compound or project.
if OUTPUT_COMMENTS: out += linenumber() + "(compound: " + pathobj.Label + ")\n"
for p in pathobj.Group:
out += parse(p)
return out
else: # parsing simple path
if not hasattr(pathobj,"Path"): #groups might contain non-path things like stock.
return out
if OUTPUT_COMMENTS: out += linenumber() + "(Path: " + pathobj.Label + ")\n"
for c in pathobj.Path.Commands:
outstring = []
command = c.Name
outstring.append(command)
# if modal: only print the command if it is not the same as the last one
if MODAL == True:
if command == lastcommand:
outstring.pop(0)
# Now add the remaining parameters in order
for param in params:
if param in c.Parameters:
if param == 'F':
if command not in RAPID_MOVES:
outstring.append(param + format(c.Parameters['F'] * SPEED_MULTIPLIER, '.2f'))
elif param == 'T':
outstring.append(param + str(c.Parameters['T']))
else:
outstring.append(param + format(c.Parameters[param], precision_string))
# store the latest command
lastcommand = command
# Memorise la position courante pour calcul des mouvements relatis et du plan de retrait
if command in MOTION_COMMANDS:
if 'X' in c.Parameters:
CURRENT_X = c.Parameters['X']
if 'Y' in c.Parameters:
CURRENT_Y = c.Parameters['Y']
if 'Z' in c.Parameters:
CURRENT_Z = c.Parameters['Z']
if command in ('G98', 'G99'):
DRILL_RETRACT_MODE = command
if command in ('G90', 'G91'):
MOTION_MODE = command
if TRANSLATE_DRILL_CYCLES:
if command in ('G81', 'G82', 'G83'):
out += drill_translate(outstring, command, c.Parameters)
# Efface la ligne que l'on vient de translater
del(outstring[:])
outstring = []
# Check for Tool Change:
if command in ('M6', 'M06'):
if OUTPUT_COMMENTS: out += linenumber() + "(begin toolchange)\n"
if not OUTPUT_TOOL_CHANGE:
outstring[0] = "(" + outstring[0]
outstring[-1] = outstring[-1] + ")"
else:
for line in TOOL_CHANGE.splitlines(True):
out += linenumber() + line
if command == "message":
if OUTPUT_COMMENTS == False:
out = []
else:
outstring.pop(0) #remove the command
if command in SUPPRESS_COMMANDS:
outstring[0] = "(" + outstring[0]
outstring[-1] = outstring[-1] + ")"
#prepend a line number and append a newline
if len(outstring) >= 1:
out += linenumber() + format_outstring(outstring) + "\n"
return out
def drill_translate(outstring, cmd, params):
global DRILL_RETRACT_MODE
global MOTION_MODE
global CURRENT_X
global CURRENT_Y
global CURRENT_Z
strFormat = '.' + str(PRECISION) +'f'
trBuff = ""
if OUTPUT_COMMENTS: # Comment the original command
outstring[0] = "(" + outstring[0]
outstring[-1] = outstring[-1] + ")"
trBuff += linenumber() + format_outstring(outstring) + "\n"
# Conversion du cycle
# Pour l'instant, on gere uniquement les cycles dans le plan XY (G17)
# les autres plans ZX (G18) et YZ (G19) ne sont pas traites : Calculs sur Z uniquement.
if MOTION_MODE == 'G90': # Deplacements en coordonnees absolues
drill_X = params['X']
drill_Y = params['Y']
drill_Z = params['Z']
RETRACT_Z = params['R'] #RETRACT_Z_SMALL = params['R'] # added in the mod to enable small retracts with G83
else: # G91 Deplacements relatifs
drill_X = CURRENT_X + params['X']
drill_Y = CURRENT_Y + params['Y']
drill_Z = CURRENT_Z + params['Z']
RETRACT_Z = CURRENT_Z + params['R']
if DRILL_RETRACT_MODE == 'G98' and CURRENT_Z >= RETRACT_Z:
RETRACT_Z = CURRENT_Z
# Recupere les valeurs des autres parametres
drill_Speed = params['F'] * SPEED_MULTIPLIER
if cmd == 'G83':
drill_Step = params['Q']
elif cmd == 'G82':
drill_DwellTime = params['P']
if MOTION_MODE == 'G91':
trBuff += linenumber() + "G90" + "\n" # Force des deplacements en coordonnees absolues pendant les cycles
#COMMIT DOCS Don't think this applies to G99 so propose a conditional. Don't know what to do for safe height move though, or even if that's needed
# Mouvement(s) preliminaire(s))
if CURRENT_Z < RETRACT_Z and DRILL_RETRACT_MODE == 'G98': #COMMIT DOCS added condition
trBuff += linenumber() + 'G0 Z' + format(RETRACT_Z, strFormat) + "\n"
trBuff += linenumber() + 'G0 X' + format(drill_X, strFormat) + ' Y' + format(drill_Y, strFormat) + "\n"
if CURRENT_Z > RETRACT_Z and DRILL_RETRACT_MODE == 'G98': #COMMIT DOCS added condition
trBuff += linenumber() + 'G0 Z' + format(CURRENT_Z, strFormat) + "\n"
# Mouvement de percage
if cmd in ('G81', 'G82'):
trBuff += linenumber() + 'G1 Z' + format(drill_Z, strFormat) + ' F' + format(drill_Speed, '.2f') + "\n"
# Temporisation eventuelle
if cmd == 'G82':
trBuff += linenumber() + 'G4 P' + str(drill_DwellTime) + "\n"
# Sortie de percage
trBuff += linenumber() + 'G0 Z' + format(RETRACT_Z, strFormat) + "\n"
else: # 'G83'
if DRILL_RETRACT_MODE == 'G98':#COMMIT DOCS added condition
next_Stop_Z = RETRACT_Z - drill_Step
elif DRILL_RETRACT_MODE == 'G99': #COMMIT DOCS added condition
next_Stop_Z = CURRENT_Z - drill_Step #COMMIT DOCS added alternative point#
while 1:
if next_Stop_Z > drill_Z:
trBuff += linenumber() + 'G1 Z' + format(next_Stop_Z, strFormat) + ' F' + format(drill_Speed, '.2f') + "\n"
if DRILL_RETRACT_MODE == 'G98': #COMMIT DOCS added condition
trBuff += linenumber() + 'G0 Z' + format(RETRACT_Z, strFormat) + "\n"
elif DRILL_RETRACT_MODE == 'G99': #COMMIT DOCS added condition
trBuff += linenumber() + 'G0 Z' + format(next_Stop_Z + RETRACT_Z, strFormat) + "\n" #COMMIT DOCS adapted retract height to match G99
next_Stop_Z -= drill_Step
else:
trBuff += linenumber() + 'G1 Z' + format(drill_Z, strFormat) + ' F' + format(drill_Speed, '.2f') + "\n"
if DRILL_RETRACT_MODE == 'G98': #COMMIT DOCS added condition
trBuff += linenumber() + 'G0 Z' + format(RETRACT_Z, strFormat) + "\n"
elif DRILL_RETRACT_MODE == 'G99': #COMMIT DOCS added condition
trBuff += linenumber() + 'G0 Z' + format(CURRENT_Z, strFormat) + "\n" #COMMIT DOCS adapted retract to original rapids height before drilling operation in Z
break
if MOTION_MODE == 'G91':
trBuff += linenumber() + 'G91' # Restore le mode de deplacement relatif
return trBuff
print(__name__ + ": gCode postprocessor loaded.")
Re: GRBL new post processor with drill cycles G81..G83
Hi @smerrett79,
Warning, the grbl_81_post included in the 0.18.4 FreeCAD's version is not the last version of the post processor.
In FreeCAD v0.19, grbl_81_post have been renamed and replace the old grbl_post. It also have some updates who made it evolve...
However, the resulting moves it give are correct regarding the G83 definition and the post processor is correct for this point.
It is the value of your retract plane (R parameter: R0.1000) that is not correct.
The G83 retract plan is a fixed Z height wich is differently defined with G98 or G99, but it's a fixed height. In your case, you defined it at 0.1mm. Your stock is 15 mm height and you can't begin to drill at 14.7mm (the first step of your cycle) and go up to 0.1mm!
You need to define the retract plane at least at 15mm => R15.0000.
@++;
Gauthier.
Warning, the grbl_81_post included in the 0.18.4 FreeCAD's version is not the last version of the post processor.
In FreeCAD v0.19, grbl_81_post have been renamed and replace the old grbl_post. It also have some updates who made it evolve...
However, the resulting moves it give are correct regarding the G83 definition and the post processor is correct for this point.
It is the value of your retract plane (R parameter: R0.1000) that is not correct.
The G83 retract plan is a fixed Z height wich is differently defined with G98 or G99, but it's a fixed height. In your case, you defined it at 0.1mm. Your stock is 15 mm height and you can't begin to drill at 14.7mm (the first step of your cycle) and go up to 0.1mm!
You need to define the retract plane at least at 15mm => R15.0000.
@++;
Gauthier.