diff --git a/Grbl_Esp32/src/Grbl.cpp b/Grbl_Esp32/src/Grbl.cpp
index d0b2199f..3eb8c382 100644
--- a/Grbl_Esp32/src/Grbl.cpp
+++ b/Grbl_Esp32/src/Grbl.cpp
@@ -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;
}
diff --git a/Grbl_Esp32/src/Limits.cpp b/Grbl_Esp32/src/Limits.cpp
index bfdda4b7..d273dbb6 100644
--- a/Grbl_Esp32/src/Limits.cpp
+++ b/Grbl_Esp32/src/Limits.cpp
@@ -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
diff --git a/Grbl_Esp32/src/MachineConfig.cpp b/Grbl_Esp32/src/MachineConfig.cpp
index 137e2517..fc9abf71 100644
--- a/Grbl_Esp32/src/MachineConfig.cpp
+++ b/Grbl_Esp32/src/MachineConfig.cpp
@@ -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");
}
diff --git a/Grbl_Esp32/src/MachineConfig.h b/Grbl_Esp32/src/MachineConfig.h
index bdae0827..e88f852f 100644
--- a/Grbl_Esp32/src/MachineConfig.h
+++ b/Grbl_Esp32/src/MachineConfig.h
@@ -321,7 +321,7 @@ public:
class MachineConfig : public Configuration::Configurable {
public:
MachineConfig() = default;
-
+
Axes* _axes = nullptr;
SPIBus* _spi = nullptr;
I2SOBus* _i2so = nullptr;
diff --git a/Grbl_Esp32/src/NutsBolts.h b/Grbl_Esp32/src/NutsBolts.h
index 189b8492..8c1d0833 100644
--- a/Grbl_Esp32/src/NutsBolts.h
+++ b/Grbl_Esp32/src/NutsBolts.h
@@ -20,8 +20,6 @@
along with Grbl. If not, see .
*/
-#include "Config.h"
-
// #define false 0
// #define true 1
diff --git a/Grbl_Esp32/src/Pin.cpp b/Grbl_Esp32/src/Pin.cpp
index 1bf2689c..05bc9d4f 100644
--- a/Grbl_Esp32/src/Pin.cpp
+++ b/Grbl_Esp32/src/Pin.cpp
@@ -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()));
}
}
diff --git a/Grbl_Esp32/src/Pins/ErrorPinDetail.cpp b/Grbl_Esp32/src/Pins/ErrorPinDetail.cpp
index 8eaa99c7..a61aba45 100644
--- a/Grbl_Esp32/src/Pins/ErrorPinDetail.cpp
+++ b/Grbl_Esp32/src/Pins/ErrorPinDetail.cpp
@@ -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"; }
diff --git a/Grbl_Esp32/src/Pins/ErrorPinDetail.h b/Grbl_Esp32/src/Pins/ErrorPinDetail.h
index 5a1af166..73a34b96 100644
--- a/Grbl_Esp32/src/Pins/ErrorPinDetail.h
+++ b/Grbl_Esp32/src/Pins/ErrorPinDetail.h
@@ -23,8 +23,10 @@
namespace Pins {
class ErrorPinDetail : public PinDetail {
+ String _description;
+
public:
- ErrorPinDetail();
+ ErrorPinDetail(const String& descr);
PinCapabilities capabilities() const override;
diff --git a/Grbl_Esp32/src/Protocol.cpp b/Grbl_Esp32/src/Protocol.cpp
index 6afcddb5..892238c3 100644
--- a/Grbl_Esp32/src/Protocol.cpp
+++ b/Grbl_Esp32/src/Protocol.cpp
@@ -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:
diff --git a/Grbl_Esp32/src/Report.cpp b/Grbl_Esp32/src/Report.cpp
index 864d2b06..cd85bc2e 100644
--- a/Grbl_Esp32/src/Report.cpp
+++ b/Grbl_Esp32/src/Report.cpp
@@ -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;
diff --git a/Grbl_Esp32/src/Report.h b/Grbl_Esp32/src/Report.h
index bc6a774e..b1f26d06 100644
--- a/Grbl_Esp32/src/Report.h
+++ b/Grbl_Esp32/src/Report.h
@@ -1,6 +1,10 @@
#pragma once
#include "Error.h"
+#include "NutsBolts.h"
+#include "Exec.h"
+
+#include
/*
Report.h - Header for system level commands and real-time processes
diff --git a/Grbl_Esp32/src/System.h b/Grbl_Esp32/src/System.h
index da05b606..c66c31b3 100644
--- a/Grbl_Esp32/src/System.h
+++ b/Grbl_Esp32/src/System.h
@@ -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.
diff --git a/Grbl_Esp32/src/WebUI/WebSettings.cpp b/Grbl_Esp32/src/WebUI/WebSettings.cpp
index 77f249a3..feaafade 100644
--- a/Grbl_Esp32/src/WebUI/WebSettings.cpp
+++ b/Grbl_Esp32/src/WebUI/WebSettings.cpp
@@ -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;
}