// 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 // if a limit switch is being disengaged. It's impossible to reliably tell the state of a // bouncing pin without a debouncing method. A simple software debouncing feature may be enabled // through the config.h file, where an extra timer delays the limit pin read by several milli- // seconds to help with, not fix, bouncing switches. // NOTE: Do not attach an e-stop to the limit pins, because this interrupt is disabled during // homing cycles and will not respond correctly. Upon user request or need, there may be a // special pinout for an e-stop, but it is generally recommended to just directly connect // your e-stop switch to the Arduino reset pin, since it is the most correct way to do this. //#ifndef ENABLE_SOFTWARE_DEBOUNCE // ISR(LIMIT_INT_vect) // DEFAULT: Limit pin change interrupt process. void limitpin_check(void) { static uint8_t oldlimit; uint8_t newlimit; if(!limitintison) return; newlimit = limits_get_state(); if(newlimit == oldlimit) return; oldlimit = newlimit; // Ignore limit switches if already in an alarm state or in-process of executing an alarm. // When in the alarm state, Grbl should have been reset or will force a reset, so any pending // moves in the planner and serial buffers are all cleared and newly sent blocks will be // locked out until a homing cycle or a kill lock command. Allows the user to disable the hard // limit setting if their limits are constantly triggering after a reset and move their axes. if (sys.state != STATE_ALARM) { if (!(sys_rt_exec_alarm)) { #ifdef HARD_LIMIT_FORCE_STATE_CHECK // Check limit pin state. if ( limits_get_state() == 0) return; #endif mc_reset(); // Initiate system kill. if(newlimit & 0x8) system_set_exec_alarm_flag((EXEC_ALARM_STEPPER_FAIL|EXEC_CRITICAL_EVENT)); // Indicate hard limit critical event else system_set_exec_alarm_flag((EXEC_ALARM_HARD_LIMIT|EXEC_CRITICAL_EVENT)); // Indicate hard limit critical event } } }
// Performs a soft limit check. Called from mc_line() only. Assumes the machine has been homed, // the workspace volume is in all negative space, and the system is in normal operation. void limits_soft_check(float *target) { uint8_t idx; uint8_t soft_limit_error = false; for (idx=0; idx<N_AXIS; idx++) { #ifdef HOMING_FORCE_SET_ORIGIN // When homing forced set origin is enabled, soft limits checks need to account for directionality. // NOTE: max_travel is stored as negative if (bit_istrue(settings.homing_dir_mask,bit(idx))) { if (target[idx] < 0 || target[idx] > -settings.max_travel[idx]) { soft_limit_error = true; } } else { if (target[idx] > 0 || target[idx] < settings.max_travel[idx]) { soft_limit_error = true; } } #else // NOTE: max_travel is stored as negative if (target[idx] > 0 || target[idx] < settings.max_travel[idx]) { soft_limit_error = true; } #endif if (soft_limit_error) { // Force feed hold if cycle is active. All buffered blocks are guaranteed to be within // workspace volume so just come to a controlled stop so position is not lost. When complete // enter alarm mode. if (sys.state == STATE_CYCLE) { system_set_exec_state_flag(EXEC_FEED_HOLD); do { protocol_execute_realtime(); if (sys.abort) { return; } } while ( sys.state != STATE_IDLE ); } mc_reset(); // Issue system reset and ensure spindle and coolant are shutdown. system_set_exec_alarm_flag((EXEC_ALARM_SOFT_LIMIT|EXEC_CRITICAL_EVENT)); // Indicate soft limit critical event protocol_execute_realtime(); // Execute to enter critical event loop and system abort return; } } }