From 9afb772b3904dc8e44b9b300c5f134442d8875b5 Mon Sep 17 00:00:00 2001 From: Paciente8159 Date: Sun, 1 Aug 2021 00:56:12 +0100 Subject: [PATCH 01/24] implemented codes M0 and M1 -implemented codes M0 and M1 -M1_CONDITION can be defined to assert M1 stop. If undefined M1 will act as M0 --- src/cnc.c | 8 +++- src/core/interpolator.c | 81 ++++++++++++++++++++++++++-------- src/core/interpolator.h | 1 - src/core/motion_control.h | 2 + src/core/parser.c | 11 ++++- src/core/planner.c | 1 + src/core/planner.h | 2 +- src/interface/grbl_interface.h | 1 + 8 files changed, 84 insertions(+), 23 deletions(-) diff --git a/src/cnc.c b/src/cnc.c index 5d81702c4..914c6086a 100644 --- a/src/cnc.c +++ b/src/cnc.c @@ -205,6 +205,7 @@ extern "C" bool cnc_dotasks(void) { + static bool lock_itp = false; //run all mcu_internal tasks mcu_dotasks(); @@ -229,7 +230,12 @@ extern "C" return !cnc_get_exec_state(EXEC_ABORT); } - itp_run(); + if (!lock_itp) + { + lock_itp = true; + itp_run(); + lock_itp = false; + } return !cnc_get_exec_state(EXEC_ABORT); } diff --git a/src/core/interpolator.c b/src/core/interpolator.c index f0524238a..48eb20405 100644 --- a/src/core/interpolator.c +++ b/src/core/interpolator.c @@ -42,6 +42,13 @@ extern "C" //integrator calculates 10ms (minimum size) time frame windows #define INTERPOLATOR_BUFFER_SIZE 5 //number of windows in the buffer +//Itp update flags +#define ITP_NOUPDATE 0 +#define ITP_DWELL 1 +#define ITP_UPDATE_TOOLS 2 +#define ITP_PAUSE 4 +#define ITP_PAUSE_CONDITIONAL 8 + //contains data of the block being executed by the pulse routine //this block has the necessary data to execute the Bresenham line algorithm typedef struct itp_blk_ @@ -78,7 +85,7 @@ extern "C" bool spindle_inv; #endif float feed; - uint8_t update_speed; + uint8_t update_itp; } itp_segment_t; //circular buffers @@ -110,6 +117,7 @@ extern "C" FORCEINLINE static void itp_sgm_clear(void); FORCEINLINE static void itp_blk_buffer_write(void); static void itp_blk_clear(void); + FORCEINLINE static void itp_nomotion(uint8_t type, uint16_t delay); /* Interpolator segment buffer functions @@ -228,23 +236,38 @@ extern "C" itp_blk_data[itp_blk_data_write].line = itp_cur_plan_block->line; #endif + uint8_t nomotion_type = ITP_NOUPDATE; if (itp_cur_plan_block->dwell != 0) { - itp_delay(itp_cur_plan_block->dwell); + nomotion_type |= ITP_DWELL; } if (itp_cur_plan_block->total_steps == 0) { #ifdef USE_SPINDLE - if (itp_cur_plan_block->dwell == 0) //if dwell is 0 then run a single loop to updtate outputs (spindle) + nomotion_type = ITP_UPDATE_TOOLS; +#endif + if (itp_cur_plan_block->action & (MOTIONCONTROL_MODE_PAUSEPROGRAM | MOTIONCONTROL_MODE_PAUSEPROGRAM_CONDITIONAL)) { - itp_delay(0); + nomotion_type |= ITP_PAUSE; + } + + if (itp_cur_plan_block->action & (MOTIONCONTROL_MODE_PAUSEPROGRAM_CONDITIONAL)) + { + nomotion_type |= ITP_PAUSE_CONDITIONAL; + } + } + + if (nomotion_type) + { + itp_nomotion(nomotion_type, itp_cur_plan_block->dwell); + if (nomotion_type > ITP_DWELL) + { + //no motion action (doesn't need a interpolator block = NULL) + itp_cur_plan_block = NULL; + planner_discard_block(); + break; //exits after adding the dwell segment if motion is 0 (empty motion block) } -#endif - //no motion action (doesn't need a interpolator block = NULL) - itp_cur_plan_block = NULL; - planner_discard_block(); - break; //exits after adding the dwell segment if motion is 0 (empty motion block) } //overwrites previous values @@ -355,7 +378,7 @@ extern "C" */ speed_change = half_speed_change; //(!initial_accel_negative) ? half_speed_change : -half_speed_change; profile_steps_limit = accel_until; - sgm->update_speed = 1; + sgm->update_itp = ITP_DWELL; is_initial_transition = true; } else if (remaining_steps > deaccel_from) @@ -363,14 +386,14 @@ extern "C" //constant speed segment speed_change = 0; profile_steps_limit = deaccel_from; - sgm->update_speed = is_initial_transition ? 2 : 0; + sgm->update_itp = is_initial_transition ? ITP_UPDATE_TOOLS : ITP_NOUPDATE; is_initial_transition = false; } else { speed_change = -half_speed_change; profile_steps_limit = 0; - sgm->update_speed = 1; + sgm->update_itp = ITP_DWELL; is_initial_transition = true; } @@ -691,17 +714,31 @@ extern "C" io_set_dirs(itp_rt_sgm->block->dirbits); } - if (itp_rt_sgm->update_speed) + if (itp_rt_sgm->update_itp) { - if (itp_rt_sgm->update_speed & 0x01) + if (itp_rt_sgm->update_itp & ITP_DWELL) { mcu_change_itp_isr(itp_rt_sgm->timer_counter, itp_rt_sgm->timer_prescaller); } + else if (itp_rt_sgm->update_itp & ITP_PAUSE) + { + mcu_disable_global_isr(); + itp_busy = false; +#ifdef M1_CONDITION + if (!M1_CONDITION) + { + return; + } +#endif + itp_stop(); //stop the isr + cnc_set_exec_state(EXEC_HOLD); + return; + } #ifdef USE_SPINDLE io_set_spindle(itp_rt_sgm->spindle, itp_rt_sgm->spindle_inv); itp_rt_spindle = itp_rt_sgm->spindle; #endif - itp_rt_sgm->update_speed = 0; + itp_rt_sgm->update_itp = ITP_NOUPDATE; } } else @@ -957,8 +994,16 @@ extern "C" itp_busy = false; } - void itp_delay(uint16_t delay) + void itp_nomotion(uint8_t type, uint16_t delay) { + while (itp_sgm_is_full()) + { + if (!cnc_dotasks()) + { + return; + } + } + itp_sgm_data[itp_sgm_data_write].block = NULL; //clicks every 100ms (10Hz) if (delay) @@ -969,9 +1014,9 @@ extern "C" { mcu_freq_to_clocks(g_settings.max_step_rate, &(itp_sgm_data[itp_sgm_data_write].timer_counter), &(itp_sgm_data[itp_sgm_data_write].timer_prescaller)); } - itp_sgm_data[itp_sgm_data_write].remaining_steps = MAX(delay, 1); - itp_sgm_data[itp_sgm_data_write].update_speed = 1; + itp_sgm_data[itp_sgm_data_write].remaining_steps = MAX(delay, 0); itp_sgm_data[itp_sgm_data_write].feed = 0; + itp_sgm_data[itp_sgm_data_write].update_itp = type; #ifdef USE_SPINDLE #ifdef LASER_MODE if (g_settings.laser_mode) diff --git a/src/core/interpolator.h b/src/core/interpolator.h index e6ab2613a..b1b250e37 100644 --- a/src/core/interpolator.h +++ b/src/core/interpolator.h @@ -47,7 +47,6 @@ extern "C" #ifdef GCODE_PROCESS_LINE_NUMBERS uint32_t itp_get_rt_line_number(void); #endif - void itp_delay(uint16_t delay); #ifdef __cplusplus } diff --git a/src/core/motion_control.h b/src/core/motion_control.h index b5d0e3379..3b742ff0b 100644 --- a/src/core/motion_control.h +++ b/src/core/motion_control.h @@ -31,6 +31,8 @@ extern "C" #define MOTIONCONTROL_MODE_NOMOTION 1 #define MOTIONCONTROL_MODE_INVERSEFEED 2 #define MOTIONCONTROL_MODE_BACKLASH_COMPENSATION 4 +#define MOTIONCONTROL_MODE_PAUSEPROGRAM 8 +#define MOTIONCONTROL_MODE_PAUSEPROGRAM_CONDITIONAL 16 typedef struct { diff --git a/src/core/parser.c b/src/core/parser.c index 5fb521af9..1ae1a0d73 100644 --- a/src/core/parser.c +++ b/src/core/parser.c @@ -961,10 +961,15 @@ extern "C" float planner_last_pos[AXIS_COUNT]; motion_data_t block_data = {0}; - //stoping from previous command is active + //stoping from previous command M2 or M30 command if (new_state->groups.stopping && !CHECKFLAG(cmd->groups, GCODE_GROUP_STOPPING)) { - return STATUS_OK; + if (new_state->groups.stopping == 3 || new_state->groups.stopping == 4) + { + return STATUS_PROGRAM_ENDED; + } + + new_state->groups.stopping = 0; } #ifdef GCODE_PROCESS_LINE_NUMBERS @@ -1480,6 +1485,8 @@ extern "C" switch (new_state->groups.stopping) { case 1: //M0 + block_data.update_tools = true; + block_data.motion_mode |= MOTIONCONTROL_MODE_NOMOTION | MOTIONCONTROL_MODE_PAUSEPROGRAM; break; case 2: //M1 break; diff --git a/src/core/planner.c b/src/core/planner.c index 4d995ad6b..689082c6b 100644 --- a/src/core/planner.c +++ b/src/core/planner.c @@ -121,6 +121,7 @@ extern "C" { memset(planner_data[planner_data_write].steps, 0, sizeof(planner_data[planner_data_write].steps)); planner_data[planner_data_write].total_steps = 0; + planner_data[planner_data_write].action = block_data->motion_mode & (MOTIONCONTROL_MODE_PAUSEPROGRAM | MOTIONCONTROL_MODE_PAUSEPROGRAM_CONDITIONAL); } else { diff --git a/src/core/planner.h b/src/core/planner.h index 36d4f5a15..4734308a1 100644 --- a/src/core/planner.h +++ b/src/core/planner.h @@ -64,7 +64,7 @@ extern "C" #ifdef ENABLE_BACKLASH_COMPENSATION bool backlash_comp; #endif - + uint8_t action; bool optimal; } planner_block_t; diff --git a/src/interface/grbl_interface.h b/src/interface/grbl_interface.h index 9bee1f5b0..0ddd1af48 100644 --- a/src/interface/grbl_interface.h +++ b/src/interface/grbl_interface.h @@ -94,6 +94,7 @@ extern "C" #define STATUS_FEED_NOT_SET 41 #define STATUS_SETTING_WRITE_FAIL 42 #define STATUS_SETTING_PROTECTED_FAIL 43 +#define STATUS_PROGRAM_ENDED 44 #define STATUS_CRITICAL_FAIL 255 //special Grbl system commands return codes From 87e7f790dd82dbfdd4ed6102c84600fa71fcb85e Mon Sep 17 00:00:00 2001 From: Paciente8159 Date: Tue, 3 Aug 2021 13:32:56 +0100 Subject: [PATCH 02/24] initial release -moved delay from mcu to cnc to allow cnc tasks to run will in the delay loop -removed all non motion gcodes and actions from pipeline. These are now executed at the motion control level. This lead to a small code footprint reduction. -non motion or sync actions now cause the planner and interpolation to get empty before executing. -delay on resume now working properly though it needs improving -changed virtual mcu to support these changes (stalled on delays) --- src/cnc.c | 36 +++- src/cnc.h | 3 +- src/core/interpolator.c | 39 +++-- src/core/interpolator.h | 2 + src/core/motion_control.c | 229 +++++++++++++------------- src/core/motion_control.h | 19 ++- src/core/parser.c | 67 ++++---- src/core/planner.c | 224 +++++++++++++------------ src/core/planner.h | 4 +- src/hal/mcus/mcu.h | 14 -- src/hal/mcus/virtual/mcu_virtual.c | 21 ++- src/hal/mcus/virtual/mcumap_virtual.h | 2 - 12 files changed, 343 insertions(+), 317 deletions(-) diff --git a/src/cnc.c b/src/cnc.c index 914c6086a..87ee0136f 100644 --- a/src/cnc.c +++ b/src/cnc.c @@ -141,10 +141,10 @@ extern "C" SETFLAG(cnc_state.rt_cmd, RT_CMD_REPORT); break; case CMD_CODE_CYCLE_START: - cnc_clear_exec_state(EXEC_HOLD); //tries to clear hold if possible + SETFLAG(cnc_state.rt_cmd, RT_CMD_CYCLE_START); //tries to clear hold if possible break; case CMD_CODE_SAFETY_DOOR: - cnc_clear_exec_state(EXEC_HOLD | EXEC_DOOR); + cnc_set_exec_state(EXEC_HOLD | EXEC_DOOR); break; case CMD_CODE_JOG_CANCEL: if (cnc_get_exec_state(EXEC_JOG)) @@ -277,7 +277,7 @@ extern "C" //reset position itp_reset_rt_position(); - planner_resync_position(); + planner_sync_position(); //invokes startup block execution SETFLAG(cnc_state.rt_cmd, RT_CMD_STARTUP_BLOCK0); } @@ -311,7 +311,7 @@ extern "C" //all other alarm flags remain active if any input is still active CLEARFLAG(cnc_state.exec_state, EXEC_NOHOME | EXEC_LIMITS); //clears all other locking flags - cnc_clear_exec_state(EXEC_LOCKED); + cnc_clear_exec_state(EXEC_GCODE_LOCKED); //signals stepper enable pins io_set_steps(g_settings.step_invert_mask); @@ -341,7 +341,7 @@ extern "C" #ifdef SAFETY_DOOR if (CHECKFLAG(controls, SAFETY_DOOR_MASK)) //can't clear the door flag if SAFETY_DOOR is active { - CLEARFLAG(statemask, EXEC_DOOR); + CLEARFLAG(statemask, EXEC_DOOR | EXEC_HOLD); } #endif #ifdef FHOLD @@ -361,9 +361,27 @@ extern "C" CLEARFLAG(statemask, EXEC_NOHOME); } + if (CHECKFLAG(statemask, EXEC_HOLD)) + { + itp_sync_spindle(); + if (!planner_buffer_is_empty()) + { + cnc_delay_ms(DELAY_ON_RESUME * 1000); + } + } CLEARFLAG(cnc_state.exec_state, statemask); } + void cnc_delay_ms(uint32_t miliseconds) + { + uint32_t t_start = mcu_millis(); + uint32_t t_end = mcu_millis(); + while (t_end - t_start < miliseconds && cnc_dotasks()) + { + t_end = mcu_millis(); + } + } + void cnc_reset(void) { cnc_state.active_alarm = EXEC_ALARM_STARTUP; @@ -410,8 +428,8 @@ extern "C" bool update_tools = false; //executes feeds override rt commands - uint8_t cmd_mask = 0x04; - uint8_t command = cnc_state.rt_cmd & 0x07; //copies realtime flags states + uint8_t cmd_mask = 0x08; + uint8_t command = cnc_state.rt_cmd & 0x0F; //copies realtime flags states CLEARFLAG(cnc_state.rt_cmd, ~RT_CMD_REPORT); //clears all command flags except report request while (command) { @@ -423,7 +441,9 @@ extern "C" protocol_send_status(); CLEARFLAG(cnc_state.rt_cmd, RT_CMD_REPORT); //if a report request is sent, clear the respective flag } - + break; + case RT_CMD_CYCLE_START: + cnc_clear_exec_state(EXEC_HOLD); break; case RT_CMD_STARTUP_BLOCK0: if (settings_check_startup_gcode(STARTUP_BLOCK0_ADDRESS_OFFSET)) //loads command 0 diff --git a/src/cnc.h b/src/cnc.h index d3b99df64..b0260b92f 100644 --- a/src/cnc.h +++ b/src/cnc.h @@ -30,6 +30,7 @@ extern "C" #define RT_CMD_STARTUP_BLOCK0 1 #define RT_CMD_STARTUP_BLOCK1 2 #define RT_CMD_REPORT 4 +#define RT_CMD_CYCLE_START 8 #define RT_CMD_ABORT 128 //feed_ovr_cmd @@ -63,7 +64,6 @@ extern "C" #define EXEC_ABORT 128 //Emergency stop #define EXEC_ALARM (EXEC_NOHOME | EXEC_LIMITS | EXEC_DOOR | EXEC_ABORT) //System alarms #define EXEC_ALARM_ABORT (EXEC_LIMITS | EXEC_DOOR | EXEC_ABORT) //System alarms checked after abort -#define EXEC_LOCKED (EXEC_ALARM | EXEC_HOLD | EXEC_HOMING | EXEC_JOG) //Gcode is locked by an active state #define EXEC_GCODE_LOCKED (EXEC_ALARM | EXEC_HOMING | EXEC_JOG) //Gcode is locked by an alarm or any special motion state #define EXEC_ALLACTIVE 255 //All states @@ -199,6 +199,7 @@ extern "C" void cnc_alarm(uint8_t code); void cnc_stop(void); void cnc_unlock(void); + void cnc_delay_ms(uint32_t miliseconds); uint8_t cnc_get_exec_state(uint8_t statemask); void cnc_set_exec_state(uint8_t statemask); diff --git a/src/core/interpolator.c b/src/core/interpolator.c index 48eb20405..54a906c9c 100644 --- a/src/core/interpolator.c +++ b/src/core/interpolator.c @@ -29,6 +29,7 @@ extern "C" #include #include "cnc.h" #include "core/interpolator.h" +#include "interface/grbl_interface.h" #include "interface/settings.h" #include "core/planner.h" #include "core/io_control.h" @@ -112,7 +113,6 @@ extern "C" static void itp_sgm_buffer_read(void); static void itp_sgm_buffer_write(void); - FORCEINLINE static bool itp_sgm_is_empty(void); FORCEINLINE static bool itp_sgm_is_full(void); FORCEINLINE static void itp_sgm_clear(void); FORCEINLINE static void itp_blk_buffer_write(void); @@ -149,11 +149,6 @@ extern "C" itp_sgm_data_segments++; } - static bool itp_sgm_is_empty(void) - { - return (!itp_sgm_data_segments); - } - static bool itp_sgm_is_full(void) { return (itp_sgm_data_segments == INTERPOLATOR_BUFFER_SIZE); @@ -235,7 +230,7 @@ extern "C" #ifdef GCODE_PROCESS_LINE_NUMBERS itp_blk_data[itp_blk_data_write].line = itp_cur_plan_block->line; #endif - +/* uint8_t nomotion_type = ITP_NOUPDATE; if (itp_cur_plan_block->dwell != 0) { @@ -268,7 +263,7 @@ extern "C" planner_discard_block(); break; //exits after adding the dwell segment if motion is 0 (empty motion block) } - } + }*/ //overwrites previous values #ifdef ENABLE_BACKLASH_COMPENSATION @@ -515,7 +510,7 @@ extern "C" #endif //starts the step isr if is stopped and there are segments to execute - if (!cnc_get_exec_state(EXEC_HOLD | EXEC_ALARM | EXEC_RUN) && !itp_sgm_is_empty()) //exec state is not hold or alarm and not already running + if (!cnc_get_exec_state(EXEC_HOLD | EXEC_ALARM | EXEC_RUN) && itp_sgm_data_segments) //exec state is not hold or alarm and not already running { cnc_set_exec_state(EXEC_RUN); //flags that it started running mcu_start_itp_isr(itp_sgm_data[itp_sgm_data_read].timer_counter, itp_sgm_data[itp_sgm_data_read].timer_prescaller); @@ -599,6 +594,30 @@ extern "C" return feed; } + uint8_t itp_sync(void) + { + while (!planner_buffer_is_empty() || itp_sgm_data_segments) + { + if (!cnc_dotasks()) + { + return STATUS_CRITICAL_FAIL; + } + } + + return STATUS_OK; + } + + //sync spindle in a stopped motion + uint8_t itp_sync_spindle(void) + { +#ifdef USE_SPINDLE + uint8_t spindle = 0; + bool spindle_inv = 0; + planner_get_spindle_speed(0, &spindle, &spindle_inv); + io_set_spindle(spindle, spindle_inv); +#endif + } + #ifdef USE_SPINDLE uint16_t itp_get_rt_spindle(void) { @@ -652,7 +671,7 @@ extern "C" if (itp_rt_sgm == NULL) { //if buffer is not empty - if (!itp_sgm_is_empty()) + if (itp_sgm_data_segments) { //loads a new segment itp_rt_sgm = &itp_sgm_data[itp_sgm_data_read]; diff --git a/src/core/interpolator.h b/src/core/interpolator.h index b1b250e37..999675f7a 100644 --- a/src/core/interpolator.h +++ b/src/core/interpolator.h @@ -38,6 +38,8 @@ extern "C" void itp_get_rt_position(int32_t *position); void itp_reset_rt_position(void); float itp_get_rt_feed(void); + uint8_t itp_sync(void); + uint8_t itp_sync_spindle(void); #ifdef USE_SPINDLE uint16_t itp_get_rt_spindle(void); #endif diff --git a/src/core/motion_control.c b/src/core/motion_control.c index 2ac704ea4..4773c6951 100644 --- a/src/core/motion_control.c +++ b/src/core/motion_control.c @@ -195,118 +195,114 @@ extern "C" } uint8_t error = STATUS_OK; + int32_t step_new_pos[STEPPER_COUNT]; + int32_t step_old_pos[STEPPER_COUNT]; + //converts transformed target to stepper position + kinematics_apply_inverse(target, step_new_pos); + //calculates the amount of stepper motion for this motion + planner_get_position(step_old_pos); - if (!CHECKFLAG(block_data->motion_mode, MOTIONCONTROL_MODE_NOMOTION)) + uint32_t max_steps = 0; + block_data->dirbits = 0; + block_data->main_stepper = 255; + for (uint8_t i = STEPPER_COUNT; i != 0;) { - int32_t step_new_pos[STEPPER_COUNT]; - int32_t step_old_pos[STEPPER_COUNT]; - //converts transformed target to stepper position - kinematics_apply_inverse(target, step_new_pos); - //calculates the amount of stepper motion for this motion - planner_get_position(step_old_pos); - - uint32_t max_steps = 0; - block_data->dirbits = 0; - block_data->main_stepper = 255; - for (uint8_t i = STEPPER_COUNT; i != 0;) + i--; + int32_t steps = step_new_pos[i] - step_old_pos[i]; + if (steps < 0) { - i--; - int32_t steps = step_new_pos[i] - step_old_pos[i]; - if (steps < 0) - { - block_data->dirbits |= (1 << i); - } - - steps = ABS(steps); - if (max_steps < steps) - { - max_steps = steps; - block_data->main_stepper = i; - } + block_data->dirbits |= (1 << i); } - //no significant motion will take place. don't send any thing to the planner - if (!max_steps) + steps = ABS(steps); + if (max_steps < steps) { - return STATUS_OK; + max_steps = steps; + block_data->main_stepper = i; } + } - //checks the amount of steps that this motion translates to - //if the amount of steps is higher than the limit for the 16bit bresenham algorithm - //splits the line into smaller segments + //no significant motion will take place. don't send any thing to the planner + if (!max_steps) + { + return STATUS_OK; + } - //calculates the aproximation of the inverted travelled distance - float inv_dist = 0; - float motion_segment[AXIS_COUNT]; - for (uint8_t i = AXIS_COUNT; i != 0;) - { - i--; - motion_segment[i] = target[i] - prev_target[i]; - block_data->dir_vect[i] = motion_segment[i]; - inv_dist += fast_flt_pow2(block_data->dir_vect[i]); - } + //checks the amount of steps that this motion translates to + //if the amount of steps is higher than the limit for the 16bit bresenham algorithm + //splits the line into smaller segments - inv_dist = fast_flt_invsqrt(inv_dist); + //calculates the aproximation of the inverted travelled distance + float inv_dist = 0; + float motion_segment[AXIS_COUNT]; + for (uint8_t i = AXIS_COUNT; i != 0;) + { + i--; + motion_segment[i] = target[i] - prev_target[i]; + block_data->dir_vect[i] = motion_segment[i]; + inv_dist += fast_flt_pow2(block_data->dir_vect[i]); + } - //calculates max junction speed factor in (axis driven). Else the cos_theta is calculated in the planner (linear actuator driven) + inv_dist = fast_flt_invsqrt(inv_dist); + + //calculates max junction speed factor in (axis driven). Else the cos_theta is calculated in the planner (linear actuator driven) #ifndef ENABLE_LINACT_PLANNER + for (uint8_t i = AXIS_COUNT; i != 0;) + { + i--; + block_data->dir_vect[i] *= inv_dist; + } +#endif + + //calculated the total motion execution time @ the given rate + float inv_delta = (!CHECKFLAG(block_data->motion_mode, MOTIONCONTROL_MODE_INVERSEFEED) ? (block_data->feed * inv_dist) : (1.0f / block_data->feed)); + block_data->feed = (float)max_steps * inv_delta; + + //this contains a motion. Any tool update will be done here + block_data->update_tools = false; + uint32_t line_segments = 1; + if (max_steps > MAX_STEPS_PER_LINE) + { + line_segments += (max_steps >> MAX_STEPS_PER_LINE_BITS); + float m_inv = 1.0f / (float)line_segments; for (uint8_t i = AXIS_COUNT; i != 0;) { i--; - block_data->dir_vect[i] *= inv_dist; + motion_segment[i] *= m_inv; } -#endif - - //calculated the total motion execution time @ the given rate - float inv_delta = (!CHECKFLAG(block_data->motion_mode, MOTIONCONTROL_MODE_INVERSEFEED) ? (block_data->feed * inv_dist) : (1.0f / block_data->feed)); - block_data->feed = (float)max_steps * inv_delta; + } - //this contains a motion. Any tool update will be done here - block_data->update_tools = false; - uint32_t line_segments = 1; - if (max_steps > MAX_STEPS_PER_LINE) + while (line_segments--) + { + while (planner_buffer_is_full()) { - line_segments += (max_steps >> MAX_STEPS_PER_LINE_BITS); - float m_inv = 1.0f / (float)line_segments; - for (uint8_t i = AXIS_COUNT; i != 0;) + if (!cnc_dotasks()) { - i--; - motion_segment[i] *= m_inv; + block_data->feed = feed; + return STATUS_CRITICAL_FAIL; } } - while (line_segments--) + if (line_segments) { - while (planner_buffer_is_full()) + for (uint8_t i = AXIS_COUNT; i != 0;) { - if (!cnc_dotasks()) - { - block_data->feed = feed; - return STATUS_CRITICAL_FAIL; - } + i--; + prev_target[i] += motion_segment[i]; } - if (line_segments) + error = mc_line_segment(prev_target, block_data); + if (error) { - for (uint8_t i = AXIS_COUNT; i != 0;) - { - i--; - prev_target[i] += motion_segment[i]; - } - - error = mc_line_segment(prev_target, block_data); - if (error) - { - break; - } + break; } - else + } + else + { + error = mc_line_segment(target, block_data); + if (error) { - error = mc_line_segment(target, block_data); - if (error) - { - break; - } + break; } } } @@ -449,23 +445,42 @@ extern "C" uint8_t mc_dwell(motion_data_t *block_data) { - if (mc_checkmode) // check mode (gcode simulation) doesn't send code to planner + if (!mc_checkmode) // check mode (gcode simulation) doesn't send code to planner { - return STATUS_OK; + mc_update_tools(block_data); + cnc_delay_ms(block_data->dwell); } - while (planner_buffer_is_full()) + return STATUS_OK; + } + + uint8_t mc_pause(void) + { + if (!mc_checkmode) // check mode (gcode simulation) doesn't send code to planner { - if (!cnc_dotasks()) + if (itp_sync()) { return STATUS_CRITICAL_FAIL; } } - //send dwell (planner linear motion with distance == 0) - SETFLAG(block_data->motion_mode, MOTIONCONTROL_MODE_NOMOTION); - planner_add_line(NULL, block_data); - CLEARFLAG(block_data->motion_mode, MOTIONCONTROL_MODE_NOMOTION); + cnc_set_exec_state(EXEC_HOLD); + return STATUS_OK; + } + + uint8_t mc_update_tools(motion_data_t *block_data) + { + if (!mc_checkmode) // check mode (gcode simulation) doesn't send code to planner + { + if (itp_sync()) + { + return STATUS_CRITICAL_FAIL; + } + //synchronizes the tools + planner_sync_tools(block_data); + itp_sync_spindle(); + } + return STATUS_OK; } @@ -503,7 +518,7 @@ extern "C" { max_home_dist = -max_home_dist; } - planner_resync_position(); + planner_sync_position(); mc_resync_position(); mc_get_position(target); target[axis] += max_home_dist; @@ -537,7 +552,7 @@ extern "C" return EXEC_ALARM_HOMING_FAIL_RESET; } - mcu_delay_ms(g_settings.debounce_ms); //adds a delay before reading io pin (debounce) + cnc_delay_ms(g_settings.debounce_ms); //adds a delay before reading io pin (debounce) limits_flags = io_get_limits(); //the wrong switch was activated bails @@ -550,7 +565,7 @@ extern "C" max_home_dist = g_settings.homing_offset * 5.0f; //sync's the planner and motion control done when clearing the planner - //planner_resync_position(); + //planner_sync_position(); mc_resync_position(); mc_get_position(target); if (g_settings.homing_dir_invert_mask & axis_mask) @@ -578,7 +593,7 @@ extern "C" } } while (cnc_get_exec_state(EXEC_RUN)); - mcu_delay_ms(g_settings.debounce_ms); //adds a delay before reading io pin (debounce) + cnc_delay_ms(g_settings.debounce_ms); //adds a delay before reading io pin (debounce) //resets limit mask g_settings.limits_invert_mask ^= axis_limit; //stops, flushes buffers and clears the hold if active @@ -592,7 +607,7 @@ extern "C" return EXEC_ALARM_HOMING_FAIL_RESET; } - mcu_delay_ms(g_settings.debounce_ms); //adds a delay before reading io pin (debounce) + cnc_delay_ms(g_settings.debounce_ms); //adds a delay before reading io pin (debounce) limits_flags = io_get_limits(); if (CHECKFLAG(limits_flags, axis_limit)) @@ -603,26 +618,6 @@ extern "C" return STATUS_OK; } - uint8_t mc_update_tools(motion_data_t *block_data) - { - if (mc_checkmode) // check mode (gcode simulation) doesn't send code to planner - { - return STATUS_OK; - } - - while (planner_buffer_is_full()) - { - if (!cnc_dotasks()) - { - return STATUS_CRITICAL_FAIL; - } - } - - SETFLAG(block_data->motion_mode, MOTIONCONTROL_MODE_NOMOTION); - planner_add_line(NULL, block_data); - return STATUS_OK; - } - uint8_t mc_probe(float *target, bool invert_probe, motion_data_t *block_data) { #ifdef PROBE @@ -652,7 +647,7 @@ extern "C" itp_clear(); planner_clear(); cnc_clear_exec_state(~prev_state & EXEC_HOLD); //restores HOLD previous state - mcu_delay_ms(g_settings.debounce_ms); //adds a delay before reading io pin (debounce) + cnc_delay_ms(g_settings.debounce_ms); //adds a delay before reading io pin (debounce) bool probe_notok = (!invert_probe) ? io_get_probe() : !io_get_probe(); if (probe_notok) { diff --git a/src/core/motion_control.h b/src/core/motion_control.h index 3b742ff0b..1938a0497 100644 --- a/src/core/motion_control.h +++ b/src/core/motion_control.h @@ -28,11 +28,10 @@ extern "C" #include #define MOTIONCONTROL_MODE_FEED 0 -#define MOTIONCONTROL_MODE_NOMOTION 1 -#define MOTIONCONTROL_MODE_INVERSEFEED 2 -#define MOTIONCONTROL_MODE_BACKLASH_COMPENSATION 4 -#define MOTIONCONTROL_MODE_PAUSEPROGRAM 8 -#define MOTIONCONTROL_MODE_PAUSEPROGRAM_CONDITIONAL 16 +#define MOTIONCONTROL_MODE_INVERSEFEED 1 +#define MOTIONCONTROL_MODE_BACKLASH_COMPENSATION 2 +#define MOTIONCONTROL_MODE_PAUSEPROGRAM 4 +#define MOTIONCONTROL_MODE_PAUSEPROGRAM_CONDITIONAL 8 typedef struct { @@ -58,12 +57,20 @@ extern "C" void mc_init(void); bool mc_get_checkmode(void); bool mc_toogle_checkmode(void); + + //async motions uint8_t mc_line(float *target, motion_data_t *block_data); uint8_t mc_arc(float *target, float center_offset_a, float center_offset_b, float radius, uint8_t axis_0, uint8_t axis_1, bool isclockwise, motion_data_t *block_data); + + //sync motions uint8_t mc_dwell(motion_data_t *block_data); - uint8_t mc_home_axis(uint8_t axis, uint8_t axis_limit); + uint8_t mc_pause(void); uint8_t mc_update_tools(motion_data_t *block_data); + + //mixed/special motions + uint8_t mc_home_axis(uint8_t axis, uint8_t axis_limit); uint8_t mc_probe(float *target, bool invert_probe, motion_data_t *block_data); + void mc_get_position(float *target); void mc_resync_position(void); diff --git a/src/core/parser.c b/src/core/parser.c index 1ae1a0d73..5086b3d3d 100644 --- a/src/core/parser.c +++ b/src/core/parser.c @@ -968,7 +968,7 @@ extern "C" { return STATUS_PROGRAM_ENDED; } - + new_state->groups.stopping = 0; } @@ -1036,7 +1036,7 @@ extern "C" if (!g_settings.laser_mode) { #endif - block_data.dwell = (uint16_t)roundf(DELAY_ON_SPINDLE_SPEED_CHANGE * 10.0); + block_data.dwell = (uint16_t)roundf(DELAY_ON_SPINDLE_SPEED_CHANGE * 1000); #ifdef LASER_MODE } #endif @@ -1063,28 +1063,17 @@ extern "C" if (new_state->groups.nonmodal == G4) { //calc dwell in time in 10ms increments - block_data.dwell = MAX(block_data.dwell, (uint16_t)roundf(words->p * 10.0)); -#ifdef LASER_MODE - //laser disabled in dwell - int16_t laserpwm = block_data.spindle; - if (g_settings.laser_mode) - { - block_data.spindle = 0; - block_data.update_tools = true; - } -#endif - if (mc_dwell(&block_data)) - { - return STATUS_CRITICAL_FAIL; - } - -#ifdef LASER_MODE - //laser disabled in dwell - block_data.spindle = laserpwm; -#endif + block_data.dwell = MAX(block_data.dwell, (uint16_t)roundf(words->p)); new_state->groups.nonmodal = 0; } + //after all spindle, overrides, coolant and dwells are set + //execute sync if dwell is present + if (block_data.dwell) + { + mc_dwell(&block_data); + } + //11. set active plane (G17, G18, G19) switch (new_state->groups.plane) { @@ -1482,35 +1471,41 @@ extern "C" } //stop (M0, M1, M2, M30, M60) (not implemented yet). + bool hold = false; + bool resetparser = false; switch (new_state->groups.stopping) { case 1: //M0 - block_data.update_tools = true; - block_data.motion_mode |= MOTIONCONTROL_MODE_NOMOTION | MOTIONCONTROL_MODE_PAUSEPROGRAM; + case 6: //M60 (pallet change has no effect) + hold = true; break; case 2: //M1 +#ifdef M1_CONDITION_ASSERT + hold = M1_CONDITION_ASSERT; +#endif break; case 3: //M2 - case 4: //M30 - //reset to initial states - parser_reset(); - protocol_send_feedback(MSG_FEEDBACK_8); - break; - case 6: //M60 + case 4: //M30 (pallet change has no effect) + hold = true; + resetparser = true; break; } + if (hold) + { + mc_pause(); + if (resetparser) + { + cnc_stop(); + parser_reset(); + protocol_send_feedback(MSG_FEEDBACK_8); + } + } + //if reached here the execution was not intersected //send a spindle and coolant update if needed if (block_data.update_tools) { -#ifdef LASER_MODE - //laser disabled in G0 - if (g_settings.laser_mode) - { - block_data.spindle = 0; - } -#endif return mc_update_tools(&block_data); } diff --git a/src/core/planner.c b/src/core/planner.c index 689082c6b..b60baf355 100644 --- a/src/core/planner.c +++ b/src/core/planner.c @@ -108,7 +108,6 @@ extern "C" #ifdef GCODE_PROCESS_LINE_NUMBERS planner_data[planner_data_write].line = block_data->line; #endif - planner_data[planner_data_write].dwell = block_data->dwell; #ifdef ENABLE_BACKLASH_COMPENSATION if (CHECKFLAG(block_data->motion_mode, MOTIONCONTROL_MODE_BACKLASH_COMPENSATION)) @@ -117,144 +116,135 @@ extern "C" } #endif - if (CHECKFLAG(block_data->motion_mode, MOTIONCONTROL_MODE_NOMOTION)) - { - memset(planner_data[planner_data_write].steps, 0, sizeof(planner_data[planner_data_write].steps)); - planner_data[planner_data_write].total_steps = 0; - planner_data[planner_data_write].action = block_data->motion_mode & (MOTIONCONTROL_MODE_PAUSEPROGRAM | MOTIONCONTROL_MODE_PAUSEPROGRAM_CONDITIONAL); - } - else - { - memcpy(planner_data[planner_data_write].steps, block_data->steps, sizeof(planner_data[planner_data_write].steps)); - planner_data[planner_data_write].total_steps = block_data->total_steps; + memcpy(planner_data[planner_data_write].steps, block_data->steps, sizeof(planner_data[planner_data_write].steps)); + planner_data[planner_data_write].total_steps = block_data->total_steps; - //calculates the normalized vector with the amount of motion in any linear actuator - //also calculates the maximum feedrate and acceleration for each linear actuator + //calculates the normalized vector with the amount of motion in any linear actuator + //also calculates the maximum feedrate and acceleration for each linear actuator #ifdef ENABLE_LINACT_PLANNER - float inv_total_steps = 1.0f / (float)(block_data->full_steps); + float inv_total_steps = 1.0f / (float)(block_data->full_steps); #endif #ifdef ENABLE_LINACT_COLD_START - bool coldstart = false; + bool coldstart = false; #endif - float cos_theta = 0; - float rapid_feed = FLT_MAX; - planner_data[planner_data_write].acceleration = FLT_MAX; + float cos_theta = 0; + float rapid_feed = FLT_MAX; + planner_data[planner_data_write].acceleration = FLT_MAX; #ifdef ENABLE_LINACT_PLANNER - float dir_vect[STEPPER_COUNT]; - memset(dir_vect, 0, sizeof(dir_vect)); + float dir_vect[STEPPER_COUNT]; + memset(dir_vect, 0, sizeof(dir_vect)); #else - for (uint8_t i = AXIS_COUNT; i != 0;) - { - i--; - cos_theta += block_data->dir_vect[i] * last_dir_vect[i]; - last_dir_vect[i] = block_data->dir_vect[i]; - } + for (uint8_t i = AXIS_COUNT; i != 0;) + { + i--; + cos_theta += block_data->dir_vect[i] * last_dir_vect[i]; + last_dir_vect[i] = block_data->dir_vect[i]; + } #endif - for (uint8_t i = STEPPER_COUNT; i != 0;) + for (uint8_t i = STEPPER_COUNT; i != 0;) + { + i--; + if (planner_data[planner_data_write].steps[i] != 0) { - i--; - if (planner_data[planner_data_write].steps[i] != 0) - { #ifdef ENABLE_LINACT_PLANNER - dir_vect[i] = inv_total_steps * (float)planner_data[planner_data_write].steps[i]; + dir_vect[i] = inv_total_steps * (float)planner_data[planner_data_write].steps[i]; - if (!planner_buffer_is_empty()) - { - cos_theta += last_dir_vect[i] * dir_vect[i]; + if (!planner_buffer_is_empty()) + { + cos_theta += last_dir_vect[i] * dir_vect[i]; #ifdef ENABLE_LINACT_COLD_START - if (last_dir_vect[i] == 0) //tests if actuator is starting from a full stop - { - coldstart = true; - } -#endif + if (last_dir_vect[i] == 0) //tests if actuator is starting from a full stop + { + coldstart = true; } - - last_dir_vect[i] = dir_vect[i]; #endif - //calculate (per linear actuator) the minimum inverted time of travel (1/min) an acceleration (1/s^2) - float step_ratio = g_settings.step_per_mm[i] / (float)planner_data[planner_data_write].steps[i]; - float stepper_feed = g_settings.max_feed_rate[i] * step_ratio; - rapid_feed = MIN(rapid_feed, stepper_feed); - float stepper_accel = g_settings.acceleration[i] * step_ratio; - planner_data[planner_data_write].acceleration = MIN(planner_data[planner_data_write].acceleration, stepper_accel); - } - else - { - last_dir_vect[i] = 0; } - } - - //converts to steps per second (st/s) - block_data->feed *= MIN_SEC_MULT; - rapid_feed *= MIN_SEC_MULT; - rapid_feed *= (float)block_data->total_steps; - //converts to steps per second^2 (st/s^2) - planner_data[planner_data_write].acceleration *= (float)block_data->total_steps; - if (block_data->feed > rapid_feed) + last_dir_vect[i] = dir_vect[i]; +#endif + //calculate (per linear actuator) the minimum inverted time of travel (1/min) an acceleration (1/s^2) + float step_ratio = g_settings.step_per_mm[i] / (float)planner_data[planner_data_write].steps[i]; + float stepper_feed = g_settings.max_feed_rate[i] * step_ratio; + rapid_feed = MIN(rapid_feed, stepper_feed); + float stepper_accel = g_settings.acceleration[i] * step_ratio; + planner_data[planner_data_write].acceleration = MIN(planner_data[planner_data_write].acceleration, stepper_accel); + } + else { - block_data->feed = rapid_feed; + last_dir_vect[i] = 0; } + } - planner_data[planner_data_write].feed_sqr = fast_flt_pow2(block_data->feed); - planner_data[planner_data_write].rapid_feed_sqr = fast_flt_pow2(rapid_feed); + //converts to steps per second (st/s) + block_data->feed *= MIN_SEC_MULT; + rapid_feed *= MIN_SEC_MULT; + rapid_feed *= (float)block_data->total_steps; + //converts to steps per second^2 (st/s^2) + planner_data[planner_data_write].acceleration *= (float)block_data->total_steps; - //consider initial angle factor of 1 (90 degree angle corner or more) - float angle_factor = 1.0f; - uint8_t prev = 0; + if (block_data->feed > rapid_feed) + { + block_data->feed = rapid_feed; + } - if (!planner_buffer_is_empty()) - { - prev = planner_buffer_prev(planner_data_write); //BUFFER_PTR(planner_buffer, prev_index); + planner_data[planner_data_write].feed_sqr = fast_flt_pow2(block_data->feed); + planner_data[planner_data_write].rapid_feed_sqr = fast_flt_pow2(rapid_feed); + + //consider initial angle factor of 1 (90 degree angle corner or more) + float angle_factor = 1.0f; + uint8_t prev = 0; + + if (!planner_buffer_is_empty()) + { + prev = planner_buffer_prev(planner_data_write); //BUFFER_PTR(planner_buffer, prev_index); #ifdef ENABLE_LINACT_COLD_START - if ((planner_data[prev].dirbits ^ planner_data[planner_data_write].dirbits)) - { - cos_theta = 0; - } -#endif - } - else + if ((planner_data[prev].dirbits ^ planner_data[planner_data_write].dirbits)) { cos_theta = 0; } +#endif + } + else + { + cos_theta = 0; + } - //if more than one move stored cals juntion speeds and recalculates speed profiles - if (cos_theta != 0 && !CHECKFLAG(block_data->motion_mode, PLANNER_MOTION_EXACT_STOP | MOTIONCONTROL_MODE_BACKLASH_COMPENSATION)) + //if more than one move stored cals juntion speeds and recalculates speed profiles + if (cos_theta != 0 && !CHECKFLAG(block_data->motion_mode, PLANNER_MOTION_EXACT_STOP | MOTIONCONTROL_MODE_BACKLASH_COMPENSATION)) + { + //calculates the junction angle with previous + if (cos_theta > 0) { - //calculates the junction angle with previous - if (cos_theta > 0) - { - //uses the half angle identity conversion to convert from cos(theta) to tan(theta/2) where: - // tan(theta/2) = sqrt((1-cos(theta)/(1+cos(theta)) - //to simplify the calculations it multiplies by sqrt((1+cos(theta)/(1+cos(theta)) - //transforming the equation to sqrt((1^2-cos(theta)^2))/(1+cos(theta)) - //this way the output will be between 0motion_mode, PLANNER_MOTION_CONTINUOUS)) ? 0 : g_settings.g64_angle_factor); - angle_factor = MAX(angle_factor - factor, 0); - angle_factor = MIN(angle_factor, 1); + //uses the half angle identity conversion to convert from cos(theta) to tan(theta/2) where: + // tan(theta/2) = sqrt((1-cos(theta)/(1+cos(theta)) + //to simplify the calculations it multiplies by sqrt((1+cos(theta)/(1+cos(theta)) + //transforming the equation to sqrt((1^2-cos(theta)^2))/(1+cos(theta)) + //this way the output will be between 0motion_mode, PLANNER_MOTION_CONTINUOUS)) ? 0 : g_settings.g64_angle_factor); + angle_factor = MAX(angle_factor - factor, 0); + angle_factor = MIN(angle_factor, 1); - //forces reaclculation with the new block - planner_recalculate(); + if (angle_factor < 1.0f) + { + float junc_feed_sqr = (1 - angle_factor); + junc_feed_sqr = fast_flt_pow2(junc_feed_sqr); + junc_feed_sqr *= planner_data[prev].feed_sqr; + //the maximum feed is the minimal feed between the previous feed given the angle and the current feed + planner_data[planner_data_write].entry_max_feed_sqr = MIN(planner_data[planner_data_write].feed_sqr, junc_feed_sqr); } + + //forces reaclculation with the new block + planner_recalculate(); } //advances the buffer @@ -365,7 +355,7 @@ extern "C" planner_coolant = 0; #endif //resyncs position with interpolator - planner_resync_position(); + planner_sync_position(); //forces motion control to resync postition after clearing the planner buffer mc_resync_position(); } @@ -538,11 +528,7 @@ extern "C" while (!planner_data[block].optimal && block != first) { float speedchange = ((float)(planner_data[block].total_steps << 1)) * planner_data[block].acceleration; - if (planner_data[block].dwell != 0) - { - planner_data[block].entry_feed_sqr = 0; - } - else if (planner_data[block].entry_feed_sqr != planner_data[block].entry_max_feed_sqr) + if (planner_data[block].entry_feed_sqr != planner_data[block].entry_max_feed_sqr) { speedchange = MIN(planner_data[block].entry_max_feed_sqr, speedchange); speedchange += (block != last) ? planner_data[next].entry_max_feed_sqr : 0; @@ -593,12 +579,22 @@ extern "C" memcpy(steps, planner_step_pos, sizeof(planner_step_pos)); } - void planner_resync_position(void) + void planner_sync_position(void) { //resyncs the position with the interpolator itp_get_rt_position(planner_step_pos); } + void planner_sync_tools(motion_data_t *block_data) + { +#ifdef USE_SPINDLE + planner_spindle = block_data->spindle; +#endif +#ifdef USE_COOLANT + planner_coolant = block_data->coolant; +#endif + } + //overrides void planner_toggle_overrides(void) { diff --git a/src/core/planner.h b/src/core/planner.h index 4734308a1..51af5d9b3 100644 --- a/src/core/planner.h +++ b/src/core/planner.h @@ -60,7 +60,6 @@ extern "C" #ifdef USE_COOLANT uint8_t coolant; #endif - uint16_t dwell; #ifdef ENABLE_BACKLASH_COMPENSATION bool backlash_comp; #endif @@ -88,7 +87,8 @@ extern "C" void planner_add_analog_output(uint8_t output, uint8_t value); void planner_add_digital_output(uint8_t output, uint8_t value); void planner_get_position(int32_t *steps); - void planner_resync_position(void); + void planner_sync_position(void); + void planner_sync_tools(motion_data_t *block_data); //overrides void planner_toggle_overrides(void); diff --git a/src/hal/mcus/mcu.h b/src/hal/mcus/mcu.h index ecf031160..30c1fc7d5 100644 --- a/src/hal/mcus/mcu.h +++ b/src/hal/mcus/mcu.h @@ -205,20 +205,6 @@ extern "C" * */ void mcu_dotasks(void); - /** - * generates a delay in ms. - * */ - static void mcu_delay_ms(uint32_t miliseconds) - { - uint32_t t_start = mcu_millis(); - uint32_t t_end = mcu_millis(); - while (t_end - t_start < miliseconds) - { - mcu_dotasks(); - t_end = mcu_millis(); - } - } - //Non volatile memory /** * gets a byte at the given EEPROM (or other non volatile memory) address of the MCU. diff --git a/src/hal/mcus/virtual/mcu_virtual.c b/src/hal/mcus/virtual/mcu_virtual.c index ae2656a91..3f4b46723 100644 --- a/src/hal/mcus/virtual/mcu_virtual.c +++ b/src/hal/mcus/virtual/mcu_virtual.c @@ -122,12 +122,11 @@ void *comsimul(void) { uart_char = c; while (!serial_rx_is_empty()) - { - } + { + } serial_rx_isr(c); if (c == '\n' | c == '\r') { - } } } @@ -148,21 +147,31 @@ void *comoutsimul(void) } } +//simulates internal clock (1Kz limited by windows timer) +volatile static uint32_t mcu_runtime = 0; + void *stepsimul(void) { static uint16_t tick_counter = 0; static uint16_t timer_counter = 0; unsigned long lasttime = getTickCounter(); - + unsigned long acumm = 0; while (1) { unsigned long time = getTickCounter(); unsigned long elapsed = time - lasttime; + acumm += elapsed; elapsed *= F_CPU; elapsed /= g_cpu_freq; elapsed = (elapsed < 100) ? elapsed : 100; + while (acumm > (F_CPU / 1000)) + { + acumm -= (F_CPU / 1000); + mcu_runtime++; + } + while (elapsed--) { if (pulse_interval && resetpulse_interval && pulse_enabled) @@ -222,8 +231,6 @@ void *stepsimul(void) } } -//simulates internal clock (1Kz limited by windows timer) -static uint32_t mcu_runtime = 0; void ticksimul(void) { @@ -279,7 +286,7 @@ void mcu_init(void) } } g_cpu_freq = getCPUFreq(); - start_timer(1, &ticksimul); + //start_timer(1, &ticksimul); pthread_create(&thread_id, NULL, &comsimul, NULL); #ifdef USECONSOLE pthread_create(&thread_idout, NULL, &comoutsimul, NULL); diff --git a/src/hal/mcus/virtual/mcumap_virtual.h b/src/hal/mcus/virtual/mcumap_virtual.h index 68bf4ae7e..0c1ef1403 100644 --- a/src/hal/mcus/virtual/mcumap_virtual.h +++ b/src/hal/mcus/virtual/mcumap_virtual.h @@ -94,6 +94,4 @@ extern virtports_t virtualports; #define mcu_tx_ready() true #define mcu_rx_ready() true -#define mcu_delay_ms(x) delay(x) - #endif From 3ca371cfba0c0a74cbb91737ad3212e4b31484bb Mon Sep 17 00:00:00 2001 From: Paciente8159 Date: Tue, 3 Aug 2021 18:00:31 +0100 Subject: [PATCH 03/24] internal execution modes modified -internal execution modes modified -no home state removed -resuming state added -fixed hold and jog state changes --- src/cnc.c | 27 +++++++++++++++------------ src/cnc.h | 25 ++++++++++++------------- src/core/interpolator.c | 2 +- src/core/io_control.c | 2 +- src/core/parser.c | 4 ++-- src/interface/protocol.c | 2 +- 6 files changed, 32 insertions(+), 30 deletions(-) diff --git a/src/cnc.c b/src/cnc.c index 87ee0136f..61ae0b81c 100644 --- a/src/cnc.c +++ b/src/cnc.c @@ -111,7 +111,7 @@ extern "C" cnc_clear_exec_state(EXEC_ABORT); //clears the abort flag serial_flush(); - if (cnc_get_exec_state(EXEC_ALARM_ABORT)) //checks if any alarm is active (except NOHOME - ignore it) + if (cnc_get_exec_state(EXEC_ALARM)) //checks if any alarm is active (except NOHOME - ignore it) { cnc_check_fault_systems(); protocol_send_feedback(MSG_FEEDBACK_1); @@ -293,7 +293,7 @@ extern "C" //halt is active and was running flags it lost home position if (cnc_get_exec_state(EXEC_RUN) && g_settings.homing_enabled) { - cnc_set_exec_state(EXEC_NOHOME); + cnc_set_exec_state(EXEC_LIMITS); } itp_stop(); //stop tools @@ -308,10 +308,11 @@ extern "C" void cnc_unlock(void) { //on unlock any alarm caused by not having homing reference or hitting a limit switch is reset at user request + //this must be done directly beacuse cnc_clear_exec_state will check the limit switch state //all other alarm flags remain active if any input is still active - CLEARFLAG(cnc_state.exec_state, EXEC_NOHOME | EXEC_LIMITS); + CLEARFLAG(cnc_state.exec_state, EXEC_LIMITS); //clears all other locking flags - cnc_clear_exec_state(EXEC_GCODE_LOCKED); + cnc_clear_exec_state(EXEC_GCODE_LOCKED | EXEC_HOLD); //signals stepper enable pins io_set_steps(g_settings.step_invert_mask); @@ -350,24 +351,26 @@ extern "C" CLEARFLAG(statemask, EXEC_HOLD); } #endif + + uint8_t limits = 0; #if (LIMITS_MASK != 0) - if (g_settings.hard_limits_enabled && io_get_limits()) //can't clear the EXEC_LIMITS is any limit is triggered - { - CLEARFLAG(statemask, EXEC_LIMITS); - } + limits = io_get_limits(); //can't clear the EXEC_LIMITS is any limit is triggered #endif - if (g_settings.homing_enabled) //if the machine doesn't know the homing position and homing is enabled + if (g_settings.homing_enabled && limits) //if the machine doesn't know the homing position and homing is enabled { - CLEARFLAG(statemask, EXEC_NOHOME); + CLEARFLAG(statemask, EXEC_LIMITS); } if (CHECKFLAG(statemask, EXEC_HOLD)) { + SETFLAG(cnc_state.exec_state, EXEC_RESUMING); + CLEARFLAG(cnc_state.exec_state, EXEC_HOLD); itp_sync_spindle(); if (!planner_buffer_is_empty()) { cnc_delay_ms(DELAY_ON_RESUME * 1000); } + CLEARFLAG(cnc_state.exec_state, EXEC_RESUMING); } CLEARFLAG(cnc_state.exec_state, statemask); } @@ -663,10 +666,10 @@ extern "C" } //clears EXEC_JOG if not step ISR is stopped and planner has no more moves - if (CHECKFLAG(cnc_state.exec_state, EXEC_JOG) && !CHECKFLAG(cnc_state.exec_state, EXEC_RUN) && planner_buffer_is_empty()) + /*if (CHECKFLAG(cnc_state.exec_state, EXEC_JOG) && !CHECKFLAG(cnc_state.exec_state, EXEC_RUN) && planner_buffer_is_empty()) { CLEARFLAG(cnc_state.exec_state, EXEC_JOG); - } + }*/ return true; } diff --git a/src/cnc.h b/src/cnc.h index b0260b92f..627a7bd31 100644 --- a/src/cnc.h +++ b/src/cnc.h @@ -53,19 +53,18 @@ extern "C" #define RT_CMD_COOL_MST_TOGGLE 128 //current cnc states (multiple can be active/overlapped at the same time) -#define EXEC_IDLE 0 // All flags cleared -#define EXEC_RUN 1 // Motions are being executed -#define EXEC_HOLD 2 // Feed hold is active -#define EXEC_JOG 4 // Jogging in execution -#define EXEC_HOMING 8 // Homing in execution -#define EXEC_NOHOME 16 //Homing enable but home position is unkowned -#define EXEC_LIMITS 32 //Limit switch is active -#define EXEC_DOOR 64 //Safety door open -#define EXEC_ABORT 128 //Emergency stop -#define EXEC_ALARM (EXEC_NOHOME | EXEC_LIMITS | EXEC_DOOR | EXEC_ABORT) //System alarms -#define EXEC_ALARM_ABORT (EXEC_LIMITS | EXEC_DOOR | EXEC_ABORT) //System alarms checked after abort -#define EXEC_GCODE_LOCKED (EXEC_ALARM | EXEC_HOMING | EXEC_JOG) //Gcode is locked by an alarm or any special motion state -#define EXEC_ALLACTIVE 255 //All states +#define EXEC_IDLE 0 // All flags cleared +#define EXEC_RUN 1 // Motions are being executed +#define EXEC_RESUMING 2 // Motions are being resumed from a hold +#define EXEC_HOLD 4 // Feed hold is active +#define EXEC_JOG 8 // Jogging in execution +#define EXEC_HOMING 16 // Homing in execution +#define EXEC_LIMITS 32 // Limit switch is active or position lost +#define EXEC_DOOR 64 // Safety door open +#define EXEC_ABORT 128 // Emergency stop +#define EXEC_ALARM (EXEC_LIMITS | EXEC_DOOR | EXEC_ABORT) // System alarms +#define EXEC_GCODE_LOCKED (EXEC_ALARM | EXEC_HOMING | EXEC_JOG) // Gcode is locked by an alarm or any special motion state +#define EXEC_ALLACTIVE 255 // All states //creates a set of helper masks used to configure the controller #define ESTOP_MASK 1 diff --git a/src/core/interpolator.c b/src/core/interpolator.c index 54a906c9c..e208aa67d 100644 --- a/src/core/interpolator.c +++ b/src/core/interpolator.c @@ -510,7 +510,7 @@ extern "C" #endif //starts the step isr if is stopped and there are segments to execute - if (!cnc_get_exec_state(EXEC_HOLD | EXEC_ALARM | EXEC_RUN) && itp_sgm_data_segments) //exec state is not hold or alarm and not already running + if (!cnc_get_exec_state(EXEC_HOLD | EXEC_ALARM | EXEC_RUN | EXEC_RESUMING) && itp_sgm_data_segments) //exec state is not hold or alarm and not already running { cnc_set_exec_state(EXEC_RUN); //flags that it started running mcu_start_itp_isr(itp_sgm_data[itp_sgm_data_read].timer_counter, itp_sgm_data[itp_sgm_data_read].timer_prescaller); diff --git a/src/core/io_control.c b/src/core/io_control.c index 3fc19b9e8..77c53047d 100644 --- a/src/core/io_control.c +++ b/src/core/io_control.c @@ -49,7 +49,7 @@ extern "C" { if (g_settings.homing_enabled) { - cnc_set_exec_state(EXEC_NOHOME); //if motions was executing flags home position lost + cnc_set_exec_state(EXEC_LIMITS); //if motions was executing flags home position lost } cnc_alarm(EXEC_ALARM_HARD_LIMIT); diff --git a/src/core/parser.c b/src/core/parser.c index 5086b3d3d..544c23851 100644 --- a/src/core/parser.c +++ b/src/core/parser.c @@ -312,12 +312,12 @@ extern "C" if (error == GRBL_JOG_CMD) { - if (cnc_get_exec_state(EXEC_GCODE_LOCKED & ~EXEC_JOG)) + if (cnc_get_exec_state(~EXEC_JOG)) { return STATUS_SYSTEM_GC_LOCK; } } - else if (cnc_get_exec_state(EXEC_GCODE_LOCKED)) + else if (cnc_get_exec_state(~EXEC_RUN)) { return STATUS_SYSTEM_GC_LOCK; } diff --git a/src/interface/protocol.c b/src/interface/protocol.c index 375be86aa..07504a8dc 100644 --- a/src/interface/protocol.c +++ b/src/interface/protocol.c @@ -207,7 +207,6 @@ extern "C" } break; case EXEC_LIMITS: - case EXEC_NOHOME: serial_print_str(__romstr__("Alarm")); break; case EXEC_HOLD: @@ -227,6 +226,7 @@ extern "C" case EXEC_JOG: serial_print_str(__romstr__("Jog")); break; + case EXEC_RESUMING: case EXEC_RUN: serial_print_str(__romstr__("Run")); break; From 848a45680e7813c8c142612e61b54deb7e8102cc Mon Sep 17 00:00:00 2001 From: Paciente8159 Date: Wed, 4 Aug 2021 00:11:37 +0100 Subject: [PATCH 04/24] internal alarms tweak -internal alarms renaming and reworking -reviewed interlocking to reduce code size -reviewed alarm code flow --- src/cnc.c | 72 ++++++++++++++++++++-------------- src/cnc.h | 4 +- src/core/io_control.c | 2 +- src/core/motion_control.c | 4 +- src/interface/grbl_interface.h | 5 ++- src/interface/protocol.c | 2 +- 6 files changed, 52 insertions(+), 37 deletions(-) diff --git a/src/cnc.c b/src/cnc.c index 61ae0b81c..01735d3ff 100644 --- a/src/cnc.c +++ b/src/cnc.c @@ -42,7 +42,7 @@ extern "C" { //uint8_t system_state; //signals if CNC is system_state and gcode can run volatile uint8_t exec_state; - uint8_t active_alarm; + uint8_t loop_state; volatile uint8_t rt_cmd; volatile uint8_t feed_ovr_cmd; volatile uint8_t tool_ovr_cmd; @@ -53,7 +53,7 @@ extern "C" static void cnc_check_fault_systems(); static bool cnc_check_interlocking(); static void cnc_exec_rt_commands(); - static void cnc_reset(); + FORCEINLINE static void cnc_reset(); void cnc_init(void) { @@ -61,7 +61,7 @@ extern "C" #ifdef FORCE_GLOBALS_TO_0 memset(&cnc_state, 0, sizeof(cnc_state_t)); #endif - cnc_state.active_alarm = EXEC_ALARM_STARTUP; + cnc_state.loop_state = LOOP_STARTUP; //initializes all systems mcu_init(); //mcu mcu_disable_probe_isr(); //forces probe isr disabling @@ -109,7 +109,9 @@ extern "C" } } while (cnc_dotasks()); - cnc_clear_exec_state(EXEC_ABORT); //clears the abort flag + cnc_state.loop_state = LOOP_ERROR_RESET; + + cnc_clear_exec_state(EXEC_KILL); //clears the kill flag serial_flush(); if (cnc_get_exec_state(EXEC_ALARM)) //checks if any alarm is active (except NOHOME - ignore it) { @@ -117,7 +119,7 @@ extern "C" protocol_send_feedback(MSG_FEEDBACK_1); do { - mcu_dotasks(); + cnc_dotasks(); } while (!CHECKFLAG(cnc_state.rt_cmd, RT_CMD_ABORT)); } } @@ -125,13 +127,21 @@ extern "C" void cnc_call_rt_command(uint8_t command) { //executes the realtime commands + //only reset command is executed right away //control commands affect the exec_state directly (Abort, hold, safety door, cycle_start) + //the effects are then propagate in the cnc_dotasks switch (command) { case CMD_CODE_RESET: - cnc_stop(); - serial_rx_clear(); //dumps all commands - cnc_alarm(EXEC_ALARM_RESET); //abort state is activated through cnc_alarm + if (cnc_get_exec_state(EXEC_RUN)) + { + cnc_alarm(EXEC_ALARM_ABORT_CYCLE); + } + else + { + cnc_alarm(EXEC_ALARM_RESET); + } + serial_rx_clear(); //dumps all commands SETFLAG(cnc_state.rt_cmd, RT_CMD_ABORT); break; case CMD_CODE_FEED_HOLD: @@ -210,7 +220,7 @@ extern "C" mcu_dotasks(); //let µCNC finnish startup/reset code - if (cnc_state.active_alarm == EXEC_ALARM_STARTUP) + if (cnc_state.loop_state == LOOP_STARTUP) { return; } @@ -227,7 +237,7 @@ extern "C" //check security interlocking for any problem if (!cnc_check_interlocking()) { - return !cnc_get_exec_state(EXEC_ABORT); + return !cnc_get_exec_state(EXEC_KILL); } if (!lock_itp) @@ -237,7 +247,7 @@ extern "C" lock_itp = false; } - return !cnc_get_exec_state(EXEC_ABORT); + return !cnc_get_exec_state(EXEC_KILL); } void cnc_home(void) @@ -284,8 +294,12 @@ extern "C" void cnc_alarm(uint8_t code) { - cnc_set_exec_state(EXEC_ABORT); - cnc_state.active_alarm = code; + cnc_set_exec_state(EXEC_KILL); + cnc_stop(); + if (code) + { + protocol_send_alarm(code); + } } void cnc_stop(void) @@ -333,10 +347,11 @@ extern "C" void cnc_clear_exec_state(uint8_t statemask) { uint8_t controls = io_get_controls(); + #ifdef ESTOP if (CHECKFLAG(controls, ESTOP_MASK)) //can't clear the alarm flag if ESTOP is active { - CLEARFLAG(statemask, EXEC_ABORT); + CLEARFLAG(statemask, EXEC_KILL); } #endif #ifdef SAFETY_DOOR @@ -387,7 +402,7 @@ extern "C" void cnc_reset(void) { - cnc_state.active_alarm = EXEC_ALARM_STARTUP; + cnc_state.loop_state = LOOP_STARTUP; //resets all realtime command flags cnc_state.rt_cmd = RT_CMD_CLEAR; cnc_state.feed_ovr_cmd = RT_CMD_CLEAR; @@ -399,7 +414,7 @@ extern "C" planner_clear(); protocol_send_string(MSG_STARTUP); - cnc_state.active_alarm = EXEC_ALARM_RESET; + cnc_state.loop_state = LOOP_RUNNING; //tries to clear alarms or any active hold state cnc_clear_exec_state(EXEC_ALARM | EXEC_HOLD); @@ -407,7 +422,7 @@ extern "C" if (cnc_get_exec_state(EXEC_ALARM)) { //cnc_check_fault_systems(); - if (!cnc_get_exec_state(EXEC_ABORT)) + if (!cnc_get_exec_state(EXEC_KILL)) { protocol_send_feedback(MSG_FEEDBACK_2); } @@ -616,19 +631,14 @@ extern "C" bool cnc_check_interlocking(void) { //if abort is flagged - if (CHECKFLAG(cnc_state.exec_state, EXEC_ABORT)) + if (CHECKFLAG(cnc_state.exec_state, EXEC_KILL)) { - if (cnc_state.active_alarm) //active alarm message - { - protocol_send_alarm(cnc_state.active_alarm); - cnc_state.active_alarm = 0; - return false; - } return false; } if (CHECKFLAG(cnc_state.exec_state, EXEC_DOOR | EXEC_HOLD)) { + //machine is still running after hold/security door if (CHECKFLAG(cnc_state.exec_state, EXEC_RUN)) { return true; @@ -637,12 +647,14 @@ extern "C" itp_stop(); if (CHECKFLAG(cnc_state.exec_state, EXEC_DOOR)) { - cnc_stop(); //stop all tools not only motion - } - - if (CHECKFLAG(cnc_state.exec_state, EXEC_HOMING) && CHECKFLAG(cnc_state.exec_state, EXEC_DOOR)) //door opened during a homing cycle - { - cnc_alarm(EXEC_ALARM_HOMING_FAIL_DOOR); + if (CHECKFLAG(cnc_state.exec_state, EXEC_HOMING)) //door opened during a homing cycle + { + cnc_alarm(EXEC_ALARM_HOMING_FAIL_DOOR); + } + else + { + cnc_stop(); //stop all tools not only motion + } } if (CHECKFLAG(cnc_state.exec_state, EXEC_HOMING | EXEC_JOG)) //flushes the buffers if motions was homing or jog diff --git a/src/cnc.h b/src/cnc.h index 627a7bd31..792d801eb 100644 --- a/src/cnc.h +++ b/src/cnc.h @@ -61,8 +61,8 @@ extern "C" #define EXEC_HOMING 16 // Homing in execution #define EXEC_LIMITS 32 // Limit switch is active or position lost #define EXEC_DOOR 64 // Safety door open -#define EXEC_ABORT 128 // Emergency stop -#define EXEC_ALARM (EXEC_LIMITS | EXEC_DOOR | EXEC_ABORT) // System alarms +#define EXEC_KILL 128 // Emergency stop +#define EXEC_ALARM (EXEC_LIMITS | EXEC_DOOR | EXEC_KILL) // System alarms #define EXEC_GCODE_LOCKED (EXEC_ALARM | EXEC_HOMING | EXEC_JOG) // Gcode is locked by an alarm or any special motion state #define EXEC_ALLACTIVE 255 // All states diff --git a/src/core/io_control.c b/src/core/io_control.c index 77c53047d..d8779992c 100644 --- a/src/core/io_control.c +++ b/src/core/io_control.c @@ -47,7 +47,7 @@ extern "C" { if (!cnc_get_exec_state(EXEC_HOMING)) //if not in a homing motion triggers an alarm { - if (g_settings.homing_enabled) + if (g_settings.hard_limits_enabled) { cnc_set_exec_state(EXEC_LIMITS); //if motions was executing flags home position lost } diff --git a/src/core/motion_control.c b/src/core/motion_control.c index 4773c6951..25a6ed3bf 100644 --- a/src/core/motion_control.c +++ b/src/core/motion_control.c @@ -547,7 +547,7 @@ extern "C" itp_clear(); planner_clear(); - if (cnc_get_exec_state(EXEC_ABORT)) + if (cnc_get_exec_state(EXEC_KILL)) { return EXEC_ALARM_HOMING_FAIL_RESET; } @@ -602,7 +602,7 @@ extern "C" itp_clear(); planner_clear(); - if (cnc_get_exec_state(EXEC_ABORT)) + if (cnc_get_exec_state(EXEC_KILL)) { return EXEC_ALARM_HOMING_FAIL_RESET; } diff --git a/src/interface/grbl_interface.h b/src/interface/grbl_interface.h index 0ddd1af48..b44a428e1 100644 --- a/src/interface/grbl_interface.h +++ b/src/interface/grbl_interface.h @@ -111,6 +111,10 @@ extern "C" #define GRBL_HELP (GRBL_SYSTEM_CMD + 8) #define GRBL_JOG_CMD (GRBL_SYSTEM_CMD + 9) +#define LOOP_STARTUP 0 +#define LOOP_RUNNING 1 +#define LOOP_ERROR_RESET 2 + #define EXEC_ALARM_RESET 0 // Grbl alarm codes. Valid values (1-255). Zero is reserved. #define EXEC_ALARM_HARD_LIMIT 1 @@ -124,7 +128,6 @@ extern "C" #define EXEC_ALARM_HOMING_FAIL_APPROACH 9 #define EXEC_ALARM_HOMING_FAIL_DUAL_APPROACH 10 #define EXEC_ALARM_HOMING_FAIL_LIMIT_ACTIVE 11 -#define EXEC_ALARM_STARTUP 255 //this is a special alarm that signals µCNC is starting up. It's not a real alarm. //formated messages #define STR_EOL "\r\n" diff --git a/src/interface/protocol.c b/src/interface/protocol.c index 07504a8dc..fc47533c7 100644 --- a/src/interface/protocol.c +++ b/src/interface/protocol.c @@ -177,7 +177,7 @@ extern "C" { switch (state) { - case EXEC_ABORT: + case EXEC_KILL: serial_print_str(__romstr__("Abort")); break; case EXEC_DOOR: From d39ba0812b29ccda566f481cd3e275d58af156b8 Mon Sep 17 00:00:00 2001 From: Paciente8159 Date: Wed, 4 Aug 2021 01:12:05 +0100 Subject: [PATCH 05/24] improved reset loop -modified reset loop condition checking. If kill condition is not enforced (emergency stop), allows reset. -replaced Abort (non Grbl) state by Alarm (Grbl) to improve software compatibility -fixed limit switch condition checking before clear -moved some ROM strings to grbl_inferface file --- src/cnc.c | 9 +++------ src/interface/grbl_interface.h | 18 ++++++++++++++++++ src/interface/protocol.c | 34 +++++++++++++++++----------------- 3 files changed, 38 insertions(+), 23 deletions(-) diff --git a/src/cnc.c b/src/cnc.c index 01735d3ff..1e749acf0 100644 --- a/src/cnc.c +++ b/src/cnc.c @@ -111,7 +111,6 @@ extern "C" cnc_state.loop_state = LOOP_ERROR_RESET; - cnc_clear_exec_state(EXEC_KILL); //clears the kill flag serial_flush(); if (cnc_get_exec_state(EXEC_ALARM)) //checks if any alarm is active (except NOHOME - ignore it) { @@ -119,8 +118,8 @@ extern "C" protocol_send_feedback(MSG_FEEDBACK_1); do { - cnc_dotasks(); - } while (!CHECKFLAG(cnc_state.rt_cmd, RT_CMD_ABORT)); + cnc_clear_exec_state(EXEC_KILL); //tries to clear the kill flag if possible + } while (!cnc_dotasks()); } } @@ -288,8 +287,6 @@ extern "C" //reset position itp_reset_rt_position(); planner_sync_position(); - //invokes startup block execution - SETFLAG(cnc_state.rt_cmd, RT_CMD_STARTUP_BLOCK0); } void cnc_alarm(uint8_t code) @@ -371,7 +368,7 @@ extern "C" #if (LIMITS_MASK != 0) limits = io_get_limits(); //can't clear the EXEC_LIMITS is any limit is triggered #endif - if (g_settings.homing_enabled && limits) //if the machine doesn't know the homing position and homing is enabled + if (g_settings.hard_limits_enabled && limits) //if hardlimits are enabled and limits are triggered { CLEARFLAG(statemask, EXEC_LIMITS); } diff --git a/src/interface/grbl_interface.h b/src/interface/grbl_interface.h index b44a428e1..36291eb5d 100644 --- a/src/interface/grbl_interface.h +++ b/src/interface/grbl_interface.h @@ -164,6 +164,24 @@ extern "C" /*NEW*/ #define MSG_FEEDBACK_12 __romstr__("Check Emergency stop") +#define MSG_STATUS_ALARM __romstr__("Alarm") +#define MSG_STATUS_DOOR __romstr__("Door:") +#define MSG_STATUS_HOLD __romstr__("Hold:") +#define MSG_STATUS_HOME __romstr__("Home") +#define MSG_STATUS_JOG __romstr__("Jog") +#define MSG_STATUS_RUN __romstr__("Run") +#define MSG_STATUS_IDLE __romstr__("Idle") +#define MSG_STATUS_CHECK __romstr__("Check") + +#define MSG_STATUS_MPOS __romstr__("|MPos:") +#define MSG_STATUS_FS __romstr__("|FS:") +#define MSG_STATUS_F __romstr__("|F:") +#define MSG_STATUS_WCO __romstr__("|WCO:") +#define MSG_STATUS_OVR __romstr__("|Ov:") +#define MSG_STATUS_TOOL __romstr__("|A:") +#define MSG_STATUS_LINE __romstr__("|Ln:") +#define MSG_STATUS_PIN __romstr__("|Pn:") + //#define MSG_INT "%d" //#define MSG_FLT "%0.3f" //#define MSG_FLT_IMPERIAL "%0.5f" diff --git a/src/interface/protocol.c b/src/interface/protocol.c index fc47533c7..63f59d073 100644 --- a/src/interface/protocol.c +++ b/src/interface/protocol.c @@ -108,7 +108,7 @@ extern "C" float axis[MAX(AXIS_COUNT, 3)]; if (parser_get_wco(axis)) { - serial_print_str(__romstr__("|WCO:")); + serial_print_str(MSG_STATUS_WCO); serial_print_fltarr(axis, AXIS_COUNT); return; } @@ -116,7 +116,7 @@ extern "C" uint8_t ovr[3]; if (planner_get_overflows(ovr)) { - serial_print_str(__romstr__("|Ov:")); + serial_print_str(MSG_STATUS_OVR); serial_print_int(ovr[0]); serial_putc(','); serial_print_int(ovr[1]); @@ -125,7 +125,7 @@ extern "C" uint8_t tools = protocol_get_tools(); if (tools) { - serial_print_str(__romstr__("|A:")); + serial_print_str(MSG_STATUS_TOOL); if (CHECKFLAG(tools, 4)) { serial_putc('S'); @@ -178,10 +178,10 @@ extern "C" switch (state) { case EXEC_KILL: - serial_print_str(__romstr__("Abort")); + serial_print_str(MSG_STATUS_ALARM); break; case EXEC_DOOR: - serial_print_str(__romstr__("Door:")); + serial_print_str(MSG_STATUS_DOOR); if (CHECKFLAG(controls, SAFETY_DOOR_MASK)) { @@ -207,10 +207,10 @@ extern "C" } break; case EXEC_LIMITS: - serial_print_str(__romstr__("Alarm")); + serial_print_str(MSG_STATUS_ALARM); break; case EXEC_HOLD: - serial_print_str(__romstr__("Hold:")); + serial_print_str(MSG_STATUS_HOLD); if (cnc_get_exec_state(EXEC_RUN)) { serial_putc('1'); @@ -221,32 +221,32 @@ extern "C" } break; case EXEC_HOMING: - serial_print_str(__romstr__("Home")); + serial_print_str(MSG_STATUS_HOME); break; case EXEC_JOG: - serial_print_str(__romstr__("Jog")); + serial_print_str(MSG_STATUS_JOG); break; case EXEC_RESUMING: case EXEC_RUN: - serial_print_str(__romstr__("Run")); + serial_print_str(MSG_STATUS_RUN); break; default: - serial_print_str(__romstr__("Idle")); + serial_print_str(MSG_STATUS_IDLE); break; } } else { - serial_print_str(__romstr__("Check")); + serial_print_str(MSG_STATUS_CHECK); } - serial_print_str(__romstr__("|MPos:")); + serial_print_str(MSG_STATUS_MPOS); serial_print_fltarr(axis, AXIS_COUNT); #ifdef USE_SPINDLE - serial_print_str(__romstr__("|FS:")); + serial_print_str(MSG_STATUS_FS); #else - serial_print_str(__romstr__("|F:")); + serial_print_str(MSG_STATUS_F); #endif serial_print_int((uint16_t)feed); #ifdef USE_SPINDLE @@ -255,13 +255,13 @@ extern "C" #endif #ifdef GCODE_PROCESS_LINE_NUMBERS - serial_print_str(__romstr__("|Ln:")); + serial_print_str(MSG_STATUS_LINE); serial_print_long(itp_get_rt_line_number()); #endif if (CHECKFLAG(controls, (ESTOP_MASK | SAFETY_DOOR_MASK | FHOLD_MASK)) | CHECKFLAG(limits, LIMITS_MASK)) { - serial_print_str(__romstr__("|Pn:")); + serial_print_str(MSG_STATUS_PIN); if (CHECKFLAG(controls, ESTOP_MASK)) { From 950b4cfdafee7aa876dbc0e23ae4dc9575a464d2 Mon Sep 17 00:00:00 2001 From: Paciente8159 Date: Wed, 4 Aug 2021 01:26:32 +0100 Subject: [PATCH 06/24] fixed execution state checking while parsing gcode -fixed execution state checking while parsing gcode that was throwing errors on HOLD state --- src/cnc.c | 2 +- src/core/parser.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cnc.c b/src/cnc.c index 1e749acf0..52cf3968a 100644 --- a/src/cnc.c +++ b/src/cnc.c @@ -112,7 +112,7 @@ extern "C" cnc_state.loop_state = LOOP_ERROR_RESET; serial_flush(); - if (cnc_get_exec_state(EXEC_ALARM)) //checks if any alarm is active (except NOHOME - ignore it) + if (cnc_get_exec_state(EXEC_ALARM)) //checks if any alarm is active { cnc_check_fault_systems(); protocol_send_feedback(MSG_FEEDBACK_1); diff --git a/src/core/parser.c b/src/core/parser.c index 544c23851..0293e82c2 100644 --- a/src/core/parser.c +++ b/src/core/parser.c @@ -317,7 +317,7 @@ extern "C" return STATUS_SYSTEM_GC_LOCK; } } - else if (cnc_get_exec_state(~EXEC_RUN)) + else if (cnc_get_exec_state(~(EXEC_RUN | EXEC_HOLD | EXEC_RESUMING))) { return STATUS_SYSTEM_GC_LOCK; } From 66a71cab11d98a7361436ead9e8d6759967fb7e6 Mon Sep 17 00:00:00 2001 From: Paciente8159 Date: Wed, 4 Aug 2021 10:14:21 +0100 Subject: [PATCH 07/24] fixed startup messages format -fixed startup messages format by blocking status reports until startup blocks are sent --- src/cnc.c | 16 +++++++++++----- src/interface/grbl_interface.h | 5 ----- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/cnc.c b/src/cnc.c index 52cf3968a..ebfaaf3a0 100644 --- a/src/cnc.c +++ b/src/cnc.c @@ -38,6 +38,11 @@ extern "C" #include "modules/encoder.h" #include "modules/pid_controller.h" +#define LOOP_STARTUP_RESET 0 +#define LOOP_STARTUP_BLOCKS 1 +#define LOOP_RUNNING 2 +#define LOOP_ERROR_RESET 3 + typedef struct { //uint8_t system_state; //signals if CNC is system_state and gcode can run @@ -61,7 +66,7 @@ extern "C" #ifdef FORCE_GLOBALS_TO_0 memset(&cnc_state, 0, sizeof(cnc_state_t)); #endif - cnc_state.loop_state = LOOP_STARTUP; + cnc_state.loop_state = LOOP_STARTUP_RESET; //initializes all systems mcu_init(); //mcu mcu_disable_probe_isr(); //forces probe isr disabling @@ -219,7 +224,7 @@ extern "C" mcu_dotasks(); //let µCNC finnish startup/reset code - if (cnc_state.loop_state == LOOP_STARTUP) + if (cnc_state.loop_state == LOOP_STARTUP_RESET) { return; } @@ -399,7 +404,7 @@ extern "C" void cnc_reset(void) { - cnc_state.loop_state = LOOP_STARTUP; + 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; @@ -411,7 +416,7 @@ extern "C" planner_clear(); protocol_send_string(MSG_STARTUP); - cnc_state.loop_state = LOOP_RUNNING; + cnc_state.loop_state = LOOP_STARTUP_BLOCKS; //tries to clear alarms or any active hold state cnc_clear_exec_state(EXEC_ALARM | EXEC_HOLD); @@ -451,7 +456,7 @@ extern "C" switch (command & cmd_mask) { case RT_CMD_REPORT: - if (!protocol_is_busy()) + if (!protocol_is_busy() && cnc_state.loop_state >= LOOP_RUNNING) { protocol_send_status(); CLEARFLAG(cnc_state.rt_cmd, RT_CMD_REPORT); //if a report request is sent, clear the respective flag @@ -472,6 +477,7 @@ extern "C" if (settings_check_startup_gcode(STARTUP_BLOCK1_ADDRESS_OFFSET)) //loads command 1 { serial_select(SERIAL_N1); + cnc_state.loop_state = LOOP_RUNNING; } break; } diff --git a/src/interface/grbl_interface.h b/src/interface/grbl_interface.h index 36291eb5d..90687c70c 100644 --- a/src/interface/grbl_interface.h +++ b/src/interface/grbl_interface.h @@ -111,10 +111,6 @@ extern "C" #define GRBL_HELP (GRBL_SYSTEM_CMD + 8) #define GRBL_JOG_CMD (GRBL_SYSTEM_CMD + 9) -#define LOOP_STARTUP 0 -#define LOOP_RUNNING 1 -#define LOOP_ERROR_RESET 2 - #define EXEC_ALARM_RESET 0 // Grbl alarm codes. Valid values (1-255). Zero is reserved. #define EXEC_ALARM_HARD_LIMIT 1 @@ -150,7 +146,6 @@ extern "C" #define MSG_START __romstr__("[MSG:") #define MSG_END __romstr__("]" STR_EOL) #define MSG_FEEDBACK_1 __romstr__("Reset to continue") -#define MSG_FEEDBACK_1 __romstr__("Reset to continue") #define MSG_FEEDBACK_2 __romstr__("'$H'|'$X' to unlock") #define MSG_FEEDBACK_3 __romstr__("Caution: Unlocked") #define MSG_FEEDBACK_4 __romstr__("Enabled") From 38cc71d6fe2dbde0df630d15d5e9d0835af2f2b3 Mon Sep 17 00:00:00 2001 From: Paciente8159 Date: Wed, 4 Aug 2021 12:22:20 +0100 Subject: [PATCH 08/24] fixed report in inches -fixed report output in inch mode -fixed step rate settings print value -dropped integer print in 16bit and used only 32bit version --- src/core/parser.c | 12 ++++---- src/core/utils.h | 7 +++-- src/interface/protocol.c | 6 ++-- src/interface/serial.c | 61 ++++++++-------------------------------- src/interface/serial.h | 6 ++-- 5 files changed, 26 insertions(+), 66 deletions(-) diff --git a/src/core/parser.c b/src/core/parser.c index 0293e82c2..877cc4c40 100644 --- a/src/core/parser.c +++ b/src/core/parser.c @@ -1109,26 +1109,26 @@ extern "C" for (uint8_t i = AXIS_COUNT; i != 0;) { i--; - words->xyzabc[i] *= 25.4f; + words->xyzabc[i] *= INCH_MM_MULT; } //check if any i, j or k words were used if (CHECKFLAG(cmd->words, GCODE_IJK_AXIS)) { - words->ijk[0] *= 25.4f; - words->ijk[1] *= 25.4f; - words->ijk[2] *= 25.4f; + words->ijk[0] *= INCH_MM_MULT; + words->ijk[1] *= INCH_MM_MULT; + words->ijk[2] *= INCH_MM_MULT; } //if normal feed mode convert to mm/s if (CHECKFLAG(cmd->words, GCODE_WORD_F) && (new_state->groups.feedrate_mode != G93)) { - new_state->feedrate *= 25.4f; + new_state->feedrate *= INCH_MM_MULT; } if (CHECKFLAG(cmd->words, GCODE_WORD_R)) { - words->r *= 25.4f; + words->r *= INCH_MM_MULT; } } diff --git a/src/core/utils.h b/src/core/utils.h index 8c8b8cb44..a017a9761 100644 --- a/src/core/utils.h +++ b/src/core/utils.h @@ -165,9 +165,10 @@ extern "C" #endif #endif -#define MM_INCH_MULT 0.0393700787401574803 -#define MIN_SEC_MULT 0.0166666666666666667 -#define UINT8_MAX_INV 0.0039215686274509804 +#define MM_INCH_MULT 0.0393700787401574803f +#define INCH_MM_MULT 25.4f +#define MIN_SEC_MULT 0.0166666666666666667f +#define UINT8_MAX_INV 0.0039215686274509804f #define FORCEINLINE __attribute__((always_inline)) inline diff --git a/src/interface/protocol.c b/src/interface/protocol.c index 63f59d073..b73471964 100644 --- a/src/interface/protocol.c +++ b/src/interface/protocol.c @@ -248,7 +248,7 @@ extern "C" #else serial_print_str(MSG_STATUS_F); #endif - serial_print_int((uint16_t)feed); + serial_print_fltunits(feed); #ifdef USE_SPINDLE serial_putc(','); serial_print_int(spindle); @@ -431,7 +431,7 @@ extern "C" serial_putc(' '); serial_putc('F'); - serial_print_int(feed); + serial_print_fltunits(feed); serial_putc(' '); serial_putc('S'); @@ -501,7 +501,7 @@ extern "C" void protocol_send_cnc_settings(void) { protocol_busy = true; - protocol_send_gcode_setting_line_int(0, g_settings.max_step_rate); + protocol_send_gcode_setting_line_flt(0, g_settings.max_step_rate); #ifdef EMULATE_GRBL_STARTUP // just adds this for compatibility // this setting is not used diff --git a/src/interface/serial.c b/src/interface/serial.c index d7e41a52a..46ff93538 100644 --- a/src/interface/serial.c +++ b/src/interface/serial.c @@ -233,39 +233,7 @@ extern "C" } while (c != 0); } - void serial_print_int(int16_t num) - { - if (num == 0) - { - serial_putc('0'); - return; - } - - unsigned char buffer[6]; - uint8_t i = 0; - if (num < 0) - { - serial_putc('-'); - num = -num; - } - - while (num > 0) - { - uint8_t digit = num % 10; - num = ((((uint32_t)num * (UINT16_MAX / 10)) >> 16) + ((digit != 0) ? 0 : 1)); //same has divide by 10 but faster - buffer[i++] = digit; - /*buffer[i++] = num % 10; - num /= 10;*/ - } - - do - { - i--; - serial_putc('0' + buffer[i]); - } while (i); - } -#ifdef GCODE_PROCESS_LINE_NUMBERS - void serial_print_long(int32_t num) + void serial_print_int(int32_t num) { if (num == 0) { @@ -287,8 +255,6 @@ extern "C" uint8_t digit = num % 10; num = (uint32_t)truncf((float)num * 0.1f); buffer[i++] = digit; - /*buffer[i++] = num % 10; - num /= 10;*/ } do @@ -297,36 +263,25 @@ extern "C" serial_putc('0' + buffer[i]); } while (i); } -#endif void serial_print_flt(float num) { - if (g_settings.report_inches) - { - num *= MM_INCH_MULT; - } - if (num < 0) { serial_putc('-'); num = -num; } - uint16_t digits = (uint16_t)floorf(num); + uint32_t digits = (uint32_t)floorf(num); serial_print_int(digits); serial_putc('.'); num -= digits; - num *= 1000; - digits = (uint16_t)roundf(num); + num *= (!g_settings.report_inches) ? 1000 : 10000; + digits = (uint32_t)roundf(num); if (g_settings.report_inches) { - if (digits < 10000) - { - serial_putc('0'); - } - if (digits < 1000) { serial_putc('0'); @@ -346,6 +301,12 @@ extern "C" serial_print_int(digits); } + void serial_print_fltunits(float num) + { + num = (!g_settings.report_inches) ? num : (num * MM_INCH_MULT); + serial_print_flt(num); + } + void serial_print_intarr(uint16_t *arr, uint8_t count) { do @@ -365,7 +326,7 @@ extern "C" uint8_t i = count; do { - serial_print_flt(*arr++); + serial_print_fltunits(*arr++); i--; if (i) { diff --git a/src/interface/serial.h b/src/interface/serial.h index 7d4e7fc41..3a5d6889b 100644 --- a/src/interface/serial.h +++ b/src/interface/serial.h @@ -56,11 +56,9 @@ extern "C" void serial_putc(unsigned char c); void serial_print_str(const unsigned char *__s); - void serial_print_int(int16_t num); -#ifdef GCODE_PROCESS_LINE_NUMBERS - void serial_print_long(int32_t num); -#endif + void serial_print_int(int32_t num); void serial_print_flt(float num); + void serial_print_fltunits(float num); void serial_print_intarr(uint16_t *arr, uint8_t count); void serial_print_fltarr(float *arr, uint8_t count); void serial_flush(void); From 8138f01c9407ca557b2b133ceb3701a121933a9c Mon Sep 17 00:00:00 2001 From: Paciente8159 Date: Wed, 4 Aug 2021 15:40:17 +0100 Subject: [PATCH 09/24] fixed coordinates system offsets -fixed G92 offset calculations -added support for G10 L2 P0 (current coordinate system) --- src/core/parser.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/core/parser.c b/src/core/parser.c index 877cc4c40..639558a2c 100644 --- a/src/core/parser.c +++ b/src/core/parser.c @@ -782,7 +782,7 @@ extern "C" //P is not between 1 and N of coord systems if (words->p != 28 && words->p != 30) { - if (words->p < 1 || words->p > COORD_SYS_COUNT) + if (words->p > COORD_SYS_COUNT) { return STATUS_GCODE_UNSUPPORTED_COORD_SYS; } @@ -1184,7 +1184,7 @@ extern "C" switch (new_state->groups.nonmodal) { case G10: //G10 - index = (uint8_t)words->p; + index = ((uint8_t)words->p) ? words->p : (parser_parameters.coord_system_index + 1); switch (index) { case 28: @@ -1301,6 +1301,10 @@ extern "C" if (index <= G30HOME) { settings_save(SETTINGS_PARSER_PARAMETERS_ADDRESS_OFFSET + (index * PARSER_PARAM_ADDR_OFFSET), (uint8_t *)&axis[0], PARSER_PARAM_SIZE); + if (index == parser_parameters.coord_system_index) + { + memcpy(parser_parameters.coord_system_offset, axis, sizeof(parser_parameters.coord_system_offset)); + } parser_wco_counter = 0; } @@ -1343,7 +1347,7 @@ extern "C" for (uint8_t i = AXIS_COUNT; i != 0;) { i--; - parser_parameters.g92_offset[i] = planner_last_pos[i] - parser_parameters.coord_system_offset[i] - axis[i]; + parser_parameters.g92_offset[i] = -(axis[i] - planner_last_pos[i] - parser_parameters.g92_offset[i]); } memcpy(g92permanentoffset, parser_parameters.g92_offset, sizeof(g92permanentoffset)); //settings_save(G92ADDRESS, (uint8_t *)&parser_parameters.g92_offset[0], PARSER_PARAM_SIZE); From b923b5f5e570d50a7d438c2843ec3f6d2b3004c4 Mon Sep 17 00:00:00 2001 From: Paciente8159 Date: Wed, 4 Aug 2021 20:56:50 +0100 Subject: [PATCH 10/24] improved startup code -improve startup code with reduced code size and stable results -fixed startup blocks result not printing in the same line -moved reset to continue message to the end of the alarm condition --- src/cnc.c | 53 +++++++++++++++++++++++------------------- src/cnc.h | 6 ++--- src/interface/serial.c | 1 - 3 files changed, 31 insertions(+), 29 deletions(-) diff --git a/src/cnc.c b/src/cnc.c index ebfaaf3a0..4172be918 100644 --- a/src/cnc.c +++ b/src/cnc.c @@ -39,9 +39,12 @@ extern "C" #include "modules/pid_controller.h" #define LOOP_STARTUP_RESET 0 -#define LOOP_STARTUP_BLOCKS 1 -#define LOOP_RUNNING 2 -#define LOOP_ERROR_RESET 3 +#define LOOP_STARTUP_BLOCK0 1 +#define LOOP_STARTUP_BLOCK1 2 +#define LOOP_RUNNING 4 +#define LOOP_ERROR_RESET 8 +#define LOOP_STARTUP_BLOCKS (LOOP_STARTUP_BLOCK0 | LOOP_STARTUP_BLOCK1) +#define LOOP_STARTUP (LOOP_STARTUP_RESET | LOOP_STARTUP_BLOCKS) typedef struct { @@ -85,6 +88,8 @@ extern "C" void cnc_run(void) { cnc_reset(); + cnc_state.loop_state = LOOP_STARTUP_BLOCK0; + serial_select(SERIAL_N0); do { @@ -112,6 +117,15 @@ extern "C" protocol_send_error(error); } } + + if (cnc_state.loop_state != LOOP_RUNNING) + { + cnc_state.loop_state <<= 1; + if (cnc_state.loop_state == LOOP_STARTUP_BLOCK1) + { + serial_select(SERIAL_N1); + } + } } while (cnc_dotasks()); cnc_state.loop_state = LOOP_ERROR_RESET; @@ -120,7 +134,6 @@ extern "C" if (cnc_get_exec_state(EXEC_ALARM)) //checks if any alarm is active { cnc_check_fault_systems(); - protocol_send_feedback(MSG_FEEDBACK_1); do { cnc_clear_exec_state(EXEC_KILL); //tries to clear the kill flag if possible @@ -416,7 +429,6 @@ extern "C" planner_clear(); protocol_send_string(MSG_STARTUP); - cnc_state.loop_state = LOOP_STARTUP_BLOCKS; //tries to clear alarms or any active hold state cnc_clear_exec_state(EXEC_ALARM | EXEC_HOLD); @@ -432,7 +444,6 @@ extern "C" else { cnc_unlock(); - SETFLAG(cnc_state.rt_cmd, RT_CMD_STARTUP_BLOCK0); } } @@ -448,15 +459,15 @@ extern "C" bool update_tools = false; //executes feeds override rt commands - uint8_t cmd_mask = 0x08; - uint8_t command = cnc_state.rt_cmd & 0x0F; //copies realtime flags states + uint8_t cmd_mask = 0x02; + uint8_t command = cnc_state.rt_cmd & 0x03; //copies realtime flags states CLEARFLAG(cnc_state.rt_cmd, ~RT_CMD_REPORT); //clears all command flags except report request while (command) { switch (command & cmd_mask) { case RT_CMD_REPORT: - if (!protocol_is_busy() && cnc_state.loop_state >= LOOP_RUNNING) + if (!protocol_is_busy() && !(cnc_state.loop_state & LOOP_STARTUP)) { protocol_send_status(); CLEARFLAG(cnc_state.rt_cmd, RT_CMD_REPORT); //if a report request is sent, clear the respective flag @@ -465,21 +476,6 @@ extern "C" case RT_CMD_CYCLE_START: cnc_clear_exec_state(EXEC_HOLD); break; - case RT_CMD_STARTUP_BLOCK0: - if (settings_check_startup_gcode(STARTUP_BLOCK0_ADDRESS_OFFSET)) //loads command 0 - { - serial_select(SERIAL_N0); - } - - SETFLAG(cnc_state.rt_cmd, RT_CMD_STARTUP_BLOCK1); //invokes command 1 on next pass - break; - case RT_CMD_STARTUP_BLOCK1: - if (settings_check_startup_gcode(STARTUP_BLOCK1_ADDRESS_OFFSET)) //loads command 1 - { - serial_select(SERIAL_N1); - cnc_state.loop_state = LOOP_RUNNING; - } - break; } CLEARFLAG(command, cmd_mask); @@ -606,16 +602,19 @@ extern "C" void cnc_check_fault_systems(void) { + bool fail = false; uint8_t inputs = io_get_controls(); #ifdef ESTOP if (CHECKFLAG(inputs, ESTOP_MASK)) //fault on emergency stop { + fail = true; protocol_send_feedback(MSG_FEEDBACK_12); } #endif #ifdef SAFETY_DOOR if (CHECKFLAG(inputs, SAFETY_DOOR_MASK)) //fault on safety door { + fail = true; protocol_send_feedback(MSG_FEEDBACK_6); } #endif @@ -625,10 +624,16 @@ extern "C" inputs = io_get_limits(); if (CHECKFLAG(inputs, LIMITS_MASK)) { + fail = true; protocol_send_feedback(MSG_FEEDBACK_7); } } #endif + + if (fail) + { + protocol_send_feedback(MSG_FEEDBACK_1); + } } bool cnc_check_interlocking(void) diff --git a/src/cnc.h b/src/cnc.h index 792d801eb..a8cc65bf7 100644 --- a/src/cnc.h +++ b/src/cnc.h @@ -27,10 +27,8 @@ extern "C" //rt_cmd #define RT_CMD_CLEAR 0 -#define RT_CMD_STARTUP_BLOCK0 1 -#define RT_CMD_STARTUP_BLOCK1 2 -#define RT_CMD_REPORT 4 -#define RT_CMD_CYCLE_START 8 +#define RT_CMD_REPORT 1 +#define RT_CMD_CYCLE_START 2 #define RT_CMD_ABORT 128 //feed_ovr_cmd diff --git a/src/interface/serial.c b/src/interface/serial.c index 46ff93538..63bb76b6e 100644 --- a/src/interface/serial.c +++ b/src/interface/serial.c @@ -371,7 +371,6 @@ extern "C" switch (c) { case CMD_CODE_RESET: - serial_rx_clear(); //dumps all unexecuted commands case CMD_CODE_FEED_HOLD: case CMD_CODE_REPORT: cnc_call_rt_command((uint8_t)c); From 5320d1a1bca91c0799156b9accc1656953d107a0 Mon Sep 17 00:00:00 2001 From: Paciente8159 Date: Wed, 4 Aug 2021 22:44:28 +0100 Subject: [PATCH 11/24] Update parser.c -added command discard call to prevent infinite error loop --- src/core/parser.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/parser.c b/src/core/parser.c index 639558a2c..be0f024a4 100644 --- a/src/core/parser.c +++ b/src/core/parser.c @@ -271,7 +271,7 @@ extern "C" FORCEINLINE static uint8_t parser_exec_command(parser_state_t *new_state, parser_words_t *words, parser_cmd_explicit_t *cmd); static uint8_t parser_grbl_command(void); FORCEINLINE static uint8_t parser_gcode_command(void); - FORCEINLINE static void parser_discard_command(void); + static void parser_discard_command(void); static void parser_reset(); /* @@ -305,7 +305,6 @@ extern "C" } else { - return error; } } @@ -319,6 +318,7 @@ extern "C" } else if (cnc_get_exec_state(~(EXEC_RUN | EXEC_HOLD | EXEC_RESUMING))) { + parser_discard_command(); return STATUS_SYSTEM_GC_LOCK; } From 0167a5d28144ca6dac56b27b03ebee23a7c7f216 Mon Sep 17 00:00:00 2001 From: Paciente8159 Date: Thu, 5 Aug 2021 00:00:55 +0100 Subject: [PATCH 12/24] Update cnc.c -minor fix in exec state flag clear --- src/cnc.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/cnc.c b/src/cnc.c index 4172be918..6fc0c06ba 100644 --- a/src/cnc.c +++ b/src/cnc.c @@ -386,9 +386,12 @@ extern "C" #if (LIMITS_MASK != 0) limits = io_get_limits(); //can't clear the EXEC_LIMITS is any limit is triggered #endif - if (g_settings.hard_limits_enabled && limits) //if hardlimits are enabled and limits are triggered + if (g_settings.hard_limits_enabled) //if hardlimits are enabled and limits are triggered { - CLEARFLAG(statemask, EXEC_LIMITS); + if (limits || g_settings.homing_enabled) + { + CLEARFLAG(statemask, EXEC_LIMITS); + } } if (CHECKFLAG(statemask, EXEC_HOLD)) @@ -402,6 +405,7 @@ extern "C" } CLEARFLAG(cnc_state.exec_state, EXEC_RESUMING); } + CLEARFLAG(cnc_state.exec_state, statemask); } From 11ba2314d1804ec2ed1383c2282683931425e4d5 Mon Sep 17 00:00:00 2001 From: Paciente8159 Date: Thu, 5 Aug 2021 01:44:29 +0100 Subject: [PATCH 13/24] initial changes -modifications to the interlocking checking and the rt call functions --- src/cnc.c | 172 ++++++++++++++++++++++------------------ src/cnc.h | 2 +- src/core/interpolator.c | 4 +- src/core/io_control.c | 40 ++++------ 4 files changed, 110 insertions(+), 108 deletions(-) diff --git a/src/cnc.c b/src/cnc.c index 6fc0c06ba..cb59e3e47 100644 --- a/src/cnc.c +++ b/src/cnc.c @@ -61,7 +61,7 @@ extern "C" static void cnc_check_fault_systems(); static bool cnc_check_interlocking(); static void cnc_exec_rt_commands(); - FORCEINLINE static void cnc_reset(); + static bool cnc_reset(); void cnc_init(void) { @@ -87,46 +87,49 @@ extern "C" void cnc_run(void) { - cnc_reset(); - cnc_state.loop_state = LOOP_STARTUP_BLOCK0; - serial_select(SERIAL_N0); - - do + // tries to reset. If fails jumps to error + if (cnc_reset()) { - //process gcode commands - if (!serial_rx_is_empty()) + cnc_state.loop_state = LOOP_STARTUP_BLOCK0; + serial_select(SERIAL_N0); + + do { - uint8_t error = 0; - //protocol_echo(); - uint8_t c = serial_peek(); - switch (c) + //process gcode commands + if (!serial_rx_is_empty()) { - case EOL: //not necessary but faster to catch empty lines and windows newline (CR+LF) - serial_getc(); - break; - default: - error = parser_read_command(); - break; - } - if (!error) - { - protocol_send_ok(); - } - else - { - protocol_send_error(error); + uint8_t error = 0; + //protocol_echo(); + uint8_t c = serial_peek(); + switch (c) + { + case EOL: //not necessary but faster to catch empty lines and windows newline (CR+LF) + serial_getc(); + break; + default: + error = parser_read_command(); + break; + } + if (!error) + { + protocol_send_ok(); + } + else + { + protocol_send_error(error); + } } - } - if (cnc_state.loop_state != LOOP_RUNNING) - { - cnc_state.loop_state <<= 1; - if (cnc_state.loop_state == LOOP_STARTUP_BLOCK1) + if (cnc_state.loop_state != LOOP_RUNNING) { - serial_select(SERIAL_N1); + cnc_state.loop_state <<= 1; + if (cnc_state.loop_state == LOOP_STARTUP_BLOCK1) + { + serial_select(SERIAL_N1); + } } - } - } while (cnc_dotasks()); + } while (cnc_dotasks()); + } cnc_state.loop_state = LOOP_ERROR_RESET; @@ -147,22 +150,18 @@ extern "C" //only reset command is executed right away //control commands affect the exec_state directly (Abort, hold, safety door, cycle_start) //the effects are then propagate in the cnc_dotasks + //uses macro to be faster switch (command) { case CMD_CODE_RESET: - if (cnc_get_exec_state(EXEC_RUN)) + if (CHECKFLAG(cnc_state.exec_state, EXEC_KILL)) { - cnc_alarm(EXEC_ALARM_ABORT_CYCLE); + SETFLAG(cnc_state.rt_cmd, RT_CMD_RESET); } - else - { - cnc_alarm(EXEC_ALARM_RESET); - } - serial_rx_clear(); //dumps all commands - SETFLAG(cnc_state.rt_cmd, RT_CMD_ABORT); + SETFLAG(cnc_state.exec_state, EXEC_KILL); break; case CMD_CODE_FEED_HOLD: - cnc_set_exec_state(EXEC_HOLD); + SETFLAG(cnc_state.exec_state, EXEC_HOLD); break; case CMD_CODE_REPORT: SETFLAG(cnc_state.rt_cmd, RT_CMD_REPORT); @@ -171,12 +170,12 @@ extern "C" SETFLAG(cnc_state.rt_cmd, RT_CMD_CYCLE_START); //tries to clear hold if possible break; case CMD_CODE_SAFETY_DOOR: - cnc_set_exec_state(EXEC_HOLD | EXEC_DOOR); + SETFLAG(cnc_state.exec_state, (EXEC_HOLD | EXEC_DOOR)); break; case CMD_CODE_JOG_CANCEL: - if (cnc_get_exec_state(EXEC_JOG)) + if (CHECKFLAG(cnc_state.exec_state, EXEC_JOG)) { - cnc_set_exec_state(EXEC_HOLD); + SETFLAG(cnc_state.exec_state, EXEC_HOLD); } break; case CMD_CODE_FEED_100: @@ -239,7 +238,7 @@ extern "C" //let µCNC finnish startup/reset code if (cnc_state.loop_state == LOOP_STARTUP_RESET) { - return; + return true; } #if ((LIMITEN_MASK ^ LIMITISR_MASK) || defined(FORCE_SOFT_POLLING)) @@ -419,7 +418,7 @@ extern "C" } } - void cnc_reset(void) + bool cnc_reset(void) { cnc_state.loop_state = LOOP_STARTUP_RESET; //resets all realtime command flags @@ -429,6 +428,7 @@ extern "C" cnc_state.exec_state = EXEC_ALARM | EXEC_HOLD; //Activates all alarms and hold //clear all systems + serial_rx_clear(); itp_clear(); planner_clear(); protocol_send_string(MSG_STARTUP); @@ -444,11 +444,17 @@ extern "C" { protocol_send_feedback(MSG_FEEDBACK_2); } + else + { + return false; + } } else { cnc_unlock(); } + + return true; } //Executes pending realtime commands @@ -463,13 +469,20 @@ extern "C" bool update_tools = false; //executes feeds override rt commands - uint8_t cmd_mask = 0x02; - uint8_t command = cnc_state.rt_cmd & 0x03; //copies realtime flags states + uint8_t cmd_mask = 0x04; + uint8_t command = cnc_state.rt_cmd; //copies realtime flags states CLEARFLAG(cnc_state.rt_cmd, ~RT_CMD_REPORT); //clears all command flags except report request while (command) { switch (command & cmd_mask) { + case RT_CMD_RESET: + cnc_clear_exec_state(EXEC_KILL); + if (cnc_get_exec_state(EXEC_KILL)) + { + cnc_check_fault_systems(); + } + break; case RT_CMD_REPORT: if (!protocol_is_busy() && !(cnc_state.loop_state & LOOP_STARTUP)) { @@ -642,40 +655,28 @@ extern "C" bool cnc_check_interlocking(void) { - //if abort is flagged + //check all flags + //if kill leave if (CHECKFLAG(cnc_state.exec_state, EXEC_KILL)) { - return false; - } - - if (CHECKFLAG(cnc_state.exec_state, EXEC_DOOR | EXEC_HOLD)) - { - //machine is still running after hold/security door - if (CHECKFLAG(cnc_state.exec_state, EXEC_RUN)) + if (CHECKFLAG(cnc_state.exec_state, EXEC_HOMING)) //reset or emergency stop during a homing cycle { - return true; + cnc_alarm(EXEC_ALARM_HOMING_FAIL_RESET); } - - itp_stop(); - if (CHECKFLAG(cnc_state.exec_state, EXEC_DOOR)) + else if (CHECKFLAG(cnc_state.exec_state, EXEC_RUN)) //reset or emergency stop during a running cycle { - if (CHECKFLAG(cnc_state.exec_state, EXEC_HOMING)) //door opened during a homing cycle - { - cnc_alarm(EXEC_ALARM_HOMING_FAIL_DOOR); - } - else - { - cnc_stop(); //stop all tools not only motion - } + cnc_alarm(EXEC_ALARM_ABORT_CYCLE); } - - if (CHECKFLAG(cnc_state.exec_state, EXEC_HOMING | EXEC_JOG)) //flushes the buffers if motions was homing or jog + else { - itp_clear(); - planner_clear(); - CLEARFLAG(cnc_state.exec_state, EXEC_HOMING | EXEC_JOG | EXEC_HOLD); + cnc_alarm(EXEC_ALARM_RESET); //reset or emergency stop } + return false; + } + if (CHECKFLAG(cnc_state.exec_state, EXEC_DOOR) & CHECKFLAG(cnc_state.exec_state, EXEC_HOMING)) //door opened during a homing cycle + { + cnc_alarm(EXEC_ALARM_HOMING_FAIL_DOOR); return false; } @@ -689,11 +690,24 @@ extern "C" return false; } - //clears EXEC_JOG if not step ISR is stopped and planner has no more moves - /*if (CHECKFLAG(cnc_state.exec_state, EXEC_JOG) && !CHECKFLAG(cnc_state.exec_state, EXEC_RUN) && planner_buffer_is_empty()) + //opened door or hold with the machine still + if (CHECKFLAG(cnc_state.exec_state, EXEC_DOOR | EXEC_HOLD) & !CHECKFLAG(cnc_state.exec_state, EXEC_RUN)) { - CLEARFLAG(cnc_state.exec_state, EXEC_JOG); - }*/ + itp_stop(); + if (CHECKFLAG(cnc_state.exec_state, EXEC_DOOR)) + { + cnc_stop(); //stop all tools not only motion + } + + if (CHECKFLAG(cnc_state.exec_state, EXEC_HOMING | EXEC_JOG)) //flushes the buffers if motions was homing or jog + { + itp_clear(); + planner_clear(); + CLEARFLAG(cnc_state.exec_state, EXEC_HOMING | EXEC_JOG | EXEC_HOLD); + } + + return false; + } return true; } diff --git a/src/cnc.h b/src/cnc.h index a8cc65bf7..2a9ce6204 100644 --- a/src/cnc.h +++ b/src/cnc.h @@ -29,7 +29,7 @@ extern "C" #define RT_CMD_REPORT 1 #define RT_CMD_CYCLE_START 2 -#define RT_CMD_ABORT 128 +#define RT_CMD_RESET 4 //feed_ovr_cmd #define RT_CMD_FEED_100 1 diff --git a/src/core/interpolator.c b/src/core/interpolator.c index e208aa67d..0fa7af95a 100644 --- a/src/core/interpolator.c +++ b/src/core/interpolator.c @@ -527,7 +527,6 @@ extern "C" { io_set_steps(g_settings.step_invert_mask); io_set_dirs(g_settings.dir_invert_mask); - cnc_clear_exec_state(EXEC_RUN); #ifdef LASER_MODE if (g_settings.laser_mode) { @@ -764,7 +763,8 @@ extern "C" { mcu_disable_global_isr(); itp_busy = false; - itp_stop(); //the buffer is empty. The ISR can stop + itp_stop(); //the buffer is empty. The ISR can stop + cnc_clear_exec_state(EXEC_RUN); //this naturally clears the RUN flag. Any other ISR stop does not clear the flag. return; } } diff --git a/src/core/io_control.c b/src/core/io_control.c index d8779992c..42eca9c94 100644 --- a/src/core/io_control.c +++ b/src/core/io_control.c @@ -43,44 +43,32 @@ extern "C" { if (limits) { - if (cnc_get_exec_state(EXEC_RUN)) - { - if (!cnc_get_exec_state(EXEC_HOMING)) //if not in a homing motion triggers an alarm - { - if (g_settings.hard_limits_enabled) - { - cnc_set_exec_state(EXEC_LIMITS); //if motions was executing flags home position lost - } - - cnc_alarm(EXEC_ALARM_HARD_LIMIT); - } #ifdef ENABLE_DUAL_DRIVE_AXIS - else - { + if (cnc_get_exec_state(EXEC_RUN) & cnc_get_exec_state(EXEC_HOMING)) + { //if homing and dual drive axis are enabled #ifdef DUAL_DRIVE_AXIS0 - if ((limits & (LIMIT_DUAL0 | LIMITS_DUAL_MASK) & io_limits_homing_filter)) //the limit triggered matches the first dual drive axis - { - itp_lock_stepper((limits & LIMITS_LIMIT1_MASK) ? STEP6_MASK : STEP_DUAL0); + if ((limits & (LIMIT_DUAL0 | LIMITS_DUAL_MASK) & io_limits_homing_filter)) //the limit triggered matches the first dual drive axis + { + itp_lock_stepper((limits & LIMITS_LIMIT1_MASK) ? STEP6_MASK : STEP_DUAL0); - if ((limits & LIMITS_DUAL_MASK) != LIMITS_DUAL_MASK) //but not both - { - return; //exits and doesn't trip the alarm - } + if ((limits & LIMITS_DUAL_MASK) != LIMITS_DUAL_MASK) //but not both + { + return; //exits and doesn't trip the alarm } + } #endif #ifdef DUAL_DRIVE_AXIS1 - if (limits & LIMIT_DUAL1 & io_limits_homing_filter) //the limit triggered matches the second dual drive axis + if (limits & LIMIT_DUAL1 & io_limits_homing_filter) //the limit triggered matches the second dual drive axis + { + if ((limits & LIMITS_DUAL_MASK) != LIMITS_DUAL_MASK) //but not both { - if ((limits & LIMITS_DUAL_MASK) != LIMITS_DUAL_MASK) //but not both - { - itp_lock_stepper((limits & LIMITS_LIMIT1_MASK) ? STEP7_MASK : STEP_DUAL1); - } + itp_lock_stepper((limits & LIMITS_LIMIT1_MASK) ? STEP7_MASK : STEP_DUAL1); } -#endif } #endif } +#endif #ifdef ENABLE_DUAL_DRIVE_AXIS itp_lock_stepper(0); //unlocks axis #endif From 7bdfbb9ed6ade91c5e65222d80ff0471d3e196a9 Mon Sep 17 00:00:00 2001 From: Paciente8159 Date: Thu, 5 Aug 2021 09:08:29 +0100 Subject: [PATCH 14/24] Update interpolator.c -cleaned non-motion code from interpolator --- src/core/interpolator.c | 61 ++++------------------------------------- 1 file changed, 5 insertions(+), 56 deletions(-) diff --git a/src/core/interpolator.c b/src/core/interpolator.c index 0fa7af95a..437fe0dc3 100644 --- a/src/core/interpolator.c +++ b/src/core/interpolator.c @@ -45,10 +45,7 @@ extern "C" //Itp update flags #define ITP_NOUPDATE 0 -#define ITP_DWELL 1 -#define ITP_UPDATE_TOOLS 2 -#define ITP_PAUSE 4 -#define ITP_PAUSE_CONDITIONAL 8 +#define ITP_UPDATE_ISR 1 //contains data of the block being executed by the pulse routine //this block has the necessary data to execute the Bresenham line algorithm @@ -230,40 +227,6 @@ extern "C" #ifdef GCODE_PROCESS_LINE_NUMBERS itp_blk_data[itp_blk_data_write].line = itp_cur_plan_block->line; #endif -/* - uint8_t nomotion_type = ITP_NOUPDATE; - if (itp_cur_plan_block->dwell != 0) - { - nomotion_type |= ITP_DWELL; - } - - if (itp_cur_plan_block->total_steps == 0) - { -#ifdef USE_SPINDLE - nomotion_type = ITP_UPDATE_TOOLS; -#endif - if (itp_cur_plan_block->action & (MOTIONCONTROL_MODE_PAUSEPROGRAM | MOTIONCONTROL_MODE_PAUSEPROGRAM_CONDITIONAL)) - { - nomotion_type |= ITP_PAUSE; - } - - if (itp_cur_plan_block->action & (MOTIONCONTROL_MODE_PAUSEPROGRAM_CONDITIONAL)) - { - nomotion_type |= ITP_PAUSE_CONDITIONAL; - } - } - - if (nomotion_type) - { - itp_nomotion(nomotion_type, itp_cur_plan_block->dwell); - if (nomotion_type > ITP_DWELL) - { - //no motion action (doesn't need a interpolator block = NULL) - itp_cur_plan_block = NULL; - planner_discard_block(); - break; //exits after adding the dwell segment if motion is 0 (empty motion block) - } - }*/ //overwrites previous values #ifdef ENABLE_BACKLASH_COMPENSATION @@ -373,7 +336,7 @@ extern "C" */ speed_change = half_speed_change; //(!initial_accel_negative) ? half_speed_change : -half_speed_change; profile_steps_limit = accel_until; - sgm->update_itp = ITP_DWELL; + sgm->update_itp = ITP_UPDATE_ISR; is_initial_transition = true; } else if (remaining_steps > deaccel_from) @@ -381,14 +344,14 @@ extern "C" //constant speed segment speed_change = 0; profile_steps_limit = deaccel_from; - sgm->update_itp = is_initial_transition ? ITP_UPDATE_TOOLS : ITP_NOUPDATE; + sgm->update_itp = is_initial_transition ? ITP_UPDATE_ISR : ITP_NOUPDATE; is_initial_transition = false; } else { speed_change = -half_speed_change; profile_steps_limit = 0; - sgm->update_itp = ITP_DWELL; + sgm->update_itp = ITP_UPDATE_ISR; is_initial_transition = true; } @@ -734,24 +697,10 @@ extern "C" if (itp_rt_sgm->update_itp) { - if (itp_rt_sgm->update_itp & ITP_DWELL) + if (itp_rt_sgm->update_itp & ITP_UPDATE_ISR) { mcu_change_itp_isr(itp_rt_sgm->timer_counter, itp_rt_sgm->timer_prescaller); } - else if (itp_rt_sgm->update_itp & ITP_PAUSE) - { - mcu_disable_global_isr(); - itp_busy = false; -#ifdef M1_CONDITION - if (!M1_CONDITION) - { - return; - } -#endif - itp_stop(); //stop the isr - cnc_set_exec_state(EXEC_HOLD); - return; - } #ifdef USE_SPINDLE io_set_spindle(itp_rt_sgm->spindle, itp_rt_sgm->spindle_inv); itp_rt_spindle = itp_rt_sgm->spindle; From 2a038fd6f04f1a29950e7cc68550a9563618c8d3 Mon Sep 17 00:00:00 2001 From: Paciente8159 Date: Thu, 5 Aug 2021 16:29:32 +0100 Subject: [PATCH 15/24] modified interlocking -modified unlock code -removed all print code (except status report) from dotasks -alarm print moved to error reset loop -tweaked all interlocking and system fail functions --- src/cnc.c | 305 +++++++++++++++++---------------- src/cnc.h | 6 +- src/core/interpolator.c | 7 +- src/core/io_control.c | 8 +- src/core/motion_control.c | 18 +- src/core/parser.c | 4 +- src/interface/grbl_interface.h | 3 +- src/interface/protocol.c | 2 +- src/interface/serial.c | 25 +-- 9 files changed, 183 insertions(+), 195 deletions(-) diff --git a/src/cnc.c b/src/cnc.c index cb59e3e47..007cef4d7 100644 --- a/src/cnc.c +++ b/src/cnc.c @@ -54,6 +54,7 @@ extern "C" volatile uint8_t rt_cmd; volatile uint8_t feed_ovr_cmd; volatile uint8_t tool_ovr_cmd; + volatile uint8_t alarm; } cnc_state_t; static cnc_state_t cnc_state; @@ -132,100 +133,16 @@ extern "C" } cnc_state.loop_state = LOOP_ERROR_RESET; - serial_flush(); - if (cnc_get_exec_state(EXEC_ALARM)) //checks if any alarm is active + if (cnc_state.alarm) { + protocol_send_alarm(cnc_state.alarm); cnc_check_fault_systems(); do { - cnc_clear_exec_state(EXEC_KILL); //tries to clear the kill flag if possible - } while (!cnc_dotasks()); - } - } - - void cnc_call_rt_command(uint8_t command) - { - //executes the realtime commands - //only reset command is executed right away - //control commands affect the exec_state directly (Abort, hold, safety door, cycle_start) - //the effects are then propagate in the cnc_dotasks - //uses macro to be faster - switch (command) - { - case CMD_CODE_RESET: - if (CHECKFLAG(cnc_state.exec_state, EXEC_KILL)) - { - SETFLAG(cnc_state.rt_cmd, RT_CMD_RESET); - } - SETFLAG(cnc_state.exec_state, EXEC_KILL); - break; - case CMD_CODE_FEED_HOLD: - SETFLAG(cnc_state.exec_state, EXEC_HOLD); - break; - case CMD_CODE_REPORT: - SETFLAG(cnc_state.rt_cmd, RT_CMD_REPORT); - break; - case CMD_CODE_CYCLE_START: - SETFLAG(cnc_state.rt_cmd, RT_CMD_CYCLE_START); //tries to clear hold if possible - break; - case CMD_CODE_SAFETY_DOOR: - SETFLAG(cnc_state.exec_state, (EXEC_HOLD | EXEC_DOOR)); - break; - case CMD_CODE_JOG_CANCEL: - if (CHECKFLAG(cnc_state.exec_state, EXEC_JOG)) - { - SETFLAG(cnc_state.exec_state, EXEC_HOLD); - } - break; - case CMD_CODE_FEED_100: - SETFLAG(cnc_state.feed_ovr_cmd, RT_CMD_FEED_100); - break; - case CMD_CODE_FEED_INC_COARSE: - SETFLAG(cnc_state.feed_ovr_cmd, RT_CMD_FEED_INC_COARSE); - break; - case CMD_CODE_FEED_DEC_COARSE: - SETFLAG(cnc_state.feed_ovr_cmd, RT_CMD_FEED_DEC_COARSE); - break; - case CMD_CODE_FEED_INC_FINE: - SETFLAG(cnc_state.feed_ovr_cmd, RT_CMD_FEED_INC_FINE); - break; - case CMD_CODE_FEED_DEC_FINE: - SETFLAG(cnc_state.feed_ovr_cmd, RT_CMD_FEED_DEC_FINE); - break; - case CMD_CODE_RAPIDFEED_100: - SETFLAG(cnc_state.feed_ovr_cmd, RT_CMD_RAPIDFEED_100); - break; - case CMD_CODE_RAPIDFEED_OVR1: - SETFLAG(cnc_state.feed_ovr_cmd, RT_CMD_RAPIDFEED_OVR1); - break; - case CMD_CODE_RAPIDFEED_OVR2: - SETFLAG(cnc_state.feed_ovr_cmd, RT_CMD_RAPIDFEED_OVR2); - break; - case CMD_CODE_SPINDLE_100: - SETFLAG(cnc_state.tool_ovr_cmd, RT_CMD_SPINDLE_100); - break; - case CMD_CODE_SPINDLE_INC_COARSE: - SETFLAG(cnc_state.tool_ovr_cmd, RT_CMD_SPINDLE_INC_COARSE); - break; - case CMD_CODE_SPINDLE_DEC_COARSE: - SETFLAG(cnc_state.tool_ovr_cmd, RT_CMD_SPINDLE_DEC_COARSE); - break; - case CMD_CODE_SPINDLE_INC_FINE: - SETFLAG(cnc_state.tool_ovr_cmd, RT_CMD_SPINDLE_INC_FINE); - break; - case CMD_CODE_SPINDLE_DEC_FINE: - SETFLAG(cnc_state.tool_ovr_cmd, RT_CMD_SPINDLE_DEC_FINE); - break; - case CMD_CODE_SPINDLE_TOGGLE: - SETFLAG(cnc_state.tool_ovr_cmd, RT_CMD_SPINDLE_TOGGLE); - break; - case CMD_CODE_COOL_FLD_TOGGLE: - SETFLAG(cnc_state.tool_ovr_cmd, RT_CMD_COOL_FLD_TOGGLE); - break; - case CMD_CODE_COOL_MST_TOGGLE: - SETFLAG(cnc_state.tool_ovr_cmd, RT_CMD_COOL_MST_TOGGLE); - break; + cnc_clear_exec_state(EXEC_ALARM); + cnc_dotasks(); + } while (cnc_state.alarm); } } @@ -250,6 +167,12 @@ extern "C" cnc_exec_rt_commands(); //executes all pending realtime commands + //µCNC already in error loop. No point in sending the alarms + if (cnc_state.loop_state == LOOP_ERROR_RESET) + { + return !cnc_get_exec_state(EXEC_KILL); + } + //check security interlocking for any problem if (!cnc_check_interlocking()) { @@ -279,7 +202,7 @@ extern "C" } //unlocks the machine to go to offset - cnc_unlock(); + cnc_unlock(true); float target[AXIS_COUNT]; motion_data_t block_data; @@ -310,19 +233,11 @@ extern "C" { cnc_set_exec_state(EXEC_KILL); cnc_stop(); - if (code) - { - protocol_send_alarm(code); - } + cnc_state.alarm = code; } void cnc_stop(void) { - //halt is active and was running flags it lost home position - if (cnc_get_exec_state(EXEC_RUN) && g_settings.homing_enabled) - { - cnc_set_exec_state(EXEC_LIMITS); - } itp_stop(); //stop tools #ifdef USE_SPINDLE @@ -333,19 +248,47 @@ extern "C" #endif } - void cnc_unlock(void) + bool cnc_unlock(bool force) { - //on unlock any alarm caused by not having homing reference or hitting a limit switch is reset at user request - //this must be done directly beacuse cnc_clear_exec_state will check the limit switch state - //all other alarm flags remain active if any input is still active - CLEARFLAG(cnc_state.exec_state, EXEC_LIMITS); - //clears all other locking flags - cnc_clear_exec_state(EXEC_GCODE_LOCKED | EXEC_HOLD); - //signals stepper enable pins - - io_set_steps(g_settings.step_invert_mask); - io_set_dirs(g_settings.dir_invert_mask); - io_enable_steps(); + //tries to clear alarms or any active hold state + cnc_clear_exec_state(EXEC_ALARM | EXEC_HOLD); + //checks all interlocking again + cnc_check_interlocking(); + + //forces to clear HALT error to allow motion after limit switch trigger + if (force) + { + CLEARFLAG(cnc_state.exec_state, EXEC_HALT); + } + + //if any alarm state is still active checks system faults + if (cnc_get_exec_state(EXEC_ALARM)) + { + if (!cnc_get_exec_state(EXEC_KILL)) + { + protocol_send_feedback(MSG_FEEDBACK_2); + } + else + { + return false; + } + } + else + { + //on unlock any alarm caused by not having homing reference or hitting a limit switch is reset at user request + //this must be done directly beacuse cnc_clear_exec_state will check the limit switch state + //all other alarm flags remain active if any input is still active + CLEARFLAG(cnc_state.exec_state, EXEC_HALT); + //clears all other locking flags + cnc_clear_exec_state(EXEC_GCODE_LOCKED | EXEC_HOLD); + //signals stepper enable pins + + io_set_steps(g_settings.step_invert_mask); + io_set_dirs(g_settings.dir_invert_mask); + io_enable_steps(); + } + + return true; } uint8_t cnc_get_exec_state(uint8_t statemask) @@ -383,13 +326,13 @@ extern "C" uint8_t limits = 0; #if (LIMITS_MASK != 0) - limits = io_get_limits(); //can't clear the EXEC_LIMITS is any limit is triggered + limits = io_get_limits(); //can't clear the EXEC_HALT is any limit is triggered #endif if (g_settings.hard_limits_enabled) //if hardlimits are enabled and limits are triggered { if (limits || g_settings.homing_enabled) { - CLEARFLAG(statemask, EXEC_LIMITS); + CLEARFLAG(statemask, EXEC_HALT); } } @@ -433,28 +376,89 @@ extern "C" planner_clear(); protocol_send_string(MSG_STARTUP); - //tries to clear alarms or any active hold state - cnc_clear_exec_state(EXEC_ALARM | EXEC_HOLD); + return cnc_unlock(false); + } - //if any alarm state is still active checks system faults - if (cnc_get_exec_state(EXEC_ALARM)) + void cnc_call_rt_command(uint8_t command) + { + //executes the realtime commands + //only reset command is executed right away + //control commands affect the exec_state directly (Abort, hold, safety door, cycle_start) + //the effects are then propagate in the cnc_dotasks + //uses macro to be faster + switch (command) { - //cnc_check_fault_systems(); - if (!cnc_get_exec_state(EXEC_KILL)) - { - protocol_send_feedback(MSG_FEEDBACK_2); - } - else + case CMD_CODE_RESET: + SETFLAG(cnc_state.rt_cmd, RT_CMD_RESET); + SETFLAG(cnc_state.exec_state, EXEC_KILL); + break; + case CMD_CODE_FEED_HOLD: + SETFLAG(cnc_state.exec_state, EXEC_HOLD); + break; + case CMD_CODE_REPORT: + SETFLAG(cnc_state.rt_cmd, RT_CMD_REPORT); + break; + case CMD_CODE_CYCLE_START: + SETFLAG(cnc_state.rt_cmd, RT_CMD_CYCLE_START); //tries to clear hold if possible + break; + case CMD_CODE_SAFETY_DOOR: + SETFLAG(cnc_state.exec_state, (EXEC_HOLD | EXEC_DOOR)); + break; + case CMD_CODE_JOG_CANCEL: + if (CHECKFLAG(cnc_state.exec_state, EXEC_JOG)) { - return false; + SETFLAG(cnc_state.exec_state, EXEC_HOLD); } + break; + case CMD_CODE_FEED_100: + SETFLAG(cnc_state.feed_ovr_cmd, RT_CMD_FEED_100); + break; + case CMD_CODE_FEED_INC_COARSE: + SETFLAG(cnc_state.feed_ovr_cmd, RT_CMD_FEED_INC_COARSE); + break; + case CMD_CODE_FEED_DEC_COARSE: + SETFLAG(cnc_state.feed_ovr_cmd, RT_CMD_FEED_DEC_COARSE); + break; + case CMD_CODE_FEED_INC_FINE: + SETFLAG(cnc_state.feed_ovr_cmd, RT_CMD_FEED_INC_FINE); + break; + case CMD_CODE_FEED_DEC_FINE: + SETFLAG(cnc_state.feed_ovr_cmd, RT_CMD_FEED_DEC_FINE); + break; + case CMD_CODE_RAPIDFEED_100: + SETFLAG(cnc_state.feed_ovr_cmd, RT_CMD_RAPIDFEED_100); + break; + case CMD_CODE_RAPIDFEED_OVR1: + SETFLAG(cnc_state.feed_ovr_cmd, RT_CMD_RAPIDFEED_OVR1); + break; + case CMD_CODE_RAPIDFEED_OVR2: + SETFLAG(cnc_state.feed_ovr_cmd, RT_CMD_RAPIDFEED_OVR2); + break; + case CMD_CODE_SPINDLE_100: + SETFLAG(cnc_state.tool_ovr_cmd, RT_CMD_SPINDLE_100); + break; + case CMD_CODE_SPINDLE_INC_COARSE: + SETFLAG(cnc_state.tool_ovr_cmd, RT_CMD_SPINDLE_INC_COARSE); + break; + case CMD_CODE_SPINDLE_DEC_COARSE: + SETFLAG(cnc_state.tool_ovr_cmd, RT_CMD_SPINDLE_DEC_COARSE); + break; + case CMD_CODE_SPINDLE_INC_FINE: + SETFLAG(cnc_state.tool_ovr_cmd, RT_CMD_SPINDLE_INC_FINE); + break; + case CMD_CODE_SPINDLE_DEC_FINE: + SETFLAG(cnc_state.tool_ovr_cmd, RT_CMD_SPINDLE_DEC_FINE); + break; + case CMD_CODE_SPINDLE_TOGGLE: + SETFLAG(cnc_state.tool_ovr_cmd, RT_CMD_SPINDLE_TOGGLE); + break; + case CMD_CODE_COOL_FLD_TOGGLE: + SETFLAG(cnc_state.tool_ovr_cmd, RT_CMD_COOL_FLD_TOGGLE); + break; + case CMD_CODE_COOL_MST_TOGGLE: + SETFLAG(cnc_state.tool_ovr_cmd, RT_CMD_COOL_MST_TOGGLE); + break; } - else - { - cnc_unlock(); - } - - return true; } //Executes pending realtime commands @@ -470,19 +474,15 @@ extern "C" //executes feeds override rt commands uint8_t cmd_mask = 0x04; - uint8_t command = cnc_state.rt_cmd; //copies realtime flags states - CLEARFLAG(cnc_state.rt_cmd, ~RT_CMD_REPORT); //clears all command flags except report request + uint8_t command = cnc_state.rt_cmd; //copies realtime flags states + CLEARFLAG(cnc_state.rt_cmd, ~(RT_CMD_REPORT)); //clears all command flags except report request while (command) { switch (command & cmd_mask) { case RT_CMD_RESET: - cnc_clear_exec_state(EXEC_KILL); - if (cnc_get_exec_state(EXEC_KILL)) - { - cnc_check_fault_systems(); - } - break; + cnc_alarm(EXEC_ALARM_RESET); + return; case RT_CMD_REPORT: if (!protocol_is_busy() && !(cnc_state.loop_state & LOOP_STARTUP)) { @@ -619,19 +619,19 @@ extern "C" void cnc_check_fault_systems(void) { - bool fail = false; - uint8_t inputs = io_get_controls(); + uint8_t inputs; +#ifdef CONTROLS_MASK + inputs = io_get_controls(); +#endif #ifdef ESTOP if (CHECKFLAG(inputs, ESTOP_MASK)) //fault on emergency stop { - fail = true; protocol_send_feedback(MSG_FEEDBACK_12); } #endif #ifdef SAFETY_DOOR if (CHECKFLAG(inputs, SAFETY_DOOR_MASK)) //fault on safety door { - fail = true; protocol_send_feedback(MSG_FEEDBACK_6); } #endif @@ -641,13 +641,12 @@ extern "C" inputs = io_get_limits(); if (CHECKFLAG(inputs, LIMITS_MASK)) { - fail = true; protocol_send_feedback(MSG_FEEDBACK_7); } } #endif - if (fail) + if (cnc_get_exec_state(EXEC_KILL)) { protocol_send_feedback(MSG_FEEDBACK_1); } @@ -659,6 +658,14 @@ extern "C" //if kill leave if (CHECKFLAG(cnc_state.exec_state, EXEC_KILL)) { +#ifdef ESTOP + //the emergency stop is pressed. + if (io_get_controls() & ESTOP_MASK) + { + cnc_alarm(EXEC_ALARM_EMERGENCY_STOP); + return false; + } +#endif if (CHECKFLAG(cnc_state.exec_state, EXEC_HOMING)) //reset or emergency stop during a homing cycle { cnc_alarm(EXEC_ALARM_HOMING_FAIL_RESET); @@ -674,15 +681,15 @@ extern "C" return false; } - if (CHECKFLAG(cnc_state.exec_state, EXEC_DOOR) & CHECKFLAG(cnc_state.exec_state, EXEC_HOMING)) //door opened during a homing cycle + if (CHECKFLAG(cnc_state.exec_state, EXEC_DOOR) && CHECKFLAG(cnc_state.exec_state, EXEC_HOMING)) //door opened during a homing cycle { cnc_alarm(EXEC_ALARM_HOMING_FAIL_DOOR); return false; } - if (CHECKFLAG(cnc_state.exec_state, EXEC_LIMITS)) + if (CHECKFLAG(cnc_state.exec_state, EXEC_HALT) && CHECKFLAG(cnc_state.exec_state, EXEC_RUN)) { - if (CHECKFLAG(cnc_state.exec_state, EXEC_RUN)) //if a motion is being performed allow trigger the limit switch alarm + if (!CHECKFLAG(cnc_state.exec_state, EXEC_HOMING) && io_get_limits()) //if a motion is being performed allow trigger the limit switch alarm { cnc_alarm(EXEC_ALARM_HARD_LIMIT); } @@ -690,8 +697,8 @@ extern "C" return false; } - //opened door or hold with the machine still - if (CHECKFLAG(cnc_state.exec_state, EXEC_DOOR | EXEC_HOLD) & !CHECKFLAG(cnc_state.exec_state, EXEC_RUN)) + //opened door or hold with the machine still moving + if (CHECKFLAG(cnc_state.exec_state, EXEC_DOOR | EXEC_HOLD) && !CHECKFLAG(cnc_state.exec_state, EXEC_RUN)) { itp_stop(); if (CHECKFLAG(cnc_state.exec_state, EXEC_DOOR)) diff --git a/src/cnc.h b/src/cnc.h index 2a9ce6204..a2a95b4c7 100644 --- a/src/cnc.h +++ b/src/cnc.h @@ -57,10 +57,10 @@ extern "C" #define EXEC_HOLD 4 // Feed hold is active #define EXEC_JOG 8 // Jogging in execution #define EXEC_HOMING 16 // Homing in execution -#define EXEC_LIMITS 32 // Limit switch is active or position lost +#define EXEC_HALT 32 // Limit switch is active or position lost due to abrupt stop #define EXEC_DOOR 64 // Safety door open #define EXEC_KILL 128 // Emergency stop -#define EXEC_ALARM (EXEC_LIMITS | EXEC_DOOR | EXEC_KILL) // System alarms +#define EXEC_ALARM (EXEC_HALT | EXEC_DOOR | EXEC_KILL) // System alarms #define EXEC_GCODE_LOCKED (EXEC_ALARM | EXEC_HOMING | EXEC_JOG) // Gcode is locked by an alarm or any special motion state #define EXEC_ALLACTIVE 255 // All states @@ -195,7 +195,7 @@ extern "C" void cnc_home(void); void cnc_alarm(uint8_t code); void cnc_stop(void); - void cnc_unlock(void); + bool cnc_unlock(bool force); void cnc_delay_ms(uint32_t miliseconds); uint8_t cnc_get_exec_state(uint8_t statemask); diff --git a/src/core/interpolator.c b/src/core/interpolator.c index 437fe0dc3..2c1a50ec8 100644 --- a/src/core/interpolator.c +++ b/src/core/interpolator.c @@ -488,6 +488,11 @@ extern "C" void itp_stop(void) { + // any stop command while running triggers an HALT alarm + if (cnc_get_exec_state(EXEC_RUN)) + { + cnc_set_exec_state(EXEC_HALT); + } io_set_steps(g_settings.step_invert_mask); io_set_dirs(g_settings.dir_invert_mask); #ifdef LASER_MODE @@ -712,8 +717,8 @@ extern "C" { mcu_disable_global_isr(); itp_busy = false; - itp_stop(); //the buffer is empty. The ISR can stop cnc_clear_exec_state(EXEC_RUN); //this naturally clears the RUN flag. Any other ISR stop does not clear the flag. + itp_stop(); //the buffer is empty. The ISR can stop return; } } diff --git a/src/core/io_control.c b/src/core/io_control.c index 42eca9c94..48970e985 100644 --- a/src/core/io_control.c +++ b/src/core/io_control.c @@ -72,8 +72,8 @@ extern "C" #ifdef ENABLE_DUAL_DRIVE_AXIS itp_lock_stepper(0); //unlocks axis #endif - cnc_set_exec_state(EXEC_LIMITS); itp_stop(); + cnc_set_exec_state(EXEC_HALT); } } } @@ -85,7 +85,7 @@ extern "C" #ifdef ESTOP if (CHECKFLAG(controls, ESTOP_MASK)) { - cnc_call_rt_command(CMD_CODE_RESET); + cnc_set_exec_state(EXEC_KILL); return; //forces exit } #endif @@ -93,13 +93,13 @@ extern "C" if (CHECKFLAG(controls, SAFETY_DOOR_MASK)) { //safety door activates hold simultaneously to start the controlled stop - cnc_call_rt_command(CMD_CODE_SAFETY_DOOR); + cnc_set_exec_state(EXEC_DOOR | EXEC_HOLD); } #endif #ifdef FHOLD if (CHECKFLAG(controls, FHOLD_MASK)) { - cnc_call_rt_command(CMD_CODE_FEED_HOLD); + cnc_set_exec_state(EXEC_HOLD); } #endif #ifdef CS_RES diff --git a/src/core/motion_control.c b/src/core/motion_control.c index 25a6ed3bf..8e189f9d3 100644 --- a/src/core/motion_control.c +++ b/src/core/motion_control.c @@ -500,7 +500,7 @@ extern "C" #endif #endif - cnc_unlock(); + cnc_unlock(true); //if HOLD or ALARM are still active or any limit switch is not cleared fails to home if (cnc_get_exec_state(EXEC_HOLD | EXEC_ALARM) || CHECKFLAG(io_get_limits(), LIMITS_MASK)) @@ -530,7 +530,7 @@ extern "C" block_data.spindle = 0; block_data.dwell = 0; block_data.motion_mode = MOTIONCONTROL_MODE_FEED; - cnc_unlock(); + cnc_unlock(true); mc_line(target, &block_data); //flags homing clear by the unlock cnc_set_exec_state(EXEC_HOMING); @@ -547,11 +547,6 @@ extern "C" itp_clear(); planner_clear(); - if (cnc_get_exec_state(EXEC_KILL)) - { - return EXEC_ALARM_HOMING_FAIL_RESET; - } - cnc_delay_ms(g_settings.debounce_ms); //adds a delay before reading io pin (debounce) limits_flags = io_get_limits(); @@ -577,11 +572,11 @@ extern "C" block_data.feed = g_settings.homing_slow_feed_rate; block_data.total_steps = ABS(max_home_dist); block_data.steps[axis] = max_home_dist; - //unlocks the machine for next motion (this will clear the EXEC_LIMITS flag + //unlocks the machine for next motion (this will clear the EXEC_HALT flag //temporary inverts the limit mask to trigger ISR on switch release g_settings.limits_invert_mask ^= axis_limit; //io_set_homing_limits_filter(LIMITS_DUAL_MASK);//if axis pin goes off triggers - cnc_unlock(); + cnc_unlock(true); mc_line(target, &block_data); //flags homing clear by the unlock cnc_set_exec_state(EXEC_HOMING); @@ -602,11 +597,6 @@ extern "C" itp_clear(); planner_clear(); - if (cnc_get_exec_state(EXEC_KILL)) - { - return EXEC_ALARM_HOMING_FAIL_RESET; - } - cnc_delay_ms(g_settings.debounce_ms); //adds a delay before reading io pin (debounce) limits_flags = io_get_limits(); diff --git a/src/core/parser.c b/src/core/parser.c index be0f024a4..1bf5791e4 100644 --- a/src/core/parser.c +++ b/src/core/parser.c @@ -620,7 +620,7 @@ extern "C" protocol_send_feedback(MSG_FEEDBACK_9); return STATUS_OK; case GRBL_UNLOCK: - cnc_unlock(); + cnc_unlock(true); if (cnc_get_exec_state(EXEC_DOOR)) { return STATUS_CHECK_DOOR; @@ -633,7 +633,7 @@ extern "C" return STATUS_SETTING_DISABLED; } - cnc_unlock(); + cnc_unlock(true); if (cnc_get_exec_state(EXEC_DOOR)) { return STATUS_CHECK_DOOR; diff --git a/src/interface/grbl_interface.h b/src/interface/grbl_interface.h index 90687c70c..070cccb8e 100644 --- a/src/interface/grbl_interface.h +++ b/src/interface/grbl_interface.h @@ -112,7 +112,7 @@ extern "C" #define GRBL_JOG_CMD (GRBL_SYSTEM_CMD + 9) #define EXEC_ALARM_RESET 0 -// Grbl alarm codes. Valid values (1-255). Zero is reserved. +// Grbl alarm codes. Valid values (1-255). Zero is reserved for the reset alarm. #define EXEC_ALARM_HARD_LIMIT 1 #define EXEC_ALARM_SOFT_LIMIT 2 #define EXEC_ALARM_ABORT_CYCLE 3 @@ -124,6 +124,7 @@ extern "C" #define EXEC_ALARM_HOMING_FAIL_APPROACH 9 #define EXEC_ALARM_HOMING_FAIL_DUAL_APPROACH 10 #define EXEC_ALARM_HOMING_FAIL_LIMIT_ACTIVE 11 +#define EXEC_ALARM_EMERGENCY_STOP 12 //formated messages #define STR_EOL "\r\n" diff --git a/src/interface/protocol.c b/src/interface/protocol.c index b73471964..1b04ab703 100644 --- a/src/interface/protocol.c +++ b/src/interface/protocol.c @@ -206,7 +206,7 @@ extern "C" } } break; - case EXEC_LIMITS: + case EXEC_HALT: serial_print_str(MSG_STATUS_ALARM); break; case EXEC_HOLD: diff --git a/src/interface/serial.c b/src/interface/serial.c index 63bb76b6e..897e14495 100644 --- a/src/interface/serial.c +++ b/src/interface/serial.c @@ -80,10 +80,7 @@ extern "C" case SERIAL_UART: while (serial_rx_write == serial_rx_read) { - if (!cnc_dotasks()) - { - return STATUS_CRITICAL_FAIL; - } + cnc_dotasks(); } c = serial_rx_buffer[serial_rx_read]; @@ -154,10 +151,7 @@ extern "C" case SERIAL_UART: while (serial_rx_write == serial_rx_read) { - if (!cnc_dotasks()) - { - return STATUS_CRITICAL_FAIL; - } + cnc_dotasks(); } c = serial_rx_buffer[serial_rx_read]; switch (c) @@ -199,10 +193,7 @@ extern "C" } while (write == serial_tx_read) { - if (!cnc_dotasks()) //on any alarm abort - { - return; - } + cnc_dotasks(); } //while buffer is full serial_tx_buffer[serial_tx_write] = c; @@ -214,10 +205,7 @@ extern "C" #else while (!mcu_tx_ready()) { - if (!cnc_dotasks()) //on any alarm abort - { - return; - } + cnc_dotasks(); } mcu_putc(c); #endif @@ -352,10 +340,7 @@ extern "C" while (serial_tx_write != serial_tx_read) { mcu_putc(0); - if (!cnc_dotasks()) - { - return; - } + cnc_dotasks(); } #endif } From d75beb87df79b1a973e8618c18e18443488a091f Mon Sep 17 00:00:00 2001 From: Paciente8159 Date: Thu, 5 Aug 2021 18:18:40 +0100 Subject: [PATCH 16/24] fixed homing with new interlocking -fixed homing with new interlocking --- src/cnc.c | 8 ++++++-- src/core/motion_control.c | 23 ++++++++++++++++------- src/core/parser.c | 2 +- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/cnc.c b/src/cnc.c index 007cef4d7..9162a5688 100644 --- a/src/cnc.c +++ b/src/cnc.c @@ -197,7 +197,7 @@ extern "C" { //disables homing and reenables alarm messages cnc_clear_exec_state(EXEC_HOMING); - cnc_alarm(error); + //cnc_alarm(error); return; } @@ -676,7 +676,7 @@ extern "C" } else { - cnc_alarm(EXEC_ALARM_RESET); //reset or emergency stop + cnc_alarm(cnc_state.alarm); //reset or emergency stop or any other (software) alarm } return false; } @@ -693,6 +693,10 @@ extern "C" { cnc_alarm(EXEC_ALARM_HARD_LIMIT); } + else + { + CLEARFLAG(cnc_state.exec_state, EXEC_RUN); + } return false; } diff --git a/src/core/motion_control.c b/src/core/motion_control.c index 8e189f9d3..24e129732 100644 --- a/src/core/motion_control.c +++ b/src/core/motion_control.c @@ -503,9 +503,11 @@ extern "C" cnc_unlock(true); //if HOLD or ALARM are still active or any limit switch is not cleared fails to home - if (cnc_get_exec_state(EXEC_HOLD | EXEC_ALARM) || CHECKFLAG(io_get_limits(), LIMITS_MASK)) + io_limits_isr(); + if (cnc_get_exec_state(EXEC_HOLD | EXEC_ALARM) /*|| CHECKFLAG(io_get_limits(), LIMITS_MASK)*/) { - return EXEC_ALARM_HOMING_FAIL_LIMIT_ACTIVE; + cnc_alarm(EXEC_ALARM_HOMING_FAIL_LIMIT_ACTIVE); + return STATUS_CRITICAL_FAIL; } io_set_homing_limits_filter(axis_limit); @@ -530,10 +532,12 @@ extern "C" block_data.spindle = 0; block_data.dwell = 0; block_data.motion_mode = MOTIONCONTROL_MODE_FEED; + cnc_unlock(true); - mc_line(target, &block_data); - //flags homing clear by the unlock + //re-flags homing clear by the unlock cnc_set_exec_state(EXEC_HOMING); + mc_line(target, &block_data); + do { if (!cnc_dotasks()) @@ -553,7 +557,9 @@ extern "C" //the wrong switch was activated bails if (!CHECKFLAG(limits_flags, axis_limit)) { - return EXEC_ALARM_HOMING_FAIL_APPROACH; + cnc_set_exec_state(EXEC_HALT); + cnc_alarm(EXEC_ALARM_HOMING_FAIL_APPROACH); + return STATUS_CRITICAL_FAIL; } //back off from switch at lower speed @@ -602,7 +608,9 @@ extern "C" if (CHECKFLAG(limits_flags, axis_limit)) { - return EXEC_ALARM_HOMING_FAIL_APPROACH; + cnc_set_exec_state(EXEC_HALT); + cnc_alarm(EXEC_ALARM_HOMING_FAIL_APPROACH); + return STATUS_CRITICAL_FAIL; } return STATUS_OK; @@ -641,7 +649,8 @@ extern "C" bool probe_notok = (!invert_probe) ? io_get_probe() : !io_get_probe(); if (probe_notok) { - return EXEC_ALARM_PROBE_FAIL_CONTACT; + cnc_alarm(EXEC_ALARM_PROBE_FAIL_CONTACT); + return STATUS_CRITICAL_FAIL; } #endif diff --git a/src/core/parser.c b/src/core/parser.c index 1bf5791e4..0d4bfb698 100644 --- a/src/core/parser.c +++ b/src/core/parser.c @@ -1462,7 +1462,7 @@ extern "C" parser_parameters.last_probe_ok = 0; if (!(new_state->groups.motion & 0x01)) { - cnc_alarm(probe_error); + return probe_error; } } parser_parameters.last_probe_ok = 1; From 8ab85f3d7e794f68e7c7df24cd31020bcf746537 Mon Sep 17 00:00:00 2001 From: Paciente8159 Date: Thu, 5 Aug 2021 19:34:36 +0100 Subject: [PATCH 17/24] Update protocol.c -fixed hidden probe alarm if it's the only active --- src/interface/protocol.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/interface/protocol.c b/src/interface/protocol.c index 1b04ab703..7facfed43 100644 --- a/src/interface/protocol.c +++ b/src/interface/protocol.c @@ -163,6 +163,7 @@ extern "C" #endif uint8_t controls = io_get_controls(); uint8_t limits = io_get_limits(); + bool probe = io_get_probe(); uint8_t state = cnc_get_exec_state(0xFF); uint8_t filter = 0x80; while (!(state & filter) && filter) @@ -259,7 +260,7 @@ extern "C" serial_print_long(itp_get_rt_line_number()); #endif - if (CHECKFLAG(controls, (ESTOP_MASK | SAFETY_DOOR_MASK | FHOLD_MASK)) | CHECKFLAG(limits, LIMITS_MASK)) + if (CHECKFLAG(controls, (ESTOP_MASK | SAFETY_DOOR_MASK | FHOLD_MASK)) || CHECKFLAG(limits, LIMITS_MASK) || probe) { serial_print_str(MSG_STATUS_PIN); @@ -278,7 +279,7 @@ extern "C" serial_putc('H'); } - if (io_get_probe()) + if (probe) { serial_putc('P'); } From ba2de0eb89c1bbb843429b8566a133530d0eef1e Mon Sep 17 00:00:00 2001 From: Paciente8159 Date: Thu, 5 Aug 2021 21:06:39 +0100 Subject: [PATCH 18/24] fixed probing -fixed probing motion alarms and flags -fixed probing position (translation from steps to units was missing) --- src/core/motion_control.c | 10 ++++++---- src/core/parser.c | 9 ++++++++- src/core/parser.h | 1 + 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/core/motion_control.c b/src/core/motion_control.c index 24e129732..387b06d65 100644 --- a/src/core/motion_control.c +++ b/src/core/motion_control.c @@ -621,7 +621,7 @@ extern "C" #ifdef PROBE uint8_t prev_state = cnc_get_exec_state(EXEC_HOLD); io_enable_probe(); - + block_data->feed = g_settings.homing_fast_feed_rate; mc_line(target, block_data); do @@ -641,13 +641,15 @@ extern "C" } while (cnc_get_exec_state(EXEC_RUN)); io_disable_probe(); - itp_stop(); + cnc_stop(); itp_clear(); planner_clear(); + parser_update_probe_pos(); cnc_clear_exec_state(~prev_state & EXEC_HOLD); //restores HOLD previous state cnc_delay_ms(g_settings.debounce_ms); //adds a delay before reading io pin (debounce) - bool probe_notok = (!invert_probe) ? io_get_probe() : !io_get_probe(); - if (probe_notok) + bool probe_ok = io_get_probe(); + probe_ok = (!invert_probe) ? probe_ok : !probe_ok; + if (!probe_ok) { cnc_alarm(EXEC_ALARM_PROBE_FAIL_CONTACT); return STATUS_CRITICAL_FAIL; diff --git a/src/core/parser.c b/src/core/parser.c index 0d4bfb698..9b5febff6 100644 --- a/src/core/parser.c +++ b/src/core/parser.c @@ -256,6 +256,7 @@ extern "C" static parser_parameters_t parser_parameters; static uint8_t parser_wco_counter; static float g92permanentoffset[AXIS_COUNT]; + static int32_t rt_probe_step_pos[STEPPER_COUNT]; static unsigned char parser_get_next_preprocessed(bool peek); FORCEINLINE static uint8_t parser_get_comment(void); @@ -423,7 +424,13 @@ extern "C" void parser_sync_probe(void) { - itp_get_rt_position(parser_parameters.last_probe_position); + itp_get_rt_position(rt_probe_step_pos); + } + + void parser_update_probe_pos(void) + { + kinematics_apply_forward(rt_probe_step_pos, parser_parameters.last_probe_position); + kinematics_apply_reverse_transform(parser_parameters.last_probe_position); } static uint8_t parser_grbl_command(void) diff --git a/src/core/parser.h b/src/core/parser.h index 1ae0432c6..bacd981f2 100644 --- a/src/core/parser.h +++ b/src/core/parser.h @@ -44,6 +44,7 @@ void parser_update_coolant(uint8_t state); void parser_toogle_coolant(uint8_t state); #endif*/ void parser_sync_probe(void); + void parser_update_probe_pos(void); uint8_t parser_get_probe_result(void); void parser_parameters_load(void); void parser_parameters_reset(void); From b7b3db9e1d9946d7d61f073277c16adc95f1d5e0 Mon Sep 17 00:00:00 2001 From: Paciente8159 Date: Fri, 6 Aug 2021 10:34:01 +0100 Subject: [PATCH 19/24] cleaner startup and running code -broke cnc code into smaller sections and connected the new blocks in a cleaner way -fixed step enabling logic (negative logic) -stepper enabling after correct reset -only reset, hard and soft limits alarms will require reset has stated in the Grbl interface. With a reset alarm steppers will be disabled also. --- src/cnc.c | 136 +++++++++++++++++++++++------------------- src/cnc.h | 2 +- src/core/io_control.c | 24 +++++++- src/core/io_control.h | 3 +- 4 files changed, 101 insertions(+), 64 deletions(-) diff --git a/src/cnc.c b/src/cnc.c index 9162a5688..12878ed7b 100644 --- a/src/cnc.c +++ b/src/cnc.c @@ -39,12 +39,12 @@ extern "C" #include "modules/pid_controller.h" #define LOOP_STARTUP_RESET 0 -#define LOOP_STARTUP_BLOCK0 1 -#define LOOP_STARTUP_BLOCK1 2 -#define LOOP_RUNNING 4 -#define LOOP_ERROR_RESET 8 -#define LOOP_STARTUP_BLOCKS (LOOP_STARTUP_BLOCK0 | LOOP_STARTUP_BLOCK1) -#define LOOP_STARTUP (LOOP_STARTUP_RESET | LOOP_STARTUP_BLOCKS) +#define LOOP_RUNNING 1 +#define LOOP_ERROR_RESET 2 + +#define UNLOCK_ERROR 0 +#define UNLOCK_LOCKED 1 +#define UNLOCK_OK 2 typedef struct { @@ -59,10 +59,11 @@ extern "C" static cnc_state_t cnc_state; - static void cnc_check_fault_systems(); - static bool cnc_check_interlocking(); - static void cnc_exec_rt_commands(); - static bool cnc_reset(); + static void cnc_check_fault_systems(void); + static bool cnc_check_interlocking(void); + static void cnc_exec_rt_commands(void); + static bool cnc_reset(void); + static void cnc_exec_cmd(void); void cnc_init(void) { @@ -72,18 +73,18 @@ extern "C" #endif cnc_state.loop_state = LOOP_STARTUP_RESET; //initializes all systems - mcu_init(); //mcu - mcu_disable_probe_isr(); //forces probe isr disabling - serial_init(); //serial - settings_init(); //settings - itp_init(); //interpolator - planner_init(); //motion planner - mc_init(); //motion control - parser_init(); //parser + mcu_init(); //mcu + io_disable_steppers(); //disables steppers at start + io_disable_probe(); //forces probe isr disabling + serial_init(); //serial + settings_init(); //settings + itp_init(); //interpolator + planner_init(); //motion planner + mc_init(); //motion control + parser_init(); //parser #if PID_CONTROLLERS > 0 pid_init(); //pid #endif - io_enable_steps(); //enables stepper motors } void cnc_run(void) @@ -91,51 +92,20 @@ extern "C" // tries to reset. If fails jumps to error if (cnc_reset()) { - cnc_state.loop_state = LOOP_STARTUP_BLOCK0; - serial_select(SERIAL_N0); + cnc_state.loop_state = LOOP_RUNNING; + serial_select(SERIAL_UART); do { - //process gcode commands - if (!serial_rx_is_empty()) - { - uint8_t error = 0; - //protocol_echo(); - uint8_t c = serial_peek(); - switch (c) - { - case EOL: //not necessary but faster to catch empty lines and windows newline (CR+LF) - serial_getc(); - break; - default: - error = parser_read_command(); - break; - } - if (!error) - { - protocol_send_ok(); - } - else - { - protocol_send_error(error); - } - } - - if (cnc_state.loop_state != LOOP_RUNNING) - { - cnc_state.loop_state <<= 1; - if (cnc_state.loop_state == LOOP_STARTUP_BLOCK1) - { - serial_select(SERIAL_N1); - } - } + cnc_exec_cmd(); } while (cnc_dotasks()); } cnc_state.loop_state = LOOP_ERROR_RESET; serial_flush(); - if (cnc_state.alarm) + if (cnc_state.alarm < EXEC_ALARM_PROBE_FAIL_INITIAL) { + io_disable_steppers(); protocol_send_alarm(cnc_state.alarm); cnc_check_fault_systems(); do @@ -146,6 +116,34 @@ extern "C" } } + void cnc_exec_cmd(void) + { + //process gcode commands + if (!serial_rx_is_empty()) + { + uint8_t error = 0; + //protocol_echo(); + uint8_t c = serial_peek(); + switch (c) + { + case EOL: //not necessary but faster to catch empty lines and windows newline (CR+LF) + serial_getc(); + break; + default: + error = parser_read_command(); + break; + } + if (!error) + { + protocol_send_ok(); + } + else + { + protocol_send_error(error); + } + } + } + bool cnc_dotasks(void) { static bool lock_itp = false; @@ -248,7 +246,7 @@ extern "C" #endif } - bool cnc_unlock(bool force) + uint8_t cnc_unlock(bool force) { //tries to clear alarms or any active hold state cnc_clear_exec_state(EXEC_ALARM | EXEC_HOLD); @@ -267,10 +265,11 @@ extern "C" if (!cnc_get_exec_state(EXEC_KILL)) { protocol_send_feedback(MSG_FEEDBACK_2); + return UNLOCK_LOCKED; } else { - return false; + return UNLOCK_ERROR; } } else @@ -285,10 +284,10 @@ extern "C" io_set_steps(g_settings.step_invert_mask); io_set_dirs(g_settings.dir_invert_mask); - io_enable_steps(); + io_enable_steppers(); } - return true; + return UNLOCK_OK; } uint8_t cnc_get_exec_state(uint8_t statemask) @@ -376,7 +375,22 @@ extern "C" planner_clear(); protocol_send_string(MSG_STARTUP); - return cnc_unlock(false); + uint8_t ok = cnc_unlock(false); + + if (ok == UNLOCK_OK) + { + serial_select(SERIAL_N0); + cnc_exec_cmd(); + serial_select(SERIAL_N1); + cnc_exec_cmd(); + } + + if (ok) + { + io_enable_steppers(); + } + + return (ok != 0); } void cnc_call_rt_command(uint8_t command) @@ -484,7 +498,7 @@ extern "C" cnc_alarm(EXEC_ALARM_RESET); return; case RT_CMD_REPORT: - if (!protocol_is_busy() && !(cnc_state.loop_state & LOOP_STARTUP)) + if (!protocol_is_busy() && cnc_state.loop_state) { protocol_send_status(); CLEARFLAG(cnc_state.rt_cmd, RT_CMD_REPORT); //if a report request is sent, clear the respective flag diff --git a/src/cnc.h b/src/cnc.h index a2a95b4c7..9d29cdc8c 100644 --- a/src/cnc.h +++ b/src/cnc.h @@ -195,7 +195,7 @@ extern "C" void cnc_home(void); void cnc_alarm(uint8_t code); void cnc_stop(void); - bool cnc_unlock(bool force); + uint8_t cnc_unlock(bool force); void cnc_delay_ms(uint32_t miliseconds); uint8_t cnc_get_exec_state(uint8_t statemask); diff --git a/src/core/io_control.c b/src/core/io_control.c index 48970e985..4fd064f92 100644 --- a/src/core/io_control.c +++ b/src/core/io_control.c @@ -481,7 +481,7 @@ extern "C" #endif } - void io_enable_steps(void) + void io_disable_steppers(void) { #ifdef STEPPER_ENABLE mcu_set_output(STEPPER_ENABLE); @@ -503,6 +503,28 @@ extern "C" #endif } + void io_enable_steppers(void) + { +#ifdef STEPPER_ENABLE + mcu_clear_output(STEPPER_ENABLE); +#endif +#ifdef STEPPER1_ENABLE + mcu_clear_output(STEPPER1_ENABLE); +#endif +#ifdef STEPPER2_ENABLE + mcu_clear_output(STEPPER2_ENABLE); +#endif +#ifdef STEPPER3_ENABLE + mcu_clear_output(STEPPER3_ENABLE); +#endif +#ifdef STEPPER4_ENABLE + mcu_clear_output(STEPPER4_ENABLE); +#endif +#ifdef STEPPER5_ENABLE + mcu_clear_output(STEPPER5_ENABLE); +#endif + } + #ifdef USE_SPINDLE void io_set_spindle(uint8_t value, bool invert) { diff --git a/src/core/io_control.h b/src/core/io_control.h index 93d9d5233..ebfc3c828 100644 --- a/src/core/io_control.h +++ b/src/core/io_control.h @@ -217,7 +217,8 @@ extern "C" void io_toggle_steps(uint8_t mask); void io_set_dirs(uint8_t mask); - void io_enable_steps(void); + void io_enable_steppers(void); + void io_disable_steppers(void); #ifdef USE_SPINDLE void io_set_spindle(uint8_t value, bool invert); From 3176dea1513c64fe281b99b1c08f2e106b164618 Mon Sep 17 00:00:00 2001 From: Paciente8159 Date: Fri, 6 Aug 2021 11:25:03 +0100 Subject: [PATCH 20/24] fixed axis drifting after home -fixed axis drifting after homing. This happened on all motions until a target of that axis is specified --- src/cnc.c | 3 ++- src/core/motion_control.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/cnc.c b/src/cnc.c index 12878ed7b..0c5410694 100644 --- a/src/cnc.c +++ b/src/cnc.c @@ -203,7 +203,7 @@ extern "C" cnc_unlock(true); float target[AXIS_COUNT]; - motion_data_t block_data; + motion_data_t block_data = {0}; mc_get_position(target); for (uint8_t i = AXIS_COUNT; i != 0;) @@ -225,6 +225,7 @@ extern "C" //reset position itp_reset_rt_position(); planner_sync_position(); + mc_resync_position(); } void cnc_alarm(uint8_t code) diff --git a/src/core/motion_control.c b/src/core/motion_control.c index 387b06d65..1c874dbda 100644 --- a/src/core/motion_control.c +++ b/src/core/motion_control.c @@ -566,7 +566,7 @@ extern "C" max_home_dist = g_settings.homing_offset * 5.0f; //sync's the planner and motion control done when clearing the planner - //planner_sync_position(); + planner_sync_position(); mc_resync_position(); mc_get_position(target); if (g_settings.homing_dir_invert_mask & axis_mask) From 2d45f7b46420049ef015fb49beb5156213b39282 Mon Sep 17 00:00:00 2001 From: Paciente8159 Date: Fri, 6 Aug 2021 12:15:01 +0100 Subject: [PATCH 21/24] minor modification to reset alarm -modified reset alarm to hide Reset to continue message -planner_sync_position, now calls mc_sync_position to reduce code size --- src/cnc.c | 38 ++++++++++++++++++++-------------- src/cnc.h | 2 +- src/core/planner.c | 4 ++-- src/interface/grbl_interface.h | 2 +- src/interface/protocol.c | 2 +- src/interface/protocol.h | 2 +- 6 files changed, 28 insertions(+), 22 deletions(-) diff --git a/src/cnc.c b/src/cnc.c index 0c5410694..87f87da1d 100644 --- a/src/cnc.c +++ b/src/cnc.c @@ -39,8 +39,9 @@ extern "C" #include "modules/pid_controller.h" #define LOOP_STARTUP_RESET 0 -#define LOOP_RUNNING 1 -#define LOOP_ERROR_RESET 2 +#define LOOP_RUNNING_FIRST_RUN 1 +#define LOOP_RUNNING 2 +#define LOOP_ERROR_RESET 3 #define UNLOCK_ERROR 0 #define UNLOCK_LOCKED 1 @@ -54,7 +55,7 @@ extern "C" volatile uint8_t rt_cmd; volatile uint8_t feed_ovr_cmd; volatile uint8_t tool_ovr_cmd; - volatile uint8_t alarm; + volatile int8_t alarm; } cnc_state_t; static cnc_state_t cnc_state; @@ -92,7 +93,7 @@ extern "C" // tries to reset. If fails jumps to error if (cnc_reset()) { - cnc_state.loop_state = LOOP_RUNNING; + cnc_state.loop_state = LOOP_RUNNING_FIRST_RUN; serial_select(SERIAL_UART); do @@ -106,7 +107,10 @@ extern "C" if (cnc_state.alarm < EXEC_ALARM_PROBE_FAIL_INITIAL) { io_disable_steppers(); - protocol_send_alarm(cnc_state.alarm); + if (cnc_state.alarm) + { + protocol_send_alarm(cnc_state.alarm); + } cnc_check_fault_systems(); do { @@ -141,6 +145,8 @@ extern "C" { protocol_send_error(error); } + + cnc_state.loop_state = LOOP_RUNNING; } } @@ -225,10 +231,9 @@ extern "C" //reset position itp_reset_rt_position(); planner_sync_position(); - mc_resync_position(); } - void cnc_alarm(uint8_t code) + void cnc_alarm(int8_t code) { cnc_set_exec_state(EXEC_KILL); cnc_stop(); @@ -286,6 +291,15 @@ extern "C" io_set_steps(g_settings.step_invert_mask); io_set_dirs(g_settings.dir_invert_mask); io_enable_steppers(); + + if (cnc_state.loop_state < LOOP_RUNNING) + { + serial_select(SERIAL_N0); + cnc_exec_cmd(); + serial_select(SERIAL_N1); + cnc_exec_cmd(); + serial_select(SERIAL_UART); + } } return UNLOCK_OK; @@ -378,14 +392,6 @@ extern "C" uint8_t ok = cnc_unlock(false); - if (ok == UNLOCK_OK) - { - serial_select(SERIAL_N0); - cnc_exec_cmd(); - serial_select(SERIAL_N1); - cnc_exec_cmd(); - } - if (ok) { io_enable_steppers(); @@ -661,7 +667,7 @@ extern "C" } #endif - if (cnc_get_exec_state(EXEC_KILL)) + if (cnc_get_exec_state(EXEC_KILL) && cnc_state.alarm) { protocol_send_feedback(MSG_FEEDBACK_1); } diff --git a/src/cnc.h b/src/cnc.h index 9d29cdc8c..1d9783589 100644 --- a/src/cnc.h +++ b/src/cnc.h @@ -193,7 +193,7 @@ extern "C" //do events returns true if all OK and false if an ABORT alarm is reached bool cnc_dotasks(void); void cnc_home(void); - void cnc_alarm(uint8_t code); + void cnc_alarm(int8_t code); void cnc_stop(void); uint8_t cnc_unlock(bool force); void cnc_delay_ms(uint32_t miliseconds); diff --git a/src/core/planner.c b/src/core/planner.c index b60baf355..48bfdfe95 100644 --- a/src/core/planner.c +++ b/src/core/planner.c @@ -356,8 +356,6 @@ extern "C" #endif //resyncs position with interpolator planner_sync_position(); - //forces motion control to resync postition after clearing the planner buffer - mc_resync_position(); } planner_block_t *planner_get_block(void) @@ -583,6 +581,8 @@ extern "C" { //resyncs the position with the interpolator itp_get_rt_position(planner_step_pos); + //forces the motion control to resync as well + mc_resync_position(); } void planner_sync_tools(motion_data_t *block_data) diff --git a/src/interface/grbl_interface.h b/src/interface/grbl_interface.h index 070cccb8e..d22de86c8 100644 --- a/src/interface/grbl_interface.h +++ b/src/interface/grbl_interface.h @@ -111,6 +111,7 @@ extern "C" #define GRBL_HELP (GRBL_SYSTEM_CMD + 8) #define GRBL_JOG_CMD (GRBL_SYSTEM_CMD + 9) +#define EXEC_ALARM_EMERGENCY_STOP -1 #define EXEC_ALARM_RESET 0 // Grbl alarm codes. Valid values (1-255). Zero is reserved for the reset alarm. #define EXEC_ALARM_HARD_LIMIT 1 @@ -124,7 +125,6 @@ extern "C" #define EXEC_ALARM_HOMING_FAIL_APPROACH 9 #define EXEC_ALARM_HOMING_FAIL_DUAL_APPROACH 10 #define EXEC_ALARM_HOMING_FAIL_LIMIT_ACTIVE 11 -#define EXEC_ALARM_EMERGENCY_STOP 12 //formated messages #define STR_EOL "\r\n" diff --git a/src/interface/protocol.c b/src/interface/protocol.c index 7facfed43..baf059b86 100644 --- a/src/interface/protocol.c +++ b/src/interface/protocol.c @@ -60,7 +60,7 @@ extern "C" protocol_busy = false; } - void protocol_send_alarm(uint8_t alarm) + void protocol_send_alarm(int8_t alarm) { protocol_busy = true; serial_print_str(MSG_ALARM); diff --git a/src/interface/protocol.h b/src/interface/protocol.h index 73589d933..3b425ff4e 100644 --- a/src/interface/protocol.h +++ b/src/interface/protocol.h @@ -30,7 +30,7 @@ extern "C" bool protocol_is_busy(void); void protocol_send_ok(void); void protocol_send_error(uint8_t error); - void protocol_send_alarm(uint8_t alarm); + void protocol_send_alarm(int8_t alarm); void protocol_send_status(void); void protocol_send_string(const unsigned char *__s); void protocol_send_feedback(const unsigned char *__s); From 0ca9e5443a09ea58665425669d7b49211f43fcad Mon Sep 17 00:00:00 2001 From: Paciente8159 Date: Fri, 6 Aug 2021 12:25:53 +0100 Subject: [PATCH 22/24] Update motion_control.c -code cleaning --- src/core/motion_control.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/core/motion_control.c b/src/core/motion_control.c index 1c874dbda..ba1c7bafe 100644 --- a/src/core/motion_control.c +++ b/src/core/motion_control.c @@ -521,7 +521,6 @@ extern "C" max_home_dist = -max_home_dist; } planner_sync_position(); - mc_resync_position(); mc_get_position(target); target[axis] += max_home_dist; //initializes planner block data @@ -567,7 +566,6 @@ extern "C" //sync's the planner and motion control done when clearing the planner planner_sync_position(); - mc_resync_position(); mc_get_position(target); if (g_settings.homing_dir_invert_mask & axis_mask) { From 1e99400acc7a241ff8b57abfe4991e1afef2b839 Mon Sep 17 00:00:00 2001 From: Paciente8159 Date: Fri, 6 Aug 2021 13:01:00 +0100 Subject: [PATCH 23/24] updated version and documentation -updated version and documentation --- CHANGELOG.md | 25 +++++++++++++++++++++++++ README.md | 7 ++++--- src/cnc_build.h | 2 +- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c5f1396e..f1d670c7d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,30 @@ # Changelog +## [1.2.1] - 2021-08-06 + +Version 1.2.1 is a minor revision from the previous version. This version aims mainly to improve the overhall response of µCNC and fix a few bugs. +The following things were changed: + +### Added + - added support for G10 L2 P0 (current coordinate system) (#61) + - implemented codes M0 and M1. M60 is also supported but behave like M0 (#58) + +### Changed + - revised and improved interlocking system that is more straight forward (code flow). Also this makes µCNC act more inline with the interface described by Grbl (#63) + - all hard/soft limit alarms cause the firmware to lock until software reset is issued as described by Grbl (#63) + - readapted homing and probing to the new interlocking logic (#63) + - startup code improvements (#62) + - modified µCNC to execute synchronous motions at motion control level. This reduces the pipeline travelling of the code at the expense of additional restart delay that is negletable (#59) + - dropped the Abort status in favor of the Alarm status to be more Grbl compliant (#59) + - blocked status reports during startup blocks to prevent startup block ill-formated strings that were causing the interface softwares to correctly recognize the responses (#59) + +### Fixed + - fixed axis drifting after homing. This happened on all motions until an explicit coordinate was set for that axis (#63) + - fixed hidden probe alarm status that only showed if other input alarms were active (#63) + - G92 and G5x.x offset calculations (#61) + - fixed inch report mode converted values output (#60) + ## [1.2.0] - 2021-07-31 Version 1.2.0 is a major revision from the previous version that packs lots of new features and bug fixes. @@ -239,6 +263,7 @@ Version 1.1.0 comes with many added features and improvements over the previous ### Initial release +[1.2.1]: https://github.com/Paciente8159/uCNC/releases/tag/v1.2.1 [1.2.0]: https://github.com/Paciente8159/uCNC/releases/tag/v1.2.0 [1.1.2]: https://github.com/Paciente8159/uCNC/releases/tag/v1.1.2 [1.1.1]: https://github.com/Paciente8159/uCNC/releases/tag/v1.1.1 diff --git a/README.md b/README.md index 06db12b9a..b4537baaf 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ Heavily inspired by the by [Grbl](https://github.com/gnea/grbl) and [LinuxCNC](h [![paypal](https://www.paypalobjects.com/webstatic/en_US/i/buttons/PP_logo_h_100x26.png)](https://www.paypal.me/paciente8159) ## Current µCNC status -µCNC current version is v1.2.0. This update added lot of new features needed for the future hardware/features support and some important bug fixes. +µCNC current version is v1.2.1. This update added lot of new features needed for the future hardware/features support and some important bug fixes. These include: - the new HAL configuration file that introduces a more flexible way to modify the HAL and give customization power of LinuxCNC. @@ -31,6 +31,7 @@ These include: - the addition of an option for a 16bit version of the bresenham line algorithm that can improve step rate for weak 8bit processors or for specific applications like laser engraving. ### G-Codes support +µCNC v1.2.1 added additional Gcode support. µCNC for now supports most of the RS274NGC v3: ``` @@ -45,17 +46,17 @@ List of Supported G-Codes since µCNC 1.0.0-beta.2: - Cutter Compensation Modes: G40 - Coordinate System Modes: G54, G55, G56, G57, G58, G59, G59.1, G59.2, G59.3 - Control Modes: G61, G61.1, G64 - - Program Flow: M2, M30(same has M2) + - Program Flow: M0, M1, M2, M30(same has M2), M60(same has M0) - Coolant Control: M7, M8, M9 - Spindle Control: M3, M4, M5 - Valid Non-Command Words: A, B, C, F, I, J, K, L, N, P, R, S, T, X, Y, Z - Valid Non-Command Words: E (used by 3D printing firmwares like [Marlin](https://github.com/MarlinFirmware/Marlin)) (currently not used) _* also G10 L2 P28 and P30 to set homing coordinates_ + _* also G10 L2 P0 to set the current coordinates system offset_ ``` TODO List of G-Codes in µCNC future releases: - - Program Flow: M0, M1 with the new HAL config - extending the capabilities and functions of the new HAL config ### µCNC capabilities diff --git a/src/cnc_build.h b/src/cnc_build.h index 417422cd0..0cb8ad848 100644 --- a/src/cnc_build.h +++ b/src/cnc_build.h @@ -25,7 +25,7 @@ extern "C" #endif #define CNC_MAJOR_MINOR_VERSION "1.2." -#define CNC_PATCH_VERSION "0" +#define CNC_PATCH_VERSION "1" #define CNC_VERSION CNC_MAJOR_MINOR_VERSION CNC_PATCH_VERSION From 1b85622297403b887dfa45f74d81070ff8f5c4cc Mon Sep 17 00:00:00 2001 From: Paciente8159 Date: Fri, 6 Aug 2021 13:10:46 +0100 Subject: [PATCH 24/24] Update CHANGELOG.md --- CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f1d670c7d..1c779665b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ ## [1.2.1] - 2021-08-06 -Version 1.2.1 is a minor revision from the previous version. This version aims mainly to improve the overhall response of µCNC and fix a few bugs. +Version 1.2.1 is a minor revision from the previous version. This version aims mainly to improve the overall response of µCNC and fix a few bugs. The following things were changed: ### Added @@ -19,9 +19,9 @@ The following things were changed: - all hard/soft limit alarms cause the firmware to lock until software reset is issued as described by Grbl (#63) - readapted homing and probing to the new interlocking logic (#63) - startup code improvements (#62) - - modified µCNC to execute synchronous motions at motion control level. This reduces the pipeline travelling of the code at the expense of additional restart delay that is negletable (#59) + - modified µCNC to execute synchronous motions at motion control level. This reduces the pipeline travelling of the code at the expense of additional restart delay that is neglectable (#59) - dropped the Abort status in favor of the Alarm status to be more Grbl compliant (#59) - - blocked status reports during startup blocks to prevent startup block ill-formated strings that were causing the interface softwares to correctly recognize the responses (#59) + - blocked status reports during startup blocks to prevent startup block ill-formated strings that were causing the interface software to correctly recognize the responses (#59) ### Fixed - fixed axis drifting after homing. This happened on all motions until an explicit coordinate was set for that axis (#63)