├── .gitignore ├── README.md ├── TODO ├── lib ├── grbl │ └── src │ │ ├── config.hpp │ │ ├── coolant_control.cpp │ │ ├── coolant_control.hpp │ │ ├── cpu_map.hpp │ │ ├── credentials.hpp │ │ ├── defaults.hpp │ │ ├── eeprom.cpp │ │ ├── eeprom.hpp │ │ ├── gcode.cpp │ │ ├── gcode.hpp │ │ ├── grbl.hpp │ │ ├── jog.cpp │ │ ├── jog.hpp │ │ ├── limits.cpp │ │ ├── limits.hpp │ │ ├── motion_control.cpp │ │ ├── motion_control.hpp │ │ ├── nuts_bolts.cpp │ │ ├── nuts_bolts.hpp │ │ ├── planner.cpp │ │ ├── planner.hpp │ │ ├── print.cpp │ │ ├── print.hpp │ │ ├── probe.cpp │ │ ├── probe.hpp │ │ ├── protocol.cpp │ │ ├── protocol.hpp │ │ ├── report.cpp │ │ ├── report.hpp │ │ ├── serial.cpp │ │ ├── serial.hpp │ │ ├── serial2socket.cpp │ │ ├── serial2socket.hpp │ │ ├── settings.cpp │ │ ├── settings.hpp │ │ ├── spindle_control.cpp │ │ ├── spindle_control.hpp │ │ ├── stepper.cpp │ │ ├── stepper.hpp │ │ ├── system.cpp │ │ ├── system.hpp │ │ ├── telnet_server.cpp │ │ ├── telnet_server.hpp │ │ ├── websocket.cpp │ │ ├── websocket.hpp │ │ ├── wifi.cpp │ │ └── wifi.hpp └── readme.txt ├── platformio.ini ├── schemas ├── spi-connection.fzz └── spi-connection_schem.png └── src └── main.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | .pioenvs 2 | .piolibdeps 3 | .clang_complete 4 | .gcc-flags.json 5 | **/credentials.hpp 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GRBLESP 2 | 3 | Implements the latest version of GRBL using ESP8266 only, being able to connect by serial port, raw socket or websocket. 4 | To overcome the problem of the lack of pins, it uses SPI to drive 4 shift registers of 8 bits each. The aim of having 5 | 32 pins is to be able to handle up to 8 axis. 6 | 7 | Interfaces 8 | ---------- 9 | 10 | For the raw socket connection, you can use pyserial, which supports it through "socket" protocol. 11 | **socket://[IP_OF_ESP_DEVICE]:23**. It can be tested easily with [bCNC](https://github.com/vlachoudis/bCNC) 12 | 13 | 14 | For the websocket connection, the url is: **ws://[IP_OF_ESP_DEVICE]:80/ws** 15 | 16 | 17 | Wiring 18 | ------ 19 | 20 | - GPIO0 controls inputs as RESET, FEED_HOLD, START_CYCLE and SAFETY_DOOR 21 | 22 | - GPIO2 controls all limits switches 23 | 24 | - GPIO12 remains unused (because it functions as SPI HMISO) 25 | 26 | - GPIO13 sends data to the shift registers (SPI HMOSI) 27 | 28 | - GPIO14 clock signal for the shift registers (SPI HSCLK) 29 | 30 | - GPIO15 serves as CHIP_SELECT for the SPI 31 | 32 | The board should use 4 x 8-bit shift registers. They are arranged this way: 33 | - 8 bits for step pins 34 | - 8 bits for direction pins 35 | - 8 bits for Misc, inputs and outputs, following this structure (although it might change still a bit): 36 | 37 | #define CONTROL_RESET_BIT 0 38 | #define CONTROL_FEED_HOLD_BIT 1 39 | #define CONTROL_CYCLE_START_BIT 2 40 | #define CONTROL_SAFETY_DOOR_BIT 3 41 | #define PROBE_BIT 4 42 | #define COOLANT_FLOOD_BIT 5 43 | #define COOLANT_MIST_BIT 6 44 | #define STEPPERS_DISABLE_BIT 7 45 | 46 | - 8 bits for limits. All inputs 47 | 48 | Probe, spindle, and probably other features, are not yet supported 49 | 50 | ![Connection diagram](https://github.com/gcobos/grblesp/blob/master/schemas/spi-connection_schem.png) 51 | 52 | #### J4 53 | |Pin|Function|Type| 54 | |-|-|-| 55 | | 1 | STEP X | (output) | 56 | | 2 | STEP Y | (output) | 57 | | 3 | STEP Z | (output) | 58 | | 4 | STEP A | (output) | 59 | | 5 | STEP B | (output) | 60 | | 6 | STEP C | (output) | 61 | | 7 | STEP D | (output) | 62 | | 8 | STEP E | (output) | 63 | 64 | #### J3 65 | |Pin|Function|Type| 66 | |-|-|-| 67 | | 1 | DIR X |(output) | 68 | | 2 | DIR Y |(output) | 69 | | 3 | DIR Z |(output) | 70 | | 4 | DIR A |(output) | 71 | | 5 | DIR B |(output) | 72 | | 6 | DIR C |(output) | 73 | | 7 | DIR D |(output) | 74 | | 8 | DIR E |(output) | 75 | 76 | #### J2 77 | |Pin|Function|Type| 78 | |-|-|-| 79 | | 1 | RESET | (input) | 80 | | 2 | FEED HOLD | (input) | 81 | | 3 | CYCLE START | (input) | 82 | | 4 | SAFETY DOOR | (input) | 83 | | 5 | PROBE | (input) | 84 | | 6 | COOLANT/FLOOD |(output) | 85 | | 7 | COOLANT/MIST |(output) | 86 | | 8 | STEPPERS_DISABLE |(output) | 87 | 88 | #### J1 89 | |Pin|Function|Type| 90 | |-|-|-| 91 | | 1 | LIMIT X | (input) | 92 | | 2 | LIMIT Y | (input) | 93 | | 3 | LIMIT Z | (input) | 94 | | 4 | LIMIT A | (input) | 95 | | 5 | LIMIT B | (input) | 96 | | 6 | LIMIT C | (input) | 97 | | 7 | LIMIT D | (input) | 98 | | 8 | LIMIT E | (input) | 99 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | 2 | - Input system 3 | - Change AsyncWebSockets to WebSockets maybe? 4 | - Connecting bCNC through sockets! -------------------------------------------------------------------------------- /lib/grbl/src/coolant_control.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | coolant_control.c - coolant control methods 3 | Part of Grbl 4 | 5 | Copyright (c) 2012-2016 Sungeun K. Jeon for Gnea Research LLC 6 | 7 | Grbl is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Grbl is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with Grbl. If not, see . 19 | */ 20 | 21 | #include "grbl.hpp" 22 | 23 | 24 | void coolant_init() 25 | { 26 | COOLANT_FLOOD_PORT |= (1 << COOLANT_FLOOD_BIT); // Configure as output pin 27 | #ifdef ENABLE_M7 28 | COOLANT_MIST_PORT |= (1 << COOLANT_MIST_BIT); 29 | #endif 30 | coolant_stop(); 31 | } 32 | 33 | 34 | // Returns current coolant output state. Overrides may alter it from programmed state. 35 | uint8_t coolant_get_state() 36 | { 37 | uint8_t cl_state = COOLANT_STATE_DISABLE; 38 | #ifdef INVERT_COOLANT_FLOOD_PIN 39 | if (bit_isfalse(COOLANT_FLOOD_PORT,(1 << COOLANT_FLOOD_BIT))) { 40 | #else 41 | if (bit_istrue(COOLANT_FLOOD_PORT,(1 << COOLANT_FLOOD_BIT))) { 42 | #endif 43 | cl_state |= COOLANT_STATE_FLOOD; 44 | } 45 | #ifdef ENABLE_M7 46 | #ifdef INVERT_COOLANT_MIST_PIN 47 | if (bit_isfalse(COOLANT_MIST_PORT,(1 << COOLANT_MIST_BIT))) { 48 | #else 49 | if (bit_istrue(COOLANT_MIST_PORT,(1 << COOLANT_MIST_BIT))) { 50 | #endif 51 | cl_state |= COOLANT_STATE_MIST; 52 | } 53 | #endif 54 | return(cl_state); 55 | } 56 | 57 | 58 | // Directly called by coolant_init(), coolant_set_state(), and mc_reset(), which can be at 59 | // an interrupt-level. No report flag set, but only called by routines that don't need it. 60 | void coolant_stop() 61 | { 62 | #ifdef INVERT_COOLANT_FLOOD_PIN 63 | COOLANT_FLOOD_PORT |= (1 << COOLANT_FLOOD_BIT); 64 | #else 65 | COOLANT_FLOOD_PORT &= ~(1 << COOLANT_FLOOD_BIT); 66 | #endif 67 | #ifdef ENABLE_M7 68 | #ifdef INVERT_COOLANT_MIST_PIN 69 | COOLANT_MIST_PORT |= (1 << COOLANT_MIST_BIT); 70 | #else 71 | COOLANT_MIST_PORT &= ~(1 << COOLANT_MIST_BIT); 72 | #endif 73 | #endif 74 | } 75 | 76 | 77 | // Main program only. Immediately sets flood coolant running state and also mist coolant, 78 | // if enabled. Also sets a flag to report an update to a coolant state. 79 | // Called by coolant toggle override, parking restore, parking retract, sleep mode, g-code 80 | // parser program end, and g-code parser coolant_sync(). 81 | void coolant_set_state(uint8_t mode) 82 | { 83 | if (sys.abort) { return; } // Block during abort. 84 | 85 | if (mode & COOLANT_FLOOD_ENABLE) { 86 | #ifdef INVERT_COOLANT_FLOOD_PIN 87 | COOLANT_FLOOD_PORT &= ~(1 << COOLANT_FLOOD_BIT); 88 | #else 89 | COOLANT_FLOOD_PORT |= (1 << COOLANT_FLOOD_BIT); 90 | #endif 91 | } else { 92 | #ifdef INVERT_COOLANT_FLOOD_PIN 93 | COOLANT_FLOOD_PORT |= (1 << COOLANT_FLOOD_BIT); 94 | #else 95 | COOLANT_FLOOD_PORT &= ~(1 << COOLANT_FLOOD_BIT); 96 | #endif 97 | } 98 | 99 | #ifdef ENABLE_M7 100 | if (mode & COOLANT_MIST_ENABLE) { 101 | #ifdef INVERT_COOLANT_MIST_PIN 102 | COOLANT_MIST_PORT &= ~(1 << COOLANT_MIST_BIT); 103 | #else 104 | COOLANT_MIST_PORT |= (1 << COOLANT_MIST_BIT); 105 | #endif 106 | } else { 107 | #ifdef INVERT_COOLANT_MIST_PIN 108 | COOLANT_MIST_PORT |= (1 << COOLANT_MIST_BIT); 109 | #else 110 | COOLANT_MIST_PORT &= ~(1 << COOLANT_MIST_BIT); 111 | #endif 112 | } 113 | #endif 114 | 115 | sys.report_ovr_counter = 0; // Set to report change immediately 116 | } 117 | 118 | 119 | // G-code parser entry-point for setting coolant state. Forces a planner buffer sync and bails 120 | // if an abort or check-mode is active. 121 | void coolant_sync(uint8_t mode) 122 | { 123 | if (sys.state == STATE_CHECK_MODE) { return; } 124 | protocol_buffer_synchronize(); // Ensure coolant turns on when specified in program. 125 | coolant_set_state(mode); 126 | } 127 | -------------------------------------------------------------------------------- /lib/grbl/src/coolant_control.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | coolant_control.h - spindle control methods 3 | Part of Grbl 4 | 5 | Copyright (c) 2012-2016 Sungeun K. Jeon for Gnea Research LLC 6 | 7 | Grbl is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Grbl is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with Grbl. If not, see . 19 | */ 20 | 21 | #ifndef coolant_control_h 22 | #define coolant_control_h 23 | 24 | #define COOLANT_NO_SYNC false 25 | #define COOLANT_FORCE_SYNC true 26 | 27 | #define COOLANT_STATE_DISABLE 0 // Must be zero 28 | #define COOLANT_STATE_FLOOD PL_COND_FLAG_COOLANT_FLOOD 29 | #define COOLANT_STATE_MIST PL_COND_FLAG_COOLANT_MIST 30 | 31 | 32 | // Initializes coolant control pins. 33 | void coolant_init(); 34 | 35 | // Returns current coolant output state. Overrides may alter it from programmed state. 36 | uint8_t coolant_get_state(); 37 | 38 | // Immediately disables coolant pins. 39 | void coolant_stop(); 40 | 41 | // Sets the coolant pins according to state specified. 42 | void coolant_set_state(uint8_t mode); 43 | 44 | // G-code parser entry-point for setting coolant states. Checks for and executes additional conditions. 45 | void coolant_sync(uint8_t mode); 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /lib/grbl/src/cpu_map.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | cpu_map.hpp - Machine dependent code for the ESP8266 and family 3 | Part of Grbl 4 | 5 | Copyright (c) 2012-2016 Sungeun K. Jeon for Gnea Research LLC 6 | 7 | Grbl is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Grbl is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with Grbl. If not, see . 19 | */ 20 | 21 | /* The cpu_map.h files serve as a central pin mapping selection file for different 22 | processor types or alternative pin layouts. This version of Grbl officially supports 23 | only the Arduino Mega328p. */ 24 | 25 | 26 | #ifndef cpu_map_h 27 | #define cpu_map_h 28 | 29 | #define save_SREG() xt_rsil(2); // this routine will allow level 3 and above (returns an uint32_t) 30 | #define restore_SREG(state) xt_wsr_ps(state); sei(); // restore the state (uint32_t) 31 | 32 | volatile static union { 33 | uint32_t data; 34 | struct { 35 | uint8_t STEP_PORT_OFFSET:8; // All outputs 36 | uint8_t DIRECTION_PORT_OFFSET:8; // All outputs 37 | uint8_t MISC_PORT_OFFSET:8; // Inputs and outputs 38 | uint8_t LIMIT_PORT_OFFSET:8; // All inputs 39 | }; 40 | } regs; 41 | 42 | // Used to modify SPI registers without altering Grbl's registers 43 | decltype(regs) regs_tmp; 44 | 45 | #ifdef CPU_MAP_ESP8266 46 | 47 | // Define serial port pins and interrupt vectors. 48 | #define SERIAL_RX USART_RX_vect 49 | #define SERIAL_UDRE USART_UDRE_vect 50 | 51 | // Define step pulse output pins. NOTE: All step bit pins must be on the same port. 52 | #define STEP_PORT regs.STEP_PORT_OFFSET 53 | #define X_STEP_BIT 0 54 | #define Y_STEP_BIT 1 55 | #define Z_STEP_BIT 2 56 | #define A_STEP_BIT 3 57 | #define B_STEP_BIT 4 58 | #define C_STEP_BIT 5 59 | #define D_STEP_BIT 6 60 | #define E_STEP_BIT 7 61 | #define STEP_MASK ((1< 62.5kHz 155 | // #define SPINDLE_TCCRB_INIT_MASK (1< 7.8kHz (Used in v0.9) 156 | // #define SPINDLE_TCCRB_INIT_MASK ((1< 1.96kHz 157 | #define SPINDLE_TCCRB_INIT_MASK (1< 0.98kHz (J-tech laser) 158 | 159 | // NOTE: On the 328p, these must be the same as the SPINDLE_ENABLE settings. 160 | #define SPINDLE_PWM_DDR DDRB 161 | #define SPINDLE_PWM_PORT PORTB 162 | #define SPINDLE_PWM_BIT 3 // Uno Digital Pin 11 163 | 164 | #define CONTROL_INPUT_GPIO_PIN D3 // GPIO_0 = D3 165 | 166 | #define LIMIT_INPUT_GPIO_PIN D4 // GPIO_2 = D4 167 | 168 | #define F_STEPPER_TIMER 80000000/2 // frequency in Hz of step pulse timer (SPI) 169 | 170 | #endif 171 | 172 | /* 173 | #ifdef CPU_MAP_CUSTOM_PROC 174 | // For a custom pin map or different processor, copy and edit one of the available cpu 175 | // map files and modify it to your needs. Make sure the defined name is also changed in 176 | // the config.h file. 177 | #endif 178 | */ 179 | 180 | #endif /* CPU_MAP_H_ */ 181 | -------------------------------------------------------------------------------- /lib/grbl/src/credentials.hpp: -------------------------------------------------------------------------------- 1 | #ifndef credentials_h 2 | #define credentials_h 3 | 4 | #define WIFI_SSID "Whatever" 5 | #define WIFI_PASSWORD "mydummypassword" 6 | #define WIFI_HOSTNAME "grblesp" 7 | 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /lib/grbl/src/eeprom.cpp: -------------------------------------------------------------------------------- 1 | // This file has been prepared for Doxygen automatic documentation generation. 2 | /*! \file ******************************************************************** 3 | * Taken from ArduinoESP examples 4 | ******************************************************************************/ 5 | 6 | #include 7 | 8 | /*! \brief Read byte from EEPROM. 9 | * 10 | * This function Initializes the EEPROM buffer. 11 | * 12 | */ 13 | void eeprom_init() 14 | { 15 | EEPROM.begin(2048); 16 | } 17 | 18 | /*! \brief Read byte from EEPROM. 19 | * 20 | * This function reads one byte from a given EEPROM address. 21 | * 22 | * \note The CPU is halted for 4 clock cycles during EEPROM read. 23 | * 24 | * \param addr EEPROM address to read from. 25 | * \return The byte read from the EEPROM address. 26 | */ 27 | unsigned char eeprom_get_char( unsigned int addr ) 28 | { 29 | return EEPROM.read(addr); // Return the byte read from EEPROM. 30 | } 31 | 32 | /*! \brief Write byte to EEPROM. 33 | * 34 | * This function writes one byte to a given EEPROM address. 35 | * 36 | * \param addr EEPROM address to write to. 37 | * \param new_value New EEPROM value. 38 | */ 39 | void eeprom_put_char( unsigned int addr, unsigned char new_value ) 40 | { 41 | EEPROM.write(addr, new_value); 42 | } 43 | 44 | // Extensions added as part of Grbl 45 | 46 | 47 | void memcpy_to_eeprom_with_checksum(unsigned int destination, char *source, unsigned int size) { 48 | unsigned char checksum = 0; 49 | for(; size > 0; size--) { 50 | checksum = (checksum << 1) || (checksum >> 7); 51 | checksum += *source; 52 | eeprom_put_char(destination++, *(source++)); 53 | } 54 | eeprom_put_char(destination, checksum); 55 | EEPROM.commit(); 56 | } 57 | 58 | int memcpy_from_eeprom_with_checksum(char *destination, unsigned int source, unsigned int size) { 59 | unsigned char data, checksum = 0; 60 | for(; size > 0; size--) { 61 | data = eeprom_get_char(source++); 62 | checksum = (checksum << 1) || (checksum >> 7); 63 | checksum += data; 64 | *(destination++) = data; 65 | } 66 | return(checksum == eeprom_get_char(source)); 67 | } 68 | 69 | // end of file 70 | -------------------------------------------------------------------------------- /lib/grbl/src/eeprom.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | eeprom.h - EEPROM methods 3 | Part of Grbl 4 | 5 | Copyright (c) 2009-2011 Simen Svale Skogsrud 6 | 7 | Grbl is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Grbl is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with Grbl. If not, see . 19 | */ 20 | 21 | #ifndef eeprom_h 22 | #define eeprom_h 23 | 24 | #ifdef ESP8266 25 | //extern "C" { 26 | #include 27 | //} 28 | #endif 29 | 30 | void eeprom_init(); 31 | unsigned char eeprom_get_char(unsigned int addr); 32 | void eeprom_put_char(unsigned int addr, unsigned char new_value); 33 | void memcpy_to_eeprom_with_checksum(unsigned int destination, char *source, unsigned int size); 34 | int memcpy_from_eeprom_with_checksum(char *destination, unsigned int source, unsigned int size); 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /lib/grbl/src/gcode.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | gcode.h - rs274/ngc parser. 3 | Part of Grbl 4 | 5 | Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC 6 | Copyright (c) 2009-2011 Simen Svale Skogsrud 7 | 8 | Grbl is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | Grbl is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with Grbl. If not, see . 20 | */ 21 | 22 | #ifndef gcode_h 23 | #define gcode_h 24 | 25 | 26 | // Define modal group internal numbers for checking multiple command violations and tracking the 27 | // type of command that is called in the block. A modal group is a group of g-code commands that are 28 | // mutually exclusive, or cannot exist on the same line, because they each toggle a state or execute 29 | // a unique motion. These are defined in the NIST RS274-NGC v3 g-code standard, available online, 30 | // and are similar/identical to other g-code interpreters by manufacturers (Haas,Fanuc,Mazak,etc). 31 | // NOTE: Modal group define values must be sequential and starting from zero. 32 | #define MODAL_GROUP_G0 0 // [G4,G10,G28,G28.1,G30,G30.1,G53,G92,G92.1] Non-modal 33 | #define MODAL_GROUP_G1 1 // [G0,G1,G2,G3,G38.2,G38.3,G38.4,G38.5,G80] Motion 34 | #define MODAL_GROUP_G2 2 // [G17,G18,G19] Plane selection 35 | #define MODAL_GROUP_G3 3 // [G90,G91] Distance mode 36 | #define MODAL_GROUP_G4 4 // [G91.1] Arc IJK distance mode 37 | #define MODAL_GROUP_G5 5 // [G93,G94] Feed rate mode 38 | #define MODAL_GROUP_G6 6 // [G20,G21] Units 39 | #define MODAL_GROUP_G7 7 // [G40] Cutter radius compensation mode. G41/42 NOT SUPPORTED. 40 | #define MODAL_GROUP_G8 8 // [G43.1,G49] Tool length offset 41 | #define MODAL_GROUP_G12 9 // [G54,G55,G56,G57,G58,G59] Coordinate system selection 42 | #define MODAL_GROUP_G13 10 // [G61] Control mode 43 | 44 | #define MODAL_GROUP_M4 11 // [M0,M1,M2,M30] Stopping 45 | #define MODAL_GROUP_M7 12 // [M3,M4,M5] Spindle turning 46 | #define MODAL_GROUP_M8 13 // [M7,M8,M9] Coolant control 47 | #define MODAL_GROUP_M9 14 // [M56] Override control 48 | 49 | // Define command actions for within execution-type modal groups (motion, stopping, non-modal). Used 50 | // internally by the parser to know which command to execute. 51 | // NOTE: Some macro values are assigned specific values to make g-code state reporting and parsing 52 | // compile a little smaller. Necessary due to being completely out of flash on the 328p. Although not 53 | // ideal, just be careful with values that state 'do not alter' and check both report.c and gcode.c 54 | // to see how they are used, if you need to alter them. 55 | 56 | // Modal Group G0: Non-modal actions 57 | #define NON_MODAL_NO_ACTION 0 // (Default: Must be zero) 58 | #define NON_MODAL_DWELL 4 // G4 (Do not alter value) 59 | #define NON_MODAL_SET_COORDINATE_DATA 10 // G10 (Do not alter value) 60 | #define NON_MODAL_GO_HOME_0 28 // G28 (Do not alter value) 61 | #define NON_MODAL_SET_HOME_0 38 // G28.1 (Do not alter value) 62 | #define NON_MODAL_GO_HOME_1 30 // G30 (Do not alter value) 63 | #define NON_MODAL_SET_HOME_1 40 // G30.1 (Do not alter value) 64 | #define NON_MODAL_ABSOLUTE_OVERRIDE 53 // G53 (Do not alter value) 65 | #define NON_MODAL_SET_COORDINATE_OFFSET 92 // G92 (Do not alter value) 66 | #define NON_MODAL_RESET_COORDINATE_OFFSET 102 //G92.1 (Do not alter value) 67 | 68 | // Modal Group G1: Motion modes 69 | #define MOTION_MODE_SEEK 0 // G0 (Default: Must be zero) 70 | #define MOTION_MODE_LINEAR 1 // G1 (Do not alter value) 71 | #define MOTION_MODE_CW_ARC 2 // G2 (Do not alter value) 72 | #define MOTION_MODE_CCW_ARC 3 // G3 (Do not alter value) 73 | #define MOTION_MODE_PROBE_TOWARD 140 // G38.2 (Do not alter value) 74 | #define MOTION_MODE_PROBE_TOWARD_NO_ERROR 141 // G38.3 (Do not alter value) 75 | #define MOTION_MODE_PROBE_AWAY 142 // G38.4 (Do not alter value) 76 | #define MOTION_MODE_PROBE_AWAY_NO_ERROR 143 // G38.5 (Do not alter value) 77 | #define MOTION_MODE_NONE 80 // G80 (Do not alter value) 78 | 79 | // Modal Group G2: Plane select 80 | #define PLANE_SELECT_XY 0 // G17 (Default: Must be zero) 81 | #define PLANE_SELECT_ZX 1 // G18 (Do not alter value) 82 | #define PLANE_SELECT_YZ 2 // G19 (Do not alter value) 83 | 84 | // Modal Group G3: Distance mode 85 | #define DISTANCE_MODE_ABSOLUTE 0 // G90 (Default: Must be zero) 86 | #define DISTANCE_MODE_INCREMENTAL 1 // G91 (Do not alter value) 87 | 88 | // Modal Group G4: Arc IJK distance mode 89 | #define DISTANCE_ARC_MODE_INCREMENTAL 0 // G91.1 (Default: Must be zero) 90 | 91 | // Modal Group M4: Program flow 92 | #define PROGRAM_FLOW_RUNNING 0 // (Default: Must be zero) 93 | #define PROGRAM_FLOW_PAUSED 3 // M0 94 | #define PROGRAM_FLOW_OPTIONAL_STOP 1 // M1 NOTE: Not supported, but valid and ignored. 95 | #define PROGRAM_FLOW_COMPLETED_M2 2 // M2 (Do not alter value) 96 | #define PROGRAM_FLOW_COMPLETED_M30 30 // M30 (Do not alter value) 97 | 98 | // Modal Group G5: Feed rate mode 99 | #define FEED_RATE_MODE_UNITS_PER_MIN 0 // G94 (Default: Must be zero) 100 | #define FEED_RATE_MODE_INVERSE_TIME 1 // G93 (Do not alter value) 101 | 102 | // Modal Group G6: Units mode 103 | #define UNITS_MODE_MM 0 // G21 (Default: Must be zero) 104 | #define UNITS_MODE_INCHES 1 // G20 (Do not alter value) 105 | 106 | // Modal Group G7: Cutter radius compensation mode 107 | #define CUTTER_COMP_DISABLE 0 // G40 (Default: Must be zero) 108 | 109 | // Modal Group G13: Control mode 110 | #define CONTROL_MODE_EXACT_PATH 0 // G61 (Default: Must be zero) 111 | 112 | // Modal Group M7: Spindle control 113 | #define SPINDLE_DISABLE 0 // M5 (Default: Must be zero) 114 | #define SPINDLE_ENABLE_CW PL_COND_FLAG_SPINDLE_CW // M3 (NOTE: Uses planner condition bit flag) 115 | #define SPINDLE_ENABLE_CCW PL_COND_FLAG_SPINDLE_CCW // M4 (NOTE: Uses planner condition bit flag) 116 | 117 | // Modal Group M8: Coolant control 118 | #define COOLANT_DISABLE 0 // M9 (Default: Must be zero) 119 | #define COOLANT_FLOOD_ENABLE PL_COND_FLAG_COOLANT_FLOOD // M8 (NOTE: Uses planner condition bit flag) 120 | #define COOLANT_MIST_ENABLE PL_COND_FLAG_COOLANT_MIST // M7 (NOTE: Uses planner condition bit flag) 121 | 122 | // Modal Group G8: Tool length offset 123 | #define TOOL_LENGTH_OFFSET_CANCEL 0 // G49 (Default: Must be zero) 124 | #define TOOL_LENGTH_OFFSET_ENABLE_DYNAMIC 1 // G43.1 125 | 126 | // Modal Group M9: Override control 127 | #ifdef DEACTIVATE_PARKING_UPON_INIT 128 | #define OVERRIDE_DISABLED 0 // (Default: Must be zero) 129 | #define OVERRIDE_PARKING_MOTION 1 // M56 130 | #else 131 | #define OVERRIDE_PARKING_MOTION 0 // M56 (Default: Must be zero) 132 | #define OVERRIDE_DISABLED 1 // Parking disabled. 133 | #endif 134 | 135 | // Modal Group G12: Active work coordinate system 136 | // N/A: Stores coordinate system value (54-59) to change to. 137 | 138 | // Define parameter word mapping. 139 | #define WORD_F 0 140 | #define WORD_I 1 141 | #define WORD_J 2 142 | #define WORD_K 3 143 | #define WORD_L 4 144 | #define WORD_N 5 145 | #define WORD_P 6 146 | #define WORD_R 7 147 | #define WORD_S 8 148 | #define WORD_T 9 149 | #define WORD_X 10 150 | #define WORD_Y 11 151 | #define WORD_Z 12 152 | #define WORD_A 13 153 | #define WORD_B 14 154 | #define WORD_C 15 155 | #define WORD_D 16 156 | #define WORD_E 17 157 | 158 | // Define g-code parser position updating flags 159 | #define GC_UPDATE_POS_TARGET 0 // Must be zero 160 | #define GC_UPDATE_POS_SYSTEM 1 161 | #define GC_UPDATE_POS_NONE 2 162 | 163 | // Define probe cycle exit states and assign proper position updating. 164 | #define GC_PROBE_FOUND GC_UPDATE_POS_SYSTEM 165 | #define GC_PROBE_ABORT GC_UPDATE_POS_NONE 166 | #define GC_PROBE_FAIL_INIT GC_UPDATE_POS_NONE 167 | #define GC_PROBE_FAIL_END GC_UPDATE_POS_TARGET 168 | #ifdef SET_CHECK_MODE_PROBE_TO_START 169 | #define GC_PROBE_CHECK_MODE GC_UPDATE_POS_NONE 170 | #else 171 | #define GC_PROBE_CHECK_MODE GC_UPDATE_POS_TARGET 172 | #endif 173 | 174 | // Define gcode parser flags for handling special cases. 175 | #define GC_PARSER_NONE 0 // Must be zero. 176 | #define GC_PARSER_JOG_MOTION bit(0) 177 | #define GC_PARSER_CHECK_MANTISSA bit(1) 178 | #define GC_PARSER_ARC_IS_CLOCKWISE bit(2) 179 | #define GC_PARSER_PROBE_IS_AWAY bit(3) 180 | #define GC_PARSER_PROBE_IS_NO_ERROR bit(4) 181 | #define GC_PARSER_LASER_FORCE_SYNC bit(5) 182 | #define GC_PARSER_LASER_DISABLE bit(6) 183 | #define GC_PARSER_LASER_ISMOTION bit(7) 184 | 185 | 186 | // NOTE: When this struct is zeroed, the above defines set the defaults for the system. 187 | typedef struct { 188 | uint8_t motion; // {G0,G1,G2,G3,G38.2,G80} 189 | uint8_t feed_rate; // {G93,G94} 190 | uint8_t units; // {G20,G21} 191 | uint8_t distance; // {G90,G91} 192 | // uint8_t distance_arc; // {G91.1} NOTE: Don't track. Only default supported. 193 | uint8_t plane_select; // {G17,G18,G19} 194 | // uint8_t cutter_comp; // {G40} NOTE: Don't track. Only default supported. 195 | uint8_t tool_length; // {G43.1,G49} 196 | uint8_t coord_select; // {G54,G55,G56,G57,G58,G59} 197 | // uint8_t control; // {G61} NOTE: Don't track. Only default supported. 198 | uint8_t program_flow; // {M0,M1,M2,M30} 199 | uint8_t coolant; // {M7,M8,M9} 200 | uint8_t spindle; // {M3,M4,M5} 201 | uint8_t override; // {M56} 202 | } gc_modal_t; 203 | 204 | typedef struct { 205 | float f; // Feed 206 | float ijk[N_AXIS]; // I,J,K... Axis arc offsets 207 | uint8_t l; // G10 or canned cycles parameters 208 | int32_t n; // Line number 209 | float p; // G10 or dwell parameters 210 | // float q; // G82 peck drilling 211 | float r; // Arc radius 212 | float s; // Spindle speed 213 | uint8_t t; // Tool selection 214 | float xyz[N_AXIS]; // X,Y,Z... Translational axes 215 | } gc_values_t; 216 | 217 | 218 | typedef struct { 219 | gc_modal_t modal; 220 | 221 | float spindle_speed; // RPM 222 | float feed_rate; // Millimeters/min 223 | uint8_t tool; // Tracks tool number. NOT USED. 224 | int32_t line_number; // Last line number sent 225 | 226 | float position[N_AXIS]; // Where the interpreter considers the tool to be at this point in the code 227 | 228 | float coord_system[N_AXIS]; // Current work coordinate system (G54+). Stores offset from absolute machine 229 | // position in mm. Loaded from EEPROM when called. 230 | float coord_offset[N_AXIS]; // Retains the G92 coordinate offset (work coordinates) relative to 231 | // machine zero in mm. Non-persistent. Cleared upon reset and boot. 232 | float tool_length_offset; // Tracks tool length offset value when enabled. 233 | } parser_state_t; 234 | extern parser_state_t gc_state; 235 | 236 | 237 | typedef struct { 238 | uint8_t non_modal_command; 239 | gc_modal_t modal; 240 | gc_values_t values; 241 | } parser_block_t; 242 | 243 | 244 | // Initialize the parser 245 | void gc_init(); 246 | 247 | // Execute one block of rs275/ngc/g-code 248 | uint8_t gc_execute_line(char *line, uint8_t client); 249 | 250 | // Set g-code parser position. Input in steps. 251 | void gc_sync_position(); 252 | 253 | #endif 254 | -------------------------------------------------------------------------------- /lib/grbl/src/grbl.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | grbl.h - main Grbl include file 3 | Part of Grbl 4 | 5 | Copyright (c) 2015-2016 Sungeun K. Jeon for Gnea Research LLC 6 | 7 | Grbl is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Grbl is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with Grbl. If not, see . 19 | */ 20 | 21 | #ifndef grbl_h 22 | #define grbl_h 23 | 24 | // Grbl versioning system 25 | #define GRBL_VERSION "1.1g" 26 | #define GRBL_VERSION_BUILD "20181112" 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | // Define the Grbl system include files. NOTE: Do not alter organization. 37 | #include "config.hpp" 38 | 39 | #include "nuts_bolts.hpp" 40 | #include "settings.hpp" 41 | #include "system.hpp" 42 | #include "defaults.hpp" 43 | #include "cpu_map.hpp" 44 | #include "planner.hpp" 45 | #include "coolant_control.hpp" 46 | #include "eeprom.hpp" 47 | #include "gcode.hpp" 48 | #include "limits.hpp" 49 | #include "motion_control.hpp" 50 | #include "planner.hpp" 51 | #include "print.hpp" 52 | #include "probe.hpp" 53 | #include "protocol.hpp" 54 | #include "report.hpp" 55 | #include "serial.hpp" 56 | #ifdef ENABLE_WIFI 57 | #include "wifi.hpp" 58 | #ifdef ENABLE_WEBSOCKET 59 | #include "websocket.hpp" 60 | #include "serial2socket.hpp" 61 | #endif 62 | #ifdef ENABLE_TELNET 63 | #include "telnet_server.hpp" 64 | #endif 65 | #endif 66 | #include "spindle_control.hpp" 67 | #include "stepper.hpp" 68 | #include "jog.hpp" 69 | 70 | // --------------------------------------------------------------------------------------- 71 | // COMPILE-TIME ERROR CHECKING OF DEFINE VALUES: 72 | 73 | #ifndef HOMING_CYCLE_0 74 | #error "Required HOMING_CYCLE_0 not defined." 75 | #endif 76 | 77 | #if defined(USE_SPINDLE_DIR_AS_ENABLE_PIN) && !defined(VARIABLE_SPINDLE) 78 | #error "USE_SPINDLE_DIR_AS_ENABLE_PIN may only be used with VARIABLE_SPINDLE enabled" 79 | #endif 80 | 81 | #if defined(USE_SPINDLE_DIR_AS_ENABLE_PIN) && !defined(CPU_MAP_ATMEGA328P) 82 | #error "USE_SPINDLE_DIR_AS_ENABLE_PIN may only be used with a 328p processor" 83 | #endif 84 | 85 | #if !defined(USE_SPINDLE_DIR_AS_ENABLE_PIN) && defined(SPINDLE_ENABLE_OFF_WITH_ZERO_SPEED) 86 | #error "SPINDLE_ENABLE_OFF_WITH_ZERO_SPEED may only be used with USE_SPINDLE_DIR_AS_ENABLE_PIN enabled" 87 | #endif 88 | 89 | #if defined(PARKING_ENABLE) 90 | #if defined(HOMING_FORCE_SET_ORIGIN) 91 | #error "HOMING_FORCE_SET_ORIGIN is not supported with PARKING_ENABLE at this time." 92 | #endif 93 | #endif 94 | 95 | #if defined(ENABLE_PARKING_OVERRIDE_CONTROL) 96 | #if !defined(PARKING_ENABLE) 97 | #error "ENABLE_PARKING_OVERRIDE_CONTROL must be enabled with PARKING_ENABLE." 98 | #endif 99 | #endif 100 | 101 | #if defined(SPINDLE_PWM_MIN_VALUE) 102 | #if !(SPINDLE_PWM_MIN_VALUE > 0) 103 | #error "SPINDLE_PWM_MIN_VALUE must be greater than zero." 104 | #endif 105 | #endif 106 | 107 | #if (REPORT_WCO_REFRESH_BUSY_COUNT < REPORT_WCO_REFRESH_IDLE_COUNT) 108 | #error "WCO busy refresh is less than idle refresh." 109 | #endif 110 | #if (REPORT_OVR_REFRESH_BUSY_COUNT < REPORT_OVR_REFRESH_IDLE_COUNT) 111 | #error "Override busy refresh is less than idle refresh." 112 | #endif 113 | #if (REPORT_WCO_REFRESH_IDLE_COUNT < 2) 114 | #error "WCO refresh must be greater than one." 115 | #endif 116 | #if (REPORT_OVR_REFRESH_IDLE_COUNT < 1) 117 | #error "Override refresh must be greater than zero." 118 | #endif 119 | 120 | // --------------------------------------------------------------------------------------- 121 | 122 | #endif 123 | -------------------------------------------------------------------------------- /lib/grbl/src/jog.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | jog.h - Jogging methods 3 | Part of Grbl 4 | 5 | Copyright (c) 2016 Sungeun K. Jeon for Gnea Research LLC 6 | 7 | Grbl is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Grbl is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with Grbl. If not, see . 19 | */ 20 | 21 | #include "grbl.hpp" 22 | 23 | 24 | // Sets up valid jog motion received from g-code parser, checks for soft-limits, and executes the jog. 25 | uint8_t jog_execute(plan_line_data_t *pl_data, parser_block_t *gc_block) 26 | { 27 | // Initialize planner data struct for jogging motions. 28 | // NOTE: Spindle and coolant are allowed to fully function with overrides during a jog. 29 | pl_data->feed_rate = gc_block->values.f; 30 | pl_data->condition |= PL_COND_FLAG_NO_FEED_OVERRIDE; 31 | #ifdef USE_LINE_NUMBERS 32 | pl_data->line_number = gc_block->values.n; 33 | #endif 34 | 35 | if (bit_istrue(settings.flags,BITFLAG_SOFT_LIMIT_ENABLE)) { 36 | if (system_check_travel_limits(gc_block->values.xyz)) { return(STATUS_TRAVEL_EXCEEDED); } 37 | } 38 | 39 | // Valid jog command. Plan, set state, and execute. 40 | mc_line(gc_block->values.xyz,pl_data); 41 | if (sys.state == STATE_IDLE) { 42 | if (plan_get_current_block() != NULL) { // Check if there is a block to execute. 43 | sys.state = STATE_JOG; 44 | st_prep_buffer(); 45 | st_wake_up(); // NOTE: Manual start. No state machine required. 46 | } 47 | } 48 | 49 | return(STATUS_OK); 50 | } 51 | -------------------------------------------------------------------------------- /lib/grbl/src/jog.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | jog.h - Jogging methods 3 | Part of Grbl 4 | 5 | Copyright (c) 2016 Sungeun K. Jeon for Gnea Research LLC 6 | 7 | Grbl is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Grbl is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with Grbl. If not, see . 19 | */ 20 | 21 | #ifndef jog_h 22 | #define jog_h 23 | 24 | #include "gcode.hpp" 25 | 26 | // System motion line numbers must be zero. 27 | #define JOG_LINE_NUMBER 0 28 | 29 | // Sets up valid jog motion received from g-code parser, checks for soft-limits, and executes the jog. 30 | uint8_t jog_execute(plan_line_data_t *pl_data, parser_block_t *gc_block); 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /lib/grbl/src/limits.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | limits.c - code pertaining to limit-switches and performing the homing cycle 3 | Part of Grbl 4 | 5 | Copyright (c) 2012-2016 Sungeun K. Jeon for Gnea Research LLC 6 | Copyright (c) 2009-2011 Simen Svale Skogsrud 7 | 8 | Grbl is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | Grbl is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with Grbl. If not, see . 20 | */ 21 | 22 | #include "grbl.hpp" 23 | #include 24 | 25 | // Homing axis search distance multiplier. Computed by this value times the cycle travel. 26 | #ifndef HOMING_AXIS_SEARCH_SCALAR 27 | #define HOMING_AXIS_SEARCH_SCALAR 1.5 // Must be > 1 to ensure limit switch will be engaged. 28 | #endif 29 | #ifndef HOMING_AXIS_LOCATE_SCALAR 30 | #define HOMING_AXIS_LOCATE_SCALAR 5.0 // Must be > 1 to ensure limit switch is cleared. 31 | #endif 32 | 33 | void limits_init() 34 | { 35 | // Turn off all limit inputs 36 | LIMIT_PORT &= ~LIMIT_MASK; 37 | SPI.write(regs.data); 38 | 39 | // Attach interrupt to limit input pin 40 | pinMode(LIMIT_INPUT_GPIO_PIN, INPUT_PULLUP); 41 | attachInterrupt(digitalPinToInterrupt(LIMIT_INPUT_GPIO_PIN), pin_limit_vect, CHANGE); 42 | } 43 | 44 | // Disables hard limits. 45 | void limits_disable() 46 | { 47 | detachInterrupt(digitalPinToInterrupt(LIMIT_INPUT_GPIO_PIN)); 48 | } 49 | 50 | 51 | // Returns limit state as a bit-wise uint8 variable. Each bit indicates an axis limit, where 52 | // triggered is 1 and not triggered is 0. Invert mask is applied. Axes are defined by their 53 | // number in bit position, i.e. Z_AXIS is (1<<2) or bit 2, and Y_AXIS is (1<<1) or bit 1. 54 | uint8_t limits_get_state() 55 | { 56 | uint8_t limit_state = 0; 57 | 58 | uint8_t pin = (LIMIT_PORT_INPUTS & LIMIT_MASK); 59 | #ifdef INVERT_LIMIT_PIN_MASK 60 | pin ^= INVERT_LIMIT_PIN_MASK; 61 | #endif 62 | if (bit_istrue(settings.flags,BITFLAG_INVERT_LIMIT_PINS)) { pin ^= LIMIT_MASK; } 63 | if (pin) { 64 | uint8_t idx; 65 | for (idx=0; idxcondition = (PL_COND_FLAG_SYSTEM_MOTION|PL_COND_FLAG_NO_FEED_OVERRIDE); 151 | #ifdef USE_LINE_NUMBERS 152 | pl_data->line_number = HOMING_CYCLE_LINE_NUMBER; 153 | #endif 154 | 155 | // Initialize variables used for homing computations. 156 | uint8_t n_cycle = (2*N_HOMING_LOCATE_CYCLE+1); 157 | uint8_t step_pin[N_AXIS]; 158 | float target[N_AXIS]; 159 | float max_travel = 0.0; 160 | uint8_t idx; 161 | for (idx=0; idxfeed_rate = homing_rate; // Set current homing rate. 223 | plan_buffer_line(target, pl_data); // Bypass mc_line(). Directly plan homing motion. 224 | 225 | sys.step_control = STEP_CONTROL_EXECUTE_SYS_MOTION; // Set to execute homing motion and clear existing flags. 226 | st_prep_buffer(); // Prep and fill segment buffer from newly planned block. 227 | st_wake_up(); // Initiate motion 228 | do { 229 | ///delay(0); 230 | if (approach) { 231 | // Check limit state. Lock out cycle axes when they change. 232 | limit_state = limits_get_state(); 233 | for (idx=0; idx 0); 289 | 290 | // The active cycle axes should now be homed and machine limits have been located. By 291 | // default, Grbl defines machine space as all negative, as do most CNCs. Since limit switches 292 | // can be on either side of an axes, check and set axes machine zero appropriately. Also, 293 | // set up pull-off maneuver from axes limit switches that have been homed. This provides 294 | // some initial clearance off the switches and should also help prevent them from falsely 295 | // triggering when hard limits are enabled or when more than one axes shares a limit pin. 296 | int32_t set_axis_position; 297 | // Set machine positions for homed limit switches. Don't update non-homed axes. 298 | for (idx=0; idx. 20 | */ 21 | 22 | #ifndef limits_h 23 | #define limits_h 24 | 25 | 26 | // Initialize the limits module 27 | void limits_init(); 28 | 29 | // Disables hard limits. 30 | void limits_disable(); 31 | 32 | // Returns limit state as a bit-wise uint8 variable. 33 | uint8_t limits_get_state(); 34 | 35 | // Perform one portion of the homing cycle based on the input settings. 36 | void limits_go_home(uint8_t cycle_mask); 37 | 38 | // Check for soft limit violations 39 | void limits_soft_check(float *target); 40 | 41 | void pin_limit_vect(); 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /lib/grbl/src/motion_control.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | motion_control.c - high level interface for issuing motion commands 3 | Part of Grbl 4 | 5 | Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC 6 | Copyright (c) 2009-2011 Simen Svale Skogsrud 7 | 8 | Grbl is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | Grbl is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with Grbl. If not, see . 20 | */ 21 | 22 | #include "grbl.hpp" 23 | 24 | 25 | // Execute linear motion in absolute millimeter coordinates. Feed rate given in millimeters/second 26 | // unless invert_feed_rate is true. Then the feed_rate means that the motion should be completed in 27 | // (1 minute)/feed_rate time. 28 | // NOTE: This is the primary gateway to the grbl planner. All line motions, including arc line 29 | // segments, must pass through this routine before being passed to the planner. The seperation of 30 | // mc_line and plan_buffer_line is done primarily to place non-planner-type functions from being 31 | // in the planner and to let backlash compensation or canned cycle integration simple and direct. 32 | void mc_line(float *target, plan_line_data_t *pl_data) 33 | { 34 | // If enabled, check for soft limit violations. Placed here all line motions are picked up 35 | // from everywhere in Grbl. 36 | if (bit_istrue(settings.flags,BITFLAG_SOFT_LIMIT_ENABLE)) { 37 | // NOTE: Block jog state. Jogging is a special case and soft limits are handled independently. 38 | if (sys.state != STATE_JOG) { limits_soft_check(target); } 39 | } 40 | 41 | // If in check gcode mode, prevent motion by blocking planner. Soft limits still work. 42 | if (sys.state == STATE_CHECK_MODE) { return; } 43 | 44 | // NOTE: Backlash compensation may be installed here. It will need direction info to track when 45 | // to insert a backlash line motion(s) before the intended line motion and will require its own 46 | // plan_check_full_buffer() and check for system abort loop. Also for position reporting 47 | // backlash steps will need to be also tracked, which will need to be kept at a system level. 48 | // There are likely some other things that will need to be tracked as well. However, we feel 49 | // that backlash compensation should NOT be handled by Grbl itself, because there are a myriad 50 | // of ways to implement it and can be effective or ineffective for different CNC machines. This 51 | // would be better handled by the interface as a post-processor task, where the original g-code 52 | // is translated and inserts backlash motions that best suits the machine. 53 | // NOTE: Perhaps as a middle-ground, all that needs to be sent is a flag or special command that 54 | // indicates to Grbl what is a backlash compensation motion, so that Grbl executes the move but 55 | // doesn't update the machine position values. Since the position values used by the g-code 56 | // parser and planner are separate from the system machine positions, this is doable. 57 | 58 | // If the buffer is full: good! That means we are well ahead of the robot. 59 | // Remain in this loop until there is room in the buffer. 60 | do { 61 | protocol_execute_realtime(); // Check for any run-time commands 62 | if (sys.abort) { return; } // Bail, if system abort. 63 | if ( plan_check_full_buffer() ) { protocol_auto_cycle_start(); } // Auto-cycle start when buffer is full. 64 | else { break; } 65 | delay(0); 66 | } while (1); 67 | 68 | // Plan and queue motion into planner buffer 69 | if (plan_buffer_line(target, pl_data) == PLAN_EMPTY_BLOCK) { 70 | if (bit_istrue(settings.flags,BITFLAG_LASER_MODE)) { 71 | // Correctly set spindle state, if there is a coincident position passed. Forces a buffer 72 | // sync while in M3 laser mode only. 73 | if (pl_data->condition & PL_COND_FLAG_SPINDLE_CW) { 74 | spindle_sync(PL_COND_FLAG_SPINDLE_CW, pl_data->spindle_speed); 75 | } 76 | } 77 | } 78 | } 79 | 80 | 81 | // Execute an arc in offset mode format. position == current xyz, target == target xyz, 82 | // offset == offset from current xyz, axis_X defines circle plane in tool space, axis_linear is 83 | // the direction of helical travel, radius == circle radius, isclockwise boolean. Used 84 | // for vector transformation direction. 85 | // The arc is approximated by generating a huge number of tiny, linear segments. The chordal tolerance 86 | // of each segment is configured in settings.arc_tolerance, which is defined to be the maximum normal 87 | // distance from segment to the circle when the end points both lie on the circle. 88 | void mc_arc(float *target, plan_line_data_t *pl_data, float *position, float *offset, float radius, 89 | uint8_t axis_0, uint8_t axis_1, uint8_t axis_linear, uint8_t is_clockwise_arc) 90 | { 91 | float center_axis0 = position[axis_0] + offset[axis_0]; 92 | float center_axis1 = position[axis_1] + offset[axis_1]; 93 | float r_axis0 = -offset[axis_0]; // Radius vector from center to current location 94 | float r_axis1 = -offset[axis_1]; 95 | float rt_axis0 = target[axis_0] - center_axis0; 96 | float rt_axis1 = target[axis_1] - center_axis1; 97 | 98 | // CCW angle between position and target from circle center. Only one atan2() trig computation required. 99 | float angular_travel = atan2(r_axis0*rt_axis1-r_axis1*rt_axis0, r_axis0*rt_axis0+r_axis1*rt_axis1); 100 | if (is_clockwise_arc) { // Correct atan2 output per direction 101 | if (angular_travel >= -ARC_ANGULAR_TRAVEL_EPSILON) { angular_travel -= 2*M_PI; } 102 | } else { 103 | if (angular_travel <= ARC_ANGULAR_TRAVEL_EPSILON) { angular_travel += 2*M_PI; } 104 | } 105 | 106 | // NOTE: Segment end points are on the arc, which can lead to the arc diameter being smaller by up to 107 | // (2x) settings.arc_tolerance. For 99% of users, this is just fine. If a different arc segment fit 108 | // is desired, i.e. least-squares, midpoint on arc, just change the mm_per_arc_segment calculation. 109 | // For the intended uses of Grbl, this value shouldn't exceed 2000 for the strictest of cases. 110 | uint16_t segments = floor(fabs(0.5*angular_travel*radius)/ 111 | sqrt(settings.arc_tolerance*(2*radius - settings.arc_tolerance)) ); 112 | 113 | if (segments) { 114 | // Multiply inverse feed_rate to compensate for the fact that this movement is approximated 115 | // by a number of discrete segments. The inverse feed_rate should be correct for the sum of 116 | // all segments. 117 | if (pl_data->condition & PL_COND_FLAG_INVERSE_TIME) { 118 | pl_data->feed_rate *= segments; 119 | bit_false(pl_data->condition,PL_COND_FLAG_INVERSE_TIME); // Force as feed absolute mode over arc segments. 120 | } 121 | 122 | float theta_per_segment = angular_travel/segments; 123 | float linear_per_segment = (target[axis_linear] - position[axis_linear])/segments; 124 | 125 | /* Vector rotation by transformation matrix: r is the original vector, r_T is the rotated vector, 126 | and phi is the angle of rotation. Solution approach by Jens Geisler. 127 | r_T = [cos(phi) -sin(phi); 128 | sin(phi) cos(phi] * r ; 129 | 130 | For arc generation, the center of the circle is the axis of rotation and the radius vector is 131 | defined from the circle center to the initial position. Each line segment is formed by successive 132 | vector rotations. Single precision values can accumulate error greater than tool precision in rare 133 | cases. So, exact arc path correction is implemented. This approach avoids the problem of too many very 134 | expensive trig operations [sin(),cos(),tan()] which can take 100-200 usec each to compute. 135 | 136 | Small angle approximation may be used to reduce computation overhead further. A third-order approximation 137 | (second order sin() has too much error) holds for most, if not, all CNC applications. Note that this 138 | approximation will begin to accumulate a numerical drift error when theta_per_segment is greater than 139 | ~0.25 rad(14 deg) AND the approximation is successively used without correction several dozen times. This 140 | scenario is extremely unlikely, since segment lengths and theta_per_segment are automatically generated 141 | and scaled by the arc tolerance setting. Only a very large arc tolerance setting, unrealistic for CNC 142 | applications, would cause this numerical drift error. However, it is best to set N_ARC_CORRECTION from a 143 | low of ~4 to a high of ~20 or so to avoid trig operations while keeping arc generation accurate. 144 | 145 | This approximation also allows mc_arc to immediately insert a line segment into the planner 146 | without the initial overhead of computing cos() or sin(). By the time the arc needs to be applied 147 | a correction, the planner should have caught up to the lag caused by the initial mc_arc overhead. 148 | This is important when there are successive arc motions. 149 | */ 150 | // Computes: cos_T = 1 - theta_per_segment^2/2, sin_T = theta_per_segment - theta_per_segment^3/6) in ~52usec 151 | float cos_T = 2.0 - theta_per_segment*theta_per_segment; 152 | float sin_T = theta_per_segment*0.16666667*(cos_T + 4.0); 153 | cos_T *= 0.5; 154 | 155 | float sin_Ti; 156 | float cos_Ti; 157 | float r_axisi; 158 | uint16_t i; 159 | uint8_t count = 0; 160 | 161 | for (i = 1; i. 20 | */ 21 | 22 | #ifndef motion_control_h 23 | #define motion_control_h 24 | 25 | 26 | // System motion commands must have a line number of zero. 27 | #define HOMING_CYCLE_LINE_NUMBER 0 28 | #define PARKING_MOTION_LINE_NUMBER 0 29 | 30 | #define HOMING_CYCLE_ALL 0 // Must be zero. 31 | #define HOMING_CYCLE_X bit(X_AXIS) 32 | #define HOMING_CYCLE_Y bit(Y_AXIS) 33 | #define HOMING_CYCLE_Z bit(Z_AXIS) 34 | 35 | 36 | // Execute linear motion in absolute millimeter coordinates. Feed rate given in millimeters/second 37 | // unless invert_feed_rate is true. Then the feed_rate means that the motion should be completed in 38 | // (1 minute)/feed_rate time. 39 | void mc_line(float *target, plan_line_data_t *pl_data); 40 | 41 | // Execute an arc in offset mode format. position == current xyz, target == target xyz, 42 | // offset == offset from current xyz, axis_XXX defines circle plane in tool space, axis_linear is 43 | // the direction of helical travel, radius == circle radius, is_clockwise_arc boolean. Used 44 | // for vector transformation direction. 45 | void mc_arc(float *target, plan_line_data_t *pl_data, float *position, float *offset, float radius, 46 | uint8_t axis_0, uint8_t axis_1, uint8_t axis_linear, uint8_t is_clockwise_arc); 47 | 48 | // Dwell for a specific number of seconds 49 | void mc_dwell(float seconds); 50 | 51 | // Perform homing cycle to locate machine zero. Requires limit switches. 52 | void mc_homing_cycle(uint8_t cycle_mask); 53 | 54 | // Perform tool length probe cycle. Requires probe switch. 55 | uint8_t mc_probe_cycle(float *target, plan_line_data_t *pl_data, uint8_t parser_flags); 56 | 57 | // Handles updating the override control state. 58 | void mc_override_ctrl_update(uint8_t override_state); 59 | 60 | // Plans and executes the single special motion case for parking. Independent of main planner buffer. 61 | void mc_parking_motion(float *parking_target, plan_line_data_t *pl_data); 62 | 63 | // Performs system reset. If in motion state, kills all motion and sets system alarm. 64 | void mc_reset(); 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /lib/grbl/src/nuts_bolts.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | nuts_bolts.c - Shared functions 3 | Part of Grbl 4 | 5 | Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC 6 | Copyright (c) 2009-2011 Simen Svale Skogsrud 7 | 8 | Grbl is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | Grbl is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with Grbl. If not, see . 20 | */ 21 | 22 | #include "grbl.hpp" 23 | 24 | #define MAX_INT_DIGITS 8 // Maximum number of digits in int32 (and float) 25 | 26 | 27 | // Extracts a floating point value from a string. The following code is based loosely on 28 | // the avr-libc strtod() function by Michael Stumpf and Dmitry Xmelkov and many freely 29 | // available conversion method examples, but has been highly optimized for Grbl. For known 30 | // CNC applications, the typical decimal value is expected to be in the range of E0 to E-4. 31 | // Scientific notation is officially not supported by g-code, and the 'E' character may 32 | // be a g-code word on some CNC systems. So, 'E' notation will not be recognized. 33 | // NOTE: Thanks to Radu-Eosif Mihailescu for identifying the issues with using strtod(). 34 | uint8_t read_float(char *line, uint8_t *char_counter, float *float_ptr) 35 | { 36 | char *ptr = line + *char_counter; 37 | unsigned char c; 38 | 39 | // Grab first character and increment pointer. No spaces assumed in line. 40 | c = *ptr++; 41 | 42 | // Capture initial positive/minus character 43 | bool isnegative = false; 44 | if (c == '-') { 45 | isnegative = true; 46 | c = *ptr++; 47 | } else if (c == '+') { 48 | c = *ptr++; 49 | } 50 | 51 | // Extract number into fast integer. Track decimal in terms of exponent value. 52 | uint32_t intval = 0; 53 | int8_t exp = 0; 54 | uint8_t ndigit = 0; 55 | bool isdecimal = false; 56 | while(1) { 57 | c -= '0'; 58 | if (c <= 9) { 59 | ndigit++; 60 | if (ndigit <= MAX_INT_DIGITS) { 61 | if (isdecimal) { exp--; } 62 | intval = (((intval << 2) + intval) << 1) + c; // intval*10 + c 63 | } else { 64 | if (!(isdecimal)) { exp++; } // Drop overflow digits 65 | } 66 | } else if (c == (('.'-'0') & 0xff) && !(isdecimal)) { 67 | isdecimal = true; 68 | } else { 69 | break; 70 | } 71 | c = *ptr++; 72 | } 73 | 74 | // Return if no digits have been read. 75 | if (!ndigit) { return(false); }; 76 | 77 | // Convert integer into floating point. 78 | float fval; 79 | fval = (float)intval; 80 | 81 | // Apply decimal. Should perform no more than two floating point multiplications for the 82 | // expected range of E0 to E-4. 83 | if (fval != 0) { 84 | while (exp <= -2) { 85 | fval *= 0.01; 86 | exp += 2; 87 | } 88 | if (exp < 0) { 89 | fval *= 0.1; 90 | } else if (exp > 0) { 91 | do { 92 | fval *= 10.0; 93 | } while (--exp > 0); 94 | } 95 | } 96 | 97 | // Assign floating point value with correct sign. 98 | if (isnegative) { 99 | *float_ptr = -fval; 100 | } else { 101 | *float_ptr = fval; 102 | } 103 | 104 | *char_counter = ptr - line - 1; // Set char_counter to next statement 105 | 106 | return(true); 107 | } 108 | 109 | 110 | // Non-blocking delay function used for general operation and suspend features. 111 | void delay_sec(float seconds, uint8_t mode) 112 | { 113 | uint16_t i = ceil(1000/DWELL_TIME_STEP*seconds); 114 | while (i-- > 0) { 115 | ESP.wdtFeed(); 116 | if (sys.abort) { return; } 117 | if (mode == DELAY_MODE_DWELL) { 118 | protocol_execute_realtime(); 119 | } else { // DELAY_MODE_SYS_SUSPEND 120 | // Execute rt_system() only to avoid nesting suspend loops. 121 | protocol_exec_rt_system(); 122 | if (sys.suspend & SUSPEND_RESTART_RETRACT) { return; } // Bail, if safety door reopens. 123 | } 124 | delay_ms(DWELL_TIME_STEP); // Delay DWELL_TIME_STEP increment 125 | } 126 | } 127 | 128 | // Delays variable defined milliseconds. Compiler compatibility fix for _delay_ms(), 129 | // which only accepts constants in future compiler releases. 130 | void delay_ms(uint16_t ms) 131 | { 132 | while ( ms-- ) { ESP.wdtFeed(); delayMicroseconds(950); } 133 | } 134 | 135 | // Simple hypotenuse computation function. 136 | float hypot_f(float x, float y) { return(sqrt(x*x + y*y)); } 137 | 138 | 139 | float convert_delta_vector_to_unit_vector(float *vector) 140 | { 141 | uint8_t idx; 142 | float magnitude = 0.0; 143 | for (idx=0; idx. 20 | */ 21 | 22 | #ifndef nuts_bolts_h 23 | #define nuts_bolts_h 24 | 25 | #define SOME_LARGE_VALUE 1.0E+38 26 | 27 | // Axis array index values. Must start with 0 and be continuous. 28 | #define N_AXIS 8 // Number of axes 29 | #define X_AXIS 0 // Axis indexing value. 30 | #define Y_AXIS 1 31 | #define Z_AXIS 2 32 | #define A_AXIS 3 33 | #define B_AXIS 4 34 | #define C_AXIS 5 35 | #define D_AXIS 6 36 | #define E_AXIS 7 37 | 38 | // CoreXY motor assignments. DO NOT ALTER. 39 | // NOTE: If the A and B motor axis bindings are changed, this effects the CoreXY equations. 40 | #ifdef COREXY 41 | #define A_MOTOR X_AXIS // Must be X_AXIS 42 | #define B_MOTOR Y_AXIS // Must be Y_AXIS 43 | #endif 44 | 45 | // Conversions 46 | #define MM_PER_INCH (25.40) 47 | #define INCH_PER_MM (0.0393701) 48 | #define TICKS_PER_MICROSECOND (F_CPU / 16000000) 49 | 50 | #define DELAY_MODE_DWELL 0 51 | #define DELAY_MODE_SYS_SUSPEND 1 52 | 53 | // Useful macros 54 | #define clear_vector(a) memset(a, 0, sizeof(a)) 55 | #define clear_vector_float(a) memset(a, 0.0, sizeof(float)*N_AXIS) 56 | // #define clear_vector_long(a) memset(a, 0.0, sizeof(long)*N_AXIS) 57 | #define max(a,b) (((a) > (b)) ? (a) : (b)) 58 | #define min(a,b) (((a) < (b)) ? (a) : (b)) 59 | #define isequal_position_vector(a,b) !(memcmp(a, b, sizeof(float)*N_AXIS)) 60 | 61 | // Bit field and masking macros 62 | #ifndef bit 63 | #define bit(n) (1 << n) 64 | #endif 65 | #define bit_true(x,mask) (x) |= (mask) 66 | #define bit_false(x,mask) (x) &= ~(mask) 67 | #define bit_istrue(x,mask) ((x & mask) != 0) 68 | #define bit_isfalse(x,mask) ((x & mask) == 0) 69 | 70 | // Read a floating point value from a string. Line points to the input buffer, char_counter 71 | // is the indexer pointing to the current character of the line, while float_ptr is 72 | // a pointer to the result variable. Returns true when it succeeds 73 | uint8_t read_float(char *line, uint8_t *char_counter, float *float_ptr); 74 | 75 | // Non-blocking delay function used for general operation and suspend features. 76 | void delay_sec(float seconds, uint8_t mode); 77 | 78 | // Delays variable-defined milliseconds. Compiler compatibility fix for _delay_ms(). 79 | void delay_ms(uint16_t ms); 80 | 81 | // Computes hypotenuse, avoiding avr-gcc's bloated version and the extra error checking. 82 | float hypot_f(float x, float y); 83 | 84 | float convert_delta_vector_to_unit_vector(float *vector); 85 | float limit_value_by_axis_maximum(float *max_value, float *unit_vec); 86 | 87 | #endif 88 | -------------------------------------------------------------------------------- /lib/grbl/src/planner.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | planner.h - buffers movement commands and manages the acceleration profile plan 3 | Part of Grbl 4 | 5 | Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC 6 | Copyright (c) 2009-2011 Simen Svale Skogsrud 7 | 8 | Grbl is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | Grbl is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with Grbl. If not, see . 20 | */ 21 | 22 | #ifndef planner_h 23 | #define planner_h 24 | 25 | 26 | // The number of linear motions that can be in the plan at any give time 27 | #ifndef BLOCK_BUFFER_SIZE 28 | #ifdef USE_LINE_NUMBERS 29 | #define BLOCK_BUFFER_SIZE 15 30 | #else 31 | #define BLOCK_BUFFER_SIZE 16 32 | #endif 33 | #endif 34 | 35 | // Returned status message from planner. 36 | #define PLAN_OK true 37 | #define PLAN_EMPTY_BLOCK false 38 | 39 | // Define planner data condition flags. Used to denote running conditions of a block. 40 | #define PL_COND_FLAG_RAPID_MOTION bit(0) 41 | #define PL_COND_FLAG_SYSTEM_MOTION bit(1) // Single motion. Circumvents planner state. Used by home/park. 42 | #define PL_COND_FLAG_NO_FEED_OVERRIDE bit(2) // Motion does not honor feed override. 43 | #define PL_COND_FLAG_INVERSE_TIME bit(3) // Interprets feed rate value as inverse time when set. 44 | #define PL_COND_FLAG_SPINDLE_CW bit(4) 45 | #define PL_COND_FLAG_SPINDLE_CCW bit(5) 46 | #define PL_COND_FLAG_COOLANT_FLOOD bit(6) 47 | #define PL_COND_FLAG_COOLANT_MIST bit(7) 48 | #define PL_COND_MOTION_MASK (PL_COND_FLAG_RAPID_MOTION|PL_COND_FLAG_SYSTEM_MOTION|PL_COND_FLAG_NO_FEED_OVERRIDE) 49 | #define PL_COND_SPINDLE_MASK (PL_COND_FLAG_SPINDLE_CW|PL_COND_FLAG_SPINDLE_CCW) 50 | #define PL_COND_ACCESSORY_MASK (PL_COND_FLAG_SPINDLE_CW|PL_COND_FLAG_SPINDLE_CCW|PL_COND_FLAG_COOLANT_FLOOD|PL_COND_FLAG_COOLANT_MIST) 51 | 52 | 53 | // This struct stores a linear movement of a g-code block motion with its critical "nominal" values 54 | // are as specified in the source g-code. 55 | typedef struct { 56 | // Fields used by the bresenham algorithm for tracing the line 57 | // NOTE: Used by stepper algorithm to execute the block correctly. Do not alter these values. 58 | uint32_t steps[N_AXIS]; // Step count along each axis 59 | uint32_t step_event_count; // The maximum step axis count and number of steps required to complete this block. 60 | uint8_t direction_bits; // The direction bit set for this block (refers to *_DIRECTION_BIT in config.h) 61 | 62 | // Block condition data to ensure correct execution depending on states and overrides. 63 | uint8_t condition; // Block bitflag variable defining block run conditions. Copied from pl_line_data. 64 | #ifdef USE_LINE_NUMBERS 65 | int32_t line_number; // Block line number for real-time reporting. Copied from pl_line_data. 66 | #endif 67 | 68 | // Fields used by the motion planner to manage acceleration. Some of these values may be updated 69 | // by the stepper module during execution of special motion cases for replanning purposes. 70 | float entry_speed_sqr; // The current planned entry speed at block junction in (mm/min)^2 71 | float max_entry_speed_sqr; // Maximum allowable entry speed based on the minimum of junction limit and 72 | // neighboring nominal speeds with overrides in (mm/min)^2 73 | float acceleration; // Axis-limit adjusted line acceleration in (mm/min^2). Does not change. 74 | float millimeters; // The remaining distance for this block to be executed in (mm). 75 | // NOTE: This value may be altered by stepper algorithm during execution. 76 | 77 | // Stored rate limiting data used by planner when changes occur. 78 | float max_junction_speed_sqr; // Junction entry speed limit based on direction vectors in (mm/min)^2 79 | float rapid_rate; // Axis-limit adjusted maximum rate for this block direction in (mm/min) 80 | float programmed_rate; // Programmed rate of this block (mm/min). 81 | 82 | #ifdef VARIABLE_SPINDLE 83 | // Stored spindle speed data used by spindle overrides and resuming methods. 84 | float spindle_speed; // Block spindle speed. Copied from pl_line_data. 85 | #endif 86 | } plan_block_t; 87 | 88 | 89 | // Planner data prototype. Must be used when passing new motions to the planner. 90 | typedef struct { 91 | float feed_rate; // Desired feed rate for line motion. Value is ignored, if rapid motion. 92 | float spindle_speed; // Desired spindle speed through line motion. 93 | uint8_t condition; // Bitflag variable to indicate planner conditions. See defines above. 94 | #ifdef USE_LINE_NUMBERS 95 | int32_t line_number; // Desired line number to report when executing. 96 | #endif 97 | } plan_line_data_t; 98 | 99 | 100 | // Initialize and reset the motion plan subsystem 101 | void plan_reset(); // Reset all 102 | void plan_reset_buffer(); // Reset buffer only. 103 | 104 | // Add a new linear movement to the buffer. target[N_AXIS] is the signed, absolute target position 105 | // in millimeters. Feed rate specifies the speed of the motion. If feed rate is inverted, the feed 106 | // rate is taken to mean "frequency" and would complete the operation in 1/feed_rate minutes. 107 | uint8_t plan_buffer_line(float *target, plan_line_data_t *pl_data); 108 | 109 | // Called when the current block is no longer needed. Discards the block and makes the memory 110 | // availible for new blocks. 111 | void plan_discard_current_block(); 112 | 113 | // Gets the planner block for the special system motion cases. (Parking/Homing) 114 | plan_block_t *plan_get_system_motion_block(); 115 | 116 | // Gets the current block. Returns NULL if buffer empty 117 | plan_block_t *plan_get_current_block(); 118 | 119 | // Called periodically by step segment buffer. Mostly used internally by planner. 120 | uint8_t plan_next_block_index(uint8_t block_index); 121 | 122 | // Called by step segment buffer when computing executing block velocity profile. 123 | float plan_get_exec_block_exit_speed_sqr(); 124 | 125 | // Called by main program during planner calculations and step segment buffer during initialization. 126 | float plan_compute_profile_nominal_speed(plan_block_t *block); 127 | 128 | // Re-calculates buffered motions profile parameters upon a motion-based override change. 129 | void plan_update_velocity_profile_parameters(); 130 | 131 | // Reset the planner position vector (in steps) 132 | void plan_sync_position(); 133 | 134 | // Reinitialize plan with a partially completed block 135 | void plan_cycle_reinitialize(); 136 | 137 | // Returns the number of available blocks are in the planner buffer. 138 | uint8_t plan_get_block_buffer_available(); 139 | 140 | // Returns the number of active blocks are in the planner buffer. 141 | // NOTE: Deprecated. Not used unless classic status reports are enabled in config.h 142 | uint8_t plan_get_block_buffer_count(); 143 | 144 | // Returns the status of the block ring buffer. True, if buffer is full. 145 | uint8_t plan_check_full_buffer(); 146 | 147 | void plan_get_planner_mpos(float *target); 148 | 149 | 150 | #endif 151 | -------------------------------------------------------------------------------- /lib/grbl/src/print.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | print.c - Functions for formatting output strings 3 | Part of Grbl 4 | 5 | Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC 6 | Copyright (c) 2009-2011 Simen Svale Skogsrud 7 | 8 | Grbl is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | Grbl is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with Grbl. If not, see . 20 | */ 21 | 22 | #include "grbl.hpp" 23 | 24 | 25 | /*void printString(const char *s) 26 | { 27 | while (*s) 28 | serial_write(*s++); 29 | }*/ 30 | 31 | 32 | // Print a string stored in PGM-memory 33 | /*void printPgmString(const char *s) 34 | { 35 | char c; 36 | while ((c = pgm_read_byte_near(s++))) 37 | serial_write(c); 38 | }*/ 39 | 40 | 41 | // void printIntegerInBase(unsigned long n, unsigned long base) 42 | // { 43 | // unsigned char buf[8 * sizeof(long)]; // Assumes 8-bit chars. 44 | // unsigned long i = 0; 45 | // 46 | // if (n == 0) { 47 | // serial_write('0'); 48 | // return; 49 | // } 50 | // 51 | // while (n > 0) { 52 | // buf[i++] = n % base; 53 | // n /= base; 54 | // } 55 | // 56 | // for (; i > 0; i--) 57 | // serial_write(buf[i - 1] < 10 ? 58 | // '0' + buf[i - 1] : 59 | // 'A' + buf[i - 1] - 10); 60 | // } 61 | 62 | 63 | // Prints an uint8 variable in base 10. 64 | void print_uint8_base10(uint8_t n) 65 | { 66 | uint8_t digit_a = 0; 67 | uint8_t digit_b = 0; 68 | if (n >= 100) { // 100-255 69 | digit_a = '0' + n % 10; 70 | n /= 10; 71 | } 72 | if (n >= 10) { // 10-99 73 | digit_b = '0' + n % 10; 74 | n /= 10; 75 | } 76 | serial_write('0' + n); 77 | if (digit_b) { serial_write(digit_b); } 78 | if (digit_a) { serial_write(digit_a); } 79 | } 80 | 81 | 82 | // Prints an uint8 variable in base 2 with desired number of desired digits. 83 | void print_uint8_base2_ndigit(uint8_t n, uint8_t digits) { 84 | unsigned char buf[digits]; 85 | uint8_t i = 0; 86 | 87 | for (; i < digits; i++) { 88 | buf[i] = n % 2 ; 89 | n /= 2; 90 | } 91 | 92 | for (; i > 0; i--) 93 | serial_write('0' + buf[i - 1]); 94 | } 95 | 96 | 97 | void print_uint32_base10(uint32_t n) 98 | { 99 | if (n == 0) { 100 | serial_write('0'); 101 | return; 102 | } 103 | 104 | unsigned char buf[10]; 105 | uint8_t i = 0; 106 | 107 | while (n > 0) { 108 | buf[i++] = n % 10; 109 | n /= 10; 110 | } 111 | 112 | for (; i > 0; i--) 113 | serial_write('0' + buf[i-1]); 114 | } 115 | 116 | 117 | void printInteger(long n) 118 | { 119 | if (n < 0) { 120 | serial_write('-'); 121 | print_uint32_base10(-n); 122 | } else { 123 | print_uint32_base10(n); 124 | } 125 | } 126 | 127 | 128 | // Convert float to string by immediately converting to a long integer, which contains 129 | // more digits than a float. Number of decimal places, which are tracked by a counter, 130 | // may be set by the user. The integer is then efficiently converted to a string. 131 | // NOTE: AVR '%' and '/' integer operations are very efficient. Bitshifting speed-up 132 | // techniques are actually just slightly slower. Found this out the hard way. 133 | void printFloat(float n, uint8_t decimal_places) 134 | { 135 | if (n < 0) { 136 | serial_write('-'); 137 | n = -n; 138 | } 139 | 140 | uint8_t decimals = decimal_places; 141 | while (decimals >= 2) { // Quickly convert values expected to be E0 to E-4. 142 | n *= 100; 143 | decimals -= 2; 144 | } 145 | if (decimals) { n *= 10; } 146 | n += 0.5; // Add rounding factor. Ensures carryover through entire value. 147 | 148 | // Generate digits backwards and store in string. 149 | unsigned char buf[13]; 150 | uint8_t i = 0; 151 | uint32_t a = (long)n; 152 | while(a > 0) { 153 | buf[i++] = (a % 10) + '0'; // Get digit 154 | a /= 10; 155 | } 156 | while (i < decimal_places) { 157 | buf[i++] = '0'; // Fill in zeros to decimal point for (n < 1) 158 | } 159 | if (i == decimal_places) { // Fill in leading zero, if needed. 160 | buf[i++] = '0'; 161 | } 162 | 163 | // Print the generated string. 164 | for (; i > 0; i--) { 165 | if (i == decimal_places) { serial_write('.'); } // Insert decimal point in right place. 166 | serial_write(buf[i-1]); 167 | } 168 | } 169 | 170 | 171 | // Floating value printing handlers for special variables types used in Grbl and are defined 172 | // in the config.h. 173 | // - CoordValue: Handles all position or coordinate values in inches or mm reporting. 174 | // - RateValue: Handles feed rate and current velocity in inches or mm reporting. 175 | void printFloat_CoordValue(float n) { 176 | if (bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)) { 177 | printFloat(n*INCH_PER_MM,N_DECIMAL_COORDVALUE_INCH); 178 | } else { 179 | printFloat(n,N_DECIMAL_COORDVALUE_MM); 180 | } 181 | } 182 | 183 | void printFloat_RateValue(float n) { 184 | if (bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)) { 185 | printFloat(n*INCH_PER_MM,N_DECIMAL_RATEVALUE_INCH); 186 | } else { 187 | printFloat(n,N_DECIMAL_RATEVALUE_MM); 188 | } 189 | } 190 | 191 | // Debug tool to print free memory in bytes at the called point. 192 | // NOTE: Keep commented unless using. Part of this function always gets compiled in. 193 | // void printFreeMemory() 194 | // { 195 | // extern int __heap_start, *__brkval; 196 | // uint16_t free; // Up to 64k values. 197 | // free = (int) &free - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 198 | // printInteger((int32_t)free); 199 | // printString(" "); 200 | // } 201 | -------------------------------------------------------------------------------- /lib/grbl/src/print.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | print.h - Functions for formatting output strings 3 | Part of Grbl 4 | 5 | Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC 6 | Copyright (c) 2009-2011 Simen Svale Skogsrud 7 | 8 | Grbl is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | Grbl is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with Grbl. If not, see . 20 | */ 21 | 22 | #ifndef print_h 23 | #define print_h 24 | 25 | 26 | //void printString(const char *s); 27 | 28 | //void printPgmString(const char *s); 29 | 30 | //void printInteger(long n); 31 | 32 | //void print_uint32_base10(uint32_t n); 33 | 34 | // Prints an uint8 variable in base 10. 35 | //void print_uint8_base10(uint8_t n); 36 | 37 | // Prints an uint8 variable in base 2 with desired number of desired digits. 38 | //void print_uint8_base2_ndigit(uint8_t n, uint8_t digits); 39 | 40 | //void printFloat(float n, uint8_t decimal_places); 41 | 42 | // Floating value printing handlers for special variables types used in Grbl. 43 | // - CoordValue: Handles all position or coordinate values in inches or mm reporting. 44 | // - RateValue: Handles feed rate and current velocity in inches or mm reporting. 45 | //void printFloat_CoordValue(float n); 46 | //void printFloat_RateValue(float n); 47 | 48 | // Debug tool to print free memory in bytes at the called point. Not used otherwise. 49 | //void printFreeMemory(); 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /lib/grbl/src/probe.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | probe.c - code pertaining to probing methods 3 | Part of Grbl 4 | 5 | Copyright (c) 2014-2016 Sungeun K. Jeon for Gnea Research LLC 6 | 7 | Grbl is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Grbl is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with Grbl. If not, see . 19 | */ 20 | 21 | #include "grbl.hpp" 22 | 23 | 24 | // Inverts the probe pin state depending on user settings and probing cycle mode. 25 | uint8_t probe_invert_mask; 26 | 27 | 28 | // Probe pin initialization routine. 29 | void probe_init() 30 | { 31 | /*PROBE_DDR &= ~(PROBE_MASK); // Configure as input pins 32 | #ifdef DISABLE_PROBE_PIN_PULL_UP 33 | PROBE_PORT &= ~(PROBE_MASK); // Normal low operation. Requires external pull-down. 34 | #else 35 | PROBE_PORT |= PROBE_MASK; // Enable internal pull-up resistors. Normal high operation. 36 | #endif 37 | */ 38 | probe_configure_invert_mask(false); // Initialize invert mask. 39 | } 40 | 41 | 42 | // Called by probe_init() and the mc_probe() routines. Sets up the probe pin invert mask to 43 | // appropriately set the pin logic according to setting for normal-high/normal-low operation 44 | // and the probing cycle modes for toward-workpiece/away-from-workpiece. 45 | void probe_configure_invert_mask(uint8_t is_probe_away) 46 | { 47 | probe_invert_mask = 0; // Initialize as zero. 48 | if (bit_isfalse(settings.flags,BITFLAG_INVERT_PROBE_PIN)) { probe_invert_mask ^= PROBE_MASK; } 49 | if (is_probe_away) { probe_invert_mask ^= PROBE_MASK; } 50 | } 51 | 52 | 53 | // Returns the probe pin state. Triggered = true. Called by gcode parser and probe state monitor. 54 | uint8_t probe_get_state() { 55 | return((PROBE_BIT & PROBE_MASK) ^ probe_invert_mask); 56 | } 57 | 58 | 59 | // Monitors probe pin state and records the system position when detected. Called by the 60 | // stepper ISR per ISR tick. 61 | // NOTE: This function must be extremely efficient as to not bog down the stepper ISR. 62 | void probe_state_monitor() 63 | { 64 | if (probe_get_state()) { 65 | sys_probe_state = PROBE_OFF; 66 | memcpy(sys_probe_position, sys_position, sizeof(sys_position)); 67 | bit_true(sys_rt_exec_state, EXEC_MOTION_CANCEL); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /lib/grbl/src/probe.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | probe.h - code pertaining to probing methods 3 | Part of Grbl 4 | 5 | Copyright (c) 2014-2016 Sungeun K. Jeon for Gnea Research LLC 6 | 7 | Grbl is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Grbl is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with Grbl. If not, see . 19 | */ 20 | 21 | #ifndef probe_h 22 | #define probe_h 23 | 24 | // Values that define the probing state machine. 25 | #define PROBE_OFF 0 // Probing disabled or not in use. (Must be zero.) 26 | #define PROBE_ACTIVE 1 // Actively watching the input pin. 27 | 28 | // Probe pin initialization routine. 29 | void probe_init(); 30 | 31 | // Called by probe_init() and the mc_probe() routines. Sets up the probe pin invert mask to 32 | // appropriately set the pin logic according to setting for normal-high/normal-low operation 33 | // and the probing cycle modes for toward-workpiece/away-from-workpiece. 34 | void probe_configure_invert_mask(uint8_t is_probe_away); 35 | 36 | // Returns probe pin state. Triggered = true. Called by gcode parser and probe state monitor. 37 | uint8_t probe_get_state(); 38 | 39 | // Monitors probe pin state and records the system position when detected. Called by the 40 | // stepper ISR per ISR tick. 41 | void probe_state_monitor(); 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /lib/grbl/src/protocol.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | protocol.h - controls Grbl execution protocol and procedures 3 | Part of Grbl 4 | 5 | Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC 6 | Copyright (c) 2009-2011 Simen Svale Skogsrud 7 | 8 | Grbl is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | Grbl is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with Grbl. If not, see . 20 | */ 21 | 22 | #ifndef protocol_h 23 | #define protocol_h 24 | 25 | // Line buffer size from the serial input stream to be executed. 26 | // NOTE: Not a problem except for extreme cases, but the line buffer size can be too small 27 | // and g-code blocks can get truncated. Officially, the g-code standards support up to 256 28 | // characters. In future versions, this will be increased, when we know how much extra 29 | // memory space we can invest into here or we re-write the g-code parser not to have this 30 | // buffer. 31 | #ifndef LINE_BUFFER_SIZE 32 | #define LINE_BUFFER_SIZE 200 33 | #endif 34 | 35 | // Starts Grbl main loop. It handles all incoming characters from the serial port and executes 36 | // them as they complete. It is also responsible for finishing the initialization procedures. 37 | void protocol_main_loop(); 38 | 39 | // Checks and executes a realtime command at various stop points in main program 40 | void protocol_execute_realtime(); 41 | void protocol_exec_rt_system(); 42 | 43 | // Executes the auto cycle feature, if enabled. 44 | void protocol_auto_cycle_start(); 45 | 46 | // Block until all buffered steps are executed 47 | void protocol_buffer_synchronize(); 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /lib/grbl/src/report.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | report.h - reporting and messaging methods 3 | Part of Grbl 4 | 5 | Copyright (c) 2012-2016 Sungeun K. Jeon for Gnea Research LLC 6 | 7 | Grbl is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Grbl is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with Grbl. If not, see . 19 | */ 20 | #ifndef report_h 21 | #define report_h 22 | 23 | // Define Grbl status codes. Valid values (0-255) 24 | #define STATUS_OK 0 25 | #define STATUS_EXPECTED_COMMAND_LETTER 1 26 | #define STATUS_BAD_NUMBER_FORMAT 2 27 | #define STATUS_INVALID_STATEMENT 3 28 | #define STATUS_NEGATIVE_VALUE 4 29 | #define STATUS_SETTING_DISABLED 5 30 | #define STATUS_SETTING_STEP_PULSE_MIN 6 31 | #define STATUS_SETTING_READ_FAIL 7 32 | #define STATUS_IDLE_ERROR 8 33 | #define STATUS_SYSTEM_GC_LOCK 9 34 | #define STATUS_SOFT_LIMIT_ERROR 10 35 | #define STATUS_OVERFLOW 11 36 | #define STATUS_MAX_STEP_RATE_EXCEEDED 12 37 | #define STATUS_CHECK_DOOR 13 38 | #define STATUS_LINE_LENGTH_EXCEEDED 14 39 | #define STATUS_TRAVEL_EXCEEDED 15 40 | #define STATUS_INVALID_JOG_COMMAND 16 41 | #define STATUS_SETTING_DISABLED_LASER 17 42 | 43 | #define STATUS_GCODE_UNSUPPORTED_COMMAND 20 44 | #define STATUS_GCODE_MODAL_GROUP_VIOLATION 21 45 | #define STATUS_GCODE_UNDEFINED_FEED_RATE 22 46 | #define STATUS_GCODE_COMMAND_VALUE_NOT_INTEGER 23 47 | #define STATUS_GCODE_AXIS_COMMAND_CONFLICT 24 48 | #define STATUS_GCODE_WORD_REPEATED 25 49 | #define STATUS_GCODE_NO_AXIS_WORDS 26 50 | #define STATUS_GCODE_INVALID_LINE_NUMBER 27 51 | #define STATUS_GCODE_VALUE_WORD_MISSING 28 52 | #define STATUS_GCODE_UNSUPPORTED_COORD_SYS 29 53 | #define STATUS_GCODE_G53_INVALID_MOTION_MODE 30 54 | #define STATUS_GCODE_AXIS_WORDS_EXIST 31 55 | #define STATUS_GCODE_NO_AXIS_WORDS_IN_PLANE 32 56 | #define STATUS_GCODE_INVALID_TARGET 33 57 | #define STATUS_GCODE_ARC_RADIUS_ERROR 34 58 | #define STATUS_GCODE_NO_OFFSETS_IN_PLANE 35 59 | #define STATUS_GCODE_UNUSED_WORDS 36 60 | #define STATUS_GCODE_G43_DYNAMIC_AXIS_ERROR 37 61 | #define STATUS_GCODE_MAX_VALUE_EXCEEDED 38 62 | 63 | // Define Grbl alarm codes. Valid values (1-255). 0 is reserved. 64 | #define ALARM_HARD_LIMIT_ERROR EXEC_ALARM_HARD_LIMIT 65 | #define ALARM_SOFT_LIMIT_ERROR EXEC_ALARM_SOFT_LIMIT 66 | #define ALARM_ABORT_CYCLE EXEC_ALARM_ABORT_CYCLE 67 | #define ALARM_PROBE_FAIL_INITIAL EXEC_ALARM_PROBE_FAIL_INITIAL 68 | #define ALARM_PROBE_FAIL_CONTACT EXEC_ALARM_PROBE_FAIL_CONTACT 69 | #define ALARM_HOMING_FAIL_RESET EXEC_ALARM_HOMING_FAIL_RESET 70 | #define ALARM_HOMING_FAIL_DOOR EXEC_ALARM_HOMING_FAIL_DOOR 71 | #define ALARM_HOMING_FAIL_PULLOFF EXEC_ALARM_HOMING_FAIL_PULLOFF 72 | #define ALARM_HOMING_FAIL_APPROACH EXEC_ALARM_HOMING_FAIL_APPROACH 73 | 74 | // Define Grbl feedback message codes. Valid values (0-255). 75 | #define MESSAGE_CRITICAL_EVENT 1 76 | #define MESSAGE_ALARM_LOCK 2 77 | #define MESSAGE_ALARM_UNLOCK 3 78 | #define MESSAGE_ENABLED 4 79 | #define MESSAGE_DISABLED 5 80 | #define MESSAGE_SAFETY_DOOR_AJAR 6 81 | #define MESSAGE_CHECK_LIMITS 7 82 | #define MESSAGE_PROGRAM_END 8 83 | #define MESSAGE_RESTORE_DEFAULTS 9 84 | #define MESSAGE_SPINDLE_RESTORE 10 85 | #define MESSAGE_SLEEP_MODE 11 86 | 87 | #define CLIENT_SERIAL 1 88 | #define CLIENT_WEBSOCKET 2 89 | #define CLIENT_TELNET 3 90 | #define CLIENT_ALL 0xFF 91 | #define CLIENT_COUNT 3 // total number of client types regardless if they are used 92 | 93 | #define MSG_LEVEL_NONE 0 // set GRBL_MSG_LEVEL in config.h to the level you want to see 94 | #define MSG_LEVEL_ERROR 1 95 | #define MSG_LEVEL_WARNING 2 96 | #define MSG_LEVEL_INFO 3 97 | #define MSG_LEVEL_DEBUG 4 98 | #define MSG_LEVEL_VERBOSE 5 99 | 100 | // functions to send data to the user (from Grbl_Esp32) 101 | void grbl_send(uint8_t client, const char *text); 102 | void grbl_sendf(uint8_t client, const char *format, ...); 103 | 104 | // Prints system status messages. 105 | void report_status_message(uint8_t status_code, uint8_t client); 106 | 107 | // Prints system alarm messages. 108 | void report_alarm_message(uint8_t alarm_code); 109 | 110 | // Prints miscellaneous feedback messages. 111 | void report_feedback_message(uint8_t message_code); 112 | 113 | // Prints welcome message 114 | void report_init_message(uint8_t client); 115 | 116 | // Prints Grbl help and current global settings 117 | void report_grbl_help(uint8_t client); 118 | 119 | // Prints Grbl global settings 120 | void report_grbl_settings(uint8_t client); 121 | 122 | // Prints an echo of the pre-parsed line received right before execution. 123 | void report_echo_line_received(char *line, uint8_t client); 124 | 125 | // Prints realtime status report 126 | void report_realtime_status(uint8_t client); 127 | 128 | // Prints recorded probe position 129 | void report_probe_parameters(uint8_t client); 130 | 131 | // Prints Grbl NGC parameters (coordinate offsets, probe) 132 | void report_ngc_parameters(uint8_t client); 133 | 134 | // Prints current g-code parser mode state 135 | void report_gcode_modes(uint8_t client); 136 | 137 | // Prints startup line when requested and executed. 138 | void report_startup_line(uint8_t n, char *line, uint8_t client); 139 | void report_execute_startup_message(char *line, uint8_t status_code, uint8_t client); 140 | 141 | // Prints build info and user info 142 | void report_build_info(char *line, uint8_t client); 143 | 144 | #ifdef DEBUG 145 | void report_realtime_debug(); 146 | #endif 147 | 148 | #endif 149 | -------------------------------------------------------------------------------- /lib/grbl/src/serial.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | serial.c - Low level functions for sending and recieving bytes via the serial port 3 | Part of Grbl 4 | 5 | Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC 6 | Copyright (c) 2009-2011 Simen Svale Skogsrud 7 | 8 | Grbl is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | Grbl is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with Grbl. If not, see . 20 | */ 21 | 22 | #include "grbl.hpp" 23 | #include 24 | 25 | #define RX_RING_BUFFER (RX_BUFFER_SIZE+1) 26 | #define TX_RING_BUFFER (TX_BUFFER_SIZE+1) 27 | 28 | uint8_t serial_rx_buffer[CLIENT_COUNT][RX_RING_BUFFER]; 29 | uint8_t serial_rx_buffer_head[CLIENT_COUNT] = {0}; 30 | volatile uint8_t serial_rx_buffer_tail[CLIENT_COUNT] = {0}; 31 | 32 | Ticker serial_poll_task; 33 | 34 | // Returns the number of bytes available in the RX serial buffer. 35 | uint8_t serial_get_rx_buffer_available(uint8_t client) 36 | { 37 | uint8_t client_idx = client - 1; 38 | 39 | uint8_t rtail = serial_rx_buffer_tail[client_idx]; // Copy to limit multiple calls to volatile 40 | if (serial_rx_buffer_head[client_idx] >= rtail) { return(RX_BUFFER_SIZE - (serial_rx_buffer_head[client_idx]-rtail)); } 41 | return((rtail-serial_rx_buffer_head[client_idx]-1)); 42 | } 43 | 44 | void serial_init() 45 | { 46 | Serial.begin(BAUD_RATE); 47 | 48 | Serial.setDebugOutput(false); 49 | Serial.setTimeout(10); 50 | serial_poll_task.attach_ms(33, serial_poll_rx); 51 | } 52 | 53 | // Writes one byte to the TX serial buffer. Called by main program. 54 | void serial_write(uint8_t data) { 55 | 56 | // Wait until there is space in the buffer 57 | while (!Serial.availableForWrite()) { 58 | // TODO: Restructure st_prep_buffer() calls to be executed here during a long print. 59 | if (sys_rt_exec_state & EXEC_RESET) { return; } // Only check for abort to avoid an endless loop. 60 | } 61 | 62 | Serial.write((char)data); 63 | } 64 | 65 | // Fetches the first byte in the serial read buffer. Called by main program. 66 | uint8_t serial_read(uint8_t client) 67 | { 68 | uint8_t client_idx = client - 1; 69 | 70 | uint8_t tail = serial_rx_buffer_tail[client_idx]; // Temporary serial_rx_buffer_tail (to optimize for volatile) 71 | if (serial_rx_buffer_head[client_idx] == tail) { 72 | return SERIAL_NO_DATA; 73 | } else { 74 | // enter mutex 75 | cli(); 76 | uint8_t data = serial_rx_buffer[client_idx][tail]; 77 | 78 | tail++; 79 | if (tail == RX_RING_BUFFER) { tail = 0; } 80 | serial_rx_buffer_tail[client_idx] = tail; 81 | // exit mutex 82 | sei(); 83 | return data; 84 | } 85 | } 86 | 87 | void serial_poll_rx() 88 | { 89 | uint8_t data = 0; 90 | uint8_t next_head; 91 | uint8_t client = CLIENT_SERIAL; // who sent the data 92 | uint8_t client_idx = 0; // index of data buffer 93 | 94 | while (Serial.available() > 0 95 | #if (defined ENABLE_WIFI) && (defined ENABLE_WEBSOCKET) 96 | || Serial2Socket.available() > 0 97 | #endif 98 | #if (defined ENABLE_WIFI) && (defined ENABLE_TELNET) 99 | || telnetServer.available() > 0 100 | #endif 101 | ) { 102 | if (Serial.available() > 0) { 103 | client = CLIENT_SERIAL; 104 | data = Serial.read(); 105 | } 106 | #if (defined ENABLE_WIFI) && (defined ENABLE_WEBSOCKET) 107 | else if (Serial2Socket.available() > 0) { 108 | client = CLIENT_WEBSOCKET; 109 | data = Serial2Socket.read(); 110 | } 111 | #endif 112 | #if (defined ENABLE_WIFI) && (defined ENABLE_TELNET) 113 | else if (telnetServer.available() > 0) { 114 | client = CLIENT_TELNET; 115 | data = telnetServer.read(); 116 | } 117 | #endif 118 | client_idx = client - 1; // for zero based array 119 | 120 | // Pick off realtime command characters directly from the serial stream. These characters are 121 | // not passed into the main buffer, but these set system state flag bits for realtime execution. 122 | switch (data) { 123 | case CMD_RESET: mc_reset(); break; // Call motion control reset routine. 124 | case CMD_STATUS_REPORT: report_realtime_status(client); break; 125 | case CMD_CYCLE_START: system_set_exec_state_flag(EXEC_CYCLE_START); break; // Set as true 126 | case CMD_FEED_HOLD: system_set_exec_state_flag(EXEC_FEED_HOLD); break; // Set as true 127 | default : 128 | if (data > 0x7F) { // Real-time control characters are extended ACSII only. 129 | switch(data) { 130 | case CMD_SAFETY_DOOR: system_set_exec_state_flag(EXEC_SAFETY_DOOR); break; // Set as true 131 | case CMD_JOG_CANCEL: 132 | if (sys.state & STATE_JOG) { // Block all other states from invoking motion cancel. 133 | system_set_exec_state_flag(EXEC_MOTION_CANCEL); 134 | } 135 | break; 136 | #ifdef DEBUG 137 | case CMD_DEBUG_REPORT: bit_true(sys_rt_exec_debug,EXEC_DEBUG_REPORT); break; 138 | #endif 139 | case CMD_FEED_OVR_RESET: system_set_exec_motion_override_flag(EXEC_FEED_OVR_RESET); break; 140 | case CMD_FEED_OVR_COARSE_PLUS: system_set_exec_motion_override_flag(EXEC_FEED_OVR_COARSE_PLUS); break; 141 | case CMD_FEED_OVR_COARSE_MINUS: system_set_exec_motion_override_flag(EXEC_FEED_OVR_COARSE_MINUS); break; 142 | case CMD_FEED_OVR_FINE_PLUS: system_set_exec_motion_override_flag(EXEC_FEED_OVR_FINE_PLUS); break; 143 | case CMD_FEED_OVR_FINE_MINUS: system_set_exec_motion_override_flag(EXEC_FEED_OVR_FINE_MINUS); break; 144 | case CMD_RAPID_OVR_RESET: system_set_exec_motion_override_flag(EXEC_RAPID_OVR_RESET); break; 145 | case CMD_RAPID_OVR_MEDIUM: system_set_exec_motion_override_flag(EXEC_RAPID_OVR_MEDIUM); break; 146 | case CMD_RAPID_OVR_LOW: system_set_exec_motion_override_flag(EXEC_RAPID_OVR_LOW); break; 147 | case CMD_SPINDLE_OVR_RESET: system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_RESET); break; 148 | case CMD_SPINDLE_OVR_COARSE_PLUS: system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_COARSE_PLUS); break; 149 | case CMD_SPINDLE_OVR_COARSE_MINUS: system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_COARSE_MINUS); break; 150 | case CMD_SPINDLE_OVR_FINE_PLUS: system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_FINE_PLUS); break; 151 | case CMD_SPINDLE_OVR_FINE_MINUS: system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_FINE_MINUS); break; 152 | case CMD_SPINDLE_OVR_STOP: system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_STOP); break; 153 | case CMD_COOLANT_FLOOD_OVR_TOGGLE: system_set_exec_accessory_override_flag(EXEC_COOLANT_FLOOD_OVR_TOGGLE); break; 154 | #ifdef ENABLE_M7 155 | case CMD_COOLANT_MIST_OVR_TOGGLE: system_set_exec_accessory_override_flag(EXEC_COOLANT_MIST_OVR_TOGGLE); break; 156 | #endif 157 | } 158 | // Throw away any unfound extended-ASCII character by not passing it to the serial buffer. 159 | } else { // Write character to buffer 160 | // enter mutex 161 | cli(); 162 | next_head = serial_rx_buffer_head[client_idx] + 1; 163 | if (next_head == RX_RING_BUFFER) { next_head = 0; } 164 | 165 | // Write data to buffer unless it is full. 166 | if (next_head != serial_rx_buffer_tail[client_idx]) { 167 | serial_rx_buffer[client_idx][serial_rx_buffer_head[client_idx]] = data; 168 | serial_rx_buffer_head[client_idx] = next_head; 169 | } 170 | // exit mutex 171 | sei(); 172 | } 173 | } 174 | } 175 | Serial.flush(); 176 | #ifdef ENABLE_WIFI 177 | wifi_handle(); 178 | #endif 179 | #if (defined ENABLE_WIFI) && (defined ENABLE_WEBSOCKET) 180 | Serial2Socket.handle_flush(); 181 | #endif 182 | } 183 | 184 | void serial_reset_read_buffer(uint8_t client) 185 | { 186 | for (uint8_t client_num = 1; client_num <= CLIENT_COUNT; client_num++) { 187 | if (client == client_num || client == CLIENT_ALL) { 188 | serial_rx_buffer_tail[client_num-1] = serial_rx_buffer_head[client_num-1]; 189 | } 190 | } 191 | } -------------------------------------------------------------------------------- /lib/grbl/src/serial.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | serial.c - Low level functions for sending and recieving bytes via the serial port 3 | Part of Grbl 4 | 5 | Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC 6 | Copyright (c) 2009-2011 Simen Svale Skogsrud 7 | 8 | Grbl is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | Grbl is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with Grbl. If not, see . 20 | */ 21 | 22 | #ifndef serial_h 23 | #define serial_h 24 | 25 | #ifndef RX_BUFFER_SIZE 26 | #define RX_BUFFER_SIZE 342 27 | #endif 28 | #ifndef TX_BUFFER_SIZE 29 | #ifdef USE_LINE_NUMBERS 30 | #define TX_BUFFER_SIZE 300 31 | #else 32 | #define TX_BUFFER_SIZE 278 33 | #endif 34 | #endif 35 | 36 | #define SERIAL_NO_DATA 0xff 37 | 38 | void serial_init(); 39 | 40 | // Writes one byte to the TX serial buffer. Called by main program. 41 | void serial_write(uint8_t data); 42 | 43 | // Fetches the first byte in the serial read buffer. Called by main program. 44 | uint8_t serial_read(uint8_t client); 45 | 46 | // Reset and empty data in read buffer. Used by e-stop and reset. 47 | void serial_reset_read_buffer(uint8_t client); 48 | 49 | // Returns the number of bytes available in the RX serial buffer. 50 | uint8_t serial_get_rx_buffer_available(uint8_t client); 51 | 52 | // Serial rx "interrupt" 53 | void serial_poll_rx(); 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /lib/grbl/src/serial2socket.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | serial2socket.cpp - serial 2 socket functions class 3 | 4 | Copyright (c) 2014 Luc Lebosse. All rights reserved. 5 | 6 | This library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Lesser General Public 8 | License as published by the Free Software Foundation; either 9 | version 2.1 of the License, or (at your option) any later version. 10 | 11 | This library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public 17 | License along with this library; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | 20 | This file was borrowed from the awesome project: https://github.com/bdring/Grbl_Esp32.git 21 | */ 22 | 23 | #include "grbl.hpp" 24 | 25 | #ifdef ENABLE_WEBSOCKET 26 | 27 | Serial_2_Socket Serial2Socket; 28 | 29 | Serial_2_Socket::Serial_2_Socket(){ 30 | _web_socket = NULL; 31 | _TXbufferSize = 0; 32 | _RXbufferSize = 0; 33 | _RXbufferpos = 0; 34 | } 35 | Serial_2_Socket::~Serial_2_Socket(){ 36 | if (_web_socket) detachWS(); 37 | _TXbufferSize = 0; 38 | _RXbufferSize = 0; 39 | _RXbufferpos = 0; 40 | } 41 | void Serial_2_Socket::begin(long speed){ 42 | _TXbufferSize = 0; 43 | _RXbufferSize = 0; 44 | _RXbufferpos = 0; 45 | } 46 | 47 | void Serial_2_Socket::end(){ 48 | _TXbufferSize = 0; 49 | _RXbufferSize = 0; 50 | _RXbufferpos = 0; 51 | } 52 | 53 | long Serial_2_Socket::baudRate(){ 54 | return 0; 55 | } 56 | 57 | bool Serial_2_Socket::attachWS(void * web_socket){ 58 | if (web_socket) { 59 | _web_socket = web_socket; 60 | _TXbufferSize=0; 61 | return true; 62 | } 63 | return false; 64 | } 65 | 66 | bool Serial_2_Socket::detachWS(){ 67 | _web_socket = NULL; 68 | return true; 69 | } 70 | 71 | Serial_2_Socket::operator bool() const 72 | { 73 | return true; 74 | } 75 | 76 | int Serial_2_Socket::available(){ 77 | return _RXbufferSize; 78 | } 79 | 80 | size_t Serial_2_Socket::write(uint8_t c) 81 | { 82 | if(!_web_socket) return 0; 83 | write(&c,1); 84 | return 1; 85 | } 86 | 87 | size_t Serial_2_Socket::write(const uint8_t *buffer, size_t size) 88 | { 89 | if((buffer == NULL) ||(!_web_socket)) { 90 | //if(buffer == NULL)printPgmString("[SOCKET]No buffer"); 91 | //if(!_web_socket)printPgmString("[SOCKET]No socket"); 92 | return 0; 93 | } 94 | if (_TXbufferSize==0)_lastflush = millis(); 95 | //send full line 96 | if (_TXbufferSize + size > TXBUFFERSIZE) flush(); 97 | //need periodic check to force to flush in case of no end 98 | for (int i = 0; i < size;i++){ 99 | _TXbuffer[_TXbufferSize] = buffer[i]; 100 | _TXbufferSize++; 101 | } 102 | //Serial.printf("[SOCKET]buffer size %d",_TXbufferSize); 103 | handle_flush(); 104 | return size; 105 | } 106 | 107 | int Serial_2_Socket::peek(void){ 108 | if (_RXbufferSize > 0)return _RXbuffer[_RXbufferpos]; 109 | else return -1; 110 | } 111 | 112 | bool Serial_2_Socket::push(const char * data){ 113 | int data_size = strlen(data); 114 | if ((data_size + _RXbufferSize) <= RXBUFFERSIZE){ 115 | int current = _RXbufferpos + _RXbufferSize; 116 | if (current > RXBUFFERSIZE) current = current - RXBUFFERSIZE; 117 | for (int i = 0; i < data_size; i++){ 118 | if (current > (RXBUFFERSIZE-1)) current = 0; 119 | _RXbuffer[current] = data[i]; 120 | current ++; 121 | } 122 | _RXbufferSize+=strlen(data); 123 | return true; 124 | } 125 | return false; 126 | } 127 | 128 | int Serial_2_Socket::read(void){ 129 | if (_RXbufferSize > 0) { 130 | int v = _RXbuffer[_RXbufferpos]; 131 | _RXbufferpos++; 132 | if (_RXbufferpos > (RXBUFFERSIZE-1))_RXbufferpos = 0; 133 | _RXbufferSize--; 134 | return v; 135 | } else return -1; 136 | } 137 | 138 | void Serial_2_Socket::handle_flush() { 139 | if (_TXbufferSize > 0) { 140 | if ((_TXbufferSize>=TXBUFFERSIZE) || ((millis()- _lastflush) > FLUSHTIMEOUT)) { 141 | //Serial.printf("[SOCKET]need flush, buffer size %d\n",_TXbufferSize); 142 | flush(); 143 | } 144 | } 145 | } 146 | 147 | void Serial_2_Socket::flush(void){ 148 | if (_TXbufferSize > 0){ 149 | if (((AsyncWebSocket *)_web_socket)->count() > 0) { 150 | //Serial.printf("[SOCKET]flush data, buffer size %d",_TXbufferSize); 151 | ((AsyncWebSocket *)_web_socket)->textAll(_TXbuffer,_TXbufferSize); 152 | } else { 153 | //Serial.printf("[SOCKET]Cannot flush, buffer size %d",_TXbufferSize); 154 | } 155 | //refresh timout 156 | _lastflush = millis(); 157 | //reset buffer 158 | _TXbufferSize = 0; 159 | } 160 | } 161 | 162 | #endif 163 | -------------------------------------------------------------------------------- /lib/grbl/src/serial2socket.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | serial2socket.h - serial 2 socket functions class 3 | 4 | Copyright (c) 2014 Luc Lebosse. All rights reserved. 5 | 6 | This library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Lesser General Public 8 | License as published by the Free Software Foundation; either 9 | version 2.1 of the License, or (at your option) any later version. 10 | 11 | This library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public 17 | License along with this library; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | 20 | This file was borrowed from the awesome project: https://github.com/bdring/Grbl_Esp32.git 21 | */ 22 | 23 | #ifndef _SERIAL_2_SOCKET_H_ 24 | #define _SERIAL_2_SOCKET_H_ 25 | 26 | #include 27 | #define TXBUFFERSIZE 1200 28 | #define RXBUFFERSIZE 128 29 | #define FLUSHTIMEOUT 300 30 | class Serial_2_Socket: public Print{ 31 | public: 32 | Serial_2_Socket(); 33 | ~Serial_2_Socket(); 34 | size_t write(uint8_t c); 35 | size_t write(const uint8_t *buffer, size_t size); 36 | 37 | inline size_t write(const char * s) 38 | { 39 | return write((uint8_t*) s, strlen(s)); 40 | } 41 | inline size_t write(unsigned long n) 42 | { 43 | return write((uint8_t) n); 44 | } 45 | inline size_t write(long n) 46 | { 47 | return write((uint8_t) n); 48 | } 49 | inline size_t write(unsigned int n) 50 | { 51 | return write((uint8_t) n); 52 | } 53 | inline size_t write(int n) 54 | { 55 | return write((uint8_t) n); 56 | } 57 | long baudRate(); 58 | void begin(long speed); 59 | void end(); 60 | int available(); 61 | int peek(void); 62 | int read(void); 63 | bool push (const char * data); 64 | void flush(void); 65 | void handle_flush(); 66 | operator bool() const; 67 | bool attachWS(void * web_socket); 68 | bool detachWS(); 69 | private: 70 | uint32_t _lastflush; 71 | void * _web_socket; 72 | uint8_t _TXbuffer[TXBUFFERSIZE]; 73 | uint16_t _TXbufferSize; 74 | uint8_t _RXbuffer[RXBUFFERSIZE]; 75 | uint16_t _RXbufferSize; 76 | uint16_t _RXbufferpos; 77 | }; 78 | 79 | extern Serial_2_Socket Serial2Socket; 80 | 81 | #endif 82 | -------------------------------------------------------------------------------- /lib/grbl/src/settings.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | settings.c - eeprom configuration handling 3 | Part of Grbl 4 | 5 | Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC 6 | Copyright (c) 2009-2011 Simen Svale Skogsrud 7 | 8 | Grbl is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | Grbl is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with Grbl. If not, see . 20 | */ 21 | 22 | #include "grbl.hpp" 23 | 24 | settings_t settings; 25 | 26 | // Method to store startup lines into EEPROM 27 | void settings_store_startup_line(uint8_t n, char *line) 28 | { 29 | #ifdef FORCE_BUFFER_SYNC_DURING_EEPROM_WRITE 30 | protocol_buffer_synchronize(); // A startup line may contain a motion and be executing. 31 | #endif 32 | uint32_t addr = n*(LINE_BUFFER_SIZE+1)+EEPROM_ADDR_STARTUP_BLOCK; 33 | memcpy_to_eeprom_with_checksum(addr,(char*)line, LINE_BUFFER_SIZE); 34 | } 35 | 36 | 37 | // Method to store build info into EEPROM 38 | // NOTE: This function can only be called in IDLE state. 39 | void settings_store_build_info(char *line) 40 | { 41 | // Build info can only be stored when state is IDLE. 42 | memcpy_to_eeprom_with_checksum(EEPROM_ADDR_BUILD_INFO,(char*)line, LINE_BUFFER_SIZE); 43 | } 44 | 45 | 46 | // Method to store coord data parameters into EEPROM 47 | void settings_write_coord_data(uint8_t coord_select, float *coord_data) 48 | { 49 | #ifdef FORCE_BUFFER_SYNC_DURING_EEPROM_WRITE 50 | protocol_buffer_synchronize(); 51 | #endif 52 | uint32_t addr = coord_select*(sizeof(float)*N_AXIS+1) + EEPROM_ADDR_PARAMETERS; 53 | memcpy_to_eeprom_with_checksum(addr,(char*)coord_data, sizeof(float)*N_AXIS); 54 | } 55 | 56 | 57 | // Method to store Grbl global settings struct and version number into EEPROM 58 | // NOTE: This function can only be called in IDLE state. 59 | void write_global_settings() 60 | { 61 | eeprom_put_char(0, SETTINGS_VERSION); 62 | memcpy_to_eeprom_with_checksum(EEPROM_ADDR_GLOBAL, (char*)&settings, sizeof(settings_t)); 63 | } 64 | 65 | 66 | // Method to restore EEPROM-saved Grbl global settings back to defaults. 67 | void settings_restore(uint8_t restore_flag) { 68 | if (restore_flag & SETTINGS_RESTORE_DEFAULTS) { 69 | settings.pulse_microseconds = DEFAULT_STEP_PULSE_MICROSECONDS; 70 | settings.stepper_idle_lock_time = DEFAULT_STEPPER_IDLE_LOCK_TIME; 71 | settings.step_invert_mask = DEFAULT_STEPPING_INVERT_MASK; 72 | settings.dir_invert_mask = DEFAULT_DIRECTION_INVERT_MASK; 73 | settings.status_report_mask = DEFAULT_STATUS_REPORT_MASK; 74 | settings.junction_deviation = DEFAULT_JUNCTION_DEVIATION; 75 | settings.arc_tolerance = DEFAULT_ARC_TOLERANCE; 76 | 77 | settings.rpm_max = DEFAULT_SPINDLE_RPM_MAX; 78 | settings.rpm_min = DEFAULT_SPINDLE_RPM_MIN; 79 | 80 | settings.homing_dir_mask = DEFAULT_HOMING_DIR_MASK; 81 | settings.homing_feed_rate = DEFAULT_HOMING_FEED_RATE; 82 | settings.homing_seek_rate = DEFAULT_HOMING_SEEK_RATE; 83 | settings.homing_debounce_delay = DEFAULT_HOMING_DEBOUNCE_DELAY; 84 | settings.homing_pulloff = DEFAULT_HOMING_PULLOFF; 85 | 86 | settings.flags = 0; 87 | if (DEFAULT_REPORT_INCHES) { settings.flags |= BITFLAG_REPORT_INCHES; } 88 | if (DEFAULT_LASER_MODE) { settings.flags |= BITFLAG_LASER_MODE; } 89 | if (DEFAULT_INVERT_ST_ENABLE) { settings.flags |= BITFLAG_INVERT_ST_ENABLE; } 90 | if (DEFAULT_HARD_LIMIT_ENABLE) { settings.flags |= BITFLAG_HARD_LIMIT_ENABLE; } 91 | if (DEFAULT_HOMING_ENABLE) { settings.flags |= BITFLAG_HOMING_ENABLE; } 92 | if (DEFAULT_SOFT_LIMIT_ENABLE) { settings.flags |= BITFLAG_SOFT_LIMIT_ENABLE; } 93 | if (DEFAULT_INVERT_LIMIT_PINS) { settings.flags |= BITFLAG_INVERT_LIMIT_PINS; } 94 | if (DEFAULT_INVERT_PROBE_PIN) { settings.flags |= BITFLAG_INVERT_PROBE_PIN; } 95 | 96 | settings.steps_per_mm[X_AXIS] = DEFAULT_X_STEPS_PER_MM; 97 | settings.steps_per_mm[Y_AXIS] = DEFAULT_Y_STEPS_PER_MM; 98 | settings.steps_per_mm[Z_AXIS] = DEFAULT_Z_STEPS_PER_MM; 99 | settings.steps_per_mm[A_AXIS] = DEFAULT_A_STEPS_PER_MM; 100 | settings.steps_per_mm[B_AXIS] = DEFAULT_B_STEPS_PER_MM; 101 | settings.steps_per_mm[C_AXIS] = DEFAULT_C_STEPS_PER_MM; 102 | settings.steps_per_mm[D_AXIS] = DEFAULT_D_STEPS_PER_MM; 103 | settings.steps_per_mm[E_AXIS] = DEFAULT_E_STEPS_PER_MM; 104 | settings.max_rate[X_AXIS] = DEFAULT_X_MAX_RATE; 105 | settings.max_rate[Y_AXIS] = DEFAULT_Y_MAX_RATE; 106 | settings.max_rate[Z_AXIS] = DEFAULT_Z_MAX_RATE; 107 | settings.max_rate[A_AXIS] = DEFAULT_A_MAX_RATE; 108 | settings.max_rate[B_AXIS] = DEFAULT_B_MAX_RATE; 109 | settings.max_rate[C_AXIS] = DEFAULT_C_MAX_RATE; 110 | settings.max_rate[D_AXIS] = DEFAULT_D_MAX_RATE; 111 | settings.max_rate[E_AXIS] = DEFAULT_E_MAX_RATE; 112 | settings.acceleration[X_AXIS] = DEFAULT_X_ACCELERATION; 113 | settings.acceleration[Y_AXIS] = DEFAULT_Y_ACCELERATION; 114 | settings.acceleration[Z_AXIS] = DEFAULT_Z_ACCELERATION; 115 | settings.acceleration[A_AXIS] = DEFAULT_A_ACCELERATION; 116 | settings.acceleration[B_AXIS] = DEFAULT_B_ACCELERATION; 117 | settings.acceleration[C_AXIS] = DEFAULT_C_ACCELERATION; 118 | settings.acceleration[D_AXIS] = DEFAULT_D_ACCELERATION; 119 | settings.acceleration[E_AXIS] = DEFAULT_E_ACCELERATION; 120 | settings.max_travel[X_AXIS] = (-DEFAULT_X_MAX_TRAVEL); 121 | settings.max_travel[Y_AXIS] = (-DEFAULT_Y_MAX_TRAVEL); 122 | settings.max_travel[Z_AXIS] = (-DEFAULT_Z_MAX_TRAVEL); 123 | settings.max_travel[A_AXIS] = (-DEFAULT_A_MAX_TRAVEL); 124 | settings.max_travel[B_AXIS] = (-DEFAULT_B_MAX_TRAVEL); 125 | settings.max_travel[C_AXIS] = (-DEFAULT_C_MAX_TRAVEL); 126 | settings.max_travel[D_AXIS] = (-DEFAULT_D_MAX_TRAVEL); 127 | settings.max_travel[E_AXIS] = (-DEFAULT_E_MAX_TRAVEL); 128 | 129 | 130 | write_global_settings(); 131 | } 132 | 133 | if (restore_flag & SETTINGS_RESTORE_PARAMETERS) { 134 | uint8_t idx; 135 | float coord_data[N_AXIS]; 136 | memset(&coord_data, 0, sizeof(coord_data)); 137 | for (idx=0; idx <= SETTING_INDEX_NCOORD; idx++) { settings_write_coord_data(idx, coord_data); } 138 | } 139 | 140 | if (restore_flag & SETTINGS_RESTORE_STARTUP_LINES) { 141 | #if N_STARTUP_LINE > 0 142 | eeprom_put_char(EEPROM_ADDR_STARTUP_BLOCK, 0); 143 | eeprom_put_char(EEPROM_ADDR_STARTUP_BLOCK+1, 0); // Checksum 144 | #endif 145 | #if N_STARTUP_LINE > 1 146 | eeprom_put_char(EEPROM_ADDR_STARTUP_BLOCK+(LINE_BUFFER_SIZE+1), 0); 147 | eeprom_put_char(EEPROM_ADDR_STARTUP_BLOCK+(LINE_BUFFER_SIZE+2), 0); // Checksum 148 | #endif 149 | } 150 | 151 | if (restore_flag & SETTINGS_RESTORE_BUILD_INFO) { 152 | eeprom_put_char(EEPROM_ADDR_BUILD_INFO , 0); 153 | eeprom_put_char(EEPROM_ADDR_BUILD_INFO+1 , 0); // Checksum 154 | } 155 | } 156 | 157 | 158 | // Reads startup line from EEPROM. Updated pointed line string data. 159 | uint8_t settings_read_startup_line(uint8_t n, char *line) 160 | { 161 | uint32_t addr = n*(LINE_BUFFER_SIZE+1)+EEPROM_ADDR_STARTUP_BLOCK; 162 | if (!(memcpy_from_eeprom_with_checksum((char*)line, addr, LINE_BUFFER_SIZE))) { 163 | // Reset line with default value 164 | line[0] = 0; // Empty line 165 | settings_store_startup_line(n, line); 166 | return(false); 167 | } 168 | return(true); 169 | } 170 | 171 | 172 | // Reads startup line from EEPROM. Updated pointed line string data. 173 | uint8_t settings_read_build_info(char *line) 174 | { 175 | if (!(memcpy_from_eeprom_with_checksum((char*)line, EEPROM_ADDR_BUILD_INFO, LINE_BUFFER_SIZE))) { 176 | // Reset line with default value 177 | line[0] = 0; // Empty line 178 | settings_store_build_info(line); 179 | return(false); 180 | } 181 | return(true); 182 | } 183 | 184 | 185 | // Read selected coordinate data from EEPROM. Updates pointed coord_data value. 186 | uint8_t settings_read_coord_data(uint8_t coord_select, float *coord_data) 187 | { 188 | uint32_t addr = coord_select*(sizeof(float)*N_AXIS+1) + EEPROM_ADDR_PARAMETERS; 189 | if (!(memcpy_from_eeprom_with_checksum((char*)coord_data, addr, sizeof(float)*N_AXIS))) { 190 | // Reset with default zero vector 191 | clear_vector_float(coord_data); 192 | settings_write_coord_data(coord_select,coord_data); 193 | return(false); 194 | } 195 | return(true); 196 | } 197 | 198 | 199 | // Reads Grbl global settings struct from EEPROM. 200 | uint8_t read_global_settings() { 201 | // Check version-byte of eeprom 202 | uint8_t version = eeprom_get_char(0); 203 | if (version == SETTINGS_VERSION) { 204 | // Read settings-record and check checksum 205 | if (!(memcpy_from_eeprom_with_checksum((char*)&settings, EEPROM_ADDR_GLOBAL, sizeof(settings_t)))) { 206 | return(false); 207 | } 208 | } else { 209 | return(false); 210 | } 211 | return(true); 212 | } 213 | 214 | 215 | // A helper method to set settings from command line 216 | uint8_t settings_store_global_setting(uint8_t parameter, float value) { 217 | if (value < 0.0) { return(STATUS_NEGATIVE_VALUE); } 218 | if (parameter >= AXIS_SETTINGS_START_VAL) { 219 | // Store axis configuration. Axis numbering sequence set by AXIS_SETTING defines. 220 | // NOTE: Ensure the setting index corresponds to the report.c settings printout. 221 | parameter -= AXIS_SETTINGS_START_VAL; 222 | uint8_t set_idx = 0; 223 | while (set_idx < AXIS_N_SETTINGS) { 224 | if (parameter < N_AXIS) { 225 | // Valid axis setting found. 226 | switch (set_idx) { 227 | case 0: 228 | #ifdef MAX_STEP_RATE_HZ 229 | if (value*settings.max_rate[parameter] > (MAX_STEP_RATE_HZ*60.0)) { return(STATUS_MAX_STEP_RATE_EXCEEDED); } 230 | #endif 231 | settings.steps_per_mm[parameter] = value; 232 | break; 233 | case 1: 234 | #ifdef MAX_STEP_RATE_HZ 235 | if (value*settings.steps_per_mm[parameter] > (MAX_STEP_RATE_HZ*60.0)) { return(STATUS_MAX_STEP_RATE_EXCEEDED); } 236 | #endif 237 | settings.max_rate[parameter] = value; 238 | break; 239 | case 2: settings.acceleration[parameter] = value*60*60; break; // Convert to mm/min^2 for grbl internal use. 240 | case 3: settings.max_travel[parameter] = -value; break; // Store as negative for grbl internal use. 241 | } 242 | break; // Exit while-loop after setting has been configured and proceed to the EEPROM write call. 243 | } else { 244 | set_idx++; 245 | // If axis index greater than N_AXIS or setting index greater than number of axis settings, error out. 246 | if ((parameter < AXIS_SETTINGS_INCREMENT) || (set_idx == AXIS_N_SETTINGS)) { return(STATUS_INVALID_STATEMENT); } 247 | parameter -= AXIS_SETTINGS_INCREMENT; 248 | } 249 | } 250 | } else { 251 | // Store non-axis Grbl settings 252 | uint8_t int_value = trunc(value); 253 | switch(parameter) { 254 | case 0: 255 | if (int_value < 3) { return(STATUS_SETTING_STEP_PULSE_MIN); } 256 | settings.pulse_microseconds = int_value; break; 257 | case 1: settings.stepper_idle_lock_time = int_value; break; 258 | case 2: 259 | settings.step_invert_mask = int_value; 260 | st_generate_step_dir_invert_masks(); // Regenerate step and direction port invert masks. 261 | break; 262 | case 3: 263 | settings.dir_invert_mask = int_value; 264 | st_generate_step_dir_invert_masks(); // Regenerate step and direction port invert masks. 265 | break; 266 | case 4: // Reset to ensure change. Immediate re-init may cause problems. 267 | if (int_value) { settings.flags |= BITFLAG_INVERT_ST_ENABLE; } 268 | else { settings.flags &= ~BITFLAG_INVERT_ST_ENABLE; } 269 | break; 270 | case 5: // Reset to ensure change. Immediate re-init may cause problems. 271 | if (int_value) { settings.flags |= BITFLAG_INVERT_LIMIT_PINS; } 272 | else { settings.flags &= ~BITFLAG_INVERT_LIMIT_PINS; } 273 | break; 274 | case 6: // Reset to ensure change. Immediate re-init may cause problems. 275 | if (int_value) { settings.flags |= BITFLAG_INVERT_PROBE_PIN; } 276 | else { settings.flags &= ~BITFLAG_INVERT_PROBE_PIN; } 277 | probe_configure_invert_mask(false); 278 | break; 279 | case 10: settings.status_report_mask = int_value; break; 280 | case 11: settings.junction_deviation = value; break; 281 | case 12: settings.arc_tolerance = value; break; 282 | case 13: 283 | if (int_value) { settings.flags |= BITFLAG_REPORT_INCHES; } 284 | else { settings.flags &= ~BITFLAG_REPORT_INCHES; } 285 | system_flag_wco_change(); // Make sure WCO is immediately updated. 286 | break; 287 | case 20: 288 | if (int_value) { 289 | if (bit_isfalse(settings.flags, BITFLAG_HOMING_ENABLE)) { return(STATUS_SOFT_LIMIT_ERROR); } 290 | settings.flags |= BITFLAG_SOFT_LIMIT_ENABLE; 291 | } else { settings.flags &= ~BITFLAG_SOFT_LIMIT_ENABLE; } 292 | break; 293 | case 21: 294 | if (int_value) { settings.flags |= BITFLAG_HARD_LIMIT_ENABLE; } 295 | else { settings.flags &= ~BITFLAG_HARD_LIMIT_ENABLE; } 296 | limits_init(); // Re-init to immediately change. NOTE: Nice to have but could be problematic later. 297 | break; 298 | case 22: 299 | if (int_value) { settings.flags |= BITFLAG_HOMING_ENABLE; } 300 | else { 301 | settings.flags &= ~BITFLAG_HOMING_ENABLE; 302 | settings.flags &= ~BITFLAG_SOFT_LIMIT_ENABLE; // Force disable soft-limits. 303 | } 304 | break; 305 | case 23: settings.homing_dir_mask = int_value; break; 306 | case 24: settings.homing_feed_rate = value; break; 307 | case 25: settings.homing_seek_rate = value; break; 308 | case 26: settings.homing_debounce_delay = int_value; break; 309 | case 27: settings.homing_pulloff = value; break; 310 | case 30: settings.rpm_max = value; spindle_init(); break; // Re-initialize spindle rpm calibration 311 | case 31: settings.rpm_min = value; spindle_init(); break; // Re-initialize spindle rpm calibration 312 | case 32: 313 | #ifdef VARIABLE_SPINDLE 314 | if (int_value) { settings.flags |= BITFLAG_LASER_MODE; } 315 | else { settings.flags &= ~BITFLAG_LASER_MODE; } 316 | #else 317 | return(STATUS_SETTING_DISABLED_LASER); 318 | #endif 319 | break; 320 | default: 321 | return(STATUS_INVALID_STATEMENT); 322 | } 323 | } 324 | write_global_settings(); 325 | return(STATUS_OK); 326 | } 327 | 328 | void settings_init() 329 | { 330 | if(!read_global_settings()) { 331 | report_status_message(STATUS_SETTING_READ_FAIL, CLIENT_SERIAL); 332 | settings_restore(SETTINGS_RESTORE_ALL); // Force restore all EEPROM data. 333 | report_grbl_settings(CLIENT_SERIAL); // only the serial could be working at this point 334 | } 335 | } 336 | 337 | // Returns step pin mask according to Grbl internal axis indexing. 338 | uint8_t get_step_pin_mask(uint8_t axis_idx) 339 | { 340 | if ( axis_idx == X_AXIS ) { return((1<. 20 | */ 21 | 22 | #ifndef settings_h 23 | #define settings_h 24 | 25 | #include "grbl.hpp" 26 | 27 | 28 | // Version of the EEPROM data. Will be used to migrate existing data from older versions of Grbl 29 | // when firmware is upgraded. Always stored in byte 0 of eeprom 30 | #define SETTINGS_VERSION 10 // NOTE: Check settings_reset() when moving to next version. 31 | 32 | // Define bit flag masks for the boolean settings in settings.flag. 33 | #define BIT_REPORT_INCHES 0 34 | #define BIT_LASER_MODE 1 35 | #define BIT_INVERT_ST_ENABLE 2 36 | #define BIT_HARD_LIMIT_ENABLE 3 37 | #define BIT_HOMING_ENABLE 4 38 | #define BIT_SOFT_LIMIT_ENABLE 5 39 | #define BIT_INVERT_LIMIT_PINS 6 40 | #define BIT_INVERT_PROBE_PIN 7 41 | 42 | #define BITFLAG_REPORT_INCHES bit(BIT_REPORT_INCHES) 43 | #define BITFLAG_LASER_MODE bit(BIT_LASER_MODE) 44 | #define BITFLAG_INVERT_ST_ENABLE bit(BIT_INVERT_ST_ENABLE) 45 | #define BITFLAG_HARD_LIMIT_ENABLE bit(BIT_HARD_LIMIT_ENABLE) 46 | #define BITFLAG_HOMING_ENABLE bit(BIT_HOMING_ENABLE) 47 | #define BITFLAG_SOFT_LIMIT_ENABLE bit(BIT_SOFT_LIMIT_ENABLE) 48 | #define BITFLAG_INVERT_LIMIT_PINS bit(BIT_INVERT_LIMIT_PINS) 49 | #define BITFLAG_INVERT_PROBE_PIN bit(BIT_INVERT_PROBE_PIN) 50 | 51 | // Define status reporting boolean enable bit flags in settings.status_report_mask 52 | #define BITFLAG_RT_STATUS_POSITION_TYPE bit(0) 53 | #define BITFLAG_RT_STATUS_BUFFER_STATE bit(1) 54 | 55 | // Define settings restore bitflags. 56 | #define SETTINGS_RESTORE_DEFAULTS bit(0) 57 | #define SETTINGS_RESTORE_PARAMETERS bit(1) 58 | #define SETTINGS_RESTORE_STARTUP_LINES bit(2) 59 | #define SETTINGS_RESTORE_BUILD_INFO bit(3) 60 | #ifndef SETTINGS_RESTORE_ALL 61 | #define SETTINGS_RESTORE_ALL 0xFF // All bitflags 62 | #endif 63 | 64 | // Define EEPROM memory address location values for Grbl settings and parameters 65 | // NOTE: The Atmega328p has 1KB EEPROM. The upper half is reserved for parameters and 66 | // the startup script. The lower half contains the global settings and space for future 67 | // developments. 68 | #define EEPROM_ADDR_GLOBAL 1U 69 | #define EEPROM_ADDR_PARAMETERS 1024U 70 | #define EEPROM_ADDR_STARTUP_BLOCK 1536U 71 | #define EEPROM_ADDR_BUILD_INFO 1792U 72 | 73 | // Define EEPROM address indexing for coordinate parameters 74 | #define N_COORDINATE_SYSTEM 6 // Number of supported work coordinate systems (from index 1) 75 | #define SETTING_INDEX_NCOORD N_COORDINATE_SYSTEM+1 // Total number of system stored (from index 0) 76 | // NOTE: Work coordinate indices are (0=G54, 1=G55, ... , 6=G59) 77 | #define SETTING_INDEX_G28 N_COORDINATE_SYSTEM // Home position 1 78 | #define SETTING_INDEX_G30 N_COORDINATE_SYSTEM+1 // Home position 2 79 | // #define SETTING_INDEX_G92 N_COORDINATE_SYSTEM+2 // Coordinate offset (G92.2,G92.3 not supported) 80 | 81 | // Define Grbl axis settings numbering scheme. Starts at START_VAL, every INCREMENT, over N_SETTINGS. 82 | #define AXIS_N_SETTINGS 4 83 | #define AXIS_SETTINGS_START_VAL 100 // NOTE: Reserving settings values >= 100 for axis settings. Up to 255. 84 | #define AXIS_SETTINGS_INCREMENT 10 // Must be greater than the number of axis settings 85 | 86 | // Global persistent settings (Stored from byte EEPROM_ADDR_GLOBAL onwards) 87 | typedef struct { 88 | // Axis settings 89 | float steps_per_mm[N_AXIS]; 90 | float max_rate[N_AXIS]; 91 | float acceleration[N_AXIS]; 92 | float max_travel[N_AXIS]; 93 | 94 | // Remaining Grbl settings 95 | uint8_t pulse_microseconds; 96 | uint8_t step_invert_mask; 97 | uint8_t dir_invert_mask; 98 | uint8_t stepper_idle_lock_time; // If max value 255, steppers do not disable. 99 | uint8_t status_report_mask; // Mask to indicate desired report data. 100 | float junction_deviation; 101 | float arc_tolerance; 102 | 103 | float rpm_max; 104 | float rpm_min; 105 | 106 | uint8_t flags; // Contains default boolean settings 107 | 108 | uint8_t homing_dir_mask; 109 | float homing_feed_rate; 110 | float homing_seek_rate; 111 | uint16_t homing_debounce_delay; 112 | float homing_pulloff; 113 | } settings_t; 114 | extern settings_t settings; 115 | 116 | // Initialize the configuration subsystem (load settings from EEPROM) 117 | void settings_init(); 118 | 119 | // Helper function to clear and restore EEPROM defaults 120 | void settings_restore(uint8_t restore_flag); 121 | 122 | // A helper method to set new settings from command line 123 | uint8_t settings_store_global_setting(uint8_t parameter, float value); 124 | 125 | // Stores the protocol line variable as a startup line in EEPROM 126 | void settings_store_startup_line(uint8_t n, char *line); 127 | 128 | // Reads an EEPROM startup line to the protocol line variable 129 | uint8_t settings_read_startup_line(uint8_t n, char *line); 130 | 131 | // Stores build info user-defined string 132 | void settings_store_build_info(char *line); 133 | 134 | // Reads build info user-defined string 135 | uint8_t settings_read_build_info(char *line); 136 | 137 | // Writes selected coordinate data to EEPROM 138 | void settings_write_coord_data(uint8_t coord_select, float *coord_data); 139 | 140 | // Reads selected coordinate data from EEPROM 141 | uint8_t settings_read_coord_data(uint8_t coord_select, float *coord_data); 142 | 143 | // Returns the step pin mask according to Grbl's internal axis numbering 144 | uint8_t get_step_pin_mask(uint8_t i); 145 | 146 | // Returns the direction pin mask according to Grbl's internal axis numbering 147 | uint8_t get_direction_pin_mask(uint8_t i); 148 | 149 | // Returns the limit pin mask according to Grbl's internal axis numbering 150 | uint8_t get_limit_pin_mask(uint8_t i); 151 | 152 | 153 | #endif 154 | -------------------------------------------------------------------------------- /lib/grbl/src/spindle_control.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | spindle_control.c - spindle control methods 3 | Part of Grbl 4 | 5 | Copyright (c) 2012-2017 Sungeun K. Jeon for Gnea Research LLC 6 | Copyright (c) 2009-2011 Simen Svale Skogsrud 7 | 8 | Grbl is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | Grbl is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with Grbl. If not, see . 20 | */ 21 | 22 | #include "grbl.hpp" 23 | 24 | #ifdef VARIABLE_SPINDLE 25 | static float pwm_gradient; // Precalulated value to speed up rpm to PWM conversions. 26 | #endif 27 | 28 | 29 | void spindle_init() 30 | { 31 | #ifdef VARIABLE_SPINDLE 32 | 33 | // Configure variable spindle PWM and enable pin, if requried. On the Uno, PWM and enable are 34 | // combined unless configured otherwise. 35 | //SPINDLE_PWM_DDR |= (1<= settings.rpm_max) || (rpm >= RPM_MAX)) { 150 | rpm = RPM_MAX; 151 | pwm_value = SPINDLE_PWM_MAX_VALUE; 152 | } else if (rpm <= RPM_MIN) { 153 | if (rpm == 0.0) { // S0 disables spindle 154 | pwm_value = SPINDLE_PWM_OFF_VALUE; 155 | } else { 156 | rpm = RPM_MIN; 157 | pwm_value = SPINDLE_PWM_MIN_VALUE; 158 | } 159 | } else { 160 | // Compute intermediate PWM value with linear spindle speed model via piecewise linear fit model. 161 | #if (N_PIECES > 3) 162 | if (rpm > RPM_POINT34) { 163 | pwm_value = floor(RPM_LINE_A4*rpm - RPM_LINE_B4); 164 | } else 165 | #endif 166 | #if (N_PIECES > 2) 167 | if (rpm > RPM_POINT23) { 168 | pwm_value = floor(RPM_LINE_A3*rpm - RPM_LINE_B3); 169 | } else 170 | #endif 171 | #if (N_PIECES > 1) 172 | if (rpm > RPM_POINT12) { 173 | pwm_value = floor(RPM_LINE_A2*rpm - RPM_LINE_B2); 174 | } else 175 | #endif 176 | { 177 | pwm_value = floor(RPM_LINE_A1*rpm - RPM_LINE_B1); 178 | } 179 | } 180 | sys.spindle_speed = rpm; 181 | return(pwm_value); 182 | } 183 | 184 | #else 185 | 186 | // Called by spindle_set_state() and step segment generator. Keep routine small and efficient. 187 | uint8_t spindle_compute_pwm_value(float rpm) // 328p PWM register is 8-bit. 188 | { 189 | uint8_t pwm_value; 190 | rpm *= (0.010*sys.spindle_speed_ovr); // Scale by spindle speed override value. 191 | // Calculate PWM register value based on rpm max/min settings and programmed rpm. 192 | if ((settings.rpm_min >= settings.rpm_max) || (rpm >= settings.rpm_max)) { 193 | // No PWM range possible. Set simple on/off spindle control pin state. 194 | sys.spindle_speed = settings.rpm_max; 195 | pwm_value = SPINDLE_PWM_MAX_VALUE; 196 | } else if (rpm <= settings.rpm_min) { 197 | if (rpm == 0.0) { // S0 disables spindle 198 | sys.spindle_speed = 0.0; 199 | pwm_value = SPINDLE_PWM_OFF_VALUE; 200 | } else { // Set minimum PWM output 201 | sys.spindle_speed = settings.rpm_min; 202 | pwm_value = SPINDLE_PWM_MIN_VALUE; 203 | } 204 | } else { 205 | // Compute intermediate PWM value with linear spindle speed model. 206 | // NOTE: A nonlinear model could be installed here, if required, but keep it VERY light-weight. 207 | sys.spindle_speed = rpm; 208 | pwm_value = floor((rpm-settings.rpm_min)*pwm_gradient) + SPINDLE_PWM_MIN_VALUE; 209 | } 210 | return(pwm_value); 211 | } 212 | 213 | #endif 214 | #endif 215 | 216 | 217 | // Immediately sets spindle running state with direction and spindle rpm via PWM, if enabled. 218 | // Called by g-code parser spindle_sync(), parking retract and restore, g-code program end, 219 | // sleep, and spindle stop override. 220 | #ifdef VARIABLE_SPINDLE 221 | void spindle_set_state(uint8_t state, float rpm) 222 | #else 223 | void _spindle_set_state(uint8_t state) 224 | #endif 225 | { 226 | if (sys.abort) { return; } // Block during abort. 227 | if (state == SPINDLE_DISABLE) { // Halt or set spindle direction and rpm. 228 | 229 | #ifdef VARIABLE_SPINDLE 230 | sys.spindle_speed = 0.0; 231 | #endif 232 | spindle_stop(); 233 | 234 | } else { 235 | 236 | #ifndef USE_SPINDLE_DIR_AS_ENABLE_PIN 237 | if (state == SPINDLE_ENABLE_CW) { 238 | //SPINDLE_DIRECTION_PORT &= ~(1<. 20 | */ 21 | 22 | #ifndef spindle_control_h 23 | #define spindle_control_h 24 | 25 | #define SPINDLE_NO_SYNC false 26 | #define SPINDLE_FORCE_SYNC true 27 | 28 | #define SPINDLE_STATE_DISABLE 0 // Must be zero. 29 | #define SPINDLE_STATE_CW bit(0) 30 | #define SPINDLE_STATE_CCW bit(1) 31 | 32 | 33 | // Initializes spindle pins and hardware PWM, if enabled. 34 | void spindle_init(); 35 | 36 | // Returns current spindle output state. Overrides may alter it from programmed states. 37 | uint8_t spindle_get_state(); 38 | 39 | // Called by g-code parser when setting spindle state and requires a buffer sync. 40 | // Immediately sets spindle running state with direction and spindle rpm via PWM, if enabled. 41 | // Called by spindle_sync() after sync and parking motion/spindle stop override during restore. 42 | #ifdef VARIABLE_SPINDLE 43 | 44 | // Called by g-code parser when setting spindle state and requires a buffer sync. 45 | void spindle_sync(uint8_t state, float rpm); 46 | 47 | // Sets spindle running state with direction, enable, and spindle PWM. 48 | void spindle_set_state(uint8_t state, float rpm); 49 | 50 | // Sets spindle PWM quickly for stepper ISR. Also called by spindle_set_state(). 51 | // NOTE: 328p PWM register is 8-bit. 52 | void spindle_set_speed(uint8_t pwm_value); 53 | 54 | // Computes 328p-specific PWM register value for the given RPM for quick updating. 55 | uint8_t spindle_compute_pwm_value(float rpm); 56 | 57 | #else 58 | 59 | // Called by g-code parser when setting spindle state and requires a buffer sync. 60 | #define spindle_sync(state, rpm) _spindle_sync(state) 61 | void _spindle_sync(uint8_t state); 62 | 63 | // Sets spindle running state with direction and enable. 64 | #define spindle_set_state(state, rpm) _spindle_set_state(state) 65 | void _spindle_set_state(uint8_t state); 66 | 67 | #endif 68 | 69 | // Stop and start spindle routines. Called by all spindle routines and stepper ISR. 70 | void spindle_stop(); 71 | 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /lib/grbl/src/stepper.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | stepper.h - stepper motor driver: executes motion plans of planner.c using the stepper motors 3 | Part of Grbl 4 | 5 | Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC 6 | Copyright (c) 2009-2011 Simen Svale Skogsrud 7 | 8 | Grbl is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | Grbl is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with Grbl. If not, see . 20 | */ 21 | 22 | #ifndef stepper_h 23 | #define stepper_h 24 | 25 | #ifndef SEGMENT_BUFFER_SIZE 26 | #define SEGMENT_BUFFER_SIZE 6 27 | #endif 28 | 29 | // Initialize and setup the stepper motor subsystem 30 | void stepper_init(); 31 | 32 | // Enable steppers, but cycle does not start unless called by motion control or realtime command. 33 | void st_wake_up(); 34 | 35 | // Immediately disables steppers 36 | void st_go_idle(); 37 | 38 | // Generate the step and direction port invert masks. 39 | void st_generate_step_dir_invert_masks(); 40 | 41 | // Reset the stepper subsystem variables 42 | void st_reset(); 43 | 44 | // Changes the run state of the step segment buffer to execute the special parking motion. 45 | void st_parking_setup_buffer(); 46 | 47 | // Restores the step segment buffer to the normal run state after a parking motion. 48 | void st_parking_restore_buffer(); 49 | 50 | // Reloads step segment buffer. Called continuously by realtime execution system. 51 | void st_prep_buffer(); 52 | 53 | // Called by planner_recalculate() when the executing block is updated by the new plan. 54 | void st_update_plan_block_parameters(); 55 | 56 | // Called by realtime status reporting if realtime rate reporting is enabled in config.h. 57 | float st_get_realtime_rate(); 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /lib/grbl/src/system.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | system.c - Handles system level commands and real-time processes 3 | Part of Grbl 4 | 5 | Copyright (c) 2014-2016 Sungeun K. Jeon for Gnea Research LLC 6 | 7 | Grbl is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Grbl is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with Grbl. If not, see . 19 | */ 20 | 21 | #include "grbl.hpp" 22 | #include 23 | 24 | void system_init() 25 | { 26 | SPI.begin(); 27 | SPI.setHwCs(true); 28 | SPI.setFrequency(F_STEPPER_TIMER); 29 | 30 | // Turn off all control inputs 31 | CONTROL_PORT &= ~CONTROL_MASK; 32 | SPI.write(regs.data); 33 | 34 | // Attach interrupt to control input pin 35 | pinMode(CONTROL_INPUT_GPIO_PIN, INPUT_PULLUP); 36 | attachInterrupt(digitalPinToInterrupt(CONTROL_INPUT_GPIO_PIN), pin_control_vect, CHANGE); 37 | } 38 | 39 | 40 | // Returns control pin state as a uint8 bitfield. Each bit indicates the input pin state, where 41 | // triggered is 1 and not triggered is 0. Invert mask is applied. Bitfield organization is 42 | // defined by the CONTROL_PIN_INDEX in the header file. 43 | IRAM_ATTR uint8_t system_control_get_state() 44 | { 45 | uint8_t control_state = 0; 46 | uint8_t pin = (CONTROL_PORT_INPUTS & CONTROL_MASK); 47 | #ifdef INVERT_CONTROL_PIN_MASK 48 | pin ^= INVERT_CONTROL_PIN_MASK; 49 | #endif 50 | if (pin) { 51 | #ifdef ENABLE_SAFETY_DOOR_INPUT_PIN 52 | if (bit_istrue(pin,(1< 255)) { return(STATUS_INVALID_STATEMENT); } 302 | return(settings_store_global_setting((uint8_t)parameter, value)); 303 | } 304 | } 305 | } 306 | return(STATUS_OK); // If '$' command makes it to here, then everything's ok. 307 | } 308 | 309 | 310 | 311 | void system_flag_wco_change() 312 | { 313 | #ifdef FORCE_BUFFER_SYNC_DURING_WCO_CHANGE 314 | protocol_buffer_synchronize(); 315 | #endif 316 | sys.report_wco_counter = 0; 317 | } 318 | 319 | 320 | // Returns machine position of axis 'idx'. Must be sent a 'step' array. 321 | // NOTE: If motor steps and machine position are not in the same coordinate frame, this function 322 | // serves as a central place to compute the transformation. 323 | float system_convert_axis_steps_to_mpos(int32_t *steps, uint8_t idx) 324 | { 325 | float pos; 326 | #ifdef COREXY 327 | if (idx==X_AXIS) { 328 | pos = (float)system_convert_corexy_to_x_axis_steps(steps) / settings.steps_per_mm[idx]; 329 | } else if (idx==Y_AXIS) { 330 | pos = (float)system_convert_corexy_to_y_axis_steps(steps) / settings.steps_per_mm[idx]; 331 | } else { 332 | pos = steps[idx]/settings.steps_per_mm[idx]; 333 | } 334 | #else 335 | pos = steps[idx]/settings.steps_per_mm[idx]; 336 | #endif 337 | return(pos); 338 | } 339 | 340 | 341 | void system_convert_array_steps_to_mpos(float *position, int32_t *steps) 342 | { 343 | uint8_t idx; 344 | for (idx=0; idx -settings.max_travel[idx]) { return(true); } 374 | } else { 375 | if (target[idx] > 0 || target[idx] < settings.max_travel[idx]) { return(true); } 376 | } 377 | #else 378 | // NOTE: max_travel is stored as negative 379 | if (target[idx] > 0 || target[idx] < settings.max_travel[idx]) { return(true); } 380 | #endif 381 | } 382 | return(false); 383 | } 384 | 385 | 386 | // Special handlers for setting and clearing Grbl's real-time execution flags. 387 | void system_set_exec_state_flag(uint8_t mask) { 388 | //uint8_t sreg = save_SREG(); 389 | //cli(); 390 | sys_rt_exec_state |= (mask); 391 | //restore_SREG(sreg); 392 | } 393 | 394 | void system_clear_exec_state_flag(uint8_t mask) { 395 | //uint8_t sreg = save_SREG(); 396 | //cli(); 397 | sys_rt_exec_state &= ~(mask); 398 | //restore_SREG(sreg); 399 | //sei(); 400 | } 401 | 402 | void system_set_exec_alarm(uint8_t code) { 403 | //uint8_t sreg = save_SREG(); 404 | //cli(); 405 | sys_rt_exec_alarm = code; 406 | //restore_SREG(sreg); 407 | } 408 | 409 | void system_clear_exec_alarm() { 410 | //uint8_t sreg = save_SREG(); 411 | //cli(); 412 | sys_rt_exec_alarm = 0; 413 | //restore_SREG(sreg); 414 | // sei(); 415 | } 416 | 417 | void system_set_exec_motion_override_flag(uint8_t mask) { 418 | //uint8_t sreg = save_SREG(); 419 | //cli(); 420 | sys_rt_exec_motion_override |= (mask); 421 | //restore_SREG(sreg); 422 | } 423 | 424 | void system_set_exec_accessory_override_flag(uint8_t mask) { 425 | //uint8_t sreg = save_SREG(); 426 | //cli(); 427 | sys_rt_exec_accessory_override |= (mask); 428 | //restore_SREG(sreg); 429 | } 430 | 431 | void system_clear_exec_motion_overrides() { 432 | //uint8_t sreg = save_SREG(); 433 | //cli(); 434 | sys_rt_exec_motion_override = 0; 435 | //restore_SREG(sreg); 436 | // sei(); 437 | } 438 | 439 | void system_clear_exec_accessory_overrides() { 440 | //uint8_t sreg = save_SREG(); 441 | //cli(); 442 | sys_rt_exec_accessory_override = 0; 443 | //restore_SREG(sreg); 444 | // sei(); 445 | } 446 | -------------------------------------------------------------------------------- /lib/grbl/src/system.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | system.h - Header for system level commands and real-time processes 3 | Part of Grbl 4 | 5 | Copyright (c) 2014-2016 Sungeun K. Jeon for Gnea Research LLC 6 | 7 | Grbl is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Grbl is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with Grbl. If not, see . 19 | */ 20 | 21 | #ifndef system_h 22 | #define system_h 23 | 24 | #include "grbl.hpp" 25 | 26 | // Define system executor bit map. Used internally by realtime protocol as realtime command flags, 27 | // which notifies the main program to execute the specified realtime command asynchronously. 28 | // NOTE: The system executor uses an unsigned 8-bit volatile variable (8 flag limit.) The default 29 | // flags are always false, so the realtime protocol only needs to check for a non-zero value to 30 | // know when there is a realtime command to execute. 31 | #define EXEC_STATUS_REPORT bit(0) // bitmask 00000001 32 | #define EXEC_CYCLE_START bit(1) // bitmask 00000010 33 | #define EXEC_CYCLE_STOP bit(2) // bitmask 00000100 34 | #define EXEC_FEED_HOLD bit(3) // bitmask 00001000 35 | #define EXEC_RESET bit(4) // bitmask 00010000 36 | #define EXEC_SAFETY_DOOR bit(5) // bitmask 00100000 37 | #define EXEC_MOTION_CANCEL bit(6) // bitmask 01000000 38 | #define EXEC_SLEEP bit(7) // bitmask 10000000 39 | 40 | // Alarm executor codes. Valid values (1-255). Zero is reserved. 41 | #define EXEC_ALARM_HARD_LIMIT 1 42 | #define EXEC_ALARM_SOFT_LIMIT 2 43 | #define EXEC_ALARM_ABORT_CYCLE 3 44 | #define EXEC_ALARM_PROBE_FAIL_INITIAL 4 45 | #define EXEC_ALARM_PROBE_FAIL_CONTACT 5 46 | #define EXEC_ALARM_HOMING_FAIL_RESET 6 47 | #define EXEC_ALARM_HOMING_FAIL_DOOR 7 48 | #define EXEC_ALARM_HOMING_FAIL_PULLOFF 8 49 | #define EXEC_ALARM_HOMING_FAIL_APPROACH 9 50 | 51 | // Override bit maps. Realtime bitflags to control feed, rapid, spindle, and coolant overrides. 52 | // Spindle/coolant and feed/rapids are separated into two controlling flag variables. 53 | #define EXEC_FEED_OVR_RESET bit(0) 54 | #define EXEC_FEED_OVR_COARSE_PLUS bit(1) 55 | #define EXEC_FEED_OVR_COARSE_MINUS bit(2) 56 | #define EXEC_FEED_OVR_FINE_PLUS bit(3) 57 | #define EXEC_FEED_OVR_FINE_MINUS bit(4) 58 | #define EXEC_RAPID_OVR_RESET bit(5) 59 | #define EXEC_RAPID_OVR_MEDIUM bit(6) 60 | #define EXEC_RAPID_OVR_LOW bit(7) 61 | // #define EXEC_RAPID_OVR_EXTRA_LOW bit(*) // *NOT SUPPORTED* 62 | 63 | #define EXEC_SPINDLE_OVR_RESET bit(0) 64 | #define EXEC_SPINDLE_OVR_COARSE_PLUS bit(1) 65 | #define EXEC_SPINDLE_OVR_COARSE_MINUS bit(2) 66 | #define EXEC_SPINDLE_OVR_FINE_PLUS bit(3) 67 | #define EXEC_SPINDLE_OVR_FINE_MINUS bit(4) 68 | #define EXEC_SPINDLE_OVR_STOP bit(5) 69 | #define EXEC_COOLANT_FLOOD_OVR_TOGGLE bit(6) 70 | #define EXEC_COOLANT_MIST_OVR_TOGGLE bit(7) 71 | 72 | // Define system state bit map. The state variable primarily tracks the individual functions 73 | // of Grbl to manage each without overlapping. It is also used as a messaging flag for 74 | // critical events. 75 | #define STATE_IDLE 0 // Must be zero. No flags. 76 | #define STATE_ALARM bit(0) // In alarm state. Locks out all g-code processes. Allows settings access. 77 | #define STATE_CHECK_MODE bit(1) // G-code check mode. Locks out planner and motion only. 78 | #define STATE_HOMING bit(2) // Performing homing cycle 79 | #define STATE_CYCLE bit(3) // Cycle is running or motions are being executed. 80 | #define STATE_HOLD bit(4) // Active feed hold 81 | #define STATE_JOG bit(5) // Jogging mode. 82 | #define STATE_SAFETY_DOOR bit(6) // Safety door is ajar. Feed holds and de-energizes system. 83 | #define STATE_SLEEP bit(7) // Sleep state. 84 | 85 | // Define system suspend flags. Used in various ways to manage suspend states and procedures. 86 | #define SUSPEND_DISABLE 0 // Must be zero. 87 | #define SUSPEND_HOLD_COMPLETE bit(0) // Indicates initial feed hold is complete. 88 | #define SUSPEND_RESTART_RETRACT bit(1) // Flag to indicate a retract from a restore parking motion. 89 | #define SUSPEND_RETRACT_COMPLETE bit(2) // (Safety door only) Indicates retraction and de-energizing is complete. 90 | #define SUSPEND_INITIATE_RESTORE bit(3) // (Safety door only) Flag to initiate resume procedures from a cycle start. 91 | #define SUSPEND_RESTORE_COMPLETE bit(4) // (Safety door only) Indicates ready to resume normal operation. 92 | #define SUSPEND_SAFETY_DOOR_AJAR bit(5) // Tracks safety door state for resuming. 93 | #define SUSPEND_MOTION_CANCEL bit(6) // Indicates a canceled resume motion. Currently used by probing routine. 94 | #define SUSPEND_JOG_CANCEL bit(7) // Indicates a jog cancel in process and to reset buffers when complete. 95 | 96 | // Define step segment generator state flags. 97 | #define STEP_CONTROL_NORMAL_OP 0 // Must be zero. 98 | #define STEP_CONTROL_END_MOTION bit(0) 99 | #define STEP_CONTROL_EXECUTE_HOLD bit(1) 100 | #define STEP_CONTROL_EXECUTE_SYS_MOTION bit(2) 101 | #define STEP_CONTROL_UPDATE_SPINDLE_PWM bit(3) 102 | 103 | // Define control pin index for Grbl internal use. Pin maps may change, but these values don't. 104 | #ifdef ENABLE_SAFETY_DOOR_INPUT_PIN 105 | #define N_CONTROL_PIN 4 106 | #define CONTROL_PIN_INDEX_SAFETY_DOOR bit(0) 107 | #define CONTROL_PIN_INDEX_RESET bit(1) 108 | #define CONTROL_PIN_INDEX_FEED_HOLD bit(2) 109 | #define CONTROL_PIN_INDEX_CYCLE_START bit(3) 110 | #else 111 | #define N_CONTROL_PIN 3 112 | #define CONTROL_PIN_INDEX_RESET bit(0) 113 | #define CONTROL_PIN_INDEX_FEED_HOLD bit(1) 114 | #define CONTROL_PIN_INDEX_CYCLE_START bit(2) 115 | #endif 116 | 117 | // Define spindle stop override control states. 118 | #define SPINDLE_STOP_OVR_DISABLED 0 // Must be zero. 119 | #define SPINDLE_STOP_OVR_ENABLED bit(0) 120 | #define SPINDLE_STOP_OVR_INITIATE bit(1) 121 | #define SPINDLE_STOP_OVR_RESTORE bit(2) 122 | #define SPINDLE_STOP_OVR_RESTORE_CYCLE bit(3) 123 | 124 | 125 | // Define global system variables 126 | typedef struct { 127 | uint8_t state; // Tracks the current system state of Grbl. 128 | uint8_t abort; // System abort flag. Forces exit back to main loop for reset. 129 | uint8_t suspend; // System suspend bitflag variable that manages holds, cancels, and safety door. 130 | uint8_t soft_limit; // Tracks soft limit errors for the state machine. (boolean) 131 | uint8_t step_control; // Governs the step segment generator depending on system state. 132 | uint8_t probe_succeeded; // Tracks if last probing cycle was successful. 133 | uint8_t homing_axis_lock; // Locks axes when limits engage. Used as an axis motion mask in the stepper ISR. 134 | uint8_t f_override; // Feed rate override value in percent 135 | uint8_t r_override; // Rapids override value in percent 136 | uint8_t spindle_speed_ovr; // Spindle speed value in percent 137 | uint8_t spindle_stop_ovr; // Tracks spindle stop override states 138 | uint8_t report_ovr_counter; // Tracks when to add override data to status reports. 139 | uint8_t report_wco_counter; // Tracks when to add work coordinate offset data to status reports. 140 | #ifdef ENABLE_PARKING_OVERRIDE_CONTROL 141 | uint8_t override_ctrl; // Tracks override control states. 142 | #endif 143 | #ifdef VARIABLE_SPINDLE 144 | float spindle_speed; 145 | #endif 146 | } system_t; 147 | extern system_t sys; 148 | 149 | // NOTE: These position variables may need to be declared as volatiles, if problems arise. 150 | extern int32_t sys_position[N_AXIS]; // Real-time machine (aka home) position vector in steps. 151 | extern int32_t sys_probe_position[N_AXIS]; // Last probe position in machine coordinates and steps. 152 | 153 | extern volatile uint8_t sys_probe_state; // Probing state value. Used to coordinate the probing cycle with stepper ISR. 154 | extern volatile uint8_t sys_rt_exec_state; // Global realtime executor bitflag variable for state management. See EXEC bitmasks. 155 | extern volatile uint8_t sys_rt_exec_alarm; // Global realtime executor bitflag variable for setting various alarms. 156 | extern volatile uint8_t sys_rt_exec_motion_override; // Global realtime executor bitflag variable for motion-based overrides. 157 | extern volatile uint8_t sys_rt_exec_accessory_override; // Global realtime executor bitflag variable for spindle/coolant overrides. 158 | 159 | #ifdef DEBUG 160 | #define EXEC_DEBUG_REPORT bit(0) 161 | extern volatile uint8_t sys_rt_exec_debug; 162 | #endif 163 | 164 | // Initialize the serial protocol 165 | void system_init(); 166 | 167 | // Returns bitfield of control pin states, organized by CONTROL_PIN_INDEX. (1=triggered, 0=not triggered). 168 | uint8_t system_control_get_state(); 169 | 170 | // Returns if safety door is open or closed, based on pin state. 171 | uint8_t system_check_safety_door_ajar(); 172 | 173 | // Executes an internal system command, defined as a string starting with a '$' 174 | uint8_t system_execute_line(char *line, uint8_t client); 175 | 176 | // Execute the startup script lines stored in EEPROM upon initialization 177 | void system_execute_startup(char *line); 178 | 179 | 180 | void system_flag_wco_change(); 181 | 182 | // Returns machine position of axis 'idx'. Must be sent a 'step' array. 183 | float system_convert_axis_steps_to_mpos(int32_t *steps, uint8_t idx); 184 | 185 | // Updates a machine 'position' array based on the 'step' array sent. 186 | void system_convert_array_steps_to_mpos(float *position, int32_t *steps); 187 | 188 | // CoreXY calculation only. Returns x or y-axis "steps" based on CoreXY motor steps. 189 | #ifdef COREXY 190 | int32_t system_convert_corexy_to_x_axis_steps(int32_t *steps); 191 | int32_t system_convert_corexy_to_y_axis_steps(int32_t *steps); 192 | #endif 193 | 194 | // Checks and reports if target array exceeds machine travel limits. 195 | uint8_t system_check_travel_limits(float *target); 196 | 197 | // Special handlers for setting and clearing Grbl's real-time execution flags. 198 | void system_set_exec_state_flag(uint8_t mask); 199 | void system_clear_exec_state_flag(uint8_t mask); 200 | void system_set_exec_alarm(uint8_t code); 201 | void system_clear_exec_alarm(); 202 | void system_set_exec_motion_override_flag(uint8_t mask); 203 | void system_set_exec_accessory_override_flag(uint8_t mask); 204 | void system_clear_exec_motion_overrides(); 205 | void system_clear_exec_accessory_overrides(); 206 | 207 | void pin_control_vect(); 208 | 209 | #endif 210 | -------------------------------------------------------------------------------- /lib/grbl/src/telnet_server.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include "config.h" 4 | #include "telnet_server.hpp" 5 | #include "grbl.hpp" 6 | #include "report.hpp" 7 | 8 | Telnet_Server telnetServer; 9 | bool Telnet_Server::_setupdone = false; 10 | uint16_t Telnet_Server::_port = 0; 11 | AsyncServer *Telnet_Server::_telnetServer = NULL; 12 | AsyncClient *Telnet_Server::_telnetClients[MAX_TELNET_CLIENTS] = {NULL}; 13 | 14 | Telnet_Server::Telnet_Server(){ 15 | _RXbufferSize = 0; 16 | _RXbufferpos = 0; 17 | } 18 | Telnet_Server::~Telnet_Server(){ 19 | end(); 20 | } 21 | 22 | bool Telnet_Server::begin(){ 23 | bool no_error = true; 24 | end(); 25 | _RXbufferSize = 0; 26 | _RXbufferpos = 0; 27 | #ifdef ENABLE_TELNET 28 | int8_t penabled = 1; 29 | #else 30 | int8_t penabled = 0; 31 | #endif 32 | _port = TELNET_SERVER_PORT; 33 | 34 | if (penabled == 0) return false; 35 | _telnetServer = new AsyncServer(_port); 36 | _telnetServer->setNoDelay(true); 37 | String s = "[MSG:TELNET Started " + String(_port) + "]\r\n"; 38 | grbl_send(CLIENT_ALL,(char *)s.c_str()); 39 | 40 | //start telnet server 41 | _telnetServer->onClient(&Telnet_Server::handleNewClient, _telnetServer); 42 | _telnetServer->begin(); 43 | _setupdone = true; 44 | return no_error; 45 | } 46 | 47 | void Telnet_Server::end(){ 48 | _setupdone = false; 49 | _RXbufferSize = 0; 50 | _RXbufferpos = 0; 51 | if (_telnetServer) { 52 | delete _telnetServer; 53 | _telnetServer = NULL; 54 | } 55 | } 56 | 57 | size_t Telnet_Server::write(const uint8_t *buffer, size_t size){ 58 | size_t wsize = 0; 59 | if ( !_setupdone || _telnetServer == NULL) { 60 | return 0; 61 | } 62 | //push UART data to all connected telnet clients 63 | for(uint8_t i = 0; i < MAX_TELNET_CLIENTS; i++){ 64 | if (_telnetClients[i] != NULL && _telnetClients[i]->connected()){ 65 | wsize = _telnetClients[i]->write((const char*)buffer, size); 66 | ///delay(0); 67 | } 68 | } 69 | return wsize; 70 | } 71 | 72 | static void handleError(void* arg, AsyncClient* client, int8_t error) { 73 | Serial.printf("\n connection error %s from client %s \n", client->errorToString(error), client->remoteIP().toString().c_str()); 74 | } 75 | 76 | void Telnet_Server::handleData(void* arg, AsyncClient* client, void *data, size_t len) { 77 | //printf("Received '%.*s'\n", len, (uint8_t*)data); 78 | telnetServer.push((uint8_t *)data, len); 79 | } 80 | 81 | void Telnet_Server::handleDisconnect(void* arg, AsyncClient* client) { 82 | Serial.printf("\n client %s disconnected \n", client->remoteIP().toString().c_str()); 83 | uint8_t i = 0; 84 | for (i = 0; i < MAX_TELNET_CLIENTS; i++) { 85 | //find free/disconnected spot 86 | if (_telnetClients[i] != NULL && _telnetClients[i] == client) { 87 | _telnetClients[i] = NULL; 88 | break; 89 | } 90 | } 91 | } 92 | 93 | static void handleTimeOut(void* arg, AsyncClient* client, uint32_t time) { 94 | Serial.printf("\n client ACK timeout ip: %s \n", client->remoteIP().toString().c_str()); 95 | } 96 | 97 | void Telnet_Server::handleNewClient(void* arg, AsyncClient* client) 98 | { 99 | //Serial.printf("\n client connected ip: %s \n", client->remoteIP().toString().c_str()); 100 | client->onData(&handleData, NULL); 101 | client->onError(&handleError, NULL); 102 | client->onDisconnect(&handleDisconnect, NULL); 103 | client->onTimeout(&handleTimeOut, NULL); 104 | 105 | uint8_t i = 0; 106 | for (i = 0; i < MAX_TELNET_CLIENTS; i++) { 107 | //find free/disconnected spot 108 | if (_telnetClients[i] == NULL || !_telnetClients[i]->connected()){ 109 | _telnetClients[i] = client; 110 | break; 111 | } 112 | } 113 | 114 | if (i >= MAX_TELNET_CLIENTS) { 115 | //no free/disconnected spot so reject 116 | client->stop(); 117 | } 118 | } 119 | 120 | int Telnet_Server::peek(void){ 121 | //Serial.printf("TELNET PEEK"); 122 | if (_RXbufferSize > 0)return _RXbuffer[_RXbufferpos]; 123 | else return -1; 124 | } 125 | 126 | int Telnet_Server::available(){ 127 | return _RXbufferSize; 128 | } 129 | 130 | int Telnet_Server::get_rx_buffer_available(){ 131 | return TELNET_RXBUFFERSIZE - _RXbufferSize; 132 | } 133 | 134 | bool Telnet_Server::push(uint8_t data){ 135 | if ((1 + _RXbufferSize) <= TELNET_RXBUFFERSIZE){ 136 | int current = _RXbufferpos + _RXbufferSize; 137 | if (current > TELNET_RXBUFFERSIZE) current = current - TELNET_RXBUFFERSIZE; 138 | if (current > (TELNET_RXBUFFERSIZE-1)) current = 0; 139 | _RXbuffer[current] = data; 140 | _RXbufferSize++; 141 | return true; 142 | } 143 | return false; 144 | } 145 | 146 | bool Telnet_Server::push(const uint8_t * data, int data_size){ 147 | if ((data_size + _RXbufferSize) <= TELNET_RXBUFFERSIZE) { 148 | int data_processed = 0; 149 | int current = _RXbufferpos + _RXbufferSize; 150 | if (current > TELNET_RXBUFFERSIZE) current = current - TELNET_RXBUFFERSIZE; 151 | for (int i = 0; i < data_size; i++){ 152 | if (current > (TELNET_RXBUFFERSIZE-1)) current = 0; 153 | _RXbuffer[current] = data[i]; 154 | current++; 155 | data_processed++; 156 | } 157 | _RXbufferSize+=data_processed; 158 | return true; 159 | } 160 | return false; 161 | } 162 | 163 | int Telnet_Server::read(void){ 164 | if (_RXbufferSize > 0) { 165 | int v = _RXbuffer[_RXbufferpos]; 166 | _RXbufferpos++; 167 | if (_RXbufferpos > (TELNET_RXBUFFERSIZE-1))_RXbufferpos = 0; 168 | _RXbufferSize--; 169 | return v; 170 | } else return -1; 171 | } 172 | -------------------------------------------------------------------------------- /lib/grbl/src/telnet_server.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _TELNET_SERVER_H 3 | #define _TELNET_SERVER_H 4 | 5 | #include 6 | #include 7 | #include "config.h" 8 | 9 | // how many clients should be able to telnet 10 | #define MAX_TELNET_CLIENTS 1 11 | #define TELNET_RXBUFFERSIZE 1200 12 | #define TELNET_SERVER_PORT 23 13 | 14 | class Telnet_Server { 15 | public: 16 | Telnet_Server(); 17 | ~Telnet_Server(); 18 | bool begin(); 19 | void end(); 20 | size_t write(const uint8_t *buffer, size_t size); 21 | int read(void); 22 | int peek(void); 23 | int available(); 24 | int get_rx_buffer_available(); 25 | bool push (uint8_t data); 26 | bool push (const uint8_t * data, int datasize); 27 | void clearClients(); 28 | static void handleNewClient(void* arg, AsyncClient *client); 29 | static void handleData(void* arg, AsyncClient* client, void *data, size_t len); 30 | static void handleDisconnect(void* arg, AsyncClient* client); 31 | static uint16_t port(){return _port;} 32 | private: 33 | static bool _setupdone; 34 | static AsyncServer *_telnetServer; 35 | static AsyncClient *_telnetClients[MAX_TELNET_CLIENTS]; 36 | static uint16_t _port; 37 | uint32_t _lastflush; 38 | uint8_t _RXbuffer[TELNET_RXBUFFERSIZE]; 39 | uint16_t _RXbufferSize; 40 | uint16_t _RXbufferpos; 41 | }; 42 | 43 | extern Telnet_Server telnetServer; 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /lib/grbl/src/websocket.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | websocket.cpp - Take advantage of the Wifi connection by using websockets instead 3 | of a serial connection 4 | */ 5 | #include "grbl.hpp" 6 | #include 7 | 8 | #ifdef ENABLE_WEBSOCKET 9 | 10 | AsyncWebServer webSocketServer(WEBSOCKET_SERVER_PORT); 11 | AsyncWebSocket ws("/ws"); 12 | //AsyncEventSource events("/events"); 13 | 14 | void websocket_init() 15 | { 16 | ws.onEvent(onWsEvent); 17 | webSocketServer.addHandler(&ws); 18 | webSocketServer.begin(); 19 | Serial2Socket.attachWS(&ws); 20 | } 21 | 22 | void onWsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len){ 23 | if(type == WS_EVT_CONNECT){ 24 | //Serial.printf("ws[%s][%u] connect\n", server->url(), client->id()); 25 | //client->printf("Hello Client %u :)", client->id()); 26 | client->ping(); 27 | } else if(type == WS_EVT_DISCONNECT){ 28 | Serial.printf("ws[%s][%u] disconnect: %u\n", server->url(), client->id()); 29 | } else if(type == WS_EVT_ERROR){ 30 | Serial.printf("ws[%s][%u] error(%u): %s\n", server->url(), client->id(), *((uint16_t*)arg), (char*)data); 31 | } else if(type == WS_EVT_PONG){ 32 | Serial.printf("ws[%s][%u] pong[%u]: %s\n", server->url(), client->id(), len, (len)?(char*)data:""); 33 | } else if(type == WS_EVT_DATA){ 34 | AwsFrameInfo * info = (AwsFrameInfo*)arg; 35 | String msg = ""; 36 | if (info->final && info->index == 0 && info->len == len){ 37 | //the whole message is in a single frame and we got all of it's data 38 | for(size_t i=0; i < info->len; i++) { 39 | msg += (char)data[i]; 40 | } 41 | msg += '\n'; 42 | Serial2Socket.push(msg.c_str()); 43 | } 44 | } 45 | } 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /lib/grbl/src/websocket.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | websocket.hpp - Take advantage of the Wifi connection by using websockets instead 3 | of a websocket connection 4 | */ 5 | 6 | #ifndef websocket_h 7 | #define websocket_h 8 | 9 | #include 10 | 11 | #define WEBSOCKET_SERVER_PORT 80 12 | #define WEBSOCKET_NO_DATA 0xff 13 | 14 | void websocket_init(); 15 | 16 | // Called on every event received by websocket 17 | void onWsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len); 18 | 19 | // Writes one byte to the TX websocket buffer. Called by main program. 20 | void websocket_write(uint8_t data); 21 | 22 | // Fetches the first byte in the websocket read buffer. Called by main program. 23 | uint8_t websocket_read(); 24 | 25 | // Reset and empty data in read buffer. Used by e-stop and reset. 26 | void websocket_reset_read_buffer(); 27 | 28 | // Returns the number of bytes available in the RX websocket buffer. 29 | uint8_t websocket_get_rx_buffer_available(); 30 | 31 | // Returns the number of bytes used in the RX websocket buffer. 32 | // NOTE: Deprecated. Not used unless classic status reports are enabled in config.h. 33 | uint8_t websocket_get_rx_buffer_count(); 34 | 35 | // Returns the number of bytes used in the TX websocket buffer. 36 | // NOTE: Not used except for debugging and ensuring no TX bottlenecks. 37 | uint8_t websocket_get_tx_buffer_count(); 38 | 39 | // Handles connections/disconnection events on the websocket server 40 | void websocket_check_connection(); 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /lib/grbl/src/wifi.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | wifi.cpp - Handles connection to wifi and makes web, websockets and telnet 3 | connections available 4 | */ 5 | 6 | #include 7 | //#include 8 | #include "credentials.hpp" 9 | #include "report.hpp" 10 | #include "config.hpp" 11 | #ifdef ENABLE_WEBSOCKET 12 | #include "websocket.hpp" 13 | #include "serial2socket.hpp" 14 | #endif 15 | #ifdef ENABLE_TELNET 16 | #include "telnet_server.hpp" 17 | #endif 18 | 19 | void wifi_init() 20 | { 21 | WiFi.mode(WIFI_STA); 22 | WiFi.hostname(WIFI_HOSTNAME); 23 | WiFi.begin(WIFI_SSID, WIFI_PASSWORD); 24 | while (WiFi.status() != WL_CONNECTED) { 25 | delay(500); 26 | } 27 | Serial.print("\n[Connected: "); 28 | Serial.print(WiFi.localIP()); 29 | Serial.println("]"); 30 | 31 | //MDNS.addService("http", "tcp", WEBSOCKET_SERVER_PORT); 32 | 33 | #ifdef ENABLE_TELNET 34 | telnetServer.begin(); 35 | #endif 36 | #ifdef ENABLE_WEBSOCKET 37 | websocket_init(); 38 | #endif 39 | //be sure we are not is mixed mode in setup 40 | WiFi.scanNetworks(true); 41 | } 42 | 43 | void wifi_handle() 44 | { 45 | if (WiFi.getMode() == WIFI_AP_STA) { 46 | if (WiFi.scanComplete() != WIFI_SCAN_RUNNING) { 47 | WiFi.enableSTA(false); 48 | } 49 | } 50 | #ifdef ENABLE_OTA 51 | ArduinoOTA.handle(); 52 | #endif 53 | #ifdef ENABLE_HTTP 54 | web_server.handle(); 55 | #endif 56 | } 57 | -------------------------------------------------------------------------------- /lib/grbl/src/wifi.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | wifi.cpp - Handles connection to wifi and makes web, websockets and telnet 3 | connections available 4 | */ 5 | 6 | #ifndef wifi_h 7 | #define wifi_h 8 | 9 | #include "grbl.hpp" 10 | 11 | void wifi_init(); 12 | void wifi_handle(); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /lib/readme.txt: -------------------------------------------------------------------------------- 1 | 2 | This directory is intended for the project specific (private) libraries. 3 | PlatformIO will compile them to static libraries and link to executable file. 4 | 5 | The source code of each library should be placed in separate directory, like 6 | "lib/private_lib/[here are source files]". 7 | 8 | For example, see how can be organized `Foo` and `Bar` libraries: 9 | 10 | |--lib 11 | | |--Bar 12 | | | |--docs 13 | | | |--examples 14 | | | |--src 15 | | | |- Bar.c 16 | | | |- Bar.h 17 | | |--Foo 18 | | | |- Foo.c 19 | | | |- Foo.h 20 | | |- readme.txt --> THIS FILE 21 | |- platformio.ini 22 | |--src 23 | |- main.c 24 | 25 | Then in `src/main.c` you should use: 26 | 27 | #include 28 | #include 29 | 30 | // rest H/C/CPP code 31 | 32 | PlatformIO will find your libraries automatically, configure preprocessor's 33 | include paths and build them. 34 | 35 | More information about PlatformIO Library Dependency Finder 36 | - http://docs.platformio.org/page/librarymanager/ldf.html 37 | -------------------------------------------------------------------------------- /platformio.ini: -------------------------------------------------------------------------------- 1 | ; PlatformIO Project Configuration File 2 | ; 3 | ; Build options: build flags, source filter 4 | ; Upload options: custom upload port, speed and extra flags 5 | ; Library options: dependencies, extra library storages 6 | ; Advanced options: extra scripting 7 | ; 8 | ; Please visit documentation for the other options and examples 9 | ; https://docs.platformio.org/page/projectconf.html 10 | 11 | [env:esp12e] 12 | platform = espressif8266@4.0.1 13 | framework = arduino 14 | board = esp12e 15 | upload_resetmethod = nodemcu 16 | upload_speed = 230400 17 | upload_port = /dev/ttyUSB0 18 | monitor_port = /dev/ttyUSB0 19 | monitor_speed = 115200 20 | monitor_echo = yes 21 | lib_deps = 22 | me-no-dev/ESPAsyncWebServer@1.2.4 23 | me-no-dev/ESPAsyncTCP@1.2.2 24 | lib_ignore = RPAsyncTCP, AsyncTCP 25 | build_flags = -DVTABLES_IN_FLASH 26 | -------------------------------------------------------------------------------- /schemas/spi-connection.fzz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gcobos/grblesp/497762bd6390b6384049f1aac3e59b2b0a4b04dd/schemas/spi-connection.fzz -------------------------------------------------------------------------------- /schemas/spi-connection_schem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gcobos/grblesp/497762bd6390b6384049f1aac3e59b2b0a4b04dd/schemas/spi-connection_schem.png -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | main.c - An embedded CNC Controller with rs274/ngc (g-code) support 3 | Part of Grbl 4 | 5 | Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC 6 | Copyright (c) 2009-2011 Simen Svale Skogsrud 7 | 8 | Grbl is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | Grbl is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with Grbl. If not, see . 20 | */ 21 | 22 | #include 23 | #include "grbl.hpp" 24 | 25 | // Declare system global variable structure 26 | system_t sys; 27 | int32_t sys_position[N_AXIS]; // Real-time machine (aka home) position vector in steps. 28 | int32_t sys_probe_position[N_AXIS]; // Last probe position in machine coordinates and steps. 29 | volatile uint8_t sys_probe_state; // Probing state value. Used to coordinate the probing cycle with stepper ISR. 30 | volatile uint8_t sys_rt_exec_state; // Global realtime executor bitflag variable for state management. See EXEC bitmasks. 31 | volatile uint8_t sys_rt_exec_alarm; // Global realtime executor bitflag variable for setting various alarms. 32 | volatile uint8_t sys_rt_exec_motion_override; // Global realtime executor bitflag variable for motion-based overrides. 33 | volatile uint8_t sys_rt_exec_accessory_override; // Global realtime executor bitflag variable for spindle/coolant overrides. 34 | #ifdef DEBUG 35 | volatile uint8_t sys_rt_exec_debug; 36 | #endif 37 | 38 | void setup(void){ 39 | // Initialize system upon power-up. 40 | serial_init(); // Setup serial connection 41 | eeprom_init(); // Initialize EEPROM 42 | settings_init(); // Load Grbl settings from EEPROM 43 | stepper_init(); // Configure stepper pins and interrupt timers 44 | system_init(); // Configure pinout pins and pin-change interrupt 45 | 46 | memset(sys_position,0,sizeof(sys_position)); // Clear machine position. 47 | sei(); // Enable interrupts 48 | 49 | // Initialize system state. 50 | #ifdef FORCE_INITIALIZATION_ALARM 51 | // Force Grbl into an ALARM state upon a power-cycle or hard reset. 52 | sys.state = STATE_ALARM; 53 | #else 54 | sys.state = STATE_IDLE; 55 | #endif 56 | 57 | // Check for power-up and set system alarm if homing is enabled to force homing cycle 58 | // by setting Grbl's alarm state. Alarm locks out all g-code commands, including the 59 | // startup scripts, but allows access to settings and internal commands. Only a homing 60 | // cycle '$H' or kill alarm locks '$X' will disable the alarm. 61 | // NOTE: The startup script will run after successful completion of the homing cycle, but 62 | // not after disabling the alarm locks. Prevents motion startup blocks from crashing into 63 | // things uncontrollably. Very bad. 64 | #ifdef HOMING_INIT_LOCK 65 | if (bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE)) { sys.state = STATE_ALARM; } 66 | #endif 67 | 68 | #ifdef ENABLE_WIFI 69 | wifi_init(); 70 | #endif 71 | } 72 | 73 | void loop(void) 74 | { 75 | // Grbl initialization loop upon power-up or a system abort. For the latter, all processes 76 | // will return to this loop to be cleanly re-initialized. 77 | 78 | // Reset system variables. 79 | uint8_t prior_state = sys.state; 80 | memset(&sys, 0, sizeof(system_t)); // Clear system struct variable. 81 | sys.state = prior_state; 82 | sys.f_override = DEFAULT_FEED_OVERRIDE; // Set to 100% 83 | sys.r_override = DEFAULT_RAPID_OVERRIDE; // Set to 100% 84 | sys.spindle_speed_ovr = DEFAULT_SPINDLE_SPEED_OVERRIDE; // Set to 100% 85 | memset(sys_probe_position,0,sizeof(sys_probe_position)); // Clear probe position. 86 | sys_probe_state = 0; 87 | sys_rt_exec_state = 0; 88 | sys_rt_exec_alarm = 0; 89 | sys_rt_exec_motion_override = 0; 90 | sys_rt_exec_accessory_override = 0; 91 | 92 | // Reset Grbl primary systems. 93 | serial_reset_read_buffer(CLIENT_ALL); // Clear serial read buffer 94 | gc_init(); // Set g-code parser to default state 95 | spindle_init(); 96 | coolant_init(); 97 | limits_init(); 98 | probe_init(); 99 | plan_reset(); // Clear block buffer and planner variables 100 | st_reset(); // Clear stepper subsystem variables. 101 | 102 | // Sync cleared gcode and planner positions to current system position. 103 | plan_sync_position(); 104 | gc_sync_position(); 105 | 106 | // Print welcome message. Indicates an initialization has occured at power-up or with a reset. 107 | report_init_message(CLIENT_ALL); 108 | 109 | // Start Grbl main loop. Processes program inputs and executes them. 110 | protocol_main_loop(); 111 | } 112 | --------------------------------------------------------------------------------