1
0
mirror of https://github.com/bdring/Grbl_Esp32.git synced 2025-08-31 10:01:48 +02:00

Added better error reporting for incorrect configs. Added ConfigAlarm state, which you can't get out off so easily - but you are still able to upload, use files, etc.

This commit is contained in:
Stefan de Bruijn
2021-06-08 21:00:08 +02:00
parent f38bc96195
commit 3bbe92a48d
13 changed files with 53 additions and 15 deletions

View File

@@ -71,12 +71,14 @@ void grbl_init() {
machine_init(); // user supplied function for special initialization
// Initialize system state.
if (sys.state != State::ConfigAlarm) {
#ifdef FORCE_INITIALIZATION_ALARM
// Force Grbl into an ALARM state upon a power-cycle or hard reset.
sys.state = State::Alarm;
// Force Grbl into an ALARM state upon a power-cycle or hard reset.
sys.state = State::Alarm;
#else
sys.state = State::Idle;
sys.state = State::Idle;
#endif
}
// Check for power-up and set system alarm if homing is enabled to force homing cycle
// by setting Grbl's alarm state. Alarm locks out all g-code commands, including the
// startup scripts, but allows access to settings and internal commands. Only a homing
@@ -84,7 +86,7 @@ void grbl_init() {
// NOTE: The startup script will run after successful completion of the homing cycle, but
// not after disabling the alarm locks. Prevents motion startup blocks from crashing into
// things uncontrollably. Very bad.
if (config->_homingInitLock && homingAxes()) {
if (config->_homingInitLock && homingAxes() && sys.state != State::ConfigAlarm) {
// If there is an axis with homing configured, enter Alarm state on startup
sys.state = State::Alarm;
}
@@ -108,6 +110,7 @@ void grbl_init() {
} catch (const AssertionFailed& ex) {
// This means something is terribly broken:
info_serial("Critical error in run_once: %s", ex.what());
sys.state = State::ConfigAlarm;
sleep(10000);
throw;
}

View File

@@ -46,7 +46,7 @@ void IRAM_ATTR isr_limit_switches(void* /*unused */) {
// moves in the planner and serial buffers are all cleared and newly sent blocks will be
// locked out until a homing cycle or a kill lock command. Allows the user to disable the hard
// limit setting if their limits are constantly triggering after a reset and move their axes.
if (sys.state != State::Alarm && sys.state != State::Homing) {
if (sys.state != State::Alarm && sys.state != State::ConfigAlarm && sys.state != State::Homing) {
if (sys_rt_exec_alarm == ExecAlarm::None) {
#ifdef ENABLE_SOFTWARE_DEBOUNCE
// we will start a task that will recheck the switches after a small delay

View File

@@ -570,18 +570,22 @@ bool MachineConfig::load(const char* filename) {
// That way, we can always check if the yaml is there, and if it's not, load the yaml.new.
} catch (const Configuration::ParseException& ex) {
sys.state = State::ConfigAlarm;
auto startNear = ex.Near();
auto endNear = (startNear + 10) > (buffer + filesize) ? (buffer + filesize) : (startNear + 10);
StringRange near(startNear, endNear);
log_error("Configuration parse error: " << ex.What() << " @ " << ex.LineNumber() << ":" << ex.ColumnNumber() << " near " << near);
} catch (const AssertionFailed& ex) {
sys.state = State::ConfigAlarm;
// Get rid of buffer and return
log_error("Configuration loading failed: " << ex.what());
} catch (std::exception& ex) {
sys.state = State::ConfigAlarm;
// Log exception:
log_error("Configuration validation error: " << ex.what());
} catch (...) {
sys.state = State::ConfigAlarm;
// Get rid of buffer and return
log_error("Unknown error while processing config file");
}

View File

@@ -321,7 +321,7 @@ public:
class MachineConfig : public Configuration::Configurable {
public:
MachineConfig() = default;
Axes* _axes = nullptr;
SPIBus* _spi = nullptr;
I2SOBus* _i2so = nullptr;

View File

@@ -20,8 +20,6 @@
along with Grbl. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Config.h"
// #define false 0
// #define true 1

View File

@@ -41,7 +41,7 @@
#endif
Pins::PinDetail* Pin::undefinedPin = new Pins::VoidPinDetail();
Pins::PinDetail* Pin::errorPin = new Pins::ErrorPinDetail();
Pins::PinDetail* Pin::errorPin = new Pins::ErrorPinDetail("unknown");
bool Pin::parse(StringRange tmp, Pins::PinDetail*& pinImplementation) {
String str = tmp.str();
@@ -151,7 +151,7 @@ Pin Pin::create(const StringRange& str) {
pin_error("Setting up pin [%s] failed. Details: %s\r\n", str.str().c_str(), ex.what());
(void)ex; // Get rid of compiler warning
return Pin(pinImplementation);
return Pin(new Pins::ErrorPinDetail(str.str()));
}
}

View File

@@ -19,15 +19,30 @@
#include "ErrorPinDetail.h"
#include "../Assert.h"
#ifdef ESP32
#include "../Report.h"
#endif
namespace Pins {
ErrorPinDetail::ErrorPinDetail() : PinDetail(0) {}
ErrorPinDetail::ErrorPinDetail(const String& descr) : PinDetail(0), _description(descr) {}
PinCapabilities ErrorPinDetail::capabilities() const { return PinCapabilities::Error; }
#ifdef ESP32
void ErrorPinDetail::write(int high) { info_all("Cannot write to pin %s. The config is incorrect.", _description.c_str()); }
int ErrorPinDetail::read() { info_all("Cannot read from pin %s. The config is incorrect.", _description.c_str()); }
void ErrorPinDetail::setAttr(PinAttributes value) {
info_all("Cannot set mode on pin %s. The config is incorrect.", _description.c_str());
}
#else
void ErrorPinDetail::write(int high) { Assert(false, "Cannot write to an error pin."); }
int ErrorPinDetail::read() { Assert(false, "Cannot read from an error pin."); }
void ErrorPinDetail::setAttr(PinAttributes value) { /* Fine, this won't get you anywhere. */
}
#endif
PinAttributes ErrorPinDetail::getAttr() const { return PinAttributes::None; }
String ErrorPinDetail::toString() { return "ERROR_PIN"; }

View File

@@ -23,8 +23,10 @@
namespace Pins {
class ErrorPinDetail : public PinDetail {
String _description;
public:
ErrorPinDetail();
ErrorPinDetail(const String& descr);
PinCapabilities capabilities() const override;

View File

@@ -87,7 +87,7 @@ Error execute_line(char* line, uint8_t client, WebUI::AuthenticationLevel auth_l
return system_execute_line(line, client, auth_level);
}
// Everything else is gcode. Block if in alarm or jog mode.
if (sys.state == State::Alarm || sys.state == State::Jog) {
if (sys.state == State::Alarm || sys.state == State::ConfigAlarm || sys.state == State::Jog) {
return Error::SystemGcLock;
}
return gc_execute_line(line, client);
@@ -137,7 +137,9 @@ void protocol_main_loop() {
// Check for and report alarm state after a reset, error, or an initial power up.
// NOTE: Sleep mode disables the stepper drivers and position can't be guaranteed.
// Re-initialize the sleep state as an ALARM mode to ensure user homes or acknowledges.
if (sys.state == State::Alarm || sys.state == State::Sleep) {
if (sys.state == State::ConfigAlarm) {
report_feedback_message(Message::AlarmLock);
} else if (sys.state == State::Alarm || sys.state == State::Sleep) {
report_feedback_message(Message::AlarmLock);
sys.state = State::Alarm; // Ensure alarm state is set.
} else {
@@ -325,6 +327,7 @@ static void protocol_do_motion_cancel() {
// will handle and clear multiple planner block motions.
switch (sys.state) {
case State::Alarm:
case State::ConfigAlarm:
case State::CheckMode:
return; // Do not set motionCancel
@@ -356,6 +359,7 @@ static void protocol_do_feedhold() {
rtFeedHold = false;
rtCycleStart = false; // Cancel any pending start
switch (sys.state) {
case State::ConfigAlarm:
case State::Alarm:
case State::CheckMode:
case State::SafetyDoor:
@@ -390,6 +394,8 @@ static void protocol_do_safety_door() {
rtCycleStart = false; // Cancel any pending start
report_feedback_message(Message::SafetyDoorAjar);
switch (sys.state) {
case State::ConfigAlarm:
return;
case State::Alarm:
case State::CheckMode:
case State::Sleep:
@@ -443,6 +449,7 @@ static void protocol_do_safety_door() {
static void protocol_do_sleep() {
rtSleep = false;
switch (sys.state) {
case State::ConfigAlarm:
case State::Alarm:
sys.suspend.bit.retractComplete = true;
sys.suspend.bit.holdComplete = true;
@@ -518,6 +525,7 @@ static void protocol_do_cycle_start() {
}
}
break;
case State::ConfigAlarm:
case State::Alarm:
case State::CheckMode:
case State::Sleep:
@@ -552,6 +560,7 @@ static void protocol_do_cycle_stop() {
break;
}
// Fall through
case State::ConfigAlarm:
case State::Alarm:
case State::CheckMode:
case State::Idle:
@@ -686,6 +695,7 @@ void protocol_exec_rt_system() {
#endif
// Reload step segment buffer
switch (sys.state) {
case State::ConfigAlarm:
case State::Alarm:
case State::CheckMode:
case State::Idle:

View File

@@ -858,6 +858,7 @@ char* report_state_text() {
case State::Homing:
strcpy(state, "Home");
break;
case State::ConfigAlarm:
case State::Alarm:
strcpy(state, "Alarm");
break;

View File

@@ -1,6 +1,10 @@
#pragma once
#include "Error.h"
#include "NutsBolts.h"
#include "Exec.h"
#include <FreeRTOS.h>
/*
Report.h - Header for system level commands and real-time processes

View File

@@ -40,6 +40,7 @@ enum class State : uint8_t {
Jog, // Jogging mode.
SafetyDoor, // Safety door is ajar. Feed holds and de-energizes system.
Sleep, // Sleep state.
ConfigAlarm, // You can't do anything but fix your config file.
};
// Step segment generator state flags.

View File

@@ -678,7 +678,7 @@ namespace WebUI {
static Error runSDFile(char* parameter, AuthenticationLevel auth_level) { // ESP220
Error err;
if (sys.state == State::Alarm) {
if (sys.state == State::Alarm || sys.state == State::ConfigAlarm) {
webPrintln("Alarm");
return Error::IdleError;
}