TMC2209 and ESP32 - UART Wiring

My setup:

  • TMC2209 v1.3 stepper driver
  • AZ Delivery D1 Mini ESP32
  • Want to control the motor via UART communication

I've tried following the manual and various example wirings from other discussions online without success (I've spent days...). At best, I've temporarily achieved one-way communication, both getting the motor to move and receiving responses from the TMC2209, but never simultaneously, and as soon as I add additional features, it stops working.

I'm confused about exactly which pin on the TMC2209 should be used for UART communication. The manual refers to "UART" as a specific pin, but it doesn't seem clearly defined from what I can see.

My questions:

  1. Which specific pin on the TMC2209 should be used for UART communication?
  2. What's required to activate UART and are there other important aspects to consider?

Does anyone have a working wiring diagram for TMC2209 and ESP32 (preferably D1 Mini) for UART control? I would really appreciate a diagram showing all connections, but any help is more than welcome!

1 Like

Post a link to technical information on what you have. There are several different modules available plus the chip?

Sure, here's a link to the one I have: BIGTREETECH TMC2209 V1.3 Stepper Motor Driver – Biqu Equipment

Thanks for posting, I understand why you are having problems, that is a great sales ad but it is missing the details needed to operate it. I would suggest you get your money back and get a different unit that provides the needed documentation. First try your existing vendor and see if they can offer help, if not return it.

1 Like

Thanks. I thought the TMC2209 from BTT was a fairly established product in the community. But I'll definitely consider other alternatives - are there any recommendations for a well-documented and proven motor driver with stallguard/sensorless homing, that works well with ESP32?

1 Like

Im also having the same issue but i cant get mine to even turn. How do you have your TMC2209 wired? have a look at the following pages. Silent2209 - FYSETC WIKI . GitHub - janelia-arduino/TMC2209: The TMC2209 is an ultra-silent motor driver IC for two phase stepper motors with both UART serial and step and direction interfaces.

I've checked several wirings including the ones in your linked pages. Unfortunately I don't remember my semi working wiring since I've only managed to get the motor running on rare occasions, but haven't been able to consistently reproduce it after adding more functionality to the code.

Have you made any progress?

i have! here is the code im using to run booth stepper with the TMC2209

#include <TMCStepper.h>
#include <AccelStepper.h>

#define SW_RX             17 // TMC2208/TMC2224 SoftwareSerial receive pin
#define SW_TX             16 // TMC2208/TMC2224 SoftwareSerial transmit pin
#define EN_PIN            32  // LOW: Driver enabled. HIGH: Driver disabled
#define STEP_PIN          12  // Step on rising edge
#define DIR_PIN           13  // Step on rising edge
#define SERIAL_PORT       Serial2 // TMC2208/TMC2224 HardwareSerial port
#define R_SENSE           0.11  // SilentStepStick series use 0.11, Watterott TMC5160 uses 0.075
#define DRIVER_ADDRESS    0b00 // TMC2209 Driver address according to MS1 and MS2
TMC2209Stepper driver(&SERIAL_PORT, R_SENSE, DRIVER_ADDRESS);
AccelStepper stepper = AccelStepper(AccelStepper::DRIVER, STEP_PIN, DIR_PIN);

#define EN_PIN_2          26  // LOW: Driver enabled. HIGH: Driver disabled
#define STEP_PIN_2        27  // Step on rising edge
#define DIR_PIN_2         14  // Step on rising edge
#define R_SENSE_2         0.11  // SilentStepStick series use 0.11, Watterott TMC5160 uses 0.075
#define DRIVER_ADDRESS_2  0b10 // TMC2209 Driver address according to MS1 and MS2
TMC2209Stepper driver_2(&SERIAL_PORT, R_SENSE_2, DRIVER_ADDRESS_2);
AccelStepper stepper_2 = AccelStepper(AccelStepper::DRIVER, STEP_PIN_2, DIR_PIN_2);

void setup() {
  Serial.begin(115200); 

  // Initialize UART for TMC2209
  SERIAL_PORT.begin(115200, SERIAL_8N1, SW_RX, SW_TX);

  // Enable drivers
  pinMode(EN_PIN, OUTPUT);
  pinMode(EN_PIN_2, OUTPUT);
  digitalWrite(EN_PIN, LOW);   // Enable Yaw stepper
  digitalWrite(EN_PIN_2, LOW); // Enable Pitch stepper

  // Configure steppers
  stepper.setMaxSpeed(2000); // Set max speed (steps per second)
  stepper.setAcceleration(1000); // Set acceleration (steps per second^2)
  stepper_2.setMaxSpeed(2000);
  stepper_2.setAcceleration(1000);
}

void loop() {
  Serial.println("Moving Yaw & Pitch...");

  // Move Yaw stepper forward & backward
  stepper.move(5000);
  while (stepper.distanceToGo() != 0) {
    stepper.run();
  }
  delay(500);
  stepper.move(-5000);
  while (stepper.distanceToGo() != 0) {
    stepper.run();
  }

  // Move Pitch stepper forward & backward
  stepper_2.move(5000);
  while (stepper_2.distanceToGo() != 0) {
    stepper_2.run();
  }
  delay(500);
  stepper_2.move(-5000);
  while (stepper_2.distanceToGo() != 0) {
    stepper_2.run();
  }

  Serial.println("Completed one movement cycle.");
  delay(2000);
}

I used a 1K resistor over the TX and RX lines on the ESP32 and the other 2 lines run 2 the RX and TX pins of the TMC2209

1 Like

Thanks for sharing your setup. I've followed your approach and I'm getting a response of "2" from the test_connection() function, which seems to mean some communication with the driver. However, my motor isn't moving at all.

Could you show in more detail exactly how you connected the 1K resistor between the TX and RX lines and what pin you are using for UART in TMC2209?

