Prusa-MMU-Private
PrusaMultiMaterialUpgradev3firmwareforMK3SMK4
pulse_gen.h
Go to the documentation of this file.
1 #pragma once
3 #include "speed_table.h"
4 #include "../hal/tmc2130.h"
5 #include "../hal/circular_buffer.h"
6 #include "../cmath.h"
7 
8 namespace modules {
9 
11 namespace pulse_gen {
12 
17 using speed_table::st_timer_t;
18 
19 typedef CircularIndex<uint8_t, blockBufferSize> circular_index_t;
20 typedef uint32_t steps_t;
21 typedef uint32_t rate_t;
22 typedef int32_t pos_t;
23 
24 class PulseGen {
25 public:
26  PulseGen(steps_t max_jerk, steps_t acceleration);
27 
29  inline steps_t Jerk() const { return max_jerk; };
30 
32  inline void SetJerk(steps_t max_jerk) { this->max_jerk = max_jerk; };
33 
35  inline steps_t Acceleration() const { return acceleration; };
36 
38  inline void SetAcceleration(steps_t accel) { acceleration = accel; }
39 
46  bool PlanMoveTo(pos_t pos, steps_t feed_rate, steps_t end_rate = 0);
47 
50  void AbortPlannedMoves(bool halt = true);
51 
53  pos_t Position() const { return position; }
54 
59  pos_t CurPosition() const;
60 
64  inline void SetPosition(pos_t x) { position = x; }
65 
68  inline steps_t Rate() const { return last_rate; }
69 
71  inline bool QueueEmpty() const { return block_index.empty(); }
72 
74  inline bool Full() const { return block_index.full(); }
75 
76  inline uint8_t PlannedMoves() const { return block_index.count(); }
77 
80  inline st_timer_t Step(const hal::tmc2130::MotorParams &motorParams) {
81  if (!current_block) {
82  // fetch next block
83  if (!block_index.empty())
84  current_block = &block_buffer[block_index.front()];
85  if (!current_block)
86  return 0;
87 
88  // Set direction early so that the direction-change delay is accounted for
89  TMC2130::SetDir(motorParams, current_block->direction);
90 
91  // Initializes the trapezoid generator from the current block.
92  deceleration_time = 0;
93  acc_step_rate = uint16_t(current_block->initial_rate);
94  acceleration_time = calc_timer(acc_step_rate, step_loops);
95  steps_completed = 0;
96 
97  // Set the nominal step loops to zero to indicate that the timer value is not
98  // known yet. That means, delay the initialization of nominal step rate and
99  // step loops until the steady state is reached.
100  step_loops_nominal = 0;
101  }
102 
103  // Step the motor
104  for (uint8_t i = 0; i < step_loops; ++i) {
105  TMC2130::Step(motorParams);
106  if (++steps_completed >= current_block->steps)
107  break;
108  }
109 
110  // Calculate new timer value
111  // 13.38-14.63us for steady state,
112  // 25.12us for acceleration / deceleration.
113  st_timer_t timer;
114  if (steps_completed <= current_block->accelerate_until) {
115  // v = t * a -> acc_step_rate = acceleration_time * current_block->acceleration_rate
116  acc_step_rate = mulU24X24toH16(acceleration_time, current_block->acceleration_rate);
117  acc_step_rate += uint16_t(current_block->initial_rate);
118  // upper limit
119  if (acc_step_rate > uint16_t(current_block->nominal_rate))
120  acc_step_rate = current_block->nominal_rate;
121  // step_rate to timer interval
122  timer = calc_timer(acc_step_rate, step_loops);
123  acceleration_time += timer;
124  } else if (steps_completed > current_block->decelerate_after) {
125  st_timer_t step_rate = mulU24X24toH16(deceleration_time, current_block->acceleration_rate);
126 
127  if (step_rate > acc_step_rate) { // Check step_rate stays positive
128  step_rate = uint16_t(current_block->final_rate);
129  } else {
130  step_rate = acc_step_rate - step_rate; // Decelerate from acceleration end point.
131 
132  // lower limit
133  if (step_rate < current_block->final_rate)
134  step_rate = uint16_t(current_block->final_rate);
135  }
136 
137  // Step_rate to timer interval.
138  timer = calc_timer(step_rate, step_loops);
139  deceleration_time += timer;
140  } else {
141  if (!step_loops_nominal) {
142  // Calculation of the steady state timer rate has been delayed to the 1st tick
143  // of the steady state to lower the initial interrupt blocking.
144  timer_nominal = calc_timer(uint16_t(current_block->nominal_rate), step_loops);
145  step_loops_nominal = step_loops;
146  }
147  timer = timer_nominal;
148  }
149 
150  // If current block is finished, reset pointer
151  if (steps_completed >= current_block->steps) {
152  current_block = nullptr;
153  block_index.pop();
154  }
155 
156  return timer;
157  }
158 
159 private:
161  struct block_t {
162  steps_t steps;
163  bool direction;
164 
165  rate_t acceleration_rate;
166  steps_t accelerate_until;
167  steps_t decelerate_after;
168 
169  // Settings for the trapezoid generator (runs inside an interrupt handler)
170  rate_t nominal_rate;
171  rate_t initial_rate;
172  rate_t final_rate;
173  rate_t acceleration;
174  };
175 
176  // Block buffer parameters
177  block_t block_buffer[blockBufferSize];
178  circular_index_t block_index;
179  block_t *current_block;
180 
181  // Axis data
182  pos_t position;
183  steps_t max_jerk;
184  steps_t acceleration;
185  steps_t last_rate;
186 
187  // Step parameters
188  rate_t acceleration_time, deceleration_time;
189  st_timer_t acc_step_rate; // decelaration start point
190  uint8_t step_loops; // steps per loop
191  uint8_t step_loops_nominal; // steps per loop at nominal speed
192  st_timer_t timer_nominal; // nominal interval
193  steps_t steps_completed; // steps completed
194 
196  void CalculateTrapezoid(block_t *block, steps_t entry_speed, steps_t exit_speed);
197 
199  static inline pos_t BlockShift(const block_t *block) {
200  return block->direction ? block->steps : -block->steps;
201  }
202 
203 #ifdef UNITTEST_MOTION
204 public:
205 #endif
207  inline pos_t CurBlockShift() const {
208  steps_t steps_missing = (current_block->steps - steps_completed);
209  return current_block->direction ? steps_missing : -steps_missing;
210  }
211 };
212 
213 } // namespace pulse_gen
214 } // namespace modules
bool empty() const
Definition: circular_buffer.h:25
index_t count() const
Definition: circular_buffer.h:64
void pop()
Definition: circular_buffer.h:47
index_t front() const
Definition: circular_buffer.h:53
bool full() const
Definition: circular_buffer.h:30
TMC2130 interface - instances of this class are hidden in modules::motion::Motion::AxisData.
Definition: tmc2130.h:59
static void Step(const MotorParams &params)
Step the motor.
Definition: tmc2130.h:129
static void SetDir(const MotorParams &params, bool dir)
Set direction.
Definition: tmc2130.h:118
Definition: pulse_gen.h:24
void SetPosition(pos_t x)
Definition: pulse_gen.h:64
void AbortPlannedMoves(bool halt=true)
Definition: pulse_gen.cpp:155
void SetAcceleration(steps_t accel)
Set acceleration for the axis.
Definition: pulse_gen.h:38
bool Full() const
Definition: pulse_gen.h:74
pos_t CurPosition() const
Definition: pulse_gen.cpp:136
bool QueueEmpty() const
Definition: pulse_gen.h:71
bool PlanMoveTo(pos_t pos, steps_t feed_rate, steps_t end_rate=0)
Definition: pulse_gen.cpp:92
void SetJerk(steps_t max_jerk)
Set maximum jerk for the axis.
Definition: pulse_gen.h:32
pos_t Position() const
Definition: pulse_gen.h:53
steps_t Jerk() const
Definition: pulse_gen.h:29
steps_t Rate() const
Definition: pulse_gen.h:68
st_timer_t Step(const hal::tmc2130::MotorParams &motorParams)
Definition: pulse_gen.h:80
steps_t Acceleration() const
Definition: pulse_gen.h:35
static constexpr uint8_t blockBufferSize
Size for the motion planner block buffer size.
Definition: config.h:68
static uint16_t mulU24X24toH16(const uint32_t &longIn1, const uint32_t &longIn2)
(longIn1 * longIn2) >> 24
Definition: math.h:33
int32_t pos_t
Axis position (signed)
Definition: pulse_gen.h:22
uint32_t steps_t
Absolute step units.
Definition: pulse_gen.h:20
uint32_t rate_t
Type for step rates.
Definition: pulse_gen.h:21
static st_timer_t calc_timer(st_timer_t step_rate, uint8_t &step_loops)
Calculate the next timer interval and steps according to current step rate.
Definition: speed_table.h:26
The modules namespace contains models of MMU's components.
Definition: command_base.h:8
Definition: tmc2130.h:20