Replacing a DVR 8825 with a TMC 2208/2209

Hi!

I am using a NEMA 17 Stepper to turn some discs in an artwork. Nothing very complicated. So far I have been using DVR 8825 to drive the stepper, but I have notice that they are really very loud, and I would like to keep it as quiet as possible, so after a recommendation from a fellow artist, I got myself a couple of TCM 2208 and TMC 2209.

Already in their normal modes, these are VERY quiet in comparison. I also tried them using microstepping, and it gets better, plus it gives me some resolution that I actually appreciate: 1/16 for TMC 2208 and 1/64 for TMC 2209

I also saw that it is possible to use them with 1/256 microsteps. I wonder if this makes sense for my application, but I would definitely like to try it. I have seen I must enable UART mode, but I have no idea what this is, and I wonder if this has actually more to do with a function that works together with SKR control boards, and this makes no sense for me, since I am not using one, simply the driver (2208 or 2209) connected with an arduino nano.

I copy here the code I am currently using in hope that somebody can let me know if really UART is what I am looking for.

Thank you in advance

#include <AccelStepper.h>

#define EN_PIN    5  // LOW: Driver enabled. HIGH: Driver disabled

const int MS1 = 3; 
const int MS2 = 4;

const int dirPin = 7;
const int stepPin = 6;


AccelStepper stepper(AccelStepper::DRIVER, stepPin, dirPin);


void setup() {
  pinMode(EN_PIN, OUTPUT);
  pinMode(MS1,OUTPUT);
  pinMode(MS2,OUTPUT);

  digitalWrite(EN_PIN, LOW);    // Enable driver in hardware
  digitalWrite(MS1,HIGH); 
  digitalWrite(MS2,HIGH); 
  
  stepper.setMaxSpeed(900);
  stepper.setSpeed(90);
}

void loop () {
  stepper.runSpeed();
}

UART stands for universal asynchronous receiver / transmitter and defines a protocol, or set of rules, for exchanging serial data between two devices . UART is very simple and only uses two wires between transmitter and receiver to transmit and receive in both directions.

The TMCs can be configured with a serial interface.

If microstepping 1/256 is useful for you depends on the maximum rpm you need.
increasing microsteps means higher step-frequency for the same rpm.

example
60 rpm = 1 rotation per second in fullstep mode 200 steps per second = 200 Hz

60 rpm = 1 rotation per second in 1/256 microstepping means 200 * 256 = 51200 steps per second = 51.200 Hz = 51.2 kHz which is pretty much for an arduino Uno.

Thank you stefan.

Can you recommend me a guide to configure the TMCs considering that I am not used to these topics and dont need any complicated features as if I would run cncs or 3d printers? The ones I have found have seem too difficult for me and they scared me off.

You mention serial data exchange between two devices. Which kind of devices? As explained, in my setup, there is an arduino, the stepper driver and the stepper. Could it be that UART is for an application that requires a device that I do not have in my configuration? Or in this case would be arduino and driver the transmitter and receiver?

1/256 is useful for me if it is quieter than regular 1/16 (2208) or 1/64 (2209) microstepping. If it is not quieter, I dont need it. But since I dont know, I wanted to try it. Do you have experience on this?

The speed of rotation I am using is actually very slow. A full rotation takes longer than one minute.

You can use the AccelStepper (or my preference the MobaTools stepper library) to control the step/dir of the motor and another library like the TMCStepper library to talk to the TMC2209 through its UART.

Here is an example using the MobaTools and TMCStepper libraries with an Uno. I use a software serial port on the Uno to talk with the TMC2209. This is kind of like the Bounce example from the Stepper library except that the code uses 2 pots, 1 to control stepper speed and another to control distance. I have been using this code to experiment with the TMC2209 stepper. It shows how to interface with MobaTools and setting up the serial port for use with the TMCStepper library. It is similar to the TMC_AccelStepper example from the TMCStepper library.

// TMC2209 test code by groundFungus aka c.goulding
// stepper bounce with speed and distance controlled by pot

