ESP Vroom 32 & TMC2209 Driver

Hi everyone,

I’m having trouble getting my MKS TMC2209 V2 (for 3D printer applications) working with my ESP32 board to drive a NEMA 17 42-40 stepper motor. I’ve wired everything following the guidelines I found online, but despite the driver reporting “Setup Complete” and diagnostic messages on the serial monitor, the motor does not move.

My Setup:

  • Driver Board: MKS TMC2209 V2 (version used in 3D printer motherboards; EN, MS1, and MS2 are soldered to GND so the UART address is 0)
  • ESP32: Using Serial2 for the TMC2209 UART communication.
  • Motor: NEMA 17 42-40
  • Power Supply: I’m supplying the driver’s motor voltage (VM) with a 12V (or 24V) supply, and the logic (VIO) is powered from the ESP32 (3.3V).

Wiring Details:

  • Step/Dir Interface:
    • STEP from ESP32 (GPIO12) → TMC2209 STEP input.
    • DIR from ESP32 (GPIO14) → TMC2209 DIR input.
  • UART Single‑Wire Interface:
    • ESP32 TX (GPIO17) and RX (GPIO16) are tied together through a 1kΩ resistor.
    • The common node from TX/RX is connected to the PDN_UART pin on the TMC2209.
  • Common Grounds: All GND connections (ESP32, TMC2209 board, motor supply) are tied together.
  • Other pins (EN, DIAG, etc.): Not used in my current test; EN and DIAG are left out of the control code.

Software:

I’m using the TMCStepper library along with the SpeedyStepper library for motion control. Here’s a simplified version of my code:

#include <Arduino.h>
#include <SpeedyStepper.h>     // Simple & good stepper library by Stan Reifel
#include <TMCStepper.h>        // TMCStepper library

// ----- Pin Definitions -----
#define STEP_PIN      12   // STEP signal from ESP32
#define DIR_PIN       14   // DIR signal from ESP32

// ----- UART Single-Wire Setup -----
// ESP32 TX (GPIO17) and RX (GPIO16) are tied together through a 1kΩ resistor,
// and connected to the TMC2209 PDN_UART pin.
#define RX_PIN        16   // ESP32 Serial2 RX
#define TX_PIN        17   // ESP32 Serial2 TX
#define SERIAL_PORT   Serial2

// ----- TMC2209 Settings -----
#define DRIVER_ADDRESS  0    // UART address is 0 (MS1 & MS2 soldered to GND)
#define R_SENSE         0.11f // Sense resistor value (ohms)
#define STALL_VALUE     2    // Example StallGuard threshold

// ----- Instantiate Objects -----
TMC2209Stepper driver(&SERIAL_PORT, R_SENSE, DRIVER_ADDRESS);
SpeedyStepper stepper;

void setup() {
  Serial.begin(115200);
  while (!Serial); // Wait for Serial Monitor
  Serial.println(F("Serial Initialized"));

  // Initialize step/direction pins using SpeedyStepper.
  stepper.connectToPins(STEP_PIN, DIR_PIN);
  
  // Initialize the hardware serial port for TMC2209.
  SERIAL_PORT.begin(115200, SERIAL_8N1, RX_PIN, TX_PIN);
  delay(500);
  
  Serial.println(F("Initializing TMC2209..."));

  // Initialize the TMC2209 driver.
  driver.begin();
  driver.toff(3);                // Sets toff=3 (recommended for SpreadCycle)
  driver.blank_time(24);         // Set blank time
  driver.rms_current(600, 0.5);    // Set run current to 600 mA, hold current at 50%
  driver.microsteps(2);          // Set microstepping (note: if interpolation is enabled, microsteps() returns 256)
  driver.intpol(true);           // Enable interpolation to 256 microsteps
  driver.pwm_autoscale(true);    // Enable PWM autoscale (needed for stealthChop/SpreadCycle)
  driver.en_spreadCycle(true);   // Enable SpreadCycle mode (can try false for stealthChop)
  driver.TCOOLTHRS(0xFFFFF);      // Set cooling threshold
  driver.semin(0);
  driver.semax(2);
  driver.shaft(false);           // Set motor direction
  driver.sedn(0b01);             // Set stallGuard delay (example)
  driver.SGTHRS(STALL_VALUE);    // Set StallGuard threshold

  Serial.println(F("TMC2209 Setup Complete. Starting movement test..."));

  // Initialize stepper motion parameters.
  stepper.setCurrentPositionInSteps(0);
  stepper.setSpeedInStepsPerSecond(400);
  stepper.setAccelerationInStepsPerSecondPerSecond(400);

  // Diagnostic: Print microstep setting (should read 256 when interpolation is enabled)
  uint16_t msread = driver.microsteps();
  Serial.print(F("Read microsteps via UART: "));
  Serial.println(msread);

  // Test Movement Sequence:
  Serial.println(F("Moving 6400 steps forward at 600mA"));
  driver.rms_current(600, 0.5);
  stepper.moveToPositionInSteps(6400);
  while (!stepper.motionComplete()) {
    stepper.processMovement();
  }

  Serial.println(F("Waiting 3 sec and lowering current"));
  driver.rms_current(10, 0.5);
  delay(3000);

  Serial.println(F("Moving back to 0 position at 300mA"));
  driver.rms_current(300, 0.5);
  stepper.moveToPositionInSteps(0);
  while (!stepper.motionComplete()) {
    stepper.processMovement();
  }

  // Test internal velocity control (VACTUAL)
  Serial.println(F("Running motor via VACTUAL (16000) for 2 sec"));
  driver.VACTUAL(16000);
  delay(2000);
  driver.VACTUAL(0);
  
  // Toggle motor direction via UART command.
  bool currentShaft = driver.shaft();
  driver.shaft(!currentShaft);
  delay(2000);
}

void loop() {
  // Print microstep status every 3 seconds.
  uint16_t msread = driver.microsteps();
  Serial.print(F("Read microsteps via UART: "));
  Serial.println(msread);
  delay(3000);
}

If anyone can assist me ill be great full thank you!

1 Like

Check the driver datasheet about the EN.what's the amp capacity of the power supply and how much current is set up for the stepper?

Hi Railroader..Thanx for your reply. Im Using a 12V 5A power supply. I have set the current to 1.7A on the TMC2209

Good.
And the first sentense in #2?

Im not sure what you mean sir?

Have You done that?

Yes i have. EN to GND. But some documentation refers connecting to a GPIO pin on the ESP32. I have tried both ways aleady.

It looks like EN is active low and connected to GND. Keep that to avoid a possible double error in the build.
So far nothing discouverd.

Looking at the code a lot is done in setup but no motor stepping in loop.
That looks odd.
What is Your idea how movement would go on? Can You please produce a flowchart for setup and loop?

Please post the entire code You are using for the moment.

       +---------------------+
       |      Start          |
       +---------------------+
                 │
                 ▼
       +---------------------+
       |   setup() begins    |
       +---------------------+
                 │
                 ▼
       +---------------------+
       | Initialize Serial   |   <-- Open Serial monitor (115200 baud)
       +---------------------+
                 │
                 ▼
       +---------------------+
       | Initialize UART for |   <-- Serial2.begin(115200)
       |  TMC2209 Driver     |
       +---------------------+
                 │
                 ▼
       +---------------------+
       | Configure Stepper   |   <-- Setup step and direction pins (SpeedyStepper)
       |    Library          |
       +---------------------+
                 │
                 ▼
       +---------------------+
       | Initialize TMC2209  |   <-- Call driver.begin()
       |  (toff, blank_time, |
       |  current, microsteps, etc.)  |
       +---------------------+
                 │
                 ▼
       +---------------------+
       | Print "Setup        |
       | Complete" message   |
       +---------------------+
                 │
                 ▼
       +---------------------+
       |   Enter loop()      |
       +---------------------+
                 │
                 ▼
       +---------------------+
       |   Read microsteps   |   <-- Query driver.microsteps()
       +---------------------+
                 │
                 ▼
       +---------------------+
       | Print microsteps to |
       | Serial Monitor      |
       +---------------------+
                 │
                 ▼
       +---------------------+
       | Set RMS current to  |   <-- 600mA for full-current movement
       | 600mA and command    |
       | move 6400 steps     |
       +---------------------+
                 │
                 ▼
       +---------------------+
       | Block until target  |   <-- stepper.moveToPositionInSteps() waits
       | reached (forward)   |
       +---------------------+
                 │
                 ▼
       +---------------------+
       | Lower current to    |   <-- Set current to low (e.g. 10mA) for manual turn
       | 10mA, delay 3 sec   |
       +---------------------+
                 │
                 ▼
       +---------------------+
       | Set RMS current to  |   <-- Set current to 300mA and move back to 0 steps
       | 300mA and command    |
       | move to position 0  |
       +---------------------+
                 │
                 ▼
       +---------------------+
       | Block until target  |   <-- Wait until move completes
       | reached (backward)  |
       +---------------------+
                 │
                 ▼
       +---------------------+
       | Use VACTUAL() to    |   <-- Command internal velocity (16000) for 2 sec
       | run motor briefly   |
       +---------------------+
                 │
                 ▼
       +---------------------+
       | Stop motor (VACTUAL 0)|
       +---------------------+
                 │
                 ▼
       +---------------------+
       | Toggle motor        |   <-- Change direction via driver.shaft()
       | direction           |
       +---------------------+
                 │
                 ▼
       +---------------------+
       | Loop back to start  |   <-- Wait a bit, then repeat the test
       +---------------------+

