teemuatlut / TMCStepper

MIT License
515 stars 201 forks source link

TMC2160 support #234

Open owardC opened 2 years ago

owardC commented 2 years ago

I am using TMC2160 to drive a stepper motor with an esp32. When I try to compile the code I get an error:

Arduino: 1.8.19 (Windows Store 1.8.57.0) (Windows 10), Board: "ESP32 Dev Module, Disabled, Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS), 240MHz (WiFi/BT), QIO, 80MHz, 4MB (32Mb), 921600, None"

C:\Users\oward\Documents\Arduino\stepper_driver\stepper_driver.ino: In function 'void loop()':

stepper_driver:60:24: error: no matching function for call to 'TMC2160Stepper::refr_dir(int)'

   driver.refr_dir(0);
                    ^

In file included from C:\Users\oward\Documents\Arduino\stepper_driver\stepper_driver.ino:6:0:

C:\Users\oward\Documents\Arduino\libraries\TMCStepper\src/TMCStepper.h:396:11: note: candidate: bool TMC2160Stepper::refr_dir()

bool refr_dir(); ^

C:\Users\oward\Documents\Arduino\libraries\TMCStepper\src/TMCStepper.h:396:11: note: candidate expects 0 arguments, 1 provided

stepper_driver:63:24: error: no matching function for call to 'TMC2160Stepper::refr_dir(int)'

   driver.refr_dir(1);
                    ^

In file included from C:\Users\oward\Documents\Arduino\stepper_driver\stepper_driver.ino:6:0:

C:\Users\oward\Documents\Arduino\libraries\TMCStepper\src/TMCStepper.h:396:11: note: candidate: bool TMC2160Stepper::refr_dir()

bool refr_dir(); ^

C:\Users\oward\Documents\Arduino\libraries\TMCStepper\src/TMCStepper.h:396:11: note: candidate expects 0 arguments, 1 provided

exit status 1

no matching function for call to 'TMC2160Stepper::refr_dir(int)'

This report would have more information with "Show verbose output during compilation" option enabled in File -> Preferences."

I am trying to use "refr_dir()" instead of "shaft()" but the library can't find "ref_dir()" with respect to TMC2160

SobhanAbedi commented 2 years ago

Hi. There is no refr_dir(bool) function defined in any of the libraries. The function that has been implemented is refr_dir() which returns a Boolean. Based on 2160 datasheet returned value indicates the state of DIR pin. and this is a read-only register which means there is no way to write to it. And there are 2 good reasons for it to be read-only.

  1. You already have a dir pin which defines the value of this register. if you had two ways to set this value, there would have been conflicting situations that needed fixing.
  2. SPI is nowhere low latency enough to be used for stepping or setting the direction. This is why dedicated step/dir/en pins are still being used and they don't get disabled in SPI mode.

Register table form datasheet: image

teemuatlut commented 2 years ago

Looks like the 2160 IOIN calls need to be renamed and they were probably copied over from one of the other models. You can still use .refr_dir() to query the state of the input pin as the bit position is the same and you can use .shaft(bool) to invert direction pin logic.

owardC commented 2 years ago

Thanks for the quick response. I went back and decided to use the spi example file in arduino and edit the code to match my driver type using .shaft(bool) to change the direction of the motor but I can't get the stepper motor to drive with the TMC2160 using SPI. here is my code: `#include

define EN_PIN 34 // Enable

define DIR_PIN 39 // Direction

define STEP_PIN 36 // Step

define CS_PIN 5 // Chip select

define SW_MOSI 23 // Software Master Out Slave In (MOSI)

define SW_MISO 19 // Software Master In Slave Out (MISO)

define SW_SCK 18 // Software Slave Clock (SCK)

define led 2 // led

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 TMC2160Stepper driver = TMC2160Stepper(CS_PIN, R_SENSE, SW_MOSI, SW_MISO, SW_SCK); // Software SPI

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(led, OUTPUT); 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(led, HIGH); delay(1000); 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; digitalWrite(led, LOW); delay(1000); } }` Can you guys upload an TMC2160 driver example using SPI or tell me what I am doing wrong in my code? I check the wiring and power of my circuit and everything seems to check out.

teemuatlut commented 2 years ago

First make sure you have a working connection to the driver by reading the .version() value or by reading the full .IOIN() register. Then make sure off time (.toff()) is not zero and that the enable line is pulled low (.encb_dcen_cfg4()) and that the .irun() setting is not zero.

owardC commented 2 years ago

Here is my latest code to check .version(), .toff(), .encb_dcen_cfg4(), and irun() everything seems to check out except .encb_dcen_cfg4(). I can't seem to change the en state to nonzero. I have DRV_ENN pin on TMC2160 connected to pin 27 on esp32. `#include

define EN_PIN 27 // Enable

define DIR_PIN 39 // Direction

define STEP_PIN 36 // Step

define CS_PIN 5 // Chip select

define SW_MOSI 23 // Software Master Out Slave In (MOSI)

define SW_MISO 19 // Software Master In Slave Out (MISO)

define SW_SCK 18 // Software Slave Clock (SCK)

define led 2 // led

define R_SENSE 0.075f // Match to your driver

// Select your stepper driver type TMC2160Stepper driver = TMC2160Stepper(CS_PIN, R_SENSE); // hardware SPI bool dir = true;

void setup() { Serial.begin(9600); while (!Serial); Serial.println("Start...");

pinMode(led, OUTPUT); pinMode(EN_PIN, OUTPUT); pinMode(STEP_PIN, OUTPUT); digitalWrite(EN_PIN, LOW);

SPI.begin(); 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(true); // Enable extremely quiet stepping driver.toff(5); driver.pwm_autoscale(true); // Needed for stealthChop Serial.print("DRV_STATUS=0b"); Serial.println(driver.DRV_STATUS(), BIN); } void loop() { int ver = driver.version(); digitalWrite(led, HIGH); delay(1000); Serial.print("version: " ); Serial.println(ver); 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()); 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; digitalWrite(led, LOW); delay(1000); } } ` Here is the output to my code. Also I am using hardware SPI pins on the esp32.

16:45:58.970 -> version: 48 16:45:58.970 -> run status: 11 16:45:58.970 -> run en stat: 0 16:45:59.017 -> toff: 5 16:45:59.017 -> Dir -> 0 16:46:00.961 -> version: 48 16:46:00.961 -> run status: 11 16:46:00.961 -> run en stat: 0 16:46:01.007 -> toff: 5 16:46:01.954 -> version: 48 16:46:01.954 -> run status: 11 16:46:02.001 -> run en stat: 0 16:46:02.001 -> toff: 5 16:46:02.001 -> Dir -> 1

SobhanAbedi commented 2 years ago

The .encb_dcen_cfg4() should be low (should be 0). I think the problem is with your loop function. You have a 1 second delay before each pulse generation. That means you do 1 micro-step roughly every 1 second. With a 16 micro-stepping, you would be doing 1 step every 16 seconds and (with a 200 step/rotation stepper) 1 full rotation every 53.333 minutes!!!