#include <TMCStepper.h>
#include <SoftwareSerial.h>
#include <MobaTools.h>

const byte EN_PIN = 8; // Enable
const byte DIR_PIN = 4; // Direction
const byte STEP_PIN = 5; // Step
const byte speedPotPin = A0;
const byte distancePotPin = A1;

const byte SW_RX = 6; // TMC2208/TMC2224 SoftwareSerial receive pin
const byte SW_TX = 7; // TMC2208/TMC2224 SoftwareSerial transmit pin

#define DRIVER_ADDRESS 0b00 // TMC2209 Driver address according to MS1 and MS2

#define R_SENSE 0.11f // SilentStepStick series use 0.11

const int stepperPulsePerRev = 200;
int microstepping = 4;
int stepsPerRev = stepperPulsePerRev * microstepping;

TMC2209Stepper driver(SW_RX, SW_TX, R_SENSE, DRIVER_ADDRESS);
SoftwareSerial ss(SW_RX, SW_TX);
MoToStepper myStepper( stepsPerRev, STEPDIR );

void setup()
{
   Serial.begin(115200);
   ss.begin(19200);  // SoftwareSerial

   pinMode(EN_PIN, OUTPUT);
   pinMode(STEP_PIN, OUTPUT);
   pinMode(DIR_PIN, OUTPUT);
   digitalWrite(EN_PIN, LOW);      // Enable driver in hardware

   // set up stepper 
   myStepper.attach( STEP_PIN, DIR_PIN );
   myStepper.attachEnable(EN_PIN, 0, 0);  // pin, delay, active state
   myStepper.setSpeed(1000);  // rpm /10
   myStepper.setRampLen(10); // set acceleration
   myStepper.setZero(); // home position

   // set up driver 
   driver.begin();
   driver.toff(4);                 // Enables driver in software
   driver.rms_current(1000);        // Set motor RMS current
   driver.microsteps(microstepping); // Set microsteps

   //driver.en_spreadCycle(false);   // Toggle spreadCycle on TMC2208/2209/2224
   driver.pwm_autoscale(true);     // Needed for stealthChop

   delay(1000);
 }

void loop()
{
   static int sign = 1;
   int stepperSpeed = analogRead(speedPotPin) * 2.5;
   int stepperDistance = analogRead(distancePotPin) * 4;

   if(stepperSpeed < 10)
   {
      stepperSpeed = 10;
   }

   myStepper.setSpeed(stepperSpeed);

   if (myStepper.moving() == 0)
   {
      sign = sign * -1;
      myStepper.move(stepperDistance * sign);
   }
}

Tested on real hardware.

Thank you very much groundFungus for your answer and guidance.

I have succesfully run this code with my setup. Now I would like to get rid of the potentiometers and give them the very simple instruction of turning at a certain speed, so I can make a loadness comparison between the 2208 and 2209. In my original code for 2208 I have:

void setup() {
 
  stepper.setMaxSpeed(900);
  stepper.setSpeed(90);
}

void loop () {
  stepper.runSpeed();
}

How can I give this instruction with TMCStepper, if at all? I have the feeling looking at your code that it works more with distance or steps given

And my other important question, how do I achieve 256 microsteps?
int microstepping = 256; ?

Thanks again for your support!

There are different ways to set the stepper speed in the MobaTools library. See the docs.

The setSpeed() function sets the speed in RPM (assuming that the stepper steps / rev is set accurately in the constructor [ stepsPerRev ]) The argument is RPM * 10 so setSpeed(500) is 50RPM.

The setSpeedSteps() function sets the speed in steps * 10. So setSpeedSteps(500) is 50 steps per second.

The setMaxSpeed() function sets the speed in steps. So setMaxSpeed(500) is 500 steps per second.

To run the stepper at speed without specifying a destination use the rotate() function. So rotate(1) for ClockWise, rotate(-1) for CounterClockWise and rotate(0) to stop.

