This library is used to control one or more TMC2209 modules via UART using an AVR microcontroller. Apart from reading and writing the TMC2209 registers, this library can also be used to drive a stepper motor by using the stepperCon library in the background. The stepperCon library provides non blocking functions by using an interrupt, to drive multiple stepper motors with custom acceleration and speed, to keep track of motor positions, 3-axis motor coordination, as well as other useful functions. UART library is also provided that can use up to 2 USART peripherals at the same time: one for interfacing with the driver IC and one for debugging (assuming the microcontroller has two USART peripherals).
The serial communication has some extra features for checkup such as:
- reads the interface transmission counter (IFCNT) register after every write to ensure the IC received the correct data.
- compares CRCs.
- checks if correct number of bytes has been received.
- if an error occurs it retries 2 times then sets a communication error flag that the user can check after each function is executed and take the appropriate action if an error occurs.
If you wish to learn on how to wire the TMC2209 driver, you can find a tutorial here.
Contents
- Library Structure
- Default Settings
- Usage
- Documentation
- Create a structure object for each driver
- Initialization
- Read IC version
- Read Global Status Flags (GSTAT)
- GSTAT check if module was Reset
- GSTAT check if Driver Error
- GSTAT check if Charge Pump is Under Voltage
- Status check for UART error
- Read register PWM_SCALE_SUM
- Read register PWM_SCALE_AUTO
- Read register PWM_OFS_AUTO
- Read register PWM_GRAD_AUTO
- Read register SG_RESULT (StallGuard)
- Read register TSTEP
- Read register DRV_STATUS (Driver Status Flags)
- DRV_STATUS check Standstill
- DRV_STATUS check Chopper type
- DRV_STATUS check CS_ACTUAL
- DRV_STATUS check Temperature flags
- DRV_STATUS check Open Load flags
- DRV_STATUS check Low Side Short flags
- DRV_STATUS check Short to Ground flags
- DRV_STATUS check Over-temperature flag
- DRV_STATUS check Over-temperature Pre-warning flag
- Set micro-step resolution
- Set speed
- Set acceleration and deceleration
- Set direction
- Set chopper
- Set SpreadCycle threshold
- Set register IHOLD_IRUN
- Set register TPOWERDOWN
- Set register SGTHRS (StallGuard)
- Set register TCOOLTHRS (CoolStep threshold)
- Set register COOLCONF (CoolStep)
- Set Standstill mode
- Enable/disable driver by software
- Move to absolute position
- Move to relative position
- Start TMC2209 internal step generator
- Stop TMC2209 internal step generator
- StealthChop Automatic Tuning (AT)
- Download
Library Structure
The library consists of the following files:
TMC2209.h and TMC2209.c files are the main library files that contain configurations for the driver ic and functions to communicate with the ic over UART. There are also functions like move() and setAcceleration() that are just a wrapper for functions included in the stepperCon library.
uart.h and uart.c: UART library to serial interface with the driver IC. By default it uses UART 1 but it can be changed to 0 if your microcontroller doesn't have two uarts.
utils.h and utils.c: included by uart headers. Contains functions and settings that might be used by other libraries such as converting an integer or float to a string for example.
micros.h and micros.c: keeps track of microseconds with 40 microseconds resolution. Included by stepperCon.h. Default timer used is Timer2. Here F_CPU is defined as 16MHz. Consider modifying this if your microcontroller uses different frequency.
stepperCon.h and stepperCon.c: included by TMC2209.h. A library used to control stepper motor drivers.
stepperConfig.h and stepperConfig.c: included by stepperCon.h. Contains pin definitions and custom functions used to control the stepper motor driver.
Optionally a pin interrupt can be used to trigger an interrupt when StallGuard pulls DIAG pin high. Using this pin interrupt library you can easily setup an interrupt for any microcontroller pin.
Default Settings
At the beginning of the TMC2209.h file there are default settings that consist of:
TMC_UART_BAUD_RATE: UART baud rate for serial communication with the TMC2209 chip. Default 115200.
TMC_USE_HARDWARE_ENABLE_PIN: enable pin can be tied to ground and the driver can be disabled by software. Set to 1 if EN pin is controlled by the microcontroller or 0 if not.
After this settings, follows default values for the TMC2209 registers. These default values are written to the registers by TMC_init() that is called by TMC_addDriver(). If the TMC2209 chip is reset, the registers will be reset to their factory default values so the TMC_init() function must be used to reconfigure the registers with user default values.
F_CPU: is defined as
16MHz inside micros.h. Consider modifying this if your microcontroller
uses different frequency.F_CPU is best to be defined inside project properties in Microchip Studio or a Makefile if custom Makefiles are used. Please see https://www.programming-electronics-diy.xyz/2024/01/defining-fcpu.html for more details.
MAX_NR_OF_STEPPER_DRIVERS: defined by stepperConfig.h. This sets the maximum number of drivers
supported, by setting the size of an array. Default is 2.
Usage
TMC2209 library usage example: in this file is some working code showing how most of the functions could
be implemented.
Documentation
Create a structure object for each driver
TMC* TMC_addDriver(uint8_t driver_addr, uint16_t steps_per_revolution)
Initialization function used to add a driver. Creates a stepperCon and a TMC
structure objects. Calls TMC_init().
driver_addr: serial address of the driver
steps_per_revolution: steps per revolution (usually 200). For 1.8 degree motor (360 / 1.8 =
200).
Return: a pointer to a TMC structure object or null in case of an error such as there is no more room in the array for a new object pointer.
Initialization
uint8_t TMC_init(TMC* self)
Used by TMC_addDriver(). Used to initiate the UART and to set the TMC2209 to
default values using macros that can have values defined by the user.
self: pointer to a TMC structure object
Return: 1 if a serial communication error occurs
Read IC version
uint8_t TMC_readVersion(TMC* self)
Returns IC version. 0x21 = first version of the IC.
Read Global Status Flags (GSTAT)
uint8_t TMC_readStatus(TMC* self)
Returns the 3 status bits of the GSTAT register and clears them on the device.
Use the associated functions to check which flag is set.
GSTAT check if module was Reset
uint8_t TMC_statusIsReset(TMC* self)
Returns 1 if the device has been reset since the last read. The initialization
function should be used again to reconfigure the registers. Use after
TMC_readStatus().
GSTAT check if Driver Error
uint8_t TMC_statusDriverError(TMC* self)
Returns 1 if the driver has been shut down due to over temperature or short circuit detection since the last read access. Read DRV_STATUS for details. The flag can only be cleared when all error conditions are cleared. Use after TMC_readStatus().
GSTAT check if Charge Pump is Under Voltage
uint8_t TMC_statusChargePumpUV(TMC* self)
Returns 1 if an under voltage on the charge pump has been detected. The driver is disabled in this case. This flag is not latched and thus does not need to be cleared. Use after TMC_readStatus().
Status check for UART error
uint8_t TMC_deviceConnectionLost(TMC* self)
Returns 1 if the communication failure flag is set. This flag is set when CRC
fails, wrong number of bytes is received or write confirmation is not
received. The flag is cleared automatically by read/write functions.
Read register PWM_SCALE_SUM
uint8_t TMC_readPwmScaleSum(TMC* self)
Information about the motor state is available with automatic scaling by
reading out PWM_SCALE_SUM. As this parameter reflects the actual voltage
required to drive the target current into the motor, it depends on several
factors: motor load, coil resistance, supply voltage, and current setting.
Therefore, an evaluation of the PWM_SCALE_SUM value allows checking the motor
operation point. When reaching the limit (255), the current regulator cannot
sustain the full motor current, e.g. due to a drop in supply volage.
Return: PWM_SCALE_SUM (0...255) which is bits 0...7 of the PWM_SCALE register
Read register PWM_SCALE_AUTO
int16_t TMC_readPwmScaleAuto(TMC* self)
Read back of the actual StealthChop voltage PWM scaling correction as
determined by the current regulator. Should regulate to a value close to 0
during tuning procedure. Scaling value becomes frozen when operating in
SpreadCycle.
Return: PWM_SCALE_AUTO (-255...255) which is bits 16...24 of the PWM_SCALE register
Read register PWM_OFS_AUTO
uint8_t TMC_readPwmOfsAuto(TMC* self)
Automatically determined offset value. Allow monitoring of the automatic
tuning and determination of initial values for PWM_OFS and PWM_GRAD.
Return: PWM_OFS_AUTO (0...255) which is bits 0...7 of the PWM_AUTO register
Read register PWM_GRAD_AUTO
uint8_t TMC_readPwmGradAuto(TMC* self)
Automatically determined gradient value. Allow monitoring of the automatic tuning and determination of initial values for PWM_OFS and PWM_GRAD.
Return: PWM_GRAD_AUTO (0...255) which is bits 16...23 of the PWM_AUTO register
Read register SG_RESULT (StallGuard)
uint16_t TMC_readStallGuard(TMC* self)
SG_RESULT becomes updated with each fullstep. A higher value signals a lower
motor load and more torque headroom. Intended for StealthChop mode, only.
Return: StallGuard result (0...510). A higher reading indicates less mechanical load. A lower reading indicates a higher load and thus a higher load angle.
Read register TSTEP
uint32_t TMC_readTstep(TMC* self)
Actual measured time between two 1/256 microsteps derived from the step input frequency in units of 1/fCLK. Measured value is (2^20)-1 in case of overflow or stand still.
Read register DRV_STATUS (Driver Status Flags)
uint32_t TMC_readDrvStat(TMC* self)
Return: the 32 bits register. Use the associated functions to check each driver
status.
DRV_STATUS check Standstill
bool TMC_checkStandstil(TMC* self)
This flag indicates motor stand still in each operation mode. This occurs 2^20
clocks after the last step pulse.
Return: 0 or 1 flag
DRV_STATUS check Chopper type
bool TMC_checkChopper(TMC* self)
1: Driver operates in StealthChop mode
0: Driver operates in SpreadCycle mode
Return: 0 or 1 flag representing active chopper type. Optionally, the following
macros are available that can be used in an if condition for more
readability.
// Chopper mode returned by DRV_STATUS SPREAD_CYCLE_MODE 0 STEALTH_CHOP_MODE 1
DRV_STATUS check CS_ACTUAL
uint8_t TMC_checkCS(TMC* self)
Actual current control scaling, for monitoring the function of the automatic
current scaling.
Return: current scaling value (0...31)
DRV_STATUS check Temperature flags
uint8_t TMC_checkTempFlags(TMC* self)
Return: 4 flags, each flag representing a temperature threshold. Bit 0 (t120), bit
1 (t143), bit 2 (t150), bit 3 (t157).
See datasheet chapter 15.1 for details.
DRV_STATUS check Open Load flags
uint8_t TMC_checkOpenLoad(TMC* self)
1: Open load detected on phase A or B.
Hint: This is just an informative flag. The driver takes no action upon it.
False detection may occur in fast motion and standstill. Check during slow
motion, only.
Return: 2 flags. Bit 0 (open load indicator phase A), bit 1 (open load indicator phase B). See datasheet chapter 15.3 for details.
DRV_STATUS check Low Side Short flags
uint8_t TMC_checkLowSideShort(TMC* self)
1: Short on low-side MOSFET detected on phase A or B.
The driver becomes disabled. The flags stay active, until the driver is
disabled by software (TOFF=0) or by the ENN input. Flags are separate for both
chopper modes.
Return: 2 flags. Bit 0 (low side short indicator phase A), bit 1 (low side short indicator phase B). See datasheet chapter 15.2 for details.
DRV_STATUS check Short to Ground flags
uint8_t TMC_checkShortToGnd(TMC* self)
1: Short to GND detected on phase A or B.
The driver becomes disabled. The flags stay active, until the driver is
disabled by software (TOFF=0) or by the ENN input. Flags are separate for both
chopper modes.
Return: 2 flags. Bit 0 (short to ground indicator phase A), bit 1 (short to ground indicator phase B). See datasheet chapter 15.2 for details.
DRV_STATUS check Over-temperature flag
uint8_t TMC_checkOverTemp(TMC* self)
1: The selected over-temperature limit has been reached.
Drivers become disabled until otpw (Over Temperature Pre-warning) is also cleared due to cooling down of the IC. The over-temperature flag is common for both bridges.
Return: 0 or 1 flag. See datasheet chapter 15.1 for details.
DRV_STATUS check Over-temperature Pre-warning flag
uint8_t TMC_checkOverTempPreWarning(TMC* self)
1: The selected over-temperature pre-warning threshold is exceeded.
The over-temperature pre-warning flag is common for both bridges.
Return: 0 or 1 flag. See datasheet chapter 15.1 for details.
Set micro-step resolution
void TMC_setMicrostepResolution(TMC* self, uint16_t mstep_res)
Select microstep resolution. Sets MRES bits in CHOPCONF register.
Example: the stepper is 200 steps/revolution type, and microstep resolution is 16 (mstep_res is MRES_16). To make a full revolution now the stepper requires 3200 steps (200 * 16).
mstep_res: microstep resolution as defined by these macros:
MRES_1, MRES_2, MRES_4, MRES_8, MRES_16, MRES_32, MRES_64, MRES_128,
MRES_256. The suffix represents the micro-step resolution.
Set speed
void TMC_setSpeed(TMC* self, float speed)
Sets the speed in steps per second at which the motor should run. The set
speed can only be reached if there is enough steps (distance), if not, try
increasing the acceleration. The maximum speed can be reached when the speed
profile is trapezoid. Wrapper of stepperCon.stepperSetSpeed().
Set acceleration and deceleration
void TMC_setAcceleration(TMC* self, uint32_t acceleration) void TMC_setDeceleration(TMC* self, uint32_t deceleration)
Set acceleration and deceleration rate in steps/second2. The given values will
be multiplied by ACCEL_SCALING_FACTOR(100) so the user can use a lower number
for readability. So instead of using 15000 use 150. The deceleration will also
be set with the acceleration value, so in case that they have the same value,
running setDeceleration() is not necessary.
Wrapper of stepperCon.stepperSetAcceleration().
Set direction
void TMC_setDirection(TMC* self, int8_t dir)
Inverse spin direction. Sets the shaft bit in GCONF register. Normally
the direction is set by the move() functions based on the sign of the distance
but if that doesn't fit your needs then the direction can be inverted.
dir: direction can be one of the following macros: DIRECTION_CW or
DIRECTION_CCW (clockwise or counter-clockwise).
Set chopper
void TMC_setChopper(TMC* self, bool chopper)
Switch between StealthChop and SpreadCycle. Sets en_SpreadCycle bit in
GCONF register.
chopper: available macros:
STEALTH_CHOP 0 SPREAD_CYCLE 1
Set SpreadCycle threshold
uint32_t TMC_spreadCycleThreshold(TMC* driver, uint16_t rpm_threshold)
Writes TPWMTHRS register. When the velocity exceeds the limit set by TPWMTHRS,
the driver switches to SpreadCycle. Set TPWMTHRS zero if you want to work with
StealthChop only. RPM is converted to TSTEP.
rpm_threshold: velocity threshold in RPM. When the motor velocity exceeds this threshold,
the driver switches to SpreadCycle.
Return: calculated TSTEP value written to the register.
Set register IHOLD_IRUN
void TMC_setIrunIhold(TMC* driver, uint8_t irun, uint8_t ihold, uint8_t ihold_delay)
Used to set the motor run and standstill current.
irun: (reset default=31). Motor run current (0=1/32 … 31=32/32). Hint: Choose sense resistors in a way, that normal IRUN is 16 to 31 for best micro-step performance.
ihold: (reset default: OTP). Standstill current (0=1/32 … 31=32/32). In combination with StealthChop mode, setting IHOLD=0 allows to choose freewheeling or coil short circuit (passive braking) for motor stand still.
ihold_delay: (reset default: OTP). Controls the number of clock cycles for motor power down after standstill is detected (stst=1) and TPOWERDOWN has expired. The smooth transition avoids a motor jerk upon power down.
0: instant power down
1..15: delay per current reduction step in multiple of 2^18 clocks
Hint: use the provided spreadsheet calculator to convert time to number of
clocks.
Set register TPOWERDOWN
void TMC_setTPowerDown(TMC* driver, uint8_t value)
Sets the delay time from stand still detection to motor current power down. Time range is about 0 to 5.6 seconds. 0…((2^8)-1) * 2^18 tCLK.
Attention: A minimum setting of 2 is required to allow automatic tuning of StealthChop PWM_OFFS_AUTO.
value = time(s) / (1 / 12MHz) / 2^18
tclk = 1 / 12MHz
time(s) = value * 2^18 * tclk
value: 0 to 255 (255 is 5.6 seconds). Reset default = 20.
Hint: use the provided spreadsheet calculator to convert time to register
value.
Set register SGTHRS (StallGuard)
void TMC_setStallGuard(TMC* self, uint8_t value)
Detection threshold for stall. The StallGuard value SG_RESULT becomes compared to the double of this threshold.
Note: Sensor-less homing/probing is not recommend for machines that use a lead screws due to high torque.
value: SGTHRS value (0...255). This value controls the StallGuard4 threshold level for stall detection. It compensates for motor specific characteristics and controls sensitivity. A higher value gives a higher sensitivity. A higher value makes StallGuard4 more sensitive and requires less torque to indicate a stall. The stall output becomes active if SG_RESULT fall below this value. See datasheet chapter 11 for details.
Set register TCOOLTHRS (CoolStep threshold)
void TMC_coolStepThreshold(TMC* self, uint16_t rpm_threshold)
This is the lower threshold velocity for switching on smart energy CoolStep
and StallGuard to DIAG output. Set this parameter to disable CoolStep at low
speeds, where it cannot work reliably. The stall output signal become enabled
when exceeding this velocity. It becomes disabled again once the velocity
falls below this threshold. Specifies lower CoolStep velocity by comparing the
threshold value to TSTEP. RPM is converted to TSTEP inside the function.
TCOOLTHRS ≥ TSTEP > TPWMTHRS
- CoolStep is enabled, if configured (only with StealthChop)
- Stall output signal on pin DIAG is enabled
rpm_threshold: velocity threshold in RPM. When the motor velocity exceeds this threshold, the driver enables CoolStep and stall output. See datasheet chapter 12 for details.
Set register COOLCONF (CoolStep)
void TMC_setCoolStep(TMC* self, uint16_t semin, uint8_t semax, uint8_t seup, uint8_t sedn, uint8_t seimin)
Register values for CoolStep configuration. See datasheet chapter 12 for details.
semin: minimum StallGuard value for smart current control and smart current enable (1...15). If the StallGuard result falls below SEMIN*32, the motor current becomes increased to reduce motor load angle.
0000: smart current control CoolStep off
0001…1111: 1…15
semax: StallGuard hysteresis value for smart current control (1...15). If the
StallGuard result is equal to or above (SEMIN+SEMAX+1)*32, the motor current
becomes decreased to save energy.
0000…1111: 0…15
seup: current up step width. Current increment steps per measured StallGuard value.
00…11: 1, 2, 4, 8
Optionally these macros could be use for clarity:
SEUP_1 0 SEUP_2 1 SEUP_4 2 SEUP_8 3
sedn: current down step speed.
%00: For each 32 StallGuard4 values decrease by one
%01: For each 8 StallGuard4 values decrease by one
%10: For each 2 StallGuard4 values decrease by one
%11: For each StallGuard4 value decrease by one
Optionally these macros could be use for clarity:
SEDN_32 0 SEDN_8 1 SEDN_2 2 SEDN_1 3
seimin: minimum current for smart current control.
0: 1/2 of current setting (IRUN)
1: 1/4 of current setting (IRUN)
Optionally these macros could be use for clarity:
SEIMIN_1_2 0 // 1/2 of current setting (IRUN) SEIMIN_1_4 1 // 1/4 of current setting (IRUN)
Set Standstill mode
void TMC_setStandstillMode(TMC* self, uint8_t mode)
Sets freewheel bits in PWMCONF register. Only available with StealthChop enabled. The freewheeling option makes the motor easy movable, while both coil short options realize a passive brake. See datasheet chapter 6.7 for details.
Notes:
- IHOLD must be set to 0 first except when using normal operation (mode 00).
- Open load flag will be set
- Driver must be enabled
mode: stand still option when motor current setting is zero (I_HOLD=0).
00: Normal operation
01: Freewheeling
10: Coil shorted using LS drivers
11: Coil shorted using HS drivers
Available macros:
// Freewheel bits NORMAL_OPERATION 0x00 FREEWHEELING 0x01 COIL_SHORTED_LS 0x02 COIL_SHORTED_HS 0x03
Enable/disable driver by software
void TMC_softEnable(TMC* self, bool enable)
To save microcontroller pins, the enable pin can be connected to ground, thus
keeping the drive enabled and then disable the driver using this function.
Writes TOFF bits inside the CHOPCONF register.
enable:
0 - disable the driver by setting TOFF to 0
1 - restores TOFF off time with previous values
Move to absolute position
void TMC_moveTo(TMC* self, int32_t absolute)
Move the motor using absolute positioning. The stepping is not done here. The function sets the logical and pin direction and calculates the number of steps necessary to reach the target position then sets a flag that triggers the segment generation function that in turn triggers the ISR where the stepping is done. Negative values changes direction. Wrapper of stepperCon.stepperMoveTo().
This function will not do anything if:
- the motor is still running
- the current position and target position are the same
- the set speed is 0
Move to relative position
void TMC_move(TMC* self, int32_t relative)
Move the motor using relative positioning. See TMC_moveTo().
Start TMC2209 internal step generator
void TMC_startStepGeneratorRPS(TMC* self, float rps, uint16_t accel, float* accel_time_ms, float* vactual_p)
Writes VACTUAL register that allows moving the motor by UART control. Converts RPS speed to a "vactual" value which represents rotation speed in revolutions per second. A value other than 0 will activate the internal step generator. With internal oscillator: VACTUAL = v[Hz] / 0.715Hz.
After setting the internal step generator, the motor will spin at set velocity even if the microcontroller is at sleep. However, the TMC2209 chip doesn't provide acceleration and deceleration. At slow speeds this might not be an issue but after a certain speed, the acceleration is needed. This function implements a simple but efficient acceleration algorithm using the micros library.
rps: velocity in RPS. If negative the rotation will be inverted. If 0 the motor will be controlled by the STEP input pin.
accel: acceleration value (e.g. 20, 100)
accel_time_ms: pointer to a float variable defined by the user where the total
acceleration time will be stored. Needed for deceleration.
vactual_p: pointer to a float variable defined by the user where vactual value will be saved. Needed for deceleration.
void TMC_startStepGeneratorRPM(TMC* self, float rpm, uint16_t accel, float* accel_time_ms, float* vactual_p)
Wrapper to TMC_startStepGeneratorRPS() that converts RPM to RPS.
rpm: velocity in RPM. If negative the rotation will be inverted. If 0 the motor will be controlled by the STEP input pin.
Stop TMC2209 internal step generator
void TMC_stopStepGenerator(TMC* self, uint16_t decel, float accel_time_ms, float vactual)
Stops the internal step generator using deceleration.
decel: deceleration value (e.g. 20, 100)
accel_time_ms: saved value during acceleration
vactual_p: saved value during acceleration
StealthChop Automatic Tuning (AT)
void TMC_stealthChopAT(TMC* self, uint8_t irun)
Automatic Tuning (AT) of StealthChop following AT#1 step from the datasheet (chapter 6.1). This function could be used before homing or any other movement that must be done for AT#2.
The function does the following:
- Sets IHOLD same as IRUN
- Sets TPOWERDOWN to a larger value to prevent automatic power down before tuning is done
- Sets SpreadCycle threshold to 0 to prevent changing to SpreadCycle at threshold velocity
- Enables the driver using EN pin or by software
- Makes 1 step to exit a potential stand still mode
- Wait for 130ms
irun: IRUN current scale value used in your application (1...31)
Links
v1.2 | TMC2209 library | Folder including all files that can be downloaded as a zip file |
v1.0 | TMC2209 calculator.ods | LibreOffice spreadsheet ods file |
TMC2209 datasheet v1.03.pdf | TMC2209 datasheet that includes bookmarks | |
External Links | ||
https://learn.watterott.com/silentstepstick | More information about TMC drivers | |
Changelog | ||
v1.2 | 2/2/2024: - added support for modern AVR devices (UPDI devices). |
|
v1.0 | TMC2209 release date 20, December, 2023, under GNU GPL v3 license |
No comments:
Post a Comment