Work on secondary feedholds

This commit is contained in:
Alden Hart
2017-02-05 10:39:28 -05:00
parent 21cd532f69
commit fec6c33612
5 changed files with 76 additions and 42 deletions
+4 -4
View File
@@ -206,14 +206,14 @@ stat_t cm_shutdown(const stat_t status, const char *msg)
spindle_reset(); // stop spindle immediately and set speed to 0 RPM
coolant_reset(); // stop coolant immediately
temperature_reset(); // turn off heaters and fans
cm_queue_flush(); // flush all queues and reset positions
cm_queue_flush(&cm1); // flush all queues and reset positions
for (uint8_t i = 0; i < HOMING_AXES; i++) { // unhome axes and the machine
cm->homed[i] = false;
}
cm->homing_state = HOMING_NOT_HOMED;
cm->machine_state = MACHINE_SHUTDOWN; // do this after all other activity
cm->machine_state = MACHINE_SHUTDOWN; // do this after all other activity
rpt_exception(status, msg); // send exception report
return (status);
}
@@ -239,9 +239,9 @@ stat_t cm_panic(const stat_t status, const char *msg)
spindle_reset(); // stop spindle immediately and set speed to 0 RPM
coolant_reset(); // stop coolant immediately
temperature_reset(); // turn off heaters and fans
cm_queue_flush(); // flush all queues and reset positions
cm_queue_flush(&cm1); // flush all queues and reset positions
cm->machine_state = MACHINE_PANIC; // don't reset anything. Panics are not recoverable
cm->machine_state = MACHINE_PANIC; // don't reset anything. Panics are not recoverable
rpt_exception(status, msg); // send panic report
return (status);
}
-2
View File
@@ -114,7 +114,6 @@
**** CM GLOBALS & STRUCTURE ALLOCATIONS *******************************************
***********************************************************************************/
cmMachineSelect cm_select; // CM_PRIMARY, CM_SECONDARY, CM_SECONDARY_RETURN
cmMachine_t *cm; // pointer to active canonical machine
cmMachine_t cm1; // canonical machine primary machine
cmMachine_t cm2; // canonical machine secondary machine
@@ -156,7 +155,6 @@ void canonical_machine_inits()
cm = &cm1; // set global canonical machine pointer to primary machine
mp = &mp1; // set global pointer to the primary planner
mr = &mr1; // and primary runtime
cm_select = CM_PRIMARY;
}
void canonical_machine_init(cmMachine_t *_cm, void *_mp)
+4 -10
View File
@@ -108,6 +108,7 @@ typedef enum {
} cmMotionState;
typedef enum { // feedhold state machine
// FEEDHOLD_FLUSH = -2, // set when p2 feedhold is ready to flush p2 queue
FEEDHOLD_EXIT = -1, // set when feedhold is due to exit
FEEDHOLD_OFF = 0, // no feedhold in effect
FEEDHOLD_REQUESTED, // feedhold has been requested but not started yet
@@ -150,12 +151,6 @@ typedef enum { // queue flush state machine
FLUSH_WAS_RUN // transient state to note that a queue flush has been run
} cmQueueFlushState;
typedef enum {
CM_NOT_INIT = 0, // planners need initialization
CM_PRIMARY, // in primary machine/planner
CM_SECONDARY, // in secondary machine/planner
} cmMachineSelect;
/*****************************************************************************
* CANONICAL MACHINE STRUCTURES
*/
@@ -291,7 +286,6 @@ typedef struct cmToolTable { // struct to keep a global tool tabl
/**** Externs - See canonical_machine.cpp for allocation ****/
extern cmMachineSelect cm_select; // CM_PRIMARY, CM_SECONDARY, CM_SECONDARY_RETURN
extern cmMachine_t *cm; // pointer to active canonical machine
extern cmMachine_t cm1; // canonical machine primary machine
extern cmMachine_t cm2; // canonical machine secondary machine
@@ -441,9 +435,9 @@ void cm_request_end_hold(void);
void cm_request_queue_flush(void);
stat_t cm_feedhold_sequencing_callback(void); // process feedhold, cycle start and queue flush requests
bool cm_has_hold(void);
void cm_start_hold(void);
void cm_queue_flush(void); // flush serial and planner queues with coordinate resets
bool cm_has_hold(void); // has hold in primary planner
void cm_start_hold(void); // starts hold in primary planner
void cm_queue_flush(cmMachine_t *_cm); // queue flush in either planner
// Homing cycles (cycle_homing.cpp)
stat_t cm_homing_cycle_start(const float axes[], const bool flags[]); // G28.2
+57 -19
View File
@@ -143,21 +143,41 @@ void cm_start_hold()
* cm_request_feedhold()
* cm_request_end_hold()
* cm_request_queue_flush()
*
* p1 is the primary planner, p2 is the secondary planner, which is active if the
* primary planner is in hold. IOW p2 can only be in a hold if p1 is already in one.
* Request_feedhold, request_end_hold, and request_queue_flush are contextual:
*
* request_feedhold:
* - If p1 is not in HOLD & is in motion, request_feedhold requests a p1 hold
* - If p1 is in HOLD & p2 is in motion, request_feedhold requests a p2 hold
* - If both p1 and p2 are in HOLD, request_feedhold is ignored
*
* request_end_hold:
* - If p1 is not in HOLD, request_end_hold is ignored
* - If p1 is in HOLD request_end_hold will end p1 hold & resume motion.
* Pre-defined exit actions (coolant, spindle, Z move) are completed first
* Any executing or pending "in-hold" moves are stopped prior to the exit actions
*
* request_queue_flush:
* - If p1 is not in HOLD, request_queue_flush is ignored
* - If p1 is in HOLD request_queue_flush will end p1 hold & queue flush (stop motion).
* Pre-defined exit actions (coolant, spindle, Z move) are completed first
* Any executing or pending "in-hold" moves are stopped prior to the exit actions
*/
void cm_request_feedhold(void)
{
// cannot generate a feedhold request from the secondary context
if (cm_select != CM_PRIMARY) {
return;
}
// only generate request if not already in a feedhold and the machine is in motion
// Only generate request if not already in a feedhold and the machine is in motion
if ((cm1.hold_state == FEEDHOLD_OFF) && (cm1.motion_state != MOTION_STOP)) {
cm1.hold_state = FEEDHOLD_REQUESTED;
} else
if ((cm2.hold_state == FEEDHOLD_OFF) && (cm2.motion_state != MOTION_STOP)) {
cm2.hold_state = FEEDHOLD_REQUESTED;
}
}
void cm_request_end_hold(void) // This is usually requested from the secondary context
void cm_request_end_hold(void)
{
if (cm1.hold_state != FEEDHOLD_OFF) {
cm1.end_hold_requested = true;
@@ -166,11 +186,10 @@ void cm_request_end_hold(void) // This is usually requested from the secondary
void cm_request_queue_flush()
{
// NOTE: this function used to flush input buffers, but this is handled in xio *prior* to queue flush now
if ((cm1.hold_state != FEEDHOLD_OFF) && // don't honor request unless you are in a feedhold
(cm1.queue_flush_state == FLUSH_OFF)) { // ...and only once
cm1.queue_flush_state = FLUSH_REQUESTED; // request planner flush once motion has stopped
// NOTE: this function used to flush the input buffers,
// but this is handled in xio *prior* to queue flush now
}
}
@@ -193,24 +212,38 @@ void cm_request_queue_flush()
stat_t cm_feedhold_sequencing_callback()
{
// invoking a feedhold is a 2 step process - get to the stop, then execute the hold actions
// invoking a p1 feedhold is a 2 step process - get to the stop, then execute the hold actions
if (cm1.hold_state == FEEDHOLD_REQUESTED) {
if (mp_has_runnable_buffer(mp)) { // bypass cm_start_hold() to start from here
if (mp_has_runnable_buffer(&mp1)) { // bypass cm_start_hold() to start from here
cm_set_motion_state(MOTION_HOLD);
cm->hold_state = FEEDHOLD_SYNC; // invokes hold from aline execution
cm1.hold_state = FEEDHOLD_SYNC; // invokes hold from aline execution
}
}
if (cm1.hold_state == FEEDHOLD_ACTIONS_START) { // perform Z lift, spindle & coolant actions
_run_p1_hold_entry_actions();
}
if (cm2.hold_state == FEEDHOLD_REQUESTED) {
if (mp_has_runnable_buffer(&mp2)) {
cm_set_motion_state(MOTION_HOLD);
cm2.hold_state = FEEDHOLD_SYNC;
}
}
// queue flush won't run until the hold is complete and all (subsequent) motion has stopped
/*
if ((cm2.queue_flush_state == FLUSH_REQUESTED) && (mp_runtime_is_idle())) {
cm_queue_flush(&cm2);
return (STAT_OK);
}
*/
if ((cm1.queue_flush_state == FLUSH_REQUESTED) &&
(cm1.hold_state == FEEDHOLD_HOLD) && // only flush once hold is actually holding
(mp_runtime_is_idle())) { // don't flush planner during movement
cm_queue_flush();
} // queue flush always ends hold, so it drops through
cm_queue_flush(&cm1);
cm1.end_hold_requested = true; // p1 queue flush always ends the hold
}
// exit_hold runs for both ~ and % feedhold ends
if (cm1.end_hold_requested) {
@@ -225,7 +258,7 @@ stat_t cm_feedhold_sequencing_callback()
}
if (cm1.hold_state == FEEDHOLD_EXIT) {
return(_finalize_p1_hold_exit()); // run multiple times until actions are complete
}
}
return (STAT_OK);
}
@@ -267,7 +300,6 @@ static stat_t _run_p1_hold_entry_actions()
cm = &cm2;
mp = (mpPlanner_t *)cm->mp; // mp is a void pointer
mr = mp->mr;
cm_select = CM_SECONDARY;
// set motion state and ACTIVE_MODEL. This must be performed after cm is set to cm2
cm_set_g30_position();
@@ -345,7 +377,6 @@ static stat_t _finalize_p1_hold_exit()
cm = &cm1;
mp = (mpPlanner_t *)cm->mp; // cm->mp is a void pointer
mr = mp->mr;
cm_select = CM_PRIMARY;
// execute this block if a queue flush was performed
// adjust primary planner positions to runtime positions
@@ -408,18 +439,25 @@ static stat_t _finalize_p1_hold_exit()
*/
/***********************************************************************************
* cm_queue_flush() - Flush primary planner queue
* cm_queue_flush() - Flush planner queue
*
* This function assumes that the feedhold sequencing callback has resolved all
* state and timing issues and it's OK to call this now. Do not call this function
* directly. Always use the feedhold sequencing callback.
*/
void cm_queue_flush()
void cm_queue_flush(cmMachine_t *_cm)
{
cm_abort_arc(_cm); // kill arcs so they don't just create more alines
planner_reset((mpPlanner_t *)_cm->mp); // reset primary planner. also resets the mr under the planner
_cm->queue_flush_state = FLUSH_WAS_RUN;
qr_request_queue_report(0); // request a queue report, since we've changed the number of buffers available
/*
cm_abort_arc(&cm1); // kill arcs so they don't just create more alines
planner_reset((mpPlanner_t *)cm1.mp); // reset primary planner. also resets the mr under the planner
cm1.queue_flush_state = FLUSH_WAS_RUN;
cm1.end_hold_requested = true; // queue flush always ends the hold
qr_request_queue_report(0); // request a queue report, since we've changed the number of buffers available
*/
}
+11 -7
View File
@@ -527,24 +527,28 @@ stat_t mp_exec_aline(mpBuf_t *bf)
// (4) - We have decelerated a block to some velocity > zero (needs continuation in next block)
// (5) - We have decelerated a block to zero velocity
// (6) - We have finished all the runtime work now we have to wait for the steppers to stop
// (7) - The steppers have stopped. No motion should occur. ALlows hold finalization to commence
// (6a) - It's a homing or probing feedhold - ditch the remaining buffer & go directly to OFF
// (6b) - It's a p2 feedhold - ditch the remaining buffer & signal we want a p2 queue flush
// (6c) - It's a normal feedhold - signal we want the entry action
// (7) - The steppers have stopped. No motion should occur. Allows hold actions to complete
// (8) - We are removing the hold state and there is queued motion (handled outside this routine)
// (9) - We are removing the hold state and there is no queued motion (also handled outside this routine)
if (cm->motion_state == MOTION_HOLD) {
// Case (7) - All motion has ceased
// FEEDHOLD_ACTIONS_START, FEEDHOLD_ACTIONS_WAIT or FEEDHOLD HOLD
if (cm->hold_state >= FEEDHOLD_ACTIONS_START) {
return (STAT_NOOP); // VERY IMPORTANT to exit as a NOOP. No more movement
if (cm->hold_state >= FEEDHOLD_ACTIONS_START) { // FEEDHOLD_ACTIONS_START, FEEDHOLD_ACTIONS_WAIT or FEEDHOLD HOLD
return (STAT_NOOP); // VERY IMPORTANT to exit as a NOOP. No more movement
}
// Case (6) - Wait for the steppers to stop
if (cm->hold_state == FEEDHOLD_STOPPING) {
if (mp_runtime_is_idle()) { // wait for the steppers to actually clear out
if (mp_runtime_is_idle()) { // wait for steppers to actually finish
// when homing or probing don't stay in HOLD or execute entry actions
if ((cm->cycle_state == CYCLE_HOMING) || (cm->cycle_state == CYCLE_PROBE)) {
// when homing or probing we don't want to stay in HOLD or execute finalizations
cm->hold_state = FEEDHOLD_OFF;
} else {
} else if (cm == &cm2) { // if in p2 hold set up a flush
cm->queue_flush_state = FLUSH_REQUESTED;
} else {
cm->hold_state = FEEDHOLD_ACTIONS_START; // perform Z-lift, spindle, coolant actions
}
mp_zero_segment_velocity(); // for reporting purposes