Here is a code that should mimic the code that you posted in post #5.

// TMC2209 test code by groundFungus aka c.goulding

#include <TMCStepper.h>
#include <SoftwareSerial.h>
#include <MobaTools.h>

const byte EN_PIN = 8; // Enable
const byte DIR_PIN = 4; // Direction
const byte STEP_PIN = 5; // Step

const byte SW_RX = 6; // TMC2208/TMC2224 SoftwareSerial receive pin
const byte SW_TX = 7; // TMC2208/TMC2224 SoftwareSerial transmit pin

#define DRIVER_ADDRESS 0b00 // TMC2209 Driver address according to MS1 and MS2

#define R_SENSE 0.11f // SilentStepStick series use 0.11

int current = 500; // 500mA coil current
const int stepperPulsePerRev = 200;
int microstepping = 8;  //  *****&&&&&&&&&*********&&&&&*** microsteps
int stepsPerRev = stepperPulsePerRev * microstepping;

TMC2209Stepper driver(SW_RX, SW_TX, R_SENSE, DRIVER_ADDRESS);
SoftwareSerial ss(SW_RX, SW_TX);
MoToStepper stepper( stepsPerRev, STEPDIR );

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

    ss.begin(19200);  // SoftwareSerial

   pinMode(EN_PIN, OUTPUT);
   pinMode(STEP_PIN, OUTPUT);
   pinMode(DIR_PIN, OUTPUT);
   digitalWrite(EN_PIN, LOW);      // Enable driver in hardware

   stepper.attach( STEP_PIN, DIR_PIN );
   stepper.attachEnable(EN_PIN, 0, 0);  // pin, delay, active state
   
   stepper.setZero(); // home position

   driver.begin();
   driver.toff(4);                 // Enables driver in software
   driver.rms_current(current);        // Set motor RMS current
   driver.microsteps(microstepping); // Set microsteps

   //driver.en_spreadCycle(false);   // Toggle spreadCycle on TMC2208/2209/2224
   driver.pwm_autoscale(true);     // Needed for stealthChop
}

void loop()
{
   // set acceleration more acceleration steps for high speeds
   stepper.setRampLen(10); 
   
   // 3 ways to set speed, uncomment 1 line to see the effect

   //stepper.setSpeedSteps(500); // 50 steps/sec
   //stepper.setMaxSpeed(500); // 500 steps/sec
   stepper.setSpeed(500); // 50 RPM

   stepper.rotate(1);  // constantly rotate CW
}

Yes, to set the microstepping change the number in the line. You will have to recompile for it to take effect, of course.

int microstepping = 8;  //  *****&&&&&&&&&*********&&&&&*** microsteps

I need to check a couple of things one step at the time because I am starting to have a mess in my head.

Should I connect TX of the TMC 2209 to D1 (RX) of the Arduino nano and RX of the TMC 2209 to D0 (TX) of the Arduino nano?

const byte SW_RX = 1; 
const byte SW_TX = 0; 

(in your code it appeared as )

const byte SW_RX = 6; 
const byte SW_TX = 7; 

No. In my code I use a software serial port for the TMC2209 in order to keep the hardware serial port (pins 0 & 1) free for program upload, program output and debugging. The software serial port uses pins 6 and 7.

Connect the TMC2209 TX to Nano pin 6 and TMC2209 RX to Nano pin 7.

1 Like

Understood. I had them at D0 and D1, and I had to disconnect them to be able to upload the code. Now I understand why.

Now I have it running correctly. I copy here the code that I am using with the STEP/DIR method, and the code with the MULTISTEPPING method, for future reference.

STEP/DIR

#include <AccelStepper.h>

#define EN_PIN    8  // LOW: Driver enabled. HIGH: Driver disabled

const int MS1 = 2; 
const int MS2 = 3;

const int dirPin = 4;
const int stepPin = 5;


AccelStepper stepper(AccelStepper::DRIVER, stepPin, dirPin);


