Open surei01 opened 3 years ago
The TMC2209 DIAG pin will inform you whenever the stallGuard reading falls below the configured value and you don't have to read the value with slow SW UART. Your condition seems to be the wrong way. See Chapter 11 on datasheet. You also need to reset the flag after the fact.
Aside from not setting up StallGuard parameters correctly, you need to add an interrupt in order to actually stop the motor once a high signal is detected on the DIAG pin
Please reference my updated book for more info: https://amzn.to/3XCbUEb
For anyone trying to do sensorless homing, here is some Arduino example code that's working for me. It uses the TMC2209 driver from BigTreeTech to run a NEMA 17 stepper and is controlled by a Teensy 4.0.
/**
//#define DIR_PIN 3 // Direction
// higher value of STALL_VALUE increases stall sensitivity
// diag pin pulsed HIGH when SG_RESULT falls below 2*STALL_VALUE
// must be in StealthChop Mode for stallguard to work
// Value of TCOOLTHRS must be greater than TSTEP & TPWMTHRS
int stepTime = 160; bool startup = true; // set false after homing
TMC2209Stepper driver(&SERIAL_PORT, R_SENSE, DRIVER_ADDRESS); bool shaftVal = false; bool stalled_X = false;
void stallInterruptX(){ // flag set when motor stalls stalled_X = true; }
void setup() { pinMode(EN_PIN, OUTPUT); pinMode(STEP_PIN, OUTPUT); // shaft direction controlled through uart: driver.shaft(true or false) pinMode(STALL_PIN_X, INPUT);
SERIAL_PORT.begin(115200); // HW UART drivers
driver.begin(); // SPI: Init CS pins and possible SW SPI pins driver.toff(4); // Enables driver in software, changed from 5 driver.blank_time(24); driver.rms_current(400); // Set motor RMS current driver.microsteps(16); // Set microsteps to 1/16th
//driver.en_pwm_mode(true); // Toggle stealthChop on TMC2130/2160/5130/5160
//driver.en_spreadCycle(false); // Toggle spreadCycle on TMC2208/2209/2224
driver.pwm_autoscale(true); // Needed for stealthChop
driver.semin(5);
driver.semax(2);
driver.sedn(0b01);
driver.shaft(shaftVal);
// TCOOLTHRS needs to be set for stallgaurd to work //
driver.TCOOLTHRS(0xFFFFF); // 20bit max
driver.SGTHRS(STALL_VALUE);
attachInterrupt(digitalPinToInterrupt(STALL_PIN_X), stallInterruptX, RISING);
digitalWrite(EN_PIN, LOW); // Enable driver in hardware
}
void loop() {
if(startup){ // home on starting up
startup = false;
homeX();
}
if(stalled_X){ int backSteps = 1000; Serial.println("stalled"); stalled_X = false; shaftVal =! shaftVal; motor(backSteps,160); }
if(Serial.available()>0){
char readVal = Serial.read();
if (readVal == 'x'){
int steps = Serial.parseInt();
if(steps < 0){
shaftVal = true;
steps *= -1;
} else { shaftVal = false; }
motor(steps,160);
} else if (readVal == 'h'){
homeX();
}
}
}
void homeX(){
int homeDelay = 160;
int backSteps = 5000;
Serial.println("fast homing x");
shaftVal = true;
while(!stalled_X){ // fast home x
motor(1000,homeDelay);
}
stalled_X = false;
delay(1000);
Serial.println("backing off");
shaftVal = false;
motor(backSteps,homeDelay);
Serial.println("slow homing x"); shaftVal = true; while(!stalled_X){ // slow home x motor(1000,homeDelay*2); } stalled_X = false; delay(1000); Serial.println("backing off"); shaftVal = false; motor(backSteps, homeDelay); }
void motor(int steps, int stepDelay){ digitalWrite(EN_PIN, LOW); driver.shaft(shaftVal); for(int i = 0; i<steps; i++){ digitalWrite(STEP_PIN,HIGH); delayMicroseconds(stepDelay); digitalWrite(STEP_PIN,LOW); delayMicroseconds(stepDelay); if(stalled_X){ i = steps; } } digitalWrite(EN_PIN,HIGH); }
@WheeSci can you provide some type of wiring diagram that you used for you setup. I have read online that the TMC2209 can have a voltage spike when turning on the motor power source and end up killing the Teensy 4.0/ 4.1 due to it only being 3.3v tolerant. I'm pretty new to this so I hope that makes sense. I don't want to kill my Teensy but want to use the TMC2209. Greatly appreciated!!!
@WheeSci Wow, the first working example I've found! Thank you very much for sharing!
Hello all - I just spent one month trying to figure this out - so frustrating... In the labyrinth of confusing TMC related docs online, including Github, there is little about using the TMC drivers as a standalone controller, as it is all about 3D printers on mother boards like Marlin, Octopus etc. I emailed BigtreeTech as well though got zero response - despite their promise on their website that they are responsive.
The main problem is that the Arduino Library examples are useless and confusing as they miss the most important element of getting these to work which is the use of interrupts - totally missing from the Arduino library examples - e.g. the "Stallguard" example has no interrupts at all which is kind of dumb. It would be much better if they included the code above in the library download??
Thanks to @WheeSci, this code actually works as it includes the interrupts that pick up the change on the diag pin. Without this, nothing happens.
The other thing to be highlighted is that the code above uses a combination of UART and wired communications in that the step pin is still used together with UART (controlling a bunch of parameters such as shaft direction, micro-stepping, current etc.) The step pin controls the stepping and works fine, though there most probably is a way to control the stepping though UART though after spending to much time on this I am sticking with this as it works.
Once sorted, however, this code works really well and the TMC controller it really great piece of technology - way more powerful than the A4988 and a lot quieter. The homing function is excellent with accurate, repeatable results.
Its a pity that TMC/BigtreeTech etc. do not have better docs for standalone operation of their products, and moreover, better examples in the Arduino Library!!
Hello all - I just spent one month trying to figure this out - so frustrating...
I agree, I've been working with these drivers for years and it's frustrating how bad the documentation is. I ended up writing a kindle book that talks about them in layman's terms if anyone is interested. It's everything I wish someone shared with me when I started to work with these steppers
Thanks @daniel-frenkel I wish I had known about your book one month ago! I will certainly get one.
For anyone trying to do sensorless homing, here is some Arduino example code that's working for me. It uses the TMC2209 driver from BigTreeTech to run a NEMA 17 stepper and is controlled by a Teensy 4.0.
/**
- HomeX sketch for sensorless homing stepper
- TMC2209 with Teensy 4.0
- Based on Simple sketch by Teemu Mäntykallio
- homes on power up.
- send 'x' followed by int to begin stepping.
- send 'h' to re-home.
RX on pin 7, TX on pin 8
PDN_UART pin on tmc2209 connected to pin 7
1 k resistor between teensy pins 7 and 8
motor direction controlled by uart:
driver.shaft(true or false);
**/
include
define EN_PIN 10 // Enable //#define DIR_PIN 3 // Direction #define STEP_PIN 2 // Step #define STALL_PIN_X 21 // Teensy pin that diag pin is attached to #define SERIAL_PORT Serial2 // HardwareSerial port for Teensy 4.0 #define DRIVER_ADDRESS 0b00 // TMC2209 Driver address according to MS1 and MS2 #define R_SENSE 0.11f // Match to your driver
// higher value of STALL_VALUE increases stall sensitivity // diag pin pulsed HIGH when SG_RESULT falls below 2*STALL_VALUE // must be in StealthChop Mode for stallguard to work // Value of TCOOLTHRS must be greater than TSTEP & TPWMTHRS
define STALL_VALUE 50 // [0..255] int stepTime = 160; bool startup = true; // set false after homing
TMC2209Stepper driver(&SERIAL_PORT, R_SENSE, DRIVER_ADDRESS); bool shaftVal = false; bool stalled_X = false;
void stallInterruptX(){ // flag set when motor stalls stalled_X = true; }
void setup() { pinMode(EN_PIN, OUTPUT); pinMode(STEP_PIN, OUTPUT); // shaft direction controlled through uart: driver.shaft(true or false) pinMode(STALL_PIN_X, INPUT);
SERIAL_PORT.begin(115200); // HW UART drivers
driver.begin(); // SPI: Init CS pins and possible SW SPI pins driver.toff(4); // Enables driver in software, changed from 5 driver.blank_time(24); driver.rms_current(400); // Set motor RMS current driver.microsteps(16); // Set microsteps to 1/16th
//driver.en_pwm_mode(true); // Toggle stealthChop on TMC2130/2160/5130/5160 //driver.en_spreadCycle(false); // Toggle spreadCycle on TMC2208/2209/2224 driver.pwm_autoscale(true); // Needed for stealthChop driver.semin(5); driver.semax(2); driver.sedn(0b01); driver.shaft(shaftVal); // TCOOLTHRS needs to be set for stallgaurd to work // driver.TCOOLTHRS(0xFFFFF); // 20bit max driver.SGTHRS(STALL_VALUE); attachInterrupt(digitalPinToInterrupt(STALL_PIN_X), stallInterruptX, RISING); digitalWrite(EN_PIN, LOW); // Enable driver in hardware }
void loop() { if(startup){ // home on starting up startup = false; homeX(); }
if(stalled_X){ int backSteps = 1000; Serial.println("stalled"); stalled_X = false; shaftVal =! shaftVal; motor(backSteps,160); }
if(Serial.available()>0){ char readVal = Serial.read(); if (readVal == 'x'){ int steps = Serial.parseInt(); if(steps < 0){ shaftVal = true; steps *= -1; } else { shaftVal = false; } motor(steps,160); } else if (readVal == 'h'){ homeX(); } } }
void homeX(){ int homeDelay = 160; int backSteps = 5000; Serial.println("fast homing x"); shaftVal = true; while(!stalled_X){ // fast home x motor(1000,homeDelay); } stalled_X = false; delay(1000); Serial.println("backing off"); shaftVal = false; motor(backSteps,homeDelay);
Serial.println("slow homing x"); shaftVal = true; while(!stalled_X){ // slow home x motor(1000,homeDelay*2); } stalled_X = false; delay(1000); Serial.println("backing off"); shaftVal = false; motor(backSteps, homeDelay); }
void motor(int steps, int stepDelay){ digitalWrite(EN_PIN, LOW); driver.shaft(shaftVal); for(int i = 0; i<steps; i++){ digitalWrite(STEP_PIN,HIGH); delayMicroseconds(stepDelay); digitalWrite(STEP_PIN,LOW); delayMicroseconds(stepDelay); if(stalled_X){ i = steps; } } digitalWrite(EN_PIN,HIGH); }
Thank you very much for sharing the code. With a few modifications, I was able to get it running with the AccelStepper library. Now the motor homes without and limit switch and it is very satisfying to see it do so.
For anyone trying to do sensorless homing, here is some Arduino example code that's working for me. It uses the TMC2209 driver from BigTreeTech to run a NEMA 17 stepper and is controlled by a Teensy 4.0. /**
- HomeX sketch for sensorless homing stepper
- TMC2209 with Teensy 4.0
- Based on Simple sketch by Teemu Mäntykallio
- homes on power up.
- send 'x' followed by int to begin stepping.
- send 'h' to re-home.
RX on pin 7, TX on pin 8
PDN_UART pin on tmc2209 connected to pin 7
1 k resistor between teensy pins 7 and 8
motor direction controlled by uart:
driver.shaft(true or false);
**/
include
define EN_PIN 10 // Enable //#define DIR_PIN 3 // Direction #define STEP_PIN 2 // Step #define STALL_PIN_X 21 // Teensy pin that diag pin is attached to #define SERIAL_PORT Serial2 // HardwareSerial port for Teensy 4.0 #define DRIVER_ADDRESS 0b00 // TMC2209 Driver address according to MS1 and MS2 #define R_SENSE 0.11f // Match to your driver
// higher value of STALL_VALUE increases stall sensitivity // diag pin pulsed HIGH when SG_RESULT falls below 2*STALL_VALUE // must be in StealthChop Mode for stallguard to work // Value of TCOOLTHRS must be greater than TSTEP & TPWMTHRS
define STALL_VALUE 50 // [0..255] int stepTime = 160; bool startup = true; // set false after homing
TMC2209Stepper driver(&SERIAL_PORT, R_SENSE, DRIVER_ADDRESS); bool shaftVal = false; bool stalled_X = false; void stallInterruptX(){ // flag set when motor stalls stalled_X = true; } void setup() { pinMode(EN_PIN, OUTPUT); pinMode(STEP_PIN, OUTPUT); // shaft direction controlled through uart: driver.shaft(true or false) pinMode(STALL_PIN_X, INPUT); SERIAL_PORT.begin(115200); // HW UART drivers driver.begin(); // SPI: Init CS pins and possible SW SPI pins driver.toff(4); // Enables driver in software, changed from 5 driver.blank_time(24); driver.rms_current(400); // Set motor RMS current driver.microsteps(16); // Set microsteps to 1/16th //driver.en_pwm_mode(true); // Toggle stealthChop on TMC2130/2160/5130/5160 //driver.en_spreadCycle(false); // Toggle spreadCycle on TMC2208/2209/2224 driver.pwm_autoscale(true); // Needed for stealthChop driver.semin(5); driver.semax(2); driver.sedn(0b01); driver.shaft(shaftVal); // TCOOLTHRS needs to be set for stallgaurd to work // driver.TCOOLTHRS(0xFFFFF); // 20bit max driver.SGTHRS(STALL_VALUE); attachInterrupt(digitalPinToInterrupt(STALL_PIN_X), stallInterruptX, RISING); digitalWrite(EN_PIN, LOW); // Enable driver in hardware } void loop() { if(startup){ // home on starting up startup = false; homeX(); } if(stalled_X){ int backSteps = 1000; Serial.println("stalled"); stalled_X = false; shaftVal =! shaftVal; motor(backSteps,160); } if(Serial.available()>0){ char readVal = Serial.read(); if (readVal == 'x'){ int steps = Serial.parseInt(); if(steps < 0){ shaftVal = true; steps = -1; } else { shaftVal = false; } motor(steps,160); } else if (readVal == 'h'){ homeX(); } } } void homeX(){ int homeDelay = 160; int backSteps = 5000; Serial.println("fast homing x"); shaftVal = true; while(!stalled_X){ // fast home x motor(1000,homeDelay); } stalled_X = false; delay(1000); Serial.println("backing off"); shaftVal = false; motor(backSteps,homeDelay); Serial.println("slow homing x"); shaftVal = true; while(!stalled_X){ // slow home x motor(1000,homeDelay2); } stalled_X = false; delay(1000); Serial.println("backing off"); shaftVal = false; motor(backSteps, homeDelay); } void motor(int steps, int stepDelay){ digitalWrite(EN_PIN, LOW); driver.shaft(shaftVal); for(int i = 0; i<steps; i++){ digitalWrite(STEP_PIN,HIGH); delayMicroseconds(stepDelay); digitalWrite(STEP_PIN,LOW); delayMicroseconds(stepDelay); if(stalled_X){ i = steps; } } digitalWrite(EN_PIN,HIGH); }
Thank you very much for sharing the code. With a few modifications, I was able to get it running with the AccelStepper library. Now the motor homes without and limit switch and it is very satisfying to see it do so.
Would you be willing to share your code? I am stuck trying to do the exact same thing with accelstepper and TMC2209!
Hi all, I am trying to set up a small machine using the TMC 2209 driver and want to use the sensorless homing feature. So my idea is to have the stepper run until it reaches the end and have it stop when the driver reports a stall. I am running this on an Arduino Uno using the CNC shield. I got the thing up and running with the driver in UART mode, communication appears to work, I can control the stepper and query the driver. But I do not find any documentation what it actually is reporting and how I can use that to detect the stall.
Below is my code, bits and pieces copied together from various examples. After setting up the driver it is executing a home() function that should stop when the driver reports the stall. What is the correct code piece to make that work? Also it appears that reading the driver.SG_result() function is rather slow, so I might need another approach to have get the motor run at a higher speed during homing (it is rather slow now).
Any help is highly appreciated!
Best regards Reiner