Running CNC and Laser on TwoTrees TTC450 with FluidNC
How I replaced the stock GRBL-ESP32 firmware on a TwoTrees TTC450 with FluidNC, enabling instant CNC/laser switching via YAML config without touching esptool again.
I bought the TTC450 to cover both milling and laser engraving on a single machine without two separate setups — the first post in the CNC & Laser Workshop build series. The decision to replace the firmware came within the first week, when I realized that switching modes meant reflashing.
The problem with the stock firmware
The TwoTrees TTC450 is a capable machine — 460×460 mm work area, NEMA 17 steppers on a ball screw Z axis, a 500 W spindle, and a reasonably solid frame. Mine came with the 20 W diode laser module, which makes it usable for both milling and engraving. The controller is the MKS DLC32 v2.1, an ESP32-based board that can run both CNC and laser modes. The MKS TS35 touchscreen sits on top and gives the whole thing a finished look.
Melvin Isken’s TTC450 page on diode-laser-wiki is an excellent reference for this machine — it covers setup, firmware, settings, and FluidNC in detail. This post builds on that work, extends the FluidNC config to the 20 W laser and CNC mode, and documents the changes needed when running the display and extra plugins.
The stock firmware, a Makerbase build of GRBL-ESP32, works well as shipped. But it has one limitation that I ran into immediately: CNC and laser are two separate firmware binaries. Switching from milling to engraving means connecting a USB cable, running the MKS Flash Tool, waiting for the reflash, and reconnecting everything. On a machine I use for both regularly, that becomes friction fast.
I also discovered that the local TwoTrees binary and the machine’s actual running firmware were not identical — the application partition differed byte-for-byte from the vendor file, which made me cautious about assuming the stock firmware was exactly what TwoTrees documented.
Why FluidNC
FluidNC is a modern ESP32 firmware with an architecture built around a YAML configuration file. CNC vs laser is not a firmware question — it is a config file question. You keep two YAML files on the board’s flash, and switching modes is:
1 2 | |
That is the whole switching procedure. No cable, no reflash, no Windows tool.
FluidNC also has a proper web interface served over WiFi, detailed serial logging, runtime-editable configuration, and a richer plugin model than GRBL. The ecosystem is active and the release cadence is predictable.
The table below summarizes the tradeoffs:
| Criterion | Stock (Makerbase) | FluidNC |
|---|---|---|
| CNC without reflash | ✅ | ✅ |
| Laser without reflash | ❌ (separate binary) | ✅ |
| Switch CNC↔Laser | Reflash ~5 min | $Config/Filename=… + $Bye |
| Configuration | GRBL $$ params |
YAML + WebUI |
| Web interface | Basic | Rich (file manager, terminal, macros) |
| Debug / logs | Limited | Detailed serial + WebSocket |
| Config rollback | — | Always possible |
| MKS TS35 display | ✅ | ❌ (upstream) |
| Community TTC450 | ★★★★☆ | ★★★☆☆ |
The last two rows were the catch: the stock firmware drives the TS35 display natively, and FluidNC upstream has no TS35 support (and has explicitly declined to add it). I will come back to that.
The backup procedure
Before touching the firmware I wanted a complete backup of the original state. The ESP32 flash is accessible over serial with esptool, and a full dump captures everything: bootloader, partition table, both OTA app slots, and SPIFFS.
1 2 | |
Then I verified the dump was not just zeros and confirmed the firmware identity:
- Board string from
$I:PRODUCER:MKS_DLC32 / VER:1.1h.2023070302 - TS35 display string:
MKS DLC32 CNC V2.1 — V2.3 (8M.H35.20230803)
That gave me a complete recovery baseline. If anything goes wrong, one write_flash call puts the machine back exactly where it started.
Flash layout and partition analysis
I also extracted the partition table from the dump to understand how the flash was organized. The stock firmware uses a standard ESP32 OTA layout with two app slots and a SPIFFS partition. FluidNC uses huge_app.csv, a non-OTA layout that gives the application a 3 MB slot — no OTA rolling update, but no wasted space either.
A quick concern I had: does reflashing damage the ESP32? The datasheet spec for NOR flash is 100,000 erase cycles per sector. At one reflash per day that is 273 years before reaching the limit. The concern is not worth worrying about.
Installing FluidNC
The install is three binaries: bootloader, partition table, and the firmware itself.
1 2 3 4 5 | |
On first boot, FluidNC creates a WiFi AP (FluidNC / no password). You connect to it, open http://192.168.4.1, upload a YAML config, and you are running.
Writing the YAML config
The YAML config is where the real work is. FluidNC expects a complete machine description: axis definitions, steps/mm, max rates, acceleration, limits, spindle or laser output, probe input.
For the TTC450 CNC config, the relevant values come from the stepper specs:
1 2 3 4 | |
The laser config is the same mechanical definition with a different spindle block — a PWM laser output instead of the relay-controlled spindle.
Getting the config right required some cross-referencing. One community FluidNC config for the TTC450 existed as a starting point, but it covered only a lower-power laser variant and was not validated against CNC mode or the 20W module. I checked it against TwoTrees’ factory settings and the Makerbase firmware source, which resolved a few discrepancies — some values in the reference appear to be conservative safety margins rather than hard physical limits. The result is a complete, sourced config for both modes on the TwoTrees TTC450 with the 20W laser module. The full source list and decisions are in docs/yaml-config-sources.md.
The TTC450 configs, install procedure, and pre-built firmware variants — including builds with the plugins covered in the posts that follow — are in github.com/jordanauge/fluidnc-ttc450. I have the 20W laser; the repo also collects the config from diode-laser-wiki for the 5.5W variant. PRs for other hardware combinations are welcome.
Both configs live on the board as config_cnc.yaml and config_laser.yaml. Switching is instant and reversible.
The display problem
The MKS TS35 display is controlled over SPI and is specific to the Makerbase firmware. FluidNC upstream does not support it, and after public discussion in issue #759, the core team closed the request as out of scope.
This meant running FluidNC without a local display — the machine was fully operational via WiFi, but the screen went dark. For a machine in a shop that is a noticeable regression.
I ended up writing a standalone FluidNC plugin to restore the display, as well as a few useful plugins. But that will be the subject of future dedicated posts.
Result
The machine now boots FluidNC v4.0.2, connects to the local WiFi in STA mode, and is reachable via browser at its assigned IP. Initial tests with gSender seems to show it is able to communicate with the CNC over WiFi, although this is not a recommended way to use it for reliabiilty. Switching between CNC and laser takes about 10 seconds and requires no tools. The backup procedure means I can restore the original Makerbase firmware in under two minutes if needed.
The YAML config approach turned out to be a genuine upgrade over the $$ parameter system. Machine configuration is now a text file in version control, with readable comments, history, and the ability to diff changes.
This post is the first in a series on the TTC450 CNC project. The repository with the TTC450 configs, firmware builds, and install procedure is at github.com/jordanauge/fluidnc-ttc450.