mirror of
https://github.com/synthetos/g2.git
synced 2026-09-22 11:29:24 +08:00
Milestone: First time it makes it all the way through a !~ cycle with actions
This commit is contained in:
+2
-2
@@ -166,7 +166,7 @@ stat_t cm_alarm(const stat_t status, const char *msg)
|
||||
(cm->machine_state == MACHINE_PANIC)) {
|
||||
return (STAT_OK); // don't alarm if already in an alarm state
|
||||
}
|
||||
cm_request_feedhold(FEEDHOLD_TYPE_SCRAM, FEEDHOLD_FINAL_ALARM); // fast stop and alarm
|
||||
cm_request_feedhold(FEEDHOLD_TYPE_SCRAM, FEEDHOLD_EXIT_ALARM); // fast stop and alarm
|
||||
rpt_exception(status, msg); // send alarm message
|
||||
sr_request_status_report(SR_REQUEST_TIMED);
|
||||
return (status);
|
||||
@@ -194,7 +194,7 @@ stat_t cm_shutdown(const stat_t status, const char *msg)
|
||||
if ((cm->machine_state == MACHINE_SHUTDOWN) || (cm->machine_state == MACHINE_PANIC)) {
|
||||
return (STAT_OK); // don't shutdown if shutdown or panic'd
|
||||
}
|
||||
cm_request_feedhold(FEEDHOLD_TYPE_SCRAM, FEEDHOLD_FINAL_SHUTDOWN); // fast stop and shutdown
|
||||
cm_request_feedhold(FEEDHOLD_TYPE_SCRAM, FEEDHOLD_EXIT_SHUTDOWN); // fast stop and shutdown
|
||||
|
||||
// cm_halt_motion(); // halt motors (may have already been done from GPIO)
|
||||
// spindle_reset(); // stop spindle immediately and set speed to 0 RPM
|
||||
|
||||
+81
-88
@@ -63,131 +63,124 @@
|
||||
|
||||
// ### LAYER 8 CRITICAL REGION ###
|
||||
// ### DO NOT CHANGE THESE ENUMERATIONS WITHOUT COMMUNITY INPUT ###
|
||||
typedef enum { // check alignment with messages in config.c / msg_stat strings
|
||||
COMBINED_INITIALIZING = 0, // [0] machine is initializing
|
||||
COMBINED_READY, // [1] machine is ready for use
|
||||
COMBINED_ALARM, // [2] machine in alarm state
|
||||
COMBINED_PROGRAM_STOP, // [3] program stop/no more blocks
|
||||
COMBINED_PROGRAM_END, // [4] program end
|
||||
COMBINED_RUN, // [5] machine is running
|
||||
COMBINED_HOLD, // [6] machine is holding
|
||||
COMBINED_PROBE, // [7] probe cycle activ
|
||||
COMBINED_CYCLE, // [8] reserved for canned cycles
|
||||
COMBINED_HOMING, // [9] homing cycle active
|
||||
COMBINED_JOG, // [10] jogging cycle active
|
||||
COMBINED_INTERLOCK, // [11] machine in safety interlock hold
|
||||
COMBINED_SHUTDOWN, // [12] machine in shutdown state
|
||||
COMBINED_PANIC // [13] machine in panic state
|
||||
typedef enum { // check alignment with messages in config.c / msg_stat strings
|
||||
COMBINED_INITIALIZING = 0, // [0] machine is initializing
|
||||
COMBINED_READY, // [1] machine is ready for use
|
||||
COMBINED_ALARM, // [2] machine in alarm state
|
||||
COMBINED_PROGRAM_STOP, // [3] program stop/no more blocks
|
||||
COMBINED_PROGRAM_END, // [4] program end
|
||||
COMBINED_RUN, // [5] machine is running
|
||||
COMBINED_HOLD, // [6] machine is holding
|
||||
COMBINED_PROBE, // [7] probe cycle activ
|
||||
COMBINED_CYCLE, // [8] reserved for canned cycles
|
||||
COMBINED_HOMING, // [9] homing cycle active
|
||||
COMBINED_JOG, // [10] jogging cycle active
|
||||
COMBINED_INTERLOCK, // [11] machine in safety interlock hold
|
||||
COMBINED_SHUTDOWN, // [12] machine in shutdown state
|
||||
COMBINED_PANIC // [13] machine in panic state
|
||||
} cmCombinedState;
|
||||
//### END CRITICAL REGION ###
|
||||
|
||||
typedef enum { // Note: MachineState signals if the machine is in cycle (5) or some other non-cycle state
|
||||
MACHINE_INITIALIZING = 0, // machine is initializing
|
||||
MACHINE_READY, // machine is ready for use but idle
|
||||
MACHINE_ALARM, // machine is in alarm state
|
||||
MACHINE_PROGRAM_STOP, // no blocks to run; like PROGRAM_END but without the M2 to reset gcode state
|
||||
MACHINE_PROGRAM_END, // program end (same as MACHINE_READY, really...)
|
||||
MACHINE_CYCLE, // machine is in cycle, running; blocks still to run, or steppers are busy
|
||||
MACHINE_INTERLOCK, // machine is in interlock state
|
||||
MACHINE_SHUTDOWN, // machine is in shutdown state
|
||||
MACHINE_PANIC // machine is in panic state
|
||||
typedef enum { // Note: MachineState signals if the machine is in cycle (5) or some other non-cycle state
|
||||
MACHINE_INITIALIZING = 0, // machine is initializing
|
||||
MACHINE_READY, // machine is ready for use but idle
|
||||
MACHINE_ALARM, // machine is in alarm state
|
||||
MACHINE_PROGRAM_STOP, // no blocks to run; like PROGRAM_END but without the M2 to reset gcode state
|
||||
MACHINE_PROGRAM_END, // program end (same as MACHINE_READY, really...)
|
||||
MACHINE_CYCLE, // machine is in cycle, running; blocks still to run, or steppers are busy
|
||||
MACHINE_INTERLOCK, // machine is in interlock state
|
||||
MACHINE_SHUTDOWN, // machine is in shutdown state
|
||||
MACHINE_PANIC // machine is in panic state
|
||||
} cmMachineState;
|
||||
|
||||
typedef enum {
|
||||
MOTION_STOP = 0, // motion has stopped: set when the steppers reach the end of the planner queue
|
||||
MOTION_RUN // machine is in motion: set when the steppers execute an ALINE segment
|
||||
MOTION_STOP = 0, // motion has stopped: set when the steppers reach the end of the planner queue
|
||||
MOTION_RUN // machine is in motion: set when the steppers execute an ALINE segment
|
||||
} cmMotionState;
|
||||
|
||||
typedef enum { // state machine for cycle start
|
||||
CYCLE_START_NONE = 0, // not in a cycle
|
||||
typedef enum { // state machine for cycle start
|
||||
CYCLE_START_OFF = 0, // not requested
|
||||
CYCLE_START_REQUESTED,
|
||||
CYCLE_START_COMPLETE
|
||||
} cmCycleState;
|
||||
|
||||
typedef enum {
|
||||
CYCLE_NONE = 0, // not in a cycle
|
||||
CYCLE_MACHINING, // in normal machining cycle
|
||||
CYCLE_HOMING, // in homing cycle
|
||||
CYCLE_PROBE, // in probe cycle
|
||||
CYCLE_JOG // in jogging cycle
|
||||
// CYCLE_G81 // illustration of canned cycles
|
||||
CYCLE_NONE = 0, // not in a cycle
|
||||
CYCLE_MACHINING, // in normal machining cycle
|
||||
CYCLE_HOMING, // in homing cycle
|
||||
CYCLE_PROBE, // in probe cycle
|
||||
CYCLE_JOG // in jogging cycle
|
||||
// CYCLE_G81 // illustration of canned cycles
|
||||
// ...
|
||||
} cmCycleType;
|
||||
|
||||
typedef enum { // feedhold type parameter
|
||||
FEEDHOLD_TYPE_ACTIONS = 0, // feedhold at max jerk with actions
|
||||
FEEDHOLD_TYPE_NO_ACTIONS, // feedhold at max jerk with no actions
|
||||
FEEDHOLD_TYPE_SYNC, // feedhold at max jerk with queue flush and sync command
|
||||
FEEDHOLD_TYPE_FAST, // feedhold at high jerk with no actions. Can resume
|
||||
FEEDHOLD_TYPE_SCRAM // feedhold at high jerk and stop all active devices
|
||||
typedef enum { // feedhold type parameter
|
||||
FEEDHOLD_TYPE_ACTIONS = 0, // feedhold at max jerk with actions
|
||||
FEEDHOLD_TYPE_NO_ACTIONS, // feedhold at max jerk with no actions
|
||||
FEEDHOLD_TYPE_SYNC, // feedhold at max jerk with queue flush and sync command
|
||||
FEEDHOLD_TYPE_FAST, // feedhold at high jerk with no actions. Can resume
|
||||
FEEDHOLD_TYPE_SCRAM // feedhold at high jerk and stop all active devices
|
||||
} cmFeedholdType;
|
||||
|
||||
typedef enum { // feedhold final operation
|
||||
FEEDHOLD_FINAL_CYCLE = 0, // normal final state - HOLD or STOP, depending on type
|
||||
FEEDHOLD_FINAL_STOP, // perform program stop
|
||||
FEEDHOLD_FINAL_END, // perform program end
|
||||
FEEDHOLD_FINAL_ALARM, // perform alarm
|
||||
FEEDHOLD_FINAL_SHUTDOWN, // perform shutdown
|
||||
FEEDHOLD_FINAL_INTERLOCK // report as interlock
|
||||
typedef enum { // feedhold final operation
|
||||
FEEDHOLD_EXIT_CYCLE = 0, // exit feedhold with cycle restart - HOLD or STOP, depending on type
|
||||
FEEDHOLD_EXIT_FLUSH, // exit feedhold with flush
|
||||
FEEDHOLD_EXIT_STOP, // perform program stop
|
||||
FEEDHOLD_EXIT_END, // perform program end
|
||||
FEEDHOLD_EXIT_ALARM, // perform alarm
|
||||
FEEDHOLD_EXIT_SHUTDOWN, // perform shutdown
|
||||
FEEDHOLD_EXIT_INTERLOCK // report as interlock
|
||||
} cmFeedholdFinal;
|
||||
|
||||
typedef enum { // feedhold state machine
|
||||
// FEEDHOLD_P1_EXIT = -1, // set when p1 feedhold is due to exit
|
||||
FEEDHOLD_OFF = 0, // no feedhold in effect
|
||||
FEEDHOLD_REQUESTED, // feedhold has been requested but not started yet
|
||||
FEEDHOLD_SYNC, // start hold - sync to latest aline segment
|
||||
FEEDHOLD_DECEL_CONTINUE, // in deceleration that will not end at zero
|
||||
FEEDHOLD_DECEL_TO_ZERO, // in deceleration that will go to zero
|
||||
FEEDHOLD_DECEL_COMPLETE, // feedhold deceleration has completed, but motors may not have stopped yet
|
||||
FEEDHOLD_MOTION_STOPPING, // waiting for motors to have stopped at hold point (motion stop)
|
||||
FEEDHOLD_MOTION_STOPPED, // motion has stopped at hold point
|
||||
// FEEDHOLD_P2_START, // enter secondary planner and perform feedhold actions (once)
|
||||
// FEEDHOLD_P2_WAIT, // wait for feedhold actions to complete
|
||||
|
||||
FEEDHOLD_HOLD_ACTION_START,
|
||||
FEEDHOLD_HOLD_PENDING, // wait for feedhold actions to complete
|
||||
FEEDHOLD_HOLD_DONE, //
|
||||
|
||||
FEEDHOLD_HOLD, // holding (steady state) Must be last state
|
||||
|
||||
FEEDHOLD_HOLD_EXIT_PENDING, // performing exit actions
|
||||
FEEDHOLD_HOLD_EXIT_DONE, // completed exit actions
|
||||
|
||||
// FEEDHOLD_P2_EXIT // set when p2 feedhold is finishing
|
||||
typedef enum { // feedhold state machine
|
||||
FEEDHOLD_OFF = 0, // no feedhold in effect
|
||||
FEEDHOLD_REQUESTED, // feedhold has been requested but not started yet
|
||||
FEEDHOLD_SYNC, // start hold - sync to latest aline segment
|
||||
FEEDHOLD_DECEL_CONTINUE, // in deceleration that will not end at zero
|
||||
FEEDHOLD_DECEL_TO_ZERO, // in deceleration that will go to zero
|
||||
FEEDHOLD_DECEL_COMPLETE, // feedhold deceleration has completed, but motors may not have stopped yet
|
||||
FEEDHOLD_MOTION_STOPPING, // waiting for motors to have stopped at hold point (motion stop)
|
||||
FEEDHOLD_MOTION_STOPPED, // motion has stopped at hold point
|
||||
FEEDHOLD_HOLD_ACTIONS_START,
|
||||
FEEDHOLD_HOLD_ACTIONS_PENDING, // wait for feedhold actions to complete
|
||||
FEEDHOLD_HOLD_ACTIONS_COMPLETE, //
|
||||
FEEDHOLD_HOLD, // HOLDING (steady state)
|
||||
FEEDHOLD_EXIT_ACTIONS_PENDING, // performing exit actions
|
||||
FEEDHOLD_EXIT_ACTIONS_COMPLETE // completed exit actions
|
||||
} cmFeedholdState;
|
||||
|
||||
typedef enum { // applies to cm->homing_state
|
||||
HOMING_NOT_HOMED = 0, // machine is not homed (0=false)
|
||||
HOMING_HOMED = 1, // machine is homed (1=true)
|
||||
HOMING_WAITING // machine waiting to be homed
|
||||
typedef enum { // applies to cm->homing_state
|
||||
HOMING_NOT_HOMED = 0, // machine is not homed (0=false)
|
||||
HOMING_HOMED = 1, // machine is homed (1=true)
|
||||
HOMING_WAITING // machine waiting to be homed
|
||||
} cmHomingState;
|
||||
|
||||
typedef enum { // applies to cm->probe_state
|
||||
PROBE_FAILED = 0, // probe reached endpoint without triggering
|
||||
PROBE_SUCCEEDED = 1, // probe was triggered, cm.probe_results has position
|
||||
PROBE_WAITING = 2 // probe is waiting to be started or is running
|
||||
typedef enum { // applies to cm->probe_state
|
||||
PROBE_FAILED = 0, // probe reached endpoint without triggering
|
||||
PROBE_SUCCEEDED = 1, // probe was triggered, cm.probe_results has position
|
||||
PROBE_WAITING = 2 // probe is waiting to be started or is running
|
||||
} cmProbeState;
|
||||
|
||||
typedef enum {
|
||||
SAFETY_INTERLOCK_ENGAGED = 0, // meaning the interlock input is CLOSED (low)
|
||||
SAFETY_INTERLOCK_ENGAGED = 0, // meaning the interlock input is CLOSED (low)
|
||||
SAFETY_INTERLOCK_DISENGAGED
|
||||
} cmSafetyState;
|
||||
|
||||
typedef enum { // feed override state machine
|
||||
typedef enum { // feed override state machine
|
||||
MFO_OFF = 0,
|
||||
MFO_REQUESTED,
|
||||
MFO_SYNC
|
||||
} cmOverrideState;
|
||||
|
||||
typedef enum { // queue flush state machine
|
||||
FLUSH_OFF = 0, // no queue flush in effect
|
||||
FLUSH_REQUESTED, // flush has been requested but not started yet
|
||||
FLUSH_WAS_RUN // transient state to note that a queue flush has been run
|
||||
typedef enum { // queue flush state machine
|
||||
FLUSH_OFF = 0, // no queue flush in effect
|
||||
FLUSH_REQUESTED, // flush has been requested but not started yet
|
||||
FLUSH_WAS_RUN // transient state to note that a queue flush has been run
|
||||
} cmFlushState;
|
||||
|
||||
typedef enum { // Motion profiles
|
||||
PROFILE_NORMAL = 0, // Normal jerk in effect
|
||||
PROFILE_FAST // High speed jerk in effect
|
||||
typedef enum { // Motion profiles
|
||||
PROFILE_NORMAL = 0, // Normal jerk in effect
|
||||
PROFILE_FAST // High speed jerk in effect
|
||||
} cmMotion_profile;
|
||||
|
||||
/*****************************************************************************
|
||||
|
||||
@@ -238,9 +238,8 @@ static void _dispatch_kernel(const devflags_t flags)
|
||||
}
|
||||
|
||||
// trap single character commands
|
||||
if (*cs.bufp == '!') { cm_request_feedhold(FEEDHOLD_TYPE_ACTIONS, FEEDHOLD_FINAL_CYCLE); }
|
||||
if (*cs.bufp == '!') { cm_request_feedhold(FEEDHOLD_TYPE_ACTIONS, FEEDHOLD_EXIT_CYCLE); }
|
||||
else if (*cs.bufp == '%') { cm_request_queue_flush(); xio_flush_to_command(); }
|
||||
// else if (*cs.bufp == '~') { cm_request_exit_hold(); } +++++
|
||||
else if (*cs.bufp == '~') { cm_request_cycle_start(); }
|
||||
else if (*cs.bufp == EOT) { cm_job_kill(); }
|
||||
else if (*cs.bufp == ENQ) { controller_request_enquiry(); }
|
||||
@@ -435,7 +434,7 @@ static stat_t _interlock_handler(void)
|
||||
if (cm->safety_interlock_disengaged != 0) {
|
||||
cm->safety_interlock_disengaged = 0;
|
||||
cm->safety_interlock_state = SAFETY_INTERLOCK_DISENGAGED;
|
||||
cm_request_feedhold(FEEDHOLD_TYPE_ACTIONS, FEEDHOLD_FINAL_INTERLOCK); // may have already requested STOP as INPUT_ACTION
|
||||
cm_request_feedhold(FEEDHOLD_TYPE_ACTIONS, FEEDHOLD_EXIT_INTERLOCK); // may have already requested STOP as INPUT_ACTION
|
||||
// feedhold was initiated by input action in gpio
|
||||
// pause spindle
|
||||
// pause coolant
|
||||
|
||||
+115
-123
@@ -42,13 +42,16 @@ static void _initiate_feedhold(void);
|
||||
static void _initiate_cycle_start(void);
|
||||
static void _initiate_queue_flush(void);
|
||||
|
||||
// Feedhold actions
|
||||
static stat_t _feedhold_with_actions(float *param);
|
||||
static stat_t _feedhold_with_no_actions(float *param);
|
||||
static stat_t _feedhold_with_sync(float *param);
|
||||
static stat_t _feedhold_exit_with_actions(float *param);
|
||||
static stat_t _feedhold_exit_with_no_actions(float *param);
|
||||
static stat_t _feedhold_restart_with_actions(float *param);
|
||||
static stat_t _feedhold_restart_with_no_actions(float *param);
|
||||
|
||||
static stat_t _cycle_exit(float *param);
|
||||
// Feedhold exits (finalization)
|
||||
static stat_t _restart_cycle(float *param);
|
||||
static stat_t _restart_flush(float *param);
|
||||
static stat_t _program_stop(float *param);
|
||||
static stat_t _program_end(float *param);
|
||||
static stat_t _alarm(float *param);
|
||||
@@ -71,11 +74,15 @@ static stat_t _interlock(float *param);
|
||||
* STAT_OK - operation has completed successfully
|
||||
* STAT_EAGAIN - operation needs to be re-entered to complete (via operation callback)
|
||||
* STAT_XXXXX - any other status is an error that quits the operation
|
||||
*
|
||||
* Constraints:
|
||||
* - Operations run to completion. They are not preemptable (at this point)
|
||||
* - Actions cannot be added to an operation once it is being run
|
||||
*/
|
||||
|
||||
/*** Object Definitions ***/
|
||||
|
||||
#define PARAM_MAX 4 // maximum number of parameters that can be passed in param
|
||||
#define PARAM_MAX 2 // maximum number of parameters that can be passed in param
|
||||
#define ACTION_MAX 12 // maximum actions that can be queued for an operation
|
||||
typedef stat_t (*action_exec_t)(float *); // callback to action execution function
|
||||
|
||||
@@ -123,9 +130,7 @@ typedef struct cmOperation { // operation runner object
|
||||
};
|
||||
|
||||
stat_t run_operation(void) {
|
||||
if (run->func == NULL) {
|
||||
return (STAT_NOOP);
|
||||
} // not an error. This is normal.
|
||||
if (run->func == NULL) { return (STAT_NOOP); } // not an error. This is normal.
|
||||
in_operation = true; // disable add_action during operations
|
||||
|
||||
stat_t status;
|
||||
@@ -136,9 +141,7 @@ typedef struct cmOperation { // operation runner object
|
||||
return (STAT_OK);
|
||||
}
|
||||
}
|
||||
if (status == STAT_EAGAIN) {
|
||||
return (STAT_EAGAIN);
|
||||
}
|
||||
if (status == STAT_EAGAIN) { return (STAT_EAGAIN); }
|
||||
reset(); // reset operation if action threw an error
|
||||
return (status); // return error code
|
||||
};
|
||||
@@ -244,15 +247,7 @@ bool cm_has_hold()
|
||||
{
|
||||
return (cm1.hold_state != FEEDHOLD_OFF);
|
||||
}
|
||||
/*
|
||||
void cm_start_hold()
|
||||
{
|
||||
// Can only request a feedhold if the machine is in motion and there not one is not already in progress
|
||||
if ((cm1.hold_state == FEEDHOLD_OFF) && (mp_has_runnable_buffer(mp))) {
|
||||
cm1.hold_state = FEEDHOLD_SYNC; // invokes hold from aline execution
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
stat_t cm_feedhold_command_blocker()
|
||||
{
|
||||
if (cm1.hold_state != FEEDHOLD_OFF) {
|
||||
@@ -261,14 +256,9 @@ stat_t cm_feedhold_command_blocker()
|
||||
return (STAT_OK);
|
||||
}
|
||||
|
||||
void cm_request_alarm()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
* request_cycle_start() - set request flag only
|
||||
* start_cycle_start() - run the cycle start
|
||||
* cm_request_cycle_start() - set request flag only
|
||||
* _initiate_cycle_start() - run the cycle start
|
||||
*/
|
||||
|
||||
void cm_request_cycle_start()
|
||||
@@ -280,6 +270,7 @@ static void _initiate_cycle_start()
|
||||
{
|
||||
// Normal cycle start - not in a feedhold
|
||||
if (cm1.hold_state == FEEDHOLD_OFF) {
|
||||
cm1.cycle_state = CYCLE_START_OFF;
|
||||
cm_cycle_start(); // execute cycle start directly
|
||||
st_request_exec_move();
|
||||
return;
|
||||
@@ -287,83 +278,23 @@ static void _initiate_cycle_start()
|
||||
|
||||
// Feedhold cycle starts run an operation to complete multiple actions
|
||||
if (cm1.hold_state == FEEDHOLD_HOLD) {
|
||||
cm1.cycle_state = CYCLE_START_OFF;
|
||||
switch (cm1.hold_type) {
|
||||
case FEEDHOLD_TYPE_ACTIONS: { op.add_action(_feedhold_exit_with_actions, nullptr); break; }
|
||||
case FEEDHOLD_TYPE_NO_ACTIONS: { op.add_action(_feedhold_exit_with_no_actions, nullptr); break; }
|
||||
case FEEDHOLD_TYPE_ACTIONS: { op.add_action(_feedhold_restart_with_actions, nullptr); break; }
|
||||
case FEEDHOLD_TYPE_NO_ACTIONS: { op.add_action(_feedhold_restart_with_no_actions, nullptr); break; }
|
||||
default: {}
|
||||
}
|
||||
switch (cm1.hold_final) {
|
||||
case FEEDHOLD_FINAL_CYCLE: { op.add_action(_cycle_exit, nullptr); break; }
|
||||
case FEEDHOLD_FINAL_STOP: { op.add_action(_program_stop, nullptr); break; }
|
||||
case FEEDHOLD_FINAL_END: { op.add_action(_program_end, nullptr); break; }
|
||||
case FEEDHOLD_FINAL_ALARM: { op.add_action(_alarm, nullptr); break; }
|
||||
case FEEDHOLD_FINAL_SHUTDOWN: { op.add_action(_shutdown, nullptr); break; }
|
||||
case FEEDHOLD_FINAL_INTERLOCK: { op.add_action(_interlock, nullptr); break; }
|
||||
case FEEDHOLD_EXIT_CYCLE: { op.add_action(_restart_cycle, nullptr); break; }
|
||||
case FEEDHOLD_EXIT_FLUSH: { op.add_action(_restart_flush, nullptr); break; }
|
||||
case FEEDHOLD_EXIT_STOP: { op.add_action(_program_stop, nullptr); break; }
|
||||
case FEEDHOLD_EXIT_END: { op.add_action(_program_end, nullptr); break; }
|
||||
case FEEDHOLD_EXIT_ALARM: { op.add_action(_alarm, nullptr); break; }
|
||||
case FEEDHOLD_EXIT_SHUTDOWN: { op.add_action(_shutdown, nullptr); break; }
|
||||
case FEEDHOLD_EXIT_INTERLOCK: { op.add_action(_interlock, nullptr); break; }
|
||||
default: {}
|
||||
}
|
||||
}
|
||||
op.run_operation();
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
* cm_request_feedhold() - request a feedhold - d0 not run it yet
|
||||
* _initiate_feedhold() - start feedhold of correct type and finalization
|
||||
* _feedhold_sync() - planner callback to reach sync point
|
||||
* _feedhold_with_actions() - perform hold entry actions
|
||||
*/
|
||||
|
||||
void cm_request_feedhold(cmFeedholdType type, cmFeedholdFinal final)
|
||||
{
|
||||
cm->hold_type = type;
|
||||
cm->hold_final = final;
|
||||
cm->hold_state = FEEDHOLD_REQUESTED;
|
||||
_initiate_feedhold(); // attempt to run it immediately
|
||||
}
|
||||
|
||||
static void _initiate_feedhold()
|
||||
{
|
||||
// This function is "safe" and will not initiate a feedhold unless it's OK to.
|
||||
|
||||
if ((cm1.hold_state == FEEDHOLD_REQUESTED) && (cm1.motion_state == MOTION_RUN)) {
|
||||
switch (cm1.hold_type) {
|
||||
case FEEDHOLD_TYPE_ACTIONS: { op.add_action(_feedhold_with_actions, nullptr); break; }
|
||||
case FEEDHOLD_TYPE_NO_ACTIONS: { op.add_action(_feedhold_with_no_actions, nullptr); break; }
|
||||
case FEEDHOLD_TYPE_SYNC: { op.add_action(_feedhold_with_sync, nullptr); break; }
|
||||
default: { }
|
||||
}
|
||||
switch (cm1.hold_final) {
|
||||
case FEEDHOLD_FINAL_STOP: { op.add_action(_program_stop, nullptr); break; }
|
||||
case FEEDHOLD_FINAL_END: { op.add_action(_program_end, nullptr); break; }
|
||||
case FEEDHOLD_FINAL_ALARM: { op.add_action(_alarm, nullptr); break; }
|
||||
case FEEDHOLD_FINAL_SHUTDOWN: { op.add_action(_shutdown, nullptr); break; }
|
||||
case FEEDHOLD_FINAL_INTERLOCK: { op.add_action(_interlock, nullptr); break; }
|
||||
default: { }
|
||||
}
|
||||
cm1.hold_state = FEEDHOLD_SYNC; // start feedhold state machine in aline exec
|
||||
return;
|
||||
}
|
||||
|
||||
// P2 feedholds only allow feedhold sync types
|
||||
if ((cm2.hold_state == FEEDHOLD_REQUESTED) && (cm2.motion_state == MOTION_RUN)) {
|
||||
op.add_action(_feedhold_with_sync, nullptr);
|
||||
cm2.hold_state = FEEDHOLD_SYNC;
|
||||
}
|
||||
}
|
||||
|
||||
static void _feedhold_sync_to_planner(float* vect, bool* flag)
|
||||
{
|
||||
cm1.hold_state = FEEDHOLD_HOLD_DONE; // penultimate state before transitioning to FEEDHOLD_HOLD
|
||||
sr_request_status_report(SR_REQUEST_IMMEDIATE);
|
||||
}
|
||||
|
||||
static stat_t _feedhold_with_no_actions(float *param)
|
||||
{
|
||||
return (STAT_OK);
|
||||
}
|
||||
|
||||
static stat_t _feedhold_with_sync(float *param)
|
||||
{
|
||||
return (STAT_OK);
|
||||
}
|
||||
|
||||
static stat_t _program_stop(float *param)
|
||||
@@ -391,12 +322,74 @@ static stat_t _interlock(float *param)
|
||||
return (STAT_OK);
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
* cm_request_feedhold() - request a feedhold - d0 not run it yet
|
||||
* _initiate_feedhold() - start feedhold of correct type and finalization
|
||||
* _feedhold_sync_to_planner() - planner callback to reach sync point
|
||||
* _feedhold_with_sync()
|
||||
* _feedhold_with_no_actions()
|
||||
* _feedhold_with_actions() - perform hold entry actions
|
||||
*/
|
||||
|
||||
void cm_request_feedhold(cmFeedholdType type, cmFeedholdFinal final)
|
||||
{
|
||||
cm->hold_type = type;
|
||||
cm->hold_final = final;
|
||||
cm->hold_state = FEEDHOLD_REQUESTED;
|
||||
_initiate_feedhold(); // attempt to run it immediately
|
||||
}
|
||||
|
||||
static void _initiate_feedhold()
|
||||
{
|
||||
// This function is "safe" and will not initiate a feedhold unless it's OK to.
|
||||
|
||||
if ((cm1.hold_state == FEEDHOLD_REQUESTED) && (cm1.motion_state == MOTION_RUN)) {
|
||||
switch (cm1.hold_type) {
|
||||
case FEEDHOLD_TYPE_ACTIONS: { op.add_action(_feedhold_with_actions, nullptr); break; }
|
||||
case FEEDHOLD_TYPE_NO_ACTIONS: { op.add_action(_feedhold_with_no_actions, nullptr); break; }
|
||||
case FEEDHOLD_TYPE_SYNC: { op.add_action(_feedhold_with_sync, nullptr); break; }
|
||||
default: { }
|
||||
}
|
||||
switch (cm1.hold_final) {
|
||||
case FEEDHOLD_EXIT_STOP: { op.add_action(_program_stop, nullptr); break; }
|
||||
case FEEDHOLD_EXIT_END: { op.add_action(_program_end, nullptr); break; }
|
||||
case FEEDHOLD_EXIT_ALARM: { op.add_action(_alarm, nullptr); break; }
|
||||
case FEEDHOLD_EXIT_SHUTDOWN: { op.add_action(_shutdown, nullptr); break; }
|
||||
case FEEDHOLD_EXIT_INTERLOCK: { op.add_action(_interlock, nullptr); break; }
|
||||
default: { }
|
||||
}
|
||||
cm1.hold_state = FEEDHOLD_SYNC; // start feedhold state machine in aline exec
|
||||
return;
|
||||
}
|
||||
|
||||
// P2 feedholds only allow feedhold sync types
|
||||
if ((cm2.hold_state == FEEDHOLD_REQUESTED) && (cm2.motion_state == MOTION_RUN)) {
|
||||
op.add_action(_feedhold_with_sync, nullptr);
|
||||
cm2.hold_state = FEEDHOLD_SYNC;
|
||||
}
|
||||
}
|
||||
|
||||
static void _feedhold_sync_to_planner(float* vect, bool* flag)
|
||||
{
|
||||
cm1.hold_state = FEEDHOLD_HOLD_ACTIONS_COMPLETE; // penultimate state before transitioning to FEEDHOLD_HOLD
|
||||
sr_request_status_report(SR_REQUEST_IMMEDIATE);
|
||||
}
|
||||
|
||||
static stat_t _feedhold_with_no_actions(float *param)
|
||||
{
|
||||
return (STAT_OK);
|
||||
}
|
||||
|
||||
static stat_t _feedhold_with_sync(float *param)
|
||||
{
|
||||
return (STAT_OK);
|
||||
}
|
||||
|
||||
static stat_t _feedhold_with_actions(float *param) // Execute Case (5)
|
||||
{
|
||||
// Check to run first-time code
|
||||
if (cm1.hold_state == FEEDHOLD_HOLD_ACTION_START) {
|
||||
cm->hold_state = FEEDHOLD_HOLD_PENDING; // next state
|
||||
if (cm1.hold_state == FEEDHOLD_HOLD_ACTIONS_START) {
|
||||
cm->hold_state = FEEDHOLD_HOLD_ACTIONS_PENDING; // next state
|
||||
|
||||
// copy the primary canonical machine to the secondary,
|
||||
// fix the planner pointer, and reset the secondary planner
|
||||
@@ -442,12 +435,12 @@ static stat_t _feedhold_with_actions(float *param) // Execute Case (5)
|
||||
}
|
||||
|
||||
// wait for hold actions to complete
|
||||
if (cm1.hold_state == FEEDHOLD_HOLD_PENDING) {
|
||||
if (cm1.hold_state == FEEDHOLD_HOLD_ACTIONS_PENDING) {
|
||||
return (STAT_EAGAIN);
|
||||
}
|
||||
|
||||
// finalize feedhold exit
|
||||
if (cm1.hold_state == FEEDHOLD_HOLD_DONE) {
|
||||
// finalize feedhold entry after callback (this is needed so we can return STAT_OK)
|
||||
if (cm1.hold_state == FEEDHOLD_HOLD_ACTIONS_COMPLETE) {
|
||||
cm1.hold_state = FEEDHOLD_HOLD;
|
||||
return (STAT_OK);
|
||||
}
|
||||
@@ -455,44 +448,45 @@ static stat_t _feedhold_with_actions(float *param) // Execute Case (5)
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
* _feedhold_exit_sync() - planner callback to reach sync point
|
||||
* _feedhold_exit_with_actions() - perform hold exit actions
|
||||
* _feedhold_restart_sync_to_planner() - planner callback to reach sync point
|
||||
* _feedhold_restart_with_no_actions() - perform hold restart with no actions
|
||||
* _feedhold_restart_with_actions() - perform hold restart with actions
|
||||
*/
|
||||
|
||||
static void _feedhold_exit_sync_to_planner(float* vect, bool* flag)
|
||||
static void _feedhold_restart_sync_to_planner(float* vect, bool* flag)
|
||||
{
|
||||
cm1.hold_state = FEEDHOLD_HOLD_EXIT_DONE; // penultimate state before transitioning to FEEDHOLD_OFF
|
||||
cm1.hold_state = FEEDHOLD_EXIT_ACTIONS_COMPLETE; // penultimate state before transitioning to FEEDHOLD_OFF
|
||||
sr_request_status_report(SR_REQUEST_IMMEDIATE);
|
||||
}
|
||||
|
||||
static stat_t _feedhold_exit_with_no_actions(float *param)
|
||||
static stat_t _feedhold_restart_with_no_actions(float *param)
|
||||
{
|
||||
return (STAT_OK);
|
||||
}
|
||||
|
||||
static stat_t _feedhold_exit_with_actions(float *param) // Execute Cases (6) and (7)
|
||||
static stat_t _feedhold_restart_with_actions(float *param) // Execute Cases (6) and (7)
|
||||
{
|
||||
// Check to run first-time code
|
||||
if (cm1.hold_state == FEEDHOLD_HOLD) {
|
||||
// perform end-hold actions --- while still in secondary machine
|
||||
coolant_control_sync(COOLANT_RESUME, COOLANT_BOTH); // resume coolant if paused
|
||||
spindle_control_sync(SPINDLE_RESUME); // resume spindle if paused
|
||||
|
||||
|
||||
// do return move though an intermediate point; queue a wait
|
||||
cm2.return_flags[AXIS_Z] = false;
|
||||
cm_goto_g30_position(cm2.gmx.g30_position, cm2.return_flags);
|
||||
mp_queue_command(_feedhold_exit_sync_to_planner, nullptr, nullptr);
|
||||
cm1.hold_state = FEEDHOLD_HOLD_EXIT_PENDING;
|
||||
mp_queue_command(_feedhold_restart_sync_to_planner, nullptr, nullptr);
|
||||
cm1.hold_state = FEEDHOLD_EXIT_ACTIONS_PENDING;
|
||||
return (STAT_EAGAIN);
|
||||
}
|
||||
|
||||
// wait for exit actions to complete
|
||||
if (cm1.hold_state == FEEDHOLD_HOLD_EXIT_PENDING) {
|
||||
if (cm1.hold_state == FEEDHOLD_EXIT_ACTIONS_PENDING) {
|
||||
return (STAT_EAGAIN);
|
||||
}
|
||||
|
||||
// finalize feedhold exit
|
||||
if (cm1.hold_state == FEEDHOLD_HOLD_EXIT_DONE) {
|
||||
if (cm1.hold_state == FEEDHOLD_EXIT_ACTIONS_COMPLETE) {
|
||||
|
||||
// return to primary planner (p1)
|
||||
cm = &cm1;
|
||||
@@ -505,29 +499,25 @@ static stat_t _feedhold_exit_with_actions(float *param) // Execute Cases (6) a
|
||||
cm_reset_position_to_absolute_position(cm);
|
||||
cm1.flush_state = FLUSH_OFF;
|
||||
}
|
||||
/*
|
||||
// resume motion from primary planner or end cycle if no moves in planner
|
||||
if (mp_has_runnable_buffer(&mp1)) {
|
||||
cm_cycle_start();
|
||||
st_request_exec_move();
|
||||
} else {
|
||||
cm_cycle_end();
|
||||
}
|
||||
cm1.hold_state = FEEDHOLD_OFF;
|
||||
*/
|
||||
return (STAT_OK);
|
||||
}
|
||||
return (STAT_EAGAIN);
|
||||
}
|
||||
|
||||
static stat_t _cycle_exit(float *param)
|
||||
static stat_t _restart_cycle(float *param)
|
||||
{
|
||||
cm1.hold_state = FEEDHOLD_OFF; // must precede st_request_exec_move()
|
||||
if (mp_has_runnable_buffer(&mp1)) {
|
||||
cm_cycle_start();
|
||||
st_request_exec_move();
|
||||
} else {
|
||||
cm_cycle_end();
|
||||
}
|
||||
return (STAT_OK);
|
||||
}
|
||||
|
||||
static stat_t _restart_flush(float *param)
|
||||
{
|
||||
cm1.hold_state = FEEDHOLD_OFF;
|
||||
return (STAT_OK);
|
||||
}
|
||||
@@ -607,6 +597,8 @@ void cm_queue_flush(cmMachine_t *_cm)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//static stat_t _run_p1_hold_entry_actions(void);
|
||||
//static void _sync_to_p1_hold_entry_actions_done(float* vect, bool* flag);
|
||||
|
||||
|
||||
+4
-8
@@ -143,8 +143,7 @@ struct ioDigitalInputExt {
|
||||
if (in->homing_mode) {
|
||||
if (in->edge == INPUT_EDGE_LEADING) { // we only want the leading edge to fire
|
||||
en_take_encoder_snapshot();
|
||||
//+++++ cm_start_hold();
|
||||
cm_request_feedhold(FEEDHOLD_TYPE_SYNC, FEEDHOLD_FINAL_STOP);
|
||||
cm_request_feedhold(FEEDHOLD_TYPE_SYNC, FEEDHOLD_EXIT_STOP);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -155,8 +154,7 @@ struct ioDigitalInputExt {
|
||||
// Probing tests the start condition for the correct direction ahead of time.
|
||||
// If we see any edge, it's the right one.
|
||||
en_take_encoder_snapshot();
|
||||
//+++++ cm_start_hold();
|
||||
cm_request_feedhold(FEEDHOLD_TYPE_SYNC, FEEDHOLD_FINAL_STOP);
|
||||
cm_request_feedhold(FEEDHOLD_TYPE_SYNC, FEEDHOLD_EXIT_STOP);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -165,12 +163,10 @@ struct ioDigitalInputExt {
|
||||
// trigger the action on leading edges
|
||||
if (in->edge == INPUT_EDGE_LEADING) {
|
||||
if (in->action == INPUT_ACTION_STOP) {
|
||||
//+++++ cm_start_hold();
|
||||
cm_request_feedhold(FEEDHOLD_TYPE_SYNC, FEEDHOLD_FINAL_STOP);
|
||||
cm_request_feedhold(FEEDHOLD_TYPE_SYNC, FEEDHOLD_EXIT_STOP);
|
||||
}
|
||||
if (in->action == INPUT_ACTION_FAST_STOP) {
|
||||
//+++++ cm_start_hold(); // for now is same as STOP
|
||||
cm_request_feedhold(FEEDHOLD_TYPE_SYNC, FEEDHOLD_FINAL_STOP);
|
||||
cm_request_feedhold(FEEDHOLD_TYPE_SYNC, FEEDHOLD_EXIT_STOP);
|
||||
}
|
||||
if (in->action == INPUT_ACTION_HALT) {
|
||||
cm_halt(); // hard stop, including spindle, coolant and heaters
|
||||
|
||||
+12
-7
@@ -484,9 +484,8 @@ stat_t mp_exec_aline(mpBuf_t *bf)
|
||||
|
||||
// Feedhold Processing - We need to handle the following cases (listed in rough sequence order):
|
||||
if (cm->hold_state != FEEDHOLD_OFF) {
|
||||
// if FEEDHOLD_P2_START, FEEDHOLD_P2_WAIT, FEEDHOLD HOLD or FEEDHOLD_P2_EXIT
|
||||
// if (cm->hold_state >= FEEDHOLD_P2_START) { // handles _exec_aline_feedhold_processing case (7)
|
||||
if (cm->hold_state >= FEEDHOLD_HOLD_ACTION_START) { // handles _exec_aline_feedhold_processing case (7)
|
||||
// if running actions, or in HOLD state, or exiting with actions
|
||||
if (cm->hold_state >= FEEDHOLD_HOLD_ACTIONS_START) { // handles _exec_aline_feedhold_processing case (7)
|
||||
return (STAT_NOOP); // VERY IMPORTANT to exit as a NOOP. Do not load another move
|
||||
}
|
||||
// STAT_OK terminates aline execution for this move
|
||||
@@ -1032,18 +1031,20 @@ static stat_t _exec_aline_feedhold(mpBuf_t *bf)
|
||||
|
||||
// If in a p2 hold, exit the p2 hold immediately set up a flush of the p2 planner queue
|
||||
if (cm == &cm2) {
|
||||
cm->hold_state = FEEDHOLD_HOLD_EXIT_PENDING;
|
||||
// cm->hold_type = FEEDHOLD_TYPE_SYNC; // force to a sync hold
|
||||
cm->hold_state = FEEDHOLD_HOLD;
|
||||
return (STAT_OK); // will end this exec_aline() with no more movement
|
||||
}
|
||||
// At this point we know we are in a p1 hold
|
||||
|
||||
|
||||
// If probing or homing, exit the move and advance to the _motion_end_callback()'s.
|
||||
// Stop the runtime, clear the run buffer and do not transition to p2 planner.
|
||||
else if ((cm->cycle_type == CYCLE_HOMING) || (cm->cycle_type == CYCLE_PROBE)) {
|
||||
// else if (cm->hold_type == FEEDHOLD_TYPE_SYNC) {
|
||||
mr->block_state = BLOCK_INACTIVE; // disable the rest of the runtime movement
|
||||
mp_free_run_buffer(); // free buffer and enable finalization move to get loaded
|
||||
cm->hold_state = FEEDHOLD_OFF;
|
||||
}
|
||||
}
|
||||
|
||||
// In a regular p1 hold. Motion has stopped, so we can rely on positions and other values to be stable
|
||||
else {
|
||||
@@ -1057,7 +1058,11 @@ static stat_t _exec_aline_feedhold(mpBuf_t *bf)
|
||||
st_request_forward_plan(); // replan the current bf buffer
|
||||
|
||||
// Set state to enable transition to p2 and perform entry actions in the p2 planner
|
||||
cm->hold_state = FEEDHOLD_HOLD_ACTION_START; // signal operations runner to start actions
|
||||
if (cm->hold_type == FEEDHOLD_TYPE_ACTIONS) {
|
||||
cm->hold_state = FEEDHOLD_HOLD_ACTIONS_START; // signal to start entry actions
|
||||
} else {
|
||||
cm->hold_state = FEEDHOLD_HOLD; // achieved hold state
|
||||
}
|
||||
}
|
||||
|
||||
sr_request_status_report(SR_REQUEST_IMMEDIATE);
|
||||
|
||||
Reference in New Issue
Block a user