mirror of
https://github.com/synthetos/g2.git
synced 2026-09-22 19:43:53 +08:00
Testing pause and resume cases. Check.
This commit is contained in:
+85
-115
@@ -45,12 +45,19 @@ spSpindle_t spindle;
|
||||
|
||||
static float _get_spindle_pwm (spSpindle_t &_spindle, pwmControl_t &_pwm);
|
||||
|
||||
#define SPINDLE_DIRECTION_ASSERT \
|
||||
if ((spindle.direction < SPINDLE_CW) || (spindle.direction > SPINDLE_CCW)) { \
|
||||
spindle.direction = SPINDLE_CW; \
|
||||
}
|
||||
|
||||
/***********************************************************************************
|
||||
* spindle_init()
|
||||
* spindle_reset() - stop spindle, set speed to zero, and reset values
|
||||
*/
|
||||
void spindle_init()
|
||||
{
|
||||
SPINDLE_DIRECTION_ASSERT // spindle needs an initial direction
|
||||
|
||||
if( pwm.c[PWM_1].frequency < 0 ) {
|
||||
pwm.c[PWM_1].frequency = 0;
|
||||
}
|
||||
@@ -70,45 +77,47 @@ void spindle_reset()
|
||||
* _exec_spindle_control() - actually execute the spindle command
|
||||
*
|
||||
* Basic operation: Spindle function is effected by _exec_spindle_control().
|
||||
* Spindle_control_immediate() runs command as soon as it's received.
|
||||
* Spindle_control_sync() inserts spindle move into the planner, and handles optional dwells
|
||||
* Spindle_control_immediate() performs the control as soon as it's received.
|
||||
* Spindle_control_sync() inserts spindle move into the planner, and handles spinup and spindowns
|
||||
*
|
||||
* Valid inputs to Spindle_control_immediate() and Spindle_control_sync() are:
|
||||
*
|
||||
* - SPINDLE_OFF turns off spindle and sets spindle state to SPINDLE_OFF.
|
||||
* This will also re-load enable and direction polarity to the pins if they have changed.
|
||||
* The spindle.direction value is not affected (although this doesn't really matter).
|
||||
*
|
||||
* - SPINDLE_CW or SPINDLE_CCW turns spindle on and sets direction accordingly.
|
||||
* If spindle_control_sync() has a non-zero dwell a dwell move is added to the planner queue.
|
||||
* In this case spindle.state is SPINDLE_WAIT until move is "played", and dwell completes.
|
||||
* spindle_control_immediate() has no dwell behavior.
|
||||
* - SPINDLE_CW or SPINDLE_CCW turns sets direction accordingly and spindle on.
|
||||
* In spindle_control_sync() a non-zero spinup delay puts a dwell in the planner queue.
|
||||
* In this case spindle.state is SPINDLE_SPINUP until spindle command is "played", and dwell completes.
|
||||
* Spindle_control_immediate() has no spinup delay or dwell behavior.
|
||||
*
|
||||
* - SPINDLE_PAUSE is only applicable to CW and CCW states. It forces the spindle OFF and
|
||||
* - SPINDLE_PAUSE is only applicable to CW, CCW and SPINUP states. It forces the spindle OFF and
|
||||
* sets spindle.state to PAUSE. If PAUSE is received when not in CW or CCW state it is ignored.
|
||||
*
|
||||
* - SPINDLE_RESUME, if in a PAUSE state, reverts to previous SPINDLE_CW or SPINDLE_CCW.
|
||||
* The SPEED is not changed, and if it were changed in the interim the "new" speed is used.
|
||||
* If RESUME is received from spindle_control_sync() the usual dwell and WAIT behavior occurs.
|
||||
* If RESUME is received from spindle_control_sync() the usual spinup delay behavior occurs.
|
||||
* If RESUME is received when not in a PAUSED state it is ignored. This recognizes that the main
|
||||
* reason an immediate command would be issued - either manually by the user or by an alarm or
|
||||
* some other program function - is to stop a spindle. So the Resume should be ignored for safety.
|
||||
*
|
||||
* Notes:
|
||||
* - Changes to polarities and other setup parameters take effect on the next spindle action.
|
||||
* There is no reason to make these occur instantly.
|
||||
* - Since it's possible to queue a sync'd control, and then set any spindle state with an
|
||||
* immediate() before the queued command is reached, _exec_spindle_control() must gracefully
|
||||
* handle any arbitrary state transition (not just the "legal" ones).
|
||||
*
|
||||
* - The spinup and spindown rows are present, but are not implemented unless we findwe need them.
|
||||
* It's easy enough to set these flags using the bit vector passed from sync(), but unsetting
|
||||
* them once the delay is complete would take some more work.
|
||||
*
|
||||
* - Since it's possible to queue a sync'd control, then set any control value with an
|
||||
* immediate() before the queued command is reached, _exec_spindle_control() must gracefully
|
||||
* handle any arbitrary state transition (not just the "legal" ones)
|
||||
*
|
||||
* - Do we need a spin-down for direction reversal?
|
||||
* - Should the JSON be able to pause and resume?
|
||||
* Q: Do we need a spin-down for direction reversal?
|
||||
* Q: Should the JSON be able to pause and resume? For test purposes only?
|
||||
*/
|
||||
/* State/Control matrix. Read "If you are in state X and get control Y do action Z"
|
||||
|
||||
Control: OFF CW CCW PAUSE RESUME SPINUP SPINDN
|
||||
State: |-----------|-----------|-----------|-----------|-----------|-----------|-----------|
|
||||
OFF | RELOAD | CW | CCW | OFF | NOP | XXXXXXXXX | XXXXXXXXX |
|
||||
OFF | OFF | CW | CCW | NOP | NOP | XXXXXXXXX | XXXXXXXXX |
|
||||
|-----------|-----------|-----------|-----------|-----------|-----------|-----------|
|
||||
CW | OFF | NOP | REVERSE | PAUSE | NOP | XXXXXXXXX | XXXXXXXXX |
|
||||
|-----------|-----------|-----------|-----------|-----------|-----------|-----------|
|
||||
@@ -124,122 +133,71 @@ void spindle_reset()
|
||||
|-----------|-----------|-----------|-----------|-----------|-----------|-----------|
|
||||
NOP(OFF)s are effectively OFFs
|
||||
Actions:
|
||||
- NOP No operation, ignore
|
||||
- NOPCW No-op if spinning up to CW. If the spinning to CCW perform a REVERSE
|
||||
- NOPCCW No-op if spinning up to CCW. If the spinning to CW perform a REVERSE
|
||||
- OFF Turn spindle off
|
||||
- OFF Turn spindle off. Even if it's already off (reloads polarities)
|
||||
- CW Turn spindle on clockwise
|
||||
- CCW Turn spindle on counterclockwise
|
||||
- PAUSE Turn off spindle, enter PAUSE state
|
||||
- RESUME Turn spindle n CW or CCW as before
|
||||
- REV Reverse spindle direction (implies a cycle)
|
||||
- RELOAD Reload (LOAD) settings from spindle structure to spindle bits
|
||||
- XXXXXXX Impossible state. RESUME is not a state and PSINOP/SPINDN are not inputs
|
||||
- RESUME Turn spindle on CW or CCW as before
|
||||
- NOP No operation, ignore
|
||||
- NOPCW No-op if spinning up to CW. If the spinning to CCW perform a REVERSE
|
||||
- NOPCCW No-op if spinning up to CCW. If the spinning to CW perform a REVERSE
|
||||
- REV Reverse spindle direction (Q: need a cycle to spin down then back up again?)
|
||||
- XXXXXXX Impossible box. RESUME is not a state and SPINUP/SPINDN are not inputs
|
||||
*/
|
||||
|
||||
static void _exec_spindle_control(float *value, bool *flag)
|
||||
{
|
||||
spControl control = (spControl)value[0];
|
||||
if (control >= SPINDLE_ACTION_MAX) {
|
||||
if (control > SPINDLE_ACTION_MAX) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint matrix[35] = { SPINDLE_LOAD, SPINDLE_CW, SPINDLE_CCW, SPINDLE_OFF, SPINDLE_NOP,
|
||||
SPINDLE_OFF, SPINDLE_NOP, SPINDLE_REV, SPINDLE_PAUSE, SPINDLE_NOP,
|
||||
SPINDLE_OFF, SPINDLE_REV, SPINDLE_NOP, SPINDLE_PAUSE, SPINDLE_NOP,
|
||||
SPINDLE_OFF, SPINDLE_CW, SPINDLE_CCW, SPINDLE_NOP, SPINDLE_RESUME,
|
||||
SPINDLE_NOP, SPINDLE_NOP, SPINDLE_NOP, SPINDLE_NOP, SPINDLE_NOP,
|
||||
SPINDLE_OFF, SPINDLE_NOPCW, SPINDLE_NOPCCW, SPINDLE_PAUSE, SPINDLE_NOP,
|
||||
SPINDLE_OFF, SPINDLE_NOPCW, SPINDLE_NOPCCW, SPINDLE_NOP, SPINDLE_NOP
|
||||
};
|
||||
spControl matrix[40] = {
|
||||
SPINDLE_OFF, SPINDLE_CW, SPINDLE_CCW, SPINDLE_NOP, SPINDLE_NOP,
|
||||
SPINDLE_OFF, SPINDLE_NOP, SPINDLE_REV, SPINDLE_PAUSE, SPINDLE_NOP,
|
||||
SPINDLE_OFF, SPINDLE_REV, SPINDLE_NOP, SPINDLE_PAUSE, SPINDLE_NOP,
|
||||
SPINDLE_OFF, SPINDLE_CW, SPINDLE_CCW, SPINDLE_NOP, SPINDLE_RESUME,
|
||||
SPINDLE_NOP, SPINDLE_NOP, SPINDLE_NOP, SPINDLE_NOP, SPINDLE_NOP,
|
||||
SPINDLE_OFF, SPINDLE_NOPCW, SPINDLE_NOPCCW, SPINDLE_PAUSE, SPINDLE_NOP,
|
||||
SPINDLE_OFF, SPINDLE_NOPCW, SPINDLE_NOPCCW, SPINDLE_NOP, SPINDLE_NOP,
|
||||
SPINDLE_NOP, SPINDLE_NOP, SPINDLE_NOP, SPINDLE_NOP, SPINDLE_NOP // impossible row added for safety
|
||||
};
|
||||
uint8_t index = ((spindle.state & 0x07) * 5) + control;
|
||||
uint8_t action = matrix[index];
|
||||
spControl action = matrix[index];
|
||||
|
||||
spindle.state = control; // record new spindle state
|
||||
uint8_t on_bit = SPINDLE_OFF; // default to off
|
||||
int8_t dir_bit = -1; // -1 will skip setting the direction
|
||||
SPINDLE_DIRECTION_ASSERT; // ensure that the spindle direction is sane
|
||||
int8_t enable_bit = 0; // default to 0=off
|
||||
int8_t dir_bit = -1; // -1 will skip setting the direction. 0 & 1 are valid values
|
||||
|
||||
switch (action) {
|
||||
case SPINDLE_NOP: { return; }
|
||||
case SPINDLE_OFF: { break; } // on_nit and state are already set for this case
|
||||
case SPINDLE_PAUSE : { break; } // on_nit and state are also already set for this case
|
||||
|
||||
case SPINDLE_CW: case SPINDLE_CCW: {
|
||||
on_bit = 1; // use 1 (not true) - this is a bitmask
|
||||
case SPINDLE_NOP: case SPINDLE_NOPCW: case SPINDLE_NOPCCW: { return; } // reversals not handled yet
|
||||
|
||||
case SPINDLE_OFF: { // enable_bit already set for this case
|
||||
dir_bit = spindle.direction-1; // spindle direction was stored as '1' & '2'
|
||||
spindle.state = SPINDLE_OFF; // the control might have been something other than SPINDLE_OFF
|
||||
break;
|
||||
}
|
||||
case SPINDLE_CW: case SPINDLE_CCW: case SPINDLE_REV: { // REV is handled same as CW or CCW for now
|
||||
enable_bit = 1;
|
||||
dir_bit = control-1; // adjust direction to be used as a bitmask
|
||||
spindle.direction = control;
|
||||
spindle.state = control;
|
||||
break;
|
||||
}
|
||||
|
||||
case SPINDLE_PAUSE : {
|
||||
spindle.state = SPINDLE_PAUSE;
|
||||
break; // enable bit is already set up to stop the move
|
||||
}
|
||||
case SPINDLE_RESUME: {
|
||||
on_bit = 1;
|
||||
dir_bit = spindle.direction-1; // Note: spindle direction was stored as '1' & '2'
|
||||
enable_bit = 1;
|
||||
dir_bit = spindle.direction-1; // spindle direction was stored as '1' & '2'
|
||||
spindle.state = spindle.direction;
|
||||
break;
|
||||
}
|
||||
|
||||
case SPINDLE_LOAD: { // can be used to change enable and dir polarities
|
||||
dir_bit = control-1; // adjust direction to be used as a bitmask
|
||||
break;
|
||||
}
|
||||
|
||||
case SPINDLE_REV: { // for now we treat this as a simple CW or CCW request
|
||||
on_bit = 1; // use 1 (not true) - this is a bitmask
|
||||
dir_bit = control-1; // adjust direction to be used as a bitmask
|
||||
spindle.direction = control;
|
||||
break;
|
||||
}
|
||||
case SPINDLE_NOPCW: { return; } // reversal case not handled yet
|
||||
case SPINDLE_NOPCCW: { return; } // reversal case not handled yet
|
||||
default: {} // keeps the compiler happy
|
||||
}
|
||||
|
||||
// Apply the enable and direction bits and adjust the PWM as required
|
||||
|
||||
// set the direction first
|
||||
if (dir_bit >= 0) {
|
||||
if (dir_bit ^ spindle.dir_polarity) {
|
||||
spindle_dir_pin.set(); // drive pin HI
|
||||
} else {
|
||||
spindle_dir_pin.clear(); // drive pin LO
|
||||
}
|
||||
}
|
||||
|
||||
// set on/off
|
||||
if (on_bit ^ spindle.enable_polarity) {
|
||||
spindle_enable_pin.clear(); // drive pin LO
|
||||
} else {
|
||||
spindle_enable_pin.set(); // drive pin HI
|
||||
}
|
||||
pwm_set_duty(PWM_1, _get_spindle_pwm(spindle, pwm));
|
||||
}
|
||||
|
||||
/*
|
||||
spControl control = (spControl)value[0];
|
||||
if (control >= SPINDLE_ACTION_MAX) {
|
||||
return;
|
||||
}
|
||||
if ((control == SPINDLE_RESUME) && (spindle.state != SPINDLE_PAUSE)) {
|
||||
return;
|
||||
}
|
||||
if ((control == SPINDLE_PAUSE) && (spindle.state != SPINDLE_OFF)) {
|
||||
return;
|
||||
}
|
||||
|
||||
spindle.state = control; // record new spindle state
|
||||
uint8_t on_bit = SPINDLE_OFF; // default to off
|
||||
int8_t dir_bit = -1; // -1 will skip setting the direction
|
||||
|
||||
if ((control == SPINDLE_CW) || (control == SPINDLE_CCW)) {
|
||||
on_bit = 1; // use 1 (not true) to indicate this is a bitmask
|
||||
dir_bit = control-1; // adjust direction so it can be used as a bitmask
|
||||
spindle.direction = control;
|
||||
}
|
||||
else if (control == SPINDLE_RESUME) {
|
||||
on_bit = 1;
|
||||
dir_bit = spindle.direction-1; // Note: spindle direction is stored as 1 & 2
|
||||
spindle.state = spindle.direction;
|
||||
}
|
||||
|
||||
// set the direction first
|
||||
if (dir_bit >= 0) {
|
||||
if (dir_bit ^ spindle.dir_polarity) {
|
||||
@@ -249,15 +207,14 @@ static void _exec_spindle_control(float *value, bool *flag)
|
||||
}
|
||||
}
|
||||
|
||||
// set on/off
|
||||
if (on_bit ^ spindle.enable_polarity) {
|
||||
// set spindle enable
|
||||
if (enable_bit ^ spindle.enable_polarity) {
|
||||
spindle_enable_pin.clear(); // drive pin LO
|
||||
} else {
|
||||
spindle_enable_pin.set(); // drive pin HI
|
||||
}
|
||||
pwm_set_duty(PWM_1, _get_spindle_pwm(spindle, pwm));
|
||||
}
|
||||
*/
|
||||
|
||||
stat_t spindle_control_immediate(spControl control)
|
||||
{
|
||||
@@ -403,21 +360,34 @@ void spindle_end_override(const float ramp_time)
|
||||
***********************************************************************************/
|
||||
|
||||
/***********************************************************************************
|
||||
**** Spindle Settings
|
||||
**** Spindle Settings *************************************************************
|
||||
***********************************************************************************/
|
||||
|
||||
stat_t sp_get_spmo(nvObj_t *nv) { return(get_int(nv, spindle.mode)); }
|
||||
stat_t sp_set_spmo(nvObj_t *nv) { return(set_int(nv, (uint8_t &)spindle.mode, SPINDLE_DISABLED, SPINDLE_MODE_MAX)); }
|
||||
|
||||
stat_t sp_get_spep(nvObj_t *nv) { return(get_int(nv, spindle.enable_polarity)); }
|
||||
stat_t sp_set_spep(nvObj_t *nv) { return(set_int(nv, (uint8_t &)spindle.enable_polarity, 0, 1)); }
|
||||
stat_t sp_set_spep(nvObj_t *nv) {
|
||||
stat_t status = set_int(nv, (uint8_t &)spindle.enable_polarity, 0, 1);
|
||||
spindle_control_immediate(SPINDLE_OFF); // stop spindle and apply new settings
|
||||
return (status);
|
||||
}
|
||||
|
||||
stat_t sp_get_spdp(nvObj_t *nv) { return(get_int(nv, spindle.dir_polarity)); }
|
||||
stat_t sp_set_spdp(nvObj_t *nv) { return(set_int(nv, (uint8_t &)spindle.dir_polarity, 0, 1)); }
|
||||
stat_t sp_get_spph(nvObj_t *nv) { return(get_int(nv, spindle.dir_polarity)); }
|
||||
stat_t sp_set_spph(nvObj_t *nv) { return(set_int(nv, (uint8_t &)spindle.dir_polarity, 0, 1)); }
|
||||
stat_t sp_set_spdp(nvObj_t *nv) {
|
||||
stat_t status = set_int(nv, (uint8_t &)spindle.dir_polarity, 0, 1);
|
||||
spindle_control_immediate(SPINDLE_OFF); // stop spindle and apply new settings
|
||||
return (status);
|
||||
}
|
||||
|
||||
stat_t sp_get_spph(nvObj_t *nv) { return(get_int(nv, spindle.pause_on_hold)); }
|
||||
stat_t sp_set_spph(nvObj_t *nv) { return(set_int(nv, (uint8_t &)spindle.pause_on_hold, 0, 1)); }
|
||||
|
||||
stat_t sp_get_spde(nvObj_t *nv) { return(get_float(nv, spindle.spinup_delay)); }
|
||||
stat_t sp_set_spde(nvObj_t *nv) { return(set_float_range(nv, spindle.spinup_delay, 0, SPINDLE_DWELL_MAX)); }
|
||||
//stat_t sp_get_spdn(nvObj_t *nv) { return(get_float(nv, spindle.spindown_delay)); }
|
||||
//stat_t sp_set_spdn(nvObj_t *nv) { return(set_float_range(nv, spindle.spindown_delay, 0, SPINDLE_DWELL_MAX)); }
|
||||
|
||||
stat_t sp_get_spsn(nvObj_t *nv) { return(get_float(nv, spindle.speed_min)); }
|
||||
stat_t sp_set_spsn(nvObj_t *nv) { return(set_float_range(nv, spindle.speed_min, SPINDLE_SPEED_MIN, SPINDLE_SPEED_MAX)); }
|
||||
stat_t sp_get_spsm(nvObj_t *nv) { return(get_float(nv, spindle.speed_max)); }
|
||||
|
||||
+2
-7
@@ -52,20 +52,16 @@ typedef enum { // how spindle controls are presented by the Gco
|
||||
SPINDLE_CCW = 2, // M4 and store CCW to spsindle.direction
|
||||
SPINDLE_PAUSE, // request PAUSE and store PAUSED state to spindle.state
|
||||
SPINDLE_RESUME, // request RESUME and revert spindle.state to CW, CCW
|
||||
|
||||
SPINDLE_SPINUP, // spindle is coming up to speed
|
||||
SPINDLE_SPINDOWN, // spindle is spinning down to stop
|
||||
|
||||
SPINDLE_NOP, // no operation
|
||||
SPINDLE_NOPCW, // no operation, starts from clockwise
|
||||
SPINDLE_NOPCCW, // no operation, starts from counterclockwise
|
||||
SPINDLE_REV, // operation to reverse spindle direction
|
||||
SPINDLE_LOAD // operation to reload spindle structure into spindle bits
|
||||
|
||||
SPINDLE_REV // operation to reverse spindle direction
|
||||
} spControl;
|
||||
#define SPINDLE_ACTION_MAX SPINDLE_RESUME
|
||||
|
||||
|
||||
|
||||
// *** NOTE: The spindle polarity active hi/low values currently agree with ioMode in gpio.h
|
||||
// These will all need to be changed to ACTIVE_HIGH = 0, ACTIVE_LOW = 1
|
||||
// See: https://github.com/synthetos/g2_private/wiki/GPIO-Design-Discussion#settings-common-to-all-io-types
|
||||
@@ -102,7 +98,6 @@ typedef struct spSpindle {
|
||||
bool pause_on_hold; // {spph:} pause on feedhold
|
||||
float spinup_delay; // {spde:} optional delay on spindle start (set to 0 to disable)
|
||||
float spindown_delay; // {spds:} optional delay on spindle stop (set to 0 to disable)
|
||||
float reversal_delay; // {spdr:} optional delay on direction reversal (set to 0 to disable)
|
||||
|
||||
bool override_enable; // {spoe:} TRUE = spindle speed override enabled (see also m48_enable in canonical machine)
|
||||
float override_factor; // {spo:} 1.0000 x S spindle speed. Go up or down from there
|
||||
|
||||
Reference in New Issue
Block a user