mirror of
https://github.com/bdring/Grbl_Esp32.git
synced 2025-08-30 09:39:49 +02:00
Added $A AKA Alarms/List command (#654)
* Added $A AKA Alarms/List command Similar to $E AKA Errors/List $E used to be AKA ErrorCodes/List Also added $Errors/Verbose setting to display full error text instead of the error number. It defaults to true because it works with every sender I have tried so far - cncjs, UGS, and Chrome GCode Sender. If you have problems with some sender you can set it to false. * Added static_assert per atlaste's comment * Added a default and fixed Authentication issue Co-authored-by: bdring <barton.dring@gmail.com>
This commit is contained in:
@@ -70,6 +70,10 @@
|
|||||||
# define DEFAULT_STATUS_REPORT_MASK 1 // $10
|
# define DEFAULT_STATUS_REPORT_MASK 1 // $10
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef DEFAULT_VERBOSE_ERRORS
|
||||||
|
# define DEFAULT_VERBOSE_ERRORS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef DEFAULT_JUNCTION_DEVIATION
|
#ifndef DEFAULT_JUNCTION_DEVIATION
|
||||||
# define DEFAULT_JUNCTION_DEVIATION 0.01 // $11 mm
|
# define DEFAULT_JUNCTION_DEVIATION 0.01 // $11 mm
|
||||||
#endif
|
#endif
|
||||||
|
@@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
#include "Error.h"
|
#include "Error.h"
|
||||||
|
|
||||||
std::map<Error, const char*> ErrorCodes = {
|
std::map<Error, const char*> ErrorNames = {
|
||||||
{ Error::Ok, "No error" },
|
{ Error::Ok, "No error" },
|
||||||
{ Error::ExpectedCommandLetter, "Expected GCodecommand letter" },
|
{ Error::ExpectedCommandLetter, "Expected GCodecommand letter" },
|
||||||
{ Error::BadNumberFormat, "Bad GCode number format" },
|
{ Error::BadNumberFormat, "Bad GCode number format" },
|
||||||
|
@@ -85,4 +85,4 @@ enum class Error : uint8_t {
|
|||||||
Eol = 111,
|
Eol = 111,
|
||||||
};
|
};
|
||||||
|
|
||||||
extern std::map<Error, const char*> ErrorCodes;
|
extern std::map<Error, const char*> ErrorNames;
|
||||||
|
15
Grbl_Esp32/src/Exec.cpp
Normal file
15
Grbl_Esp32/src/Exec.cpp
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#include "Exec.h"
|
||||||
|
|
||||||
|
std::map<ExecAlarm, const char*> AlarmNames = {
|
||||||
|
{ ExecAlarm::None, "None"},
|
||||||
|
{ ExecAlarm::HardLimit, "Hard Limit"},
|
||||||
|
{ ExecAlarm::SoftLimit, "Soft Limit"},
|
||||||
|
{ ExecAlarm::AbortCycle, "Abort Cycle"},
|
||||||
|
{ ExecAlarm::ProbeFailInitial, "Probe Fail Initial"},
|
||||||
|
{ ExecAlarm::ProbeFailContact, "Probe Fail Contact"},
|
||||||
|
{ ExecAlarm::HomingFailReset, "Homing Fail Reset"},
|
||||||
|
{ ExecAlarm::HomingFailDoor, "Homing Fail Door"},
|
||||||
|
{ ExecAlarm::HomingFailPulloff, "Homing Fail Pulloff"},
|
||||||
|
{ ExecAlarm::HomingFailApproach, "Homing Fail Approach"},
|
||||||
|
{ ExecAlarm::SpindleControl, "Spindle Control"},
|
||||||
|
};
|
57
Grbl_Esp32/src/Exec.h
Normal file
57
Grbl_Esp32/src/Exec.h
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(ExecStateBits) == sizeof(uint8_t), "ExecStateBits is not an uint8");
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
struct ExecAccessoryBits {
|
||||||
|
uint8_t spindleOvrStop : 1;
|
||||||
|
uint8_t coolantFloodOvrToggle : 1;
|
||||||
|
uint8_t coolantMistOvrToggle : 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
union ExecAccessory {
|
||||||
|
uint8_t value;
|
||||||
|
ExecAccessoryBits bit;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Alarm codes.
|
||||||
|
enum class ExecAlarm : uint8_t {
|
||||||
|
None = 0,
|
||||||
|
HardLimit = 1,
|
||||||
|
SoftLimit = 2,
|
||||||
|
AbortCycle = 3,
|
||||||
|
ProbeFailInitial = 4,
|
||||||
|
ProbeFailContact = 5,
|
||||||
|
HomingFailReset = 6,
|
||||||
|
HomingFailDoor = 7,
|
||||||
|
HomingFailPulloff = 8,
|
||||||
|
HomingFailApproach = 9,
|
||||||
|
SpindleControl = 10,
|
||||||
|
};
|
||||||
|
|
||||||
|
extern std::map<ExecAlarm, const char*> AlarmNames;
|
@@ -325,12 +325,42 @@ Error doJog(const char* value, WebUI::AuthenticationLevel auth_level, WebUI::ESP
|
|||||||
return gc_execute_line(jogLine, out->client());
|
return gc_execute_line(jogLine, out->client());
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* errorString(Error errorNumber) {
|
const char* alarmString(ExecAlarm alarmNumber) {
|
||||||
auto it = ErrorCodes.find(errorNumber);
|
auto it = AlarmNames.find(alarmNumber);
|
||||||
return it == ErrorCodes.end() ? NULL : it->second;
|
return it == AlarmNames.end() ? NULL : it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error listErrorCodes(const char* value, WebUI::AuthenticationLevel auth_level, WebUI::ESPResponseStream* out) {
|
Error listAlarms(const char* value, WebUI::AuthenticationLevel auth_level, WebUI::ESPResponseStream* out) {
|
||||||
|
if (value) {
|
||||||
|
char* endptr = NULL;
|
||||||
|
uint8_t alarmNumber = strtol(value, &endptr, 10);
|
||||||
|
if (*endptr) {
|
||||||
|
grbl_sendf(out->client(), "Malformed alarm number: %s\r\n", value);
|
||||||
|
return Error::InvalidValue;
|
||||||
|
}
|
||||||
|
const char* alarmName = alarmString(static_cast<ExecAlarm>(alarmNumber));
|
||||||
|
if (alarmName) {
|
||||||
|
grbl_sendf(out->client(), "%d: %s\r\n", alarmNumber, alarmName);
|
||||||
|
return Error::Ok;
|
||||||
|
} else {
|
||||||
|
grbl_sendf(out->client(), "Unknown alarm number: %d\r\n", alarmNumber);
|
||||||
|
return Error::InvalidValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto it = AlarmNames.begin(); it != AlarmNames.end(); it++) {
|
||||||
|
grbl_sendf(out->client(), "%d: %s\r\n", it->first, it->second);
|
||||||
|
}
|
||||||
|
return Error::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char* errorString(Error errorNumber) {
|
||||||
|
auto it = ErrorNames.find(errorNumber);
|
||||||
|
return it == ErrorNames.end() ? NULL : it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
Error listErrors(const char* value, WebUI::AuthenticationLevel auth_level, WebUI::ESPResponseStream* out) {
|
||||||
if (value) {
|
if (value) {
|
||||||
char* endptr = NULL;
|
char* endptr = NULL;
|
||||||
uint8_t errorNumber = strtol(value, &endptr, 10);
|
uint8_t errorNumber = strtol(value, &endptr, 10);
|
||||||
@@ -348,7 +378,7 @@ Error listErrorCodes(const char* value, WebUI::AuthenticationLevel auth_level, W
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto it = ErrorCodes.begin(); it != ErrorCodes.end(); it++) {
|
for (auto it = ErrorNames.begin(); it != ErrorNames.end(); it++) {
|
||||||
grbl_sendf(out->client(), "%d: %s\r\n", it->first, it->second);
|
grbl_sendf(out->client(), "%d: %s\r\n", it->first, it->second);
|
||||||
}
|
}
|
||||||
return Error::Ok;
|
return Error::Ok;
|
||||||
@@ -383,7 +413,8 @@ void make_grbl_commands() {
|
|||||||
new GrblCommand("S", "Settings/List", list_settings, notCycleOrHold);
|
new GrblCommand("S", "Settings/List", list_settings, notCycleOrHold);
|
||||||
new GrblCommand("SC", "Settings/ListChanged", list_changed_settings, notCycleOrHold);
|
new GrblCommand("SC", "Settings/ListChanged", list_changed_settings, notCycleOrHold);
|
||||||
new GrblCommand("CMD", "Commands/List", list_commands, notCycleOrHold);
|
new GrblCommand("CMD", "Commands/List", list_commands, notCycleOrHold);
|
||||||
new GrblCommand("E", "ErrorCodes/List", listErrorCodes, anyState);
|
new GrblCommand("A", "Alarms/List", listAlarms, anyState);
|
||||||
|
new GrblCommand("E", "Errors/List", listErrors, anyState);
|
||||||
new GrblCommand("G", "GCode/Modes", report_gcode, anyState);
|
new GrblCommand("G", "GCode/Modes", report_gcode, anyState);
|
||||||
new GrblCommand("C", "GCode/Check", toggle_check_mode, anyState);
|
new GrblCommand("C", "GCode/Check", toggle_check_mode, anyState);
|
||||||
new GrblCommand("X", "Alarm/Disable", disable_alarm_lock, anyState);
|
new GrblCommand("X", "Alarm/Disable", disable_alarm_lock, anyState);
|
||||||
|
@@ -247,7 +247,14 @@ void report_status_message(Error status_code, uint8_t client) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
grbl_sendf(client, "error:%d\r\n", static_cast<int>(status_code));
|
// With verbose errors, the message text is displayed instead of the number.
|
||||||
|
// Grbl 0.9 used to display the text, while Grbl 1.1 switched to the number.
|
||||||
|
// Many senders support both formats.
|
||||||
|
if (verbose_errors->get()) {
|
||||||
|
grbl_sendf(client, "error: %s\r\n", errorString(status_code));
|
||||||
|
} else {
|
||||||
|
grbl_sendf(client, "error:%d\r\n", static_cast<int>(status_code));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
bool motorSettingChanged = false;
|
bool motorSettingChanged = false;
|
||||||
|
|
||||||
|
FlagSetting* verbose_errors;
|
||||||
|
|
||||||
FakeSetting<int>* number_axis;
|
FakeSetting<int>* number_axis;
|
||||||
|
|
||||||
StringSetting* startup_line_0;
|
StringSetting* startup_line_0;
|
||||||
@@ -237,6 +239,8 @@ void make_settings() {
|
|||||||
make_coordinate(CoordIndex::G28, "G28");
|
make_coordinate(CoordIndex::G28, "G28");
|
||||||
make_coordinate(CoordIndex::G30, "G30");
|
make_coordinate(CoordIndex::G30, "G30");
|
||||||
|
|
||||||
|
verbose_errors = new FlagSetting(EXTENDED, WG, NULL, "Errors/Verbose", DEFAULT_VERBOSE_ERRORS);
|
||||||
|
|
||||||
// number_axis = new IntSetting(EXTENDED, WG, NULL, "NumberAxis", N_AXIS, 0, 6, NULL, true);
|
// number_axis = new IntSetting(EXTENDED, WG, NULL, "NumberAxis", N_AXIS, 0, 6, NULL, true);
|
||||||
number_axis = new FakeSetting<int>(N_AXIS);
|
number_axis = new FakeSetting<int>(N_AXIS);
|
||||||
|
|
||||||
|
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
extern bool motorSettingChanged;
|
extern bool motorSettingChanged;
|
||||||
|
|
||||||
|
extern FlagSetting* verbose_errors;
|
||||||
|
|
||||||
extern FakeSetting<int>* number_axis;
|
extern FakeSetting<int>* number_axis;
|
||||||
|
|
||||||
extern AxisSettings* x_axis_settings;
|
extern AxisSettings* x_axis_settings;
|
||||||
|
@@ -20,6 +20,9 @@
|
|||||||
along with Grbl. If not, see <http://www.gnu.org/licenses/>.
|
along with Grbl. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Execution states and alarm
|
||||||
|
#include "Exec.h"
|
||||||
|
|
||||||
// System states. The state variable primarily tracks the individual functions
|
// System states. The state variable primarily tracks the individual functions
|
||||||
// of Grbl to manage each without overlapping. It is also used as a messaging flag for
|
// of Grbl to manage each without overlapping. It is also used as a messaging flag for
|
||||||
// critical events.
|
// critical events.
|
||||||
@@ -107,56 +110,6 @@ typedef struct {
|
|||||||
} system_t;
|
} system_t;
|
||||||
extern system_t sys;
|
extern system_t sys;
|
||||||
|
|
||||||
// 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.
|
|
||||||
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 {
|
|
||||||
None = 0,
|
|
||||||
HardLimit = 1,
|
|
||||||
SoftLimit = 2,
|
|
||||||
AbortCycle = 3,
|
|
||||||
ProbeFailInitial = 4,
|
|
||||||
ProbeFailContact = 5,
|
|
||||||
HomingFailReset = 6,
|
|
||||||
HomingFailDoor = 7,
|
|
||||||
HomingFailPulloff = 8,
|
|
||||||
HomingFailApproach = 9,
|
|
||||||
SpindleControl = 10,
|
|
||||||
};
|
|
||||||
|
|
||||||
// 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.
|
|
||||||
|
|
||||||
struct ExecAccessoryBits {
|
|
||||||
uint8_t spindleOvrStop : 1;
|
|
||||||
uint8_t coolantFloodOvrToggle : 1;
|
|
||||||
uint8_t coolantMistOvrToggle : 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
union ExecAccessory {
|
|
||||||
uint8_t value;
|
|
||||||
ExecAccessoryBits bit;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Control pin states
|
// Control pin states
|
||||||
struct ControlPinBits {
|
struct ControlPinBits {
|
||||||
uint8_t safetyDoor : 1;
|
uint8_t safetyDoor : 1;
|
||||||
|
@@ -306,9 +306,9 @@ namespace WebUI {
|
|||||||
return Error::SdFailedOpenFile;
|
return Error::SdFailedOpenFile;
|
||||||
}
|
}
|
||||||
//until no line in file
|
//until no line in file
|
||||||
Error err;
|
Error err;
|
||||||
Error accumErr = Error::Ok;
|
Error accumErr = Error::Ok;
|
||||||
uint8_t client = (espresponse) ? espresponse->client() : CLIENT_ALL;
|
uint8_t client = (espresponse) ? espresponse->client() : CLIENT_ALL;
|
||||||
while (currentfile.available()) {
|
while (currentfile.available()) {
|
||||||
String currentline = currentfile.readStringUntil('\n');
|
String currentline = currentfile.readStringUntil('\n');
|
||||||
if (currentline.length() > 0) {
|
if (currentline.length() > 0) {
|
||||||
@@ -398,7 +398,7 @@ namespace WebUI {
|
|||||||
user_password->setDefault();
|
user_password->setDefault();
|
||||||
return Error::Ok;
|
return Error::Ok;
|
||||||
}
|
}
|
||||||
if (user_password->setStringValue(parameter)) {
|
if (user_password->setStringValue(parameter) != Error::Ok) {
|
||||||
webPrintln("Invalid Password");
|
webPrintln("Invalid Password");
|
||||||
return Error::InvalidValue;
|
return Error::InvalidValue;
|
||||||
}
|
}
|
||||||
@@ -730,7 +730,7 @@ namespace WebUI {
|
|||||||
webPrintln("");
|
webPrintln("");
|
||||||
return Error::Ok;
|
return Error::Ok;
|
||||||
}
|
}
|
||||||
SD_client = (espresponse) ? espresponse->client() : CLIENT_ALL;
|
SD_client = (espresponse) ? espresponse->client() : CLIENT_ALL;
|
||||||
SD_auth_level = auth_level;
|
SD_auth_level = auth_level;
|
||||||
// execute the first line now; Protocol.cpp handles later ones when SD_ready_next
|
// execute the first line now; Protocol.cpp handles later ones when SD_ready_next
|
||||||
report_status_message(execute_line(fileLine, SD_client, SD_auth_level), SD_client);
|
report_status_message(execute_line(fileLine, SD_client, SD_auth_level), SD_client);
|
||||||
|
Reference in New Issue
Block a user