Prusa-MMU-Private
PrusaMultiMaterialUpgradev3firmwareforMK3SMK4
motion.h
Go to the documentation of this file.
1 #pragma once
3 #include "../pins.h"
4 #include "pulse_gen.h"
5 #include "axisunit.h"
6 
7 namespace modules {
8 
11 namespace motion {
12 
13 // Import axes definitions
14 using config::NUM_AXIS;
15 
16 using namespace hal::tmc2130;
17 using pulse_gen::st_timer_t;
18 
19 // Check for configuration invariants
20 static_assert(
22  > (1. / config::maxStepFrequency),
23  "stepTimerQuantum must be larger than the maximal stepping frequency interval");
24 
26 struct AxisParams {
27  char name;
28  MotorParams params;
29  MotorCurrents currents;
30  MotorMode mode;
31  steps_t jerk;
32  steps_t accel;
33 };
34 
36 static constexpr MotorMode DefaultMotorMode(const config::AxisConfig &axis) {
37  return axis.stealth ? MotorMode::Stealth : MotorMode::Normal;
38 }
39 
42  // Pulley
43  {
44  .name = 'P',
45  .params = { .spi = hal::spi::TmcSpiBus, .idx = Pulley, .dirOn = config::pulley.dirOn, .csPin = PULLEY_CS_PIN, .stepPin = PULLEY_STEP_PIN, .sgPin = PULLEY_SG_PIN, .mRes = config::pulley.mRes, .sg_thrs = config::pulley.sg_thrs, Axis::Pulley },
46  .currents = MotorCurrents(config::pulley.iRun, config::pulley.iHold),
48  .jerk = unitToSteps<P_speed_t>(config::pulleyLimits.jerk),
49  .accel = unitToSteps<P_accel_t>(config::pulleyLimits.accel),
50  },
51  // Selector
52  {
53  .name = 'S',
54  .params = { .spi = hal::spi::TmcSpiBus, .idx = Selector, .dirOn = config::selector.dirOn, .csPin = SELECTOR_CS_PIN, .stepPin = SELECTOR_STEP_PIN, .sgPin = SELECTOR_SG_PIN, .mRes = config::selector.mRes, .sg_thrs = config::selector.sg_thrs, Axis::Selector },
55  .currents = MotorCurrents(config::selector.iRun, config::selector.iHold),
57  .jerk = unitToSteps<S_speed_t>(config::selectorLimits.jerk),
58  .accel = unitToSteps<S_accel_t>(config::selectorLimits.accel),
59  },
60  // Idler
61  {
62  .name = 'I',
63  .params = { .spi = hal::spi::TmcSpiBus, .idx = Idler, .dirOn = config::idler.dirOn, .csPin = IDLER_CS_PIN, .stepPin = IDLER_STEP_PIN, .sgPin = IDLER_SG_PIN, .mRes = config::idler.mRes, .sg_thrs = config::idler.sg_thrs, Axis::Idler },
64  .currents = MotorCurrents(config::idler.iRun, config::idler.iHold),
66  .jerk = unitToSteps<I_speed_t>(config::idlerLimits.jerk),
67  .accel = unitToSteps<I_accel_t>(config::idlerLimits.accel),
68  },
69 };
70 
71 class Motion {
72 public:
73  inline constexpr Motion() = default;
74 
79  bool InitAxis(Axis axis);
80  bool InitAxis(Axis axis, MotorCurrents mc);
81 
83  bool Enabled(Axis axis) const { return axisData[axis].enabled; }
84 
87  void SetEnabled(Axis axis, bool enabled);
88 
91  void Disable(Axis axis) { SetEnabled(axis, false); }
92 
95  void SetMode(Axis axis, MotorMode mode);
96 
98  void SetMode(MotorMode mode);
99 
101  bool StallGuard(Axis axis);
102 
104  void StallGuardReset(Axis axis);
105 
108  void PlanStallGuardThreshold(Axis axis, int8_t sg_thrs);
109 
116  void PlanMoveTo(Axis axis, pos_t pos, steps_t feed_rate, steps_t end_rate = 0);
117 
121  template <Axis A>
123  AxisUnit<steps_t, A, Speed> feed_rate, AxisUnit<steps_t, A, Speed> end_rate = { 0 }) {
124  PlanMoveTo(A, pos.v, feed_rate.v, end_rate.v);
125  }
126 
130  template <Axis A, config::UnitBase B>
133  PlanMoveTo<A>(
137  }
138 
145  void PlanMove(Axis axis, pos_t delta, steps_t feed_rate, steps_t end_rate = 0) {
146  PlanMoveTo(axis, Position(axis) + delta, feed_rate, end_rate);
147  }
148 
152  template <Axis A>
153  constexpr void PlanMove(AxisUnit<pos_t, A, Lenght> delta,
154  AxisUnit<steps_t, A, Speed> feed_rate, AxisUnit<steps_t, A, Speed> end_rate = { 0 }) {
155  PlanMove(A, delta.v, feed_rate.v, end_rate.v);
156  }
157 
161  template <Axis A, config::UnitBase B>
164  PlanMove<A>(
168  }
169 
172  pos_t Position(Axis axis) const;
173 
177  template <Axis A>
179  return AxisUnit<pos_t, A, Lenght> { Position(A) };
180  }
181 
187  pos_t CurPosition(Axis axis) const;
188 
192  template <Axis A>
194  return AxisUnit<pos_t, A, Lenght> { CurPosition(A) };
195  }
196 
200 #if !defined(UNITTEST) || defined(UNITTEST_MOTION)
201  void SetPosition(Axis axis, pos_t x) {
202  axisData[axis].ctrl.SetPosition(x);
203  }
204 #else
205  // Force STUB for testing
206  void SetPosition(Axis axis, pos_t x);
207 #endif
208 
212  steps_t Acceleration(Axis axis) const {
213  return axisData[axis].ctrl.Acceleration();
214  }
215 
219  void SetAcceleration(Axis axis, steps_t accel) {
220  axisData[axis].ctrl.SetAcceleration(accel);
221  }
222 
226  template <Axis A>
228  SetAcceleration(A, accel.v);
229  }
230 
236  template <Axis A, config::UnitBase B>
238  SetAcceleration<A>(unitToAxisUnit<AxisUnit<steps_t, A, Accel>>(accel));
239  }
240 
244  steps_t Jerk(Axis axis) const {
245  return axisData[axis].ctrl.Jerk();
246  }
247 
251  void SetJerk(Axis axis, steps_t max_jerk) {
252  return axisData[axis].ctrl.SetJerk(max_jerk);
253  }
254 
259  steps_t Rate(Axis axis) const {
260  return axisData[axis].ctrl.Rate();
261  }
262 
265 #if !defined(UNITTEST) || defined(UNITTEST_MOTION)
266  inline st_timer_t Step() {
267  st_timer_t timers[NUM_AXIS];
268 
269  // step and calculate interval for each new move
270  for (uint8_t i = 0; i != NUM_AXIS; ++i) {
271  timers[i] = axisData[i].residual;
272  if (timers[i] <= config::stepTimerQuantum) {
273  if (timers[i] || !axisData[i].ctrl.QueueEmpty()) {
274  st_timer_t next = axisData[i].ctrl.Step(axisParams[i].params);
275  if (next) {
276  timers[i] += next;
277 
278  // axis has been moved, run the tmc2130 Isr for this axis
279  axisData[i].drv.Isr(axisParams[i].params);
280  } else {
281  // axis finished, reset residual
282  timers[i] = 0;
283  }
284  }
285  }
286  }
287 
288  // plan next closest interval
289  st_timer_t next = timers[0];
290  for (uint8_t i = 1; i != NUM_AXIS; ++i) {
291  if (timers[i] && (!next || timers[i] < next))
292  next = timers[i];
293  }
294 
295  // update residuals
296  for (uint8_t i = 0; i != NUM_AXIS; ++i) {
297  axisData[i].residual = (timers[i] ? timers[i] - next : 0);
298  }
299 
300  return next;
301  }
302 #else
303  // Force STUB for testing
304  st_timer_t Step();
305 #endif
306 
308  bool QueueEmpty() const;
309 
312 #if !defined(UNITTEST) || defined(UNITTEST_MOTION)
313  bool QueueEmpty(Axis axis) const {
314  return axisData[axis].ctrl.QueueEmpty();
315  }
316 #else
317  // Force STUB for testing
318  bool QueueEmpty(Axis axis) const;
319 #endif
320 
321 #if !defined(UNITTEST) || defined(UNITTEST_MOTION)
323  uint8_t PlannedMoves(Axis axis) const {
324  return axisData[axis].ctrl.PlannedMoves();
325  }
326 #else
327  // Force STUB for testing
328  uint8_t PlannedMoves(Axis axis) const;
329 #endif
332  bool Full(Axis axis) const { return axisData[axis].ctrl.Full(); }
333 
337  void AbortPlannedMoves(Axis axis, bool halt = true);
338 
341  void AbortPlannedMoves(bool halt = true);
342 
345  return axisData[axis].drv;
346  }
347 
352  return axisData[axis].drv;
353  }
354 
356  inline const pulse_gen::PulseGen &CtrlForAxis(Axis axis) const {
357  return axisData[axis].ctrl;
358  }
359 
360  inline const MotorCurrents &CurrentsForAxis(Axis axis) const {
361  return axisData[axis].currents;
362  }
363  inline void SetIRunForAxis(Axis axis, uint8_t i) {
364  axisData[axis].currents.iRun = i;
365  }
366 
367 private:
368  struct AxisData {
369  TMC2130 drv;
370  pulse_gen::PulseGen ctrl;
371  bool enabled;
372  MotorCurrents currents;
373  st_timer_t residual;
374  };
375 
377  static AxisData DataForAxis(Axis axis) {
378  return {
379  .drv = {},
380  .ctrl = {
381  axisParams[axis].jerk,
382  axisParams[axis].accel,
383  },
384  .enabled = false,
385  .currents = axisParams[axis].currents
386  };
387  }
388 
390  AxisData axisData[NUM_AXIS] = {
391  DataForAxis(Pulley),
392  DataForAxis(Selector),
393  DataForAxis(Idler),
394  };
395 };
396 
398 extern void Init();
399 
400 extern Motion motion;
401 
402 } // namespace motion
403 } // namespace modules
404 
405 namespace mm = modules::motion;
TMC2130 interface - instances of this class are hidden in modules::motion::Motion::AxisData.
Definition: tmc2130.h:59
Definition: motion.h:71
void SetAcceleration(config::Unit< long double, B, Accel > accel)
Definition: motion.h:237
constexpr void PlanMove(AxisUnit< pos_t, A, Lenght > delta, AxisUnit< steps_t, A, Speed > feed_rate, AxisUnit< steps_t, A, Speed > end_rate={ 0 })
Definition: motion.h:153
bool Full(Axis axis) const
Definition: motion.h:332
void PlanMove(Axis axis, pos_t delta, steps_t feed_rate, steps_t end_rate=0)
Definition: motion.h:145
hal::tmc2130::TMC2130 & MMU_NEEDS_ATTENTION_DriverForAxis(Axis axis)
Definition: motion.h:351
const pulse_gen::PulseGen & CtrlForAxis(Axis axis) const
Definition: motion.h:356
constexpr void PlanMoveTo(config::Unit< long double, B, Lenght > pos, config::Unit< long double, B, Speed > feed_rate, config::Unit< long double, B, Speed > end_rate={ 0 })
Definition: motion.h:131
steps_t Acceleration(Axis axis) const
Definition: motion.h:212
void SetAcceleration(AxisUnit< steps_t, A, Accel > accel)
Definition: motion.h:227
void SetPosition(Axis axis, pos_t x)
Definition: motion.h:201
constexpr void PlanMove(config::Unit< long double, B, Lenght > delta, config::Unit< long double, B, Speed > feed_rate, config::Unit< long double, B, Speed > end_rate={ 0 })
Definition: motion.h:162
void Disable(Axis axis)
Definition: motion.h:91
constexpr AxisUnit< pos_t, A, Lenght > CurPosition() const
Definition: motion.h:193
bool QueueEmpty(Axis axis) const
Definition: motion.h:313
uint8_t PlannedMoves(Axis axis) const
Definition: motion.h:323
steps_t Rate(Axis axis) const
Definition: motion.h:259
void SetJerk(Axis axis, steps_t max_jerk)
Definition: motion.h:251
bool Enabled(Axis axis) const
Return the axis power status.
Definition: motion.h:83
constexpr void PlanMoveTo(AxisUnit< pos_t, A, Lenght > pos, AxisUnit< steps_t, A, Speed > feed_rate, AxisUnit< steps_t, A, Speed > end_rate={ 0 })
Definition: motion.h:122
steps_t Jerk(Axis axis) const
Definition: motion.h:244
hal::tmc2130::TMC2130 & DriverForAxis(Axis axis)
Definition: motion.h:344
constexpr AxisUnit< pos_t, A, Lenght > Position() const
Definition: motion.h:178
void SetAcceleration(Axis axis, steps_t accel)
Definition: motion.h:219
Definition: pulse_gen.h:24
#define F_CPU
Main clock frequency.
Definition: cpu.h:11
static constexpr AxisConfig selector
End: Pulley axis configuration.
Definition: config.h:136
static constexpr IdlerLimits idlerLimits
Idler motion limits.
Definition: config.h:197
static constexpr SelectorLimits selectorLimits
Selector motion limits.
Definition: config.h:149
static constexpr uint16_t maxStepFrequency
Max step frequency 40KHz.
Definition: config.h:62
static constexpr AxisConfig idler
End: Selector configuration.
Definition: config.h:186
static constexpr PulleyLimits pulleyLimits
Pulley motion limits.
Definition: config.h:122
static constexpr uint8_t stepTimerFrequencyDivider
Step timer frequency divider (F = F_CPU / divider)
Definition: config.h:71
static constexpr AxisConfig pulley
Begin: Pulley axis configuration.
Definition: config.h:111
static constexpr uint8_t NUM_AXIS
Number of available axes.
Definition: axis.h:43
static constexpr uint16_t stepTimerQuantum
Definition: config.h:76
Axis
List of available axes.
Definition: axis.h:35
Definition: tmc2130.cpp:82
Definition: command_base.h:9
static AxisParams axisParams[NUM_AXIS]
Static axis configuration.
Definition: motion.h:41
static constexpr MotorMode DefaultMotorMode(const config::AxisConfig &axis)
Return the default motor mode for an Axis.
Definition: motion.h:36
static constexpr AU unitToAxisUnit(U v)
Definition: axisunit.h:109
void Init()
ISR initialization.
Definition: motion.cpp:151
int32_t pos_t
Axis position (signed)
Definition: pulse_gen.h:22
uint32_t steps_t
Absolute step units.
Definition: pulse_gen.h:20
The modules namespace contains models of MMU's components.
Definition: command_base.h:8
Axis configuration data.
Definition: axis.h:24
bool dirOn
direction ON state (for inversion)
Definition: axis.h:25
MRes mRes
microstepping [0-8, where 0 is x256 and 8 is fullstepping]
Definition: axis.h:26
Definition: tmc2130.h:32
uint8_t iRun
Running current.
Definition: tmc2130.h:34
Definition: tmc2130.h:20
Main axis enumeration.
Definition: motion.h:26
Definition: axisunit.h:68