+ ======================================= + This post processor reads the material setup for the cut and outputs the correct units, cut style (flat or rotary) and wrap orientation based on user selected settings. + BrianO (10/28/23) Version 1 + + ======================================= POST_NAME = "ShopBot Milling TC (*.sbp)" FILE_EXTENSION = "sbp" UNITS = "inches" +------------------------------------------------ | line terminating characters +------------------------------------------------ LINE_ENDING = "[13][10]" +------------------------------------------------ | Block Numbering +------------------------------------------------ LINE_NUMBER_START = 0 LINE_NUMBER_INCREMENT = 10 LINE_NUMBER_MAXIMUM = 999999 SCRIPT require "strict" pp = require "ppVariables" Options = {} -- Initialize options table g_title = "ShopBot Universal Post Processor" -- name for registry entry where settings are recorded. g_default_window_width = 200 -- window width for UI in pixels g_default_window_height = 400 -- window height for UI in pixels RotationAxis = MaterialBlock().RotationAxis RotationAxisString = "Along X Axis" SurfaceAdjust = 0 if RotationAxis == 1 then RotationAxisString = "Along Y Axis" end JobTypeString = "Single Sided" if MaterialBlock().JobType == 1 then JobTypeString = "Double Sided" elseif MaterialBlock().JobType == 2 then JobTypeString = "Rotary" end if MaterialBlock().InMM then UNITS = "mm" UnitMultiple = 25.4 UnitsIndex = 1 else UNITS = "Inches" UnitMultiple = 1 UnitsIndex = 0 end Diameter = MaterialBlock().Thickness * 2 / UnitMultiple if MaterialBlock().JobType < 2 then if MaterialBlock().ZOrigin == 0 then ZOriginString = "Material Surface" elseif MaterialBlock().ZOrigin == 2 then ZOriginString = "Table Surface" end elseif MaterialBlock().JobType == 2 then if MaterialBlock().ZOrigin == 0 then ZOriginString = "Cylinder Surface" elseif MaterialBlock().ZOrigin == 2 then ZOriginString = "Cylinder Axis" end end g_dialogHtml = [[]] ..[[]] ..[[Confirm your toolpath settings: ]] ..[[]] ..[[]] .. [[]] .. [[Confirm your toolpath settings:]] .. [[
]] .. [[
]] .. [[

Units

]] .. [[]] .. [[
]] .. [[]] .. [[
]] if (tonumber(MaterialBlock().JobType) < 2) then g_dialogHtml = g_dialogHtml .. [[
]] .. [[

Z Zero Position

]] .. [[]] .. [[
]] .. [[]] .. [[
]] .. [[
]] .. [[]] .. [[]] .. [[]] .. [[
]] .. [[ ]] .. [[]] .. [[]] .. [[
]] .. [[]] g_default_window_height = 400 elseif (tonumber(MaterialBlock().JobType) == 2) then g_dialogHtml = g_dialogHtml .. [[
]] .. [[
]] .. [[

Z Zero Position

]] .. [[]] .. [[
]] .. [[]] .. [[
]] .. [[
]] .. [[
]] .. [[
]] .. [[

Orientation

]] .. [[]] .. [[
]] .. [[]] .. [[
]] .. [[
]] .. [[
]] .. [[]] .. [[]] .. [[]] .. [[
]] .. [[ ]] .. [[]] .. [[]] .. [[
]] .. [[]] g_default_window_height = 550 end function DisplayDialog() -- Called in main. Pulls up UI local dialog = HTML_Dialog(true,g_dialogHtml, g_default_window_width, g_default_window_height, "Confirm Your Settings") dialog:AddRadioGroup("units", tonumber(UnitsIndex) + 1) if (tonumber(MaterialBlock().JobType) < 2) then dialog:AddRadioGroup("zZeroPos", tonumber(MaterialBlock().ZOrigin) + 1) elseif (tonumber(MaterialBlock().JobType) == 2) then dialog:AddRadioGroup("rotaryZZeroPos", tonumber(MaterialBlock().ZOrigin) + 1) dialog:AddRadioGroup("rotaryOrient", tonumber(MaterialBlock().RotationAxis) + 1) end if not dialog:ShowDialog() then return 0 end UnitsIndex = tonumber(dialog:GetRadioIndex("units")) - 1 if UnitsIndex == 1 then UNITS = "mm" UnitMultiple = 25.4 else UNITS = "Inches" UnitMultiple = 1 end if MaterialBlock().JobType < 2 then local ZOrigin = tonumber(dialog:GetRadioIndex("zZeroPos") - 1) * 2 if tonumber(MaterialBlock().ZOrigin) - ZOrigin < 0 then SurfaceAdjust = 1 elseif tonumber(MaterialBlock().ZOrigin) - ZOrigin > 0 then SurfaceAdjust = -1 end elseif MaterialBlock().JobType == 2 then RotationAxis = tonumber(dialog:GetRadioIndex("rotaryOrient")) - 1 local ZOrigin = tonumber(dialog:GetRadioIndex("rotaryZZeroPos") - 1) * 2 if tonumber(MaterialBlock().ZOrigin) - ZOrigin < 0 then SurfaceAdjust = 1 elseif tonumber(MaterialBlock().ZOrigin) - ZOrigin > 0 then SurfaceAdjust = -1 end end if (tonumber(MaterialBlock().JobType) < 2) then elseif (tonumber(MaterialBlock().JobType) == 2) then end return 1 end function main() if pp.Init() == false then DisplayMessageBox('Failed to initialise ppVariables module!') end local dialog_result = -1 while dialog_result == -1 do dialog_result = DisplayDialog() end -- The user cancelled if dialog_result == 0 then return false end return true end function Round(number) if UNITS == "Inches" then return tonumber(string.format("%.4f",number)) elseif UNITS == "mm" then return tonumber(string.format("%.3f",number)) end end function DegRound(number) return tonumber(string.format("%.3f",number)) end function Header() --Filename pp.PostP:OutputLine("'" .. tostring(pp.TP_FILENAME) .. "\r\n", false) --File Description, Date and Time if MaterialBlock().JobType < 2 then pp.PostP:OutputLine("'ShopBot Cut File created on " .. tostring(pp.DATE) .. " at " .. tostring(pp.TIME) .. "\r\n", false) elseif MaterialBlock().JobType == 2 then pp.PostP:OutputLine("'ShopBot Rotary Cut File created on " .. tostring(pp.DATE) .. " at " .. tostring(pp.TIME) .. "\r\n", false) end --Cutting envelope and material specs if MaterialBlock().JobType < 2 then pp.PostP:OutputLine("'Minimum extent in X = " .. Round(pp.XMIN.Value*UnitMultiple) .. " Minimum extent in Y = " .. Round(pp.YMIN.Value*UnitMultiple) .. " Minimum extent in Z = " .. Round(pp.ZMIN.Value*UnitMultiple) .. "\r\n", false) pp.PostP:OutputLine("'Maximum extent in X = " .. Round(pp.XMAX.Value*UnitMultiple) .. " Maximum extent in Y = " .. Round(pp.YMAX.Value*UnitMultiple) .. " Maximum extent in Z = " .. Round(pp.ZMAX.Value*UnitMultiple) .. "\r\n", false) pp.PostP:OutputLine("'Length of material in X = " .. Round(pp.XLENGTH.Value*UnitMultiple) .. "\r\n", false) pp.PostP:OutputLine("'Length of material in Y = " .. Round(pp.YLENGTH.Value*UnitMultiple) .. "\r\n", false) pp.PostP:OutputLine("'Depth of material in Z = " .. Round(pp.ZLENGTH.Value*UnitMultiple) .. "\r\n", false) elseif MaterialBlock().JobType == 2 then if RotationAxis == 0 then pp.PostP:OutputLine("'Minimum extent in X = " .. Round(pp.XMIN.Value*UnitMultiple) .. " Minimum extent in Z = " .. Round(pp.ZMIN.Value*UnitMultiple) .. " Minimum extent in B = " .. DegRound(pp.YMIN.Value/(math.pi*Diameter*UnitMultiple)*360) .. "\r\n", false) pp.PostP:OutputLine("'Maximum extent in X = " .. Round(pp.XMAX.Value*UnitMultiple) .. " Maximum extent in Z = " .. Round(pp.ZMAX.Value*UnitMultiple) .. " Maximum extent in B = " .. DegRound(pp.YMAX.Value/(math.pi*Diameter*UnitMultiple)*360) .. "\r\n", false) pp.PostP:OutputLine("'Length of material in X = " .. Round(pp.XLENGTH.Value*UnitMultiple) .. "\r\n", false) pp.PostP:OutputLine("'Diameter of material = " .. Round(Diameter*UnitMultiple) .. "\r\n", false) end if RotationAxis == 1 then pp.PostP:OutputLine("'Minimum extent in Y = " .. Round(pp.YMIN.Value*UnitMultiple) .. " Minimum extent in Z = " .. Round(pp.ZMIN.Value*UnitMultiple) .. " Minimum extent in B = " .. DegRound(pp.XMIN.Value/(math.pi*Diameter*UnitMultiple)*360) .. "\r\n", false) pp.PostP:OutputLine("'Maximum extent in Y = " .. Round(pp.YMAX.Value*UnitMultiple) .. " Maximum extent in Z = " .. Round(pp.ZMAX.Value*UnitMultiple) .. " Maximum extent in B = " .. DegRound(pp.XMAX.Value/(math.pi*Diameter*UnitMultiple)*360) .. "\r\n", false) pp.PostP:OutputLine("'Length of material in Y = " .. Round(pp.YLENGTH.Value*UnitMultiple) .. "\r\n", false) pp.PostP:OutputLine("'Diameter of material = " .. Round(Diameter*UnitMultiple) .. "\r\n", false) end end --Origin information pp.PostP:OutputLine("'Z Origin set to " .. ZOriginString .. "\r\n", false) pp.PostP:OutputLine("'Home X = " .. Round(pp.XH.Value*UnitMultiple) .. " Home Y = " .. Round(pp.YH.Value*UnitMultiple) .. " Home Z = " .. Round(pp.ZH.Value*UnitMultiple) .. "\r\n", false) pp.PostP:OutputLine("'Rapid clearance gap or Safe Z = " .. Round(pp.SAFEZ.Value*UnitMultiple) .. "\r\n", false) --Units error checking pp.PostP:OutputLine("'Units: " .. UNITS .. "\r\n", false) if UNITS == "Inches" then pp.PostP:OutputLine("IF %(25)=0 THEN GOTO UNIT_OK 'Check to make sure software is set to Inches" .. "\r\n", false) elseif UNITS == "mm" then pp.PostP:OutputLine("IF %(25)=1 THEN GOTO UNIT_OK 'Check to make sure software is set to mm" .. "\r\n", false) end pp.PostP:OutputLine("UNIT_ERROR:" .. "\r\n", false) pp.PostP:OutputLine("CN,91 'Run file explaining Unit Error" .. "\r\n", false) pp.PostP:OutputLine("END" .. "\r\n", false) pp.PostP:OutputLine("UNIT_OK:" .. "\r\n", false) --First path setup and start pp.PostP:OutputLine("SA 'Set program to absolute coordinate mode" .. "\r\n", false) pp.PostP:OutputLine("CN, 90" .. "\r\n", false) pp.PostP:OutputLine("'New Path" .. "\r\n", false) pp.PostP:OutputLine("'Toolpath Name = " .. tostring(pp.TOOLPATH_NAME) .. "\r\n", false) pp.PostP:OutputLine("'Tool Name = " .. tostring(pp.TOOLNAME) .. "\r\n", false) pp.PostP:OutputLine("\r\n", false) pp.PostP:OutputLine("&PWSafeZ = " .. Round(pp.SAFEZ.Value*UnitMultiple) .. "\r\n", false) pp.PostP:OutputLine("&PWZorigin = " .. ZOriginString .. "\r\n", false) pp.PostP:OutputLine("&PWMaterial = " .. Round(pp.ZLENGTH.Value*UnitMultiple) .. "\r\n", false) pp.PostP:OutputLine("'&ToolName = " .. tostring(pp.TOOLNAME) .. "\r\n", false) pp.PostP:OutputLine("&Tool = " .. pp.T.Value .. " 'Tool number to change to" .. "\r\n", false) pp.PostP:OutputLine("C9 'Change tool" .. "\r\n", false) pp.PostP:OutputLine("TR," .. pp.S.Value .. " 'Set spindle RPM" .. "\r\n", false) pp.PostP:OutputLine("C6 'Spindle on" .. "\r\n", false) pp.PostP:OutputLine("PAUSE 2" .. "\r\n", false) pp.PostP:OutputLine("'" .. "\r\n", false) Feedrates() pp.PostP:OutputLine("JZ," .. Round(pp.ZH.Value + MaterialBlock().Thickness * SurfaceAdjust)*UnitMultiple .. "\r\n", false) end function Feedrates() if MaterialBlock().JobType < 2 then pp.PostP:OutputLine("MS," .. Round(pp.FC.Value/60*UnitMultiple) .. "," .. Round(pp.FP.Value/60*UnitMultiple) .. "\r\n", false) elseif MaterialBlock().JobType == 2 then pp.PostP:OutputLine("MS," .. Round(pp.FC.Value/60*UnitMultiple) .. "," .. Round(pp.FP.Value/60*UnitMultiple) .. ",," .. Round((pp.FC.Value/60)/(Diameter*math.pi)*360) .. "\r\n", false) end end function Move() if MaterialBlock().JobType < 2 then pp.PostP:OutputLine("M3," .. Round(pp.X.Value * UnitMultiple) .. "," .. Round(pp.Y.Value * UnitMultiple) .. "," .. Round((pp.Z.Value + MaterialBlock().Thickness * SurfaceAdjust) * UnitMultiple) .. "\r\n", false) elseif MaterialBlock().JobType == 2 then if RotationAxis == 0 then pp.PostP:OutputLine("M5," .. Round(pp.X.Value * UnitMultiple) .. ",," .. Round((pp.Z.Value + MaterialBlock().Thickness * SurfaceAdjust) * UnitMultiple) .. ",," .. DegRound(pp.Y.Value/(math.pi*Diameter)*360) .. "\r\n", false) end if RotationAxis == 1 then pp.PostP:OutputLine("M5,," .. Round(pp.Y.Value * UnitMultiple) .. "," .. Round((pp.Z.Value + MaterialBlock().Thickness * SurfaceAdjust)* UnitMultiple) .. ",," .. DegRound(pp.X.Value/(math.pi*Diameter)*360) .. "\r\n", false) end end end function Jog() if MaterialBlock().JobType < 2 then pp.PostP:OutputLine("J3," .. Round(pp.X.Value * UnitMultiple) .. "," .. Round(pp.Y.Value * UnitMultiple) .. "," .. Round((pp.Z.Value + MaterialBlock().Thickness * SurfaceAdjust) * UnitMultiple) .. "\r\n", false) elseif MaterialBlock().JobType == 2 then if RotationAxis == 0 then pp.PostP:OutputLine("J5," .. Round(pp.X.Value * UnitMultiple) .. ",," .. Round((pp.Z.Value + MaterialBlock().Thickness * SurfaceAdjust) * UnitMultiple) .. ",," .. DegRound(pp.Y.Value/(math.pi*Diameter)*360) .. "\r\n", false) end if RotationAxis == 1 then pp.PostP:OutputLine("J5,," .. Round(pp.Y.Value * UnitMultiple) .. "," .. Round((pp.Z.Value + MaterialBlock().Thickness * SurfaceAdjust) * UnitMultiple) .. ",," .. DegRound(pp.X.Value/(math.pi*Diameter)*360) .. "\r\n", false) end end end function CWArc() pp.PostP:OutputLine("CG, ," .. Round(pp.X.Value*UnitMultiple) .. "," .. Round(pp.Y.Value*UnitMultiple) .. "," .. Round(pp.I.Value*UnitMultiple) .. "," .. Round(pp.J.Value*UnitMultiple) .. ",T,1" .. "\r\n", false) end function CCWArc() pp.PostP:OutputLine("CG, ," .. Round(pp.X.Value*UnitMultiple) .. "," .. Round(pp.Y.Value*UnitMultiple) .. "," .. Round(pp.I.Value*UnitMultiple) .. "," .. Round(pp.J.Value*UnitMultiple) .. ",T,-1" .. "\r\n", false) end function Toolchange() pp.PostP:OutputLine("'Tool Change" .. "\r\n", false) pp.PostP:OutputLine("C7 'Stopping Spindle" .. "\r\n", false) pp.PostP:OutputLine("&TOOL = " .. pp.T.Value .. " 'New Tool Number" .. "\r\n", false) pp.PostP:OutputLine("C9 'Starting Tool Change" .. "\r\n", false) pp.PostP:OutputLine("C6 'Restarting Spindle" .. "\r\n", false) end function NewSegment() pp.PostP:OutputLine("'New Path" .. "\r\n", false) pp.PostP:OutputLine("'Toolpath Name = " .. tostring(pp.TOOLPATH_NAME) .. "\r\n", false) pp.PostP:OutputLine("'Tool Name = " .. tostring(pp.TOOLNAME) .. "\r\n", false) pp.PostP:OutputLine("TR," .. pp.S.Value .. "\r\n", false) Feedrates() pp.PostP:OutputLine("JZ," .. Round((pp.ZH.Value + MaterialBlock().Thickness * SurfaceAdjust)*UnitMultiple) .. "\r\n", false) end function Footer() pp.PostP:OutputLine("JZ," .. Round((pp.ZH.Value + MaterialBlock().Thickness * SurfaceAdjust)*UnitMultiple) .. "\r\n", false) if MaterialBlock().JobType < 2 then pp.PostP:OutputLine("J2," .. Round(pp.XH.Value*UnitMultiple) .. "," .. Round(pp.YH.Value*UnitMultiple) .. "\r\n", false) elseif MaterialBlock().JobType == 2 then if RotationAxis == 0 then pp.PostP:OutputLine("J5," .. Round(pp.XH.Value*UnitMultiple) .. ",,,," .. Round(pp.YH.Value/(math.pi*Diameter)*360) .. "\r\n", false) elseif RotationAxis == 1 then pp.PostP:OutputLine("J5,," .. Round(pp.YH.Value*UnitMultiple) .. ",,," .. Round(pp.XH.Value/(math.pi*Diameter)*360) .. "\r\n", false) end end pp.PostP:OutputLine("'Turning router OFF" .. "\r\n", false) pp.PostP:OutputLine("C7" .. "\r\n", false) end ENDSCRIPT +================================================ + + Block definitions for toolpath output + +================================================ +--------------------------------------------- + Start of file +--------------------------------------------- begin HEADER "Header()" +-------------------------------------------- + Program moves +-------------------------------------------- begin RAPID_MOVE "Jog()" +--------------------------------------------- begin FIRST_FEED_MOVE "Move()" +--------------------------------------------- begin FEED_MOVE "Move()" +--------------------------------------------------- + Commands output for clockwise arc move +--------------------------------------------------- begin CW_ARC_MOVE "CWArc()" +--------------------------------------------------- + Commands output for counterclockwise arc move +--------------------------------------------------- begin CCW_ARC_MOVE "CCWArc()" +--------------------------------------------------- + Commands output at toolchange +--------------------------------------------------- begin TOOLCHANGE "Toolchange()" +--------------------------------------------------- + Commands output for a new segment - toolpath + with same toolnumber but maybe different feedrates +--------------------------------------------------- begin NEW_SEGMENT "NewSegment()" +--------------------------------------------- + End of file +--------------------------------------------- begin FOOTER "Footer()"