diff --git a/src/config/axis.h b/src/config/axis.h index c9d9d69b..3e484a46 100644 --- a/src/config/axis.h +++ b/src/config/axis.h @@ -28,6 +28,7 @@ struct AxisConfig { uint8_t iHold; ///< holding current bool stealth; ///< Default to Stealth mode 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 }; diff --git a/src/config/config.h b/src/config/config.h index 313d6417..7fd8d260 100644 --- a/src/config/config.h +++ b/src/config/config.h @@ -115,6 +115,7 @@ static constexpr AxisConfig pulley = { .iHold = 0, /// 17mA in SpreadCycle, freewheel in StealthChop .stealth = false, .stepsPerUnit = (200 * 8 / 19.147274), + .stepsPerUnitReciprocal = 1 / ((200 * 8 / 19.147274)), .sg_thrs = 8, }; @@ -140,6 +141,7 @@ static constexpr AxisConfig selector = { .iHold = 0, /// 17mA in SpreadCycle, freewheel in StealthChop .stealth = false, .stepsPerUnit = (200 * 8 / 8.), + .stepsPerUnitReciprocal = 1 / ((200 * 8 / 8.)), .sg_thrs = 3, }; @@ -190,6 +192,7 @@ static constexpr AxisConfig idler = { .iHold = 5, /// 99mA - parked current .stealth = false, .stepsPerUnit = (200 * 16 / 360.), + .stepsPerUnitReciprocal = 1 / ((200 * 16 / 360.)), .sg_thrs = 7, }; diff --git a/src/modules/axisunit.h b/src/modules/axisunit.h index 9dc413c4..bbbcf1ea 100644 --- a/src/modules/axisunit.h +++ b/src/modules/axisunit.h @@ -94,12 +94,13 @@ constexpr AxisUnit operator*(const long double f, const AxisUnit static constexpr T axisUnitToTruncatedUnit(AU v, long double mul = 1.) { static_assert(AU::unit == U::unit, "incorrect unit type 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) diff --git a/src/modules/idler.cpp b/src/modules/idler.cpp index 1539a3d0..5b68e130 100644 --- a/src/modules/idler.cpp +++ b/src/modules/idler.cpp @@ -64,7 +64,7 @@ void Idler::FinishMove() { } bool Idler::StallGuardAllowed(bool forward) const { - const uint8_t checkDistance = forward ? 220 : 200; + const uint8_t checkDistance = forward ? 200 : 180; return AxisDistance(mm::axisUnitToTruncatedUnit(mm::motion.CurPosition())) > checkDistance; } diff --git a/src/registers.cpp b/src/registers.cpp index 58512d2e..81e4e0b4 100644 --- a/src/registers.cpp +++ b/src/registers.cpp @@ -145,9 +145,9 @@ | 0x0bh 11 | uint8 | extra_load_distance | 00h 0 | 1eh 30 | unit mm | Read / Write | M707 A0x0b | M708 A0x0b Xnn | 0x0ch 12 | uint8 | FSensor_unload_check_dist. | 00h 0 | 28h 30 | unit mm | Read / Write | M707 A0x0c | M708 A0x0c Xnn | 0x0dh 13 | uint16 | Pulley_unload_feedrate | 0000h 0 | 005fh 95 | unit mm/s | Read / Write | M707 A0x0d | M708 A0x0d Xnnnn -| 0x0eh 14 | uint16 | Pulley_acceleration | 0000h 0 | 320h 800.0 | unit mm/s² | Read (Write) | M707 A0x0e | (M708 A0x0e Xnnnn) -| 0x0fh 15 | uint16 | Selector_acceleration | 0000h 0 | 00c8h 200.0 | unit mm/s² | Read (Write) | M707 A0x0f | (M708 A0x0f Xnnnn) -| 0x10h 16 | uint16 | Idler_acceleration | 0000h 0 | 01f4h 500.0 | unit deg/s² | Read (Write) | M707 A0x10 | (M708 A0x10 Xnnnn) +| 0x0eh 14 | uint16 | Pulley_acceleration | 0000h 0 | 320h 800.0 | unit mm/s² | Read / Write | M707 A0x0e | M708 A0x0e Xnnnn +| 0x0fh 15 | uint16 | Selector_acceleration | 0000h 0 | 00c8h 200.0 | unit mm/s² | Read / Write | M707 A0x0f | M708 A0x0f Xnnnn +| 0x10h 16 | uint16 | Idler_acceleration | 0000h 0 | 01f4h 500.0 | unit deg/s² | Read / Write | M707 A0x10 | M708 A0x10 Xnnnn | 0x11h 17 | uint16 | Pulley_load_feedrate | 0000h 0 | 005fh 95 | unit mm/s | Read / Write | M707 A0x11 | M708 A0x11 Xnnnn | 0x12h 18 | uint16 | Selector_nominal_feedrate | 0000h 0 | 002dh 45 | unit mm/s | Read / Write | M707 A0x12 | M708 A0x12 Xnnnn | 0x13h 19 | uint16 | Idler_nominal_feedrate | 0000h 0 | 012ch 300 | unit deg/s | Read / Write | M707 A0x13 | M708 A0x13 Xnnnn @@ -331,18 +331,27 @@ static const RegisterRec registers[] PROGMEM = { // 0xe Pulley acceleration [mm/s2] RW RegisterRec( - []() -> uint16_t { return config::pulleyLimits.accel.v; }, - //@@TODO please update documentation as well + []() -> uint16_t { + mm::steps_t val = mm::motion.Acceleration(config::Pulley); + return mm::axisUnitToTruncatedUnit( mm::P_accel_t({ val })); + }, + [](uint16_t d) { mm::motion.SetAcceleration(config::Pulley, mm::unitToSteps(config::U_mm_s2({ (long double)d }))); }, 2), // 0xf Selector acceleration [mm/s2] RW RegisterRec( - []() -> uint16_t { return config::selectorLimits.accel.v; }, - //@@TODO please update documentation as well + []() -> uint16_t { + mm::steps_t val = mm::motion.Acceleration(config::Selector); + return mm::axisUnitToTruncatedUnit( mm::S_accel_t({ val })); + }, + [](uint16_t d) { (mm::motion.SetAcceleration(config::Selector, mm::unitToSteps(config::U_mm_s2({ (long double)d })))); }, 2), // 0x10 Idler acceleration [deg/s2] RW RegisterRec( - []() -> uint16_t { return config::idlerLimits.accel.v; }, - //@@TODO please update documentation as well + []() -> uint16_t { + mm::steps_t val = mm::motion.Acceleration(config::Idler); + return mm::axisUnitToTruncatedUnit( mm::I_accel_t({ val })); + }, + [](uint16_t d) { mm::motion.SetAcceleration(config::Idler, mm::unitToSteps(config::U_deg_s2({ (long double)d }))); }, 2), // 0x11 Pulley load feedrate [mm/s] RW diff --git a/tests/unit/logic/load_filament/test_load_filament.cpp b/tests/unit/logic/load_filament/test_load_filament.cpp index 3d5ab5de..9fac5142 100644 --- a/tests/unit/logic/load_filament/test_load_filament.cpp +++ b/tests/unit/logic/load_filament/test_load_filament.cpp @@ -84,6 +84,13 @@ void LoadFilamentSuccessful(uint8_t slot, logic::LoadFilament &lf) { void LoadFilamentSuccessfulWithRehomeSelector(uint8_t slot, logic::LoadFilament &lf) { // Stage 2 - feeding to finda // make FINDA switch on + // engaging idler + + REQUIRE(WhileCondition( + lf, + [&](uint32_t) { return !mi::idler.Engaged(); }, + 5000)); + REQUIRE(WhileCondition(lf, std::bind(SimulateFeedToFINDA, _1, 100), 5000)); REQUIRE(VerifyState(lf, mg::FilamentLoadState::InSelector, slot, slot, true, true, ml::blink0, ml::off, ErrorCode::RUNNING, ProgressCode::RetractingFromFinda)); @@ -176,8 +183,6 @@ void FailedLoadToFindaResolveTryAgain(uint8_t slot, logic::LoadFilament &lf) { REQUIRE(VerifyState(lf, mg::FilamentLoadState::InSelector, config::toolCount, slot, false, false, ml::blink0, ml::off, ErrorCode::RUNNING, ProgressCode::FeedingToFinda)); ClearButtons(lf); - SimulateIdlerHoming(lf); - LoadFilamentSuccessfulWithRehomeSelector(slot, lf); } diff --git a/tests/unit/logic/stubs/homing.cpp b/tests/unit/logic/stubs/homing.cpp index 13488e6a..8c345c92 100644 --- a/tests/unit/logic/stubs/homing.cpp +++ b/tests/unit/logic/stubs/homing.cpp @@ -8,6 +8,8 @@ #include "../stubs/stub_motion.h" +#include "catch2/catch_test_macros.hpp" + void SimulateIdlerAndSelectorHoming(logic::CommandBase &cb) { #if 0 // do 5 steps until we trigger the simulated StallGuard @@ -58,6 +60,18 @@ void SimulateIdlerAndSelectorHoming(logic::CommandBase &cb) { void SimulateIdlerHoming(logic::CommandBase &cb) { uint32_t idlerStepsFwd = mm::unitToSteps(config::idlerLimits.lenght - 5.0_deg); + + // Sometimes the initial idler state is Ready. Let's wait for the firmware to start + // homing. + REQUIRE(WhileCondition( + cb, + [&](uint32_t) { return mi::idler.State() == mm::MovableBase::Ready; }, + 5000)); + + // At this point the idler should always be homing forward. + REQUIRE((int)mi::idler.State() == (int)mm::MovableBase::HomeForward); + + // Simulate the idler steps in one direction (forward) for (uint32_t i = 0; i < idlerStepsFwd; ++i) { main_loop(); cb.Step(); @@ -68,6 +82,8 @@ void SimulateIdlerHoming(logic::CommandBase &cb) { cb.Step(); mm::motion.StallGuardReset(mm::Idler); + REQUIRE((int)mi::idler.State() == (int)mm::MovableBase::HomeBack); + // now do a correct amount of steps of each axis towards the other end uint32_t idlerSteps = mm::unitToSteps(config::idlerLimits.lenght); uint32_t maxSteps = idlerSteps + 1; @@ -82,6 +98,9 @@ void SimulateIdlerHoming(logic::CommandBase &cb) { mm::motion.StallGuardReset(mm::Idler); } } + + // If the homing has failed, the axis length was too short. + REQUIRE(!((mi::idler.State() & mm::MovableBase::HomingFailed) == mm::MovableBase::HomingFailed)); } void SimulateIdlerWaitForHomingValid(logic::CommandBase &cb) { @@ -185,33 +204,40 @@ bool SimulateFailedHomeSelectorPostfix(logic::CommandBase &cb) { } bool SimulateFailedHomeFirstTime(logic::CommandBase &cb) { - if (mi::idler.HomingValid()) - return false; - if (ms::selector.HomingValid()) - return false; + REQUIRE(!mi::idler.HomingValid()); + REQUIRE(!ms::selector.HomingValid()); + + // Idler homing is successful + SimulateIdlerHoming(cb); + SimulateIdlerWaitForHomingValid(cb); + + // Selector homes once the idler homing is valid. + REQUIRE(mi::idler.HomingValid()); + REQUIRE(!ms::selector.HomingValid()); + + // The selector will only rehome once the idler homing is valid. At that moment + // the state will change to HomeForward. + REQUIRE(WhileCondition( + cb, + [&](uint32_t) { return ms::selector.State() != mm::MovableBase::HomeForward; }, + 5000)); constexpr uint32_t selectorSteps = mm::unitToSteps(config::selectorLimits.lenght) + 1; { // do 5 steps until we trigger the simulated StallGuard - constexpr uint32_t idlerStepsFwd = mm::unitToSteps(config::idlerLimits.lenght - 5.0_deg); - static_assert(idlerStepsFwd < selectorSteps); // beware, we expect that the Idler homes faster than Selector (less steps) - for (uint32_t i = 0; i < idlerStepsFwd; ++i) { + for (uint32_t i = 0; i < selectorSteps; ++i) { main_loop(); cb.Step(); } mm::TriggerStallGuard(mm::Selector); - mm::TriggerStallGuard(mm::Idler); main_loop(); cb.Step(); mm::motion.StallGuardReset(mm::Selector); - mm::motion.StallGuardReset(mm::Idler); } - // now do a correct amount of steps of each axis towards the other end - constexpr uint32_t idlerSteps = mm::unitToSteps(config::idlerLimits.lenght); - // now do LESS steps than expected to simulate something is blocking the selector - constexpr uint32_t selectorTriggerShort = std::min(idlerSteps, selectorSteps) / 2; + // now do LESS steps than expected to simulate something is blocking the selector + constexpr uint32_t selectorTriggerShort = selectorSteps / 2; constexpr uint32_t maxSteps = selectorTriggerShort + 1; { for (uint32_t i = 0; i < maxSteps; ++i) { @@ -225,17 +251,6 @@ bool SimulateFailedHomeFirstTime(logic::CommandBase &cb) { } } - // make sure the Idler finishes its homing procedure (makes further checks much easier) - for (uint32_t i = maxSteps; i < idlerSteps + 1; ++i) { - main_loop(); - cb.Step(); - if (i == idlerSteps) { - mm::TriggerStallGuard(mm::Idler); - } else { - mm::motion.StallGuardReset(mm::Idler); - } - } - while (!(ms::selector.State() & mm::MovableBase::OnHold)) { main_loop(); cb.Step();