Hello Guest it is April 18, 2024, 07:41:57 AM

Author Topic: Consolidated Answer - Control Panel and Hybrid stepper Motor Driver Alarms  (Read 712 times)

0 Members and 1 Guest are viewing this topic.

Here is my final (?) code that got my control panel et al working.

Code: [Select]
--------------------------------------------------------------
-- 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()

I've been working on some lathe jobs since the control panel was installed and programmed, and Sweet Mother of Lob was all that worth it!

The increase in productivity between the jog handle and the program run controls is just off the charts. Setup is just so much less fiddly.