tmc2130: Fix bug with vSense bit and current values

If vSense changes at runtime due to Run current
being changed. Then we must always shift the Hold current
correctly. Whether the vSense is changing 1 -> 0 or 0 ->1

Change in memory (with TMC2130_SERVICE_CODES_M910_M918):
Flash: +76 bytes
SRAM: 0 bytes
This commit is contained in:
Guðni Már Gilbert 2023-07-30 13:54:05 +00:00 committed by DRracer
parent a1a3194985
commit 02332018ec
4 changed files with 82 additions and 29 deletions

View File

@ -1085,8 +1085,8 @@ void setup()
#ifdef TMC2130
if(FarmOrUserECool()) {
//increased extruder current (PFW363)
currents[E_AXIS].iRun = TMC2130_CURRENTS_FARM;
currents[E_AXIS].iHold = TMC2130_CURRENTS_FARM;
currents[E_AXIS].setiRun(TMC2130_CURRENTS_FARM);
currents[E_AXIS].setiHold(TMC2130_CURRENTS_FARM);
}
#endif //TMC2130
@ -8064,8 +8064,8 @@ Sigma_Exit:
}
float cur_mA = code_value();
uint8_t val = tmc2130_cur2val(cur_mA);
currents[i].iHold = val;
currents[i].iRun = val;
currents[i].setiHold(val);
currents[i].setiRun(val);
tmc2130_setup_chopper(i, tmc2130_mres[i]);
}
}
@ -8140,7 +8140,7 @@ Sigma_Exit:
{
for (uint8_t axis = 0; axis < NUM_AXIS; axis++) {
if (code_seen(axis_codes[axis])) {
currents[axis].iHold = code_value_uint8();
currents[axis].setiHold(code_value_uint8());
tmc2130_setup_chopper(axis, tmc2130_mres[axis]);
}
}
@ -8164,7 +8164,7 @@ Sigma_Exit:
{
for (uint8_t axis = 0; axis < NUM_AXIS; axis++) {
if (code_seen(axis_codes[axis])) {
currents[axis].iRun = code_value_uint8();
currents[axis].setiRun(code_value_uint8());
tmc2130_setup_chopper(axis, tmc2130_mres[axis]);
}
}

View File

@ -61,11 +61,11 @@ void uvlo_() {
// Minimise Z and E motor currents (Hold and Run)
#ifdef TMC2130
currents[Z_AXIS].iHold = 20;
currents[Z_AXIS].iRun = 20;
currents[Z_AXIS].setiHold(20);
currents[Z_AXIS].setiRun(20);
tmc2130_setup_chopper(Z_AXIS, tmc2130_mres[Z_AXIS]);
currents[E_AXIS].iHold = 20;
currents[E_AXIS].iRun = 20;
currents[E_AXIS].setiHold(20);
currents[E_AXIS].setiRun(20);
tmc2130_setup_chopper(E_AXIS, tmc2130_mres[E_AXIS]);
#endif //TMC2130
@ -227,8 +227,8 @@ static void uvlo_tiny() {
disable_e0();
#ifdef TMC2130
currents[Z_AXIS].iHold = 20;
currents[Z_AXIS].iRun = 20;
currents[Z_AXIS].setiHold(20);
currents[Z_AXIS].setiRun(20);
tmc2130_setup_chopper(Z_AXIS, tmc2130_mres[Z_AXIS]);
#endif //TMC2130

View File

@ -419,7 +419,7 @@ void tmc2130_home_enter(uint8_t axes_mask)
tmc2130_wr(axis, TMC2130_REG_GCONF, TMC2130_GCONF_NORMAL);
tmc2130_wr(axis, TMC2130_REG_COOLCONF, (((uint32_t)tmc2130_sg_thr_home[axis]) << 16));
tmc2130_wr(axis, TMC2130_REG_TCOOLTHRS, __tcoolthrs(axis));
currents[axis].iRun = tmc2130_current_r_home[axis];
currents[axis].setiRun(tmc2130_current_r_home[axis]);
tmc2130_setup_chopper(axis, tmc2130_mres[axis]);
tmc2130_wr(axis, TMC2130_REG_GCONF, TMC2130_GCONF_SGSENS); //stallguard output DIAG1, DIAG1 = pushpull
}
@ -517,15 +517,15 @@ static constexpr bool getIntpolBit([[maybe_unused]]const uint8_t axis, const uin
}
static void SetCurrents(const uint8_t axis) {
uint8_t iHold = currents[axis].iHold;
const uint8_t iRun = currents[axis].iRun;
uint8_t iHold = currents[axis].getiHold();
const uint8_t iRun = currents[axis].getiRun();
// Make sure iHold never exceeds iRun at runtime
if (iHold > iRun) {
iHold = iRun;
// Update global array such that M913 reports correct values
currents[axis].iHold = currents[axis].iRun;
currents[axis].setiHold(iRun);
// Let user know firmware modified the value
SERIAL_ECHO_START;
@ -554,11 +554,8 @@ static void SetCurrents(const uint8_t axis) {
void tmc2130_setup_chopper(uint8_t axis, uint8_t mres)
{
// Update the currents, this will re-calculate the Vsense flag
currents[axis] = MotorCurrents(currents[axis].iRun, currents[axis].iHold);
// Initialise the chopper configuration
ChopConfU chopconf = ChopConfU(currents[axis].vSense, mres);
ChopConfU chopconf = ChopConfU(currents[axis].getvSense(), mres);
chopconf.s.intpol = getIntpolBit(axis, mres);
chopconf.s.toff = tmc2130_chopper_config[axis].toff; // toff = 3 (fchop = 27.778kHz)
@ -573,24 +570,24 @@ void tmc2130_setup_chopper(uint8_t axis, uint8_t mres)
void tmc2130_set_current_h(uint8_t axis, uint8_t current)
{
// DBG(_n("tmc2130_set_current_h(axis=%d, current=%d\n"), axis, current);
currents[axis].iHold = current;
currents[axis].setiHold(current);
tmc2130_setup_chopper(axis, tmc2130_mres[axis]);
}
void tmc2130_set_current_r(uint8_t axis, uint8_t current)
{
// DBG(_n("tmc2130_set_current_r(axis=%d, current=%d\n"), axis, current);
currents[axis].iRun = current;
currents[axis].setiRun(current);
tmc2130_setup_chopper(axis, tmc2130_mres[axis]);
}
void tmc2130_print_currents()
{
printf_P(_n("tmc2130_print_currents()\n\tH\tR\nX\t%d\t%d\nY\t%d\t%d\nZ\t%d\t%d\nE\t%d\t%d\n"),
currents[0].iHold, currents[0].iRun,
currents[1].iHold, currents[1].iRun,
currents[2].iHold, currents[2].iRun,
currents[3].iHold, currents[3].iRun
currents[0].getiHold(), currents[0].getiRun(),
currents[1].getiHold(), currents[1].getiRun(),
currents[2].getiHold(), currents[2].getiRun(),
currents[3].getiHold(), currents[3].getiRun()
);
}

View File

@ -60,14 +60,70 @@ typedef struct
extern tmc2130_chopper_config_t tmc2130_chopper_config[NUM_AXIS];
struct MotorCurrents {
bool vSense; ///< VSense current scaling
uint8_t iRun; ///< Running current
uint8_t iHold; ///< Holding current
// Refresh the vSense flag
// If the vSense flag changes then both Run and Hold current values
// must be shifted accordingly. This is done especially to handle
// the edge case where only either of the current values are changed at runtime.
// See M911 and M912
void refreshCurrentScaling() {
// IMPORTANT: iRun must have range 0 to 63 (2^6) so we can properly
// update the current scaling back and forth
// Detect new vSense value
const bool newvSense = (iRun < 32);
if (vSense != newvSense) {
// Update currents to match current scaling
if (vSense) {
// vSense was 1 [V_FS = 0.32V] but is changing to 0 [V_FS = 0.18V]
// Half both current values to be in sync with current scale range
iHold >>= 1;
iRun >>= 1;
} else {
// vSense was 0 [V_FS = 0.18V], but is changing to 1 [V_FS = 0.32V]
// double the Hold current value
// iRun is expected to already be correct so no shift needed.
// Keep in mind, only a change in iRun can change vSense.
iHold <<= 1;
}
// Update vSense
vSense = newvSense;
} else if (!vSense) {
// No change in vSense, but vSense = 0, which means we must scale down the iRun value
// from range [0, 63] to range [0, 31]
iRun >>= 1;
}
}
constexpr inline __attribute__((always_inline)) MotorCurrents(uint8_t ir, uint8_t ih)
: vSense((ir < 32) ? 1 : 0)
, iRun((ir < 32) ? ir : (ir >> 1))
, iHold((ir < 32) ? ih : (ih >> 1)) {}
inline uint8_t getiRun() const { return iRun; }
inline uint8_t getiHold() const { return iHold; }
inline uint8_t getvSense() const { return vSense; }
void __attribute__((noinline)) setiRun(uint8_t ir) {
iRun = ir;
// Refresh the vSense bit and take care of updating Hold/Run currents
// accordingly
refreshCurrentScaling();
}
void __attribute__((noinline)) setiHold(uint8_t ih) {
iHold = vSense ? ih : ih >> 1;
// Note that iHold cannot change the vSense bit. If iHold is larger
// than iRun, then iHold is truncated later in SetCurrents()
}
private:
// These members are protected in order to ensure that
// the struct methods are used always to update these values at runtime.
bool vSense; ///< VSense current scaling
uint8_t iRun; ///< Running current
uint8_t iHold; ///< Holding current
};
extern MotorCurrents currents[NUM_AXIS];