Arduino library for Trinamic TMC2208 Stepper driver
- Wiring setup
- Example
- Writing to a register
- Reading from a register
- Using the functions
- Helper functions
- Setting registers
- Bit positions and bit masks
- Datasheet
With Watterott SilentStepStick2208 TMC2208 powered stepper drivers with UART single wire interface, first make a solder bridge across J2 near PDN_UART pin located in the middle of the driver.
To write to the driver, connect the microcontroller TX line to PDN_UART.
To allow both writing and reading with the driver, connect microcontroller RX to PDN_UART and connect microcontroller TX to RX with a 1kOhm resistor.
Image by Watterott
#define EN_PIN 13 // LOW: Driver enabled. HIGH: Driver disabled
#define STEP_PIN 54 // Step on rising edge
#include <TMC2208Stepper.h> // Include library
TMC2208Stepper driver = TMC2208Stepper(&Serial); // Create driver and use
// HardwareSerial0 for communication
void setup() {
Serial.begin(115200); // Init used serial port
while(!Serial); // Wait for port to be ready
// Prepare pins
pinMode(EN_PIN, OUTPUT);
pinMode(STEP_PIN, OUTPUT);
driver.pdn_disable(1); // Use PDN/UART pin for communication
driver.I_scale_analog(0); // Adjust current from the registers
driver.rms_current(500); // Set driver current 500mA
driver.toff(0x2); // Enable driver
digitalWrite(13, LOW); // Enable driver
}
void loop() {
digitalWrite(STEP_PIN, !digitalRead(STEP_PIN)); // Step
delay(10);
}
Writing to a register will update the shadow register held by the library and then push the result to the driver.
uint32_t my_ihold_irun = 0x140C; // Set IRUN to 20 (DEC) and IHOLD to 12 (DEC)
driver.IHOLD_IRUN(my_ihold_irun);
Writing to a register will return a boolean value indicating whether the CRC was valid. You need to give the function an address to the 32bit variable into which the function will store the response.
uint32_t data;
driver.DRV_STATUS(&data);
Serial.println(data, BIN);
All functions to Read and Write and Write-only registers provide both Read and Write capabilities. If the register is Write-only, the value will be read from a shadow register held by the library. Read functions to Read registers will read the register value and then bit mask and bit shift it for you. All non-helper functions write the given bit pattern to the register.
driver.tbl(0b10); // Is the same as...
driver.tbl(2); // And will set the blank time to 32
// Read value from register
uint8_t my_blank_time = driver.tbl();
Function | Description |
---|---|
void rms_current( uint16_t float float ) |
Set motor RMS current Arguments: uint16_t current_rms Optional: float hold current multiplier (default=0.5) float sense resistor value (default=0.11) |
uint16_t rms_current() | Reads rms_current based on the register settings |
void setCurrent( uint16_t float float ) |
(legacy) Same as rms_current but rsense and hold current arguments are switched. No defaults so requires all three parameters. |
uint16_t getCurrent() | Read back the user input value for rms_current() or setCurrent() |
void microsteps(uint16_t) | [0..256] Set number of microsteps |
bool checkOT() | Read otpw flag from DRV_STATUS register and return the result. Also store the result in variable held by the library. |
bool getOTPW() | Return the flag value set by checkOT() |
void clear_otpw() | Clear the flag held by the libarary |
Function | Description |
---|---|
bool GCONF(uint32_t *) | Read GCONF register |
void GCONF(uint32_t) | Write to the GCONF register |
void I_scale_analog(bool) | (Reset default=1) 0: Use internal reference derived from 5VOUT 1: Use voltage supplied to VREF as current reference |
void internal_Rsense(bool) | (Reset default: OTP) 0: Operation with external sense resistors 1: Internal sense resistors. Use current supplied into VREF as reference for internal sense resistor. VREF pin internally is driven to GND in this mode. |
void en_spreadCycle(bool) | (Reset default: OTP) 0: stealthChop PWM mode enabled (depending on velocity thresholds). Initially switch from off to on state while in stand still, only. 1: spreadCycle mode enabled |
void shaft(bool) | 1: Inverse motor direction |
void index_otpw(bool) | 0: INDEX shows the first microstep position of sequencer 1: INDEX pin outputs overtemperature prewarning flag (otpw) instead |
void index_step(bool) | 0: INDEX output as selected by index_otpw 1: INDEX output shows step pulses from internal pulse generator (toggle upon each step) |
void pdn_disable(bool) | 0: PDN_UART controls standstill current reduction 1: PDN_UART input function disabled. Set this bit, when using the UART interface! |
void mstep_reg_select(bool) | 0: Microstep resolution selected by pins MS1, MS2 1: Microstep resolution selected by MSTEP register |
void multistep_filt(bool) | (Reset default=1) 0: No filtering of STEP pulses 1: Software pulse generator optimization enabled when fullstep frequency > 750Hz (roughly). TSTEP shows filtered step time values when active. |
Function | Description |
---|---|
void GSTAT(uint32_t) | Write to GSTAT register |
bool GSTAT(uint32_t*) | Read GSTAT register |
void reset(bool) | 1: Indicates that the IC has been reset since the last read access to GSTAT. All registers have been cleared to reset values. |
void drv_err(bool) | 1: Indicates, that the driver has been shut down due to overtemperature 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. |
void uv_cp(bool) | 1: Indicates an undervoltage on the charge pump. The driver is disabled in this case. This flag is not latched and thus does not need to be cleared. |
Function | Description |
---|---|
bool IFCNT(uint32_t*) | Interface transmission counter. This register becomes incremented with each successful UART interface write access. Read out to check the serial transmission for lost data. Read accesses do not change the content. The counter wraps around from 255 to 0. |
Function | Description |
---|---|
void SLAVECONF(uint32_t) | Write register |
bool SLAVECONF(uint32_t*) | Read register |
void senddelay(uint8_t) | SENDDELAY for read access (time until reply is sent): 0, 1: 8 bit times 2, 3: 38 bit times 4, 5: 58 bit times 6, 7: 78 bit times 8, 9: 98 bit times 10, 11: 118 bit times 12, 13: 138 bit times 14, 15: 15*8 bit times |
Function | Description |
---|---|
void OTP_PROG(uint32_t) | OTP_PROGRAM – OTP programming Write access programs OTP memory (one bit at a time), Read access refreshes read data from OTP after a write 2..0 OTPBIT Selection of OTP bit to be programmed to the selected byte location (n=0..7: programs bit n to a logic 1) 5..4 OTPBYTE Selection of OTP programming location (0, 1 or 2) 15..8 OTPMAGIC Set to 0xbd to enable programming. A programming time of minimum 10ms per bit is recommended (check by reading OTP_READ). |
Function | Description |
---|
Function | Description |
---|---|
bool IOIN(uint32_t*) | INPUT (Reads the state of all input pins available) |
bool enn() | ENN |
bool ms1() | MS1 |
bool ms2() | MS2 |
bool diag() | DIAG |
bool pdn_uart() | PDN_UART |
bool step() | STEP |
bool sel_a() | SEL_A: Driver type 1: TMC220x 0: TMC222x |
bool dir() | DIR |
uint8_t version() | VERSION: 0x20=first version of the IC Identical numbers mean full digital compatibility. |
Function | Description |
---|---|
void FACTORY_CONF(uint32_t) | Write register |
bool FACTORY_CONF(uint32_t*) | Read register |
void fclktrim(uint8_t) | 0…31: Lowest to highest clock frequency. Check at charge pump output. The frequency span is not guaranteed, but it is tested, that tuning to 12MHz internal clock is possible. The devices come preset to 12MHz clock frequency by OTP programming. |
void ottrim(uint8_t) | %00: OT=143°C, OTPW=120°C %01: OT=150°C, OTPW=120°C %10: OT=150°C, OTPW=143°C %11: OT=157°C, OTPW=143°C |
Function | Description |
---|---|
void IHOLD_IRUN(uint32_t) | |
bool IHOLD_IRUN(uint32_t*) | |
void ihold(uint8_t) | (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. |
void irun(uint8_t) | (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 microstep performance. |
void iholddelay(uint8_t) | (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 |
Function | Description |
---|---|
void TPOWERDOWN(uint32_t) | (Reset default=20) Sets the delay time from stand still (stst) 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. |
bool TPOWERDOWN(uint32_t*) |
Function | Description |
---|---|
bool TSTEP(uint32_t*) | 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. The TSTEP related threshold uses a hysteresis of 1/16 of the compare value to compensate for jitter in the clock or the step frequency: (Txxx*15/16)-1 is the lower compare value for each TSTEP based comparison. This means, that the lower switching velocity equals the calculated setting, but the upper switching velocity is higher as defined by the hysteresis setting. |
Function | Description |
---|---|
void TPWMTHRS(uint32_t) | Sets the upper velocity for stealthChop voltage PWM mode. TSTEP ≥ TPWMTHRS - stealthChop PWM mode is enabled, if configured When the velocity exceeds the limit set by TPWMTHRS, the driver switches to spreadCycle. 0: Disabled |
bool TPWMTHRS(uint32_t*) |
Function | Description |
---|---|
void VACTUAL(uint32_t) | VACTUAL allows moving the motor by UART control. It gives the motor velocity in +-(2^23)-1 [μsteps / t] 0: Normal operation. Driver reacts to STEP input. 0: Motor moves with the velocity given by VACTUAL. Step pulses can be monitored via INDEX output. The motor direction is controlled by the sign of VACTUAL. |
bool VACTUAL(uint32_t *) |
Function | Description |
---|---|
bool MSCNT(uint32_t*) | Microstep counter. Indicates actual position in the microstep table for CUR_A. CUR_B uses an offset of 256 into the table. Reading out MSCNT allows determination of the motor position within the electrical wave. |
Function | Description |
---|---|
bool MSCURACT(uint32_t*) | |
uint16_t cur_a() | CUR_A (signed): Actual microstep current for motor phase A as read from the internal sine wave table (not scaled by current setting) |
uint16_t cur_b() | CUR_B (signed): Actual microstep current for motor phase B as read from the internal sine wave table (not scaled by current setting) |
Function | Description |
---|---|
void CHOPCONF(uint32_t) | |
void toff(uint8_t) | off time and driver enable Off time setting controls duration of slow decay phase |
void hstrt(uint8_t) | hysteresis start value added to HEND %000 … %111: |
void hend(uint8_t) | hysteresis low value %0000 … %1111: |
void tbl(uint8_t) | blank time select %00 … %11: |
void vsense(bool) | sense resistor voltage based current scaling 0: Low sensitivity, high sense resistor voltage |
void mres(uint8_t) | micro step resolution %0000: |
void intpol(bool) | interpolation to 256 microsteps 1: The actual microstep resolution (MRES) becomes extrapolated to 256 microsteps |
void dedge(bool) | enable double edge step pulses 1: Enable step impulse at each step edge to reduce step frequency requirement. This mode |
void diss2g(bool) | 0: Short to GND protection is on 1: Short to GND protection is disabled |
void diss2vs(bool) | 0: Short protection low side is on 1: Short protection low side is disabled |
Function | Description |
---|---|
bool DRV_STATUS(uint32_t*) | |
bool otpw() | 1: The selected overtemperature pre-warning threshold is exceeded. The overtemperature pre-warning flag is common for both bridges. |
bool ot() | 1: The selected overtemperature limit has been reached. Drivers become disabled until otpw is also cleared due to cooling down of the IC. The overtemperature flag is common for both bridges. |
bool s2ga() | 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. |
bool s2gb() | |
bool s2vsa() | 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. |
bool s2vsb() | |
bool ola() | 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. |
bool olb() | |
bool t120() | 1: Temperature threshold is exceeded |
bool t143() | |
bool t150() | |
bool t157() | |
bool stealth() | 1: Driver operates in stealthChop mode 0: Driver operates in spreadCycle mode |
bool stst() | This flag indicates motor stand still in each operation mode. This occurs 2^20 clocks after the last step pulse. |
Function | Description |
---|---|
void PWMCONF(uint32_t) | |
void pwm_ofs(uint8_t) | User defined amplitude (offset) User defined PWM amplitude offset (0-255) related to full When using automatic scaling (pwm_autoscale=1) the value is PWM_OFS = 0 will disable scaling down motor current below a PWM_OFS > 0 allows automatic scaling to low PWM duty cycles even |
void pwm_grad(uint8_t) | User defined amplitude gradient Velocity dependent gradient for PWM amplitude: With automatic scaling (pwm_autoscale=1) the value is used for |
void pwm_freq(uint8_t) | PWM frequency frequency %00: fPWM=2/1024 fCLK |
void pwm_autoscale(bool) | PWM automatic amplitude scaling 0: User defined feed forward PWM amplitude. The current settings IRUN |
void pwm_autograd(bool) | PWM automatic gradient adaptation 0: Fixed value for PWM_GRAD Preconditions 1. PWM_OFS_AUTO has been automatically initialized. This requires 2. Motor running and |
void freewheel(uint8_t) | Allows different standstill modes Stand still option when motor current setting is zero (I_HOLD=0). |
void pwm_reg(uint8_t) | Regulation loop gradient User defined maximum PWM amplitude change per half wave when using |
void pwm_lim(uint8_t) | PWM automatic scale amplitude limit when switching on Limit for PWM_SCALE_AUTO when switching back from spreadCycle to stealthChop. |
Function | Description |
---|---|
bool PWM_SCALE(uint32_t*) | |
uint8_t pwm_scale_sum() | Results of stealthChop amplitude regulator. These values can be used to monitor automatic PWM amplitude scaling (255=max. voltage). bit 7… 0 PWM_SCALE_SUM: bit 24… 16 PWM_SCALE_AUTO: |
int16_t pwm_scale_auto() | These automatically generated values can be read out in order to determine a default / power up setting for PWM_GRAD and PWM_OFS. bit 7… 0 PWM_OFS_AUTO: bit 23… 16 PWM_GRAD_AUTO: |
You can gain access to the register bit position and bit masks with
#include <TMC2208Stepper_REGDEFS.h>
Register addresses follow the patter REG_<reg_name>
Bit positions are <setting>_bp
Bit masks are <setting>_bm
uint32_t my_gconf = (1 << SHAFT_bp) & SHAFT_bm;