Checkpoint on spindle functions

This commit is contained in:
Alden Hart
2017-01-14 09:02:25 -05:00
parent 2b07f865c6
commit 59c4cbad7e
10 changed files with 175 additions and 107 deletions

View File

@@ -123,7 +123,7 @@ stat_t cm_is_alarmed()
void cm_halt_all(void)
{
cm_halt_motion();
spindle_control_immediate(SPINDLE_OFF, false);
spindle_control_immediate(SPINDLE_OFF);
cm_coolant_off_immediate();
}

View File

@@ -1555,7 +1555,7 @@ static void _exec_program_finalize(float *value, bool *flag)
cm_select_plane(cm->default_select_plane); // reset to default arc plane
cm_set_distance_mode(cm->default_distance_mode);
cm_set_arc_distance_mode(INCREMENTAL_DISTANCE_MODE);// always the default
spindle_control_immediate(SPINDLE_OFF, false); // M5
spindle_control_immediate(SPINDLE_OFF); // M5
cm_coolant_off_immediate(); // M9
cm_set_feed_rate_mode(UNITS_PER_MINUTE_MODE); // G94
cm_set_motion_mode(MODEL, MOTION_MODE_CANCEL_MOTION_MODE);// NIST specifies G1 (MOTION_MODE_STRAIGHT_FEED), but we cancel motion mode. Safer.

View File

