/* limits.c - code pertaining to limit-switches and performing the homing cycle Part of Grbl v0.9 Copyright (c) 2012-2014 Sungeun K. Jeon Grbl is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Grbl is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Grbl. If not, see . */ /* This file is based on work from Grbl v0.8, distributed under the terms of the MIT-license. See COPYING for more details. Copyright (c) 2009-2011 Simen Svale Skogsrud Copyright (c) 2012 Sungeun K. Jeon */ #include "system.h" #include "settings.h" #include "protocol.h" #include "planner.h" #include "stepper.h" #include "motion_control.h" #include "limits.h" #include "report.h" // Homing axis search distance multiplier. Computed by this value times the axis max travel. #define HOMING_AXIS_SEARCH_SCALAR 1.5 // Must be > 1 to ensure limit switch will be engaged. void limits_init() { LIMIT_DDR &= ~(LIMIT_MASK); // Set as input pins if (bit_istrue(settings.flags,BITFLAG_INVERT_LIMIT_PINS)) { LIMIT_PORT &= ~(LIMIT_MASK); // Normal low operation. Requires external pull-down. } else { LIMIT_PORT |= (LIMIT_MASK); // Enable internal pull-up resistors. Normal high operation. } if (bit_istrue(settings.flags,BITFLAG_HARD_LIMIT_ENABLE)) { LIMIT_PCMSK |= LIMIT_MASK; // Enable specific pins of the Pin Change Interrupt PCICR |= (1 << LIMIT_INT); // Enable Pin Change Interrupt } else { limits_disable(); } #ifdef ENABLE_SOFTWARE_DEBOUNCE MCUSR &= ~(1< settings.max_travel[idx]) { max_travel = settings.max_travel[idx]; } } max_travel *= -HOMING_AXIS_SEARCH_SCALAR; // Ensure homing switches engaged by over-estimating max travel. plan_reset(); // Reset planner buffer to zero planner current position and to clear previous motions. do { // Initialize invert_pin boolean based on approach and invert pin user setting. if (bit_isfalse(settings.flags,BITFLAG_INVERT_LIMIT_PINS)) { invert_pin = approach; } else { invert_pin = !approach; } // Initialize and declare variables needed for homing routine. uint8_t n_active_axis = 0; uint8_t axislock = 0; for (idx=0; idx 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, // 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 // triggering when hard limits are enabled or when more than one axes shares a limit pin. for (idx=0; 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) { bit_true_atomic(sys.execute, EXEC_FEED_HOLD); do { protocol_execute_runtime(); if (sys.abort) { return; } } while ( sys.state != STATE_IDLE || sys.state != STATE_QUEUED); } mc_reset(); // Issue system reset and ensure spindle and coolant are shutdown. bit_true_atomic(sys.execute, (EXEC_ALARM | EXEC_CRIT_EVENT)); // Indicate soft limit critical event protocol_execute_runtime(); // Execute to enter critical event loop and system abort return; } } }