TMC5160 running stepper at higher speed?

Hello Community!

After some struggling i finally got the TMC5160 to play with Arduino and a Nema23 stepper motor. I opted for this driver as I understand it can handle heavier currents - and the eventual build I envision would benefit from having more torque available.

Current setup is:

My code is based on the famous TMCstepper library (GitHub - teemuatlut/TMCStepper) and the example from Watterotts 5160 driver (which doesnt seem to be available anymore, hence the Fysetc driver) (GitHub - watterott/SilentStepStick: Stepper Motor Driver based on a Trinamic TMC2100 / TMC2130 / TMC2208 / TMC2209 / TMC5160.).

From reading on the forum + trial and error I understand that the driver expects a VM-in to boot properly, and as such i practice to turn on the lab supply before turning on the arduino, or at least reset it subsequently. I also learned (the hard way) that Fysetc marks individual coils as A1/2 and B1/2, while watterotts drivers marks them opposite 1A/B and 2A/B.... took a while!

My question is: How do i get the motor to run faster, and what would be the max speed of the motor?

The datasheet(S) does not provide any information on this - but from calling the supplier I understand that most steppers should be able to run safely at 500RPM. With providing a pulsewidth of 1 microsecond, i can achieve only around 120RPM... and for the usual 10ms, slower even.

I have read a couple of posts that found serial prints can slow down the clock rate of the arduino, jeopardising the pulse width. But i have no Serial prints (only when its not running properly)... I also tried accellstepper library, as this allegedly should max out at 4000 - but in all my experience this library just makes for incredibly slow movement.

I should maybe also mention that i set microstepping to 1, as the 200 full steps are fine for this configuration. When it was set to 16, the motor would just sing an uncomfortable song... No clue why!

On a more general note: The driver also seems slightly unreliable. Randomly, it will drop into Open Load A and Open Load B status, and shut off the motor. But not necessarily correlated to strain or long operation. Its just a bit... flakey?

I hope this is enough information. I've run out of things to debug and try. Suggestions are much appreciated!

Peace

UPDATE EDIT in case anyone is also struggling with this driver:

  • microsteps() expects 0 for proper full step configuration. TIL: read source codes more often:)
  • As kindly suggested by jremington: To gain higher speeds, an acceleration profile is needed. A simple loop raising step frequency will do the trick.
  • The driver is still unpredictable. Stops working after a few hours of running (not too hot)...


#include <TMCStepper.h>

#define EN_PIN    7 //enable
#define DIR_PIN   8 //direction
#define STEP_PIN  9 //step
#define CS_PIN   10 //CS
#define MOSI_PIN 11 //SDI/MOSI
#define MISO_PIN 12 //SDO/MISO
#define SCK_PIN  13 //CLK/SCK 
 
#define R_SENSE   0.075f

TMC5160Stepper tmc = TMC5160Stepper(CS_PIN, R_SENSE);

void setup()
{
  pinMode(EN_PIN, OUTPUT);
  pinMode(DIR_PIN, OUTPUT);
  pinMode(STEP_PIN, OUTPUT);
  digitalWrite(EN_PIN, HIGH); //deactivate driver for now...
  digitalWrite(DIR_PIN, LOW);
  digitalWrite(STEP_PIN, LOW);

  //SPI setup on hardware pins: 10, 11, 12, 13
  pinMode(SS, OUTPUT);
  pinMode(MOSI, OUTPUT);
  pinMode(MISO, INPUT);
  pinMode(SCK, OUTPUT);
  digitalWrite(SS, HIGH);
  digitalWrite(MOSI, LOW);
  digitalWrite(MISO, HIGH);
  digitalWrite(SCK, LOW);

  Serial.begin(9600); //init serial port and set baudrate
  Serial.println("\nRestart ");

  tmc.begin();
  tmc.toff(4); 
  tmc.blank_time(24);
  tmc.en_pwm_mode(true); //Enable StealthChop (quiet driving)
  tmc.pwm_autoscale(true); //Some say this is needed?
  tmc.microsteps(1);  //NB - adding 16 microstep resolution breaks?
  tmc.rms_current(2000); //Motor runs 2.8A peak ≈ keep it round 2 for good measure.

  digitalWrite(EN_PIN, LOW); //Enable motor
}

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

  if ((ms - last_time) > 1000) //DIAGNOSTICS run
  {
    last_time = ms;

    if (tmc.diag0_error()) {
      Serial.println(F("DIAG0 error"));
    }
    if (tmc.ot())         {
      Serial.println(F("Overtemp."));
    }
    if (tmc.otpw())       {
      Serial.println(F("Overtemp. PW"));
    }
    if (tmc.s2ga())       {
      Serial.println(F("Short to Gnd A"));
    }
    if (tmc.s2gb())       {
      Serial.println(F("Short to Gnd B"));
    }
    if (tmc.ola())        {
      Serial.println(F("Open Load A"));
    }
    if (tmc.olb())        {
      Serial.println(F("Open Load B"));
    }
  }

  //make steps
  digitalWrite(STEP_PIN, HIGH)
  delayMicroseconds(10);
  digitalWrite(STEP_PIN, LOW);
  delayMicroseconds(10);
}

