Homing and limit updates. Minor bug fixes.

- Updated new homing cycle to error out when a pull-off motion detects
the limit is still active.

- Created a limits_get_state() function to centralize it. It reports
state as a bit-wise booleans according to axis numbering.

- Updated the print uint8 functions. Generalized it to allow both base2
and base10 printouts, while allowing base2 prints with N_AXIS digits
for limit state status reports. Doing this saved about 100bytes of
flash as well.

- Applied CoreXY status reporting bug fix by @phd0. Thanks!
This commit is contained in:
Sonny Jeon
2015-05-23 11:57:30 -06:00
parent e704862f11
commit f85c481ded
10 changed files with 172 additions and 70 deletions

View File

@ -26,7 +26,9 @@
Ensure one and only one of these DEFAULTS_XXX values is defined in config.h */
#ifndef defaults_h
// Don't #define defaults_h here, let the selected file do it. Prevents incuding more than one.
// Only define the DEFAULT_XXX with where to find the corresponding default_XXX.h file.
// Don't #define defaults_h here, let the selected file do it. Prevents including more than one.
#ifdef DEFAULTS_GENERIC
// Grbl generic default settings. Should work across different machines.

View File

@ -23,7 +23,7 @@
// Grbl versioning system
#define GRBL_VERSION "0.9i"
#define GRBL_VERSION_BUILD "20150516"
#define GRBL_VERSION_BUILD "20150523"
// Define standard libraries used by Grbl.
#include <avr/io.h>

View File