void setup() {
  pinMode(EN_PIN, OUTPUT);
  pinMode(MS1,OUTPUT);
  pinMode(MS2,OUTPUT);

  digitalWrite(EN_PIN, LOW);    // Enable driver in hardware
  digitalWrite(MS1,LOW); 
  digitalWrite(MS2,HIGH); 
  
  stepper.setMaxSpeed(900);
  stepper.setSpeed(90);
}

void loop () {
  stepper.runSpeed();
}

MULTISTEPPING

#include <TMCStepper.h>
#include <SoftwareSerial.h>
#include <MobaTools.h>

const byte EN_PIN = 8;    // Enable
const byte DIR_PIN = 4;   // Direction
const byte STEP_PIN = 5;  // Step

const byte SW_RX = 6;     // TMC2208/TMC2224 SoftwareSerial receive pin
const byte SW_TX = 7;     // TMC2208/TMC2224 SoftwareSerial transmit pin

#define DRIVER_ADDRESS 0b00 // TMC2209 Driver address according to MS1 and MS2

#define R_SENSE 0.11f // SilentStepStick series use 0.11

int current = 500;                      // 500mA coil current
const int stepperPulsePerRev = 200;
int microstepping = 256;                //  microsteps
int stepsPerRev = stepperPulsePerRev * microstepping;

TMC2209Stepper driver(SW_RX, SW_TX, R_SENSE, DRIVER_ADDRESS);
SoftwareSerial ss(SW_RX, SW_TX);
MoToStepper stepper( stepsPerRev, STEPDIR );

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

    ss.begin(19200);  // SoftwareSerial

   pinMode(EN_PIN, OUTPUT);
   pinMode(STEP_PIN, OUTPUT);
   pinMode(DIR_PIN, OUTPUT);
   digitalWrite(EN_PIN, LOW);      // Enable driver in hardware

   stepper.attach( STEP_PIN, DIR_PIN );
   stepper.attachEnable(EN_PIN, 0, 0);  // pin, delay, active state
   
   stepper.setZero(); // home position

   driver.begin();
   driver.toff(4);                      // Enables driver in software
   driver.rms_current(current);         // Set motor RMS current
   driver.microsteps(microstepping);    // Set microsteps

   //driver.en_spreadCycle(false);   // Toggle spreadCycle on TMC2208/2209/2224
   driver.pwm_autoscale(true);     // Needed for stealthChop
}

void loop()
{
   // set acceleration more acceleration steps for high speeds
   stepper.setRampLen(10); 
   
   // 3 ways to set speed, uncomment 1 line to see the effect

   //stepper.setSpeedSteps(500);  // 50 steps/sec
   //stepper.setMaxSpeed(500);    // 500 steps/sec
   //stepper.setSpeed(500);       // 50 RPM

   stepper.setSpeed(500);         // 50 RPM

   stepper.rotate(1);             // constantly rotate CW
}

I havent seen TX/RX pins in the TMC 2208. Is the MICROSTEPPING method different in the 2208 as in the 2209? Is it very difficult to adapt to the code we adapted for the 2209?

The TMC2208 offers 1/16 microstepping. The rotation is smoothed by internally using 1/256-micro-stepping this means the transition from one 1/32 microstep to the next is internally sub-divided into 1/256 microsteps.

You can't access 1/256 microstepping form outside but if I understonnd right in your application the motor rotates continiously anyway and just has to be silent.

best regards Stefan

this means the axle will only stop at each 360 / (200 * 32) = 0.05625 degrees
but internally the axle rotates in 360 / (200 * 256) = 0.00703125 degree steps but the axle only stops every 0.05625 degrees.

You can read about the UART-interface in the TMC2208 datasheet.

I have a general question:
Do you want to depend fully on th egrace of other users to get all your questions answered and code-modifications done
or
do you want to learn some basics about programming to be able to do the modifications yourself?

best regards Stefan

Thank you StefanL38 for your input. I already understand conceptually how microstepping works.

