teemuatlut / TMCStepper

MIT License
514 stars 202 forks source link

TMC5161 StallGuard issue #148

Open totum opened 4 years ago

totum commented 4 years ago

First of, thanks for the amazing work with this library! I'm trying to get StallGuard to work with a TMC5161 from BGT (this one: https://raw.githubusercontent.com/bigtreetech/BIGTREETECH-TMC5161-V1.0/master/TMC5161%20v1.0%20mamual.pdf), and running into issues. I use an Arduino mega 2560 as my controller.

I use the StallGuard example, adjusted for my pins, and it compiles fine, motor runs, and I can control speed with +/-. However, I get constant values in the serial readout: 0 0 32 when the motor is running. The last value (32) is a different but still constant value when I change the RMS current in the script. When I turn off motor power supply, the values change to something like 0 10XY 10ZW. So SPI seems to work. I've triple-checked my setup, and can find no mistakes, so I'm wondering if StallGuard and the TMC5161 board that I use, are simply not supported by v0.71 of the library?

Issue #143 mentions a 5160 issue with the DRV_Status, which prompted me to try the 1.0 branch. Alas, I get the following error when I compile the Simple example: "TMC5161Stepper {aka class TMC5160Stepper}' has no member named 'begin'; did you mean 'semin'? driver.begin(); // SPI: Init CS pins and possible SW SPI pins"

teemuatlut commented 4 years ago

Read and print out the IOIN register to confirm your communication is working properly. You can either use .IOIN() or .version().

totum commented 4 years ago

Thanks for your quick reply. I solved the issue this morning, and got it working (at least the SG value is responsive) v0.71. My mistake was using hardware SPI, setting up the driver using: TMC5161Stepper driver(CS_PIN, R_SENSE, SW_MOSI, SW_MISO, SW_SCK);

Changing to SW SPI, using: TMC5161Stepper driver(CS_PIN, R_SENSE);

Now, testing and getting it dialled in. Hooray :)

For reference, using version() and ioin(), I get the following: Software SPI:

With hardware SPI:

Strangely, I cannot get the motor to run using HW SPI today, like it did last week (and I don't understand that it could, considering that communication didn't work...). But, as it works with SW SPI now, I guess I don't care so much :)

teemuatlut commented 4 years ago

Good to hear you got it working. Version should never be 0 or 255 (0xFF) and both indicate a communication issue. If by "motor off" you mean that it doesn't have VMOT voltage then that would explain the value. The drivers need to have the high voltage enabled for comms to work properly.


From: totum notifications@github.com Sent: Monday, September 7, 2020 12:52:26 PM To: teemuatlut/TMCStepper TMCStepper@noreply.github.com Cc: teemuatlut teemu.mantykallio@live.fi; Comment comment@noreply.github.com Subject: Re: [teemuatlut/TMCStepper] TMC5161 StallGuard issue (#148)

Thanks for your quick reply. I solved the issue this morning, and got it working (at least the SG value is responsive) v0.71. My mistake was using hardware SPI, setting up the driver using: TMC5161Stepper driver(CS_PIN, R_SENSE, SW_MOSI, SW_MISO, SW_SCK);

Changing to SW SPI, using: TMC5161Stepper driver(CS_PIN, R_SENSE);

Now, testing and getting it dialled in. Hooray :)

For reference, using version() and ioin(), I get the following: Software SPI:

With hardware SPI:

Strangely, I cannot get the motor to run using HW SPI today, like it did last week (and I don't understand that it could, considering that communication didn't work...). But, as it works with SW SPI now, I guess I don't care so much :)

— You are receiving this because you commented. Reply to this email directly, view it on GitHubhttps://github.com/teemuatlut/TMCStepper/issues/148#issuecomment-688211587, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AB3HF7UTKMWFXRT5DOB4G53SESUNVANCNFSM4QYPEAYQ.

johnsmakar commented 4 years ago

@totum Do you mind sharing your code? I am not sure if I am setting up my driver completely correct. Mine connects but the motor does not spin

totum commented 4 years ago

Hi @johnsmakar, definitely. Apologies for the slow reply. It's more or less the StallGuard example, adjusted for pins and the TMC5161. What driver are you using?

#include <TMCStepper.h>

#define MAX_SPEED        40 // In timer value
#define MIN_SPEED      1000

#define STALL_VALUE      10 // [-64..63]

