claude init

This commit is contained in:
Thaddeus Hughes
2026-04-03 21:47:22 -05:00
parent f3953d66ae
commit 9d2379205f
26 changed files with 2382 additions and 4243 deletions

View File

@@ -0,0 +1,11 @@
{
"permissions": {
"allow": [
"WebFetch(domain:www.mesanet.com)",
"Bash(where pdftotext:*)",
"Bash(where python:*)",
"Bash(where python3:*)",
"Bash(where py:*)"
]
}
}

View File

@@ -0,0 +1,163 @@
# Lagun Milling Machine - GMOCCAPY Configuration
LinuxCNC configuration for a Lagun 3-axis (X, Y, Z) milling machine with servo drives, controlled by a Mesa 5i24 FPGA card and the GMOCCAPY GUI. Units are imperial (inches).
Originally generated by PNCconf (July 2024), then modified for GMOCCAPY and dual-encoder feedback.
## Files
| File | Purpose |
|------|---------|
| `lagun_gmoccapy.ini` | Main config: axes, PID gains, encoder scales, limits, MDI commands |
| `lagun.hal` | Main HAL: loads drivers, wires encoders/PWM/PID/GPIO, tool change |
| `xhc-whb04b-6.hal` | Pendant HAL: jog, axis select, feed override, macro buttons |
| `gmoccapy_postgui.hal` | Post-GUI HAL: connects tool offset display to GMOCCAPY |
| `shutdown.hal` | Shutdown HAL: currently empty (placeholder) |
| `tool.tbl` | Tool table with 6 tools (T0-T5) |
## Hardware
### Controller
- **Mesa 5i24** PCI FPGA card (`hm2_pci`)
- 6 encoder channels, 6 PWM generators
- PWM frequency: 15,500 Hz
- Servo period: 1 ms (1,000,000 ns)
### Servo Drives and PWM Mapping
| Axis | PWM Channel | Output Scale |
|------|-------------|-------------|
| X | pwmgen.00 | +1 |
| Y | pwmgen.02 | -1 (inverted) |
| Z | pwmgen.04 | -1 (inverted) |
### Encoder Mapping
X and Y each have two encoders (motor + linear scale). Z has only a linear scale.
| Signal | Encoder Channel | Scale (counts/inch) | Purpose |
|--------|----------------|---------------------|---------|
| X linear | encoder.00 | 5085.5 | Position feedback (used for joint FB) |
| Y linear | encoder.01 | 5085.4 | Position feedback (used for joint FB) |
| Z linear | encoder.02 | -10075 | Position feedback (used for joint FB) |
| X motor | encoder.03 | -27939.6 | Velocity/damping feedback |
| Y motor | encoder.04 | 27453.6 | Velocity/damping feedback |
| Z motor | (none) | N/A | Not installed |
### GPIO Pin Assignments
**Relay outputs** (active low / inverted):
| GPIO | Function |
|------|----------|
| 041 | Spindle on/off relay |
| 044 | Z-axis servo enable relay |
| 046 | X-axis servo enable relay |
**Button inputs** (active low, currently unused/commented out):
| GPIO | Function |
|------|----------|
| 027 | Button (unassigned) |
| 028 | Button (unassigned) |
| 029 | ESTOP button |
| 030 | START button |
| 031 | STOP button |
The button inputs are configured as inputs but their HAL net connections are commented out because they were causing unexpected machine shutoff.
## Dual PID Feedback (X and Y Axes)
X and Y each use two PID loops running in parallel, whose outputs are summed:
1. **Motor encoder PID** (`pid.x` / `pid.y`): Uses D gain and FF1 for velocity damping. No I gain. Feedback from the motor-mounted encoder.
2. **Linear scale PID** (`pid.xl` / `pid.yl`): Uses high P and I gains for accurate position correction. Feedback from the linear scale mounted on the axis.
The outputs are summed via `sum2` components:
- `sum2.0`: X motor PID + X linear PID
- `sum2.1`: Y motor PID + Y linear PID
- `sum2.2`: Z linear PID only (no motor encoder)
The **linear scale** position is used as the joint feedback (`joint.N.motor-pos-fb`), so LinuxCNC tracks actual table position rather than motor position.
## Z-Axis Override Mechanism
The Z-axis has a special enable/disable mechanism for manual quill operation:
- A HAL `logic AND` gate combines two signals: `z-override` and `z-enable`
- The combined output `z-enable-comb` controls the Z servo PID enable and the GPIO 044 relay
- `z-override` defaults to TRUE at startup (CNC controls Z)
- M101 can set `z-override` to FALSE, disabling the Z servo so the quill can be moved manually
- M102 can set `z-override` back to TRUE to re-enable CNC Z control
**Workaround**: Because the Z servo is disabled during manual quill use, the quill position diverges from the commanded position. To prevent following-error faults, `MIN_FERROR` is set to 100 inches in the INI file (ideally it would be 0.2). An attempt to dynamically switch the ferror value via a `mux2` component exists in the HAL but is non-functional (the output signal is not connected to the joint).
## Spindle
On/off relay control only via GPIO 041. No speed control or encoder feedback. The spindle PID section in the INI exists but is effectively unused (FF0=1 with no feedback). Default spindle speed in the GUI is 500 RPM.
## Pendant (XHC WHB04B-6)
Wireless pendant loaded with `xhc-whb04b-6 -HsfB` (HAL-only, step, filtered, 6-axis model).
Connected to `joint.N.jog-*` pins (not `axis.x.jog-*`, which GMOCCAPY does not create).
### Macro Button Mapping
Macro buttons trigger MDI commands defined in the `[HALUI]` section of the INI:
| Button | MDI Index | G-code | Action |
|--------|-----------|--------|--------|
| Macro 1 | 01 | `G10 L20 P0 X[#<_x>/2.0]` | Halve X coordinate |
| Macro 2 | 02 | `G10 L20 P0 Y[#<_y>/2.0]` | Halve Y coordinate |
| Macro 3 | -- | (hardcoded) | Spindle speed increase |
| Macro 4 | -- | (hardcoded) | Spindle speed decrease |
| Macro 5 | 05 | `G10 L20 P0 X0` | Zero X |
| Macro 6 | 06 | `G10 L20 P0 Y0` | Zero Y |
| Macro 7 | 07 | `G10 L20 P0 Z0` | Zero Z |
| Macro 8 | -- | (hardcoded) | Spindle direction |
| Macro 10 | -- | (hardcoded) | Toggle ABS/REL DRO |
| Macro 15 | -- | (hardcoded) | Flood coolant toggle |
| Macro 16 | -- | (hardcoded) | Mist coolant toggle |
### Function Buttons
| Button | Action |
|--------|--------|
| M-Home | Home all axes (`halui.home-all`) |
| Safe-Z | MDI command 03 (debug/placeholder) |
| W-Home | MDI command 04 (debug/placeholder) |
| Probe-Z | MDI command 08 (debug/placeholder) |
Feed override is connected and functional via the pendant knob.
## Tool Change
Manual tool change using `hal_manualtoolchange`. A dialog pops up on screen prompting the operator to change the tool. Tool prepare requests are looped back (no automatic tool changer).
## Axis Limits and Homing
| Axis | Travel (inches) | Home Sequence |
|------|----------------|---------------|
| X | -24.0 to +24.0 | 2 |
| Y | -12.0 to +12.0 | 3 |
| Z | -4.0 to +1.0 | 1 (first) |
`NO_FORCE_HOMING = 1` is set, so the machine can be jogged and run programs without homing first.
## Startup G-code
```
G20 G40 G90 G94 G97 G64 P0.001
```
- G20: Inch mode
- G40: Cancel cutter compensation
- G90: Absolute distance mode
- G94: Feed per minute
- G97: RPM mode (constant spindle speed)
- G64 P0.001: Path blending with 0.001" tolerance
## E-Stop
The estop signal is looped back internally (`user-enable-out` -> `emc-enable-in`). There is no external hardware estop chain connected through LinuxCNC. The physical ESTOP button on GPIO 029 is configured as an input but not wired into the estop logic.

View File

@@ -2,5 +2,6 @@
# These connections are made after the GUI loads so gmoccapy pins exist # These connections are made after the GUI loads so gmoccapy pins exist
# --- Tool offset display --- # --- Tool offset display ---
# Pass tool offset values to GMOCCAPY for DRO display
net tooloffset-x gmoccapy.tooloffset-x <= motion.tooloffset.x net tooloffset-x gmoccapy.tooloffset-x <= motion.tooloffset.x
net tooloffset-z gmoccapy.tooloffset-z <= motion.tooloffset.z net tooloffset-z gmoccapy.tooloffset-z <= motion.tooloffset.z

View File

@@ -1,20 +1,30 @@
# ============================================================================
# Lagun milling machine - Main HAL configuration
# Generated by PNCconf at Fri Jul 26 13:18:08 2024 # Generated by PNCconf at Fri Jul 26 13:18:08 2024
# Using LinuxCNC version: Master (2.9) # Using LinuxCNC version: Master (2.9)
# If you make changes to this file, they will be # If you make changes to this file, they will be
# overwritten when you run PNCconf again # overwritten when you run PNCconf again
# ============================================================================
# --- Load realtime modules ---
loadrt [KINS]KINEMATICS loadrt [KINS]KINEMATICS
loadrt [EMCMOT]EMCMOT servo_period_nsec=[EMCMOT]SERVO_PERIOD num_joints=[KINS]JOINTS base_thread_fp=1 loadrt [EMCMOT]EMCMOT servo_period_nsec=[EMCMOT]SERVO_PERIOD num_joints=[KINS]JOINTS base_thread_fp=1
loadrt hostmot2 loadrt hostmot2
loadrt hm2_pci config="num_encoders=6 num_pwmgens=6" loadrt hm2_pci config="num_encoders=6 num_pwmgens=6"
# mux16: used by pendant for jog increment, feed override, max velocity override, spindle override
loadrt mux16 names=jogincr,foincr,mvoincr,soincr loadrt mux16 names=jogincr,foincr,mvoincr,soincr
# mux2: selects ferror value based on z-override state (attempted but unused)
loadrt mux2 count=1 loadrt mux2 count=1
# sum2: sums dual PID outputs for X(0), Y(1), Z(2)
loadrt sum2 count=3 loadrt sum2 count=3
# logic: 2-input AND gate for z-override mechanism
# personality 0x0102 = 1 output, 2 inputs, AND function
loadrt logic count=1 personality=0x0102 loadrt logic count=1 personality=0x0102
addf logic.0 servo-thread addf logic.0 servo-thread
addf mux2.0 servo-thread addf mux2.0 servo-thread
# weighted_sum: for ADC reading (currently unused)
loadrt weighted_sum wsum_sizes=8 #wsum_sizes=[128,64,32,16,8,4,2,1] # default should do conversion?? loadrt weighted_sum wsum_sizes=8 #wsum_sizes=[128,64,32,16,8,4,2,1] # default should do conversion??
addf process_wsums servo-thread addf process_wsums servo-thread
@@ -26,11 +36,19 @@ addf foincr servo-thread
addf mvoincr servo-thread addf mvoincr servo-thread
addf soincr servo-thread addf soincr servo-thread
# --- Mesa 5i24 global PWM/watchdog settings ---
setp hm2_5i24.0.pwmgen.pwm_frequency 15500 setp hm2_5i24.0.pwmgen.pwm_frequency 15500
setp hm2_5i24.0.pwmgen.pdm_frequency 15500 setp hm2_5i24.0.pwmgen.pdm_frequency 15500
setp hm2_5i24.0.watchdog.timeout_ns 5000000 setp hm2_5i24.0.watchdog.timeout_ns 5000000
# --- Load PID controllers ---
# pid.x / pid.xl = X motor encoder / linear scale (dual loop)
# pid.y / pid.yl = Y motor encoder / linear scale (dual loop)
# pid.zl = Z linear scale (single loop, no motor encoder)
# pid.s = spindle (not actively used)
loadrt pid names=pid.x,pid.y,pid.s,pid.xl,pid.yl,pid.zl loadrt pid names=pid.x,pid.y,pid.s,pid.xl,pid.yl,pid.zl
# --- Servo thread function execution order ---
addf hm2_5i24.0.read servo-thread addf hm2_5i24.0.read servo-thread
addf motion-command-handler servo-thread addf motion-command-handler servo-thread
addf motion-controller servo-thread addf motion-controller servo-thread
@@ -42,7 +60,10 @@ addf pid.zl.do-pid-calcs servo-thread
addf pid.s.do-pid-calcs servo-thread addf pid.s.do-pid-calcs servo-thread
addf hm2_5i24.0.write servo-thread addf hm2_5i24.0.write servo-thread
# relay outputs # --- GPIO relay outputs (active low / inverted) ---
# GPIO 041 = spindle on/off relay
# GPIO 044 = Z-axis servo enable relay
# GPIO 046 = X-axis servo enable relay
setp hm2_5i24.0.gpio.041.is_output true setp hm2_5i24.0.gpio.041.is_output true
setp hm2_5i24.0.gpio.044.is_output true setp hm2_5i24.0.gpio.044.is_output true
setp hm2_5i24.0.gpio.046.is_output true setp hm2_5i24.0.gpio.046.is_output true
@@ -50,13 +71,15 @@ setp hm2_5i24.0.gpio.041.invert_output true
setp hm2_5i24.0.gpio.044.invert_output true setp hm2_5i24.0.gpio.044.invert_output true
setp hm2_5i24.0.gpio.046.invert_output true setp hm2_5i24.0.gpio.046.invert_output true
# some inputs # --- GPIO button inputs (active low, not all wired into HAL logic) ---
# GPIO 029 = ESTOP, 030 = START, 031 = STOP
setp hm2_5i24.0.gpio.027.is_output false setp hm2_5i24.0.gpio.027.is_output false
setp hm2_5i24.0.gpio.028.is_output false setp hm2_5i24.0.gpio.028.is_output false
setp hm2_5i24.0.gpio.029.is_output false # ESTOP setp hm2_5i24.0.gpio.029.is_output false # ESTOP
setp hm2_5i24.0.gpio.030.is_output false # START setp hm2_5i24.0.gpio.030.is_output false # START
setp hm2_5i24.0.gpio.031.is_output false # STOP setp hm2_5i24.0.gpio.031.is_output false # STOP
# Button wiring attempts - commented out, caused machine to shut off unexpectedly
#net machine_estop_out <= hm2_5i24.0.gpio.029.in_not #net machine_estop_out <= hm2_5i24.0.gpio.029.in_not
#net machine_estop_out => halui.machine.on #net machine_estop_out => halui.machine.on
@@ -69,7 +92,8 @@ setp hm2_5i24.0.gpio.031.is_output false # STOP
# net btn-start hm2_5i24.0.gpio.030.in_not => halui.program.resume # net btn-start hm2_5i24.0.gpio.030.in_not => halui.program.resume
# first ADC # --- ADC inputs (commented out, unused) ---
# first ADC (GPIO 032-039)
#setp hm2_5i24.0.gpio.032.is_output false #setp hm2_5i24.0.gpio.032.is_output false
#setp hm2_5i24.0.gpio.033.is_output false #setp hm2_5i24.0.gpio.033.is_output false
#setp hm2_5i24.0.gpio.034.is_output false #setp hm2_5i24.0.gpio.034.is_output false
@@ -79,7 +103,7 @@ setp hm2_5i24.0.gpio.031.is_output false # STOP
#setp hm2_5i24.0.gpio.038.is_output false #setp hm2_5i24.0.gpio.038.is_output false
#setp hm2_5i24.0.gpio.039.is_output false #setp hm2_5i24.0.gpio.039.is_output false
# second ADC # second ADC (GPIO 040-047)
#setp hm2_5i24.0.gpio.040.is_output false #setp hm2_5i24.0.gpio.040.is_output false
#setp hm2_5i24.0.gpio.041.is_output false #setp hm2_5i24.0.gpio.041.is_output false
#setp hm2_5i24.0.gpio.042.is_output false #setp hm2_5i24.0.gpio.042.is_output false
@@ -89,7 +113,7 @@ setp hm2_5i24.0.gpio.031.is_output false # STOP
#setp hm2_5i24.0.gpio.046.is_output false #setp hm2_5i24.0.gpio.046.is_output false
#setp hm2_5i24.0.gpio.047.is_output false #setp hm2_5i24.0.gpio.047.is_output false
# weighted_sum wiring for ADC (unused)
#net hm2_5i24.0.gpio.032 <= wsum.0.bit.0.in #net hm2_5i24.0.gpio.032 <= wsum.0.bit.0.in
#net hm2_5i24.0.gpio.033 <= wsum.0.bit.1.in #net hm2_5i24.0.gpio.033 <= wsum.0.bit.1.in
#net hm2_5i24.0.gpio.034 <= wsum.0.bit.2.in #net hm2_5i24.0.gpio.034 <= wsum.0.bit.2.in
@@ -99,10 +123,16 @@ setp hm2_5i24.0.gpio.031.is_output false # STOP
#net hm2_5i24.0.gpio.038 <= wsum.0.bit.6.in #net hm2_5i24.0.gpio.038 <= wsum.0.bit.6.in
#net hm2_5i24.0.gpio.039 <= wsum.0.bit.7.in #net hm2_5i24.0.gpio.039 <= wsum.0.bit.7.in
# ****************** # ============================================================================
# AXIS X JOINT 0 # AXIS X - JOINT 0
# ****************** # Dual PID: pid.x (motor encoder) + pid.xl (linear scale), summed via sum2.0
# Motor encoder: hm2 encoder 03
# Linear scale: hm2 encoder 00
# PWM output: pwmgen.00
# Enable relay: GPIO 046 (active low)
# ============================================================================
# --- X motor encoder PID (velocity/damping loop) ---
setp pid.x.Pgain [JOINT_0]P setp pid.x.Pgain [JOINT_0]P
setp pid.x.Igain 0 setp pid.x.Igain 0
setp pid.x.Dgain [JOINT_0]D setp pid.x.Dgain [JOINT_0]D
@@ -118,6 +148,7 @@ net x-enable => pid.x.enable
net x-pos-mtr => pid.x.feedback net x-pos-mtr => pid.x.feedback
net x-output-mtr <= pid.x.output net x-output-mtr <= pid.x.output
# --- X linear scale PID (position correction loop) ---
setp pid.xl.Pgain [JOINT_0]P_LIN setp pid.xl.Pgain [JOINT_0]P_LIN
setp pid.xl.Igain [JOINT_0]I_LIN setp pid.xl.Igain [JOINT_0]I_LIN
setp pid.xl.Dgain [JOINT_0]D_LIN setp pid.xl.Dgain [JOINT_0]D_LIN
@@ -133,10 +164,12 @@ net x-enable => pid.xl.enable
net x-pos-lin => pid.xl.feedback net x-pos-lin => pid.xl.feedback
net x-output-lin <= pid.xl.output net x-output-lin <= pid.xl.output
# Sum motor + linear PID outputs for final X drive signal
net x-output-lin => sum2.0.in0 net x-output-lin => sum2.0.in0
net x-output-mtr => sum2.0.in1 net x-output-mtr => sum2.0.in1
net x-output <= sum2.0.out net x-output <= sum2.0.out
# Position command feeds both PID loops
net x-pos-cmd <= joint.0.motor-pos-cmd net x-pos-cmd <= joint.0.motor-pos-cmd
net x-pos-cmd => pid.xl.command net x-pos-cmd => pid.xl.command
net x-pos-cmd => pid.x.command net x-pos-cmd => pid.x.command
@@ -149,11 +182,13 @@ setp hm2_5i24.0.pwmgen.00.offset-mode 1
net x-output => hm2_5i24.0.pwmgen.00.value net x-output => hm2_5i24.0.pwmgen.00.value
net x-enable joint.0.amp-enable-out => hm2_5i24.0.pwmgen.00.enable net x-enable joint.0.amp-enable-out => hm2_5i24.0.pwmgen.00.enable
# X enable also drives GPIO 046 relay
net x-enable => hm2_5i24.0.gpio.046.out net x-enable => hm2_5i24.0.gpio.046.out
net x-pos-rawcounts <= hm2_5i24.0.encoder.00.rawcounts net x-pos-rawcounts <= hm2_5i24.0.encoder.00.rawcounts
# ---Encoder feedback signals/setup--- # ---Encoder feedback signals/setup---
# Motor encoder (encoder 03)
setp hm2_5i24.0.encoder.03.counter-mode 0 setp hm2_5i24.0.encoder.03.counter-mode 0
setp hm2_5i24.0.encoder.03.filter 1 setp hm2_5i24.0.encoder.03.filter 1
setp hm2_5i24.0.encoder.03.index-invert 0 setp hm2_5i24.0.encoder.03.index-invert 0
@@ -161,6 +196,7 @@ setp hm2_5i24.0.encoder.03.index-mask 0
setp hm2_5i24.0.encoder.03.index-mask-invert 0 setp hm2_5i24.0.encoder.03.index-mask-invert 0
setp hm2_5i24.0.encoder.03.scale [JOINT_0]ENCODER_MTR_SCALE setp hm2_5i24.0.encoder.03.scale [JOINT_0]ENCODER_MTR_SCALE
# Linear scale (encoder 00)
setp hm2_5i24.0.encoder.00.counter-mode 0 setp hm2_5i24.0.encoder.00.counter-mode 0
setp hm2_5i24.0.encoder.00.filter 1 setp hm2_5i24.0.encoder.00.filter 1
setp hm2_5i24.0.encoder.00.index-invert 0 setp hm2_5i24.0.encoder.00.index-invert 0
@@ -173,15 +209,21 @@ net x-vel-mtr <= hm2_5i24.0.encoder.03.velocity
net x-index-enable joint.0.index-enable <=> hm2_5i24.0.encoder.03.index-enable net x-index-enable joint.0.index-enable <=> hm2_5i24.0.encoder.03.index-enable
#net x-pos-mtr => joint.0.motor-pos-fb #net x-pos-mtr => joint.0.motor-pos-fb
# Linear scale provides the actual position feedback to the joint
net x-pos-lin <= hm2_5i24.0.encoder.00.position net x-pos-lin <= hm2_5i24.0.encoder.00.position
net x-vel-lin <= hm2_5i24.0.encoder.00.velocity net x-vel-lin <= hm2_5i24.0.encoder.00.velocity
net x-index-enable joint.0.index-enable <=> hm2_5i24.0.encoder.00.index-enable net x-index-enable joint.0.index-enable <=> hm2_5i24.0.encoder.00.index-enable
net x-pos-lin => joint.0.motor-pos-fb net x-pos-lin => joint.0.motor-pos-fb
# ****************** # ============================================================================
# AXIS Y JOINT 1 # AXIS Y - JOINT 1
# ****************** # Dual PID: pid.y (motor encoder) + pid.yl (linear scale), summed via sum2.1
# Motor encoder: hm2 encoder 04
# Linear scale: hm2 encoder 01
# PWM output: pwmgen.02
# ============================================================================
# --- Y motor encoder PID (velocity/damping loop) ---
setp pid.y.Pgain [JOINT_1]P setp pid.y.Pgain [JOINT_1]P
setp pid.y.Igain 0 setp pid.y.Igain 0
setp pid.y.Dgain [JOINT_1]D setp pid.y.Dgain [JOINT_1]D
@@ -197,6 +239,7 @@ net y-enable => pid.y.enable
net y-pos-mtr => pid.y.feedback net y-pos-mtr => pid.y.feedback
net y-output-mtr <= pid.y.output net y-output-mtr <= pid.y.output
# --- Y linear scale PID (position correction loop) ---
setp pid.yl.Pgain [JOINT_1]P_LIN setp pid.yl.Pgain [JOINT_1]P_LIN
setp pid.yl.Igain [JOINT_1]I_LIN setp pid.yl.Igain [JOINT_1]I_LIN
setp pid.yl.Dgain [JOINT_1]D_LIN setp pid.yl.Dgain [JOINT_1]D_LIN
@@ -212,10 +255,12 @@ net y-enable => pid.yl.enable
net y-pos-lin => pid.yl.feedback net y-pos-lin => pid.yl.feedback
net y-output-lin <= pid.yl.output net y-output-lin <= pid.yl.output
# Sum motor + linear PID outputs for final Y drive signal
net y-output-lin => sum2.1.in0 net y-output-lin => sum2.1.in0
net y-output-mtr => sum2.1.in1 net y-output-mtr => sum2.1.in1
net y-output <= sum2.1.out net y-output <= sum2.1.out
# Position command feeds both PID loops
net y-pos-cmd <= joint.1.motor-pos-cmd net y-pos-cmd <= joint.1.motor-pos-cmd
net y-pos-cmd => pid.yl.command net y-pos-cmd => pid.yl.command
net y-pos-cmd => pid.y.command net y-pos-cmd => pid.y.command
@@ -233,6 +278,7 @@ net y-pos-rawcounts <= hm2_5i24.0.encoder.01.rawcounts
# ---Encoder feedback signals/setup--- # ---Encoder feedback signals/setup---
# Motor encoder (encoder 04)
setp hm2_5i24.0.encoder.04.counter-mode 0 setp hm2_5i24.0.encoder.04.counter-mode 0
setp hm2_5i24.0.encoder.04.filter 1 setp hm2_5i24.0.encoder.04.filter 1
setp hm2_5i24.0.encoder.04.index-invert 0 setp hm2_5i24.0.encoder.04.index-invert 0
@@ -240,6 +286,7 @@ setp hm2_5i24.0.encoder.04.index-mask 0
setp hm2_5i24.0.encoder.04.index-mask-invert 0 setp hm2_5i24.0.encoder.04.index-mask-invert 0
setp hm2_5i24.0.encoder.04.scale [JOINT_1]ENCODER_MTR_SCALE setp hm2_5i24.0.encoder.04.scale [JOINT_1]ENCODER_MTR_SCALE
# Linear scale (encoder 01)
setp hm2_5i24.0.encoder.01.counter-mode 0 setp hm2_5i24.0.encoder.01.counter-mode 0
setp hm2_5i24.0.encoder.01.filter 1 setp hm2_5i24.0.encoder.01.filter 1
setp hm2_5i24.0.encoder.01.index-invert 0 setp hm2_5i24.0.encoder.01.index-invert 0
@@ -252,15 +299,28 @@ net y-vel-mtr <= hm2_5i24.0.encoder.04.velocity
net y-index-enable joint.1.index-enable <=> hm2_5i24.0.encoder.04.index-enable net y-index-enable joint.1.index-enable <=> hm2_5i24.0.encoder.04.index-enable
#net y-pos-mtr => joint.1.motor-pos-fb #net y-pos-mtr => joint.1.motor-pos-fb
# Linear scale provides the actual position feedback to the joint
net y-pos-lin <= hm2_5i24.0.encoder.01.position net y-pos-lin <= hm2_5i24.0.encoder.01.position
net y-vel-lin <= hm2_5i24.0.encoder.01.velocity net y-vel-lin <= hm2_5i24.0.encoder.01.velocity
net y-index-enable joint.1.index-enable <=> hm2_5i24.0.encoder.01.index-enable net y-index-enable joint.1.index-enable <=> hm2_5i24.0.encoder.01.index-enable
net y-pos-lin => joint.1.motor-pos-fb net y-pos-lin => joint.1.motor-pos-fb
#******************* # ============================================================================
# AXIS Z JOINT 2 # AXIS Z - JOINT 2
#******************* # Single PID: pid.zl (linear scale only), output via sum2.2
# Linear scale: hm2 encoder 02
# PWM output: pwmgen.04
# Enable relay: GPIO 044 (active low), gated by z-override AND gate
#
# Z-OVERRIDE MECHANISM:
# A HAL "logic AND" gate combines z-override (default TRUE) with z-enable.
# When z-override is set FALSE (via M101), the AND output goes low,
# disabling the Z servo and GPIO 044 relay. This allows manual quill use.
# M102 sets z-override back to TRUE to re-enable CNC Z control.
# MIN_FERROR is set to 100 in INI to prevent following errors during manual mode.
# ============================================================================
# Z motor encoder PID commented out - no motor encoder on Z axis
#setp pid.z.Pgain [JOINT_2]P #setp pid.z.Pgain [JOINT_2]P
#setp pid.z.Igain 0 #setp pid.z.Igain 0
#setp pid.z.Dgain [JOINT_2]D #setp pid.z.Dgain [JOINT_2]D
@@ -276,6 +336,7 @@ net y-pos-lin => joint.1.motor-pos-fb
#net z-pos-mtr => pid.z.feedback #net z-pos-mtr => pid.z.feedback
#net z-output-mtr <= pid.z.output #net z-output-mtr <= pid.z.output
# --- Z linear scale PID ---
setp pid.zl.Pgain [JOINT_2]P setp pid.zl.Pgain [JOINT_2]P
setp pid.zl.Igain [JOINT_2]I setp pid.zl.Igain [JOINT_2]I
setp pid.zl.Dgain [JOINT_2]D setp pid.zl.Dgain [JOINT_2]D
@@ -287,13 +348,17 @@ setp pid.zl.deadband [JOINT_2]DEADBAND
setp pid.zl.maxoutput [JOINT_2]MAX_OUTPUT setp pid.zl.maxoutput [JOINT_2]MAX_OUTPUT
setp pid.zl.error-previous-target true setp pid.zl.error-previous-target true
# Z-override AND gate: z-enable-comb = z-override AND z-enable
# When z-override is FALSE, Z servo is disabled (manual quill mode)
net z-override => logic.0.in-00 net z-override => logic.0.in-00
net z-enable => logic.0.in-01 net z-enable => logic.0.in-01
net z-enable-comb <= logic.0.and net z-enable-comb <= logic.0.and
# Default: z-override is TRUE (CNC controls Z)
sets z-override TRUE sets z-override TRUE
# this section about ferror doesnt work # Attempted dynamic ferror switching (not functional - see INI workaround)
# mux2 selects between 100 (disabled) and 0.2 (enabled) based on z-enable-comb
net z-enable-comb => mux2.0.sel net z-enable-comb => mux2.0.sel
setp mux2.0.in0 100 setp mux2.0.in0 100
setp mux2.0.in1 0.2 setp mux2.0.in1 0.2
@@ -304,6 +369,7 @@ net z-enable-comb => pid.zl.enable
net z-pos-lin => pid.zl.feedback net z-pos-lin => pid.zl.feedback
net z-output-lin <= pid.zl.output net z-output-lin <= pid.zl.output
# Z only has linear scale PID, no motor encoder sum needed
net z-output-lin => sum2.2.in0 net z-output-lin => sum2.2.in0
#net z-output-mtr => sum2.2.in1 #net z-output-mtr => sum2.2.in1
net z-output <= sum2.2.out net z-output <= sum2.2.out
@@ -320,11 +386,13 @@ setp hm2_5i24.0.pwmgen.04.offset-mode 1
net z-output => hm2_5i24.0.pwmgen.04.value net z-output => hm2_5i24.0.pwmgen.04.value
net z-enable joint.2.amp-enable-out => hm2_5i24.0.pwmgen.04.enable net z-enable joint.2.amp-enable-out => hm2_5i24.0.pwmgen.04.enable
# Z enable relay gated through AND gate (z-override mechanism)
net z-enable-comb => hm2_5i24.0.gpio.044.out net z-enable-comb => hm2_5i24.0.gpio.044.out
net z-pos-rawcounts <= hm2_5i24.0.encoder.02.rawcounts net z-pos-rawcounts <= hm2_5i24.0.encoder.02.rawcounts
# ---Encoder feedback signals/setup--- # ---Encoder feedback signals/setup---
# Motor encoder (encoder 05) - not used on Z axis
#setp hm2_5i24.0.encoder.05.counter-mode 0 #setp hm2_5i24.0.encoder.05.counter-mode 0
#setp hm2_5i24.0.encoder.05.filter 1 #setp hm2_5i24.0.encoder.05.filter 1
#setp hm2_5i24.0.encoder.05.index-invert 0 #setp hm2_5i24.0.encoder.05.index-invert 0
@@ -332,6 +400,7 @@ net z-pos-rawcounts <= hm2_5i24.0.encoder.02.rawcounts
#setp hm2_5i24.0.encoder.05.index-mask-invert 0 #setp hm2_5i24.0.encoder.05.index-mask-invert 0
#setp hm2_5i24.0.encoder.05.scale [JOINT_2]ENCODER_MTR_SCALE #setp hm2_5i24.0.encoder.05.scale [JOINT_2]ENCODER_MTR_SCALE
# Linear scale (encoder 02)
setp hm2_5i24.0.encoder.02.counter-mode 0 setp hm2_5i24.0.encoder.02.counter-mode 0
setp hm2_5i24.0.encoder.02.filter 1 setp hm2_5i24.0.encoder.02.filter 1
setp hm2_5i24.0.encoder.02.index-invert 0 setp hm2_5i24.0.encoder.02.index-invert 0
@@ -344,19 +413,23 @@ setp hm2_5i24.0.encoder.02.scale [JOINT_2]ENCODER_LIN_SCALE
#net z-index-enable joint.2.index-enable <=> hm2_5i24.0.encoder.05.index-enable #net z-index-enable joint.2.index-enable <=> hm2_5i24.0.encoder.05.index-enable
#net z-pos-mtr => joint.2.motor-pos-fb #net z-pos-mtr => joint.2.motor-pos-fb
# Linear scale provides the actual position feedback to the joint
net z-pos-lin <= hm2_5i24.0.encoder.02.position net z-pos-lin <= hm2_5i24.0.encoder.02.position
net z-vel-lin <= hm2_5i24.0.encoder.02.velocity net z-vel-lin <= hm2_5i24.0.encoder.02.velocity
net z-index-enable joint.2.index-enable <=> hm2_5i24.0.encoder.02.index-enable net z-index-enable joint.2.index-enable <=> hm2_5i24.0.encoder.02.index-enable
net z-pos-lin => joint.2.motor-pos-fb net z-pos-lin => joint.2.motor-pos-fb
#### SPINDLE #### # ============================================================================
# SPINDLE
# On/off relay via GPIO 041 (active low). No speed control or feedback.
# ============================================================================
#net spindle.0.on spindle-enable #net spindle.0.on spindle-enable
net spindle-enable spindle.0.on => hm2_5i24.0.gpio.041.out net spindle-enable spindle.0.on => hm2_5i24.0.gpio.041.out
#****************************** # ============================================================================
# connect miscellaneous signals # MISCELLANEOUS SIGNALS
#****************************** # ============================================================================
# ---coolant signals--- # ---coolant signals---
@@ -375,7 +448,7 @@ net machine-is-enabled <= motion.motion-enabled
# ---digital in / out signals--- # ---digital in / out signals---
# ---estop signals--- # ---estop signals---
# Estop loops back: user-enable-out feeds emc-enable-in (no external estop chain)
net estop-out <= iocontrol.0.user-enable-out net estop-out <= iocontrol.0.user-enable-out
net estop-out => iocontrol.0.emc-enable-in net estop-out => iocontrol.0.emc-enable-in
@@ -395,4 +468,3 @@ net tool-number => hal_manualtoolchange.number
# ---ignore tool prepare requests--- # ---ignore tool prepare requests---
net tool-prepare-loopback iocontrol.0.tool-prepare => iocontrol.0.tool-prepared net tool-prepare-loopback iocontrol.0.tool-prepare => iocontrol.0.tool-prepared