I was actually refering to the method with which you can with arduino access to the 1/256 microstepping of the TMC 2208, as we have been exploring with groundFungus in this post with the TMC 2209.

Regarding to your general question. I am an artist and I use technology for artistic porpouses. I am not a programmer or an engineer, and I am certainly not interested in understanding some things that are much more complex that what I am ready to deal with. I am willing and happy to learn a lot during this process, and I dont need to justify any of this to anybody. Nevertheless, since you ask, I am not depending fully on the grace of nobody to get things work. I spend a lot of time doing a lot of research on my own, and when this surpasses the scope of my understanding, my needs and my will to understand, I happily ask for help and very happily receive help, than then I apply in my projects.

I have been trying several days to understand how to access UART, watching videos on youtube, searching for tutorials, etc. All of this material is generally addressed to people who want to understand deeply how things work in order to build a cnc machine, and this level of complexity scares me off. I need a stepper to turn constantly, in one direction, slowly and silently.

Microstepping 1/256 is done automatically in all microstepping modes
1/2 microstepping does 1/256
1/4 microstepping does 1/256
1/8 microstepping does 1/256
1/16 microstepping does 1/256

I hope that this information makes you scratch your head:

??? "how can it be that the TMC2208 is doing 1/16 microstepping ??"
and
at the same time is doing 1/256-microstepping????

The explanation is in post # 11
and here

the explanation about the UART-pins is here

best regards Stefan

StefanL38, what you are writing makes no reference to my question.

The answer to this question is:

ALL

microsteping-modes use 1/256

internal interpolation

in other words:
as soon as you use a TMC2208 the TMC2208 makes 1/256 interpolation
for each and every microstepping-mode

there is a difference between interpolation microstepping
and
microstepping

interpolation microstepping is done internally by the chip
in difference
microstepping is done by your code

You get the smoothness of 1/256-microstepping with a resolution of 1/16 microstepping

When ever you give a single-pulse on the step-input
the stepper-motor-axle rotates for 0.1125 degrees
startposition: 0.0000 degree
one step-pulse from the code
endposition: 0.1125 degrees

What the TMC2208 internally does is
one step-pulse from the code

  1. rotate from 0.0000 degrees to 0.00703125 degrees
  2. rotate from 0.00703125 degrees to 0.00140625 degrees
  3. rotate from 0.10546875 degrees to 0.1125degrees
  4. stop rotation at 0.1125degrees

second step-pulse do 16 internal 1/256 steps and stop rotation at 0.225 degrees
third step-pulse do 16 internal 1/256 steps and stop rotation at 0.3375 degrees

Hi @camilozk

I must apologise to you.

If UART-configuration is used there is the possability to get 1/256 microstepping
This requires to set several bits in registers over UART-commands

Setting bit 7 in the GCONF-register enables microstep-resolution in the MSTEP-register

Setting bits 24 to 27 in the MRES-register to zero sets 1/256 microstepping

I haven't examined that in detail but I guess that these adjustments can be done by the TMCStepper.h-library.

Though I haven't found an example-cde that would go that deep into the functions of the TMCStepper.h-library.

There is another library especcially for the TMC2208

which has a command

mstep_reg_select(true) // Microstep resolution selected by MSTEP register
mres(0000); // %0000 Native 256 microstep setting. 

I don't have a TMC2208 laying around so I can't really test it.
connecting to UART for read/write-access is done this way
image

Where the USB-Serial-adapter can be replaced by any microcontroller.

best regards Stefan

This forum works this way:

learn users fishing instead of serving fish

You post your best attempt to write the code.
The code must be posted as a code-section.
You describe what behaviour your code shows
you describe how the shown behaviour deviates from the wanted behaviour
you ask specific questions how to change the code to get the wanted behaviour.

As a preparation for asking go to the Github mainpage of the TMC2208-library search for that term that you are interested in.
In your case this is microstep

search the word microstep on the github-website for the TMC-2208 library
and you will find it

best regards Stefan

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