Added spindle speed min/max values; added spindle mode; Separated spindle into its own group (SP); Made spindle standalone from canonical machine

This commit is contained in:
Alden Hart
2017-01-13 14:36:48 -05:00
parent fb10abfff8
commit c456b5ce88
10 changed files with 339 additions and 193 deletions
+1 -1
View File
@@ -123,7 +123,7 @@ stat_t cm_is_alarmed()
void cm_halt_all(void)
{
cm_halt_motion();
cm_spindle_off_immediate();
spindle_off_immediate();
cm_coolant_off_immediate();
}
+1 -2
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
cm_spindle_off_immediate(); // M5
spindle_off_immediate(); // 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.
@@ -2262,7 +2262,6 @@ stat_t cm_run_jog(nvObj_t *nv)
return (STAT_OK);
}
/***********************************************************************************
* Debugging Commands
***********************************************************************************/
+25 -11
View File
@@ -852,16 +852,29 @@ const cfgItem_t cfgArray[] = {
{ "", "md", _f0, 0, st_print_md, get_nul, st_set_md, (float *)&cs.null, 0 }, // SET to disable motors
// Spindle functions
{ "sys","spep",_fipn,0, cm_print_spep,get_ui8, set_01, (float *)&spindle.enable_polarity, SPINDLE_ENABLE_POLARITY },
{ "sys","spdp",_fipn,0, cm_print_spdp,get_ui8, set_01, (float *)&spindle.dir_polarity, SPINDLE_DIR_POLARITY },
{ "sys","spph",_fipn,0, cm_print_spph,get_ui8, set_01, (float *)&spindle.pause_on_hold, SPINDLE_PAUSE_ON_HOLD },
{ "sys","spdw",_fipn,2, cm_print_spdw,get_flt, set_flt, (float *)&spindle.dwell_seconds, SPINDLE_DWELL_TIME },
{ "sys","ssoe",_fipn,0, cm_print_ssoe,get_ui8, set_01, (float *)&spindle.sso_enable, SPINDLE_OVERRIDE_ENABLE},
{ "sys","sso", _fipn,3, cm_print_sso, get_flt,cm_set_sso,(float *)&spindle.sso_factor, SPINDLE_OVERRIDE_FACTOR},
{ "", "spe", _fiz, 0, cm_print_spe, get_ui8, set_nul, (float *)&spindle.enable, 0 }, // get spindle enable
{ "", "spd", _fiz, 0, cm_print_spd, get_ui8,cm_set_dir,(float *)&spindle.direction, 0 }, // get spindle direction
{ "", "sps", _fiz, 0, cm_print_sps, get_flt, set_nul, (float *)&spindle.speed, 0 }, // get spindle speed
{ "sp","spmo",_fipn, 0, sp_print_spmo, sp_get_spmo, sp_set_spmo, (float *)&cs.null, SPINDLE_MODE },
{ "sp","spep",_fipn, 0, sp_print_spep, sp_get_spep, sp_set_spep, (float *)&cs.null, SPINDLE_ENABLE_POLARITY },
{ "sp","spdp",_fipn, 0, sp_print_spdp, sp_get_spdp, sp_set_spdp, (float *)&cs.null, SPINDLE_DIR_POLARITY },
{ "sp","spph",_fipn, 0, sp_print_spph, sp_get_spph, sp_set_spph, (float *)&cs.null, SPINDLE_PAUSE_ON_HOLD },
{ "sp","spdw",_fipn, 2, sp_print_spdw, sp_get_spdw, sp_set_spdw, (float *)&cs.null, SPINDLE_DWELL_TIME },
{ "sp","spsn",_fipn, 2, sp_print_spsn, sp_get_spsn, sp_set_spsn, (float *)&cs.null, SPINDLE_SPEED_MIN},
{ "sp","spsm",_fipn, 2, sp_print_spsm, sp_get_spsm, sp_set_spsm, (float *)&cs.null, SPINDLE_SPEED_MAX},
{ "sp","ssoe",_fipn, 0, sp_print_ssoe, sp_get_spep, sp_set_spep, (float *)&cs.null, SPINDLE_OVERRIDE_ENABLE},
{ "sp","sso", _fipn, 3, sp_print_sso, sp_get_sso, sp_set_sso, (float *)&cs.null, SPINDLE_OVERRIDE_FACTOR},
{ "", "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 },
@@ -1059,9 +1072,10 @@ const cfgItem_t cfgArray[] = {
// - Optional DIAGNOSTIC_PARAMETERS
// - Uber groups (count these separately)
#define FIXED_GROUPS 2
#define FIXED_GROUPS 3
{ "","sys",_f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0 }, // system group
{ "","p1", _f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0 }, // PWM 1 group
{ "","sp", _f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0 }, // Spindle group
#define AXIS_GROUPS AXES
{ "","x", _f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0 }, // axis groups
+22 -11
View File
@@ -37,11 +37,20 @@
#include "util.h"
/***********************************************************************************
**** CODE *************************************************************************
**** Feedholds ********************************************************************
***********************************************************************************/
/*
* Feedholds, queue flushes and end_holds are all related. The request functions set flags
* or change state to "REQUESTED". The sequencing callback interprets the flags as so:
* Feedholds, queue flushes and end_holds are all related and are in this file.
* Feedholds are implemented as a state machine (cmFeedholdState) that runs in the
* planner (plan_exec.cpp, see Feedhold Processing around line 500) and in this file.
*
* Feedholds also use the dual planner (secondary context, or hold context) where a
* new canonical machine and planner are spun up and entered when a feedhold is initiated.
* This allows (almost) all of the machine operations to be accessible during a feedhold.
*
* Feedholds are initiated and ended by a series of request flags (requests).
* The request functions set flags or change state to "REQUESTED".
* The sequencing callback interprets the flags as so:
* - A feedhold request received during motion should be honored
* - A feedhold request received during a feedhold should be ignored
* - A feedhold request received during a motion stop should be ignored
@@ -55,8 +64,8 @@
* - Said end_hold request received during a feedhold should be deferred until the
* feedhold enters a HOLD state (i.e. until deceleration is complete).
* If a queue flush request is also present the queue flush should be done first
*
* Below the request level, feedholds work like this:
*/
/* Below the request level, feedholds work like this:
* - The hold is initiated by calling cm_start_hold(). cm->hold_state is set to
* FEEDHOLD_SYNC, motion_state is set to MOTION_HOLD, and the spindle is turned off
* (if it it on). The remainder of feedhold
@@ -101,7 +110,7 @@
- Machine alarm state is not (yet) taken into account in feedhold sequencing and restart
*/
/*
/***********************************************************************************
* cm_request_feedhold()
* cm_request_end_hold()
* cm_request_queue_flush()
@@ -161,7 +170,7 @@ stat_t cm_feedhold_sequencing_callback()
return (STAT_OK);
}
/*
/***********************************************************************************
* cm_has_hold() - return true if a hold condition exists (or a pending hold request)
* cm_start_hold() - start a feedhhold by signalling the exec
* cm_end_hold() - end a feedhold by returning the system to normal operation
@@ -187,7 +196,7 @@ void cm_end_hold()
}
}
/*
/***********************************************************************************
* cm_switch_to_hold_context() - switch to secondary machine context
*
* Moving between contexts is only safe when the machine is completely stopped
@@ -248,7 +257,7 @@ stat_t cm_switch_to_hold_context()
return (STAT_OK);
}
/*
/***********************************************************************************
* cm_return_from_hold_context() - initiate return from secondary context
* cm_return_from_hold_callback() - main loop callback to finsh return once moves are done
* _planner_done_callback() - callback to sync to end of planner operations
@@ -320,7 +329,8 @@ stat_t cm_return_from_hold_callback()
return (STAT_OK);
}
/* Queue Flush operation
/***********************************************************************************
* Queue Flush operations
*
* This one's complicated. See here first:
* https://github.com/synthetos/g2/wiki/Alarm-Processing
@@ -355,7 +365,8 @@ stat_t cm_return_from_hold_callback()
* to ensure that it either arrives on the data channel or that the data channel is
* empty before writing it to the control channel.
*/
/*
/***********************************************************************************
* cm_queue_flush() - Flush planner queue and correct model positions
*/
+2 -2
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
cm_spindle_optional_pause(true); // pause the spindle if it's on
spindle_optional_pause(true); // 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
cm_spindle_resume(spindle.dwell_seconds);
spindle_resume(spindle.dwell_seconds);
// cancel the feed modes used during probing
cm_set_motion_mode(MODEL, MOTION_MODE_CANCEL_MOTION_MODE);
+3 -3
View File
@@ -733,14 +733,14 @@ static stat_t _execute_gcode_block(char *active_comment)
cm_set_model_linenum(gv.linenum);
EXEC_FUNC(cm_set_feed_rate_mode, feed_rate_mode); // G93, G94
EXEC_FUNC(cm_set_feed_rate, F_word); // F
EXEC_FUNC(cm_set_spindle_speed, S_word); // S
EXEC_FUNC(spindle_queue_speed, S_word); // S
if (gf.sso_control) { // spindle speed override
ritorno(cm_sso_control(gv.P_word, gf.P_word));
ritorno(spindle_override_control(gv.P_word, gf.P_word));
}
EXEC_FUNC(cm_select_tool, tool_select); // tool_select is where it's written
EXEC_FUNC(cm_change_tool, tool_change); // M6
EXEC_FUNC(cm_spindle_control, spindle_control); // spindle CW, CCW, OFF
EXEC_FUNC(spindle_queue_control, spindle_control); // spindle CW, CCW, OFF
EXEC_FUNC(cm_mist_coolant_control, mist_coolant); // M7, M9
EXEC_FUNC(cm_flood_coolant_control, flood_coolant); // M8, M9 also disables mist coolant if OFF
Executable → Regular
+18
View File
@@ -53,6 +53,24 @@ typedef enum {
#define NORMALLY_OPEN IO_ACTIVE_LOW // equivalent
#define NORMALLY_CLOSED IO_ACTIVE_HIGH // equivalent
// *** NOTE: The active hi/low values currently agree with spindle and coolant values
// The above 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
/* The above will become:
typedef enum {
IO_ACTIVE_HIGH = 0, // input is active high (aka normally closed)
IO_ACTIVE_LOW = 1 // input is active low (aka normally open)
} ioPolarity;
#define NORMALLY_OPEN IO_ACTIVE_LOW // equivalent
#define NORMALLY_CLOSED IO_ACTIVE_HIGH // equivalent
typedef enum {
IO_DISABLED = 0, // IO will not operate
IO_ENABLED // IO will operate
} ioMode;
*/
typedef enum { // actions are initiated from within the input's ISR
INPUT_ACTION_NONE = 0,
INPUT_ACTION_STOP, // stop at normal jerk - preserves positional accuracy
+16
View File
@@ -81,6 +81,10 @@
#define SAFETY_INTERLOCK_ENABLE 1 // {saf: 0=off, 1=on
#endif
#ifndef SPINDLE_MODE
#define SPINDLE_MODE 1 // {spmo; 0=diabled, 1=plan to stop, 2=continuous
#endif
#ifndef SPINDLE_ENABLE_POLARITY
#define SPINDLE_ENABLE_POLARITY SPINDLE_ACTIVE_HIGH // {spep: 0=active low, 1=active high
#endif
@@ -97,6 +101,18 @@
#define SPINDLE_DWELL_TIME 1.0 // {spdw:
#endif
#ifndef SPINDLE_DWELL_MAX
#define SPINDLE_DWELL_MAX 10000000.0 // maximum allowable dwell time. May be overridden in settings files
#endif
#ifndef SPINDLE_SPEED_MIN
#define SPINDLE_SPEED_MIN 0.0 // {spsn:
#endif
#ifndef SPINDLE_SPEED_MAX
#define SPINDLE_SPEED_MAX 1000000.0 // {spsm:
#endif
#ifndef COOLANT_MIST_POLARITY
#define COOLANT_MIST_POLARITY 1 // {comp: 0=active low, 1=active high
#endif
+147 -109
View File
@@ -33,6 +33,7 @@
#include "spindle.h"
#include "planner.h"
#include "hardware.h"
#include "settings.h"
#include "pwm.h"
#include "util.h"
@@ -44,9 +45,9 @@ cmSpindleton_t spindle;
static void _exec_spindle_speed(float *value, bool *flag);
static void _exec_spindle_control(float *value, bool *flag);
static float _get_spindle_pwm (cmSpindleEnable enable, cmSpindleDir direction);
static float _get_spindle_pwm (spState state, spDir direction);
/*
/***********************************************************************************
* spindle_init()
* spindle_reset() - stop spindle, set speed to zero, and reset values
*/
@@ -64,20 +65,58 @@ 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);
cm_spindle_off_immediate(); // turn spindle off
spindle_off_immediate(); // turn spindle off
}
/*
* cm_set_spindle_speed() - queue the S parameter to the planner buffer
/***********************************************************************************
* spindle_off_immediate() - turn on/off spindle w/o planning
* spindle_optional_pause() - pause spindle immediately if option is true
* spindle_resume() - restart a paused spindle with an optional dwell
*/
void spindle_off_immediate()
{
spindle.state = SPINDLE_OFF;
float value[] = { (float)SPINDLE_OFF, 0,0,0,0,0 };
bool flags[] = { 1,0,0,0,0,0 };
_exec_spindle_control(value, flags);
}
void spindle_optional_pause(bool option)
{
if (option && spindle.state == SPINDLE_ON) {
spindle_off_immediate();
spindle.state = SPINDLE_PAUSE;
}
}
void spindle_resume(float dwell_seconds)
{
if(spindle.state == SPINDLE_PAUSE) {
spindle.state = SPINDLE_ON;
mp_request_out_of_band_dwell(dwell_seconds);
float value[] = { (float)SPINDLE_ON, (float)spindle.direction, 0,0,0,0 };
bool flags[] = { 1,0,0,0,0,0 };
_exec_spindle_control(value, flags);
}
}
/***********************************************************************************
* spindle_queue_speed() - queue the S parameter to the planner buffer
* _exec_spindle_speed() - spindle speed callback from planner queue
*/
stat_t cm_set_spindle_speed(float speed)
stat_t spindle_queue_speed(float speed)
{
// if (speed > cfg.max_spindle speed) { return (STAT_MAX_SPINDLE_SPEED_EXCEEDED);}
if (speed < spindle.speed_min) {
return (STAT_SPINDLE_SPEED_BELOW_MINIMUM);
}
if (speed > spindle.speed_max) {
return (STAT_SPINDLE_SPEED_MAX_EXCEEDED);
}
float value[AXES] = { speed, 0,0,0,0,0 };
bool flags[] = { 1,0,0,0,0,0 };
bool flags[] = { 1,0,0,0,0,0 };
mp_queue_command(_exec_spindle_speed, value, flags);
return (STAT_OK);
}
@@ -89,81 +128,47 @@ static void _exec_spindle_speed(float *value, bool *flag)
}
if (flag[1]) {
spindle.direction = (cmSpindleDir)value[1];
spindle.direction = (spDir)value[1];
}
// update spindle speed if we're running
pwm_set_duty(PWM_1, _get_spindle_pwm(spindle.enable, spindle.direction));
pwm_set_duty(PWM_1, _get_spindle_pwm(spindle.state, spindle.direction));
}
/*
* cm_spindle_off_immediate() - turn on/off spindle w/o planning
* cm_spindle_optional_pause() - pause spindle immediately if option is true
* cm_spindle_resume() - restart a paused spindle with an optional dwell
*/
void cm_spindle_off_immediate()
{
spindle.enable = SPINDLE_OFF;
float value[] = { (float)SPINDLE_OFF, 0,0,0,0,0 };
bool flags[] = { 1,0,0,0,0,0 };
_exec_spindle_control(value, flags);
}
void cm_spindle_optional_pause(bool option)
{
if (option && spindle.enable == SPINDLE_ON) {
cm_spindle_off_immediate();
spindle.enable = SPINDLE_PAUSE;
}
}
void cm_spindle_resume(float dwell_seconds)
{
if(spindle.enable == SPINDLE_PAUSE) {
spindle.enable = SPINDLE_ON;
mp_request_out_of_band_dwell(dwell_seconds);
float value[] = { (float)SPINDLE_ON, (float)spindle.direction, 0,0,0,0 };
bool flags[] = { 1,0,0,0,0,0 };
_exec_spindle_control(value, flags);
}
}
/*
* cm_spindle_control() - queue the spindle command to the planner buffer. Observe PAUSE
/***********************************************************************************
* spindle_queue_control() - queue the spindle command to the planner buffer. Observe PAUSE
* _exec_spindle_control() - actually execute the spindle command
*/
stat_t cm_spindle_control(uint8_t control) // requires SPINDLE_CONTROL_xxx style args
stat_t spindle_queue_control(uint8_t control) // requires SPINDLE_CONTROL_xxx style args
{
if (control == SPINDLE_CONTROL_OFF) {
spindle.enable = SPINDLE_OFF;
spindle.state = SPINDLE_OFF;
} else {
spindle.enable = SPINDLE_ON;
spindle.state = SPINDLE_ON;
if (control == SPINDLE_CONTROL_CW) {
spindle.direction = SPINDLE_CW;
} else {
spindle.direction = SPINDLE_CCW;
}
}
float value[] = { (float)spindle.enable, (float)spindle.direction, 0,0,0,0 };
float value[] = { (float)spindle.state, (float)spindle.direction, 0,0,0,0 };
bool flags[] = { 1,1,0,0,0,0 };
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()
#define _set_spindle_direction_bit_lo() spindle_dir_pin.clear()
#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()
#define _set_spindle_direction_bit_lo() spindle_dir_pin.clear()
static void _exec_spindle_control(float *value, bool *flag)
{
// set the direction first
if (flag[1])
{
spindle.direction = (cmSpindleDir)value[1]; // record spindle direction in the struct
spindle.direction = (spDir)value[1]; // record spindle direction in the struct
if (spindle.direction ^ spindle.dir_polarity) {
_set_spindle_direction_bit_hi();
} else {
@@ -174,22 +179,21 @@ static void _exec_spindle_control(float *value, bool *flag)
if (flag[0])
{
// set on/off. Mask out PAUSE and consider it OFF
spindle.enable = (cmSpindleEnable)value[0]; // record spindle enable in the struct
if ((spindle.enable & 0x01) ^ spindle.enable_polarity) {
spindle.state = (spState)value[0]; // record spindle state in the struct
if ((spindle.state & 0x01) ^ spindle.enable_polarity) {
_set_spindle_enable_bit_lo();
} else {
_set_spindle_enable_bit_hi();
}
}
pwm_set_duty(PWM_1, _get_spindle_pwm(spindle.enable, spindle.direction));
pwm_set_duty(PWM_1, _get_spindle_pwm(spindle.state, spindle.direction));
}
/*
/***********************************************************************************
* _get_spindle_pwm() - return PWM phase (duty cycle) for dir and speed
*/
static float _get_spindle_pwm (cmSpindleEnable enable, cmSpindleDir direction)
static float _get_spindle_pwm (spState state, spDir direction)
{
float speed_lo=0, speed_hi=0, phase_lo=0, phase_hi=0;
if (direction == SPINDLE_CW ) {
@@ -204,7 +208,7 @@ static float _get_spindle_pwm (cmSpindleEnable enable, cmSpindleDir direction)
phase_hi = pwm.c[PWM_1].ccw_phase_hi;
}
if (enable == SPINDLE_ON) {
if (state == SPINDLE_ON) {
// clamp spindle speed to lo/hi range
if (spindle.speed < speed_lo) {
spindle.speed = speed_lo;
@@ -220,24 +224,23 @@ static float _get_spindle_pwm (cmSpindleEnable enable, cmSpindleDir direction)
}
}
/*
* cm_spindle_override_control()
* cm_start_spindle_override()
* cm_end_spindle_override()
/***********************************************************************************
* spindle_override_control()
* spindle_sp_start_spindle_override()
* sp_end_spindle_override()
*/
void cm_start_spindle_override(const float ramp_time, const float override_factor)
void spindle_start_override(const float ramp_time, const float override_factor)
{
return;
}
void cm_end_spindle_override(const float ramp_time)
void spindle_end_override(const float ramp_time)
{
return;
}
stat_t cm_sso_control(const float P_word, const bool P_flag) // M51
stat_t spindle_override_control(const float P_word, const bool P_flag) // M51
{
bool new_enable = true;
bool new_override = false;
@@ -257,9 +260,9 @@ stat_t cm_sso_control(const float P_word, const bool P_flag) // M51
}
if (cm->gmx.m48_enable) { // if master enable is ON
if (new_enable && (new_override || !spindle.sso_enable)) { // 3 cases to start a ramp
cm_start_spindle_override(SPINDLE_OVERRIDE_RAMP_TIME, spindle.sso_factor);
spindle_start_override(SPINDLE_OVERRIDE_RAMP_TIME, spindle.sso_factor);
} else if (spindle.sso_enable && !new_enable) { // case to turn off the ramp
cm_end_spindle_override(SPINDLE_OVERRIDE_RAMP_TIME);
spindle_end_override(SPINDLE_OVERRIDE_RAMP_TIME);
}
}
spindle.sso_enable = new_enable; // always update the enable state
@@ -275,37 +278,66 @@ stat_t cm_sso_control(const float P_word, const bool P_flag) // M51
* Functions to get and set variables from the cfgArray table
***********************************************************************************/
/*
* cm_set_dir() - a cheat to set direction w/o using the M commands
*
* This is provided as a way to set and clear spindle direction without using M commands
* It's here because disabling a spindle (M5) does not change the direction, only the enable.
/***********************************************************************************
**** 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_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_get_spdw(nvObj_t *nv) { return(get_float(nv, spindle.dwell_seconds)); }
stat_t sp_set_spdw(nvObj_t *nv) { return(set_float_range(nv, spindle.dwell_seconds, 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)); }
stat_t sp_set_spsm(nvObj_t *nv) { return(set_float_range(nv, spindle.speed_max, SPINDLE_SPEED_MIN, SPINDLE_SPEED_MAX)); }
stat_t sp_get_ssoe(nvObj_t *nv) { return(get_int(nv, spindle.sso_enable)); }
stat_t sp_set_ssoe(nvObj_t *nv) { return(set_int(nv, (uint8_t &)spindle.sso_enable, 0, 1)); }
stat_t sp_get_sso(nvObj_t *nv) { return(get_float(nv, spindle.sso_factor)); }
stat_t sp_set_sso(nvObj_t *nv) { return(set_float_range(nv, spindle.sso_factor, SPINDLE_OVERRIDE_MIN, SPINDLE_OVERRIDE_MAX)); }
/* These are provided as a way to set and clear spindle states without using M commands
* SPD is useful because disabling a spindle (M5) does not change the direction, only the enable.
*/
stat_t cm_set_dir(nvObj_t *nv)
stat_t sp_get_sps(nvObj_t *nv) { return(get_float(nv, spindle.speed)); }
stat_t sp_set_sps(nvObj_t *nv)
{
set_01(nv);
float value[] = { (float)spindle.enable, (float)spindle.direction, 0,0,0,0 };
bool flags[] = { 1,1,0,0,0,0 };
_exec_spindle_control(value, flags);
set_float_range(nv, spindle.speed, spindle.speed_min, spindle.speed_max);
float value[] = { spindle.speed, 0,0,0,0,0 };
bool flags[] = { 1,0,0,0,0,0 };
_exec_spindle_speed(value, flags);
return (STAT_OK);
}
stat_t sp_get_spe(nvObj_t *nv) { return(get_int(nv, spindle.state)); }
/*
* cm_set_sso() - set spindle speed feedrate override factor
*/
stat_t cm_set_sso(nvObj_t *nv)
stat_t sp_set_spe(nvObj_t *nv)
{
if (nv->value < SPINDLE_OVERRIDE_MIN) {
return (STAT_INPUT_LESS_THAN_MIN_VALUE);
}
if (nv->value > SPINDLE_OVERRIDE_MAX) {
return (STAT_INPUT_EXCEEDS_MAX_VALUE);
}
set_flt(nv);
return(STAT_OK);
// set_int(nv, (uint8_t &)spindle.state, 0, 1);
float value[] = { (float)spindle.state, (float)spindle.direction, 0,0,0,0 };
bool flags[] = { 1,1,0,0,0,0 };
_exec_spindle_control(value, flags);
return (STAT_OK);
}
*/
stat_t sp_get_spd(nvObj_t *nv) { return(get_int(nv, spindle.direction)); }
stat_t sp_set_spd(nvObj_t *nv)
{
set_int(nv, (uint8_t &)spindle.direction, 0, 1);
float value[] = { (float)spindle.state, (float)spindle.direction, 0,0,0,0 };
bool flags[] = { 1,1,0,0,0,0 };
_exec_spindle_control(value, flags);
return (STAT_OK);
}
/***********************************************************************************
@@ -315,24 +347,30 @@ stat_t cm_set_sso(nvObj_t *nv)
#ifdef __TEXT_MODE
const char fmt_spmo[] = "[spmo] spindle mode%16d [0=disabled,1=plan-to-stop,2=continuous]\n";
const char fmt_spep[] = "[spep] spindle enable polarity%5d [0=active_low,1=active_high]\n";
const char fmt_spdp[] = "[spdp] spindle direction polarity%2d [0=CW_low,1=CW_high]\n";
const char fmt_spph[] = "[spph] spindle pause on hold%7d [0=no,1=pause_on_hold]\n";
const char fmt_spdw[] = "[spdw] spindle dwell time%12.1f seconds\n";
const char fmt_ssoe[] ="[ssoe] spindle speed override ena%2d [0=disable,1=enable]\n";
const char fmt_sso[] ="[sso] spindle speed override%11.3f [0.050 < sso < 2.000]\n";
const char fmt_spe[] = "Spindle Enable:%7d [0=OFF,1=ON,2=PAUSE]\n";
const char fmt_spd[] = "Spindle Direction:%4d [0=CW,1=CCW]\n";
const char fmt_sps[] = "Spindle Speed: %7.0f rpm\n";
const char fmt_spsn[] = "[spsn] spindle speed min%14.2f rpm\n";
const char fmt_spsm[] = "[spsm] spindle speed max%14.2f rpm\n";
const char fmt_ssoe[] = "[ssoe] spindle speed override ena%2d [0=disable,1=enable]\n";
const char fmt_sso[] = "[sso] spindle speed override%10.3f [0.050 < sso < 2.000]\n";
const char fmt_sps[] = "Spindle Speed: %7.0f rpm\n";
const char fmt_spe[] = "Spindle Enable:%7d [0=OFF,1=ON,2=PAUSE]\n";
const char fmt_spd[] = "Spindle Direction:%4d [0=CW,1=CCW]\n";
void cm_print_spep(nvObj_t *nv) { text_print(nv, fmt_spep);} // TYPE_INT
void cm_print_spdp(nvObj_t *nv) { text_print(nv, fmt_spdp);} // TYPE_INT
void cm_print_spph(nvObj_t *nv) { text_print(nv, fmt_spph);} // TYPE_INT
void cm_print_spdw(nvObj_t *nv) { text_print(nv, fmt_spdw);} // TYPE_FLOAT
void cm_print_ssoe(nvObj_t *nv) { text_print(nv, fmt_ssoe);} // TYPE INT
void cm_print_sso(nvObj_t *nv) { text_print(nv, fmt_sso);} // TYPE FLOAT
void cm_print_spe(nvObj_t *nv) { text_print(nv, fmt_spe);} // TYPE_INT
void cm_print_spd(nvObj_t *nv) { text_print(nv, fmt_spd);} // TYPE_INT
void cm_print_sps(nvObj_t *nv) { text_print(nv, fmt_sps);} // TYPE_FLOAT
void sp_print_spmo(nvObj_t *nv) { text_print(nv, fmt_spmo);} // TYPE_INT
void sp_print_spep(nvObj_t *nv) { text_print(nv, fmt_spep);} // TYPE_INT
void sp_print_spdp(nvObj_t *nv) { text_print(nv, fmt_spdp);} // TYPE_INT
void sp_print_spph(nvObj_t *nv) { text_print(nv, fmt_spph);} // TYPE_INT
void sp_print_spdw(nvObj_t *nv) { text_print(nv, fmt_spdw);} // TYPE_FLOAT
void sp_print_spsn(nvObj_t *nv) { text_print(nv, fmt_spsn);} // TYPE_FLOAT
void sp_print_spsm(nvObj_t *nv) { text_print(nv, fmt_spsm);} // TYPE_FLOAT
void sp_print_ssoe(nvObj_t *nv) { text_print(nv, fmt_ssoe);} // TYPE INT
void sp_print_sso(nvObj_t *nv) { text_print(nv, fmt_sso);} // TYPE FLOAT
void sp_print_spe(nvObj_t *nv) { text_print(nv, fmt_spe);} // TYPE_INT
void sp_print_spd(nvObj_t *nv) { text_print(nv, fmt_spd);} // TYPE_INT
void sp_print_sps(nvObj_t *nv) { text_print(nv, fmt_sps);} // TYPE_FLOAT
#endif // __TEXT_MODE
+104 -54
View File
@@ -32,23 +32,36 @@ typedef enum { // how spindle controls are presented by the Gco
SPINDLE_CONTROL_OFF = 0, // M5
SPINDLE_CONTROL_CW, // M3
SPINDLE_CONTROL_CCW // M4
} cmSpindleControl;
typedef enum {
SPINDLE_OFF = 0,
SPINDLE_ON,
SPINDLE_PAUSE // meaning it was on and now it's off
} cmSpindleEnable;
} spControl;
typedef enum { // spindle direction state
SPINDLE_CW = 0,
SPINDLE_CCW
} cmSpindleDir;
} spDir;
typedef enum {
SPINDLE_ACTIVE_LOW = 0,
SPINDLE_ACTIVE_HIGH
} cmSpindlePolarity;
// *** 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
typedef enum {
SPINDLE_DISABLED = 0, // spindle will not operate
SPINDLE_PLAN_TO_STOP, // spindle operating, plans to stop
SPINDLE_CONTINUOUS, // spindle operating, does not plan to stop
} spMode;
#define SPINDLE_MODE_MAX SPINDLE_CONTINUOUS
typedef enum { // Note: These values agree with
SPINDLE_ACTIVE_LOW = 0, // Will set output to 0 to enable the spindle or CW direction
SPINDLE_ACTIVE_HIGH = 1, // Will set output to 1 to enable the spindle or CW direction
} spPolarity;
typedef enum { // basic spindle state machine
SPINDLE_OFF = 0,
SPINDLE_ON, // spindle on and at speed
SPINDLE_PAUSE, // meaning it was on and now it's off
SPINDLE_WAITING // spindle not at speed yet
} spState;
typedef enum {
ESC_ONLINE = 0,
@@ -56,7 +69,7 @@ typedef enum {
ESC_LOCKOUT,
ESC_REBOOTING,
ESC_LOCKOUT_AND_REBOOTING,
} cmESCState;
} ESCState;
#define SPINDLE_OVERRIDE_ENABLE false
#define SPINDLE_OVERRIDE_FACTOR 1.00
@@ -69,21 +82,27 @@ typedef enum {
*/
typedef struct cmSpindleSingleton {
float speed; // S in RPM
cmSpindleEnable enable; // OFF, ON, PAUSE
cmSpindleDir direction; // CW, CCW
bool pause_on_hold; // pause on feedhold
cmSpindlePolarity enable_polarity; // 0=active low, 1=active high
cmSpindlePolarity dir_polarity; // 0=clockwise low, 1=clockwise high
float dwell_seconds; // dwell on spindle resume
// Public and settable
spMode mode; // spondle operating mode
float speed; // S in RPM
float speed_min; // minimum settable spindle speed
float speed_max; // maximum settable spindle speed
spDir direction; // CW, 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
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
cmESCState esc_state; // state management for ESC controller
uint32_t esc_boot_timer; // When the ESC last booted up
uint32_t esc_lockout_timer; // When the ESC lockout last triggered
// Spindle speed controller variables
ESCState esc_state; // state management for ESC controller
uint32_t esc_boot_timer; // When the ESC last booted up
uint32_t esc_lockout_timer; // When the ESC lockout last triggered
} cmSpindleton_t;
extern cmSpindleton_t spindle;
@@ -94,44 +113,75 @@ extern cmSpindleton_t spindle;
void spindle_init();
void spindle_reset();
stat_t cm_set_spindle_speed(float speed); // S parameter
stat_t cm_spindle_control(uint8_t control); // M3, M4, M5 integrated spindle control
void cm_spindle_off_immediate(void);
void cm_spindle_optional_pause(bool option); // stop spindle based on system options selected
void cm_spindle_resume(float dwell_seconds); // restart spindle after pause based on previous state
stat_t spindle_queue_speed(float speed); // S parameter
stat_t spindle_queue_control(uint8_t control); // M3, M4, M5 integrated spindle control
void spindle_off_immediate(void);
void spindle_optional_pause(bool option); // stop spindle based on system options selected
void spindle_resume(float dwell_seconds); // restart spindle after pause based on previous state
stat_t cm_sso_control(const float P_word, const bool P_flag); // M51
void cm_start_spindle_override(const float ramp_time, const float override_factor);
void cm_end_spindle_override(const float ramp_time);
stat_t spindle_override_control(const float P_word, const bool P_flag); // M51
void spindle_start_override(const float ramp_time, const float override_factor);
void spindle_end_override(const float ramp_time);
stat_t cm_set_dir(nvObj_t* nv);
stat_t cm_set_sso(nvObj_t* nv);
stat_t sp_get_spmo(nvObj_t *nv);
stat_t sp_set_spmo(nvObj_t *nv);
stat_t sp_get_spep(nvObj_t *nv);
stat_t sp_set_spep(nvObj_t *nv);
stat_t sp_get_spdp(nvObj_t *nv);
stat_t sp_set_spdp(nvObj_t *nv);
stat_t sp_get_spph(nvObj_t *nv);
stat_t sp_set_spph(nvObj_t *nv);
stat_t sp_get_spdw(nvObj_t *nv);
stat_t sp_set_spdw(nvObj_t *nv);
stat_t sp_get_spsn(nvObj_t *nv);
stat_t sp_set_spsn(nvObj_t *nv);
stat_t sp_get_spsm(nvObj_t *nv);
stat_t sp_set_spsm(nvObj_t *nv);
stat_t sp_get_ssoe(nvObj_t* nv);
stat_t sp_set_ssoe(nvObj_t* nv);
stat_t sp_get_sso(nvObj_t* nv);
stat_t sp_set_sso(nvObj_t* nv);
stat_t sp_get_sps(nvObj_t* nv);
stat_t sp_set_sps(nvObj_t* nv);
stat_t sp_get_spe(nvObj_t* nv);
stat_t sp_set_spe(nvObj_t* nv);
stat_t sp_get_spd(nvObj_t* nv);
stat_t sp_set_spd(nvObj_t* nv);
/*--- text_mode support functions ---*/
#ifdef __TEXT_MODE
void cm_print_spep(nvObj_t* nv);
void cm_print_spdp(nvObj_t* nv);
void cm_print_spph(nvObj_t* nv);
void cm_print_spdw(nvObj_t* nv);
void cm_print_ssoe(nvObj_t* nv);
void cm_print_sso(nvObj_t* nv);
void cm_print_spe(nvObj_t* nv);
void cm_print_spd(nvObj_t* nv);
void cm_print_sps(nvObj_t* nv);
void sp_print_spmo(nvObj_t* nv);
void sp_print_spep(nvObj_t* nv);
void sp_print_spdp(nvObj_t* nv);
void sp_print_spph(nvObj_t* nv);
void sp_print_spdw(nvObj_t* nv);
void sp_print_spsn(nvObj_t* nv);
void sp_print_spsm(nvObj_t* nv);
void sp_print_ssoe(nvObj_t* nv);
void sp_print_sso(nvObj_t* nv);
void sp_print_sps(nvObj_t* nv);
void sp_print_spe(nvObj_t* nv);
void sp_print_spd(nvObj_t* nv);
#else
#define cm_print_spep tx_print_stub
#define cm_print_spdp tx_print_stub
#define cm_print_spph tx_print_stub
#define cm_print_spdw tx_print_stub
#define cm_print_ssoe tx_print_stub
#define cm_print_spe tx_print_stub
#define cm_print_sso tx_print_stub
#define cm_print_spd tx_print_stub
#define cm_print_sps tx_print_stub
#define sp_print_spmo tx_print_stub
#define sp_print_spep tx_print_stub
#define sp_print_spdp tx_print_stub
#define sp_print_spph tx_print_stub
#define sp_print_spdw tx_print_stub
#define sp_print_spsn tx_print_stub
#define sp_print_spsm tx_print_stub
#define sp_print_ssoe tx_print_stub
#define sp_print_spe tx_print_stub
#define sp_print_sps tx_print_stub
#define sp_print_sso tx_print_stub
#define sp_print_spd tx_print_stub
#endif // __TEXT_MODE