--============================================================ -- Fadal 88HS Format 2 SheetCam Post Processor -- Version 2.0 -- -- Developed and machine validated with Mike Akatiff -- -- Validated on: -- _ Fadal VMC -- _ CNC 88HS Control -- _ Format 2 Programming -- -- Expected to be compatible with standard -- Fadal CNC 88 controls using Format 2. -- -- Always perform an air-cut before running any -- new or modified CNC program. -- -- Machine Notes: -- _ Native Fadal G83 (I/J/K/P) -- _ G82 dwell (P) is specified in milliseconds. -- _ G81 and G84 are generated automatically by SheetCam. -- _ G82 and G85 are selected by including "G82" -- or "G85" in the tool or operation name. --============================================================ -------------------------------------------------- -- USER CONFIGURATION -------------------------------------------------- FADAL_USE_G98 = true -- false = G99 FADAL_R_PLANE = 0.100 FADAL_G82_DWELL = 250 FADAL_G89_DWELL = 250 FADAL_RETURN_HOME = true -------------------------------------------------- -- G83 DEEP-HOLE DRILLING CONFIGURATION -------------------------------------------------- -- "Q" = Constant peck G83. SheetCam Peck Depth outputs as Q. -- "IJK" = Native Fadal decreasing-peck G83. -- SheetCam Peck Depth becomes I, the initial peck. -- J is calculated as I x FADAL_G83_REDUCTION. -- K is the minimum peck size. -- P is the distance above the previous cut depth where feed resumes. FADAL_G83_MODE = "IJK" -- "Q" or "IJK" FADAL_G83_REDUCTION = 0.10 -- 10% reduction per peck FADAL_G83_MINIMUM = 0.100 -- Minimum peck FADAL_G83_RESUME = 0.020 -- Feed resume distance -- Example with SheetCam Peck Depth = 0.500: -- I0.500 J0.050 K0.100 P0.020 -- Approximate peck sequence: 0.500, 0.450, 0.400, 0.350 ... minimum 0.100 --========================================================= -- Fadal 88HS Format 2 -- Native SheetCam post processor for Fadal CNC88/88HS Format 2 -- -- Machine validated on a Fadal VMC-10 / 88HS control. -- -- Version history: -- 1.0 Initial native Fadal Format 2 release. -- 1.1 Fixed forced G01 plunge after rapid moves. -- 1.2 Added G98 canned-cycle retract support using SheetCam rapid clearance. -- 1.3 Added cycle override support for G82/G85/G89 by post variable, -- operation name, or tool name. -- 1.4 Added default P0.5 dwell for G82 and G89. G85 remains no-dwell. -- Preferred cycle selection is by including G82, G85, or G89 in the tool name. -- 1.6 Added selectable G83 Q or native Fadal I/J/K/P decreasing-peck output. -- -- Basic cycle rules: -- Normal drill, no peck: G81 -- Peck drill: G83 -- Tapping: G84 -- Optional cycles: G82/G85/G89 by override -- -- Optional override methods: -- 1) Set Post Variable, if available in your SheetCam installation: -- Name: Cycle -- Value: G85 (or G82, G89, AUTO) -- 2) Put G85, G89, or G82 in the drilling operation name. -- 3) Put G85, G89, or G82 in the tool name. -- -- Notes: -- Keep Output File Units set to Inch for this Fadal setup. -- G98 uses SheetCam Rapid Clearance as the between-hole return height. -- R plane is controlled by FADAL_CYCLE_R_PLANE below. --========================================================= function OnAbout(event) ctrl = event:GetTextCtrl() ctrl:AppendText("Fadal 88HS Format 2 Ver 2.0 Final - Native Fadal G83 I/J/K/P test\n") ctrl:AppendText("\n") ctrl:AppendText("Non modal G-codes\n") ctrl:AppendText("Modal coordinates\n") ctrl:AppendText("Comments enclosed with ( and )\n") ctrl:AppendText("Incremental IJ\n") ctrl:AppendText("uses G43 tool length offsets\n") end function OnInit() -- ACK Technologies / Fadal VMC-10 88HS Format 2 native start. -- No percent marks: the 88HS editor treats % as a mark and faults. OnNewLine = nil post.SetCommentChars ("()", "[]") --make sure ( and ) characters do not appear in system text -- Fixed program number for drip/load compatibility. Change if desired. post.Text("O1001\n") post.Text ("(Filename: ", fileName, ")\n") post.Text ("(Post processor: ", postName, ")\n") post.Text ("(Fadal 88HS Format 2 Post V2.0 Cycle Name Fix)\n") post.Text("(Date:",date," Time:",time,")\n") OnNewLine = OnNewLine2 if(scale == metric) then post.Text (" G21 (Units: Metric)\n") --metric mode else post.Text (" G20 (Units: Inches)\n") --inch mode end post.Text (" G17 G90 G40 G80\n E1\n") bigArcs = 1 --stitch arc segments together minArcSize = 0.05 --arcs smaller than this are converted to moves end function OnNewLine2() post.Text ("N") post.Number (lineNumber, "0000") lineNumber = lineNumber + 10 end --========================================================= -- User-adjustable Fadal clearance settings, in programmed units. -- For inch programs these are inches. For metric programs these output as mm. -- The values below were chosen from machine testing to avoid slow cycles -- caused by unnecessary Z0.4 clearance moves. --========================================================= FADAL_RAPID_CLEARANCE = 0.100 FADAL_CYCLE_R_PLANE = 0.100 -- For canned cycles only: start the cycle from SheetCam rapid clearance (safeZ). -- With G98 the Fadal returns to this initial Z after each hole, but feeds only from R. FADAL_USE_SHEETCAM_RAPID_CLEARANCE_FOR_G98 = true function FadalProgramUnitsToInternal(v) -- Internal SheetCam values are converted to output by multiplying by scale. -- Therefore divide programmed values by scale before passing to FadalOutWord. return v / scale end -- Canned cycle state for Fadal Format 2. -- The Fadal should see the cycle command once, then only X/Y hole positions. cycleActive = false activeCycle = "" function CancelCycleIfActive() if cycleActive then post.Text(" G80\n") cycleActive = false activeCycle = "" end end function FadalRPlane() -- Fixed Fadal canned-cycle R plane. -- Do not use SheetCam's high clearance value here because it slows drilling. -- Default output is R0.100 in inch mode. return FadalProgramUnitsToInternal(FADAL_CYCLE_R_PLANE) end function FadalCycleInitialPlane() -- Initial plane for G98 canned cycles. This should be high enough to clear -- clamps/fixtures between holes. SheetCam stores this as safeZ/rapid clearance. local rplane = FadalRPlane() local z = rplane if FADAL_USE_SHEETCAM_RAPID_CLEARANCE_FOR_G98 and safeZ and safeZ > rplane then z = safeZ end return z end function FadalRapidToCycleInitialPlane() -- Force the initial plane before starting a canned cycle so G98 has a -- high return point. This does not change the R plane/feed start height. local z = FadalCycleInitialPlane() post.Text(" G00") FadalOutWord("Z", z, "0.0###") post.Eol() end function FadalOutWord(letter, value, fmt) -- Use explicit letter output. Some SheetCam/Fadal combinations dropped the R -- when post.NonModalNumber(" R",...) was used, leaving an unlabeled number. post.Text(" ", letter) post.Number(value * scale, fmt or "0.0###") end function FadalOutPlain(letter, value, fmt) post.Text(" ", letter) post.Number(value, fmt or "0.###") end function StartOrContinueFadalCycle(cycle, zval, rplane, qval, dwellval, fval) if (not cycleActive) or (activeCycle ~= cycle) then -- First hole: rapid to the SheetCam clearance height first. -- G98 then makes the Fadal return to that initial Z between holes. FadalRapidToCycleInitialPlane() -- First hole: start the canned cycle at the current X/Y. post.Text(" ", cycle, " G98") FadalOutWord("X", endX, "0.0###") FadalOutWord("Y", endY, "0.0###") FadalOutWord("Z", zval, "0.0###") FadalOutWord("R", rplane, "0.0###") if cycle == "G83" and qval and (qval * scale) > 0.0005 then local g83Mode = string.upper(tostring(FADAL_G83_MODE or "Q")) if g83Mode == "IJK" then -- Native Fadal decreasing-peck cycle: -- I = SheetCam initial peck -- J = reduction amount calculated from the initial peck -- K = minimum peck -- P = feed-resume distance above the previous cut depth local initialPeck = qval local reduction = initialPeck * FADAL_G83_REDUCTION FadalOutWord("I", initialPeck, "0.0###") FadalOutWord("J", reduction, "0.0###") FadalOutWord("K", FadalProgramUnitsToInternal(FADAL_G83_MINIMUM), "0.0###") FadalOutWord("P", FadalProgramUnitsToInternal(FADAL_G83_RESUME), "0.0###") else -- Constant-peck cycle. SheetCam Peck Depth outputs directly as Q. FadalOutWord("Q", qval, "0.0###") end end if (cycle == "G82" or cycle == "G89") and dwellval and dwellval > 0 then FadalOutPlain("P", dwellval, "0.###") end post.Text(" F") post.Number(fval * scale, "0.0###") post.Eol() cycleActive = true activeCycle = cycle else -- Additional holes: with the Fadal cycle active, output only the next position. FadalOutWord("X", endX, "0.0###") FadalOutWord("Y", endY, "0.0###") post.Eol() end end function OnFinish() -- End sequence verified for the Fadal 88HS. -- Cancel any active canned cycle, return to program X0/Y0 if needed, -- stop spindle, cancel cutter comp, cancel tool length, and end program. CancelCycleIfActive() local atXYZero = (math.abs((currentX or 0)) < 0.0005) and (math.abs((currentY or 0)) < 0.0005) if not atXYZero then post.Text (" G00 X0.0 Y0.0\n") end post.Text (" M05\n") post.Text (" G40\n") post.Text (" H0\n") post.Text (" M30\n") end function OnRapid() CancelCycleIfActive() -- Suppress SheetCam's rapid plunge close to final depth, for example: -- Z-0.1053 -- G01 Z-0.125 -- The Fadal should feed from clearance to cutting depth instead of rapiding below Z0. if (endZ < 0) and (math.abs(endX - currentX) < 0.000001) and (math.abs(endY - currentY) < 0.000001) then return end -- Keep clearance moves close to the part by default. -- If SheetCam outputs Z0.4, this post outputs Z0.100 unless the value above -- is changed in FADAL_RAPID_CLEARANCE. local zOut = endZ if zOut > FadalProgramUnitsToInternal(FADAL_RAPID_CLEARANCE) then zOut = FadalProgramUnitsToInternal(FADAL_RAPID_CLEARANCE) end -- Output G00 through ModalText so SheetCam's modal state knows the control is in rapid. -- This forces the next feed move to print G01, instead of leaving a bare Z move -- that the Fadal would execute at rapid speed. post.ModalText (" G00") post.ModalNumber (" X", endX * scale, "0.0###") post.ModalNumber (" Y", endY * scale, "0.0###") post.ModalNumber (" Z", (zOut + toolOffset) * scale, "0.0###") post.Eol() end function OnMove() CancelCycleIfActive() post.ModalText (" G01") post.ModalNumber (" X", endX * scale, "0.0###") post.ModalNumber (" Y", endY * scale, "0.0###") post.ModalNumber (" Z", (endZ + toolOffset) * scale, "0.0###") post.ModalNumber (" F", feedRate * scale, "0.0###") post.Eol() end function OnArc() CancelCycleIfActive() if(arcAngle <0) then post.ModalText (" G03") else post.ModalText (" G02") end post.NonModalNumber (" X", endX * scale, "0.0###") post.NonModalNumber (" Y", endY * scale, "0.0###") post.ModalNumber (" Z", (endZ + toolOffset) * scale, "0.0###") post.Text (" I") post.Number ((arcCentreX - currentX) * scale, "0.0###") post.Text (" J") post.Number ((arcCentreY - currentY) * scale, "0.0###") post.ModalNumber (" F", feedRate * scale, "0.0###") post.Eol() end function OnSpindleCW() post.ModalNumber (" S", spindleSpeed, "0.##") post.Text (" M03") post.Eol() end function OnSpindleCCW() post.ModalNumber (" S", spindleSpeed, "0.##") post.Text (" M04") post.Eol() end function OnSpindleOff() -- Suppress standalone M05. OnFinish handles spindle stop. end function OnNewOperation() CancelCycleIfActive() post.Text (" (Operation: ", operationName, ")\n") end function OnComment() post.Text(" (",commentText,")\n") end function OnToolChange() CancelCycleIfActive() post.Text (" (", toolName, ")\n") post.Text (" T") post.Number (tool, "0") post.Text (" M06\n") post.Text(" G43 H") post.Number (tool, "0") post.Eol() if (plungeRate <= 0) then post.Warning("WARNING: Plunge rate is zero") end if (feedRate <= 0) then post.Warning("WARNING: Feed rate is zero") end end function OnSpindleChanged() post.ModalNumber (" S", spindleSpeed, "0.##") if (spindleSpeed <= 0) then post.Warning("WARNING: Spindle speed is zero") end end function OnNewPart() post.Text(" (Part: ",partName,")\n"); end function OnFloodOn() post.Text(" M08 (Flood coolant on)\n") end function OnMistOn() post.Text(" M07 (Mist coolant on)\n") end function OnCoolantOff() post.Text(" M09 (Coolant off)\n") end function FadalPeckValue() -- V2.2: Use SheetCam's actual drillPeck value only. -- Earlier versions also checked peckDepth/peck/drillQ, but on this SheetCam -- install one of those values can be the total drill depth. That caused false -- G83 output and Q equal to the full hole depth. -- Rule: drillPeck <= 0 means standard drill G81, no Q word. if drillPeck and (drillPeck * scale) > 0.0005 then return drillPeck end return 0 end function FadalHasPeck() return FadalPeckValue() > 0 end function FadalDwellValue(cycle) if cycle == "G82" then return FADAL_G82_DWELL elseif cycle == "G89" then return FADAL_G89_DWELL end return 0 end function FadalNormalizeCycle(v) -- Accept G81/G82/G83/G84/G85/G89, or AUTO/NONE to cancel override. if not v then return "" end local s = string.upper(tostring(v)) s = string.gsub(s, "%s+", "") if s == "" or s == "AUTO" or s == "NONE" or s == "OFF" then return "" end if string.sub(s,1,1) ~= "G" and tonumber(s) then s = "G" .. s end if s == "G81" or s == "G82" or s == "G83" or s == "G84" or s == "G85" or s == "G89" then return s end return "" end function FadalGetCycleOverride() -- SheetCam's "Set post variable" operation may expose the variable as a Lua global. -- This checks several likely names. The safest user-facing name is: Cycle local names = {"Cycle", "cycle", "FadalCycle", "fadalCycle", "FADAL_CYCLE", "CannedCycle", "cannedCycle"} for i, n in ipairs(names) do local c = FadalNormalizeCycle(_G[n]) if c ~= "" then return c end end return "" end function FadalCycleCode() local opname = string.lower(operationName or "") local tname = string.lower(toolName or "") -- Make cycle-name recognition tolerant of spaces and punctuation. -- Examples that all work: G82, G 82, [G82], G-82. local opcompact = string.gsub(opname, "[^a-z0-9]", "") local tcompact = string.gsub(tname, "[^a-z0-9]", "") -- Highest priority: SheetCam Set Post Variable if it creates one of these globals. local override = FadalGetCycleOverride() if override ~= "" then return override end -- Manual override by operation or tool name. if string.find(opcompact, "g89", 1, true) or string.find(tcompact, "g89", 1, true) or string.find(opname, "bore dwell", 1, true) or string.find(opname, "dwell bore", 1, true) then return "G89" end if string.find(opcompact, "g85", 1, true) or string.find(tcompact, "g85", 1, true) or string.find(opname, "boring", 1, true) or string.find(tname, "boring", 1, true) or string.find(tname, "bore", 1, true) then return "G85" end if string.find(opcompact, "g82", 1, true) or string.find(tcompact, "g82", 1, true) or string.find(opname, "spot", 1, true) or string.find(tname, "spot", 1, true) or string.find(opname, "counterbore", 1, true) then return "G82" end if string.find(opcompact, "g83", 1, true) or string.find(tcompact, "g83", 1, true) then return "G83" end if string.find(opcompact, "g84", 1, true) or string.find(tcompact, "g84", 1, true) or string.find(opname, "tap", 1, true) or string.find(tname, "tap", 1, true) then return "G84" end -- Normal SheetCam behavior: no peck = G81; nonzero peck = G83. if FadalHasPeck() then return "G83" end return "G81" end function OnDrill() local cycle = FadalCycleCode() local rplane = FadalRPlane() local qval = FadalPeckValue() local pval = FadalDwellValue(cycle) -- Absolute safety: never allow G83 with zero drillPeck. if cycle == "G83" and not FadalHasPeck() then cycle = "G81" end -- Fadal dwell defaults. A dwell entered in SheetCam overrides these values. -- G85 is intentionally excluded because it is a feed-in/feed-out cycle with no dwell. if cycle == "G82" and (not pval or pval <= 0) then elseif cycle == "G89" and (not pval or pval <= 0) then elseif cycle == "G85" then pval = 0 end StartOrContinueFadalCycle(cycle, drillZ, rplane, qval, pval, feedRate) endZ = safeZ end function OnSetFeed() end function OnTapStart() CancelCycleIfActive() -- Fadal floating tap holder tapping. Feed must match pitch x RPM. post.Text(" G94\n") end function OnAutoTap() local rplane = FadalRPlane() feedRate = tapPitch * spindleSpeed StartOrContinueFadalCycle("G84", drillZ, rplane, nil, nil, feedRate) endZ = safeZ end function OnRigidTap() -- Use same floating tap cycle as AutoTap for Version A. OnAutoTap() end function OnTapEnd() CancelCycleIfActive() post.Text(" G94\n") end