diff --git a/.vscode/launch.json b/.vscode/launch.json index 05162896d..2dc3ecfb6 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -25,21 +25,21 @@ "type": "platformio-debug", "request": "launch", "name": "PIO Debug", - "executable": "c:/Users/JCEM/Documents/GitHub/uCNC/.pio/build/x_controller/firmware.elf", - "projectEnvName": "x_controller", + "executable": "c:/Users/JCEM/Documents/GitHub/uCNC/.pio/build/uno/firmware.elf", + "projectEnvName": "uno", "toolchainBinDir": "C:/gcc-avr8/bin", "internalConsoleOptions": "openOnSessionStart", "preLaunchTask": { "type": "PlatformIO", - "task": "Pre-Debug (x_controller)" + "task": "Pre-Debug (uno)" } }, { "type": "platformio-debug", "request": "launch", "name": "PIO Debug (skip Pre-Debug)", - "executable": "c:/Users/JCEM/Documents/GitHub/uCNC/.pio/build/x_controller/firmware.elf", - "projectEnvName": "x_controller", + "executable": "c:/Users/JCEM/Documents/GitHub/uCNC/.pio/build/uno/firmware.elf", + "projectEnvName": "uno", "toolchainBinDir": "C:/gcc-avr8/bin", "internalConsoleOptions": "openOnSessionStart" }, @@ -47,8 +47,8 @@ "type": "platformio-debug", "request": "launch", "name": "PIO Debug (without uploading)", - "executable": "c:/Users/JCEM/Documents/GitHub/uCNC/.pio/build/x_controller/firmware.elf", - "projectEnvName": "x_controller", + "executable": "c:/Users/JCEM/Documents/GitHub/uCNC/.pio/build/uno/firmware.elf", + "projectEnvName": "uno", "toolchainBinDir": "C:/gcc-avr8/bin", "internalConsoleOptions": "openOnSessionStart", "loadMode": "manual" diff --git a/CHANGELOG.md b/CHANGELOG.md index 53a395f13..08a27defa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,9 +16,15 @@ ### Changed - added option to accept G0 and G1 without explicit axis words to target (#169) +- implemented Grbl report status mask (#170) +- full Grbl welcome message emulation to fix recognition by PC softwares (#170) +- modified startup blocks execution to match Grbl behavior (#170) ### Fixed +- fixed parser wrong coordinates after coordinate offset command changes axis followed by a motion command with implicit target coordinates modified by the previous command, resulting in unexpected motion path (#170) +- forces run state flag during dwell (reported idle state) (#170) + ## [1.4.1] - 2022-04-17 diff --git a/uCNC/src/cnc.c b/uCNC/src/cnc.c index d01c26a74..0af098968 100644 --- a/uCNC/src/cnc.c +++ b/uCNC/src/cnc.c @@ -23,13 +23,12 @@ #include "cnc.h" #define LOOP_STARTUP_RESET 0 -#define LOOP_RUNNING_FIRST_RUN 1 -#define LOOP_RUNNING 2 -#define LOOP_ERROR_RESET 3 +#define LOOP_RUNNING 1 +#define LOOP_ERROR_RESET 2 -#define UNLOCK_ERROR 0 +#define UNLOCK_OK 0 #define UNLOCK_LOCKED 1 -#define UNLOCK_OK 2 +#define UNLOCK_ERROR 2 #define RTCMD_NORMAL_MASK (RT_CMD_FEED_100 | RT_CMD_FEED_INC_COARSE | RT_CMD_FEED_DEC_COARSE | RT_CMD_FEED_INC_FINE | RT_CMD_FEED_DEC_FINE) #define RTCMD_RAPID_MASK (RT_CMD_RAPIDFEED_100 | RT_CMD_RAPIDFEED_OVR1 | RT_CMD_RAPIDFEED_OVR2) @@ -47,6 +46,7 @@ typedef struct } cnc_state_t; static cnc_state_t cnc_state; +bool cnc_status_report_lock; static void cnc_check_fault_systems(void); static bool cnc_check_interlocking(void); @@ -54,12 +54,14 @@ static void cnc_exec_rt_commands(void); static void cnc_io_dotasks(void); static void cnc_reset(void); static bool cnc_exec_cmd(void); +static void cnc_run_startup_blocks(void); void cnc_init(void) { // initializes cnc state #ifdef FORCE_GLOBALS_TO_0 memset(&cnc_state, 0, sizeof(cnc_state_t)); + cnc_status_report_lock = false; #endif cnc_state.loop_state = LOOP_STARTUP_RESET; // initializes all systems @@ -78,14 +80,15 @@ void cnc_init(void) void cnc_run(void) { + // enters loop reset cnc_reset(); - cnc_state.loop_state = LOOP_RUNNING_FIRST_RUN; - serial_select(SERIAL_UART); - // tries to reset. If fails jumps to error - while (cnc_unlock(false)) + while (cnc_unlock(false) != UNLOCK_ERROR) { + serial_select(SERIAL_UART); + cnc_state.loop_state = LOOP_RUNNING; + do { } while (cnc_exec_cmd()); @@ -115,7 +118,15 @@ void cnc_run(void) } } cnc_dotasks(); - } while (io_get_controls() & ESTOP_MASK); + if (io_get_controls() & ESTOP_MASK) + { + cnc_state.loop_state = LOOP_STARTUP_RESET; + } + else + { + break; + } + } while (1); } bool cnc_exec_cmd(void) @@ -143,8 +154,6 @@ bool cnc_exec_cmd(void) { protocol_send_error(error); } - - cnc_state.loop_state = LOOP_RUNNING; } return cnc_dotasks(); @@ -267,6 +276,7 @@ void cnc_home(void) // sync's the motion control with the real time position mc_sync_position(); + cnc_run_startup_blocks(); } void cnc_alarm(int8_t code) @@ -333,19 +343,11 @@ uint8_t cnc_unlock(bool force) io_enable_steppers(g_settings.step_enable_invert); parser_reset(); - if (cnc_state.loop_state < LOOP_RUNNING) + // hard reset + // if homing not enabled run startup blocks + if (cnc_state.loop_state == LOOP_STARTUP_RESET && !g_settings.homing_enabled) { - serial_select(SERIAL_N0); - if (!cnc_exec_cmd()) - { - return UNLOCK_ERROR; - } - serial_select(SERIAL_N1); - if (!cnc_exec_cmd()) - { - return UNLOCK_ERROR; - } - serial_select(SERIAL_UART); + cnc_run_startup_blocks(); } } @@ -451,7 +453,6 @@ void cnc_delay_ms(uint32_t miliseconds) void cnc_reset(void) { - cnc_state.loop_state = LOOP_STARTUP_RESET; // resets all realtime command flags cnc_state.rt_cmd = RT_CMD_CLEAR; cnc_state.feed_ovr_cmd = RT_CMD_CLEAR; @@ -802,10 +803,24 @@ static void cnc_io_dotasks(void) #endif mcu_controls_changed_cb(); - if (cnc_state.loop_state > LOOP_STARTUP_RESET && CHECKFLAG(cnc_state.rt_cmd, RT_CMD_REPORT)) + if (cnc_status_report_lock) + { + return; + } + + if (CHECKFLAG(cnc_state.rt_cmd, RT_CMD_REPORT)) { // if a report request is sent, clear the respective flag CLEARFLAG(cnc_state.rt_cmd, RT_CMD_REPORT); protocol_send_status(); } } + +void cnc_run_startup_blocks(void) +{ + serial_select(SERIAL_N0); + cnc_exec_cmd(); + serial_select(SERIAL_N1); + cnc_exec_cmd(); + serial_select(SERIAL_UART); +} diff --git a/uCNC/src/cnc.h b/uCNC/src/cnc.h index 98dfb48e8..5e46baade 100644 --- a/uCNC/src/cnc.h +++ b/uCNC/src/cnc.h @@ -222,6 +222,8 @@ extern "C" #include #include + extern bool cnc_status_report_lock; + void cnc_init(void); void cnc_run(void); // do events returns true if all OK and false if an ABORT alarm is reached diff --git a/uCNC/src/core/motion_control.c b/uCNC/src/core/motion_control.c index 76023e4dc..ccacc2690 100644 --- a/uCNC/src/core/motion_control.c +++ b/uCNC/src/core/motion_control.c @@ -465,7 +465,11 @@ uint8_t mc_dwell(motion_data_t *block_data) if (!mc_checkmode) // check mode (gcode simulation) doesn't send code to planner { mc_update_tools(block_data); + // restores/forces run flag + cnc_set_exec_state(EXEC_RUN); cnc_delay_ms(block_data->dwell); + // clear forced run flag to allow next motions + cnc_clear_exec_state(EXEC_RUN); } return STATUS_OK; @@ -599,7 +603,7 @@ uint8_t mc_home_axis(uint8_t axis, uint8_t axis_limit) // flags homing clear by the unlock cnc_set_exec_state(EXEC_HOMING); mc_line(target, &block_data); - + if (itp_sync() != STATUS_OK) { return STATUS_CRITICAL_FAIL; diff --git a/uCNC/src/core/parser.c b/uCNC/src/core/parser.c index cebf65a79..8f6e911ff 100644 --- a/uCNC/src/core/parser.c +++ b/uCNC/src/core/parser.c @@ -1466,6 +1466,9 @@ uint8_t parser_exec_command(parser_state_t *new_state, parser_words_t *words, pa return error; } + + // saves position + memcpy(parser_last_pos, target, sizeof(parser_last_pos)); } if (error) @@ -1473,9 +1476,6 @@ uint8_t parser_exec_command(parser_state_t *new_state, parser_words_t *words, pa return error; } - // saves position - memcpy(parser_last_pos, target, sizeof(parser_last_pos)); - // stop (M0, M1, M2, M30, M60) (not implemented yet). bool hold = false; bool resetparser = false; @@ -2682,3 +2682,18 @@ uint8_t parser_exec_command_block(parser_state_t *new_state, parser_words_t *wor return error; } #endif + +void parser_machine_to_work(float *axis) +{ + for (uint8_t i = 0; i < AXIS_COUNT; i++) + { + axis[i] -= (parser_parameters.g92_offset[i] + parser_parameters.coord_system_offset[i]); + } + +#ifdef AXIS_TOOL + if (parser_state.groups.tlo_mode != G49) + { + axis[AXIS_TOOL] -= parser_parameters.tool_length_offset; + } +#endif +} \ No newline at end of file diff --git a/uCNC/src/core/parser.h b/uCNC/src/core/parser.h index 339333957..8fa25c7fc 100644 --- a/uCNC/src/core/parser.h +++ b/uCNC/src/core/parser.h @@ -184,6 +184,7 @@ extern "C" void parser_parameters_save(void); void parser_sync_position(void); void parser_reset(void); + void parser_machine_to_work(float *axis); uint8_t parser_exec_command(parser_state_t *new_state, parser_words_t *words, parser_cmd_explicit_t *cmd); #ifdef __cplusplus diff --git a/uCNC/src/core/planner.c b/uCNC/src/core/planner.c index a6fa864c0..e17f9d991 100644 --- a/uCNC/src/core/planner.c +++ b/uCNC/src/core/planner.c @@ -659,3 +659,8 @@ bool planner_get_overflows(uint8_t *overflows) planner_ovr_counter--; return false; } + +uint8_t planner_get_buffer_freeblocks() +{ + return PLANNER_BUFFER_SIZE - planner_data_blocks; +} diff --git a/uCNC/src/core/planner.h b/uCNC/src/core/planner.h index b68789f97..2a43bb4a4 100644 --- a/uCNC/src/core/planner.h +++ b/uCNC/src/core/planner.h @@ -105,6 +105,8 @@ extern "C" bool planner_get_overflows(uint8_t *overflows); + uint8_t planner_get_buffer_freeblocks(); + #ifdef __cplusplus } #endif diff --git a/uCNC/src/interface/grbl_interface.h b/uCNC/src/interface/grbl_interface.h index ef408b89b..d1d675468 100644 --- a/uCNC/src/interface/grbl_interface.h +++ b/uCNC/src/interface/grbl_interface.h @@ -149,11 +149,11 @@ extern "C" #ifndef EMULATE_GRBL_STARTUP #define MSG_STARTUP_START "uCNC " #define MSG_STARTUP_END " ['$' for help]" +#define MSG_STARTUP __romstr__(STR_EOL MSG_STARTUP_START CNC_VERSION MSG_STARTUP_END STR_EOL) #else -#define MSG_STARTUP_START "Grbl " -#define MSG_STARTUP_END " ['$' for uCNC help]" +#define MSG_STARTUP __romstr__(STR_EOL "Grbl 1.1h ['$' for help]" STR_EOL) #endif -#define MSG_STARTUP __romstr__(MSG_STARTUP_START CNC_VERSION MSG_STARTUP_END STR_EOL) + #define MSG_HELP __romstr__("[HLP:$$ $# $G $I $N $x=val $Nx=line $J=line $C $X $H ~ ! ? ctrl-x]" STR_EOL) // Non query feedback messages @@ -186,6 +186,7 @@ extern "C" #define MSG_STATUS_CHECK __romstr__("Check") #define MSG_STATUS_MPOS __romstr__("|MPos:") +#define MSG_STATUS_WPOS __romstr__("|WPos:") #define MSG_STATUS_FS __romstr__("|FS:") #define MSG_STATUS_F __romstr__("|F:") #define MSG_STATUS_WCO __romstr__("|WCO:") @@ -193,6 +194,7 @@ extern "C" #define MSG_STATUS_TOOL __romstr__("|A:") #define MSG_STATUS_LINE __romstr__("|Ln:") #define MSG_STATUS_PIN __romstr__("|Pn:") +#define MSG_STATUS_BUF __romstr__("|Buf:") //#define MSG_INT "%d" //#define MSG_FLT "%0.3f" diff --git a/uCNC/src/interface/protocol.c b/uCNC/src/interface/protocol.c index 4d9d2daf1..f43e91450 100644 --- a/uCNC/src/interface/protocol.c +++ b/uCNC/src/interface/protocol.c @@ -1,15 +1,13 @@ /* - Name: protocol.h + Name: protocol.c Description: µCNC implementation of a Grbl compatible send-response protocol Copyright: Copyright (c) João Martins Author: João Martins Date: 19/09/2019 - µCNC 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. Please see - µCNC is distributed WITHOUT ANY WARRANTY; Also without the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -254,7 +252,16 @@ void protocol_send_status(void) } } - serial_print_str(MSG_STATUS_MPOS); + if ((g_settings.status_report_mask & 1)) + { + serial_print_str(MSG_STATUS_MPOS); + } + else + { + serial_print_str(MSG_STATUS_WPOS); + parser_machine_to_work(axis); + } + serial_print_fltarr(axis, AXIS_COUNT); #if TOOL_COUNT > 0 @@ -330,6 +337,14 @@ void protocol_send_status(void) protocol_send_status_tail(); + if ((g_settings.status_report_mask & 2)) + { + serial_print_str(MSG_STATUS_BUF); + serial_print_int((uint32_t)planner_get_buffer_freeblocks()); + serial_putc(','); + serial_print_int((uint32_t)serial_get_rx_freebytes()); + } + serial_putc('>'); procotol_send_newline(); #ifdef ECHO_CMD @@ -824,4 +839,4 @@ void protocol_send_cnc_info(void) protocol_busy = false; #endif } -#endif +#endif \ No newline at end of file diff --git a/uCNC/src/interface/serial.c b/uCNC/src/interface/serial.c index a4e098591..12befb607 100644 --- a/uCNC/src/interface/serial.c +++ b/uCNC/src/interface/serial.c @@ -186,9 +186,12 @@ void serial_putc(unsigned char c) } while (write == serial_tx_read) { + cnc_status_report_lock = true; cnc_dotasks(); } // while buffer is full + cnc_status_report_lock = false; + serial_tx_buffer[serial_tx_write] = c; serial_tx_write = write; if (c == '\n') @@ -409,3 +412,14 @@ void serial_rx_clear(void) serial_rx_overflow = 0; serial_rx_buffer[0] = EOL; } + +uint8_t serial_get_rx_freebytes(void) +{ + uint16_t buf = serial_rx_write; + if (serial_rx_read > buf) + { + buf += RX_BUFFER_SIZE; + } + + return (uint8_t)(RX_BUFFER_CAPACITY - (buf - serial_rx_read)); +} diff --git a/uCNC/src/interface/serial.h b/uCNC/src/interface/serial.h index 6633b2e9e..e5fb59a7f 100644 --- a/uCNC/src/interface/serial.h +++ b/uCNC/src/interface/serial.h @@ -62,6 +62,7 @@ extern "C" void serial_print_intarr(int32_t *arr, uint8_t count); void serial_print_fltarr(float *arr, uint8_t count); void serial_flush(void); + uint8_t serial_get_rx_freebytes(void); #ifdef __cplusplus }