teemuatlut / TMCStepper

MIT License
501 stars 196 forks source link

Help with rapidly fluctuating intermittent StallGuard values #293

Open Okscientist opened 8 months ago

Okscientist commented 8 months ago

Hello all,

Although I got some StallGuard values output, the results are hard to interpret. I have the TMC2209 connected to an Arduino Mega via UART. I have written a script where the motor accelerates when a button is pressed.

As soon as the motor is up to speed, the StallGuard values are displayed in the Serial Monitor and Serial Plotter. However, the StallGuard values rise and fall rapidly and periodically. By averaging the StallGuard readings, I get some useful values (that decrease when torque is applied to the motor shaft), but it is really hard to tell how StallGuard is behaving. For each speed, current setting, etc., the StallGuard values are very different.

Furthermore, very high loads on the motor shaft are required to see the slightest change in the StallGuard value.

Would anyone be able to give me some advice? Do I oversee something? I have tried so many things already, but nothing seems to make it smoother or better...

A screenshot of the StallGuard values (in green) and the average of the last 20 StallGuard values (in yellow) in the Serial monitor. image

My Arduino script:

// S C 4443527

#include <Arduino.h>
#include <FastAccelStepper.h>
#include <HardwareSerial.h>
#include <TMCStepper.h>
#include <SPI.h>
#include <AverageValue.h>

// Number of values to calculate with. Prevents memory problems
const long MAX_VALUES_NUM = 20;
AverageValue<long> averageValue(MAX_VALUES_NUM);

#define ENABLE_PIN 4
#define RXD2 15
#define TXD2 14
#define STALLGUARD 18        //Be sure to only use interupt pins!!
#define R_SENSE 0.11f        // R_SENSE for current calc.
#define DRIVER_ADDRESS 0b00  // TMC2209 Driver address according to MS1 and MS2
#define startPin 25

//Change these values to get different results
int set_velocity = 16000;
int set_current = 800;
int set_stall = 10;    //Do not set the value too high or the TMC will not detect it. Start low and work your way up
int set_tcools = 10;  //5000 Velocity = 800 TSTEP
int i = 0;
int startState;
int count = 0;

int motor_microsteps = 32;
bool run_motor = false;
bool stalled_motor = false;

/* We communicate with the TMC2209 over UART.
 * But the Arduino UNO only has one Serial port which is connected to the Serial Monitor
 * We have to use software serial on the UNO, and can use hardware serial on the ESP32 or Mega 2560
 */
#define SERIAL_PORT_2 Serial3

TMC2209Stepper driver(&SERIAL_PORT_2, R_SENSE, DRIVER_ADDRESS);

void stalled_position() {
  stalled_motor = true;
}

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

  pinMode(ENABLE_PIN, OUTPUT);
  pinMode(STALLGUARD, INPUT);
  pinMode(startPin, INPUT_PULLUP);

  driver.begin();                       // Start all the UART communications functions behind the scenes
  driver.toff(4);                       //For operation with StealthChop, this parameter is not used, but it is required to enable the motor. In case of operation with StealthChop only, any setting is OK
  driver.blank_time(24);                //Recommended blank time select value
  driver.I_scale_analog(true);          // Disbaled to use the extrenal current sense resistors
  driver.internal_Rsense(false);        // Use the external Current Sense Resistors. Do not use the internal resistor as it can't handle high current.
  driver.mstep_reg_select(true);        //Microstep resolution selected by MSTEP register and NOT from the legacy pins.
  driver.microsteps(motor_microsteps);  //Set the number of microsteps. Due to the "MicroPlyer" feature, all steps get converterd to 256 microsteps automatically. However, setting a higher step count allows you to more accurately more the motor exactly where you want.
  driver.TPWMTHRS(0);                   //DisableStealthChop PWM mode/ Page 25 of datasheet
  driver.semin(0);                      // Turn off smart current control, known as CoolStep. It's a neat feature but is more complex and messes with StallGuard.
  driver.shaft(true);                   // Set the shaft direction.
  driver.en_spreadCycle(false);         // Disable SpreadCycle. We want StealthChop becuase it works with StallGuard.
  driver.pdn_disable(true);             // Enable UART control
  driver.index_step(true);              //Index pin output step pulses from internal pulse generator
  driver.rms_current(set_current);
  driver.SGTHRS(set_stall);
  driver.TCOOLTHRS(set_tcools);
  digitalWrite(ENABLE_PIN, LOW);
  driver.VACTUAL(0);
}

void loop() {
  startState = digitalRead(startPin);

  if (startState == LOW && count == 0) {
    delay(200);  //Change delay for faster SG_RESULT values
    count = 1;
    startState = digitalRead(startPin);
    if (i <= set_velocity) {
      for (i; i < set_velocity; i += 100) {
        driver.VACTUAL(i);
        Serial.print("Speed = ");
        Serial.println(i);
        delay(60);
      }
    }
  }

  if (startState == HIGH && count == 1) {
    Serial.print("Stallguard value");
    Serial.print("\t");
    Serial.print(driver.SG_RESULT());
    Serial.print("\t");
    Serial.print("Average stallguard value");
    Serial.print("\t");
    averageValue.push(driver.SG_RESULT());
    Serial.println(averageValue.average());
    delay(100);
  }

  if (startState == LOW && count == 1) {
    delay(200);  //Change delay for faster SG_RESULT values
    if (i <= set_velocity || i == set_velocity) {
      for (i; i > -1; i -= 100) {
        driver.VACTUAL(i);
        Serial.print("Speed = ");
        Serial.println(i);
        delay(30);
        if (i == 0) {
          count = 0;
        }
      }
    }
  }
}
sywong2000 commented 4 weeks ago

I have the same problem on my arduino uno. I do not know if it's caused by the motor characteristics. I'll try to change another stepper and see if the behavior would come out in a different manner.

sywong2000 commented 4 weeks ago

I can confirm different motor causes different SG_RESULT

the strange thing I noticed is that it seemed the actual current remains the same all the time. My understanding is that the actual current (driver.cs2rms(driver.cs_actual())) should varies at different load but that's not for my case. No idea what I've done wrong