From 8ab368559a665d97e7b90aac5093be69cb16179d Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Wed, 1 Nov 2017 13:08:46 -0500 Subject: [PATCH] Implement CNC_COORDINATE_SYSTEMS --- .travis.yml | 2 +- Marlin/Conditionals_post.h | 2 +- Marlin/Marlin.h | 8 ++ Marlin/Marlin_main.cpp | 154 +++++++++++++++++++++++++++------ Marlin/SanityCheck.h | 4 + Marlin/configuration_store.cpp | 40 ++++++++- Marlin/gcode.cpp | 20 +++++ Marlin/gcode.h | 5 ++ 8 files changed, 204 insertions(+), 31 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4ed3a6484..ad6732017 100644 --- a/.travis.yml +++ b/.travis.yml @@ -86,7 +86,7 @@ script: - opt_set TEMP_SENSOR_0 -2 - opt_set TEMP_SENSOR_1 1 - opt_set TEMP_SENSOR_BED 1 - - opt_enable PIDTEMPBED FIX_MOUNTED_PROBE Z_SAFE_HOMING ARC_P_CIRCLES CNC_WORKSPACE_PLANES + - opt_enable PIDTEMPBED FIX_MOUNTED_PROBE Z_SAFE_HOMING ARC_P_CIRCLES CNC_WORKSPACE_PLANES CNC_COORDINATE_SYSTEMS - opt_enable REPRAP_DISCOUNT_SMART_CONTROLLER SDSUPPORT EEPROM_SETTINGS - opt_enable BLINKM PCA9632 RGB_LED NEOPIXEL_LED - opt_enable AUTO_BED_LEVELING_LINEAR Z_MIN_PROBE_REPEATABILITY_TEST DEBUG_LEVELING_FEATURE diff --git a/Marlin/Conditionals_post.h b/Marlin/Conditionals_post.h index 29686a724..cbceb619c 100644 --- a/Marlin/Conditionals_post.h +++ b/Marlin/Conditionals_post.h @@ -1036,7 +1036,7 @@ #define GRID_MAX_POINTS ((GRID_MAX_POINTS_X) * (GRID_MAX_POINTS_Y)) // Add commands that need sub-codes to this list - #define USE_GCODE_SUBCODES ENABLED(G38_PROBE_TARGET) + #define USE_GCODE_SUBCODES ENABLED(G38_PROBE_TARGET) || ENABLED(CNC_COORDINATE_SYSTEMS) // MESH_BED_LEVELING overrides PROBE_MANUALLY #if ENABLED(MESH_BED_LEVELING) diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index 39a62fc52..0487f189d 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -290,6 +290,14 @@ extern float soft_endstop_min[XYZ], soft_endstop_max[XYZ]; void update_software_endstops(const AxisEnum axis); #endif +#if ENABLED(CNC_COORDINATE_SYSTEMS) + #define MAX_COORDINATE_SYSTEMS 9 + extern float coordinate_system[MAX_COORDINATE_SYSTEMS][XYZ]; + bool select_coordinate_system(const int8_t _new); +#endif + +void report_current_position(); + #if IS_KINEMATIC extern float delta[ABC]; void inverse_kinematics(const float raw[XYZ]); diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp index f8a928c3c..aed37731a 100644 --- a/Marlin/Marlin_main.cpp +++ b/Marlin/Marlin_main.cpp @@ -364,6 +364,11 @@ #define LED_WHITE 0, 0, 0, 255 #endif +#if ENABLED(CNC_COORDINATE_SYSTEMS) + int8_t active_coordinate_system = -1; // machine space + float coordinate_system[MAX_COORDINATE_SYSTEMS][XYZ]; +#endif + bool Running = true; uint8_t marlin_debug_flags = DEBUG_NONE; @@ -745,6 +750,7 @@ void stop(); void get_available_commands(); void process_next_command(); +void process_parsed_command(); void prepare_move_to_destination(); void get_cartesian_from_steppers(); @@ -3672,6 +3678,73 @@ inline void gcode_G4() { #endif // CNC_WORKSPACE_PLANES +#if ENABLED(CNC_COORDINATE_SYSTEMS) + + /** + * Select a coordinate system and update the current position. + * System index -1 is used to specify machine-native. + */ + bool select_coordinate_system(const int8_t _new) { + if (active_coordinate_system == _new) return false; + float old_offset[XYZ] = { 0 }, new_offset[XYZ] = { 0 }; + if (WITHIN(active_coordinate_system, 0, MAX_COORDINATE_SYSTEMS - 1)) + COPY(old_offset, coordinate_system[active_coordinate_system]); + if (WITHIN(_new, 0, MAX_COORDINATE_SYSTEMS - 1)) + COPY(new_offset, coordinate_system[_new]); + active_coordinate_system = _new; + bool didXYZ = false; + LOOP_XYZ(i) { + const float diff = new_offset[i] - old_offset[i]; + if (diff) { + position_shift[i] += diff; + update_software_endstops((AxisEnum)i); + didXYZ = true; + } + } + if (didXYZ) SYNC_PLAN_POSITION_KINEMATIC(); + return true; + } + + /** + * In CNC G-code G53 is like a modifier + * It precedes a movement command (or other modifiers) on the same line. + * This is the first command to use parser.chain() to make this possible. + */ + inline void gcode_G53() { + // If this command has more following... + if (parser.chain()) { + const int8_t _system = active_coordinate_system; + active_coordinate_system = -1; + process_parsed_command(); + active_coordinate_system = _system; + } + } + + /** + * G54-G59.3: Select a new workspace + * + * A workspace is an XYZ offset to the machine native space. + * All workspaces default to 0,0,0 at start, or with EEPROM + * support they may be restored from a previous session. + * + * G92 is used to set the current workspace's offset. + */ + inline void gcode_G54_59(uint8_t subcode=0) { + const int8_t _space = parser.codenum - 54 + subcode; + if (select_coordinate_system(_space)) { + SERIAL_PROTOCOLLNPAIR("Select workspace ", _space); + report_current_position(); + } + } + FORCE_INLINE void gcode_G54() { gcode_G54_59(); } + FORCE_INLINE void gcode_G55() { gcode_G54_59(); } + FORCE_INLINE void gcode_G56() { gcode_G54_59(); } + FORCE_INLINE void gcode_G57() { gcode_G54_59(); } + FORCE_INLINE void gcode_G58() { gcode_G54_59(); } + FORCE_INLINE void gcode_G59() { gcode_G54_59(parser.subcode); } + +#endif + #if ENABLED(INCH_MODE_SUPPORT) /** * G20: Set input mode to inches @@ -4153,13 +4226,12 @@ inline void gcode_G28(const bool always_home_all) { // Restore the active tool after homing #if HOTENDS > 1 - tool_change(old_tool_index, 0, - #if ENABLED(PARKING_EXTRUDER) - false // fetch the previous toolhead - #else - true - #endif - ); + #if ENABLED(PARKING_EXTRUDER) + #define NO_FETCH false // fetch the previous toolhead + #else + #define NO_FETCH true + #endif + tool_change(old_tool_index, 0, NO_FETCH); #endif lcd_refresh(); @@ -6201,7 +6273,30 @@ inline void gcode_G92() { if (!didE) stepper.synchronize(); - LOOP_XYZE(i) { + #if ENABLED(CNC_COORDINATE_SYSTEMS) + switch (parser.subcode) { + case 1: + // Zero the G92 values and restore current position + #if !IS_SCARA + LOOP_XYZ(i) { + const float v = position_shift[i]; + if (v) { + position_shift[i] = 0; + update_software_endstops((AxisEnum)i); + } + } + #endif // Not SCARA + return; + } + #endif + + #if ENABLED(CNC_COORDINATE_SYSTEMS) + #define IS_G92_0 (parser.subcode == 0) + #else + #define IS_G92_0 true + #endif + + if (IS_G92_0) LOOP_XYZE(i) { if (parser.seenval(axis_codes[i])) { #if IS_SCARA if (i != E_AXIS) didXYZ = true; @@ -6221,6 +6316,13 @@ inline void gcode_G92() { #endif } } + + #if ENABLED(CNC_COORDINATE_SYSTEMS) + // Apply workspace offset to the active coordinate system + if (WITHIN(active_coordinate_system, 0, MAX_COORDINATE_SYSTEMS - 1)) + COPY(coordinate_system[active_coordinate_system], position_shift); + #endif + if (didXYZ) SYNC_PLAN_POSITION_KINEMATIC(); else if (didE) @@ -11194,26 +11296,11 @@ inline void gcode_T(const uint8_t tmp_extruder) { } /** - * Process a single command and dispatch it to its handler - * This is called from the main loop() + * Process the parsed command and dispatch it to its handler */ -void process_next_command() { - char * const current_command = command_queue[cmd_queue_index_r]; - - if (DEBUGGING(ECHO)) { - SERIAL_ECHO_START(); - SERIAL_ECHOLN(current_command); - #if ENABLED(M100_FREE_MEMORY_WATCHER) - SERIAL_ECHOPAIR("slot:", cmd_queue_index_r); - M100_dump_routine(" Command Queue:", (const char*)command_queue, (const char*)(command_queue + sizeof(command_queue))); - #endif - } - +void process_parsed_command() { KEEPALIVE_STATE(IN_HANDLER); - // Parse the next command in the queue - parser.parse(current_command); - // Handle a known G, M, or T switch (parser.command_letter) { case 'G': switch (parser.codenum) { @@ -12053,6 +12140,23 @@ void process_next_command() { ok_to_send(); } +void process_next_command() { + char * const current_command = command_queue[cmd_queue_index_r]; + + if (DEBUGGING(ECHO)) { + SERIAL_ECHO_START(); + SERIAL_ECHOLN(current_command); + #if ENABLED(M100_FREE_MEMORY_WATCHER) + SERIAL_ECHOPAIR("slot:", cmd_queue_index_r); + M100_dump_routine(" Command Queue:", (const char*)command_queue, (const char*)(command_queue + sizeof(command_queue))); + #endif + } + + // Parse the next command in the queue + parser.parse(current_command); + process_parsed_command(); +} + /** * Send a "Resend: nnn" message to the host to * indicate that a command needs to be re-sent. diff --git a/Marlin/SanityCheck.h b/Marlin/SanityCheck.h index 61b148206..74cb848c0 100644 --- a/Marlin/SanityCheck.h +++ b/Marlin/SanityCheck.h @@ -1483,3 +1483,7 @@ static_assert(COUNT(sanity_arr_3) <= XYZE_N, "DEFAULT_MAX_ACCELERATION has too m #endif #endif #endif // SPINDLE_LASER_ENABLE + +#if ENABLED(CNC_COORDINATE_SYSTEMS) && ENABLED(NO_WORKSPACE_OFFSETS) + #error "CNC_COORDINATE_SYSTEMS is incompatible with NO_WORKSPACE_OFFSETS." +#endif diff --git a/Marlin/configuration_store.cpp b/Marlin/configuration_store.cpp index 1ab43adb8..fa8df06b5 100644 --- a/Marlin/configuration_store.cpp +++ b/Marlin/configuration_store.cpp @@ -36,13 +36,13 @@ * */ -#define EEPROM_VERSION "V43" +#define EEPROM_VERSION "V44" // Change EEPROM version if these are changed: #define EEPROM_OFFSET 100 /** - * V43 EEPROM Layout: + * V44 EEPROM Layout: * * 100 Version (char x4) * 104 EEPROM CRC16 (uint16_t) @@ -162,8 +162,11 @@ * 588 M907 Z Stepper Z current (uint32_t) * 592 M907 E Stepper E current (uint32_t) * - * 596 Minimum end-point - * 1917 (596 + 36 + 9 + 288 + 988) Maximum end-point + * CNC_COORDINATE_SYSTEMS 108 bytes + * 596 G54-G59.3 coordinate_system (float x 27) + * + * 704 Minimum end-point + * 2025 (704 + 36 + 9 + 288 + 988) Maximum end-point * * ======================================================================== * meshes_begin (between max and min end-point, directly above) @@ -209,6 +212,10 @@ MarlinSettings settings; float new_z_fade_height; #endif +#if ENABLED(CNC_COORDINATE_SYSTEMS) + bool position_changed; +#endif + /** * Post-process after Retrieve or Reset */ @@ -253,6 +260,13 @@ void MarlinSettings::postprocess() { #if HAS_MOTOR_CURRENT_PWM stepper.refresh_motor_power(); #endif + + #if ENABLED(CNC_COORDINATE_SYSTEMS) + if (position_changed) { + report_current_position(); + position_changed = false; + } + #endif } #if ENABLED(EEPROM_SETTINGS) @@ -663,6 +677,13 @@ void MarlinSettings::postprocess() { for (uint8_t q = 3; q--;) EEPROM_WRITE(dummyui32); #endif + #if ENABLED(CNC_COORDINATE_SYSTEMS) + EEPROM_WRITE(coordinate_system); // 27 floats + #else + dummy = 0.0f; + for (uint8_t q = 27; q--;) EEPROM_WRITE(dummy); + #endif + if (!eeprom_error) { const int eeprom_size = eeprom_index; @@ -1093,6 +1114,17 @@ void MarlinSettings::postprocess() { for (uint8_t q = 3; q--;) EEPROM_READ(dummyui32); #endif + // + // CNC Coordinate System + // + + #if ENABLED(CNC_COORDINATE_SYSTEMS) + position_changed = select_coordinate_system(-1); // Go back to machine space + EEPROM_READ(coordinate_system); // 27 floats + #else + for (uint8_t q = 27; q--;) EEPROM_READ(dummy); + #endif + if (working_crc == stored_crc) { postprocess(); #if ENABLED(EEPROM_CHITCHAT) diff --git a/Marlin/gcode.cpp b/Marlin/gcode.cpp index edeb00e22..f7516eb69 100644 --- a/Marlin/gcode.cpp +++ b/Marlin/gcode.cpp @@ -228,6 +228,26 @@ void GCodeParser::parse(char *p) { } } +#if ENABLED(CNC_COORDINATE_SYSTEMS) + + // Parse the next parameter as a new command + bool GCodeParser::chain() { + #if ENABLED(FASTER_GCODE_PARSER) + char *next_command = command_ptr; + if (next_command) { + while (*next_command && *next_command != ' ') ++next_command; + while (*next_command == ' ') ++next_command; + if (!*next_command) next_command = NULL; + } + #else + const char *next_command = command_args; + #endif + if (next_command) parse(next_command); + return !!next_command; + } + +#endif // CNC_COORDINATE_SYSTEMS + void GCodeParser::unknown_command_error() { SERIAL_ECHO_START(); SERIAL_ECHOPAIR(MSG_UNKNOWN_COMMAND, command_ptr); diff --git a/Marlin/gcode.h b/Marlin/gcode.h index 8c255ef7b..b415dcb11 100644 --- a/Marlin/gcode.h +++ b/Marlin/gcode.h @@ -169,6 +169,11 @@ public: // This uses 54 bytes of SRAM to speed up seen/value static void parse(char * p); + #if ENABLED(CNC_COORDINATE_SYSTEMS) + // Parse the next parameter as a new command + static bool chain(); + #endif + // The code value pointer was set FORCE_INLINE static bool has_value() { return value_ptr != NULL; }