Machsupport Forum
Mach Discussion => Mach4 General Discussion => Topic started by: Jeff_Birt on November 30, 2016, 12:28:04 PM
-
I have a set of 20 or so subroutines in separate files. I have a custom M code that pops up a message box to reposition a part and then the next subroutine is called. Different products use different combinations of the code in these subroutines to this set up makes it very easy to call what subs are needed for an individual product. This would also allow the code for one subroutine to be updated at some future time without having to rewrite the code for each product.
The gcode for one product might look like:
G20 G90 G91.1 G64 G40
( Start at tool change height)
G0 Z4.0
T1 M6
G17
( Engrave Position 1 )
M101
M98 P1000
M5
G0 Z4.0
( Engrave Position 2 )
M101
M98 P1001
M5
G0 Z4.0
(Done)
M30
This set up works well except that the toolpath is generated for the gcode in all subs. The code in each sub is centered around (0,0) as the part is repositioned before each sub is called. This means that all the toolpaths for each sub are drawn over each other which does not hurt anything but looks messy.
I have been looking for a way to selectively show the toolpath for each sub but have not found anything that works.
Any thoughts or ideas? Thanks!
-
Maybe you could use Block Skip? I think we can handle 9 levels or something like that. You would need to add buttons for the added levels on the screen, etc...
Or, you could generate the main G code file that calls the subs on the fly. It would be easy to do in LUA. Generate a main file and load it with a push button or something.
Just throwing out ideas... Maybe one of them is decent. :)
Steve
-
I agree with steve on that, perhaps a wizard that outputs the gcode and loads it into mach4.
DazTheGas
-
Or, you could generate the main G code file that calls the subs on the fly. It would be easy to do in LUA. Generate a main file and load it with a push button or something.
Steve
So, maybe an M code that loads a file, it will be run, then the next M code loads the next file?
That might work, it would let me just use the output from the CAM program directly and just have one custom M code per file.
I'll give that a whirl. it will be a nice change after spending a few hours trying to fix what happens when you drive your Z axis at full speed down over your tool change carousel :(
-
Using block skip/delete was the trick.
The GCode looks like below. The subroutines called have the sections of engraving code that is used in different combinations on different products. This works really slick and the GCode that needs to be written to support different products is trivial.
( Tony Pass, 500TS Engraving )
( T1 : 0.025 )
G20 G90 G91.1 G64 G40
( Start at tool change height)
G0 Z4.0
T1 M6
G17
M101 (Check if just starting)
( Engrave Position 1 )
/1 M98 P1000 (Tony Pass)
/1 M5
/1 G0 Z4.0
/1 M102
( Engrave Position 2 )
/2 M98 P1001 (500TS)
/2 M5
/2 G0 Z4.0
/2 M199 (Reset Block Skip)
(Done)
M30
There are three types of macros used. The first, M101, sets things up for the first pass through the code. that is, if it is the first pass through the code it sets the block skip levels to indicate that and prompts the user to locate the part at position 1 (Block skip 0 is cleared as a flag and clearing Block skip level 1 enable the first block of code) . The user would need to position the part, click OK and then click Start.
-- If this is the frist pass through the GCode,
-- prompt user to insert part at position 1
-- uses block skip/delete level 0 for first pass flag
function m101()
local inst=mc.mcGetInstance();
local val, rc = mc.mcCntlGetBlockDelete(inst, 0);
if ( val == 1) then
mc.mcCntlSetBlockDelete(inst, 0, false);
mc.mcCntlSetBlockDelete(inst, 1, false);
--mc.mcCntlSetBlockDelete(inst, 2, true);
--mc.mcCntlSetBlockDelete(inst, 3, true);
--mc.mcCntlSetBlockDelete(inst, 4, true);
--mc.mcCntlSetBlockDelete(inst, 5, true);
--mc.mcCntlSetBlockDelete(inst, 6, true);
--mc.mcCntlSetBlockDelete(inst, 7, true);
--mc.mcCntlSetBlockDelete(inst, 8, true);
--mc.mcCntlSetBlockDelete(inst, 9, true);
wx.wxMessageBox("Position 1, Press Start");
mc.mcCntlCycleStop(inst);
mc.mcCntlRewindFile(inst);
mc.mcToolPathGenerate(inst);
end
--wx.wxMessageBox("M101 Skip");
end
if (mc.mcInEditor() == 1) then
m101()
end
The next type of macro is the 'Rotate to position #n'
-- Prompts user to place part as position 2
function m102()
local inst=mc.mcGetInstance();
--mc.mcCntlSetBlockDelete(inst, 0, false);
mc.mcCntlSetBlockDelete(inst, 1, true);
mc.mcCntlSetBlockDelete(inst, 2, false);
--mc.mcCntlSetBlockDelete(inst, 3, true);
--mc.mcCntlSetBlockDelete(inst, 4, true);
--mc.mcCntlSetBlockDelete(inst, 5, true);
--mc.mcCntlSetBlockDelete(inst, 6, true);
--mc.mcCntlSetBlockDelete(inst, 7, true);
--mc.mcCntlSetBlockDelete(inst, 8, true);
--mc.mcCntlSetBlockDelete(inst, 9, true);
wx.wxMessageBox("Position 2, Press Start");
mc.mcCntlCycleStop(inst);
mc.mcCntlRewindFile(inst);
mc.mcToolPathGenerate(inst);
end
if (mc.mcInEditor() == 1) then
m102()
end
When done M199 is called to clean things up
-- Part remove prompt, reset block skip/delete
function m199()
local inst=mc.mcGetInstance();
local val, rc = mc.mcCntlGetBlockDelete(inst, 0);
if ( val == 0) then
wx.wxMessageBox("Part done, Remove!");
end
mc.mcCntlSetBlockDelete(inst, 0, true);
mc.mcCntlSetBlockDelete(inst, 1, true);
mc.mcCntlSetBlockDelete(inst, 2, true);
mc.mcCntlSetBlockDelete(inst, 3, true);
mc.mcCntlSetBlockDelete(inst, 4, true);
mc.mcCntlSetBlockDelete(inst, 5, true);
mc.mcCntlSetBlockDelete(inst, 6, true);
mc.mcCntlSetBlockDelete(inst, 7, true);
mc.mcCntlSetBlockDelete(inst, 8, true);
mc.mcCntlSetBlockDelete(inst, 9, true);
mc.mcCntlCycleStop(inst);
mc.mcCntlRewindFile(inst);
mc.mcToolPathGenerate(inst);
end
if (mc.mcInEditor() == 1) then
m199()
end