From 62c60b9a765746d4e5760c40804f627cc6123b80 Mon Sep 17 00:00:00 2001 From: bdring Date: Mon, 10 Sep 2018 12:40:45 -0500 Subject: [PATCH] Added support for Spindle Enable and Direction - Added Spindle Enable Support - Added Spindle Direction Support - M7 and M8 are now both optional See the Wiki on how to setup I/O --- Grbl_Esp32/config.h | 4 ++- Grbl_Esp32/coolant_control.cpp | 49 +++++++++++++++++---------- Grbl_Esp32/cpu_map.h | 14 +++++--- Grbl_Esp32/gcode.cpp | 52 +++++++++++++++------------- Grbl_Esp32/grbl.h | 2 +- Grbl_Esp32/protocol.cpp | 31 +++++++++++------ Grbl_Esp32/report.cpp | 24 ++++++------- Grbl_Esp32/serial.cpp | 10 ++++-- Grbl_Esp32/spindle_control.cpp | 62 +++++++++++++++++++++++++++++----- Grbl_Esp32/spindle_control.h | 7 ++-- README.md | 1 - 11 files changed, 167 insertions(+), 89 deletions(-) diff --git a/Grbl_Esp32/config.h b/Grbl_Esp32/config.h index f16f2cc2..6da95f92 100644 --- a/Grbl_Esp32/config.h +++ b/Grbl_Esp32/config.h @@ -185,7 +185,9 @@ Some features should not be changed. See notes below. // Enables a second coolant control pin via the mist coolant g-code command M7 on the Arduino Uno // analog pin 4. Only use this option if you require a second coolant control pin. // NOTE: The M8 flood coolant control pin on analog pin 3 will still be functional regardless. -//#define ENABLE_M7 // Disabled by default. Uncomment to enable. +// ESP32 NOTE! This is here for reference only. You enable both M7 and M8 by assigning them a GPIO Pin +// in cpu_map.h +//#define ENABLE_M7 // Don't uncomment...see above! // This option causes the feed hold input to act as a safety door switch. A safety door, when triggered, // immediately forces a feed hold and then safely de-energizes the machine. Resuming is blocked until diff --git a/Grbl_Esp32/coolant_control.cpp b/Grbl_Esp32/coolant_control.cpp index 7e5c0ed7..10e08338 100644 --- a/Grbl_Esp32/coolant_control.cpp +++ b/Grbl_Esp32/coolant_control.cpp @@ -26,8 +26,12 @@ void coolant_init() { - pinMode(COOLANT_FLOOD_PIN, OUTPUT); - #ifdef ENABLE_M7 + #ifdef COOLANT_FLOOD_PIN + pinMode(COOLANT_FLOOD_PIN, OUTPUT); + #endif + + + #ifdef COOLANT_MIST_PIN pinMode(COOLANT_MIST_PIN, OUTPUT); #endif coolant_stop(); @@ -39,14 +43,18 @@ uint8_t coolant_get_state() { uint8_t cl_state = COOLANT_STATE_DISABLE; - #ifdef INVERT_COOLANT_FLOOD_PIN - if (! digitalRead(COOLANT_FLOOD_PIN)) { - #else - if (digitalRead(COOLANT_FLOOD_PIN)) { - #endif - cl_state |= COOLANT_STATE_FLOOD; - } - #ifdef ENABLE_M7 + #ifdef COOLANT_FLOOD_PIN + #ifdef INVERT_COOLANT_FLOOD_PIN + if (! digitalRead(COOLANT_FLOOD_PIN)) { + #else + if (digitalRead(COOLANT_FLOOD_PIN)) { + #endif + cl_state |= COOLANT_STATE_FLOOD; + } + #endif + + + #ifdef COOLANT_MIST_PIN #ifdef INVERT_COOLANT_MIST_PIN if (! digitalRead(COOLANT_MIST_PIN)) { #else @@ -65,12 +73,15 @@ uint8_t coolant_get_state() // an interrupt-level. No report flag set, but only called by routines that don't need it. void coolant_stop() { - #ifdef INVERT_COOLANT_FLOOD_PIN - digitalWrite(COOLANT_FLOOD_PIN, 1); - #else - digitalWrite(COOLANT_FLOOD_PIN, 0); - #endif - #ifdef ENABLE_M7 + #ifdef COOLANT_FLOOD_PIN + #ifdef INVERT_COOLANT_FLOOD_PIN + digitalWrite(COOLANT_FLOOD_PIN, 1); + #else + digitalWrite(COOLANT_FLOOD_PIN, 0); + #endif + #endif + + #ifdef COOLANT_MIST_PIN #ifdef INVERT_COOLANT_MIST_PIN digitalWrite(COOLANT_MIST_PIN, 1); #else @@ -93,7 +104,8 @@ void coolant_set_state(uint8_t mode) coolant_stop(); } else { - + + #ifdef COOLANT_FLOOD_PIN if (mode & COOLANT_FLOOD_ENABLE) { #ifdef INVERT_COOLANT_FLOOD_PIN digitalWrite(COOLANT_FLOOD_PIN, 0); @@ -101,8 +113,9 @@ void coolant_set_state(uint8_t mode) digitalWrite(COOLANT_FLOOD_PIN, 1); #endif } + #endif - #ifdef ENABLE_M7 + #ifdef COOLANT_MIST_PIN if (mode & COOLANT_MIST_ENABLE) { #ifdef INVERT_COOLANT_MIST_PIN digitalWrite(COOLANT_MIST_PIN, 0); diff --git a/Grbl_Esp32/cpu_map.h b/Grbl_Esp32/cpu_map.h index 17f8da11..ca729736 100644 --- a/Grbl_Esp32/cpu_map.h +++ b/Grbl_Esp32/cpu_map.h @@ -34,8 +34,6 @@ changed. They are just preserved right now to make it easy to stay in sync with AVR grbl - - */ // This is the CPU Map for the ESP32 CNC Controller R2 @@ -59,8 +57,11 @@ #define STEPPERS_DISABLE_PIN GPIO_NUM_13 - #define COOLANT_FLOOD_PIN GPIO_NUM_16 - #define COOLANT_MIST_PIN GPIO_NUM_19 + + // *** the flood coolant feature code is activated by defining this pins + // *** Comment it out to use the pin for other features + #define COOLANT_FLOOD_PIN GPIO_NUM_16 + //#define COOLANT_MIST_PIN GPIO_NUM_21 #define SPINDLE_PWM_PIN GPIO_NUM_17 #define SPINDLE_PWM_CHANNEL 0 @@ -70,6 +71,11 @@ #define SPINDLE_PWM_MAX_VALUE 255 // TODO ESP32 Calc from resolution #define SPINDLE_PWM_RANGE (SPINDLE_PWM_MAX_VALUE-SPINDLE_PWM_MIN_VALUE) + // if these spindle function pins are defined, they will be activated in the code + // comment them out to use the pins for other functions + //#define SPINDLE_ENABLE_PIN GPIO_NUM_16 + //#define SPINDLE_DIR_PIN GPIO_NUM_16 + #define X_LIMIT_BIT 0 #define Y_LIMIT_BIT 1 #define Z_LIMIT_BIT 2 diff --git a/Grbl_Esp32/gcode.cpp b/Grbl_Esp32/gcode.cpp index 97fc033e..22584f06 100644 --- a/Grbl_Esp32/gcode.cpp +++ b/Grbl_Esp32/gcode.cpp @@ -255,34 +255,38 @@ uint8_t gc_execute_line(char *line, uint8_t client) default: gc_block.modal.program_flow = int_value; // Program end and reset } break; - #ifndef USE_SPINDLE_DIR_AS_ENABLE_PIN - case 4: - #endif - case 3: case 5: + + case 3: case 4: case 5: word_bit = MODAL_GROUP_M7; switch(int_value) { - case 3: gc_block.modal.spindle = SPINDLE_ENABLE_CW; break; - #ifndef USE_SPINDLE_DIR_AS_ENABLE_PIN - case 4: gc_block.modal.spindle = SPINDLE_ENABLE_CCW; break; - #endif + case 3: + gc_block.modal.spindle = SPINDLE_ENABLE_CW; + break; + case 4: + #ifdef SPINDLE_DIR_PIN + gc_block.modal.spindle = SPINDLE_ENABLE_CCW; + #else + FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); + #endif + break; case 5: gc_block.modal.spindle = SPINDLE_DISABLE; break; } - break; - #ifdef ENABLE_M7 - case 7: case 8: case 9: - #else - case 8: case 9: - #endif - word_bit = MODAL_GROUP_M8; - switch(int_value) { - #ifdef ENABLE_M7 - case 7: gc_block.modal.coolant = COOLANT_MIST_ENABLE; break; - #endif - case 8: gc_block.modal.coolant = COOLANT_FLOOD_ENABLE; break; - case 9: gc_block.modal.coolant = COOLANT_DISABLE; break; - } - break; - default: FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); // [Unsupported M command] + break; + case 7: case 8: case 9: + word_bit = MODAL_GROUP_M8; + switch(int_value) { + #ifdef COOLANT_MIST_PIN + case 7: gc_block.modal.coolant = COOLANT_MIST_ENABLE; break; + #endif + #ifdef COOLANT_FLOOD_PIN + case 8: gc_block.modal.coolant = COOLANT_FLOOD_ENABLE; break; + #endif + case 9: gc_block.modal.coolant = COOLANT_DISABLE; break; + default: FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); // [Unsupported M command] + } + break; + default: + FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); // [Unsupported M command] } // Check for more than one command per modal group violations in the current block diff --git a/Grbl_Esp32/grbl.h b/Grbl_Esp32/grbl.h index 800fe47d..afdf0289 100644 --- a/Grbl_Esp32/grbl.h +++ b/Grbl_Esp32/grbl.h @@ -20,7 +20,7 @@ // Grbl versioning system #define GRBL_VERSION "1.1f" -#define GRBL_VERSION_BUILD "20180906" +#define GRBL_VERSION_BUILD "20180910" //#include #include diff --git a/Grbl_Esp32/protocol.cpp b/Grbl_Esp32/protocol.cpp index e356c66d..e561a437 100644 --- a/Grbl_Esp32/protocol.cpp +++ b/Grbl_Esp32/protocol.cpp @@ -511,19 +511,28 @@ void protocol_exec_rt_system() if (rt_exec & (EXEC_COOLANT_FLOOD_OVR_TOGGLE | EXEC_COOLANT_MIST_OVR_TOGGLE)) { if ((sys.state == STATE_IDLE) || (sys.state & (STATE_CYCLE | STATE_HOLD))) { uint8_t coolant_state = gc_state.modal.coolant; - #ifdef ENABLE_M7 - if (rt_exec & EXEC_COOLANT_MIST_OVR_TOGGLE) { - if (coolant_state & COOLANT_MIST_ENABLE) { bit_false(coolant_state,COOLANT_MIST_ENABLE); } - else { coolant_state |= COOLANT_MIST_ENABLE; } + #ifdef COOLANT_FLOOD_PIN + if (rt_exec & EXEC_COOLANT_FLOOD_OVR_TOGGLE) + { + if (coolant_state & COOLANT_FLOOD_ENABLE) { + bit_false(coolant_state,COOLANT_FLOOD_ENABLE); + } + else { + coolant_state |= COOLANT_FLOOD_ENABLE; + } } - if (rt_exec & EXEC_COOLANT_FLOOD_OVR_TOGGLE) { - if (coolant_state & COOLANT_FLOOD_ENABLE) { bit_false(coolant_state,COOLANT_FLOOD_ENABLE); } - else { coolant_state |= COOLANT_FLOOD_ENABLE; } + #endif + #ifdef COOLANT_MIST_PIN + if (rt_exec & EXEC_COOLANT_MIST_OVR_TOGGLE) { + if (coolant_state & COOLANT_MIST_ENABLE) { + bit_false(coolant_state,COOLANT_MIST_ENABLE); + } + else { + coolant_state |= COOLANT_MIST_ENABLE; + } } - #else - if (coolant_state & COOLANT_FLOOD_ENABLE) { bit_false(coolant_state,COOLANT_FLOOD_ENABLE); } - else { coolant_state |= COOLANT_FLOOD_ENABLE; } - #endif + #endif + coolant_set_state(coolant_state); // Report counter set in coolant_set_state(). gc_state.modal.coolant = coolant_state; } diff --git a/Grbl_Esp32/report.cpp b/Grbl_Esp32/report.cpp index 3255d75a..b76d39ed 100644 --- a/Grbl_Esp32/report.cpp +++ b/Grbl_Esp32/report.cpp @@ -403,16 +403,14 @@ void report_gcode_modes(uint8_t client) case SPINDLE_DISABLE : strcat(modes_rpt, " M5"); break; } - //report_util_gcode_modes_M(); - #ifdef ENABLE_M7 - if (gc_state.modal.coolant) { // Note: Multiple coolant states may be active at the same time. - if (gc_state.modal.coolant & PL_COND_FLAG_COOLANT_MIST) { strcat(modes_rpt, " M7"); } - if (gc_state.modal.coolant & PL_COND_FLAG_COOLANT_FLOOD) { strcat(modes_rpt, " M8"); } - } else { strcat(modes_rpt, " M9"); } - #else - if (gc_state.modal.coolant) { strcat(modes_rpt, " M8"); } - else { strcat(modes_rpt, " M9"); } - #endif + //report_util_gcode_modes_M(); // optional M7 and M8 should have been dealt with by here + if (gc_state.modal.coolant) { // Note: Multiple coolant states may be active at the same time. + if (gc_state.modal.coolant & PL_COND_FLAG_COOLANT_MIST) { strcat(modes_rpt, " M7"); } + if (gc_state.modal.coolant & PL_COND_FLAG_COOLANT_FLOOD) { strcat(modes_rpt, " M8"); } + } + else { + strcat(modes_rpt, " M9"); + } sprintf(temp, " T%d", gc_state.tool); strcat(modes_rpt, temp); @@ -459,8 +457,8 @@ void report_build_info(char *line, uint8_t client) #ifdef USE_LINE_NUMBERS strcat(build_info,"N"); #endif - #ifdef ENABLE_M7 - strcat(build_info,"M"); + #ifdef COOLANT_MIST_PIN + strcat(build_info,"M"); // TODO Need to deal with M8...it could be disabled #endif #ifdef COREXY strcat(build_info,"C"); @@ -703,7 +701,7 @@ void report_realtime_status(uint8_t client) #endif } if (cl_state & COOLANT_STATE_FLOOD) { strcat(status, "F"); } - #ifdef ENABLE_M7 + #ifdef COOLANT_MIST_PIN // TODO Deal with M8 - Flood if (cl_state & COOLANT_STATE_MIST) { strcat(status, "M"); } #endif } diff --git a/Grbl_Esp32/serial.cpp b/Grbl_Esp32/serial.cpp index 06b04157..e83b6488 100644 --- a/Grbl_Esp32/serial.cpp +++ b/Grbl_Esp32/serial.cpp @@ -141,8 +141,10 @@ void serialCheckTask(void *pvParameters) case CMD_SPINDLE_OVR_FINE_PLUS: system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_FINE_PLUS); break; case CMD_SPINDLE_OVR_FINE_MINUS: system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_FINE_MINUS); break; case CMD_SPINDLE_OVR_STOP: system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_STOP); break; + #ifdef COOLANT_FLOOD_PIN case CMD_COOLANT_FLOOD_OVR_TOGGLE: system_set_exec_accessory_override_flag(EXEC_COOLANT_FLOOD_OVR_TOGGLE); break; - #ifdef ENABLE_M7 + #endif + #ifdef COOLANT_MIST_PIN case CMD_COOLANT_MIST_OVR_TOGGLE: system_set_exec_accessory_override_flag(EXEC_COOLANT_MIST_OVR_TOGGLE); break; #endif } @@ -246,8 +248,10 @@ void serialCheck() case CMD_SPINDLE_OVR_FINE_PLUS: system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_FINE_PLUS); break; case CMD_SPINDLE_OVR_FINE_MINUS: system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_FINE_MINUS); break; case CMD_SPINDLE_OVR_STOP: system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_STOP); break; + #ifdef COOLANT_FLOOD_PIN case CMD_COOLANT_FLOOD_OVR_TOGGLE: system_set_exec_accessory_override_flag(EXEC_COOLANT_FLOOD_OVR_TOGGLE); break; - #ifdef ENABLE_M7 + #endif + #ifdef COOLANT_MIST_PIN case CMD_COOLANT_MIST_OVR_TOGGLE: system_set_exec_accessory_override_flag(EXEC_COOLANT_MIST_OVR_TOGGLE); break; #endif } @@ -274,7 +278,7 @@ void serial_reset_read_buffer(uint8_t client) { if (client == client_num || client == CLIENT_ALL) { - serial_rx_buffer_tail[client_num] = serial_rx_buffer_head[client_num]; + serial_rx_buffer_tail[client_num-1] = serial_rx_buffer_head[client_num-1]; } } } diff --git a/Grbl_Esp32/spindle_control.cpp b/Grbl_Esp32/spindle_control.cpp index b8e3afe0..0c1a32f2 100644 --- a/Grbl_Esp32/spindle_control.cpp +++ b/Grbl_Esp32/spindle_control.cpp @@ -3,7 +3,7 @@ Part of Grbl Copyright (c) 2014-2016 Sungeun K. Jeon for Gnea Research LLC - 2018 - Bart Dring This file was modifed for use on the ESP32 + 2018 - Bart Dring This file was modified for use on the ESP32 CPU. Do not use this with Grbl for atMega328P Grbl is free software: you can redistribute it and/or modify @@ -23,31 +23,55 @@ void spindle_init() { + // Use DIR and Enable if pins are defined + #ifdef SPINDLE_ENABLE_PIN + pinMode(SPINDLE_ENABLE_PIN, OUTPUT); + #endif + + #ifdef SPINDLE_DIR_PIN + pinMode(SPINDLE_DIR_PIN, OUTPUT); + #endif + // use the LED control feature to setup PWM https://esp-idf.readthedocs.io/en/v1.0/api/ledc.html ledcSetup(SPINDLE_PWM_CHANNEL, SPINDLE_PWM_BASE_FREQ, SPINDLE_PWM_BIT_PRECISION); // setup the channel ledcAttachPin(SPINDLE_PWM_PIN, SPINDLE_PWM_CHANNEL); // attach the PWM to the pin - - // Start with PWM off + + // Start with spindle off off spindle_stop(); } void spindle_stop() { - grbl_analogWrite(SPINDLE_PWM_CHANNEL, 0); + spindle_set_enable(false); + grbl_analogWrite(SPINDLE_PWM_CHANNEL, 0); } -uint8_t spindle_get_state() +uint8_t spindle_get_state() // returns SPINDLE_STATE_DISABLE, SPINDLE_STATE_CW or SPINDLE_STATE_CCW { // TODO Update this when direction and enable pin are added - if (ledcRead(SPINDLE_PWM_CHANNEL) == 0) // Check the PWM value + if (ledcRead(SPINDLE_PWM_CHANNEL) == 0) // Check the PWM value return(SPINDLE_STATE_DISABLE); else - return(SPINDLE_STATE_CW); // only CW is supported right now. + { + #ifdef SPINDLE_DIR_PIN + if (digitalRead(SPINDLE_DIR_PIN)) + return (SPINDLE_STATE_CW); + else + return(SPINDLE_STATE_CCW); + #else + return(SPINDLE_STATE_CW); + #endif + } } void spindle_set_speed(uint8_t pwm_value) -{ - grbl_analogWrite(SPINDLE_PWM_CHANNEL, pwm_value); +{ + #ifndef SPINDLE_ENABLE_OFF_WITH_ZERO_SPEED + spindle_set_enable(true); + #else + spindle_set_enable(pwm_value != 0); + #endif + grbl_analogWrite(SPINDLE_PWM_CHANNEL, pwm_value); } // Called by spindle_set_state() and step segment generator. Keep routine small and efficient. @@ -70,12 +94,22 @@ void spindle_set_state(uint8_t state, float rpm) } else { // TODO ESP32 Enable and direction control + #ifdef SPINDLE_DIR_PIN + if (state == SPINDLE_ENABLE_CW) { + digitalWrite(SPINDLE_DIR_PIN, 1); + } + else + { + digitalWrite(SPINDLE_DIR_PIN, 0); + } + #endif // NOTE: Assumes all calls to this function is when Grbl is not moving or must remain off. if (settings.flags & BITFLAG_LASER_MODE) { if (state == SPINDLE_ENABLE_CCW) { rpm = 0.0; } // TODO: May need to be rpm_min*(100/MAX_SPINDLE_SPEED_OVERRIDE); } + spindle_set_speed(spindle_compute_pwm_value(rpm)); } sys.report_ovr_counter = 0; // Set to report change immediately @@ -98,4 +132,14 @@ void grbl_analogWrite(uint8_t chan, uint32_t duty) } } +void spindle_set_enable(bool enable) +{ + #ifdef SPINDLE_ENABLE_PIN + #ifndef INVERT_SPINDLE_ENABLE_PIN + digitalWrite(SPINDLE_ENABLE_PIN, enable); // turn off (low) with zero speed + #else + digitalWrite(SPINDLE_ENABLE_PIN, !enable); // turn off (high) with zero speed + #endif + #endif +} diff --git a/Grbl_Esp32/spindle_control.h b/Grbl_Esp32/spindle_control.h index 1201a650..0349c3cf 100644 --- a/Grbl_Esp32/spindle_control.h +++ b/Grbl_Esp32/spindle_control.h @@ -29,7 +29,6 @@ #define SPINDLE_STATE_DISABLE 0 // Must be zero. #define SPINDLE_STATE_CW bit(0) #define SPINDLE_STATE_CCW bit(1) - void spindle_init(); void spindle_stop(); @@ -37,8 +36,8 @@ void spindle_set_speed(uint8_t pwm_value); uint8_t spindle_compute_pwm_value(float rpm); void spindle_set_state(uint8_t state, float rpm); - void spindle_sync(uint8_t state, float rpm); - - void grbl_analogWrite(uint8_t chan, uint32_t duty); + void spindle_sync(uint8_t state, float rpm); + void grbl_analogWrite(uint8_t chan, uint32_t duty); + void spindle_set_enable(bool enable); #endif diff --git a/README.md b/README.md index ea1f15a6..1b955af1 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,6 @@ Using SD Card ### Roadmap - Add Wifi support and a web page interface -- Add spindle enable and direction. ### Credits