Use an acceleration profile to attain the highest speed. Steppers don't start up from zero at such high step rates. The AccelStepper library will work.

Thanks for your reply! So without the acceleration profile, it wont run properly?

I tried with the example code from same library that use Accellstepper - but does not do anything. Weird thing is, when i reupload the previous code (with no accelleration profile) it does not work either. Could i have damaged motor/driver from running it all day without a profile?

This is the code i tried:

#include <TMCStepper.h>

#define EN_PIN           7 // Enable
#define DIR_PIN          8 // Direction
#define STEP_PIN         9 // Step
#define CS_PIN           10 // Chip select
#define SW_MOSI          11 // Software Master Out Slave In (MOSI)
#define SW_MISO          12 // Software Master In Slave Out (MISO)
#define SW_SCK           13 // Software Slave Clock (SCK)
#define R_SENSE 0.075f 

TMC5160Stepper driver = TMC5160Stepper(CS_PIN, R_SENSE);

#include <AccelStepper.h>
AccelStepper stepper = AccelStepper(stepper.DRIVER, STEP_PIN, DIR_PIN);

void setup() {
    SPI.begin();
    Serial.begin(9600);
    while(!Serial);
    Serial.println("Start...");
    pinMode(CS_PIN, OUTPUT);
    digitalWrite(CS_PIN, HIGH);
    driver.begin();             // Initiate pins and registeries
    driver.rms_current(2000);    // Set stepper current to 600mA. The command is the same as command TMC2130.setCurrent(600, 0.11, 0.5);
    driver.en_pwm_mode(1);      // Enable extremely quiet stepping
    driver.pwm_autoscale(1);
    driver.microsteps(1);

    stepper.setMaxSpeed(50);
    stepper.setAcceleration(1000);
    stepper.setEnablePin(EN_PIN);
    stepper.setPinsInverted(false, false, true);
    stepper.enableOutputs();
}

void loop() {
    if (stepper.distanceToGo() == 0) {
        stepper.disableOutputs();
        delay(100);
        stepper.move(100);
        stepper.enableOutputs();
    }
    stepper.run();
}

Isn't that what your tests are telling you?

Your favorite motor vehicle does not start out at top speed either.

Well no. As adding accellstepper (and adjusting accelleration/max speed) previously made it run very slow, around 1-10RPM, or simply lowering the frequency with a timer/delays:

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

  if ((ms - last_time) > 1000) // 1 step pr second
  {
    last_time = ms;


    //make steps
    digitalWrite(STEP_PIN, HIGH);
    delayMicroseconds(10);
    digitalWrite(STEP_PIN, LOW);
    delayMicroseconds(10);
  }


}

...Did not help.

In any case - I cannot get it to run now at all. I might just look into replacing driver/motor to see if this helps. Do you think i might have damaged my favorite motor vehicle? :slight_smile:

You are definitely doing something wrong. You can't hurt a stepper by attempts to run it too fast, or by stalling, etc. On the other hand, steppers aren't the best choice for high RPM operation.

What does "for the usual 10ms, slower even" mean?

Make sure that the motor driver current limit is set correctly (2.8 Amperes per coil, maximum). The average current drawn from the 24V motor power supply will be significantly lower.

I'm not familiar with that motor driver, but in general, it is highly recommended to put a 330-470 uF capacitor directly across the motor driver power input terminals, to avoid high voltage ringing in the motor power supply leads.

I read that the pulse width should be between 5-10ms, and indeed found many examples that practiced this, but I might be wrong? I just noticed, that changing the pulsewidth to 1ms gave a higher speed (around 120RPM)