@ -55,6 +55,7 @@ void limits_init()
}
// Disables hard limits.
void limits_disable()
{
LIMIT_PCMSK &= ~LIMIT_MASK; // Disable specific pins of the Pin Change Interrupt
@ -62,6 +63,24 @@ void limits_disable()
}
// Returns limit state as a bit-wise uint8 variable. Each bit indicates an axis limit, where
// triggered is 1 and not triggered is 0. Invert mask is applied. Axes are defined by their
// number in bit position, i.e. Z_AXIS is (1<<2) or bit 2, and Y_AXIS is (1<<1) or bit 1.
uint8_t limits_get_state()
{
uint8_t limit_state = 0;
uint8_t pin = (LIMIT_PIN & LIMIT_MASK);
if (bit_isfalse(settings.flags,BITFLAG_INVERT_LIMIT_PINS)) { pin ^= LIMIT_MASK; }
if (pin) {
uint8_t idx;
for (idx=0; idx<N_AXIS; idx++) {
if (pin & get_limit_pin_mask(idx)) { limit_state |= (1 << idx); }
}
}
return(limit_state);
}
// This is the Limit Pin Change Interrupt, which handles the hard limit feature. A bouncing
// limit switch can cause a lot of problems, like false readings and multiple interrupt calls.
// If a switch is triggered at all, something bad has happened and treat it as such, regardless
@ -84,10 +103,8 @@ void limits_disable()
if (sys.state != STATE_ALARM) {
if (!(sys.rt_exec_alarm)) {
#ifdef HARD_LIMIT_FORCE_STATE_CHECK
uint8_t bits = (LIMIT_PIN & LIMIT_MASK);
// Check limit pin state.
if (bit_isfalse(settings.flags,BITFLAG_INVERT_LIMIT_PINS)) { bits ^= LIMIT_MASK; }
if (bits) {
if (limits_get_state()) {
mc_reset(); // Initiate system kill.
bit_true_atomic(sys.rt_exec_alarm, (EXEC_ALARM_HARD_LIMIT|EXEC_CRITICAL_EVENT)); // Indicate hard limit critical event
}
@ -106,10 +123,8 @@ void limits_disable()
WDTCSR &= ~(1<<WDIE); // Disable watchdog timer.
if (sys.state != STATE_ALARM) { // Ignore if already in alarm state.
if (!(sys.rt_exec_alarm)) {
uint8_t bits = (LIMIT_PIN & LIMIT_MASK);
// Check limit pin state.
if (bit_isfalse(settings.flags,BITFLAG_INVERT_LIMIT_PINS)) { bits ^= LIMIT_MASK; }
if (bits) {
if (limits_get_state()) {
mc_reset(); // Initiate system kill.
bit_true_atomic(sys.rt_exec_alarm, (EXEC_ALARM_HARD_LIMIT|EXEC_CRITICAL_EVENT)); // Indicate hard limit critical event
}
@ -118,7 +133,7 @@ void limits_disable()
}
#endif
// Homes the specified cycle axes, sets the machine position, and performs a pull-off motion after
// completing. Homing is a special motion case, which involves rapid uncontrolled stops to locate
// the trigger point of the limit switches. The rapid stops are handled by a system level axis lock
@ -132,13 +147,12 @@ void limits_go_home(uint8_t cycle_mask)
// Initialize
uint8_t n_cycle = (2*N_HOMING_LOCATE_CYCLE+1);
uint8_t limit_pin[N_AXIS], step_pin[N_AXIS];
uint8_t step_pin[N_AXIS];
float target[N_AXIS];
float max_travel = 0.0;
uint8_t idx;
for (idx=0; idx<N_AXIS; idx++) {
// Initialize limit and step pin masks
limit_pin[idx] = get_limit_pin_mask(idx);
// Initialize step pin masks
step_pin[idx] = get_step_pin_mask(idx);
#ifdef COREXY
if ((idx==A_MOTOR)||(idx==B_MOTOR)) { step_pin[idx] = (get_step_pin_mask(X_AXIS)|get_step_pin_mask(Y_AXIS)); }
@ -199,11 +213,10 @@ void limits_go_home(uint8_t cycle_mask)
do {
if (approach) {
// Check limit state. Lock out cycle axes when they change.
limit_state = LIMIT_PIN;
if (bit_isfalse(settings.flags,BITFLAG_INVERT_LIMIT_PINS)) { limit_state ^= LIMIT_MASK; }
limit_state = limits_get_state();
for (idx=0; idx<N_AXIS; idx++) {
if (axislock & step_pin[idx]) {
if (limit_state & limit_pin[idx]) { axislock &= ~(step_pin[idx]); }
if (limit_state & (1 << idx)) { axislock &= ~(step_pin[idx]); }
}
}
sys.homing_axis_lock = axislock;
@ -211,16 +224,18 @@ void limits_go_home(uint8_t cycle_mask)
st_prep_buffer(); // Check and prep segment buffer. NOTE: Should take no longer than 200us.
// Exit routines: User abort homing and alarm upon safety door or no limit switch found.
// No time to run protocol_execute_realtime() in this loop.
// Exit routines: No time to run protocol_execute_realtime() in this loop.
if (sys.rt_exec_state & (EXEC_SAFETY_DOOR | EXEC_RESET | EXEC_CYCLE_STOP)) {
if ((sys.rt_exec_state & (EXEC_SAFETY_DOOR | EXEC_RESET)) ||
((approach) && (sys.rt_exec_state & EXEC_CYCLE_STOP))) {
mc_reset();
// Homing failure: Limit switches are still engaged after pull-off motion
if ( (sys.rt_exec_state & (EXEC_SAFETY_DOOR | EXEC_RESET)) || // Safety door or reset issued
(!approach && (limits_get_state() & cycle_mask)) || // Limit switch still engaged after pull-off motion
( approach && (sys.rt_exec_state & EXEC_CYCLE_STOP)) ) { // Limit switch not found during approach.
mc_reset(); // Stop motors, if they are running.
protocol_execute_realtime();
return;
} else {
bit_false_atomic(sys.rt_exec_state,EXEC_CYCLE_STOP);
// Pull-off motion complete. Disable CYCLE_STOP from executing.
bit_false_atomic(sys.rt_exec_state,EXEC_CYCLE_STOP);
break;
}
}
@ -245,7 +260,7 @@ void limits_go_home(uint8_t cycle_mask)
}
} while (n_cycle-- > 0);
// The active cycle axes 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 axes machine zero appropriately. Also,
@ -289,9 +304,8 @@ void limits_go_home(uint8_t cycle_mask)
}
}
plan_sync_position(); // Sync planner position to homed machine position.
// Set system state to homing before returning.
sys.state = STATE_HOMING;
// sys.state = STATE_HOMING; // Ensure system state set as homing before returning.
}

View File

@ -26,8 +26,12 @@
// Initialize the limits module
void limits_init();
// Disables hard limits.
void limits_disable();
// Returns limit state as a bit-wise uint8 variable.
uint8_t limits_get_state();
// Perform one portion of the homing cycle based on the input settings.
void limits_go_home(uint8_t cycle_mask);

View File

@ -225,9 +225,7 @@ void mc_homing_cycle()
// with machines with limits wired on both ends of travel to one limit pin.
// TODO: Move the pin-specific LIMIT_PIN call to limits.c as a function.
#ifdef LIMITS_TWO_SWITCHES_ON_AXES
uint8_t limit_state = (LIMIT_PIN & LIMIT_MASK);
if (bit_isfalse(settings.flags,BITFLAG_INVERT_LIMIT_PINS)) { limit_state ^= LIMIT_MASK; }
if (limit_state) {
if (limits_get_state()) {
mc_reset(); // Issue system reset and ensure spindle and coolant are shutdown.
bit_true_atomic(sys.rt_exec_alarm, (EXEC_ALARM_HARD_LIMIT|EXEC_CRITICAL_EVENT));
return;
@ -256,7 +254,7 @@ void mc_homing_cycle()
// Gcode parser position was circumvented by the limits_go_home() routine, so sync position now.
gc_sync_position();
// If hard limits feature enabled, re-enable hard limits pin change register after homing cycle.
limits_init();
}

View File

@ -60,38 +60,36 @@ void printPgmString(const char *s)
// }
void print_uint8_base2(uint8_t n)
// Prints an uint8 variable with base and number of desired digits.
void print_unsigned_int8(uint8_t n, uint8_t base, uint8_t digits)
{
unsigned char buf[8];
uint8_t i = 0;
for (; i < 8; i++) {
buf[i] = n & 1;
n >>= 1;
}
for (; i > 0; i--)
serial_write('0' + buf[i - 1]);
}
void print_uint8_base10(uint8_t n)
{
if (n == 0) {
serial_write('0');
return;
}
unsigned char buf[3];
unsigned char buf[digits];
uint8_t i = 0;
while (n > 0) {
buf[i++] = n % 10 + '0';
n /= 10;
for (; i < digits; i++) {
buf[i] = n % base ;
n /= base;
}
for (; i > 0; i--)
serial_write(buf[i - 1]);
serial_write('0' + buf[i - 1]);
}
// Prints an uint8 variable in base 2.
void print_uint8_base2(uint8_t n) {
print_unsigned_int8(n,2,8);
}
// Prints an uint8 variable in base 10.
void print_uint8_base10(uint8_t n)
{
uint8_t digits;
if (n < 10) { digits = 1; }
else if (n < 100) { digits = 2; }
else { digits = 3; }
print_unsigned_int8(n,10,digits);
}
@ -119,7 +117,7 @@ void printInteger(long n)
{
if (n < 0) {
serial_write('-');
print_uint32_base10((-n));
print_uint32_base10(-n);
} else {
print_uint32_base10(n);
}
@ -194,12 +192,13 @@ void printFloat_RateValue(float n) {
void printFloat_SettingValue(float n) { printFloat(n,N_DECIMAL_SETTINGVALUE); }
// Debug tool to print free memory in bytes at the called point. Not used otherwise.
void printFreeMemory()
{
extern int __heap_start, *__brkval;
uint16_t free; // Up to 64k values.
free = (int) &free - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
printInteger((int32_t)free);
printString(" ");
}
// Debug tool to print free memory in bytes at the called point.
// NOTE: Keep commented unless using. Part of this function always gets compiled in.
// void printFreeMemory()
// {
// extern int __heap_start, *__brkval;
// uint16_t free; // Up to 64k values.
// free = (int) &free - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
// printInteger((int32_t)free);
// printString(" ");
// }

View File

@ -31,8 +31,13 @@ void printInteger(long n);
void print_uint32_base10(uint32_t n);
// Prints uint8 variable with base and number of desired digits.
void print_unsigned_int8(uint8_t n, uint8_t base, uint8_t digits);
// Prints an uint8 variable in base 2.
void print_uint8_base2(uint8_t n);
// Prints an uint8 variable in base 10.
void print_uint8_base10(uint8_t n);
void printFloat(float n, uint8_t decimal_places);

View File

@ -496,10 +496,7 @@ void report_realtime_status()
if (bit_istrue(settings.status_report_mask,BITFLAG_RT_STATUS_LIMIT_PINS)) {
printPgmString(PSTR(",Lim:"));
for (idx=0; idx<N_AXIS; idx++) {
if (LIMIT_PIN & get_limit_pin_mask(idx)) { printPgmString(PSTR("1")); }
else { printPgmString(PSTR("0")); }
}
print_unsigned_int8(limits_get_state(),2,N_AXIS);
}
#ifdef REPORT_CONTROL_PIN_STATE

View File

@ -252,8 +252,10 @@ float system_convert_axis_steps_to_mpos(int32_t *steps, uint8_t idx)
#ifdef COREXY
if (idx==A_MOTOR) {
pos = 0.5*((steps[A_MOTOR] + steps[B_MOTOR])/settings.steps_per_mm[idx]);
} else { // (idx==B_MOTOR)
} else if (idx==B_MOTOR) {
pos = 0.5*((steps[A_MOTOR] - steps[B_MOTOR])/settings.steps_per_mm[idx]);
} else {
pos = steps[idx]/settings.steps_per_mm[idx];
}
#else
pos = steps[idx]/settings.steps_per_mm[idx];