Dual motor support for self-squaring gantry homing.

- New dual motor support feature for gantry CNC machines. An axis motor is  efficiently mirrored to a dedicated set of step and direction pins (D12/D13 or A3/A4) with no detectable loss of performance. Primarily used to independently home both sides of a dual-motor gantry with a pair of limit switches (second shared with Z-axis limit pin). When the limit switches are setup correctly, Grbl will self-square the gantry (and stay square if $1=255 is programmed). Beware use at your own risk! Grbl is not responsible for any damage to any machines.

- Dual axis motors is only supported on the X-axis or Y-axis. And deletes the spindle direction(D13) and optional coolant mist (A4) features to make room for the dual motor step and direction pins.

- Dual axis homing will automatically abort homing if one limit switch triggers and travels more than 5% (default) of the non-dual axis max travel setting. For example, if the X-axis has dual motors and one X-axis triggers during homing, Grbl will abort 5% of the Y-axis max travel and the other X-axis limit fails to trigger. This will help keep any misconfigurations or failed limit switches from damaging the machine, but not completely eliminate this risk. Please take all precautions and test thouroughly before using this.

- Dual axis motors supports two configurations:

- Support for Arduino CNC shield clones. For these, step/dir on pins D12/D13, and spindle enable is moved to A3 (old coolant enable), while coolant enable is moved to A4 (SDA pin). Variable spindle/laser mode option is NOT supported for this shield.

- Support for Protoneer CNC Shield v3.51. Step/dir on pins A3/A4, and  coolant enable is moved to D13 (old spindle direction pin). Variable spindle/laser mode option IS supported for this shield.

- Added Bob's CNC E3 and E4 CNC machine defaults.
This commit is contained in:
Sonny Jeon 2019-07-30 21:51:49 -04:00
parent bb25d2f97e
commit b75e5571ee
13 changed files with 578 additions and 104 deletions

View file

