teemuatlut / TMCStepper

MIT License
479 stars 188 forks source link

Cant make TMC5160 from BTT to work #268

Open Phil1988 opened 1 year ago

Phil1988 commented 1 year ago

Hello,

I am trying to make the TMC5160 vom BTT to work. I am having the v1.2 and 1.3v of these stepper drivers. Both do not have any solder pads or jumpers to change their used mode (as far as I know).

As microcontroller boards I used a Raspberry Pi Pico RP2040, a Arduino Micro and a currently an Arduino Mega.

For compiling I am using the Arduino IDE 2.0.4.

I am using the master branch of this library.

Vm is 12V, VIO is connected to the according logic high level of the microcontroller and I guess SPI is working as I could set and read the driver.rms_current.

Currently even the simple Software_SPI.ino example does not spin any of my (8 tested) Nema17 stepper motors. I am currenty using it with an Arduino Mega, only having changed the pins and driver part:

/**
 * Author Teemu Mäntykallio
 * Initializes the library and runs the stepper motor.
 */

#include <TMCStepper.h>

#define EN_PIN 6    // Enable
#define DIR_PIN 7   // Direction
#define STEP_PIN 8  // Step
#define CS_PIN 53   // Chip select
#define SW_MOSI 51  // Software Master Out Slave In (MOSI)
#define SW_MISO 50  // Software Master In Slave Out (MISO)
#define SW_SCK 52   // Software Slave Clock (SCK)

#define R_SENSE 0.075f  // 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

// Select your stepper driver type
//TMC2130Stepper driver = TMC2130Stepper(CS_PIN, R_SENSE); // Hardware SPI
//TMC2130Stepper driver = TMC2130Stepper(CS_PIN, R_SENSE, SW_MOSI, SW_MISO, SW_SCK); // Software SPI
//TMC2660Stepper driver = TMC2660Stepper(CS_PIN, R_SENSE); // Hardware SPI
//TMC2660Stepper driver = TMC2660Stepper(CS_PIN, R_SENSE, SW_MOSI, SW_MISO, SW_SCK);
//TMC5160Stepper driver = TMC5160Stepper(CS_PIN, R_SENSE);
TMC5160Stepper driver = TMC5160Stepper(CS_PIN, R_SENSE, SW_MOSI, SW_MISO, SW_SCK);

bool dir = true;

void setup() {
    Serial.begin(9600);
    while(!Serial);
    Serial.println("Start...");
    driver.begin();             // Initiate pins and registeries
    driver.rms_current(600);    // 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

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

    Serial.print("DRV_STATUS=0b");
    Serial.println(driver.DRV_STATUS(), BIN);
}

void loop() {
    digitalWrite(STEP_PIN, HIGH);
    delayMicroseconds(10);
    digitalWrite(STEP_PIN, LOW);
    delayMicroseconds(10);
    uint32_t ms = millis();
    static uint32_t last_time = 0;
    if ((ms - last_time) > 2000) {
        if (dir) {
            Serial.println("Dir -> 0");
            driver.shaft(0);
        } else {
            Serial.println("Dir -> 1");
            driver.shaft(1);
        }
        dir = !dir;
        last_time = ms;
    }
}

So even as I use the hardware SPI pins, I am declaring it as SW pins to make sure its assigned correctly. On startup I get:

DRV_STATUS=0b10000000000001010100000000000000
Dir -> 0
Dir -> 1
Dir -> 0
[...]

Ineresstingly, the DIR_PIN does not logically change every 2 seconds. Instead I can see an about 560mV 2,5kHz pulse. grafik

The motor does not spin. The driver gets moderately warm, but n signal at all at the A1, A2, B1 and B2 outputs.

I changet the dir pin output by declaring

  pinMode(DIR_PIN, OUTPUT);
  digitalWrite(DIR_PIN, LOW);

in the setup() and changing the loop to this.

