Here is my final (?) code that got my control panel et al working.
--------------------------------------------------------------
-- Added by DG May 30 2021 to enable the control panel
-- Monitor the switches on the control panel.
-- We break the three different mechanical switches into three separate function calls, since each function has a separate job.
-- We don't need to assign the MPG wheel since Mach handles that for us.
---------------------------------------------------------------
SigLib = {
-------------
-- Axis Select Switch
-- Must always be X or Y
[mc.ISIG_INPUT5] = function (state) -- X Axis Select signal 5
PendantAxisChange()
end,
[mc.ISIG_INPUT4] = function (state) -- Z Axis Select signl 4
PendantAxisChange()
end,
-------------
-- Jog Enable / Speed
-- 4-position rotary switch
-- No active signals mean JOG OFF
[mc.ISIG_INPUT6] = function (state) -- Enable Jog Speed 0.1 signal 6
PendantSpeedChange()
end,
[mc.ISIG_INPUT7] = function (state) -- Enable Jog Speed 0.01 signal 7
PendantSpeedChange()
end,
[mc.ISIG_INPUT8] = function (state) -- Enable Jog Speed 0.001 signal 8
PendantSpeedChange()
end,
-------------
-- Axis driver Alarms
-- Each motor driver has an alarm line that goes high
-- if ********* goes south
-- Stop machine and recover using external reset switches
[mc.ISIG_INPUT9] = function (state) -- X Axis
mc.mcCntlSetLastError(inst, "X Axis driver ALARM - STOPPING")
eStop()
end,
[mc.ISIG_INPUT10] = function (state) -- Z axis
mc.mcCntlSetLastError(inst, "Z Axis driver ALARM - STOPPING")
eStop()
end,
-------------
-- Cycle Start Panel Button
[mc.ISIG_INPUT1] = function (state) -- Signal 1
InputCycleStart()
end,
--------------
-- Feed Hold Panel Button
[mc.ISIG_INPUT2] = function (state) -- Signal 2
InputFeedHold()
end,
---------------
-- Manual Spindle ON/OFF Panel Button
[mc.ISIG_INPUT3] = function (state) -- Starts the spindle manually signal 3
InputManualSpindle()
end,
----------------
-- Feed Hold Light
-- We waant to blink this during tool change
-- So watch the native FEED HOLD signal
-- And toggle the LED if Mach changes state
[mc.OSIG_FEEDHOLD] = function (state)
local inst = mc.mcGetInstance()
local hSig = mc.mcSignalGetHandle(inst, mc.OSIG_OUTPUT6) -- Output 6
if( state == 1) then
mc.mcSignalSetState(hSig, mc.MC_ON)
else
mc.mcSignalSetState(hSig, mc.MC_OFF)
end
end,
--------------------
-- Tool Change
--- So we can blink the panel light
[mc.OSIG_TOOL_CHANGE] = function (state)
local inst = mc.mcGetInstance()
if( state == 1) then
--Start timer to flash feed hold LED 500ms interval
FeedHoldTimer:Start(500, false)
else
--Stop timer and turn off feed hold LED in case it's still on.
FeedHoldTimer:Stop()
local hSig = mc.mcSignalGetHandle(inst, mc.OSIG_OUTPUT6) -- Output 6
mc.mcSignalSetState(hSig, mc.MC_OFF)
end
end
}
---------------------------------------------------------------
-- Tool Change LED blink function
---------------------------------------------------------------
FeedHoldTimerPanel = wx.wxPanel (wx.NULL, wx.wxID_ANY, wx.wxDefaultPosition, wx.wxSize( 0,0 ) )
FeedHoldTimer = wx.wxTimer(FeedHoldTimerPanel)
FeedHoldTimerPanel:Connect(wx.wxEVT_TIMER,
function (event)
local inst = mc.mcGetInstance()
local hSig = mc.mcSignalGetHandle(inst, mc.OSIG_OUTPUT6) -- Output 6
local sSig = mc.mcSignalGetState(hSig)
if sSig == mc.MC_ON then
mc.mcSignalSetState(hSig, mc.MC_OFF)
else
mc.mcSignalSetState(hSig, mc.MC_ON)
end
end)
---------------------------------------------------------------
-- Control Panel Cycle Start
---------------------------------------------------------------
function InputCycleStart()
-- Momentary pushbutton, so we get TWO signals with each button press:
-- an "ON" and an "OFF"
-- So check state and ignore the "OFF"
local hStartButton
local StartButtonState
hStartButton, rc = mc.mcSignalGetHandle(inst, mc.ISIG_INPUT1) -- signal 1
StartButtonState, rc = mc.mcSignalGetState(hStartButton)
mc.mcCntlSetLastError(inst, "Control Panel Cycle Start PRESS")
if (StartButtonState == 1) then
CycleStart()
mc.mcCntlSetLastError(inst, "Control Panel CYCLE START")
else
mc.mcCntlSetLastError(inst, "Control Panel Cycle Start RELEASE")
end
end
---------------------------------------------------------------
-- Control Panel Feed Hold
-- One push for Feed Hold, two pushes for Cycle Stop
---------------------------------------------------------------
function InputFeedHold()
-- Momentary pushbutton, so we get TWO signals with each button press:
-- an "ON" and an "OFF"
-- So check state and ignore the "OFF"
local hHoldButton
local HoldButtonState
hHoldButton, rc = mc.mcSignalGetHandle(inst, mc.ISIG_INPUT2) -- signal 2
HoldButtonState, rc = mc.mcSignalGetState(hHoldButton)
if (HoldButtonState == 1) then
mc.mcCntlSetLastError(inst, "Control Panel Feed Hold PRESS")
-- If we are running a program, pause
-- If we are already paused, stop
local Running
local Paused
Running, rc = mc.mcCntlGetState(inst)
Paused, rc = mc.mcCntlFeedHoldState(inst)
if (Paused == 1) then -- We are paused, so stop
CycleStop()
mc.mcCntlSetLastError(inst, "Control Panel CYCLE STOP")
elseif ((Running == mc.MC_STATE_FRUN ) or (Running == mc.MC_STATE_MRUN)) then -- We are running, so do something.
-- Have to check both File and MDI because
-- Mach differentiates between them!
rc = mc.mcCntlFeedHold(inst)
mc.mcCntlSetLastError(inst, "Control Panel FEED HOLD")
else
-- Spurious button press
mc.mcCntlSetLastError(inst, "Not running or paused - IGNORE ME")
end
else
mc.mcCntlSetLastError(inst, "Control Panel Feed Hold RELEASE")
end
end
---------------------------------------------------------------
-- Control Panel Manual Spindle
---------------------------------------------------------------
function InputManualSpindle()
-- Momentary pushbutton, so we get TWO signals with each button press:
-- an "ON" and an "OFF"
-- So check state and ignore the "OFF"
local hSpindleButton
local SpindleButtonState
hSpindleButton, rc = mc.mcSignalGetHandle(inst, mc.ISIG_INPUT3) -- signal 3
SpindleButtonState, rc = mc.mcSignalGetState(hSpindleButton)
if (SpindleButtonState == 1) then
mc.mcCntlSetLastError(inst, "Control Panel Manual Spindle PRESS")
local hsig = mc.mcSignalGetHandle(inst, mc.OSIG_SPINDLEFWD)
local spinstate = mc.mcSignalGetState(hsig)
if (spindstate == 0) then -- If spindle is off, turn it on
-- mc.mcSignalSetState(hsig, 1)
SpinCW()
mc.mcCntlSetLastError(inst, "Control Panel Manual Spindle ON")
else -- Otherwise, turn it off
-- mc.mcSignalSetState(hsig, 0)
SpinCW()
mc.mcCntlSetLastError(inst, "Control Panel Manual Spindle OFF")
end
else
mc.mcCntlSetLastError(inst, "Control Panel Manual Spindle RELEASE")
end
end
----------------------------
-- We use MPG 7
local MachMpgNumberForPendant = 7
local PendantStepSize = 0.001
local PendantDistanceX1 = PendantStepSize * 1 -- Multiply by one (0.001)
local PendantDistanceX10 = PendantStepSize * 10 -- Multiply by ten (0.01)
local PendantDistanceX100 = PendantStepSize * 100 -- Multiply by one hundred (0.1)
-- Constants for readability
local UnmapMPG = -1 -- Use this one for when Axis selector switch is set to OFF
local AxisNumber_X = 0 -- Linear axis X
local AxisNumber_Z = 2 -- Linear axis Z
---------------------------------------------------------------
-- Jog Speed/Enable Rotary Switch
---------------------------------------------------------------
function PendantSpeedChange()
local hX1
local hX10
local hX100
-- Need to get current state of axis selector switch so we move the right axis
local hAxis_X -- X Axis Select Switch
local hAxis_Z -- Z Axis Select Switch
local Step1
local Step10
local Step100
local msg
hX1, rc = mc.mcSignalGetHandle(inst, mc.ISIG_INPUT8) -- Speed 0.001 signal 8
Step1, rc = mc.mcSignalGetState(hX1)
hX10, rc = mc.mcSignalGetHandle(inst, mc.ISIG_INPUT7) -- Speed 0.01 signal 7
Step10, rc = mc.mcSignalGetState(hX10)
hX100, rc = mc.mcSignalGetHandle(inst, mc.ISIG_INPUT6) -- Speed 0.1 signal 6
Step100, rc = mc.mcSignalGetState(hX100)
-- Jog Active Light handle
local hJogLight
hJogLight, rc = mc.mcSignalGetHandle(inst, mc.OSIG_OUTPUT5) -- Jog Light Signal 5
-- Figure out which axis is active by reading the axis select switch
hAxis_X, rc = mc.mcSignalGetHandle(inst, mc.ISIG_INPUT4) -- If X is selected, activate X signal 4
SelectAxis_X, rc = mc.mcSignalGetState(hAxis_X)
hAxis_Z, rc = mc.mcSignalGetHandle(inst, mc.ISIG_INPUT5) -- If Z is selected, activate Z signal 5
SelectAxis_Z, rc = mc.mcSignalGetState(hAxis_Z)
-- TODO - This should really check that we have X || Z, but not neither or both!
if (SelectAxis_X == 1) then
mc.mcMpgSetAxis(inst, MachMpgNumberForPendant, AxisNumber_X) -- Map the MPG to control the X Axis
mc.mcCntlSetLastError(inst, "Jog Axis X Selected") -- Show a message in the Screen Set
elseif (SelectAxis_Z== 1) then
mc.mcMpgSetAxis(inst, MachMpgNumberForPendant, AxisNumber_Z) -- Map the MPG to control the Z Axis
mc.mcCntlSetLastError(inst, "Jog Axis Z Selected") -- Show a message in the Screen Set
end
if (Step1 == 1) then
mc.mcMpgSetInc(inst, MachMpgNumberForPendant, PendantDistanceX1 )
mc.mcSignalSetState(hJogLight, 1) -- Turn Jog light on
msg = "Jog Active X1 = " .. PendantDistanceX1
mc.mcCntlSetLastError(inst, msg) -- Show a message in the Screen Set
elseif (Step10 == 1) then
mc.mcMpgSetInc(inst, MachMpgNumberForPendant, PendantDistanceX10)
mc.mcSignalSetState(hJogLight, 1) -- Turn Jog light on
msg = "Pendant Distance X10 = " .. PendantDistanceX10
mc.mcCntlSetLastError(inst, msg) -- Show a message in the Screen Set
elseif (Step100 == 1) then
mc.mcMpgSetInc(inst, MachMpgNumberForPendant, PendantDistanceX100)
mc.mcSignalSetState(hJogLight, 1) -- Turn Jog light on
msg = "Pendant Distance X100 = " .. PendantDistanceX100
mc.mcCntlSetLastError(inst, msg) -- Show a message in the Screen Set
else
-- If we got here, it means the one of the speed inputs changed, but none are active
-- That means "JOG OFF"
mc.mcMpgSetInc(inst, MachMpgNumberForPendant, 0 ) -- TODO Can we set the jog distance to 0?
mc.mcSignalSetState(hJogLight, 0) -- Turn Jog light off
mc.mcMpgSetAxis(inst, MachMpgNumberForPendant, UnmapMPG ) -- Unmap the MPG, so it won't control any axes
mc.mcCntlSetLastError(inst, "Jog Handle Disabled") -- Show a message in the Screen Set
end
end
---------------------------------------------------------------
-- The Pendant's Axis switch changed.
-- Need to handle this for when the axis switch is flipped while jogging is active
---------------------------------------------------------------
function PendantAxisChange()
-- handles
local hAxis_X
local hAxis_Z
local SelectAxis_X
local SelectAxis_Z
-- Before we do anything, we need to check if the jog handle is assigned to axis -1
-- If it is, jog is DISABLED, so we do nothing (the act of enabling jog will read the axis switch)
-- Otherwise we enable jog, which is BAD
-- TODO - need a function to check which axis is assigned
-- This is a guess!
local AxisState
AxisState, rc = mc.mcMpgGetAxis(inst, MachMpgNumberForPendant)
if (AxisState ~= UnmapMPG) then
hAxis_X, rc = mc.mcSignalGetHandle(inst, mc.ISIG_INPUT4)
SelectAxis_X, rc = mc.mcSignalGetState(hAxis_X)
hAxis_Z, rc = mc.mcSignalGetHandle(inst, mc.ISIG_INPUT5)
SelectAxis_Z, rc = mc.mcSignalGetState(hAxis_Z)
-- Now actual axis Selection Switch processing code
if (SelectAxis_X == 1) then
mc.mcMpgSetAxis(inst, MachMpgNumberForPendant, AxisNumber_X) -- Map the MPG to control the X Axis
mc.mcCntlSetLastError(inst, "Pendant Axis X Selected") -- Show a message in the Screen Set
elseif (SelectAxis_Z== 1) then
mc.mcMpgSetAxis(inst, MachMpgNumberForPendant, AxisNumber_Z) -- Map the MPG to control the Z Axis
mc.mcCntlSetLastError(inst, "Pendant Axis Z Selected") -- Show a message in the Screen Set
else
-- This is a problem, because the axis select switch is one or the other
-- We have no high pin - so shut off jogging
mc.mcMpgSetAxis(inst, MachMpgNumberForPendant, UnmapMPG ) -- Unmap the MPG, so it won't control any axes
mc.mcCntlSetLastError(inst, "ABEND - no valid axis selected on control panel!") -- Show a message in the Screen Set
end
else
mc.mcCntlSetLastError(inst, "Changed axis select while jog disabled - IGNORED")
end
end
-- Set jog state when the Screen is loaded by Mach4
PendantSpeedChange()