mirror of
https://github.com/bdring/Grbl_Esp32.git
synced 2025-08-16 11:35:44 +02:00
Most #defines are gone (#595)
* Many more #defines bite the dust * Fixed botch in rt accessory logic * Update Probe.cpp * Update System.cpp * Typo
This commit is contained in:
@@ -179,7 +179,7 @@ void atari_home_task(void* pvParameters) {
|
||||
void calc_solenoid(float penZ) {
|
||||
bool isPenUp;
|
||||
static bool previousPenState = false;
|
||||
uint32_t solenoid_pen_pulse_len; // duty cycle of solenoid
|
||||
uint32_t solenoid_pen_pulse_len; // duty cycle of solenoid
|
||||
isPenUp = ((penZ > 0) || (sys.state == State::Alarm)); // is pen above Z0 or is there an alarm
|
||||
// if the state has not change, we only count down to the pull time
|
||||
if (previousPenState == isPenUp) {
|
||||
@@ -247,23 +247,17 @@ void atari_next_pen() {
|
||||
void user_defined_macro(uint8_t index) {
|
||||
char gcode_line[20];
|
||||
switch (index) {
|
||||
#ifdef MACRO_BUTTON_0_PIN
|
||||
case CONTROL_PIN_INDEX_MACRO_0:
|
||||
case 0:
|
||||
grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Pen switch");
|
||||
WebUI::inputBuffer.push("$H\r");
|
||||
break;
|
||||
#endif
|
||||
#ifdef MACRO_BUTTON_1_PIN
|
||||
case CONTROL_PIN_INDEX_MACRO_1:
|
||||
case 1:
|
||||
grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Color switch");
|
||||
atari_next_pen();
|
||||
sprintf(gcode_line, "G90G0X%3.2f\r", ATARI_PAPER_WIDTH); // alway return to right side to reduce home travel stalls
|
||||
WebUI::inputBuffer.push(gcode_line);
|
||||
break;
|
||||
#endif
|
||||
#ifdef MACRO_BUTTON_2_PIN
|
||||
case CONTROL_PIN_INDEX_MACRO_2:
|
||||
// feed out some paper and reset the Y 0
|
||||
case 2:
|
||||
grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Paper switch");
|
||||
WebUI::inputBuffer.push("G0Y-25\r");
|
||||
WebUI::inputBuffer.push("G4P0.1\r"); // sync...forces wait for planner to clear
|
||||
@@ -271,9 +265,7 @@ void user_defined_macro(uint8_t index) {
|
||||
gc_sync_position();
|
||||
plan_sync_position();
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Unknown Switch %d", index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@@ -223,25 +223,15 @@ float abs_angle(float ang) {
|
||||
// Polar coaster has macro buttons, this handles those button pushes.
|
||||
void user_defined_macro(uint8_t index) {
|
||||
switch (index) {
|
||||
#ifdef MACRO_BUTTON_0_PIN
|
||||
case CONTROL_PIN_INDEX_MACRO_0:
|
||||
case 0:
|
||||
WebUI::inputBuffer.push("$H\r"); // home machine
|
||||
break;
|
||||
#endif
|
||||
#ifdef MACRO_BUTTON_1_PIN
|
||||
case CONTROL_PIN_INDEX_MACRO_1:
|
||||
case 1:
|
||||
WebUI::inputBuffer.push("[ESP220]/1.nc\r"); // run SD card file 1.nc
|
||||
break;
|
||||
#endif
|
||||
#ifdef MACRO_BUTTON_2_PIN
|
||||
case CONTROL_PIN_INDEX_MACRO_2:
|
||||
case 2:
|
||||
WebUI::inputBuffer.push("[ESP220]/2.nc\r"); // run SD card file 2.nc
|
||||
break;
|
||||
#endif
|
||||
#ifdef MACRO_BUTTON_3_PIN
|
||||
case CONTROL_PIN_INDEX_MACRO_3:
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@@ -167,40 +167,37 @@ const int DEFAULT_RADIO_MODE = ESP_RADIO_OFF;
|
||||
// GCode programs, maybe selected for interface programs.
|
||||
// NOTE: If changed, manually update help message in report.c.
|
||||
|
||||
const uint8_t CMD_RESET = 0x18; // ctrl-x.
|
||||
const uint8_t CMD_STATUS_REPORT = '?';
|
||||
const uint8_t CMD_CYCLE_START = '~';
|
||||
const uint8_t CMD_FEED_HOLD = '!';
|
||||
|
||||
// NOTE: All override realtime commands must be in the extended ASCII character set, starting
|
||||
// at character value 128 (0x80) and up to 255 (0xFF). If the normal set of realtime commands,
|
||||
// such as status reports, feed hold, reset, and cycle start, are moved to the extended set
|
||||
// space, serial.c's RX ISR will need to be modified to accommodate the change.
|
||||
|
||||
// const uint8_t CMD_RESET = 0x80;
|
||||
// const uint8_t CMD_STATUS_REPORT = 0x81;
|
||||
// const uint8_t CMD_CYCLE_START = 0x82;
|
||||
// const uint8_t CMD_FEED_HOLD = 0x83;
|
||||
const uint8_t CMD_SAFETY_DOOR = 0x84;
|
||||
const uint8_t CMD_JOG_CANCEL = 0x85;
|
||||
const uint8_t CMD_DEBUG_REPORT = 0x86; // Only when DEBUG enabled, sends debug report in '{}' braces.
|
||||
const uint8_t CMD_FEED_OVR_RESET = 0x90; // Restores feed override value to 100%.
|
||||
const uint8_t CMD_FEED_OVR_COARSE_PLUS = 0x91;
|
||||
const uint8_t CMD_FEED_OVR_COARSE_MINUS = 0x92;
|
||||
const uint8_t CMD_FEED_OVR_FINE_PLUS = 0x93;
|
||||
const uint8_t CMD_FEED_OVR_FINE_MINUS = 0x94;
|
||||
const uint8_t CMD_RAPID_OVR_RESET = 0x95; // Restores rapid override value to 100%.
|
||||
const uint8_t CMD_RAPID_OVR_MEDIUM = 0x96;
|
||||
const uint8_t CMD_RAPID_OVR_LOW = 0x97;
|
||||
// const uint8_t CMD_RAPID_OVR_EXTRA_LOW = 0x98; // *NOT SUPPORTED*
|
||||
const uint8_t CMD_SPINDLE_OVR_RESET = 0x99; // Restores spindle override value to 100%.
|
||||
const uint8_t CMD_SPINDLE_OVR_COARSE_PLUS = 0x9A; // 154
|
||||
const uint8_t CMD_SPINDLE_OVR_COARSE_MINUS = 0x9B;
|
||||
const uint8_t CMD_SPINDLE_OVR_FINE_PLUS = 0x9C;
|
||||
const uint8_t CMD_SPINDLE_OVR_FINE_MINUS = 0x9D;
|
||||
const uint8_t CMD_SPINDLE_OVR_STOP = 0x9E;
|
||||
const uint8_t CMD_COOLANT_FLOOD_OVR_TOGGLE = 0xA0;
|
||||
const uint8_t CMD_COOLANT_MIST_OVR_TOGGLE = 0xA1;
|
||||
enum class Cmd : uint8_t {
|
||||
Reset = 0x18, // Ctrl-X
|
||||
StatusReport = '?',
|
||||
CycleStart = '~',
|
||||
FeedHold = '!',
|
||||
SafetyDoor = 0x84,
|
||||
JogCancel = 0x85,
|
||||
DebugReport = 0x86, // Only when DEBUG enabled, sends debug report in '{}' braces.
|
||||
FeedOvrReset = 0x90, // Restores feed override value to 100%.
|
||||
FeedOvrCoarsePlus = 0x91,
|
||||
FeedOvrCoarseMinus = 0x92,
|
||||
FeedOvrFinePlus = 0x93,
|
||||
FeedOvrFineMinus = 0x94,
|
||||
RapidOvrReset = 0x95, // Restores rapid override value to 100%.
|
||||
RapidOvrMedium = 0x96,
|
||||
RapidOvrLow = 0x97,
|
||||
RapidOvrExtraLow = 0x98, // *NOT SUPPORTED*
|
||||
SpindleOvrReset = 0x99, // Restores spindle override value to 100%.
|
||||
SpindleOvrCoarsePlus = 0x9A, // 154
|
||||
SpindleOvrCoarseMinus = 0x9B,
|
||||
SpindleOvrFinePlus = 0x9C,
|
||||
SpindleOvrFineMinus = 0x9D,
|
||||
SpindleOvrStop = 0x9E,
|
||||
CoolantFloodOvrToggle = 0xA0,
|
||||
CoolantMistOvrToggle = 0xA1,
|
||||
};
|
||||
|
||||
// If homing is enabled, homing init lock sets Grbl into an alarm state upon power up. This forces
|
||||
// the user to perform the homing cycle (or override the locks) before doing anything else. This is
|
||||
@@ -309,22 +306,27 @@ const double SAFETY_DOOR_COOLANT_DELAY = 1.0; // Float (seconds)
|
||||
// Configure rapid, feed, and spindle override settings. These values define the max and min
|
||||
// allowable override values and the coarse and fine increments per command received. Please
|
||||
// note the allowable values in the descriptions following each define.
|
||||
const int DEFAULT_FEED_OVERRIDE = 100; // 100%. Don't change this value.
|
||||
const int MAX_FEED_RATE_OVERRIDE = 200; // Percent of programmed feed rate (100-255). Usually 120% or 200%
|
||||
const int MIN_FEED_RATE_OVERRIDE = 10; // Percent of programmed feed rate (1-100). Usually 50% or 1%
|
||||
const int FEED_OVERRIDE_COARSE_INCREMENT = 10; // (1-99). Usually 10%.
|
||||
const int FEED_OVERRIDE_FINE_INCREMENT = 1; // (1-99). Usually 1%.
|
||||
namespace FeedOverride {
|
||||
const int Default = 100; // 100%. Don't change this value.
|
||||
const int Max = 200; // Percent of programmed feed rate (100-255). Usually 120% or 200%
|
||||
const int Min = 10; // Percent of programmed feed rate (1-100). Usually 50% or 1%
|
||||
const int CoarseIncrement = 10; // (1-99). Usually 10%.
|
||||
const int FineIncrement = 1; // (1-99). Usually 1%.
|
||||
};
|
||||
namespace RapidOverride {
|
||||
const int Default = 100; // 100%. Don't change this value.
|
||||
const int Medium = 50; // Percent of rapid (1-99). Usually 50%.
|
||||
const int Low = 25; // Percent of rapid (1-99). Usually 25%.
|
||||
const int ExtraLow = 5; // Percent of rapid (1-99). Usually 5%. Not Supported
|
||||
};
|
||||
|
||||
const int DEFAULT_RAPID_OVERRIDE = 100; // 100%. Don't change this value.
|
||||
const int RAPID_OVERRIDE_MEDIUM = 50; // Percent of rapid (1-99). Usually 50%.
|
||||
const int RAPID_OVERRIDE_LOW = 25; // Percent of rapid (1-99). Usually 25%.
|
||||
// const int RAPID_OVERRIDE_EXTRA_LOW = 5; // *NOT SUPPORTED* Percent of rapid (1-99). Usually 5%.
|
||||
|
||||
const int DEFAULT_SPINDLE_SPEED_OVERRIDE = 100; // 100%. Don't change this value.
|
||||
const int MAX_SPINDLE_SPEED_OVERRIDE = 200; // Percent of programmed spindle speed (100-255). Usually 200%.
|
||||
const int MIN_SPINDLE_SPEED_OVERRIDE = 10; // Percent of programmed spindle speed (1-100). Usually 10%.
|
||||
const int SPINDLE_OVERRIDE_COARSE_INCREMENT = 10; // (1-99). Usually 10%.
|
||||
const int SPINDLE_OVERRIDE_FINE_INCREMENT = 1; // (1-99). Usually 1%.
|
||||
namespace SpindleSpeedOverride {
|
||||
const int Default = 100; // 100%. Don't change this value.
|
||||
const int Max = 200; // Percent of programmed spindle speed (100-255). Usually 200%.
|
||||
const int Min = 10; // Percent of programmed spindle speed (1-100). Usually 10%.
|
||||
const int CoarseIncrement = 10; // (1-99). Usually 10%.
|
||||
const int FineIncrement = 1; // (1-99). Usually 1%.
|
||||
}
|
||||
|
||||
// When a M2 or M30 program end command is executed, most GCode states are restored to their defaults.
|
||||
// This compile-time option includes the restoring of the feed, rapid, and spindle speed override values
|
||||
|
@@ -1565,8 +1565,8 @@ Error gc_execute_line(char* line, uint8_t client) {
|
||||
case ProgramFlow::Paused:
|
||||
protocol_buffer_synchronize(); // Sync and finish all remaining buffered motions before moving on.
|
||||
if (sys.state != State::CheckMode) {
|
||||
system_set_exec_state_flag(EXEC_FEED_HOLD); // Use feed hold for program pause.
|
||||
protocol_execute_realtime(); // Execute suspend.
|
||||
sys_rt_exec_state.bit.feedHold = true; // Use feed hold for program pause.
|
||||
protocol_execute_realtime(); // Execute suspend.
|
||||
}
|
||||
break;
|
||||
case ProgramFlow::CompletedM2:
|
||||
@@ -1594,9 +1594,9 @@ Error gc_execute_line(char* line, uint8_t client) {
|
||||
#endif
|
||||
// gc_state.modal.override = OVERRIDE_DISABLE; // Not supported.
|
||||
#ifdef RESTORE_OVERRIDES_AFTER_PROGRAM_END
|
||||
sys.f_override = DEFAULT_FEED_OVERRIDE;
|
||||
sys.r_override = DEFAULT_RAPID_OVERRIDE;
|
||||
sys.spindle_speed_ovr = DEFAULT_SPINDLE_SPEED_OVERRIDE;
|
||||
sys.f_override = FeedOverride::Default;
|
||||
sys.r_override = RapidOverride::Default;
|
||||
sys.spindle_speed_ovr = SpindleSpeedOverride::Default;
|
||||
#endif
|
||||
// Execute coordinate change and spindle/coolant stop.
|
||||
if (sys.state != State::CheckMode) {
|
||||
|
@@ -163,15 +163,6 @@ struct CoolantState {
|
||||
|
||||
// Modal Group M8: Coolant control
|
||||
// Modal Group M9: Override control
|
||||
enum class Override : uint8_t {
|
||||
#ifdef DEACTIVATE_PARKING_UPON_INIT
|
||||
Disabled = 0, // (Default: Must be zero)
|
||||
ParkingMotion = 1, // M56
|
||||
#else
|
||||
ParkingMotion = 0, // M56 (Default: Must be zero)
|
||||
Disabled = 1, // Parking disabled.
|
||||
#endif
|
||||
};
|
||||
|
||||
// Modal Group M10: User I/O control
|
||||
enum class IoControl : uint8_t {
|
||||
|
@@ -80,16 +80,20 @@ static void reset_variables() {
|
||||
State prior_state = sys.state;
|
||||
memset(&sys, 0, sizeof(system_t)); // Clear system struct variable.
|
||||
sys.state = prior_state;
|
||||
sys.f_override = DEFAULT_FEED_OVERRIDE; // Set to 100%
|
||||
sys.r_override = DEFAULT_RAPID_OVERRIDE; // Set to 100%
|
||||
sys.spindle_speed_ovr = DEFAULT_SPINDLE_SPEED_OVERRIDE; // Set to 100%
|
||||
sys.f_override = FeedOverride::Default; // Set to 100%
|
||||
sys.r_override = RapidOverride::Default; // Set to 100%
|
||||
sys.spindle_speed_ovr = SpindleSpeedOverride::Default; // Set to 100%
|
||||
memset(sys_probe_position, 0, sizeof(sys_probe_position)); // Clear probe position.
|
||||
sys_probe_state = 0;
|
||||
sys_rt_exec_state = 0;
|
||||
cycle_stop = false;
|
||||
sys_rt_exec_motion_override = 0;
|
||||
sys_rt_exec_accessory_override = 0;
|
||||
system_clear_exec_alarm();
|
||||
|
||||
sys_probe_state = Probe::Off;
|
||||
sys_rt_exec_state.value = 0;
|
||||
sys_rt_exec_accessory_override.value = 0;
|
||||
sys_rt_exec_alarm = ExecAlarm::None;
|
||||
cycle_stop = false;
|
||||
sys_rt_f_override = FeedOverride::Default;
|
||||
sys_rt_r_override = RapidOverride::Default;
|
||||
sys_rt_s_override = SpindleSpeedOverride::Default;
|
||||
|
||||
// Reset Grbl primary systems.
|
||||
serial_reset_read_buffer(CLIENT_ALL); // Clear serial read buffer
|
||||
gc_init(); // Set g-code parser to default state
|
||||
|
@@ -44,6 +44,7 @@ const char* const GRBL_VERSION_BUILD = "20201004";
|
||||
#include "Eeprom.h"
|
||||
#include "WebUI/Authentication.h"
|
||||
#include "WebUI/Commands.h"
|
||||
#include "Probe.h"
|
||||
#include "System.h"
|
||||
|
||||
#include "GCode.h"
|
||||
@@ -51,7 +52,6 @@ const char* const GRBL_VERSION_BUILD = "20201004";
|
||||
#include "CoolantControl.h"
|
||||
#include "Limits.h"
|
||||
#include "MotionControl.h"
|
||||
#include "Probe.h"
|
||||
#include "Protocol.h"
|
||||
#include "Report.h"
|
||||
#include "Serial.h"
|
||||
|
@@ -55,12 +55,12 @@ void IRAM_ATTR isr_limit_switches() {
|
||||
# ifdef HARD_LIMIT_FORCE_STATE_CHECK
|
||||
// Check limit pin state.
|
||||
if (limits_get_state()) {
|
||||
mc_reset(); // Initiate system kill.
|
||||
system_set_exec_alarm(ExecAlarm::HardLimit); // Indicate hard limit critical event
|
||||
mc_reset(); // Initiate system kill.
|
||||
sys_rt_exec_alarm = ExecAlarm::HardLimit; // Indicate hard limit critical event
|
||||
}
|
||||
# else
|
||||
mc_reset(); // Initiate system kill.
|
||||
system_set_exec_alarm(ExecAlarm::HardLimit); // Indicate hard limit critical event
|
||||
mc_reset(); // Initiate system kill.
|
||||
sys_rt_exec_alarm = ExecAlarm::HardLimit; // Indicate hard limit critical event
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
@@ -125,9 +125,10 @@ void limits_go_home(uint8_t cycle_mask) {
|
||||
}
|
||||
}
|
||||
// Set search mode with approach at seek rate to quickly engage the specified cycle_mask limit switches.
|
||||
bool approach = true;
|
||||
float homing_rate = homing_seek_rate->get();
|
||||
uint8_t limit_state, axislock, n_active_axis;
|
||||
bool approach = true;
|
||||
float homing_rate = homing_seek_rate->get();
|
||||
uint8_t n_active_axis;
|
||||
AxisMask limit_state, axislock;
|
||||
do {
|
||||
system_convert_array_steps_to_mpos(target, sys_position);
|
||||
// Initialize and declare variables needed for homing routine.
|
||||
@@ -174,11 +175,12 @@ void limits_go_home(uint8_t cycle_mask) {
|
||||
homing_rate *= sqrt(n_active_axis); // [sqrt(number of active axis)] Adjust so individual axes all move at homing rate.
|
||||
sys.homing_axis_lock = axislock;
|
||||
// Perform homing cycle. Planner buffer should be empty, as required to initiate the homing cycle.
|
||||
pl_data->feed_rate = homing_rate; // Set current homing rate.
|
||||
plan_buffer_line(target, pl_data); // Bypass mc_line(). Directly plan homing motion.
|
||||
sys.step_control = STEP_CONTROL_EXECUTE_SYS_MOTION; // Set to execute homing motion and clear existing flags.
|
||||
st_prep_buffer(); // Prep and fill segment buffer from newly planned block.
|
||||
st_wake_up(); // Initiate motion
|
||||
pl_data->feed_rate = homing_rate; // Set current homing rate.
|
||||
plan_buffer_line(target, pl_data); // Bypass mc_line(). Directly plan homing motion.
|
||||
sys.step_control = {};
|
||||
sys.step_control.executeSysMotion = true; // Set to execute homing motion and clear existing flags.
|
||||
st_prep_buffer(); // Prep and fill segment buffer from newly planned block.
|
||||
st_wake_up(); // Initiate motion
|
||||
do {
|
||||
if (approach) {
|
||||
// Check limit state. Lock out cycle axes when they change.
|
||||
@@ -202,23 +204,24 @@ void limits_go_home(uint8_t cycle_mask) {
|
||||
}
|
||||
st_prep_buffer(); // Check and prep segment buffer. NOTE: Should take no longer than 200us.
|
||||
// Exit routines: No time to run protocol_execute_realtime() in this loop.
|
||||
if ((sys_rt_exec_state & (EXEC_SAFETY_DOOR | EXEC_RESET)) || cycle_stop) {
|
||||
uint8_t rt_exec = sys_rt_exec_state;
|
||||
if (sys_rt_exec_state.bit.safetyDoor || sys_rt_exec_state.bit.reset || cycle_stop) {
|
||||
ExecState rt_exec_state;
|
||||
rt_exec_state.value = sys_rt_exec_state.value;
|
||||
// Homing failure condition: Reset issued during cycle.
|
||||
if (rt_exec & EXEC_RESET) {
|
||||
system_set_exec_alarm(ExecAlarm::HomingFailReset);
|
||||
if (rt_exec_state.bit.reset) {
|
||||
sys_rt_exec_alarm = ExecAlarm::HomingFailReset;
|
||||
}
|
||||
// Homing failure condition: Safety door was opened.
|
||||
if (rt_exec & EXEC_SAFETY_DOOR) {
|
||||
system_set_exec_alarm(ExecAlarm::HomingFailDoor);
|
||||
if (rt_exec_state.bit.safetyDoor) {
|
||||
sys_rt_exec_alarm = ExecAlarm::HomingFailDoor;
|
||||
}
|
||||
// Homing failure condition: Limit switch still engaged after pull-off motion
|
||||
if (!approach && (limits_get_state() & cycle_mask)) {
|
||||
system_set_exec_alarm(ExecAlarm::HomingFailPulloff);
|
||||
sys_rt_exec_alarm = ExecAlarm::HomingFailPulloff;
|
||||
}
|
||||
// Homing failure condition: Limit switch not found during approach.
|
||||
if (approach && cycle_stop) {
|
||||
system_set_exec_alarm(ExecAlarm::HomingFailApproach);
|
||||
sys_rt_exec_alarm = ExecAlarm::HomingFailApproach;
|
||||
}
|
||||
|
||||
if (sys_rt_exec_alarm != ExecAlarm::None) {
|
||||
@@ -303,7 +306,7 @@ void limits_go_home(uint8_t cycle_mask) {
|
||||
#endif
|
||||
}
|
||||
}
|
||||
sys.step_control = STEP_CONTROL_NORMAL_OP; // Return step control to normal operation.
|
||||
sys.step_control = {}; // Return step control to normal operation.
|
||||
motors_set_homing_mode(cycle_mask, false); // tell motors homing is done
|
||||
}
|
||||
|
||||
@@ -371,8 +374,8 @@ void limits_disable() {
|
||||
// Returns limit state as a bit-wise uint8 variable. Each bit indicates an axis limit, where
|
||||
// triggered is 1 and not triggered is 0. Invert mask is applied. Axes are defined by their
|
||||
// number in bit position, i.e. Z_AXIS is bit(2), and Y_AXIS is bit(1).
|
||||
uint8_t limits_get_state() {
|
||||
uint8_t pinMask = 0;
|
||||
AxisMask limits_get_state() {
|
||||
AxisMask pinMask = 0;
|
||||
auto n_axis = number_axis->get();
|
||||
for (int axis = 0; axis < n_axis; axis++) {
|
||||
for (int gang_index = 0; gang_index < 2; gang_index++) {
|
||||
@@ -402,7 +405,7 @@ void limits_soft_check(float* target) {
|
||||
// workspace volume so just come to a controlled stop so position is not lost. When complete
|
||||
// enter alarm mode.
|
||||
if (sys.state == State::Cycle) {
|
||||
system_set_exec_state_flag(EXEC_FEED_HOLD);
|
||||
sys_rt_exec_state.bit.feedHold = true;
|
||||
do {
|
||||
protocol_execute_realtime();
|
||||
if (sys.abort) {
|
||||
@@ -410,9 +413,9 @@ void limits_soft_check(float* target) {
|
||||
}
|
||||
} while (sys.state != State::Idle);
|
||||
}
|
||||
mc_reset(); // Issue system reset and ensure spindle and coolant are shutdown.
|
||||
system_set_exec_alarm(ExecAlarm::SoftLimit); // Indicate soft limit critical event
|
||||
protocol_execute_realtime(); // Execute to enter critical event loop and system abort
|
||||
mc_reset(); // Issue system reset and ensure spindle and coolant are shutdown.
|
||||
sys_rt_exec_alarm = ExecAlarm::SoftLimit; // Indicate soft limit critical event
|
||||
protocol_execute_realtime(); // Execute to enter critical event loop and system abort
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -423,12 +426,12 @@ void limitCheckTask(void* pvParameters) {
|
||||
int evt;
|
||||
xQueueReceive(limit_sw_queue, &evt, portMAX_DELAY); // block until receive queue
|
||||
vTaskDelay(DEBOUNCE_PERIOD / portTICK_PERIOD_MS); // delay a while
|
||||
uint8_t switch_state;
|
||||
AxisMask switch_state;
|
||||
switch_state = limits_get_state();
|
||||
if (switch_state) {
|
||||
//grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Limit Switch State %08d", switch_state);
|
||||
mc_reset(); // Initiate system kill.
|
||||
system_set_exec_alarm(ExecAlarm::HardLimit); // Indicate hard limit critical event
|
||||
mc_reset(); // Initiate system kill.
|
||||
sys_rt_exec_alarm = ExecAlarm::HardLimit; // Indicate hard limit critical event
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -36,7 +36,7 @@ void limits_init();
|
||||
void limits_disable();
|
||||
|
||||
// Returns limit state as a bit-wise uint8 variable.
|
||||
uint8_t limits_get_state();
|
||||
AxisMask limits_get_state();
|
||||
|
||||
// Perform one portion of the homing cycle based on the input settings.
|
||||
void limits_go_home(uint8_t cycle_mask);
|
||||
|
@@ -283,7 +283,7 @@ void mc_homing_cycle(uint8_t cycle_mask) {
|
||||
#ifdef LIMITS_TWO_SWITCHES_ON_AXES
|
||||
if (limits_get_state()) {
|
||||
mc_reset(); // Issue system reset and ensure spindle and coolant are shutdown.
|
||||
system_set_exec_alarm(ExecAlarm::HardLimit);
|
||||
sys_rt_exec_alarm = ExecAlarm::HardLimit;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -379,16 +379,16 @@ GCUpdatePos mc_probe_cycle(float* target, plan_line_data_t* pl_data, uint8_t par
|
||||
// After syncing, check if probe is already triggered. If so, halt and issue alarm.
|
||||
// NOTE: This probe initialization error applies to all probing cycles.
|
||||
if (probe_get_state() ^ is_probe_away) { // Check probe pin state.
|
||||
system_set_exec_alarm(ExecAlarm::ProbeFailInitial);
|
||||
sys_rt_exec_alarm = ExecAlarm::ProbeFailInitial;
|
||||
protocol_execute_realtime();
|
||||
return GCUpdatePos::None; // Nothing else to do but bail.
|
||||
}
|
||||
// Setup and queue probing motion. Auto cycle-start should not start the cycle.
|
||||
mc_line(target, pl_data);
|
||||
// Activate the probing state monitor in the stepper module.
|
||||
sys_probe_state = PROBE_ACTIVE;
|
||||
sys_probe_state = Probe::Active;
|
||||
// Perform probing cycle. Wait here until probe is triggered or motion completes.
|
||||
system_set_exec_state_flag(EXEC_CYCLE_START);
|
||||
sys_rt_exec_state.bit.cycleStart = true;
|
||||
do {
|
||||
protocol_execute_realtime();
|
||||
if (sys.abort) {
|
||||
@@ -397,17 +397,17 @@ GCUpdatePos mc_probe_cycle(float* target, plan_line_data_t* pl_data, uint8_t par
|
||||
} while (sys.state != State::Idle);
|
||||
// Probing cycle complete!
|
||||
// Set state variables and error out, if the probe failed and cycle with error is enabled.
|
||||
if (sys_probe_state == PROBE_ACTIVE) {
|
||||
if (sys_probe_state == Probe::Active) {
|
||||
if (is_no_error) {
|
||||
memcpy(sys_probe_position, sys_position, sizeof(sys_position));
|
||||
} else {
|
||||
system_set_exec_alarm(ExecAlarm::ProbeFailContact);
|
||||
sys_rt_exec_alarm = ExecAlarm::ProbeFailContact;
|
||||
}
|
||||
} else {
|
||||
sys.probe_succeeded = true; // Indicate to system the probing cycle completed successfully.
|
||||
}
|
||||
sys_probe_state = PROBE_OFF; // Ensure probe state monitor is disabled.
|
||||
protocol_execute_realtime(); // Check and execute run-time commands
|
||||
sys_probe_state = Probe::Off; // Ensure probe state monitor is disabled.
|
||||
protocol_execute_realtime(); // Check and execute run-time commands
|
||||
// Reset the stepper and planner buffers to remove the remainder of the probe motion.
|
||||
st_reset(); // Reset step segment buffer.
|
||||
plan_reset(); // Reset planner buffer. Zero planner positions. Ensure probing motion is cleared.
|
||||
@@ -431,9 +431,9 @@ void mc_parking_motion(float* parking_target, plan_line_data_t* pl_data) {
|
||||
}
|
||||
uint8_t plan_status = plan_buffer_line(parking_target, pl_data);
|
||||
if (plan_status) {
|
||||
bit_true(sys.step_control, STEP_CONTROL_EXECUTE_SYS_MOTION);
|
||||
bit_false(sys.step_control, STEP_CONTROL_END_MOTION); // Allow parking motion to execute, if feed hold is active.
|
||||
st_parking_setup_buffer(); // Setup step segment buffer for special parking motion case
|
||||
sys.step_control.executeSysMotion = true;
|
||||
sys.step_control.endMotion = false; // Allow parking motion to execute, if feed hold is active.
|
||||
st_parking_setup_buffer(); // Setup step segment buffer for special parking motion case
|
||||
st_prep_buffer();
|
||||
st_wake_up();
|
||||
do {
|
||||
@@ -441,10 +441,10 @@ void mc_parking_motion(float* parking_target, plan_line_data_t* pl_data) {
|
||||
if (sys.abort) {
|
||||
return;
|
||||
}
|
||||
} while (sys.step_control & STEP_CONTROL_EXECUTE_SYS_MOTION);
|
||||
} while (sys.step_control.executeSysMotion);
|
||||
st_parking_restore_buffer(); // Restore step segment buffer to normal run state.
|
||||
} else {
|
||||
bit_false(sys.step_control, STEP_CONTROL_EXECUTE_SYS_MOTION);
|
||||
sys.step_control.executeSysMotion = false;
|
||||
protocol_exec_rt_system();
|
||||
}
|
||||
}
|
||||
@@ -467,8 +467,8 @@ void mc_override_ctrl_update(uint8_t override_state) {
|
||||
// realtime abort command and hard limits. So, keep to a minimum.
|
||||
void mc_reset() {
|
||||
// Only this function can set the system reset. Helps prevent multiple kill calls.
|
||||
if (bit_isfalse(sys_rt_exec_state, EXEC_RESET)) {
|
||||
system_set_exec_state_flag(EXEC_RESET);
|
||||
if (!sys_rt_exec_state.bit.reset) {
|
||||
sys_rt_exec_state.bit.reset = true;
|
||||
// Kill spindle and coolant.
|
||||
spindle->stop();
|
||||
coolant_stop();
|
||||
@@ -489,13 +489,13 @@ void mc_reset() {
|
||||
// the steppers enabled by avoiding the go_idle call altogether, unless the motion state is
|
||||
// violated, by which, all bets are off.
|
||||
if ((sys.state == State::Cycle || sys.state == State::Homing || sys.state == State::Jog) ||
|
||||
(sys.step_control & (STEP_CONTROL_EXECUTE_HOLD | STEP_CONTROL_EXECUTE_SYS_MOTION))) {
|
||||
(sys.step_control.executeHold || sys.step_control.executeSysMotion)) {
|
||||
if (sys.state == State::Homing) {
|
||||
if (sys_rt_exec_alarm == ExecAlarm::None) {
|
||||
system_set_exec_alarm(ExecAlarm::HomingFailReset);
|
||||
sys_rt_exec_alarm = ExecAlarm::HomingFailReset;
|
||||
}
|
||||
} else {
|
||||
system_set_exec_alarm(ExecAlarm::AbortCycle);
|
||||
sys_rt_exec_alarm = ExecAlarm::AbortCycle;
|
||||
}
|
||||
st_go_idle(); // Force kill steppers. Position has likely been lost.
|
||||
}
|
||||
|
@@ -123,7 +123,7 @@ void delay_sec(float seconds, uint8_t mode) {
|
||||
} else { // DELAY_MODE_SYS_SUSPEND
|
||||
// Execute rt_system() only to avoid nesting suspend loops.
|
||||
protocol_exec_rt_system();
|
||||
if (sys.suspend & SUSPEND_RESTART_RETRACT) {
|
||||
if (sys.suspend.bit.restartRetract) {
|
||||
return; // Bail, if safety door reopens.
|
||||
}
|
||||
}
|
||||
|
@@ -58,8 +58,8 @@ bool probe_get_state() {
|
||||
// NOTE: This function must be extremely efficient as to not bog down the stepper ISR.
|
||||
void probe_state_monitor() {
|
||||
if (probe_get_state() ^ is_probe_away) {
|
||||
sys_probe_state = PROBE_OFF;
|
||||
sys_probe_state = Probe::Off;
|
||||
memcpy(sys_probe_position, sys_position, sizeof(sys_position));
|
||||
bit_true(sys_rt_exec_state, EXEC_MOTION_CANCEL);
|
||||
sys_rt_exec_state.bit.motionCancel = true;
|
||||
}
|
||||
}
|
||||
|
@@ -24,8 +24,10 @@
|
||||
*/
|
||||
|
||||
// Values that define the probing state machine.
|
||||
const int PROBE_OFF = 0; // Probing disabled or not in use. (Must be zero.)
|
||||
const int PROBE_ACTIVE = 1; // Actively watching the input pin.
|
||||
enum class Probe : uint8_t {
|
||||
Off = 0, // Probing disabled or not in use. (Must be zero.)
|
||||
Active = 1, // Actively watching the input pin.
|
||||
};
|
||||
|
||||
// Probe pin initialization routine.
|
||||
void probe_init();
|
||||
|
@@ -267,7 +267,7 @@ Error home_c(const char* value, WebUI::AuthenticationLevel auth_level, WebUI::ES
|
||||
return home(bit(C_AXIS));
|
||||
}
|
||||
Error sleep_grbl(const char* value, WebUI::AuthenticationLevel auth_level, WebUI::ESPResponseStream* out) {
|
||||
system_set_exec_state_flag(EXEC_SLEEP);
|
||||
sys_rt_exec_state.bit.sleep = true;
|
||||
return Error::Ok;
|
||||
}
|
||||
Error get_report_build_info(const char* value, WebUI::AuthenticationLevel auth_level, WebUI::ESPResponseStream* out) {
|
||||
|
@@ -94,7 +94,7 @@ Error execute_line(char* line, uint8_t client, WebUI::AuthenticationLevel auth_l
|
||||
bool can_park() {
|
||||
return
|
||||
#ifdef ENABLE_PARKING_OVERRIDE_CONTROL
|
||||
sys.override_ctrl == OVERRIDE_PARKING_MOTION &&
|
||||
sys.override_ctrl == Override::ParkingMotion &&
|
||||
#endif
|
||||
homing_enable->get() && !laser_mode->get();
|
||||
}
|
||||
@@ -125,7 +125,7 @@ void protocol_main_loop() {
|
||||
// Check if the safety door is open.
|
||||
sys.state = State::Idle;
|
||||
if (system_check_safety_door_ajar()) {
|
||||
bit_true(sys_rt_exec_state, EXEC_SAFETY_DOOR);
|
||||
sys_rt_exec_state.bit.safetyDoor = true;
|
||||
protocol_execute_realtime(); // Enter safety door mode. Should return as IDLE state.
|
||||
}
|
||||
// All systems go!
|
||||
@@ -222,8 +222,8 @@ void protocol_buffer_synchronize() {
|
||||
// is finished, single commands), a command that needs to wait for the motions in the buffer to
|
||||
// execute calls a buffer sync, or the planner buffer is full and ready to go.
|
||||
void protocol_auto_cycle_start() {
|
||||
if (plan_get_current_block() != NULL) { // Check if there are any blocks in the buffer.
|
||||
system_set_exec_state_flag(EXEC_CYCLE_START); // If so, execute them!
|
||||
if (plan_get_current_block() != NULL) { // Check if there are any blocks in the buffer.
|
||||
sys_rt_exec_state.bit.cycleStart = true; // If so, execute them!
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,11 +236,11 @@ void protocol_auto_cycle_start() {
|
||||
// handles them, removing the need to define more computationally-expensive volatile variables. This
|
||||
// also provides a controlled way to execute certain tasks without having two or more instances of
|
||||
// the same task, such as the planner recalculating the buffer upon a feedhold or overrides.
|
||||
// NOTE: The sys_rt_exec_state variable flags are set by any process, step or serial interrupts, pinouts,
|
||||
// NOTE: The sys_rt_exec_state.bit variable flags are set by any process, step or serial interrupts, pinouts,
|
||||
// limit switches, or the main program.
|
||||
void protocol_execute_realtime() {
|
||||
protocol_exec_rt_system();
|
||||
if (sys.suspend) {
|
||||
if (sys.suspend.value) {
|
||||
protocol_exec_rt_suspend();
|
||||
}
|
||||
}
|
||||
@@ -259,145 +259,156 @@ void protocol_exec_rt_system() {
|
||||
// Halt everything upon a critical event flag. Currently hard and soft limits flag this.
|
||||
if ((alarm == ExecAlarm::HardLimit) || (alarm == ExecAlarm::SoftLimit)) {
|
||||
report_feedback_message(Message::CriticalEvent);
|
||||
system_clear_exec_state_flag(EXEC_RESET); // Disable any existing reset
|
||||
sys_rt_exec_state.bit.reset = false; // Disable any existing reset
|
||||
do {
|
||||
// Block everything, except reset and status reports, until user issues reset or power
|
||||
// cycles. Hard limits typically occur while unattended or not paying attention. Gives
|
||||
// the user and a GUI time to do what is needed before resetting, like killing the
|
||||
// incoming stream. The same could be said about soft limits. While the position is not
|
||||
// lost, continued streaming could cause a serious crash if by chance it gets executed.
|
||||
} while (bit_isfalse(sys_rt_exec_state, EXEC_RESET));
|
||||
} while (!sys_rt_exec_state.bit.reset);
|
||||
}
|
||||
system_clear_exec_alarm(); // Clear alarm
|
||||
sys_rt_exec_alarm = ExecAlarm::None;
|
||||
}
|
||||
uint8_t rt_exec = sys_rt_exec_state; // Copy volatile sys_rt_exec_state.
|
||||
if (rt_exec || cycle_stop) {
|
||||
ExecState rt_exec_state;
|
||||
rt_exec_state.value = sys_rt_exec_state.value; // Copy volatile sys_rt_exec_state.
|
||||
if (rt_exec_state.value != 0 || cycle_stop) { // Test if any bits are on
|
||||
// Execute system abort.
|
||||
if (rt_exec & EXEC_RESET) {
|
||||
if (rt_exec_state.bit.reset) {
|
||||
sys.abort = true; // Only place this is set true.
|
||||
return; // Nothing else to do but exit.
|
||||
}
|
||||
// Execute and serial print status
|
||||
if (rt_exec & EXEC_STATUS_REPORT) {
|
||||
if (rt_exec_state.bit.statusReport) {
|
||||
report_realtime_status(CLIENT_ALL);
|
||||
system_clear_exec_state_flag(EXEC_STATUS_REPORT);
|
||||
sys_rt_exec_state.bit.statusReport = false;
|
||||
}
|
||||
// NOTE: Once hold is initiated, the system immediately enters a suspend state to block all
|
||||
// main program processes until either reset or resumed. This ensures a hold completes safely.
|
||||
if (rt_exec & (EXEC_MOTION_CANCEL | EXEC_FEED_HOLD | EXEC_SAFETY_DOOR | EXEC_SLEEP)) {
|
||||
if (rt_exec_state.bit.motionCancel || rt_exec_state.bit.feedHold || rt_exec_state.bit.safetyDoor || rt_exec_state.bit.sleep) {
|
||||
// State check for allowable states for hold methods.
|
||||
if (!(sys.state == State::Alarm || sys.state == State::CheckMode)) {
|
||||
// If in CYCLE or JOG states, immediately initiate a motion HOLD.
|
||||
if (sys.state == State::Cycle || sys.state == State::Jog) {
|
||||
if (!(sys.suspend & (SUSPEND_MOTION_CANCEL | SUSPEND_JOG_CANCEL))) { // Block, if already holding.
|
||||
st_update_plan_block_parameters(); // Notify stepper module to recompute for hold deceleration.
|
||||
sys.step_control = STEP_CONTROL_EXECUTE_HOLD; // Initiate suspend state with active flag.
|
||||
if (sys.state == State::Jog) { // Jog cancelled upon any hold event, except for sleeping.
|
||||
if (!(rt_exec & EXEC_SLEEP)) {
|
||||
sys.suspend |= SUSPEND_JOG_CANCEL;
|
||||
if (!(sys.suspend.bit.motionCancel || sys.suspend.bit.jogCancel)) { // Block, if already holding.
|
||||
st_update_plan_block_parameters(); // Notify stepper module to recompute for hold deceleration.
|
||||
sys.step_control = {};
|
||||
sys.step_control.executeHold = true; // Initiate suspend state with active flag.
|
||||
if (sys.state == State::Jog) { // Jog cancelled upon any hold event, except for sleeping.
|
||||
if (!rt_exec_state.bit.sleep) {
|
||||
sys.suspend.bit.jogCancel = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// If IDLE, Grbl is not in motion. Simply indicate suspend state and hold is complete.
|
||||
if (sys.state == State::Idle) {
|
||||
sys.suspend = SUSPEND_HOLD_COMPLETE;
|
||||
sys.suspend.value = 0;
|
||||
sys.suspend.bit.holdComplete = true;
|
||||
}
|
||||
// Execute and flag a motion cancel with deceleration and return to idle. Used primarily by probing cycle
|
||||
// to halt and cancel the remainder of the motion.
|
||||
if (rt_exec & EXEC_MOTION_CANCEL) {
|
||||
if (rt_exec_state.bit.motionCancel) {
|
||||
// MOTION_CANCEL only occurs during a CYCLE, but a HOLD and SAFETY_DOOR may been initiated beforehand
|
||||
// to hold the CYCLE. Motion cancel is valid for a single planner block motion only, while jog cancel
|
||||
// will handle and clear multiple planner block motions.
|
||||
if (sys.state != State::Jog) {
|
||||
sys.suspend |= SUSPEND_MOTION_CANCEL; // NOTE: State is State::Cycle.
|
||||
sys.suspend.bit.motionCancel = true; // NOTE: State is State::Cycle.
|
||||
}
|
||||
sys_rt_exec_state.bit.motionCancel = false;
|
||||
}
|
||||
// Execute a feed hold with deceleration, if required. Then, suspend system.
|
||||
if (rt_exec & EXEC_FEED_HOLD) {
|
||||
if (rt_exec_state.bit.feedHold) {
|
||||
// Block SAFETY_DOOR, JOG, and SLEEP states from changing to HOLD state.
|
||||
if (!(sys.state == State::SafetyDoor || sys.state == State::Jog || sys.state == State::Sleep)) {
|
||||
sys.state = State::Hold;
|
||||
}
|
||||
sys_rt_exec_state.bit.feedHold = false;
|
||||
}
|
||||
// Execute a safety door stop with a feed hold and disable spindle/coolant.
|
||||
// NOTE: Safety door differs from feed holds by stopping everything no matter state, disables powered
|
||||
// devices (spindle/coolant), and blocks resuming until switch is re-engaged.
|
||||
if (rt_exec & EXEC_SAFETY_DOOR) {
|
||||
if (rt_exec_state.bit.safetyDoor) {
|
||||
report_feedback_message(Message::SafetyDoorAjar);
|
||||
// If jogging, block safety door methods until jog cancel is complete. Just flag that it happened.
|
||||
if (!(sys.suspend & SUSPEND_JOG_CANCEL)) {
|
||||
if (!(sys.suspend.bit.jogCancel)) {
|
||||
// Check if the safety re-opened during a restore parking motion only. Ignore if
|
||||
// already retracting, parked or in sleep state.
|
||||
if (sys.state == State::SafetyDoor) {
|
||||
if (sys.suspend & SUSPEND_INITIATE_RESTORE) { // Actively restoring
|
||||
if (sys.suspend.bit.initiateRestore) { // Actively restoring
|
||||
#ifdef PARKING_ENABLE
|
||||
// Set hold and reset appropriate control flags to restart parking sequence.
|
||||
if (sys.step_control & STEP_CONTROL_EXECUTE_SYS_MOTION) {
|
||||
if (sys.step_control.executeSysMotion) {
|
||||
st_update_plan_block_parameters(); // Notify stepper module to recompute for hold deceleration.
|
||||
sys.step_control = (STEP_CONTROL_EXECUTE_HOLD | STEP_CONTROL_EXECUTE_SYS_MOTION);
|
||||
sys.suspend &= ~(SUSPEND_HOLD_COMPLETE);
|
||||
sys.step_control = {};
|
||||
sys.step_control.executeHold = true;
|
||||
sys.step_control.executeSysMotion = true;
|
||||
sys.suspend.bit.holdComplete = false;
|
||||
} // else NO_MOTION is active.
|
||||
#endif
|
||||
sys.suspend &= ~(SUSPEND_RETRACT_COMPLETE | SUSPEND_INITIATE_RESTORE | SUSPEND_RESTORE_COMPLETE);
|
||||
sys.suspend |= SUSPEND_RESTART_RETRACT;
|
||||
sys.suspend.bit.retractComplete = false;
|
||||
sys.suspend.bit.initiateRestore = false;
|
||||
sys.suspend.bit.restoreComplete = false;
|
||||
sys.suspend.bit.restartRetract = true;
|
||||
}
|
||||
}
|
||||
if (sys.state != State::Sleep) {
|
||||
sys.state = State::SafetyDoor;
|
||||
}
|
||||
sys_rt_exec_state.bit.safetyDoor = false;
|
||||
}
|
||||
// NOTE: This flag doesn't change when the door closes, unlike sys.state. Ensures any parking motions
|
||||
// are executed if the door switch closes and the state returns to HOLD.
|
||||
sys.suspend |= SUSPEND_SAFETY_DOOR_AJAR;
|
||||
sys.suspend.bit.safetyDoorAjar = true;
|
||||
}
|
||||
}
|
||||
if (rt_exec & EXEC_SLEEP) {
|
||||
if (rt_exec_state.bit.sleep) {
|
||||
if (sys.state == State::Alarm) {
|
||||
sys.suspend |= (SUSPEND_RETRACT_COMPLETE | SUSPEND_HOLD_COMPLETE);
|
||||
sys.suspend.bit.retractComplete = true;
|
||||
sys.suspend.bit.holdComplete = true;
|
||||
}
|
||||
sys.state = State::Sleep;
|
||||
sys.state = State::Sleep;
|
||||
sys_rt_exec_state.bit.sleep = false;
|
||||
}
|
||||
system_clear_exec_state_flag((EXEC_MOTION_CANCEL | EXEC_FEED_HOLD | EXEC_SAFETY_DOOR | EXEC_SLEEP));
|
||||
}
|
||||
// Execute a cycle start by starting the stepper interrupt to begin executing the blocks in queue.
|
||||
if (rt_exec & EXEC_CYCLE_START) {
|
||||
if (rt_exec_state.bit.cycleStart) {
|
||||
// Block if called at same time as the hold commands: feed hold, motion cancel, and safety door.
|
||||
// Ensures auto-cycle-start doesn't resume a hold without an explicit user-input.
|
||||
if (!(rt_exec & (EXEC_FEED_HOLD | EXEC_MOTION_CANCEL | EXEC_SAFETY_DOOR))) {
|
||||
if (!(rt_exec_state.bit.feedHold || rt_exec_state.bit.motionCancel || rt_exec_state.bit.safetyDoor)) {
|
||||
// Resume door state when parking motion has retracted and door has been closed.
|
||||
if ((sys.state == State::SafetyDoor) && !(sys.suspend & SUSPEND_SAFETY_DOOR_AJAR)) {
|
||||
if (sys.suspend & SUSPEND_RESTORE_COMPLETE) {
|
||||
if (sys.state == State::SafetyDoor && !(sys.suspend.bit.safetyDoorAjar)) {
|
||||
if (sys.suspend.bit.restoreComplete) {
|
||||
sys.state = State::Idle; // Set to IDLE to immediately resume the cycle.
|
||||
} else if (sys.suspend & SUSPEND_RETRACT_COMPLETE) {
|
||||
} else if (sys.suspend.bit.retractComplete) {
|
||||
// Flag to re-energize powered components and restore original position, if disabled by SAFETY_DOOR.
|
||||
// NOTE: For a safety door to resume, the switch must be closed, as indicated by HOLD state, and
|
||||
// the retraction execution is complete, which implies the initial feed hold is not active. To
|
||||
// restore normal operation, the restore procedures must be initiated by the following flag. Once,
|
||||
// they are complete, it will call CYCLE_START automatically to resume and exit the suspend.
|
||||
sys.suspend |= SUSPEND_INITIATE_RESTORE;
|
||||
sys.suspend.bit.initiateRestore = true;
|
||||
}
|
||||
}
|
||||
// Cycle start only when IDLE or when a hold is complete and ready to resume.
|
||||
if ((sys.state == State::Idle) || ((sys.state == State::Hold) && (sys.suspend & SUSPEND_HOLD_COMPLETE))) {
|
||||
if (sys.state == State::Hold && sys.spindle_stop_ovr) {
|
||||
sys.spindle_stop_ovr |= SPINDLE_STOP_OVR_RESTORE_CYCLE; // Set to restore in suspend routine and cycle start after.
|
||||
if (sys.state == State::Idle || (sys.state == State::Hold && sys.suspend.bit.holdComplete)) {
|
||||
if (sys.state == State::Hold && sys.spindle_stop_ovr.value) {
|
||||
sys.spindle_stop_ovr.bit.restoreCycle = true; // Set to restore in suspend routine and cycle start after.
|
||||
} else {
|
||||
// Start cycle only if queued motions exist in planner buffer and the motion is not canceled.
|
||||
sys.step_control = STEP_CONTROL_NORMAL_OP; // Restore step control to normal operation
|
||||
if (plan_get_current_block() && bit_isfalse(sys.suspend, SUSPEND_MOTION_CANCEL)) {
|
||||
sys.suspend = SUSPEND_DISABLE; // Break suspend state.
|
||||
sys.state = State::Cycle;
|
||||
sys.step_control = {}; // Restore step control to normal operation
|
||||
if (plan_get_current_block() && !sys.suspend.bit.motionCancel) {
|
||||
sys.suspend.value = 0; // Break suspend state.
|
||||
sys.state = State::Cycle;
|
||||
st_prep_buffer(); // Initialize step segment buffer before beginning cycle.
|
||||
st_wake_up();
|
||||
} else { // Otherwise, do nothing. Set and resume IDLE state.
|
||||
sys.suspend = SUSPEND_DISABLE; // Break suspend state.
|
||||
sys.state = State::Idle;
|
||||
} else { // Otherwise, do nothing. Set and resume IDLE state.
|
||||
sys.suspend.value = 0; // Break suspend state.
|
||||
sys.state = State::Idle;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
system_clear_exec_state_flag(EXEC_CYCLE_START);
|
||||
sys_rt_exec_state.bit.cycleStart = false;
|
||||
}
|
||||
if (cycle_stop) {
|
||||
// Reinitializes the cycle plan and stepper system after a feed hold for a resume. Called by
|
||||
@@ -406,150 +417,95 @@ void protocol_exec_rt_system() {
|
||||
// cycle reinitializations. The stepper path should continue exactly as if nothing has happened.
|
||||
// NOTE: cycle_stop is set by the stepper subsystem when a cycle or feed hold completes.
|
||||
if ((sys.state == State::Hold || sys.state == State::SafetyDoor || sys.state == State::Sleep) && !(sys.soft_limit) &&
|
||||
!(sys.suspend & SUSPEND_JOG_CANCEL)) {
|
||||
!(sys.suspend.bit.jogCancel)) {
|
||||
// Hold complete. Set to indicate ready to resume. Remain in HOLD or DOOR states until user
|
||||
// has issued a resume command or reset.
|
||||
plan_cycle_reinitialize();
|
||||
if (sys.step_control & STEP_CONTROL_EXECUTE_HOLD) {
|
||||
sys.suspend |= SUSPEND_HOLD_COMPLETE;
|
||||
if (sys.step_control.executeHold) {
|
||||
sys.suspend.bit.holdComplete = true;
|
||||
}
|
||||
bit_false(sys.step_control, (STEP_CONTROL_EXECUTE_HOLD | STEP_CONTROL_EXECUTE_SYS_MOTION));
|
||||
sys.step_control.executeHold = false;
|
||||
sys.step_control.executeSysMotion = false;
|
||||
} else {
|
||||
// Motion complete. Includes CYCLE/JOG/HOMING states and jog cancel/motion cancel/soft limit events.
|
||||
// NOTE: Motion and jog cancel both immediately return to idle after the hold completes.
|
||||
if (sys.suspend & SUSPEND_JOG_CANCEL) { // For jog cancel, flush buffers and sync positions.
|
||||
sys.step_control = STEP_CONTROL_NORMAL_OP;
|
||||
if (sys.suspend.bit.jogCancel) { // For jog cancel, flush buffers and sync positions.
|
||||
sys.step_control = {};
|
||||
plan_reset();
|
||||
st_reset();
|
||||
gc_sync_position();
|
||||
plan_sync_position();
|
||||
}
|
||||
if (sys.suspend & SUSPEND_SAFETY_DOOR_AJAR) { // Only occurs when safety door opens during jog.
|
||||
sys.suspend &= ~(SUSPEND_JOG_CANCEL);
|
||||
sys.suspend |= SUSPEND_HOLD_COMPLETE;
|
||||
sys.state = State::SafetyDoor;
|
||||
if (sys.suspend.bit.safetyDoorAjar) { // Only occurs when safety door opens during jog.
|
||||
sys.suspend.bit.jogCancel = false;
|
||||
sys.suspend.bit.holdComplete = true;
|
||||
sys.state = State::SafetyDoor;
|
||||
} else {
|
||||
sys.suspend = SUSPEND_DISABLE;
|
||||
sys.state = State::Idle;
|
||||
sys.suspend.value = 0;
|
||||
sys.state = State::Idle;
|
||||
}
|
||||
}
|
||||
cycle_stop = false;
|
||||
}
|
||||
}
|
||||
// Execute overrides.
|
||||
rt_exec = sys_rt_exec_motion_override; // Copy volatile sys_rt_exec_motion_override
|
||||
if (rt_exec) {
|
||||
system_clear_exec_motion_overrides(); // Clear all motion override flags.
|
||||
uint8_t new_f_override = sys.f_override;
|
||||
if (rt_exec & EXEC_FEED_OVR_RESET) {
|
||||
new_f_override = DEFAULT_FEED_OVERRIDE;
|
||||
}
|
||||
if (rt_exec & EXEC_FEED_OVR_COARSE_PLUS) {
|
||||
new_f_override += FEED_OVERRIDE_COARSE_INCREMENT;
|
||||
}
|
||||
if (rt_exec & EXEC_FEED_OVR_COARSE_MINUS) {
|
||||
new_f_override -= FEED_OVERRIDE_COARSE_INCREMENT;
|
||||
}
|
||||
if (rt_exec & EXEC_FEED_OVR_FINE_PLUS) {
|
||||
new_f_override += FEED_OVERRIDE_FINE_INCREMENT;
|
||||
}
|
||||
if (rt_exec & EXEC_FEED_OVR_FINE_MINUS) {
|
||||
new_f_override -= FEED_OVERRIDE_FINE_INCREMENT;
|
||||
}
|
||||
new_f_override = MIN(new_f_override, MAX_FEED_RATE_OVERRIDE);
|
||||
new_f_override = MAX(new_f_override, MIN_FEED_RATE_OVERRIDE);
|
||||
uint8_t new_r_override = sys.r_override;
|
||||
if (rt_exec & EXEC_RAPID_OVR_RESET) {
|
||||
new_r_override = DEFAULT_RAPID_OVERRIDE;
|
||||
}
|
||||
if (rt_exec & EXEC_RAPID_OVR_MEDIUM) {
|
||||
new_r_override = RAPID_OVERRIDE_MEDIUM;
|
||||
}
|
||||
if (rt_exec & EXEC_RAPID_OVR_LOW) {
|
||||
new_r_override = RAPID_OVERRIDE_LOW;
|
||||
}
|
||||
if ((new_f_override != sys.f_override) || (new_r_override != sys.r_override)) {
|
||||
sys.f_override = new_f_override;
|
||||
sys.r_override = new_r_override;
|
||||
sys.report_ovr_counter = 0; // Set to report change immediately
|
||||
plan_update_velocity_profile_parameters();
|
||||
plan_cycle_reinitialize();
|
||||
if ((sys_rt_f_override != sys.f_override) || (sys_rt_r_override != sys.r_override)) {
|
||||
sys.f_override = sys_rt_f_override;
|
||||
sys.r_override = sys_rt_r_override;
|
||||
sys.report_ovr_counter = 0; // Set to report change immediately
|
||||
plan_update_velocity_profile_parameters();
|
||||
plan_cycle_reinitialize();
|
||||
}
|
||||
|
||||
// NOTE: Unlike motion overrides, spindle overrides do not require a planner reinitialization.
|
||||
if (sys_rt_s_override != sys.spindle_speed_ovr) {
|
||||
sys.step_control.updateSpindleRpm = true;
|
||||
sys.spindle_speed_ovr = sys_rt_s_override;
|
||||
sys.report_ovr_counter = 0; // Set to report change immediately
|
||||
// If spinlde is on, tell it the rpm has been overridden
|
||||
if (gc_state.modal.spindle != SpindleState::Disable) {
|
||||
spindle->set_rpm(gc_state.spindle_speed);
|
||||
}
|
||||
}
|
||||
rt_exec = sys_rt_exec_accessory_override;
|
||||
if (rt_exec) {
|
||||
system_clear_exec_accessory_overrides(); // Clear all accessory override flags.
|
||||
// NOTE: Unlike motion overrides, spindle overrides do not require a planner reinitialization.
|
||||
uint8_t last_s_override = sys.spindle_speed_ovr;
|
||||
if (rt_exec & EXEC_SPINDLE_OVR_RESET) {
|
||||
last_s_override = DEFAULT_SPINDLE_SPEED_OVERRIDE;
|
||||
}
|
||||
if (rt_exec & EXEC_SPINDLE_OVR_COARSE_PLUS) {
|
||||
last_s_override += SPINDLE_OVERRIDE_COARSE_INCREMENT;
|
||||
}
|
||||
if (rt_exec & EXEC_SPINDLE_OVR_COARSE_MINUS) {
|
||||
last_s_override -= SPINDLE_OVERRIDE_COARSE_INCREMENT;
|
||||
}
|
||||
if (rt_exec & EXEC_SPINDLE_OVR_FINE_PLUS) {
|
||||
last_s_override += SPINDLE_OVERRIDE_FINE_INCREMENT;
|
||||
}
|
||||
if (rt_exec & EXEC_SPINDLE_OVR_FINE_MINUS) {
|
||||
last_s_override -= SPINDLE_OVERRIDE_FINE_INCREMENT;
|
||||
}
|
||||
last_s_override = MIN(last_s_override, MAX_SPINDLE_SPEED_OVERRIDE);
|
||||
last_s_override = MAX(last_s_override, MIN_SPINDLE_SPEED_OVERRIDE);
|
||||
if (last_s_override != sys.spindle_speed_ovr) {
|
||||
bit_true(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_RPM);
|
||||
sys.spindle_speed_ovr = last_s_override;
|
||||
sys.report_ovr_counter = 0; // Set to report change immediately
|
||||
// If spinlde is on, tell it the rpm has been overridden
|
||||
if (gc_state.modal.spindle != SpindleState::Disable) {
|
||||
spindle->set_rpm(gc_state.spindle_speed);
|
||||
|
||||
if (sys_rt_exec_accessory_override.bit.spindleOvrStop) {
|
||||
sys_rt_exec_accessory_override.bit.spindleOvrStop = false;
|
||||
// Spindle stop override allowed only while in HOLD state.
|
||||
// NOTE: Report counters are set in spindle_set_state() when spindle stop is executed.
|
||||
if (sys.state == State::Hold) {
|
||||
if (sys.spindle_stop_ovr.value == 0) {
|
||||
sys.spindle_stop_ovr.bit.initiate = true;
|
||||
} else if (sys.spindle_stop_ovr.bit.enabled) {
|
||||
sys.spindle_stop_ovr.bit.restore = true;
|
||||
}
|
||||
}
|
||||
if (rt_exec & EXEC_SPINDLE_OVR_STOP) {
|
||||
// Spindle stop override allowed only while in HOLD state.
|
||||
// NOTE: Report counters are set in spindle_set_state() when spindle stop is executed.
|
||||
if (sys.state == State::Hold) {
|
||||
if (!(sys.spindle_stop_ovr)) {
|
||||
sys.spindle_stop_ovr = SPINDLE_STOP_OVR_INITIATE;
|
||||
} else if (sys.spindle_stop_ovr & SPINDLE_STOP_OVR_ENABLED) {
|
||||
sys.spindle_stop_ovr |= SPINDLE_STOP_OVR_RESTORE;
|
||||
}
|
||||
}
|
||||
}
|
||||
// NOTE: Since coolant state always performs a planner sync whenever it changes, the current
|
||||
// run state can be determined by checking the parser state.
|
||||
if (rt_exec & (EXEC_COOLANT_FLOOD_OVR_TOGGLE | EXEC_COOLANT_MIST_OVR_TOGGLE)) {
|
||||
if (sys.state == State::Idle || sys.state == State::Cycle || sys.state == State::Hold) {
|
||||
CoolantState coolant_state = gc_state.modal.coolant;
|
||||
}
|
||||
|
||||
// NOTE: Since coolant state always performs a planner sync whenever it changes, the current
|
||||
// run state can be determined by checking the parser state.
|
||||
if (sys_rt_exec_accessory_override.bit.coolantFloodOvrToggle) {
|
||||
sys_rt_exec_accessory_override.bit.coolantFloodOvrToggle = false;
|
||||
#ifdef COOLANT_FLOOD_PIN
|
||||
if (rt_exec & EXEC_COOLANT_FLOOD_OVR_TOGGLE) {
|
||||
if (coolant_state.Flood) {
|
||||
coolant_state.Flood = 0;
|
||||
} else {
|
||||
coolant_state.Flood = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef COOLANT_MIST_PIN
|
||||
if (rt_exec & EXEC_COOLANT_MIST_OVR_TOGGLE) {
|
||||
if (coolant_state.Mist) {
|
||||
coolant_state.Mist = 0;
|
||||
} else {
|
||||
coolant_state.Mist = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
coolant_set_state(coolant_state); // Report counter set in coolant_set_state().
|
||||
gc_state.modal.coolant = coolant_state;
|
||||
}
|
||||
if (sys.state == State::Idle || sys.state == State::Cycle || sys.state == State::Hold) {
|
||||
gc_state.modal.coolant.Flood = !gc_state.modal.coolant.Flood;
|
||||
coolant_set_state(gc_state.modal.coolant); // Report counter set in coolant_set_state().
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (sys_rt_exec_accessory_override.bit.coolantMistOvrToggle) {
|
||||
sys_rt_exec_accessory_override.bit.coolantMistOvrToggle = false;
|
||||
#ifdef COOLANT_MIST_PIN
|
||||
if (sys.state == State::Idle || sys.state == State::Cycle || sys.state == State::Hold) {
|
||||
gc_state.modal.coolant.Mist = !gc_state.modal.coolant.Mist;
|
||||
coolant_set_state(gc_state.modal.coolant); // Report counter set in coolant_set_state().
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (sys_rt_exec_debug) {
|
||||
report_realtime_debug();
|
||||
sys_rt_exec_debug = 0;
|
||||
sys_rt_exec_debug = false;
|
||||
}
|
||||
#endif
|
||||
// Reload step segment buffer
|
||||
@@ -603,30 +559,30 @@ static void protocol_exec_rt_suspend() {
|
||||
}
|
||||
#ifdef DISABLE_LASER_DURING_HOLD
|
||||
if (laser_mode->get()) {
|
||||
system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_STOP);
|
||||
sys_rt_exec_accessory_override.bit.spindleOvrStop = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
while (sys.suspend) {
|
||||
while (sys.suspend.value) {
|
||||
if (sys.abort) {
|
||||
return;
|
||||
}
|
||||
// Block until initial hold is complete and the machine has stopped motion.
|
||||
if (sys.suspend & SUSPEND_HOLD_COMPLETE) {
|
||||
if (sys.suspend.bit.holdComplete) {
|
||||
// Parking manager. Handles de/re-energizing, switch state checks, and parking motions for
|
||||
// the safety door and sleep states.
|
||||
if (sys.state == State::SafetyDoor || sys.state == State::Sleep) {
|
||||
// Handles retraction motions and de-energizing.
|
||||
if (bit_isfalse(sys.suspend, SUSPEND_RETRACT_COMPLETE)) {
|
||||
if (!sys.suspend.bit.retractComplete) {
|
||||
// Ensure any prior spindle stop override is disabled at start of safety door routine.
|
||||
sys.spindle_stop_ovr = SPINDLE_STOP_OVR_DISABLED;
|
||||
sys.spindle_stop_ovr.value = 0; // Disable override
|
||||
#ifndef PARKING_ENABLE
|
||||
spindle->set_state(SpindleState::Disable, 0); // De-energize
|
||||
coolant_off();
|
||||
#else
|
||||
// Get current position and store restore location and spindle retract waypoint.
|
||||
system_convert_array_steps_to_mpos(parking_target, sys_position);
|
||||
if (bit_isfalse(sys.suspend, SUSPEND_RESTART_RETRACT)) {
|
||||
if (!sys.suspend.bit.restartRetract) {
|
||||
memcpy(restore_target, parking_target, sizeof(parking_target));
|
||||
retract_waypoint += restore_target[PARKING_AXIS];
|
||||
retract_waypoint = MIN(retract_waypoint, PARKING_TARGET);
|
||||
@@ -667,8 +623,8 @@ static void protocol_exec_rt_suspend() {
|
||||
coolant_off();
|
||||
}
|
||||
#endif
|
||||
sys.suspend &= ~(SUSPEND_RESTART_RETRACT);
|
||||
sys.suspend |= SUSPEND_RETRACT_COMPLETE;
|
||||
sys.suspend.bit.restartRetract = false;
|
||||
sys.suspend.bit.retractComplete = true;
|
||||
} else {
|
||||
if (sys.state == State::Sleep) {
|
||||
report_feedback_message(Message::SleepMode);
|
||||
@@ -684,11 +640,11 @@ static void protocol_exec_rt_suspend() {
|
||||
// Allows resuming from parking/safety door. Actively checks if safety door is closed and ready to resume.
|
||||
if (sys.state == State::SafetyDoor) {
|
||||
if (!(system_check_safety_door_ajar())) {
|
||||
sys.suspend &= ~(SUSPEND_SAFETY_DOOR_AJAR); // Reset door ajar flag to denote ready to resume.
|
||||
sys.suspend.bit.safetyDoorAjar = false; // Reset door ajar flag to denote ready to resume.
|
||||
}
|
||||
}
|
||||
// Handles parking restore and safety door resume.
|
||||
if (sys.suspend & SUSPEND_INITIATE_RESTORE) {
|
||||
if (sys.suspend.bit.initiateRestore) {
|
||||
#ifdef PARKING_ENABLE
|
||||
// Execute fast restore motion to the pull-out position. Parking requires homing enabled.
|
||||
// NOTE: State is will remain DOOR, until the de-energizing and retract is complete.
|
||||
@@ -704,10 +660,10 @@ static void protocol_exec_rt_suspend() {
|
||||
// Delayed Tasks: Restart spindle and coolant, delay to power-up, then resume cycle.
|
||||
if (gc_state.modal.spindle != SpindleState::Disable) {
|
||||
// Block if safety door re-opened during prior restore actions.
|
||||
if (bit_isfalse(sys.suspend, SUSPEND_RESTART_RETRACT)) {
|
||||
if (!sys.suspend.bit.restartRetract) {
|
||||
if (laser_mode->get()) {
|
||||
// When in laser mode, ignore spindle spin-up delay. Set to turn on laser when cycle starts.
|
||||
bit_true(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_RPM);
|
||||
sys.step_control.updateSpindleRpm = true;
|
||||
} else {
|
||||
spindle->set_state(restore_spindle, (uint32_t)restore_spindle_speed);
|
||||
delay_sec(SAFETY_DOOR_SPINDLE_DELAY, DELAY_MODE_SYS_SUSPEND);
|
||||
@@ -716,7 +672,7 @@ static void protocol_exec_rt_suspend() {
|
||||
}
|
||||
if (gc_state.modal.coolant.Flood || gc_state.modal.coolant.Mist) {
|
||||
// Block if safety door re-opened during prior restore actions.
|
||||
if (bit_isfalse(sys.suspend, SUSPEND_RESTART_RETRACT)) {
|
||||
if (!sys.suspend.bit.restartRetract) {
|
||||
// NOTE: Laser mode will honor this delay. An exhaust system is often controlled by this pin.
|
||||
coolant_set_state(restore_coolant);
|
||||
delay_sec(SAFETY_DOOR_COOLANT_DELAY, DELAY_MODE_SYS_SUSPEND);
|
||||
@@ -726,7 +682,7 @@ static void protocol_exec_rt_suspend() {
|
||||
// Execute slow plunge motion from pull-out position to resume position.
|
||||
if (can_park()) {
|
||||
// Block if safety door re-opened during prior restore actions.
|
||||
if (bit_isfalse(sys.suspend, SUSPEND_RESTART_RETRACT)) {
|
||||
if (!sys.suspend.bit.restartRetract) {
|
||||
// Regardless if the retract parking motion was a valid/safe motion or not, the
|
||||
// restore parking motion should logically be valid, either by returning to the
|
||||
// original position through valid machine space or by not moving at all.
|
||||
@@ -738,46 +694,47 @@ static void protocol_exec_rt_suspend() {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (bit_isfalse(sys.suspend, SUSPEND_RESTART_RETRACT)) {
|
||||
sys.suspend |= SUSPEND_RESTORE_COMPLETE;
|
||||
system_set_exec_state_flag(EXEC_CYCLE_START); // Set to resume program.
|
||||
if (!sys.suspend.bit.restartRetract) {
|
||||
sys.suspend.bit.restoreComplete = true;
|
||||
sys_rt_exec_state.bit.cycleStart = true; // Set to resume program.
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Feed hold manager. Controls spindle stop override states.
|
||||
// NOTE: Hold ensured as completed by condition check at the beginning of suspend routine.
|
||||
if (sys.spindle_stop_ovr) {
|
||||
if (sys.spindle_stop_ovr.value) {
|
||||
// Handles beginning of spindle stop
|
||||
if (sys.spindle_stop_ovr & SPINDLE_STOP_OVR_INITIATE) {
|
||||
if (sys.spindle_stop_ovr.bit.initiate) {
|
||||
if (gc_state.modal.spindle != SpindleState::Disable) {
|
||||
spindle->set_state(SpindleState::Disable, 0); // De-energize
|
||||
sys.spindle_stop_ovr = SPINDLE_STOP_OVR_ENABLED; // Set stop override state to enabled, if de-energized.
|
||||
spindle->set_state(SpindleState::Disable, 0); // De-energize
|
||||
sys.spindle_stop_ovr.value = 0;
|
||||
sys.spindle_stop_ovr.bit.enabled = true; // Set stop override state to enabled, if de-energized.
|
||||
} else {
|
||||
sys.spindle_stop_ovr = SPINDLE_STOP_OVR_DISABLED; // Clear stop override state
|
||||
sys.spindle_stop_ovr.value = 0; // Clear stop override state
|
||||
}
|
||||
// Handles restoring of spindle state
|
||||
} else if (sys.spindle_stop_ovr & (SPINDLE_STOP_OVR_RESTORE | SPINDLE_STOP_OVR_RESTORE_CYCLE)) {
|
||||
} else if (sys.spindle_stop_ovr.bit.restore || sys.spindle_stop_ovr.bit.restoreCycle) {
|
||||
if (gc_state.modal.spindle != SpindleState::Disable) {
|
||||
report_feedback_message(Message::SpindleRestore);
|
||||
if (laser_mode->get()) {
|
||||
// When in laser mode, ignore spindle spin-up delay. Set to turn on laser when cycle starts.
|
||||
bit_true(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_RPM);
|
||||
sys.step_control.updateSpindleRpm = true;
|
||||
} else {
|
||||
spindle->set_state(restore_spindle, (uint32_t)restore_spindle_speed);
|
||||
}
|
||||
}
|
||||
if (sys.spindle_stop_ovr & SPINDLE_STOP_OVR_RESTORE_CYCLE) {
|
||||
system_set_exec_state_flag(EXEC_CYCLE_START); // Set to resume program.
|
||||
if (sys.spindle_stop_ovr.bit.restoreCycle) {
|
||||
sys_rt_exec_state.bit.cycleStart = true; // Set to resume program.
|
||||
}
|
||||
sys.spindle_stop_ovr = SPINDLE_STOP_OVR_DISABLED; // Clear stop override state
|
||||
sys.spindle_stop_ovr.value = 0; // Clear stop override state
|
||||
}
|
||||
} else {
|
||||
// Handles spindle state during hold. NOTE: Spindle speed overrides may be altered during hold state.
|
||||
// NOTE: STEP_CONTROL_UPDATE_SPINDLE_RPM is automatically reset upon resume in step generator.
|
||||
if (bit_istrue(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_RPM)) {
|
||||
// NOTE: sys.step_control.updateSpindleRpm is automatically reset upon resume in step generator.
|
||||
if (sys.step_control.updateSpindleRpm) {
|
||||
spindle->set_state(restore_spindle, (uint32_t)restore_spindle_speed);
|
||||
bit_false(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_RPM);
|
||||
sys.step_control.updateSpindleRpm = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -487,7 +487,7 @@ void report_gcode_modes(uint8_t client) {
|
||||
}
|
||||
|
||||
#ifdef ENABLE_PARKING_OVERRIDE_CONTROL
|
||||
if (sys.override_ctrl == OVERRIDE_PARKING_MOTION) {
|
||||
if (sys.override_ctrl == Override::ParkingMotion) {
|
||||
strcat(modes_rpt, " M56");
|
||||
}
|
||||
#endif
|
||||
@@ -601,13 +601,9 @@ void report_realtime_status(uint8_t client) {
|
||||
strcat(status, "Run");
|
||||
break;
|
||||
case State::Hold:
|
||||
if (!(sys.suspend & SUSPEND_JOG_CANCEL)) {
|
||||
if (!(sys.suspend.bit.jogCancel)) {
|
||||
strcat(status, "Hold:");
|
||||
if (sys.suspend & SUSPEND_HOLD_COMPLETE) {
|
||||
strcat(status, "0"); // Ready to resume
|
||||
} else {
|
||||
strcat(status, "1"); // Actively holding
|
||||
}
|
||||
strcat(status, sys.suspend.bit.holdComplete ? "0" : "1"); // Ready to resume
|
||||
break;
|
||||
} // Continues to print jog state during jog cancel.
|
||||
case State::Jog:
|
||||
@@ -624,15 +620,11 @@ void report_realtime_status(uint8_t client) {
|
||||
break;
|
||||
case State::SafetyDoor:
|
||||
strcat(status, "Door:");
|
||||
if (sys.suspend & SUSPEND_INITIATE_RESTORE) {
|
||||
if (sys.suspend.bit.initiateRestore) {
|
||||
strcat(status, "3"); // Restoring
|
||||
} else {
|
||||
if (sys.suspend & SUSPEND_RETRACT_COMPLETE) {
|
||||
if (sys.suspend & SUSPEND_SAFETY_DOOR_AJAR) {
|
||||
strcat(status, "1"); // Door ajar
|
||||
} else {
|
||||
strcat(status, "0");
|
||||
}
|
||||
if (sys.suspend.bit.retractComplete) {
|
||||
strcat(status, sys.suspend.bit.safetyDoorAjar ? "1" : "0"); // Door ajar
|
||||
// Door closed and ready to resume
|
||||
} else {
|
||||
strcat(status, "2"); // Retracting
|
||||
@@ -713,10 +705,10 @@ void report_realtime_status(uint8_t client) {
|
||||
strcat(status, temp);
|
||||
#endif
|
||||
#ifdef REPORT_FIELD_PIN_STATE
|
||||
uint8_t lim_pin_state = limits_get_state();
|
||||
uint8_t ctrl_pin_state = system_control_get_state();
|
||||
uint8_t prb_pin_state = probe_get_state();
|
||||
if (lim_pin_state | ctrl_pin_state | prb_pin_state) {
|
||||
AxisMask lim_pin_state = limits_get_state();
|
||||
ControlPins ctrl_pin_state = system_control_get_state();
|
||||
bool prb_pin_state = probe_get_state();
|
||||
if (lim_pin_state || ctrl_pin_state.value || prb_pin_state) {
|
||||
strcat(status, "|Pn:");
|
||||
if (prb_pin_state) {
|
||||
strcat(status, "P");
|
||||
@@ -742,21 +734,31 @@ void report_realtime_status(uint8_t client) {
|
||||
strcat(status, "C");
|
||||
}
|
||||
}
|
||||
if (ctrl_pin_state) {
|
||||
# ifdef ENABLE_SAFETY_DOOR_INPUT_PIN
|
||||
if (bit_istrue(ctrl_pin_state, CONTROL_PIN_INDEX_SAFETY_DOOR)) {
|
||||
if (ctrl_pin_state.value) {
|
||||
if (ctrl_pin_state.bit.safetyDoor) {
|
||||
strcat(status, "D");
|
||||
}
|
||||
# endif
|
||||
if (bit_istrue(ctrl_pin_state, CONTROL_PIN_INDEX_RESET)) {
|
||||
if (ctrl_pin_state.bit.reset) {
|
||||
strcat(status, "R");
|
||||
}
|
||||
if (bit_istrue(ctrl_pin_state, CONTROL_PIN_INDEX_FEED_HOLD)) {
|
||||
if (ctrl_pin_state.bit.feedHold) {
|
||||
strcat(status, "H");
|
||||
}
|
||||
if (bit_istrue(ctrl_pin_state, CONTROL_PIN_INDEX_CYCLE_START)) {
|
||||
if (ctrl_pin_state.bit.cycleStart) {
|
||||
strcat(status, "S");
|
||||
}
|
||||
if (ctrl_pin_state.bit.macro0) {
|
||||
strcat(status, "M0");
|
||||
}
|
||||
if (ctrl_pin_state.bit.macro1) {
|
||||
strcat(status, "M1");
|
||||
}
|
||||
if (ctrl_pin_state.bit.macro2) {
|
||||
strcat(status, "M2");
|
||||
}
|
||||
if (ctrl_pin_state.bit.macro3) {
|
||||
strcat(status, "M3");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@@ -131,7 +131,7 @@ void serialCheckTask(void* pvParameters) {
|
||||
// Pick off realtime command characters directly from the serial stream. These characters are
|
||||
// not passed into the main buffer, but these set system state flag bits for realtime execution.
|
||||
if (is_realtime_command(data)) {
|
||||
execute_realtime_command(data, client);
|
||||
execute_realtime_command(static_cast<Cmd>(data), client);
|
||||
} else {
|
||||
vTaskEnterCritical(&myMutex);
|
||||
client_buffer[client].write(data);
|
||||
@@ -196,91 +196,115 @@ bool any_client_has_data() {
|
||||
|
||||
// checks to see if a character is a realtime character
|
||||
bool is_realtime_command(uint8_t data) {
|
||||
return data == CMD_RESET || data == CMD_STATUS_REPORT || data == CMD_CYCLE_START || data == CMD_FEED_HOLD || data > 0x7F;
|
||||
if (data >= 0x80) {
|
||||
return true;
|
||||
}
|
||||
auto cmd = static_cast<Cmd>(data);
|
||||
return cmd == Cmd::Reset || cmd == Cmd::StatusReport || cmd == Cmd::CycleStart || cmd == Cmd::FeedHold;
|
||||
}
|
||||
|
||||
// Act upon a realtime character
|
||||
void execute_realtime_command(uint8_t command, uint8_t client) {
|
||||
void execute_realtime_command(Cmd command, uint8_t client) {
|
||||
switch (command) {
|
||||
case CMD_RESET:
|
||||
case Cmd::Reset:
|
||||
mc_reset(); // Call motion control reset routine.
|
||||
break;
|
||||
case CMD_STATUS_REPORT:
|
||||
case Cmd::StatusReport:
|
||||
report_realtime_status(client); // direct call instead of setting flag
|
||||
break;
|
||||
case CMD_CYCLE_START:
|
||||
system_set_exec_state_flag(EXEC_CYCLE_START); // Set as true
|
||||
case Cmd::CycleStart:
|
||||
sys_rt_exec_state.bit.cycleStart = true;
|
||||
break;
|
||||
case CMD_FEED_HOLD:
|
||||
system_set_exec_state_flag(EXEC_FEED_HOLD); // Set as true
|
||||
case Cmd::FeedHold:
|
||||
sys_rt_exec_state.bit.feedHold = true;
|
||||
break;
|
||||
case CMD_SAFETY_DOOR:
|
||||
system_set_exec_state_flag(EXEC_SAFETY_DOOR);
|
||||
break; // Set as true
|
||||
case CMD_JOG_CANCEL:
|
||||
case Cmd::SafetyDoor:
|
||||
sys_rt_exec_state.bit.safetyDoor = true;
|
||||
break;
|
||||
case Cmd::JogCancel:
|
||||
if (sys.state == State::Jog) { // Block all other states from invoking motion cancel.
|
||||
system_set_exec_state_flag(EXEC_MOTION_CANCEL);
|
||||
sys_rt_exec_state.bit.motionCancel = true;
|
||||
}
|
||||
break;
|
||||
case Cmd::DebugReport:
|
||||
#ifdef DEBUG
|
||||
case CMD_DEBUG_REPORT: {
|
||||
uint8_t sreg = SREG;
|
||||
cli();
|
||||
bit_true(sys_rt_exec_debug, EXEC_DEBUG_REPORT);
|
||||
SREG = sreg;
|
||||
} break;
|
||||
sys_rt_exec_debug = true;
|
||||
#endif
|
||||
case CMD_FEED_OVR_RESET:
|
||||
system_set_exec_motion_override_flag(EXEC_FEED_OVR_RESET);
|
||||
break;
|
||||
case CMD_FEED_OVR_COARSE_PLUS:
|
||||
system_set_exec_motion_override_flag(EXEC_FEED_OVR_COARSE_PLUS);
|
||||
case Cmd::SpindleOvrStop:
|
||||
sys_rt_exec_accessory_override.bit.spindleOvrStop = 1;
|
||||
break;
|
||||
case CMD_FEED_OVR_COARSE_MINUS:
|
||||
system_set_exec_motion_override_flag(EXEC_FEED_OVR_COARSE_MINUS);
|
||||
case Cmd::FeedOvrReset:
|
||||
sys_rt_f_override = FeedOverride::Default;
|
||||
break;
|
||||
case CMD_FEED_OVR_FINE_PLUS:
|
||||
system_set_exec_motion_override_flag(EXEC_FEED_OVR_FINE_PLUS);
|
||||
case Cmd::FeedOvrCoarsePlus:
|
||||
sys_rt_f_override += FeedOverride::CoarseIncrement;
|
||||
if (sys_rt_f_override > FeedOverride::Max) {
|
||||
sys_rt_f_override = FeedOverride::Max;
|
||||
}
|
||||
break;
|
||||
case CMD_FEED_OVR_FINE_MINUS:
|
||||
system_set_exec_motion_override_flag(EXEC_FEED_OVR_FINE_MINUS);
|
||||
case Cmd::FeedOvrCoarseMinus:
|
||||
sys_rt_f_override -= FeedOverride::CoarseIncrement;
|
||||
if (sys_rt_f_override < FeedOverride::Min) {
|
||||
sys_rt_f_override = FeedOverride::Min;
|
||||
}
|
||||
break;
|
||||
case CMD_RAPID_OVR_RESET:
|
||||
system_set_exec_motion_override_flag(EXEC_RAPID_OVR_RESET);
|
||||
case Cmd::FeedOvrFinePlus:
|
||||
sys_rt_f_override += FeedOverride::FineIncrement;
|
||||
if (sys_rt_f_override > FeedOverride::Max) {
|
||||
sys_rt_f_override = FeedOverride::Max;
|
||||
}
|
||||
break;
|
||||
case CMD_RAPID_OVR_MEDIUM:
|
||||
system_set_exec_motion_override_flag(EXEC_RAPID_OVR_MEDIUM);
|
||||
case Cmd::FeedOvrFineMinus:
|
||||
sys_rt_f_override -= FeedOverride::FineIncrement;
|
||||
if (sys_rt_f_override < FeedOverride::Min) {
|
||||
sys_rt_f_override = FeedOverride::Min;
|
||||
}
|
||||
break;
|
||||
case CMD_RAPID_OVR_LOW:
|
||||
system_set_exec_motion_override_flag(EXEC_RAPID_OVR_LOW);
|
||||
case Cmd::RapidOvrReset:
|
||||
sys_rt_r_override = RapidOverride::Default;
|
||||
break;
|
||||
case CMD_SPINDLE_OVR_RESET:
|
||||
system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_RESET);
|
||||
case Cmd::RapidOvrMedium:
|
||||
sys_rt_r_override = RapidOverride::Medium;
|
||||
break;
|
||||
case CMD_SPINDLE_OVR_COARSE_PLUS:
|
||||
system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_COARSE_PLUS);
|
||||
case Cmd::RapidOvrLow:
|
||||
sys_rt_r_override = RapidOverride::Low;
|
||||
break;
|
||||
case CMD_SPINDLE_OVR_COARSE_MINUS:
|
||||
system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_COARSE_MINUS);
|
||||
case Cmd::RapidOvrExtraLow:
|
||||
sys_rt_r_override = RapidOverride::ExtraLow;
|
||||
break;
|
||||
case CMD_SPINDLE_OVR_FINE_PLUS:
|
||||
system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_FINE_PLUS);
|
||||
case Cmd::SpindleOvrReset:
|
||||
sys_rt_s_override = SpindleSpeedOverride::Default;
|
||||
break;
|
||||
case CMD_SPINDLE_OVR_FINE_MINUS:
|
||||
system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_FINE_MINUS);
|
||||
case Cmd::SpindleOvrCoarsePlus:
|
||||
sys_rt_s_override += SpindleSpeedOverride::CoarseIncrement;
|
||||
if (sys_rt_s_override > SpindleSpeedOverride::Max) {
|
||||
sys_rt_s_override = SpindleSpeedOverride::Max;
|
||||
}
|
||||
break;
|
||||
case CMD_SPINDLE_OVR_STOP:
|
||||
system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_STOP);
|
||||
case Cmd::SpindleOvrCoarseMinus:
|
||||
sys_rt_s_override -= SpindleSpeedOverride::CoarseIncrement;
|
||||
if (sys_rt_s_override < SpindleSpeedOverride::Min) {
|
||||
sys_rt_s_override = SpindleSpeedOverride::Min;
|
||||
}
|
||||
break;
|
||||
#ifdef COOLANT_FLOOD_PIN
|
||||
case CMD_COOLANT_FLOOD_OVR_TOGGLE:
|
||||
system_set_exec_accessory_override_flag(EXEC_COOLANT_FLOOD_OVR_TOGGLE);
|
||||
case Cmd::SpindleOvrFinePlus:
|
||||
sys_rt_s_override += SpindleSpeedOverride::FineIncrement;
|
||||
if (sys_rt_s_override > SpindleSpeedOverride::Max) {
|
||||
sys_rt_s_override = SpindleSpeedOverride::Max;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifdef COOLANT_MIST_PIN
|
||||
case CMD_COOLANT_MIST_OVR_TOGGLE:
|
||||
system_set_exec_accessory_override_flag(EXEC_COOLANT_MIST_OVR_TOGGLE);
|
||||
case Cmd::SpindleOvrFineMinus:
|
||||
sys_rt_s_override -= SpindleSpeedOverride::FineIncrement;
|
||||
if (sys_rt_s_override < SpindleSpeedOverride::Min) {
|
||||
sys_rt_s_override = SpindleSpeedOverride::Min;
|
||||
}
|
||||
break;
|
||||
case Cmd::CoolantFloodOvrToggle:
|
||||
sys_rt_exec_accessory_override.bit.coolantFloodOvrToggle = 1;
|
||||
break;
|
||||
case Cmd::CoolantMistOvrToggle:
|
||||
sys_rt_exec_accessory_override.bit.coolantMistOvrToggle = 1;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@@ -51,6 +51,6 @@ void serial_reset_read_buffer(uint8_t client);
|
||||
// Returns the number of bytes available in the RX serial buffer.
|
||||
uint8_t serial_get_rx_buffer_available(uint8_t client);
|
||||
|
||||
void execute_realtime_command(uint8_t command, uint8_t client);
|
||||
void execute_realtime_command(Cmd command, uint8_t client);
|
||||
bool any_client_has_data();
|
||||
bool is_realtime_command(uint8_t data);
|
||||
|
@@ -193,7 +193,7 @@ namespace Spindles {
|
||||
grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Spindle RS485 Unresponsive %d", next_cmd.rx_length);
|
||||
if (next_cmd.critical) {
|
||||
grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Critical Spindle RS485 Unresponsive");
|
||||
system_set_exec_alarm(ExecAlarm::SpindleControl);
|
||||
sys_rt_exec_alarm = ExecAlarm::SpindleControl;
|
||||
}
|
||||
unresponsive = true;
|
||||
}
|
||||
|
@@ -301,7 +301,7 @@ static void stepper_pulse_func() {
|
||||
}
|
||||
}
|
||||
// Check probing state.
|
||||
if (sys_probe_state == PROBE_ACTIVE) {
|
||||
if (sys_probe_state == Probe::Active) {
|
||||
probe_state_monitor();
|
||||
}
|
||||
// Reset step out bits.
|
||||
@@ -796,7 +796,7 @@ static uint8_t st_next_block_index(uint8_t block_index) {
|
||||
*/
|
||||
void st_prep_buffer() {
|
||||
// Block step prep buffer, while in a suspend state and there is no suspend motion to execute.
|
||||
if (bit_istrue(sys.step_control, STEP_CONTROL_END_MOTION)) {
|
||||
if (sys.step_control.endMotion) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -804,7 +804,7 @@ void st_prep_buffer() {
|
||||
// Determine if we need to load a new planner block or if the block needs to be recomputed.
|
||||
if (pl_block == NULL) {
|
||||
// Query planner for a queued block
|
||||
if (sys.step_control & STEP_CONTROL_EXECUTE_SYS_MOTION) {
|
||||
if (sys.step_control.executeSysMotion) {
|
||||
pl_block = plan_get_system_motion_block();
|
||||
} else {
|
||||
pl_block = plan_get_current_block();
|
||||
@@ -854,7 +854,7 @@ void st_prep_buffer() {
|
||||
prep.step_per_mm = prep.steps_remaining / pl_block->millimeters;
|
||||
prep.req_mm_increment = REQ_MM_INCREMENT_SCALAR / prep.step_per_mm;
|
||||
prep.dt_remainder = 0.0; // Reset for new segment block
|
||||
if ((sys.step_control & STEP_CONTROL_EXECUTE_HOLD) || prep.recalculate_flag.decelOverride) {
|
||||
if ((sys.step_control.executeHold) || prep.recalculate_flag.decelOverride) {
|
||||
// New block loaded mid-hold. Override planner block entry speed to enforce deceleration.
|
||||
prep.current_speed = prep.exit_speed;
|
||||
pl_block->entry_speed_sqr = prep.exit_speed * prep.exit_speed;
|
||||
@@ -879,7 +879,7 @@ void st_prep_buffer() {
|
||||
*/
|
||||
prep.mm_complete = 0.0; // Default velocity profile complete at 0.0mm from end of block.
|
||||
float inv_2_accel = 0.5 / pl_block->acceleration;
|
||||
if (sys.step_control & STEP_CONTROL_EXECUTE_HOLD) { // [Forced Deceleration to Zero Velocity]
|
||||
if (sys.step_control.executeHold) { // [Forced Deceleration to Zero Velocity]
|
||||
// Compute velocity profile parameters for a feed hold in-progress. This profile overrides
|
||||
// the planner block profile, enforcing a deceleration to zero speed.
|
||||
prep.ramp_type = RAMP_DECEL;
|
||||
@@ -898,7 +898,7 @@ void st_prep_buffer() {
|
||||
prep.accelerate_until = pl_block->millimeters;
|
||||
float exit_speed_sqr;
|
||||
float nominal_speed;
|
||||
if (sys.step_control & STEP_CONTROL_EXECUTE_SYS_MOTION) {
|
||||
if (sys.step_control.executeSysMotion) {
|
||||
prep.exit_speed = exit_speed_sqr = 0.0; // Enforce stop at end of system motion.
|
||||
} else {
|
||||
exit_speed_sqr = plan_get_exec_block_exit_speed_sqr();
|
||||
@@ -956,7 +956,7 @@ void st_prep_buffer() {
|
||||
}
|
||||
}
|
||||
|
||||
bit_true(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_RPM); // Force update whenever updating block.
|
||||
sys.step_control.updateSpindleRpm = true; // Force update whenever updating block.
|
||||
}
|
||||
|
||||
// Initialize new segment
|
||||
@@ -1075,7 +1075,7 @@ void st_prep_buffer() {
|
||||
/* -----------------------------------------------------------------------------------
|
||||
Compute spindle speed PWM output for step segment
|
||||
*/
|
||||
if (st_prep_block->is_pwm_rate_adjusted || (sys.step_control & STEP_CONTROL_UPDATE_SPINDLE_RPM)) {
|
||||
if (st_prep_block->is_pwm_rate_adjusted || sys.step_control.updateSpindleRpm) {
|
||||
if (pl_block->spindle != SpindleState::Disable) {
|
||||
float rpm = pl_block->spindle_speed;
|
||||
// NOTE: Feed and rapid overrides are independent of PWM value and do not alter laser power/rate.
|
||||
@@ -1092,7 +1092,7 @@ void st_prep_buffer() {
|
||||
sys.spindle_speed = 0.0;
|
||||
prep.current_spindle_rpm = 0.0;
|
||||
}
|
||||
bit_false(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_RPM);
|
||||
sys.step_control.updateSpindleRpm = false;
|
||||
}
|
||||
prep_segment->spindle_rpm = prep.current_spindle_rpm; // Reload segment PWM value
|
||||
|
||||
@@ -1113,10 +1113,10 @@ void st_prep_buffer() {
|
||||
|
||||
// Bail if we are at the end of a feed hold and don't have a step to execute.
|
||||
if (prep_segment->n_step == 0) {
|
||||
if (sys.step_control & STEP_CONTROL_EXECUTE_HOLD) {
|
||||
if (sys.step_control.executeHold) {
|
||||
// Less than one step to decelerate to zero speed, but already very close. AMASS
|
||||
// requires full steps to execute. So, just bail.
|
||||
bit_true(sys.step_control, STEP_CONTROL_END_MOTION);
|
||||
sys.step_control.endMotion = true;
|
||||
#ifdef PARKING_ENABLE
|
||||
if (!(prep.recalculate_flag.parking)) {
|
||||
prep.recalculate_flag.holdPartialBlock = 1;
|
||||
@@ -1195,7 +1195,7 @@ void st_prep_buffer() {
|
||||
// Reset prep parameters for resuming and then bail. Allow the stepper ISR to complete
|
||||
// the segment queue, where realtime protocol will set new state upon receiving the
|
||||
// cycle stop flag from the ISR. Prep_segment is blocked until then.
|
||||
bit_true(sys.step_control, STEP_CONTROL_END_MOTION);
|
||||
sys.step_control.endMotion = true;
|
||||
#ifdef PARKING_ENABLE
|
||||
if (!(prep.recalculate_flag.parking)) {
|
||||
prep.recalculate_flag.holdPartialBlock = 1;
|
||||
@@ -1204,8 +1204,8 @@ void st_prep_buffer() {
|
||||
return; // Bail!
|
||||
} else { // End of planner block
|
||||
// The planner block is complete. All steps are set to be executed in the segment buffer.
|
||||
if (sys.step_control & STEP_CONTROL_EXECUTE_SYS_MOTION) {
|
||||
bit_true(sys.step_control, STEP_CONTROL_END_MOTION);
|
||||
if (sys.step_control.executeSysMotion) {
|
||||
sys.step_control.endMotion = true;
|
||||
return;
|
||||
}
|
||||
pl_block = NULL; // Set pointer to indicate check and load next planner block.
|
||||
|
@@ -22,18 +22,20 @@
|
||||
#include "Config.h"
|
||||
|
||||
// Declare system global variable structure
|
||||
system_t sys;
|
||||
int32_t sys_position[MAX_N_AXIS]; // Real-time machine (aka home) position vector in steps.
|
||||
int32_t sys_probe_position[MAX_N_AXIS]; // Last probe position in machine coordinates and steps.
|
||||
volatile uint8_t sys_probe_state; // Probing state value. Used to coordinate the probing cycle with stepper ISR.
|
||||
volatile uint8_t sys_rt_exec_state; // Global realtime executor bitflag variable for state management. See EXEC bitmasks.
|
||||
volatile ExecAlarm sys_rt_exec_alarm; // Global realtime executor bitflag variable for setting various alarms.
|
||||
volatile uint8_t sys_rt_exec_motion_override; // Global realtime executor bitflag variable for motion-based overrides.
|
||||
volatile uint8_t sys_rt_exec_accessory_override; // Global realtime executor bitflag variable for spindle/coolant overrides.
|
||||
volatile bool cycle_stop; // For state transitions, instead of bitflag
|
||||
system_t sys;
|
||||
int32_t sys_position[MAX_N_AXIS]; // Real-time machine (aka home) position vector in steps.
|
||||
int32_t sys_probe_position[MAX_N_AXIS]; // Last probe position in machine coordinates and steps.
|
||||
volatile Probe sys_probe_state; // Probing state value. Used to coordinate the probing cycle with stepper ISR.
|
||||
volatile ExecState sys_rt_exec_state; // Global realtime executor bitflag variable for state management. See EXEC bitmasks.
|
||||
volatile ExecAlarm sys_rt_exec_alarm; // Global realtime executor bitflag variable for setting various alarms.
|
||||
volatile ExecAccessory sys_rt_exec_accessory_override; // Global realtime executor bitflag variable for spindle/coolant overrides.
|
||||
volatile bool cycle_stop; // For state transitions, instead of bitflag
|
||||
#ifdef DEBUG
|
||||
volatile uint8_t sys_rt_exec_debug;
|
||||
volatile bool sys_rt_exec_debug;
|
||||
#endif
|
||||
volatile Percent sys_rt_f_override; // Global realtime executor feedrate override percentage
|
||||
volatile Percent sys_rt_r_override; // Global realtime executor rapid override percentage
|
||||
volatile Percent sys_rt_s_override; // Global realtime executor spindle override percentage
|
||||
|
||||
UserOutput::AnalogOutput* myAnalogOutputs[MaxUserDigitalPin];
|
||||
UserOutput::DigitalOutput* myDigitalOutputs[MaxUserDigitalPin];
|
||||
@@ -116,9 +118,9 @@ void controlCheckTask(void* pvParameters) {
|
||||
int evt;
|
||||
xQueueReceive(control_sw_queue, &evt, portMAX_DELAY); // block until receive queue
|
||||
vTaskDelay(CONTROL_SW_DEBOUNCE_PERIOD); // delay a while
|
||||
uint8_t pin = system_control_get_state();
|
||||
if (pin) {
|
||||
system_exec_control_pin(pin);
|
||||
ControlPins pins = system_control_get_state();
|
||||
if (pins.value) {
|
||||
system_exec_control_pin(pins);
|
||||
}
|
||||
debouncing = false;
|
||||
}
|
||||
@@ -134,77 +136,20 @@ void IRAM_ATTR isr_control_inputs() {
|
||||
xQueueSendFromISR(control_sw_queue, &evt, NULL);
|
||||
}
|
||||
#else
|
||||
uint8_t pin = system_control_get_state();
|
||||
system_exec_control_pin(pin);
|
||||
ControlPins pins = system_control_get_state();
|
||||
system_exec_control_pin(pins);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Returns if safety door is ajar(T) or closed(F), based on pin state.
|
||||
uint8_t system_check_safety_door_ajar() {
|
||||
#ifdef ENABLE_SAFETY_DOOR_INPUT_PIN
|
||||
return system_control_get_state() & CONTROL_PIN_INDEX_SAFETY_DOOR;
|
||||
return system_control_get_state().bit.safetyDoor;
|
||||
#else
|
||||
return false; // Input pin not enabled, so just return that it's closed.
|
||||
#endif
|
||||
}
|
||||
|
||||
// Special handlers for setting and clearing Grbl's real-time execution flags.
|
||||
void system_set_exec_state_flag(uint8_t mask) {
|
||||
// TODO uint8_t sreg = SREG;
|
||||
// TODO cli();
|
||||
sys_rt_exec_state |= (mask);
|
||||
// TODO SREG = sreg;
|
||||
}
|
||||
|
||||
void system_clear_exec_state_flag(uint8_t mask) {
|
||||
//uint8_t sreg = SREG;
|
||||
//cli();
|
||||
sys_rt_exec_state &= ~(mask);
|
||||
//SREG = sreg;
|
||||
}
|
||||
|
||||
void system_set_exec_alarm(ExecAlarm code) {
|
||||
//uint8_t sreg = SREG;
|
||||
//cli();
|
||||
sys_rt_exec_alarm = code;
|
||||
//SREG = sreg;
|
||||
}
|
||||
|
||||
void system_clear_exec_alarm() {
|
||||
//uint8_t sreg = SREG;
|
||||
//cli();
|
||||
sys_rt_exec_alarm = ExecAlarm::None;
|
||||
//SREG = sreg;
|
||||
}
|
||||
|
||||
void system_set_exec_motion_override_flag(uint8_t mask) {
|
||||
//uint8_t sreg = SREG;
|
||||
//cli();
|
||||
sys_rt_exec_motion_override |= (mask);
|
||||
//SREG = sreg;
|
||||
}
|
||||
|
||||
void system_set_exec_accessory_override_flag(uint8_t mask) {
|
||||
//uint8_t sreg = SREG;
|
||||
//cli();
|
||||
sys_rt_exec_accessory_override |= (mask);
|
||||
//SREG = sreg;
|
||||
}
|
||||
|
||||
void system_clear_exec_motion_overrides() {
|
||||
//uint8_t sreg = SREG;
|
||||
//cli();
|
||||
sys_rt_exec_motion_override = 0;
|
||||
//SREG = sreg;
|
||||
}
|
||||
|
||||
void system_clear_exec_accessory_overrides() {
|
||||
//uint8_t sreg = SREG;
|
||||
//cli();
|
||||
sys_rt_exec_accessory_override = 0;
|
||||
//SREG = sreg;
|
||||
}
|
||||
|
||||
void system_flag_wco_change() {
|
||||
#ifdef FORCE_BUFFER_SYNC_DURING_WCO_CHANGE
|
||||
protocol_buffer_synchronize();
|
||||
@@ -267,98 +212,88 @@ uint8_t system_check_travel_limits(float* target) {
|
||||
|
||||
// Returns control pin state as a uint8 bitfield. Each bit indicates the input pin state, where
|
||||
// triggered is 1 and not triggered is 0. Invert mask is applied. Bitfield organization is
|
||||
// defined by the CONTROL_PIN_INDEX in the header file.
|
||||
uint8_t system_control_get_state() {
|
||||
uint8_t defined_pin_mask = 0; // a mask of defined pins
|
||||
uint8_t control_state = 0;
|
||||
// defined by the ControlPin in System.h.
|
||||
ControlPins system_control_get_state() {
|
||||
ControlPins defined_pins;
|
||||
defined_pins.value = 0;
|
||||
|
||||
ControlPins pin_states;
|
||||
pin_states.value = 0;
|
||||
|
||||
#ifdef CONTROL_SAFETY_DOOR_PIN
|
||||
defined_pin_mask |= CONTROL_PIN_INDEX_SAFETY_DOOR;
|
||||
defined_pins.bit.safetyDoor = true;
|
||||
if (digitalRead(CONTROL_SAFETY_DOOR_PIN)) {
|
||||
control_state |= CONTROL_PIN_INDEX_SAFETY_DOOR;
|
||||
pin_states.bit.safetyDoor = true;
|
||||
}
|
||||
#endif
|
||||
#ifdef CONTROL_RESET_PIN
|
||||
defined_pin_mask |= CONTROL_PIN_INDEX_RESET;
|
||||
defined_pins.bit.reset = true;
|
||||
if (digitalRead(CONTROL_RESET_PIN)) {
|
||||
control_state |= CONTROL_PIN_INDEX_RESET;
|
||||
pin_states.bit.reset = true;
|
||||
}
|
||||
#endif
|
||||
#ifdef CONTROL_FEED_HOLD_PIN
|
||||
defined_pin_mask |= CONTROL_PIN_INDEX_FEED_HOLD;
|
||||
defined_pins.bit.feedHold = true;
|
||||
if (digitalRead(CONTROL_FEED_HOLD_PIN)) {
|
||||
control_state |= CONTROL_PIN_INDEX_FEED_HOLD;
|
||||
pin_states.bit.feedHold = true;
|
||||
}
|
||||
#endif
|
||||
#ifdef CONTROL_CYCLE_START_PIN
|
||||
defined_pin_mask |= CONTROL_PIN_INDEX_CYCLE_START;
|
||||
defined_pins.bit.cycleStart = true;
|
||||
if (digitalRead(CONTROL_CYCLE_START_PIN)) {
|
||||
control_state |= CONTROL_PIN_INDEX_CYCLE_START;
|
||||
pin_states.bit.cycleStart = true;
|
||||
}
|
||||
#endif
|
||||
#ifdef MACRO_BUTTON_0_PIN
|
||||
defined_pin_mask |= CONTROL_PIN_INDEX_MACRO_0;
|
||||
defined_pins.bit.macro0 = true;
|
||||
if (digitalRead(MACRO_BUTTON_0_PIN)) {
|
||||
control_state |= CONTROL_PIN_INDEX_MACRO_0;
|
||||
pin_states.bit.macro0 = true;
|
||||
}
|
||||
#endif
|
||||
#ifdef MACRO_BUTTON_1_PIN
|
||||
defined_pin_mask |= CONTROL_PIN_INDEX_MACRO_1;
|
||||
defined_pins.bit.macro1 = true;
|
||||
if (digitalRead(MACRO_BUTTON_1_PIN)) {
|
||||
control_state |= CONTROL_PIN_INDEX_MACRO_1;
|
||||
pin_states.bit.macro1 = true;
|
||||
}
|
||||
#endif
|
||||
#ifdef MACRO_BUTTON_2_PIN
|
||||
defined_pin_mask |= CONTROL_PIN_INDEX_MACRO_2;
|
||||
defined_pins.bit.macro2 = true;
|
||||
if (digitalRead(MACRO_BUTTON_2_PIN)) {
|
||||
control_state |= CONTROL_PIN_INDEX_MACRO_2;
|
||||
pin_states.bit.macro2 = true;
|
||||
}
|
||||
#endif
|
||||
#ifdef MACRO_BUTTON_3_PIN
|
||||
defined_pin_mask |= CONTROL_PIN_INDEX_MACRO_3;
|
||||
defined_pins.bit.macro3 = true;
|
||||
if (digitalRead(MACRO_BUTTON_3_PIN)) {
|
||||
control_state |= CONTROL_PIN_INDEX_MACRO_3;
|
||||
pin_states.bit.macro3 = true;
|
||||
}
|
||||
#endif
|
||||
#ifdef INVERT_CONTROL_PIN_MASK
|
||||
control_state ^= (INVERT_CONTROL_PIN_MASK & defined_pin_mask);
|
||||
pin_states.value ^= (INVERT_CONTROL_PIN_MASK & defined_pins.value);
|
||||
#endif
|
||||
|
||||
return control_state;
|
||||
return pin_states;
|
||||
}
|
||||
|
||||
// execute the function of the control pin
|
||||
void system_exec_control_pin(uint8_t pin) {
|
||||
if (bit_istrue(pin, CONTROL_PIN_INDEX_RESET)) {
|
||||
void system_exec_control_pin(ControlPins pins) {
|
||||
if (pins.bit.reset) {
|
||||
grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Reset via control pin");
|
||||
mc_reset();
|
||||
} else if (bit_istrue(pin, CONTROL_PIN_INDEX_CYCLE_START)) {
|
||||
bit_true(sys_rt_exec_state, EXEC_CYCLE_START);
|
||||
} else if (bit_istrue(pin, CONTROL_PIN_INDEX_FEED_HOLD)) {
|
||||
bit_true(sys_rt_exec_state, EXEC_FEED_HOLD);
|
||||
} else if (bit_istrue(pin, CONTROL_PIN_INDEX_SAFETY_DOOR)) {
|
||||
bit_true(sys_rt_exec_state, EXEC_SAFETY_DOOR);
|
||||
} else if (pins.bit.cycleStart) {
|
||||
sys_rt_exec_state.bit.cycleStart = true;
|
||||
} else if (pins.bit.feedHold) {
|
||||
sys_rt_exec_state.bit.feedHold = true;
|
||||
} else if (pins.bit.safetyDoor) {
|
||||
sys_rt_exec_state.bit.safetyDoor = true;
|
||||
} else if (pins.bit.macro0) {
|
||||
user_defined_macro(0); // function must be implemented by user
|
||||
} else if (pins.bit.macro1) {
|
||||
user_defined_macro(1); // function must be implemented by user
|
||||
} else if (pins.bit.macro2) {
|
||||
user_defined_macro(2); // function must be implemented by user
|
||||
} else if (pins.bit.macro3) {
|
||||
user_defined_macro(3); // function must be implemented by user
|
||||
}
|
||||
#ifdef MACRO_BUTTON_0_PIN
|
||||
else if (bit_istrue(pin, CONTROL_PIN_INDEX_MACRO_0)) {
|
||||
user_defined_macro(CONTROL_PIN_INDEX_MACRO_0); // function must be implemented by user
|
||||
}
|
||||
#endif
|
||||
#ifdef MACRO_BUTTON_1_PIN
|
||||
else if (bit_istrue(pin, CONTROL_PIN_INDEX_MACRO_1)) {
|
||||
user_defined_macro(CONTROL_PIN_INDEX_MACRO_1); // function must be implemented by user
|
||||
}
|
||||
#endif
|
||||
#ifdef MACRO_BUTTON_2_PIN
|
||||
else if (bit_istrue(pin, CONTROL_PIN_INDEX_MACRO_2)) {
|
||||
user_defined_macro(CONTROL_PIN_INDEX_MACRO_2); // function must be implemented by user
|
||||
}
|
||||
#endif
|
||||
#ifdef MACRO_BUTTON_3_PIN
|
||||
else if (bit_istrue(pin, CONTROL_PIN_INDEX_MACRO_3)) {
|
||||
user_defined_macro(CONTROL_PIN_INDEX_MACRO_3); // function must be implemented by user
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// CoreXY calculation only. Returns x or y-axis "steps" based on CoreXY motor steps.
|
||||
@@ -449,3 +384,4 @@ uint8_t sys_calc_pwm_precision(uint32_t freq) {
|
||||
|
||||
return precision - 1;
|
||||
}
|
||||
void __attribute__((weak)) user_defined_macro(uint8_t index);
|
||||
|
@@ -6,7 +6,7 @@
|
||||
Copyright (c) 2014-2016 Sungeun K. Jeon for Gnea Research LLC
|
||||
|
||||
2018 - Bart Dring This file was modifed for use on the ESP32
|
||||
CPU. Do not use this with Grbl for atMega328P
|
||||
CPU. Do not use this with Grbl for atMega328P
|
||||
|
||||
Grbl is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -37,43 +37,98 @@ enum class State : uint8_t {
|
||||
Sleep, // Sleep state.
|
||||
};
|
||||
|
||||
// Define global system variables
|
||||
typedef struct {
|
||||
volatile State state; // Tracks the current system state of Grbl.
|
||||
uint8_t abort; // System abort flag. Forces exit back to main loop for reset.
|
||||
uint8_t suspend; // System suspend bitflag variable that manages holds, cancels, and safety door.
|
||||
uint8_t soft_limit; // Tracks soft limit errors for the state machine. (boolean)
|
||||
uint8_t step_control; // Governs the step segment generator depending on system state.
|
||||
uint8_t probe_succeeded; // Tracks if last probing cycle was successful.
|
||||
uint8_t homing_axis_lock; // Locks axes when limits engage. Used as an axis motion mask in the stepper ISR.
|
||||
uint8_t f_override; // Feed rate override value in percent
|
||||
uint8_t r_override; // Rapids override value in percent
|
||||
uint8_t spindle_speed_ovr; // Spindle speed value in percent
|
||||
uint8_t spindle_stop_ovr; // Tracks spindle stop override states
|
||||
uint8_t report_ovr_counter; // Tracks when to add override data to status reports.
|
||||
uint8_t report_wco_counter; // Tracks when to add work coordinate offset data to status reports.
|
||||
#ifdef ENABLE_PARKING_OVERRIDE_CONTROL
|
||||
uint8_t override_ctrl; // Tracks override control states.
|
||||
// Step segment generator state flags.
|
||||
struct StepControl {
|
||||
uint8_t endMotion : 1;
|
||||
uint8_t executeHold : 1;
|
||||
uint8_t executeSysMotion : 1;
|
||||
uint8_t updateSpindleRpm : 1;
|
||||
};
|
||||
|
||||
// System suspend flags. Used in various ways to manage suspend states and procedures.
|
||||
struct SuspendBits {
|
||||
uint8_t holdComplete : 1; // Indicates initial feed hold is complete.
|
||||
uint8_t restartRetract : 1; // Flag to indicate a retract from a restore parking motion.
|
||||
uint8_t retractComplete : 1; // (Safety door only) Indicates retraction and de-energizing is complete.
|
||||
uint8_t initiateRestore : 1; // (Safety door only) Flag to initiate resume procedures from a cycle start.
|
||||
uint8_t restoreComplete : 1; // (Safety door only) Indicates ready to resume normal operation.
|
||||
uint8_t safetyDoorAjar : 1; // Tracks safety door state for resuming.
|
||||
uint8_t motionCancel : 1; // Indicates a canceled resume motion. Currently used by probing routine.
|
||||
uint8_t jogCancel : 1; // Indicates a jog cancel in process and to reset buffers when complete.
|
||||
};
|
||||
union Suspend {
|
||||
uint8_t value;
|
||||
SuspendBits bit;
|
||||
};
|
||||
|
||||
typedef uint8_t AxisMask; // Bits indexed by axis number
|
||||
typedef uint8_t Percent; // Integer percent
|
||||
typedef uint8_t Counter; // Report interval
|
||||
|
||||
enum class Override : uint8_t {
|
||||
#ifdef DEACTIVATE_PARKING_UPON_INIT
|
||||
Disabled = 0, // (Default: Must be zero)
|
||||
ParkingMotion = 1, // M56
|
||||
#else
|
||||
ParkingMotion = 0, // M56 (Default: Must be zero)
|
||||
Disabled = 1, // Parking disabled.
|
||||
#endif
|
||||
};
|
||||
|
||||
// Spindle stop override control states.
|
||||
struct SpindleStopBits {
|
||||
uint8_t enabled : 1;
|
||||
uint8_t initiate : 1;
|
||||
uint8_t restore : 1;
|
||||
uint8_t restoreCycle : 1;
|
||||
};
|
||||
union SpindleStop {
|
||||
uint8_t value;
|
||||
SpindleStopBits bit;
|
||||
};
|
||||
|
||||
// Global system variables
|
||||
typedef struct {
|
||||
volatile State state; // Tracks the current system state of Grbl.
|
||||
bool abort; // System abort flag. Forces exit back to main loop for reset.
|
||||
Suspend suspend; // System suspend bitflag variable that manages holds, cancels, and safety door.
|
||||
bool soft_limit; // Tracks soft limit errors for the state machine. (boolean)
|
||||
StepControl step_control; // Governs the step segment generator depending on system state.
|
||||
bool probe_succeeded; // Tracks if last probing cycle was successful.
|
||||
AxisMask homing_axis_lock; // Locks axes when limits engage. Used as an axis motion mask in the stepper ISR.
|
||||
Percent f_override; // Feed rate override value in percent
|
||||
Percent r_override; // Rapids override value in percent
|
||||
Percent spindle_speed_ovr; // Spindle speed value in percent
|
||||
SpindleStop spindle_stop_ovr; // Tracks spindle stop override states
|
||||
Counter report_ovr_counter; // Tracks when to add override data to status reports.
|
||||
Counter report_wco_counter; // Tracks when to add work coordinate offset data to status reports.
|
||||
#ifdef ENABLE_PARKING_OVERRIDE_CONTROL
|
||||
Override override_ctrl; // Tracks override control states.
|
||||
#endif
|
||||
uint32_t spindle_speed;
|
||||
|
||||
} system_t;
|
||||
extern system_t sys;
|
||||
|
||||
// Define system executor bit map. Used internally by realtime protocol as realtime command flags,
|
||||
// System executor bit map. Used internally by realtime protocol as realtime command flags,
|
||||
// which notifies the main program to execute the specified realtime command asynchronously.
|
||||
// NOTE: The system executor uses an unsigned 8-bit volatile variable (8 flag limit.) The default
|
||||
// flags are always false, so the realtime protocol only needs to check for a non-zero value to
|
||||
// know when there is a realtime command to execute.
|
||||
#define EXEC_STATUS_REPORT bit(0) // bitmask 00000001
|
||||
#define EXEC_CYCLE_START bit(1) // bitmask 00000010
|
||||
// #define EXEC_CYCLE_STOP bit(2) // bitmask 00000100 moved to cycle_stop
|
||||
#define EXEC_FEED_HOLD bit(3) // bitmask 00001000
|
||||
#define EXEC_RESET bit(4) // bitmask 00010000
|
||||
#define EXEC_SAFETY_DOOR bit(5) // bitmask 00100000
|
||||
#define EXEC_MOTION_CANCEL bit(6) // bitmask 01000000
|
||||
#define EXEC_SLEEP bit(7) // bitmask 10000000
|
||||
struct ExecStateBits {
|
||||
uint8_t statusReport : 1;
|
||||
uint8_t cycleStart : 1;
|
||||
uint8_t cycleStop : 1; // Unused, per cycle_stop variable
|
||||
uint8_t feedHold : 1;
|
||||
uint8_t reset : 1;
|
||||
uint8_t safetyDoor : 1;
|
||||
uint8_t motionCancel : 1;
|
||||
uint8_t sleep : 1;
|
||||
};
|
||||
|
||||
union ExecState {
|
||||
uint8_t value;
|
||||
ExecStateBits bit;
|
||||
};
|
||||
|
||||
// Alarm executor codes. Valid values (1-255). Zero is reserved.
|
||||
enum class ExecAlarm : uint8_t {
|
||||
@@ -92,104 +147,60 @@ enum class ExecAlarm : uint8_t {
|
||||
|
||||
// Override bit maps. Realtime bitflags to control feed, rapid, spindle, and coolant overrides.
|
||||
// Spindle/coolant and feed/rapids are separated into two controlling flag variables.
|
||||
#define EXEC_FEED_OVR_RESET bit(0)
|
||||
#define EXEC_FEED_OVR_COARSE_PLUS bit(1)
|
||||
#define EXEC_FEED_OVR_COARSE_MINUS bit(2)
|
||||
#define EXEC_FEED_OVR_FINE_PLUS bit(3)
|
||||
#define EXEC_FEED_OVR_FINE_MINUS bit(4)
|
||||
#define EXEC_RAPID_OVR_RESET bit(5)
|
||||
#define EXEC_RAPID_OVR_MEDIUM bit(6)
|
||||
#define EXEC_RAPID_OVR_LOW bit(7)
|
||||
// #define EXEC_RAPID_OVR_EXTRA_LOW bit(*) // *NOT SUPPORTED*
|
||||
|
||||
#define EXEC_SPINDLE_OVR_RESET bit(0)
|
||||
#define EXEC_SPINDLE_OVR_COARSE_PLUS bit(1)
|
||||
#define EXEC_SPINDLE_OVR_COARSE_MINUS bit(2)
|
||||
#define EXEC_SPINDLE_OVR_FINE_PLUS bit(3)
|
||||
#define EXEC_SPINDLE_OVR_FINE_MINUS bit(4)
|
||||
#define EXEC_SPINDLE_OVR_STOP bit(5)
|
||||
#define EXEC_COOLANT_FLOOD_OVR_TOGGLE bit(6)
|
||||
#define EXEC_COOLANT_MIST_OVR_TOGGLE bit(7)
|
||||
struct ExecAccessoryBits {
|
||||
uint8_t spindleOvrStop : 1;
|
||||
uint8_t coolantFloodOvrToggle : 1;
|
||||
uint8_t coolantMistOvrToggle : 1;
|
||||
};
|
||||
|
||||
// Define system suspend flags. Used in various ways to manage suspend states and procedures.
|
||||
#define SUSPEND_DISABLE 0 // Must be zero.
|
||||
#define SUSPEND_HOLD_COMPLETE bit(0) // Indicates initial feed hold is complete.
|
||||
#define SUSPEND_RESTART_RETRACT bit(1) // Flag to indicate a retract from a restore parking motion.
|
||||
#define SUSPEND_RETRACT_COMPLETE bit(2) // (Safety door only) Indicates retraction and de-energizing is complete.
|
||||
#define SUSPEND_INITIATE_RESTORE bit(3) // (Safety door only) Flag to initiate resume procedures from a cycle start.
|
||||
#define SUSPEND_RESTORE_COMPLETE bit(4) // (Safety door only) Indicates ready to resume normal operation.
|
||||
#define SUSPEND_SAFETY_DOOR_AJAR bit(5) // Tracks safety door state for resuming.
|
||||
#define SUSPEND_MOTION_CANCEL bit(6) // Indicates a canceled resume motion. Currently used by probing routine.
|
||||
#define SUSPEND_JOG_CANCEL bit(7) // Indicates a jog cancel in process and to reset buffers when complete.
|
||||
union ExecAccessory {
|
||||
uint8_t value;
|
||||
ExecAccessoryBits bit;
|
||||
};
|
||||
|
||||
// Define step segment generator state flags.
|
||||
#define STEP_CONTROL_NORMAL_OP 0 // Must be zero.
|
||||
#define STEP_CONTROL_END_MOTION bit(0)
|
||||
#define STEP_CONTROL_EXECUTE_HOLD bit(1)
|
||||
#define STEP_CONTROL_EXECUTE_SYS_MOTION bit(2)
|
||||
#define STEP_CONTROL_UPDATE_SPINDLE_RPM bit(3)
|
||||
|
||||
// Define control pin index for Grbl internal use. Pin maps may change, but these values don't.
|
||||
//#ifdef ENABLE_SAFETY_DOOR_INPUT_PIN
|
||||
#define N_CONTROL_PIN 4
|
||||
#define CONTROL_PIN_INDEX_SAFETY_DOOR bit(0)
|
||||
#define CONTROL_PIN_INDEX_RESET bit(1)
|
||||
#define CONTROL_PIN_INDEX_FEED_HOLD bit(2)
|
||||
#define CONTROL_PIN_INDEX_CYCLE_START bit(3)
|
||||
#define CONTROL_PIN_INDEX_MACRO_0 bit(4)
|
||||
#define CONTROL_PIN_INDEX_MACRO_1 bit(5)
|
||||
#define CONTROL_PIN_INDEX_MACRO_2 bit(6)
|
||||
#define CONTROL_PIN_INDEX_MACRO_3 bit(7)
|
||||
//#else
|
||||
//#define N_CONTROL_PIN 3
|
||||
//#define CONTROL_PIN_INDEX_RESET bit(0)
|
||||
//#define CONTROL_PIN_INDEX_FEED_HOLD bit(1)
|
||||
//#define CONTROL_PIN_INDEX_CYCLE_START bit(2)
|
||||
//#endif
|
||||
|
||||
// Define spindle stop override control states.
|
||||
#define SPINDLE_STOP_OVR_DISABLED 0 // Must be zero.
|
||||
#define SPINDLE_STOP_OVR_ENABLED bit(0)
|
||||
#define SPINDLE_STOP_OVR_INITIATE bit(1)
|
||||
#define SPINDLE_STOP_OVR_RESTORE bit(2)
|
||||
#define SPINDLE_STOP_OVR_RESTORE_CYCLE bit(3)
|
||||
// Control pin states
|
||||
struct ControlPinBits {
|
||||
uint8_t safetyDoor : 1;
|
||||
uint8_t reset : 1;
|
||||
uint8_t feedHold : 1;
|
||||
uint8_t cycleStart : 1;
|
||||
uint8_t macro0 : 1;
|
||||
uint8_t macro1 : 1;
|
||||
uint8_t macro2 : 1;
|
||||
uint8_t macro3 : 1;
|
||||
};
|
||||
union ControlPins {
|
||||
uint8_t value;
|
||||
ControlPinBits bit;
|
||||
};
|
||||
|
||||
// NOTE: These position variables may need to be declared as volatiles, if problems arise.
|
||||
extern int32_t sys_position[MAX_N_AXIS]; // Real-time machine (aka home) position vector in steps.
|
||||
extern int32_t sys_probe_position[MAX_N_AXIS]; // Last probe position in machine coordinates and steps.
|
||||
|
||||
extern volatile uint8_t sys_probe_state; // Probing state value. Used to coordinate the probing cycle with stepper ISR.
|
||||
extern volatile uint8_t sys_rt_exec_state; // Global realtime executor bitflag variable for state management. See EXEC bitmasks.
|
||||
extern volatile ExecAlarm sys_rt_exec_alarm; // Global realtime executor bitflag variable for setting various alarms.
|
||||
extern volatile uint8_t sys_rt_exec_motion_override; // Global realtime executor bitflag variable for motion-based overrides.
|
||||
extern volatile uint8_t sys_rt_exec_accessory_override; // Global realtime executor bitflag variable for spindle/coolant overrides.
|
||||
extern volatile bool cycle_stop;
|
||||
|
||||
extern volatile Probe sys_probe_state; // Probing state value. Used to coordinate the probing cycle with stepper ISR.
|
||||
extern volatile ExecState sys_rt_exec_state; // Global realtime executor bitflag variable for state management. See EXEC bitmasks.
|
||||
extern volatile ExecAlarm sys_rt_exec_alarm; // Global realtime executor bitflag variable for setting various alarms.
|
||||
extern volatile ExecAccessory sys_rt_exec_accessory_override; // Global realtime executor bitflag variable for spindle/coolant overrides.
|
||||
extern volatile Percent sys_rt_f_override; // Feed override value in percent
|
||||
extern volatile Percent sys_rt_r_override; // Rapid feed override value in percent
|
||||
extern volatile Percent sys_rt_s_override; // Spindle override value in percent
|
||||
extern volatile bool cycle_stop;
|
||||
#ifdef DEBUG
|
||||
# define EXEC_DEBUG_REPORT bit(0)
|
||||
extern volatile uint8_t sys_rt_exec_debug;
|
||||
extern volatile bool sys_rt_exec_debug;
|
||||
#endif
|
||||
|
||||
void system_ini(); // Renamed from system_init() due to conflict with esp32 files
|
||||
|
||||
// Returns bitfield of control pin states, organized by CONTROL_PIN_INDEX. (1=triggered, 0=not triggered).
|
||||
uint8_t system_control_get_state();
|
||||
ControlPins system_control_get_state();
|
||||
|
||||
// Returns if safety door is ajar(T) or closed(F), based on pin state.
|
||||
uint8_t system_check_safety_door_ajar();
|
||||
|
||||
void isr_control_inputs();
|
||||
|
||||
// Special handlers for setting and clearing Grbl's real-time execution flags.
|
||||
void system_set_exec_state_flag(uint8_t mask);
|
||||
void system_clear_exec_state_flag(uint8_t mask);
|
||||
void system_set_exec_alarm(ExecAlarm code);
|
||||
void system_clear_exec_alarm();
|
||||
void system_set_exec_motion_override_flag(uint8_t mask);
|
||||
void system_set_exec_accessory_override_flag(uint8_t mask);
|
||||
void system_clear_exec_motion_overrides();
|
||||
void system_clear_exec_accessory_overrides();
|
||||
|
||||
// Execute the startup script lines stored in non-volatile storage upon initialization
|
||||
void system_execute_startup(char* line);
|
||||
Error execute_line(char* line, uint8_t client, WebUI::AuthenticationLevel auth_level);
|
||||
@@ -207,27 +218,16 @@ void system_convert_array_steps_to_mpos(float* position, int32_t* steps);
|
||||
// Checks and reports if target array exceeds machine travel limits.
|
||||
uint8_t system_check_travel_limits(float* target);
|
||||
|
||||
// Special handlers for setting and clearing Grbl's real-time execution flags.
|
||||
void system_set_exec_state_flag(uint8_t mask);
|
||||
void system_clear_exec_state_flag(uint8_t mask);
|
||||
void system_set_exec_alarm(ExecAlarm code);
|
||||
void system_clear_exec_alarm();
|
||||
void system_set_exec_motion_override_flag(uint8_t mask);
|
||||
void system_set_exec_accessory_override_flag(uint8_t mask);
|
||||
void system_clear_exec_motion_overrides();
|
||||
void system_clear_exec_accessory_overrides();
|
||||
|
||||
int32_t system_convert_corexy_to_x_axis_steps(int32_t* steps);
|
||||
int32_t system_convert_corexy_to_y_axis_steps(int32_t* steps);
|
||||
|
||||
// A task that runs after a control switch interrupt for debouncing.
|
||||
void controlCheckTask(void* pvParameters);
|
||||
void system_exec_control_pin(uint8_t pin);
|
||||
void system_exec_control_pin(ControlPins pins);
|
||||
|
||||
bool sys_io_control(uint8_t io_num_mask, bool turnOn, bool synchronized);
|
||||
bool sys_pwm_control(uint8_t io_num_mask, float duty, bool synchronized);
|
||||
|
||||
int8_t sys_get_next_RMT_chan_num();
|
||||
|
||||
int8_t sys_get_next_RMT_chan_num();
|
||||
int8_t sys_get_next_PWM_chan_num();
|
||||
uint8_t sys_calc_pwm_precision(uint32_t freq);
|
||||
|
@@ -430,35 +430,7 @@ namespace WebUI {
|
||||
}
|
||||
# endif
|
||||
|
||||
bool Web_Server::is_realtime_cmd(char c) {
|
||||
switch (c) {
|
||||
case CMD_STATUS_REPORT:
|
||||
case CMD_CYCLE_START:
|
||||
case CMD_RESET:
|
||||
case CMD_FEED_HOLD:
|
||||
case CMD_SAFETY_DOOR:
|
||||
case CMD_JOG_CANCEL:
|
||||
case CMD_DEBUG_REPORT:
|
||||
case CMD_FEED_OVR_RESET:
|
||||
case CMD_FEED_OVR_COARSE_PLUS:
|
||||
case CMD_FEED_OVR_COARSE_MINUS:
|
||||
case CMD_FEED_OVR_FINE_PLUS:
|
||||
case CMD_FEED_OVR_FINE_MINUS:
|
||||
case CMD_RAPID_OVR_RESET:
|
||||
case CMD_RAPID_OVR_MEDIUM:
|
||||
case CMD_RAPID_OVR_LOW:
|
||||
case CMD_SPINDLE_OVR_COARSE_PLUS:
|
||||
case CMD_SPINDLE_OVR_COARSE_MINUS:
|
||||
case CMD_SPINDLE_OVR_FINE_PLUS:
|
||||
case CMD_SPINDLE_OVR_FINE_MINUS:
|
||||
case CMD_SPINDLE_OVR_STOP:
|
||||
case CMD_COOLANT_FLOOD_OVR_TOGGLE:
|
||||
case CMD_COOLANT_MIST_OVR_TOGGLE:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
bool Web_Server::is_realtime_cmd(char c) { return is_realtime_cmd(c); }
|
||||
|
||||
void Web_Server::_handle_web_command(bool silent) {
|
||||
//to save time if already disconnected
|
||||
|
Reference in New Issue
Block a user