Hello Guest it is October 18, 2026, 07:29:29 AM

Recent Posts

Pages: « 1 2 3 4 5 6 7 8 9 10 »
71
MachPro General Discussion / Re: MachPro upgrade questions
« Last post by paul.stephens on September 17, 2026, 11:42:34 AM »
Hi,

Quote
Can I also assume that any functionality that I would normally include in the Mach4 ScreenLoad script I can include in UserGUIModule.mcs?

That is correct! We Ideally want to keep any custom User logic abstracted from the main framework. It is the same way for MCodes as well. We have a UserMCodeModule that is used for MCodes. The process is slightly different for them, but the results are the same.

I'll run through the basics of the MCode as well..

How to make a new MCode:

What is an MCode?
An MCode is a command in a part program (G-code file) that makes the machine do something other than move; turn a spindle on, open a clamp, run a probe routine, and so on. MCodes look like M3 (spindle clockwise) or M30 (end of program).

Mach comes with many MCodes already built in. You can also create your own, for example, M500 could turn on a vacuum pump, open a door, or run any sequence your machine needs. This guide walks through creating M500 from scratch. The same steps work for any new MCode, just pick a number that isn't already used (numbers 500 and above are the safest choices for custom codes).

The Big Picture (two files, two jobs)
A custom MCode needs two files. Keeping them straight is the whole trick:

FileFolder PathJob / Description
m500.mcsMach\Profiles\<your profile>\Macros\The doorbell. When the machine sees M500 in a program, it looks for and runs this file. Without this file, nothing happens, ever.
UserMCodeModule.mcs     Mach\Profiles\<your profile>\Macros\Scripts\     The brain. This is where you write what M500 actually does.

Think of it this way: the machine can't call you unless you have a doorbell (m500.mcs). The doorbell's only job is to ring you. What you do when you answer is written in the brain (UserMCodeModule.mcs).

Adding a Custom MCode:
Step 1: Create the doorbell: m500.mcs
Open the folder Mach\Profiles\<your profile>\Macros\.
Create a new plain-text file named exactly m500.mcs (all lowercase; not M500.txt, not m500.mcs.txt - Windows sometimes hides the extension, so double-check).
Paste this in, exactly as shown, and save:
Code: [Select]
function m500(hVars, GcodeComment)
    return m.InvokeMacro('m500', hVars, GcodeComment)
end

if (mc.mcInEditor() == 1) then
    m500()
end
You never need to edit this file again. It simply says: "When M500 runs, go find my instructions in UserMCodeModule."

If someday you add M501, M502, etc., each gets its own copy of this file with only the number changed (m501.mcs containing function m501(...) / m.InvokeMacro('m501', ...)).

Step 2: Create the brain; UserMCodeModule.mcs
Open the folder Mach\Profiles\<your profile>\Macros\Scripts\.

Check whether UserMCodeModule.mcs already exists:

If it exists: open it in a text editor (or the Mach script editor) and skip to step 4 - you'll just add to it.
If it does not exist: create it and paste in the starter template below.
Starter template for a brand-new UserMCodeModule.mcs:
Code: [Select]
local UserMCodeModule = {}

-- Custom MCode functions go here (Step 4).

return UserMCodeModule
Now write what M500 should do. Add this function inside the file (between the two lines of the starter template):
Code: [Select]
function UserMCodeModule.m500(hVars)
    ------------------ Your instructions go below this line ------------------

    -- Example: turn OUTPUT #4 on.
    local hReg, rc = mc.mcRegGetHandle(inst, "mc.OSIG_OUTPUT4")
    if rc == mc.MERROR_NOERROR then
        mc.mcRegSetValue(hReg, 1)
    end

    ------------------ Don't edit below this line ------------------
    return true, true, w.FunctionCompleted()
end

What the parts mean:

function UserMCodeModule.m500(hVars); the name must match the MCode: m500 for M500, m501 for M501, and so on. This is how the doorbell finds the right instructions.
The middle is where you put your actual machine logic: turn outputs on/off, wait for inputs, jog an axis, write to registers, show a message, anything the Mach scripting API can do.
return true, true, w.FunctionCompleted(); the standard "I finished successfully" sign-off. Leave it as the last line.