@@ -864,17 +864,7 @@ const cfgItem_t cfgArray[] = {
{ "", "sps", _fiz, 0, sp_print_sps, sp_get_sps, sp_set_sps, (float *)&cs.null, 0 }, // get spindle speed
{ "", "spe", _fiz, 0, sp_print_spe, sp_get_spe, set_nul, (float *)&cs.null, 0 }, // get spindle enable state
{ "", "spd", _fiz, 0, sp_print_spd, sp_get_spd, sp_set_spd, (float *)&cs.null, 0 }, // get spindle direction
/*
{ "sys","spep",_fipn,0, sp_print_spep, get_ui8, set_01, (float *)&spindle.enable_polarity, SPINDLE_ENABLE_POLARITY },
{ "sys","spdp",_fipn,0, sp_print_spdp, get_ui8, set_01, (float *)&spindle.dir_polarity, SPINDLE_DIR_POLARITY },
{ "sys","spph",_fipn,0, sp_print_spph, get_ui8, set_01, (float *)&spindle.pause_on_hold, SPINDLE_PAUSE_ON_HOLD },
{ "sys","spdw",_fipn,2, sp_print_spdw, get_flt, set_flt, (float *)&spindle.dwell_seconds, SPINDLE_DWELL_TIME },
{ "sys","ssoe",_fipn,0, sp_print_ssoe, get_ui8, set_01, (float *)&spindle.sso_enable, SPINDLE_OVERRIDE_ENABLE},
{ "sys","sso", _fipn,3, sp_print_sso, sp_get_sso, sp_set_sso,(float *)&spindle.sso_factor, SPINDLE_OVERRIDE_FACTOR},
{ "", "spe", _fiz, 0, sp_print_spe, get_ui8, set_nul, (float *)&spindle.state, 0 }, // get spindle enable state
{ "", "spd", _fiz, 0, sp_print_spd, get_ui8,sp_set_dir,(float *)&spindle.direction, 0 }, // get spindle direction
{ "", "sps", _fiz, 0, sp_print_sps, get_flt, set_nul, (float *)&spindle.speed, 0 }, // get spindle speed
*/
// Coolant functions
{ "sys","cofp",_fipn,0, cm_print_cofp,get_ui8, set_01, (float *)&coolant.flood_polarity, COOLANT_FLOOD_POLARITY },
{ "sys","comp",_fipn,0, cm_print_comp,get_ui8, set_01, (float *)&coolant.mist_polarity, COOLANT_MIST_POLARITY },

View File

@@ -251,7 +251,7 @@ static uint8_t _probing_init() {
gpio_set_probing_mode(pb.probe_input, true);
// turn off spindle and start the move
spindle_pause(); // pause the spindle if it's on
spindle_control_immediate(SPINDLE_PAUSE); // pause the spindle if it's on
return (_set_pb_func(_probing_start)); // start the probe move
}
@@ -391,7 +391,7 @@ static void _probe_restore_settings() {
cm_set_distance_mode(pb.saved_distance_mode);
// restart spindle if it was paused
spindle_resume();
spindle_control_immediate(SPINDLE_RESUME);
// cancel the feed modes used during probing
cm_set_motion_mode(MODEL, MOTION_MODE_CANCEL_MOTION_MODE);

View File

@@ -73,7 +73,7 @@
<InterfaceName>SWD</InterfaceName>
</ToolOptions>
<ToolType>com.atmel.avrdbg.tool.atmelice</ToolType>
<ToolNumber>J41800030015</ToolNumber>
<ToolNumber>J41800036434</ToolNumber>
<ToolName>Atmel-ICE</ToolName>
</com_atmel_avrdbg_tool_atmelice>
<UseGdb>True</UseGdb>
@@ -100,7 +100,7 @@
<HWProgramCounterSampling>True</HWProgramCounterSampling>
</PercepioTrace>
<preserveEEPROM>true</preserveEEPROM>
<avrtoolserialnumber>J41800030015</avrtoolserialnumber>
<avrtoolserialnumber>J41800036434</avrtoolserialnumber>
<avrdeviceexpectedsignature>0x284E0A60</avrdeviceexpectedsignature>
<avrtoolinterfaceclock>10000000</avrtoolinterfaceclock>
<custom>

View File

@@ -634,9 +634,9 @@ static stat_t _parse_gcode_block(char *buf, char *active_comment)
SET_MODAL (MODAL_GROUP_M4, program_flow, PROGRAM_STOP);
case 2: case 30:
SET_MODAL (MODAL_GROUP_M4, program_flow, PROGRAM_END);
case 3: SET_MODAL (MODAL_GROUP_M7, spindle_control, SPINDLE_CONTROL_CW);
case 4: SET_MODAL (MODAL_GROUP_M7, spindle_control, SPINDLE_CONTROL_CCW);
case 5: SET_MODAL (MODAL_GROUP_M7, spindle_control, SPINDLE_CONTROL_OFF);
case 3: SET_MODAL (MODAL_GROUP_M7, spindle_control, SPINDLE_CW);
case 4: SET_MODAL (MODAL_GROUP_M7, spindle_control, SPINDLE_CCW);
case 5: SET_MODAL (MODAL_GROUP_M7, spindle_control, SPINDLE_OFF);
case 6: SET_NON_MODAL (tool_change, true);
case 7: SET_MODAL (MODAL_GROUP_M8, mist_coolant, true);
case 8: SET_MODAL (MODAL_GROUP_M8, flood_coolant, true);
@@ -743,7 +743,7 @@ static stat_t _execute_gcode_block(char *active_comment)
EXEC_FUNC(cm_change_tool, tool_change); // M6
if (gf.spindle_control) { // spindle OFF, CW, CCW
ritorno(spindle_control_sync(gv.spindle_control, false));
ritorno(spindle_control_sync((spState)gv.spindle_control));
}
EXEC_FUNC(cm_mist_coolant_control, mist_coolant); // M7, M9

2
g2core/pwm.cpp Executable file → Normal file
View File

@@ -36,7 +36,7 @@
/***** PWM defines, structures and memory allocation *****/
pwmSingleton_t pwm;
pwmControl_t pwm;
// Setup motate PWM pins

6
g2core/pwm.h Executable file → Normal file
View File

@@ -45,12 +45,12 @@ typedef struct pwmChannel {
// no data required in ARM
} pwmChannel_t;
typedef struct pwmSingleton {
typedef struct pwmControl {
pwmConfigChannel_t c[PWMS]; // array of channel configs
pwmChannel_t p[PWMS]; // array of PWM channels
} pwmSingleton_t;
} pwmControl_t;
extern pwmSingleton_t pwm;
extern pwmControl_t pwm;
/*** function prototypes ***/

View File

@@ -44,8 +44,8 @@ spSpindle_t spindle;
/**** Static functions ****/
static void _exec_spindle_speed(float *value, bool *flag);
static void _exec_spindle_control(float *value, bool *flag);
static float _get_spindle_pwm (spState state, spControl direction);
//static void _exec_spindle_control(float *value, bool *flag);
static float _get_spindle_pwm (spState state, spState direction);
/***********************************************************************************
* spindle_init()
@@ -65,59 +65,36 @@ void spindle_reset()
float value[AXES] = { 0,0,0,0,0,0 }; // set spindle speed to zero
bool flags[] = { 1,0,0,0,0,0 };
_exec_spindle_speed(value, flags);
spindle_control_immediate(SPINDLE_CONTROL_OFF, false); // turn spindle off
spindle_control_immediate(SPINDLE_OFF);
}
/***********************************************************************************
* spindle_pause() - pause spindle immediately if option is true
* spindle_resume() - restart a paused spindle with an optional dwell
* spindle_control_immediate() - execute spindle control immediately
* spindle_control_sync() - queue a spindle control to the planner buffer
* _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
*
* Valid inputs to Spindle_control_immediate() and Spindle_control_sync() are:
*
* - SPINDLE_OFF turns off spindle and sets spindle state to SPINDLE_OFF.
* 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_PAUSE, when in CW or CCW state, turns spindle OFF and preserves PAUSE in spindle.state.
* 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.
* If RESUME is received from spindle_control_sync() the same dwell and WAIT behavior occurs.
* If RESUME is received when not in a PAUSED state it is ignored.
*/
void spindle_pause()
{
if (spindle.state == SPINDLE_ON) {
spindle_control_sync(SPINDLE_CONTROL_OFF, true);
}
}
void spindle_resume()
{
if (spindle.state == SPINDLE_PAUSE) {
spindle_control_sync(SPINDLE_CONTROL_CW, false);
}
}
stat_t spindle_control_immediate(uint8_t control, bool pause)
{
float value[] = { (float)SPINDLE_OFF, 0,0,0,0,0 };
bool flags[] = { 1,0, pause, 0,0,0 };
if (control != SPINDLE_CONTROL_OFF) {
value[0] = SPINDLE_ON;
value[1] = control;
flags[1] = true;
}
_exec_spindle_control(value, flags);
return(STAT_OK);
}
stat_t spindle_control_sync(uint8_t control, bool pause) // uses spControl arg: OFF, CW, CCW
{
float value[] = { (float)SPINDLE_OFF, 0,0,0,0,0 };
bool flags[] = { 1,0, pause, 0,0,0 };
if (control != SPINDLE_CONTROL_OFF) {
value[0] = SPINDLE_ON;
value[1] = control;
flags[1] = true;
}
mp_queue_command(_exec_spindle_control, value, flags);
return(STAT_OK);
}
#define _set_spindle_enable_bit_hi() spindle_enable_pin.set()
#define _set_spindle_enable_bit_lo() spindle_enable_pin.clear()
#define _set_spindle_direction_bit_hi() spindle_dir_pin.set()
@@ -125,28 +102,89 @@ stat_t spindle_control_sync(uint8_t control, bool pause) // uses spControl arg:
static void _exec_spindle_control(float *value, bool *flag)
{
if (flag[1]) { // set the direction first
spindle.direction = (spControl)value[1]; // record spindle direction in the struct
if ((spindle.direction-1) ^ spindle.dir_polarity) { // take CW/CCW down to 0 or 1
spState control = (spState)value[0];
if (control > SPINDLE_RESUME) {
return;
}
uint8_t on_bit = SPINDLE_OFF;
int8_t dir_bit = -1; // use this value to skip setting the direction
spindle.state = control; // record spindle state
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;
// spindle.state = 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) {
_set_spindle_direction_bit_hi();
} else {
_set_spindle_direction_bit_lo();
}
}
if (flag[0]) { // set on/off
spindle.state = (spState)value[0]; // record spindle state in the struct
if ((spindle.state & 0x01) ^ spindle.enable_polarity) { // mask out PAUSE bit and consider it to be OFF
_set_spindle_enable_bit_lo();
} else {
_set_spindle_enable_bit_hi();
}
// set on/off
if (on_bit ^ spindle.enable_polarity) {
_set_spindle_enable_bit_lo();
} else {
_set_spindle_enable_bit_hi();
}
if (flag[2]) { // set pause
spindle.state = SPINDLE_PAUSE;
}
// if (flag[2]) { // set pause
// spindle.state = SPINDLE_PAUSE;
// }
pwm_set_duty(PWM_1, _get_spindle_pwm(spindle.state, spindle.direction));
}
stat_t spindle_control_immediate(spState control)
{
// bool pause = (control == SPINDLE_PAUSE) ? true : false;
// float value[] = { (float)control, 0,0,0,0,0 };
float value[] = { (float)control };
// bool flags[] = { 1,0, pause, 0,0,0 };
// if (control != SPINDLE_CONTROL_OFF) {
// value[0] = SPINDLE_ON;
// value[1] = control;
// flags[1] = true;
// }
_exec_spindle_control(value, nullptr);
return(STAT_OK);
}
stat_t spindle_control_sync(spState control) // uses spControl arg: OFF, CW, CCW
{
/*
bool pause = (control == SPINDLE_PAUSE) ? true : false;
float value[] = { (float)SPINDLE_OFF, 0,0,0,0,0 };
bool flags[] = { 1,0, pause, 0,0,0 };
if (control != SPINDLE_CONTROL_OFF) {
value[0] = SPINDLE_ON;
value[1] = control;
flags[1] = true;
}
*/
float value[] = { (float)control, 0,0,0,0,0 };
mp_queue_command(_exec_spindle_control, value, nullptr);
if (fp_NOT_ZERO(spindle.dwell_seconds)) {
// mp_queue_command(dwell);
}
return(STAT_OK);
}
/***********************************************************************************
* spindle_queue_speed() - queue the S parameter to the planner buffer
* _exec_spindle_speed() - spindle speed callback from planner queue
@@ -195,23 +233,55 @@ static void _exec_spindle_speed(float *value, bool *flag)
/***********************************************************************************
* _get_spindle_pwm() - return PWM phase (duty cycle) for dir and speed
*/
/*
static float _get_spindle_pwm (spSpindle_t *sp, pwmControl_t *pwm)
{
float speed_lo, speed_hi, phase_lo, phase_hi;
if (sp->direction == SPINDLE_CW ) {
speed_lo = pwm->c[PWM_1].cw_speed_lo;
speed_hi = pwm->c[PWM_1].cw_speed_hi;
phase_lo = pwm->c[PWM_1].cw_phase_lo;
phase_hi = pwm->c[PWM_1].cw_phase_hi;
} else { // if (direction == SPINDLE_CCW ) {
speed_lo = pwm->c[PWM_1].ccw_speed_lo;
speed_hi = pwm->c[PWM_1].ccw_speed_hi;
phase_lo = pwm->c[PWM_1].ccw_phase_lo;
phase_hi = pwm->c[PWM_1].ccw_phase_hi;
}
static float _get_spindle_pwm (spState state, spControl direction)
if ((sp->state == SPINDLE_CW) || (sp->state == SPINDLE_CCW)) {
// clamp spindle speed to lo/hi range
if (spindle->speed < speed_lo) {
spindle->speed = speed_lo;
}
if (spindle->speed > speed_hi) {
spindle->speed = speed_hi;
}
// normalize speed to [0..1]
float speed = (spindle->speed - speed_lo) / (speed_hi - speed_lo);
return (speed * (phase_hi - phase_lo)) + phase_lo;
} else {
return pwm->c[PWM_1].phase_off;
}
}
*/
static float _get_spindle_pwm (spState state, spState direction)
{
float speed_lo=0, speed_hi=0, phase_lo=0, phase_hi=0;
if (direction == SPINDLE_CONTROL_CW ) {
if (direction == SPINDLE_CW ) {
speed_lo = pwm.c[PWM_1].cw_speed_lo;
speed_hi = pwm.c[PWM_1].cw_speed_hi;
phase_lo = pwm.c[PWM_1].cw_phase_lo;
phase_hi = pwm.c[PWM_1].cw_phase_hi;
} else { // if (direction == SPINDLE_CONTROL_CCW ) {
} else { // if (direction == SPINDLE_CCW ) {
speed_lo = pwm.c[PWM_1].ccw_speed_lo;
speed_hi = pwm.c[PWM_1].ccw_speed_hi;
phase_lo = pwm.c[PWM_1].ccw_phase_lo;
phase_hi = pwm.c[PWM_1].ccw_phase_hi;
}
if (state == SPINDLE_ON) {
if ((state == SPINDLE_CW) || (state == SPINDLE_CCW)) {
// clamp spindle speed to lo/hi range
if (spindle.speed < speed_lo) {
spindle.speed = speed_lo;
@@ -222,7 +292,7 @@ static float _get_spindle_pwm (spState state, spControl direction)
// normalize speed to [0..1]
float speed = (spindle.speed - speed_lo) / (speed_hi - speed_lo);
return (speed * (phase_hi - phase_lo)) + phase_lo;
} else {
} else {
return pwm.c[PWM_1].phase_off;
}
}

View File

@@ -35,14 +35,22 @@ typedef enum {
} spMode;
#define SPINDLE_MODE_MAX SPINDLE_CONTINUOUS
// Note on spControl:
// This enum is used to both request the spindle operation (ON, CW, CCW),
// and to record spindle direction (1=CW, 2=CCW) in spindle.direction
// spState is used for multiple purposes:
// - request the spindle operation (OFF, CW, CCW)
// - request PAUSE and RESUME
// - run the spindle state machine for spindle wait states
// - store current direction (1=CW, 2=CCW) in spindle.direction
typedef enum { // how spindle controls are presented by the Gcode parser
SPINDLE_CONTROL_OFF = 0, // M5
SPINDLE_CONTROL_CW = 1, // M3
SPINDLE_CONTROL_CCW = 2 // M4
} spControl;
SPINDLE_OFF = 0, // M5
SPINDLE_CW = 1, // M3 and store CW to spindle.direction
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_WAIT // handle transient WAIT states
} spState;
// SPINDLE_ON is either of SPINDLE_CW or SPINDLE_CCW
//#define SPINDLE_ON(s) ((s == SPINDLE_CW) || (s == SPINDLE__CCW))
// *** 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
@@ -53,12 +61,14 @@ typedef enum { // Note: These values agree with
SPINDLE_ACTIVE_HIGH = 1, // Will set output to 1 to enable the spindle or CW direction
} spPolarity;
/*
typedef enum { // basic spindle state machine. Do not change this enum
SPINDLE_OFF = 0,
SPINDLE_ON = 1, // spindle on and at speed
SPINDLE_PAUSE = 2, // meaning it was on and now it's off
SPINDLE_WAITING = 3 // spindle not at speed yet
} spState;
*/
typedef enum { // electronic speed controller for some spindles
ESC_ONLINE = 0,
@@ -80,22 +90,22 @@ typedef enum { // electronic speed controller for some spindles
typedef struct spSpindle {
// Public and settable
spMode mode; // spondle operating mode
spMode mode; // spindle operating mode
spState state; // OFF, ON, PAUSE, RESUME, WAIT
spState direction; // 1=CW, 2=CCW (subset of above state)
float speed; // S in RPM
float speed_min; // minimum settable spindle speed
float speed_max; // maximum settable spindle speed
spControl direction; // 1=CW, 2=CCW
spPolarity enable_polarity; // 0=active low, 1=active high
spPolarity dir_polarity; // 0=clockwise low, 1=clockwise high
float dwell_seconds; // dwell on spindle resume
bool pause_on_hold; // pause on feedhold
bool sso_enable; // TRUE = spindle speed override enabled (see also m48_enable in canonical machine)
float sso_factor; // 1.0000 x S spindle speed. Go up or down from there
// Spindle internal state - not directly settable by user or program
spState state; // OFF, ON, PAUSE, WAITING
// Spindle speed controller variables
ESCState esc_state; // state management for ESC controller
uint32_t esc_boot_timer; // When the ESC last booted up
@@ -111,10 +121,8 @@ extern spSpindle_t spindle;
void spindle_init();
void spindle_reset();
void spindle_pause(void);
void spindle_resume(void);
stat_t spindle_control_immediate(uint8_t control, bool pause);
stat_t spindle_control_sync(uint8_t control, bool pause);
stat_t spindle_control_immediate(spState control);
stat_t spindle_control_sync(spState control);
stat_t spindle_speed_immediate(float speed); // S parameter
stat_t spindle_speed_sync(float speed); // S parameter