Wiki Search Terms
atc / M6 / M61Q
Controller Board
6x controller
Machine Description
CNC router XYYZ, external drivers, VFD, Laser
Input Circuits
No response
Configuration file
“yaml`
board: 6x CNC Controller
name: 6x CNC Controller
arctolerancemm: 0.002
junctiondeviationmm: 0.01
verbose_errors: false
report_inches: false
enableparkingoverride_control: false
uselinenumbers: false
planner_blocks: 16
start:
must_home: false
deactivate_parking: false
check_limits: true
stepping:
engine: I2S_STATIC
idle_ms: 255
pulse_us: 4
dirdelayus: 4
disabledelayus: 0
segments: 6
axes:
sharedstepperdisable_pin: i2so.0
homing_runs: 2
x:
stepspermm: 200
maxratemmpermin: 8000
accelerationmmper_sec2: 500
maxtravelmm: 645
soft_limits: true
homing:
cycle: 2
positive_direction: false
mpos_mm: -645
seekmmper_min: 1500
feedmmper_min: 250
seek_scaler: 1.1
feed_scaler: 1.1
motor0:
limitallpin: gpio.2:pu
hard_limits: true
pulloff_mm: 2
standard_stepper:
step_pin: i2so.2
direction_pin: i2so.1
disablepin: NOPIN
limitnegpin: NO_PIN
limitpospin: NO_PIN
y:
stepspermm: 200
maxratemmpermin: 8000
accelerationmmper_sec2: 500
maxtravelmm: 735
soft_limits: true
homing:
cycle: 2
positive_direction: false
mpos_mm: -735
seekmmper_min: 1500
feedmmper_min: 250
settle_ms: 500
seek_scaler: 1.5
feed_scaler: 1.5
motor0:
limitallpin: gpio.33:pu
hard_limits: true
pulloff_mm: 1
standard_stepper:
step_pin: i2so.5
direction_pin: i2so.4:low
disablepin: NOPIN
limitnegpin: NO_PIN
limitpospin: NO_PIN
motor1:
limitallpin: gpio.26:pu
standard_stepper:
step_pin: i2so.10
direction_pin: i2so.9:low
disablepin: NOPIN
limitnegpin: NO_PIN
limitpospin: NO_PIN
pulloff_mm: 3
hard_limits: true
z:
stepspermm: 200
maxratemmpermin: 4000
accelerationmmper_sec2: 500
maxtravelmm: 115
soft_limits: true
homing:
cycle: 1
positive_direction: true
mpos_mm: 0
seekmmper_min: 1500
feedmmper_min: 250
seek_scaler: 1.1
feed_scaler: 1.1
motor0:
limitallpin: gpio.32
hard_limits: true
pulloff_mm: 1
standard_stepper:
step_pin: i2so.13
direction_pin: i2so.12:low
disablepin: NOPIN
limitnegpin: NO_PIN
limitpospin: NO_PIN
probe:
pin: gpio.34:low
toolsetter_pin: gpio.35
checkmodestart: false
hard_stop: false
10V:
forward_pin: gpio.15
reverse_pin: gpio.14
pwm_hz: 5000
output_pin: gpio.13
enablepin: NOPIN
directionpin: NOPIN
disablewiths0: false
s0withdisable: true
spinup_ms: 0
spindown_ms: 0
tool_num: 0
speed_map: 0=0.000% 1700=7.000% 2400=10.000% 6000=24.390% 12000=48.387% 24000=100.000%
offonalarm: false
m6_macro: $SD/Run=tc.nc
atc_manual:
safezmpos_mm: -2
probeseekratemmper_min: 400
probefeedratemmper_min: 80
changemposmm: 80.000 2.000 -2.000
etsmposmm: 25.000 25.000 -40.000
etsrapidzmposmm: -25
Laser:
pwm_hz: 5000
output_pin: gpio.4:pu
enablepin: NOPIN
disablewiths0: false
s0withdisable: true
tool_num: 50
speed_map: 0=0.000% 255=100.000%
offonalarm: true
sdcard:
carddetectpin: NO_PIN
cs_pin: gpio.5
i2so:
bck_pin: gpio.22
data_pin: gpio.21
ws_pin: gpio.17
spi:
miso_pin: gpio.19
mosi_pin: gpio.23
sck_pin: gpio.18
uart1:
txd_pin: gpio.25
rxd_pin: gpio.27
rtspin: NOPIN
ctspin: NOPIN
baud: 1000000
mode: 8N1
uart_channel1:
reportintervalms: 75
uart_num: 1
coolant:
flood_pin: i2so.20
mist_pin: gpio.12
delay_ms: 0
parking:
enable: true
axis: Z
pulloutdistancemm: 5
pulloutratemmpermin: 250
targetmposmm: -5
ratemmper_min: 800
control:
macro0pin: NOPIN
safetydoorpin: gpio.39:low
resetpin: NOPIN
feedholdpin: NO_PIN
cyclestartpin: gpio.36:low
macro1pin: NOPIN
macro2pin: NOPIN
macro3pin: NOPIN
faultpin: NOPIN
estoppin: NOPIN
macros:
startupline0: $SD/Run=initatc.nc
Startup Messages
`text
[10:54:21] [ $ss ] [MSG:INFO: FluidNC v3.9.3 https://github.com/bdring/FluidNC]
[10:54:21] [ $ss ] [MSG:INFO: Compiled with ESP32 SDK:v4.4.7-dirty]
[10:54:21] [ $ss ] [MSG:INFO: Local filesystem type is littlefs]
[10:54:21] [ $ss ] [MSG:INFO: Configuration file:Roxyz rev0.yaml]
[10:54:21] [ $ss ] [MSG:DBG: Running after-parse tasks]
[10:54:21] [ $ss ] [MSG:DBG: Checking configuration]
[10:54:21] [ $ss ] [MSG:INFO: Machine 6x CNC Controller]
[10:54:21] [ $ss ] [MSG:INFO: Board 6x CNC Controller]
[10:54:21] [ $ss ] [MSG:INFO: UART1 Tx:gpio.25 Rx:gpio.27 RTS:NO_PIN Baud:1000000]
[10:54:22] [ $ss ] [MSG:INFO: uart_channel1 created at report interval: 75]
[10:54:22] [ $ss ] [MSG:INFO: I2SO BCK:gpio.22 WS:gpio.17 DATA:gpio.21]
[10:54:22] [ $ss ] [MSG:INFO: SPI SCK:gpio.18 MOSI:gpio.23 MISO:gpio.19]
[10:54:22] [ $ss ] [MSG:INFO: SD Card cspin:gpio.5 detect:NOPIN freq:8000000]
[10:54:22] [ $ss ] [MSG:INFO: Stepping:I2S_STATIC Pulse:4us Dsbl Delay:0us Dir Delay:4us Idle Delay:255ms]
[10:54:22] [ $ss ] [MSG:INFO: Axis count 3]
[10:54:22] [ $ss ] [MSG:INFO: Shared stepper disable I2SO.0]
[10:54:22] [ $ss ] [MSG:INFO: Axis X (-645.000,0.000)]
[10:54:22] [ $ss ] [MSG:INFO: Motor0]
[10:54:22] [ $ss ] [MSG:INFO: standardstepper Step:I2SO.2 Dir:I2SO.1 Disable:NOPIN]
[10:54:22] [ $ss ] [MSG:INFO: X All Limit gpio.2:pu]
[10:54:22] [ $ss ] [MSG:INFO: Axis Y (-735.000,0.000)]
[10:54:22] [ $ss ] [MSG:INFO: Motor0]
[10:54:22] [ $ss ] [MSG:INFO: standardstepper Step:I2SO.5 Dir:I2SO.4:low Disable:NOPIN]
[10:54:22] [ $ss ] [MSG:INFO: Y All Limit gpio.33:pu]
[10:54:22] [ $ss ] [MSG:INFO: Motor1]
[10:54:22] [ $ss ] [MSG:INFO: standardstepper Step:I2SO.10 Dir:I2SO.9:low Disable:NOPIN]
[10:54:22] [ $ss ] [MSG:INFO: Y2 All Limit gpio.26:pu]
[10:54:22] [ $ss ] [MSG:INFO: Axis Z (-115.000,0.000)]
[10:54:22] [ $ss ] [MSG:INFO: Motor0]
[10:54:22] [ $ss ] [MSG:INFO: standardstepper Step:I2SO.13 Dir:I2SO.12:low Disable:NOPIN]
[10:54:22] [ $ss ] [MSG:INFO: Z All Limit gpio.32]
[10:54:22] [ $ss ] [MSG:INFO: safetydoorpin gpio.39:low]
[10:54:22] [ $ss ] [MSG:INFO: cyclestartpin gpio.36:low]
[10:54:22] [ $ss ] [MSG:INFO: Kinematic system: Cartesian]
[10:54:22] [ $ss ] [MSG:INFO: Connecting to STA SSID:Sys_Workshop]
[10:54:22] [ $ss ] [MSG:INFO: Connecting.]
[10:54:22] [ $ss ] [MSG:INFO: Connecting..]
[10:54:22] [ $ss ] [MSG:INFO: Connected - IP is 192.168.0.36]
[10:54:22] [ $ss ] [MSG:INFO: WiFi on]
[10:54:22] [ $ss ] [MSG:INFO: Start mDNS with hostname:http://fluidnc.local/]
[10:54:22] [ $ss ] [MSG:INFO: HTTP started on port 80]
[10:54:22] [ $ss ] [MSG:INFO: Telnet started on port 23]
[10:54:22] [ $ss ] [MSG:INFO: ATC:atc_manual]
[10:54:22] [ $ss ] [MSG:INFO: 10V Spindle Ena:NOPIN Out:gpio.13 Dir:NOPIN Fwd:gpio.15 Rev:gpio.14 Freq:5000Hz Period:8191 with m6_macro]
[10:54:22] [ $ss ] [MSG:INFO: Laser Ena:NO_PIN Out:gpio.4:pu Freq:5000Hz Period:8191]
[10:54:22] [ $ss ] [MSG:INFO: Flood coolant I2SO.20]
[10:54:22] [ $ss ] [MSG:INFO: Mist coolant gpio.12]
[10:54:22] [ $ss ] [MSG:INFO: Probe gpio.34:low]
[10:54:22] [ $ss ] [MSG:INFO: Toolsetter gpio.35]
[10:54:22] [ $ss ] ok
“
User Interface Software
No response
What happened?
I’m trying to make use of the new variables introduced in 3.9.3 but I’m facing a strange issue.
Testing procedure :
* a macro is executed when m6 is called (==> yaml config)
* at the beginning of the macro is displayed currenttool and selectedtool values.
* I set the current_tool using M61Q to x tool
* then use M6Ty to proceed to a tool change
Result : currenttool equals selectedtool ( y value) at the beginning of the macro, so no tool changed is performed.
I assumed that currenttool should be manually updated by the user macro in that case.
Last thing, when I sent a M61Q-1 the spindle was changed to my laser (tool number 50 in the yaml).
Best
GCode File
(debug, begin Selected Tool: #<selectedtool> – Current Tool: #<currenttool>.)
Other Information
[10:47:58] [ ] [MSG:INFO: 10V spindle changed to tool:1 using m6_macro]
[10:47:58] [ ] [MSG:INFO: 10V spindle run macro: $SD/Run=tc.nc]
[10:47:58] [ ] [MSG:DBG: Macro line: $SD/Run=tc.nc]
[10:47:58] [ ] [MSG:DBG: DEBUG, begin Selected Tool: 1.000000- Current Tool: 1.000000]
评论 (23)
#2 – bdring 于 2025-01-02
I made a mistake in my test. I meant to send M6T6. Here is the result. It looks OK to me.
““
Grbl 3.9 [FluidNC v3.9.3 (main-c692589c) (wifi) '$' for help]
D#<selectedtool>
[MSG:INFO: Value is 0.000]
ok
D#<currenttool>
[MSG:INFO: Value is -1.000]
ok
M61Q5
ok
D#<currenttool>
[MSG:INFO: Value is 5.000]
ok
D#<selectedtool>
[MSG:INFO: Value is 5.000]
ok
M6T5
ok
D#<selectedtool>
[MSG:INFO: Value is 5.000]
ok
D#<currenttool>
[MSG:INFO: Value is 5.000]
ok
The Q value in M61 must be a positive integer.
https://linuxcnc.org/docs/2.8/html/gcode/m-code.html#mcode:m61
I can add code to give an error in that case.
#3 – rvalotta 于 2025-01-02
I can no longer test this as my fluidNC board was exposed to my stupidity. To test this properly a M6 macro should be created that displays the current and selected tool At the start of the macro these values should be different. Selected Tool being the tool about to be loaded and current tool being the tool in the spindle… Traditionally my M6 Macro would do a M61Q<selectedtool> to update the current tool on successful tool change… Selected too should be updated with the T# so the macro knows what tool to grab.
#4 – bdring 于 2025-01-02
You should not need to do an M61Qx after an M6. Look at last console session. M61 is used to set the tool number without doing a tool change.
I only use M61 when I turn on my machine and the tool is already installed. It lets FluidNC know what tool is there.
FWIW:
M6 and T are separate commands, even if they are on the same line.
T2
M6
if the same thing as
M6T2
or
T2M6
M6
T2
Is not the same.
#5 – rvalotta 于 2025-01-02
Okay so how does fluid know that the tool change was successful and to update the current_tool? I ask for M6T2 it should call my macro saying current-tool is the loaded tool and selected tool is 2. At some point I need to tell fluid the tool change was successful or halt the script and let the user take the appropriate actions to fix any issue.
#6 – rvalotta 于 2025-01-02
Yes T2 is a separate command and should be setting selected_tool
#7 – rvalotta 于 2025-01-02
From the linuxcnc docs:
https://linuxcnc.org/docs/html/gcode/overview.html
#<currenttool> – Return number of the current tool in spindle. Same as #5400.
#<selectedtool> – Return number of the selected tool post a T code. Default -1.
#8 – bdring 于 2025-01-02
It is probably best to let FluidNC handle the non failure case and you handle the failure cases.
The failures cases are probably pretty complicated. The machine could generate an alarm (hard limit, probe fail), you could manually do a reset or the macro could generate an alarm. In many cases the macro will have been aborted. You will need to manually reset things
How are you detecting the failures.
#9 – rvalotta 于 2025-01-02
So the m6 script is question is for the RapidChangeATC. It has a break beam sensor and we check to make sure the nut has either loaded or unloaded properly and currently issue an alarm on failures. Traditional on success I set the currenttool using a M61Q
#10 – bdring 于 2025-01-02
– What happens after the failure.
– Are you in alarm state?
– Were the values changed (correctly or incorrectly)?
– What should the values be after failure in all fail cases?
#11 – xspy69 于 2025-01-02
If the tool can’t be loaded/unloaded an alarm is thrown.
current_tool is updated accordingly.
In case of failure, to my point of view values should stay the same before calling the macro as the alarm must be handle by the user.
What’s your opinion on this ?
Best
#12 – rvalotta 于 2025-01-02
Lets be honest on an alarm they are going to have to restart their program.
Current tool and selected tool should be their respective values as they were at the start of the M6 script.
When they restart their gcode it will hit a M6T2 and set a new seleccted_tool. If the user unloads the current tool its up to them to set it back to 0.
that is my thoughts on it…
Right now I couldn’t tell you what the values are as I stated I toasted my FluidNC controller.
#13 – bdring 于 2025-01-02
I don’t know. It depends on the state. What if the tool is picked up, but fails on toolsetter probing. You have the right tool, but are in alarm.
Machine generated failures are harder to handle than macro generated failures because you can still send gcode before the macro generates the failure.
We might be able to detect the failure of an ATC macro and do one common thing. More than that and you would have to use the class method.
#14 – xspy69 于 2025-01-02
Bart, I’m a bit lost, sorry. According to you how should we handle those variables in a m6 macro ?
Previously we used a user variable to handle tool change but without the possibility of using M61Q, so we should always start a job with no tool loaded.
I’m curious to read your suggestions on this. there is no generic way to handle that ?
Thanks !
#15 – rvalotta 于 2025-01-03
Just a thought. If the tool change is being handed over to the macro shouldn’t the macro be the one to update current_tool or stop the script if something goes wrong…. or at a minimum have a way of informing fluidnc that it was successful. I don’t think that behaviour should be part of the firmware. You are handing over the tool change functionality to the macro.
#16 – bdring 于 2025-01-03
This is a complicated issue. We also have to deal with our ability to change spindles via M6. A macro cannot do that by itself.
We will need to think about our options. It will not be a quick fix.
#17 – rvalotta 于 2025-01-03
I wouldn’t of thought multiple spindles would of mattered as they would have their own m6 script or use the internal handling.
#19 – xspy69 于 2025-01-13
Hi Bart,
I’ve tested out this PR and it works flawlessly! Changing spindle works also, it just needs to take care of current_tool when coming from a laser for example but that’s the job of the M6 macro. Starting with a tool set at -1 is also a good point as it requires to call M61Qx before starting. Really appreciate your work on this !
#20 – bdring 于 2025-01-13
@rvalotta are you able to test this? Let me know if you have any questions.
#21 – rvalotta 于 2025-01-13
@bdring Sadly no… I used my superpowers and managed to release the smoke on my fluidNC on one of the io modules and the ESP and just replaced it with a controller i had on hand.
I have been working with xspy69 to make sure it works as its suppose to
#22 – rvalotta 于 2025-01-13
Just thinking out loud here more so people are aware than anything else
Spoke with xspy69. His setup is a spindle with a m6 macro and a laser without a macro (tool 50).
As he explains it When he switches from the Laser back to the spindle it is saying current_tool is 50. which is fine as long as they put the tool that is in the spindle away before switching to the laser or their macro makes sure the tool number for current tool is within range of the atc.. In my case it would trigger a manual tool change as the tool number is outside the valid pocket range.
I don’t think their is anything that can be done in the core to rectify this. I would suggest a note on the wiki for m6macro saying if they are going to be switching spindles to ensure they only handle valid tool ranges or something to the like or if the tool has no m6 macro it sets the currenttool to 0.
Maybe even disallow a spindle change is the current_tool is not 0 to make sure its unloaded?
Anyways that is just some thoughts but as it is now it is working wonderfully… Thankyou
#23 – bdring 于 2025-01-13
The M6 macro will only be sent to the tool that has the selected tool within its range.
Assume you have a VFD ATC spindle with tools 0-99 and a laser with tools 100-255. The laser has an active lens cap.
If you want to sculpt a part with the spindle, etch with the laser, then cut out the part with the spindle, you would do something like this.
““
M6T1 ; select tool 1
; sculpting gcode
M6T0; put away the spindle tool
M6T101; select the laser, open the lens cap, etc.
; etch the part
M6T100 ; close the lens cap
M6T2; get a spindle tool
; cut out the part.
M6T0 ; return the tool
; end the job.
– The spindle m6_macro should remember its own last tool. This allows you properly deal with returning from the laser.
– The laser m6_macro needs to know that 100 is the lasers version of T0.
#1 – bdring 于 2025-01-02
I can reproduce the problem. I will work on it when I get a chance.
“
“Grbl 3.9 [FluidNC v3.9.3 (main-c692589c) (wifi) '$' for help]
D#<currenttool>
[MSG:INFO: Value is -1.000]
ok
D#<selectedtool>
[MSG:INFO: Value is 0.000]
ok
M61Q5
ok
D#<selectedtool>
[MSG:INFO: Value is 5.000]
ok
D#<currenttool>
[MSG:INFO: Value is 5.000]
ok
M5T6
ok
D#<selectedtool>
[MSG:INFO: Value is 6.000]
ok
D#<currenttool>
[MSG:INFO: Value is 5.000]
ok
$G
[GC:G0 G54 G17 G21 G90 G94 M5 M9 T6 F0 S0]
ok