Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

registers: support writing axis acceleration value #337

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/config/axis.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
};

Expand Down
3 changes: 3 additions & 0 deletions src/config/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};

Expand All @@ -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,
};

Expand Down Expand Up @@ -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,
};

Expand Down
9 changes: 5 additions & 4 deletions src/modules/axisunit.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,13 @@ constexpr AxisUnit<T, A, U> operator*(const long double f, const AxisUnit<T, A,
struct AxisScale {
unit::UnitBase base;
long double stepsPerUnit;
long double stepsPerUnitReciprocal;
};

static constexpr AxisScale axisScale[config::NUM_AXIS] = {
{ config::pulleyLimits.base, config::pulley.stepsPerUnit },
{ config::selectorLimits.base, config::selector.stepsPerUnit },
{ config::idlerLimits.base, config::idler.stepsPerUnit },
{ config::pulleyLimits.base, config::pulley.stepsPerUnit, config::pulley.stepsPerUnitReciprocal },
{ config::selectorLimits.base, config::selector.stepsPerUnit, config::selector.stepsPerUnitReciprocal },
{ config::idlerLimits.base, config::idler.stepsPerUnit, config::idler.stepsPerUnitReciprocal },
};

/// Convert a unit::Unit to AxisUnit.
Expand All @@ -126,7 +127,7 @@ template <typename U, typename AU, typename T = int32_t>
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)
Expand Down
2 changes: 1 addition & 1 deletion src/modules/idler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we can tighten these values closer to 225°

return AxisDistance(mm::axisUnitToTruncatedUnit<config::U_deg>(mm::motion.CurPosition<mm::Idler>())) > checkDistance;
}

Expand Down
27 changes: 18 additions & 9 deletions src/registers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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<config::U_mm_s2>( mm::P_accel_t({ val }));
},
[](uint16_t d) { mm::motion.SetAcceleration(config::Pulley, mm::unitToSteps<mm::P_accel_t>(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<config::U_mm_s2>( mm::S_accel_t({ val }));
},
[](uint16_t d) { (mm::motion.SetAcceleration(config::Selector, mm::unitToSteps<mm::S_accel_t>(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<config::U_deg_s2>( mm::I_accel_t({ val }));
},
[](uint16_t d) { mm::motion.SetAcceleration(config::Idler, mm::unitToSteps<mm::I_accel_t>(config::U_deg_s2({ (long double)d }))); },
2),

// 0x11 Pulley load feedrate [mm/s] RW
Expand Down
9 changes: 7 additions & 2 deletions tests/unit/logic/load_filament/test_load_filament.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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));

Expand Down Expand Up @@ -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);
}

Expand Down
63 changes: 39 additions & 24 deletions tests/unit/logic/stubs/homing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -58,6 +60,18 @@ void SimulateIdlerAndSelectorHoming(logic::CommandBase &cb) {

void SimulateIdlerHoming(logic::CommandBase &cb) {
uint32_t idlerStepsFwd = mm::unitToSteps<mm::I_pos_t>(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();
Expand All @@ -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<mm::I_pos_t>(config::idlerLimits.lenght);
uint32_t maxSteps = idlerSteps + 1;
Expand All @@ -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) {
Expand Down Expand Up @@ -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<mm::S_pos_t>(config::selectorLimits.lenght) + 1;
{
// do 5 steps until we trigger the simulated StallGuard
constexpr uint32_t idlerStepsFwd = mm::unitToSteps<mm::I_pos_t>(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<mm::I_pos_t>(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) {
Expand All @@ -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();
Expand Down
Loading