void loop() {
  digitalWrite(STEP_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(STEP_PIN, LOW);
  delayMicroseconds(10);
  uint32_t ms = millis();
  static uint32_t last_time = 0;
  if ((ms - last_time) > 2000) {
    if (dir) {
      Serial.println("Dir -> 0");
      //driver.shaft(0);
      digitalWrite(DIR_PIN, LOW);
    } else {
      Serial.println("Dir -> 1");
      //driver.shaft(1);
      digitalWrite(DIR_PIN, HIGH);
    }
    dir = !dir;
    last_time = ms;
  }
}

This resulted in the expected result in 5V logic level signals, changing every 2000ms; grafik

I hope you can help me and tell me, why the motor is not running.

In the future I want to use SPI communication for setting motor current and microstepping later on. I am having the issue, that code posted here in github in the past (for TMC5160 drivers and SPI) dont work work for me, when I try to get for example the current mode (sd_mode or spi_mode).

I cant read the ioin registers

TMC5160Stepper::IOIN_t ioin{ driver.IOIN() };
    if (ioin.version == 0xFF || ioin.version == 0) {
        Serial.println("Driver communication error");
        while(true);
    }
    Serial.print("Driver firmware version: ");
    Serial.println(ioin.version);
    if (ioin.sd_mode) {
        Serial.println("Driver is hardware configured for Step & Dir mode");
        while(true);
    }
    if (ioin.drv_enn) {
        Serial.println("Driver is not hardware enabled");
        while(true);
    }

gives me an Compilation error: 'IOIN_t' is not a member of 'TMC5160Stepper'

I also found this comment https://github.com/teemuatlut/TMCStepper/issues/157#issuecomment-721960004 where you use TMC5160_n. Usind exactly your code results in Compilation error: no matching function for call to 'TMC5160Stepper::TMC5160Stepper(SPIClass&, const uint16_t&, const float&)' for me.

What am I doing wrong or what should I change/test?

daniel-frenkel commented 1 year ago

Do not buy the SilentStepStick TMC5160. It is designed for a 3D printer and not in standalone mode. I recommend buying the TMC5160-BOB made by Trinamic which exposes the pins you need.

https://www.digikey.com/en/products/detail/trinamic-motion-control-gmbh/TMC5160-BOB/8440397

HOWEVER, the TMC5160 is NOT A STEPPER MOTOR DRIVER. It is a MOTION CONTROLLER, which can be run as a stepper driver if you desolder one of the pins.

Since you are trying to use the STEP and DIR pin, it looks like you want a stepper driver. In this case, I recommend using the TMC2160 for that.

https://www.digikey.com/en/products/detail/trinamic-motion-control-gmbh/TMC2160-BOB/9645274

The motion controller has a built in motion generator, and is meant to be controlled by SPI and not Step/Dir

Phil1988 commented 1 year ago

Thank you @daniel-frenkel for jumping in and your comment.

The reason I went down the road to Step/Dir is, that SPI doesnt work for me. This was as you may say a "check everything that you can think of and see were the problems starts".

I only want to use a microcontroller (RP2040) to setup the TCM5160 according to the motor and use AccelStepper in a later stage to actually run the motor.

So far none of the SPI examples or snippets did work. Even not the ones that were posted even by @teemuatlut here: https://github.com/teemuatlut/TMCStepper/issues/157#issuecomment-721960004 (just as an ecample)

I think that this library was changed since, so that the functions that have been used are not functional any more. At least I am getting compiler errors of all kinds.

So do you know of a working code snippet that is functional with SPI and the TMC5160 at the current state? I need a starting point were at least "something" is working and do my way from there.

Microcontrollers I have for testing: Arduino Uno, Nano, Leonardo, Mega ESP8266, ESP32 RP2040

daniel-frenkel commented 1 year ago

Do you have a schematic of your board? I only see a BTT 5160 schematic of version 1.0 on Github.

If you look at the 5160 datasheet on page 5, you'll notice that you are trying to use Mode 2, which means that you have to tie SD_MODE pin HIGH.

https://www.trinamic.com/fileadmin/assets/Products/ICs_Documents/TMC5160A_Datasheet_Rev1.14.pdf

You have to make sure the SD_MODE pin is connected to 3.3V or 5V. Are you sure that's the case?

daniel-frenkel commented 1 year ago

It's been a while since I tested the 5160 but I plan to do test it again this week. This code should work

Just be sure your SD_MODE pin is tied HIGH.

And to make this move, just do digitalWrite high and low like you were doing in your code. You don't want to add the AccelStepper library until everything works here.

These pins are for my ESP32 so be sure to update them.

#define STEP_PIN               15
#define DIR_PIN                  14
#define ENABLE_PIN          4

#define R_SENSE                 0.10f      // R_SENSE for current calc.  Match to board
#define SW_MOSI                9
#define SW_MISO                2
#define SW_SCK                  10
#define CS_PIN                    5

TMC5160Stepper driver = TMC5160Stepper(CS_PIN, R_SENSE, SW_MOSI, SW_MISO, SW_SCK);

void setup () {
  pinMode(ENABLE_PIN, OUTPUT);
  pinMode(DIR_PIN, OUTPUT);
  pinMode(STEP_PIN, OUTPUT);

  driver.begin();
  driver.diag0_stall(true);
  driver.rms_current(800); //800 mA current
  //driver.sgt(stall);
  driver.microsteps(64);
  //driver.TCOOLTHRS(500);  // Only for stallgaurd
  driver.toff(4);
  driver.blank_time(24);
  driver.TPWMTHRS(0);
  driver.semin(0);
  driver.en_pwm_mode(1); // Enable extremely quiet stepping
  driver.pwm_autoscale(1);
Phil1988 commented 1 year ago

Hi @daniel-frenkel ,

The BTT TMC5160 v1.2 and up (what I own) dont have the SD_MODE pin anymore as far as I know. They are always in the SPI communication mode.

I will test your snippet the next days. How do you drive the motor from there?

Simply use AccelStepper library and let it run or do you suggest something different?

daniel-frenkel commented 1 year ago

@Phil1988

I prefer the FastAccelStepper library, but it's limited to certain microcontrollers whereas AccelStepper works on everything. But FastAccelStepper allows you to run much faster and tries to use dedicated hardware if your MC has it.

I'm working on a Udemy course that will be done this week and I'll send you the link when it's done. So far I have about 80 slides that will turn you into a Trinamic expert

Phil1988 commented 1 year ago

@daniel-frenkel

I will have a look at FastAccelStepper then.

Interessting is, that you used 0.10f as R_SENSE, while 0.075f seems more common for these steppers. Do you use ENABLE_PIN later or only define it?

Currently I have a basic code, but the motor is not moving (also not turned on, because it has no holding torque) but the driver gets pretty warm to abou 60°C

This is my code:

// #include <Arduino.h>
#include <SPI.h>
#include <TMCStepper.h>

//SPI
#define EN_PIN 20    // Enable
#define DIR_PIN 14   // Direction
#define STEP_PIN 15  // Step
#define CS_PIN 17    // Chip select (CSN)
#define SW_MOSI 19   // Software Master Out Slave In (MOSI)(SDI)
#define SW_MISO 16   // Software Master In Slave Out (MISO) (SDO)
#define SW_SCK 18    // Software Slave Clock (SCK)
#define R_SENSE 0.075f

TMC5160Stepper driver(CS_PIN, R_SENSE, SW_MOSI, SW_MISO, SW_SCK);

void setup() {
  Serial.begin(9600);
    delay(6000);
  Serial.println("Start setup");

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

  pinMode(CS_PIN, OUTPUT);
  digitalWrite(CS_PIN, HIGH);

    // Setup hardware SPI
  SPI.begin();

  // Initialise driver
  driver.begin();           //  SPI: Init CS pins and possible SW SPI pins

  driver.toff(3);           // Enables driver in software
  driver.rms_current(500);  // Set motor RMS current
  driver.microsteps(4);
  driver.en_pwm_mode(true);  // Toggle stealthChop on TMC2130/2160/5130/5160, extremely quiet stepping (stealthChop)

  Serial.print("MOSI: ");
  Serial.println(MOSI);
  Serial.print("MISO: ");
  Serial.println(MISO);
  Serial.print("SCK: ");
  Serial.println(SCK);
  Serial.print("SS: ");
  Serial.println(SS); 

  Serial.print("DRV_STATUS=0b");
  Serial.println(driver.DRV_STATUS(), BIN);

  Serial.print("version: " );
  Serial.println(driver.version());
  Serial.print("run status: " );
  Serial.println(driver.irun());
  Serial.print("run en stat: " );
  Serial.println(driver.encb_dcen_cfg4());
  Serial.print("toff: " );
  Serial.println(driver.toff());

  //TMC5160Stepper::IOIN_t ioin{ driver.IOIN() };

  delay(1000);
  Serial.println("Setup finished");
}

void loop() {
  delay(1000);
  Serial.println("Test");

for (int i=0; i < 100; i++)
{
  digitalWrite(STEP_PIN, HIGH);
  delay(100);
  digitalWrite(STEP_PIN, LOW);
  delay(100);
  //delayMicroseconds(10);
}
}

It returns:

MOSI: 19
MISO: 16
SCK: 18
SS: 17
DRV_STATUS=0b10000100000001000100000000000000
version: 48
run status: 9
run en stat: 0
toff: 3

I dont know if that is valid. Do you maybe have a basic code where the motor is simply turning a bit so I can confirm my driver(hardware) is OK?

daniel-frenkel commented 1 year ago

@Phil1988

Give this a try, I just tested it.

https://github.com/daniel-frenkel/udemy/blob/main/TMC5160/Main_Demo/Main_Demo.ino

And the R_SENSE value just depends on the resistors that are placed on your board, I have a BTT board but a different one