Configure the spindle as normal - this is required because we're hooking the spindle control so it needs to already be setup with enable, direction and speed ports:
; Configure Spindle for Modbus
M950 R0 T1 C"spindlepwm+spindleen+spindledir" L1999:24000 Q1000
Configure an Aux port for Modbus at the right baud rate:
; Configure RS485 UART on Aux 1 at 38400bps
M575 P1 B38400 S7
Work out how to control the spindle using direct M260.1
(if your VFD is modbus-rtu compliant) or M260.4
(if your VFD uses modbus timing and framing but does not support the register / coil model).
For example with the Shihlin SL3 VFD:
; NOTES:
; VFD is set to group mode, so parameters are 10000 + param number read as a number.
; For example, param 01-01 is 10101 in decimal, or 0x2775. Addresses are different
; when the VFD is set to raw parameter mode.
; VFD has speed configuration set that converts input speed from RPM to frequency.
; With other VFD types or with a SL3 VFD in default mode you'll likely have to
; enter a frequency in Hz.
;
; Reset inverter
M260.1 P1 A1 F6 R4353 B38550
;Set Frequency to 22000RPM
M260.1 P1 A1 F6 R4098 B22000
; Run forwards
M260.1 P1 A1 F6 R4097 B2
Once you're happy with controlling the spindle manually, you can create a daemon.g
file which checks
the state of the configured spindle and applies these as M260.x
commands, for example with the SL3 VFD:
if { !exists(global.runDaemon) }
global runDaemon = true
while { global.runDaemon }
G4 P250 ; Minimum interval between daemon runs
; 0 = Status Bits, 1 = Requested Frequency, 2 = Output Frequency, 3 = Output Current, 4 = Output Voltage
M261.1 P1 A1 F3 R4097 B5 V"spindleState"
; Note - some VFDs have a minimum processing time for requests. Check the manual to see what this
; is - you might need to apply manual pauses between commands to make sure these dont error.
G4 P1
; Read output power
M261.1 P1 A1 F3 R4123 B1 V"spindlePower"
;2f10 0124 30ea
G4 P1
; Read any error codes
M261.1 P1 A1 F3 R4103 B2 V"spindleErrors"
G4 P1
; spindleState[0] is a bitmask of the following values:
; b15:during tuning
; b14: during inverter reset
; b13, b12: Reserved
; b11: inverter E0 status
; b10~8: Reserved
; b7:alarm occurred
; b6:frequency detect
; b5:Parameters reset end
; b4: overload
; b3: frequency arrive
; b2: during reverse rotation
; b1: during forward rotation
; b0: running
if { var.spindleState == null }
M99
var shouldRun = { spindles[0].state == "forward" || spindles[0].state == "reverse" }
; Extract current state to variables
var vfdForward = { mod(floor(var.spindleState[0]/pow(2,1)),2) == 1 }
var vfdReverse = { mod(floor(var.spindleState[0]/pow(2,2)),2) == 1 }
var vfdSpeedReached = { mod(floor(var.spindleState[0]/pow(2,3)),2) == 1 }
var vfdRunning = { var.vfdForward || var.vfdReverse }
var vfdInputFreq = { var.spindleState[1] }
var vfdOutputFreq = { var.spindleState[2] }
var vfdOutputCurrent = { var.spindleState[3] }
var vfdOutputVoltage = { var.spindleState[4] }
var vfdOutputPower = null
if { var.spindlePower == null }
set var.vfdOutputPower = 0
else
; Efficiency based on nameplate info
set var.vfdOutputPower = { var.spindlePower[0] * 0.75 * 10 }
; If spindle should not run but is running, stop it
if { !var.shouldRun && var.vfdRunning }
; Stop spindle, set frequency to 0
M260.1 P1 A1 F6 R4097 B0
G4 P1
M260.1 P1 A1 F6 R4098 B0
continue
; If VFD frequency does not match frequency in RRF, update it
if { var.vfdInputFreq != spindles[0].active }
M260.1 P1 A1 F6 R4098 B{spindles[0].active}
G4 P1
if { spindles[0].state == "forward" && !var.vfdForward }
M260.1 P1 A1 F6 R4097 B2
elif { spindles[0].state == "reverse" && !var.vfdReverse }
M260.1 P1 A1 F6 R4097 B4
Modify this file to suit your VFD and needs for monitoring the spindle.
This is a working configuration for the Huanyang HY02D223B: