Section 7: StallGuard
Look what happens when my fingers get in the way of a moving window:
This this video, it only takes five pounds of force for my fingers to stop the window. This works using a feature called StallGuard.
StallGuard works by monitoring the back EMF while driving the motor. As the motor encounters resistance, the back EMF of the motor begins to rise and the driver detects this. It then sends signal to the ESP32 to stop the motor.
To learn more, go here.
On the BigTreeTech driver, the pin is actually sticking up in the air and may need to soldered on.
When stallGuard is activated, the TMC2209 sends a HIGH signal on the Diag pin. On the VAL-2000 the diag pin is connected to pin 2 on the ESP32.
What we will do it monitor the DIAG pin for a HIGH signal. If one is detected, it is our responsibility to stop the motor.
Let’s look at the interrupt function what will get triggered by this high pin.
Go to line 58 of the sketch:
void IRAM_ATTR stalled_position()
stalled_motor = true;
stop_motor = true;
Notice the IRAM_ATTR. This is a special ESP32 word that makes sure to store this function into a special area of the memory, this way it is called very very fast.
When this interrupt is called, we want to set a the stalled_motor Boolean to false. Keep it as simple as possible for interrupts.
We now need to place some code to initialize this interrupt.
On line 211 we initialize it on the RISING edge like this:
attachInterrupt(STALLGUARD, stalled_position, RISING);
By looking for a rising edge, we can see it very fast.
You can learn more about interrupts here:
Remember, when a stall takes place, pin 2 is normally LOW, and then becomes HIGH. We want to watch for the rising edge when it goes from low to high in order to trigger this interrupt.
You can also use two additional interrupts that are used for the optional limit switches you can place on this board, I will not cover those.
We will now cover the basics of setting up StallGuard.
Before we begin, you need to understand the difference between StallGuard2 and StallGuard4. StallGuard2 has been around for many years and is used on most of the older Trinamic drivers such as the TMC2208, TMC2130, TMC2160 and so on. StallGuard4 is newer and is found on the TMC2209 and a couple other newer chips.
StallGuard4 is not better, it is different.
Most Trinamic drivers give you the choice of using two chopper algorithms called SpreadCycle and StealthChop.
Go to page 6 of the datasheet, section 1.4.
This is important to understand as we will set this in the settings. Here is how I best describe it:
SpreadCycle: Super fast but louder.
StealthChop: Silent but much slower.
If you need to run your motor very fast, you need to set it to SpreadCycle
If you need to run your motor very quietly, you need to set it to StealthChop.
I love Stealthchop as it is very quiet.
StallGuard2 ONLY works with SpreadCycle
StallGuard4 ONLY works with StealthChop
The TMC2209 has StallGuard4 which means we can only run it with StealthChop and it will not work at high speeds.
Setting StallGuard ValueNow that we have the interrupt set up in the code, we need to set the correct values to trigger StallGuard.
There are 256 values we can set by using the code:
Remember, the driver monitors the back EMF and triggers a stall when the back EMF gets too high. So we need to tell it what that high point is, so it triggers correctly.
StallGuard is actually quite complex and more of an art than a science in order to set properly, so it will take some time to play around and get it right based on your conditions.
Let’s go to page 55 of the datasheet.
While the datasheet talks about using SG_RESULT a lot, I don’t find it all that useful, but you might.
SG_RESULT is a value between 0-510 that you can read using UART.
To monitor it, find the SG_RESULT register and use Serial.print to read to the serial monitor. This can be helpful if you just cannot get StallGuard to trigger.
After years of messing around with this, here is what you need to know.
StallGuard is a combination of your:
- TCOOLTHRS setting
- SGTHRS setting
The current you are using will determine the amount of back EMF created, so first set your current to a level you want. A high current will make the motor louder and stronger. A low current will do the opposite. Dial that in first.
Next, set the velocity. How fast do you need your motor to go.
Next, set the acceleration. Slow speeds are not reliable for StallGuard, so a very long and slow acceleration will not be good with StallGuard. Try to accelerate as fast as you can based on your project. Just know during the acceleration phase, StallGuard may not work, so can you risk having it now work until it gets to a stable velocity?
In my window opener, I cannot risk it, because what if the window is locked when trying to open the window? Damage may occur. So I need to accelerate it as quickly as possible, but not too fast. So take some time to get your acceleration right.
Now we can set the TCOOLTHRS value. It is on page 26 of the datasheet.
This is the velocity threshold at which point StallGuard will activate. Remember, StallGuard is not reliable at low speeds, we need to keep it turned off until a certain speed is reached. There’s a chance that it will trigger the stall pin HIGH when starting up, even when there is no stall.
So we need to set the correct value, but this can be very difficult to do, because the value is quite hard to figure out.
Luckily I’ve spent a lot of time figuring this out, and here is the formula I’ve come up with based on many many tests.
TCOOLS = (3089838.00*pow(float(MOVE_VELOCITY),-1.00161534))*1.5;
Simply plug in the MOVE_VELOCITY value into it, and it will give you this threshold. This is a regression curve that I’ve created to help you out. It’s worked very well so far.
Finally, we need to set the SGTHRS value which is the main value to set. It is a value from 0 - 255 as seen on page 55.
A value of 0 will turn StallGuard off completely. The higher you go, the more sensitive it will be to tripping.
My workflow for setting StallGuard :
- First I figure out the current to set. I need to have enough current to move whatever needs to be moved, but not much more. If the current is too high, StallGuard will required a lot of force to trip, so don’t set it much higher than the application calls for.
- Then I figure out what velocity I want and set that.
- Then I figure out what acceleration I want, trying to use the fastest I can for the application
- Then I set the TCOOLTHRS value based on the formula above. In fact, I have it automatically set alongside the velocity
- Then I start at 0 and start moving the motor and applying pressure to it with my fingers. I slowly increase this number until it stalls. Just keep running the motor, applying pressure, and increasing the value.
- Section 0: Background
- Section 1: Hardware Setup
- Section 2: Stepper Motor Basics
- Section 3: Arduino Setup
- Section 4: Understanding Trinamic Drivers
- Section 5: Setting Trinamic Drivers
- Section 6: Power Requirements
- Section 7: StallGuard
- Section 8: FastAccelStepper Library
- Section 9: ESP32 Dual Core Setup
- Section 10: Motor Setup
- Section 11: Preferences Library
- Section 12: ESPUI
- Section 13: API