teemuatlut / TMC2130Stepper

Arduino library for Trinamic TMC2130 Stepper driver
MIT License
160 stars 50 forks source link

Problems with Stallguard #75

Open roelandbenoot opened 5 years ago

roelandbenoot commented 5 years ago

Hi! First of all thank you for your amazing work! Now my problem: I'm trying to get stallguard working with my arduino nano and fysetc tmc2130. I got the "simple" example working fairly quickly, but I added the "driver.stallguard" and "driver.sg_result" as you can see in my code below. (I also disabled stealthchop) Now when I try it out, I get back "Stalling" and "0" in my serial monitor, nothing changes even when I block the motor. However when I turn down the 12V power from the VM pin (the arduino is powered through USB), I get back "Not stalling" and "0". I don't really know what I'm doing wrong, I've been experimenting with this library for a quit a few days now, I even remember using the same functions and getting back different numbers, but they weren't really correct. So I'm kind of at a loss right now and I hope you can help me ^^ Kind regards.

#define EN_PIN    7  // Nano v3:    16 Mega:    38  //enable (CFG6)
#define DIR_PIN   6  //         19          55  //direction
#define STEP_PIN  5  //         18          54  //step
#define CS_PIN    10  //            17          64  //chip select

bool dir = true;

#include <TMC2130Stepper.h>
TMC2130Stepper driver = TMC2130Stepper(EN_PIN, DIR_PIN, STEP_PIN, CS_PIN);

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.stealthChop(1);  // Enable extremely quiet stepping

    digitalWrite(EN_PIN, LOW);
}

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_dir(0);
        } else {
            Serial.println("Dir -> 1");
            driver.shaft_dir(1);
        }
        dir = !dir;
        last_time = ms;
 if(driver.stallguard()){
  Serial.println("Stalling");
 }else{
  Serial.println("Not stalling");
 }
 Serial.println(driver.sg_result());
    }
}`
teemuatlut commented 5 years ago

The library comes with a proven example for testing the stallGuard feature. I'd suggest you start there. I remember when testing SG for the first time that I had to move the stepping calls to an interrupt routine. Otherwise the motor would stop for a moment to communicate with the driver to fetch the values and then do the serial printing for the user and then anything else that might be written there. The stepping rate should be fairly consistent if you want to try using stallGuard measurements.

roelandbenoot commented 5 years ago

Thanks for the quick response! The motor doesn't really seem to stop, so I don't think the problem lies there, I might be mistaken tho.. But I tried the stallGuard example and added in a bit of code, so that the motor actually turns. The output I constantly get is "0 0 1049" and an occasional dir->0/1 ofcourse. And when I turn off power, I get "0 0 55". I suspect that that's not what I should get tho, since there is no change in output...

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

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

// Note: You also have to connect GND, 5V and VM.
//       A connection diagram can be found in the schematics.
#define EN_PIN    7  // Nano v3:  16 Mega:  38  //enable (CFG6)
#define DIR_PIN   6  //           19        55  //direction
#define STEP_PIN  5  //           18        54  //step
#define CS_PIN    10  //           17        64  //chip select

#include <SPI.h>
#include <TMC2130Stepper.h>
#include <TMC2130Stepper_REGDEFS.h>
TMC2130Stepper driver = TMC2130Stepper(EN_PIN, DIR_PIN, STEP_PIN, CS_PIN);

bool vsense;

uint16_t rms_current(uint8_t CS, float Rsense = 0.11) {
  return (float)(CS+1)/32.0 * (vsense?0.180:0.325)/(Rsense+0.02) / 1.41421 * 1000;
}

void setup() {
  //init serial port
  {
    Serial.begin(9600); //init serial port and set baudrate
    Serial.println("\nStart...");
    driver.begin();
  }

  //set TMC2130 config
  {
    driver.rms_current(600); // mA
    //driver.microsteps(16);
    driver.diag1_stall(1);
    driver.diag1_active_high(1);
    driver.coolstep_min_speed(0xFFFFF); // 20bit max
    driver.THIGH(0);
    driver.semin(5);
    driver.semax(2);
    driver.sedn(0b01);
    driver.sg_stall_value(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
  }

  //TMC2130 outputs on (LOW active)
  digitalWrite(EN_PIN, LOW);

  //vsense = driver.vsense();
}

ISR(TIMER1_COMPA_vect){
  digitalWrite(STEP_PIN, HIGH);
  digitalWrite(STEP_PIN, LOW);
}

bool dir = false;

void loop()
{
  for(uint16_t i=0; i<51200; i++){
    digitalWrite(STEP_PIN, HIGH);
    delayMicroseconds(10);
    digitalWrite(STEP_PIN, LOW);
    delayMicroseconds(10);

    static uint32_t last_time=0;
    uint32_t ms = millis();

    while(Serial.available() > 0) {
      int8_t read_byte = Serial.read();
      if (read_byte == '0')      { TIMSK1 &= ~(1 << OCIE1A); digitalWrite( EN_PIN, HIGH ); }
      else if (read_byte == '1') { TIMSK1 |=  (1 << OCIE1A); digitalWrite( EN_PIN,  LOW ); }
      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 if >100
    {
      last_time = ms;
      uint32_t drv_status = driver.DRV_STATUS();
      Serial.print("0 ");
      Serial.print((drv_status & SG_RESULT_bm)>>SG_RESULT_bp , DEC);
      Serial.print(" ");
      Serial.println(rms_current((drv_status & CS_ACTUAL_bm)>>CS_ACTUAL_bp), DEC);
    }
  }
  if (dir) {
      Serial.println("Dir -> 0");
      driver.shaft_dir(0);
    } else {
      Serial.println("Dir -> 1");
      driver.shaft_dir(1);
    }
    dir = !dir;
}`
teemuatlut commented 5 years ago

The motor doesn't stop because the code doesn't react to activated stallGaurd signal. Only set the pins before you start modifying the example.

You can set the code syntax with markdown.

roelandbenoot commented 5 years ago

I'm quite confused with what you mean with 'set the pins before you start modifying the example". And btw the motor has been turning the way I want.

teemuatlut commented 5 years ago

You should first try to get the example working as is and then start expanding from there. Of course you may need to edit pins and the port definition but try to take small steps and see where things start to break.

MilanVDB commented 4 years ago

I'm quite confused with what you mean with 'set the pins before you start modifying the example". And btw the motor has been turning the way I want.

did you manage to get the example to work?

roelandbenoot commented 4 years ago

I didn't, I stopped trying since I didn't have time anymore...

DamirTomic commented 1 year ago

This doesn't work for me either. I'm getting stallguard measurements before moving the motor, but as soon as I do as single step, either via

digitalWrite(STEP_PIN, HIGH); delayMicroseconds(10); digitalWrite(STEP_PIN, LOW); delayMicroseconds(10);

or by using the AccelStepper library's stepper.run() method to move the motor, I stop receiving any stallguard measurements.

The only way to get measurements again is resetting the whole device, and this lasts until the motor moves a step.