#define EN_PIN           29 // Enable
#define DIR_PIN          23 // Direction
#define STEP_PIN         22 // Step
#define CS_PIN           31 // 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.060f
                      // SilentStepStick series use 0.11
                      // UltiMachine Einsy and Archim2 boards use 0.2
                      // Panucatt BSD2660 uses 0.1
                      // Watterott TMC5160 uses 0.075
                      // TMC5161 from BTT uses 0.060 according to docs

// Select your stepper driver type
TMC5161Stepper driver(CS_PIN, R_SENSE); // Software SPI

using namespace TMC2130_n;  // Associate namespace

// Using direct register manipulation can reach faster stepping times
#define STEP_PORT     PORTF // Match with STEP_PIN
#define STEP_BIT_POS      0 // Match with STEP_PIN

ISR(TIMER1_COMPA_vect){
  //STEP_PORT ^= 1 << STEP_BIT_POS;
  digitalWrite(STEP_PIN, !digitalRead(STEP_PIN));
}

void setup() {
  SPI.begin();
  Serial.begin(250000);         // Init serial port and set baudrate
  while(!Serial);               // Wait for serial port to connect
  Serial.println("\nStart...");

  pinMode(EN_PIN, OUTPUT);
  pinMode(STEP_PIN, OUTPUT);
  pinMode(CS_PIN, OUTPUT);
  pinMode(DIR_PIN, OUTPUT);
  pinMode(MISO, INPUT_PULLUP);
  digitalWrite(EN_PIN, LOW);

  driver.begin();
  driver.toff(4);
  driver.blank_time(24);
  driver.rms_current(800); // mA
  driver.microsteps(16);
  driver.TCOOLTHRS(0xFFFFF); // 20bit max
  driver.THIGH(0);
  driver.semin(5);
  driver.semax(2);
  driver.sedn(0b01);
  driver.sgt(STALL_VALUE);

  // Set stepper interrupt
  {
    cli();//stop interrupts
    TCCR1A = 0;// set entire TCCR1A register to 0
    TCCR1B = 0;// same for TCCR1B
    TCNT1  = 0;//initialize counter value to 0
    OCR1A = 256;// = (16*10^6) / (1*1024) - 1 (must be <65536)
    // turn on CTC mode
    TCCR1B |= (1 << WGM12);
    // Set CS11 bits for 8 prescaler
    TCCR1B |= (1 << CS11);// | (1 << CS10);
    // enable timer compare interrupt
    TIMSK1 |= (1 << OCIE1A);
    sei();//allow interrupts
  }
}

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

  while(Serial.available() > 0) {
    int8_t read_byte = Serial.read();
    #ifdef USING_TMC2660
      if (read_byte == '0')      { TIMSK1 &= ~(1 << OCIE1A); driver.toff(0); }
      else if (read_byte == '1') { TIMSK1 |=  (1 << OCIE1A); driver.toff(driver.savedToff()); }
    #else
      if (read_byte == '0')      { TIMSK1 &= ~(1 << OCIE1A); digitalWrite( EN_PIN, HIGH ); }
      else if (read_byte == '1') { TIMSK1 |=  (1 << OCIE1A); digitalWrite( EN_PIN,  LOW ); }
    #endif
    else if (read_byte == '+') { if (OCR1A > MAX_SPEED) OCR1A -= 20; }
    else if (read_byte == '-') { if (OCR1A < MIN_SPEED) OCR1A += 20; }
  }

  if((ms-last_time) > 100) { //run every 0.1s
    last_time = ms;

    DRV_STATUS_t drv_status{0};
    drv_status.sr = driver.DRV_STATUS();

    Serial.print("0 ");
    Serial.print(drv_status.sg_result, DEC);                  // StallGuard value
    Serial.print(" ");
    Serial.println(driver.cs2rms(drv_status.cs_actual), DEC); // CoolStep
  }
}
johnsmakar commented 4 years ago

@totum Thanks so much!

I am using the TMC5161 from BTT as well but with an ESP-32 NodeMCU.

Because the ESP 32 does not use register manipulation for interrupts, do you know if the the STEP_PIN is still required? and do you happen to know which function changes the speed? (like for the 2209 drivers, .VACTUAL(speed) is used)

johnsmakar commented 4 years ago

This is what I have, and I checked that everything is wired as it should be, the motor is hissing as if it was running. I know the motor and driver work because i ran the Simple example...

