TMCstepper - Arduino - TMC2209

For max torque, you might want to just run at 0 microsteps, sounds like in your use there is really no need for more than 200 steps. And then just interpolate to 256 for less noise. And disable coolstep for max power output. Just set a low hold current if the motors don't need to be holding stuff when not moving.

driver.intpol(true);         //interpolate
driver.TCOOLTHRS(0);  //disable coolstep
driver.ihold(0);               // hold current  0=1/32 … 31=32/32

Note that if you want to use stallguard WITH fine accuracy, the diag pin will not fire if TCOOLTHRS(0).

5.3 StallGuard Control
TCOOLTHRS ≥ TSTEP > TPWMTHRS

  • CoolStep is enabled, if configured (only with StealthChop)
  • Stall output signal on pin DIAG is enabled

This seems ironic as the datasheet also mentions to disable coolstep if accuracy is desired, but if DIAG is disabled... :-/. All that can be done is to temporarily max out the value (COOLTHRS(2^20-1), which is fine I guess. All that considered, I'm still reaching ~.1mm accuracy with coolstep enabled using the DIAG pin.

If you don't need accuracy then reading the value via UART is fast enough.

Hello, i'm quite new to Arduino and everything

Wanted to launch stepper motor with Arduiono Uno, tried to use the code from the top, but the only result i get, that i see 0.1A used (12V) and motor is not moving (cant move it with hand).

Is there any advice what did i do wrong?

What did your sketch look like after completing using an end stop?

First thing to do is to check that you are getting correct microstep reading so you know your UART connection is properly set up.

Arduino UNO has i think 3 UART ports, the top example is for software UART.

@willyw0nka
You don't need to disable the UART to use DIR & STEP pins, thats the normal way. It always uses DIR & STEP pins.

In your diagram, you have the 1k resistor in the wrong place.

The 1k resistor goes from TX to RX.

FYSEC drivers also have their own resistors:

So when using a resistor & single wire connection, you need to connect to the RX pin.

Not sure what that SP pin is in your diagram?

Also, you dont have any voltage connected to the VIO? The stepped driver should not even work without it. VM is voltage motor, hope you know this. So you wont end up putting like 12v onto the VIO pin.

I have no clue why you have a switch on the power line? You can just turn the driver off via UART or the EN pin you also have. You could just wire the EN directly to ground on the driver, as you can use UART to enable & disable the driver.

The settings you change do not really affect anything. Well, the first one does disable the UART connection, im not really sure what you are doing. Its kinda weird if it works. It should not work :slight_smile:

You always need motor power for the driver to work, you need motor power first. Otherwise it wont work.

Check the datasheet for what they actually affect:
https://www.trinamic.com/fileadmin/assets/Products/ICs_Documents/TMC2209_datasheet_rev1.08.pdf

Mres i think is same as microstepping setting, so you are setting microstepping twice.

The TMCStepper just has a bit more user friendly microstepping setting interface.

Also, another thing is that your board has 3 hardware UARTS, so you dont need to use software UART.

This is also unnecessary, as its default on. You can just keyword search all the settings from the datasheet so you know what you are setting.

You also don't need to have the power switch, as you already have the EN pin. That does the same. And you don't even need the EN pin, as you have UART. You can use UART to enable & disable the driver. Though im not completely sure what you are referring to with "activate the movement".

You can find some simple test codes from the original thread. Here is one, though i'm now using FastAccelStepper, its better but a bit more complex. Speedystepper is really simple. So you have acceleration control from the getgo.

You can see that you only need to define quite few settings, most of the advanced settings relate to CoolStep powersaving. This example only has the basics; set current, microstepping & choose stepping mode.

Its exactly indented so that you can get the driver running fast, and confirm you have the correct wiring setup.

#include <SpeedyStepper.h> //Simple & good stepper library, get it.

#include <TMCStepper.h>

//Solder EN & MS1 & MS2 to ground on the driver. This enables the driver and sets its UART address as 0. You can use UART to enable & disable the driver.

#define DIR_PIN           14 // Direction
#define STEP_PIN         12 // Step
#define SERIAL_PORT Serial2 // HardwareSerial2, check your pins
#define DRIVER_ADDRESS 0b00 // TMC2209 Driver address according to MS1 and MS2.

// UART addresses set by MS1 & MS2:
// 0b00 = 0 MS1 low  MS2 low
// 0b01 = 1 MS1 low  MS2 high
// 0b10 = 2 MS1 high MS2 low
// 0b11 = 3 MS1 high MS2 high

#define R_SENSE 0.11f // Match to your driver
                      // SilentStepStick series use 0.11
                      // UltiMachine Einsy and Archim2 boards use 0.2
                      // Panucatt BSD2660 uses 0.1
                      // Watterott TMC5160 uses 0.075


TMC2209Stepper driver(&SERIAL_PORT, R_SENSE, DRIVER_ADDRESS);

SpeedyStepper stepper;

void setup() {

stepper.connectToPins(STEP_PIN, DIR_PIN); // INITIALIZE SpeedyStepper
  
SERIAL_PORT.begin(115200);      // INITIALIZE UART TMC2209
Serial.begin(115200);
delay(500);
Serial.println(F("Serial Initialized"));

  driver.begin();                // Initialize driver
                           
  driver.toff(3);                 // Enables driver in software and 0 disables the driver

  driver.rms_current(600, 0.5);       // Set motor RMS current & hold current divider.
  driver.microsteps(2);            // Set microsteps to 1/2

  driver.intpol(true);               // Interpolate to 256 steps, smooth stepping even with 0 microsteps.

  driver.pwm_autoscale(true);    // Needed for stealthChop
  driver.en_spreadCycle(true);   // false = StealthChop / true = SpreadCycle

  stepper.setCurrentPositionInSteps(0);                   // Set zero position
  stepper.setSpeedInStepsPerSecond(400);              //Set Speed
  stepper.setAccelerationInStepsPerSecondPerSecond(400);   //Set acceleration, smaller value for super smooth direction changing

}

void loop() {

uint16_t msread=driver.microsteps();
Serial.print(F("Read microsteps via UART to test UART receive : "));    Serial.println(msread); 
  
Serial.println(F("Move 6400 steps forward at 600ma"));
driver.rms_current(600); 
stepper.moveToPositionInSteps(6400);

Serial.println(F("Wait 3sec and turn current low so you can turn the motor shaft"));
driver.rms_current(10); 
delay(3000);

Serial.println(F("Move back to 0 position at 300ma"));
driver.rms_current(300); 
stepper.moveToPositionInSteps(0);

//MOVE MOTOR VIA UART AND CHANGE DIRECTION VIA SOFTWARE, IT RUNS AS LONG AS YOU LET IT... PROBABLY ONLY USEFUL WITH ENCODER. THE VALUE SETS ONLY THE SPEED.

driver.VACTUAL(16000); //SET SPEED OF MOTOR
delay(2000); // MOTOR MOVES 2 SEC THEN STOPS
driver.VACTUAL(0); //STOP MOTOR BY SETTING SPEED TO 0
driver.shaft(!driver.shaft); // REVERSE DIRECTION

}

This was the only setting that you changed, as its normally 1. And you set it to 0.

Im not completely sure, but i think it relates to you not having the logic power connection on your driver.

It also seems you have the UART connected to the SP pin, and that is a chopper selection pin.

Just pointing these out so people don't follow that example, as the wiring is a total mess and its the wiring that is the issue, not the code.

Hi All,

Wanting to use this project as a way to test Bigtreetech TMC2209 v1.2 driver. I only have mega2560 pro(Compact board).

I'm very new to Arduino. I am using the version of script with pots. all wired up and everything checked and uploaded. turn on power and the driver just holds the motor i try to move and its solid. I turn off power and motor turns off and moves. i adjust the pot to see any response but nothing. Circuit wired as per script below.

Any advice.

Many thanks

> #include <TMCStepper.h>
> #include <SoftwareSerial.h>         // Use software serial for the UART to TMC2209 
> # include <Streaming.h>             // For debugging
> 
> #define EN_PIN           2          // Enable - PURPLE
> #define DIR_PIN          3          // Direction - WHITE
> #define STEP_PIN         4          // Step - ORANGE
> #define SW_SCK           5          // Software Slave Clock (SCK) - BLUE
> #define SW_TX            6          // SoftwareSerial receive pin - BROWN
> #define SW_RX            7          // SoftwareSerial transmit pin - YELLOW
> #define DRIVER_ADDRESS   0b00       // TMC2209 Driver address according to MS1 and MS2
> #define R_SENSE 0.11f               // SilentStepStick series use 0.11 ...and so does my fysetc TMC2209 (?)
> #define POT1             A0         // Potentiometers to adjust speed and travel
> #define POT2             A1
> 
> SoftwareSerial SoftSerial(SW_RX, SW_TX);
> 
> TMC2209Stepper TMC_Driver(&SoftSerial, R_SENSE, DRIVER_ADDRESS);
> 
> 
> //== Setup ======================================================================================
> 
> void setup() {
> 
>   Serial.begin(115200);               // initialize hardware serial for debugging
>   SoftSerial.begin(115200);            // initialize software serial for UART motor control
>   
>   pinMode(EN_PIN, OUTPUT);
>   digitalWrite(EN_PIN, LOW);          // Enable driver in hardware
>   pinMode(STEP_PIN, OUTPUT);
>   pinMode(DIR_PIN, OUTPUT);
> 
>   TMC_Driver.beginSerial(115200);     // Initialize UART
> 
>   TMC_Driver.begin();                                                                                                                                                                                                                                                                                                                            // UART: Init SW UART (if selected) with default 115200 baudrate
>   TMC_Driver.toff(5);                 // Enables driver in software
>   TMC_Driver.rms_current(1770);       // Set motor RMS current
>   TMC_Driver.microsteps(256);         // Set microsteps
> 
>   TMC_Driver.en_spreadCycle(false);   // Toggle spreadCycle
>   TMC_Driver.pwm_autoscale(true);     // Needed for stealthChop
>   
> }
> 
> //== Loop ========================================================================================
> 
> void loop() {
> 
>   int potVal = analogRead(A0);                              // Read potentiometer (0-1023)
>   long stepperSpeed;
> 
>   if (potVal <= 500)                                        // In lower half of range turn counter clockwise
>   {                                                         // (direction depends on motor wiring?)
>     stepperSpeed =  map(potVal, 0, 500, -200000, 0);
>   }
>   else if (potVal >= 520)                                   // In high half of range turn clockwise
>   {
>     stepperSpeed =  map(potVal, 520, 1023, 0, 200000);
>   }else                                                     // Create a "dead zone" between CW and CCW
>   {                                                         // if 500 < potVal <520
>     stepperSpeed = 0;                                           
>   }
> 
>   Serial << potVal << "       " << stepperSpeed << endl;
>   
>   TMC_Driver.VACTUAL(stepperSpeed);
>   TMC_Driver.step();
> 
> } // end loop

@ regenerate3d:
My guess would be: comment out / delete

TMC_Driver.step();


However, I think we all got this message (2022-the-year-in-review)

And to my surprise:
2022


I haven't been back here much but really awesome to see so much input, tweaks, feedback etc.
That's actually what this forum is about isn't it? Posting, asking and helping eachother out in the best way we can.

Thanks for all the contributions and...

Happy new year!

SoftwareSerial SoftSerial(SW_RX, SW_TX);
SoftSerial.begin(115200);

The Mega 2560 has multiple hardware serial ports, you should not be using software serial.
https://www.arduino.cc/reference/en/language/functions/communication/serial/

Furthermore, Software serial will not work at 115000 baud. Additionally not all pins support software serial on the Mega and 6 and 7 are not among them.

Not all pins on the Mega and Mega 2560 boards support change interrupts, so only the following can be used for RX: 10, 11, 12, 13, 14, 15, 50, 51, 52, 53, A8 (62), A9 (63), A10 (64), A11 (65), A12 (66), A13 (67), A14 (68), A15 (69).

First check that you have UART connection available before doing anything else.

Try this example, and check that thread as it has way more information than this:

I've spent a couple of days getting things to "kinda" work.

Still don't have the ability to read back from the TMC2209. But, I can write to it to

  1. Change the current setting
  2. Change the direction
  3. Set steps
  4. Change Microsteps

and that's probably enough to get what I need.

However, to make this work with software serial on an Arduino Nano, the baud rate has to be significantly reduced. I started out on 115200. It seemed to do some things, but not reliably. I ran most of yesterday at 51600. It worked, but still was unreliable. In particular, I couldn't get the current level sufficiently high to overcome my finger stopping the shaft. Seemed like current changes did little or nothing. I finally dropped to 19200 for a baud rate and it appears that all problems setting registers are gone.

For those probing with an oscilloscope, know that almost everything is going thru the UART for this code example. You won't see any signals on STEP or DIR or CLK. In fact, I suspect this sketch would work fine with just a single TX wire from the Arduino and the other wires (2,3,4,5, &7) can be removed. I'd test that, but I've already re-coded to use the STEP pin.

From a checkout point of view, it might be easier to actually use STEP and DIR since you can probe these signals and verify they are working.

The UART receive connection seems to be a major hurdle for many people. I started out as the diagram showed and then switched to a single wire with a 1K resistor. Still no joy, but it's not essential for control...so I've given up on that issue.

Good news is that I can make the stepper run at less than 1 RPM and it's no warmer after running for an hour than it was at the start.

@rrcylist
The sketch mrExplorer posted cut out all the STEP/DIR commands.

Its useful only for testing the UART connection. You can't actually run the stepper solely via the UART. You do need STEP/DIR pins to actually use it as a stepper. The UART interface is only for configuration purposes.

Most likely you are missing the 1k resistor, if you only have a one way connection. Or you have connected to wrong pin on the driver. Some drivers have integrated 1k resistor.

At least FYSETC drivers seems to have this integrated 1k resistor on one pin.

Oh contraire.... :grinning:

You can run stepper motors without using STEP and DIR. In fact, I have neither of those signals connected and my project is complete. The TMC2209 will run without them. They have caveats about doing so, since the TMC driver won't "ramp" speeds if you load a speed value to VACTUAL that require dramatic accel or decel, but it's fine for my use case (a variable speed peristaltic pump controller).

I did finally get the UART working. The thing that made it hard is that I was writing the value of "1" for microstepping to my TMC 2209 (since I did not want microstepping and I assumed that "1" would be full steps"). But, I was wrong. When I read back the microstepping value (to test for bi-directional UART comms), I got back a value of 256. This is the value received when bi-directional comms aren't working. Unfortunately, it's also the value you get back when you write a "1" to the register.

Eventually, I tried writing other values to the microstepping register....and I could read those back. Turns out, if you don't want to microstep at all, you need to write a zero to that register.

Once I did that, I started to play with setting other register values in the TMC2209. Eventually, I was able to get it doing what I wanted. This website was very helpful, even though I was using a different library: https://github.com/janelia-arduino/TMC2209

Yes, you can run the motor.. but you cant count the steps. So its not exactly a stepper motor at that point.

The UART vactual command simply sets the motor into motion with a set speed, but you have no way to instruct it to move set amount of steps. As you cant count the steps.

The data sheet says that its possible to use the INDEX pin to count steps, but it not sure if that makes any sense.

You want to use a stepper library, that provide you with accelerations ramps & step counting etc.

Its possible to get by without the DIR pin, and use UART to change the direction. I did post an example about that using FastAccelStepper. But the STEP pin is kinda essential, if you want to use it as a stepper motor.

The problem is that mrExplorer copied my original example, but changed it in a way that it no longer did what it was supposed to do. It was supposed to be an example to get the UART working fast & serve as a fool proof example to know that your wiring is OK. It exactly set the microstepping at 0 to confirm that it works. And had example of VACTUAL & normal stepper motion control.

All this was explained few comments under the example. Like the microstepping settings.

But good that you got it working.

Any here gotten sensorless homing (using stallguard) to function with an Arduino Uno?

Thanks in advance for posting an example .ino with pinout that functions.

PS: What is the pinout of the TMCStepper library and TMC2209 library? Been challenging to use either because the pinout for the Arduino Uno has seemed so ambiguous on those.

Au...