diff --git a/config.h b/config.h
index fc5605e..73c4533 100755
--- a/config.h
+++ b/config.h
@@ -46,9 +46,9 @@
#define X_LIMIT_BIT 1 // Uno Digital Pin 9
#define Y_LIMIT_BIT 2 // Uno Digital Pin 10
#define Z_LIMIT_BIT 3 // Uno Digital Pin 11
-// #define LIMIT_INT PCIE0 // Pin change interrupt settings
-// #define LIMIT_INT_vect PCINT0_vect
-// #define LIMIT_PCMSK PCMSK0
+#define LIMIT_INT PCIE0 // Pin change interrupt settings
+#define LIMIT_INT_vect PCINT0_vect
+#define LIMIT_PCMSK PCMSK0
#define SPINDLE_ENABLE_DDR DDRB
#define SPINDLE_ENABLE_PORT PORTB
@@ -159,9 +159,7 @@
// TODO: The following options are set as compile-time options for now, until the next EEPROM
// settings version has solidified. This is to prevent having to support dozens of different
// incremental settings versions.
-#define CYCLE_AUTO_START 1 // Cycle auto-start boolean flag for the planner.
#define BLOCK_DELETE_ENABLE 0 // Block delete enable/disable flag during g-code parsing
-#define REPORT_INCH_MODE 0 // Status reporting unit mode (1 = inch, 0 = mm)
// This parameter sets the delay time before disabling the steppers after the final block of movement.
// A short delay ensures the steppers come to a complete stop and the residual inertial force in the
diff --git a/gcode.c b/gcode.c
index c59bac7..8437405 100755
--- a/gcode.c
+++ b/gcode.c
@@ -108,7 +108,8 @@ void gc_init()
// protocol_status_message(settings_execute_startup());
}
-// Sets g-code parser position in mm. Input in steps. Called by the system abort routine.
+// Sets g-code parser position in mm. Input in steps. Called by the system abort and hard
+// limit pull-off routines.
void gc_set_current_position(int32_t x, int32_t y, int32_t z)
{
gc.position[X_AXIS] = x/settings.steps_per_mm[X_AXIS];
@@ -183,7 +184,7 @@ uint8_t gc_execute_line(char *line)
case 21: gc.inches_mode = false; break;
case 28: case 30:
// NOTE: G28.1, G30.1 sets home position parameters. Not currently supported.
- if (bit_istrue(settings.flags,FLAG_BIT_HOMING_ENABLE)) {
+ if (bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE)) {
non_modal_action = NON_MODAL_GO_HOME;
} else {
FAIL(STATUS_SETTING_DISABLED);
diff --git a/limits.c b/limits.c
index da36409..0785fa5 100755
--- a/limits.c
+++ b/limits.c
@@ -38,8 +38,31 @@ void limits_init()
{
LIMIT_DDR &= ~(LIMIT_MASK); // Set as input pins
LIMIT_PORT |= (LIMIT_MASK); // Enable internal pull-up resistors. Normal high operation.
+
+ if bit_istrue(settings.flags,BITFLAG_HARD_LIMIT_ENABLE) {
+ MCUCR = (1<.
*/
+/* A big thanks to Alden Hart of Synthetos, supplier of grblshield and TinyG, who has
+ been integral throughout the development of the higher level details of Grbl, as well
+ as being a consistent sounding board for the future of accessible and free CNC. */
+
#include
#include
#include "config.h"
@@ -46,7 +50,9 @@ int main(void)
memset(&sys, 0, sizeof(sys)); // Clear all system variables
sys.abort = true; // Set abort to complete initialization
-
+
+ // TODO: When Grbl system status is installed, need to set position lost state upon startup.
+
for(;;) {
// Execute system reset upon a system abort, where the main program will return to this loop.
@@ -87,9 +93,9 @@ int main(void)
// Set system runtime defaults
// TODO: Eventual move to EEPROM from config.h when all of the new settings are worked out.
// Mainly to avoid having to maintain several different versions.
- #ifdef CYCLE_AUTO_START
+ if (bit_istrue(settings.flags,BITFLAG_AUTO_START)) {
sys.auto_start = true;
- #endif
+ }
// TODO: Install G20/G21 unit default into settings and load appropriate settings.
}
diff --git a/motion_control.c b/motion_control.c
index 26f16bc..76d8092 100755
--- a/motion_control.c
+++ b/motion_control.c
@@ -196,9 +196,30 @@ void mc_dwell(float seconds)
// Execute homing cycle to locate and set machine zero.
void mc_go_home()
{
- limits_go_home();
+ plan_synchronize(); // Empty all motions in buffer before homing.
+ PCICR &= ~(1 << LIMIT_INT); // Disable hard limits pin change interrupt
+
+ limits_go_home(); // Perform homing routine.
+
// Upon completion, reset all internal position vectors (g-code parser, planner, system)
gc_clear_position();
plan_clear_position();
clear_vector_float(sys.position);
+
+ // If hard limits enabled, move all axes off limit switches before enabling the hard limit
+ // pin change interrupt. This should help prevent the switches from falsely tripping.
+ // NOTE: G-code parser was circumvented so its position needs to be updated explicitly.
+ if (bit_istrue(settings.flags,BITFLAG_HARD_LIMIT_ENABLE)) {
+ int8_t x_dir, y_dir, z_dir;
+ x_dir = y_dir = z_dir = 1;
+ if (bit_istrue(settings.homing_dir_mask,bit(X_DIRECTION_BIT))) { x_dir = -1; }
+ if (bit_istrue(settings.homing_dir_mask,bit(Y_DIRECTION_BIT))) { y_dir = -1; }
+ if (bit_istrue(settings.homing_dir_mask,bit(Z_DIRECTION_BIT))) { z_dir = -1; }
+ mc_line(x_dir*settings.homing_pulloff, y_dir*settings.homing_pulloff,
+ z_dir*settings.homing_pulloff, settings.homing_feed_rate, false);
+ st_cycle_start(); // Nothing should be in the buffer except this motion.
+ plan_synchronize(); // Make sure the motion completes.
+ gc_set_current_position(sys.position[X_AXIS],sys.position[Y_AXIS],sys.position[Z_AXIS]);
+ PCICR |= (1 << LIMIT_INT); // Re-enable hard limits.
+ }
}
diff --git a/nuts_bolts.h b/nuts_bolts.h
index 8e9b58b..d4ecb2d 100755
--- a/nuts_bolts.h
+++ b/nuts_bolts.h
@@ -35,6 +35,7 @@
#define Z_AXIS 2
#define MM_PER_INCH (25.4)
+#define INCH_PER_MM (0.03937)
// Useful macros
#define clear_vector(a) memset(a, 0, sizeof(a))
@@ -60,16 +61,29 @@
#define EXEC_CYCLE_STOP bit(2) // bitmask 00000100
#define EXEC_FEED_HOLD bit(3) // bitmask 00001000
#define EXEC_RESET bit(4) // bitmask 00010000
-// #define bit(5) // bitmask 00100000
+#define EXEC_ALARM bit(5) // bitmask 00100000
// #define bit(6) // bitmask 01000000
// #define bit(7) // bitmask 10000000
+// Define bit flag masks for sys.switches. (8 flag limit)
+#define BITFLAG_BLOCK_DELETE bit(0)
+#define BITFLAG_SINGLE_BLOCK bit(1)
+#define BITFLAG_OPT_STOP bit(2)
+// #define bit(3)
+// #define bit(4)
+// #define bit(5)
+// #define bit(6)
+// #define bit(7)
+
// Define global system variables
typedef struct {
uint8_t abort; // System abort flag. Forces exit back to main loop for reset.
uint8_t feed_hold; // Feed hold flag. Held true during feed hold. Released when ready to resume.
uint8_t auto_start; // Planner auto-start flag. Toggled off during feed hold. Defaulted by settings.
-
+ uint8_t alarm; // Alarm mode. Causes all functions to immediately cease until a system abort
+ // is issued by the user.
+// uint8_t switches; // Switches state bitflag variable. For settings not governed by g-code.
+
int32_t position[3]; // Real-time machine (aka home) position vector in steps.
// NOTE: This may need to be a volatile variable, if problems arise.
@@ -82,6 +96,7 @@ typedef struct {
volatile uint8_t cycle_start; // Cycle start flag. Set by stepper subsystem or main program.
volatile uint8_t execute; // Global system runtime executor bitflag variable. See EXEC bitmasks.
+
} system_t;
extern system_t sys;
diff --git a/protocol.c b/protocol.c
index 78e42bf..234ad45 100755
--- a/protocol.c
+++ b/protocol.c
@@ -73,7 +73,7 @@ void protocol_status_report()
// may be distance to go on block, processed block id, and feed rate. A secondary, non-critical
// status report may include g-code state, i.e. inch mode, plane mode, absolute mode, etc.
// The report generated must be as short as possible, yet still provide the user easily readable
- // information, i.e. 'x0.23,y120.4,z2.4'. This is necessary as it minimizes the computational
+ // information, i.e. '[0.23,120.4,2.4]'. This is necessary as it minimizes the computational
// overhead and allows grbl to keep running smoothly, especially with g-code programs with fast,
// short line segments and interface setups that require real-time status reports (5-20Hz).
@@ -85,24 +85,33 @@ void protocol_status_report()
// home position by the user (likely through '$' setting interface).
// Successfully tested at a query rate of 10-20Hz while running a gauntlet of programs at various
// speeds.
- int32_t print_position[3];
- memcpy(print_position,sys.position,sizeof(sys.position));
- #if REPORT_INCH_MODE
- printString("MPos:["); printFloat(print_position[X_AXIS]/(settings.steps_per_mm[X_AXIS]*MM_PER_INCH));
- printString(","); printFloat(print_position[Y_AXIS]/(settings.steps_per_mm[Y_AXIS]*MM_PER_INCH));
- printString(","); printFloat(print_position[Z_AXIS]/(settings.steps_per_mm[Z_AXIS]*MM_PER_INCH));
- printString("],WPos:["); printFloat((print_position[X_AXIS]/settings.steps_per_mm[X_AXIS]-sys.coord_system[sys.coord_select][X_AXIS]-sys.coord_offset[X_AXIS])/MM_PER_INCH);
- printString(","); printFloat((print_position[Y_AXIS]/settings.steps_per_mm[Y_AXIS]-sys.coord_system[sys.coord_select][Y_AXIS]-sys.coord_offset[Y_AXIS])/MM_PER_INCH);
- printString(","); printFloat((print_position[Z_AXIS]/settings.steps_per_mm[Z_AXIS]-sys.coord_system[sys.coord_select][Z_AXIS]-sys.coord_offset[Z_AXIS])/MM_PER_INCH);
- #else
- printString("MPos:["); printFloat(print_position[X_AXIS]/(settings.steps_per_mm[X_AXIS]));
- printString(","); printFloat(print_position[Y_AXIS]/(settings.steps_per_mm[Y_AXIS]));
- printString(","); printFloat(print_position[Z_AXIS]/(settings.steps_per_mm[Z_AXIS]));
- printString("],WPos:["); printFloat(print_position[X_AXIS]/settings.steps_per_mm[X_AXIS]-sys.coord_system[sys.coord_select][X_AXIS]-sys.coord_offset[X_AXIS]);
- printString(","); printFloat(print_position[Y_AXIS]/settings.steps_per_mm[Y_AXIS]-sys.coord_system[sys.coord_select][Y_AXIS]-sys.coord_offset[Y_AXIS]);
- printString(","); printFloat(print_position[Z_AXIS]/settings.steps_per_mm[Z_AXIS]-sys.coord_system[sys.coord_select][Z_AXIS]-sys.coord_offset[Z_AXIS]);
- #endif
- printString("]\r\n");
+ uint8_t i;
+ int32_t current_position[3]; // Copy current state of the system position variable
+ memcpy(current_position,sys.position,sizeof(sys.position));
+ float print_position[3];
+
+ // Report machine position
+ printPgmString(PSTR("MPos:["));
+ for (i=0; i<= 2; i++) {
+ print_position[i] = current_position[i]/settings.steps_per_mm[i];
+ if (bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)) { print_position[i] *= INCH_PER_MM; }
+ printFloat(print_position[i]);
+ if (i < 2) { printPgmString(PSTR(",")); }
+ }
+
+ // Report work position
+ printPgmString(PSTR("],WPos:["));
+ for (i=0; i<= 2; i++) {
+ if (bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)) {
+ print_position[i] -= (sys.coord_system[sys.coord_select][i]+sys.coord_offset[i])*INCH_PER_MM;
+ } else {
+ print_position[i] -= sys.coord_system[sys.coord_select][i]+sys.coord_offset[i];
+ }
+ printFloat(print_position[i]);
+ if (i < 2) { printPgmString(PSTR(",")); }
+ }
+
+ printPgmString(PSTR("]\r\n"));
}
@@ -129,6 +138,12 @@ void protocol_execute_runtime()
{
if (sys.execute) { // Enter only if any bit flag is true
uint8_t rt_exec = sys.execute; // Avoid calling volatile multiple times
+
+ // System alarm. Something has gone wrong. Disable everything until system reset.
+ if (rt_exec & EXEC_ALARM) {
+ while (bit_isfalse(sys.execute,EXEC_RESET)) { sleep_mode(); }
+ bit_false(sys.execute,EXEC_ALARM);
+ }
// System abort. Steppers have already been force stopped.
if (rt_exec & EXEC_RESET) {
@@ -157,12 +172,12 @@ void protocol_execute_runtime()
if (rt_exec & EXEC_CYCLE_START) {
st_cycle_start(); // Issue cycle start command to stepper subsystem
- #ifdef CYCLE_AUTO_START
+ if (bit_istrue(settings.flags,BITFLAG_AUTO_START)) {
sys.auto_start = true; // Re-enable auto start after feed hold.
- #endif
+ }
bit_false(sys.execute,EXEC_CYCLE_START);
- }
- }
+ }
+ }
}
diff --git a/serial.c b/serial.c
index aa35237..a346cd3 100755
--- a/serial.c
+++ b/serial.c
@@ -165,7 +165,11 @@ ISR(USART_RX_vect)
case CMD_STATUS_REPORT: sys.execute |= EXEC_STATUS_REPORT; break; // Set as true
case CMD_CYCLE_START: sys.execute |= EXEC_CYCLE_START; break; // Set as true
case CMD_FEED_HOLD: sys.execute |= EXEC_FEED_HOLD; break; // Set as true
- case CMD_RESET:
+ case CMD_RESET:
+ sys.alarm |= EXEC_ALARM; // Set alarm to allow subsystem disable for certain settings.
+
+ // TODO: When Grbl system status is installed, set position lost state if the cycle is active.
+
// Immediately force stepper and spindle subsystem idle at an interrupt level.
if (!(sys.execute & EXEC_RESET)) { // Force stop only first time.
st_go_idle();
diff --git a/settings.c b/settings.c
index e012c5c..d4e723c 100755
--- a/settings.c
+++ b/settings.c
@@ -69,14 +69,16 @@ typedef struct {
#define DEFAULT_STEPPING_INVERT_MASK ((1<