Newer
Older
This is a stepper controller based on a xiao RP2040 communicating with a TMC2209 driver. One interesting application is using Stallguard for sensorless homing:
- 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:

| **Signal** | **GPIO** |
|------------|----------|
| DIAG | P07 |
| ENN | P06 |
| DIR | P27 |
| STEP | P28 |
| TX | P0 |
| RX | P29 |
Note that P29 is not the [standard RX pin](https://wiki.seeedstudio.com/XIAO-RP2040/) for `Serial1` on the Xiao. This can be changed with `Serial1.setRX(29)` in `init()`.
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.
The library [TMCStepper](https://github.com/teemuatlut/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:
#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]
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();
}
```