Current limit is set in the code, changing it between 400mA-2000mA affected the torque when it was running, so I believe it should be limited properly.

Ah, you made some edits i didnt see before posting my previous answer: Regarding high RPM, i will not need this - ideally it should run around 200RPM. I just noticed it was running slower than expected and thought this could point to something else being wrong with the setup - as you have pointed out, something is definitely in the wrong

That is probably nonsense, the sort of thing one picks up from tutorials written by beginners. Most motor drivers step on the rising edge of the STEP pulse, and a 1 us STEP pulse is fine.

For accurate information consult the TMC5160 data sheet. Quite the beast, though!

Thanks, i have consulted it quite a bit! Maybe someone else has a suggestion as to what might be in the wrong :slight_smile:

That suggests a wiring or pin conflict problem. Forum members will want to see a close up, focused photo of the setup. I don't currently have any setup suitable for testing.

Possibly, there is a conflict between the motor driver library and accelstepper library.

Pin diagram is attached in #1… The reason for posting is simply that it stopped working unrelated to touching the physical setup. But indeed, i will try to rebuild it to weed out any stray connections!

If it stopped working for no obvious reason, check all connections for proper soldering, and post a photo of the setup.

Breadboards are for temporary experiments with low power logic circuitry, and don't work with high currents -- the tracks will burn.

Incidentally, motor drivers can be instantly destroyed by disconnecting motors while powered up, or if breadboard tracks burn, loose connections wiggle, etc.

Thanks for the suggestions !

  • I've bought a new driver to outrule if I unplugged anything in a hazard manner.

  • Soldered a perfboard with female headers for all I/O-connections, and soldered Motor-power supply + stepper motor directly to the board. See attached picture for closeup.

Now what happens is that motor makes a few "spasms" on launch, turning a bit (first motor,power, then Arduino is powered). Then it gets stuck in a struggle: it "holds" the motor torqued, so i cant turn it by hand, and makes very small vibrations following the frequency used for stepping in the code (0.1second), without turning. Also, the lab power supply shows a reading ≈600mA in the same rhythm (i do not have an oscilloscope to record it unfortantely).

I tried changing the pulse width and frequency, as well as changing the polarity of one of the coils, as the datasheet is a bit unclear on this.

Code:

#include <TMCStepper.h>

#define EN_PIN    7 //enable
#define DIR_PIN   8 //direction
#define STEP_PIN  9 //step
#define CS_PIN   10 //CS
#define MOSI_PIN 11 //SDI/MOSI
#define MISO_PIN 12 //SDO/MISO
#define SCK_PIN  13 //CLK/SCK 

#define R_SENSE   0.075f //Respective to QHV5160 TMC5160 module

TMC5160Stepper tmc = TMC5160Stepper(CS_PIN, R_SENSE);

void setup()
{
  pinMode(EN_PIN, OUTPUT);
  pinMode(DIR_PIN, OUTPUT);
  pinMode(STEP_PIN, OUTPUT);
  digitalWrite(EN_PIN, HIGH); //deactivate driver for now...
  digitalWrite(DIR_PIN, LOW);
  digitalWrite(STEP_PIN, LOW);

  //SPI setup on hardware pins: 10, 11, 12, 13
  pinMode(SS, OUTPUT);
  pinMode(MOSI, OUTPUT);
  pinMode(MISO, INPUT);
  pinMode(SCK, OUTPUT);
  digitalWrite(SS, HIGH);
  digitalWrite(MOSI, LOW);
  digitalWrite(MISO, HIGH);
  digitalWrite(SCK, LOW);

  Serial.begin(9600); //init serial port and set baudrate
  Serial.println("\nRestart ");

  tmc.begin();
  tmc.toff(4);
  tmc.blank_time(24);
  //tmc.en_pwm_mode(true); //Enable StealthChop (quiet driving)
  //tmc.pwm_autoscale(true); //Some say this is needed?
  tmc.microsteps(1);  //NB - adding 16 microstep resolution breaks?
  tmc.rms_current(2000); //Motor runs 2.8A peak ≈ keep it round 2 for good measure.

  digitalWrite(EN_PIN, LOW); //Enable motor
}

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

  if ((ms - last_time) > 1000) //DIAGNOSTICS run
  {
    last_time = ms;

    if (tmc.diag0_error()) {
      Serial.println(F("DIAG0 error"));
    }
    if (tmc.ot())         {
      Serial.println(F("Overtemp."));
    }
    if (tmc.otpw())       {
      Serial.println(F("Overtemp. PW"));
    }
    if (tmc.s2ga())       {
      Serial.println(F("Short to Gnd A"));
    }
    if (tmc.s2gb())       {
      Serial.println(F("Short to Gnd B"));
    }
    if (tmc.ola())        {
      Serial.println(F("Open Load A"));
    }
    if (tmc.olb())        {
      Serial.println(F("Open Load B"));
    }
  }


  static uint32_t last_time2 = 0;
  uint32_t ms2 = millis();

  if ((ms2 - last_time2) > 100){
    last_time2 = ms2;

    //make steps
    digitalWrite(STEP_PIN, HIGH);
    delayMicroseconds(1);
    digitalWrite(STEP_PIN, LOW);
    delayMicroseconds(1);
  }

}



