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.
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.
#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