Merge branch 'dev_2' into dev
Conflicts: README.md gcode.c motion_control.c planner.c planner.h protocol.c report.c settings.c settings.h stepper.c stepper.h
This commit is contained in:
129
motion_control.c
129
motion_control.c
@ -3,7 +3,7 @@
|
||||
Part of Grbl
|
||||
|
||||
Copyright (c) 2009-2011 Simen Svale Skogsrud
|
||||
Copyright (c) 2011-2012 Sungeun K. Jeon
|
||||
Copyright (c) 2011-2013 Sungeun K. Jeon
|
||||
Copyright (c) 2011 Jens Geisler
|
||||
|
||||
Grbl is free software: you can redistribute it and/or modify
|
||||
@ -42,41 +42,15 @@
|
||||
// (1 minute)/feed_rate time.
|
||||
// NOTE: This is the primary gateway to the grbl planner. All line motions, including arc line
|
||||
// segments, must pass through this routine before being passed to the planner. The seperation of
|
||||
// mc_line and plan_buffer_line is done primarily to make backlash compensation or canned cycle
|
||||
// integration simple and direct.
|
||||
// TODO: Check for a better way to avoid having to push the arguments twice for non-backlash cases.
|
||||
// However, this keeps the memory requirements lower since it doesn't have to call and hold two
|
||||
// plan_buffer_lines in memory. Grbl only has to retain the original line input variables during a
|
||||
// backlash segment(s).
|
||||
// mc_line and plan_buffer_line is done primarily to place non-planner-type functions from being
|
||||
// in the planner and to let backlash compensation or canned cycle integration simple and direct.
|
||||
void mc_line(float *target, float feed_rate, uint8_t invert_feed_rate)
|
||||
{
|
||||
// TO TEST: Perform soft limit check here. Just check if the target x,y,z values are outside the
|
||||
// work envelope. Should be straightforward and efficient. By placing it here, rather than in
|
||||
// the g-code parser, it directly picks up motions from everywhere in Grbl.
|
||||
// TODO: Eventually move the soft limit check into limits.c.
|
||||
if (bit_istrue(settings.flags,BITFLAG_SOFT_LIMIT_ENABLE)) {
|
||||
uint8_t i;
|
||||
for (i=0; i<N_AXIS; i++) {
|
||||
// TODO: This does not account for homing switches on the other side of travel, meaning that
|
||||
// the machine travel envelope is flipped or negative, instead of positive. There needs to be
|
||||
// a fix to this problem before release.
|
||||
if ((target[i] < 0) || (target[i] > settings.max_travel[i])) {
|
||||
// TODO: Need to make this more in-line with the rest of the alarm and runtime execution handling.
|
||||
// Not quite right. Also this should force Grbl to feed hold and exit, rather than stopping and alarm
|
||||
// out. This would help retain machine position, but is this really required?
|
||||
if (sys.state != STATE_ALARM) {
|
||||
if (bit_isfalse(sys.execute,EXEC_ALARM)) {
|
||||
mc_reset(); // Initiate system kill.
|
||||
report_alarm_message(ALARM_SOFT_LIMIT);
|
||||
sys.state = STATE_ALARM;
|
||||
sys.execute |= EXEC_CRIT_EVENT; // Indicate hard limit critical event
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If in check gcode mode, prevent motion by blocking planner.
|
||||
// If enabled, check for soft limit violations. Placed here all line motions are picked up
|
||||
// from everywhere in Grbl.
|
||||
if (bit_istrue(settings.flags,BITFLAG_SOFT_LIMIT_ENABLE)) { limits_soft_check(target); }
|
||||
|
||||
// If in check gcode mode, prevent motion by blocking planner. Soft limits still work.
|
||||
if (sys.state == STATE_CHECK_MODE) { return; }
|
||||
|
||||
// TODO: Backlash compensation may be installed here. Only need direction info to track when
|
||||
@ -85,31 +59,25 @@ void mc_line(float *target, float feed_rate, uint8_t invert_feed_rate)
|
||||
// backlash steps will need to be also tracked. Not sure what the best strategy is for this,
|
||||
// i.e. keep the planner independent and do the computations in the status reporting, or let
|
||||
// the planner handle the position corrections. The latter may get complicated.
|
||||
// TODO: Backlash comp positioning values may need to be kept at a system level, i.e. tracking
|
||||
// true position after a feed hold in the middle of a backlash move. The difficulty is in making
|
||||
// sure that the stepper subsystem and planner are working in sync, and the status report
|
||||
// position also takes this into account.
|
||||
|
||||
// If the buffer is full: good! That means we are well ahead of the robot.
|
||||
// Remain in this loop until there is room in the buffer.
|
||||
do {
|
||||
protocol_execute_runtime(); // Check for any run-time commands
|
||||
if (sys.abort) { return; } // Bail, if system abort.
|
||||
} while ( plan_check_full_buffer() );
|
||||
plan_buffer_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS], feed_rate, invert_feed_rate);
|
||||
if ( plan_check_full_buffer() ) { mc_auto_cycle_start(); } // Auto-cycle start when buffer is full.
|
||||
else { break; }
|
||||
} while (1);
|
||||
|
||||
plan_buffer_line(target, feed_rate, invert_feed_rate);
|
||||
|
||||
// If idle, indicate to the system there is now a planned block in the buffer ready to cycle
|
||||
// start. Otherwise ignore and continue on.
|
||||
if (!sys.state) { sys.state = STATE_QUEUED; }
|
||||
|
||||
// Auto-cycle start immediately after planner finishes. Enabled/disabled by grbl settings. During
|
||||
// a feed hold, auto-start is disabled momentarily until the cycle is resumed by the cycle-start
|
||||
// runtime command.
|
||||
// NOTE: This is allows the user to decide to exclusively use the cycle start runtime command to
|
||||
// begin motion or let grbl auto-start it for them. This is useful when: manually cycle-starting
|
||||
// when the buffer is completely full and primed; auto-starting, if there was only one g-code
|
||||
// command sent during manual operation; or if a system is prone to buffer starvation, auto-start
|
||||
// helps make sure it minimizes any dwelling/motion hiccups and keeps the cycle going.
|
||||
// NOTE: Moved into main loop and plan_check_full_buffer() as a test. This forces Grbl to process
|
||||
// all of the commands in the serial read buffer or until the planner buffer is full before auto
|
||||
// cycle starting. Will eventually need to remove the following command.
|
||||
// if (sys.auto_start) { st_cycle_start(); }
|
||||
}
|
||||
|
||||
|
||||
@ -181,8 +149,8 @@ void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8
|
||||
This is important when there are successive arc motions.
|
||||
*/
|
||||
// Computes: cos_T = 1 - theta_per_segment^2/2, sin_T = theta_per_segment - theta_per_segment^3/6) in ~52usec
|
||||
float cos_T = 2 - theta_per_segment*theta_per_segment;
|
||||
float sin_T = theta_per_segment*0.16666667*(cos_T + 4);
|
||||
float cos_T = 2.0 - theta_per_segment*theta_per_segment;
|
||||
float sin_T = theta_per_segment*0.16666667*(cos_T + 4.0);
|
||||
cos_T *= 0.5;
|
||||
|
||||
float arc_target[N_AXIS];
|
||||
@ -256,32 +224,40 @@ void mc_go_home()
|
||||
protocol_execute_runtime(); // Check for reset and set system abort.
|
||||
if (sys.abort) { return; } // Did not complete. Alarm state set by mc_alarm.
|
||||
|
||||
// The machine should now be homed and machine zero has been located. Upon completion,
|
||||
// reset system position and sync internal position vectors.
|
||||
clear_vector_float(sys.position); // Set machine zero
|
||||
sys_sync_current_position();
|
||||
sys.state = STATE_IDLE; // Set system state to IDLE to complete motion and indicate homed.
|
||||
|
||||
// Pull-off axes (that have been homed) from limit switches before continuing motion.
|
||||
// The machine should now be homed and machine limits have been located. By default,
|
||||
// grbl defines machine space as all negative, as do most CNCs. Since limit switches
|
||||
// can be on either side of an axes, check and set machine zero appropriately.
|
||||
// At the same time, set up pull-off maneuver from axes limit switches that have been homed.
|
||||
// This provides some initial clearance off the switches and should also help prevent them
|
||||
// from falsely tripping when hard limits are enabled.
|
||||
float target[N_AXIS];
|
||||
target[X_AXIS] = target[Y_AXIS] = target[Z_AXIS] = settings.homing_pulloff;
|
||||
if (HOMING_LOCATE_CYCLE & (1<<X_AXIS)) {
|
||||
if (bit_isfalse(settings.homing_dir_mask,(1<<X_DIRECTION_BIT))) { target[X_AXIS] = -target[X_AXIS]; }
|
||||
float pulloff_target[N_AXIS];
|
||||
clear_vector_float(pulloff_target); // Zero pulloff target.
|
||||
clear_vector_long(sys.position); // Zero current position for now.
|
||||
uint8_t idx;
|
||||
for (idx=0; idx<N_AXIS; idx++) {
|
||||
// Set up pull off targets and machine positions for limit switches homed in the negative
|
||||
// direction, rather than the traditional positive. Leave non-homed positions as zero and
|
||||
// do not move them.
|
||||
// NOTE: settings.max_travel[] is stored as a negative value.
|
||||
if (HOMING_LOCATE_CYCLE & bit(idx)) {
|
||||
if ( settings.homing_dir_mask & get_direction_mask(idx) ) {
|
||||
pulloff_target[idx] = settings.homing_pulloff+settings.max_travel[idx];
|
||||
sys.position[idx] = lround(settings.max_travel[idx]*settings.steps_per_mm[idx]);
|
||||
} else {
|
||||
pulloff_target[idx] = -settings.homing_pulloff;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (HOMING_LOCATE_CYCLE & (1<<Y_AXIS)) {
|
||||
if (bit_isfalse(settings.homing_dir_mask,(1<<Y_DIRECTION_BIT))) { target[Y_AXIS] = -target[Y_AXIS]; }
|
||||
}
|
||||
if (HOMING_LOCATE_CYCLE & (1<<Z_AXIS)) {
|
||||
if (bit_isfalse(settings.homing_dir_mask,(1<<Z_DIRECTION_BIT))) { target[Z_AXIS] = -target[Z_AXIS]; }
|
||||
}
|
||||
mc_line(target, settings.homing_seek_rate, false);
|
||||
plan_sync_position(); // Sync planner position to home for pull-off move.
|
||||
|
||||
sys.state = STATE_IDLE; // Set system state to IDLE to complete motion and indicate homed.
|
||||
|
||||
mc_line(pulloff_target, settings.homing_seek_rate, false);
|
||||
st_cycle_start(); // Move it. Nothing should be in the buffer except this motion.
|
||||
plan_synchronize(); // Make sure the motion completes.
|
||||
|
||||
// The gcode parser position circumvented by the pull-off maneuver, so sync position vectors.
|
||||
sys_sync_current_position();
|
||||
// The gcode parser position circumvented by the pull-off maneuver, so sync position now.
|
||||
gc_sync_position();
|
||||
|
||||
// If hard limits feature enabled, re-enable hard limits pin change register after homing cycle.
|
||||
if (bit_istrue(settings.flags,BITFLAG_HARD_LIMIT_ENABLE)) { LIMIT_PCMSK |= LIMIT_MASK; }
|
||||
@ -289,6 +265,17 @@ void mc_go_home()
|
||||
}
|
||||
|
||||
|
||||
// Auto-cycle start is a user setting that automatically begins the cycle when a user enters
|
||||
// a valid motion command either manually or by a streaming tool. This is intended as a beginners
|
||||
// feature to help new users to understand g-code. It can be disabled. Otherwise, the normal
|
||||
// operation of cycle start is manually issuing a cycle start command whenever the user is
|
||||
// ready and there is a valid motion command in the planner queue.
|
||||
// NOTE: This function is called from the main loop and mc_line() only and executes when one of
|
||||
// two conditions exist respectively: There are no more blocks sent (i.e. streaming is finished,
|
||||
// single commands), or the planner buffer is full and ready to go.
|
||||
void mc_auto_cycle_start() { if (sys.auto_start) { st_cycle_start(); } }
|
||||
|
||||
|
||||
// Method to ready the system to reset by setting the runtime reset command and killing any
|
||||
// active processes in the system. This also checks if a system reset is issued while Grbl
|
||||
// is in a motion state. If so, kills the steppers and sets the system alarm to flag position
|
||||
|
Reference in New Issue
Block a user