I don't see a problem with the code, and think it should work.

I wonder about this comment and suggest that you get full steps working first.

  tmc.microsteps(1);  //NB - adding 16 microstep resolution breaks?

Changing the polarity of one of the coils should just change the direction of rotation.

I agree! Or at least, that is the goal- i don’t require microstepping so i set it to 1. many example codes from across libraries (accellstepper, tmcstepper) has 16 as default.

When i try accellstepper, it always behaves as though it has 1600 steps (x8) , even though i set microstepping to 1 - meaning i have to call stepper.move(1600) to get a full rotation. stepper.move(200) only gives an 8th rotation.

I have a (unqualified) hunch this is connected to the speed issue- but i dont know where else i can look for microstep configuration?

There is clearly some confusion between you, your motor driver and the various libraries.

From your last post, it sounds like the stepper is working correctly except that, for some reason, microstepping is enabled. Is it possible that the wrong driver IC type has been selected?

I don't use that type of stepper driver and so can't really advise. Sorry!

Update: I ended up reading through the library on Github, and found that microstepping refers to mres() which expect 0 for full step (:face_with_spiral_eyes:) This definitely helped, as the motor started working instantly, following a simple code:

  digitalWrite(EN_PIN, LOW); //Enable motor

  for (int i = 0; i <= 200; i++) {
    digitalWrite(STEP_PIN, HIGH);
    delayMicroseconds(1);
    digitalWrite(STEP_PIN, LOW);
    delay(stepSpeed);
  }

  digitalWrite(EN_PIN, HIGH); //Disable
  delay(5000);

} //End of void

I experimented with stepSpeed delay ranging 100-10, subsequently providing around 0.5-50 RPM. I ran it stable for a few hours - the torque is quite amazing!

However, it now stopped dead again. Once again, i was only changing the software, making sure to power off the motor before uploading any code. I repeatedly monitored heat in both driver and motor, which never went above anything unreasonable (nothing above comfortably warm to touch on heatsink).

Uploading previous codes, that had worked 30 min earlier did not help. All soldered connections on high current pins are verified with multimeter.

Still hoping someone with TMC5160-experience might have a suggestion for why it acts flakey :pray:

I know it’s a kinda old post.
Curious if you ever figured out your phantom issue with the motor quitting on you? I picked up some Bigtreetech tmc5160’s v1.0 and am running into the same-ish issue that you are where the motor just doesn’t work any longer. Seems to work just fine and then I change the code, re-upload and then I assume I made a bad change. I then revert the change and get nothing. I’m using teensy 4.1 to drive the nema 17 400 step motors. The only thing we have in common is the 5160 and SPI interface. Reading through the datasheet is pretty rough and finding real examples is almost non-existent. I didn’t put caps on the motors leads and hoping I didn’t mess up the driver with back fed current. I bought 4 of each (drivers/motors) and will try your code with the drivers I have and the teensy 4.1 and the esp32. I’ll be adding the caps too and if I figure out why the sudden broken state, I’ll be sure to update here.

Thanks for sharing your experience!

No - im sorry to say I gave up. Eventually I dropped the TMC5160, and redesigned the mechanical part to require less torque - and thereby settled for the TMC2209 which worked perfectly.

My last lead from talking to a machinist about it, is that the TMC5160 potentially could be a bit more picky about the routine for shutting it down. From that perspective, I assume I damaged them as I cannot get any life from them with or without SPI. But as you say - the documentation is a bit out of DIY league, so i wouldn't know for sure.

Good luck - please share your results! :slight_smile: