typedef struct {
float velocity_max; // max velocity in mm/min or deg/min
- float feedrate_max; // max velocity in mm/min or deg/min
float travel_max; // max work envelope for soft limits
float travel_min; // min work envelope for soft limits
float jerk_max; // max jerk (Jm) in mm/min^3 divided by 1 million
float recip_jerk; // reciprocal of current jerk value - with million
- float junction_dev; // aka cornering delta
float radius; // radius in mm for rotary axes
float search_velocity; // homing search velocity
float latch_velocity; // homing latch velocity
} axis_t;
-axis_t axes[MOTORS] = {
- {
- .velocity_max = X_VELOCITY_MAX,
- .feedrate_max = X_FEEDRATE_MAX,
- .travel_min = X_TRAVEL_MIN,
- .travel_max = X_TRAVEL_MAX,
- .jerk_max = X_JERK_MAX,
- .junction_dev = X_JUNCTION_DEVIATION,
- .search_velocity = X_SEARCH_VELOCITY,
- .latch_velocity = X_LATCH_VELOCITY,
- .latch_backoff = X_LATCH_BACKOFF,
- .zero_backoff = X_ZERO_BACKOFF,
- .homing_mode = X_HOMING_MODE,
- }, {
- .velocity_max = Y_VELOCITY_MAX,
- .feedrate_max = Y_FEEDRATE_MAX,
- .travel_min = Y_TRAVEL_MIN,
- .travel_max = Y_TRAVEL_MAX,
- .jerk_max = Y_JERK_MAX,
- .junction_dev = Y_JUNCTION_DEVIATION,
- .search_velocity = Y_SEARCH_VELOCITY,
- .latch_velocity = Y_LATCH_VELOCITY,
- .latch_backoff = Y_LATCH_BACKOFF,
- .zero_backoff = Y_ZERO_BACKOFF,
- .homing_mode = Y_HOMING_MODE,
- }, {
- .velocity_max = Z_VELOCITY_MAX,
- .feedrate_max = Z_FEEDRATE_MAX,
- .travel_min = Z_TRAVEL_MIN,
- .travel_max = Z_TRAVEL_MAX,
- .jerk_max = Z_JERK_MAX,
- .junction_dev = Z_JUNCTION_DEVIATION,
- .search_velocity = Z_SEARCH_VELOCITY,
- .latch_velocity = Z_LATCH_VELOCITY,
- .latch_backoff = Z_LATCH_BACKOFF,
- .zero_backoff = Z_ZERO_BACKOFF,
- .homing_mode = Z_HOMING_MODE,
- }, {
- .velocity_max = A_VELOCITY_MAX,
- .feedrate_max = A_FEEDRATE_MAX,
- .travel_min = A_TRAVEL_MIN,
- .travel_max = A_TRAVEL_MAX,
- .jerk_max = A_JERK_MAX,
- .junction_dev = A_JUNCTION_DEVIATION,
- .radius = A_RADIUS,
- .search_velocity = A_SEARCH_VELOCITY,
- .latch_velocity = A_LATCH_VELOCITY,
- .latch_backoff = A_LATCH_BACKOFF,
- .zero_backoff = A_ZERO_BACKOFF,
- .homing_mode = A_HOMING_MODE,
- }
-};
+axis_t axes[MOTORS] = {{0}};
bool axis_is_enabled(int axis) {
AXIS_GET(velocity_max, float, 0)
-AXIS_GET(feedrate_max, float, 0)
AXIS_GET(homed, bool, false)
AXIS_SET(homed, bool)
AXIS_GET(homing_mode, homing_mode_t, HOMING_DISABLED)
AXIS_GET(latch_velocity, float, 0)
AXIS_GET(zero_backoff, float, 0)
AXIS_GET(latch_backoff, float, 0)
-AXIS_GET(junction_dev, float, 0)
AXIS_GET(recip_jerk, float, 0)
AXIS_VAR_SET(velocity_max, float)
-AXIS_VAR_SET(feedrate_max, float)
AXIS_VAR_SET(radius, float)
AXIS_VAR_SET(travel_min, float)
AXIS_VAR_SET(travel_max, float)
AXIS_VAR_SET(latch_velocity, float)
AXIS_VAR_SET(zero_backoff, float)
AXIS_VAR_SET(latch_backoff, float)
-AXIS_VAR_SET(junction_dev, float)
AXIS_VAR_SET(jerk_max, float)
float axis_get_vector_length(const float a[], const float b[]);
float axis_get_velocity_max(int axis);
-float axis_get_feedrate_max(int axis);
float axis_get_jerk_max(int axis);
void axis_set_jerk_max(int axis, float jerk);
bool axis_get_homed(int axis);
float axis_get_latch_velocity(int axis);
float axis_get_zero_backoff(int axis);
float axis_get_latch_backoff(int axis);
-float axis_get_junction_dev(int axis);
float axis_get_recip_jerk(int axis);
float axis_get_jerk_max(int axis);
}
-uint8_t command_bootloader(int argc, char *argv[]) {
- hw_request_bootloader();
- return 0;
-}
-
-
-uint8_t command_save(int argc, char *argv[]) {
- vars_save();
- return 0;
-}
-
-
-uint8_t command_valid(int argc, char *argv[]) {
- printf_P(vars_valid() ? PSTR("true\n") : PSTR("false\n"));
- return 0;
-}
-
-
-uint8_t command_restore(int argc, char *argv[]) {
- return vars_restore();
-}
-
-
-uint8_t command_clear(int argc, char *argv[]) {
- vars_clear();
- return 0;
-}
-
-
uint8_t command_messages(int argc, char *argv[]) {
status_help();
return 0;
// Name Min, Max args, Help
CMD(help, 0, 1, "Print this help screen")
CMD(reboot, 0, 0, "Reboot the controller")
-CMD(bootloader, 0, 0, "Load bootloader")
-CMD(save, 0, 0, "Save settings")
-CMD(valid, 0, 0, "Print 'true' if saved settings are valid")
-CMD(restore, 0, 0, "Restore settings")
-CMD(clear, 0, 0, "Clear saved settings")
CMD(jog, 1, 4, "Jog")
CMD(mreset, 0, 1, "Reset motor")
CMD(calibrate, 0, 0, "Calibrate motors")
#define PWMS 2 // number of supported PWM channels
-// Motor settings. See motor.c
-#define MOTOR_MAX_CURRENT 1.0 // 1.0 is full power
-#define MOTOR_MIN_CURRENT 0.25 // 1.0 is full power
-#define MOTOR_IDLE_CURRENT 0.05 // 1.0 is full power
-#define MOTOR_STALL_THRESHOLD 0 // 0 -> 1 is least -> most sensitive
-#define MOTOR_MICROSTEPS 32
-#define MOTOR_POWER_MODE MOTOR_POWERED_ONLY_WHEN_MOVING
-#define MOTOR_IDLE_TIMEOUT 0.25 // secs, motor off after this time
-
-#define M1_AXIS AXIS_X
-#define M1_STEP_ANGLE 1.8
-#define M1_TRAVEL_PER_REV 6.35
-#define M1_MICROSTEPS MOTOR_MICROSTEPS
-#define M1_REVERSE false
-#define M1_POWER_MODE MOTOR_POWER_MODE
-
-#define M2_AXIS AXIS_Y
-#define M2_STEP_ANGLE 1.8
-#define M2_TRAVEL_PER_REV 6.35
-#define M2_MICROSTEPS MOTOR_MICROSTEPS
-#define M2_REVERSE false
-#define M2_POWER_MODE MOTOR_POWER_MODE
-
-#define M3_AXIS AXIS_Z
-#define M3_STEP_ANGLE 1.8
-#define M3_TRAVEL_PER_REV (25.4 / 6.0)
-#define M3_MICROSTEPS MOTOR_MICROSTEPS
-#define M3_REVERSE false
-#define M3_POWER_MODE MOTOR_POWER_MODE
-
-#define M4_AXIS AXIS_A
-#define M4_STEP_ANGLE 1.8
-#define M4_TRAVEL_PER_REV 360 // degrees per motor rev
-#define M4_MICROSTEPS MOTOR_MICROSTEPS
-#define M4_REVERSE false
-#define M4_POWER_MODE MOTOR_POWER_MODE
-
-
-// Machine settings
-//#define STEP_CORRECTION // Enable step correction
-#define MAX_STEP_CORRECTION 4 // In steps per segment
-#define CHORDAL_TOLERANCE 0.01 // chordal accuracy for arcs
-#define JERK_MAX 5 // yes, that's km/min^3
-#define JUNCTION_DEVIATION 0.05 // default value, in mm
-#define JUNCTION_ACCELERATION 100000 // centripetal corner accel
-#define JOG_JERK_MULT 4 // Jogging jerk multipler
-#define JOG_MIN_VELOCITY 10 // mm/min
-#define CAL_ACCELERATION 500000 // mm/min^2
-
-// Axis settings
-#define VELOCITY_MAX 13000 // mm/min
-#define FEEDRATE_MAX VELOCITY_MAX
-
-#define X_VELOCITY_MAX VELOCITY_MAX // G0 max velocity in mm/min
-#define X_FEEDRATE_MAX FEEDRATE_MAX // G1 max feed rate in mm/min
-#define X_TRAVEL_MIN 0 // minimum travel for soft limits
-#define X_TRAVEL_MAX 350 // between switches or crashes
-#define X_JERK_MAX JERK_MAX
-#define X_JUNCTION_DEVIATION JUNCTION_DEVIATION
-#define X_SEARCH_VELOCITY 2400 // move in negative direction
-#define X_LATCH_VELOCITY 100 // mm/min
-#define X_LATCH_BACKOFF 5 // mm
-#define X_ZERO_BACKOFF 1 // mm
-#define X_HOMING_MODE HOMING_STALL_MAX
-
-#define Y_VELOCITY_MAX VELOCITY_MAX
-#define Y_FEEDRATE_MAX FEEDRATE_MAX
-#define Y_TRAVEL_MIN 0
-#define Y_TRAVEL_MAX 350
-#define Y_JERK_MAX JERK_MAX
-#define Y_JUNCTION_DEVIATION JUNCTION_DEVIATION
-#define Y_SEARCH_VELOCITY 3000
-#define Y_LATCH_VELOCITY 100
-#define Y_LATCH_BACKOFF 5
-#define Y_ZERO_BACKOFF 1
-#define Y_HOMING_MODE HOMING_STALL_MAX
-
-#define Z_VELOCITY_MAX 2000 // VELOCITY_MAX
-#define Z_FEEDRATE_MAX FEEDRATE_MAX
-#define Z_TRAVEL_MIN 0
-#define Z_TRAVEL_MAX 75
-#define Z_JERK_MAX JERK_MAX
-#define Z_JUNCTION_DEVIATION JUNCTION_DEVIATION
-#define Z_SEARCH_VELOCITY 400
-#define Z_LATCH_VELOCITY 100
-#define Z_LATCH_BACKOFF 5
-#define Z_ZERO_BACKOFF 1
-#define Z_HOMING_MODE HOMING_STALL_MAX
-
-// A values are chosen to make the A motor react the same as X for testing
-// set to the same speed as X axis
-#define A_VELOCITY_MAX (X_VELOCITY_MAX / M1_TRAVEL_PER_REV * 360)
-#define A_FEEDRATE_MAX A_VELOCITY_MAX
-#define A_TRAVEL_MIN -1
-#define A_TRAVEL_MAX -1 // same value means infinite
-#define A_JERK_MAX (X_JERK_MAX * 360 / M1_TRAVEL_PER_REV)
-#define A_JUNCTION_DEVIATION JUNCTION_DEVIATION
-#define A_RADIUS (M1_TRAVEL_PER_REV / 2 / M_PI)
-#define A_SEARCH_VELOCITY 600
-#define A_LATCH_VELOCITY 100
-#define A_LATCH_BACKOFF 5
-#define A_ZERO_BACKOFF 2
-#define A_HOMING_MODE HOMING_DISABLED
-
-
-// Spindle settings
-#define SPINDLE_TYPE SPINDLE_TYPE_HUANYANG
-#define SPINDLE_PWM_FREQUENCY 100 // in Hz
-#define SPINDLE_MIN_RPM 1000
-#define SPINDLE_MAX_RPM 24000
-#define SPINDLE_MIN_DUTY 0.05
-#define SPINDLE_MAX_DUTY 0.99
-#define SPINDLE_REVERSE false
-
-
-// Gcode defaults
-#define GCODE_DEFAULT_UNITS MILLIMETERS // MILLIMETERS or INCHES
-#define GCODE_DEFAULT_PLANE PLANE_XY // See machine.h
-#define GCODE_DEFAULT_COORD_SYSTEM G54 // G54, G55, G56, G57, G58, G59
-#define GCODE_DEFAULT_PATH_CONTROL PATH_CONTINUOUS
-#define GCODE_DEFAULT_DISTANCE_MODE ABSOLUTE_MODE
-#define GCODE_DEFAULT_ARC_DISTANCE_MODE INCREMENTAL_MODE
-
-
-// Arc
-#define ARC_RADIUS_ERROR_MAX 1.0 // max mm diff between start and end radius
-#define ARC_RADIUS_ERROR_MIN 0.005 // min mm where 1% rule applies
-#define ARC_RADIUS_TOLERANCE 0.001 // 0.1% radius variance test
-
-
// Switch settings. See switch.c
#define SWITCH_INTLVL PORT_INT0LVL_MED_gc
#define SW_LOCKOUT_TICKS 250 // ms
#define I2C_ISR TWIC_TWIS_vect
#define I2C_ADDR 0x2b
#define I2C_MAX_DATA 8
+
+
+// Settings ********************************************************************
+
+// Motor settings. See motor.c
+#define MOTOR_IDLE_TIMEOUT 0.25 // secs, motor off after this time
+
+
+//#define STEP_CORRECTION // Enable step correction
+#define MAX_STEP_CORRECTION 4 // In steps per segment
+#define CHORDAL_TOLERANCE 0.01 // chordal accuracy for arcs
+#define JUNCTION_DEVIATION 0.05 // default value, in mm
+#define JUNCTION_ACCELERATION 100000 // centripetal corner accel
+#define JOG_JERK_MULT 1 // Jogging jerk multipler
+#define JOG_MIN_VELOCITY 10 // mm/min
+#define CAL_ACCELERATION 500000 // mm/min^2
+
+
+// Arc
+#define ARC_RADIUS_ERROR_MAX 1.0 // max mm diff between start and end radius
+#define ARC_RADIUS_ERROR_MIN 0.005 // min mm where 1% rule applies
+#define ARC_RADIUS_TOLERANCE 0.001 // 0.1% radius variance test
+
+
+// Gcode defaults
+#define GCODE_DEFAULT_UNITS MILLIMETERS // MILLIMETERS or INCHES
+#define GCODE_DEFAULT_PLANE PLANE_XY // See machine.h
+#define GCODE_DEFAULT_COORD_SYSTEM G54 // G54, G55, G56, G57, G58, G59
+#define GCODE_DEFAULT_PATH_CONTROL PATH_CONTINUOUS
+#define GCODE_DEFAULT_DISTANCE_MODE ABSOLUTE_MODE
+#define GCODE_DEFAULT_ARC_DISTANCE_MODE INCREMENTAL_MODE
typedef struct {
uint8_t status;
- bool active;
+ drv8711_state_t state;
float idle_current;
float max_current;
float min_current;
static float _driver_get_current(int driver) {
drv8711_driver_t *drv = &drivers[driver];
- if (!drv->active) return drv->idle_current;
- return drv->min_current + (drv->max_current - drv->min_current) * drv->power;
+ switch (drv->state) {
+ case DRV8711_IDLE: return drv->idle_current;
+
+ case DRV8711_ACTIVE:
+ return drv->min_current +
+ (drv->max_current - drv->min_current) * drv->power;
+
+ default: return 0;
+ }
}
// Prep next command
for (int driver = 0; driver < DRIVERS; driver++) {
+ drv8711_driver_t *drv = &drivers[driver];
uint16_t *command = &spi.commands[driver][cmd];
switch (DRV8711_CMD_ADDR(*command)) {
case DRV8711_STATUS_REG:
if (!DRV8711_CMD_IS_READ(*command))
- *command = (*command & 0xf000) | (0x0fff & ~(drivers[driver].status));
+ *command = (*command & 0xf000) | (0x0fff & ~(drv->status));
break;
case DRV8711_TORQUE_REG: // Update motor current setting
break;
case DRV8711_CTRL_REG: // Set microsteps
- *command = (*command & 0xff87) | (drivers[driver].mode << 3);
+ *command = (*command & 0xff86) | (drv->mode << 3) |
+ (_driver_get_current(driver) ? DRV8711_CTRL_ENBL_bm : 0);
break;
default: break;
// Set DECAY
commands[spi.ncmds++] =
- DRV8711_WRITE(DRV8711_DECAY_REG, DRV8711_DECAY_DECMOD_AUTO_OPT | 6);
+ DRV8711_WRITE(DRV8711_DECAY_REG, DRV8711_DECAY_DECMOD_OPT | 6);
// Set STALL
commands[spi.ncmds++] =
commands[spi.ncmds++] =
DRV8711_WRITE(DRV8711_TORQUE_REG, DRV8711_TORQUE_SMPLTH_50);
- // Set CTRL enable motor & set ISENSE gain
+ // Set CTRL set ISENSE gain
commands[spi.ncmds++] =
- DRV8711_WRITE(DRV8711_CTRL_REG, DRV8711_CTRL_ENBL_bm |
+ DRV8711_WRITE(DRV8711_CTRL_REG,
DRV8711_CTRL_ISGAIN_10 | DRV8711_CTRL_DTIME_850);
// Read STATUS
void drv8711_init() {
- // Configure drivers
- for (int i = 0; i < DRIVERS; i++) {
- drivers[i].idle_current = MOTOR_IDLE_CURRENT;
- drivers[i].max_current = MOTOR_MAX_CURRENT;
- drivers[i].min_current = MOTOR_MIN_CURRENT;
- drivers[i].stall_threshold = MOTOR_STALL_THRESHOLD;
-
- drv8711_disable(i);
- }
-
// Setup pins
// Must set the SS pin either in/high or any/output for master mode to work
// Note, this pin is also used by the USART as the CTS line
}
-void drv8711_enable(int driver) {
- if (driver < 0 || DRIVERS <= driver) return;
- drivers[driver].active = true;
+drv8711_state_t drv8711_get_state(int driver) {
+ if (driver < 0 || DRIVERS <= driver) return DRV8711_DISABLED;
+ return drivers[driver].state;
}
-void drv8711_disable(int driver) {
+void drv8711_set_state(int driver, drv8711_state_t state) {
if (driver < 0 || DRIVERS <= driver) return;
- drivers[driver].active = false;
+ drivers[driver].state = state;
}
#define DRV8711_CMD_IS_READ(CMD) ((1 << 15) & (CMD))
+typedef enum {
+ DRV8711_DISABLED,
+ DRV8711_IDLE,
+ DRV8711_ACTIVE,
+} drv8711_state_t;
+
+
void drv8711_init();
-void drv8711_enable(int driver);
-void drv8711_disable(int driver);
+drv8711_state_t drv8711_get_state(int driver);
+void drv8711_set_state(int driver, drv8711_state_t state);
void drv8711_set_power(int driver, float power);
void drv8711_set_microsteps(int driver, uint16_t msteps);
void drv8711_set_stall_callback(int driver, stall_callback_t cb);
HUANYANG_ACTUAL_FREQ,
HUANYANG_ACTUAL_CURRENT,
HUANYANG_ACTUAL_RPM,
- HUANYANG_DC_VOLTAGE,
- HUANYANG_AC_VOLTAGE,
HUANYANG_CONT,
HUANYANG_TEMPERATURE,
};
float actual_freq;
float actual_current;
uint16_t actual_rpm;
- uint16_t dc_voltage;
- uint16_t ac_voltage;
uint16_t temperature;
float max_freq;
case 1: ha.actual_freq = CTRL_STATUS_RESPONSE(ha.response) * 0.01; break;
case 2: ha.actual_current = CTRL_STATUS_RESPONSE(ha.response) * 0.1; break;
case 3: ha.actual_rpm = CTRL_STATUS_RESPONSE(ha.response); break;
- case 4: ha.dc_voltage = CTRL_STATUS_RESPONSE(ha.response); break;
- case 5: ha.ac_voltage = CTRL_STATUS_RESPONSE(ha.response); break;
- case 6: ha.temperature = CTRL_STATUS_RESPONSE(ha.response); break;
+ case 4: ha.temperature = CTRL_STATUS_RESPONSE(ha.response); break;
default: break;
}
case 0: var = HUANYANG_ACTUAL_FREQ; break;
case 1: var = HUANYANG_ACTUAL_CURRENT; break;
case 2: var = HUANYANG_ACTUAL_RPM; break;
- case 3: var = HUANYANG_DC_VOLTAGE; break;
- case 4: var = HUANYANG_AC_VOLTAGE; break;
- case 5: var = HUANYANG_TEMPERATURE; break;
+ case 3: var = HUANYANG_TEMPERATURE; break;
default:
report_request();
return false;
float get_huanyang_freq() {return ha.actual_freq;}
float get_huanyang_current() {return ha.actual_current;}
uint16_t get_huanyang_rpm() {return ha.actual_rpm;}
-uint16_t get_huanyang_dcv() {return ha.dc_voltage;}
-uint16_t get_huanyang_acv() {return ha.ac_voltage;}
uint16_t get_huanyang_temp() {return ha.temperature;}
float get_huanyang_max_freq() {return ha.max_freq;}
float get_huanyang_min_freq() {return ha.min_freq;}
static machine_t mach = {
- // Offsets
- .offset = {
- {}, // ABSOLUTE_COORDS
-
- {0, 0, 0, 0, 0, 0}, // G54
- {X_TRAVEL_MAX / 2, Y_TRAVEL_MAX / 2, 0, 0, 0, 0}, // G55
- {0, 0, 0, 0, 0, 0}, // G56
- {0, 0, 0, 0, 0, 0}, // G57
- {0, 0, 0, 0, 0, 0}, // G58
- {0, 0, 0, 0, 0, 0}, // G59
- },
-
- // State
.gm = {.motion_mode = MOTION_MODE_CANCEL_MOTION_MODE},
};
typedef enum {
+ MOTOR_OFF,
MOTOR_IDLE, // motor stopped and may be partially energized
MOTOR_ENERGIZING,
MOTOR_ACTIVE
static motor_t motors[MOTORS] = {
{
- .axis = M1_AXIS,
- .step_angle = M1_STEP_ANGLE,
- .travel_rev = M1_TRAVEL_PER_REV,
- .microsteps = M1_MICROSTEPS,
- .reverse = M1_REVERSE,
- .power_mode = M1_POWER_MODE,
+ .axis = AXIS_X,
.step_pin = STEP_X_PIN,
.dir_pin = DIR_X_PIN,
.timer = &M1_TIMER,
.dma = &M1_DMA_CH,
.dma_trigger = M1_DMA_TRIGGER,
}, {
- .axis = M2_AXIS,
- .step_angle = M2_STEP_ANGLE,
- .travel_rev = M2_TRAVEL_PER_REV,
- .microsteps = M2_MICROSTEPS,
- .reverse = M2_REVERSE,
- .power_mode = M2_POWER_MODE,
+ .axis = AXIS_Y,
.step_pin = STEP_Y_PIN,
.dir_pin = DIR_Y_PIN,
.timer = &M2_TIMER,
.dma = &M2_DMA_CH,
.dma_trigger = M2_DMA_TRIGGER,
}, {
- .axis = M3_AXIS,
- .step_angle = M3_STEP_ANGLE,
- .travel_rev = M3_TRAVEL_PER_REV,
- .microsteps = M3_MICROSTEPS,
- .reverse = M3_REVERSE,
- .power_mode = M3_POWER_MODE,
+ .axis = AXIS_Z,
.step_pin = STEP_Z_PIN,
.dir_pin = DIR_Z_PIN,
.timer = &M3_TIMER,
.dma = &M3_DMA_CH,
.dma_trigger = M3_DMA_TRIGGER,
}, {
- .axis = M4_AXIS,
- .step_angle = M4_STEP_ANGLE,
- .travel_rev = M4_TRAVEL_PER_REV,
- .microsteps = M4_MICROSTEPS,
- .reverse = M4_REVERSE,
- .power_mode = M4_POWER_MODE,
+ .axis = AXIS_A,
.step_pin = STEP_A_PIN,
.dir_pin = DIR_A_PIN,
.timer = (TC0_t *)&M4_TIMER,
if (enable) OUTSET_PIN(MOTOR_ENABLE_PIN); // Active high
else {
OUTCLR_PIN(MOTOR_ENABLE_PIN);
- motors[motor].power_state = MOTOR_IDLE;
+ motors[motor].power_state = MOTOR_DISABLED;
}
}
}
-/// Remove power from a motor
-static void _deenergize(int m) {
- if (motors[m].power_state == MOTOR_ACTIVE) {
- motors[m].power_state = MOTOR_IDLE;
- drv8711_disable(m);
- }
+static void _set_power_state(int motor, motor_power_state_t state) {
+ motors[motor].power_state = state;
+ report_request();
}
-/// Apply power to a motor
-static void _energize(int m) {
- if (motors[m].power_state == MOTOR_IDLE && !motor_error(m)) {
- motors[m].power_state = MOTOR_ENERGIZING;
- drv8711_enable(m);
+static void _update_power(int motor) {
+ motor_t *m = &motors[motor];
- motor_driver_callback(m); // TODO Shouldn't call this directly
- }
+ switch (m->power_mode) {
+ case MOTOR_POWERED_ONLY_WHEN_MOVING:
+ case MOTOR_POWERED_IN_CYCLE:
+ if (rtc_expired(m->timeout)) {
+ if (m->power_state == MOTOR_ACTIVE) {
+ _set_power_state(motor, MOTOR_IDLE);
+ drv8711_set_state(motor, DRV8711_IDLE);
+ }
+ break;
+ }
+ // Fall through
+
+ case MOTOR_ALWAYS_POWERED:
+ if (m->power_state != MOTOR_ACTIVE && m->power_state != MOTOR_ENERGIZING &&
+ !motor_error(motor)) {
+ _set_power_state(motor, MOTOR_ENERGIZING);
+ // TODO is ~5ms enough time to enable the motor?
+ drv8711_set_state(motor, DRV8711_ACTIVE);
- // Reset timeout, regardless
- motors[m].timeout = rtc_get_time() + MOTOR_IDLE_TIMEOUT * 1000;
+ motor_driver_callback(motor); // TODO Shouldn't call this directly
+ }
+ break;
+
+ default: // Disabled
+ if (m->power_state != MOTOR_OFF) {
+ _set_power_state(motor, MOTOR_OFF);
+ drv8711_set_state(motor, DRV8711_DISABLED);
+ }
+ }
}
/// Callback to manage motor power sequencing and power-down timing.
stat_t motor_rtc_callback() { // called by controller
for (int motor = 0; motor < MOTORS; motor++)
- // Deenergize motor if disabled or timedout
- if (motors[motor].power_mode == MOTOR_DISABLED ||
- rtc_expired(motors[motor].timeout)) _deenergize(motor);
+ _update_power(motor);
return STAT_OK;
}
if (!m->timer_period) m->timer_clock = 0;
if (!m->timer_clock) m->timer_period = 0;
+ // Compute power from axis velocity
+ m->power = travel / (_get_max_velocity(motor) * time);
+
// Power motor
switch (m->power_mode) {
- case MOTOR_DISABLED: break;
-
case MOTOR_POWERED_ONLY_WHEN_MOVING:
if (!m->timer_clock) break; // Not moving
// Fall through
case MOTOR_ALWAYS_POWERED: case MOTOR_POWERED_IN_CYCLE:
- _energize(motor); // TODO is ~5ms enough time to enable the motor?
+ // Reset timeout
+ m->timeout = rtc_get_time() + MOTOR_IDLE_TIMEOUT * 1000;
break;
- default: break; // Shouldn't get here
+ default: break;
}
-
- // Compute power from axis velocity
- m->power = travel / (_get_max_velocity(motor) * time);
+ _update_power(motor);
return STAT_OK;
}
time /= mach_get_feed_override();
// Downgrade the time if there is a rate-limiting axis
- return max4(time, planar_travel / axis_get_feedrate_max(arc.plane_axis_0),
- planar_travel / axis_get_feedrate_max(arc.plane_axis_1),
- fabs(linear_travel) / axis_get_feedrate_max(arc.linear_axis));
+ return max4(time, planar_travel / axis_get_velocity_max(arc.plane_axis_0),
+ planar_travel / axis_get_velocity_max(arc.plane_axis_1),
+ fabs(linear_travel) / axis_get_velocity_max(arc.linear_axis));
}
!bf) {
mp_runtime_set_velocity(0);
mp_runtime_set_busy(false);
+ if (mp_get_state() == STATE_STOPPING) mp_state_holding();
return STAT_NOOP; // Nothing running
}
* This creates a deviation from the path (let's call this delta),
* which is the distance from the junction to the edge of the circular
* segment. Delta needs to be defined, so let's replace the term max_jerk (see
- * note 1) with max_junction_deviation, or "delta". This indirectly sets the
+ * note 1) with max junction deviation, or "delta". This indirectly sets the
* radius of the circle, and hence limits the velocity by the centripetal
* acceleration. Think of the this as widening the race track. If a race car is
* driving on a track only as wide as a car, it'll have to slow down a lot to
float b_delta = 0;
for (int axis = 0; axis < AXES; axis++) {
- a_delta += square(a_unit[axis] * axis_get_junction_dev(axis));
- b_delta += square(b_unit[axis] * axis_get_junction_dev(axis));
+ a_delta += square(a_unit[axis] * JUNCTION_DEVIATION);
+ b_delta += square(b_unit[axis] * JUNCTION_DEVIATION);
}
if (!a_delta || !b_delta) return 0; // One or both unit vectors are null
// Compute time required for rate-limiting axis
for (int axis = 0; axis < AXES; axis++) {
- float time = fabs(axis_length[axis]) /
- (rapid ? axis_get_velocity_max(axis) : axis_get_feedrate_max(axis));
-
+ float time = fabs(axis_length[axis]) / axis_get_velocity_max(axis);
if (max_time < time) max_time = time;
}
} pwm_spindle_t;
-static pwm_spindle_t spindle = {
- .freq = SPINDLE_PWM_FREQUENCY,
- .min_rpm = SPINDLE_MIN_RPM,
- .max_rpm = SPINDLE_MAX_RPM,
- .min_duty = SPINDLE_MIN_DUTY,
- .max_duty = SPINDLE_MAX_DUTY,
- .reverse = SPINDLE_REVERSE,
- .enable_invert = false,
- .estop = false,
-};
+static pwm_spindle_t spindle = {0};
static void _spindle_set_pwm(spindle_mode_t mode, float speed) {
// TODO these need more effort and should work with the huanyang spindle too
-float get_max_spin(int index) {return spindle.max_rpm;}
-void set_max_spin(int axis, float value) {spindle.max_rpm = value;}
-float get_min_spin(int index) {return spindle.min_rpm;}
-void set_min_spin(int axis, float value) {spindle.min_rpm = value;}
-float get_spin_min_pulse(int index) {return spindle.min_duty;}
-void set_spin_min_pulse(int axis, float value) {spindle.min_duty = value;}
-float get_spin_max_pulse(int index) {return spindle.max_duty;}
-void set_spin_max_pulse(int axis, float value) {spindle.max_duty = value;}
-uint8_t get_spin_reverse(int index) {return spindle.reverse;}
-void set_spin_reverse(int axis, uint8_t value) {spindle.reverse = value;}
-float get_spin_up(int index) {return 0;}
-void set_spin_up(int axis, float value) {}
-float get_spin_down(int index) {return 0;}
-void set_spin_down(int axis, float value) {}
+float get_max_spin() {return spindle.max_rpm;}
+void set_max_spin(float value) {spindle.max_rpm = value;}
+float get_min_spin() {return spindle.min_rpm;}
+void set_min_spin(float value) {spindle.min_rpm = value;}
+float get_spin_min_pulse() {return spindle.min_duty;}
+void set_spin_min_pulse(float value) {spindle.min_duty = value;}
+float get_spin_max_pulse() {return spindle.max_duty;}
+void set_spin_max_pulse(float value) {spindle.max_duty = value;}
+uint8_t get_spin_reverse() {return spindle.reverse;}
+void set_spin_reverse(uint8_t value) {spindle.reverse = value;}
+float get_spin_up() {return 0;} // TODO
+void set_spin_up(float value) {} // TODO
+float get_spin_down() {return 0;} // TODO
+void set_spin_down(float value) {} // TODO
+uint16_t get_spin_freq() {return spindle.freq;}
+void set_spin_freq(uint16_t value) {spindle.freq = value;}
typedef enum {
- SPINDLE_TYPE_PWM,
SPINDLE_TYPE_HUANYANG,
+ SPINDLE_TYPE_PWM,
} spindle_type_t;
} spindle_t;
-static spindle_t spindle = {.type = SPINDLE_TYPE};
+static spindle_t spindle = {0};
void spindle_init() {
#include <math.h>
#include <avr/pgmspace.h>
-#include <avr/eeprom.h>
typedef uint8_t flags_t;
}
-static uint8_t eeprom_read_bool(bool *addr) {
- return eeprom_read_byte((uint8_t *)addr);
-}
-
-
-static void eeprom_update_bool(bool *addr, bool value) {
- eeprom_update_byte((uint8_t *)addr, value);
-}
-
-
// Char
static void var_print_char(char x) {putchar('"'); putchar(x); putchar('"');}
static char var_parse_char(const char *value) {return value[0];}
-static uint8_t eeprom_read_char(char *addr) {
- return eeprom_read_byte((uint8_t *)addr);
-}
-
-
-static void eeprom_update_char(char *addr, char value) {
- eeprom_update_byte((uint8_t *)addr, value);
-}
-
-
// int8
#if 0
static void var_print_int8_t(int8_t x) {
static int8_t var_parse_int8_t(const char *value) {
return strtol(value, 0, 0);
}
-
-
-static int8_t eeprom_read_int8_t(int8_t *addr) {
- return eeprom_read_byte((uint8_t *)addr);
-}
-
-
-static void eeprom_update_int8_t(int8_t *addr, int8_t value) {
- eeprom_update_byte((uint8_t *)addr, value);
-}
#endif
// uint8
}
-static uint8_t eeprom_read_uint8_t(uint8_t *addr) {
- return eeprom_read_byte(addr);
-}
-
-
-static void eeprom_update_uint8_t(uint8_t *addr, uint8_t value) {
- eeprom_update_byte(addr, value);
-}
-
-
// unit16
static void var_print_uint16_t(uint16_t x) {
printf_P(PSTR("%"PRIu16), x);
}
-static uint16_t eeprom_read_uint16_t(uint16_t *addr) {
- return eeprom_read_word(addr);
-}
-
-
-static void eeprom_update_uint16_t(uint16_t *addr, uint16_t value) {
- eeprom_update_word(addr, value);
-}
-
-
// int32
static void var_print_int32_t(uint32_t x) {
printf_P(PSTR("%"PRIi32), x);
#undef VAR
// Var names, count & help
-#define VAR(NAME, CODE, TYPE, INDEX, SET, SAVE, HELP) \
+#define VAR(NAME, CODE, TYPE, INDEX, SET, HELP) \
static const char NAME##_name[] PROGMEM = #NAME; \
static const char NAME##_help[] PROGMEM = HELP;
#include "vars.def"
#undef VAR
-// EEPROM storage
-#define VAR(NAME, CODE, TYPE, INDEX, SET, SAVE, HELP) \
- IF(SAVE) \
- (static TYPE NAME##_eeprom IF(INDEX)([INDEX]) EEMEM;)
-
-#include "vars.def"
-#undef VAR
-
-static uint16_t eeprom_crc EEMEM;
-
// Last value
#define VAR(NAME, CODE, TYPE, INDEX, ...) \
static TYPE NAME##_state IF(INDEX)([INDEX]);
void vars_init() {
- vars_restore();
-
// Initialize var state
-#define VAR(NAME, CODE, TYPE, INDEX, SET, SAVE, ...) \
+#define VAR(NAME, CODE, TYPE, INDEX, ...) \
IF(INDEX)(for (int i = 0; i < INDEX; i++)) \
(NAME##_state)IF(INDEX)([i]) = get_##NAME(IF(INDEX)(i));
// Restore watchdog
hw_restore_watchdog(wd_state);
}
-
-
-uint16_t vars_crc() {
- // Save and disable watchdog
- uint8_t wd_state = hw_disable_watchdog();
-
- CRC.CTRL = CRC_RESET_RESET0_gc;
- CRC.CTRL = CRC_SOURCE_IO_gc; // Must be after reset
-
-#define VAR(NAME, CODE, TYPE, INDEX, SET, SAVE, ...) \
- IF(SAVE) \
- ({ \
- for (int j = 0; ; j++) { \
- char c = pgm_read_byte(&NAME##_name[j]); \
- if (!c) break; \
- CRC.DATAIN = c; \
- } \
- \
- CRC.DATAIN = INDEX; \
- })
-
-#include "vars.def"
-#undef VAR
-
- // Restore watchdog
- hw_restore_watchdog(wd_state);
-
- CRC.STATUS = CRC_BUSY_bm; // Done
- return CRC.CHECKSUM1 << 8 | CRC.CHECKSUM0;
-}
-
-
-void vars_save() {
- // Save and disable watchdog
- uint8_t wd_state = hw_disable_watchdog();
-
-#define VAR(NAME, CODE, TYPE, INDEX, SET, SAVE, ...) \
- IF(SAVE) \
- (IF(INDEX)(for (int i = 0; i < (INDEX ? INDEX : 1); i++)) { \
- TYPE value = get_##NAME(IF(INDEX)(i)); \
- eeprom_update_##TYPE(&NAME##_eeprom IF(INDEX)([i]), value); \
- }) \
-
-#include "vars.def"
-#undef VAR
-
- // Restore watchdog
- hw_restore_watchdog(wd_state);
-
- // Save CRC
- eeprom_update_word(&eeprom_crc, vars_crc());
-}
-
-
-
-bool vars_valid() {
- return eeprom_read_word(&eeprom_crc) == vars_crc();
-}
-
-
-stat_t vars_restore() {
- if (!vars_valid()) return STAT_EEPROM_DATA_INVALID;
-
- // Save and disable watchdog
- uint8_t wd_state = hw_disable_watchdog();
-
-#define VAR(NAME, CODE, TYPE, INDEX, SET, SAVE, ...) \
- IF(SAVE) \
- (IF(INDEX)(for (int i = 0; i < (INDEX ? INDEX : 1); i++)) { \
- TYPE value = eeprom_read_##TYPE(&NAME##_eeprom IF(INDEX)([i])); \
- set_##NAME(IF(INDEX)(i,) value); \
- NAME##_state IF(INDEX)([i]) = value; \
- }) \
-
-#include "vars.def"
-#undef VAR
-
- // Restore watchdog
- hw_restore_watchdog(wd_state);
-
- return STAT_OK;
-}
-
-
-void vars_clear() {
- eeprom_update_word(&eeprom_crc, -1);
-}
#define AXES_LABEL "xyzabcuvw"
#define MOTORS_LABEL "0123"
-#define SWITCHES_LABEL "0123456789"
-// VAR(name, code, type, index, settable, save, help)
+// VAR(name, code, type, index, settable, help)
// Motor
-VAR(axis_name, an, char, MOTORS, 1, 1, "Maps motor to axis name")
-VAR(step_angle, sa, float, MOTORS, 1, 1, "In degrees per full step")
-VAR(travel, tr, float, MOTORS, 1, 1, "Travel in mm per revolution")
-VAR(microstep, mi, uint16_t, MOTORS, 1, 1, "Microsteps per full step")
-VAR(reverse, rv, uint8_t, MOTORS, 1, 1, "Reverse motor polarity")
-
-VAR(power_mode, pm, uint8_t, MOTORS, 1, 1, "Motor power mode")
-VAR(max_current, xc, float, MOTORS, 1, 1, "Max motor drive current")
-VAR(min_current, lc, float, MOTORS, 1, 1, "Min motor drive current")
-VAR(idle_current, ic, float, MOTORS, 1, 1, "Motor idle current")
-VAR(active_current, ac, float, MOTORS, 0, 0, "Motor current now")
-VAR(status_flags, mf, uint8_t, MOTORS, 0, 0, "Motor status flags")
-VAR(status_strings, ms, flags_t, MOTORS, 0, 0, "Motor status strings")
-
-VAR(motor_fault, fa, bool, 0, 0, 0, "Motor fault status")
-
-VAR(velocity_max, vm, float, MOTORS, 1, 1, "Maxium velocity in mm/min")
-VAR(feedrate_max, fr, float, MOTORS, 1, 1, "Maxium feedrate in mm/min")
-VAR(jerk_max, jm, float, MOTORS, 1, 1, "Maxium jerk in mm/min^3")
-VAR(junction_dev, jd, float, MOTORS, 1, 1, "Junction deviation")
-VAR(radius, ra, float, MOTORS, 1, 1, "Axis radius or zero")
+VAR(axis_name, an, char, MOTORS, 1, "Maps motor to axis name")
+VAR(step_angle, sa, float, MOTORS, 1, "In degrees per full step")
+VAR(travel, tr, float, MOTORS, 1, "Travel in mm per revolution")
+VAR(microstep, mi, uint16_t, MOTORS, 1, "Microsteps per full step")
+VAR(reverse, rv, uint8_t, MOTORS, 1, "Reverse motor polarity")
+
+VAR(power_mode, pm, uint8_t, MOTORS, 1, "Motor power mode")
+VAR(max_current, xc, float, MOTORS, 1, "Max motor drive current")
+VAR(min_current, lc, float, MOTORS, 1, "Min motor drive current")
+VAR(idle_current, ic, float, MOTORS, 1, "Motor idle current")
+VAR(active_current, ac, float, MOTORS, 0, "Motor current now")
+VAR(status_flags, mf, uint8_t, MOTORS, 0, "Motor status flags")
+VAR(status_strings, ms, flags_t, MOTORS, 0, "Motor status strings")
+
+VAR(motor_fault, fa, bool, 0, 0, "Motor fault status")
+
+VAR(velocity_max, vm, float, MOTORS, 1, "Maxium velocity in mm/min")
+VAR(jerk_max, jm, float, MOTORS, 1, "Maxium jerk in mm/min^3")
+VAR(radius, ra, float, MOTORS, 1, "Axis radius or zero")
// Switches
-VAR(travel_min, tn, float, MOTORS, 1, 1, "Minimum soft limit")
-VAR(travel_max, tm, float, MOTORS, 1, 1, "Maximum soft limit")
-VAR(min_switch, ls, uint8_t, MOTORS, 1, 1, "Minimum switch mode")
-VAR(max_switch, xs, uint8_t, MOTORS, 1, 1, "Maximum switch mode")
-VAR(estop_switch, et, uint8_t, 0, 1, 1, "Estop switch mode")
-VAR(probe_switch, pt, uint8_t, 0, 1, 1, "Probe switch mode")
+VAR(travel_min, tn, float, MOTORS, 1, "Minimum soft limit")
+VAR(travel_max, tm, float, MOTORS, 1, "Maximum soft limit")
+VAR(min_switch, ls, uint8_t, MOTORS, 1, "Minimum switch mode")
+VAR(max_switch, xs, uint8_t, MOTORS, 1, "Maximum switch mode")
+VAR(estop_switch, et, uint8_t, 0, 1, "Estop switch mode")
+VAR(probe_switch, pt, uint8_t, 0, 1, "Probe switch mode")
// Homing
-VAR(homing_mode, ho, uint8_t, MOTORS, 1, 1, "Homing type")
-VAR(search_velocity,sv, float, MOTORS, 1, 1, "Homing search velocity")
-VAR(latch_velocity, lv, float, MOTORS, 1, 1, "Homing latch velocity")
-VAR(latch_backoff, lb, float, MOTORS, 1, 1, "Homing latch backoff")
-VAR(zero_backoff, zb, float, MOTORS, 1, 1, "Homing zero backoff")
+VAR(homing_mode, ho, uint8_t, MOTORS, 1, "Homing type")
+VAR(search_velocity,sv, float, MOTORS, 1, "Homing search velocity")
+VAR(latch_velocity, lv, float, MOTORS, 1, "Homing latch velocity")
+VAR(latch_backoff, lb, float, MOTORS, 1, "Homing latch backoff")
+VAR(zero_backoff, zb, float, MOTORS, 1, "Homing zero backoff")
// Axis
-VAR(position, p, float, AXES, 0, 0, "Current axis position")
+VAR(position, p, float, AXES, 0, "Current axis position")
// Spindle
-VAR(spindle_type, st, uint8_t, 0, 1, 1, "PWM=0 or HUANYANG=1")
-VAR(spin_reverse, sr, bool, 0, 1, 1, "Reverse spin")
-VAR(max_spin, sx, float, 0, 1, 1, "Maximum spindle speed")
-VAR(min_spin, sm, float, 0, 1, 1, "Minimum spindle speed")
-VAR(spin_min_pulse, np, float, 0, 1, 1, "Minimum pulse width")
-VAR(spin_max_pulse, mp, float, 0, 1, 1, "Maximum pulse width")
-VAR(spin_up, su, float, 0, 1, 1, "Spin up velocity")
-VAR(spin_down, sd, float, 0, 1, 1, "Spin down velocity")
+VAR(spindle_type, st, uint8_t, 0, 1, "PWM=0 or HUANYANG=1")
+VAR(spin_reverse, sr, bool, 0, 1, "Reverse spin")
+VAR(max_spin, sx, float, 0, 1, "Maximum spindle speed")
+VAR(min_spin, sm, float, 0, 1, "Minimum spindle speed")
+VAR(spin_min_pulse, np, float, 0, 1, "Minimum pulse width")
+VAR(spin_max_pulse, mp, float, 0, 1, "Maximum pulse width")
+VAR(spin_up, su, float, 0, 1, "Spin up velocity")
+VAR(spin_down, sd, float, 0, 1, "Spin down velocity")
+VAR(spin_freq, sf, uint16_t, 0, 1, "Spindle PWM frequency")
// Huanyang spindle
-VAR(huanyang_id, hi, uint8_t, 0, 1, 1, "Huanyang ID")
-VAR(huanyang_freq, hz, float, 0, 0, 0, "Huanyang actual freq")
-VAR(huanyang_current, hc, float, 0, 0, 0, "Huanyang actual current")
-VAR(huanyang_rpm, hr, uint16_t, 0, 0, 0, "Huanyang actual RPM")
-//VAR(huanyang_dcv, hd, uint16_t, 0, 0, 0, "Huanyang DC voltage")
-//VAR(huanyang_acv, ha, uint16_t, 0, 0, 0, "Huanyang AC voltage")
-VAR(huanyang_temp, ht, uint16_t, 0, 0, 0, "Huanyang temperature")
-VAR(huanyang_max_freq, hx, float, 0, 0, 0, "Huanyang max freq")
-VAR(huanyang_min_freq, hm, float, 0, 0, 0, "Huanyang min freq")
-VAR(huanyang_rated_rpm, hq, uint16_t, 0, 0, 0, "Huanyang rated RPM")
-VAR(huanyang_status, hs, uint8_t, 0, 0, 0, "Huanyang status flags")
-VAR(huanyang_debug, hb, bool, 0, 1, 0, "Huanyang debugging")
-VAR(huanyang_connected, he, bool, 0, 0, 0, "Huanyang connected")
+VAR(huanyang_id, hi, uint8_t, 0, 1, "Huanyang ID")
+VAR(huanyang_freq, hz, float, 0, 0, "Huanyang actual freq")
+VAR(huanyang_current, hc, float, 0, 0, "Huanyang actual current")
+VAR(huanyang_rpm, hr, uint16_t, 0, 0, "Huanyang actual RPM")
+VAR(huanyang_temp, ht, uint16_t, 0, 0, "Huanyang temperature")
+VAR(huanyang_max_freq, hx, float, 0, 0, "Huanyang max freq")
+VAR(huanyang_min_freq, hm, float, 0, 0, "Huanyang min freq")
+VAR(huanyang_rated_rpm, hq, uint16_t, 0, 0, "Huanyang rated RPM")
+VAR(huanyang_status, hs, uint8_t, 0, 0, "Huanyang status flags")
+VAR(huanyang_debug, hb, bool, 0, 1, "Huanyang debugging")
+VAR(huanyang_connected, he, bool, 0, 0, "Huanyang connected")
// GCode
-VAR(line, ln, int32_t, 0, 0, 0, "Last GCode line executed")
-VAR(unit, u, pstring, 0, 0, 0, "Current unit of measure")
-VAR(speed, s, float, 0, 0, 0, "Current spindle speed")
-VAR(feed, f, float, 0, 0, 0, "Current feed rate")
-VAR(tool, t, uint8_t, 0, 0, 0, "Current tool")
-VAR(feed_mode, fm, pstring, 0, 0, 0, "Current feed rate mode")
-VAR(plane, pa, pstring, 0, 0, 0, "Current plane")
-VAR(coord_system, cs, pstring, 0, 0, 0, "Current coordinate system")
-VAR(abs_override, ao, bool, 0, 0, 0, "Absolute override enabled")
-VAR(path_mode, pc, pstring, 0, 0, 0, "Current path control mode")
-VAR(distance_mode, dm, pstring, 0, 0, 0, "Current distance mode")
-VAR(arc_dist_mode, ad, pstring, 0, 0, 0, "Current arc distance mode")
-VAR(mist_coolant, mc, bool, 0, 0, 0, "Mist coolant enabled")
-VAR(flood_coolant, fc, bool, 0, 0, 0, "Flood coolant enabled")
-VAR(feed_override, fo, float, 0, 0, 0, "Feed rate override")
-VAR(speed_override, so, float, 0, 0, 0, "Spindle speed override")
+VAR(line, ln, int32_t, 0, 0, "Last GCode line executed")
+VAR(unit, u, pstring, 0, 0, "Current unit of measure")
+VAR(speed, s, float, 0, 0, "Current spindle speed")
+VAR(feed, f, float, 0, 0, "Current feed rate")
+VAR(tool, t, uint8_t, 0, 0, "Current tool")
+VAR(feed_mode, fm, pstring, 0, 0, "Current feed rate mode")
+VAR(plane, pa, pstring, 0, 0, "Current plane")
+VAR(coord_system, cs, pstring, 0, 0, "Current coordinate system")
+VAR(abs_override, ao, bool, 0, 0, "Absolute override enabled")
+VAR(path_mode, pc, pstring, 0, 0, "Current path control mode")
+VAR(distance_mode, dm, pstring, 0, 0, "Current distance mode")
+VAR(arc_dist_mode, ad, pstring, 0, 0, "Current arc distance mode")
+VAR(mist_coolant, mc, bool, 0, 0, "Mist coolant enabled")
+VAR(flood_coolant, fc, bool, 0, 0, "Flood coolant enabled")
+VAR(feed_override, fo, float, 0, 0, "Feed rate override")
+VAR(speed_override, so, float, 0, 0, "Spindle speed override")
// System
-VAR(velocity, v, float, 0, 0, 0, "Current velocity")
-VAR(hw_id, id, string, 0, 0, 0, "Hardware ID")
-VAR(echo, ec, bool, 0, 1, 0, "Enable or disable echo")
-VAR(estop, es, bool, 0, 1, 0, "Emergency stop")
-VAR(estop_reason, er, pstring, 0, 0, 0, "Emergency stop reason")
-VAR(state, x, pstring, 0, 0, 0, "Machine state")
-VAR(cycle, c, pstring, 0, 0, 0, "Machine cycle")
-VAR(hold_reason, pr, pstring, 0, 0, 0, "Machine pause reason")
+VAR(velocity, v, float, 0, 0, "Current velocity")
+VAR(hw_id, id, string, 0, 0, "Hardware ID")
+VAR(echo, ec, bool, 0, 1, "Enable or disable echo")
+VAR(estop, es, bool, 0, 1, "Emergency stop")
+VAR(estop_reason, er, pstring, 0, 0, "Emergency stop reason")
+VAR(state, x, pstring, 0, 0, "Machine state")
+VAR(cycle, c, pstring, 0, 0, "Machine cycle")
+VAR(hold_reason, pr, pstring, 0, 0, "Machine pause reason")
bool vars_set(const char *name, const char *value);
int vars_parser(char *vars);
void vars_print_help();
-
-void vars_save();
-bool vars_valid();
-stat_t vars_restore();
-void vars_clear();