Sensorless Homing
The TMC51x0 (TMC5130 & TMC5160) supports sensorless homing using StallGuard2 stall detection. This allows you to home the motor without physical endstop switches by detecting when the motor stalls against a mechanical stop.
Overview
Sensorless homing uses the StallGuard2 feature to detect when the motor stalls. When the motor hits a mechanical stop, the load increases, causing StallGuard2 to trigger. The driver can automatically stop the motor when a stall is detected.
When to Use Sensorless Homing
- β Applications without space for endstop switches
- β Cost-sensitive designs
- β Homing to a known mechanical stop
- β When stall detection is acceptable (not too sensitive)
- β Applications requiring precise homing position
- β When mechanical stops arenβt reliable
- β High-speed homing applications
Prerequisites
- Mechanical Stop: A reliable physical stop that the motor can hit
- StallGuard2 Configuration: Properly tuned stall threshold
- Motor Enabled: Motor must be enabled before homing
- SpreadCycle Mode: StallGuard2 ONLY works in SpreadCycle mode (
en_pwm_mode = 0). It DOES NOT work in StealthChop mode.
Important: StallGuard2 and StealthChop Compatibility
StallGuard2 and StealthChop are mutually exclusive.
- StealthChop (
en_pwm_mode = 1): Voltage-controlled mode for silent operation. The driver cannot measure back-EMF load accurately, so StallGuard2 values are invalid or zero. - SpreadCycle (
en_pwm_mode = 0): Current-controlled mode for higher torque. The driver can measure load, enabling StallGuard2.
To perform sensorless homing:
- Disable StealthChop (switch to SpreadCycle)
- Perform the homing sequence
- Re-enable StealthChop (if desired for normal operation)
Note on Mode Switching: Switching between StealthChop and SpreadCycle can cause a small jerk or βclickβ sound. This is normal. Ideally, perform the switch at standstill.
Basic Usage
Simple Homing Sequence
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include "tmc51x0.hpp"
bool homeMotor() {
// Configure StallGuard2 for homing (SGT threshold should be set once per motor)
// This should be done during Initialize() or via ConfigureStallGuard() before homing
tmc51x0::StallGuardConfig sg_config{};
sg_config.threshold = -10; // Stall threshold (tune for your motor)
sg_config.enable_filter = true; // Enable filter for stability
if (!driver.stallGuard.ConfigureStallGuard(sg_config)) {
return false;
}
// Perform homing in negative direction
// Note: Uses existing SGT threshold from motor configuration
// Automatically caches and restores settings (StealthChop, SW_MODE, ramp settings)
int32_t pre_zero_position_steps = 0;
float search_speed = 0.01f; // 0.01 rev/s (~0.6 RPM) - Unit::RevPerSec is default
tmc51x0::TMC51x0<MyComm>::Homing::BoundsOptions opt{};
opt.speed_unit = tmc51x0::Unit::RevPerSec;
opt.position_unit = tmc51x0::Unit::Deg;
opt.search_speed = search_speed;
opt.search_span = 360.0F; // max travel cap (one direction)
opt.backoff_distance = 5.0F; // optional
opt.timeout_ms = 10000;
if (!driver.homing.PerformSensorlessHoming(false, opt, pre_zero_position_steps)) {
return false;
}
// Note: PerformSensorlessHoming() already defines home by setting XACTUAL=0.
// The returned value is the *pre-zero* position in steps (after any optional backoff),
// which is useful for diagnostics (e.g., how far the axis travelled during homing).
printf("Homing pre-zero position (steps): %d\n", pre_zero_position_steps);
return true;
}
Homing Methods
Homing methods are now in the homing subsystem and automatically cache/restore settings:
driver.homing.PerformSensorlessHoming(): Uses existing StallGuard configuration (SGT threshold from motor config)driver.homing.PerformSwitchHoming(): Uses reference switches for homing
Both methods automatically:
- Cache current settings (StealthChop, SW_MODE, ramp settings)
- Disable StealthChop if enabled (StallGuard requires SpreadCycle)
- Restore cached settings after homing completes
Note: StealthChop is automatically disabled during sensorless homing (StallGuard requires SpreadCycle mode) and restored afterward.
StallGuard2 Configuration
Understanding Stall Threshold (sgt)
The sgt parameter controls stall sensitivity:
- Range: -64 to +63
- Lower values (more negative): More sensitive, detects stall earlier
- Higher values (more positive): Less sensitive, requires more load
Tuning Stall Threshold
- Start with a conservative value:
sgt = 0 - Move motor toward stop slowly
- Monitor StallGuard value:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
void tuneStallThreshold() {
// Move motor slowly
driver.rampControl.SetRampMode(tmc51x0::RampMode::VELOCITY_POS);
driver.rampControl.SetMaxSpeed(100.0f); // Slow speed
driver.motorControl.Enable();
// Monitor StallGuard value
while (true) {
auto reached = driver.rampControl.IsTargetReached();
if (reached && reached.Value()) {
break; // Target reached
}
if (!reached) {
printf("Error checking target: %s\n", reached.ErrorMessage());
break;
}
auto sg_result = driver.stallGuard.GetStallGuardResult();
if (sg_result.IsOk()) {
uint16_t sg_value = sg_result.Value();
printf("StallGuard: %d\n", sg_value);
// When motor hits stop, SG value will drop significantly
if (sg_value < 100) { // Threshold depends on your motor
printf("Stall detected!\n");
break;
}
}
driver.rampControl.Stop();
}
- Set threshold: Use a value slightly above the stall value
- If stall occurs at SG=50, use
sgt = 30-40 - If stall occurs at SG=200, use
sgt = 150-180
- If stall occurs at SG=50, use
Complete Homing Example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include "tmc51x0.hpp"
class MotorController {
private:
tmc51x0::TMC51x0<Esp32SPI> &driver_;
int8_t stall_threshold_;
public:
MotorController(tmc51x0::TMC51x0<Esp32SPI> &driver)
: driver_(driver), stall_threshold_(-10) {}
bool home() {
// 1. Configure StallGuard2
tmc51x0::StallGuardConfig sg_config{};
sg_config.threshold = stall_threshold_;
sg_config.enable_filter = true; // Filter for stability
if (!driver_.stallGuard.ConfigureStallGuard(sg_config)) {
return false;
}
// 2. Enable StallGuard stop in SW_MODE
// (PerformSensorlessHoming automatically caches and restores settings)
// 3. Home in negative direction
int32_t home_pos = 0;
float search_speed = 0.01f; // 0.01 rev/s (~0.6 RPM) - Unit::RevPerSec is default
tmc51x0::TMC51x0<Esp32SPI>::Homing::BoundsOptions opt{};
opt.speed_unit = tmc51x0::Unit::RevPerSec;
opt.position_unit = tmc51x0::Unit::Deg;
opt.search_speed = search_speed;
opt.search_span = 360.0F; // max travel cap (one direction)
opt.backoff_distance = 5.0F; // optional
opt.timeout_ms = 10000;
if (!driver_.homing.PerformSensorlessHoming(false, opt, home_pos)) {
return false;
}
// 4. Set position to zero
driver_.rampControl.SetCurrentPosition(0);
return true;
}
bool moveToHome() {
// Move to home position (0)
driver_.rampControl.SetRampMode(tmc51x0::RampMode::POSITIONING);
driver_.rampControl.SetTargetPosition(0);
driver_.motorControl.Enable();
// Wait for completion
while (true) {
auto reached = driver_.rampControl.IsTargetReached();
if (reached && reached.Value()) {
break; // Target reached
}
if (!reached) {
// Handle error
break;
}
// Could add timeout here
}
return true;
}
};
Homing Sequence Best Practices
1. Pre-Home Setup
1
2
3
4
5
6
7
8
// Ensure motor is enabled
driver.motorControl.Enable();
// Set appropriate speed (not too fast)
driver.rampControl.SetMaxSpeed(0.01f); // 0.01 rev/s (~0.6 RPM) - Unit::RevPerSec is default
// Set acceleration
driver.rampControl.SetAcceleration(1000.0f);
2. Homing Direction
- Negative direction: Typically used for homing to βzeroβ position
- Positive direction: Can be used if mechanical stop is at max position
- Choose direction that moves away from work area
3. Post-Home Actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// After homing completes:
// 1. Set current position to zero
driver.rampControl.SetCurrentPosition(0);
// 2. Move away from stop slightly (optional)
driver.rampControl.SetTargetPosition(100); // Move 100 steps away
while (true) {
auto reached3 = driver.rampControl.IsTargetReached();
if (reached3 && reached3.Value()) {
break; // Target reached
}
if (!reached3) {
// Handle error
break;
}
// Wait
}
// 3. Set new zero position
driver.rampControl.SetCurrentPosition(0);
Troubleshooting
Motor Doesnβt Stop at Stall
Problem: Motor continues moving after hitting stop
Solution:
- Lower
sgtvalue (more negative) - Increase
sfiltfilter for stability - Verify
sg_stopis enabled inSW_MODE - Check that StallGuard2 is properly configured
False Stall Detection
Problem: Motor stops before reaching mechanical stop
Solution:
- Increase
sgtvalue (less sensitive) - Check for mechanical binding
- Verify motor current is sufficient
- Reduce acceleration to avoid false triggers
Inconsistent Homing Position
Problem: Home position varies between homing cycles
Solution:
- Use
sfiltfilter for stable readings - Ensure consistent mechanical stop
- Consider moving away from stop after homing
- Use reference switches for more precision
Advanced: Manual Stall Detection
For more control, you can implement manual stall detection:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
bool homeManual() {
// Configure StallGuard2
tmc51x0::StallGuardConfig sg_config{};
sg_config.threshold = -10;
sg_config.enable_filter = true;
driver.stallGuard.ConfigureStallGuard(sg_config);
// Start movement
driver.rampControl.SetRampMode(tmc51x0::RampMode::VELOCITY_NEG);
driver.rampControl.SetMaxSpeed(500.0f);
driver.motorControl.Enable();
// Monitor for stall
const uint16_t STALL_THRESHOLD = 100;
const uint32_t TIMEOUT_MS = 10000;
uint32_t start_time = getCurrentTimeMs();
while (getCurrentTimeMs() - start_time < TIMEOUT_MS) {
uint16_t sg_value = driver.stallGuard.GetStallGuardResult().Value();
if (sg_value < STALL_THRESHOLD) {
// Stall detected
driver.rampControl.Stop();
driver.rampControl.SetCurrentPosition(0);
return true;
}
}
// Timeout
driver.rampControl.Stop();
return false;
}
See Also
- Examples β Bounds Finding and Fatigue Testing β Complete bounds finding walkthrough
- Advanced Configuration β StallGuard2 Automatic Tuning β Let the driver find optimal SGT for you
- Fatigue Test Source Code β Production sensorless homing implementation
- StallGuard Tuning Source β ESP32 automatic SGT tuning
Navigation <- Motor Setup | Next: Advanced Configuration -> | Back to Index