Motion: implement timer multiplexing
parent
d0581bf494
commit
324fb92fd5
|
|
@ -47,6 +47,10 @@ static constexpr uint8_t blockBufferSize = 2;
|
||||||
/// Step timer frequency divider (F = F_CPU / divider)
|
/// Step timer frequency divider (F = F_CPU / divider)
|
||||||
static constexpr uint8_t stepTimerFrequencyDivider = 8;
|
static constexpr uint8_t stepTimerFrequencyDivider = 8;
|
||||||
|
|
||||||
|
/// Smallest stepping ISR scheduling slice (T = F_CPU / divider * quantum)
|
||||||
|
/// 16 = 8us (25us is the max frequency interval per maxStepFrequency)
|
||||||
|
static constexpr uint8_t stepTimerQuantum = 16;
|
||||||
|
|
||||||
/// Idler configuration
|
/// Idler configuration
|
||||||
static constexpr AxisConfig idler = {
|
static constexpr AxisConfig idler = {
|
||||||
.dirOn = true,
|
.dirOn = true,
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,29 @@ void Motion::AbortPlannedMoves() {
|
||||||
}
|
}
|
||||||
|
|
||||||
st_timer_t Motion::Step() {
|
st_timer_t Motion::Step() {
|
||||||
return 0;
|
st_timer_t timers[NUM_AXIS];
|
||||||
|
|
||||||
|
// step and calculate interval for each new move
|
||||||
|
for (uint8_t i = 0; i != NUM_AXIS; ++i) {
|
||||||
|
timers[i] = axisData[i].residual;
|
||||||
|
if (timers[i] <= config::stepTimerQuantum) {
|
||||||
|
timers[i] += axisData[i].ctrl.Step(axisParams[i].params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// plan next closest interval
|
||||||
|
st_timer_t next = timers[0];
|
||||||
|
for (uint8_t i = 1; i != NUM_AXIS; ++i) {
|
||||||
|
if (timers[i] && (!next || timers[i] < next))
|
||||||
|
next = timers[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// update residuals
|
||||||
|
for (uint8_t i = 0; i != NUM_AXIS; ++i) {
|
||||||
|
axisData[i].residual = (timers[i] ? timers[i] - next : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ISR() {}
|
void ISR() {}
|
||||||
|
|
|
||||||
|
|
@ -168,6 +168,7 @@ private:
|
||||||
TMC2130 drv; ///< Motor driver
|
TMC2130 drv; ///< Motor driver
|
||||||
pulse_gen::PulseGen ctrl; ///< Motor controller
|
pulse_gen::PulseGen ctrl; ///< Motor controller
|
||||||
bool enabled; ///< Axis enabled
|
bool enabled; ///< Axis enabled
|
||||||
|
st_timer_t residual; ///< Axis timer residual
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Helper to initialize AxisData members
|
/// Helper to initialize AxisData members
|
||||||
|
|
|
||||||
|
|
@ -125,3 +125,46 @@ TEST_CASE("motion::triple_move", "[motion]") {
|
||||||
REQUIRE(motion.Position(Selector) == 20);
|
REQUIRE(motion.Position(Selector) == 20);
|
||||||
REQUIRE(motion.Position(Pulley) == 30);
|
REQUIRE(motion.Position(Pulley) == 30);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("motion::dual_move_ramp", "[motion]") {
|
||||||
|
// TODO: output ramps still to be checked
|
||||||
|
const int idlerSteps = 100;
|
||||||
|
const int selectorSteps = 80;
|
||||||
|
const int maxFeedRate = 1000;
|
||||||
|
|
||||||
|
for (int accel = 2000; accel <= 50000; accel *= 2) {
|
||||||
|
REQUIRE(motion.QueueEmpty());
|
||||||
|
|
||||||
|
// first axis using nominal values
|
||||||
|
motion.SetPosition(Idler, 0);
|
||||||
|
motion.SetAcceleration(Idler, accel);
|
||||||
|
motion.PlanMoveTo(Idler, idlerSteps, maxFeedRate);
|
||||||
|
|
||||||
|
// second axis finishes slightly sooner at triple acceleration to maximize the
|
||||||
|
// aliasing effects
|
||||||
|
motion.SetPosition(Selector, 0);
|
||||||
|
motion.SetAcceleration(Selector, accel * 3);
|
||||||
|
motion.PlanMoveTo(Selector, selectorSteps, maxFeedRate);
|
||||||
|
|
||||||
|
// step and output time, interval and positions
|
||||||
|
unsigned long ts = 0;
|
||||||
|
st_timer_t next;
|
||||||
|
do {
|
||||||
|
next = motion.Step();
|
||||||
|
pos_t pos_idler = motion.CurPosition(Idler);
|
||||||
|
pos_t pos_selector = motion.CurPosition(Selector);
|
||||||
|
|
||||||
|
printf("%lu %u %d %d\n", ts, next, pos_idler, pos_selector);
|
||||||
|
|
||||||
|
ts += next;
|
||||||
|
} while (next);
|
||||||
|
printf("\n\n");
|
||||||
|
|
||||||
|
// check queue status
|
||||||
|
REQUIRE(motion.QueueEmpty());
|
||||||
|
|
||||||
|
// check final position
|
||||||
|
REQUIRE(motion.Position(Idler) == idlerSteps);
|
||||||
|
REQUIRE(motion.Position(Selector) == selectorSteps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue