From e3e35b9a989b4c591e23335a9fe2ae9ad9b9aea3 Mon Sep 17 00:00:00 2001 From: Paciente8159 Date: Sun, 8 Jan 2023 23:50:50 +0000 Subject: [PATCH 01/10] redesign internal machine states --- uCNC/src/cnc.c | 67 ++++++++++++++++++++--------------- uCNC/src/cnc.h | 17 ++++----- uCNC/src/core/io_control.c | 5 ++- uCNC/src/interface/protocol.c | 1 - 4 files changed, 49 insertions(+), 41 deletions(-) diff --git a/uCNC/src/cnc.c b/uCNC/src/cnc.c index cec5d56a7..07e387bf9 100644 --- a/uCNC/src/cnc.c +++ b/uCNC/src/cnc.c @@ -315,7 +315,7 @@ void cnc_alarm(int8_t code) bool cnc_has_alarm() { - return ((CHECKFLAG(cnc_state.exec_state, EXEC_ALARM) != EXEC_IDLE) || (cnc_state.alarm != EXEC_ALARM_NOALARM)); + return (cnc_get_exec_state(EXEC_KILL) || (cnc_state.alarm != EXEC_ALARM_NOALARM)); } void cnc_stop(void) @@ -435,12 +435,9 @@ void cnc_clear_exec_state(uint8_t statemask) } // if releasing from a HOLD state with and active delay in exec - if (CHECKFLAG(statemask, EXEC_HOLD) && CHECKFLAG(cnc_state.exec_state, EXEC_HOLD)) + if (CHECKFLAG(statemask, EXEC_HOLD) && cnc_get_exec_state(EXEC_HOLD)) { SETFLAG(cnc_state.exec_state, EXEC_RESUMING); - CLEARFLAG(cnc_state.exec_state, EXEC_HOLD); - // prevents from clearing twice - CLEARFLAG(statemask, EXEC_HOLD); #if TOOL_COUNT > 0 // updated the coolant pins tool_set_coolant(planner_get_coolant()); @@ -467,7 +464,6 @@ void cnc_clear_exec_state(uint8_t statemask) } #endif #endif - CLEARFLAG(cnc_state.exec_state, EXEC_RESUMING); } CLEARFLAG(cnc_state.exec_state, statemask); @@ -533,7 +529,7 @@ void cnc_call_rt_command(uint8_t command) #endif case CMD_CODE_CYCLE_START: // prevents loop if cycle start is always pressed or unconnected (during cnc_dotasks) - if (!CHECKFLAG(cnc_state.exec_state, EXEC_RESUMING)) + if (cnc_get_exec_state(EXEC_RESUMING) != EXEC_RESUMING) { SETFLAG(cnc_state.rt_cmd, RT_CMD_CYCLE_START); // tries to clear hold if possible } @@ -542,7 +538,7 @@ void cnc_call_rt_command(uint8_t command) SETFLAG(cnc_state.exec_state, (EXEC_HOLD | EXEC_DOOR)); break; case CMD_CODE_JOG_CANCEL: - if (CHECKFLAG(cnc_state.exec_state, EXEC_JOG | EXEC_RUN) == (EXEC_JOG | EXEC_RUN)) + if (cnc_get_exec_state(EXEC_JOG | EXEC_RUN) == (EXEC_JOG | EXEC_RUN)) { SETFLAG(cnc_state.exec_state, EXEC_HOLD); } @@ -762,8 +758,12 @@ void cnc_check_fault_systems(void) bool cnc_check_interlocking(void) { // check all flags - // if kill leave - if (CHECKFLAG(cnc_state.exec_state, EXEC_KILL)) + + // an existing KILL condition can be due to: + // - ESTOP trigger + // - soft reset command + // - any cnc_alarm call + if (cnc_get_exec_state(EXEC_KILL)) { #if ASSERT_PIN(ESTOP) // the emergency stop is pressed. @@ -773,50 +773,59 @@ bool cnc_check_interlocking(void) return false; } #endif - if (CHECKFLAG(cnc_state.exec_state, EXEC_HOMING)) // reset or emergency stop during a homing cycle + if (cnc_get_exec_state(EXEC_HOMING)) // reset or emergency stop during a homing cycle { cnc_alarm(EXEC_ALARM_HOMING_FAIL_RESET); } - else if (CHECKFLAG(cnc_state.exec_state, EXEC_RUN)) // reset or emergency stop during a running cycle + else if (cnc_get_exec_state(EXEC_HALT)) // reset or emergency stop during a running cycle { cnc_alarm(EXEC_ALARM_ABORT_CYCLE); } return false; } - if (CHECKFLAG(cnc_state.exec_state, EXEC_DOOR) && CHECKFLAG(cnc_state.exec_state, EXEC_HOMING)) // door opened during a homing cycle + // an HALT condition or a limit switch was triggered + // this can be due to any abrupt stop while in motion + if (cnc_get_exec_state(EXEC_HALT | EXEC_LIMTS)) { - cnc_alarm(EXEC_ALARM_HOMING_FAIL_DOOR); - return false; - } - - if (CHECKFLAG(cnc_state.exec_state, EXEC_HALT) && CHECKFLAG(cnc_state.exec_state, EXEC_RUN)) - { - if (!CHECKFLAG(cnc_state.exec_state, EXEC_HOMING) && io_get_limits()) // if a motion is being performed allow trigger the limit switch alarm + if (!cnc_get_exec_state(EXEC_HOMING)) // if a motion is being performed allow trigger the limit switch alarm { cnc_alarm(EXEC_ALARM_HARD_LIMIT); } else { - CLEARFLAG(cnc_state.exec_state, EXEC_RUN); + cnc_alarm(EXEC_ALARM_ABORT_CYCLE); } return false; } - // 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)) + // the safety door condition is active + if (cnc_get_exec_state(EXEC_DOOR)) { - if (CHECKFLAG(cnc_state.exec_state, EXEC_DOOR)) + // door opened during a homing cycle exit with alarm + if (cnc_get_exec_state(EXEC_HOMING)) { - cnc_stop(); // stop all tools not only motion + cnc_alarm(EXEC_ALARM_HOMING_FAIL_DOOR); } - else - { - itp_stop(); // stop motion + + // with the door opened put machine on HOLD + cnc_set_exec_state(EXEC_HOLD); + + // if the machined has stopped stop all tools + if(!cnc_get_exec_state(EXEC_RUN)){ + cnc_stop(); } - if (CHECKFLAG(cnc_state.exec_state, EXEC_HOMING | EXEC_JOG)) // flushes the buffers if motions was homing or jog + return false; + } + + // an hold condition is active and motion as stopped + if (cnc_get_exec_state(EXEC_HOLD) && !cnc_get_exec_state(EXEC_RUN)) + { + itp_stop(); // stop motion + + if (cnc_get_exec_state(EXEC_HOMING | EXEC_JOG)) // flushes the buffers if motions was homing or jog { itp_clear(); planner_clear(); diff --git a/uCNC/src/cnc.h b/uCNC/src/cnc.h index 03bf67cbb..5452744d6 100644 --- a/uCNC/src/cnc.h +++ b/uCNC/src/cnc.h @@ -53,15 +53,16 @@ extern "C" // 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_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_HALT 32 // Limit switch is active or position lost due to abrupt stop -#define EXEC_HOMING_HIT (EXEC_HOMING | EXEC_HALT) // Limit switch is active during a homing motion -#define EXEC_DOOR 64 // Safety door open +#define EXEC_HOLD 2 // Feed hold is active +#define EXEC_RESUMING (EXEC_HOLD | EXEC_RUN) // Motions are being being hold or resumed +#define EXEC_JOG 4 // Jogging in execution +#define EXEC_HOMING 8 // Homing in execution +#define EXEC_LIMTS 16 // Limits hit +#define EXEC_HOMING_HIT (EXEC_HOMING | EXEC_LIMTS) // Limit switch is active during a homing motion +#define EXEC_DOOR 32 // Safety door open +#define EXEC_HALT 64 // All motions are halted and machine is locked #define EXEC_KILL 128 // Emergency stop -#define EXEC_ALARM (EXEC_HALT | 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 diff --git a/uCNC/src/core/io_control.c b/uCNC/src/core/io_control.c index 8214a33c7..3724db2e5 100644 --- a/uCNC/src/core/io_control.c +++ b/uCNC/src/core/io_control.c @@ -168,7 +168,7 @@ MCU_IO_CALLBACK void mcu_limits_changed_cb(void) itp_lock_stepper(0); // unlocks axis #endif itp_stop(); - cnc_set_exec_state(EXEC_HALT); + cnc_set_exec_state(EXEC_LIMTS); #ifdef ENABLE_IO_ALARM_DEBUG io_alarm_limits = limits; #endif @@ -196,11 +196,10 @@ MCU_IO_CALLBACK void mcu_controls_changed_cb(void) #if ASSERT_PIN(ESTOP) if (CHECKFLAG(controls, ESTOP_MASK)) { - cnc_set_exec_state(EXEC_KILL); - cnc_stop(); #ifdef ENABLE_IO_ALARM_DEBUG io_alarm_controls = controls; #endif + cnc_alarm(EXEC_ALARM_EMERGENCY_STOP); return; // forces exit } #endif diff --git a/uCNC/src/interface/protocol.c b/uCNC/src/interface/protocol.c index 264533faa..28bc9cc48 100644 --- a/uCNC/src/interface/protocol.c +++ b/uCNC/src/interface/protocol.c @@ -278,7 +278,6 @@ void protocol_send_status(void) case EXEC_JOG: protocol_send_string(MSG_STATUS_JOG); break; - case EXEC_RESUMING: case EXEC_RUN: protocol_send_string(MSG_STATUS_RUN); break; From 3a28d51b827fbc2e49d3713a32b19fbd2be41142 Mon Sep 17 00:00:00 2001 From: Paciente8159 Date: Mon, 9 Jan 2023 17:52:58 +0000 Subject: [PATCH 02/10] redesigned internal machine states - redesigned internal machine states - fixed multi drive axis compilation error - added limit alarm with no motion - replaced halt state by not homed - added limits state - high priority alarms now require user reset --- uCNC/src/cnc.c | 101 +++++++++++++----------- uCNC/src/cnc.h | 29 +++---- uCNC/src/cnc_hal_config_helper.h | 8 +- uCNC/src/core/interpolator.c | 2 +- uCNC/src/core/io_control.c | 3 +- uCNC/src/core/motion_control.c | 24 ++++-- uCNC/src/hal/mcus/virtual/mcu_virtual.c | 85 ++++++++++++++------ uCNC/src/interface/grbl_interface.h | 25 +++--- uCNC/src/interface/protocol.c | 33 +++++++- 9 files changed, 202 insertions(+), 108 deletions(-) diff --git a/uCNC/src/cnc.c b/uCNC/src/cnc.c index 07e387bf9..26156a401 100644 --- a/uCNC/src/cnc.c +++ b/uCNC/src/cnc.c @@ -24,7 +24,8 @@ #define LOOP_STARTUP_RESET 0 #define LOOP_RUNNING 1 -#define LOOP_ERROR_RESET 2 +#define LOOP_FAULT 2 +#define LOOP_REQUIRE_RESET 4 #define UNLOCK_OK 0 #define UNLOCK_LOCKED 1 @@ -125,16 +126,18 @@ void cnc_run(void) { } while (cnc_exec_cmd()); - cnc_state.loop_state = LOOP_ERROR_RESET; + cnc_state.loop_state = LOOP_FAULT; serial_flush(); - if (cnc_state.alarm > 0) + uint8_t alarm = cnc_state.alarm; + if (alarm > EXEC_ALARM_NOALARM) { protocol_send_alarm(cnc_state.alarm); } - if (cnc_state.alarm < EXEC_ALARM_PROBE_FAIL_INITIAL) + if (alarm < EXEC_ALARM_PROBE_FAIL_INITIAL && alarm != EXEC_ALARM_NOALARM) { io_enable_steppers(~g_settings.step_enable_invert); cnc_check_fault_systems(); + cnc_state.loop_state = LOOP_REQUIRE_RESET; break; } } @@ -145,20 +148,17 @@ void cnc_run(void) { if (serial_getc() == EOL) { - protocol_send_feedback(MSG_FEEDBACK_12); + protocol_send_feedback(MSG_FEEDBACK_1); protocol_send_ok(); } } cnc_dotasks(); - if (io_get_controls() & ESTOP_MASK) + // a hard/soft reset is pending + if (cnc_state.alarm < 0) { cnc_state.loop_state = LOOP_STARTUP_RESET; } - else - { - break; - } - } while (1); + } while (cnc_state.loop_state == LOOP_REQUIRE_RESET); } bool cnc_exec_cmd(void) @@ -211,11 +211,11 @@ bool cnc_dotasks(void) if (cnc_has_alarm()) { - return !cnc_get_exec_state(EXEC_KILL | EXEC_HOMING); + return !cnc_get_exec_state(EXEC_KILL); } // µCNC already in error loop. No point in sending the alarms - if (cnc_state.loop_state == LOOP_ERROR_RESET) + if (cnc_state.loop_state >= LOOP_FAULT) { return !cnc_get_exec_state(EXEC_KILL); } @@ -305,9 +305,9 @@ void cnc_alarm(int8_t code) cnc_state.alarm = code; #ifdef ENABLE_IO_ALARM_DEBUG protocol_send_string(MSG_START); - protocol_send_string(__romstr__("LIMITS>")); + protocol_send_string(__romstr__("LIMITS:")); serial_print_int(io_alarm_limits); - protocol_send_string(__romstr__(" CONTROLS>")); + protocol_send_string(__romstr__("|CONTROLS:")); serial_print_int(io_alarm_controls); protocol_send_string(MSG_END); #endif @@ -331,15 +331,15 @@ void cnc_stop(void) uint8_t cnc_unlock(bool force) { - // tries to clear alarms or any active hold state - cnc_clear_exec_state(EXEC_ALARM | EXEC_HOLD); + // tries to clear alarms, door or any active hold state + cnc_clear_exec_state(EXEC_RESET_LOCKED); // 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); + CLEARFLAG(cnc_state.exec_state, EXEC_UNHOMED); cnc_state.alarm = EXEC_ALARM_NOALARM; } @@ -359,9 +359,9 @@ uint8_t cnc_unlock(bool force) 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 + // this must be done directly because 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); + CLEARFLAG(cnc_state.exec_state, EXEC_UNHOMED); // clears all other locking flags cnc_clear_exec_state(EXEC_GCODE_LOCKED | EXEC_HOLD); // signals stepper enable pins @@ -419,18 +419,18 @@ void cnc_clear_exec_state(uint8_t statemask) // has a pending (not cleared by user) alarm if (cnc_state.alarm) { - CLEARFLAG(statemask, EXEC_HALT); + CLEARFLAG(statemask, EXEC_UNHOMED); } uint8_t limits = 0; #if (LIMITS_MASK != 0) - limits = io_get_limits(); // can't clear the EXEC_HALT is any limit is triggered + limits = io_get_limits(); // can't clear the EXEC_UNHOMED 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_HALT); + CLEARFLAG(statemask, EXEC_UNHOMED); } } @@ -464,6 +464,7 @@ void cnc_clear_exec_state(uint8_t statemask) } #endif #endif + CLEARFLAG(cnc_state.exec_state, EXEC_RESUMING); } CLEARFLAG(cnc_state.exec_state, statemask); @@ -484,7 +485,7 @@ void cnc_reset(void) cnc_state.rt_cmd = RT_CMD_CLEAR; cnc_state.feed_ovr_cmd = RT_CMD_CLEAR; cnc_state.tool_ovr_cmd = RT_CMD_CLEAR; - cnc_state.exec_state = EXEC_ALARM | EXEC_HOLD; // Activates all alarms and hold + cnc_state.exec_state = EXEC_RESET_LOCKED; // Activates all alarms, door and hold cnc_state.alarm = EXEC_ALARM_NOALARM; // clear all systems @@ -517,7 +518,6 @@ void cnc_call_rt_command(uint8_t command) { 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); @@ -586,13 +586,25 @@ void cnc_exec_rt_commands(void) cnc_state.rt_cmd = RT_CMD_CLEAR; if (command & RT_CMD_RESET) { + if (cnc_get_exec_state(EXEC_HOMING)) + { + cnc_alarm(EXEC_ALARM_HOMING_FAIL_RESET); + return; + } + + if (cnc_get_exec_state(EXEC_RUN)) + { + cnc_alarm(EXEC_ALARM_ABORT_CYCLE); + return; + } + cnc_alarm(EXEC_ALARM_SOFTRESET); return; } if (command & RT_CMD_CYCLE_START) { - cnc_clear_exec_state(EXEC_HOLD); + cnc_clear_exec_state(EXEC_HOLD | EXEC_DOOR); } } @@ -773,11 +785,8 @@ bool cnc_check_interlocking(void) return false; } #endif - if (cnc_get_exec_state(EXEC_HOMING)) // reset or emergency stop during a homing cycle - { - cnc_alarm(EXEC_ALARM_HOMING_FAIL_RESET); - } - else if (cnc_get_exec_state(EXEC_HALT)) // reset or emergency stop during a running cycle + // something caused the motion to stop abruptly + if (cnc_get_exec_state(EXEC_UNHOMED)) { cnc_alarm(EXEC_ALARM_ABORT_CYCLE); } @@ -786,34 +795,38 @@ bool cnc_check_interlocking(void) // an HALT condition or a limit switch was triggered // this can be due to any abrupt stop while in motion - if (cnc_get_exec_state(EXEC_HALT | EXEC_LIMTS)) + if (cnc_get_exec_state(EXEC_LIMITS)) { if (!cnc_get_exec_state(EXEC_HOMING)) // if a motion is being performed allow trigger the limit switch alarm { - cnc_alarm(EXEC_ALARM_HARD_LIMIT); - } - else - { - cnc_alarm(EXEC_ALARM_ABORT_CYCLE); + if (cnc_get_exec_state(EXEC_UNHOMED)) + { + cnc_alarm(EXEC_ALARM_HARD_LIMIT); + } + else + { + cnc_alarm(EXEC_ALARM_HARD_LIMIT_NOMOTION); + } } return false; } // the safety door condition is active - if (cnc_get_exec_state(EXEC_DOOR)) + if (cnc_get_exec_state(EXEC_DOOR)) { // door opened during a homing cycle exit with alarm if (cnc_get_exec_state(EXEC_HOMING)) { cnc_alarm(EXEC_ALARM_HOMING_FAIL_DOOR); } - - // with the door opened put machine on HOLD - cnc_set_exec_state(EXEC_HOLD); - - // if the machined has stopped stop all tools - if(!cnc_get_exec_state(EXEC_RUN)){ + else if (cnc_get_exec_state(EXEC_RUN)) // if the machined is running + { + // with the door opened put machine on HOLD + cnc_set_exec_state(EXEC_HOLD); + } + else // if the machined is not moving stop the tool too + { cnc_stop(); } diff --git a/uCNC/src/cnc.h b/uCNC/src/cnc.h index 5452744d6..c44c8dc90 100644 --- a/uCNC/src/cnc.h +++ b/uCNC/src/cnc.h @@ -51,20 +51,21 @@ 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_RESUMING (EXEC_HOLD | EXEC_RUN) // Motions are being being hold or resumed -#define EXEC_JOG 4 // Jogging in execution -#define EXEC_HOMING 8 // Homing in execution -#define EXEC_LIMTS 16 // Limits hit -#define EXEC_HOMING_HIT (EXEC_HOMING | EXEC_LIMTS) // Limit switch is active during a homing motion -#define EXEC_DOOR 32 // Safety door open -#define EXEC_HALT 64 // All motions are halted and machine is locked -#define EXEC_KILL 128 // Emergency stop -#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 +#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_DOOR 16 // Safety door open +#define EXEC_UNHOMED 32 // Machine is not homed or lost position due to abrupt stop +#define EXEC_LIMITS 64 // Limits hit +#define EXEC_KILL 128 // Emergency stop +#define EXEC_RESUMING (EXEC_HOLD | EXEC_RUN) // Motions are being being hold or resumed +#define EXEC_HOMING_HIT (EXEC_HOMING | EXEC_LIMITS) // Limit switch is active during a homing motion +#define EXEC_ALARM (EXEC_UNHOMED | EXEC_LIMITS | EXEC_KILL) // System alarms +#define EXEC_RESET_LOCKED (EXEC_ALARM | EXEC_DOOR | EXEC_HOLD) // System reset locked +#define EXEC_GCODE_LOCKED (EXEC_ALARM | EXEC_DOOR | 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/uCNC/src/cnc_hal_config_helper.h b/uCNC/src/cnc_hal_config_helper.h index c77f7b79f..a321920d1 100644 --- a/uCNC/src/cnc_hal_config_helper.h +++ b/uCNC/src/cnc_hal_config_helper.h @@ -655,8 +655,14 @@ extern "C" #ifndef DUAL_DRIVE1_STEPPER #define DUAL_DRIVE1_STEPPER 7 #endif +#ifndef DUAL_DRIVE2_STEPPER +#define DUAL_DRIVE2_STEPPER 6 +#endif +#ifndef DUAL_DRIVE3_STEPPER +#define DUAL_DRIVE3_STEPPER 7 +#endif -#if (!defined(DUAL_DRIVE0_AXIS) && !defined(DUAL_DRIVE1_AXIS)) +#if (!defined(DUAL_DRIVE0_AXIS) && !defined(DUAL_DRIVE1_AXIS) && !defined(DUAL_DRIVE2_AXIS) && !defined(DUAL_DRIVE3_AXIS)) #error "Enabling dual axis drive requires to configure at least one axis with dual drive" #endif diff --git a/uCNC/src/core/interpolator.c b/uCNC/src/core/interpolator.c index f7c9b3f90..c7e0ee8d4 100644 --- a/uCNC/src/core/interpolator.c +++ b/uCNC/src/core/interpolator.c @@ -1056,7 +1056,7 @@ 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); + cnc_set_exec_state(EXEC_UNHOMED); } cnc_clear_exec_state(EXEC_RUN); diff --git a/uCNC/src/core/io_control.c b/uCNC/src/core/io_control.c index 3724db2e5..b6bb90121 100644 --- a/uCNC/src/core/io_control.c +++ b/uCNC/src/core/io_control.c @@ -168,7 +168,7 @@ MCU_IO_CALLBACK void mcu_limits_changed_cb(void) itp_lock_stepper(0); // unlocks axis #endif itp_stop(); - cnc_set_exec_state(EXEC_LIMTS); + cnc_set_exec_state(EXEC_LIMITS); #ifdef ENABLE_IO_ALARM_DEBUG io_alarm_limits = limits; #endif @@ -337,6 +337,7 @@ void io_lock_limits(uint8_t limitmask) void io_invert_limits(uint8_t limitmask) { io_invert_limits_mask = limitmask; + mcu_limits_changed_cb(); } uint8_t io_get_limits(void) diff --git a/uCNC/src/core/motion_control.c b/uCNC/src/core/motion_control.c index 005a8caa3..4f1bd6dbe 100644 --- a/uCNC/src/core/motion_control.c +++ b/uCNC/src/core/motion_control.c @@ -749,7 +749,7 @@ uint8_t mc_home_axis(uint8_t axis, uint8_t axis_limit) // the wrong switch was activated bails if (!CHECKFLAG(limits_flags, axis_limit)) { - cnc_set_exec_state(EXEC_HALT); + cnc_set_exec_state(EXEC_UNHOMED); cnc_alarm(EXEC_ALARM_HOMING_FAIL_APPROACH); return STATUS_CRITICAL_FAIL; } @@ -768,7 +768,7 @@ uint8_t mc_home_axis(uint8_t axis, uint8_t axis_limit) target[axis] += max_home_dist; block_data.feed = g_settings.homing_slow_feed_rate; // block_data.steps[axis] = max_home_dist; - // unlocks the machine for next motion (this will clear the EXEC_HALT flag + // unlocks the machine for next motion (this will clear the EXEC_UNHOMED flag // temporary inverts the limit mask to trigger ISR on switch release io_invert_limits(axis_limit); @@ -797,7 +797,7 @@ uint8_t mc_home_axis(uint8_t axis, uint8_t axis_limit) if (CHECKFLAG(limits_flags, axis_limit)) { - cnc_set_exec_state(EXEC_HALT); + cnc_set_exec_state(EXEC_UNHOMED); cnc_alarm(EXEC_ALARM_HOMING_FAIL_APPROACH); return STATUS_CRITICAL_FAIL; } @@ -817,6 +817,18 @@ uint8_t mc_probe(float *target, uint8_t flags, motion_data_t *block_data) return STATUS_CRITICAL_FAIL; } + bool probe_ok = io_get_probe(); + probe_ok = (flags & MOTIONCONTROL_PROBE_INVERT) ? probe_ok : !probe_ok; + + if (!probe_ok) + { + if (!(flags & MOTIONCONTROL_PROBE_NOALARM_ONFAIL)) + { + cnc_alarm(EXEC_ALARM_PROBE_FAIL_INITIAL); + } + return STATUS_OK; + } + mc_line(target, block_data); // enable the probe io_enable_probe(); @@ -833,7 +845,7 @@ uint8_t mc_probe(float *target, uint8_t flags, motion_data_t *block_data) io_disable_probe(); // clears HALT state if possible - cnc_clear_exec_state(EXEC_HALT); + cnc_clear_exec_state(EXEC_UNHOMED); itp_clear(); planner_clear(); @@ -841,13 +853,13 @@ uint8_t mc_probe(float *target, uint8_t flags, motion_data_t *block_data) // sync the position of the motion control mc_sync_position(); // HALT could not be cleared. Something is wrong - if (cnc_get_exec_state(EXEC_HALT)) + if (cnc_get_exec_state(EXEC_UNHOMED)) { return STATUS_CRITICAL_FAIL; } cnc_delay_ms(g_settings.debounce_ms); // adds a delay before reading io pin (debounce) - bool probe_ok = io_get_probe(); + probe_ok = io_get_probe(); probe_ok = (flags & MOTIONCONTROL_PROBE_INVERT) ? !probe_ok : probe_ok; if (!probe_ok) { diff --git a/uCNC/src/hal/mcus/virtual/mcu_virtual.c b/uCNC/src/hal/mcus/virtual/mcu_virtual.c index c8d8341e5..a43236f19 100644 --- a/uCNC/src/hal/mcus/virtual/mcu_virtual.c +++ b/uCNC/src/hal/mcus/virtual/mcu_virtual.c @@ -83,12 +83,12 @@ #define COM_BUFFER_SIZE 50 #endif -//MCU_IO_CALLBACK void mcu_inputs_changed_cb(void) +// MCU_IO_CALLBACK void mcu_inputs_changed_cb(void) //{ -//#ifdef ENABLE_IO_MODULES +// #ifdef ENABLE_IO_MODULES // EVENT_INVOKE(input_change, NULL); -//#endif -//} +// #endif +// } /*timers*/ int start_timer(int, void (*)(void)); @@ -154,9 +154,9 @@ unsigned long getCPUFreq(void) printf("QueryPerformanceFrequency failed!\n"); return 0; } - - cyclesPerMicrosecond = (double)perf_counter.QuadPart/1000000.0; - cyclesPerMillisecond = (double)perf_counter.QuadPart/1000.0; + + cyclesPerMicrosecond = (double)perf_counter.QuadPart / 1000000.0; + cyclesPerMillisecond = (double)perf_counter.QuadPart / 1000.0; return perf_counter.QuadPart; } @@ -723,8 +723,41 @@ DWORD WINAPI virtualconsoleserver(LPVOID lpParam) // Receive until the peer shuts down the connection do { - unsigned char c = getchar(); - mcu_com_rx_cb(c); + unsigned char c = getch(); + switch (c) + { + // case '"': + // virtualmap.special_inputs ^= (1 << (ESTOP - LIMIT_X)); + // mcu_controls_changed_cb(); + // break; + // case '%': + // virtualmap.special_inputs ^= (1 << (LIMIT_X - LIMIT_X)); + // mcu_limits_changed_cb(); + // break; + // case '&': + // virtualmap.special_inputs ^= (1 << (LIMIT_Y - LIMIT_X)); + // mcu_limits_changed_cb(); + // break; + // case '/': + // virtualmap.special_inputs ^= (1 << (LIMIT_Z - LIMIT_X)); + // mcu_limits_changed_cb(); + // break; + // case '[': + // virtualmap.special_inputs ^= (1 << (LIMIT_X2 - LIMIT_X)); + // mcu_limits_changed_cb(); + // break; + // case ']': + // virtualmap.special_inputs ^= (1 << (LIMIT_Y2 - LIMIT_X)); + // mcu_limits_changed_cb(); + // break; + // case '}': + // virtualmap.special_inputs ^= (1 << (SAFETY_DOOR - LIMIT_X)); + // mcu_controls_changed_cb(); + // break; + default: + mcu_com_rx_cb(c); + break; + } } while (1); @@ -1080,7 +1113,7 @@ void *stepsimul(void *args) void rpmsimul(void) { - virtualmap.inputs ^= (1<<7); + virtualmap.inputs ^= (1 << 7); mcu_inputs_changed_cb(); } @@ -1116,11 +1149,10 @@ void ticksimul(void) } } -//uint32_t mcu_millis() +// uint32_t mcu_millis() //{ // return mcu_runtime; -//} - +// } void mcu_init(void) { @@ -1154,9 +1186,9 @@ void mcu_init(void) g_cpu_freq = getCPUFreq(); start_timer(1, &ticksimul); start_timer(10, &rpmsimul); - //#ifdef USECONSOLE + // #ifdef USECONSOLE // pthread_create(&thread_idout, NULL, &comoutsimul, NULL); - //#endif + // #endif pthread_create(&thread_step_id, NULL, &stepsimul, NULL); pthread_create(&thread_io, NULL, &ioserver, NULL); mcu_tx_enabled = false; @@ -1180,7 +1212,8 @@ extern MCU_CALLBACK mcu_timeout_delgate mcu_timeout_cb; HANDLE oneshot_handle; VOID CALLBACK oneshot_handler(PVOID lpParameter, BOOLEAN TimerOrWaitFired) { - if(mcu_timeout_cb){ + if (mcu_timeout_cb) + { mcu_timeout_cb(); } } @@ -1188,20 +1221,21 @@ VOID CALLBACK oneshot_handler(PVOID lpParameter, BOOLEAN TimerOrWaitFired) * configures a single shot timeout in us * */ #ifndef mcu_config_timeout - void mcu_config_timeout(mcu_timeout_delgate fp, uint32_t timeout) - { - mcu_timeout_cb = fp; - mcu_timeout = timeout; - } +void mcu_config_timeout(mcu_timeout_delgate fp, uint32_t timeout) +{ + mcu_timeout_cb = fp; + mcu_timeout = timeout; +} #endif /** * starts the timeout. Once hit the the respective callback is called * */ #ifndef mcu_start_timeout - void mcu_start_timeout(){ - CreateTimerQueueTimer(&oneshot_handle, NULL, (WAITORTIMERCALLBACK)oneshot_handler, NULL, 0, mcu_timeout, WT_EXECUTEINTIMERTHREAD|WT_EXECUTEONLYONCE); - } +void mcu_start_timeout() +{ + CreateTimerQueueTimer(&oneshot_handle, NULL, (WAITORTIMERCALLBACK)oneshot_handler, NULL, 0, mcu_timeout, WT_EXECUTEINTIMERTHREAD | WT_EXECUTEONLYONCE); +} #endif #endif @@ -1602,7 +1636,8 @@ void mcu_dotasks(void) { } -void mcu_config_input_isr(int pin){ +void mcu_config_input_isr(int pin) +{ } #endif diff --git a/uCNC/src/interface/grbl_interface.h b/uCNC/src/interface/grbl_interface.h index 2e983ca03..8dc90eeea 100644 --- a/uCNC/src/interface/grbl_interface.h +++ b/uCNC/src/interface/grbl_interface.h @@ -136,18 +136,19 @@ extern "C" #define EXEC_ALARM_EMERGENCY_STOP -1 #define EXEC_ALARM_NOALARM 0 // 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 -#define EXEC_ALARM_PROBE_FAIL_INITIAL 4 -#define EXEC_ALARM_PROBE_FAIL_CONTACT 5 -#define EXEC_ALARM_HOMING_FAIL_RESET 6 -#define EXEC_ALARM_HOMING_FAIL_DOOR 7 -#define EXEC_ALARM_HOMING_FAIL_PULLOFF 8 -#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_SPINDLE_SYNC_FAIL 12 +#define EXEC_ALARM_HARD_LIMIT 1 // hard limits hit while in motion other then homing +#define EXEC_ALARM_SOFT_LIMIT 2 // target is off bounds of the machine kinematics +#define EXEC_ALARM_ABORT_CYCLE 3 // an abort command was issued +#define EXEC_ALARM_PROBE_FAIL_INITIAL 4 // probe was already triggered and was not able to initialize probing +#define EXEC_ALARM_PROBE_FAIL_CONTACT 5 // probe failed to triggered before reaching the limit target +#define EXEC_ALARM_HOMING_FAIL_RESET 6 // homing was aborted by a reset command +#define EXEC_ALARM_HOMING_FAIL_DOOR 7 // door was opened during homing motion +#define EXEC_ALARM_HOMING_FAIL_PULLOFF 8 // homing limits failed to normalize after retract by pull-distance +#define EXEC_ALARM_HOMING_FAIL_APPROACH 9 // homing limits failed make initial contact +#define EXEC_ALARM_HOMING_FAIL_DUAL_APPROACH 10 // homing limits failed make initial contact (self squaring) +#define EXEC_ALARM_HOMING_FAIL_LIMIT_ACTIVE 11 // homing could not start since one of the limits was already triggered +#define EXEC_ALARM_SPINDLE_SYNC_FAIL 12 // failed to achieve spindle sync speed +#define EXEC_ALARM_HARD_LIMIT_NOMOTION 13 // hard limits were triggered without any motion (position was not lost) // formated messages #define STR_EOL "\r\n" diff --git a/uCNC/src/interface/protocol.c b/uCNC/src/interface/protocol.c index 28bc9cc48..3759d6c8f 100644 --- a/uCNC/src/interface/protocol.c +++ b/uCNC/src/interface/protocol.c @@ -236,7 +236,6 @@ void protocol_send_status(void) protocol_send_string(MSG_STATUS_DOOR); if (CHECKFLAG(controls, SAFETY_DOOR_MASK)) { - if (cnc_get_exec_state(EXEC_RUN)) { serial_putc('2'); @@ -258,8 +257,16 @@ void protocol_send_status(void) } } break; - case EXEC_HALT: - protocol_send_string(MSG_STATUS_ALARM); + case EXEC_UNHOMED: + case EXEC_LIMITS: + if (!cnc_get_exec_state(EXEC_HOMING)) + { + protocol_send_string(MSG_STATUS_ALARM); + } + else + { + protocol_send_string(MSG_STATUS_HOME); + } break; case EXEC_HOLD: protocol_send_string(MSG_STATUS_HOLD); @@ -869,6 +876,24 @@ void protocol_send_pins_states(void) #define FASTMATH_INFO "" #endif +#ifdef RAM_ONLY_SETTINGS +#define SETTINGS_INFO "RAM," +#else +#define SETTINGS_INFO "" +#endif + +#ifdef ENABLE_IO_ALARM_DEBUG +#define IODBG_INFO "IODBG," +#else +#define IODBG_INFO "" +#endif + +#ifdef FORCE_SOFT_POLLING +#define SPOLL_INFO "SP," +#else +#define SPOLL_INFO "" +#endif + #ifdef ENABLE_LINACT_PLANNER #define LINPLAN_INFO "LP," #else @@ -908,7 +933,7 @@ void protocol_send_pins_states(void) #define BOARD_NAME "Generic board" #endif -#define OPT_INFO __romstr__("[OPT:" KINEMATIC_INFO LINES_INFO BRESENHAM_INFO DSS_INFO DYNACCEL_INFO ACCELALG_INFO SKEW_INFO LINPLAN_INFO HMAP_INFO PPI_INFO INVESTOP_INFO CONTROLS_INFO LIMITS_INFO PROBE_INFO EXTRACMD_INFO FASTMATH_INFO) +#define OPT_INFO __romstr__("[OPT:" KINEMATIC_INFO LINES_INFO BRESENHAM_INFO DSS_INFO DYNACCEL_INFO ACCELALG_INFO SKEW_INFO LINPLAN_INFO HMAP_INFO PPI_INFO INVESTOP_INFO SPOLL_INFO CONTROLS_INFO LIMITS_INFO PROBE_INFO IODBG_INFO SETTINGS_INFO EXTRACMD_INFO FASTMATH_INFO) #define VER_INFO __romstr__("[VER: uCNC " CNC_VERSION " - " BOARD_NAME "]" STR_EOL) WEAK_EVENT_HANDLER(protocol_send_cnc_info) From 38d245dc40bd12841c75546d5a9db8cc0af7856f Mon Sep 17 00:00:00 2001 From: Paciente8159 Date: Mon, 9 Jan 2023 19:16:10 +0000 Subject: [PATCH 03/10] redesigned internal machine states - fixed negative alarm state messages --- uCNC/src/cnc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/uCNC/src/cnc.c b/uCNC/src/cnc.c index 26156a401..9522e9f21 100644 --- a/uCNC/src/cnc.c +++ b/uCNC/src/cnc.c @@ -128,7 +128,7 @@ void cnc_run(void) cnc_state.loop_state = LOOP_FAULT; serial_flush(); - uint8_t alarm = cnc_state.alarm; + int8_t alarm = cnc_state.alarm; if (alarm > EXEC_ALARM_NOALARM) { protocol_send_alarm(cnc_state.alarm); @@ -400,6 +400,8 @@ void cnc_clear_exec_state(uint8_t statemask) if (CHECKFLAG(controls, ESTOP_MASK)) // can't clear the alarm flag if ESTOP is active { CLEARFLAG(statemask, EXEC_KILL); + // no point in continuing + return; } #endif #if ASSERT_PIN(SAFETY_DOOR) From eb4a2a2edc7efc27ed6e5485d22de1153b215146 Mon Sep 17 00:00:00 2001 From: Paciente8159 Date: Mon, 9 Jan 2023 19:45:42 +0000 Subject: [PATCH 04/10] redesigned internal machine states - prevent reset loop while emergency stop is pressed --- uCNC/src/cnc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/uCNC/src/cnc.c b/uCNC/src/cnc.c index 9522e9f21..31de31605 100644 --- a/uCNC/src/cnc.c +++ b/uCNC/src/cnc.c @@ -157,8 +157,9 @@ void cnc_run(void) if (cnc_state.alarm < 0) { cnc_state.loop_state = LOOP_STARTUP_RESET; + cnc_clear_exec_state(EXEC_KILL); } - } while (cnc_state.loop_state == LOOP_REQUIRE_RESET); + } while (cnc_state.loop_state == LOOP_REQUIRE_RESET || cnc_get_exec_state(EXEC_KILL)); } bool cnc_exec_cmd(void) From 6a5d33f0ad3f1c9a6de2d21830a85baf78f102d7 Mon Sep 17 00:00:00 2001 From: Paciente8159 Date: Tue, 10 Jan 2023 10:26:50 +0000 Subject: [PATCH 05/10] fixed probing motion - state clear function for not homed status - probing motion fixed to clear not homed after initial probe contact via unlock command --- uCNC/src/cnc.c | 9 +++------ uCNC/src/core/motion_control.c | 8 +++----- uCNC/src/hal/mcus/virtual/mcu_virtual.c | 24 ++++++++++++------------ 3 files changed, 18 insertions(+), 23 deletions(-) diff --git a/uCNC/src/cnc.c b/uCNC/src/cnc.c index 31de31605..9b87b1510 100644 --- a/uCNC/src/cnc.c +++ b/uCNC/src/cnc.c @@ -420,7 +420,7 @@ void cnc_clear_exec_state(uint8_t statemask) #endif // has a pending (not cleared by user) alarm - if (cnc_state.alarm) + if (cnc_state.alarm <= EXEC_ALARM_ABORT_CYCLE || g_settings.homing_enabled) { CLEARFLAG(statemask, EXEC_UNHOMED); } @@ -429,12 +429,9 @@ void cnc_clear_exec_state(uint8_t statemask) #if (LIMITS_MASK != 0) limits = io_get_limits(); // can't clear the EXEC_UNHOMED is any limit is triggered #endif - if (g_settings.hard_limits_enabled) // if hardlimits are enabled and limits are triggered + if (g_settings.hard_limits_enabled && limits) // if hardlimits are enabled and limits are triggered { - if (limits || g_settings.homing_enabled) - { - CLEARFLAG(statemask, EXEC_UNHOMED); - } + CLEARFLAG(statemask, EXEC_UNHOMED); } // if releasing from a HOLD state with and active delay in exec diff --git a/uCNC/src/core/motion_control.c b/uCNC/src/core/motion_control.c index 4f1bd6dbe..d752df416 100644 --- a/uCNC/src/core/motion_control.c +++ b/uCNC/src/core/motion_control.c @@ -689,8 +689,6 @@ uint8_t mc_home_axis(uint8_t axis, uint8_t axis_limit) motion_data_t block_data = {0}; uint8_t limits_flags; - cnc_unlock(true); - #ifdef ENABLE_G39_H_MAPPING // resets height map memset(hmap_offsets, 0, sizeof(hmap_offsets)); @@ -699,8 +697,8 @@ uint8_t mc_home_axis(uint8_t axis, uint8_t axis_limit) // locks limits to accept axis limit mask only or else throw error io_lock_limits(axis_limit); io_invert_limits(0); - // if HOLD or ALARM are still active or any limit switch is not cleared fails to home - mcu_limits_changed_cb(); + cnc_unlock(true); + if (cnc_get_exec_state(EXEC_HOLD | EXEC_ALARM) || CHECKFLAG(io_get_limits(), LIMITS_MASK)) { cnc_alarm(EXEC_ALARM_HOMING_FAIL_LIMIT_ACTIVE); @@ -845,7 +843,7 @@ uint8_t mc_probe(float *target, uint8_t flags, motion_data_t *block_data) io_disable_probe(); // clears HALT state if possible - cnc_clear_exec_state(EXEC_UNHOMED); + cnc_unlock(true); itp_clear(); planner_clear(); diff --git a/uCNC/src/hal/mcus/virtual/mcu_virtual.c b/uCNC/src/hal/mcus/virtual/mcu_virtual.c index a43236f19..4e2d7113f 100644 --- a/uCNC/src/hal/mcus/virtual/mcu_virtual.c +++ b/uCNC/src/hal/mcus/virtual/mcu_virtual.c @@ -726,18 +726,18 @@ DWORD WINAPI virtualconsoleserver(LPVOID lpParam) unsigned char c = getch(); switch (c) { - // case '"': - // virtualmap.special_inputs ^= (1 << (ESTOP - LIMIT_X)); - // mcu_controls_changed_cb(); - // break; - // case '%': - // virtualmap.special_inputs ^= (1 << (LIMIT_X - LIMIT_X)); - // mcu_limits_changed_cb(); - // break; - // case '&': - // virtualmap.special_inputs ^= (1 << (LIMIT_Y - LIMIT_X)); - // mcu_limits_changed_cb(); - // break; + case '"': + virtualmap.special_inputs ^= (1 << (ESTOP - LIMIT_X)); + mcu_controls_changed_cb(); + break; + case '%': + virtualmap.special_inputs ^= (1 << (PROBE - LIMIT_X)); + mcu_limits_changed_cb(); + break; + case '&': + virtualmap.special_inputs ^= (1 << (LIMIT_Y - LIMIT_X)); + mcu_limits_changed_cb(); + break; // case '/': // virtualmap.special_inputs ^= (1 << (LIMIT_Z - LIMIT_X)); // mcu_limits_changed_cb(); From f9861b013535027547b9f69760402c384f06525c Mon Sep 17 00:00:00 2001 From: Paciente8159 Date: Tue, 10 Jan 2023 12:47:34 +0000 Subject: [PATCH 06/10] modified SAFETY_DOOR code - removed safety door code if safety pin undefined (like stated in Grbl) --- uCNC/src/cnc.c | 4 ++++ uCNC/src/cnc.h | 20 ++++++++++++++++++++ uCNC/src/core/parser.c | 7 +++++-- uCNC/src/interface/protocol.c | 2 ++ 4 files changed, 31 insertions(+), 2 deletions(-) diff --git a/uCNC/src/cnc.c b/uCNC/src/cnc.c index 9b87b1510..82262fa14 100644 --- a/uCNC/src/cnc.c +++ b/uCNC/src/cnc.c @@ -534,9 +534,11 @@ void cnc_call_rt_command(uint8_t command) SETFLAG(cnc_state.rt_cmd, RT_CMD_CYCLE_START); // tries to clear hold if possible } break; +#if ASSERT_PIN(SAFETY_DOOR) case CMD_CODE_SAFETY_DOOR: SETFLAG(cnc_state.exec_state, (EXEC_HOLD | EXEC_DOOR)); break; +#endif case CMD_CODE_JOG_CANCEL: if (cnc_get_exec_state(EXEC_JOG | EXEC_RUN) == (EXEC_JOG | EXEC_RUN)) { @@ -812,6 +814,7 @@ bool cnc_check_interlocking(void) return false; } +#if ASSERT_PIN(SAFETY_DOOR) // the safety door condition is active if (cnc_get_exec_state(EXEC_DOOR)) { @@ -832,6 +835,7 @@ bool cnc_check_interlocking(void) return false; } +#endif // an hold condition is active and motion as stopped if (cnc_get_exec_state(EXEC_HOLD) && !cnc_get_exec_state(EXEC_RUN)) diff --git a/uCNC/src/cnc.h b/uCNC/src/cnc.h index c44c8dc90..c8eff35b2 100644 --- a/uCNC/src/cnc.h +++ b/uCNC/src/cnc.h @@ -50,6 +50,26 @@ extern "C" #define RT_CMD_COOL_FLD_TOGGLE 64 #define RT_CMD_COOL_MST_TOGGLE 128 +/** + * Flags and state changes + * + * EXEC_KILL + * Set by cnc_alarm. + * Cleared by reset or unlock depending on the the alarm priority. Cannot be cleared if ESTOP is pressed. + * + * EXEC_LIMITS + * Set when at a transition of a limit switch from inactive to the active state. + * Cleared by reset or unlock. Not affected by the limit switch state. + * + * EXEC_UNHOMED + * Set when the interpolator is abruptly stopped causing the position to be lost. + * Cleared by homing or unlock. + * + * EXEC_DOOR + * Set with when the safety door pin is active or the safety door command is called. + * Cleared by cycle resume, unlock or reset. If the door is opened it will remain active + * + */ // 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 diff --git a/uCNC/src/core/parser.c b/uCNC/src/core/parser.c index 13c43ecb9..dc7ccd91f 100644 --- a/uCNC/src/core/parser.c +++ b/uCNC/src/core/parser.c @@ -594,10 +594,12 @@ static uint8_t parse_grbl_exec_code(uint8_t code) break; case GRBL_UNLOCK: cnc_unlock(true); +#if ASSERT_PIN(SAFETY_DOOR) if (cnc_get_exec_state(EXEC_DOOR)) { return STATUS_CHECK_DOOR; } +#endif protocol_send_feedback(MSG_FEEDBACK_3); break; case GRBL_HOME: @@ -607,11 +609,12 @@ static uint8_t parse_grbl_exec_code(uint8_t code) } cnc_unlock(true); +#if ASSERT_PIN(SAFETY_DOOR) if (cnc_get_exec_state(EXEC_DOOR)) { return STATUS_CHECK_DOOR; } - +#endif cnc_home(); break; case GRBL_HELP: @@ -2583,7 +2586,7 @@ void parser_reset(void) #endif #ifdef ENABLE_PARSER_MODULES - EVENT_INVOKE(parser_reset, NULL); + EVENT_INVOKE(parser_reset, NULL); #endif } diff --git a/uCNC/src/interface/protocol.c b/uCNC/src/interface/protocol.c index 3759d6c8f..f361101a9 100644 --- a/uCNC/src/interface/protocol.c +++ b/uCNC/src/interface/protocol.c @@ -232,6 +232,7 @@ void protocol_send_status(void) { switch (state) { +#if ASSERT_PIN(SAFETY_DOOR) case EXEC_DOOR: protocol_send_string(MSG_STATUS_DOOR); if (CHECKFLAG(controls, SAFETY_DOOR_MASK)) @@ -257,6 +258,7 @@ void protocol_send_status(void) } } break; +#endif case EXEC_UNHOMED: case EXEC_LIMITS: if (!cnc_get_exec_state(EXEC_HOMING)) From 9a0f745cc82fbcb7c8abf8e20fb222156de3e859 Mon Sep 17 00:00:00 2001 From: Paciente8159 Date: Tue, 10 Jan 2023 16:31:29 +0000 Subject: [PATCH 07/10] fixed JOG stop after DOOR - modified interlocking to terminate JOG motion after DOOR is opened - homing now possible with hard limits disabled - with hard limits disabled endstop can be triggered in run mode --- uCNC/src/cnc.c | 36 ++++++++++++++++++------------------ uCNC/src/cnc.h | 3 ++- uCNC/src/core/io_control.c | 2 +- uCNC/src/core/parser.c | 2 +- 4 files changed, 22 insertions(+), 21 deletions(-) diff --git a/uCNC/src/cnc.c b/uCNC/src/cnc.c index 82262fa14..557c1e312 100644 --- a/uCNC/src/cnc.c +++ b/uCNC/src/cnc.c @@ -224,7 +224,7 @@ bool cnc_dotasks(void) // check security interlocking for any problem if (!cnc_check_interlocking()) { - return !cnc_get_exec_state(EXEC_KILL); + return !cnc_get_exec_state(EXEC_INTERLOCKING_FAIL); } if (!lock_itp) @@ -337,7 +337,7 @@ uint8_t cnc_unlock(bool force) // checks all interlocking again cnc_check_interlocking(); - // forces to clear HALT error to allow motion after limit switch trigger + // forces to clear EXEC_UNHOMED error to allow motion after limit switch trigger if (force) { CLEARFLAG(cnc_state.exec_state, EXEC_UNHOMED); @@ -345,7 +345,7 @@ uint8_t cnc_unlock(bool force) } // if any alarm state is still active checks system faults - if (cnc_get_exec_state(EXEC_ALARM)) + if (cnc_get_exec_state(EXEC_ALARM) || cnc_has_alarm()) { if (!cnc_get_exec_state(EXEC_KILL)) { @@ -813,6 +813,21 @@ bool cnc_check_interlocking(void) return false; } + + // an hold condition is active and motion as stopped + if (cnc_get_exec_state(EXEC_HOLD) && !cnc_get_exec_state(EXEC_RUN)) + { + itp_stop(); // stop motion + + if (cnc_get_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; + } #if ASSERT_PIN(SAFETY_DOOR) // the safety door condition is active @@ -837,21 +852,6 @@ bool cnc_check_interlocking(void) } #endif - // an hold condition is active and motion as stopped - if (cnc_get_exec_state(EXEC_HOLD) && !cnc_get_exec_state(EXEC_RUN)) - { - itp_stop(); // stop motion - - if (cnc_get_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/uCNC/src/cnc.h b/uCNC/src/cnc.h index c8eff35b2..6dd0c5512 100644 --- a/uCNC/src/cnc.h +++ b/uCNC/src/cnc.h @@ -82,7 +82,8 @@ extern "C" #define EXEC_KILL 128 // Emergency stop #define EXEC_RESUMING (EXEC_HOLD | EXEC_RUN) // Motions are being being hold or resumed #define EXEC_HOMING_HIT (EXEC_HOMING | EXEC_LIMITS) // Limit switch is active during a homing motion -#define EXEC_ALARM (EXEC_UNHOMED | EXEC_LIMITS | EXEC_KILL) // System alarms +#define EXEC_INTERLOCKING_FAIL (EXEC_LIMITS | EXEC_KILL) // Interlocking check failed +#define EXEC_ALARM (EXEC_UNHOMED | EXEC_INTERLOCKING_FAIL) // System alarms #define EXEC_RESET_LOCKED (EXEC_ALARM | EXEC_DOOR | EXEC_HOLD) // System reset locked #define EXEC_GCODE_LOCKED (EXEC_ALARM | EXEC_DOOR | EXEC_HOMING | EXEC_JOG) // Gcode is locked by an alarm or any special motion state #define EXEC_ALLACTIVE 255 // All states diff --git a/uCNC/src/core/io_control.c b/uCNC/src/core/io_control.c index b6bb90121..76da6b0ca 100644 --- a/uCNC/src/core/io_control.c +++ b/uCNC/src/core/io_control.c @@ -94,7 +94,7 @@ MCU_IO_CALLBACK void mcu_limits_changed_cb(void) { #ifndef DISABLE_ALL_LIMITS - if (g_settings.hard_limits_enabled) + if (g_settings.hard_limits_enabled || cnc_get_exec_state(EXEC_HOMING)) { static uint8_t prev_limits = 0; uint8_t limits = io_get_limits(); diff --git a/uCNC/src/core/parser.c b/uCNC/src/core/parser.c index dc7ccd91f..d8970f1d7 100644 --- a/uCNC/src/core/parser.c +++ b/uCNC/src/core/parser.c @@ -191,7 +191,7 @@ uint8_t parser_read_command(void) cnc_clear_exec_state(EXEC_JOG); return error; } - else if (cnc_get_exec_state(~(EXEC_RUN | EXEC_HOLD | EXEC_RESUMING))) + else if (cnc_get_exec_state(~(EXEC_RUN | EXEC_HOLD)) || cnc_has_alarm()) // if any other than idle, run or hold discards the command { parser_discard_command(); return STATUS_SYSTEM_GC_LOCK; From 656f60d28bdb8383eaabe18cc5249a9013cd2752 Mon Sep 17 00:00:00 2001 From: Paciente8159 Date: Wed, 11 Jan 2023 09:51:07 +0000 Subject: [PATCH 08/10] fixed EXEC_UNHOMED clearing at unlock --- uCNC/src/cnc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uCNC/src/cnc.c b/uCNC/src/cnc.c index 557c1e312..60b8eacaf 100644 --- a/uCNC/src/cnc.c +++ b/uCNC/src/cnc.c @@ -420,7 +420,7 @@ void cnc_clear_exec_state(uint8_t statemask) #endif // has a pending (not cleared by user) alarm - if (cnc_state.alarm <= EXEC_ALARM_ABORT_CYCLE || g_settings.homing_enabled) + if (cnc_state.alarm || g_settings.homing_enabled) { CLEARFLAG(statemask, EXEC_UNHOMED); } From 52c2f53254b3f729b3f5d841d6872746e5c33865 Mon Sep 17 00:00:00 2001 From: Paciente8159 Date: Wed, 11 Jan 2023 10:04:59 +0000 Subject: [PATCH 09/10] Update mcu_virtual.c --- uCNC/src/hal/mcus/virtual/mcu_virtual.c | 34 ++++++++++++------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/uCNC/src/hal/mcus/virtual/mcu_virtual.c b/uCNC/src/hal/mcus/virtual/mcu_virtual.c index 4e2d7113f..a094102e7 100644 --- a/uCNC/src/hal/mcus/virtual/mcu_virtual.c +++ b/uCNC/src/hal/mcus/virtual/mcu_virtual.c @@ -723,25 +723,25 @@ DWORD WINAPI virtualconsoleserver(LPVOID lpParam) // Receive until the peer shuts down the connection do { - unsigned char c = getch(); + unsigned char c = getchar(); switch (c) { - case '"': - virtualmap.special_inputs ^= (1 << (ESTOP - LIMIT_X)); - mcu_controls_changed_cb(); - break; - case '%': - virtualmap.special_inputs ^= (1 << (PROBE - LIMIT_X)); - mcu_limits_changed_cb(); - break; - case '&': - virtualmap.special_inputs ^= (1 << (LIMIT_Y - LIMIT_X)); - mcu_limits_changed_cb(); - break; - // case '/': - // virtualmap.special_inputs ^= (1 << (LIMIT_Z - LIMIT_X)); - // mcu_limits_changed_cb(); - // break; +// case '"': +// virtualmap.special_inputs ^= (1 << (ESTOP - LIMIT_X)); +// mcu_controls_changed_cb(); +// break; +// case '%': +// virtualmap.special_inputs ^= (1 << (LIMIT_X - LIMIT_X)); +// mcu_limits_changed_cb(); +// break; +// case '&': +// virtualmap.special_inputs ^= (1 << (LIMIT_Y - LIMIT_X)); +// mcu_limits_changed_cb(); +// break; +// case '/': +// virtualmap.special_inputs ^= (1 << (LIMIT_Z - LIMIT_X)); +// mcu_limits_changed_cb(); +// break; // case '[': // virtualmap.special_inputs ^= (1 << (LIMIT_X2 - LIMIT_X)); // mcu_limits_changed_cb(); From 8ee286a09fbe8b98e25f22c9661a84711611e68a Mon Sep 17 00:00:00 2001 From: Paciente8159 Date: Wed, 11 Jan 2023 14:28:55 +0000 Subject: [PATCH 10/10] fixed parser state print and unlock parser reset - unlock command only reset parser stopping group (preserves the parser state) - removed duplicated itp run condition check - fixed parser modal states active protocol print that added the group 0 mantissa to other groups as well --- uCNC/src/cnc.c | 10 ++++------ uCNC/src/cnc.h | 1 - uCNC/src/core/interpolator.c | 9 ++------- uCNC/src/core/parser.c | 10 +++++++--- uCNC/src/core/parser.h | 2 +- uCNC/src/interface/protocol.c | 5 +++-- 6 files changed, 17 insertions(+), 20 deletions(-) diff --git a/uCNC/src/cnc.c b/uCNC/src/cnc.c index 60b8eacaf..31174df13 100644 --- a/uCNC/src/cnc.c +++ b/uCNC/src/cnc.c @@ -369,7 +369,7 @@ uint8_t cnc_unlock(bool force) io_set_steps(g_settings.step_invert_mask); io_enable_steppers(g_settings.step_enable_invert); - parser_reset(); + parser_reset(true); // reset stop group only // hard reset // if homing not enabled run startup blocks @@ -437,7 +437,7 @@ void cnc_clear_exec_state(uint8_t statemask) // if releasing from a HOLD state with and active delay in exec if (CHECKFLAG(statemask, EXEC_HOLD) && cnc_get_exec_state(EXEC_HOLD)) { - SETFLAG(cnc_state.exec_state, EXEC_RESUMING); + CLEARFLAG(cnc_state.exec_state, EXEC_HOLD); #if TOOL_COUNT > 0 // updated the coolant pins tool_set_coolant(planner_get_coolant()); @@ -446,7 +446,6 @@ void cnc_clear_exec_state(uint8_t statemask) { if (!planner_buffer_is_empty()) { - cnc_delay_ms(DELAY_ON_RESUME_COOLANT * 1000); } } @@ -464,7 +463,6 @@ void cnc_clear_exec_state(uint8_t statemask) } #endif #endif - CLEARFLAG(cnc_state.exec_state, EXEC_RESUMING); } CLEARFLAG(cnc_state.exec_state, statemask); @@ -529,7 +527,7 @@ void cnc_call_rt_command(uint8_t command) #endif case CMD_CODE_CYCLE_START: // prevents loop if cycle start is always pressed or unconnected (during cnc_dotasks) - if (cnc_get_exec_state(EXEC_RESUMING) != EXEC_RESUMING) + if (!cnc_get_exec_state(EXEC_RUN)) { SETFLAG(cnc_state.rt_cmd, RT_CMD_CYCLE_START); // tries to clear hold if possible } @@ -813,7 +811,7 @@ bool cnc_check_interlocking(void) return false; } - + // an hold condition is active and motion as stopped if (cnc_get_exec_state(EXEC_HOLD) && !cnc_get_exec_state(EXEC_RUN)) { diff --git a/uCNC/src/cnc.h b/uCNC/src/cnc.h index 6dd0c5512..8cb512b36 100644 --- a/uCNC/src/cnc.h +++ b/uCNC/src/cnc.h @@ -80,7 +80,6 @@ extern "C" #define EXEC_UNHOMED 32 // Machine is not homed or lost position due to abrupt stop #define EXEC_LIMITS 64 // Limits hit #define EXEC_KILL 128 // Emergency stop -#define EXEC_RESUMING (EXEC_HOLD | EXEC_RUN) // Motions are being being hold or resumed #define EXEC_HOMING_HIT (EXEC_HOMING | EXEC_LIMITS) // Limit switch is active during a homing motion #define EXEC_INTERLOCKING_FAIL (EXEC_LIMITS | EXEC_KILL) // Interlocking check failed #define EXEC_ALARM (EXEC_UNHOMED | EXEC_INTERLOCKING_FAIL) // System alarms diff --git a/uCNC/src/core/interpolator.c b/uCNC/src/core/interpolator.c index c7e0ee8d4..19dc30cc0 100644 --- a/uCNC/src/core/interpolator.c +++ b/uCNC/src/core/interpolator.c @@ -115,8 +115,6 @@ static itp_segment_t *itp_rt_sgm; #if (defined(ENABLE_DUAL_DRIVE_AXIS) || defined(IS_DELTA_KINEMATICS)) static volatile uint8_t itp_step_lock; #endif -// keeps track if the itp timer is running or not (prevent restarting) -static volatile bool itp_is_running; #ifdef ENABLE_RT_SYNC_MOTIONS volatile int32_t itp_sync_step_counter; @@ -1059,8 +1057,6 @@ void itp_stop(void) cnc_set_exec_state(EXEC_UNHOMED); } - cnc_clear_exec_state(EXEC_RUN); - io_set_steps(g_settings.step_invert_mask); #if TOOL_COUNT > 0 if (g_settings.laser_mode) @@ -1070,7 +1066,7 @@ void itp_stop(void) #endif mcu_stop_itp_isr(); - itp_is_running = false; + cnc_clear_exec_state(EXEC_RUN); } void itp_stop_tools(void) @@ -1715,7 +1711,7 @@ MCU_CALLBACK void mcu_step_cb(void) void itp_start(bool is_synched) { // starts the step isr if is stopped and there are segments to execute - if (!cnc_get_exec_state(EXEC_HOLD | EXEC_ALARM | EXEC_RESUMING) && !itp_sgm_is_empty() && !itp_is_running) // exec state is not hold or alarm and not already running + if (!cnc_get_exec_state(EXEC_RUN | EXEC_HOLD | EXEC_ALARM) && !itp_sgm_is_empty()) // exec state is not hold or alarm and not already running { // check if the start is controlled by synched motion before start if (!is_synched) @@ -1723,7 +1719,6 @@ void itp_start(bool is_synched) __ATOMIC__ { cnc_set_exec_state(EXEC_RUN); // flags that it started running - itp_is_running = true; 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/uCNC/src/core/parser.c b/uCNC/src/core/parser.c index d8970f1d7..37869be34 100644 --- a/uCNC/src/core/parser.c +++ b/uCNC/src/core/parser.c @@ -155,7 +155,7 @@ void parser_init(void) #endif memset(parser_last_pos, 0, sizeof(parser_last_pos)); parser_parameters_load(); - parser_reset(); + parser_reset(false); } uint8_t parser_read_command(void) @@ -2557,8 +2557,13 @@ static void parser_discard_command(void) } while (c != EOL); } -void parser_reset(void) +void parser_reset(bool stopgroup_only) { + parser_state.groups.stopping = 0; // resets all stopping commands (M0,M1,M2,M30,M60) + if (stopgroup_only) + { + return; + } parser_state.groups.coord_system = G54; // G54 parser_state.groups.plane = G17; // G17 parser_state.groups.feed_speed_override = M48; // M48 @@ -2566,7 +2571,6 @@ void parser_reset(void) parser_state.groups.distance_mode = G90; // G90 parser_state.groups.feedrate_mode = G94; // G94 parser_state.groups.tlo_mode = G49; // G49 - parser_state.groups.stopping = 0; // resets all stopping commands (M0,M1,M2,M30,M60) #if TOOL_COUNT > 0 parser_state.groups.coolant = M9; // M9 parser_state.groups.spindle_turning = M5; // M5 diff --git a/uCNC/src/core/parser.h b/uCNC/src/core/parser.h index f516b4a1a..567751a39 100644 --- a/uCNC/src/core/parser.h +++ b/uCNC/src/core/parser.h @@ -278,7 +278,7 @@ extern "C" void parser_parameters_reset(void); void parser_parameters_save(void); void parser_sync_position(void); - void parser_reset(void); + void parser_reset(bool stopgroup_only); void parser_machine_to_work(float *axis); uint8_t parser_get_float(float *value); uint8_t parser_exec_command(parser_state_t *new_state, parser_words_t *words, parser_cmd_explicit_t *cmd); diff --git a/uCNC/src/interface/protocol.c b/uCNC/src/interface/protocol.c index f361101a9..c0cd694bd 100644 --- a/uCNC/src/interface/protocol.c +++ b/uCNC/src/interface/protocol.c @@ -501,9 +501,10 @@ void protocol_send_gcode_modes(void) protocol_send_string(__romstr__("[GC:")); - for (uint8_t i = 0; i < 7; i++) + protocol_send_parser_modalstate('G', modalgroups[0], modalgroups[12]); + for (uint8_t i = 1; i < 7; i++) { - protocol_send_parser_modalstate('G', modalgroups[i], modalgroups[12]); + protocol_send_parser_modalstate('G', modalgroups[i], 0); } if (modalgroups[7] == 62)