Prusa-Firmware-MMU/tests/unit/logic/load_filament/test_load_filament.cpp

170 lines
6.8 KiB
C++

#include "catch2/catch.hpp"
#include "../../../../src/modules/buttons.h"
#include "../../../../src/modules/finda.h"
#include "../../../../src/modules/fsensor.h"
#include "../../../../src/modules/globals.h"
#include "../../../../src/modules/idler.h"
#include "../../../../src/modules/leds.h"
#include "../../../../src/modules/motion.h"
#include "../../../../src/modules/permanent_storage.h"
#include "../../../../src/modules/selector.h"
#include "../../../../src/logic/load_filament.h"
#include "../../modules/stubs/stub_adc.h"
#include "../stubs/main_loop_stub.h"
#include "../stubs/stub_motion.h"
using Catch::Matchers::Equals;
namespace mm = modules::motion;
namespace mf = modules::finda;
namespace mi = modules::idler;
namespace ml = modules::leds;
namespace mb = modules::buttons;
namespace mg = modules::globals;
namespace ms = modules::selector;
#include "../helpers/helpers.ipp"
void LoadFilamentCommonSetup(uint8_t slot, logic::LoadFilament &lf) {
ForceReinitAllAutomata();
// change the startup to what we need here
EnsureActiveSlotIndex(slot);
// verify startup conditions
REQUIRE(VerifyState(lf, false, mi::Idler::IdleSlotIndex(), slot, false, ml::off, ml::off, ErrorCode::OK, ProgressCode::OK));
// restart the automaton
lf.Reset(slot);
// Stage 0 - verify state just after Reset()
// we assume the filament is not loaded
// idler should have been activated by the underlying automaton
// no change in selector's position
// FINDA off
// green LED should blink, red off
REQUIRE(VerifyState(lf, false, mi::Idler::IdleSlotIndex(), slot, false, ml::blink0, ml::off, ErrorCode::OK, ProgressCode::EngagingIdler));
// Stage 1 - engaging idler
REQUIRE(WhileTopState(lf, ProgressCode::EngagingIdler, 5000));
REQUIRE(VerifyState(lf, false, slot, slot, false, ml::blink0, ml::off, ErrorCode::OK, ProgressCode::FeedingToFinda));
}
void LoadFilamentSuccessful(uint8_t slot, logic::LoadFilament &lf) {
// Stage 2 - feeding to finda
// we'll assume the finda is working correctly here
REQUIRE(WhileCondition(
lf,
[&](int step) -> bool {
if(step == 100){ // on 100th step make FINDA trigger
hal::adc::SetADC(config::findaADCIndex, 1023);
}
return lf.TopLevelState() == ProgressCode::FeedingToFinda; },
5000));
REQUIRE(VerifyState(lf, false, slot, slot, true, ml::blink0, ml::off, ErrorCode::OK, ProgressCode::FeedingToBondtech));
// Stage 3 - feeding to bondtech
// we'll make a fsensor switch during the process
REQUIRE(WhileCondition(
lf,
[&](int step) -> bool {
if(step == 100){ // on 100th step make fsensor trigger
modules::fsensor::fsensor.ProcessMessage(true);
}
return lf.TopLevelState() == ProgressCode::FeedingToBondtech; },
5000));
REQUIRE(VerifyState(lf, false, slot, slot, true, ml::blink0, ml::off, ErrorCode::OK, ProgressCode::DisengagingIdler));
// Stage 4 - disengaging idler
REQUIRE(WhileTopState(lf, ProgressCode::DisengagingIdler, 5000));
REQUIRE(VerifyState(lf, true, mi::Idler::IdleSlotIndex(), slot, true, ml::on, ml::off, ErrorCode::OK, ProgressCode::OK));
}
TEST_CASE("load_filament::regular_load_to_slot_0-4", "[load_filament]") {
for (uint8_t slot = 0; slot < config::toolCount; ++slot) {
logic::LoadFilament lf;
LoadFilamentCommonSetup(slot, lf);
LoadFilamentSuccessful(slot, lf);
}
}
void FailedLoadToFinda(uint8_t slot, logic::LoadFilament &lf) {
// Stage 2 - feeding to finda
// we'll assume the finda is defective here and does not trigger
REQUIRE(WhileTopState(lf, ProgressCode::FeedingToFinda, 5000));
REQUIRE(VerifyState(lf, false, slot, slot, false, ml::off, ml::blink0, ErrorCode::FINDA_DIDNT_SWITCH_ON, ProgressCode::ERR1DisengagingIdler));
// Stage 3 - disengaging idler in error mode
REQUIRE(WhileTopState(lf, ProgressCode::ERR1DisengagingIdler, 5000));
REQUIRE(VerifyState(lf, false, mi::Idler::IdleSlotIndex(), slot, false, ml::off, ml::blink0, ErrorCode::FINDA_DIDNT_SWITCH_ON, ProgressCode::ERR1WaitingForUser));
}
void FailedLoadToFindaResolveHelp(uint8_t slot, logic::LoadFilament &lf) {
// Stage 3 - the user has to do something
// there are 3 options:
// - help the filament a bit
// - try again the whole sequence
// - resolve the problem by hand - after pressing the button we shall check, that FINDA is off and we should do what?
// In this case we check the first option
// Perform press on button 1 + debounce
hal::adc::SetADC(config::buttonsADCIndex, config::buttonADCLimits[0][0] + 1);
while (!mb::buttons.ButtonPressed(0)) {
main_loop();
lf.Step();
}
REQUIRE(VerifyState(lf, false, mi::Idler::IdleSlotIndex(), slot, false, ml::off, ml::blink0, ErrorCode::FINDA_DIDNT_SWITCH_ON, ProgressCode::ERR1EngagingIdler));
// Stage 4 - engage the idler
REQUIRE(WhileTopState(lf, ProgressCode::ERR1EngagingIdler, 5000));
REQUIRE(VerifyState(lf, false, slot, slot, false, ml::off, ml::blink0, ErrorCode::FINDA_DIDNT_SWITCH_ON, ProgressCode::ERR1HelpingFilament));
}
void FailedLoadToFindaResolveHelpFindaTriggered(uint8_t slot, logic::LoadFilament &lf) {
// Stage 5 - move the pulley a bit - simulate FINDA depress
REQUIRE(WhileCondition(
lf,
[&](int step) -> bool {
if(step == 100){ // on 100th step make FINDA trigger
hal::adc::SetADC(config::findaADCIndex, 1023);
}
return lf.TopLevelState() == ProgressCode::ERR1HelpingFilament; },
5000));
REQUIRE(VerifyState(lf, false, slot, slot, true, ml::off, ml::blink0, ErrorCode::OK, ProgressCode::FeedingToBondtech));
}
void FailedLoadToFindaResolveHelpFindaDidntTrigger(uint8_t slot, logic::LoadFilament &lf) {
// Stage 5 - move the pulley a bit - no FINDA change
REQUIRE(WhileTopState(lf, ProgressCode::ERR1HelpingFilament, 5000));
REQUIRE(VerifyState(lf, false, slot, slot, false, ml::off, ml::blink0, ErrorCode::FINDA_DIDNT_SWITCH_ON, ProgressCode::ERR1DisengagingIdler));
}
TEST_CASE("load_filament::failed_load_to_finda_0-4_resolve_help_second_ok", "[load_filament]") {
for (uint8_t slot = 0; slot < config::toolCount; ++slot) {
logic::LoadFilament lf;
LoadFilamentCommonSetup(slot, lf);
FailedLoadToFinda(slot, lf);
FailedLoadToFindaResolveHelp(slot, lf);
FailedLoadToFindaResolveHelpFindaTriggered(slot, lf);
}
}
TEST_CASE("load_filament::failed_load_to_finda_0-4_resolve_help_second_fail", "[load_filament]") {
for (uint8_t slot = 0; slot < config::toolCount; ++slot) {
logic::LoadFilament lf;
LoadFilamentCommonSetup(slot, lf);
FailedLoadToFinda(slot, lf);
FailedLoadToFindaResolveHelp(slot, lf);
FailedLoadToFindaResolveHelpFindaDidntTrigger(slot, lf);
}
}