motion: PlanMove() correctly also when overflowing Position()

Correctly compute both the number of steps and direction when
under/overflowing the current position by performing a relative move.

This makes a repeated PlanMove() _always_ perform the move correcly,
even when the upper-level code might require to handle the overflow
itself for measurement.

Add tests for this condition by exposing the internal CurBlockShift() to
the motion unit tests.
pull/161/head
Yuri D'Elia 2022-05-11 01:26:26 +02:00 committed by DRracer
parent 1a2034f545
commit 3fbdf8bb2b
3 changed files with 35 additions and 7 deletions

View File

@ -96,14 +96,15 @@ bool PulseGen::PlanMoveTo(pos_t target, steps_t feed_rate, steps_t end_rate) {
block_t *block = &block_buffer[block_index.back()];
// Bail if this is a zero-length block
block->steps = abs(target - position);
pos_t steps = target - position;
block->steps = abs(steps);
if (block->steps <= config::dropSegments) {
// behave as-if the block has been scheduled
return true;
}
// Direction and speed for this block
block->direction = (target >= position);
block->direction = steps >= 0;
block->nominal_rate = feed_rate;
// Acceleration of the segment, in steps/sec^2

View File

@ -195,16 +195,19 @@ private:
/// Calculate the trapezoid parameters for the block
void CalculateTrapezoid(block_t *block, steps_t entry_speed, steps_t exit_speed);
/// Return the axis shift introduced by the specified full block
static inline pos_t BlockShift(const block_t *block) {
return block->direction ? block->steps : -block->steps;
}
#ifdef UNITTEST_MOTION
public:
#endif
/// Return the axis shift introduced by the current (live) block
inline pos_t CurBlockShift() const {
steps_t steps_missing = (current_block->steps - steps_completed);
return current_block->direction ? steps_missing : -steps_missing;
}
/// Return the axis shift introduced by the specified full block
static inline pos_t BlockShift(const block_t *block) {
return block->direction ? block->steps : -block->steps;
}
};
} // namespace pulse_gen

View File

@ -278,3 +278,27 @@ TEST_CASE("motion::long_pulley_move", "[motion]") {
motion.PlanMoveTo<Pulley>(mm400, 1._mm_s);
REQUIRE(stepUntilDone() == p);
}
TEST_CASE("motion::pos_overflow", "[motion]") {
ResetMotionSim();
// set a position _at_ the overflow limit
mm::pos_t pos_max = std::numeric_limits<mm::pos_t>::max();
mm::motion.SetPosition(mm::Pulley, pos_max);
REQUIRE(mm::motion.Position(mm::Pulley) == pos_max);
// plan a move which will overflow
mm::pos_t steps = 10;
mm::motion.PlanMove(mm::Pulley, steps, 1);
// ensure we did overflow
REQUIRE(mm::motion.Position(mm::Pulley) < pos_max);
// step once to setup current_block
mm::motion.Step();
// ensure the move direction and step count is correct despite the overflow
// abuse CurBlockShift to get both, accounting for the useless single step
// we performed just above.
REQUIRE(mm::motion.CtrlForAxis(mm::Pulley).CurBlockShift() == steps - 1);
}