VCP Skin & Macro Customization Guide
Forest CNC: VCP Skin & Macro Customization Guide
Overview
We added 5 custom buttons to the CNC12 Acorn Mill v4.50 VCP (Virtual Control Panel) skin on a Velocity CNC router. The buttons replaced the default blue M55 to M58 placeholder buttons and added a new button in Row 4.
What We Built
| Button | Location | Function |
|---|---|---|
| Spindle Warm-Up | Row 4, Col 3 | Ramps spindle from 3000 to 22000 RPM in 6 stages, in place with no axis motion (revised, see note in Part 1) |
| WCS X0 Y0 | Row 5, Col 1 | Raises Z safe, rapids to part zero X and Y |
| Zero X | Row 5, Col 2 | Sets WCS X to zero at current position |
| Zero Y | Row 5, Col 3 | Sets WCS Y to zero at current position |
| Zero Z | Row 5, Col 4 | Sets WCS Z to zero at current position |
Part 1: The Macro Files
Each button fires a macro file stored in C:\cncm\. These are plain text files with a .mac extension written in Centroid G-code/macro language.
Files created:
mfunc48.mac: Runs the spindle warm-up sequence in place, no axis motion (revised, see note below)mfunc55.mac: Go to WCS X0 Y0mfunc56.mac: Zero X axismfunc57.mac: Zero Y axismfunc58.mac: Zero Z axis
Key G-code used:
G92 X0: sets WCS X to zero at current position (same for Y0, Z0)G91 / G90: switches to incremental positioning for a relative move, then back to absoluteG0 X12 Y-12: originally moved 12″ in X and -Y from home before warm-up; removed in a later revision (see note below)M3 S3000: spindle on clockwise at 3000 RPMM5: spindle stopG4 P30/G4 P45/G4 P60: dwell for the given number of seconds at each warm-up stageM225 #100 "message text": displays a popup message
Lesson learned: G10 L20 P0 X0 does not work in CNC12 v4.50 for setting WCS zero. Use G92 X0 instead.
Important lesson: why M34 didn’t work and M48 did. We originally built the spindle warm-up macro as mfunc34.mac, tied to M34. No matter how many times we edited the file, restarted CNC12, or even fully rebooted the PC, the changes never took effect; the button kept running old behavior. After extensive troubleshooting (checking for duplicate files, Windows VirtualStore redirection, and parameter values), it turned out M34 is shadowed by a native, built-in “Spin Warm” feature in CNC12 itself. That built-in feature runs its own compiled warm-up routine (multiple ramp-and-rest cycles of increasing speed) and completely ignores any custom mfunc34.mac file on disk. Editing the file changed nothing because the button was never actually reading it. Switching the macro to M48, a genuinely unused custom M-code, immediately fixed the problem: the custom macro ran exactly as written. Takeaway: if a custom macro edit refuses to take effect no matter what you try, check whether that M-code is reserved by a native CNC12 feature before assuming it’s a caching or file-path issue.
Revision note (July 2026): the 12″ X/-Y move described above was removed in a later revision after it triggered a 907 Z axis travel exceeded fault when Z was already near the top of its travel, and on reflection, the positioning assumption itself (that the spindle always starts from home) didn’t hold up. mfunc48.mac now does nothing but ramp the spindle through its six stages wherever it happens to be sitting. See the Troubleshooting The CNC post for the full account.
Part 2: The Button Graphics
Each button needs its own folder inside C:\cncm\resources\vcp\Buttons\. The folder contains two files:
- An SVG file: the button graphic (same name as the folder)
- An XML file: tells CNC12 what event to fire when pressed (same name as the folder)
Folders created:
C:\cncm\resources\vcp\Buttons\spindle_warmup\
spindle_warmup.svg
spindle_warmup.xml
C:\cncm\resources\vcp\Buttons\mach_coords\
mach_coords.svg
mach_coords.xml
C:\cncm\resources\vcp\Buttons\zero_x\
zero_x.svg
zero_x.xml
C:\cncm\resources\vcp\Buttons\zero_y\
zero_y.svg
zero_y.xml
C:\cncm\resources\vcp\Buttons\zero_z\
zero_z.svg
zero_z.xml
SVG format: Standard SVG with a 100×100 viewBox. Dark background rectangle, white text and icons. CNC12 renders SVG files natively; no image conversion needed.
Part 3: The XML Button Definition Files
Each XML file tells CNC12 which internal event number to fire when the button is pressed. The format is:
<vcp_button>
<skin_event_num>14</skin_event_num>
</vcp_button>
Critical lesson learned: The skin_event_num values are NOT sequential or obvious. We discovered the correct values by opening the stock Centroid button XML files in C:\cncm\resources\vcp\Buttons\aux8\, aux9\ etc. and reading their event numbers directly. The values for this machine are:
| Button | skin_event_num | Fires |
|---|---|---|
| mach_coords | 14 | M55 (Aux 8) |
| zero_x | 15 | M56 (Aux 9) |
| zero_y | 18 | M57 (Aux 10) |
| zero_z | 19 | M58 (Aux 11) |
| spindle_warmup | 20 | M48 (Aux 12) |
Always verify event numbers by opening the stock aux8.xml, aux9.xml etc. files first. Do not guess or assume sequential numbering.
Part 4: The VCP Skin File
The skin file C:\cncm\resources\vcp\skins\acorn_mill_vcp_skin.VCP controls which button folder appears in each row/column position. In this case, the skin file was already pre-configured by Forest CNC to reference our button folder names. No editing was required.
If you do need to edit it, open it with Notepad++ and find/add lines like:
<button row="4" column="3">spindle_warmup</button>
<button row="5" column="1">mach_coords</button>
<button row="5" column="2">zero_x</button>
<button row="5" column="3">zero_y</button>
<button row="5" column="4">zero_z</button>
Part 5: Machine Parameters
CNC12 uses parameters to map Aux key events to M-code macro files. These are set under: F1 Setup > F3 Config > F3 Parms (password: 137)
The correct parameters for this machine:
| Parameter | Value | Meaning |
|---|---|---|
| P195 | 5511 | Aux 8 fires M55 |
| P196 | 5611 | Aux 9 fires M56 |
| P197 | 5711 | Aux 10 fires M57 |
| P198 | 5811 | Aux 11 fires M58 |
| P199 | 4811 | Aux 12 fires M48 |
After changing parameters, always restart CNC12 for changes to take effect.
Part 6: Testing Order
Always test in this order (safest first):
- No-motion buttons first (zero axes): confirm DRO resets correctly
- Motion buttons (WCS X0 Y0): confirm Z raises before XY moves
- Spindle buttons (warm-up) last: confirm the 12″ X/Y move clears home and the spindle is bare before running
Key Lessons Learned
- Always back up
C:\cncm\before making any changes skin_event_numvalues must be verified from existing working button XMLs. Never assume.- Parameters P195 to P199 control Aux 8 to 12 on this machine (not P191 to 194 as documented elsewhere)
- VCP button XML files update live. No CNC12 restart needed after changing them.
- Macro files update live. No restart needed after editing
.macfiles. - Parameter changes require a full CNC12 restart to take effect
- G92 X0/Y0/Z0 is the correct WCS zeroing command in CNC12 v4.50
- Pressing a VCP macro button requires a Cycle Start press to execute. This is normal CNC12 behavior.
- M225 is the correct popup command. Use
#100 = 0as the timer variable for indefinite display. - Incremental moves (
G91) needG90immediately after to avoid leaving the control in incremental mode for subsequent commands. - Some M-codes are reserved by native CNC12 features and cannot be overridden by a custom macro file. M34 in particular is shadowed by CNC12’s built-in “Spin Warm” feature, so editing
mfunc34.machas no effect no matter how many times you save, restart, or reboot. If a macro edit refuses to take effect, test the macro directly via MDI (type the M-code and press Cycle Start) before assuming it’s a file or caching problem. If it doesn’t run correctly from MDI either, try a different, genuinely unused M-code instead.
That’s the complete process. The hardest part was discovering the correct skin_event_num values, and tracking down why M34 silently refused to run our custom macro. Everything else is straightforward once you know the file locations and naming conventions.
