diff --git a/grbl/config.h b/grbl/config.h index 6efb761..f430694 100644 --- a/grbl/config.h +++ b/grbl/config.h @@ -251,6 +251,22 @@ // spindle RPM output lower than this value will be set to this value. // #define MINIMUM_SPINDLE_PWM 5 // Default disabled. Uncomment to enable. Integer (0-255) +// By default on a 328p(Uno), Grbl combines the variable spindle PWM and the enable into one pin to help +// preserve I/O pins. For certain setups, these may need to be separate pins. This configure option uses +// the spindle direction pin(D13) as a separate spindle enable pin along with spindle speed PWM on pin D11. +// NOTE: This configure option only works with VARIABLE_SPINDLE enabled and a 328p processor (Uno). +// NOTE: With no direction pin, the spindle clockwise M4 g-code command will be removed. M3 and M5 still work. +// #define USE_SPINDLE_DIR_AS_ENABLE_PIN // Default disabled. Uncomment to enable. + +// With this enabled, Grbl sends back an echo of the line it has received, which has been pre-parsed (spaces +// removed, capitalized letters, no comments) and is to be immediately executed by Grbl. Echoes will not be +// sent upon a line buffer overflow, but should for all normal lines sent to Grbl. For example, if a user +// sendss the line 'g1 x1.032 y2.45 (test comment)', Grbl will echo back in the form '[echo: G1X1.032Y2.45]'. +// NOTE: Only use this for debugging purposes!! When echoing, this takes up valuable resources and can effect +// performance. If absolutely needed for normal operation, the serial write buffer should be greatly increased +// to help minimize transmission waiting within the serial write protocol. +// #define REPORT_ECHO_LINE_RECEIVED // Default disabled. Uncomment to enable. + // Minimum planner junction speed. Sets the default minimum junction speed the planner plans to at // every buffer block junction, except for starting from rest and end of the buffer, which are always // zero. This value controls how fast the machine moves through junctions with no regard for acceleration @@ -261,7 +277,8 @@ // Sets the minimum feed rate the planner will allow. Any value below it will be set to this minimum // value. This also ensures that a planned motion always completes and accounts for any floating-point -// round-off errors. A lower value than 1.0 mm/min may work in some cases, but we don't recommend it. +// round-off errors. Although not recommended, a lower value than 1.0 mm/min will likely work in smaller +// machines, perhaps to 0.1mm/min, but your success may vary based on multiple factors. #define MINIMUM_FEED_RATE 1.0 // (mm/min) // Number of arc generation iterations by small angle approximation before exact arc trajectory @@ -353,14 +370,20 @@ // #define HARD_LIMIT_FORCE_STATE_CHECK // Default disabled. Uncomment to enable. -// --------------------------------------------------------------------------------------- - -// TODO: Install compile-time option to send numeric status codes rather than strings. - // --------------------------------------------------------------------------------------- // COMPILE-TIME ERROR CHECKING OF DEFINE VALUES: +#ifndef HOMING_CYCLE_0 + #error "Required HOMING_CYCLE_0 not defined." +#endif +#if defined(USE_SPINDLE_DIR_AS_ENABLE_PIN) && !defined(VARIABLE_SPINDLE) + #error "USE_SPINDLE_DIR_AS_ENABLE_PIN may only be used with VARIABLE_SPINDLE enabled" +#endif + +#if defined(USE_SPINDLE_DIR_AS_ENABLE_PIN) && !defined(CPU_MAP_ATMEGA328P) + #error "USE_SPINDLE_DIR_AS_ENABLE_PIN may only be used with a 328p processor" +#endif // --------------------------------------------------------------------------------------- diff --git a/grbl/cpu_map.h b/grbl/cpu_map.h index 6469616..872e0bf 100644 --- a/grbl/cpu_map.h +++ b/grbl/cpu_map.h @@ -79,15 +79,23 @@ // Define spindle enable and spindle direction output pins. #define SPINDLE_ENABLE_DDR DDRB #define SPINDLE_ENABLE_PORT PORTB - #ifdef VARIABLE_SPINDLE // Z Limit pin and spindle enabled swapped to access hardware PWM on Pin 11. - #define SPINDLE_ENABLE_BIT 3 // Uno Digital Pin 11 + // Z Limit pin and spindle PWM/enable pin swapped to access hardware PWM on Pin 11. + #ifdef VARIABLE_SPINDLE + #ifdef USE_SPINDLE_DIR_AS_ENABLE_PIN + // If enabled, spindle direction pin now used as spindle enable, while PWM remains on D11. + #define SPINDLE_ENABLE_BIT 5 // Uno Digital Pin 13 (NOTE: D13 can't be pulled-high input due to LED.) + #else + #define SPINDLE_ENABLE_BIT 3 // Uno Digital Pin 11 + #endif #else #define SPINDLE_ENABLE_BIT 4 // Uno Digital Pin 12 - #endif - #define SPINDLE_DIRECTION_DDR DDRB - #define SPINDLE_DIRECTION_PORT PORTB - #define SPINDLE_DIRECTION_BIT 5 // Uno Digital Pin 13 (NOTE: D13 can't be pulled-high input due to LED.) - + #endif + #ifndef USE_SPINDLE_DIR_AS_ENABLE_PIN + #define SPINDLE_DIRECTION_DDR DDRB + #define SPINDLE_DIRECTION_PORT PORTB + #define SPINDLE_DIRECTION_BIT 5 // Uno Digital Pin 13 (NOTE: D13 can't be pulled-high input due to LED.) + #endif + // Define flood and mist coolant enable output pins. // NOTE: Uno analog pins 4 and 5 are reserved for an i2c interface, and may be installed at // a later date if flash and memory space allows. @@ -134,11 +142,11 @@ #define WAVE1_REGISTER WGM21 #define WAVE2_REGISTER WGM22 #define WAVE3_REGISTER WGM23 - + // NOTE: On the 328p, these must be the same as the SPINDLE_ENABLE settings. - #define SPINDLE_PWM_DDR SPINDLE_ENABLE_DDR - #define SPINDLE_PWM_PORT SPINDLE_ENABLE_PORT - #define SPINDLE_PWM_BIT SPINDLE_ENABLE_BIT // Shared with SPINDLE_ENABLE. + #define SPINDLE_PWM_DDR DDRB + #define SPINDLE_PWM_PORT PORTB + #define SPINDLE_PWM_BIT 3 // Uno Digital Pin 11 #endif // End of VARIABLE_SPINDLE #endif diff --git a/grbl/gcode.c b/grbl/gcode.c index 3893c61..db72aa2 100644 --- a/grbl/gcode.c +++ b/grbl/gcode.c @@ -281,11 +281,16 @@ uint8_t gc_execute_line(char *line) case 2: case 30: gc_block.modal.program_flow = PROGRAM_FLOW_COMPLETED; break; // Program end and reset } break; - case 3: case 4: case 5: + #ifndef USE_SPINDLE_DIR_AS_ENABLE_PIN + case 4: + #endif + case 3: case 5: word_bit = MODAL_GROUP_M7; switch(int_value) { case 3: gc_block.modal.spindle = SPINDLE_ENABLE_CW; break; - case 4: gc_block.modal.spindle = SPINDLE_ENABLE_CCW; break; + #ifndef USE_SPINDLE_DIR_AS_ENABLE_PIN + case 4: gc_block.modal.spindle = SPINDLE_ENABLE_CCW; break; + #endif case 5: gc_block.modal.spindle = SPINDLE_DISABLE; break; } break; diff --git a/grbl/grbl.h b/grbl/grbl.h index 17886ba..c12769e 100644 --- a/grbl/grbl.h +++ b/grbl/grbl.h @@ -23,7 +23,7 @@ // Grbl versioning system #define GRBL_VERSION "0.9i" -#define GRBL_VERSION_BUILD "20150315" +#define GRBL_VERSION_BUILD "20150327" // Define standard libraries used by Grbl. #include diff --git a/grbl/planner.c b/grbl/planner.c index dcf50ec..7989e00 100644 --- a/grbl/planner.c +++ b/grbl/planner.c @@ -320,7 +320,7 @@ uint8_t plan_check_full_buffer() // Adjust feed_rate value to mm/min depending on type of rate input (normal, inverse time, or rapids) // TODO: Need to distinguish a rapids vs feed move for overrides. Some flag of some sort. if (feed_rate < 0) { feed_rate = SOME_LARGE_VALUE; } // Scaled down to absolute max/rapids rate later - else if (invert_feed_rate) { feed_rate = block->millimeters/feed_rate; } + else if (invert_feed_rate) { feed_rate *= block->millimeters; } if (feed_rate < MINIMUM_FEED_RATE) { feed_rate = MINIMUM_FEED_RATE; } // Prevents step generation round-off condition. // Calculate the unit vector of the line move and the block maximum feed rate and acceleration scaled diff --git a/grbl/protocol.c b/grbl/protocol.c index dc70f50..858ffef 100644 --- a/grbl/protocol.c +++ b/grbl/protocol.c @@ -21,6 +21,11 @@ #include "grbl.h" +// Define different comment types for pre-parsing. +#define COMMENT_NONE 0 +#define COMMENT_TYPE_PARENTHESES 1 +#define COMMENT_TYPE_SEMICOLON 2 + static char line[LINE_BUFFER_SIZE]; // Line to be executed. Zero-terminated. @@ -33,6 +38,10 @@ static void protocol_execute_line(char *line) protocol_execute_realtime(); // Runtime command check point. if (sys.abort) { return; } // Bail to calling function upon system abort + #ifdef REPORT_ECHO_LINE_RECEIVED + report_echo_line_received(line); + #endif + if (line[0] == 0) { // Empty or comment line. Send status message for syncing purposes. report_status_message(STATUS_OK); @@ -82,7 +91,7 @@ void protocol_main_loop() // Primary loop! Upon a system abort, this exits back to main() to reset the system. // --------------------------------------------------------------------------------- - uint8_t iscomment = false; + uint8_t comment = COMMENT_NONE; uint8_t char_counter = 0; uint8_t c; for (;;) { @@ -101,14 +110,14 @@ void protocol_main_loop() if ((c == '\n') || (c == '\r')) { // End of line reached line[char_counter] = 0; // Set string termination character. protocol_execute_line(line); // Line is complete. Execute it! - iscomment = false; + comment = COMMENT_NONE; char_counter = 0; } else { - if (iscomment) { + if (comment != COMMENT_NONE) { // Throw away all comment characters if (c == ')') { - // End of comment. Resume line. - iscomment = false; + // End of comment. Resume line. But, not if semicolon type comment. + if (comment == COMMENT_TYPE_PARENTHESES) { comment = COMMENT_NONE; } } } else { if (c <= ' ') { @@ -121,9 +130,10 @@ void protocol_main_loop() // NOTE: This doesn't follow the NIST definition exactly, but is good enough for now. // In the future, we could simply remove the items within the comments, but retain the // comment control characters, so that the g-code parser can error-check it. - iscomment = true; - // } else if (c == ';') { - // Comment character to EOL NOT SUPPORTED. LinuxCNC definition. Not NIST. + comment = COMMENT_TYPE_PARENTHESES; + } else if (c == ';') { + // NOTE: ';' comment to EOL is a LinuxCNC definition. Not NIST. + comment = COMMENT_TYPE_SEMICOLON; // TODO: Install '%' feature // } else if (c == '%') { @@ -136,7 +146,7 @@ void protocol_main_loop() } else if (char_counter >= (LINE_BUFFER_SIZE-1)) { // Detect line buffer overflow. Report error and reset line buffer. report_status_message(STATUS_OVERFLOW); - iscomment = false; + comment = COMMENT_NONE; char_counter = 0; } else if (c >= 'a' && c <= 'z') { // Upcase lowercase line[char_counter++] = c-'a'+'A'; @@ -206,6 +216,8 @@ void protocol_execute_realtime() // to do what is needed before resetting, like killing the incoming stream. The // same could be said about soft limits. While the position is not lost, the incoming // stream could be still engaged and cause a serious crash if it continues afterwards. + + // TODO: Allow status reports during a critical alarm. Still need to think about implications of this. // if (sys.rt_exec_state & EXEC_STATUS_REPORT) { // report_realtime_status(); // bit_false_atomic(sys.rt_exec_state,EXEC_STATUS_REPORT); diff --git a/grbl/report.c b/grbl/report.c index f573602..001c02d 100644 --- a/grbl/report.c +++ b/grbl/report.c @@ -400,6 +400,15 @@ void report_build_info(char *line) } +// Prints the character string line Grbl has received from the user, which has been pre-parsed, +// and has been sent into protocol_execute_line() routine to be executed by Grbl. +void report_echo_line_received(char *line) +{ + printPgmString(PSTR("[echo: ")); printString(line); + printPgmString(PSTR("]\r\n")); +} + + // Prints real-time data. This function grabs a real-time snapshot of the stepper subprogram // and the actual location of the CNC machine. Users may change the following function to their // specific needs, but the desired real-time data report must be as short as possible. This is diff --git a/grbl/report.h b/grbl/report.h index e21df42..82593cf 100644 --- a/grbl/report.h +++ b/grbl/report.h @@ -87,6 +87,9 @@ void report_grbl_help(); // Prints Grbl global settings void report_grbl_settings(); +// Prints an echo of the pre-parsed line received right before execution. +void report_echo_line_received(char *line); + // Prints realtime status report void report_realtime_status(); diff --git a/grbl/spindle_control.c b/grbl/spindle_control.c index f0724b4..18c92ac 100644 --- a/grbl/spindle_control.c +++ b/grbl/spindle_control.c @@ -24,16 +24,21 @@ void spindle_init() { - // On the Uno, spindle enable and PWM are shared. Other CPUs have seperate enable pin. + // Configure variable spindle PWM and enable pin, if requried. On the Uno, PWM and enable are + // combined unless configured otherwise. #ifdef VARIABLE_SPINDLE SPINDLE_PWM_DDR |= (1<