Skip to content
Home » Home » Projects » TMC2209 and UART using FluidNC

TMC2209 and UART using FluidNC

From the 3D printing sector, many users know the TMC motor drivers, which have an excellent reputation. On the one hand, they make the motors much quieter, and on the other hand, they have other properties such as special configurations that can be set at runtime. Depending on the chip, this requires a UART or even SPI interface. Here we show as an example how to use TMC2209 drivers and how to configure them via UART communication with FluidNC. With this, it is also possible to convert the laser to “Sensorless Homing”. In this case, the driver measures the motor currents and detects the frame of the laser without an extra limit switch. However, this method is usually less accurate than physical limit switches, so it should only be considered as a gimmick and is rather disadvantageous in practice.

I was approached by Patrick. He did this project and also wrote a documentation about it. I have followed the individual steps and created a rather generic manual. Here comes first the generic part, and then Patrick’s report, which goes into more detail in many places. More information about firmware and FluidNC can also be found in these articles:


UART communication using MKS DLC32, TMC2209 and FluidNC

To address the TMC drivers via UART, corresponding pins must be available on the mainboard. On the MKS-DLC32 mainboard the I²C pins SDA and SCL are wired appropriately and can be used as UART communication line. However, this requires a little soldering work. Both the drivers and the lines to the drivers have to be soldered.

Here is the datasheet for the TMC2209: Link, and here is the documentation for the DLC32 board: Link

Preparation of the stepper drivers

Since the ESP32 works with 3.3V as logic voltage, but the TMC drivers receive 5V as supply voltage from the mainboard and communicate accordingly, the ESP could be damaged. The common solution is to desolder the pin for the supply voltage at the driver. But this doesn’t change anything. The driver is then supplied via the motor voltage and uses an internal 5V voltage regulator, so the chip is still running at 5V. The solution in this case is to connect the VDD pin of the driver module to the 3.3V line of the mainboard (there is a pin supplying 3.3V above the latter used SDA and SCL pins). But you only need to do this if you want to use three drivers. As long as you have only two (x and y axis), just don’t care about the 3.3V thing and don’t solder anything.

Remark on voltage and number of drivers. If you only want to use a maximum of two drivers, you don’t need to change anything with the VDD pin. You can leave it connected. If you intend to use three drivers, that’s where the weird things happen. In my tests, three drivers only worked successfully, if one of the modules has a different logic voltage than the others. It did not work with three modules using 5V, nor with three modules using 3.3V. It ONLY worked in a combination of 5V+5V+3.3V or 3.3V+3.3V+5V. Very strange and I currently have no explanation. But in both cases, the test for all three drivers was successful. My bottom line is: the ESP can work with 5V UART communication, but only using two modules (and the rest is odd). If someone wants to dig deeper, you are welcome to enlighten me! 🙂

Update! Fabio discovered that using a 470 ohms resistor instead of a 1k resistor at the UART line makes all three drivers work, regardless of the VDD voltage. So, just use a 470 ohms resistor, and you are fine and don’t need to change anything at the drivers! (I tested this as well, and it worked for me too)

Note: the stepper drivers need to have the UART interface enabled. The MKS TMC2209 V2.0 as in my pictures already have this configuration enabled. On different models/manufacturers, you might need to solder a very tiny resistor to enable the UART interface. See here and here, for example.

Addition Sensorless Homing: if you want to use this feature of the TMC drivers, you have to connect another wire from the DIAG pin of the driver to the limit switch pin of the mainboard. For this, you solder a cable as follows. The right picture shows the module with an additional cable for the 3.3V power supply (not required any more).

Connection of UART line

After the driver is prepared, the cabling can now be done. This is done according to the scheme in the following picture. You can solder it directly on the mainboard, like Patrick did, or use flying wires, like in my case. Since I use the board for many test purposes and also use the I²C interface in other ways, I would rather not have a fixed connection on the board. This is, of course, not so practical for continuous use. As noted above: use a ~470 ohms resistor instead of the 1k resistor and you can use three drivers at once.

References at the FluidNC-Wiki: TMC and UART.

This is how it can look like (first my pictures with flying wiring, then Patrick’s solution):

Afterward, you set the addresses of the individual drivers via the DIP switches, this must be done because all drivers are addressed via the same line and each module needs a unique address. The switches should be set as follows (switch no. 3 must always be off):

This prepares both the driver and the board.

Configuration of FluidNC

Two settings must be made in FluidNC: 1. Define the UART interface itself and 2. Set the individual configuration for each motor driver.

Define UART interface. In config.yaml the following section is added:

#There is one UART defined here which is chared by all drivers. Drivers have individual
#adresses defined in the sections above
uart1:
  txd_pin: gpio.0
  rxd_pin: gpio.4
  rts_pin: NO_PIN
  baud: 115200
  mode: 8N1

This creates the interface “uart1” and assigns the pins used above.

For each motor, the parameters must then still be set to use the features of the drivers (note: the value for “addr” must be different for each axis, as set above. “uart_num” always remains the same): (documentation in FluidNC Wiki, section on TMC2209).

x:
    steps_per_mm: 80.000
    max_rate_mm_per_min: 6000.000
    acceleration_mm_per_sec2: 500.000
    max_travel_mm: 410.000
    soft_limits: true
    homing:
      cycle: 1
      allow_single_axis: true
      positive_direction: false
      mpos_mm: 0.000
      feed_mm_per_min: 150.000
      seek_mm_per_min: 500.000
      settle_ms: 250
      seek_scaler: 1.100
      feed_scaler: 1.200

    motor0:
      limit_neg_pin: gpio.36:high
      limit_pos_pin: NO_PIN
      limit_all_pin: NO_PIN
      hard_limits: false
      pulloff_mm: 1.000
      tmc_2209:       <====================== new settings from here
        uart_num: 1   #ID of the uart bus defined above
        addr: 0       #address of the single driver as set via DIP switches

        #here you need to tune your values according to your machine and requirements
        r_sense_ohms: 0.120
        run_amps: 0.800
        hold_amps: 0.500
        microsteps: 16
        stallguard: 0
        stallguard_debug: true
        toff_disable: 0
        toff_stealthchop: 5
        toff_coolstep: 3
        run_mode: StealthChop
        homing_mode: StallGuard
        use_enable: true
        step_pin: I2SO.1
        #change direction using direction_pin: I2SO.2:low
        direction_pin: I2SO.2:low
        disable_pin: NO_PIN

Now a complete use of the drivers should be possible. In the example above, the settings are already selected so that sensorless homing can be used. However, it may take some time until you have set this up well for your own mechanics.

In the pictures you can see my finished test setup. Here only with a driver for the x-axis including cable for the sensorless homing and mounted heatsink (it was not yet on the pictures above). Here then the boot process with this board (driver Y and Z report errors, because there are none on the board, as seen above):

Driver Y and Z were not plugged in and are therefore reported as errors here.

Here is another example with all drivers connected:

Here is my complete configuration for the DLC32 board with most parameters optimized for sculpfun lasers. You can take this version as a start and adapt it to your own conditions: Download


Project documentation of Patrick

(translation still is work in progress, only available on the German version of this page)