|
|
|
|
@ -1,13 +1,14 @@
|
|
|
|
|
#include "../tmc2130.h"
|
|
|
|
|
#include "../../config/config.h"
|
|
|
|
|
|
|
|
|
|
namespace hal {
|
|
|
|
|
namespace tmc2130 {
|
|
|
|
|
|
|
|
|
|
TMC2130::TMC2130(const MotorParams ¶ms,
|
|
|
|
|
const MotorCurrents ¤ts,
|
|
|
|
|
MotorMode mode)
|
|
|
|
|
: currents(currents) {
|
|
|
|
|
// TODO
|
|
|
|
|
TMC2130::TMC2130(const MotorParams ¶ms, const MotorCurrents ¤ts, MotorMode mode)
|
|
|
|
|
: mode(mode)
|
|
|
|
|
, currents(currents)
|
|
|
|
|
, sg_counter(0) {
|
|
|
|
|
Init(params);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool TMC2130::Init(const MotorParams ¶ms) {
|
|
|
|
|
@ -17,22 +18,24 @@ bool TMC2130::Init(const MotorParams ¶ms) {
|
|
|
|
|
|
|
|
|
|
///check for compatible tmc driver (IOIN version field)
|
|
|
|
|
uint32_t IOIN = ReadRegister(params, Registers::IOIN);
|
|
|
|
|
if (((IOIN >> 24) != 0x11) | !(IOIN & (1 << 6))) ///if the version is incorrect or an always 1 bit is 0 (the supposed SD_MODE pin that doesn't exist on this driver variant)
|
|
|
|
|
|
|
|
|
|
// if the version is incorrect or an always 1st bit is 0
|
|
|
|
|
// (the supposed SD_MODE pin that doesn't exist on this driver variant)
|
|
|
|
|
if (((IOIN >> 24U) != 0x11) | !(IOIN & (1U << 6U)))
|
|
|
|
|
return true; // @todo return some kind of failure
|
|
|
|
|
|
|
|
|
|
///clear reset_flag as we are (re)initializing
|
|
|
|
|
errorFlags.reset_flag = false;
|
|
|
|
|
|
|
|
|
|
///apply chopper parameters
|
|
|
|
|
uint32_t chopconf = 0;
|
|
|
|
|
chopconf |= (uint32_t)(3 & 0x0F) << 0; //toff
|
|
|
|
|
chopconf |= (uint32_t)(5 & 0x07) << 4; //hstrt
|
|
|
|
|
chopconf |= (uint32_t)(1 & 0x0F) << 7; //hend
|
|
|
|
|
chopconf |= (uint32_t)(2 & 0x03) << 15; //tbl
|
|
|
|
|
chopconf |= (uint32_t)(currents.vSense & 0x01) << 17; //vsense
|
|
|
|
|
chopconf |= (uint32_t)(params.uSteps & 0x0F) << 24; //mres
|
|
|
|
|
chopconf |= (uint32_t)((bool)params.uSteps) << 28; //intpol
|
|
|
|
|
chopconf |= (uint32_t)(1 & 0x01) << 29; //dedge
|
|
|
|
|
const uint32_t chopconf = (uint32_t)(3U & 0x0FU) << 0U //toff
|
|
|
|
|
| (uint32_t)(5U & 0x07U) << 4U //hstrt
|
|
|
|
|
| (uint32_t)(1U & 0x0FU) << 7U //hend
|
|
|
|
|
| (uint32_t)(2U & 0x03U) << 15U //tbl
|
|
|
|
|
| (uint32_t)(currents.vSense & 0x01U) << 17U //vsense
|
|
|
|
|
| (uint32_t)(params.uSteps & 0x0FU) << 24U //mres
|
|
|
|
|
| (uint32_t)((bool)params.uSteps) << 28U //intpol
|
|
|
|
|
| (uint32_t)(1U & 0x01) << 29U; //dedge
|
|
|
|
|
WriteRegister(params, Registers::CHOPCONF, chopconf);
|
|
|
|
|
|
|
|
|
|
///apply currents
|
|
|
|
|
@ -42,25 +45,21 @@ bool TMC2130::Init(const MotorParams ¶ms) {
|
|
|
|
|
WriteRegister(params, Registers::TPOWERDOWN, 0);
|
|
|
|
|
|
|
|
|
|
///Stallguard parameters
|
|
|
|
|
int8_t sg_thrs = 3; // @todo 7bit two's complement for the sg_thrs
|
|
|
|
|
WriteRegister(params, Registers::COOLCONF, (((uint32_t)sg_thrs) << 16)); // @todo should be configurable
|
|
|
|
|
WriteRegister(params, Registers::TCOOLTHRS, 400); // @todo should be configurable
|
|
|
|
|
WriteRegister(params, Registers::COOLCONF, config::tmc2130_coolConf);
|
|
|
|
|
WriteRegister(params, Registers::TCOOLTHRS, config::tmc2130_coolStepThreshold);
|
|
|
|
|
|
|
|
|
|
///Write stealth mode config and setup diag0 output
|
|
|
|
|
uint32_t gconf = 0;
|
|
|
|
|
gconf |= (uint32_t)(1 & 0x01) << 2; //en_pwm_mode - always enabled since we can control it's effect with TPWMTHRS (0=only stealthchop, 0xFFFFF=only spreadcycle)
|
|
|
|
|
gconf |= (uint32_t)(1 & 0x01) << 7; //diag0_stall - diag0 is open collector => active low with external pullups
|
|
|
|
|
constexpr uint32_t gconf = (uint32_t)(1U & 0x01U) << 2U //en_pwm_mode - always enabled since we can control it's effect with TPWMTHRS (0=only stealthchop, 0xFFFFF=only spreadcycle)
|
|
|
|
|
| (uint32_t)(1U & 0x01U) << 7U; //diag0_stall - diag0 is open collector => active low with external pullups
|
|
|
|
|
WriteRegister(params, Registers::GCONF, gconf);
|
|
|
|
|
|
|
|
|
|
///stealthChop parameters
|
|
|
|
|
uint32_t pwmconf = 0; /// @todo All of these parameters should be configurable
|
|
|
|
|
pwmconf |= (uint32_t)(240 & 0xFF) << 0; //PWM_AMPL
|
|
|
|
|
pwmconf |= (uint32_t)(4 & 0xFF) << 8; //PWM_GRAD
|
|
|
|
|
pwmconf |= (uint32_t)(2 & 0x03) << 16; //pwm_freq
|
|
|
|
|
pwmconf |= (uint32_t)(1 & 0x01) << 18; //pwm_autoscale
|
|
|
|
|
constexpr uint32_t pwmconf = config::tmc2130_PWM_AMPL | config::tmc2130_PWM_GRAD | config::tmc2130_PWM_FREQ | config::tmc2130_PWM_AUTOSCALE;
|
|
|
|
|
WriteRegister(params, Registers::PWMCONF, pwmconf);
|
|
|
|
|
|
|
|
|
|
///TPWMTHRS: switching velocity between stealthChop and spreadCycle. Stallguard is also disabled if the velocity falls below this. Should be set as high as possible when homing.
|
|
|
|
|
/// TPWMTHRS: switching velocity between stealthChop and spreadCycle.
|
|
|
|
|
/// Stallguard is also disabled if the velocity falls below this.
|
|
|
|
|
/// Should be set as high as possible when homing.
|
|
|
|
|
SetMode(params, mode);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
@ -75,10 +74,9 @@ void TMC2130::SetMode(const MotorParams ¶ms, MotorMode mode) {
|
|
|
|
|
void TMC2130::SetCurrents(const MotorParams ¶ms, const MotorCurrents ¤ts) {
|
|
|
|
|
this->currents = currents;
|
|
|
|
|
|
|
|
|
|
uint32_t ihold_irun = 0;
|
|
|
|
|
ihold_irun |= (uint32_t)(currents.iHold & 0x1F) << 0; //ihold
|
|
|
|
|
ihold_irun |= (uint32_t)(currents.iRun & 0x1F) << 8; //irun
|
|
|
|
|
ihold_irun |= (uint32_t)(15 & 0x0F) << 16; //IHOLDDELAY
|
|
|
|
|
uint32_t ihold_irun = (uint32_t)(currents.iHold & 0x1F) << 0 //ihold
|
|
|
|
|
| (uint32_t)(currents.iRun & 0x1F) << 8 //irun
|
|
|
|
|
| (uint32_t)(15 & 0x0F) << 16; //IHOLDDELAY
|
|
|
|
|
WriteRegister(params, Registers::IHOLD_IRUN, ihold_irun);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -97,11 +95,11 @@ void TMC2130::ClearStallguard(const MotorParams ¶ms) {
|
|
|
|
|
bool TMC2130::CheckForErrors(const MotorParams ¶ms) {
|
|
|
|
|
uint32_t GSTAT = ReadRegister(params, Registers::GSTAT);
|
|
|
|
|
uint32_t DRV_STATUS = ReadRegister(params, Registers::DRV_STATUS);
|
|
|
|
|
errorFlags.reset_flag |= GSTAT & (1 << 0);
|
|
|
|
|
errorFlags.uv_cp = GSTAT & (1 << 2);
|
|
|
|
|
errorFlags.s2g = DRV_STATUS & (3ul << 27);
|
|
|
|
|
errorFlags.otpw = DRV_STATUS & (1ul << 26);
|
|
|
|
|
errorFlags.ot = DRV_STATUS & (1ul << 25);
|
|
|
|
|
errorFlags.reset_flag |= GSTAT & (1U << 0U);
|
|
|
|
|
errorFlags.uv_cp = GSTAT & (1U << 2U);
|
|
|
|
|
errorFlags.s2g = DRV_STATUS & (3UL << 27U);
|
|
|
|
|
errorFlags.otpw = DRV_STATUS & (1UL << 26U);
|
|
|
|
|
errorFlags.ot = DRV_STATUS & (1UL << 25U);
|
|
|
|
|
|
|
|
|
|
return GSTAT || errorFlags.reset_flag; //any bit in gstat is an error
|
|
|
|
|
}
|
|
|
|
|
|