From d0acc9bef30111590ad8f74f89d1f3365faf24a3 Mon Sep 17 00:00:00 2001 From: bdring Date: Mon, 28 Sep 2020 15:52:30 -0500 Subject: [PATCH] Devt (#618) * Fixed various small bugs (#605) * Fixed various small bugs * Fixed potential cast bug * Fixed double reporting of errors Co-authored-by: Stefan de Bruijn * Stallguard tuning (#607) * Devt (#571) * Handles Tranimic drivers errors better - If an unsupported driver is specified, it will give a message and not crash. * Cleaned up unused files Got rid of old unipolar files Got rid of servo axis feature - it is a motor class now Got rid of solenoid pen feature - never really used and it should be a motor class if it is. * Fix ENABLE_AUTHENTICATION (#569) * Fixed authentication code. * Removed another const cast Co-authored-by: Stefan de Bruijn * Fix step leakage with inverted steps (#570) * Fix step leakage with inverted steps * Update build date for merge Co-authored-by: Bart Dring Co-authored-by: Stefan de Bruijn Co-authored-by: Stefan de Bruijn Co-authored-by: Mitch Bradley Co-authored-by: Bart Dring * Update platformio.ini Per PR 583 * Created an enum for mode * Removing some unused machine defs * Added test machine definition * Clean up for PR * Remove test machine def. Co-authored-by: Stefan de Bruijn Co-authored-by: Stefan de Bruijn Co-authored-by: Mitch Bradley Co-authored-by: Bart Dring * Basic testing Complete * Made state variable volatile. * Homing cycle settings (#613) * Initial Tests Complete * Update Grbl.h * Update variables Co-authored-by: Mitch Bradley * fixed dual switches when inverted (#614) * fixed dual switches when inverted * Removed debug message * Cleaning up the machine defs Removed unused #defines. * Store coordinate offsets in NVS (#611) * Store coordinate offsets in NVS * Handle both old Eeprom formats * Implementing fixes (#616) - Stop creating additional tasks when limit_init() gets called again from homing and resets - Explicitly delete an object that was causing a memory loss. * Update Grbl.h * Tweak memory fix and add $H check for $Homing/Cycles Co-authored-by: Stefan de Bruijn Co-authored-by: Stefan de Bruijn Co-authored-by: Mitch Bradley Co-authored-by: Bart Dring --- Grbl_Esp32/src/Config.h | 28 +--- Grbl_Esp32/src/Eeprom.cpp | 19 ++- Grbl_Esp32/src/Eeprom.h | 1 + Grbl_Esp32/src/Error.cpp | 1 + Grbl_Esp32/src/Error.h | 1 + Grbl_Esp32/src/GCode.cpp | 124 ++++++++---------- Grbl_Esp32/src/GCode.h | 4 +- Grbl_Esp32/src/Grbl.cpp | 1 + Grbl_Esp32/src/Grbl.h | 2 +- Grbl_Esp32/src/Limits.cpp | 50 +++---- Grbl_Esp32/src/Machines/3axis_rs485.h | 14 +- Grbl_Esp32/src/Machines/3axis_v4.h | 13 -- .../src/Machines/6_pack_stepstick_XYZ_v1.h | 18 ++- Grbl_Esp32/src/Machines/atari_1020.h | 12 +- Grbl_Esp32/src/Machines/midtbot.h | 18 +-- Grbl_Esp32/src/Machines/polar_coaster.h | 14 +- Grbl_Esp32/src/Machines/template.h | 17 +-- Grbl_Esp32/src/MotionControl.cpp | 79 ++++------- Grbl_Esp32/src/ProcessSettings.cpp | 11 +- Grbl_Esp32/src/Protocol.cpp | 8 +- Grbl_Esp32/src/Report.cpp | 95 +++++++------- Grbl_Esp32/src/Settings.cpp | 29 ++++ Grbl_Esp32/src/Settings.h | 24 +++- Grbl_Esp32/src/SettingsDefinitions.cpp | 36 +++++ Grbl_Esp32/src/SettingsDefinitions.h | 1 + Grbl_Esp32/src/SettingsStorage.cpp | 27 ++-- Grbl_Esp32/src/SettingsStorage.h | 39 ++++-- Grbl_Esp32/src/Stepper.cpp | 20 ++- Grbl_Esp32/src/System.cpp | 1 + Grbl_Esp32/src/System.h | 7 +- 30 files changed, 361 insertions(+), 353 deletions(-) diff --git a/Grbl_Esp32/src/Config.h b/Grbl_Esp32/src/Config.h index ad29943b..205db46e 100644 --- a/Grbl_Esp32/src/Config.h +++ b/Grbl_Esp32/src/Config.h @@ -46,31 +46,7 @@ Some features should not be changed. See notes below. // machine.h is #included below, after some definitions // that the machine file might choose to undefine. -// Define the homing cycle patterns with bitmasks. The homing cycle first performs a search mode -// to quickly engage the limit switches, followed by a slower locate mode, and finished by a short -// pull-off motion to disengage the limit switches. The following HOMING_CYCLE_x defines are executed -// in order starting with suffix 0 and completes the homing routine for the specified-axes only. If -// an axis is omitted from the defines, it will not home, nor will the system update its position. -// Meaning that this allows for users with non-standard Cartesian machines, such as a lathe (x then z, -// with no y), to configure the homing cycle behavior to their needs. -// NOTE: The homing cycle is designed to allow sharing of limit pins, if the axes are not in the same -// cycle, but this requires some pin settings changes in the machine definition file. For example, the default homing -// cycle can share the Z limit pin with either X or Y limit pins, since they are on different cycles. -// By sharing a pin, this frees up a precious IO pin for other purposes. In theory, all axes limit pins -// may be reduced to one pin, if all axes are homed with separate cycles, or vice versa, all three axes -// on separate pin, but homed in one cycle. Also, it should be noted that the function of hard limits -// will not be affected by pin sharing. - -// NOTE: Defaults are set for a traditional 3-axis CNC machine. Z-axis first to clear, followed by X & Y. -// These homing cycle definitions precede the machine.h file so that the machine -// definition can undefine them if necessary. -#define HOMING_CYCLE_0 bit(Z_AXIS) // TYPICALLY REQUIRED: First move Z to clear workspace. -#define HOMING_CYCLE_1 bit(X_AXIS) -#define HOMING_CYCLE_2 bit(Y_AXIS) - -// NOTE: The following is for for homing X and Y at the same time -// #define HOMING_CYCLE_0 bit(Z_AXIS) // first home z by itself -// #define HOMING_CYCLE_1 (bit(X_AXIS)|bit(Y_AXIS)) // Homes both X-Y in one cycle. NOT COMPATIBLE WITH COREXY!!! +// Note: HOMING_CYCLES are now settings // Inverts pin logic of the control command pins based on a mask. This essentially means you can use // normally-closed switches on the specified pins, rather than the default normally-open switches. @@ -291,8 +267,6 @@ const double SAFETY_DOOR_SPINDLE_DELAY = 4.0; // Float (seconds) const double SAFETY_DOOR_COOLANT_DELAY = 1.0; // Float (seconds) // Enable CoreXY kinematics. Use ONLY with CoreXY machines. -// IMPORTANT: If homing is enabled, you must reconfigure the homing cycle #defines above to -// #define HOMING_CYCLE_0 bit(X_AXIS) and #define HOMING_CYCLE_1 bit(Y_AXIS) // NOTE: This configuration option alters the motion of the X and Y axes to principle of operation // defined at (http://corexy.com/theory.html). Motors are assumed to positioned and wired exactly as // described, if not, motions may move in strange directions. Grbl requires the CoreXY A and B motors diff --git a/Grbl_Esp32/src/Eeprom.cpp b/Grbl_Esp32/src/Eeprom.cpp index 6654289a..d88d9bc2 100644 --- a/Grbl_Esp32/src/Eeprom.cpp +++ b/Grbl_Esp32/src/Eeprom.cpp @@ -24,14 +24,29 @@ void memcpy_to_eeprom_with_checksum(unsigned int destination, const char* source unsigned char checksum = 0; for (; size > 0; size--) { unsigned char data = static_cast(*source++); - checksum = (checksum << 1) | (checksum >> 7); + // Note: This checksum calculation is broken as described below. + checksum = (checksum << 1) || (checksum >> 7); checksum += data; - EEPROM.write(destination++, data); + EEPROM.write(destination++, *(source++)); } EEPROM.write(destination, checksum); EEPROM.commit(); } +int memcpy_from_eeprom_with_old_checksum(char* destination, unsigned int source, unsigned int size) { + unsigned char data, checksum = 0; + for (; size > 0; size--) { + data = EEPROM.read(source++); + // Note: This checksum calculation is broken - the || should be just | - + // thus making the checksum very weak. + // We leave it as-is so we can read old data after a firmware upgrade. + // The new storage format uses the tagged NVS mechanism, avoiding this bug. + checksum = (checksum << 1) || (checksum >> 7); + checksum += data; + *(destination++) = data; + } + return (checksum == EEPROM.read(source)); +} int memcpy_from_eeprom_with_checksum(char* destination, unsigned int source, unsigned int size) { unsigned char data, checksum = 0; for (; size > 0; size--) { diff --git a/Grbl_Esp32/src/Eeprom.h b/Grbl_Esp32/src/Eeprom.h index a9c1d3ab..0a69ec3e 100644 --- a/Grbl_Esp32/src/Eeprom.h +++ b/Grbl_Esp32/src/Eeprom.h @@ -26,3 +26,4 @@ //void eeprom_put_char(unsigned int addr, unsigned char new_value); void memcpy_to_eeprom_with_checksum(unsigned int destination, const char* source, unsigned int size); int memcpy_from_eeprom_with_checksum(char* destination, unsigned int source, unsigned int size); +int memcpy_from_eeprom_with_old_checksum(char* destination, unsigned int source, unsigned int size); diff --git a/Grbl_Esp32/src/Error.cpp b/Grbl_Esp32/src/Error.cpp index 8f232e99..e7fa5de6 100644 --- a/Grbl_Esp32/src/Error.cpp +++ b/Grbl_Esp32/src/Error.cpp @@ -40,6 +40,7 @@ std::map ErrorCodes = { { Error::TravelExceeded, "Max travel exceeded during jog" }, { Error::InvalidJogCommand, "Invalid jog command" }, { Error::SettingDisabledLaser, "Laser mode requires PWM output" }, + { Error::HomingNoCycles, "No Homing/Cycle defined in settings" }, { Error::GcodeUnsupportedCommand, "Unsupported GCode command" }, { Error::GcodeModalGroupViolation, "Gcode modal group violation" }, { Error::GcodeUndefinedFeedRate, "Gcode undefined feed rate" }, diff --git a/Grbl_Esp32/src/Error.h b/Grbl_Esp32/src/Error.h index da7d04d2..cfc2b379 100644 --- a/Grbl_Esp32/src/Error.h +++ b/Grbl_Esp32/src/Error.h @@ -43,6 +43,7 @@ enum class Error : uint8_t { TravelExceeded = 15, InvalidJogCommand = 16, SettingDisabledLaser = 17, + HomingNoCycles = 18, GcodeUnsupportedCommand = 20, GcodeModalGroupViolation = 21, GcodeUndefinedFeedRate = 22, diff --git a/Grbl_Esp32/src/GCode.cpp b/Grbl_Esp32/src/GCode.cpp index 3f2c00c0..8d5391e2 100644 --- a/Grbl_Esp32/src/GCode.cpp +++ b/Grbl_Esp32/src/GCode.cpp @@ -37,28 +37,11 @@ parser_block_t gc_block; #define FAIL(status) return (status); void gc_init() { - // First thing we do here is iterate through the coord systems and read them all, so that - // we get all our coord system errors here, and not while we're busy: - float coord_system[MAX_N_AXIS]; - - // g54 - g59 is 6 coordinate systems, plus 2 for G28 and G30 reference positions - bool reported_error = false; - const int MAX_COORD_SYSTEMS = 8; - for (uint8_t i = 0; i < MAX_COORD_SYSTEMS; ++i) { - if (!(settings_read_coord_data(i, coord_system))) { - if (!reported_error) { - reported_error = true; - report_status_message(Error::SettingReadFail, CLIENT_SERIAL); - } - } - } - // Reset parser state: memset(&gc_state, 0, sizeof(parser_state_t)); // Load default G54 coordinate system. - if (!(settings_read_coord_data(gc_state.modal.coord_select, gc_state.coord_system))) { - report_status_message(Error::SettingReadFail, CLIENT_SERIAL); - } + gc_state.modal.coord_select = CoordIndex::G54; + coords[gc_state.modal.coord_select]->get(gc_state.coord_system); } // Sets g-code parser position in mm. Input in steps. Called by the system abort and hard @@ -149,7 +132,7 @@ Error gc_execute_line(char* line, uint8_t client) { memcpy(&gc_block.modal, &gc_state.modal, sizeof(gc_modal_t)); // Copy current modes AxisCommand axis_command = AxisCommand::None; uint8_t axis_0, axis_1, axis_linear; - uint8_t coord_select = 0; // Tracks G10 P coordinate selection for execution + CoordIndex coord_select = CoordIndex::G54; // Tracks G10 P coordinate selection for execution // Initialize bitflag tracking variables for axis indices compatible operations. uint8_t axis_words = 0; // XYZ tracking uint8_t ijk_words = 0; // IJK tracking @@ -158,6 +141,8 @@ Error gc_execute_line(char* line, uint8_t client) { uint32_t value_words = 0; // Tracks value words. uint8_t gc_parser_flags = GCParserNone; auto n_axis = number_axis->get(); + float coord_data[MAX_N_AXIS]; // Used by WCO-related commands + uint8_t pValue; // Integer value of P word // Determine if the line is a jogging motion or a normal g-code block. if (line[0] == '$') { // NOTE: `$J=` already parsed when passed to this function. @@ -409,15 +394,30 @@ Error gc_execute_line(char* line, uint8_t client) { mg_word_bit = ModalGroup::MG8; break; case 54: - case 55: - case 56: - case 57: - case 58: - case 59: - // NOTE: G59.x are not supported. (But their int_values would be 60, 61, and 62.) - gc_block.modal.coord_select = int_value - 54; // Shift to array indexing. + gc_block.modal.coord_select = CoordIndex::G54; mg_word_bit = ModalGroup::MG12; break; + case 55: + gc_block.modal.coord_select = CoordIndex::G55; + mg_word_bit = ModalGroup::MG12; + break; + case 56: + gc_block.modal.coord_select = CoordIndex::G56; + mg_word_bit = ModalGroup::MG12; + break; + case 57: + gc_block.modal.coord_select = CoordIndex::G57; + mg_word_bit = ModalGroup::MG12; + break; + case 58: + gc_block.modal.coord_select = CoordIndex::G58; + mg_word_bit = ModalGroup::MG12; + break; + case 59: + gc_block.modal.coord_select = CoordIndex::G59; + mg_word_bit = ModalGroup::MG12; + break; + // NOTE: G59.x are not supported. case 61: if (mantissa != 0) { FAIL(Error::GcodeUnsupportedCommand); // [G61.1 not supported] @@ -879,13 +879,13 @@ Error gc_execute_line(char* line, uint8_t client) { float block_coord_system[MAX_N_AXIS]; memcpy(block_coord_system, gc_state.coord_system, sizeof(gc_state.coord_system)); if (bit_istrue(command_words, bit(ModalGroup::MG12))) { // Check if called in block - if (gc_block.modal.coord_select > N_COORDINATE_SYSTEM) { + // This error probably cannot happen because preceding code sets + // gc_block.modal.coord_select only to specific supported values + if (gc_block.modal.coord_select >= CoordIndex::NWCSystems) { FAIL(Error::GcodeUnsupportedCoordSys); // [Greater than N sys] } if (gc_state.modal.coord_select != gc_block.modal.coord_select) { - if (!(settings_read_coord_data(gc_block.modal.coord_select, block_coord_system))) { - FAIL(Error::SettingReadFail); - } + coords[gc_block.modal.coord_select]->get(block_coord_system); } } // [16. Set path control mode ]: N/A. Only G61. G61.1 and G64 NOT SUPPORTED. @@ -907,10 +907,6 @@ Error gc_execute_line(char* line, uint8_t client) { if (bit_isfalse(value_words, (bit(GCodeWord::P) | bit(GCodeWord::L)))) { FAIL(Error::GcodeValueWordMissing); // [P/L word missing] } - coord_select = trunc(gc_block.values.p); // Convert p value to int. - if (coord_select > N_COORDINATE_SYSTEM) { - FAIL(Error::GcodeUnsupportedCoordSys); // [Greater than N sys] - } if (gc_block.values.l != 20) { if (gc_block.values.l == 2) { if (bit_istrue(value_words, bit(GCodeWord::R))) { @@ -920,18 +916,21 @@ Error gc_execute_line(char* line, uint8_t client) { FAIL(Error::GcodeUnsupportedCommand); // [Unsupported L] } } - bit_false(value_words, (bit(GCodeWord::L) | bit(GCodeWord::P))); - // Determine coordinate system to change and try to load from EEPROM. - if (coord_select > 0) { - coord_select--; // Adjust P1-P6 index to EEPROM coordinate data indexing. + // Select the coordinate system based on the P word + pValue = trunc(gc_block.values.p); // Convert p value to integer + if (pValue > 0) { + // P1 means G54, P2 means G55, etc. + coord_select = static_cast(pValue - 1 + CoordIndex::G54); } else { - coord_select = gc_block.modal.coord_select; // Index P0 as the active coordinate system + // P0 means use currently-selected system + coord_select = gc_block.modal.coord_select; } - // NOTE: Store parameter data in IJK values. By rule, they are not in use with this command. - // FIXME: Instead of IJK, we'd better use: float vector[MAX_N_AXIS]; // [DG] - if (!settings_read_coord_data(coord_select, gc_block.values.ijk)) { - FAIL(Error::SettingReadFail); // [EEPROM read fail] + if (coord_select >= CoordIndex::NWCSystems) { + FAIL(Error::GcodeUnsupportedCoordSys); // [Greater than N sys] } + bit_false(value_words, (bit(GCodeWord::L) | bit(GCodeWord::P))); + coords[coord_select]->get(coord_data); + // Pre-calculate the coordinate data changes. for (idx = 0; idx < n_axis; idx++) { // Axes indices are consistent, so loop may be used. // Update axes defined only in block. Always in machine coordinates. Can change non-active system. @@ -939,13 +938,13 @@ Error gc_execute_line(char* line, uint8_t client) { if (gc_block.values.l == 20) { // L20: Update coordinate system axis at current position (with modifiers) with programmed value // WPos = MPos - WCS - G92 - TLO -> WCS = MPos - G92 - TLO - WPos - gc_block.values.ijk[idx] = gc_state.position[idx] - gc_state.coord_offset[idx] - gc_block.values.xyz[idx]; + coord_data[idx] = gc_state.position[idx] - gc_state.coord_offset[idx] - gc_block.values.xyz[idx]; if (idx == TOOL_LENGTH_OFFSET_AXIS) { - gc_block.values.ijk[idx] -= gc_state.tool_length_offset; + coord_data[idx] -= gc_state.tool_length_offset; } } else { // L2: Update coordinate system axis to programmed value. - gc_block.values.ijk[idx] = gc_block.values.xyz[idx]; + coord_data[idx] = gc_block.values.xyz[idx]; } } // Else, keep current stored value. } @@ -1003,21 +1002,16 @@ Error gc_execute_line(char* line, uint8_t client) { case NonModal::GoHome1: // G30 // [G28/30 Errors]: Cutter compensation is enabled. // Retreive G28/30 go-home position data (in machine coordinates) from EEPROM - // NOTE: Store parameter data in IJK values. By rule, they are not in use with this command. if (gc_block.non_modal_command == NonModal::GoHome0) { - if (!settings_read_coord_data(SETTING_INDEX_G28, gc_block.values.ijk)) { - FAIL(Error::SettingReadFail); - } + coords[CoordIndex::G28]->get(coord_data); } else { // == NonModal::GoHome1 - if (!settings_read_coord_data(SETTING_INDEX_G30, gc_block.values.ijk)) { - FAIL(Error::SettingReadFail); - } + coords[CoordIndex::G30]->get(coord_data); } if (axis_words) { // Move only the axes specified in secondary move. for (idx = 0; idx < n_axis; idx++) { if (!(axis_words & bit(idx))) { - gc_block.values.ijk[idx] = gc_state.position[idx]; + coord_data[idx] = gc_state.position[idx]; } } } else { @@ -1454,7 +1448,7 @@ Error gc_execute_line(char* line, uint8_t client) { // [15. Coordinate system selection ]: if (gc_state.modal.coord_select != gc_block.modal.coord_select) { gc_state.modal.coord_select = gc_block.modal.coord_select; - memcpy(gc_state.coord_system, block_coord_system, MAX_N_AXIS * sizeof(float)); + memcpy(gc_state.coord_system, block_coord_system, sizeof(gc_state.coord_system)); system_flag_wco_change(); } // [16. Set path control mode ]: G61.1/G64 NOT SUPPORTED @@ -1465,10 +1459,10 @@ Error gc_execute_line(char* line, uint8_t client) { // [19. Go to predefined position, Set G10, or Set axis offsets ]: switch (gc_block.non_modal_command) { case NonModal::SetCoordinateData: - settings_write_coord_data(coord_select, gc_block.values.ijk); + coords[coord_select]->set(coord_data); // Update system coordinate system if currently active. if (gc_state.modal.coord_select == coord_select) { - memcpy(gc_state.coord_system, gc_block.values.ijk, MAX_N_AXIS * sizeof(float)); + memcpy(gc_state.coord_system, coord_data, sizeof(gc_state.coord_system)); system_flag_wco_change(); } break; @@ -1480,14 +1474,14 @@ Error gc_execute_line(char* line, uint8_t client) { if (axis_command != AxisCommand::None) { mc_line(gc_block.values.xyz, pl_data); // kinematics kinematics not used for homing righ now } - mc_line(gc_block.values.ijk, pl_data); - memcpy(gc_state.position, gc_block.values.ijk, MAX_N_AXIS * sizeof(float)); + mc_line(coord_data, pl_data); + memcpy(gc_state.position, coord_data, sizeof(gc_state.position)); break; case NonModal::SetHome0: - settings_write_coord_data(SETTING_INDEX_G28, gc_state.position); + coords[CoordIndex::G28]->set(coord_data); break; case NonModal::SetHome1: - settings_write_coord_data(SETTING_INDEX_G30, gc_state.position); + coords[CoordIndex::G30]->set(coord_data); break; case NonModal::SetCoordinateOffset: memcpy(gc_state.coord_offset, gc_block.values.xyz, sizeof(gc_block.values.xyz)); @@ -1587,7 +1581,7 @@ Error gc_execute_line(char* line, uint8_t client) { gc_state.modal.distance = Distance::Absolute; gc_state.modal.feed_rate = FeedRate::UnitsPerMin; // gc_state.modal.cutter_comp = CutterComp::Disable; // Not supported. - gc_state.modal.coord_select = 0; // G54 + gc_state.modal.coord_select = CoordIndex::G54; gc_state.modal.spindle = SpindleState::Disable; gc_state.modal.coolant = {}; #ifdef ENABLE_PARKING_OVERRIDE_CONTROL @@ -1605,9 +1599,7 @@ Error gc_execute_line(char* line, uint8_t client) { #endif // Execute coordinate change and spindle/coolant stop. if (sys.state != State::CheckMode) { - if (!(settings_read_coord_data(gc_state.modal.coord_select, gc_state.coord_system))) { - FAIL(Error::SettingReadFail); - } + coords[gc_state.modal.coord_select]->get(gc_state.coord_system); system_flag_wco_change(); // Set to refresh immediately just in case something altered. spindle->set_state(SpindleState::Disable, 0); coolant_off(); diff --git a/Grbl_Esp32/src/GCode.h b/Grbl_Esp32/src/GCode.h index d272a096..1f594bfe 100644 --- a/Grbl_Esp32/src/GCode.h +++ b/Grbl_Esp32/src/GCode.h @@ -251,7 +251,7 @@ typedef struct { Plane plane_select; // {G17,G18,G19} // CutterCompensation cutter_comp; // {G40} NOTE: Don't track. Only default supported. ToolLengthOffset tool_length; // {G43.1,G49} - uint8_t coord_select; // {G54,G55,G56,G57,G58,G59} + CoordIndex coord_select; // {G54,G55,G56,G57,G58,G59} // uint8_t control; // {G61} NOTE: Don't track. Only default supported. ProgramFlow program_flow; // {M0,M1,M2,M30} CoolantState coolant; // {M7,M8,M9} @@ -264,7 +264,7 @@ typedef struct { typedef struct { uint8_t e; // M67 float f; // Feed - float ijk[MAX_N_AXIS]; // I,J,K Axis arc offsets + float ijk[3]; // I,J,K Axis arc offsets - only 3 are possible uint8_t l; // G10 or canned cycles parameters int32_t n; // Line number float p; // G10 or dwell parameters diff --git a/Grbl_Esp32/src/Grbl.cpp b/Grbl_Esp32/src/Grbl.cpp index 8aaeebdc..737bb63e 100644 --- a/Grbl_Esp32/src/Grbl.cpp +++ b/Grbl_Esp32/src/Grbl.cpp @@ -86,6 +86,7 @@ static void reset_variables() { 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(); diff --git a/Grbl_Esp32/src/Grbl.h b/Grbl_Esp32/src/Grbl.h index 332a4f62..fcaf9890 100644 --- a/Grbl_Esp32/src/Grbl.h +++ b/Grbl_Esp32/src/Grbl.h @@ -23,7 +23,7 @@ // Grbl versioning system const char* const GRBL_VERSION = "1.3a"; -const char* const GRBL_VERSION_BUILD = "20200919"; +const char* const GRBL_VERSION_BUILD = "20200928"; //#include #include diff --git a/Grbl_Esp32/src/Limits.cpp b/Grbl_Esp32/src/Limits.cpp index 5d1bdb4e..e3539fee 100644 --- a/Grbl_Esp32/src/Limits.cpp +++ b/Grbl_Esp32/src/Limits.cpp @@ -202,7 +202,7 @@ 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 | EXEC_CYCLE_STOP)) { + if ((sys_rt_exec_state & (EXEC_SAFETY_DOOR | EXEC_RESET)) || cycle_stop) { uint8_t rt_exec = sys_rt_exec_state; // Homing failure condition: Reset issued during cycle. if (rt_exec & EXEC_RESET) { @@ -217,7 +217,7 @@ void limits_go_home(uint8_t cycle_mask) { system_set_exec_alarm(ExecAlarm::HomingFailPulloff); } // Homing failure condition: Limit switch not found during approach. - if (approach && (rt_exec & EXEC_CYCLE_STOP)) { + if (approach && cycle_stop) { system_set_exec_alarm(ExecAlarm::HomingFailApproach); } @@ -228,7 +228,7 @@ void limits_go_home(uint8_t cycle_mask) { return; } else { // Pull-off motion complete. Disable CYCLE_STOP from executing. - system_clear_exec_state_flag(EXEC_CYCLE_STOP); + cycle_stop = false; break; } } @@ -330,27 +330,29 @@ void limits_init() { } else { detachInterrupt(pin); } - /* - // Change to do this once. limits_init() happens often - grbl_msg_sendf(CLIENT_SERIAL, - MsgLevel::Info, - "%c%s Axis limit switch on pin %s", - report_get_axis_letter(axis), - gang_index ? "2" : " ", - pinName(pin).c_str()); - */ + + if (limit_sw_queue == NULL) { + grbl_msg_sendf(CLIENT_SERIAL, + MsgLevel::Info, + "%c%s Axis limit switch on pin %s", + report_get_axis_letter(axis), + gang_index ? "2" : " ", + pinName(pin).c_str()); + } } } } // setup task used for debouncing - limit_sw_queue = xQueueCreate(10, sizeof(int)); - xTaskCreate(limitCheckTask, - "limitCheckTask", - 2048, - NULL, - 5, // priority - NULL); + if (limit_sw_queue == NULL) { + limit_sw_queue = xQueueCreate(10, sizeof(int)); + xTaskCreate(limitCheckTask, + "limitCheckTask", + 2048, + NULL, + 5, // priority + NULL); + } } // Disables hard limits. @@ -371,12 +373,15 @@ void limits_disable() { // 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; - auto n_axis = number_axis->get(); + auto n_axis = number_axis->get(); for (int axis = 0; axis < n_axis; axis++) { for (int gang_index = 0; gang_index < 2; gang_index++) { uint8_t pin = limit_pins[axis][gang_index]; if (pin != UNDEFINED_PIN) { - pinMask |= (digitalRead(pin) << axis); + if (limit_invert->get()) + pinMask |= (!digitalRead(pin) << axis); + else + pinMask |= (digitalRead(pin) << axis); } } } @@ -384,9 +389,6 @@ uint8_t limits_get_state() { #ifdef INVERT_LIMIT_PIN_MASK // not normally used..unless you have both normal and inverted switches pinMask ^= INVERT_LIMIT_PIN_MASK; #endif - if (limit_invert->get()) { - pinMask ^= limit_mask; - } return pinMask; } diff --git a/Grbl_Esp32/src/Machines/3axis_rs485.h b/Grbl_Esp32/src/Machines/3axis_rs485.h index 0dd02d5e..39a565cb 100644 --- a/Grbl_Esp32/src/Machines/3axis_rs485.h +++ b/Grbl_Esp32/src/Machines/3axis_rs485.h @@ -49,19 +49,7 @@ #define Y2_LIMIT_PIN GPIO_NUM_35 #define Z_LIMIT_PIN GPIO_NUM_34 -#ifdef HOMING_CYCLE_0 - #undef HOMING_CYCLE_0 -#endif -#define HOMING_CYCLE_0 bit(Z_AXIS) // Z first - -#ifdef HOMING_CYCLE_1 - #undef HOMING_CYCLE_1 -#endif -#define HOMING_CYCLE_1 (bit(X_AXIS)|bit(Y_AXIS)) - -#ifdef HOMING_CYCLE_2 - #undef HOMING_CYCLE_2 -#endif +// Set $Homing/Cycle0=X and $Homing/Cycle=XY #define PROBE_PIN GPIO_NUM_14 // labeled Probe #define CONTROL_RESET_PIN GPIO_NUM_27 // labeled Reset diff --git a/Grbl_Esp32/src/Machines/3axis_v4.h b/Grbl_Esp32/src/Machines/3axis_v4.h index 31308420..7b817180 100644 --- a/Grbl_Esp32/src/Machines/3axis_v4.h +++ b/Grbl_Esp32/src/Machines/3axis_v4.h @@ -39,19 +39,6 @@ #define Y_LIMIT_PIN GPIO_NUM_4 #define Z_LIMIT_PIN GPIO_NUM_16 -#ifdef HOMING_CYCLE_0 - #undef HOMING_CYCLE_0 -#endif -#define HOMING_CYCLE_0 bit(Z_AXIS) // Z first - -#ifdef HOMING_CYCLE_1 - #undef HOMING_CYCLE_1 -#endif -#define HOMING_CYCLE_1 (bit(X_AXIS)|bit(Y_AXIS)) - -#ifdef HOMING_CYCLE_2 - #undef HOMING_CYCLE_2 -#endif // OK to comment out to use pin for other features #define STEPPERS_DISABLE_PIN GPIO_NUM_13 diff --git a/Grbl_Esp32/src/Machines/6_pack_stepstick_XYZ_v1.h b/Grbl_Esp32/src/Machines/6_pack_stepstick_XYZ_v1.h index f18e3ec4..b8b70c3f 100644 --- a/Grbl_Esp32/src/Machines/6_pack_stepstick_XYZ_v1.h +++ b/Grbl_Esp32/src/Machines/6_pack_stepstick_XYZ_v1.h @@ -110,11 +110,27 @@ Socket #5 */ - // 4x Input Module in Socket #1 +/* +// 4x Input Module in Socket #1 // https://github.com/bdring/6-Pack_CNC_Controller/wiki/4x-Switch-Input-module #define X_LIMIT_PIN GPIO_NUM_33 #define Y_LIMIT_PIN GPIO_NUM_32 #define Z_LIMIT_PIN GPIO_NUM_35 +*/ + +// 4x Input Module in Socket #2 +// https://github.com/bdring/6-Pack_CNC_Controller/wiki/4x-Switch-Input-module +#define X_LIMIT_PIN GPIO_NUM_2 +#define Y_LIMIT_PIN GPIO_NUM_25 +#define Z_LIMIT_PIN GPIO_NUM_39 + +// 4x Input Module in Socket #3 +// https://github.com/bdring/6-Pack_CNC_Controller/wiki/4x-Switch-Input-module +#define CONTROL_CYCLE_START_PIN GPIO_NUM_26 +#define CONTROL_FEED_HOLD_PIN GPIO_NUM_4 +#define CONTROL_RESET_PIN GPIO_NUM_16 +#define CONTROL_SAFETY_DOOR_PIN GPIO_NUM_27 +//#define INVERT_CONTROL_PIN_MASK B0000 // ================= Setting Defaults ========================== diff --git a/Grbl_Esp32/src/Machines/atari_1020.h b/Grbl_Esp32/src/Machines/atari_1020.h index 61d8556b..eecc2146 100644 --- a/Grbl_Esp32/src/Machines/atari_1020.h +++ b/Grbl_Esp32/src/Machines/atari_1020.h @@ -54,16 +54,8 @@ #define SOLENOID_DIRECTION_PIN GPIO_NUM_4 #define SOLENOID_PEN_PIN GPIO_NUM_2 -#ifdef HOMING_CYCLE_0 - #undef HOMING_CYCLE_0 -#endif -#define HOMING_CYCLE_0 bit(X_AXIS) // this 'bot only homes the X axis -#ifdef HOMING_CYCLE_1 - #undef HOMING_CYCLE_1 -#endif -#ifdef HOMING_CYCLE_2 - #undef HOMING_CYCLE_2 -#endif +// this 'bot only homes the X axis +// Set $Homing/Cycle0=0 #define REED_SW_PIN GPIO_NUM_17 diff --git a/Grbl_Esp32/src/Machines/midtbot.h b/Grbl_Esp32/src/Machines/midtbot.h index be77d54d..800faf5b 100644 --- a/Grbl_Esp32/src/Machines/midtbot.h +++ b/Grbl_Esp32/src/Machines/midtbot.h @@ -48,24 +48,8 @@ #define Z_SERVO_CAL_MIN 1.0 // calibration factor for the minimum PWM duty #define Z_SERVO_CAL_MAX 1.0 // calibration factor for the maximum PWM duty -// redefine some stuff from config.h -#ifdef HOMING_CYCLE_0 - #undef HOMING_CYCLE_0 -#endif -#define HOMING_CYCLE_0 bit(Y_AXIS) - -#ifdef HOMING_CYCLE_1 - #undef HOMING_CYCLE_1 -#endif - -#define HOMING_CYCLE_1 bit(X_AXIS) - -#ifdef HOMING_CYCLE_2 - #undef HOMING_CYCLE_2 -#endif - -#define SERVO_PEN_PIN GPIO_NUM_27 +// Set $Homing/Cycle0=Y and $Homing/Cycle1=X #define SPINDLE_TYPE SpindleType::NONE diff --git a/Grbl_Esp32/src/Machines/polar_coaster.h b/Grbl_Esp32/src/Machines/polar_coaster.h index 91526fcb..5e600d76 100644 --- a/Grbl_Esp32/src/Machines/polar_coaster.h +++ b/Grbl_Esp32/src/Machines/polar_coaster.h @@ -74,17 +74,9 @@ #define MACRO_BUTTON_1_PIN GPIO_NUM_12 #define MACRO_BUTTON_2_PIN GPIO_NUM_14 -// redefine some stuff from config.h -#ifdef HOMING_CYCLE_0 - #undef HOMING_CYCLE_0 -#endif -#define HOMING_CYCLE_0 bit(X_AXIS) // this 'bot only homes the X axis -#ifdef HOMING_CYCLE_1 - #undef HOMING_CYCLE_1 -#endif -#ifdef HOMING_CYCLE_2 - #undef HOMING_CYCLE_2 -#endif + +// this 'bot only homes the X axis +// Set $Homing/Cycle0=X // ============= End CPU MAP ================== diff --git a/Grbl_Esp32/src/Machines/template.h b/Grbl_Esp32/src/Machines/template.h index c8967c70..fc321a11 100644 --- a/Grbl_Esp32/src/Machines/template.h +++ b/Grbl_Esp32/src/Machines/template.h @@ -136,22 +136,7 @@ // #define Z_SERVO_CAL_MIN 1.0 // calibration factor for the maximum PWM duty // === Homing cycles -// The default homing order is Z first (HOMING_CYCLE_0), -// then X (HOMING_CYCLE_1), and finally Y (HOMING_CYCLE_2) -// For machines that need different homing order, you can -// undefine HOMING_CYCLE_n and redefine it accordingly. -// For example, the following would first home X and Y -// simultaneously, then A and B simultaneously, and Z -// not at all. - -// #undef HOMING_CYCLE_0 -// #define HOMING_CYCLE_0 (bit(X_AXIS)|bit(Y_AXIS)) - -// #undef HOMING_CYCLE_1 -// #define HOMING_CYCLE_1 (bit(A_AXIS)|bit(B_AXIS)) - -// #undef HOMING_CYCLE_2 -// #endif +// Set them using $Homing/Cycle0= optionally up to $Homing/Cycle5= // === Default settings // Grbl has many run-time settings that the user can changed by diff --git a/Grbl_Esp32/src/MotionControl.cpp b/Grbl_Esp32/src/MotionControl.cpp index 3e93f8e1..d122529f 100644 --- a/Grbl_Esp32/src/MotionControl.cpp +++ b/Grbl_Esp32/src/MotionControl.cpp @@ -118,7 +118,7 @@ void mc_arc(float* target, #ifdef USE_KINEMATICS float previous_position[MAX_N_AXIS]; uint16_t n; - auto n_axis = number_axis->get(); + auto n_axis = number_axis->get(); for (n = 0; n < n_axis; n++) { previous_position[n] = position[n]; } @@ -264,6 +264,7 @@ static bool axis_is_squared(uint8_t axis_mask) { // NOTE: There should be no motions in the buffer and Grbl must be in an idle state before // executing the homing cycle. This prevents incorrect buffered plans after homing. void mc_homing_cycle(uint8_t cycle_mask) { + bool no_cycles_defined = true; #ifdef USE_CUSTOM_HOMING if (user_defined_homing()) { return; @@ -313,59 +314,29 @@ void mc_homing_cycle(uint8_t cycle_mask) { else #endif { - // Search to engage all axes limit switches at faster homing seek rate. - if (!axis_is_squared(HOMING_CYCLE_0)) { - limits_go_home(HOMING_CYCLE_0); // Homing cycle 0 - } else { - ganged_mode = SquaringMode::Dual; - n_homing_locate_cycle = 0; // don't do a second touch cycle - limits_go_home(HOMING_CYCLE_0); - ganged_mode = SquaringMode::A; - n_homing_locate_cycle = NHomingLocateCycle; // restore to default value - limits_go_home(HOMING_CYCLE_0); - ganged_mode = SquaringMode::B; - limits_go_home(HOMING_CYCLE_0); - ganged_mode = SquaringMode::Dual; // always return to dual + for (int cycle = 0; cycle < MAX_N_AXIS; cycle++) { + auto homing_mask = homing_cycle[cycle]->get(); + if (homing_mask) { // if there are some axes in this cycle + no_cycles_defined = false; + if (!axis_is_squared(homing_mask)) { + limits_go_home(homing_mask); // Homing cycle 0 + } else { + ganged_mode = SquaringMode::Dual; + n_homing_locate_cycle = 0; // don't do a second touch cycle + limits_go_home(homing_mask); + ganged_mode = SquaringMode::A; + n_homing_locate_cycle = NHomingLocateCycle; // restore to default value + limits_go_home(homing_mask); + ganged_mode = SquaringMode::B; + limits_go_home(homing_mask); + ganged_mode = SquaringMode::Dual; // always return to dual + } + } } -#ifdef HOMING_CYCLE_1 - if (!axis_is_squared(HOMING_CYCLE_1)) { - limits_go_home(HOMING_CYCLE_1); - } else { - ganged_mode = SquaringMode::Dual; - n_homing_locate_cycle = 0; // don't do a second touch cycle - limits_go_home(HOMING_CYCLE_1); - ganged_mode = SquaringMode::A; - n_homing_locate_cycle = NHomingLocateCycle; // restore to default value - limits_go_home(HOMING_CYCLE_1); - ganged_mode = SquaringMode::B; - limits_go_home(HOMING_CYCLE_1); - ganged_mode = SquaringMode::Dual; // always return to dual + + if (no_cycles_defined) { + report_status_message(Error::HomingNoCycles, CLIENT_ALL); } -#endif -#ifdef HOMING_CYCLE_2 - if (!axis_is_squared(HOMING_CYCLE_2)) { - limits_go_home(HOMING_CYCLE_2); - } else { - ganged_mode = SquaringMode::Dual; - n_homing_locate_cycle = 0; // don't do a second touch cycle - limits_go_home(HOMING_CYCLE_2); - ganged_mode = SquaringMode::A; - n_homing_locate_cycle = NHomingLocateCycle; // restore to default value - limits_go_home(HOMING_CYCLE_2); - ganged_mode = SquaringMode::B; - limits_go_home(HOMING_CYCLE_2); - ganged_mode = SquaringMode::Dual; // always return to dual - } -#endif -#ifdef HOMING_CYCLE_3 - limits_go_home(HOMING_CYCLE_3); // Homing cycle 3 -#endif -#ifdef HOMING_CYCLE_4 - limits_go_home(HOMING_CYCLE_4); // Homing cycle 4 -#endif -#ifdef HOMING_CYCLE_5 - limits_go_home(HOMING_CYCLE_5); // Homing cycle 5 -#endif } protocol_execute_realtime(); // Check for reset and set system abort. if (sys.abort) { @@ -508,8 +479,8 @@ void mc_reset() { sys_io_control(0xFF, LOW, false); sys_pwm_control(0xFF, 0, false); #ifdef ENABLE_SD_CARD - // do we need to stop a running SD job? - if (get_sd_state(false) == SDCARD_BUSY_PRINTING) { + // do we need to stop a running SD job? + if (get_sd_state(false) == SDCARD_BUSY_PRINTING) { //Report print stopped report_feedback_message(Message::SdFileQuit); closeFile(); diff --git a/Grbl_Esp32/src/ProcessSettings.cpp b/Grbl_Esp32/src/ProcessSettings.cpp index 7a052381..ddae1b22 100644 --- a/Grbl_Esp32/src/ProcessSettings.cpp +++ b/Grbl_Esp32/src/ProcessSettings.cpp @@ -56,11 +56,8 @@ void settings_restore(uint8_t restore_flag) { } } if (restore_flag & SETTINGS_RESTORE_PARAMETERS) { - uint8_t idx; - float coord_data[MAX_N_AXIS]; - memset(&coord_data, 0, sizeof(coord_data)); - for (idx = 0; idx <= SETTING_INDEX_NCOORD; idx++) { - settings_write_coord_data(idx, coord_data); + for (auto idx = CoordIndex::Begin; idx < CoordIndex::End; ++idx) { + coords[idx]->setDefault(); } } if (restore_flag & SETTINGS_RESTORE_BUILD_INFO) { @@ -559,8 +556,10 @@ Error system_execute_line(char* line, WebUI::ESPResponseStream* out, WebUI::Auth // non-empty string - [ESPxxx]yyy or $xxx=yyy return do_command_or_setting(key, value, auth_level, out); } + Error system_execute_line(char* line, uint8_t client, WebUI::AuthenticationLevel auth_level) { - return system_execute_line(line, new WebUI::ESPResponseStream(client, true), auth_level); + WebUI::ESPResponseStream stream(client, true); + return system_execute_line(line, &stream, auth_level); } void system_execute_startup(char* line) { diff --git a/Grbl_Esp32/src/Protocol.cpp b/Grbl_Esp32/src/Protocol.cpp index 106d90a5..d2d3d0cb 100644 --- a/Grbl_Esp32/src/Protocol.cpp +++ b/Grbl_Esp32/src/Protocol.cpp @@ -271,7 +271,7 @@ void protocol_exec_rt_system() { system_clear_exec_alarm(); // Clear alarm } uint8_t rt_exec = sys_rt_exec_state; // Copy volatile sys_rt_exec_state. - if (rt_exec) { + if (rt_exec || cycle_stop) { // Execute system abort. if (rt_exec & EXEC_RESET) { sys.abort = true; // Only place this is set true. @@ -399,12 +399,12 @@ void protocol_exec_rt_system() { } system_clear_exec_state_flag(EXEC_CYCLE_START); } - if (rt_exec & EXEC_CYCLE_STOP) { + if (cycle_stop) { // Reinitializes the cycle plan and stepper system after a feed hold for a resume. Called by // realtime command execution in the main program, ensuring that the planner re-plans safely. // NOTE: Bresenham algorithm variables are still maintained through both the planner and stepper // cycle reinitializations. The stepper path should continue exactly as if nothing has happened. - // NOTE: EXEC_CYCLE_STOP is set by the stepper subsystem when a cycle or feed hold completes. + // 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)) { // Hold complete. Set to indicate ready to resume. Remain in HOLD or DOOR states until user @@ -433,7 +433,7 @@ void protocol_exec_rt_system() { sys.state = State::Idle; } } - system_clear_exec_state_flag(EXEC_CYCLE_STOP); + cycle_stop = false; } } // Execute overrides. diff --git a/Grbl_Esp32/src/Report.cpp b/Grbl_Esp32/src/Report.cpp index e93b578a..e307b05d 100644 --- a/Grbl_Esp32/src/Report.cpp +++ b/Grbl_Esp32/src/Report.cpp @@ -166,23 +166,24 @@ void grbl_notifyf(const char* title, const char* format, ...) { } } +static const int coordStringLen = 20; +static const int axesStringLen = coordStringLen * MAX_N_AXIS; + // formats axis values into a string and returns that string in rpt -// NOTE: rpt should have at least size: 20 * MAX_N_AXIS +// NOTE: rpt should have at least size: axesStringLen static void report_util_axis_values(float* axis_value, char* rpt) { uint8_t idx; - char axisVal[20]; + char axisVal[coordStringLen]; float unit_conv = 1.0; // unit conversion multiplier..default is mm + const char* format = "%4.3f"; // Default - report mm to 3 decimal places rpt[0] = '\0'; if (report_inches->get()) { unit_conv = 1.0 / MM_PER_INCH; + format = "%4.4f"; // Report inches to 4 decimal places } auto n_axis = number_axis->get(); for (idx = 0; idx < n_axis; idx++) { - if (report_inches->get()) { - snprintf(axisVal, 19, "%4.4f", axis_value[idx] * unit_conv); // Report inches to 4 decimals - } else { - snprintf(axisVal, 19, "%4.3f", axis_value[idx] * unit_conv); // Report mm to 3 decimals - } + snprintf(axisVal, coordStringLen-1, format, axis_value[idx] * unit_conv); strcat(rpt, axisVal); if (idx < (number_axis->get() - 1)) { strcat(rpt, ","); @@ -190,6 +191,27 @@ static void report_util_axis_values(float* axis_value, char* rpt) { } } +// This version returns the axis values as a String +static String report_util_axis_values(const float* axis_value) { + String rpt = ""; + uint8_t idx; + char axisVal[coordStringLen]; + float unit_conv = 1.0; // unit conversion multiplier..default is mm + int decimals = 3; // Default - report mm to 3 decimal places + if (report_inches->get()) { + unit_conv = 1.0 / MM_PER_INCH; + decimals = 4; // Report inches to 4 decimal places + } + auto n_axis = number_axis->get(); + for (idx = 0; idx < n_axis; idx++) { + rpt += String(axis_value[idx] * unit_conv, decimals); + if (idx < (number_axis->get() - 1)) { + rpt += ","; + } + } + return rpt; +} + // Handles the primary confirmation protocol response for streaming interfaces and human-feedback. // For every incoming line, this method responds with an 'ok' for a successful command or an // 'error:' to indicate some error event with the line or some critical system error during @@ -284,8 +306,8 @@ void report_grbl_help(uint8_t client) { void report_probe_parameters(uint8_t client) { // Report in terms of machine position. float print_position[MAX_N_AXIS]; - char probe_rpt[(MAX_N_AXIS * 20 + 13 + 6 + 1)]; // the probe report we are building here - char temp[MAX_N_AXIS * 20]; + char probe_rpt[(axesStringLen + 13 + 6 + 1)]; // the probe report we are building here + char temp[axesStringLen]; strcpy(probe_rpt, "[PRB:"); // initialize the string with the first characters // get the machine position and put them into a string and append to the probe report system_convert_array_steps_to_mpos(print_position, sys_probe_position); @@ -299,46 +321,27 @@ void report_probe_parameters(uint8_t client) { // Prints Grbl NGC parameters (coordinate offsets, probing) void report_ngc_parameters(uint8_t client) { - float coord_data[MAX_N_AXIS]; - uint8_t coord_select; - char temp[MAX_N_AXIS * 20]; - char ngc_rpt[((8 + (MAX_N_AXIS * 20)) * SETTING_INDEX_NCOORD + 4 + MAX_N_AXIS * 20 + 8 + 2 * 20)]; - ngc_rpt[0] = '\0'; - for (coord_select = 0; coord_select <= SETTING_INDEX_NCOORD; coord_select++) { - if (!(settings_read_coord_data(coord_select, coord_data))) { - report_status_message(Error::SettingReadFail, CLIENT_SERIAL); - return; - } - strcat(ngc_rpt, "[G"); - switch (coord_select) { - case 6: - strcat(ngc_rpt, "28"); - break; - case 7: - strcat(ngc_rpt, "30"); - break; - default: - sprintf(temp, "%d", coord_select + 54); - strcat(ngc_rpt, temp); - break; // G54-G59 - } - strcat(ngc_rpt, ":"); - report_util_axis_values(coord_data, temp); - strcat(ngc_rpt, temp); - strcat(ngc_rpt, "]\r\n"); + String ngc_rpt = ""; + + // Print persistent offsets G54 - G59, G28, and G30 + for (auto coord_select = CoordIndex::Begin; coord_select < CoordIndex::End; ++coord_select) { + ngc_rpt += "["; + ngc_rpt += coords[coord_select]->getName(); + ngc_rpt += ":"; + ngc_rpt += report_util_axis_values(coords[coord_select]->get()); + ngc_rpt += "]\r\n"; } - strcat(ngc_rpt, "[G92:"); // Print G92,G92.1 which are not persistent in memory - report_util_axis_values(gc_state.coord_offset, temp); - strcat(ngc_rpt, temp); - strcat(ngc_rpt, "]\r\n"); - strcat(ngc_rpt, "[TLO:"); // Print tool length offset value + ngc_rpt += "[G92:"; // Print non-persistent G92,G92.1 + ngc_rpt += report_util_axis_values(gc_state.coord_offset); + ngc_rpt += "]\r\n"; + ngc_rpt += "[TLO:"; // Print tool length offset + float tlo = gc_state.tool_length_offset; if (report_inches->get()) { - snprintf(temp, 20, "%4.3f]\r\n", gc_state.tool_length_offset * INCH_PER_MM); - } else { - snprintf(temp, 20, "%4.3f]\r\n", gc_state.tool_length_offset); + tlo *= INCH_PER_MM; } - strcat(ngc_rpt, temp); - grbl_send(client, ngc_rpt); + ngc_rpt += String(tlo, 3);; + ngc_rpt += "]\r\n"; + grbl_send(client, ngc_rpt.c_str()); report_probe_parameters(client); } diff --git a/Grbl_Esp32/src/Settings.cpp b/Grbl_Esp32/src/Settings.cpp index 701037f6..f1be2536 100644 --- a/Grbl_Esp32/src/Settings.cpp +++ b/Grbl_Esp32/src/Settings.cpp @@ -653,3 +653,32 @@ Error GrblCommand::action(char* value, WebUI::AuthenticationLevel auth_level, We } return _action((const char*)value, auth_level, out); }; +Coordinates* coords[CoordIndex::End]; + +bool Coordinates::load() { + size_t len; + switch (nvs_get_blob(Setting::_handle, _name, _currentValue, &len)) { + case ESP_OK: + return true; + case ESP_ERR_NVS_INVALID_LENGTH: + // This could happen if the stored value is longer than the buffer. + // That is highly unlikely since we always store MAX_N_AXIS coordinates. + // It would indicate that we have decreased MAX_N_AXIS since the + // value was stored. We don't flag it as an error, but rather + // accept the initial coordinates and ignore the residue. + // We could issue a warning message if we were so inclined. + return true; + case ESP_ERR_NVS_INVALID_NAME: + case ESP_ERR_NVS_INVALID_HANDLE: + default: + return false; + } +}; + +void Coordinates::set(float value[MAX_N_AXIS]) { + memcpy(&_currentValue, value, sizeof(_currentValue)); +#ifdef FORCE_BUFFER_SYNC_DURING_EEPROM_WRITE + protocol_buffer_synchronize(); +#endif + nvs_set_blob(Setting::_handle, _name, _currentValue, sizeof(_currentValue)); +} diff --git a/Grbl_Esp32/src/Settings.h b/Grbl_Esp32/src/Settings.h index 233e8571..5b91c80e 100644 --- a/Grbl_Esp32/src/Settings.h +++ b/Grbl_Esp32/src/Settings.h @@ -76,7 +76,6 @@ public: class Setting : public Word { private: protected: - static nvs_handle _handle; // group_t _group; axis_t _axis = NO_AXIS; Setting* link; // linked list of setting objects @@ -85,6 +84,7 @@ protected: const char* _keyName; public: + static nvs_handle _handle; static void init(); static Setting* List; Setting* next() { return link; } @@ -206,6 +206,28 @@ public: int32_t get() { return _currentValue; } }; +class Coordinates { +private: + float _currentValue[MAX_N_AXIS]; + const char* _name; +public: + Coordinates(const char* name) : _name(name) {} + + const char* getName() { return _name; } + bool load(); + void setDefault() { + float zeros[MAX_N_AXIS] = { 0.0, }; + set(zeros); + }; + // Copy the value to an array + void get(float* value) { memcpy(value, _currentValue, sizeof(_currentValue)); } + // Return a pointer to the array + const float* get() { return _currentValue; } + void set(float *value); +}; + +extern Coordinates* coords[CoordIndex::End]; + class FloatSetting : public Setting { private: float _defaultValue; diff --git a/Grbl_Esp32/src/SettingsDefinitions.cpp b/Grbl_Esp32/src/SettingsDefinitions.cpp index caeb5621..2f649dcb 100644 --- a/Grbl_Esp32/src/SettingsDefinitions.cpp +++ b/Grbl_Esp32/src/SettingsDefinitions.cpp @@ -39,6 +39,7 @@ FloatSetting* homing_feed_rate; FloatSetting* homing_seek_rate; FloatSetting* homing_debounce; FloatSetting* homing_pulloff; +AxisMaskSetting* homing_cycle[MAX_N_AXIS]; FloatSetting* spindle_pwm_freq; FloatSetting* rpm_max; FloatSetting* rpm_min; @@ -204,9 +205,38 @@ static const char* makeGrblName(int axisNum, int base) { return strcpy(retval, buf); } +void make_coordinate(CoordIndex index, const char* name) { + float coord_data[MAX_N_AXIS] = { 0.0 }; + auto coord = new Coordinates(name); + coords[index] = coord; + if (!coord->load()) { + grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Propagating %s data to NVS format", coord->getName()); + // If coord->load() returns false it means that no entry + // was present in non-volatile storage. In that case we + // first look for an old-format entry in the EEPROM section. + // If an entry is present some number of float values at + // the beginning of coord_data will be overwritten with + // the EEPROM data, and the rest will remain at 0.0. + // If no old-format entry is present, all will remain 0.0 + // Regardless, we create a new entry with that data. + (void)old_settings_read_coord_data(index, coord_data); + coords[index]->set(coord_data); + } +} void make_settings() { Setting::init(); + // Propagate old coordinate system data to the new format if necessary. + // G54 - G59 work coordinate systems, G28, G30 reference positions, etc + make_coordinate(CoordIndex::G54, "G54"); + make_coordinate(CoordIndex::G55, "G55"); + make_coordinate(CoordIndex::G56, "G56"); + make_coordinate(CoordIndex::G57, "G57"); + make_coordinate(CoordIndex::G58, "G58"); + make_coordinate(CoordIndex::G59, "G59"); + make_coordinate(CoordIndex::G28, "G28"); + make_coordinate(CoordIndex::G30, "G30"); + // number_axis = new IntSetting(EXTENDED, WG, NULL, "NumberAxis", N_AXIS, 0, 6, NULL, true); number_axis = new FakeSetting(N_AXIS); @@ -344,4 +374,10 @@ void make_settings() { pulse_microseconds = new IntSetting(GRBL, WG, "0", "Stepper/Pulse", DEFAULT_STEP_PULSE_MICROSECONDS, 3, 1000); spindle_type = new EnumSetting(NULL, EXTENDED, WG, NULL, "Spindle/Type", static_cast(SPINDLE_TYPE), &spindleTypes); stallguard_debug_mask = new AxisMaskSetting(EXTENDED, WG, NULL, "Report/StallGuard", 0, checkStallguardDebugMask); + + const char* homing_names[] = { "Homing/Cycle0", "Homing/Cycle1", "Homing/Cycle2", + "Homing/Cycle3", "Homing/Cycle4", "Homing/Cycle5" }; + for (uint8_t i = 0; i < MAX_N_AXIS; i++) { + homing_cycle[i] = new AxisMaskSetting(EXTENDED, WG, NULL, homing_names[i], 0); + } } diff --git a/Grbl_Esp32/src/SettingsDefinitions.h b/Grbl_Esp32/src/SettingsDefinitions.h index c3fe8310..0fd68b33 100644 --- a/Grbl_Esp32/src/SettingsDefinitions.h +++ b/Grbl_Esp32/src/SettingsDefinitions.h @@ -23,6 +23,7 @@ extern AxisMaskSetting* step_invert_mask; extern AxisMaskSetting* dir_invert_mask; extern AxisMaskSetting* homing_dir_mask; extern AxisMaskSetting* homing_squared_axes; +extern AxisMaskSetting* homing_cycle[MAX_N_AXIS]; extern FlagSetting* step_enable_invert; extern FlagSetting* limit_invert; diff --git a/Grbl_Esp32/src/SettingsStorage.cpp b/Grbl_Esp32/src/SettingsStorage.cpp index b45f040c..5c17d8ba 100644 --- a/Grbl_Esp32/src/SettingsStorage.cpp +++ b/Grbl_Esp32/src/SettingsStorage.cpp @@ -25,26 +25,21 @@ #include "Grbl.h" // Read selected coordinate data from EEPROM. Updates pointed coord_data value. -uint8_t settings_read_coord_data(uint8_t coord_select, float* coord_data) { - uint32_t addr = coord_select * (sizeof(float) * MAX_N_AXIS + 1) + EEPROM_ADDR_PARAMETERS; - if (!(memcpy_from_eeprom_with_checksum((char*)coord_data, addr, sizeof(float) * MAX_N_AXIS))) { +// This is now a compatibility routine that is used to propagate coordinate data +// in the old EEPROM format to the new tagged NVS format. +bool old_settings_read_coord_data(uint8_t coord_select, float* coord_data) { + uint32_t addr = coord_select * (sizeof(float) * N_AXIS + 1) + EEPROM_ADDR_PARAMETERS; + if (!(memcpy_from_eeprom_with_old_checksum((char*)coord_data, addr, sizeof(float) * N_AXIS)) && + !(memcpy_from_eeprom_with_checksum((char*)coord_data, addr, sizeof(float) * MAX_N_AXIS))) { // Reset with default zero vector clear_vector_float(coord_data); - settings_write_coord_data(coord_select, coord_data); + // The old code used to rewrite the zeroed data but now that is done + // elsewhere, in a different format. return false; } return true; } -// Method to store coord data parameters into EEPROM -void settings_write_coord_data(uint8_t coord_select, float* coord_data) { -#ifdef FORCE_BUFFER_SYNC_DURING_EEPROM_WRITE - protocol_buffer_synchronize(); -#endif - uint32_t addr = coord_select * (sizeof(float) * MAX_N_AXIS + 1) + EEPROM_ADDR_PARAMETERS; - memcpy_to_eeprom_with_checksum(addr, (char*)coord_data, sizeof(float) * MAX_N_AXIS); -} - // Method to store build info into EEPROM // NOTE: This function can only be called in IDLE state. void settings_store_build_info(const char* line) { @@ -73,3 +68,9 @@ uint8_t get_step_pin_mask(uint8_t axis_idx) { uint8_t get_direction_pin_mask(uint8_t axis_idx) { return bit(axis_idx); } + +// Allow iteration over CoordIndex values +CoordIndex& operator ++ (CoordIndex& i) { + i = static_cast(static_cast(i) + 1); + return i; +} diff --git a/Grbl_Esp32/src/SettingsStorage.h b/Grbl_Esp32/src/SettingsStorage.h index 02566d15..4df9870a 100644 --- a/Grbl_Esp32/src/SettingsStorage.h +++ b/Grbl_Esp32/src/SettingsStorage.h @@ -48,14 +48,6 @@ const int EEPROM_SIZE = 1024U; const int EEPROM_ADDR_PARAMETERS = 512U; const int EEPROM_ADDR_BUILD_INFO = 942U; -// Define EEPROM address indexing for coordinate parameters -const int N_COORDINATE_SYSTEM = 6; // Number of supported work coordinate systems (from index 1) -const int SETTING_INDEX_NCOORD = N_COORDINATE_SYSTEM + 1; // Total number of system stored (from index 0) -// NOTE: Work coordinate indices are (0=G54, 1=G55, ... , 6=G59) -const int SETTING_INDEX_G28 = N_COORDINATE_SYSTEM; // Home position 1 -const int SETTING_INDEX_G30 = N_COORDINATE_SYSTEM + 1; // Home position 2 -// const int SETTING_INDEX_G92 = N_COORDINATE_SYSTEM+2; // Coordinate offset (G92.2,G92.3 not supported) - // Initialize the configuration subsystem (load settings from EEPROM) void settings_init(); void settings_restore(uint8_t restore_flag); @@ -64,14 +56,37 @@ void write_global_settings(); uint8_t settings_read_build_info(char* line); void settings_store_build_info(const char* line); -// Writes selected coordinate data to EEPROM -void settings_write_coord_data(uint8_t coord_select, float* coord_data); - // Reads selected coordinate data from EEPROM -uint8_t settings_read_coord_data(uint8_t coord_select, float* coord_data); +bool old_settings_read_coord_data(uint8_t coord_select, float* coord_data); // Returns the step pin mask according to Grbl's internal axis numbering uint8_t get_step_pin_mask(uint8_t i); // Returns the direction pin mask according to Grbl's internal axis numbering uint8_t get_direction_pin_mask(uint8_t i); + +// Various places in the code access saved coordinate system data +// by a small integer index according to the values below. +enum CoordIndex : uint8_t{ + Begin = 0, + G54 = Begin, + G55, + G56, + G57, + G58, + G59, + // To support 9 work coordinate systems it would be necessary to define + // the following 3 and modify GCode.cpp to support G59.1, G59.2, G59.3 + // G59_1, + // G59_2, + // G59_3, + NWCSystems, + G28 = NWCSystems, + G30, + // G92_2, + // G92_3, + End, +}; +// Allow iteration over CoordIndex values +CoordIndex& operator ++ (CoordIndex& i); + diff --git a/Grbl_Esp32/src/Stepper.cpp b/Grbl_Esp32/src/Stepper.cpp index 639abc06..858e15c2 100644 --- a/Grbl_Esp32/src/Stepper.cpp +++ b/Grbl_Esp32/src/Stepper.cpp @@ -296,9 +296,8 @@ static void stepper_pulse_func() { spindle->set_rpm(0); } } - - system_set_exec_state_flag(EXEC_CYCLE_STOP); // Flag main program for cycle end - return; // Nothing to do but exit. + cycle_stop = true; + return; // Nothing to do but exit. } } // Check probing state. @@ -362,8 +361,7 @@ static void stepper_pulse_func() { st.counter_a -= st.exec_block->step_event_count; if (st.exec_block->direction_bits & bit(A_AXIS)) { sys_position[A_AXIS]--; - } - else { + } else { sys_position[A_AXIS]++; } } @@ -379,8 +377,7 @@ static void stepper_pulse_func() { st.counter_b -= st.exec_block->step_event_count; if (st.exec_block->direction_bits & bit(B_AXIS)) { sys_position[B_AXIS]--; - } - else { + } else { sys_position[B_AXIS]++; } } @@ -396,8 +393,7 @@ static void stepper_pulse_func() { st.counter_c -= st.exec_block->step_event_count; if (st.exec_block->direction_bits & bit(C_AXIS)) { sys_position[C_AXIS]--; - } - else { + } else { sys_position[C_AXIS]++; } } @@ -1229,8 +1225,10 @@ float st_get_realtime_rate() { case State::Homing: case State::Hold: case State::Jog: - case State::SafetyDoor: return prep.current_speed; - default: return 0.0f; + case State::SafetyDoor: + return prep.current_speed; + default: + return 0.0f; } } diff --git a/Grbl_Esp32/src/System.cpp b/Grbl_Esp32/src/System.cpp index 2aa6ad67..7c434ec3 100644 --- a/Grbl_Esp32/src/System.cpp +++ b/Grbl_Esp32/src/System.cpp @@ -30,6 +30,7 @@ volatile uint8_t sys_rt_exec_state; // Global realtime executor 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 #ifdef DEBUG volatile uint8_t sys_rt_exec_debug; #endif diff --git a/Grbl_Esp32/src/System.h b/Grbl_Esp32/src/System.h index 361bb804..4568980d 100644 --- a/Grbl_Esp32/src/System.h +++ b/Grbl_Esp32/src/System.h @@ -39,7 +39,7 @@ enum class State : uint8_t { // Define global system variables typedef struct { - State state; // Tracks the current system state of Grbl. + 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) @@ -68,7 +68,7 @@ extern system_t sys; // 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 +// #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 @@ -163,6 +163,7 @@ extern volatile uint8_t sys_rt_exec_state; // Global realtime executor bitfla 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; #ifdef DEBUG # define EXEC_DEBUG_REPORT bit(0) @@ -228,5 +229,5 @@ 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_PWM_chan_num(); +int8_t sys_get_next_PWM_chan_num(); uint8_t sys_calc_pwm_precision(uint32_t freq);