do you have a photo of your set / wiring so i can help you. and what model/name TMC2209 do you have?Then i can help you to get yours running.

Great, I'm using a TMC2209 v1.3 stepper driver with my AZ Delivery D1 Mini ESP32.

Here's my current setup:


Common GND between all components.

Did you connect MS1 or/and MS2? Your code mentions DRIVER_ADDRESS 0b00 based on MS1 and MS2, but I wasn't sure if I need to wire them up.

Ok so the MS1 and MS2 pins if you want to microstep you can use a 10k resistor from 5v on MS1. But if you dont want that then you can just use my code as is. The code sets the adress. Your EN pin on the TMC2209 needs to go to a pin on the ESP32 you dont GND the EN pin as you can see in my code as well as DIR and STEP. You can bridge a 1k resistor over TX and RX pin GPIO 16 & 17 on ESP32 and from RX TX tMC2209 UART pin. You only need one TMC2209 connect to UART pin. You dont need to connect anything on MS1 & MS2 on either TMC2209. Use the same pins im using and you wont have any issues. Connect your RX TX from Esp32 to your PDN pin on the TMC2209 just under the CLK pin

I've got the motor moving through STEP/DIR signals, just like in your code. The motor runs quietly and smoothly in StealthChop mode, so the basic functions are working well.

The problem is that the UART communication doesn't work despite multiple attempts. I've tested:

  1. Wiring exactly as shown in the manual with a 1kΩ resistor between TX (GPIO16) and RX (GPIO17) on the ESP32, and both connected to the PDN_UART pin (below CLK) on the TMC2209
  2. Different baud rates (115200, 19200, 9600)
  3. Other pin combinations for UART
  4. Left MS1 and MS2 unconnected as you suggested

I get no responses from the TMC2209 when sending UART-commands.

Do you have any other suggestions on what might be wrong? Could you share your actual wiring, especially how you've connected the resistor and the PDN_UART pin?

1 Like

I have the exact same driver and am having the exact same issues. With some different code* I get numbers but they don´t really seem to match load or stalling, so I think it's not really working. I´d be interested in getting at least StallGuard to work.

BTW the official documentation for these drivers is here: https://github.com/bigtreetech/BIGTREETECH-Stepper-Motor-Driver/tree/master/TMC2209/V1.3 though it's not much, there are schematics and manuals

*here's the code I get some numbers with. Note that I get 0 from the test_connection() call instead of 2

#include <HardwareSerial.h>
#include <TMCStepper.h>


#define DIAG_PIN_2         19          // STALL motor 2
#define EN_PIN_2           4          // Enable
#define DIR_PIN_2          18          // Direction
#define STEP_PIN_2         5          // Step
#define SERIAL_PORT_2      Serial2    // TMC2208/TMC2224 HardwareSerial port
#define DRIVER_ADDRESS_2   0b00       // TMC2209 Driver address according to MS1 and MS2
#define R_SENSE_2          0.11f      // E_SENSE for current calc.  
#define STALL_VALUE_2      200          // [0..255]

hw_timer_t * timer1 = NULL;
TMC2209Stepper driver2(&SERIAL_PORT_2, R_SENSE_2 , DRIVER_ADDRESS_2 );


void IRAM_ATTR onTimer() {

  digitalWrite(STEP_PIN_2, !digitalRead(STEP_PIN_2));
} 

void activate_interrupt(){
    {
      cli();//stop interrupts
      timer1 = timerBegin(3, 8,true); // Initialize timer 4. Se configura el timer,  ESP(0,1,2,3)
                                   // prescaler of 8, y true es una bandera que indica si la interrupcion se realiza en borde o en nivel
      timerAttachInterrupt(timer1, &onTimer, true); //link interrupt with function onTimer
      timerAlarmWrite(timer1, 8000, true); //En esta funcion se define el valor del contador en el cual se genera la interrupción del timer
      timerAlarmEnable(timer1);    //Enable timer        
      sei();//allow interrupts
    }
  }

void setup() {
//   Serial.begin(250000);         // Init serial port and set baudrate
  Serial.begin(9600);         // Init serial port and set baudrate
  while(!Serial);               // Wait for serial port to connect
  Serial.println("\nStart...");
  SERIAL_PORT_2.begin(115200);
  
  pinMode(DIAG_PIN_2 ,INPUT);
  pinMode(EN_PIN_2 ,OUTPUT);
  pinMode(STEP_PIN_2 ,OUTPUT);
  pinMode(DIR_PIN_2 ,OUTPUT);

  digitalWrite(EN_PIN_2 ,LOW);
  digitalWrite(DIR_PIN_2 ,LOW);

  driver2.begin();
  driver2.toff(4);
  driver2.blank_time(24);
  driver2.rms_current(1500); 
  driver2.microsteps(8);
  driver2.TCOOLTHRS(0xFFFFF); // 20bit max
  driver2.semin(0);
  driver2.semax(2);
  driver2.shaft(false);
  driver2.sedn(0b01);
  driver2.SGTHRS(STALL_VALUE_2);

  activate_interrupt();
}

void loop() {
 static uint32_t last_time=0;
 uint32_t ms = millis();
 

 if((ms-last_time) > 100) { //run every 0.1s
    last_time = ms;

    Serial.print("0 ");
    Serial.print(driver2.SG_RESULT(), DEC);
    Serial.print(" ");
    Serial.print(driver2.test_connection());
    Serial.print(" ");
    Serial.print(driver2.cs2rms(driver2.cs_actual()), DEC);

    Serial.println();
 }
}

I also got to move the motors..

could you explain in more detail or even in a diagram how to exactly connect the rx tx from tmc2209 to rx tx on esp32? Thank you.