Improve accuracy in axisUnitToTruncatedUnit

When converting 800mm/s2, it would be truncated to 795mm/s2 for the pulley. This is due to cutting out significant decimal digits.

Instead let's multiply in floating point, this needs quite a bit of resources. So to optimise against this, multiply with the recoprical. Then the cost is not more than 20 bytes.

Testing:
M707 A0x0e; Read Pulley Acceleration (default at boot up is 800mm/s2)
M708 A0x0e X790 ; Set Pulley Acceleration to 790mm/s2
M707 A0x0e; Read Pulley Acceleration (should be 790mm/s2)

The results before this commit:

M707 A0x0e -> returns 805
M708 A0x0e X790 ; Set Pulley Acceleration to 790mm/s2
M707 A0x0e; returns 795

After this commit:

M707 A0x0e -> returns 799
M708 A0x0e X790 ; Set Pulley Acceleration to 790mm/s2
M707 A0x0e; returns 789

NOTE:
axisUnitToTruncatedUnit is used in Idler homing, selector homing, and pulley positioning. I am not sure yet how this improvement will affect those areas.
pull/337/head
Guðni Már Gilbert 2024-12-25 14:54:13 +00:00
parent f61450debb
commit aa20e01ef2
3 changed files with 9 additions and 4 deletions

View File

@ -28,6 +28,7 @@ struct AxisConfig {
uint8_t iHold; ///< holding current uint8_t iHold; ///< holding current
bool stealth; ///< Default to Stealth mode bool stealth; ///< Default to Stealth mode
long double stepsPerUnit; ///< steps per unit long double stepsPerUnit; ///< steps per unit
long double stepsPerUnitReciprocal; ///< reciprocal of step per unit (used to avoid divisions)
int8_t sg_thrs; /// @todo 7bit two's complement for the sg_thrs int8_t sg_thrs; /// @todo 7bit two's complement for the sg_thrs
}; };

View File

@ -115,6 +115,7 @@ static constexpr AxisConfig pulley = {
.iHold = 0, /// 17mA in SpreadCycle, freewheel in StealthChop .iHold = 0, /// 17mA in SpreadCycle, freewheel in StealthChop
.stealth = false, .stealth = false,
.stepsPerUnit = (200 * 8 / 19.147274), .stepsPerUnit = (200 * 8 / 19.147274),
.stepsPerUnitReciprocal = 1 / ((200 * 8 / 19.147274)),
.sg_thrs = 8, .sg_thrs = 8,
}; };
@ -140,6 +141,7 @@ static constexpr AxisConfig selector = {
.iHold = 0, /// 17mA in SpreadCycle, freewheel in StealthChop .iHold = 0, /// 17mA in SpreadCycle, freewheel in StealthChop
.stealth = false, .stealth = false,
.stepsPerUnit = (200 * 8 / 8.), .stepsPerUnit = (200 * 8 / 8.),
.stepsPerUnitReciprocal = 1 / ((200 * 8 / 8.)),
.sg_thrs = 3, .sg_thrs = 3,
}; };
@ -190,6 +192,7 @@ static constexpr AxisConfig idler = {
.iHold = 5, /// 99mA - parked current .iHold = 5, /// 99mA - parked current
.stealth = false, .stealth = false,
.stepsPerUnit = (200 * 16 / 360.), .stepsPerUnit = (200 * 16 / 360.),
.stepsPerUnitReciprocal = 1 / ((200 * 16 / 360.)),
.sg_thrs = 7, .sg_thrs = 7,
}; };

View File

@ -94,12 +94,13 @@ constexpr AxisUnit<T, A, U> operator*(const long double f, const AxisUnit<T, A,
struct AxisScale { struct AxisScale {
unit::UnitBase base; unit::UnitBase base;
long double stepsPerUnit; long double stepsPerUnit;
long double stepsPerUnitReciprocal;
}; };
static constexpr AxisScale axisScale[config::NUM_AXIS] = { static constexpr AxisScale axisScale[config::NUM_AXIS] = {
{ config::pulleyLimits.base, config::pulley.stepsPerUnit }, { config::pulleyLimits.base, config::pulley.stepsPerUnit, config::pulley.stepsPerUnitReciprocal },
{ config::selectorLimits.base, config::selector.stepsPerUnit }, { config::selectorLimits.base, config::selector.stepsPerUnit, config::selector.stepsPerUnitReciprocal },
{ config::idlerLimits.base, config::idler.stepsPerUnit }, { config::idlerLimits.base, config::idler.stepsPerUnit, config::idler.stepsPerUnitReciprocal },
}; };
/// Convert a unit::Unit to AxisUnit. /// Convert a unit::Unit to AxisUnit.
@ -126,7 +127,7 @@ template <typename U, typename AU, typename T = int32_t>
static constexpr T axisUnitToTruncatedUnit(AU v, long double mul = 1.) { static constexpr T axisUnitToTruncatedUnit(AU v, long double mul = 1.) {
static_assert(AU::unit == U::unit, "incorrect unit type conversion"); static_assert(AU::unit == U::unit, "incorrect unit type conversion");
static_assert(U::base == axisScale[AU::axis].base, "incorrect unit base conversion"); static_assert(U::base == axisScale[AU::axis].base, "incorrect unit base conversion");
return { ((T)v.v / (T)(axisScale[AU::axis].stepsPerUnit / mul)) }; return { ((T)(v.v * (axisScale[AU::axis].stepsPerUnitReciprocal / mul))) };
} }
/// Truncate an Unit type to an integer (normally int32_t) /// Truncate an Unit type to an integer (normally int32_t)