View File

@@ -1,12 +1,21 @@
# Lagun milling machine configuration for GMOCCAPY GUI
# Based on lagun config (PNCconf Fri Jul 26 13:18:08 2024) # Based on lagun config (PNCconf Fri Jul 26 13:18:08 2024)
# Modified to use GMOCCAPY instead of AXIS # Modified to use GMOCCAPY instead of AXIS
# Using LinuxCNC version: Master (2.9) # Using LinuxCNC version: Master (2.9)
#
# Hardware: Mesa 5i24 FPGA card (hm2_pci)
# Axes: X, Y (dual encoder: motor + linear scale), Z (linear scale only)
# Pendant: XHC WHB04B-6 wireless
# Spindle: On/off relay (no speed control)
# Units: Imperial (inches)
# --- General EMC settings ---
[EMC] [EMC]
MACHINE = my_LinuxCNC_machine MACHINE = my_LinuxCNC_machine
DEBUG = 0 DEBUG = 0
VERSION = 1.1 VERSION = 1.1
# --- GUI configuration ---
[DISPLAY] [DISPLAY]
DISPLAY = gmoccapy DISPLAY = gmoccapy
POSITION_OFFSET = RELATIVE POSITION_OFFSET = RELATIVE
@@ -17,6 +26,7 @@ MIN_SPINDLE_OVERRIDE = 0.500000
INTRO_GRAPHIC = linuxcnc.gif INTRO_GRAPHIC = linuxcnc.gif
INTRO_TIME = 5 INTRO_TIME = 5
PROGRAM_PREFIX = /home/linuxcnc/linuxcnc/nc_files PROGRAM_PREFIX = /home/linuxcnc/linuxcnc/nc_files
# Jog increments available in the GUI (inches)
INCREMENTS = 0.1000 0.0500 0.0100 0.0050 0.0010 0.0005 0.0001 INCREMENTS = 0.1000 0.0500 0.0100 0.0050 0.0010 0.0005 0.0001
DEFAULT_LINEAR_VELOCITY = 3.0 DEFAULT_LINEAR_VELOCITY = 3.0
MAX_LINEAR_VELOCITY = 1.000000 MAX_LINEAR_VELOCITY = 1.000000
@@ -29,6 +39,7 @@ GEOMETRY = xyz
CYCLE_TIME = 100 CYCLE_TIME = 100
DEFAULT_SPINDLE_SPEED = 500 DEFAULT_SPINDLE_SPEED = 500
# --- File type filters for loading programs ---
[FILTER] [FILTER]
PROGRAM_EXTENSION = .png,.gif,.jpg Greyscale Depth Image PROGRAM_EXTENSION = .png,.gif,.jpg Greyscale Depth Image
PROGRAM_EXTENSION = .py Python Script PROGRAM_EXTENSION = .py Python Script
@@ -37,23 +48,31 @@ gif = image-to-gcode
jpg = image-to-gcode jpg = image-to-gcode
py = python3 py = python3
# --- Task controller ---
[TASK] [TASK]
TASK = milltask TASK = milltask
CYCLE_TIME = 0.010 CYCLE_TIME = 0.010
# --- G-code interpreter ---
[RS274NGC] [RS274NGC]
PARAMETER_FILE = linuxcnc.var PARAMETER_FILE = linuxcnc.var
# Startup: G20=inch, G40=cancel cutter comp, G90=absolute, G94=feed/min,
# G97=RPM mode, G64 P0.001=path blending tolerance 0.001"
RS274NGC_STARTUP_CODE = G20 G40 G90 G94 G97 G64 P0.001 RS274NGC_STARTUP_CODE = G20 G40 G90 G94 G97 G64 P0.001
# --- Motion controller ---
[EMCMOT] [EMCMOT]
EMCMOT = motmod EMCMOT = motmod
COMM_TIMEOUT = 1.0 COMM_TIMEOUT = 1.0
# 1ms servo period
SERVO_PERIOD = 1000000 SERVO_PERIOD = 1000000
# --- Mesa 5i24 FPGA card ---
[HMOT] [HMOT]
# **** This is for info only **** # **** This is for info only ****
CARD0=hm2_5i24.0 CARD0=hm2_5i24.0
# --- HAL file loading order ---
[HAL] [HAL]
HALUI = halui HALUI = halui
HALFILE = lagun.hal HALFILE = lagun.hal
@@ -61,6 +80,16 @@ HALFILE = xhc-whb04b-6.hal
POSTGUI_HALFILE = gmoccapy_postgui.hal POSTGUI_HALFILE = gmoccapy_postgui.hal
SHUTDOWN = shutdown.hal SHUTDOWN = shutdown.hal
# --- MDI commands for HALUI (pendant macro buttons) ---
# Index 00: (unused, debug)
# Index 01: Halve X coordinate (macro button 1)
# Index 02: Halve Y coordinate (macro button 2)
# Index 03: (unused, debug)
# Index 04: (unused, debug)
# Index 05: Zero X in current work offset (macro button 5)
# Index 06: Zero Y in current work offset (macro button 6)
# Index 07: Zero Z in current work offset (macro button 7)
# Index 08-14: (unused, debug or reserved)
[HALUI] [HALUI]
MDI_COMMAND=(DEBUG,<1>) MDI_COMMAND=(DEBUG,<1>)
MDI_COMMAND=G10 L20 P0 X[#<_x>/2.0] MDI_COMMAND=G10 L20 P0 X[#<_x>/2.0]
@@ -78,24 +107,34 @@ SHUTDOWN = shutdown.hal
MDI_COMMAND=(DEBUG,<13>) MDI_COMMAND=(DEBUG,<13>)
MDI_COMMAND=(DEBUG,<14>) MDI_COMMAND=(DEBUG,<14>)
# --- Kinematics ---
[KINS] [KINS]
JOINTS = 3 JOINTS = 3
KINEMATICS = trivkins coordinates=XYZ KINEMATICS = trivkins coordinates=XYZ
# --- Trajectory planner ---
[TRAJ] [TRAJ]
COORDINATES = XYZ COORDINATES = XYZ
LINEAR_UNITS = inch LINEAR_UNITS = inch
ANGULAR_UNITS = degree ANGULAR_UNITS = degree
DEFAULT_LINEAR_VELOCITY = 3.0 DEFAULT_LINEAR_VELOCITY = 3.0
MAX_LINEAR_VELOCITY = 1.00 MAX_LINEAR_VELOCITY = 1.00
# Allow motion without homing first
NO_FORCE_HOMING = 1 NO_FORCE_HOMING = 1
# --- I/O controller ---
[EMCIO] [EMCIO]
EMCIO = io EMCIO = io
CYCLE_TIME = 0.100 CYCLE_TIME = 0.100
TOOL_TABLE = tool.tbl TOOL_TABLE = tool.tbl
# Raise quill before tool change
TOOL_CHANGE_QUILL_UP = 1 TOOL_CHANGE_QUILL_UP = 1
#******************************************
# X AXIS - Joint 0
# Dual feedback: motor encoder (enc 03) + linear scale (enc 00)
# PWM output: pwmgen.00
# Enable relay: GPIO 046 (active low)
#****************************************** #******************************************
[AXIS_X] [AXIS_X]
MAX_VELOCITY = 1.0 MAX_VELOCITY = 1.0
@@ -113,8 +152,7 @@ MAX_ACCELERATION = 30.0
# The values below should be 25% larger than MAX_VELOCITY and MAX_ACCELERATION # The values below should be 25% larger than MAX_VELOCITY and MAX_ACCELERATION
# If using BACKLASH compensation STEPGEN_MAXACCEL should be 100% larger. # If using BACKLASH compensation STEPGEN_MAXACCEL should be 100% larger.
# Motor encoder PID gains (velocity loop)
P = 0 P = 0
I = 0 I = 0
D = 4 D = 4
@@ -123,6 +161,7 @@ FF0 = 0
FF1 = 0.6 FF1 = 0.6
FF2 = 0 FF2 = 0
# Linear scale PID gains (position correction loop)
P_LIN = 300 P_LIN = 300
I_LIN = 500 I_LIN = 500
D_LIN = 0 D_LIN = 0
@@ -131,6 +170,7 @@ BIAS = 0
DEADBAND = 0.0005 DEADBAND = 0.0005
MAX_OUTPUT = 0 MAX_OUTPUT = 0
# Encoder scales (counts per inch)
ENCODER_LIN_SCALE = 5085.5 ENCODER_LIN_SCALE = 5085.5
ENCODER_MTR_SCALE = -27939.6 ENCODER_MTR_SCALE = -27939.6
# 5.4 is the ratio between linear and motor scales, roughly # 5.4 is the ratio between linear and motor scales, roughly
@@ -149,6 +189,12 @@ HOME_SEQUENCE = 2
OUTPUT_SCALE = 1 OUTPUT_SCALE = 1
OUTPUT_OFFSET = 0 OUTPUT_OFFSET = 0
#******************************************
# Y AXIS - Joint 1
# Dual feedback: motor encoder (enc 04) + linear scale (enc 01)
# PWM output: pwmgen.02
# Enable relay: (shares Z-axis GPIO 044 line)
#******************************************
[AXIS_Y] [AXIS_Y]
MAX_VELOCITY = 1.0 MAX_VELOCITY = 1.0
MAX_ACCELERATION = 30.0 MAX_ACCELERATION = 30.0
@@ -165,6 +211,7 @@ MAX_ACCELERATION = 30.0
# The values below should be 25% larger than MAX_VELOCITY and MAX_ACCELERATION # The values below should be 25% larger than MAX_VELOCITY and MAX_ACCELERATION
# If using BACKLASH compensation STEPGEN_MAXACCEL should be 100% larger. # If using BACKLASH compensation STEPGEN_MAXACCEL should be 100% larger.
# Motor encoder PID gains (velocity loop)
P = 0 P = 0
I = 0 I = 0
D = 5 D = 5
@@ -173,6 +220,7 @@ FF0 = 0
FF1 = 0.6 FF1 = 0.6
FF2 = 0 FF2 = 0
# Linear scale PID gains (position correction loop)
P_LIN = 350 P_LIN = 350
I_LIN = 500 I_LIN = 500
D_LIN = 0 D_LIN = 0
@@ -181,6 +229,7 @@ BIAS = 0
DEADBAND = 0 DEADBAND = 0
MAX_OUTPUT = 1 MAX_OUTPUT = 1
# Encoder scales (counts per inch)
ENCODER_LIN_SCALE = 5085.4 ENCODER_LIN_SCALE = 5085.4
ENCODER_MTR_SCALE = 27453.6 ENCODER_MTR_SCALE = 27453.6
# these are in nanoseconds # these are in nanoseconds
@@ -194,10 +243,17 @@ MAX_LIMIT = +12
HOME_OFFSET = 0.0 HOME_OFFSET = 0.0
HOME_SEQUENCE = 3 HOME_SEQUENCE = 3
# Negative scale inverts direction
OUTPUT_SCALE = -1 OUTPUT_SCALE = -1
OUTPUT_OFFSET = 0 OUTPUT_OFFSET = 0
#****************************************** #******************************************
#******************************************
# Z AXIS - Joint 2
# Single feedback: linear scale only (enc 02), no motor encoder
# PWM output: pwmgen.04
# Enable relay: GPIO 044 (active low), gated by z-override AND logic
# z-override allows M101/M102 to disable CNC Z for manual quill use
#****************************************** #******************************************
[AXIS_Z] [AXIS_Z]
MAX_VELOCITY = 1.0 MAX_VELOCITY = 1.0
@@ -210,6 +266,8 @@ TYPE = LINEAR
HOME = 0.0 HOME = 0.0
FERROR = 0.5 FERROR = 0.5
# SETTING MIN_FERROR TO 100 ALLOWS Z AXIS TO DO WHATEVER. IDEALLY ITS 0.2 # SETTING MIN_FERROR TO 100 ALLOWS Z AXIS TO DO WHATEVER. IDEALLY ITS 0.2
# This is a workaround: when z-override disables the Z servo, the quill
# can be moved manually and would trip a normal following error limit.
MIN_FERROR = 100 MIN_FERROR = 100
MAX_VELOCITY = 1.0 MAX_VELOCITY = 1.0
MAX_ACCELERATION = 30.0 MAX_ACCELERATION = 30.0
@@ -217,6 +275,7 @@ MAX_ACCELERATION = 30.0
# If using BACKLASH compensation STEPGEN_MAXACCEL should be 100% larger. # If using BACKLASH compensation STEPGEN_MAXACCEL should be 100% larger.
STEPGEN_MAXVEL = 1.25 STEPGEN_MAXVEL = 1.25
STEPGEN_MAXACCEL = 37.50 STEPGEN_MAXACCEL = 37.50
# Linear scale PID gains (single loop, no motor encoder on Z)
P = 200 P = 200
I = 300 I = 300
D = 2 D = 2
@@ -237,12 +296,15 @@ MAX_LIMIT = +1.0
HOME_OFFSET = 0.0 HOME_OFFSET = 0.0
HOME_SEQUENCE = 1 HOME_SEQUENCE = 1
# Negative scale inverts direction
OUTPUT_SCALE = -1 OUTPUT_SCALE = -1
OUTPUT_OFFSET = 0 OUTPUT_OFFSET = 0
# Encoder scale (counts per inch)
ENCODER_LIN_SCALE = -10075 ENCODER_LIN_SCALE = -10075
#****************************************** #******************************************
# --- Spindle PID (not actively used; relay on/off only) ---
[SPINDLE_0] [SPINDLE_0]
P = 0 P = 0
I = 0 I = 0

View File

@@ -1,2 +1,3 @@
# Include your shutdown HAL commands here # Include your shutdown HAL commands here
# This file will not be overwritten when you run PNCconf again # This file will not be overwritten when you run PNCconf again
# Currently no shutdown actions are configured.

View File

@@ -1,30 +1,35 @@
# ============================================================================
# XHC WHB04B-6 wireless pendant configuration for Lagun mill
# Provides jog wheel, axis select, feed override, homing, and macro buttons
# ============================================================================
# ###################################################################### # ######################################################################
# load pendant components # load pendant components
# ###################################################################### # ######################################################################
# -H = HAL-only mode, -s = step mode, -f = filtered, -B = big (6-axis pendant)
loadusr -W xhc-whb04b-6 -HsfB loadusr -W xhc-whb04b-6 -HsfB
# ###################################################################### # ######################################################################
# pendant signal configuration # pendant signal configuration
# ###################################################################### # ######################################################################
# On/Off signals # --- Machine on/off ---
net machine.is-on halui.machine.is-on whb.halui.machine.is-on net machine.is-on halui.machine.is-on whb.halui.machine.is-on
# net pdnt.machine.on whb.halui.machine.on halui.machine.on # net pdnt.machine.on whb.halui.machine.on halui.machine.on
# net pdnt.machine.off whb.halui.machine.off halui.machine.off # net pdnt.machine.off whb.halui.machine.off halui.machine.off
# program related signals # --- Program state feedback (read-only status to pendant) ---
net pdnt.program.is-idle whb.halui.program.is-idle halui.program.is-idle net pdnt.program.is-idle whb.halui.program.is-idle halui.program.is-idle
net pdnt.program.is-paused whb.halui.program.is-paused halui.program.is-paused net pdnt.program.is-paused whb.halui.program.is-paused halui.program.is-paused
net pdnt.program-is-running whb.halui.program.is-running halui.program.is-running net pdnt.program-is-running whb.halui.program.is-running halui.program.is-running
# Program control buttons disabled
#net pdnt.program.resume whb.halui.program.resume halui.program.resume #net pdnt.program.resume whb.halui.program.resume halui.program.resume
#net pdnt.program.pause whb.halui.program.pause halui.program.pause #net pdnt.program.pause whb.halui.program.pause halui.program.pause
#net pdnt.program.run whb.halui.program.run halui.program.run #net pdnt.program.run whb.halui.program.run halui.program.run
#net pdnt.program.stop whb.halui.program.stop halui.program.stop #net pdnt.program.stop whb.halui.program.stop halui.program.stop
# machine mode related signals # --- Machine mode (auto/manual/mdi/joint/teleop) ---
net pdnt.mode.auto whb.halui.mode.auto halui.mode.auto net pdnt.mode.auto whb.halui.mode.auto halui.mode.auto
net pdnt.mode.manual whb.halui.mode.manual halui.mode.manual net pdnt.mode.manual whb.halui.mode.manual halui.mode.manual
net pdnt.mode.mdi whb.halui.mode.mdi halui.mode.mdi net pdnt.mode.mdi whb.halui.mode.mdi halui.mode.mdi
@@ -36,12 +41,12 @@ net pdnt.mode.is-mdi halui.mode.is-mdi
net pdnt.mode.is-joint halui.mode.is-joint whb.halui.mode.is-joint net pdnt.mode.is-joint halui.mode.is-joint whb.halui.mode.is-joint
net pdnt.mode.is-teleop halui.mode.is-teleop whb.halui.mode.is-teleop net pdnt.mode.is-teleop halui.mode.is-teleop whb.halui.mode.is-teleop
# "is-homed" axis signal for allowing pendant when machine is not homed # --- Homed status per axis (pendant needs this to allow jogging) ---
net pdnt.axis.X.is-homed halui.joint.0.is-homed whb.halui.joint.x.is-homed net pdnt.axis.X.is-homed halui.joint.0.is-homed whb.halui.joint.x.is-homed
net pdnt.axis.Y.is-homed halui.joint.1.is-homed whb.halui.joint.y.is-homed net pdnt.axis.Y.is-homed halui.joint.1.is-homed whb.halui.joint.y.is-homed
net pdnt.axis.Z.is-homed halui.joint.2.is-homed whb.halui.joint.z.is-homed net pdnt.axis.Z.is-homed halui.joint.2.is-homed whb.halui.joint.z.is-homed
# "selected axis" signals # --- Axis select (pendant rotary switch picks active axis) ---
net pdnt.axis.X.select whb.halui.axis.x.select halui.axis.x.select net pdnt.axis.X.select whb.halui.axis.x.select halui.axis.x.select
net pdnt.axis.y.select whb.halui.axis.y.select halui.axis.y.select net pdnt.axis.y.select whb.halui.axis.y.select halui.axis.y.select
net pdnt.axis.Z.select whb.halui.axis.z.select halui.axis.z.select net pdnt.axis.Z.select whb.halui.axis.z.select halui.axis.z.select
@@ -67,18 +72,27 @@ net pdnt.axis.y.jog-vel-mode whb.axis.y.jog-vel-mode
net pdnt.axis.z.jog-vel-mode whb.axis.z.jog-vel-mode joint.2.jog-vel-mode net pdnt.axis.z.jog-vel-mode whb.axis.z.jog-vel-mode joint.2.jog-vel-mode
# macro buttons to MDI commands # --- Macro buttons mapped to MDI commands (see [HALUI] in INI) ---
# Macro 1: halve X coord (MDI 01)
# Macro 2: halve Y coord (MDI 02)
net pdnt.macro-1 whb.button.macro-1 halui.mdi-command-01 # use MDI command from main.ini net pdnt.macro-1 whb.button.macro-1 halui.mdi-command-01 # use MDI command from main.ini
net pdnt.macro-2 whb.button.macro-2 halui.mdi-command-02 # use MDI command from main.ini or used for Hardcoded lube on/off net pdnt.macro-2 whb.button.macro-2 halui.mdi-command-02 # use MDI command from main.ini or used for Hardcoded lube on/off
# Macro 3,4: hardcoded spindle+/- inside pendant firmware
#net pdnt.reserved.for.spindle+ whb.button.macro-3 # Hardcoded for spindle+ whb.halui.spindle.increase #net pdnt.reserved.for.spindle+ whb.button.macro-3 # Hardcoded for spindle+ whb.halui.spindle.increase
#net pdnt.reserved.for.spindle- whb.button.macro-4 # Hardcoded for spindle- whb.halui.spindle.decrease #net pdnt.reserved.for.spindle- whb.button.macro-4 # Hardcoded for spindle- whb.halui.spindle.decrease
# Macro 5: zero X (MDI 05)
# Macro 6: zero Y (MDI 06)
# Macro 7: zero Z (MDI 07)
net pdnt.macro-5 whb.button.macro-5 halui.mdi-command-05 # use MDI command from main.ini net pdnt.macro-5 whb.button.macro-5 halui.mdi-command-05 # use MDI command from main.ini
net pdnt.macro-6 whb.button.macro-6 halui.mdi-command-06 # use MDI command from main.ini net pdnt.macro-6 whb.button.macro-6 halui.mdi-command-06 # use MDI command from main.ini
net pdnt.macro-7 whb.button.macro-7 halui.mdi-command-07 # use MDI command from main.ini net pdnt.macro-7 whb.button.macro-7 halui.mdi-command-07 # use MDI command from main.ini
# Macro 8: hardcoded spindle direction inside pendant
#net pdnt.reserved.for.spindle.dir whb.button.macro-8 # Hardcoded for spindle direction inside pendant #net pdnt.reserved.for.spindle.dir whb.button.macro-8 # Hardcoded for spindle direction inside pendant
net pdnt.macro-9 whb.button.macro-9 halui.mdi-command-09 # use MDI command from main.ini net pdnt.macro-9 whb.button.macro-9 halui.mdi-command-09 # use MDI command from main.ini
# Macro 10: hardcoded ABS/REL DRO toggle
net pdnt.reserved.for.ABS-REL whb.button.macro-10 # Hardcoded for swap Dro Relative/Absolue net pdnt.reserved.for.ABS-REL whb.button.macro-10 # Hardcoded for swap Dro Relative/Absolue
net pdnt.macro-14 whb.button.macro-14 halui.mdi-command-14 # use MDI command from main.ini net pdnt.macro-14 whb.button.macro-14 halui.mdi-command-14 # use MDI command from main.ini
# Macro 15,16: hardcoded flood/mist toggles
net pdnt.reserved.for.flood whb.button.macro-15 # Hardcoded for halui.flood on/off net pdnt.reserved.for.flood whb.button.macro-15 # Hardcoded for halui.flood on/off
net pdnt.reserved.for.mist whb.button.macro-16 # Hardcoded for halui.mist on/off net pdnt.reserved.for.mist whb.button.macro-16 # Hardcoded for halui.mist on/off
@@ -87,7 +101,7 @@ net pdnt.macro.12 whb.button.macro-12
net pdnt.macro.13 whb.button.macro-13 halui.mdi-command-13 # use MDI command from main.ini net pdnt.macro.13 whb.button.macro-13 halui.mdi-command-13 # use MDI command from main.ini
# flood and mist toggle signals # --- Flood and mist coolant toggle (pendant hardcoded buttons) ---
net pdnt.flood.is-on whb.halui.flood.is-on halui.flood.is-on #return signal is on or off net pdnt.flood.is-on whb.halui.flood.is-on halui.flood.is-on #return signal is on or off
net pdnt.flood.off whb.halui.flood.off halui.flood.off #reserved whb.button.macro-15 net pdnt.flood.off whb.halui.flood.off halui.flood.off #reserved whb.button.macro-15
net pdnt.flood.on whb.halui.flood.on halui.flood.on #reserved whb.button.macro-15 net pdnt.flood.on whb.halui.flood.on halui.flood.on #reserved whb.button.macro-15
@@ -96,19 +110,20 @@ net pdnt.mist.is-on whb.halui.mist.is-on
net pdnt.mist.off whb.halui.mist.off halui.mist.off #reserved whb.button.macro-16 net pdnt.mist.off whb.halui.mist.off halui.mist.off #reserved whb.button.macro-16
net pdnt.mist.on whb.halui.mist.on halui.mist.on #reserved whb.button.macro-16 net pdnt.mist.on whb.halui.mist.on halui.mist.on #reserved whb.button.macro-16
# Lube control (unused)
#net pdnt.lube.is-on whb.halui.lube.is-on halui.lube.is-on #return signal is on or off #net pdnt.lube.is-on whb.halui.lube.is-on halui.lube.is-on #return signal is on or off
#net pdnt.lube.off whb.halui.lube.off halui.lube.off #reserved whb.button.macro-2 #net pdnt.lube.off whb.halui.lube.off halui.lube.off #reserved whb.button.macro-2
#net pdnt.lube.on whb.halui.lube.on halui.lube.on #reserved whb.button.macro-2 #net pdnt.lube.on whb.halui.lube.on halui.lube.on #reserved whb.button.macro-2
# default function button signals # --- Default function buttons ---
net pdnt.button.m-home whb.button.m-home halui.home-all # Homing use built-in halui home all net pdnt.button.m-home whb.button.m-home halui.home-all # Homing use built-in halui home all
net pdnt.button.safe-z whb.button.safe-z halui.mdi-command-03 # Safe-z use MDI command from main.ini net pdnt.button.safe-z whb.button.safe-z halui.mdi-command-03 # Safe-z use MDI command from main.ini
net pdnt.button.w-home whb.button.w-home halui.mdi-command-04 # Unpark use MDI command from main.ini net pdnt.button.w-home whb.button.w-home halui.mdi-command-04 # Unpark use MDI command from main.ini
net pdnt.button.probe-z whb.button.probe-z halui.mdi-command-08 # Probe-Z use MDI command from main.ini net pdnt.button.probe-z whb.button.probe-z halui.mdi-command-08 # Probe-Z use MDI command from main.ini
# unused, just exposes pendant internal status or as basic button # --- Unused pendant status/button signals ---
#net pdnt.mode-lead whb.halui.feed.selected-lead #net pdnt.mode-lead whb.halui.feed.selected-lead
#net pdnt.mode-mpg-feed whb.halui.feed.selected-mpg-feed #net pdnt.mode-mpg-feed whb.halui.feed.selected-mpg-feed
#net pdnt.mode-continuous whb.halui.feed.selected-continuous #net pdnt.mode-continuous whb.halui.feed.selected-continuous
@@ -127,7 +142,7 @@ net pdnt.button.probe-z whb.button.probe-z
#net pdnt.button.feed-minus whb.button.feed-minus #net pdnt.button.feed-minus whb.button.feed-minus
# spindle related signals # --- Spindle control (disabled - relay-only spindle, no speed feedback) ---
#net pdnt.spindle.is-on whb.halui.spindle.is-on spindle.0.on #net pdnt.spindle.is-on whb.halui.spindle.is-on spindle.0.on
#net pdnt.spindle.start whb.halui.spindle.start halui.spindle.0.start #net pdnt.spindle.start whb.halui.spindle.start halui.spindle.0.start
#net pdnt.spindle.stop whb.halui.spindle.stop halui.spindle.0.stop #net pdnt.spindle.stop whb.halui.spindle.stop halui.spindle.0.stop
@@ -138,33 +153,31 @@ net pdnt.button.probe-z whb.button.probe-z
#net pdnt.spindle-speed-abs whb.halui.spindle-speed-cmd spindle.0.speed-out-abs # speed cmd from motion in rpm absolue #net pdnt.spindle-speed-abs whb.halui.spindle-speed-cmd spindle.0.speed-out-abs # speed cmd from motion in rpm absolue
# spindle speed override signals # --- Spindle speed override (disabled) ---
#net pdnt.spindle-override.scale whb.halui.spindle-override.scale halui.spindle.0.override.scale # needed for both spindle+/- and spindleoverride+/- button #net pdnt.spindle-override.scale whb.halui.spindle-override.scale halui.spindle.0.override.scale # needed for both spindle+/- and spindleoverride+/- button
#net pdnt.spindle.override.value halui.spindle.0.override.value whb.halui.spindle-override.value # GUI feed rate related signals #net pdnt.spindle.override.value halui.spindle.0.override.value whb.halui.spindle-override.value # GUI feed rate related signals
#net pdnt.spindle.override.increase whb.halui.spindle-override.increase halui.spindle.0.override.increase #net pdnt.spindle.override.increase whb.halui.spindle-override.increase halui.spindle.0.override.increase
#net pdnt.spindle.override.decrease whb.halui.spindle-override.decrease halui.spindle.0.override.decrease #net pdnt.spindle.override.decrease whb.halui.spindle-override.decrease halui.spindle.0.override.decrease
# GUI feed rate related signals can be used when program is running moving GUI slider # --- Feed override (pendant knob controls feed rate) ---
net pdnt.feed-override.scale whb.halui.feed-override.scale halui.feed-override.scale # needed for both FeedOverride+/- and rotary knob button net pdnt.feed-override.scale whb.halui.feed-override.scale halui.feed-override.scale # needed for both FeedOverride+/- and rotary knob button
net pdnt.max-velocity.value whb.halui.max-velocity.value halui.max-velocity.value # needed for Mpg mode : button feed position% * max-velocity = Mpg feedrate net pdnt.max-velocity.value whb.halui.max-velocity.value halui.max-velocity.value # needed for Mpg mode : button feed position% * max-velocity = Mpg feedrate
# take feed override min/max values from/to the GUI # --- Feed override value and increment/decrement ---
net pdnt.feed-override.value halui.feed-override.value whb.halui.feed-override.value # GUI feed rate related signals net pdnt.feed-override.value halui.feed-override.value whb.halui.feed-override.value # GUI feed rate related signals
net pdnt.feed-override.increase whb.halui.feed-override.increase halui.feed-override.increase net pdnt.feed-override.increase whb.halui.feed-override.increase halui.feed-override.increase
net pdnt.feed-override.decrease whb.halui.feed-override.decrease halui.feed-override.decrease net pdnt.feed-override.decrease whb.halui.feed-override.decrease halui.feed-override.decrease
# axis position related signals feedback # --- Axis position feedback to pendant display ---
net pdnt.axis.x.pos-feedback halui.axis.x.pos-feedback whb.halui.axis.x.pos-feedback net pdnt.axis.x.pos-feedback halui.axis.x.pos-feedback whb.halui.axis.x.pos-feedback
net pdnt.axis.y.pos-feedback halui.axis.y.pos-feedback whb.halui.axis.y.pos-feedback net pdnt.axis.y.pos-feedback halui.axis.y.pos-feedback whb.halui.axis.y.pos-feedback
net pdnt.axis.z.pos-feedback halui.axis.z.pos-feedback whb.halui.axis.z.pos-feedback net pdnt.axis.z.pos-feedback halui.axis.z.pos-feedback whb.halui.axis.z.pos-feedback
# axis position related signals relative # --- Axis position relative to work offset (for pendant DRO) ---
net pdnt.axis.x.pos-relative halui.axis.x.pos-relative whb.halui.axis.x.pos-relative net pdnt.axis.x.pos-relative halui.axis.x.pos-relative whb.halui.axis.x.pos-relative
net pdnt.axis.y.pos-relative halui.axis.y.pos-relative whb.halui.axis.y.pos-relative net pdnt.axis.y.pos-relative halui.axis.y.pos-relative whb.halui.axis.y.pos-relative
net pdnt.axis.z.pos-relative halui.axis.z.pos-relative whb.halui.axis.z.pos-relative net pdnt.axis.z.pos-relative halui.axis.z.pos-relative whb.halui.axis.z.pos-relative

BIN
datasheets/5i24man.pdf Normal file

Binary file not shown.

BIN
datasheets/7i37man.pdf Normal file

Binary file not shown.

BIN
datasheets/7i52man.pdf Normal file

Binary file not shown.

BIN
datasheets/sinoKA.pdf Normal file

Binary file not shown.

1722
datasheets/sinoKA.txt Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,5 @@
#!/bin/bash #!/bin/bash
# M101: Enable CNC Z-axis control via HAL signal (pair with M102 to disable)
halcmd sets z-override True halcmd sets z-override True
exit 0 exit 0

View File

@@ -1,4 +1,5 @@
#!/bin/bash #!/bin/bash
# M102: Disable CNC Z-axis control for manual quill operation (pair with M101 to re-enable)
halcmd sets z-override False halcmd sets z-override False
exit 0 exit 0

View File

@@ -1,3 +1,6 @@
; Helical bore subroutine - cuts a circular hole by helical interpolation
; Params: #1=x, #2=y, #3=diameter, #4=zstart, #5=zend, #6=stepdown
; Uses #<_td> (tool diameter) to compute offset radius
o<bore> sub o<bore> sub
; x, y, d, stepdown, zstart, zend ; x, y, d, stepdown, zstart, zend
G90 G90
@@ -5,22 +8,22 @@ o<bore> sub
G0 X#1 Y#2 G0 X#1 Y#2
G0 Z#4 G0 Z#4
G1 X[#1+#3/2-#<_td>/2] Y[#2] G1 X[#1+#3/2-#<_td>/2] Y[#2] ; move to bore edge, compensated for tool radius
G17 G17
#<r> = [#3/2-#<_td>/2] #<r> = [#3/2-#<_td>/2] ; effective bore radius (bore radius minus tool radius)
#<z> = [#4-#6] #<z> = [#4-#6]
o101 while [#<z> GT #5] o101 while [#<z> GT #5] ; helical passes, one full circle per stepdown
G3 X[#1+#<r>] Y[#2] I[-#<r>] Z[#<z>] P1 G3 X[#1+#<r>] Y[#2] I[-#<r>] Z[#<z>] P1
#<z> = [#<z> - #6] #<z> = [#<z> - #6]
o101 endwhile o101 endwhile
o102 if [#4 GT #5] o102 if [#4 GT #5] ; partial final pass to reach exact zend
#<ang> = [[#<z>-#5]/#6*360] #<ang> = [[#<z>-#5]/#6*360] ; angle where remaining depth is consumed
G3 X[#1+COS[#<ang>]*#<r>] Y[#2+SIN[#<ang>]*#<r>] I[-#<r>] Z[#5] G3 X[#1+COS[#<ang>]*#<r>] Y[#2+SIN[#<ang>]*#<r>] I[-#<r>] Z[#5]
G3 X[#1+COS[#<ang>]*#<r>] Y[#2+SIN[#<ang>]*#<r>] I[-COS[#<ang>]*#<r>] J[-SIN[#<ang>]*#<r>] Z[#5] G3 X[#1+COS[#<ang>]*#<r>] Y[#2+SIN[#<ang>]*#<r>] I[-COS[#<ang>]*#<r>] J[-SIN[#<ang>]*#<r>] Z[#5] ; cleanup pass at final depth
;G3 X#1 Y[#2+#3/2-#<_td>/2] J[-#3/2+#<_td>/2] ;G3 X#1 Y[#2+#3/2-#<_td>/2] J[-#3/2+#<_td>/2]
o102 endif o102 endif

View File

@@ -1,3 +1,5 @@
; Peck drill subroutine - drills with retract cycles to clear chips
; Params: #1=x, #2=y, #3=zstart, #4=zend, #5=peck_depth
o<drill> sub o<drill> sub
; x1, y1, zstart, zend, peckdp ; x1, y1, zstart, zend, peckdp
; #1 #2 #3 #4 #5 ; #1 #2 #3 #4 #5
@@ -20,9 +22,9 @@ o<drill> sub
o104 if [#5 NE 0] ; peck drilling o104 if [#5 NE 0] ; peck drilling
#<h> = #3 #<h> = #3
o101 while [#<h> GT #4] o101 while [#<h> GT #4]
G1 Z#<h> G1 Z#<h> ; drill to current peck depth
G0 Z#3 G0 Z#3 ; retract to clear chips
G0 Z[#<h>+.02] G0 Z[#<h>+.02] ; rapid back down, stopping just above previous depth
#<h> = [#<h>-#5] #<h> = [#<h>-#5]
o101 endwhile o101 endwhile
o104 endif o104 endif

View File

@@ -1,3 +1,5 @@
; Manual drill positioning - moves to X/Y, disables Z for manual quill, then pauses
; Params: #1=x, #2=y
o<drill_man> sub o<drill_man> sub
; x1, y1 ; x1, y1
; #1 #2 ; #1 #2

View File

@@ -1,3 +1,6 @@
; Semi-manual drill with Z retract - positions X/Y, retracts Z, pauses for manual drill
; Params: #1=x, #2=y, #3=z_clearance
; BUG: endsub name (drill_man_retract) doesn't match sub name (drill_retr)
o<drill_retr> sub o<drill_retr> sub
; x1, y1, z_clr ; x1, y1, z_clr
; #1 #2, #3 ; #1 #2, #3
@@ -12,12 +15,12 @@ o<drill_retr> sub
;;;;;;;;;; PROGRAM ;;;;;;;;; ;;;;;;;;;; PROGRAM ;;;;;;;;;
M101 M101 ; enable Z for CNC retract
G0 Z#<z_clearance> G0 Z#<z_clearance>
G0 X#1 Y#2 G0 X#1 Y#2
M102 ; disable Z-axis (M101 enables) M102 ; disable Z-axis (M101 enables)
M0 ; pause M0 ; pause for manual drilling
M101 M101 ; re-enable Z for retract
G0 Z#<z_clearance> G0 Z#<z_clearance>
o<drill_man_retract> endsub o<drill_man_retract> endsub

View File

@@ -1,3 +1,7 @@
; Circle perimeter cut - cuts inside or outside a circular profile
; Params: #1=x, #2=y, #3=diameter, #4=ztop, #5=zbot, #6=fincut, #7=mode
; Mode bitmask: bit0=conventional, bit1=bothways, bit2=plunge(vs helix), bit3=outside
; Uses arc lead-in/lead-out for smooth entry and exit
o<frame_circ> sub o<frame_circ> sub
; o<frame_circ> call [x][y] [diameter] [ztop][zbot] [fincut] [mode] ; o<frame_circ> call [x][y] [diameter] [ztop][zbot] [fincut] [mode]
@@ -25,7 +29,7 @@ o<frame_circ> sub
o1 endif o1 endif
#<r_entry> = #<tr> #<r_entry> = #<tr> ; lead-in arc radius, capped at 15% of diameter
o10 if [#<r_entry> GT #3*0.15] o10 if [#<r_entry> GT #3*0.15]
#<r_entry> = [#3*0.15] #<r_entry> = [#3*0.15]
o10 endif o10 endif

View File

@@ -1,3 +1,6 @@
; Rectangle perimeter cut - cuts inside or outside a rectangular frame
; Params: #1=x1, #2=y1, #3=x2, #4=y2, #5=ztop, #6=zbot, #7=mode, #8=corner_radius
; Mode bitmask: bit0=conventional, bit1=bothways, bit2=plunge(vs helix), bit3=outside
o<frame_rect> sub o<frame_rect> sub
; o<frame_rect> call [x1][y1] [x2][y2] [ztop][zbot] [mode] [radius] ; o<frame_rect> call [x1][y1] [x2][y2] [ztop][zbot] [mode] [radius]
@@ -43,7 +46,7 @@ o<frame_rect> sub
o10 if [#<M_INSIDE> AND #<M_CONVENTIONAL>] o10 if [#<M_INSIDE> AND #<M_CONVENTIONAL>]
; plunge in center ; CW inside: plunge in center, traverse to wall, trace perimeter
G0 X[[#1+#3]/2] Y[[#2+#4]/2] G0 X[[#1+#3]/2] Y[[#2+#4]/2]
G0 Z#5 G0 Z#5
G1 Z#6 G1 Z#6
@@ -74,7 +77,7 @@ o<frame_rect> sub
G0 Z#5 G0 Z#5
o10 elseif [#<M_INSIDE> AND #<M_CLIMB>] o10 elseif [#<M_INSIDE> AND #<M_CLIMB>]
; CCW inside ; CCW inside: plunge in center, trace perimeter counterclockwise
G0 X[[#1+#3]/2] Y[[#2+#4]/2] G0 X[[#1+#3]/2] Y[[#2+#4]/2]
G0 Z#5 G0 Z#5
G1 Z#6 G1 Z#6
@@ -104,7 +107,7 @@ o<frame_rect> sub
G0 Z#5 G0 Z#5
o10 elseif [#<M_OUTSIDE> AND #<M_CONVENTIONAL>] o10 elseif [#<M_OUTSIDE> AND #<M_CONVENTIONAL>]
; plunge at corner ; CW outside: plunge at corner, trace perimeter offset outward
G0 X[#<minx>-#<tr>] Y[#<maxy>+#<tr>] G0 X[#<minx>-#<tr>] Y[#<maxy>+#<tr>]
G0 Z#5 G0 Z#5
G1 Z#6 G1 Z#6
@@ -129,7 +132,7 @@ o<frame_rect> sub
G0 Z#5 G0 Z#5
o10 elseif [#<M_OUTSIDE> AND #<M_CLIMB>] o10 elseif [#<M_OUTSIDE> AND #<M_CLIMB>]
; plunge at corner ; CCW outside: plunge at corner, trace perimeter offset outward
G0 X[#<minx>-#<tr>] Y[#<miny>-#<tr>] G0 X[#<minx>-#<tr>] Y[#<miny>-#<tr>]
G0 Z#5 G0 Z#5
G1 Z#6 G1 Z#6

View File

@@ -1,26 +1,196 @@
# Modes # Macros & Subroutines
Default mode (0) is:
- Climb milling
- One-way milling
- Helix entry
- Inside
+1: Conventional milling Custom M-codes and G-code subroutines for the Lagun mill LinuxCNC configuration.
+2: Both-ways milling
+4: Plunge entry
+8: Outside
# Fun stuff ## Mode Flags (Bitmask)
Specifying a negative finish cut should cause macros to do all the roughing and leave the (positive) amount of material behind for a separate finishing op. Several macros (`pocket_circ`, `pocket_rect`, `frame_rect`, `frame_circ`, `slot`) accept a `mode` parameter as a bitmask:
| Bit | Value | Set (1) | Clear (0) |
|-----|-------|---------|-----------|
| 0 | +1 | Conventional milling | Climb milling |
| 1 | +2 | Both-ways milling | One-way milling |
| 2 | +4 | Plunge entry | Helix entry |
| 3 | +8 | Outside | Inside |
Default mode (0) = climb, one-way, helix entry, inside.
## Global Named Parameters
These optional globals configure macro behavior when set before calling:
| Parameter | Description | Default |
|-----------|-------------|---------|
| `#<_td>` | Tool diameter (from tool table) | **Required** - used by all material-removal macros |
| `#<_z_clearance>` | Safe Z retract height | Falls back to ztop param |
| `#<_rampang>` | Ramp/helix entry angle in degrees | 5.0 |
| `#<_stepover>` | Stepover distance for spiral pocketing | 40% of tool diameter |
A negative `fincut` value causes macros to rough only, leaving material for a separate finishing pass.
## M-Codes (Shell Scripts)
### M101 - Enable Z-Axis
Sets HAL signal `z-override` to True, enabling CNC control of Z.
### M102 - Disable Z-Axis
Sets HAL signal `z-override` to False, allowing manual quill control.
## Drilling Subroutines
### drill.ngc - Peck Drill
Fully automatic drilling with optional peck cycle.
# Typical Header
``` ```
#<_z_clearance> = 0.0 ; clearance height o<drill> call [x][y] [ztop][zbot] [peck]
#<_rampang> = 5.0 ; ramp angle in degrees for helical entry ```
G10 L1 P1 Z0.0 R0.25 ; set tool P1 to Z-offset Z0.0 and radius R0.25 | # | Name | Description |
T1 ; set tool to T1 |---|------|-------------|
| #1 | X | Hole X position |
| #2 | Y | Hole Y position |
| #3 | Z Start | Top of material / start Z |
| #4 | Z End | Final drill depth |
| #5 | Peck | Depth per peck (0 = no peck) |
Calls M101 to enable Z-axis. Retracts to Z Start between pecks with 0.020" rapid-approach gap.
### drill_man.ngc - Manual Drill
Positions XY then pauses for operator to manually plunge.
```
o<drill_man> call [x][y]
```
Calls M102 to disable Z-axis, then M0 pause.
### drill_retr.ngc - Semi-Manual Drill with Retract
Positions XY, retracts Z to clearance, disables Z for manual plunge, then re-enables and retracts on resume.
```
o<drill_retr> call [x][y] [z_clearance]
```
## Material Removal Subroutines
### pocket_circ.ngc - Circular Pocket
Cuts a circular pocket using an outward spiral from center.
```
o<pocket_circ> call [x][y] [diameter] [ztop][zbot] [fincut] [mode]
```
| # | Name | Description |
|---|------|-------------|
| #1 | X | Center X |
| #2 | Y | Center Y |
| #3 | Diameter | Pocket diameter |
| #4 | Z Top | Start Z |
| #5 | Z Bottom | Final depth |
| #6 | Finish Cut | Finish allowance (negative = rough only) |
| #7 | Mode | Bitmask (see above) |
Supports helix or plunge entry. Spirals outward with stepover, then does a pre-finish circle and optional finish circle at full diameter.
### pocket_rect.ngc - Rectangular Pocket
Cuts a rectangular pocket. Uses helical or straight plunge, then an outward spiral that transitions to linear passes when the spiral hits the rectangle boundary.
```
o<pocket_rect> call [x1][y1] [x2][y2] [zstart][zend] [fincut] [mode]
```
| # | Name | Description |
|---|------|-------------|
| #1,#2 | X1, Y1 | First corner |
| #3,#4 | X2, Y2 | Opposite corner |
| #5 | Z Start | Start Z |
| #6 | Z End | Final depth |
| #7 | Finish Cut | Finish allowance |
| #8 | Mode | 0=CCW/helix, 1=CW/helix, 2=CCW/plunge, 3=CW/plunge |
Contains internal sub `o<xp>` for filling corners after the spiral exceeds the rectangle bounds.
### frame_rect.ngc - Rectangular Frame
Cuts along the perimeter of a rectangle (inside or outside).
```
o<frame_rect> call [x1][y1] [x2][y2] [ztop][zbot] [mode] [radius]
```
| # | Name | Description |
|---|------|-------------|
| #1,#2 | X1, Y1 | First corner |
| #3,#4 | X2, Y2 | Opposite corner |
| #5 | Z Top | Start Z |
| #6 | Z Bottom | Final depth |
| #7 | Mode | Bitmask |
| #8 | Radius | Corner radius (0 = sharp corners) |
Supports all four combinations of inside/outside and climb/conventional. Plunges at center (inside) or corner (outside), then traces the rectangle with optional corner radii.
### frame_circ.ngc - Circular Frame
Cuts along the perimeter of a circle (inside or outside).
```
o<frame_circ> call [x][y] [diameter] [ztop][zbot] [fincut] [mode]
```
| # | Name | Description |
|---|------|-------------|
| #1 | X | Center X |
| #2 | Y | Center Y |
| #3 | Diameter | Circle diameter |
| #4 | Z Top | Start Z |
| #5 | Z Bottom | Final depth |
| #6 | Finish Cut | Finish allowance |
| #7 | Mode | Bitmask |
Uses a small arc entry/exit move (capped at 15% of diameter) for smooth engagement.
### slot.ngc - Slot
Cuts a slot (obround/stadium shape) between two points.
```
o<slot> call [x1][y1] [x2][y2] [width] [ztop][zbot] [fincut] [mode]
```
| # | Name | Description |
|---|------|-------------|
| #1,#2 | X1, Y1 | Slot start center |
| #3,#4 | X2, Y2 | Slot end center |
| #5 | Width | Slot width |
| #6 | Z Top | Start Z |
| #7 | Z Bottom | Final depth |
| #8 | Finish Cut | Finish allowance |
| #9 | Mode | Bitmask |
Plunges at start, cuts to end, then traces the obround profile. Supports optional pre-finish pass when fincut > 0.
### bore.ngc - Helical Bore
Helical-interpolation boring subroutine.
```
o<bore> call [x][y] [d] [zstart][zend] [stepdown]
```
| # | Name | Description |
|---|------|-------------|
| #1 | X | Center X |
| #2 | Y | Center Y |
| #3 | D | Bore diameter |
| #4 | Z Start | Start Z |
| #5 | Z End | Final depth |
| #6 | Stepdown | Depth per helical pass |
Spirals down in full-circle passes, then does a partial-arc cleanup and spring pass at final depth. Returns to center and Z0.
## Typical Program Header
```
#<_z_clearance> = 0.0
#<_rampang> = 5.0
G10 L1 P1 Z0.0 R0.25 ; set tool P1 offset and radius
T1 ; select tool
M06 ; manual toolchange M06 ; manual toolchange
M101 ; enable z-axis M101 ; enable z-axis
@@ -30,26 +200,28 @@ G54 ; fixture #1
F5.0 ; feedrate F5.0 ; feedrate
``` ```
## Known Bugs
# Material removal 1. **drill_retr.ngc: Sub name mismatch.** Opened as `o<drill_retr>` (line 1) but closed as `o<drill_man_retract>` (line 23). This will cause a runtime error - LinuxCNC requires matching sub/endsub names.
o<pocket_rect> call 2. **bore.ngc: Parameter comment is wrong.** The inline comment says `; x, y, d, stepdown, zstart, zend` but the actual parameter order used by the code is `x, y, d, zstart, zend, stepdown`. Anyone calling based on the comment would get wrong results.
o<pocket_circ> call
o<frame_rect> call 3. **bore.ngc: Undocumented `#<_td>` dependency.** Uses global `#<_td>` for tool-diameter compensation but never validates it. If unset (defaults to 0), the bore toolpath radius becomes `D/2` instead of `(D - tool_dia)/2`, cutting an oversized bore.
o<frame_circ> call
o<slot> call [x1][y1] [x2][y2] [width] [ztop][zbot] [finishcut] 4. **drill.ngc: First peck cycle is a no-op.** The loop initializes `#<h> = #3` (Z Start) then immediately does `G1 Z#<h>` - moving to where the tool already is. First real cut happens on the second iteration. Wastes one retract cycle.
o<bore> call [x][y] [stepdown] [ztop][zbot]
# Drilling 5. **pocket_circ.ngc: Suspicious angle calculation.** Line 66 has a `TODO` comment from the author: `; TODO: what the heck is the denominator here doing?` The finish-plunge angle divides by `[#4-#5]` (ztop - zbot). If ztop is 0 this produces a division by a potentially small number, which may cause unexpected arc endpoints.
o<drill> call [x][y] [ztop][zbot] [(peck)]; fully automoatic drilling op; drills at x,y from ztop to zbot in optional increments of peck (full retraction) 6. **pocket_rect.ngc: Incomplete rectangular clearing.** The spiral-to-rectangle transition has commented-out code (lines 141-151) and a note saying "subroutines might be the best way to do this". The `o<xp>` helper sub attempts to fill the remaining area but uses a different algorithm. Corners may not be fully cleared depending on geometry.
o<drill_man> call [x][y] ; fully manual drilling op; z axis entirely disabled 7. **slot.ngc: Test code after endsub.** Lines 79-83 contain hardcoded test calls that execute whenever the file is loaded. These should be removed or moved to a separate test file. The test calls also only provide 7 of 9 parameters (fincut and mode default to 0).
o<drill_retr> call [x][y] ; semi-manual drilling op; z axis retracts, but disabled on downstroke
# Footer 8. **frame_circ.ngc: lead-in arcs can be larger than actual pocket size.** this causes overcutting. not good.
```
M2 ; end program 9. **some combination of values will cause hangs.** This is in several macros. linuxcnc does not have stall/timeout detection; if a macro gets stuck in an infinite loop, it hangs linuxcnc.
```
## Other Todos
1. Change macros to use UPPERCASE_WITH_UNDERSCORES naming (both the filenames, and the usage of them in all .ngc files)
2. Purge all .cnc programs
3. Maybe: Use tool diameter instead of the td global. (we will use tool change stuff)

View File

@@ -1,3 +1,6 @@
; Circular pocket - clears a round pocket using spiral toolpath
; Params: #1=x, #2=y, #3=diameter, #4=ztop, #5=zbot, #6=finishcut, #7=mode
; Mode bitmask: bit0=conventional, bit1=bothways, bit2=plunge(vs helix), bit3=outside
o<pocket_circ> sub o<pocket_circ> sub
; o<pocket_circ> call [x][y] [diameter] [ztop][zbot] [finishcut] [mode] ; o<pocket_circ> call [x][y] [diameter] [ztop][zbot] [finishcut] [mode]
@@ -33,15 +36,15 @@ o<pocket_circ> sub
#<stepover> = [#<td>*0.4] #<stepover> = [#<td>*0.4]
o3 endif o3 endif
o4 if [#<td> GT #3] o4 if [#<td> GT #3] ; tool bigger than pocket, bail out
o5 return o5 return
o4 endif o4 endif
#<a> = 0 #<a> = 0
#<r> = 0 #<r> = 0
o100 if [#<M_HELIX>] ; helical plunge o100 if [#<M_HELIX>] ; helical plunge
#<r> = [#<td>*0.3] #<r> = [#<td>*0.3] ; helix radius = 30% of tool diameter
o115 if [[[#3-#<td>]/2-ABS[#6]] LE #<r>] o115 if [[[#3-#<td>]/2-ABS[#6]] LE #<r>] ; shrink if helix would exceed pocket wall
#<r> = [[[#3-#<td>]/2-ABS[#6]]*0.8] #<r> = [[[#3-#<td>]/2-ABS[#6]]*0.8]
o115 endif o115 endif
@@ -82,7 +85,7 @@ o<pocket_circ> sub
o100 endif o100 endif
; do the spiral :) ; spiral outward from center to clear pocket, stopping short by finishcut amount
#<r_base> = #<r> #<r_base> = #<r>
#<a_base> = #<a> #<a_base> = #<a>
o105 while [#<r> LT [[#3-#<td>]/2-ABS[#6]]] o105 while [#<r> LT [[#3-#<td>]/2-ABS[#6]]]
@@ -92,12 +95,12 @@ o<pocket_circ> sub
o106 else o106 else
G1 X[#1+COS[#<a>]*#<r>] Y[#2-SIN[#<a>]*#<r>] G1 X[#1+COS[#<a>]*#<r>] Y[#2-SIN[#<a>]*#<r>]
o106 endif o106 endif
#<a> = [#<a>+1] ; next angle #<a> = [#<a>+1] ; advance 1 degree per step
#<r> = [#<r_base>+[#<a>-#<a_base>]/360*#<stepover>] ; compute the radius accordingly #<r> = [#<r_base>+[#<a>-#<a_base>]/360*#<stepover>] ; radius grows by stepover each revolution
o105 endwhile o105 endwhile
; pre-finish cut ; pre-finish cut: full circle at pocket wall minus finishcut allowance
#<r> = [[#3-#<td>]/2-ABS[#6]] #<r> = [[#3-#<td>]/2-ABS[#6]]
o107 if [#<M_CLIMB>] o107 if [#<M_CLIMB>]
G1 X[#1+COS[#<a>]*#<r>] Y[#2+SIN[#<a>]*#<r>] G1 X[#1+COS[#<a>]*#<r>] Y[#2+SIN[#<a>]*#<r>]
@@ -107,18 +110,18 @@ o<pocket_circ> sub
G2 X[#1+COS[#<a>]*#<r>] Y[#2-SIN[#<a>]*#<r>] I[#1] J[#2] G2 X[#1+COS[#<a>]*#<r>] Y[#2-SIN[#<a>]*#<r>] I[#1] J[#2]
o107 endif o107 endif
; finish cut ; finish cut: full circle at final pocket wall radius
o104 if [ABS[#6] GT 0.0] o104 if [ABS[#6] GT 0.0]
#<r> = [[#3-#<td>]/2] #<r> = [[#3-#<td>]/2]
o108 if [#<M_CLIMB>] o108 if [#<M_CLIMB>]
G1 X[#1+COS[#<a>]*#<r>] Y[#2+SIN[#<a>]*#<r>] G1 X[#1+COS[#<a>]*#<r>] Y[#2+SIN[#<a>]*#<r>]
G3 X[#1+COS[#<a>]*#<r>] Y[#2+SIN[#<a>]*#<r>] I[#1] J[#2] G3 X[#1+COS[#<a>]*#<r>] Y[#2+SIN[#<a>]*#<r>] I[#1] J[#2]
#<r> = [[#3-#<td>]/2*0.9] #<r> = [[#3-#<td>]/2*0.9] ; retract slightly inward before rapid out
G1 X[#1+COS[#<a>]*#<r>] Y[#2+SIN[#<a>]*#<r>] G1 X[#1+COS[#<a>]*#<r>] Y[#2+SIN[#<a>]*#<r>]
o108 else o108 else
G1 X[#1+COS[#<a>]*#<r>] Y[#2-SIN[#<a>]*#<r>] G1 X[#1+COS[#<a>]*#<r>] Y[#2-SIN[#<a>]*#<r>]
G2 X[#1+COS[#<a>]*#<r>] Y[#2-SIN[#<a>]*#<r>] I[#1] J[#2] G2 X[#1+COS[#<a>]*#<r>] Y[#2-SIN[#<a>]*#<r>] I[#1] J[#2]
#<r> = [[#3-#<td>]/2*0.9] #<r> = [[#3-#<td>]/2*0.9] ; retract slightly inward before rapid out
G1 X[#1+COS[#<a>]*#<r>] Y[#2-SIN[#<a>]*#<r>] G1 X[#1+COS[#<a>]*#<r>] Y[#2-SIN[#<a>]*#<r>]
o108 endif o108 endif
o104 endif o104 endif

View File

@@ -1,3 +1,8 @@
; Rectangular pocket - clears using spiral then corner-clearing helper sub
; Params: #1=x1, #2=y1, #3=x2, #4=y2, #5=zstart, #6=zend, #7=fincut, #8=mode
; Mode: 0=CCW/ramp, 1=CW/ramp, 2=CCW/plunge, 3=CW/plunge
; pre-declare named params used across sub/helper scope
#<a> = 0 #<a> = 0
#<z> = 0 #<z> = 0
#<td> = 0 #<td> = 0
@@ -44,7 +49,7 @@ o<pocket_rect> sub
o3 endif o3 endif
#<z_down> = #6 #<z_down> = #6
#<z_lift> = [#6+#<td>*0.1] #<z_lift> = [#6+#<td>*0.1] ; slight lift for repositioning moves
#<minx> = #1 #<minx> = #1
#<maxx> = #3 #<maxx> = #3
@@ -60,10 +65,10 @@ o<pocket_rect> sub
#<maxy> = #2 #<maxy> = #2
o12 endif o12 endif
#<cx> = [[#<minx>+#<maxx>]/2] #<cx> = [[#<minx>+#<maxx>]/2] ; pocket center X
#<cy> = [[#<miny>+#<maxy>]/2] #<cy> = [[#<miny>+#<maxy>]/2] ; pocket center Y
#<rx> = [[[#<maxx>-#<minx>]-#<td>]/2] #<rx> = [[[#<maxx>-#<minx>]-#<td>]/2] ; half-width minus tool radius
#<ry> = [[[#<maxy>-#<miny>]-#<td>]/2] #<ry> = [[[#<maxy>-#<miny>]-#<td>]/2] ; half-height minus tool radius
G0 X#<cx> Y#<cy> G0 X#<cx> Y#<cy>
G1 X[#<cx>+#<rx>] Y[#<cy>-#<ry>] G1 X[#<cx>+#<rx>] Y[#<cy>-#<ry>]
@@ -109,7 +114,7 @@ o<pocket_rect> sub
o100 endif o100 endif
; do the spiral :) ; spiral outward from center until hitting pocket boundary
#<r_base> = #<r> #<r_base> = #<r>
#<a_base> = #<a> #<a_base> = #<a>
o105 while [1] o105 while [1]
@@ -152,7 +157,7 @@ o<pocket_rect> sub
o<xp> call o<xp> call ; clear corners that the spiral couldn't reach
@@ -165,6 +170,8 @@ o<pocket_rect> endsub
; idea: bias the main spiral. then you're left with a section to hog out ; idea: bias the main spiral. then you're left with a section to hog out
; idea 2: make angle arbitrary (blowing up the code so it's not x-y specific). That'll be fun. ; idea 2: make angle arbitrary (blowing up the code so it's not x-y specific). That'll be fun.
; Helper sub: clears rectangular corner material left by circular spiral
; Walks along the X-axis edge, tracing arcs that match the spiral boundary
o<xp> sub o<xp> sub
#<ix> = 0 #<ix> = 0
#<lastxx> = 0 #<lastxx> = 0
@@ -174,7 +181,7 @@ o<xp> sub
G0 X#<cx> Y[#<cy> - #<ry>] G0 X#<cx> Y[#<cy> - #<ry>]
G1 Z#<z_down> G1 Z#<z_down>
#<n_end> = FUP[sqrt[[#<ix>]**2 + [#<ry>]**2]/#<stepover>] #<n_end> = FUP[sqrt[[#<ix>]**2 + [#<ry>]**2]/#<stepover>] ; spiral revolution number at this corner point
#<a> = ATAN[-#<ry>]/[#<ix>] #<a> = ATAN[-#<ry>]/[#<ix>]
#<r_end> = [#<n_end>*#<stepover> + #<r_base>+[#<a>-#<a_base>]/360*#<stepover>] #<r_end> = [#<n_end>*#<stepover> + #<r_base>+[#<a>-#<a_base>]/360*#<stepover>]
#<r> = [#<ry>] #<r> = [#<ry>]

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +1,6 @@
; Slot/obround cut - cuts a slot (stadium shape) between two endpoints
; Params: #1=x1, #2=y1, #3=x2, #4=y2, #5=width, #6=ztop, #7=zbot, #8=fincut, #9=mode
; Mode bitmask: bit0=conventional, bit1=bothways, bit2=plunge(vs helix), bit3=outside
o<slot> sub o<slot> sub
; o<slot> call [x1][y1] [x2][y2] [width] [ztop][zbot] [fincut] [mode] ; o<slot> call [x1][y1] [x2][y2] [width] [ztop][zbot] [fincut] [mode]
@@ -24,20 +27,21 @@ o<slot> sub
#<z_clearance> = #5 #<z_clearance> = #5
o1 endif o1 endif
#<a> = [ATAN[#4-#2]/[#3-#1]] #<a> = [ATAN[#4-#2]/[#3-#1]] ; slot angle from p1 to p2
G0 Z#<z_clearance> G0 Z#<z_clearance>
G0 X#1 Y#2 G0 X#1 Y#2
G0 Z#6 G0 Z#6
G1 Z#7 G1 Z#7 ; plunge to cut depth
G1 X#3 Y#4 G1 X#3 Y#4 ; cut centerline of slot
#<r> = [[#5-#<_td>]/2] #<r> = [[#5-#<_td>]/2] ; offset from centerline to slot edge (compensated for tool)
; Trace obround perimeter: two straights + two semicircles at each end
o100 if [#<M_CLIMB>] o100 if [#<M_CLIMB>]
o101 if [#8 GT 0] o101 if [#8 GT 0] ; pre-finish pass offset inward by fincut
G1 X[#3 +[SIN[#<a>]*[#<r>-#8]]] Y[#4 -[COS[#<a>]*[#<r>-#8]]] ; point 1 G1 X[#3 +[SIN[#<a>]*[#<r>-#8]]] Y[#4 -[COS[#<a>]*[#<r>-#8]]] ; point 1
G3 X[#3 -[SIN[#<a>]*[#<r>-#8]]] Y[#4 +[COS[#<a>]*[#<r>-#8]]] I#3 J#4 ; point 2 G3 X[#3 -[SIN[#<a>]*[#<r>-#8]]] Y[#4 +[COS[#<a>]*[#<r>-#8]]] I#3 J#4 ; point 2
G1 X[#1 -[SIN[#<a>]*[#<r>-#8]]] Y[#2 +[COS[#<a>]*[#<r>-#8]]] ; point 3 G1 X[#1 -[SIN[#<a>]*[#<r>-#8]]] Y[#2 +[COS[#<a>]*[#<r>-#8]]] ; point 3

View File

@@ -1,28 +1,24 @@
# TODO # TODO
- [x] xyz dual loop pid setup
- [x] enable signals wired
- [x] enable signals programmed
- [x] calibration of xyz
- [x] tighten z bracket
- [x] is there a btter way to do dual PID?
- [x] wire front control panel
- [x] get AXIS how I want it, or some other ui
- [x] handwheel
- [x] cable management
- [ ] wire start/stop/estop/speed
- [ ] gcode ftp or something
- [ ] understand offsets better - [ ] understand offsets better
- [ ] understand toolchange better - [ ] understand toolchange better
- [ ] pendant buttons - [ ] pendant buttons
- [ ] holders for wrenches etc - [ ] holders for wrenches etc
- [ ] permanent good fix for z axis bracket - [ ] permanent good fix for z axis bracket
# CAM # CAM options?
https://www.scorchworks.com/Fengrave/fengrave.html https://www.scorchworks.com/Fengrave/fengrave.html
https://www.estlcam.de/ https://www.estlcam.de/
https://www.grzsoftware.com/ https://www.grzsoftware.com/
# CLAUDE todos
1. check out the macros in nc_files
A. Read and understand them
B. Generate a better MACROS.md
C. Comment the code (do not change/fix anything, just add terse comments, especially at the beginning of macros)
D. Search for bugs in the macros and add them to this document
2. document and understand the lagun_gmoccapy config (this is the only active/relevant config)
A. Read and understand it
B. Generate better comments (do not change anything functionally, just add comments)
C. Generate a README.md