If something can go wrong, report it like this instead of the success line:
Code: [Select]
    return nil, false, "M500 failed: vacuum sensor never turned on"Returning false as the second value stops the program and shows your message to the operator as an alarm, which is exactly what you want when a safety check fails.
Save the file.

Step 3: Try it
Restart Mach (or reload the screen script) so it picks up the new files.
Go to the MDI line, type M500, and press Enter.
Your instructions run. In the example above, output #4 turns on.
If nothing happens
Check these in order:
  • m500.mcs exists in Profiles<your profile>\Macros\ -  spelled exactly, lowercase, with the .mcs extension, not .txt. This is the most common mistake. Without the doorbell file, the brain never gets called.
  • The function inside UserMCodeModule is named m500 exactly; lowercase m, matching the number.
  • UserMCodeModule.mcs starts with local UserMCodeModule = {} and ends with return UserMCodeModule.
  • You restarted Mach or compiled scripts after saving.
  • You edited the files in the profile you are actually running, not a different profile's folder.

Optional extras (when you're comfortable)
Code: [Select]
Passing a value to your MCode. You can write M500 P1 in a program and read the P value inside your function:
function UserMCodeModule.m500(hVars)
    local pValue, ok, errMsg = m.GetMCodeLocalVar(hVars, mc.SV_P)
    if ok ~= true then
        pValue = 0   -- P word wasn't given; use a default
    end
    -- ... use pValue to decide what to do ...
    return true, true, w.FunctionCompleted()
end

Safety lockout. If M500 must not run unless a guard is closed, check that input first and return nil, false, "message" to abort with an alarm before doing anything else.

Where the GUI module fits. You may also have a UserGUIModule.mcs file in the same Scripts folder. That file is for screen behavior (buttons, the PLC script, LEDs) - not MCodes. MCode logic always belongs in UserMCodeModule.mcs. If your M500 needs something visible on screen (like an indicator), the screen part goes in UserGUIModule and the machine action stays in UserMCodeModule.

How to modify an existing MCode

First: The Golden Rule
Never edit the stock macro files. Every built-in MCode (M3, M5, M6, M8, M30, …) already has a file in Mach\Profiles\<your profile>\Macros\ - like m3.mcs - plus built-in logic inside Mach's modules. Do not edit those files, and do not edit Mach's modules. Why:

Updates will overwrite your changes. When MachPro software is updated, stock files get replaced and your edits silently vanish.
You don't need to. Mach has a built-in extension system - called hooks - designed exactly for this. Your changes go in your file: UserMCodeModule.mcs in Mach\Profiles\<your profile>\Macros\Scripts\. That file is yours; updates never touch it.

The Big Picture: Hooks
Every built-in MCode runs its job in stages, and at specific points it pauses and asks: "Does the user have anything to say about this?" Those asking-points are hooks. For example, when M3 (spindle forward) runs, it asks at these moments, in this order:
Code: [Select]
M3 starts
  → hook "m3"        (before anything happens)
  → the built-in job (start the spindle)
  → hook "m3End"     (after the job finished)

If you wrote a function named UserMCodeModule.m3 in your UserMCodeModule.mcs file, it gets called at that first hook point. If you wrote UserMCodeModule.m3End, it gets called at the second. If you wrote neither, Mach shrugs and carries on; hooks are purely optional.

Most MCodes follow this pattern: a hook named after the code (m3, m8, m6…) that runs before the built-in job, and an …End hook (m3End, m8End, m6End…) that runs after it.

Your Two Choices:
When a hook is called, your function answers one question: should the built-in job still run? Your answer is the first value you return:

Your first return value   What happensUse this to…
return true, true, ...Built-in job runs normallyAdd behavior before/after the stock job (log it, turn on an extra output, check a condition)
return false, true, ...Built-in job is skippedReplace the stock behavior entirely with your own
return nil, false, "message"Everything stops, operator sees your message     as an alarmBlock the MCode when a safety condition fails

Recipe 1: Add something before the stock job (most common)
Example: you want M3 to also turn on a "spindle running" lamp (output #5).

Open Mach\Profiles\<your profile>\Macros\Scripts\UserMCodeModule.mcs.
If it doesn't exist, create it with this starter:

Code: [Select]
local UserMCodeModule = {}

return UserMCodeModule

Add a function named after the MCode; this runs before the spindle starts:

Code: [Select]
function UserMCodeModule.m3(hVars)
    -- Turn on the spindle lamp.
    local hReg, rc = mc.mcRegGetHandle(inst, "mc.OSIG_OUTPUT5")
    if rc == mc.MERROR_NOERROR then
        mc.mcRegSetValue(hReg, 1)
    end

    return true, true, w.FunctionCompleted()   -- "true" = now run the normal M3 job
end

Save and select "Compile Scripts". In rare cases, you will need to restart Mach. Now every M3 - from a program, MDI, or a screen button - lights the lamp first, then starts the spindle as usual.

Recipe 2: Add something after the stock job
Use the …End hook instead. Example: after M5 (spindle stop) finishes, turn the lamp off:
Code: [Select]
function UserMCodeModule.m5End(hVars)
    local hReg, rc = mc.mcRegGetHandle(inst, "mc.OSIG_OUTPUT5")
    if rc == mc.MERROR_NOERROR then
        mc.mcRegSetValue(hReg, 0)
    end

    return true, true, w.FunctionCompleted()
end

Recipe 3: Block the MCode when a condition isn't met

Example: don't allow M3 unless the guard door is closed (input #2).

Code: [Select]
function UserMCodeModule.m3(hVars)
    local hReg, rc = mc.mcRegGetHandle(inst, "mc.ISIG_INPUT2")
    if rc == mc.MERROR_NOERROR then
        local doorClosed = mc.mcRegGetValue(hReg)
        if doorClosed ~= 1 then
            return nil, false, "M3 refused: guard door is open"
        end
    end

    return true, true, w.FunctionCompleted()
end

Returning false as the second value aborts the whole MCode and shows your message to the operator. Nothing else runs; the spindle never starts.

Recipe 4: Replace the stock behavior entirely

Return false as the first value. Mach skips its built-in job and considers the MCode done.

Example: your machine has no physical spindle relay; M3 should only set a register for your VFD over Modbus, and never run the stock spindle logic:
Code: [Select]
function UserMCodeModule.m3(hVars)
    -- My own spindle-start logic here (VFD register writes, etc.)
    -- ...

    return false, true, w.FunctionCompleted()   -- "false" = skip Mach's built-in M3 job
end
Be careful with this one. The stock job often does bookkeeping you can't see (state tracking, status displays). Replacing M6 (tool change) or M30 (end of program) this way, for instance, can leave the control's idea of "what's happening" out of sync. Prefer Recipes 1–3 unless you're sure.

Which hook names exist?
m<code>  runs before the built-in job: m3, m4, m5, m6, m8, m9, m30, …
m<code>End  runs after the built-in job: m3End, m5End, …
Some complex operations have extra named hooks; tool change, for example, offers PreMainToolChangeCycle and PostMainToolChangeCycle.
If you're not sure which hooks a particular MCode supports, look at that MCode's Default file (read-only!) in Mach\Profiles\<your profile>\Macros\ and search Mach's modules for RunHooks("…  every name found there is a hook you can use. You can also search in:
https://support.machmotion.com/docs/current/dir_f2541a3b18981391fa76fac5599e978a.html

Testing and Troubleshooting
Select "Compile Scripts" or restart Mach - hooks are loaded at startup.
Trigger the MCode from the MDI line.
If your hook doesn't seem to run, check:
  • The file is UserMCodeModule.mcs, in Macros\Scripts\ of the profile you're actually running.
  • The file starts with local UserMCodeModule = {} and ends with return UserMCodeModule.
  • The function name matches the hook exactly: UserMCodeModule.m3 (lowercase "m", correct number) or UserMCodeModule.m3End.
  • You restarted Mach or compiled after saving.

Quick reference
You want to…Hook nameReturn
Add before stock job     UserMCodeModule.m3     true, true, w.FunctionCompleted()
Add after stock jobUserMCodeModule.m3End     true, true, w.FunctionCompleted()
Block with alarmUserMCodeModule.m3nil, false, "message"
Replace stock jobUserMCodeModule.m3false, true, w.FunctionCompleted()
72
MachPro General Discussion / Re: MachPro upgrade questions
« Last post by joeaverage on September 16, 2026, 03:43:34 PM »
Hi Paul,
excellent description. I do absolutely now understand how and why you have proceeded in the manner you have, and that refinement in signal handling over
what I am used to in Mach4 is to be congratulated. It is also true that I'm going to have to learn a new procedure that reflects this newer architecture, but I readily
and easily understand why the effort is worth it.

Can I also assume that any functionality that I would normally include in the Mach4 ScreenLoad script I can include in UserGUIModule.mcs?

Craig
73
Pendants / Re: WHB Pendant
« Last post by cd_edwards on September 16, 2026, 03:13:45 PM »
thank you. I am sure I'm not the only one who will appreciate this change.
74
Pendants / Re: WHB Pendant
« Last post by paul.stephens on September 16, 2026, 03:09:50 PM »
Yeah, the plugin was just ported over by popular request. I am having one of our developers dig in to a solution for this. I have prompted a couple of options we can do moving forward. I'll keep an eye on its stage and will let you know when a build is out for it.
75
MachPro General Discussion / Re: MachPro upgrade questions
« Last post by paul.stephens on September 16, 2026, 03:05:30 PM »
Hi,

That concept still exists.. MachPro still works exactly the way you described: when Mach detects a signal change, a Signal Script runs, it consults a table keyed by signal ID, and if an entry exists for that signal, its function executes. Your understanding of the mechanism is spot on.

What changed is where your custom entries live, and that change was made to protect people doing exactly what you're doing.

Why it changed:

In Mach4, your SigLib lived inside the screen set's Screen Load script, so the only way to customize it was to copy wx4.set or wx6.set and maintain a fork and your copy drifted further from the shipped screens with every update.

In MachPro, the signal handling is split into layers:

Core layer- the shipped screen code handles the things every machine needs (limit switches, homing status, machine enable/disable, emergency stop).
Machine-type layer- mill, plasma, lathe-specific behavior (tool changers, torch height control, etc.).
Screen layer- screen cosmetics like your jog-mode labels.
User layer- this is yours. It runs first, before the built-in layers, and it lives in a file that belongs to your profile, not to the shipped screen set.
That user layer is the direct equivalent of your SigLib, with one improvement: because it's a dedicated user file rather than a copy of our screen code, a MachPro update can improve the shipped screens without touching your custom signal handlers at all. No more maintaining a fork.

Where your code goes in MachPro:

Create (or edit) this file in your MachPro installation:
Code: [Select]
Profiles\<YourProfileName>\Macros\Scripts\UserGUIModule.mcs
That file sits inside your machine profile, so it is custom to your machine and survives updates, same as your personalized screen set, but cleaner.

Inside it you can define a signal library table almost identically to your Mach4 one:

Code: [Select]
local UserGUIModule = {}

USER_SIG_LIBRARY = {
    [mc.ISIG_INPUT20] = function(state)   --EXAMPLE X servo alarm
        local inst = mc.mcGetInstance("UserGUIModule, USER_SIG_LIBRARY, X servo alarm")
        if state then
            mc.mcCntlEStop(inst)
            local handle = mc.mcRegGetHandle(inst, "iRegs0/XAlarm")
            mc.mcRegSetValue(handle, 1)
        else
            local handle = mc.mcRegGetHandle(inst, "iRegs0/XAlarm")
            mc.mcRegSetValue(handle, 0)
        end
    end,
    -- ... add your other signals here, same pattern ...
}

function UserGUIModule.SignalScript(sig, state)
    if USER_SIG_LIBRARY ~= nil and USER_SIG_LIBRARY[sig] ~= nil then
        USER_SIG_LIBRARY[sig](state)
    end
    return true, true, "User Signal Script Complete"
end

return UserGUIModule

Two small differences from your Mach4 code to watch for:

  • "state" is a true/false value, not 1/0. Your Mach4 code tests state == 1; in MachPro write if state then ... else ... end instead. (If you want, if tonumber(state) == 1 also works and is easier to port line-for-line.)
  • Get the instance inside the handler with mc.mcGetInstance("Insert Caller Name") rather than relying on a global inst from screen load.
    Everything else, latching registers, calling mc.mcCntlEStop, triggering pendant functions, ports straight across.

One more thing worth knowing:

MachPro runs the user signal handler first, then its own built-in layers. So your servo-alarm handler and the built-in limit/homing handlers can both respond to signals without interfering with each other. In Mach4, a single SigLib table meant your entry replaced (or was replaced by) whatever the donor screen set had in MachPro they coexist.


76
General Mach Discussion / Re: Diy CNC router build
« Last post by Stuartbrown06 on September 16, 2026, 01:43:56 AM »
Hi thanks for the reply, I spent a few hours trying things suggested by google ai. This included changing the step pulse and dir pulse timing all the way up to 15, changing the DirLowActive etc (this made the error go in the opposite direction) as it  was suspected it’s the pulse timing. I set up a DTI on the spindle body then ran this code..

%
G21 (Set units to Metric - change to G20 if you use Inches)
G91 (Set to Incremental Mode)
G01 X20.0 F1000 (Move right 20 units)
G01 X-20.0 F1000 (Move left 20 units)
M47 (Rewind to line 1 and repeat indefinitely)
%

I was losing approx 0.12mm each time the spindle returned to the DTI

Ran driver test which came back with good results, ordered a new breakout board from amazon in case it was this but it was just the same.  Changed the 5v power supply from the PC to a good phone charger in case of voltage drop but still the same.

I happened to read another thread on here with a similar issue where someone suggested trying sherline mode (apparently this changes the step delays to 40 (either pico or microseconds?) when mach3 settings only go as high as 15. This has sorted the error when running the loop program and it would return to the same point every time.  I re ran my program with the square inside the circle and the square now cuts out perfectly no steps on the cut at all. The circle has no steps but doesn’t look completely round though? Not sure if that’s my program or still the same error due to two axis running at once.  I’m going to order a good quality branded motion controller today as I want to build a decent machine as I will use this for work so don’t mind investing in it.  I’m looking at either an AXBB-E or a UC400-ETH

I would still like to know why my setup doesn’t seem to work with the Chinese board as lots of people seem to use them without issue on the YouTube videos I have been watching throughout my build!

Regards





77
General Mach Discussion / Re: Diy CNC router build
« Last post by coeddie11 on September 15, 2026, 10:16:21 PM »
Since the error is a consistent 2 mm per run and occurs with the cutter lifted, I’d first check your steps-per-unit calibration and whether Mach3 is actually commanding the expected distance, then verify the DM542 microstep settings match the software before chasing lost steps.
78
MachPro General Discussion / Re: MachPro upgrade questions
« Last post by joeaverage on September 15, 2026, 03:11:38 PM »
Hi Paul,
thanks for your extensive reply.

I get a general sense as to how MachPro handles signals, but my programming skills are only fair and my understanding of your terminology is poor.
I do rather believe however that MachPro and Mach4 have a similarity.

In Mach4, for which I am familiar each screen set has a ScreenLoad script, and in that script there is a Lua table called SigLib{...........}. Given that the ScreenLoad script
is part of the screen set, and most operators choose to use say wx4.set or wx6.set as a basis for their own personalised copy, and thus survive Mach build updates.

This is the SigLib table in my current Mach4 installation:
Code: [Select]
---------------------------------------------------------------
-- Signal Library
---------------------------------------------------------------
SigLib = {
[mc.OSIG_MACHINE_ENABLED] = function (state)
    machEnabled = state;
    ButtonEnable()
end,

[mc.ISIG_INPUT0] = function (state)
   
end,

[mc.ISIG_INPUT1] = function (state) -- this is an example for a condition in the signal table.
   -- if (state == 1) then   
--        CycleStart()
--    --else
--        --mc.mcCntlFeedHold (0)
--    end

end,

[mc.OSIG_JOG_CONT] = function (state)
    if( state == 1) then
       scr.SetProperty('labJogMode', 'Label', 'Continuous');
       scr.SetProperty('txtJogInc', 'Bg Color', '#C0C0C0');--Light Grey
       scr.SetProperty('txtJogInc', 'Fg Color', '#808080');--Dark Grey
    end
end,

[mc.OSIG_JOG_INC] = function (state)
    if( state == 1) then
        scr.SetProperty('labJogMode', 'Label', 'Incremental');
        scr.SetProperty('txtJogInc', 'Bg Color', '#FFFFFF');--White   
        scr.SetProperty('txtJogInc', 'Fg Color', '#000000');--Black
   end
end,

[mc.OSIG_JOG_MPG] = function (state)
    if( state == 1) then
        scr.SetProperty('labJogMode', 'Label', '');
        scr.SetProperty('txtJogInc', 'Bg Color', '#C0C0C0');--Light Grey
        scr.SetProperty('txtJogInc', 'Fg Color', '#808080');--Dark Grey
        --add the bits to grey jog buttons becasue buttons can't be MPGs
    end
end,
[mc.ISIG_INPUT20] = function(state) --X servo alarm port1 pin10
if(state==1)then
mc.mcCntlEStop(inst)
local handle=mc.mcRegGetHandle(inst,"iRegs0/XAlarm")
mc.mcRegSetValue(handle,1)
else
local handle=mc.mcRegGetHandle(inst,"iRegs0/XAlarm")
mc.mcRegSetValue(handle,0)
end
end,
[mc.ISIG_INPUT21] = function(state) --Y servo alarm port1 pin11
if(state==1)then
mc.mcCntlEStop(inst)
local handle=mc.mcRegGetHandle(inst,"iRegs0/YAlarm")
mc.mcRegSetValue(handle,1)
else
local handle=mc.mcRegGetHandle(inst,"iRegs0/YAlarm")
mc.mcRegSetValue(handle,0)
end
end,
[mc.ISIG_INPUT22] = function(state) --Z servo alarm port1 pin12
if(state==1)then
mc.mcCntlEStop(inst)
local handle=mc.mcRegGetHandle(inst,"iRegs0/ZAlarm")
mc.mcRegSetValue(handle,1)
else
local handle=mc.mcRegGetHandle(inst,"iRegs0/ZAlarm")
mc.mcRegSetValue(handle,0)
end
end,
[mc.ISIG_INPUT23] = function(state) --A servo alarm port1 pin13
if(state==1)then
mc.mcCntlEStop(inst)
local handle=mc.mcRegGetHandle(inst,"iRegs0/AAlarm")
mc.mcRegSetValue(handle,1)
else
local handle=mc.mcRegGetHandle(inst,"iRegs0/AAlarm")
mc.mcRegSetValue(handle,0)
end
end,
[mc.ISIG_INPUT24] = function(state) --B servo alarm port1 pin15
if(state==1)then
mc.mcCntlEStop(inst)
local handle=mc.mcRegGetHandle(inst,"iRegs0/BAlarm")
mc.mcRegSetValue(handle,1)
else
local handle=mc.mcRegGetHandle(inst,"iRegs0/BAlarm")
mc.mcRegSetValue(handle,0)
end
end,
[mc.ISIG_INPUT29] = function(state) --C servo alarm port2 pin2
if(state==1)then
mc.mcCntlEStop(inst)
local handle=mc.mcRegGetHandle(inst,"iRegs0/CAlarm")
mc.mcRegSetValue(handle,1)
else
local handle=mc.mcRegGetHandle(inst,"iRegs0/CAlarm")
mc.mcRegSetValue(handle,0)
end
end,

[mc.ISIG_INPUT25] = function(state) --AXIS1 port3 pin6
if(state==1)then
local handle=mc.mcRegGetHandle(inst,"iRegs0/AXIS1")
mc.mcRegSetValue(handle,0)
else
local handle=mc.mcRegGetHandle(inst,"iRegs0/AXIS1")
mc.mcRegSetValue(handle,1)
end
ChangeJogAxis()
end,
[mc.ISIG_INPUT26] = function(state) --AXIS2 port3 pin7
if(state==1)then
local handle=mc.mcRegGetHandle(inst,"iRegs0/AXIS2")
mc.mcRegSetValue(handle,0)
else
local handle=mc.mcRegGetHandle(inst,"iRegs0/AXIS2")
mc.mcRegSetValue(handle,1)
end
ChangeJogAxis()
end,
[mc.ISIG_INPUT27] = function(state) --AXIS3  port3 pin8
if(state==1)then
local handle=mc.mcRegGetHandle(inst,"iRegs0/AXIS3")
mc.mcRegSetValue(handle,0)
else
local handle=mc.mcRegGetHandle(inst,"iRegs0/AXIS3")
mc.mcRegSetValue(handle,1)
end
ChangeJogAxis()
end,

[mc.ISIG_INPUT28] = function(state) --FEEDHOLD port3 pin9
mc.mcCntlFeedHold(inst)
end,
[mc.ISIG_INPUT30] = function(state) --AXIS3  port3 pin8
if(state==1)then
local handle=mc.mcRegGetHandle(inst,"iRegs0/Velocity1")
mc.mcRegSetValue(handle,1)
else
local handle=mc.mcRegGetHandle(inst,"iRegs0/Velocity1")
mc.mcRegSetValue(handle,0)
end
ChangeJogAxis()
end,
[mc.ISIG_INPUT31] = function(state) --AXIS3  port3 pin8
if(state==1)then
local handle=mc.mcRegGetHandle(inst,"iRegs0/Velocity2")
mc.mcRegSetValue(handle,0)
else
local handle=mc.mcRegGetHandle(inst,"iRegs0/Velocity2")
mc.mcRegSetValue(handle,1)
end
ChangeJogAxis()
end,
[mc.ISIG_INPUT1]=function(state)

if(state==1)then

local handle=mc.mcRegGetHandle(inst,"iRegs0/Trial")
local LEDState=mc.mcRegGetValue(inst,handle)
wx.wxMessageBox("LED State=="..tostring(LEDState))
if(LEDState==1)then
wx.wxMessageBox("here"..tostring(LEDState))
local handle=mc.mcRegGetHandle(inst,"iRegs0/Trial")
mc.mcRegSetValue(handle,0)
else
local handle=mc.mcRegGetHandle(inst,"iRegs0/Trial")
mc.mcRegSetValue(handle,1)
end
end
end,

}

Several of the signals are generic and came fro the donor screen set, wx6.set in this case, but quite a number more are signal entries specific to my machine and I coded them.
I think you are familiar with the general idea, whenever Mach detects a signal change, of any description , from any source,  the SignalScript runs, wherein it interrogates the
SigLib table, and if it encounters an entry for that signal identity it executes the function in that table entry. My understanding is that MachPro is similar.

Where MachPro and Mach4 differ is that the SigLib table is immediately readily available to the user to add signal entries or change functionalities. Because the SigLib table is in the
ScreenLoad script it is in effect custom to the users machine.

As you can see from the code I have entries for the servo axis alarms, with each latching data into a register, and enacting an Estop. Easy.
Other signals are from my wired pendant. The SigLib entries capture those signal events and invoke functions also within the ScreenLoad script. This is a method I am very familiar with,
it is both simple and yet immensly flexible and powerful.

Why did you deem in necessary to do away with it?

Craig
79
Pendants / Re: WHB Pendant
« Last post by cd_edwards on September 15, 2026, 01:36:08 PM »
yes. WHB06 pendant. I know it's not MachPro's, but they definitely look similar enough. Anyways, allowing a checkbox or radiobutton to toggle this as a default would be amazingly appreciated. I don't know how many bits I've driven down into my spoilboard or fixtures if I forget to toggle this from the controller. There must be a way todo this in software.
80
Pendants / Re: WHB Pendant
« Last post by paul.stephens on September 15, 2026, 12:53:41 PM »
I'll report this and push to get it changed. Just want to verify for clarities sake, it is the XHCmpg plugin you're using?
Pages: « 1 2 3 4 5 6 7 8 9 10 »