gnea\grbl-Mega  1.0f
Source Code Documentation ( Internal Workings )
motion_control.c
Go to the documentation of this file.
1 /*
2  motion_control.c - high level interface for issuing motion commands
3  Part of Grbl
4 
5  Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC
6  Copyright (c) 2009-2011 Simen Svale Skogsrud
7 
8  Grbl is free software: you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation, either version 3 of the License, or
11  (at your option) any later version.
12 
13  Grbl is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with Grbl. If not, see <http://www.gnu.org/licenses/>.
20 */
21 
22 #include "grbl.h"
23 
25 // unless invert_feed_rate is true. Then the feed_rate means that the motion should be completed in
26 // (1 minute)/feed_rate time.
27 //
29 // segments, must pass through this routine before being passed to the planner. The seperation of
30 // mc_line and plan_buffer_line is done primarily to place non-planner-type functions from being
31 // in the planner and to let backlash compensation or canned cycle integration simple and direct.
32 void mc_line(float *target, plan_line_data_t *pl_data)
33 {
34 // If enabled, check for soft limit violations. Placed here all line motions are picked up
35 // from everywhere in Grbl.
37 //
39  if (sys.state != STATE_JOG) { limits_soft_check(target); }
40  }
41 
42 // If in check gcode mode, prevent motion by blocking planner. Soft limits still work.
43  if (sys.state == STATE_CHECK_MODE) { return; }
44 
45 //
47 // to insert a backlash line motion(s) before the intended line motion and will require its own
48 // plan_check_full_buffer() and check for system abort loop. Also for position reporting
49 // backlash steps will need to be also tracked, which will need to be kept at a system level.
50 // There are likely some other things that will need to be tracked as well. However, we feel
51 // that backlash compensation should NOT be handled by Grbl itself, because there are a myriad
52 // of ways to implement it and can be effective or ineffective for different CNC machines. This
53 // would be better handled by the interface as a post-processor task, where the original g-code
54 // is translated and inserts backlash motions that best suits the machine.
55 //
57 // indicates to Grbl what is a backlash compensation motion, so that Grbl executes the move but
58 // doesn't update the machine position values. Since the position values used by the g-code
59 // parser and planner are separate from the system machine positions, this is doable.
60 
61 // If the buffer is full: good! That means we are well ahead of the robot.
62 // Remain in this loop until there is room in the buffer.
63  do {
65  if (sys.abort) { return; }
67  else { break; }
68  } while (1);
69 
70 // Plan and queue motion into planner buffer
71 // uint8_t plan_status; //!< Not used in normal operation.
72  plan_buffer_line(target, pl_data);
73 }
74 
76 // offset == offset from current xyz, axis_X defines circle plane in tool space, axis_linear is
77 // the direction of helical travel, radius == circle radius, isclockwise boolean. Used
78 // for vector transformation direction.
79 // The arc is approximated by generating a huge number of tiny, linear segments. The chordal tolerance
80 // of each segment is configured in settings.arc_tolerance, which is defined to be the maximum normal
81 // distance from segment to the circle when the end points both lie on the circle.
82 void mc_arc(float *target, plan_line_data_t *pl_data, float *position, float *offset, float radius,
83  uint8_t axis_0, uint8_t axis_1, uint8_t axis_linear, uint8_t is_clockwise_arc)
84 {
85  float center_axis0 = position[axis_0] + offset[axis_0];
86  float center_axis1 = position[axis_1] + offset[axis_1];
87  float r_axis0 = -offset[axis_0];
88  float r_axis1 = -offset[axis_1];
89  float rt_axis0 = target[axis_0] - center_axis0;
90  float rt_axis1 = target[axis_1] - center_axis1;
91 
92 // CCW angle between position and target from circle center. Only one atan2() trig computation required.
93  float angular_travel = atan2(r_axis0*rt_axis1-r_axis1*rt_axis0, r_axis0*rt_axis0+r_axis1*rt_axis1);
94  if (is_clockwise_arc) {
95  if (angular_travel >= -ARC_ANGULAR_TRAVEL_EPSILON) { angular_travel -= 2*M_PI; }
96  } else {
97  if (angular_travel <= ARC_ANGULAR_TRAVEL_EPSILON) { angular_travel += 2*M_PI; }
98  }
99 
100 //
102 // (2x) settings.arc_tolerance. For 99% of users, this is just fine. If a different arc segment fit
103 // is desired, i.e. least-squares, midpoint on arc, just change the mm_per_arc_segment calculation.
104 // For the intended uses of Grbl, this value shouldn't exceed 2000 for the strictest of cases.
105  uint16_t segments = floor(fabs(0.5*angular_travel*radius)/
106  sqrt(settings.arc_tolerance*(2*radius - settings.arc_tolerance)) );
107 
108  if (segments) {
109 // Multiply inverse feed_rate to compensate for the fact that this movement is approximated
110 // by a number of discrete segments. The inverse feed_rate should be correct for the sum of
111 // all segments.
112  if (pl_data->condition & PL_COND_FLAG_INVERSE_TIME) {
113  pl_data->feed_rate *= segments;
115  }
116 
117  float theta_per_segment = angular_travel/segments;
118  float linear_per_segment = (target[axis_linear] - position[axis_linear])/segments;
119 
145 // Computes: cos_T = 1 - theta_per_segment^2/2, sin_T = theta_per_segment - theta_per_segment^3/6) in ~52usec
146  float cos_T = 2.0 - theta_per_segment*theta_per_segment;
147  float sin_T = theta_per_segment*0.16666667*(cos_T + 4.0);
148  cos_T *= 0.5;
149 
150  float sin_Ti;
151  float cos_Ti;
152  float r_axisi;
153  uint16_t i;
154  uint8_t count = 0;
155 
156  for (i = 1; i<segments; i++) {
157 
158  if (count < N_ARC_CORRECTION) {
159 // Apply vector rotation matrix. ~40 usec
160  r_axisi = r_axis0*sin_T + r_axis1*cos_T;
161  r_axis0 = r_axis0*cos_T - r_axis1*sin_T;
162  r_axis1 = r_axisi;
163  count++;
164  } else {
165 // Arc correction to radius vector. Computed only every N_ARC_CORRECTION increments. ~375 usec
166 // Compute exact location by applying transformation matrix from initial radius vector(=-offset).
167  cos_Ti = cos(i*theta_per_segment);
168  sin_Ti = sin(i*theta_per_segment);
169  r_axis0 = -offset[axis_0]*cos_Ti + offset[axis_1]*sin_Ti;
170  r_axis1 = -offset[axis_0]*sin_Ti - offset[axis_1]*cos_Ti;
171  count = 0;
172  }
173 
174 // Update arc_target location
175  position[axis_0] = center_axis0 + r_axis0;
176  position[axis_1] = center_axis1 + r_axis1;
177  position[axis_linear] += linear_per_segment;
178 
179  mc_line(position, pl_data);
180 
181 // Bail mid-circle on system abort. Runtime command check already performed by mc_line.
182  if (sys.abort) { return; }
183  }
184  }
185 // Ensure last segment arrives at target location.
186  mc_line(target, pl_data);
187 }
188 
190 void mc_dwell(float seconds)
191 {
192  if (sys.state == STATE_CHECK_MODE) { return; }
194  delay_sec(seconds, DELAY_MODE_DWELL);
195 }
196 
198 //
200 // executing the homing cycle. This prevents incorrect buffered plans after homing.
201 void mc_homing_cycle(uint8_t cycle_mask)
202 {
203 // Check and abort homing cycle, if hard limits are already enabled. Helps prevent problems
204 // with machines with limits wired on both ends of travel to one limit pin.
206  #ifdef LIMITS_TWO_SWITCHES_ON_AXES
207  if (limits_get_state()) {
208  mc_reset();
210  return;
211  }
212  #endif
213 
214  limits_disable();
215 
216 // -------------------------------------------------------------------------------------
217 // Perform homing routine.
219 
220  #ifdef HOMING_SINGLE_AXIS_COMMANDS
221  if (cycle_mask) { limits_go_home(cycle_mask); }
222  else
223  #endif
224  {
225 // Search to engage all axes limit switches at faster homing seek rate.
227  #ifdef HOMING_CYCLE_1
229  #endif
230  #ifdef HOMING_CYCLE_2
231  limits_go_home(HOMING_CYCLE_2);
232  #endif
233  }
234 
236  if (sys.abort) { return; }
237 
238 // Homing cycle complete! Setup system for normal operation.
239 // -------------------------------------------------------------------------------------
240 
241 // Sync gcode parser and planner positions to homed position.
244 
245 // If hard limits feature enabled, re-enable hard limits pin change register after homing cycle.
246  limits_init();
247 }
248 
250 //
252 uint8_t mc_probe_cycle(float *target, plan_line_data_t *pl_data, uint8_t parser_flags)
253 {
255  if (sys.state == STATE_CHECK_MODE) { return(GC_PROBE_CHECK_MODE); }
256 
257 // Finish all queued commands and empty planner buffer before starting probe cycle.
259  if (sys.abort) { return(GC_PROBE_ABORT); }
260 
261 // Initialize probing control variables
262  uint8_t is_probe_away = bit_istrue(parser_flags,GC_PARSER_PROBE_IS_AWAY);
263  uint8_t is_no_error = bit_istrue(parser_flags,GC_PARSER_PROBE_IS_NO_ERROR);
264  sys.probe_succeeded = false;
265  probe_configure_invert_mask(is_probe_away);
266 
267 // After syncing, check if probe is already triggered. If so, halt and issue alarm.
268 //
270  if ( probe_get_state() ) {
274  return(GC_PROBE_FAIL_INIT);
275  }
276 
277 // Setup and queue probing motion. Auto cycle-start should not start the cycle.
278  mc_line(target, pl_data);
279 
280 // Activate the probing state monitor in the stepper module.
282 
283 // Perform probing cycle. Wait here until probe is triggered or motion completes.
285  do {
287  if (sys.abort) { return(GC_PROBE_ABORT); }
288  } while (sys.state != STATE_IDLE);
289 
290 // Probing cycle complete!
291 
292 // Set state variables and error out, if the probe failed and cycle with error is enabled.
293  if (sys_probe_state == PROBE_ACTIVE) {
294  if (is_no_error) { memcpy(sys_probe_position, sys_position, sizeof(sys_position)); }
296  } else {
297  sys.probe_succeeded = true;
298  }
302 
303 // Reset the stepper and planner buffers to remove the remainder of the probe motion.
304  st_reset();
305  plan_reset();
307 
308  #ifdef MESSAGE_PROBE_COORDINATES
309 // All done! Output the probe position as message.
311  #endif
312 
313  if (sys.probe_succeeded) { return(GC_PROBE_FOUND); }
314  else { return(GC_PROBE_FAIL_END); }
315 }
316 
318 //
320 void mc_parking_motion(float *parking_target, plan_line_data_t *pl_data)
321 {
322  if (sys.abort) { return; }
323 
324  uint8_t plan_status = plan_buffer_line(parking_target, pl_data);
325 
326  if (plan_status) {
330  st_prep_buffer();
331  st_wake_up();
332  do {
334  if (sys.abort) { return; }
337  } else {
340  }
341 
342 }
343 
345 // active processes in the system. This also checks if a system reset is issued while Grbl
346 // is in a motion state. If so, kills the steppers and sets the system alarm to flag position
347 // lost, since there was an abrupt uncontrolled deceleration. Called at an interrupt level by
348 // realtime abort command and hard limits. So, keep to a minimum.
349 void mc_reset()
350 {
351 // Only this function can set the system reset. Helps prevent multiple kill calls.
354 
355 // Kill spindle and coolant.
356  spindle_stop();
357  coolant_stop();
358 
359 // Kill steppers only if in any motion state, i.e. cycle, actively holding, or homing.
360 //
362 // the steppers enabled by avoiding the go_idle call altogether, unless the motion state is
363 // violated, by which, all bets are off.
364  if ((sys.state & (STATE_CYCLE | STATE_HOMING | STATE_JOG)) ||
366  if (sys.state == STATE_HOMING) {
369  st_go_idle();
370  }
371  }
372 }
void st_parking_restore_buffer()
Restores the step segment buffer to the normal run state after a parking motion.
void mc_homing_cycle(uint8_t cycle_mask)
Perform homing cycle to locate and set machine zero. Only '$H' executes this command.
volatile uint8_t sys_probe_state
Probing state value. Used to coordinate the probing cycle with stepper ISR.
Definition: system.h:133
#define EXEC_ALARM_PROBE_FAIL_CONTACT
Definition: system.h:44
void st_parking_setup_buffer()
Changes the run state of the step segment buffer to execute the special parking motion.
void plan_sync_position()
Reset the planner position vectors. Called by the system abort/initialization routine.
Definition: planner.c:471
uint8_t plan_buffer_line(float *target, plan_line_data_t *pl_data)
Add a new linear movement to the buffer. target[N_AXIS] is the signed, absolute target position in mi...
Definition: planner.c:310
void protocol_auto_cycle_start()
Auto-cycle start triggers when there is a motion ready to execute and if the main program is not...
Definition: protocol.c:194
#define EXEC_ALARM_ABORT_CYCLE
Definition: system.h:42
void limits_init()
Initialize the limits module.
Definition: limits.c:32
uint8_t probe_get_state()
Returns the probe pin state. Triggered = true. Called by gcode parser and probe state monitor...
Definition: probe.c:49
void limits_disable()
Disables hard limits.
Definition: limits.c:57
void delay_sec(float seconds, uint8_t mode)
Non-blocking delay function used for general operation and suspend features.
Definition: nuts_bolts.c:111
void mc_dwell(float seconds)
Execute dwell in seconds.
void gc_sync_position()
Sets g-code parser position in mm. Input in steps. Called by the system abort and hard...
Definition: gcode.c:53
#define PROBE_OFF
Values that define the probing state machine.
Definition: probe.h:24
#define GC_PROBE_ABORT
Definition: gcode.h:141
#define bit_true(x, mask)
Definition: nuts_bolts.h:58
void system_set_exec_state_flag(uint8_t mask)
Special handlers for setting and clearing Grbl's real-time execution flags.
Definition: system.c:340
void protocol_buffer_synchronize()
Block until all buffered steps are executed or in a cycle state. Works with feed hold.
Definition: protocol.c:177
Planner data prototype. Must be used when passing new motions to the planner.
Definition: planner.h:78
#define GC_PROBE_FAIL_END
Definition: gcode.h:143
#define PROBE_ACTIVE
Actively watching the input pin.
Definition: probe.h:25
#define N_ARC_CORRECTION
Number of arc generation iterations by small angle approximation before exact arc trajectory...
Definition: config.h:336
float arc_tolerance
Definition: settings.h:87
#define BITFLAG_SOFT_LIMIT_ENABLE
Definition: settings.h:40
#define GC_PARSER_PROBE_IS_NO_ERROR
Definition: gcode.h:155
volatile uint8_t sys_rt_exec_alarm
Global realtime executor bitflag variable for setting various alarms.
Definition: system.h:135
uint8_t state
Tracks the current system state of Grbl.
Definition: system.h:112
void limits_go_home(uint8_t cycle_mask)
NOTE: Only the abort realtime command can interrupt this process.
Definition: limits.c:145
#define EXEC_RESET
bitmask 00010000
Definition: system.h:35
#define STEP_CONTROL_EXECUTE_HOLD
Definition: system.h:94
void plan_reset()
Initialize and reset the motion plan subsystem.
Definition: planner.c:198
#define ARC_ANGULAR_TRAVEL_EPSILON
The arc G2/3 g-code standard is problematic by definition. Radius-based arcs have horrible numerical...
Definition: config.h:346
#define DELAY_MODE_DWELL
Definition: nuts_bolts.h:47
void spindle_stop()
Disables the spindle and sets PWM output to zero when PWM variable spindle speed is enabled...
void mc_line(float *target, plan_line_data_t *pl_data)
Execute linear motion in absolute millimeter coordinates. Feed rate given in millimeters/second.
#define HOMING_CYCLE_1
OPTIONAL: Then move X,Y at the same time.
Definition: config.h:103
void probe_configure_invert_mask(uint8_t is_probe_away)
Called by probe_init() and the mc_probe() routines. Sets up the probe pin invert mask to...
Definition: probe.c:41
uint8_t abort
System abort flag. Forces exit back to main loop for reset.
Definition: system.h:113
#define EXEC_ALARM_HOMING_FAIL_RESET
Definition: system.h:45
uint8_t mc_probe_cycle(float *target, plan_line_data_t *pl_data, uint8_t parser_flags)
Perform tool length probe cycle. Requires probe switch.
void mc_parking_motion(float *parking_target, plan_line_data_t *pl_data)
Plans and executes the single special motion case for parking. Independent of main planner buffer...
void limits_soft_check(float *target)
Performs a soft limit check. Called from mc_line() only. Assumes the machine has been homed...
Definition: limits.c:342
#define EXEC_ALARM_PROBE_FAIL_INITIAL
Definition: system.h:43
#define STATE_CYCLE
Cycle is running or motions are being executed.
Definition: system.h:76
uint8_t flags
Contains default boolean settings.
Definition: settings.h:92
#define STATE_CHECK_MODE
G-code check mode. Locks out planner and motion only.
Definition: system.h:74
void report_probe_parameters()
Prints current probe parameters. Upon a probe command, these parameters are updated upon a...
Definition: report.c:221
uint8_t probe_succeeded
Tracks if last probing cycle was successful.
Definition: system.h:117
#define EXEC_CYCLE_START
bitmask 00000010
Definition: system.h:32
system_t sys
Declare system global variable structure.
Definition: main.c:25
#define GC_PARSER_PROBE_IS_AWAY
Definition: gcode.h:154
int32_t sys_position[N_AXIS]
NOTE: These position variables may need to be declared as volatiles, if problems arise.
Definition: system.h:130
void st_go_idle()
Stepper shutdown.
Definition: stepper.c:224
void protocol_exec_rt_system()
Executes run-time commands, when required. This function primarily operates as Grbl's state...
Definition: protocol.c:223
#define bit_isfalse(x, mask)
Definition: nuts_bolts.h:61
uint8_t step_control
Governs the step segment generator depending on system state.
Definition: system.h:116
void st_prep_buffer()
Prepares step segment buffer. Continuously called from main program.
Definition: stepper.c:594
void st_wake_up()
BLOCK VELOCITY PROFILE DEFINITION.
Definition: stepper.c:199
#define HOMING_CYCLE_0
Define the homing cycle patterns with bitmasks. The homing cycle first performs a search mode...
Definition: config.h:102
#define EXEC_ALARM_HARD_LIMIT
Alarm executor codes. Valid values (1-255). Zero is reserved.
Definition: system.h:40
volatile uint8_t sys_rt_exec_state
Global realtime executor bitflag variable for state management. See EXEC bitmasks.
Definition: system.h:134
#define PL_COND_FLAG_INVERSE_TIME
Interprets feed rate value as inverse time when set.
Definition: planner.h:36
memcpy(block_coord_system, gc_state.coord_system, sizeof(gc_state.coord_system))
settings_t settings
Definition: settings.c:24
void mc_arc(float *target, plan_line_data_t *pl_data, float *position, float *offset, float radius, uint8_t axis_0, uint8_t axis_1, uint8_t axis_linear, uint8_t is_clockwise_arc)
Execute an arc in offset mode format. position == current xyz, target == target xyz,.
#define bit_false(x, mask)
Definition: nuts_bolts.h:59
#define GC_PROBE_FAIL_INIT
Definition: gcode.h:142
#define STEP_CONTROL_END_MOTION
Definition: system.h:93
#define GC_PROBE_CHECK_MODE
Definition: gcode.h:147
#define STATE_JOG
Jogging mode.
Definition: system.h:78
#define STATE_HOMING
Performing homing cycle.
Definition: system.h:75
int32_t sys_probe_position[N_AXIS]
Last probe position in machine coordinates and steps.
Definition: system.h:131
void protocol_execute_realtime()
This function is the general interface to Grbl's real-time command execution system. It is called.
Definition: protocol.c:213
float feed_rate
Desired feed rate for line motion. Value is ignored, if rapid motion.
Definition: planner.h:79
void system_set_exec_alarm(uint8_t code)
Definition: system.c:354
uint8_t condition
Bitflag variable to indicate planner conditions. See defines above.
Definition: planner.h:82
uint8_t plan_check_full_buffer()
Returns the availability status of the block ring buffer. True, if full.
Definition: planner.c:246
void mc_reset()
Method to ready the system to reset by setting the realtime reset command and killing any...
#define STEP_CONTROL_EXECUTE_SYS_MOTION
Definition: system.h:95
plan_line_data_t * pl_data
Definition: gcode.c:859
void st_reset()
Reset and clear stepper subsystem variables.
Definition: stepper.c:476
void coolant_stop()
Directly called by coolant_init(), coolant_set_state(), and mc_reset(), which can be at...
uint8_t limits_get_state()
Returns limit state as a bit-wise uint8 variable. Each bit indicates an axis limit, where.
Definition: limits.c:66
#define GC_PROBE_FOUND
Define probe cycle exit states and assign proper position updating.
Definition: gcode.h:140
#define STATE_IDLE
Define system state bit map. The state variable primarily tracks the individual functions.
Definition: system.h:72
#define bit_istrue(x, mask)
Definition: nuts_bolts.h:60