@ -30,6 +30,14 @@
#define HOMING_AXIS_LOCATE_SCALAR 5.0 // Must be > 1 to ensure limit switch is cleared.
#endif
#ifdef ENABLE_DUAL_AXIS
// Flags for dual axis async limit trigger check.
#define DUAL_AXIS_CHECK_DISABLE 0 // Must be zero
#define DUAL_AXIS_CHECK_ENABLE bit(0)
#define DUAL_AXIS_CHECK_TRIGGER_1 bit(1)
#define DUAL_AXIS_CHECK_TRIGGER_2 bit(2)
#endif
void limits_init()
{
LIMIT_DDR &= ~(LIMIT_MASK); // Set as input pins
@ -79,6 +87,9 @@ uint8_t limits_get_state()
for (idx=0; idx<N_AXIS; idx++) {
if (pin & get_limit_pin_mask(idx)) { limit_state |= (1 << idx); }
}
#ifdef ENABLE_DUAL_AXIS
if (pin & (1<<DUAL_LIMIT_BIT)) { limit_state |= (1 << N_AXIS); }
#endif
}
return(limit_state);
}
@ -159,6 +170,20 @@ void limits_go_home(uint8_t cycle_mask)
// Initialize variables used for homing computations.
uint8_t n_cycle = (2*N_HOMING_LOCATE_CYCLE+1);
uint8_t step_pin[N_AXIS];
#ifdef ENABLE_DUAL_AXIS
uint8_t step_pin_dual;
uint8_t dual_axis_async_check;
int32_t dual_trigger_position;
#if (DUAL_AXIS_SELECT == X_AXIS)
float fail_distance = (-DUAL_AXIS_HOMING_FAIL_AXIS_LENGTH_PERCENT/100.0)*settings.max_travel[Y_AXIS];
#else
float fail_distance = (-DUAL_AXIS_HOMING_FAIL_AXIS_LENGTH_PERCENT/100.0)*settings.max_travel[X_AXIS];
#endif
fail_distance = min(fail_distance, DUAL_AXIS_HOMING_FAIL_DISTANCE_MAX);
fail_distance = max(fail_distance, DUAL_AXIS_HOMING_FAIL_DISTANCE_MIN);
int32_t dual_fail_distance = trunc(fail_distance*settings.steps_per_mm[DUAL_AXIS_SELECT]);
// int32_t dual_fail_distance = trunc((DUAL_AXIS_HOMING_TRIGGER_FAIL_DISTANCE)*settings.steps_per_mm[DUAL_AXIS_SELECT]);
#endif
float target[N_AXIS];
float max_travel = 0.0;
uint8_t idx;
@ -175,6 +200,9 @@ void limits_go_home(uint8_t cycle_mask)
max_travel = max(max_travel,(-HOMING_AXIS_SEARCH_SCALAR)*settings.max_travel[idx]);
}
}
#ifdef ENABLE_DUAL_AXIS
step_pin_dual = (1<<DUAL_STEP_BIT);
#endif
// Set search mode with approach at seek rate to quickly engage the specified cycle_mask limit switches.
bool approach = true;
@ -187,6 +215,11 @@ void limits_go_home(uint8_t cycle_mask)
// Initialize and declare variables needed for homing routine.
axislock = 0;
#ifdef ENABLE_DUAL_AXIS
sys.homing_axis_lock_dual = 0;
dual_trigger_position = 0;
dual_axis_async_check = DUAL_AXIS_CHECK_DISABLE;
#endif
n_active_axis = 0;
for (idx=0; idx<N_AXIS; idx++) {
// Set target location for active axes and setup computation for homing rate.
@ -217,6 +250,9 @@ void limits_go_home(uint8_t cycle_mask)
}
// Apply axislock to the step port pins active in this cycle.
axislock |= step_pin[idx];
#ifdef ENABLE_DUAL_AXIS
if (idx == DUAL_AXIS_SELECT) { sys.homing_axis_lock_dual = step_pin_dual; }
#endif
}
}
@ -242,11 +278,41 @@ void limits_go_home(uint8_t cycle_mask)
else { axislock &= ~(step_pin[A_MOTOR]|step_pin[B_MOTOR]); }
#else
axislock &= ~(step_pin[idx]);
#ifdef ENABLE_DUAL_AXIS
if (idx == DUAL_AXIS_SELECT) { dual_axis_async_check |= DUAL_AXIS_CHECK_TRIGGER_1; }
#endif
#endif
}
}
}
sys.homing_axis_lock = axislock;
#ifdef ENABLE_DUAL_AXIS
if (sys.homing_axis_lock_dual) { // NOTE: Only true when homing dual axis.
if (limit_state & (1 << N_AXIS)) {
sys.homing_axis_lock_dual = 0;
dual_axis_async_check |= DUAL_AXIS_CHECK_TRIGGER_2;
}
}
// When first dual axis limit triggers, record position and begin checking distance until other limit triggers. Bail upon failure.
if (dual_axis_async_check) {
if (dual_axis_async_check & DUAL_AXIS_CHECK_ENABLE) {
if (( dual_axis_async_check & (DUAL_AXIS_CHECK_TRIGGER_1 | DUAL_AXIS_CHECK_TRIGGER_2)) == (DUAL_AXIS_CHECK_TRIGGER_1 | DUAL_AXIS_CHECK_TRIGGER_2)) {
dual_axis_async_check = DUAL_AXIS_CHECK_DISABLE;
} else {
if (abs(dual_trigger_position - sys_position[DUAL_AXIS_SELECT]) > dual_fail_distance) {
system_set_exec_alarm(EXEC_ALARM_HOMING_FAIL_DUAL_APPROACH);
mc_reset();
protocol_execute_realtime();
return;
}
}
} else {
dual_axis_async_check |= DUAL_AXIS_CHECK_ENABLE;
dual_trigger_position = sys_position[DUAL_AXIS_SELECT];
}
}
#endif
}
st_prep_buffer(); // Check and prep segment buffer. NOTE: Should take no longer than 200us.
@ -273,7 +339,11 @@ void limits_go_home(uint8_t cycle_mask)
}
}
} while (STEP_MASK & axislock);
#ifdef ENABLE_DUAL_AXIS
} while ((STEP_MASK & axislock) || (sys.homing_axis_lock_dual));
#else
} while (STEP_MASK & axislock);
#endif
st_reset(); // Immediately force kill steppers and reset step segment buffer.
delay_ms(settings.homing_debounce_delay); // Delay to allow transient dynamics to dissipate.