`

include

define MAX_SPEED 40 // In timer value

define MIN_SPEED 1000

define STALL_VALUE 10 // [-64..63]

define EN_PIN 14 // Enable

//#define DIR_PIN 23 // Direction //#define STEP_PIN 22 // Step

define CS_PIN SS // Chip select

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

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

define SW_SCK SCK // Software Slave Clock (SCK)

define R_SENSE 0.060f

                  // SilentStepStick series use 0.11
                  // UltiMachine Einsy and Archim2 boards use 0.2
                  // Panucatt BSD2660 uses 0.1
                  // Watterott TMC5160 uses 0.075
                  // TMC5161 from BTT uses 0.060 according to docs

// Select your stepper driver type TMC5161Stepper driver(CS_PIN, R_SENSE); // Software SPI

using namespace TMC2130_n; // Associate namespace

int32_t speed = 1000;

void setup() { SPI.begin(); Serial.begin(250000); // Init serial port and set baudrate while(!Serial); // Wait for serial port to connect Serial.println("\nStart...");

pinMode(EN_PIN, OUTPUT); //pinMode(STEP_PIN, OUTPUT); pinMode(CS_PIN, OUTPUT); //pinMode(DIR_PIN, OUTPUT); pinMode(MISO, INPUT_PULLUP); digitalWrite(EN_PIN, LOW);

driver.begin(); driver.toff(4); driver.blank_time(24); driver.rms_current(800); // mA driver.microsteps(16); driver.TCOOLTHRS(0xFFFFF); // 20bit max driver.THIGH(0); driver.semin(5); driver.semax(2); driver.sedn(0b01); driver.sgt(STALL_VALUE);

}

void loop() { static uint32_t last_time = 0;

uint32_t ms = millis();

while (Serial.available() > 0) { int8_t read_byte = Serial.read();

if (read_byte == '0') {
  Serial.print("Motor ");

  if (driver.toff() == 0) {
    Serial.print("already ");
  }

  Serial.println("disabled.");
  driver.toff(0);
} else if (read_byte == '1') {
  Serial.print("Motor ");

  if (driver.toff() != 0) {
    Serial.print("already ");
  }

  Serial.println("enabled.");
  driver.toff(4);
} else if (read_byte == '+') {
  speed += 100;

  if (speed == 0) {
    Serial.println("Hold motor.");
  } else {
    Serial.println("Increase speed.");
  }

  driver.setSPISpeed(speed);
} else if (read_byte == '-') {
  speed -= 100;

  if (speed == 0) {
    Serial.println("Hold motor.");
  } else {
    Serial.println("Decrease speed.");
  }

  driver.setSPISpeed(speed);
}

}

if((ms-last_time) > 100) { //run every 0.1s last_time = ms;

DRV_STATUS_t drv_status{0};
drv_status.sr = driver.DRV_STATUS();

Serial.print("0 ");
Serial.print(drv_status.sg_result, DEC);                  // StallGuard value
Serial.print(" ");
Serial.println(driver.cs2rms(drv_status.cs_actual), DEC); // CoolStep

} } `

johnsmakar commented 4 years ago

@totum Hey, just pinging you. Not sure if you saw my last comment but would appreciate input, if you have any :)

totum commented 4 years ago

Hi @johnsmakar, I haven't tried it with the ESP32. What do you mean it does not have direct register manipulation? (I don't have much experience with ESP32 units).

Again, no expert on this chip nor library, but from the Stallguard example, speed is changed calling:

else if (read_byte == '+') { if (OCR1A > MAX_SPEED) OCR1A -= 20; }
else if (read_byte == '-') { if (OCR1A < MIN_SPEED) OCR1A += 20; }

Did you try calling .IOIN() or .version() to confirm that comms are working, like teemuatlut suggested to me? I called it in the loop, like this: driver.IOIN(); driver.version();

johnsmakar commented 4 years ago

Thanks for the reply @totum , the timers on the ESP32 seem to only use hardware interrupts tied to GPIO pins. As far as I can tell, we don't have any way to manipulate timers using registers like OCR1A or TCCR1A and such like the ATMega boards.

@teemuatlut could you help point me in the right direction?

No Power: IOIN: 4294967295 Version: 255

Software SPI: Motor Powered: IOIN: 805306432 Version: 48 Hardware SPI: Motor Powered: IOIN: 0 Version: 0

The motor does not spin regardless of which state I set it too (On/Off)