Skip to content
Snippets Groups Projects

TMC2209 Xiao RP2040 stepper

This is a stepper controller based on a xiao RP2040 communicating with a TMC2209 driver. One interesting application is using Stallguard for sensorless homing:

Design

Jake designed this board in EAGLE with the following in mind:

  • The TMC2209 has an internal regulator that needs to be bypassed when feeding it only 5V. A resistor of 10R must be added for this.
  • TX and RX pins are connected with a 10k resistor, with RX going to the PDN_UART pin of the TMC

The following schematic is designed for a SAMD21 Xiao board, the GPIO numbers are slightly different for a RP2040 variant:

Here is the completed board. This early prototype uses 4 layers to have a ground plane, VCC plane and signals in between:

The correct pinout for a RP2040 Xiao is:

Signal GPIO
DIAG P07
ENN P06
DIR P27
STEP P28
TX P0
RX P29

Note that P29 is not the standard RX pin for Serial1 on the Xiao. This can be changed with Serial1.setRX(29) in init().

Soldering

We soldered the prototypes using stencils + solder paste and reflow, but I had inconsistent communication to the TMC. This might have happened after incorrect settings on the VCC jumpers.

I decided to remove the driver with a hot air gun so I could inspect the solder underneath it:

After aligning a new chip, I manually reflow it with the hot air gun.

The final PCB is mounted on the back of a NEMA17 using long M3 screws. Note the VCC jumpers at the bottom.

Code

The library TMCStepper provides a good interface for reading/writing the registers of the TMC. Here's a code snippet for setting up and reading the Stallguard values:

#include <TMCStepper.h>

#define PIN_DIAG           7 // diagnostic
#define PIN_EN             6 // Enable (inverted)
#define PIN_DIR           27 // direction
#define PIN_STEP          28 // Step
#define PIN_RX            29 // RX
#define PIN_TX             0 // TX
#define SERIAL_PORT Serial1  // Serial1
#define DRIVER_ADDRESS 0b00  // MS1 and MS2 = address
#define STALL_VALUE      50  // [0...255]

#define MICROSTEPS       16

#define R_SENSE 0.1f // 100 mOhm

TMC2209Stepper driver(&SERIAL_PORT, R_SENSE, DRIVER_ADDRESS);


void setup() {
  SERIAL_PORT.setTX(PIN_TX);
  SERIAL_PORT.setRX(PIN_RX);
  SERIAL_PORT.begin(115200);

  pinMode(PIN_DIAG, INPUT);
  pinMode(PIN_EN, OUTPUT);
  pinMode(PIN_STEP, OUTPUT);
  pinMode(PIN_DIR, OUTPUT);

  driver.begin();
  driver.toff(4);
  driver.blank_time(24);
  driver.rms_current(250); // in mA
  driver.microsteps(MICROSTEPS);
  driver.TCOOLTHRS(0xFFFFF); // 20bit max
  driver.semin(5);
  driver.semax(2);
  driver.sedn(0b01);
  driver.SGTHRS(STALL_VALUE); // Stallguard < threshold -> DIAG pin goes up
}

void loop() {
    // make motor turn, needed for valid Stallguard readings
    [...]

    // 9-bit Stallguard reading
    int value = driver.SG_RESULT();
}

Result