Here is the code im using

#include <Arduino.h>
#include <TMCStepper.h>
#include <SpeedyStepper.h>

// ----- Pin Definitions -----
// For the MKS TMC2209 V2 board, solder EN, MS1, and MS2 to GND (UART address = 0)
#define DIR_PIN       14    // Direction pin
#define STEP_PIN      12    // Step pin

// UART connection for TMC2209 (using ESP32's Serial2)
// For a single‑wire UART, connect ESP32 TX (pin 17) to the TMC2209 PDN_UART pin via a 1kΩ resistor.
#define SERIAL_BAUD   115200
// (The TMCStepper library will use Serial2 with its default TX/RX pins unless you override them.)
#define DRIVER_ADDRESS  0b00  // (MS1=GND, MS2=GND)
#define R_SENSE         0.11f // Sense resistor value (in ohms)

// ----- Instantiate Objects -----
TMC2209Stepper driver(&Serial2, R_SENSE, DRIVER_ADDRESS);
SpeedyStepper stepper;

void moveStepperTo(long targetPosition) {
  stepper.moveToPositionInSteps(targetPosition);
  while (!stepper.motionComplete()) {
    stepper.processMovement();
  }
}

void setup() {
  // Initialize the primary serial monitor.
  Serial.begin(115200);
  delay(500);
  Serial.println(F("Serial Initialized"));

  // Initialize the hardware serial used by the TMC2209.
  // (On many ESP32 boards, Serial2 uses default pins TX=17 and RX=16;
  //  if you are using alternate pins, update accordingly.)
  Serial2.begin(SERIAL_BAUD);

  // Connect step and direction pins to the SpeedyStepper library.
  stepper.connectToPins(STEP_PIN, DIR_PIN);
  stepper.setSpeedInStepsPerSecond(400);  // Set speed (adjust as needed)
  stepper.setAccelerationInStepsPerSecondPerSecond(400);

  // --- TMC2209 Driver Setup ---
  driver.begin();                // Initialize driver via UART
  driver.toff(3);                // Set toff value (recommended 3 for SpreadCycle)
  driver.blank_time(24);         // Set blank time (example value)
  driver.rms_current(600, 0.5);    // Set RMS current: 600 mA run, hold = 50% of run current
  driver.microsteps(2);          // Set microstepping (here: 1/2 step resolution; read-back via UART should be 2)
  driver.intpol(true);           // Enable interpolation (to 256 microsteps for smoother motion)
  driver.pwm_autoscale(true);    // Enable PWM autoscaling (for stealthChop/SpreadCycle)
  driver.en_spreadCycle(true);   // Enable SpreadCycle mode (for high-dynamic performance)
  driver.TCOOLTHRS(0xFFFFF);      // Set cooling threshold (maximum value used in this example)
  driver.semin(0);
  driver.semax(2);
  driver.shaft(false);           // Default motor direction (false = normal)
  driver.sedn(0b01);             // Set StallGuard delay (example value)
  driver.SGTHRS(2);              // Set StallGuard threshold (example sensitivity)

  delay(1000);
  Serial.println(F("TMC2209 Setup Complete. Starting movement test..."));
}

void loop() {
  // Report the microstep setting read via UART.
  uint16_t msread = driver.microsteps();
  Serial.print(F("Read microsteps via UART: "));
  Serial.println(msread);

  // --- Test Move: Move 6400 steps forward ---
  Serial.println(F("Moving 6400 steps forward at 600mA"));
  driver.rms_current(600, 0.5);
  moveStepperTo(6400);

  // Wait 3 seconds and lower current (allow manual shaft adjustment, etc.)
  Serial.println(F("Waiting 3 sec and lowering current"));
  driver.rms_current(10, 0.5);
  delay(3000);

  // --- Test Move: Move back to 0 position ---
  Serial.println(F("Moving back to 0 position at 300mA"));
  driver.rms_current(300, 0.5);
  moveStepperTo(0);

  // --- Test Internal Pulse Generator (if supported) ---
  // Note: VACTUAL() is used to command an internal velocity in some configurations.
  Serial.println(F("Running motor via VACTUAL (16000) for 2 sec"));
  driver.VACTUAL(16000);
  delay(2000);
  driver.VACTUAL(0);

  // Toggle motor direction via UART command.
  bool currentDir = driver.shaft();
  driver.shaft(!currentDir);  // Toggle direction
  delay(3000);
}

type or paste code here
1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.