From 9a7d05f29b731a7de609fd0e0adfdf67fa5f2238 Mon Sep 17 00:00:00 2001 From: bdring Date: Fri, 3 Apr 2020 12:40:54 -0500 Subject: [PATCH 01/32] A Work in progress - Messy code - Does not work yet. --- Grbl_Esp32/config.h | 4 +- Grbl_Esp32/machine.h | 2 +- Grbl_Esp32/protocol.cpp | 12 +-- Grbl_Esp32/spindle_control.cpp | 151 +++----------------------- Grbl_Esp32/spindle_control.h | 2 + Grbl_Esp32/stepper.cpp | 73 ++++++------- Grbl_Esp32/system.h | 2 +- Grbl_Esp32/tools/SpindleClass.cpp | 174 ++++++++++++++++++++++++++++++ Grbl_Esp32/tools/SpindleClass.h | 61 +++++++++++ 9 files changed, 293 insertions(+), 188 deletions(-) create mode 100644 Grbl_Esp32/tools/SpindleClass.cpp create mode 100644 Grbl_Esp32/tools/SpindleClass.h diff --git a/Grbl_Esp32/config.h b/Grbl_Esp32/config.h index 0cb8d532..b2cba024 100644 --- a/Grbl_Esp32/config.h +++ b/Grbl_Esp32/config.h @@ -115,11 +115,11 @@ Some features should not be changed. See notes below. //#define CONNECT_TO_SSID "your SSID" //#define SSID_PASSWORD "your SSID password" //CONFIGURE_EYECATCH_BEGIN (DO NOT MODIFY THIS LINE) -#define ENABLE_BLUETOOTH // enable bluetooth +//#define ENABLE_BLUETOOTH // enable bluetooth #define ENABLE_SD_CARD // enable use of SD Card to run jobs -#define ENABLE_WIFI //enable wifi +//#define ENABLE_WIFI //enable wifi #define ENABLE_HTTP //enable HTTP and all related services #define ENABLE_OTA //enable OTA diff --git a/Grbl_Esp32/machine.h b/Grbl_Esp32/machine.h index d57814c4..1d49672e 100644 --- a/Grbl_Esp32/machine.h +++ b/Grbl_Esp32/machine.h @@ -8,7 +8,7 @@ // !!! For initial testing, start with test_drive.h which disables // all I/O pins -#include "Machines/test_drive.h" +#include "Machines/3axis_v4.h" // !!! For actual use, change the line above to select a board // from Machines/, for example: diff --git a/Grbl_Esp32/protocol.cpp b/Grbl_Esp32/protocol.cpp index e4a5b8e3..5be2fa89 100644 --- a/Grbl_Esp32/protocol.cpp +++ b/Grbl_Esp32/protocol.cpp @@ -464,7 +464,7 @@ void protocol_exec_rt_system() { last_s_override = MIN(last_s_override, MAX_SPINDLE_SPEED_OVERRIDE); last_s_override = MAX(last_s_override, MIN_SPINDLE_SPEED_OVERRIDE); if (last_s_override != sys.spindle_speed_ovr) { - bit_true(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_PWM); + bit_true(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_RPM); sys.spindle_speed_ovr = last_s_override; sys.report_ovr_counter = 0; // Set to report change immediately } @@ -657,7 +657,7 @@ static void protocol_exec_rt_suspend() { if (bit_isfalse(sys.suspend, SUSPEND_RESTART_RETRACT)) { if (bit_istrue(settings.flags, BITFLAG_LASER_MODE)) { // When in laser mode, ignore spindle spin-up delay. Set to turn on laser when cycle starts. - bit_true(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_PWM); + bit_true(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_RPM); } else { spindle_set_state((restore_condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)), restore_spindle_speed); delay_sec(SAFETY_DOOR_SPINDLE_DELAY, DELAY_MODE_SYS_SUSPEND); @@ -716,7 +716,7 @@ static void protocol_exec_rt_suspend() { report_feedback_message(MESSAGE_SPINDLE_RESTORE); if (bit_istrue(settings.flags, BITFLAG_LASER_MODE)) { // When in laser mode, ignore spindle spin-up delay. Set to turn on laser when cycle starts. - bit_true(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_PWM); + bit_true(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_RPM); } else spindle_set_state((restore_condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)), restore_spindle_speed); } @@ -727,10 +727,10 @@ static void protocol_exec_rt_suspend() { } } else { // Handles spindle state during hold. NOTE: Spindle speed overrides may be altered during hold state. - // NOTE: STEP_CONTROL_UPDATE_SPINDLE_PWM is automatically reset upon resume in step generator. - if (bit_istrue(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_PWM)) { + // NOTE: STEP_CONTROL_UPDATE_SPINDLE_RPM is automatically reset upon resume in step generator. + if (bit_istrue(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_RPM)) { spindle_set_state((restore_condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)), restore_spindle_speed); - bit_false(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_PWM); + bit_false(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_RPM); } } } diff --git a/Grbl_Esp32/spindle_control.cpp b/Grbl_Esp32/spindle_control.cpp index a7f0f7b2..79f37e77 100644 --- a/Grbl_Esp32/spindle_control.cpp +++ b/Grbl_Esp32/spindle_control.cpp @@ -19,9 +19,15 @@ */ #include "grbl.h" +#include "tools/SpindleClass.h" +#include "tools/SpindleClass.cpp" int8_t spindle_pwm_chan_num; +// define a spindle type +//RelaySpindle my_spindle; +Laser my_spindle; + #ifdef SPINDLE_PWM_PIN static float pwm_gradient; // Precalulated value to speed up rpm to PWM conversions. uint32_t spindle_pwm_period; // how many counts in 1 period @@ -31,142 +37,30 @@ int8_t spindle_pwm_chan_num; #endif void spindle_init() { -#ifdef SPINDLE_PWM_PIN -#ifdef INVERT_SPINDLE_PWM - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "INVERT_SPINDLE_PWM"); -#endif -#ifdef INVERT_SPINDLE_ENABLE_PIN - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "INVERT_SPINDLE_ENABLE_PIN"); -#endif - // determine how many PWM counts are in eqach PWM cycle - spindle_pwm_period = ((1 << SPINDLE_PWM_BIT_PRECISION) - 1); - if (settings.spindle_pwm_min_value > settings.spindle_pwm_min_value) - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Warning spindle min pwm is greater than max. Check $35 and $36"); - // pre-caculate some PWM count values - spindle_pwm_off_value = (spindle_pwm_period * settings.spindle_pwm_off_value / 100.0); - spindle_pwm_min_value = (spindle_pwm_period * settings.spindle_pwm_min_value / 100.0); - spindle_pwm_max_value = (spindle_pwm_period * settings.spindle_pwm_max_value / 100.0); - // The pwm_gradient is the pwm duty cycle units per rpm - pwm_gradient = (spindle_pwm_max_value - spindle_pwm_min_value) / (settings.rpm_max - settings.rpm_min); - // 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://docs.espressif.com/projects/esp-idf/en/latest/api-reference/peripherals/ledc.html - spindle_pwm_chan_num = sys_get_next_PWM_chan_num(); - ledcSetup(spindle_pwm_chan_num, (double)settings.spindle_pwm_freq, SPINDLE_PWM_BIT_PRECISION); // setup the channel - ledcAttachPin(SPINDLE_PWM_PIN, spindle_pwm_chan_num); // attach the PWM to the pin - // Start with spindle off off - spindle_stop(); -#endif + my_spindle.init(); + my_spindle.config_message(); } void spindle_stop() { - spindle_set_enable(false); -#ifdef SPINDLE_PWM_PIN -#ifndef INVERT_SPINDLE_PWM - grbl_analogWrite(spindle_pwm_chan_num, spindle_pwm_off_value); -#else - grbl_analogWrite(spindle_pwm_chan_num, (1 << SPINDLE_PWM_BIT_PRECISION)); // TO DO...wrong for min_pwm -#endif -#endif + my_spindle.stop(); } -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 -#ifndef SPINDLE_PWM_PIN - return (SPINDLE_STATE_DISABLE); -#else - if (ledcRead(spindle_pwm_chan_num) == 0) // Check the PWM value - return (SPINDLE_STATE_DISABLE); - else { -#ifdef SPINDLE_DIR_PIN - if (digitalRead(SPINDLE_DIR_PIN)) - return (SPINDLE_STATE_CW); - else - return (SPINDLE_STATE_CCW); -#else - return (SPINDLE_STATE_CW); -#endif - } -#endif +uint8_t spindle_get_state() { + return my_spindle.get_state(); } void spindle_set_speed(uint32_t pwm_value) { -#ifndef SPINDLE_PWM_PIN - //grbl_sendf(CLIENT_SERIAL, "[MSG: set speed...no pin defined]\r\n"); - return; -#else -#ifndef SPINDLE_ENABLE_OFF_WITH_ZERO_SPEED - spindle_set_enable(true); -#else - spindle_set_enable(pwm_value != 0); -#endif -#ifndef INVERT_SPINDLE_PWM - grbl_analogWrite(spindle_pwm_chan_num, pwm_value); -#else - grbl_analogWrite(spindle_pwm_chan_num, (1 << SPINDLE_PWM_BIT_PRECISION) - pwm_value); -#endif -#endif + my_spindle.set_pwm(pwm_value); } uint32_t spindle_compute_pwm_value(float rpm) { -#ifdef SPINDLE_PWM_PIN - uint32_t pwm_value; - rpm *= (0.010 * sys.spindle_speed_ovr); // Scale by spindle speed override value. - // Calculate PWM register value based on rpm max/min settings and programmed rpm. - if ((settings.rpm_min >= settings.rpm_max) || (rpm >= settings.rpm_max)) { - // No PWM range possible. Set simple on/off spindle control pin state. - sys.spindle_speed = settings.rpm_max; - pwm_value = spindle_pwm_max_value; - } else if (rpm <= settings.rpm_min) { - if (rpm == 0.0) { // S0 disables spindle - sys.spindle_speed = 0.0; - pwm_value = spindle_pwm_off_value; - } else { // Set minimum PWM output - sys.spindle_speed = settings.rpm_min; - pwm_value = spindle_pwm_min_value; - } - } else { - // Compute intermediate PWM value with linear spindle speed model. - // NOTE: A nonlinear model could be installed here, if required, but keep it VERY light-weight. - sys.spindle_speed = rpm; -#ifdef ENABLE_PIECEWISE_LINEAR_SPINDLE - pwm_value = piecewise_linear_fit(rpm); -#else - pwm_value = floor((rpm - settings.rpm_min) * pwm_gradient) + spindle_pwm_min_value; -#endif - } - return (pwm_value); -#else - return (0); // no SPINDLE_PWM_PIN -#endif + return 0; } // Called by spindle_set_state() and step segment generator. Keep routine small and efficient. void spindle_set_state(uint8_t state, float rpm) { -#ifdef SPINDLE_PWM_PIN - if (sys.abort) return; // Block during abort. - if (state == SPINDLE_DISABLE) { // Halt or set spindle direction and rpm. - sys.spindle_speed = 0.0; - spindle_stop(); - } else { - // TODO ESP32 Enable and direction control -#ifdef SPINDLE_DIR_PIN - digitalWrite(SPINDLE_DIR_PIN, state == SPINDLE_ENABLE_CW); -#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 -#endif + my_spindle.set_state(state, rpm); } @@ -179,24 +73,11 @@ void spindle_sync(uint8_t state, float rpm) { void grbl_analogWrite(uint8_t chan, uint32_t duty) { - // Remember the old duty cycle in memory instead of reading - // it from the I/O peripheral because I/O reads are quite - // a bit slower than memory reads. - static uint32_t old_duty = 0; - if (old_duty != duty) { // reduce unnecessary calls to ledcWrite() - old_duty = duty; - ledcWrite(chan, 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 + } uint32_t piecewise_linear_fit(float rpm) { diff --git a/Grbl_Esp32/spindle_control.h b/Grbl_Esp32/spindle_control.h index 1a655045..3e52d412 100644 --- a/Grbl_Esp32/spindle_control.h +++ b/Grbl_Esp32/spindle_control.h @@ -22,6 +22,7 @@ #define spindle_control_h #include "grbl.h" +#include "tools/SpindleClass.h" #define SPINDLE_NO_SYNC false @@ -32,6 +33,7 @@ #define SPINDLE_STATE_CCW bit(1) extern uint32_t spindle_pwm_off_value; +extern Laser my_spindle; void spindle_init(); void spindle_stop(); diff --git a/Grbl_Esp32/stepper.cpp b/Grbl_Esp32/stepper.cpp index 3c5db1ed..ad02dd50 100644 --- a/Grbl_Esp32/stepper.cpp +++ b/Grbl_Esp32/stepper.cpp @@ -37,9 +37,7 @@ typedef struct { uint32_t steps[N_AXIS]; uint32_t step_event_count; uint8_t direction_bits; -#ifdef VARIABLE_SPINDLE uint8_t is_pwm_rate_adjusted; // Tracks motions that require constant laser power/rate -#endif } st_block_t; static st_block_t st_block_buffer[SEGMENT_BUFFER_SIZE - 1]; @@ -56,9 +54,7 @@ typedef struct { #else uint8_t prescaler; // Without AMASS, a prescaler is required to adjust for slow timing. #endif -#ifdef VARIABLE_SPINDLE - uint16_t spindle_pwm; -#endif + uint16_t spindle_rpm; // TODO get rid of this. } segment_t; static segment_t segment_buffer[SEGMENT_BUFFER_SIZE]; @@ -145,10 +141,11 @@ typedef struct { float accelerate_until; // Acceleration ramp end measured from end of block (mm) float decelerate_after; // Deceleration ramp start measured from end of block (mm) -#ifdef VARIABLE_SPINDLE + float inv_rate; // Used by PWM laser mode to speed up segment calculations. - uint16_t current_spindle_pwm; -#endif + uint16_t current_spindle_pwm; // todo remove + float current_spindle_rpm; + } st_prep_t; static st_prep_t prep; @@ -283,20 +280,20 @@ void IRAM_ATTR onStepperDriverTimer(void* para) { // ISR It is time to take a st st.steps[C_AXIS] = st.exec_block->steps[C_AXIS] >> st.exec_segment->amass_level; #endif #endif -#ifdef VARIABLE_SPINDLE + // Set real-time spindle output as segment is loaded, just prior to the first step. - spindle_set_speed(st.exec_segment->spindle_pwm); -#endif + spindle_set_speed(st.exec_segment->spindle_rpm); + } else { // Segment buffer empty. Shutdown. st_go_idle(); -#if ( (defined VARIABLE_SPINDLE) && (defined SPINDLE_PWM_PIN) ) + if (!(sys.state & STATE_JOG)) { // added to prevent ... jog after probing crash // Ensure pwm is set properly upon completion of rate-controlled motion. if (st.exec_block->is_pwm_rate_adjusted) spindle_set_speed(spindle_pwm_off_value); } -#endif + system_set_exec_state_flag(EXEC_CYCLE_STOP); // Flag main program for cycle end return; // Nothing to do but exit. } @@ -677,37 +674,37 @@ void set_direction_pins_on(uint8_t onMask) { #ifdef X_DIRECTION_PIN digitalWrite(X_DIRECTION_PIN, (onMask & (1 << X_AXIS))); #endif -#ifdef X2_DIRECTION_PIN // optional ganged axis +#ifdef X2_DIRECTION_PIN // optional ganged axis digitalWrite(X2_DIRECTION_PIN, (onMask & (1 << X_AXIS))); #endif #ifdef Y_DIRECTION_PIN digitalWrite(Y_DIRECTION_PIN, (onMask & (1 << Y_AXIS))); #endif -#ifdef Y2_DIRECTION_PIN // optional ganged axis +#ifdef Y2_DIRECTION_PIN // optional ganged axis digitalWrite(Y2_DIRECTION_PIN, (onMask & (1 << Y_AXIS))); #endif #ifdef Z_DIRECTION_PIN digitalWrite(Z_DIRECTION_PIN, (onMask & (1 << Z_AXIS))); #endif -#ifdef Z2_DIRECTION_PIN // optional ganged axis +#ifdef Z2_DIRECTION_PIN // optional ganged axis digitalWrite(Z2_DIRECTION_PIN, (onMask & (1 << Z_AXIS))); #endif #ifdef A_DIRECTION_PIN digitalWrite(A_DIRECTION_PIN, (onMask & (1 << A_AXIS))); #endif -#ifdef A2_DIRECTION_PIN // optional ganged axis +#ifdef A2_DIRECTION_PIN // optional ganged axis digitalWrite(A2_DIRECTION_PIN, (onMask & (1 << A_AXIS))); #endif #ifdef B_DIRECTION_PIN digitalWrite(B_DIRECTION_PIN, (onMask & (1 << B_AXIS))); #endif -#ifdef B2_DIRECTION_PIN // optional ganged axis +#ifdef B2_DIRECTION_PIN // optional ganged axis digitalWrite(B2_DIRECTION_PIN, (onMask & (1 << B_AXIS))); #endif #ifdef C_DIRECTION_PIN digitalWrite(C_DIRECTION_PIN, (onMask & (1 << C_AXIS))); #endif -#ifdef C2_DIRECTION_PIN // optional ganged axis +#ifdef C2_DIRECTION_PIN // optional ganged axis digitalWrite(C2_DIRECTION_PIN, (onMask & (1 << C_AXIS))); #endif } @@ -986,18 +983,9 @@ void st_prep_buffer() { prep.recalculate_flag &= ~(PREP_FLAG_DECEL_OVERRIDE); } else prep.current_speed = sqrt(pl_block->entry_speed_sqr); -#ifdef VARIABLE_SPINDLE - // Setup laser mode variables. PWM rate adjusted motions will always complete a motion with the - // spindle off. - st_prep_block->is_pwm_rate_adjusted = false; - if (settings.flags & BITFLAG_LASER_MODE) { - if (pl_block->condition & PL_COND_FLAG_SPINDLE_CCW) { - // Pre-compute inverse programmed rate to speed up PWM updating per step segment. - prep.inv_rate = 1.0 / pl_block->programmed_rate; - st_prep_block->is_pwm_rate_adjusted = true; - } - } -#endif + + st_prep_block->is_pwm_rate_adjusted = my_spindle.isRateAdjusted(); + } /* --------------------------------------------------------------------------------- Compute the velocity profile of a new planner block based on its entry and exit @@ -1083,9 +1071,9 @@ void st_prep_buffer() { prep.maximum_speed = prep.exit_speed; } } -#ifdef VARIABLE_SPINDLE - bit_true(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_PWM); // Force update whenever updating block. -#endif + + bit_true(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_RPM); // Force update whenever updating block. + } // Initialize new segment segment_t* prep_segment = &segment_buffer[segment_buffer_head]; @@ -1189,11 +1177,11 @@ void st_prep_buffer() { } } } while (mm_remaining > prep.mm_complete); // **Complete** Exit loop. Profile complete. -#ifdef VARIABLE_SPINDLE + /* ----------------------------------------------------------------------------------- Compute spindle speed PWM output for step segment */ - if (st_prep_block->is_pwm_rate_adjusted || (sys.step_control & STEP_CONTROL_UPDATE_SPINDLE_PWM)) { + if (st_prep_block->is_pwm_rate_adjusted || (sys.step_control & STEP_CONTROL_UPDATE_SPINDLE_RPM)) { if (pl_block->condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)) { float rpm = pl_block->spindle_speed; // NOTE: Feed and rapid overrides are independent of PWM value and do not alter laser power/rate. @@ -1201,17 +1189,16 @@ void st_prep_buffer() { rpm *= (prep.current_speed * prep.inv_rate); // If current_speed is zero, then may need to be rpm_min*(100/MAX_SPINDLE_SPEED_OVERRIDE) // but this would be instantaneous only and during a motion. May not matter at all. - prep.current_spindle_pwm = spindle_compute_pwm_value(rpm); + prep.current_spindle_rpm = my_spindle.set_rpm(rpm); } else { sys.spindle_speed = 0.0; -#if ( (defined VARIABLE_SPINDLE) && (defined SPINDLE_PWM_PIN) ) - prep.current_spindle_pwm = spindle_pwm_off_value ; -#endif + prep.current_spindle_rpm = 0.0; + } - bit_false(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_PWM); + bit_false(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_RPM); } - prep_segment->spindle_pwm = prep.current_spindle_pwm; // Reload segment PWM value -#endif + prep_segment->spindle_rpm = prep.current_spindle_rpm; // Reload segment PWM value + /* ----------------------------------------------------------------------------------- Compute segment step rate, steps to execute, and apply necessary rate corrections. NOTE: Steps are computed by direct scalar conversion of the millimeter distance diff --git a/Grbl_Esp32/system.h b/Grbl_Esp32/system.h index c20b50c1..f2fc85c9 100644 --- a/Grbl_Esp32/system.h +++ b/Grbl_Esp32/system.h @@ -125,7 +125,7 @@ extern system_t sys; #define STEP_CONTROL_END_MOTION bit(0) #define STEP_CONTROL_EXECUTE_HOLD bit(1) #define STEP_CONTROL_EXECUTE_SYS_MOTION bit(2) -#define STEP_CONTROL_UPDATE_SPINDLE_PWM bit(3) +#define STEP_CONTROL_UPDATE_SPINDLE_RPM bit(3) // Define control pin index for Grbl internal use. Pin maps may change, but these values don't. //#ifdef ENABLE_SAFETY_DOOR_INPUT_PIN diff --git a/Grbl_Esp32/tools/SpindleClass.cpp b/Grbl_Esp32/tools/SpindleClass.cpp new file mode 100644 index 00000000..9c0162b0 --- /dev/null +++ b/Grbl_Esp32/tools/SpindleClass.cpp @@ -0,0 +1,174 @@ +#include "grbl.h" +#include "SpindleClass.h" + +bool Spindle::isRateAdjusted() { + return false; // default for basic spindles is false +} + +void PWMSpindle::init() { + _pwm_period = ((1 << SPINDLE_PWM_BIT_PRECISION) - 1); + if (settings.spindle_pwm_min_value > settings.spindle_pwm_min_value) + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Warning spindle min pwm is greater than max. Check $35 and $36"); + // pre-caculate some PWM count values + _pwm_off_value = (_pwm_period * settings.spindle_pwm_off_value / 100.0); + _pwm_min_value = (_pwm_period * settings.spindle_pwm_min_value / 100.0); + _pwm_max_value = (_pwm_period * settings.spindle_pwm_max_value / 100.0); + // The pwm_gradient is the pwm duty cycle units per rpm + _pwm_gradient = (_pwm_max_value - _pwm_min_value) / (settings.rpm_max - settings.rpm_min); + + + _spindle_pwm_chan_num = sys_get_next_PWM_chan_num(); + ledcSetup(_spindle_pwm_chan_num, (double)settings.spindle_pwm_freq, SPINDLE_PWM_BIT_PRECISION); // setup the channel + ledcAttachPin(SPINDLE_PWM_PIN, _spindle_pwm_chan_num); // attach the PWM to the pin + +#ifdef SPINDLE_ENABLE_PIN + pinMode(SPINDLE_ENABLE_PIN, OUTPUT); +#endif +#ifdef SPINDLE_DIR_PIN + pinMode(SPINDLE_DIR_PIN, OUTPUT); +#endif +} + +float PWMSpindle::set_rpm(float rpm) { + uint32_t pwm_value; + + // apply overrides and limits + rpm *= (0.010 * sys.spindle_speed_ovr); // Scale by spindle speed override value (percent) + + // Calculate PWM register value based on rpm max/min settings and programmed rpm. + if ((settings.rpm_min >= settings.rpm_max) || (rpm >= settings.rpm_max)) { + // No PWM range possible. Set simple on/off spindle control pin state. + sys.spindle_speed = settings.rpm_max; + pwm_value = _pwm_max_value; + } else if (rpm <= settings.rpm_min) { + if (rpm == 0.0) { // S0 disables spindle + sys.spindle_speed = 0.0; + pwm_value = _pwm_off_value; + } else { // Set minimum PWM output + sys.spindle_speed = settings.rpm_min; + pwm_value = _pwm_min_value; + } + } else { + // Compute intermediate PWM value with linear spindle speed model. + // NOTE: A nonlinear model could be installed here, if required, but keep it VERY light-weight. + sys.spindle_speed = rpm; +#ifdef ENABLE_PIECEWISE_LINEAR_SPINDLE + pwm_value = piecewise_linear_fit(rpm); +#else + pwm_value = floor((rpm - settings.rpm_min) * _pwm_gradient) + _pwm_min_value; +#endif + } + + set_pwm(pwm_value); + return rpm; +} + +void PWMSpindle::set_state(uint8_t state, float rpm) { + + if (sys.abort) + return; // Block during abort. + + if (state == SPINDLE_DISABLE) { // Halt or set spindle direction and rpm. + sys.spindle_speed = 0.0; + spindle_stop(); + } else { + set_spindle_dir_pin(state == SPINDLE_ENABLE_CW); + set_rpm(rpm); + } + sys.report_ovr_counter = 0; // Set to report change immediately +} + +uint8_t PWMSpindle::get_state() { + + + if (_current_pwm_duty == 0) // Check the PWM value + return (SPINDLE_STATE_DISABLE); + else { +#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 PWMSpindle::stop() { + // inverts are delt with in methods + set_enable_pin(false); + set_pwm(0); +} + +// prints the startup message of the spindle config +void PWMSpindle :: config_message() { + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "PWM spindle on GPIO %d, freq %.2fHz, Res %d bits", SPINDLE_PWM_PIN, settings.spindle_pwm_freq, SPINDLE_PWM_BIT_PRECISION); +} + + +void PWMSpindle::set_pwm(uint32_t duty) { + // to prevent excessive calls to ledcWrite, make sure duty hass changed + if (duty == _current_pwm_duty) + return; + + _current_pwm_duty = duty; + +#ifdef INVERT_SPINDLE_PWM + duty = (1 << SPINDLE_PWM_BIT_PRECISION) - duty; +#endif + + ledcWrite(_spindle_pwm_chan_num, duty); +} + +void PWMSpindle::set_enable_pin(bool enable) { +#ifdef SPINDLE_ENABLE_PIN +#ifndef INVERT_SPINDLE_ENABLE_PIN + digitalWrite(SPINDLE_ENABLE_PIN, enable); +#else + digitalWrite(SPINDLE_ENABLE_PIN, !enable); +#endif +#endif +} + +void PWMSpindle::set_spindle_dir_pin(bool Clockwise) { +#ifdef SPINDLE_DIR_PIN + digitalWrite(SPINDLE_DIR_PIN, state == SPINDLE_ENABLE_CW); +#endif +} + +// ========================= RelaySpindle ================================== +/* + This is the same as a PWM spindle, but is a digital rather than PWM output +*/ + +void RelaySpindle::init() { + pinMode(SPINDLE_PWM_PIN, OUTPUT); +#ifdef SPINDLE_ENABLE_PIN + pinMode(SPINDLE_ENABLE_PIN, OUTPUT); +#endif +#ifdef SPINDLE_DIR_PIN + pinMode(SPINDLE_DIR_PIN, OUTPUT); +#endif +} + +// prints the startup message of the spindle config +void RelaySpindle :: config_message() { + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Relay spindle on GPIO %d", SPINDLE_PWM_PIN); +} + +void RelaySpindle::set_pwm(uint32_t duty) { +#ifdef INVERT_SPINDLE_PWM + duty = (duty == 0); // flip duty +#endif + digitalWrite(SPINDLE_PWM_PIN, duty > 0); // anything greater +} + + +// ====================== Laser ============================= + + +bool Laser :: isRateAdjusted() { + // must be in $32=1 (laser mode) and M4 (CCW rotation) + return ( settings.flags & BITFLAG_LASER_MODE ); +} diff --git a/Grbl_Esp32/tools/SpindleClass.h b/Grbl_Esp32/tools/SpindleClass.h new file mode 100644 index 00000000..b22082ba --- /dev/null +++ b/Grbl_Esp32/tools/SpindleClass.h @@ -0,0 +1,61 @@ +#include "grbl.h" + +#ifndef SPINDLE_CLASS_H +#define SPINDLE_CLASS_H + +class Spindle { + public: + virtual void init(); + virtual float set_rpm(float rpm); + virtual void set_pwm(uint32_t duty); + virtual void set_state(uint8_t state, float rpm); + virtual uint8_t get_state(); + virtual void stop(); + virtual void config_message(); + virtual bool isRateAdjusted(); + + //bool _isRateAdjused = false; + +}; + +class PWMSpindle : public Spindle { + public: + void init(); + float set_rpm(float rpm); + void set_state(uint8_t state, float rpm); + uint8_t get_state(); + void stop(); + void config_message(); + virtual void set_pwm(uint32_t duty); + + private: + int8_t _spindle_pwm_chan_num; + int32_t _current_pwm_duty; + + float _pwm_gradient; // Precalulated value to speed up rpm to PWM conversions. + uint32_t _pwm_period; // how many counts in 1 period + uint32_t _pwm_off_value; + uint32_t _pwm_min_value; + uint32_t _pwm_max_value; + + + void set_enable_pin(bool enable_pin); + void set_spindle_dir_pin(bool Clockwise); +}; + +class RelaySpindle : public PWMSpindle { + public: + void init(); + void config_message(); + void set_pwm(uint32_t duty); +private: + +}; + +class Laser : public PWMSpindle { + public: + bool isRateAdjusted(); +}; + + +#endif \ No newline at end of file From 6ed09a77bc91b565ad5ca07c9f3eb53ae6bc23e2 Mon Sep 17 00:00:00 2001 From: bdring Date: Fri, 3 Apr 2020 15:37:29 -0500 Subject: [PATCH 02/32] Minimally functional Starting to work. Need to develop some tests --- Grbl_Esp32/config.h | 2 +- Grbl_Esp32/spindle_control.cpp | 51 ++----------------------------- Grbl_Esp32/spindle_control.h | 2 +- Grbl_Esp32/stepper.cpp | 9 ++++-- Grbl_Esp32/tools/SpindleClass.cpp | 10 +++++- 5 files changed, 19 insertions(+), 55 deletions(-) diff --git a/Grbl_Esp32/config.h b/Grbl_Esp32/config.h index b2cba024..881f0e9a 100644 --- a/Grbl_Esp32/config.h +++ b/Grbl_Esp32/config.h @@ -205,7 +205,7 @@ Some features should not be changed. See notes below. #define CMD_RAPID_OVR_LOW 0x97 // #define CMD_RAPID_OVR_EXTRA_LOW 0x98 // *NOT SUPPORTED* #define CMD_SPINDLE_OVR_RESET 0x99 // Restores spindle override value to 100%. -#define CMD_SPINDLE_OVR_COARSE_PLUS 0x9A +#define CMD_SPINDLE_OVR_COARSE_PLUS 0x9A // 154 #define CMD_SPINDLE_OVR_COARSE_MINUS 0x9B #define CMD_SPINDLE_OVR_FINE_PLUS 0x9C #define CMD_SPINDLE_OVR_FINE_MINUS 0x9D diff --git a/Grbl_Esp32/spindle_control.cpp b/Grbl_Esp32/spindle_control.cpp index 79f37e77..5eb22d00 100644 --- a/Grbl_Esp32/spindle_control.cpp +++ b/Grbl_Esp32/spindle_control.cpp @@ -26,19 +26,12 @@ int8_t spindle_pwm_chan_num; // define a spindle type //RelaySpindle my_spindle; -Laser my_spindle; - -#ifdef SPINDLE_PWM_PIN - static float pwm_gradient; // Precalulated value to speed up rpm to PWM conversions. - uint32_t spindle_pwm_period; // how many counts in 1 period - uint32_t spindle_pwm_off_value; - uint32_t spindle_pwm_min_value; - uint32_t spindle_pwm_max_value; -#endif +PWMSpindle my_spindle; void spindle_init() { my_spindle.init(); my_spindle.config_message(); + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Spindle is rate adjustable %d", my_spindle.isRateAdjusted()); } void spindle_stop() { @@ -49,13 +42,6 @@ uint8_t spindle_get_state() { return my_spindle.get_state(); } -void spindle_set_speed(uint32_t pwm_value) { - my_spindle.set_pwm(pwm_value); -} - -uint32_t spindle_compute_pwm_value(float rpm) { - return 0; -} // Called by spindle_set_state() and step segment generator. Keep routine small and efficient. @@ -72,36 +58,3 @@ void spindle_sync(uint8_t state, float rpm) { } -void grbl_analogWrite(uint8_t chan, uint32_t duty) { - -} - -void spindle_set_enable(bool enable) { - -} - -uint32_t piecewise_linear_fit(float rpm) { - uint32_t pwm_value; -#if (N_PIECES > 3) - if (rpm > RPM_POINT34) - pwm_value = floor(RPM_LINE_A4 * rpm - RPM_LINE_B4); - else -#endif -#if (N_PIECES > 2) - if (rpm > RPM_POINT23) - pwm_value = floor(RPM_LINE_A3 * rpm - RPM_LINE_B3); - else -#endif -#if (N_PIECES > 1) - if (rpm > RPM_POINT12) - pwm_value = floor(RPM_LINE_A2 * rpm - RPM_LINE_B2); - else -#endif - { - pwm_value = floor(RPM_LINE_A1 * rpm - RPM_LINE_B1); - } - return pwm_value; -} - - - diff --git a/Grbl_Esp32/spindle_control.h b/Grbl_Esp32/spindle_control.h index 3e52d412..1a8b8d57 100644 --- a/Grbl_Esp32/spindle_control.h +++ b/Grbl_Esp32/spindle_control.h @@ -33,7 +33,7 @@ #define SPINDLE_STATE_CCW bit(1) extern uint32_t spindle_pwm_off_value; -extern Laser my_spindle; +extern PWMSpindle my_spindle; void spindle_init(); void spindle_stop(); diff --git a/Grbl_Esp32/stepper.cpp b/Grbl_Esp32/stepper.cpp index ad02dd50..6a20f6ce 100644 --- a/Grbl_Esp32/stepper.cpp +++ b/Grbl_Esp32/stepper.cpp @@ -282,7 +282,8 @@ void IRAM_ATTR onStepperDriverTimer(void* para) { // ISR It is time to take a st #endif // Set real-time spindle output as segment is loaded, just prior to the first step. - spindle_set_speed(st.exec_segment->spindle_rpm); + //spindle_set_speed(st.exec_segment->spindle_rpm); + my_spindle.set_rpm(st.exec_segment->spindle_rpm); } else { // Segment buffer empty. Shutdown. @@ -290,8 +291,10 @@ void IRAM_ATTR onStepperDriverTimer(void* para) { // ISR It is time to take a st if (!(sys.state & STATE_JOG)) { // added to prevent ... jog after probing crash // Ensure pwm is set properly upon completion of rate-controlled motion. - if (st.exec_block->is_pwm_rate_adjusted) - spindle_set_speed(spindle_pwm_off_value); + if (st.exec_block->is_pwm_rate_adjusted) { + //spindle_set_speed(spindle_pwm_off_value); + my_spindle.set_rpm(0.0); + } } system_set_exec_state_flag(EXEC_CYCLE_STOP); // Flag main program for cycle end diff --git a/Grbl_Esp32/tools/SpindleClass.cpp b/Grbl_Esp32/tools/SpindleClass.cpp index 9c0162b0..ac2ca73b 100644 --- a/Grbl_Esp32/tools/SpindleClass.cpp +++ b/Grbl_Esp32/tools/SpindleClass.cpp @@ -1,3 +1,9 @@ +/* + + +Testing + Should $G show actual speed +*/ #include "grbl.h" #include "SpindleClass.h" @@ -32,6 +38,8 @@ void PWMSpindle::init() { float PWMSpindle::set_rpm(float rpm) { uint32_t pwm_value; + //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Set RPM %5.1f", rpm); + // apply overrides and limits rpm *= (0.010 * sys.spindle_speed_ovr); // Scale by spindle speed override value (percent) @@ -117,7 +125,7 @@ void PWMSpindle::set_pwm(uint32_t duty) { #ifdef INVERT_SPINDLE_PWM duty = (1 << SPINDLE_PWM_BIT_PRECISION) - duty; #endif - + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Set PWM %d of %d", duty, (1 << SPINDLE_PWM_BIT_PRECISION)-1); ledcWrite(_spindle_pwm_chan_num, duty); } From f9593975ce249dc89093375b5b5e3ff1ded181a0 Mon Sep 17 00:00:00 2001 From: bdring Date: Fri, 3 Apr 2020 16:26:45 -0500 Subject: [PATCH 03/32] Basic functionalty for testing. --- Grbl_Esp32/grbl.h | 4 ++-- Grbl_Esp32/tools/SpindleClass.cpp | 30 +++++++++++++++++++++++++++++- Grbl_Esp32/tools/SpindleClass.h | 23 +++++++++++++++++++++++ 3 files changed, 54 insertions(+), 3 deletions(-) diff --git a/Grbl_Esp32/grbl.h b/Grbl_Esp32/grbl.h index b7ef650a..a0125ecf 100644 --- a/Grbl_Esp32/grbl.h +++ b/Grbl_Esp32/grbl.h @@ -19,8 +19,8 @@ */ // Grbl versioning system -#define GRBL_VERSION "1.1f" -#define GRBL_VERSION_BUILD "20200319" +#define GRBL_VERSION "1.2a" +#define GRBL_VERSION_BUILD "20200403" //#include #include diff --git a/Grbl_Esp32/tools/SpindleClass.cpp b/Grbl_Esp32/tools/SpindleClass.cpp index ac2ca73b..396901b0 100644 --- a/Grbl_Esp32/tools/SpindleClass.cpp +++ b/Grbl_Esp32/tools/SpindleClass.cpp @@ -1,8 +1,36 @@ /* + SpindleClass.cpp + + A Spindle Class + + Part of Grbl_ESP32 + Copyright (c) 2014-2016 Sungeun K. Jeon for Gnea Research LLC + + 2020 - 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 + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . + +*/ + +/* + +TODO Testing - Should $G show actual speed + Should $G show actual speed (Regular Grbl does not) + Speed overrides only take place during motion + */ #include "grbl.h" #include "SpindleClass.h" diff --git a/Grbl_Esp32/tools/SpindleClass.h b/Grbl_Esp32/tools/SpindleClass.h index b22082ba..ff959fff 100644 --- a/Grbl_Esp32/tools/SpindleClass.h +++ b/Grbl_Esp32/tools/SpindleClass.h @@ -1,3 +1,26 @@ +/* + SpindleClass.h + + Header file for a Spindle Class + + Part of Grbl_ESP32 + Copyright (c) 2014-2016 Sungeun K. Jeon for Gnea Research LLC + + 2020 - 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 + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . + +*/ #include "grbl.h" #ifndef SPINDLE_CLASS_H From b9140e66b432006f579331c4eb2485d7c15a384d Mon Sep 17 00:00:00 2001 From: bdring Date: Sat, 4 Apr 2020 10:53:02 -0500 Subject: [PATCH 04/32] More cleanup and testing - A basic PWM spindle appears to work now. - More testing of options and edge cases needed. --- Grbl_Esp32/spindle_control.cpp | 3 ++- Grbl_Esp32/tools/SpindleClass.cpp | 6 +++++- Grbl_Esp32/tools/SpindleClass.h | 12 ++++++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/Grbl_Esp32/spindle_control.cpp b/Grbl_Esp32/spindle_control.cpp index 5eb22d00..1f73a22e 100644 --- a/Grbl_Esp32/spindle_control.cpp +++ b/Grbl_Esp32/spindle_control.cpp @@ -31,19 +31,20 @@ PWMSpindle my_spindle; void spindle_init() { my_spindle.init(); my_spindle.config_message(); - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Spindle is rate adjustable %d", my_spindle.isRateAdjusted()); } void spindle_stop() { my_spindle.stop(); } + uint8_t spindle_get_state() { return my_spindle.get_state(); } + // Called by spindle_set_state() and step segment generator. Keep routine small and efficient. void spindle_set_state(uint8_t state, float rpm) { my_spindle.set_state(state, rpm); diff --git a/Grbl_Esp32/tools/SpindleClass.cpp b/Grbl_Esp32/tools/SpindleClass.cpp index 396901b0..ee283577 100644 --- a/Grbl_Esp32/tools/SpindleClass.cpp +++ b/Grbl_Esp32/tools/SpindleClass.cpp @@ -81,8 +81,10 @@ float PWMSpindle::set_rpm(float rpm) { sys.spindle_speed = 0.0; pwm_value = _pwm_off_value; } else { // Set minimum PWM output - sys.spindle_speed = settings.rpm_min; + rpm = settings.rpm_min; + sys.spindle_speed = rpm; pwm_value = _pwm_min_value; + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Spindle RPM less than min RPM:%5.2f %d", rpm, pwm_value); } } else { // Compute intermediate PWM value with linear spindle speed model. @@ -92,6 +94,7 @@ float PWMSpindle::set_rpm(float rpm) { pwm_value = piecewise_linear_fit(rpm); #else pwm_value = floor((rpm - settings.rpm_min) * _pwm_gradient) + _pwm_min_value; + //pwm_value = map_float(rpm, settings.rpm_min, settings.rpm_max, _pwm_min_value, _pwm_max_value); #endif } @@ -140,6 +143,7 @@ void PWMSpindle::stop() { // prints the startup message of the spindle config void PWMSpindle :: config_message() { grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "PWM spindle on GPIO %d, freq %.2fHz, Res %d bits", SPINDLE_PWM_PIN, settings.spindle_pwm_freq, SPINDLE_PWM_BIT_PRECISION); + //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "PWM Off:%d Min:%d Max:%d", _pwm_off_value, _pwm_min_value, _pwm_max_value); } diff --git a/Grbl_Esp32/tools/SpindleClass.h b/Grbl_Esp32/tools/SpindleClass.h index ff959fff..46cdd974 100644 --- a/Grbl_Esp32/tools/SpindleClass.h +++ b/Grbl_Esp32/tools/SpindleClass.h @@ -41,6 +41,18 @@ class Spindle { }; +// This is a dummy spindle that has no I/O. +// It is used to ignore spindle activity when no spinde is desired +class NullSpindle : public Spindle { + void init(); + float set_rpm(float rpm); + void set_pwm(uint32_t duty); + void set_state(uint8_t state, float rpm); + uint8_t get_state(); + void stop(); + void config_message(); +}; + class PWMSpindle : public Spindle { public: void init(); From e4f073c9f7e362d70f599bfd386d74475546e239 Mon Sep 17 00:00:00 2001 From: bdring Date: Sat, 4 Apr 2020 19:26:57 -0500 Subject: [PATCH 05/32] More tweaking and testing - Add DacSpindle for anlog voltage out spindles --- Grbl_Esp32/settings.cpp | 2 +- Grbl_Esp32/spindle_control.cpp | 17 ++--- Grbl_Esp32/spindle_control.h | 8 +-- Grbl_Esp32/tools/SpindleClass.cpp | 100 +++++++++++++++++++++++++----- Grbl_Esp32/tools/SpindleClass.h | 45 ++++++++++---- 5 files changed, 125 insertions(+), 47 deletions(-) diff --git a/Grbl_Esp32/settings.cpp b/Grbl_Esp32/settings.cpp index 45729568..ccff977e 100644 --- a/Grbl_Esp32/settings.cpp +++ b/Grbl_Esp32/settings.cpp @@ -366,7 +366,7 @@ uint8_t settings_store_global_setting(uint8_t parameter, float value) { case 25: settings.homing_seek_rate = value; break; case 26: settings.homing_debounce_delay = int_value; break; case 27: settings.homing_pulloff = value; break; - case 30: settings.rpm_max = value; spindle_init(); break; // Re-initialize spindle rpm calibration + case 30: settings.rpm_max = std::max(value, 1.0f); spindle_init(); break; // Re-initialize spindle rpm calibration (min of 1) case 31: settings.rpm_min = value; spindle_init(); break; // Re-initialize spindle rpm calibration case 32: #ifdef VARIABLE_SPINDLE diff --git a/Grbl_Esp32/spindle_control.cpp b/Grbl_Esp32/spindle_control.cpp index 1f73a22e..e9ebe753 100644 --- a/Grbl_Esp32/spindle_control.cpp +++ b/Grbl_Esp32/spindle_control.cpp @@ -22,40 +22,35 @@ #include "tools/SpindleClass.h" #include "tools/SpindleClass.cpp" +// TODO Get rid of these intermediary functions and directly access object from Grbl +// This saves me from touching the grbl_esp32 code as much right now. + int8_t spindle_pwm_chan_num; // define a spindle type -//RelaySpindle my_spindle; -PWMSpindle my_spindle; +DacSpindle my_spindle; +//NullSpindle my_spindle; void spindle_init() { my_spindle.init(); - my_spindle.config_message(); } void spindle_stop() { my_spindle.stop(); } - uint8_t spindle_get_state() { return my_spindle.get_state(); } - - - // Called by spindle_set_state() and step segment generator. Keep routine small and efficient. void spindle_set_state(uint8_t state, float rpm) { my_spindle.set_state(state, rpm); } - void spindle_sync(uint8_t state, float rpm) { if (sys.state == STATE_CHECK_MODE) return; protocol_buffer_synchronize(); // Empty planner buffer to ensure spindle is set when programmed. spindle_set_state(state, rpm); -} - - +} \ No newline at end of file diff --git a/Grbl_Esp32/spindle_control.h b/Grbl_Esp32/spindle_control.h index 1a8b8d57..d73ecbc9 100644 --- a/Grbl_Esp32/spindle_control.h +++ b/Grbl_Esp32/spindle_control.h @@ -32,18 +32,14 @@ #define SPINDLE_STATE_CW bit(0) #define SPINDLE_STATE_CCW bit(1) -extern uint32_t spindle_pwm_off_value; -extern PWMSpindle my_spindle; +//extern uint32_t spindle_pwm_off_value; +extern DacSpindle my_spindle; void spindle_init(); void spindle_stop(); uint8_t spindle_get_state(); void spindle_set_speed(uint32_t pwm_value); -uint32_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_set_enable(bool enable); -uint32_t piecewise_linear_fit(float rpm); #endif diff --git a/Grbl_Esp32/tools/SpindleClass.cpp b/Grbl_Esp32/tools/SpindleClass.cpp index ee283577..1ad6f6ba 100644 --- a/Grbl_Esp32/tools/SpindleClass.cpp +++ b/Grbl_Esp32/tools/SpindleClass.cpp @@ -2,9 +2,8 @@ SpindleClass.cpp A Spindle Class - + Part of Grbl_ESP32 - Copyright (c) 2014-2016 Sungeun K. Jeon for Gnea Research LLC 2020 - Bart Dring This file was modified for use on the ESP32 CPU. Do not use this with Grbl for atMega328P @@ -39,21 +38,56 @@ bool Spindle::isRateAdjusted() { return false; // default for basic spindles is false } +// ======================= NullSpindle ============================== +// A bunch of do nothing (ignore) methods +void NullSpindle :: init() { + config_message(); +} +float NullSpindle :: set_rpm(float rpm) { + return rpm; +} +void NullSpindle :: set_pwm(uint32_t duty) {} +void NullSpindle :: set_state(uint8_t state, float rpm) {} +uint8_t NullSpindle :: get_state() { + return (SPINDLE_STATE_DISABLE); +} +void NullSpindle :: stop() {} +void NullSpindle :: config_message() { + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "No spindle (NullSpindle)"); +} + +// ======================= PWMSpindle ============================== + void PWMSpindle::init() { + _pwm_freq = settings.spindle_pwm_freq; _pwm_period = ((1 << SPINDLE_PWM_BIT_PRECISION) - 1); + if (settings.spindle_pwm_min_value > settings.spindle_pwm_min_value) grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Warning spindle min pwm is greater than max. Check $35 and $36"); + + if ((F_TIMERS / _pwm_freq) < _pwm_period) + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Warning spindle PWM precision (%d bits) too high for frequency (%.2f Hz)", SPINDLE_PWM_BIT_PRECISION, _pwm_freq); + + // pre-caculate some PWM count values _pwm_off_value = (_pwm_period * settings.spindle_pwm_off_value / 100.0); _pwm_min_value = (_pwm_period * settings.spindle_pwm_min_value / 100.0); _pwm_max_value = (_pwm_period * settings.spindle_pwm_max_value / 100.0); - // The pwm_gradient is the pwm duty cycle units per rpm - _pwm_gradient = (_pwm_max_value - _pwm_min_value) / (settings.rpm_max - settings.rpm_min); +#ifdef ENABLE_PIECEWISE_LINEAR_SPINDLE + _min_rpm = RPM_MIN; + _max_rpm = RPM_MAX; +#else + _min_rpm = settings.rpm_min; + _max_rpm = settings.rpm_max; +#endif + // The pwm_gradient is the pwm duty cycle units per rpm + _pwm_gradient = (_pwm_max_value - _pwm_min_value) / (_max_rpm - _min_rpm); _spindle_pwm_chan_num = sys_get_next_PWM_chan_num(); - ledcSetup(_spindle_pwm_chan_num, (double)settings.spindle_pwm_freq, SPINDLE_PWM_BIT_PRECISION); // setup the channel + ledcSetup(_spindle_pwm_chan_num, (double)_pwm_freq, SPINDLE_PWM_BIT_PRECISION); // setup the channel ledcAttachPin(SPINDLE_PWM_PIN, _spindle_pwm_chan_num); // attach the PWM to the pin + config_message(); #ifdef SPINDLE_ENABLE_PIN pinMode(SPINDLE_ENABLE_PIN, OUTPUT); @@ -72,16 +106,16 @@ float PWMSpindle::set_rpm(float rpm) { rpm *= (0.010 * sys.spindle_speed_ovr); // Scale by spindle speed override value (percent) // Calculate PWM register value based on rpm max/min settings and programmed rpm. - if ((settings.rpm_min >= settings.rpm_max) || (rpm >= settings.rpm_max)) { + if ((_min_rpm >= _max_rpm) || (rpm >= _max_rpm)) { // No PWM range possible. Set simple on/off spindle control pin state. - sys.spindle_speed = settings.rpm_max; + sys.spindle_speed = _max_rpm; pwm_value = _pwm_max_value; - } else if (rpm <= settings.rpm_min) { + } else if (rpm <= _min_rpm) { if (rpm == 0.0) { // S0 disables spindle sys.spindle_speed = 0.0; pwm_value = _pwm_off_value; } else { // Set minimum PWM output - rpm = settings.rpm_min; + rpm = _min_rpm; sys.spindle_speed = rpm; pwm_value = _pwm_min_value; grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Spindle RPM less than min RPM:%5.2f %d", rpm, pwm_value); @@ -93,8 +127,7 @@ float PWMSpindle::set_rpm(float rpm) { #ifdef ENABLE_PIECEWISE_LINEAR_SPINDLE pwm_value = piecewise_linear_fit(rpm); #else - pwm_value = floor((rpm - settings.rpm_min) * _pwm_gradient) + _pwm_min_value; - //pwm_value = map_float(rpm, settings.rpm_min, settings.rpm_max, _pwm_min_value, _pwm_max_value); + pwm_value = floor((rpm - _min_rpm) * _pwm_gradient) + _pwm_min_value; #endif } @@ -118,7 +151,7 @@ void PWMSpindle::set_state(uint8_t state, float rpm) { } uint8_t PWMSpindle::get_state() { - + if (_current_pwm_duty == 0) // Check the PWM value return (SPINDLE_STATE_DISABLE); @@ -142,8 +175,8 @@ void PWMSpindle::stop() { // prints the startup message of the spindle config void PWMSpindle :: config_message() { - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "PWM spindle on GPIO %d, freq %.2fHz, Res %d bits", SPINDLE_PWM_PIN, settings.spindle_pwm_freq, SPINDLE_PWM_BIT_PRECISION); - //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "PWM Off:%d Min:%d Max:%d", _pwm_off_value, _pwm_min_value, _pwm_max_value); + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "PWM spindle on GPIO %d, freq %.2fHz, Res %d bits", SPINDLE_PWM_PIN, _pwm_freq, SPINDLE_PWM_BIT_PRECISION); + //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "PWM Off:%d Min:%d Max:%d", _pwm_off_value, _pwm_min_value, _pwm_max_value); } @@ -157,7 +190,7 @@ void PWMSpindle::set_pwm(uint32_t duty) { #ifdef INVERT_SPINDLE_PWM duty = (1 << SPINDLE_PWM_BIT_PRECISION) - duty; #endif - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Set PWM %d of %d", duty, (1 << SPINDLE_PWM_BIT_PRECISION)-1); + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Set PWM %d of %d", duty, (1 << SPINDLE_PWM_BIT_PRECISION) - 1); ledcWrite(_spindle_pwm_chan_num, duty); } @@ -190,6 +223,7 @@ void RelaySpindle::init() { #ifdef SPINDLE_DIR_PIN pinMode(SPINDLE_DIR_PIN, OUTPUT); #endif + config_message(); } // prints the startup message of the spindle config @@ -209,6 +243,38 @@ void RelaySpindle::set_pwm(uint32_t duty) { bool Laser :: isRateAdjusted() { - // must be in $32=1 (laser mode) and M4 (CCW rotation) - return ( settings.flags & BITFLAG_LASER_MODE ); + // must be in $32=1 (laser mode) + return (settings.flags & BITFLAG_LASER_MODE); } + +// ======================= DacSpindle ======================= +void DacSpindle :: init() { + _pwm_period = ((1 << SPINDLE_PWM_BIT_PRECISION) - 1); + _gpio_ok = true; + switch (SPINDLE_PWM_PIN) { + case GPIO_NUM_25: + _dac_channel_num = DAC_CHANNEL_1; + break; + case GPIO_NUM_26: + _dac_channel_num = DAC_CHANNEL_1; + break; + default: + _gpio_ok = false; + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "DAC spindle pin invalid GPIO_NUM_%d", SPINDLE_PWM_PIN); + return; // skip config message + } + config_message(); +} + +void DacSpindle :: config_message() { + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "DAC spindle on GPIO %d", SPINDLE_PWM_PIN); +} + +void DacSpindle :: set_pwm(uint32_t duty) { + // remap duty over DAC's 0-255 range + duty = map(duty, 0, _pwm_period, 0, 255); + if (_gpio_ok) + dac_output_voltage(_dac_channel_num, (uint8_t)duty); +} + + diff --git a/Grbl_Esp32/tools/SpindleClass.h b/Grbl_Esp32/tools/SpindleClass.h index 46cdd974..38b89f73 100644 --- a/Grbl_Esp32/tools/SpindleClass.h +++ b/Grbl_Esp32/tools/SpindleClass.h @@ -2,9 +2,8 @@ SpindleClass.h Header file for a Spindle Class - + Part of Grbl_ESP32 - Copyright (c) 2014-2016 Sungeun K. Jeon for Gnea Research LLC 2020 - Bart Dring This file was modified for use on the ESP32 CPU. Do not use this with Grbl for atMega328P @@ -22,13 +21,16 @@ */ #include "grbl.h" +#include + #ifndef SPINDLE_CLASS_H #define SPINDLE_CLASS_H +// This is the base class. Do not use this as your spindle class Spindle { public: - virtual void init(); + virtual void init(); // not in constructor because this also gets called when $$ settings change virtual float set_rpm(float rpm); virtual void set_pwm(uint32_t duty); virtual void set_state(uint8_t state, float rpm); @@ -37,13 +39,12 @@ class Spindle { virtual void config_message(); virtual bool isRateAdjusted(); - //bool _isRateAdjused = false; - }; // This is a dummy spindle that has no I/O. -// It is used to ignore spindle activity when no spinde is desired +// It is used to ignore spindle commands when no spinde is desired class NullSpindle : public Spindle { + public: void init(); float set_rpm(float rpm); void set_pwm(uint32_t duty); @@ -53,6 +54,7 @@ class NullSpindle : public Spindle { void config_message(); }; +// This adds support for PWM class PWMSpindle : public Spindle { public: void init(); @@ -65,31 +67,50 @@ class PWMSpindle : public Spindle { private: int8_t _spindle_pwm_chan_num; + float _pwm_freq; + int32_t _current_pwm_duty; float _pwm_gradient; // Precalulated value to speed up rpm to PWM conversions. - uint32_t _pwm_period; // how many counts in 1 period + uint32_t _pwm_off_value; uint32_t _pwm_min_value; uint32_t _pwm_max_value; + float _min_rpm; + float _max_rpm; - void set_enable_pin(bool enable_pin); void set_spindle_dir_pin(bool Clockwise); + + protected: + uint32_t _pwm_period; // how many counts in 1 period }; +// This is for an on/off spindle all RPMs above 0 are on class RelaySpindle : public PWMSpindle { public: void init(); void config_message(); void set_pwm(uint32_t duty); -private: - + private: + }; +// this is the same as a PWM spindle, but the M4 compensation is supported. class Laser : public PWMSpindle { - public: - bool isRateAdjusted(); + public: + bool isRateAdjusted(); +}; + +// This uses one of the (2) DAC pins on ESP32 to output a voltage +class DacSpindle : public PWMSpindle { + public: + void init(); + void config_message(); + void set_pwm(uint32_t duty); // sets DAC instead of PWM + private: + dac_channel_t _dac_channel_num; + bool _gpio_ok; }; From 63401de45d33fe20358e756f0ee72b69abc2e055 Mon Sep 17 00:00:00 2001 From: bdring Date: Sun, 5 Apr 2020 11:27:09 -0500 Subject: [PATCH 06/32] Updates after testing - Spindle updates after changing $32 laser mode - Fixed mistake where RPM could twice in stepper interrupt - Added config_message to Laser - Still needs more testing, but no known errors now. --- Grbl_Esp32/config.h | 2 +- Grbl_Esp32/settings.cpp | 11 +++++----- Grbl_Esp32/spindle_control.cpp | 2 +- Grbl_Esp32/spindle_control.h | 2 +- Grbl_Esp32/stepper.cpp | 26 ++++++++++++++++------ Grbl_Esp32/tools/SpindleClass.cpp | 36 +++++++++++++++++-------------- Grbl_Esp32/tools/SpindleClass.h | 4 +++- 7 files changed, 51 insertions(+), 32 deletions(-) diff --git a/Grbl_Esp32/config.h b/Grbl_Esp32/config.h index 881f0e9a..4409d561 100644 --- a/Grbl_Esp32/config.h +++ b/Grbl_Esp32/config.h @@ -451,7 +451,7 @@ Some features should not be changed. See notes below. // enable pin will output 5V for maximum RPM with 256 intermediate levels and 0V when disabled. // NOTE: IMPORTANT for Arduino Unos! When enabled, the Z-limit pin D11 and spindle enable pin D12 switch! // The hardware PWM output on pin D11 is required for variable spindle output voltages. -#define VARIABLE_SPINDLE // Default enabled. Comment to disable. +#define VARIABLE_SPINDLE // Don't edit this for Grbl_ESP32 // Alters the behavior of the spindle enable pin. By default Grbl will not disable the enable pin if // spindle speed is zero and M3/4 is active, but still sets the PWM output to zero. This allows the users diff --git a/Grbl_Esp32/settings.cpp b/Grbl_Esp32/settings.cpp index ccff977e..8493d5ec 100644 --- a/Grbl_Esp32/settings.cpp +++ b/Grbl_Esp32/settings.cpp @@ -369,12 +369,11 @@ uint8_t settings_store_global_setting(uint8_t parameter, float value) { case 30: settings.rpm_max = std::max(value, 1.0f); spindle_init(); break; // Re-initialize spindle rpm calibration (min of 1) case 31: settings.rpm_min = value; spindle_init(); break; // Re-initialize spindle rpm calibration case 32: -#ifdef VARIABLE_SPINDLE - if (int_value) settings.flags |= BITFLAG_LASER_MODE; - else settings.flags &= ~BITFLAG_LASER_MODE; -#else - return (STATUS_SETTING_DISABLED_LASER); -#endif + if (int_value) + settings.flags |= BITFLAG_LASER_MODE; + else + settings.flags &= ~BITFLAG_LASER_MODE; + spindle_init(); // update the spindle class break; case 33: settings.spindle_pwm_freq = value; spindle_init(); break; // Re-initialize spindle pwm calibration case 34: settings.spindle_pwm_off_value = value; spindle_init(); break; // Re-initialize spindle pwm calibration diff --git a/Grbl_Esp32/spindle_control.cpp b/Grbl_Esp32/spindle_control.cpp index e9ebe753..d648b060 100644 --- a/Grbl_Esp32/spindle_control.cpp +++ b/Grbl_Esp32/spindle_control.cpp @@ -28,7 +28,7 @@ int8_t spindle_pwm_chan_num; // define a spindle type -DacSpindle my_spindle; +Laser my_spindle; //NullSpindle my_spindle; void spindle_init() { diff --git a/Grbl_Esp32/spindle_control.h b/Grbl_Esp32/spindle_control.h index d73ecbc9..f5a64a76 100644 --- a/Grbl_Esp32/spindle_control.h +++ b/Grbl_Esp32/spindle_control.h @@ -33,7 +33,7 @@ #define SPINDLE_STATE_CCW bit(1) //extern uint32_t spindle_pwm_off_value; -extern DacSpindle my_spindle; +extern Laser my_spindle; void spindle_init(); void spindle_stop(); diff --git a/Grbl_Esp32/stepper.cpp b/Grbl_Esp32/stepper.cpp index 6a20f6ce..775a5904 100644 --- a/Grbl_Esp32/stepper.cpp +++ b/Grbl_Esp32/stepper.cpp @@ -143,7 +143,7 @@ typedef struct { float inv_rate; // Used by PWM laser mode to speed up segment calculations. - uint16_t current_spindle_pwm; // todo remove + //uint16_t current_spindle_pwm; // todo remove float current_spindle_rpm; } st_prep_t; @@ -283,7 +283,9 @@ void IRAM_ATTR onStepperDriverTimer(void* para) { // ISR It is time to take a st // Set real-time spindle output as segment is loaded, just prior to the first step. //spindle_set_speed(st.exec_segment->spindle_rpm); - my_spindle.set_rpm(st.exec_segment->spindle_rpm); + //grbl_send(CLIENT_SERIAL, "A_"); + my_spindle.set_rpm(prep.current_spindle_rpm); + } else { // Segment buffer empty. Shutdown. @@ -293,6 +295,7 @@ void IRAM_ATTR onStepperDriverTimer(void* para) { // ISR It is time to take a st // Ensure pwm is set properly upon completion of rate-controlled motion. if (st.exec_block->is_pwm_rate_adjusted) { //spindle_set_speed(spindle_pwm_off_value); + //grbl_send(CLIENT_SERIAL, "B_"); my_spindle.set_rpm(0.0); } } @@ -987,7 +990,14 @@ void st_prep_buffer() { } else prep.current_speed = sqrt(pl_block->entry_speed_sqr); - st_prep_block->is_pwm_rate_adjusted = my_spindle.isRateAdjusted(); + //st_prep_block->is_pwm_rate_adjusted = my_spindle.isRateAdjusted(); + if (my_spindle.isRateAdjusted() ){ // settings.flags & BITFLAG_LASER_MODE) { + if (pl_block->condition & PL_COND_FLAG_SPINDLE_CCW) { + // Pre-compute inverse programmed rate to speed up PWM updating per step segment. + prep.inv_rate = 1.0 / pl_block->programmed_rate; + st_prep_block->is_pwm_rate_adjusted = true; + } + } } /* --------------------------------------------------------------------------------- @@ -1188,11 +1198,15 @@ void st_prep_buffer() { if (pl_block->condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)) { float rpm = pl_block->spindle_speed; // NOTE: Feed and rapid overrides are independent of PWM value and do not alter laser power/rate. - if (st_prep_block->is_pwm_rate_adjusted) + if (st_prep_block->is_pwm_rate_adjusted) { rpm *= (prep.current_speed * prep.inv_rate); + //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "RPM %.2f", rpm); + //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Rates CV %.2f IV %.2f RPM %.2f", prep.current_speed, prep.inv_rate, rpm); + } // If current_speed is zero, then may need to be rpm_min*(100/MAX_SPINDLE_SPEED_OVERRIDE) - // but this would be instantaneous only and during a motion. May not matter at all. - prep.current_spindle_rpm = my_spindle.set_rpm(rpm); + // but this would be instantaneous only and during a motion. May not matter at all. + //prep.current_spindle_rpm = my_spindle.set_rpm(rpm); + prep.current_spindle_rpm = rpm; } else { sys.spindle_speed = 0.0; prep.current_spindle_rpm = 0.0; diff --git a/Grbl_Esp32/tools/SpindleClass.cpp b/Grbl_Esp32/tools/SpindleClass.cpp index 1ad6f6ba..b420cd9f 100644 --- a/Grbl_Esp32/tools/SpindleClass.cpp +++ b/Grbl_Esp32/tools/SpindleClass.cpp @@ -2,11 +2,15 @@ SpindleClass.cpp A Spindle Class + Spindle - A base class. Do not use + PWMSpindel - A spindle with a PWM output + RelaySpindle - An on/off only spindle + Laser - Output is PWM, but the M4 laser power mode can be used + DacSpindle - Uses the DAC to output a 0-3.3V output Part of Grbl_ESP32 - 2020 - Bart Dring This file was modified for use on the ESP32 - CPU. Do not use this with Grbl for atMega328P + 2020 - Bart Dring Grbl is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,17 +23,6 @@ You should have received a copy of the GNU General Public License along with Grbl. If not, see . -*/ - -/* - -TODO - - -Testing - Should $G show actual speed (Regular Grbl does not) - Speed overrides only take place during motion - */ #include "grbl.h" #include "SpindleClass.h" @@ -190,7 +183,7 @@ void PWMSpindle::set_pwm(uint32_t duty) { #ifdef INVERT_SPINDLE_PWM duty = (1 << SPINDLE_PWM_BIT_PRECISION) - duty; #endif - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Set PWM %d of %d", duty, (1 << SPINDLE_PWM_BIT_PRECISION) - 1); + //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Set PWM %d of %d", duty, (1 << SPINDLE_PWM_BIT_PRECISION) - 1); ledcWrite(_spindle_pwm_chan_num, duty); } @@ -239,7 +232,7 @@ void RelaySpindle::set_pwm(uint32_t duty) { } -// ====================== Laser ============================= +// ===================================== Laser ============================================== bool Laser :: isRateAdjusted() { @@ -247,9 +240,20 @@ bool Laser :: isRateAdjusted() { return (settings.flags & BITFLAG_LASER_MODE); } -// ======================= DacSpindle ======================= +void Laser :: config_message() { + grbl_msg_sendf(CLIENT_SERIAL, + MSG_LEVEL_INFO, + "Laser spindle on GPIO:%d, Freq:%.2fHz, Res:%dbits Laser mode:$32=%d", + SPINDLE_PWM_PIN, + _pwm_freq, + SPINDLE_PWM_BIT_PRECISION, + isRateAdjusted()); // the current mode +} + +// ======================================== DacSpindle ====================================== void DacSpindle :: init() { _pwm_period = ((1 << SPINDLE_PWM_BIT_PRECISION) - 1); + _dac_channel_num = (dac_channel_t)0; _gpio_ok = true; switch (SPINDLE_PWM_PIN) { case GPIO_NUM_25: diff --git a/Grbl_Esp32/tools/SpindleClass.h b/Grbl_Esp32/tools/SpindleClass.h index 38b89f73..2d330c3a 100644 --- a/Grbl_Esp32/tools/SpindleClass.h +++ b/Grbl_Esp32/tools/SpindleClass.h @@ -67,7 +67,7 @@ class PWMSpindle : public Spindle { private: int8_t _spindle_pwm_chan_num; - float _pwm_freq; + int32_t _current_pwm_duty; @@ -83,6 +83,7 @@ class PWMSpindle : public Spindle { void set_spindle_dir_pin(bool Clockwise); protected: + float _pwm_freq; uint32_t _pwm_period; // how many counts in 1 period }; @@ -100,6 +101,7 @@ class RelaySpindle : public PWMSpindle { class Laser : public PWMSpindle { public: bool isRateAdjusted(); + void config_message(); }; // This uses one of the (2) DAC pins on ESP32 to output a voltage From 9f6dae87b357b295ac0c87a467c6dc37baba0ea8 Mon Sep 17 00:00:00 2001 From: bdring Date: Mon, 6 Apr 2020 21:53:01 -0500 Subject: [PATCH 07/32] More Updates and Testing - classes have local copies of I/O pins used. - Tested enable and direction - Test DacSpindle --- Grbl_Esp32/Grbl_Esp32.ino | 4 +- Grbl_Esp32/Machines/3axis_v4.h | 9 +- Grbl_Esp32/gcode.cpp | 10 +- Grbl_Esp32/grbl.h | 2 +- Grbl_Esp32/motion_control.cpp | 2 +- Grbl_Esp32/nuts_bolts.cpp | 4 + Grbl_Esp32/nuts_bolts.h | 1 + Grbl_Esp32/protocol.cpp | 16 +-- Grbl_Esp32/report.cpp | 2 +- Grbl_Esp32/settings.cpp | 16 +-- Grbl_Esp32/spindle_control.cpp | 33 +---- Grbl_Esp32/spindle_control.h | 18 +-- Grbl_Esp32/tools/SpindleClass.cpp | 209 ++++++++++++++++++++++++------ Grbl_Esp32/tools/SpindleClass.h | 38 ++++-- 14 files changed, 236 insertions(+), 128 deletions(-) diff --git a/Grbl_Esp32/Grbl_Esp32.ino b/Grbl_Esp32/Grbl_Esp32.ino index 62f3fff6..441afdb6 100644 --- a/Grbl_Esp32/Grbl_Esp32.ino +++ b/Grbl_Esp32/Grbl_Esp32.ino @@ -21,6 +21,8 @@ #include "grbl.h" #include "WiFi.h" +#include "tools/SpindleClass.cpp" + // Declare system global variable structure system_t sys; int32_t sys_position[N_AXIS]; // Real-time machine (aka home) position vector in steps. @@ -113,7 +115,7 @@ void loop() { // Reset Grbl primary systems. serial_reset_read_buffer(CLIENT_ALL); // Clear serial read buffer gc_init(); // Set g-code parser to default state - spindle_init(); + my_spindle.init(); coolant_init(); limits_init(); probe_init(); diff --git a/Grbl_Esp32/Machines/3axis_v4.h b/Grbl_Esp32/Machines/3axis_v4.h index 14d1bde3..d8904f49 100644 --- a/Grbl_Esp32/Machines/3axis_v4.h +++ b/Grbl_Esp32/Machines/3axis_v4.h @@ -40,11 +40,12 @@ // OK to comment out to use pin for other features #define STEPPERS_DISABLE_PIN GPIO_NUM_13 -#define SPINDLE_PWM_PIN GPIO_NUM_2 // labeled SpinPWM +#define SPINDLE_PWM_PIN GPIO_NUM_25 // labeled SpinPWM #define SPINDLE_ENABLE_PIN GPIO_NUM_22 // labeled SpinEnbl -#define MIST_PIN GPIO_NUM_21 // labeled Mist -#define FLOOD_PIN GPIO_NUM_25 // labeled Flood -#define PROBE_PIN GPIO_NUM_32 // labeled Probe +#define SPINDLE_DIR_PIN GPIO_NUM_21 +//#define MIST_PIN GPIO_NUM_21 // labeled Mist +//#define FLOOD_PIN GPIO_NUM_25 // labeled Flood +//#define PROBE_PIN GPIO_NUM_32 // labeled Probe #define CONTROL_SAFETY_DOOR_PIN GPIO_NUM_35 // labeled Door, needs external pullup #define CONTROL_RESET_PIN GPIO_NUM_34 // labeled Reset, needs external pullup diff --git a/Grbl_Esp32/gcode.cpp b/Grbl_Esp32/gcode.cpp index 3c09b498..5ab0eb33 100644 --- a/Grbl_Esp32/gcode.cpp +++ b/Grbl_Esp32/gcode.cpp @@ -1091,12 +1091,12 @@ uint8_t gc_execute_line(char* line, uint8_t client) { #ifdef VARIABLE_SPINDLE if (bit_isfalse(gc_parser_flags, GC_PARSER_LASER_ISMOTION)) { if (bit_istrue(gc_parser_flags, GC_PARSER_LASER_DISABLE)) - spindle_sync(gc_state.modal.spindle, 0.0); + my_spindle.set_state(gc_state.modal.spindle, 0.0); else - spindle_sync(gc_state.modal.spindle, gc_block.values.s); + my_spindle.set_state(gc_state.modal.spindle, gc_block.values.s); } #else - spindle_sync(gc_state.modal.spindle, 0.0); + my_spindle.set_state(gc_state.modal.spindle, 0.0); #endif } gc_state.spindle_speed = gc_block.values.s; // Update spindle speed state. @@ -1118,7 +1118,7 @@ uint8_t gc_execute_line(char* line, uint8_t client) { // Update spindle control and apply spindle speed when enabling it in this block. // NOTE: All spindle state changes are synced, even in laser mode. Also, pl_data, // rather than gc_state, is used to manage laser state for non-laser motions. - spindle_sync(gc_block.modal.spindle, pl_data->spindle_speed); + my_spindle.set_state(gc_block.modal.spindle, pl_data->spindle_speed); gc_state.modal.spindle = gc_block.modal.spindle; } pl_data->condition |= gc_state.modal.spindle; // Set condition flag for planner use. @@ -1294,7 +1294,7 @@ uint8_t gc_execute_line(char* line, uint8_t client) { if (!(settings_read_coord_data(gc_state.modal.coord_select, gc_state.coord_system))) FAIL(STATUS_SETTING_READ_FAIL); system_flag_wco_change(); // Set to refresh immediately just in case something altered. - spindle_set_state(SPINDLE_DISABLE, 0.0); + my_spindle.set_state(SPINDLE_DISABLE, 0.0); coolant_set_state(COOLANT_DISABLE); } report_feedback_message(MESSAGE_PROGRAM_END); diff --git a/Grbl_Esp32/grbl.h b/Grbl_Esp32/grbl.h index a0125ecf..9abb374d 100644 --- a/Grbl_Esp32/grbl.h +++ b/Grbl_Esp32/grbl.h @@ -20,7 +20,7 @@ // Grbl versioning system #define GRBL_VERSION "1.2a" -#define GRBL_VERSION_BUILD "20200403" +#define GRBL_VERSION_BUILD "20200405" //#include #include diff --git a/Grbl_Esp32/motion_control.cpp b/Grbl_Esp32/motion_control.cpp index dba7b022..c7ea8df5 100644 --- a/Grbl_Esp32/motion_control.cpp +++ b/Grbl_Esp32/motion_control.cpp @@ -424,7 +424,7 @@ void mc_reset() { if (bit_isfalse(sys_rt_exec_state, EXEC_RESET)) { system_set_exec_state_flag(EXEC_RESET); // Kill spindle and coolant. - spindle_stop(); + my_spindle.stop(); coolant_stop(); // turn off all digital I/O sys_io_control(0xFF, false); diff --git a/Grbl_Esp32/nuts_bolts.cpp b/Grbl_Esp32/nuts_bolts.cpp index ea55ab98..05c7b54a 100644 --- a/Grbl_Esp32/nuts_bolts.cpp +++ b/Grbl_Esp32/nuts_bolts.cpp @@ -149,6 +149,10 @@ float map_float(float x, float in_min, float in_max, float out_min, float out_ma return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; } +uint32_t map_uint32_t(uint32_t x, uint32_t in_min, uint32_t in_max, uint32_t out_min, uint32_t out_max) { + return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; +} + float constrain_float(float in, float min, float max) { // DrawBot_Badge if (in < min) return min; diff --git a/Grbl_Esp32/nuts_bolts.h b/Grbl_Esp32/nuts_bolts.h index e2e91ff7..0e3649bc 100644 --- a/Grbl_Esp32/nuts_bolts.h +++ b/Grbl_Esp32/nuts_bolts.h @@ -89,6 +89,7 @@ float limit_value_by_axis_maximum(float* max_value, float* unit_vec); float mapConstrain(float x, float in_min, float in_max, float out_min, float out_max); float map_float(float x, float in_min, float in_max, float out_min, float out_max); +uint32_t map_uint32_t(uint32_t x, uint32_t in_min, uint32_t in_max, uint32_t out_min, uint32_t out_max); float constrain_float(float in, float min, float max); template void swap(T& a, T& b) { diff --git a/Grbl_Esp32/protocol.cpp b/Grbl_Esp32/protocol.cpp index 5be2fa89..0668e70c 100644 --- a/Grbl_Esp32/protocol.cpp +++ b/Grbl_Esp32/protocol.cpp @@ -564,7 +564,7 @@ static void protocol_exec_rt_suspend() { // Ensure any prior spindle stop override is disabled at start of safety door routine. sys.spindle_stop_ovr = SPINDLE_STOP_OVR_DISABLED; #ifndef PARKING_ENABLE - spindle_set_state(SPINDLE_DISABLE, 0.0); // De-energize + my_spindle.set_state(SPINDLE_DISABLE, 0.0); // De-energize coolant_set_state(COOLANT_DISABLE); // De-energize #else // Get current position and store restore location and spindle retract waypoint. @@ -599,7 +599,7 @@ static void protocol_exec_rt_suspend() { // NOTE: Clear accessory state after retract and after an aborted restore motion. pl_data->condition = (PL_COND_FLAG_SYSTEM_MOTION | PL_COND_FLAG_NO_FEED_OVERRIDE); pl_data->spindle_speed = 0.0; - spindle_set_state(SPINDLE_DISABLE, 0.0); // De-energize + my_spindle.set_state((SPINDLE_DISABLE, 0.0); // De-energize coolant_set_state(COOLANT_DISABLE); // De-energize // Execute fast parking retract motion to parking target location. if (parking_target[PARKING_AXIS] < PARKING_TARGET) { @@ -610,7 +610,7 @@ static void protocol_exec_rt_suspend() { } else { // Parking motion not possible. Just disable the spindle and coolant. // NOTE: Laser mode does not start a parking motion to ensure the laser stops immediately. - spindle_set_state(SPINDLE_DISABLE, 0.0); // De-energize + my_spindle.set_state((SPINDLE_DISABLE, 0.0); // De-energize coolant_set_state(COOLANT_DISABLE); // De-energize } #endif @@ -620,7 +620,7 @@ static void protocol_exec_rt_suspend() { if (sys.state == STATE_SLEEP) { report_feedback_message(MESSAGE_SLEEP_MODE); // Spindle and coolant should already be stopped, but do it again just to be sure. - spindle_set_state(SPINDLE_DISABLE, 0.0); // De-energize + my_spindle.set_state(SPINDLE_DISABLE, 0.0); // De-energize coolant_set_state(COOLANT_DISABLE); // De-energize st_go_idle(); // Disable steppers while (!(sys.abort)) protocol_exec_rt_system(); // Do nothing until reset. @@ -659,7 +659,7 @@ static void protocol_exec_rt_suspend() { // When in laser mode, ignore spindle spin-up delay. Set to turn on laser when cycle starts. bit_true(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_RPM); } else { - spindle_set_state((restore_condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)), restore_spindle_speed); + my_spindle.set_state((restore_condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)), restore_spindle_speed); delay_sec(SAFETY_DOOR_SPINDLE_DELAY, DELAY_MODE_SYS_SUSPEND); } } @@ -705,7 +705,7 @@ static void protocol_exec_rt_suspend() { // Handles beginning of spindle stop if (sys.spindle_stop_ovr & SPINDLE_STOP_OVR_INITIATE) { if (gc_state.modal.spindle != SPINDLE_DISABLE) { - spindle_set_state(SPINDLE_DISABLE, 0.0); // De-energize + my_spindle.set_state(SPINDLE_DISABLE, 0.0); // De-energize sys.spindle_stop_ovr = SPINDLE_STOP_OVR_ENABLED; // Set stop override state to enabled, if de-energized. } else { sys.spindle_stop_ovr = SPINDLE_STOP_OVR_DISABLED; // Clear stop override state @@ -718,7 +718,7 @@ static void protocol_exec_rt_suspend() { // When in laser mode, ignore spindle spin-up delay. Set to turn on laser when cycle starts. bit_true(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_RPM); } else - spindle_set_state((restore_condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)), restore_spindle_speed); + my_spindle.set_state((restore_condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)), restore_spindle_speed); } if (sys.spindle_stop_ovr & SPINDLE_STOP_OVR_RESTORE_CYCLE) { system_set_exec_state_flag(EXEC_CYCLE_START); // Set to resume program. @@ -729,7 +729,7 @@ static void protocol_exec_rt_suspend() { // Handles spindle state during hold. NOTE: Spindle speed overrides may be altered during hold state. // NOTE: STEP_CONTROL_UPDATE_SPINDLE_RPM is automatically reset upon resume in step generator. if (bit_istrue(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_RPM)) { - spindle_set_state((restore_condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)), restore_spindle_speed); + my_spindle.set_state((restore_condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)), restore_spindle_speed); bit_false(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_RPM); } } diff --git a/Grbl_Esp32/report.cpp b/Grbl_Esp32/report.cpp index 8476c839..c882f4ec 100644 --- a/Grbl_Esp32/report.cpp +++ b/Grbl_Esp32/report.cpp @@ -744,7 +744,7 @@ void report_realtime_status(uint8_t client) { } else sys.report_ovr_counter = (REPORT_OVR_REFRESH_IDLE_COUNT - 1); sprintf(temp, "|Ov:%d,%d,%d", sys.f_override, sys.r_override, sys.spindle_speed_ovr); strcat(status, temp); - uint8_t sp_state = spindle_get_state(); + uint8_t sp_state = my_spindle.get_state(); uint8_t cl_state = coolant_get_state(); if (sp_state || cl_state) { strcat(status, "|A:"); diff --git a/Grbl_Esp32/settings.cpp b/Grbl_Esp32/settings.cpp index 8493d5ec..82a5df0d 100644 --- a/Grbl_Esp32/settings.cpp +++ b/Grbl_Esp32/settings.cpp @@ -40,7 +40,7 @@ void settings_init() { if (!read_global_settings()) { report_status_message(STATUS_SETTING_READ_FAIL, CLIENT_SERIAL); settings_restore(SETTINGS_RESTORE_ALL); // Force restore all EEPROM data. - report_grbl_settings(CLIENT_SERIAL, false); // only the serial could be working at this point + report_grbl_settings(CLIENT_SERIAL, false); } } @@ -366,19 +366,19 @@ uint8_t settings_store_global_setting(uint8_t parameter, float value) { case 25: settings.homing_seek_rate = value; break; case 26: settings.homing_debounce_delay = int_value; break; case 27: settings.homing_pulloff = value; break; - case 30: settings.rpm_max = std::max(value, 1.0f); spindle_init(); break; // Re-initialize spindle rpm calibration (min of 1) - case 31: settings.rpm_min = value; spindle_init(); break; // Re-initialize spindle rpm calibration + case 30: settings.rpm_max = std::max(value, 1.0f); my_spindle.init(); break; // Re-initialize spindle rpm calibration (min of 1) + case 31: settings.rpm_min = value; my_spindle.init(); break; // Re-initialize spindle rpm calibration case 32: if (int_value) settings.flags |= BITFLAG_LASER_MODE; else settings.flags &= ~BITFLAG_LASER_MODE; - spindle_init(); // update the spindle class + my_spindle.init(); // update the spindle class break; - case 33: settings.spindle_pwm_freq = value; spindle_init(); break; // Re-initialize spindle pwm calibration - case 34: settings.spindle_pwm_off_value = value; spindle_init(); break; // Re-initialize spindle pwm calibration - case 35: settings.spindle_pwm_min_value = value; spindle_init(); break; // Re-initialize spindle pwm calibration - case 36: settings.spindle_pwm_max_value = value; spindle_init(); break; // Re-initialize spindle pwm calibration + case 33: settings.spindle_pwm_freq = value; my_spindle.init(); break; // Re-initialize spindle pwm calibration + case 34: settings.spindle_pwm_off_value = value; my_spindle.init(); break; // Re-initialize spindle pwm calibration + case 35: settings.spindle_pwm_min_value = value; my_spindle.init(); break; // Re-initialize spindle pwm calibration + case 36: settings.spindle_pwm_max_value = value; my_spindle.init(); break; // Re-initialize spindle pwm calibration case 80: case 81: case 82: diff --git a/Grbl_Esp32/spindle_control.cpp b/Grbl_Esp32/spindle_control.cpp index d648b060..5a6a4072 100644 --- a/Grbl_Esp32/spindle_control.cpp +++ b/Grbl_Esp32/spindle_control.cpp @@ -17,40 +17,11 @@ You should have received a copy of the GNU General Public License along with Grbl. If not, see . */ - #include "grbl.h" -#include "tools/SpindleClass.h" -#include "tools/SpindleClass.cpp" +//#include "tools/SpindleClass.h" // TODO Get rid of these intermediary functions and directly access object from Grbl // This saves me from touching the grbl_esp32 code as much right now. -int8_t spindle_pwm_chan_num; - // define a spindle type -Laser my_spindle; -//NullSpindle my_spindle; - -void spindle_init() { - my_spindle.init(); -} - -void spindle_stop() { - my_spindle.stop(); -} - -uint8_t spindle_get_state() { - return my_spindle.get_state(); -} - -// Called by spindle_set_state() and step segment generator. Keep routine small and efficient. -void spindle_set_state(uint8_t state, float rpm) { - my_spindle.set_state(state, rpm); -} - -void spindle_sync(uint8_t state, float rpm) { - if (sys.state == STATE_CHECK_MODE) - return; - protocol_buffer_synchronize(); // Empty planner buffer to ensure spindle is set when programmed. - spindle_set_state(state, rpm); -} \ No newline at end of file +DacSpindle my_spindle; diff --git a/Grbl_Esp32/spindle_control.h b/Grbl_Esp32/spindle_control.h index f5a64a76..8719838e 100644 --- a/Grbl_Esp32/spindle_control.h +++ b/Grbl_Esp32/spindle_control.h @@ -24,22 +24,6 @@ #include "grbl.h" #include "tools/SpindleClass.h" - -#define SPINDLE_NO_SYNC false -#define SPINDLE_FORCE_SYNC true - -#define SPINDLE_STATE_DISABLE 0 // Must be zero. -#define SPINDLE_STATE_CW bit(0) -#define SPINDLE_STATE_CCW bit(1) - -//extern uint32_t spindle_pwm_off_value; -extern Laser my_spindle; - -void spindle_init(); -void spindle_stop(); -uint8_t spindle_get_state(); -void spindle_set_speed(uint32_t pwm_value); -void spindle_set_state(uint8_t state, float rpm); -void spindle_sync(uint8_t state, float rpm); +extern DacSpindle my_spindle; #endif diff --git a/Grbl_Esp32/tools/SpindleClass.cpp b/Grbl_Esp32/tools/SpindleClass.cpp index b420cd9f..3eb9af94 100644 --- a/Grbl_Esp32/tools/SpindleClass.cpp +++ b/Grbl_Esp32/tools/SpindleClass.cpp @@ -10,7 +10,7 @@ Part of Grbl_ESP32 - 2020 - Bart Dring + 2020 - Bart Dring Grbl is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -23,6 +23,15 @@ You should have received a copy of the GNU General Public License along with Grbl. If not, see . + TODO + Consider breaking into one file per class. + + Get rid of dependance on machine definition #defines + SPINDLE_PWM_BIT_PRECISION + SPINDLE_PWM_PIN + SPINDLE_ENABLE_PIN + SPINDLE_DIR_PIN + */ #include "grbl.h" #include "SpindleClass.h" @@ -31,6 +40,13 @@ bool Spindle::isRateAdjusted() { return false; // default for basic spindles is false } +void Spindle :: spindle_sync(uint8_t state, float rpm) { + if (sys.state == STATE_CHECK_MODE) + return; + protocol_buffer_synchronize(); // Empty planner buffer to ensure spindle is set when programmed. + set_state(state, rpm); +} + // ======================= NullSpindle ============================== // A bunch of do nothing (ignore) methods void NullSpindle :: init() { @@ -46,17 +62,26 @@ uint8_t NullSpindle :: get_state() { } void NullSpindle :: stop() {} void NullSpindle :: config_message() { - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "No spindle (NullSpindle)"); + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "No spindle"); } + + // ======================= PWMSpindle ============================== void PWMSpindle::init() { + + get_pin_numbers(); + + if (_output_pin == UNDEFINED_PIN) { + return; // We cannot continue without the output pin + } + _pwm_freq = settings.spindle_pwm_freq; _pwm_period = ((1 << SPINDLE_PWM_BIT_PRECISION) - 1); if (settings.spindle_pwm_min_value > settings.spindle_pwm_min_value) - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Warning spindle min pwm is greater than max. Check $35 and $36"); + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Warning: Spindle min pwm is greater than max. Check $35 and $36"); if ((F_TIMERS / _pwm_freq) < _pwm_period) grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Warning spindle PWM precision (%d bits) too high for frequency (%.2f Hz)", SPINDLE_PWM_BIT_PRECISION, _pwm_freq); @@ -79,18 +104,49 @@ void PWMSpindle::init() { _spindle_pwm_chan_num = sys_get_next_PWM_chan_num(); ledcSetup(_spindle_pwm_chan_num, (double)_pwm_freq, SPINDLE_PWM_BIT_PRECISION); // setup the channel - ledcAttachPin(SPINDLE_PWM_PIN, _spindle_pwm_chan_num); // attach the PWM to the pin + ledcAttachPin(_output_pin, _spindle_pwm_chan_num); // attach the PWM to the pin + + + if (_enable_pin != UNDEFINED_PIN) + pinMode(_enable_pin, OUTPUT); + + if (_direction_pin != UNDEFINED_PIN) + pinMode(_direction_pin, OUTPUT); + config_message(); +} + +void PWMSpindle :: get_pin_numbers() { + // setup all the pins + +#ifdef SPINDLE_PWM_PIN + _output_pin = SPINDLE_PWM_PIN; +#else + _output_pin = UNDEFINED_PIN; +#endif + #ifdef SPINDLE_ENABLE_PIN - pinMode(SPINDLE_ENABLE_PIN, OUTPUT); + _enable_pin = SPINDLE_ENABLE_PIN; +#else + _enable_pin = UNDEFINED_PIN; #endif + #ifdef SPINDLE_DIR_PIN - pinMode(SPINDLE_DIR_PIN, OUTPUT); + _direction_pin = SPINDLE_DIR_PIN; +#else + _direction_pin = UNDEFINED_PIN; #endif + + if (_output_pin == UNDEFINED_PIN) + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Warning: Spindle output pin not defined"); + } float PWMSpindle::set_rpm(float rpm) { + if (_output_pin == UNDEFINED_PIN) + return rpm; + uint32_t pwm_value; //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Set RPM %5.1f", rpm); @@ -124,7 +180,12 @@ float PWMSpindle::set_rpm(float rpm) { #endif } +#ifdef SPINDLE_ENABLE_OFF_WITH_ZERO_SPEED + set_enable_pin(rpm != 0); +#endif + set_pwm(pwm_value); + return rpm; } @@ -135,9 +196,10 @@ void PWMSpindle::set_state(uint8_t state, float rpm) { if (state == SPINDLE_DISABLE) { // Halt or set spindle direction and rpm. sys.spindle_speed = 0.0; - spindle_stop(); + stop(); } else { set_spindle_dir_pin(state == SPINDLE_ENABLE_CW); + set_enable_pin(true); set_rpm(rpm); } sys.report_ovr_counter = 0; // Set to report change immediately @@ -146,17 +208,16 @@ void PWMSpindle::set_state(uint8_t state, float rpm) { uint8_t PWMSpindle::get_state() { - if (_current_pwm_duty == 0) // Check the PWM value + if (_current_pwm_duty == 0 || _output_pin == UNDEFINED_PIN) return (SPINDLE_STATE_DISABLE); else { -#ifdef SPINDLE_DIR_PIN - if (digitalRead(SPINDLE_DIR_PIN)) + if (_direction_pin != UNDEFINED_PIN) { + if (digitalRead(_direction_pin)) + return (SPINDLE_STATE_CW); + else + return (SPINDLE_STATE_CCW); + } else return (SPINDLE_STATE_CW); - else - return (SPINDLE_STATE_CCW); -#else - return (SPINDLE_STATE_CW); -#endif } } @@ -168,12 +229,15 @@ void PWMSpindle::stop() { // prints the startup message of the spindle config void PWMSpindle :: config_message() { - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "PWM spindle on GPIO %d, freq %.2fHz, Res %d bits", SPINDLE_PWM_PIN, _pwm_freq, SPINDLE_PWM_BIT_PRECISION); + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "PWM spindle on GPIO %d, freq %.2fHz, Res %d bits", _output_pin, _pwm_freq, SPINDLE_PWM_BIT_PRECISION); //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "PWM Off:%d Min:%d Max:%d", _pwm_off_value, _pwm_min_value, _pwm_max_value); } void PWMSpindle::set_pwm(uint32_t duty) { + if (_output_pin == UNDEFINED_PIN) + return; + // to prevent excessive calls to ledcWrite, make sure duty hass changed if (duty == _current_pwm_duty) return; @@ -188,19 +252,18 @@ void PWMSpindle::set_pwm(uint32_t duty) { } void PWMSpindle::set_enable_pin(bool enable) { -#ifdef SPINDLE_ENABLE_PIN + if (_enable_pin == UNDEFINED_PIN) + return; #ifndef INVERT_SPINDLE_ENABLE_PIN - digitalWrite(SPINDLE_ENABLE_PIN, enable); + digitalWrite(_enable_pin, enable); #else - digitalWrite(SPINDLE_ENABLE_PIN, !enable); -#endif + digitalWrite(_enable_pin, !enable); #endif } void PWMSpindle::set_spindle_dir_pin(bool Clockwise) { -#ifdef SPINDLE_DIR_PIN - digitalWrite(SPINDLE_DIR_PIN, state == SPINDLE_ENABLE_CW); -#endif + if (_direction_pin != UNDEFINED_PIN) + digitalWrite(_direction_pin, Clockwise); } // ========================= RelaySpindle ================================== @@ -209,26 +272,31 @@ void PWMSpindle::set_spindle_dir_pin(bool Clockwise) { */ void RelaySpindle::init() { - pinMode(SPINDLE_PWM_PIN, OUTPUT); -#ifdef SPINDLE_ENABLE_PIN - pinMode(SPINDLE_ENABLE_PIN, OUTPUT); -#endif -#ifdef SPINDLE_DIR_PIN - pinMode(SPINDLE_DIR_PIN, OUTPUT); -#endif + get_pin_numbers(); + if (_output_pin == UNDEFINED_PIN) + return; + + pinMode(_output_pin, OUTPUT); + + if (_enable_pin != UNDEFINED_PIN) + pinMode(SPINDLE_ENABLE_PIN, OUTPUT); + + if (_direction_pin != UNDEFINED_PIN) + pinMode(_direction_pin, OUTPUT); + config_message(); } // prints the startup message of the spindle config void RelaySpindle :: config_message() { - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Relay spindle on GPIO %d", SPINDLE_PWM_PIN); + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Relay spindle on GPIO %d", _output_pin); } void RelaySpindle::set_pwm(uint32_t duty) { #ifdef INVERT_SPINDLE_PWM duty = (duty == 0); // flip duty #endif - digitalWrite(SPINDLE_PWM_PIN, duty > 0); // anything greater + digitalWrite(_output_pin, duty > 0); // anything greater } @@ -244,7 +312,7 @@ void Laser :: config_message() { grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Laser spindle on GPIO:%d, Freq:%.2fHz, Res:%dbits Laser mode:$32=%d", - SPINDLE_PWM_PIN, + _output_pin, _pwm_freq, SPINDLE_PWM_BIT_PRECISION, isRateAdjusted()); // the current mode @@ -252,10 +320,17 @@ void Laser :: config_message() { // ======================================== DacSpindle ====================================== void DacSpindle :: init() { - _pwm_period = ((1 << SPINDLE_PWM_BIT_PRECISION) - 1); + get_pin_numbers(); + if (_output_pin == UNDEFINED_PIN) + return; + + _min_rpm = settings.rpm_min; + _max_rpm = settings.rpm_max; + _pwm_min_value = 0; // not actually PWM...DAC counts + _pwm_max_value = 255; // not actually PWM...DAC counts _dac_channel_num = (dac_channel_t)0; _gpio_ok = true; - switch (SPINDLE_PWM_PIN) { + switch (_output_pin) { case GPIO_NUM_25: _dac_channel_num = DAC_CHANNEL_1; break; @@ -264,21 +339,73 @@ void DacSpindle :: init() { break; default: _gpio_ok = false; - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "DAC spindle pin invalid GPIO_NUM_%d", SPINDLE_PWM_PIN); + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "DAC spindle pin invalid GPIO_NUM_%d", _output_pin); return; // skip config message } + + if (_enable_pin != UNDEFINED_PIN) + pinMode(_enable_pin, OUTPUT); + + if (_direction_pin != UNDEFINED_PIN) + pinMode(_direction_pin, OUTPUT); + config_message(); } void DacSpindle :: config_message() { - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "DAC spindle on GPIO %d", SPINDLE_PWM_PIN); + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "DAC spindle on GPIO %d", _output_pin); +} + +float DacSpindle::set_rpm(float rpm) { + if (_output_pin == UNDEFINED_PIN) + return rpm; + + uint32_t pwm_value; + + //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Set RPM %5.1f", rpm); + + // apply overrides and limits + rpm *= (0.010 * sys.spindle_speed_ovr); // Scale by spindle speed override value (percent) + + // Calculate PWM register value based on rpm max/min settings and programmed rpm. + if ((_min_rpm >= _max_rpm) || (rpm >= _max_rpm)) { + // No PWM range possible. Set simple on/off spindle control pin state. + sys.spindle_speed = _max_rpm; + pwm_value = 255; + } else if (rpm <= _min_rpm) { + if (rpm == 0.0) { // S0 disables spindle + sys.spindle_speed = 0.0; + pwm_value = 0; + } else { // Set minimum PWM output + rpm = _min_rpm; + sys.spindle_speed = rpm; + pwm_value = 0; + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Spindle RPM less than min RPM:%5.2f %d", rpm, pwm_value); + } + } else { + // Compute intermediate PWM value with linear spindle speed model. + // NOTE: A nonlinear model could be installed here, if required, but keep it VERY light-weight. + sys.spindle_speed = rpm; + + //pwm_value = floor((rpm - _min_rpm) * _pwm_gradient) + _pwm_min_value; + pwm_value = (uint32_t)map_float(rpm, _min_rpm, _max_rpm, _pwm_min_value, _pwm_max_value); + + } + +#ifdef SPINDLE_ENABLE_OFF_WITH_ZERO_SPEED + set_enable_pin(rpm != 0); +#endif + + set_pwm(pwm_value); + + return rpm; } void DacSpindle :: set_pwm(uint32_t duty) { - // remap duty over DAC's 0-255 range - duty = map(duty, 0, _pwm_period, 0, 255); - if (_gpio_ok) - dac_output_voltage(_dac_channel_num, (uint8_t)duty); + if (_gpio_ok) { + dacWrite(_output_pin, (uint8_t)duty); + } + } diff --git a/Grbl_Esp32/tools/SpindleClass.h b/Grbl_Esp32/tools/SpindleClass.h index 2d330c3a..3d52aeff 100644 --- a/Grbl_Esp32/tools/SpindleClass.h +++ b/Grbl_Esp32/tools/SpindleClass.h @@ -19,11 +19,20 @@ You should have received a copy of the GNU General Public License along with Grbl. If not, see . + TODO + Consider breaking into one file per class. + */ #include "grbl.h" #include +#define SPINDLE_STATE_DISABLE 0 // Must be zero. +#define SPINDLE_STATE_CW bit(0) +#define SPINDLE_STATE_CCW bit(1) + +#define UNDEFINED_PIN 255 + #ifndef SPINDLE_CLASS_H #define SPINDLE_CLASS_H @@ -38,6 +47,7 @@ class Spindle { virtual void stop(); virtual void config_message(); virtual bool isRateAdjusted(); + virtual void spindle_sync(uint8_t state, float rpm); }; @@ -58,7 +68,7 @@ class NullSpindle : public Spindle { class PWMSpindle : public Spindle { public: void init(); - float set_rpm(float rpm); + virtual float set_rpm(float rpm); void set_state(uint8_t state, float rpm); uint8_t get_state(); void stop(); @@ -66,25 +76,32 @@ class PWMSpindle : public Spindle { virtual void set_pwm(uint32_t duty); private: - int8_t _spindle_pwm_chan_num; - + int8_t _spindle_pwm_chan_num; int32_t _current_pwm_duty; float _pwm_gradient; // Precalulated value to speed up rpm to PWM conversions. - uint32_t _pwm_off_value; - uint32_t _pwm_min_value; - uint32_t _pwm_max_value; - float _min_rpm; - float _max_rpm; - - void set_enable_pin(bool enable_pin); + + + + void set_spindle_dir_pin(bool Clockwise); protected: + float _min_rpm; + float _max_rpm; + uint32_t _pwm_off_value; + uint32_t _pwm_min_value; + uint32_t _pwm_max_value; + uint8_t _output_pin; + uint8_t _enable_pin; + uint8_t _direction_pin; float _pwm_freq; uint32_t _pwm_period; // how many counts in 1 period + + void set_enable_pin(bool enable_pin); + void get_pin_numbers(); }; // This is for an on/off spindle all RPMs above 0 are on @@ -110,6 +127,7 @@ class DacSpindle : public PWMSpindle { void init(); void config_message(); void set_pwm(uint32_t duty); // sets DAC instead of PWM + float set_rpm(float rpm); private: dac_channel_t _dac_channel_num; bool _gpio_ok; From 9b7b0d491d597c31c5fbc9706e342b423d29e944 Mon Sep 17 00:00:00 2001 From: bdring Date: Tue, 7 Apr 2020 12:26:12 -0500 Subject: [PATCH 08/32] Some cleanup --- Grbl_Esp32/tools/SpindleClass.cpp | 22 +++++++--------------- Grbl_Esp32/tools/SpindleClass.h | 19 ++++--------------- 2 files changed, 11 insertions(+), 30 deletions(-) diff --git a/Grbl_Esp32/tools/SpindleClass.cpp b/Grbl_Esp32/tools/SpindleClass.cpp index 3eb9af94..7ad7172f 100644 --- a/Grbl_Esp32/tools/SpindleClass.cpp +++ b/Grbl_Esp32/tools/SpindleClass.cpp @@ -48,7 +48,7 @@ void Spindle :: spindle_sync(uint8_t state, float rpm) { } // ======================= NullSpindle ============================== -// A bunch of do nothing (ignore) methods +// NullSpindle is just bunch of do nothing (ignore) methods to be used when you don't want a spindle void NullSpindle :: init() { config_message(); } @@ -86,7 +86,6 @@ void PWMSpindle::init() { if ((F_TIMERS / _pwm_freq) < _pwm_period) grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Warning spindle PWM precision (%d bits) too high for frequency (%.2f Hz)", SPINDLE_PWM_BIT_PRECISION, _pwm_freq); - // pre-caculate some PWM count values _pwm_off_value = (_pwm_period * settings.spindle_pwm_off_value / 100.0); _pwm_min_value = (_pwm_period * settings.spindle_pwm_min_value / 100.0); @@ -104,8 +103,7 @@ void PWMSpindle::init() { _spindle_pwm_chan_num = sys_get_next_PWM_chan_num(); ledcSetup(_spindle_pwm_chan_num, (double)_pwm_freq, SPINDLE_PWM_BIT_PRECISION); // setup the channel - ledcAttachPin(_output_pin, _spindle_pwm_chan_num); // attach the PWM to the pin - + ledcAttachPin(_output_pin, _spindle_pwm_chan_num); // attach the PWM to the pin if (_enable_pin != UNDEFINED_PIN) pinMode(_enable_pin, OUTPUT); @@ -114,9 +112,9 @@ void PWMSpindle::init() { pinMode(_direction_pin, OUTPUT); config_message(); - } +// Get the GPIO from the machine definition void PWMSpindle :: get_pin_numbers() { // setup all the pins @@ -330,18 +328,12 @@ void DacSpindle :: init() { _pwm_max_value = 255; // not actually PWM...DAC counts _dac_channel_num = (dac_channel_t)0; _gpio_ok = true; - switch (_output_pin) { - case GPIO_NUM_25: - _dac_channel_num = DAC_CHANNEL_1; - break; - case GPIO_NUM_26: - _dac_channel_num = DAC_CHANNEL_1; - break; - default: + + if (_output != GPIO_NUM_25 && _output != GPIO_NUM_26) { // DAC can only be used on these pins _gpio_ok = false; grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "DAC spindle pin invalid GPIO_NUM_%d", _output_pin); - return; // skip config message - } + return; + } if (_enable_pin != UNDEFINED_PIN) pinMode(_enable_pin, OUTPUT); diff --git a/Grbl_Esp32/tools/SpindleClass.h b/Grbl_Esp32/tools/SpindleClass.h index 3d52aeff..07843632 100644 --- a/Grbl_Esp32/tools/SpindleClass.h +++ b/Grbl_Esp32/tools/SpindleClass.h @@ -2,6 +2,7 @@ SpindleClass.h Header file for a Spindle Class + See SpindleClass.cpp for more details Part of Grbl_ESP32 @@ -19,9 +20,6 @@ You should have received a copy of the GNU General Public License along with Grbl. If not, see . - TODO - Consider breaking into one file per class. - */ #include "grbl.h" #include @@ -31,7 +29,7 @@ #define SPINDLE_STATE_CW bit(0) #define SPINDLE_STATE_CCW bit(1) -#define UNDEFINED_PIN 255 +#define UNDEFINED_PIN 255 // Pins will be set to this if not defined #ifndef SPINDLE_CLASS_H #define SPINDLE_CLASS_H @@ -76,16 +74,10 @@ class PWMSpindle : public Spindle { virtual void set_pwm(uint32_t duty); private: - int8_t _spindle_pwm_chan_num; - + int8_t _spindle_pwm_chan_num; int32_t _current_pwm_duty; - float _pwm_gradient; // Precalulated value to speed up rpm to PWM conversions. - - - - void set_spindle_dir_pin(bool Clockwise); protected: @@ -110,8 +102,6 @@ class RelaySpindle : public PWMSpindle { void init(); void config_message(); void set_pwm(uint32_t duty); - private: - }; // this is the same as a PWM spindle, but the M4 compensation is supported. @@ -129,8 +119,7 @@ class DacSpindle : public PWMSpindle { void set_pwm(uint32_t duty); // sets DAC instead of PWM float set_rpm(float rpm); private: - dac_channel_t _dac_channel_num; - bool _gpio_ok; + bool _gpio_ok; // DAC is on a valid pin }; From 2d845d26a1803932ac60e0471bea254420e1670a Mon Sep 17 00:00:00 2001 From: bdring Date: Tue, 7 Apr 2020 20:30:38 -0500 Subject: [PATCH 09/32] Added @mitchbradley suggestions --- Grbl_Esp32/system.h | 3 +-- Grbl_Esp32/tools/SpindleClass.cpp | 18 +++--------------- Grbl_Esp32/tools/SpindleClass.h | 17 ++++++++--------- 3 files changed, 12 insertions(+), 26 deletions(-) diff --git a/Grbl_Esp32/system.h b/Grbl_Esp32/system.h index f2fc85c9..d282e4d4 100644 --- a/Grbl_Esp32/system.h +++ b/Grbl_Esp32/system.h @@ -152,8 +152,7 @@ extern system_t sys; #define SPINDLE_STOP_OVR_RESTORE bit(2) #define SPINDLE_STOP_OVR_RESTORE_CYCLE bit(3) - - +#define UNDEFINED_PIN 255 // Can be used to show a pin has no i/O assigned // NOTE: These position variables may need to be declared as volatiles, if problems arise. extern int32_t sys_position[N_AXIS]; // Real-time machine (aka home) position vector in steps. diff --git a/Grbl_Esp32/tools/SpindleClass.cpp b/Grbl_Esp32/tools/SpindleClass.cpp index 7ad7172f..74e7bc48 100644 --- a/Grbl_Esp32/tools/SpindleClass.cpp +++ b/Grbl_Esp32/tools/SpindleClass.cpp @@ -3,7 +3,7 @@ A Spindle Class Spindle - A base class. Do not use - PWMSpindel - A spindle with a PWM output + PWMSpindle - A spindle with a PWM output RelaySpindle - An on/off only spindle Laser - Output is PWM, but the M4 laser power mode can be used DacSpindle - Uses the DAC to output a 0-3.3V output @@ -55,7 +55,6 @@ void NullSpindle :: init() { float NullSpindle :: set_rpm(float rpm) { return rpm; } -void NullSpindle :: set_pwm(uint32_t duty) {} void NullSpindle :: set_state(uint8_t state, float rpm) {} uint8_t NullSpindle :: get_state() { return (SPINDLE_STATE_DISABLE); @@ -68,7 +67,6 @@ void NullSpindle :: config_message() { // ======================= PWMSpindle ============================== - void PWMSpindle::init() { get_pin_numbers(); @@ -147,8 +145,6 @@ float PWMSpindle::set_rpm(float rpm) { uint32_t pwm_value; - //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Set RPM %5.1f", rpm); - // apply overrides and limits rpm *= (0.010 * sys.spindle_speed_ovr); // Scale by spindle speed override value (percent) @@ -228,7 +224,6 @@ void PWMSpindle::stop() { // prints the startup message of the spindle config void PWMSpindle :: config_message() { grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "PWM spindle on GPIO %d, freq %.2fHz, Res %d bits", _output_pin, _pwm_freq, SPINDLE_PWM_BIT_PRECISION); - //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "PWM Off:%d Min:%d Max:%d", _pwm_off_value, _pwm_min_value, _pwm_max_value); } @@ -245,7 +240,6 @@ void PWMSpindle::set_pwm(uint32_t duty) { #ifdef INVERT_SPINDLE_PWM duty = (1 << SPINDLE_PWM_BIT_PRECISION) - duty; #endif - //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Set PWM %d of %d", duty, (1 << SPINDLE_PWM_BIT_PRECISION) - 1); ledcWrite(_spindle_pwm_chan_num, duty); } @@ -268,7 +262,6 @@ void PWMSpindle::set_spindle_dir_pin(bool Clockwise) { /* This is the same as a PWM spindle, but is a digital rather than PWM output */ - void RelaySpindle::init() { get_pin_numbers(); if (_output_pin == UNDEFINED_PIN) @@ -326,10 +319,9 @@ void DacSpindle :: init() { _max_rpm = settings.rpm_max; _pwm_min_value = 0; // not actually PWM...DAC counts _pwm_max_value = 255; // not actually PWM...DAC counts - _dac_channel_num = (dac_channel_t)0; _gpio_ok = true; - if (_output != GPIO_NUM_25 && _output != GPIO_NUM_26) { // DAC can only be used on these pins + if (_output_pin != GPIO_NUM_25 && _output_pin != GPIO_NUM_26) { // DAC can only be used on these pins _gpio_ok = false; grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "DAC spindle pin invalid GPIO_NUM_%d", _output_pin); return; @@ -378,10 +370,8 @@ float DacSpindle::set_rpm(float rpm) { // Compute intermediate PWM value with linear spindle speed model. // NOTE: A nonlinear model could be installed here, if required, but keep it VERY light-weight. sys.spindle_speed = rpm; - - //pwm_value = floor((rpm - _min_rpm) * _pwm_gradient) + _pwm_min_value; + pwm_value = (uint32_t)map_float(rpm, _min_rpm, _max_rpm, _pwm_min_value, _pwm_max_value); - } #ifdef SPINDLE_ENABLE_OFF_WITH_ZERO_SPEED @@ -399,5 +389,3 @@ void DacSpindle :: set_pwm(uint32_t duty) { } } - - diff --git a/Grbl_Esp32/tools/SpindleClass.h b/Grbl_Esp32/tools/SpindleClass.h index 07843632..5f2b0a64 100644 --- a/Grbl_Esp32/tools/SpindleClass.h +++ b/Grbl_Esp32/tools/SpindleClass.h @@ -29,8 +29,6 @@ #define SPINDLE_STATE_CW bit(0) #define SPINDLE_STATE_CCW bit(1) -#define UNDEFINED_PIN 255 // Pins will be set to this if not defined - #ifndef SPINDLE_CLASS_H #define SPINDLE_CLASS_H @@ -39,7 +37,7 @@ class Spindle { public: virtual void init(); // not in constructor because this also gets called when $$ settings change virtual float set_rpm(float rpm); - virtual void set_pwm(uint32_t duty); + //virtual void set_pwm(uint32_t duty); virtual void set_state(uint8_t state, float rpm); virtual uint8_t get_state(); virtual void stop(); @@ -47,6 +45,7 @@ class Spindle { virtual bool isRateAdjusted(); virtual void spindle_sync(uint8_t state, float rpm); + }; // This is a dummy spindle that has no I/O. @@ -55,7 +54,6 @@ class NullSpindle : public Spindle { public: void init(); float set_rpm(float rpm); - void set_pwm(uint32_t duty); void set_state(uint8_t state, float rpm); uint8_t get_state(); void stop(); @@ -70,8 +68,7 @@ class PWMSpindle : public Spindle { void set_state(uint8_t state, float rpm); uint8_t get_state(); void stop(); - void config_message(); - virtual void set_pwm(uint32_t duty); + void config_message(); private: int8_t _spindle_pwm_chan_num; @@ -92,6 +89,7 @@ class PWMSpindle : public Spindle { float _pwm_freq; uint32_t _pwm_period; // how many counts in 1 period + virtual void set_pwm(uint32_t duty); void set_enable_pin(bool enable_pin); void get_pin_numbers(); }; @@ -115,12 +113,13 @@ class Laser : public PWMSpindle { class DacSpindle : public PWMSpindle { public: void init(); - void config_message(); - void set_pwm(uint32_t duty); // sets DAC instead of PWM + void config_message(); float set_rpm(float rpm); private: bool _gpio_ok; // DAC is on a valid pin + protected: + void set_pwm(uint32_t duty); // sets DAC instead of PWM }; -#endif \ No newline at end of file +#endif From ecd1401277f586e7d6fe0e68d4e8e38b86a3fcb8 Mon Sep 17 00:00:00 2001 From: bdring Date: Wed, 8 Apr 2020 10:39:30 -0500 Subject: [PATCH 10/32] Split SpindleClass into invididual class files. --- Grbl_Esp32/spindle_control.cpp | 2 +- Grbl_Esp32/spindle_control.h | 2 +- Grbl_Esp32/tools/DacSpindle.cpp | 107 +++++++++ Grbl_Esp32/tools/Laser.cpp | 42 ++++ Grbl_Esp32/tools/NullSpindle.cpp | 40 ++++ Grbl_Esp32/tools/PWMSpindle.cpp | 215 +++++++++++++++++++ Grbl_Esp32/tools/RelaySpindle.cpp | 55 +++++ Grbl_Esp32/tools/SpindleClass.cpp | 346 +----------------------------- Grbl_Esp32/tools/SpindleClass.h | 7 +- 9 files changed, 468 insertions(+), 348 deletions(-) create mode 100644 Grbl_Esp32/tools/DacSpindle.cpp create mode 100644 Grbl_Esp32/tools/Laser.cpp create mode 100644 Grbl_Esp32/tools/NullSpindle.cpp create mode 100644 Grbl_Esp32/tools/PWMSpindle.cpp create mode 100644 Grbl_Esp32/tools/RelaySpindle.cpp diff --git a/Grbl_Esp32/spindle_control.cpp b/Grbl_Esp32/spindle_control.cpp index 5a6a4072..1c4f960f 100644 --- a/Grbl_Esp32/spindle_control.cpp +++ b/Grbl_Esp32/spindle_control.cpp @@ -24,4 +24,4 @@ // This saves me from touching the grbl_esp32 code as much right now. // define a spindle type -DacSpindle my_spindle; +NullSpindle my_spindle; diff --git a/Grbl_Esp32/spindle_control.h b/Grbl_Esp32/spindle_control.h index 8719838e..d8892224 100644 --- a/Grbl_Esp32/spindle_control.h +++ b/Grbl_Esp32/spindle_control.h @@ -24,6 +24,6 @@ #include "grbl.h" #include "tools/SpindleClass.h" -extern DacSpindle my_spindle; +extern NullSpindle my_spindle; #endif diff --git a/Grbl_Esp32/tools/DacSpindle.cpp b/Grbl_Esp32/tools/DacSpindle.cpp new file mode 100644 index 00000000..1410262d --- /dev/null +++ b/Grbl_Esp32/tools/DacSpindle.cpp @@ -0,0 +1,107 @@ +/* + DacSpindle.cpp + + This uses the Analog DAC in the ESP32 to generate a voltage + proportional to the GCode S value desired. Some spindle uses + a 0-5V or 0-10V value to control the spindle. You would use + an Op Amp type circuit to get from the 0.3.3V of the ESP32 to that voltage. + + Part of Grbl_ESP32 + 2020 - Bart Dring + + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . + +*/ + +#include "grbl.h" +#include "SpindleClass.h" + +// ======================================== DacSpindle ====================================== +void DacSpindle :: init() { + get_pin_numbers(); + if (_output_pin == UNDEFINED_PIN) + return; + + _min_rpm = settings.rpm_min; + _max_rpm = settings.rpm_max; + _pwm_min_value = 0; // not actually PWM...DAC counts + _pwm_max_value = 255; // not actually PWM...DAC counts + _gpio_ok = true; + + if (_output_pin != GPIO_NUM_25 && _output_pin != GPIO_NUM_26) { // DAC can only be used on these pins + _gpio_ok = false; + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "DAC spindle pin invalid GPIO_NUM_%d", _output_pin); + return; + } + + if (_enable_pin != UNDEFINED_PIN) + pinMode(_enable_pin, OUTPUT); + + if (_direction_pin != UNDEFINED_PIN) + pinMode(_direction_pin, OUTPUT); + + config_message(); +} + +void DacSpindle :: config_message() { + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "DAC spindle on GPIO %d", _output_pin); +} + +float DacSpindle::set_rpm(float rpm) { + if (_output_pin == UNDEFINED_PIN) + return rpm; + + uint32_t pwm_value; + + //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Set RPM %5.1f", rpm); + + // apply overrides and limits + rpm *= (0.010 * sys.spindle_speed_ovr); // Scale by spindle speed override value (percent) + + // Calculate PWM register value based on rpm max/min settings and programmed rpm. + if ((_min_rpm >= _max_rpm) || (rpm >= _max_rpm)) { + // No PWM range possible. Set simple on/off spindle control pin state. + sys.spindle_speed = _max_rpm; + pwm_value = 255; + } else if (rpm <= _min_rpm) { + if (rpm == 0.0) { // S0 disables spindle + sys.spindle_speed = 0.0; + pwm_value = 0; + } else { // Set minimum PWM output + rpm = _min_rpm; + sys.spindle_speed = rpm; + pwm_value = 0; + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Spindle RPM less than min RPM:%5.2f %d", rpm, pwm_value); + } + } else { + // Compute intermediate PWM value with linear spindle speed model. + // NOTE: A nonlinear model could be installed here, if required, but keep it VERY light-weight. + sys.spindle_speed = rpm; + + pwm_value = (uint32_t)map_float(rpm, _min_rpm, _max_rpm, _pwm_min_value, _pwm_max_value); + } + +#ifdef SPINDLE_ENABLE_OFF_WITH_ZERO_SPEED + set_enable_pin(rpm != 0); +#endif + + set_pwm(pwm_value); + + return rpm; +} + +void DacSpindle :: set_pwm(uint32_t duty) { + if (_gpio_ok) { + dacWrite(_output_pin, (uint8_t)duty); + } + +} \ No newline at end of file diff --git a/Grbl_Esp32/tools/Laser.cpp b/Grbl_Esp32/tools/Laser.cpp new file mode 100644 index 00000000..68078f7d --- /dev/null +++ b/Grbl_Esp32/tools/Laser.cpp @@ -0,0 +1,42 @@ +/* + Laser.cpp + + This is similar the the PWM Spindle except that it allows the + M4 speed vs. power copensation. + + Part of Grbl_ESP32 + 2020 - Bart Dring + + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . + +*/ + +#include "grbl.h" +#include "SpindleClass.h" + +// ===================================== Laser ============================================== + + +bool Laser :: isRateAdjusted() { + // must be in $32=1 (laser mode) + return (settings.flags & BITFLAG_LASER_MODE); +} + +void Laser :: config_message() { + grbl_msg_sendf(CLIENT_SERIAL, + MSG_LEVEL_INFO, + "Laser spindle on GPIO:%d, Freq:%.2fHz, Res:%dbits Laser mode:$32=%d", + _output_pin, + _pwm_freq, + SPINDLE_PWM_BIT_PRECISION, + isRateAdjusted()); // the current mode +} \ No newline at end of file diff --git a/Grbl_Esp32/tools/NullSpindle.cpp b/Grbl_Esp32/tools/NullSpindle.cpp new file mode 100644 index 00000000..8be38ca6 --- /dev/null +++ b/Grbl_Esp32/tools/NullSpindle.cpp @@ -0,0 +1,40 @@ +/* + NullSpindle.cpp + + This is used when you don't want to use a spindle. No I/O will be used + and most methods don't do anything + + Part of Grbl_ESP32 + 2020 - Bart Dring + + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . + +*/ +#include "grbl.h" +#include "SpindleClass.h" + +// ======================= NullSpindle ============================== +// NullSpindle is just bunch of do nothing (ignore) methods to be used when you don't want a spindle +void NullSpindle :: init() { + config_message(); +} +float NullSpindle :: set_rpm(float rpm) { + return rpm; +} +void NullSpindle :: set_state(uint8_t state, float rpm) {} +uint8_t NullSpindle :: get_state() { + return (SPINDLE_STATE_DISABLE); +} +void NullSpindle :: stop() {} +void NullSpindle :: config_message() { + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "No spindle"); +} \ No newline at end of file diff --git a/Grbl_Esp32/tools/PWMSpindle.cpp b/Grbl_Esp32/tools/PWMSpindle.cpp new file mode 100644 index 00000000..94168723 --- /dev/null +++ b/Grbl_Esp32/tools/PWMSpindle.cpp @@ -0,0 +1,215 @@ +/* + PWMSpindle.cpp + + This is a full featured TTL PWM spindle. This does not include speed/power + compensation. Use the Laser class for that. + + Part of Grbl_ESP32 + 2020 - Bart Dring + + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . + +*/ +#include "grbl.h" +#include "SpindleClass.h" + +// ======================= PWMSpindle ============================== +void PWMSpindle::init() { + + get_pin_numbers(); + + if (_output_pin == UNDEFINED_PIN) { + return; // We cannot continue without the output pin + } + + _pwm_freq = settings.spindle_pwm_freq; + _pwm_period = ((1 << SPINDLE_PWM_BIT_PRECISION) - 1); + + if (settings.spindle_pwm_min_value > settings.spindle_pwm_min_value) + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Warning: Spindle min pwm is greater than max. Check $35 and $36"); + + if ((F_TIMERS / _pwm_freq) < _pwm_period) + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Warning spindle PWM precision (%d bits) too high for frequency (%.2f Hz)", SPINDLE_PWM_BIT_PRECISION, _pwm_freq); + + // pre-caculate some PWM count values + _pwm_off_value = (_pwm_period * settings.spindle_pwm_off_value / 100.0); + _pwm_min_value = (_pwm_period * settings.spindle_pwm_min_value / 100.0); + _pwm_max_value = (_pwm_period * settings.spindle_pwm_max_value / 100.0); + +#ifdef ENABLE_PIECEWISE_LINEAR_SPINDLE + _min_rpm = RPM_MIN; + _max_rpm = RPM_MAX; +#else + _min_rpm = settings.rpm_min; + _max_rpm = settings.rpm_max; +#endif + // The pwm_gradient is the pwm duty cycle units per rpm + _pwm_gradient = (_pwm_max_value - _pwm_min_value) / (_max_rpm - _min_rpm); + + _spindle_pwm_chan_num = sys_get_next_PWM_chan_num(); + ledcSetup(_spindle_pwm_chan_num, (double)_pwm_freq, SPINDLE_PWM_BIT_PRECISION); // setup the channel + ledcAttachPin(_output_pin, _spindle_pwm_chan_num); // attach the PWM to the pin + + if (_enable_pin != UNDEFINED_PIN) + pinMode(_enable_pin, OUTPUT); + + if (_direction_pin != UNDEFINED_PIN) + pinMode(_direction_pin, OUTPUT); + + config_message(); +} + +// Get the GPIO from the machine definition +void PWMSpindle :: get_pin_numbers() { + // setup all the pins + +#ifdef SPINDLE_PWM_PIN + _output_pin = SPINDLE_PWM_PIN; +#else + _output_pin = UNDEFINED_PIN; +#endif + +#ifdef SPINDLE_ENABLE_PIN + _enable_pin = SPINDLE_ENABLE_PIN; +#else + _enable_pin = UNDEFINED_PIN; +#endif + +#ifdef SPINDLE_DIR_PIN + _direction_pin = SPINDLE_DIR_PIN; +#else + _direction_pin = UNDEFINED_PIN; +#endif + + if (_output_pin == UNDEFINED_PIN) + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Warning: Spindle output pin not defined"); + +} + +float PWMSpindle::set_rpm(float rpm) { + if (_output_pin == UNDEFINED_PIN) + return rpm; + + uint32_t pwm_value; + + // apply overrides and limits + rpm *= (0.010 * sys.spindle_speed_ovr); // Scale by spindle speed override value (percent) + + // Calculate PWM register value based on rpm max/min settings and programmed rpm. + if ((_min_rpm >= _max_rpm) || (rpm >= _max_rpm)) { + // No PWM range possible. Set simple on/off spindle control pin state. + sys.spindle_speed = _max_rpm; + pwm_value = _pwm_max_value; + } else if (rpm <= _min_rpm) { + if (rpm == 0.0) { // S0 disables spindle + sys.spindle_speed = 0.0; + pwm_value = _pwm_off_value; + } else { // Set minimum PWM output + rpm = _min_rpm; + sys.spindle_speed = rpm; + pwm_value = _pwm_min_value; + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Spindle RPM less than min RPM:%5.2f %d", rpm, pwm_value); + } + } else { + // Compute intermediate PWM value with linear spindle speed model. + // NOTE: A nonlinear model could be installed here, if required, but keep it VERY light-weight. + sys.spindle_speed = rpm; +#ifdef ENABLE_PIECEWISE_LINEAR_SPINDLE + pwm_value = piecewise_linear_fit(rpm); +#else + pwm_value = floor((rpm - _min_rpm) * _pwm_gradient) + _pwm_min_value; +#endif + } + +#ifdef SPINDLE_ENABLE_OFF_WITH_ZERO_SPEED + set_enable_pin(rpm != 0); +#endif + + set_pwm(pwm_value); + + return rpm; +} + +void PWMSpindle::set_state(uint8_t state, float rpm) { + + if (sys.abort) + return; // Block during abort. + + if (state == SPINDLE_DISABLE) { // Halt or set spindle direction and rpm. + sys.spindle_speed = 0.0; + stop(); + } else { + set_spindle_dir_pin(state == SPINDLE_ENABLE_CW); + set_enable_pin(true); + set_rpm(rpm); + } + sys.report_ovr_counter = 0; // Set to report change immediately +} + +uint8_t PWMSpindle::get_state() { + + + if (_current_pwm_duty == 0 || _output_pin == UNDEFINED_PIN) + return (SPINDLE_STATE_DISABLE); + else { + if (_direction_pin != UNDEFINED_PIN) { + if (digitalRead(_direction_pin)) + return (SPINDLE_STATE_CW); + else + return (SPINDLE_STATE_CCW); + } else + return (SPINDLE_STATE_CW); + } +} + +void PWMSpindle::stop() { + // inverts are delt with in methods + set_enable_pin(false); + set_pwm(0); +} + +// prints the startup message of the spindle config +void PWMSpindle :: config_message() { + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "PWM spindle on GPIO %d, freq %.2fHz, Res %d bits", _output_pin, _pwm_freq, SPINDLE_PWM_BIT_PRECISION); +} + + +void PWMSpindle::set_pwm(uint32_t duty) { + if (_output_pin == UNDEFINED_PIN) + return; + + // to prevent excessive calls to ledcWrite, make sure duty hass changed + if (duty == _current_pwm_duty) + return; + + _current_pwm_duty = duty; + +#ifdef INVERT_SPINDLE_PWM + duty = (1 << SPINDLE_PWM_BIT_PRECISION) - duty; +#endif + ledcWrite(_spindle_pwm_chan_num, duty); +} + +void PWMSpindle::set_enable_pin(bool enable) { + if (_enable_pin == UNDEFINED_PIN) + return; +#ifndef INVERT_SPINDLE_ENABLE_PIN + digitalWrite(_enable_pin, enable); +#else + digitalWrite(_enable_pin, !enable); +#endif +} + +void PWMSpindle::set_spindle_dir_pin(bool Clockwise) { + if (_direction_pin != UNDEFINED_PIN) + digitalWrite(_direction_pin, Clockwise); +} \ No newline at end of file diff --git a/Grbl_Esp32/tools/RelaySpindle.cpp b/Grbl_Esp32/tools/RelaySpindle.cpp new file mode 100644 index 00000000..74485358 --- /dev/null +++ b/Grbl_Esp32/tools/RelaySpindle.cpp @@ -0,0 +1,55 @@ +/* + RelaySpindle.cpp + + This is used for a basic on/off spindle. All S Values about 1 + will turn the spindle on. + + Part of Grbl_ESP32 + 2020 - Bart Dring + + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . + +*/ +#include "grbl.h" +#include "SpindleClass.h" + +// ========================= RelaySpindle ================================== +/* + This is the same as a PWM spindle, but is a digital rather than PWM output +*/ +void RelaySpindle::init() { + get_pin_numbers(); + if (_output_pin == UNDEFINED_PIN) + return; + + pinMode(_output_pin, OUTPUT); + + if (_enable_pin != UNDEFINED_PIN) + pinMode(SPINDLE_ENABLE_PIN, OUTPUT); + + if (_direction_pin != UNDEFINED_PIN) + pinMode(_direction_pin, OUTPUT); + + config_message(); +} + +// prints the startup message of the spindle config +void RelaySpindle :: config_message() { + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Relay spindle on GPIO %d", _output_pin); +} + +void RelaySpindle::set_pwm(uint32_t duty) { +#ifdef INVERT_SPINDLE_PWM + duty = (duty == 0); // flip duty +#endif + digitalWrite(_output_pin, duty > 0); // anything greater +} \ No newline at end of file diff --git a/Grbl_Esp32/tools/SpindleClass.cpp b/Grbl_Esp32/tools/SpindleClass.cpp index 74e7bc48..34db4de7 100644 --- a/Grbl_Esp32/tools/SpindleClass.cpp +++ b/Grbl_Esp32/tools/SpindleClass.cpp @@ -35,6 +35,11 @@ */ #include "grbl.h" #include "SpindleClass.h" +#include "NullSpindle.cpp" +#include "PWMSpindle.cpp" +#include "DacSpindle.cpp" +#include "RelaySpindle.cpp" +#include "Laser.cpp" bool Spindle::isRateAdjusted() { return false; // default for basic spindles is false @@ -47,345 +52,4 @@ void Spindle :: spindle_sync(uint8_t state, float rpm) { set_state(state, rpm); } -// ======================= NullSpindle ============================== -// NullSpindle is just bunch of do nothing (ignore) methods to be used when you don't want a spindle -void NullSpindle :: init() { - config_message(); -} -float NullSpindle :: set_rpm(float rpm) { - return rpm; -} -void NullSpindle :: set_state(uint8_t state, float rpm) {} -uint8_t NullSpindle :: get_state() { - return (SPINDLE_STATE_DISABLE); -} -void NullSpindle :: stop() {} -void NullSpindle :: config_message() { - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "No spindle"); -} - - -// ======================= PWMSpindle ============================== -void PWMSpindle::init() { - - get_pin_numbers(); - - if (_output_pin == UNDEFINED_PIN) { - return; // We cannot continue without the output pin - } - - _pwm_freq = settings.spindle_pwm_freq; - _pwm_period = ((1 << SPINDLE_PWM_BIT_PRECISION) - 1); - - if (settings.spindle_pwm_min_value > settings.spindle_pwm_min_value) - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Warning: Spindle min pwm is greater than max. Check $35 and $36"); - - if ((F_TIMERS / _pwm_freq) < _pwm_period) - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Warning spindle PWM precision (%d bits) too high for frequency (%.2f Hz)", SPINDLE_PWM_BIT_PRECISION, _pwm_freq); - - // pre-caculate some PWM count values - _pwm_off_value = (_pwm_period * settings.spindle_pwm_off_value / 100.0); - _pwm_min_value = (_pwm_period * settings.spindle_pwm_min_value / 100.0); - _pwm_max_value = (_pwm_period * settings.spindle_pwm_max_value / 100.0); - -#ifdef ENABLE_PIECEWISE_LINEAR_SPINDLE - _min_rpm = RPM_MIN; - _max_rpm = RPM_MAX; -#else - _min_rpm = settings.rpm_min; - _max_rpm = settings.rpm_max; -#endif - // The pwm_gradient is the pwm duty cycle units per rpm - _pwm_gradient = (_pwm_max_value - _pwm_min_value) / (_max_rpm - _min_rpm); - - _spindle_pwm_chan_num = sys_get_next_PWM_chan_num(); - ledcSetup(_spindle_pwm_chan_num, (double)_pwm_freq, SPINDLE_PWM_BIT_PRECISION); // setup the channel - ledcAttachPin(_output_pin, _spindle_pwm_chan_num); // attach the PWM to the pin - - if (_enable_pin != UNDEFINED_PIN) - pinMode(_enable_pin, OUTPUT); - - if (_direction_pin != UNDEFINED_PIN) - pinMode(_direction_pin, OUTPUT); - - config_message(); -} - -// Get the GPIO from the machine definition -void PWMSpindle :: get_pin_numbers() { - // setup all the pins - -#ifdef SPINDLE_PWM_PIN - _output_pin = SPINDLE_PWM_PIN; -#else - _output_pin = UNDEFINED_PIN; -#endif - -#ifdef SPINDLE_ENABLE_PIN - _enable_pin = SPINDLE_ENABLE_PIN; -#else - _enable_pin = UNDEFINED_PIN; -#endif - -#ifdef SPINDLE_DIR_PIN - _direction_pin = SPINDLE_DIR_PIN; -#else - _direction_pin = UNDEFINED_PIN; -#endif - - if (_output_pin == UNDEFINED_PIN) - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Warning: Spindle output pin not defined"); - -} - -float PWMSpindle::set_rpm(float rpm) { - if (_output_pin == UNDEFINED_PIN) - return rpm; - - uint32_t pwm_value; - - // apply overrides and limits - rpm *= (0.010 * sys.spindle_speed_ovr); // Scale by spindle speed override value (percent) - - // Calculate PWM register value based on rpm max/min settings and programmed rpm. - if ((_min_rpm >= _max_rpm) || (rpm >= _max_rpm)) { - // No PWM range possible. Set simple on/off spindle control pin state. - sys.spindle_speed = _max_rpm; - pwm_value = _pwm_max_value; - } else if (rpm <= _min_rpm) { - if (rpm == 0.0) { // S0 disables spindle - sys.spindle_speed = 0.0; - pwm_value = _pwm_off_value; - } else { // Set minimum PWM output - rpm = _min_rpm; - sys.spindle_speed = rpm; - pwm_value = _pwm_min_value; - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Spindle RPM less than min RPM:%5.2f %d", rpm, pwm_value); - } - } else { - // Compute intermediate PWM value with linear spindle speed model. - // NOTE: A nonlinear model could be installed here, if required, but keep it VERY light-weight. - sys.spindle_speed = rpm; -#ifdef ENABLE_PIECEWISE_LINEAR_SPINDLE - pwm_value = piecewise_linear_fit(rpm); -#else - pwm_value = floor((rpm - _min_rpm) * _pwm_gradient) + _pwm_min_value; -#endif - } - -#ifdef SPINDLE_ENABLE_OFF_WITH_ZERO_SPEED - set_enable_pin(rpm != 0); -#endif - - set_pwm(pwm_value); - - return rpm; -} - -void PWMSpindle::set_state(uint8_t state, float rpm) { - - if (sys.abort) - return; // Block during abort. - - if (state == SPINDLE_DISABLE) { // Halt or set spindle direction and rpm. - sys.spindle_speed = 0.0; - stop(); - } else { - set_spindle_dir_pin(state == SPINDLE_ENABLE_CW); - set_enable_pin(true); - set_rpm(rpm); - } - sys.report_ovr_counter = 0; // Set to report change immediately -} - -uint8_t PWMSpindle::get_state() { - - - if (_current_pwm_duty == 0 || _output_pin == UNDEFINED_PIN) - return (SPINDLE_STATE_DISABLE); - else { - if (_direction_pin != UNDEFINED_PIN) { - if (digitalRead(_direction_pin)) - return (SPINDLE_STATE_CW); - else - return (SPINDLE_STATE_CCW); - } else - return (SPINDLE_STATE_CW); - } -} - -void PWMSpindle::stop() { - // inverts are delt with in methods - set_enable_pin(false); - set_pwm(0); -} - -// prints the startup message of the spindle config -void PWMSpindle :: config_message() { - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "PWM spindle on GPIO %d, freq %.2fHz, Res %d bits", _output_pin, _pwm_freq, SPINDLE_PWM_BIT_PRECISION); -} - - -void PWMSpindle::set_pwm(uint32_t duty) { - if (_output_pin == UNDEFINED_PIN) - return; - - // to prevent excessive calls to ledcWrite, make sure duty hass changed - if (duty == _current_pwm_duty) - return; - - _current_pwm_duty = duty; - -#ifdef INVERT_SPINDLE_PWM - duty = (1 << SPINDLE_PWM_BIT_PRECISION) - duty; -#endif - ledcWrite(_spindle_pwm_chan_num, duty); -} - -void PWMSpindle::set_enable_pin(bool enable) { - if (_enable_pin == UNDEFINED_PIN) - return; -#ifndef INVERT_SPINDLE_ENABLE_PIN - digitalWrite(_enable_pin, enable); -#else - digitalWrite(_enable_pin, !enable); -#endif -} - -void PWMSpindle::set_spindle_dir_pin(bool Clockwise) { - if (_direction_pin != UNDEFINED_PIN) - digitalWrite(_direction_pin, Clockwise); -} - -// ========================= RelaySpindle ================================== -/* - This is the same as a PWM spindle, but is a digital rather than PWM output -*/ -void RelaySpindle::init() { - get_pin_numbers(); - if (_output_pin == UNDEFINED_PIN) - return; - - pinMode(_output_pin, OUTPUT); - - if (_enable_pin != UNDEFINED_PIN) - pinMode(SPINDLE_ENABLE_PIN, OUTPUT); - - if (_direction_pin != UNDEFINED_PIN) - pinMode(_direction_pin, OUTPUT); - - config_message(); -} - -// prints the startup message of the spindle config -void RelaySpindle :: config_message() { - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Relay spindle on GPIO %d", _output_pin); -} - -void RelaySpindle::set_pwm(uint32_t duty) { -#ifdef INVERT_SPINDLE_PWM - duty = (duty == 0); // flip duty -#endif - digitalWrite(_output_pin, duty > 0); // anything greater -} - - -// ===================================== Laser ============================================== - - -bool Laser :: isRateAdjusted() { - // must be in $32=1 (laser mode) - return (settings.flags & BITFLAG_LASER_MODE); -} - -void Laser :: config_message() { - grbl_msg_sendf(CLIENT_SERIAL, - MSG_LEVEL_INFO, - "Laser spindle on GPIO:%d, Freq:%.2fHz, Res:%dbits Laser mode:$32=%d", - _output_pin, - _pwm_freq, - SPINDLE_PWM_BIT_PRECISION, - isRateAdjusted()); // the current mode -} - -// ======================================== DacSpindle ====================================== -void DacSpindle :: init() { - get_pin_numbers(); - if (_output_pin == UNDEFINED_PIN) - return; - - _min_rpm = settings.rpm_min; - _max_rpm = settings.rpm_max; - _pwm_min_value = 0; // not actually PWM...DAC counts - _pwm_max_value = 255; // not actually PWM...DAC counts - _gpio_ok = true; - - if (_output_pin != GPIO_NUM_25 && _output_pin != GPIO_NUM_26) { // DAC can only be used on these pins - _gpio_ok = false; - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "DAC spindle pin invalid GPIO_NUM_%d", _output_pin); - return; - } - - if (_enable_pin != UNDEFINED_PIN) - pinMode(_enable_pin, OUTPUT); - - if (_direction_pin != UNDEFINED_PIN) - pinMode(_direction_pin, OUTPUT); - - config_message(); -} - -void DacSpindle :: config_message() { - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "DAC spindle on GPIO %d", _output_pin); -} - -float DacSpindle::set_rpm(float rpm) { - if (_output_pin == UNDEFINED_PIN) - return rpm; - - uint32_t pwm_value; - - //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Set RPM %5.1f", rpm); - - // apply overrides and limits - rpm *= (0.010 * sys.spindle_speed_ovr); // Scale by spindle speed override value (percent) - - // Calculate PWM register value based on rpm max/min settings and programmed rpm. - if ((_min_rpm >= _max_rpm) || (rpm >= _max_rpm)) { - // No PWM range possible. Set simple on/off spindle control pin state. - sys.spindle_speed = _max_rpm; - pwm_value = 255; - } else if (rpm <= _min_rpm) { - if (rpm == 0.0) { // S0 disables spindle - sys.spindle_speed = 0.0; - pwm_value = 0; - } else { // Set minimum PWM output - rpm = _min_rpm; - sys.spindle_speed = rpm; - pwm_value = 0; - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Spindle RPM less than min RPM:%5.2f %d", rpm, pwm_value); - } - } else { - // Compute intermediate PWM value with linear spindle speed model. - // NOTE: A nonlinear model could be installed here, if required, but keep it VERY light-weight. - sys.spindle_speed = rpm; - - pwm_value = (uint32_t)map_float(rpm, _min_rpm, _max_rpm, _pwm_min_value, _pwm_max_value); - } - -#ifdef SPINDLE_ENABLE_OFF_WITH_ZERO_SPEED - set_enable_pin(rpm != 0); -#endif - - set_pwm(pwm_value); - - return rpm; -} - -void DacSpindle :: set_pwm(uint32_t duty) { - if (_gpio_ok) { - dacWrite(_output_pin, (uint8_t)duty); - } - -} diff --git a/Grbl_Esp32/tools/SpindleClass.h b/Grbl_Esp32/tools/SpindleClass.h index 5f2b0a64..7dae8c8c 100644 --- a/Grbl_Esp32/tools/SpindleClass.h +++ b/Grbl_Esp32/tools/SpindleClass.h @@ -37,15 +37,12 @@ class Spindle { public: virtual void init(); // not in constructor because this also gets called when $$ settings change virtual float set_rpm(float rpm); - //virtual void set_pwm(uint32_t duty); virtual void set_state(uint8_t state, float rpm); virtual uint8_t get_state(); virtual void stop(); virtual void config_message(); virtual bool isRateAdjusted(); virtual void spindle_sync(uint8_t state, float rpm); - - }; // This is a dummy spindle that has no I/O. @@ -68,7 +65,7 @@ class PWMSpindle : public Spindle { void set_state(uint8_t state, float rpm); uint8_t get_state(); void stop(); - void config_message(); + void config_message(); private: int8_t _spindle_pwm_chan_num; @@ -113,7 +110,7 @@ class Laser : public PWMSpindle { class DacSpindle : public PWMSpindle { public: void init(); - void config_message(); + void config_message(); float set_rpm(float rpm); private: bool _gpio_ok; // DAC is on a valid pin From 2af0a0734781adda88e3afc8927e03887258e0f2 Mon Sep 17 00:00:00 2001 From: bdring Date: Wed, 8 Apr 2020 11:23:26 -0500 Subject: [PATCH 11/32] Got rid of spindle_control.cpp and spindle_control.h --- Grbl_Esp32/Grbl_Esp32.ino | 1 + Grbl_Esp32/grbl.h | 2 +- Grbl_Esp32/spindle_control.cpp | 27 --------------------------- Grbl_Esp32/spindle_control.h | 29 ----------------------------- Grbl_Esp32/tools/SpindleClass.h | 10 +++++++--- 5 files changed, 9 insertions(+), 60 deletions(-) delete mode 100644 Grbl_Esp32/spindle_control.cpp delete mode 100644 Grbl_Esp32/spindle_control.h diff --git a/Grbl_Esp32/Grbl_Esp32.ino b/Grbl_Esp32/Grbl_Esp32.ino index 441afdb6..13762b6b 100644 --- a/Grbl_Esp32/Grbl_Esp32.ino +++ b/Grbl_Esp32/Grbl_Esp32.ino @@ -36,6 +36,7 @@ volatile uint8_t sys_rt_exec_accessory_override; // Global realtime executor bit volatile uint8_t sys_rt_exec_debug; #endif +NullSpindle my_spindle; void setup() { diff --git a/Grbl_Esp32/grbl.h b/Grbl_Esp32/grbl.h index 9abb374d..067bcd55 100644 --- a/Grbl_Esp32/grbl.h +++ b/Grbl_Esp32/grbl.h @@ -51,7 +51,7 @@ #include "protocol.h" #include "report.h" #include "serial.h" -#include "spindle_control.h" +#include "tools/SpindleClass.h" #include "stepper.h" #include "jog.h" #include "inputbuffer.h" diff --git a/Grbl_Esp32/spindle_control.cpp b/Grbl_Esp32/spindle_control.cpp deleted file mode 100644 index 1c4f960f..00000000 --- a/Grbl_Esp32/spindle_control.cpp +++ /dev/null @@ -1,27 +0,0 @@ -/* - spindle_control.cpp - Header for system level commands and real-time processes - Part of Grbl - Copyright (c) 2014-2016 Sungeun K. Jeon for Gnea Research LLC - - 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 - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - Grbl is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with Grbl. If not, see . -*/ -#include "grbl.h" -//#include "tools/SpindleClass.h" - -// TODO Get rid of these intermediary functions and directly access object from Grbl -// This saves me from touching the grbl_esp32 code as much right now. - -// define a spindle type -NullSpindle my_spindle; diff --git a/Grbl_Esp32/spindle_control.h b/Grbl_Esp32/spindle_control.h deleted file mode 100644 index d8892224..00000000 --- a/Grbl_Esp32/spindle_control.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - spindle.h - Header for system level commands and real-time processes - Part of Grbl - Copyright (c) 2014-2016 Sungeun K. Jeon for Gnea Research LLC - - 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 - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - Grbl is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with Grbl. If not, see . -*/ - -#ifndef spindle_control_h -#define spindle_control_h - -#include "grbl.h" -#include "tools/SpindleClass.h" - -extern NullSpindle my_spindle; - -#endif diff --git a/Grbl_Esp32/tools/SpindleClass.h b/Grbl_Esp32/tools/SpindleClass.h index 7dae8c8c..3cc76959 100644 --- a/Grbl_Esp32/tools/SpindleClass.h +++ b/Grbl_Esp32/tools/SpindleClass.h @@ -21,9 +21,6 @@ along with Grbl. If not, see . */ -#include "grbl.h" -#include - #define SPINDLE_STATE_DISABLE 0 // Must be zero. #define SPINDLE_STATE_CW bit(0) @@ -32,6 +29,11 @@ #ifndef SPINDLE_CLASS_H #define SPINDLE_CLASS_H +#include "grbl.h" +#include + + + // This is the base class. Do not use this as your spindle class Spindle { public: @@ -118,5 +120,7 @@ class DacSpindle : public PWMSpindle { void set_pwm(uint32_t duty); // sets DAC instead of PWM }; +extern NullSpindle my_spindle; + #endif From 129e9885628181c93e184f7767ba1e5df66ca21d Mon Sep 17 00:00:00 2001 From: bdring Date: Wed, 8 Apr 2020 17:07:34 -0500 Subject: [PATCH 12/32] Test of dynamic assignment --- Grbl_Esp32/Grbl_Esp32.ino | 6 ++++-- Grbl_Esp32/gcode.cpp | 10 +++++----- Grbl_Esp32/motion_control.cpp | 2 +- Grbl_Esp32/protocol.cpp | 16 ++++++++-------- Grbl_Esp32/report.cpp | 2 +- Grbl_Esp32/settings.cpp | 14 +++++++------- Grbl_Esp32/stepper.cpp | 10 +++++----- Grbl_Esp32/tools/SpindleClass.cpp | 29 +++++++++++++++++++++++++++++ Grbl_Esp32/tools/SpindleClass.h | 16 +++++++++++++++- 9 files changed, 75 insertions(+), 30 deletions(-) diff --git a/Grbl_Esp32/Grbl_Esp32.ino b/Grbl_Esp32/Grbl_Esp32.ino index 13762b6b..943c2c52 100644 --- a/Grbl_Esp32/Grbl_Esp32.ino +++ b/Grbl_Esp32/Grbl_Esp32.ino @@ -36,7 +36,8 @@ volatile uint8_t sys_rt_exec_accessory_override; // Global realtime executor bit volatile uint8_t sys_rt_exec_debug; #endif -NullSpindle my_spindle; +Spindle *my_spindle; + void setup() { @@ -116,7 +117,8 @@ void loop() { // Reset Grbl primary systems. serial_reset_read_buffer(CLIENT_ALL); // Clear serial read buffer gc_init(); // Set g-code parser to default state - my_spindle.init(); + // my_spindle.init(); + spindle_select(SPINDLE_TYPE_PWM); coolant_init(); limits_init(); probe_init(); diff --git a/Grbl_Esp32/gcode.cpp b/Grbl_Esp32/gcode.cpp index 5ab0eb33..369f2b96 100644 --- a/Grbl_Esp32/gcode.cpp +++ b/Grbl_Esp32/gcode.cpp @@ -1091,12 +1091,12 @@ uint8_t gc_execute_line(char* line, uint8_t client) { #ifdef VARIABLE_SPINDLE if (bit_isfalse(gc_parser_flags, GC_PARSER_LASER_ISMOTION)) { if (bit_istrue(gc_parser_flags, GC_PARSER_LASER_DISABLE)) - my_spindle.set_state(gc_state.modal.spindle, 0.0); + my_spindle->set_state(gc_state.modal.spindle, 0.0); else - my_spindle.set_state(gc_state.modal.spindle, gc_block.values.s); + my_spindle->set_state(gc_state.modal.spindle, gc_block.values.s); } #else - my_spindle.set_state(gc_state.modal.spindle, 0.0); + my_spindle->set_state(gc_state.modal.spindle, 0.0); #endif } gc_state.spindle_speed = gc_block.values.s; // Update spindle speed state. @@ -1118,7 +1118,7 @@ uint8_t gc_execute_line(char* line, uint8_t client) { // Update spindle control and apply spindle speed when enabling it in this block. // NOTE: All spindle state changes are synced, even in laser mode. Also, pl_data, // rather than gc_state, is used to manage laser state for non-laser motions. - my_spindle.set_state(gc_block.modal.spindle, pl_data->spindle_speed); + my_spindle->set_state(gc_block.modal.spindle, pl_data->spindle_speed); gc_state.modal.spindle = gc_block.modal.spindle; } pl_data->condition |= gc_state.modal.spindle; // Set condition flag for planner use. @@ -1294,7 +1294,7 @@ uint8_t gc_execute_line(char* line, uint8_t client) { if (!(settings_read_coord_data(gc_state.modal.coord_select, gc_state.coord_system))) FAIL(STATUS_SETTING_READ_FAIL); system_flag_wco_change(); // Set to refresh immediately just in case something altered. - my_spindle.set_state(SPINDLE_DISABLE, 0.0); + my_spindle->set_state(SPINDLE_DISABLE, 0.0); coolant_set_state(COOLANT_DISABLE); } report_feedback_message(MESSAGE_PROGRAM_END); diff --git a/Grbl_Esp32/motion_control.cpp b/Grbl_Esp32/motion_control.cpp index c7ea8df5..d8afdf08 100644 --- a/Grbl_Esp32/motion_control.cpp +++ b/Grbl_Esp32/motion_control.cpp @@ -424,7 +424,7 @@ void mc_reset() { if (bit_isfalse(sys_rt_exec_state, EXEC_RESET)) { system_set_exec_state_flag(EXEC_RESET); // Kill spindle and coolant. - my_spindle.stop(); + my_spindle->stop(); coolant_stop(); // turn off all digital I/O sys_io_control(0xFF, false); diff --git a/Grbl_Esp32/protocol.cpp b/Grbl_Esp32/protocol.cpp index 0668e70c..2f3b825f 100644 --- a/Grbl_Esp32/protocol.cpp +++ b/Grbl_Esp32/protocol.cpp @@ -564,7 +564,7 @@ static void protocol_exec_rt_suspend() { // Ensure any prior spindle stop override is disabled at start of safety door routine. sys.spindle_stop_ovr = SPINDLE_STOP_OVR_DISABLED; #ifndef PARKING_ENABLE - my_spindle.set_state(SPINDLE_DISABLE, 0.0); // De-energize + my_spindle->set_state(SPINDLE_DISABLE, 0.0); // De-energize coolant_set_state(COOLANT_DISABLE); // De-energize #else // Get current position and store restore location and spindle retract waypoint. @@ -599,7 +599,7 @@ static void protocol_exec_rt_suspend() { // NOTE: Clear accessory state after retract and after an aborted restore motion. pl_data->condition = (PL_COND_FLAG_SYSTEM_MOTION | PL_COND_FLAG_NO_FEED_OVERRIDE); pl_data->spindle_speed = 0.0; - my_spindle.set_state((SPINDLE_DISABLE, 0.0); // De-energize + my_spindle->set_state((SPINDLE_DISABLE, 0.0); // De-energize coolant_set_state(COOLANT_DISABLE); // De-energize // Execute fast parking retract motion to parking target location. if (parking_target[PARKING_AXIS] < PARKING_TARGET) { @@ -610,7 +610,7 @@ static void protocol_exec_rt_suspend() { } else { // Parking motion not possible. Just disable the spindle and coolant. // NOTE: Laser mode does not start a parking motion to ensure the laser stops immediately. - my_spindle.set_state((SPINDLE_DISABLE, 0.0); // De-energize + ->set_state((SPINDLE_DISABLE, 0.0); // De-energize coolant_set_state(COOLANT_DISABLE); // De-energize } #endif @@ -620,7 +620,7 @@ static void protocol_exec_rt_suspend() { if (sys.state == STATE_SLEEP) { report_feedback_message(MESSAGE_SLEEP_MODE); // Spindle and coolant should already be stopped, but do it again just to be sure. - my_spindle.set_state(SPINDLE_DISABLE, 0.0); // De-energize + my_spindle->set_state(SPINDLE_DISABLE, 0.0); // De-energize coolant_set_state(COOLANT_DISABLE); // De-energize st_go_idle(); // Disable steppers while (!(sys.abort)) protocol_exec_rt_system(); // Do nothing until reset. @@ -659,7 +659,7 @@ static void protocol_exec_rt_suspend() { // When in laser mode, ignore spindle spin-up delay. Set to turn on laser when cycle starts. bit_true(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_RPM); } else { - my_spindle.set_state((restore_condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)), restore_spindle_speed); + my_spindle->set_state((restore_condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)), restore_spindle_speed); delay_sec(SAFETY_DOOR_SPINDLE_DELAY, DELAY_MODE_SYS_SUSPEND); } } @@ -705,7 +705,7 @@ static void protocol_exec_rt_suspend() { // Handles beginning of spindle stop if (sys.spindle_stop_ovr & SPINDLE_STOP_OVR_INITIATE) { if (gc_state.modal.spindle != SPINDLE_DISABLE) { - my_spindle.set_state(SPINDLE_DISABLE, 0.0); // De-energize + my_spindle->set_state(SPINDLE_DISABLE, 0.0); // De-energize sys.spindle_stop_ovr = SPINDLE_STOP_OVR_ENABLED; // Set stop override state to enabled, if de-energized. } else { sys.spindle_stop_ovr = SPINDLE_STOP_OVR_DISABLED; // Clear stop override state @@ -718,7 +718,7 @@ static void protocol_exec_rt_suspend() { // When in laser mode, ignore spindle spin-up delay. Set to turn on laser when cycle starts. bit_true(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_RPM); } else - my_spindle.set_state((restore_condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)), restore_spindle_speed); + my_spindle->set_state((restore_condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)), restore_spindle_speed); } if (sys.spindle_stop_ovr & SPINDLE_STOP_OVR_RESTORE_CYCLE) { system_set_exec_state_flag(EXEC_CYCLE_START); // Set to resume program. @@ -729,7 +729,7 @@ static void protocol_exec_rt_suspend() { // Handles spindle state during hold. NOTE: Spindle speed overrides may be altered during hold state. // NOTE: STEP_CONTROL_UPDATE_SPINDLE_RPM is automatically reset upon resume in step generator. if (bit_istrue(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_RPM)) { - my_spindle.set_state((restore_condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)), restore_spindle_speed); + my_spindle->set_state((restore_condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)), restore_spindle_speed); bit_false(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_RPM); } } diff --git a/Grbl_Esp32/report.cpp b/Grbl_Esp32/report.cpp index c882f4ec..96505e81 100644 --- a/Grbl_Esp32/report.cpp +++ b/Grbl_Esp32/report.cpp @@ -744,7 +744,7 @@ void report_realtime_status(uint8_t client) { } else sys.report_ovr_counter = (REPORT_OVR_REFRESH_IDLE_COUNT - 1); sprintf(temp, "|Ov:%d,%d,%d", sys.f_override, sys.r_override, sys.spindle_speed_ovr); strcat(status, temp); - uint8_t sp_state = my_spindle.get_state(); + uint8_t sp_state = my_spindle->get_state(); uint8_t cl_state = coolant_get_state(); if (sp_state || cl_state) { strcat(status, "|A:"); diff --git a/Grbl_Esp32/settings.cpp b/Grbl_Esp32/settings.cpp index 82a5df0d..a919f43b 100644 --- a/Grbl_Esp32/settings.cpp +++ b/Grbl_Esp32/settings.cpp @@ -366,19 +366,19 @@ uint8_t settings_store_global_setting(uint8_t parameter, float value) { case 25: settings.homing_seek_rate = value; break; case 26: settings.homing_debounce_delay = int_value; break; case 27: settings.homing_pulloff = value; break; - case 30: settings.rpm_max = std::max(value, 1.0f); my_spindle.init(); break; // Re-initialize spindle rpm calibration (min of 1) - case 31: settings.rpm_min = value; my_spindle.init(); break; // Re-initialize spindle rpm calibration + case 30: settings.rpm_max = std::max(value, 1.0f); my_spindle->init(); break; // Re-initialize spindle rpm calibration (min of 1) + case 31: settings.rpm_min = value; my_spindle->init(); break; // Re-initialize spindle rpm calibration case 32: if (int_value) settings.flags |= BITFLAG_LASER_MODE; else settings.flags &= ~BITFLAG_LASER_MODE; - my_spindle.init(); // update the spindle class + my_spindle->init(); // update the spindle class break; - case 33: settings.spindle_pwm_freq = value; my_spindle.init(); break; // Re-initialize spindle pwm calibration - case 34: settings.spindle_pwm_off_value = value; my_spindle.init(); break; // Re-initialize spindle pwm calibration - case 35: settings.spindle_pwm_min_value = value; my_spindle.init(); break; // Re-initialize spindle pwm calibration - case 36: settings.spindle_pwm_max_value = value; my_spindle.init(); break; // Re-initialize spindle pwm calibration + case 33: settings.spindle_pwm_freq = value; my_spindle->init(); break; // Re-initialize spindle pwm calibration + case 34: settings.spindle_pwm_off_value = value; my_spindle->init(); break; // Re-initialize spindle pwm calibration + case 35: settings.spindle_pwm_min_value = value; my_spindle->init(); break; // Re-initialize spindle pwm calibration + case 36: settings.spindle_pwm_max_value = value; my_spindle->init(); break; // Re-initialize spindle pwm calibration case 80: case 81: case 82: diff --git a/Grbl_Esp32/stepper.cpp b/Grbl_Esp32/stepper.cpp index 775a5904..ea560b9c 100644 --- a/Grbl_Esp32/stepper.cpp +++ b/Grbl_Esp32/stepper.cpp @@ -284,7 +284,7 @@ void IRAM_ATTR onStepperDriverTimer(void* para) { // ISR It is time to take a st // Set real-time spindle output as segment is loaded, just prior to the first step. //spindle_set_speed(st.exec_segment->spindle_rpm); //grbl_send(CLIENT_SERIAL, "A_"); - my_spindle.set_rpm(prep.current_spindle_rpm); + my_spindle->set_rpm(prep.current_spindle_rpm); } else { @@ -296,7 +296,7 @@ void IRAM_ATTR onStepperDriverTimer(void* para) { // ISR It is time to take a st if (st.exec_block->is_pwm_rate_adjusted) { //spindle_set_speed(spindle_pwm_off_value); //grbl_send(CLIENT_SERIAL, "B_"); - my_spindle.set_rpm(0.0); + my_spindle->set_rpm(0.0); } } @@ -990,8 +990,8 @@ void st_prep_buffer() { } else prep.current_speed = sqrt(pl_block->entry_speed_sqr); - //st_prep_block->is_pwm_rate_adjusted = my_spindle.isRateAdjusted(); - if (my_spindle.isRateAdjusted() ){ // settings.flags & BITFLAG_LASER_MODE) { + + if (my_spindle->isRateAdjusted() ){ // settings.flags & BITFLAG_LASER_MODE) { if (pl_block->condition & PL_COND_FLAG_SPINDLE_CCW) { // Pre-compute inverse programmed rate to speed up PWM updating per step segment. prep.inv_rate = 1.0 / pl_block->programmed_rate; @@ -1205,7 +1205,7 @@ void st_prep_buffer() { } // If current_speed is zero, then may need to be rpm_min*(100/MAX_SPINDLE_SPEED_OVERRIDE) // but this would be instantaneous only and during a motion. May not matter at all. - //prep.current_spindle_rpm = my_spindle.set_rpm(rpm); + prep.current_spindle_rpm = rpm; } else { sys.spindle_speed = 0.0; diff --git a/Grbl_Esp32/tools/SpindleClass.cpp b/Grbl_Esp32/tools/SpindleClass.cpp index 34db4de7..0ea289d5 100644 --- a/Grbl_Esp32/tools/SpindleClass.cpp +++ b/Grbl_Esp32/tools/SpindleClass.cpp @@ -41,6 +41,35 @@ #include "RelaySpindle.cpp" #include "Laser.cpp" +NullSpindle null_spindle; +PWMSpindle pwm_spindle; +RelaySpindle relay_spindle; +Laser laser; +DacSpindle dac_spindle; + +void spindle_select(uint8_t spindle_type) { + + switch (spindle_type) { + case SPINDLE_TYPE_PWM: + my_spindle = &pwm_spindle; + break; + case SPINDLE_TYPE_RELAY: + my_spindle = &relay_spindle; + break; + case SPINDLE_TYPE_LASER: + my_spindle = &laser; + break; + case SPINDLE_TYPE_DAC: + my_spindle = &dac_spindle; + break; + case SPINDLE_TYPE_NONE: + default: + my_spindle = &null_spindle; + break; + } + my_spindle->init(); +} + bool Spindle::isRateAdjusted() { return false; // default for basic spindles is false } diff --git a/Grbl_Esp32/tools/SpindleClass.h b/Grbl_Esp32/tools/SpindleClass.h index 3cc76959..5620cc19 100644 --- a/Grbl_Esp32/tools/SpindleClass.h +++ b/Grbl_Esp32/tools/SpindleClass.h @@ -26,6 +26,12 @@ #define SPINDLE_STATE_CW bit(0) #define SPINDLE_STATE_CCW bit(1) +#define SPINDLE_TYPE_NONE 0 +#define SPINDLE_TYPE_PWM 1 +#define SPINDLE_TYPE_RELAY 2 +#define SPINDLE_TYPE_LASER 4 +#define SPINDLE_TYPE_DAC 5 + #ifndef SPINDLE_CLASS_H #define SPINDLE_CLASS_H @@ -120,7 +126,15 @@ class DacSpindle : public PWMSpindle { void set_pwm(uint32_t duty); // sets DAC instead of PWM }; -extern NullSpindle my_spindle; +extern Spindle *my_spindle; + +extern NullSpindle null_spindle; +extern PWMSpindle pwm_spindle; +extern RelaySpindle relay_spindle; +extern Laser laser; +extern DacSpindle dac_spindle; + +void spindle_select(uint8_t spindle_type); #endif From 35e9b4797fe6a3642e1af599cba1fd30b06bbfc2 Mon Sep 17 00:00:00 2001 From: bdring Date: Fri, 10 Apr 2020 13:58:46 -0500 Subject: [PATCH 13/32] Added some settings to test dymanic switcing of spindles --- Grbl_Esp32/Grbl_Esp32.ino | 3 +-- Grbl_Esp32/Machines/3axis_v4.h | 2 ++ Grbl_Esp32/Machines/add_esc_spindle.h | 2 +- Grbl_Esp32/defaults.h | 28 ++++++++++++++++----------- Grbl_Esp32/machine_common.h | 2 ++ Grbl_Esp32/report.cpp | 2 ++ Grbl_Esp32/settings.cpp | 18 +++++++++++------ Grbl_Esp32/settings.h | 2 ++ Grbl_Esp32/tools/Laser.cpp | 2 +- Grbl_Esp32/tools/PWMSpindle.cpp | 16 ++++++++++----- Grbl_Esp32/tools/RelaySpindle.cpp | 20 ++++++++++++++++++- Grbl_Esp32/tools/SpindleClass.cpp | 3 +-- Grbl_Esp32/tools/SpindleClass.h | 2 ++ 13 files changed, 73 insertions(+), 29 deletions(-) diff --git a/Grbl_Esp32/Grbl_Esp32.ino b/Grbl_Esp32/Grbl_Esp32.ino index 943c2c52..00d92839 100644 --- a/Grbl_Esp32/Grbl_Esp32.ino +++ b/Grbl_Esp32/Grbl_Esp32.ino @@ -117,8 +117,7 @@ void loop() { // Reset Grbl primary systems. serial_reset_read_buffer(CLIENT_ALL); // Clear serial read buffer gc_init(); // Set g-code parser to default state - // my_spindle.init(); - spindle_select(SPINDLE_TYPE_PWM); + spindle_select(settings.spindle_type); coolant_init(); limits_init(); probe_init(); diff --git a/Grbl_Esp32/Machines/3axis_v4.h b/Grbl_Esp32/Machines/3axis_v4.h index d8904f49..e16ecbfb 100644 --- a/Grbl_Esp32/Machines/3axis_v4.h +++ b/Grbl_Esp32/Machines/3axis_v4.h @@ -51,3 +51,5 @@ #define CONTROL_RESET_PIN GPIO_NUM_34 // labeled Reset, needs external pullup #define CONTROL_FEED_HOLD_PIN GPIO_NUM_36 // labeled Hold, needs external pullup #define CONTROL_CYCLE_START_PIN GPIO_NUM_39 // labeled Start, needs external pullup + +#define DEFAULT_SPINDLE_TYPE SPINDLE_TYPE_PWM diff --git a/Grbl_Esp32/Machines/add_esc_spindle.h b/Grbl_Esp32/Machines/add_esc_spindle.h index b1c078b4..64996392 100644 --- a/Grbl_Esp32/Machines/add_esc_spindle.h +++ b/Grbl_Esp32/Machines/add_esc_spindle.h @@ -35,7 +35,7 @@ #define SHOW_EXTENDED_SETTINGS -#define SPINDLE_PWM_BIT_PRECISION 16 // 16 bit recommended for ESC (don't change) +#define DEFAULT_SPINDLE_PWM_BIT_PRECISION 16 // 16 bit recommended for ESC (don't change) /* Important ESC Settings diff --git a/Grbl_Esp32/defaults.h b/Grbl_Esp32/defaults.h index 73c1c1c0..808f4669 100644 --- a/Grbl_Esp32/defaults.h +++ b/Grbl_Esp32/defaults.h @@ -114,7 +114,18 @@ #define DEFAULT_HOMING_PULLOFF 1.0 // $27 mm #endif - // ======== sPINDLE STUFF ==================== + // ======== SPINDLE STUFF ==================== + #ifndef DEFAULT_SPINDLE_RPM_MIN // $31 + #define DEFAULT_SPINDLE_RPM_MIN 0.0 // rpm + #endif + + #ifndef DEFAULT_LASER_MODE // $32 + #define DEFAULT_LASER_MODE 0 // false + #endif + + #ifndef DEFAULT_SPINDLE_RPM_MAX // $30 + #define DEFAULT_SPINDLE_RPM_MAX 1000.0 // rpm + #endif #ifndef DEFAULT_SPINDLE_FREQ #define DEFAULT_SPINDLE_FREQ 5000.0 // $33 Hz (extended set) @@ -132,20 +143,15 @@ #define DEFAULT_SPINDLE_MAX_VALUE 100.0 // $36 Percent (extended set) #endif - #ifndef DEFAULT_SPINDLE_RPM_MAX - #define DEFAULT_SPINDLE_RPM_MAX 1000.0 // rpm + #ifndef DEFAULT_SPINDLE_PWM_BIT_PRECISION // $37 + #define DEFAULT_SPINDLE_PWM_BIT_PRECISION 8 #endif - - #ifndef DEFAULT_SPINDLE_RPM_MIN - #define DEFAULT_SPINDLE_RPM_MIN 0.0 // rpm + #ifndef DEFAULT_SPINDLE_TYPE // $38 + #define DEFAULT_SPINDLE_TYPE SPINDLE_TYPE_PWM #endif - #ifndef DEFAULT_LASER_MODE - #define DEFAULT_LASER_MODE 0 // false - #endif - - // user settings + // ================ user settings ===================== #ifndef DEFAULT_USER_INT_80 #define DEFAULT_USER_INT_80 0 // $80 User integer setting #endif diff --git a/Grbl_Esp32/machine_common.h b/Grbl_Esp32/machine_common.h index 35d45cb7..4ac06ce4 100644 --- a/Grbl_Esp32/machine_common.h +++ b/Grbl_Esp32/machine_common.h @@ -1,11 +1,13 @@ #ifndef _machine_common_h #define _machine_common_h +/* #ifndef SPINDLE_PWM_BIT_PRECISION #define SPINDLE_PWM_BIT_PRECISION 8 #endif #define SPINDLE_PWM_MAX_VALUE ((1<init(); // update the spindle class break; - case 33: settings.spindle_pwm_freq = value; my_spindle->init(); break; // Re-initialize spindle pwm calibration - case 34: settings.spindle_pwm_off_value = value; my_spindle->init(); break; // Re-initialize spindle pwm calibration - case 35: settings.spindle_pwm_min_value = value; my_spindle->init(); break; // Re-initialize spindle pwm calibration - case 36: settings.spindle_pwm_max_value = value; my_spindle->init(); break; // Re-initialize spindle pwm calibration + case 33: settings.spindle_pwm_freq = value; spindle_select(settings.spindle_type); break; // Re-initialize spindle pwm calibration + case 34: settings.spindle_pwm_off_value = value; spindle_select(settings.spindle_type); break; // Re-initialize spindle pwm calibration + case 35: settings.spindle_pwm_min_value = value; spindle_select(settings.spindle_type); break; // Re-initialize spindle pwm calibration + case 36: settings.spindle_pwm_max_value = value; spindle_select(settings.spindle_type); break; // Re-initialize spindle pwm calibration + case 37: settings.spindle_pwm_precision_bits = MIN(8, value);spindle_select(settings.spindle_type); break; + case 38: settings.spindle_type = value; spindle_select(settings.spindle_type); break; case 80: case 81: case 82: diff --git a/Grbl_Esp32/settings.h b/Grbl_Esp32/settings.h index a625438a..54950682 100644 --- a/Grbl_Esp32/settings.h +++ b/Grbl_Esp32/settings.h @@ -107,6 +107,8 @@ typedef struct { float spindle_pwm_off_value; // $34 Percent (extended set) float spindle_pwm_min_value; // $35 Percent (extended set) float spindle_pwm_max_value; // $36 Percent (extended set) + uint8_t spindle_pwm_precision_bits; // $37 PWM pwm precision in bits (extended set) + uint8_t spindle_type; // $38 The spindle class to be used (extended set) float rpm_max; float rpm_min; diff --git a/Grbl_Esp32/tools/Laser.cpp b/Grbl_Esp32/tools/Laser.cpp index 68078f7d..7f5037d1 100644 --- a/Grbl_Esp32/tools/Laser.cpp +++ b/Grbl_Esp32/tools/Laser.cpp @@ -37,6 +37,6 @@ void Laser :: config_message() { "Laser spindle on GPIO:%d, Freq:%.2fHz, Res:%dbits Laser mode:$32=%d", _output_pin, _pwm_freq, - SPINDLE_PWM_BIT_PRECISION, + settings.spindle_pwm_precision_bits, isRateAdjusted()); // the current mode } \ No newline at end of file diff --git a/Grbl_Esp32/tools/PWMSpindle.cpp b/Grbl_Esp32/tools/PWMSpindle.cpp index 94168723..f3b640ce 100644 --- a/Grbl_Esp32/tools/PWMSpindle.cpp +++ b/Grbl_Esp32/tools/PWMSpindle.cpp @@ -32,13 +32,13 @@ void PWMSpindle::init() { } _pwm_freq = settings.spindle_pwm_freq; - _pwm_period = ((1 << SPINDLE_PWM_BIT_PRECISION) - 1); + _pwm_period = ((1 << settings.spindle_pwm_precision_bits) - 1); if (settings.spindle_pwm_min_value > settings.spindle_pwm_min_value) grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Warning: Spindle min pwm is greater than max. Check $35 and $36"); if ((F_TIMERS / _pwm_freq) < _pwm_period) - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Warning spindle PWM precision (%d bits) too high for frequency (%.2f Hz)", SPINDLE_PWM_BIT_PRECISION, _pwm_freq); + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Warning spindle PWM precision (%d bits) too high for frequency (%.2f Hz)", settings.spindle_pwm_precision_bits, _pwm_freq); // pre-caculate some PWM count values _pwm_off_value = (_pwm_period * settings.spindle_pwm_off_value / 100.0); @@ -56,7 +56,7 @@ void PWMSpindle::init() { _pwm_gradient = (_pwm_max_value - _pwm_min_value) / (_max_rpm - _min_rpm); _spindle_pwm_chan_num = sys_get_next_PWM_chan_num(); - ledcSetup(_spindle_pwm_chan_num, (double)_pwm_freq, SPINDLE_PWM_BIT_PRECISION); // setup the channel + ledcSetup(_spindle_pwm_chan_num, (double)_pwm_freq, settings.spindle_pwm_precision_bits); // setup the channel ledcAttachPin(_output_pin, _spindle_pwm_chan_num); // attach the PWM to the pin if (_enable_pin != UNDEFINED_PIN) @@ -99,10 +99,13 @@ float PWMSpindle::set_rpm(float rpm) { if (_output_pin == UNDEFINED_PIN) return rpm; + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Spindle RPM:%5.2f Min:%5.2f Max:%5.2f", rpm, _min_rpm, _max_rpm); + uint32_t pwm_value; // apply overrides and limits rpm *= (0.010 * sys.spindle_speed_ovr); // Scale by spindle speed override value (percent) + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Spindle RPM 1:%5.2f", rpm); // Calculate PWM register value based on rpm max/min settings and programmed rpm. if ((_min_rpm >= _max_rpm) || (rpm >= _max_rpm)) { @@ -115,6 +118,7 @@ float PWMSpindle::set_rpm(float rpm) { pwm_value = _pwm_off_value; } else { // Set minimum PWM output rpm = _min_rpm; + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Spindle RPM 2:%5.2f", rpm); sys.spindle_speed = rpm; pwm_value = _pwm_min_value; grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Spindle RPM less than min RPM:%5.2f %d", rpm, pwm_value); @@ -123,6 +127,7 @@ float PWMSpindle::set_rpm(float rpm) { // Compute intermediate PWM value with linear spindle speed model. // NOTE: A nonlinear model could be installed here, if required, but keep it VERY light-weight. sys.spindle_speed = rpm; + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Spindle RPM 3:%5.2f", rpm); #ifdef ENABLE_PIECEWISE_LINEAR_SPINDLE pwm_value = piecewise_linear_fit(rpm); #else @@ -134,6 +139,7 @@ float PWMSpindle::set_rpm(float rpm) { set_enable_pin(rpm != 0); #endif + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Spindle RPM Final:%5.2f", rpm); set_pwm(pwm_value); return rpm; @@ -179,7 +185,7 @@ void PWMSpindle::stop() { // prints the startup message of the spindle config void PWMSpindle :: config_message() { - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "PWM spindle on GPIO %d, freq %.2fHz, Res %d bits", _output_pin, _pwm_freq, SPINDLE_PWM_BIT_PRECISION); + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "PWM spindle on GPIO %d, freq %.2fHz, Res %d bits", _output_pin, _pwm_freq, settings.spindle_pwm_precision_bits); } @@ -194,7 +200,7 @@ void PWMSpindle::set_pwm(uint32_t duty) { _current_pwm_duty = duty; #ifdef INVERT_SPINDLE_PWM - duty = (1 << SPINDLE_PWM_BIT_PRECISION) - duty; + duty = (1 << settings.spindle_pwm_precision_bits) - duty; #endif ledcWrite(_spindle_pwm_chan_num, duty); } diff --git a/Grbl_Esp32/tools/RelaySpindle.cpp b/Grbl_Esp32/tools/RelaySpindle.cpp index 74485358..1b7bfc3f 100644 --- a/Grbl_Esp32/tools/RelaySpindle.cpp +++ b/Grbl_Esp32/tools/RelaySpindle.cpp @@ -17,7 +17,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Grbl. If not, see . - + */ #include "grbl.h" #include "SpindleClass.h" @@ -47,9 +47,27 @@ void RelaySpindle :: config_message() { grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Relay spindle on GPIO %d", _output_pin); } +float RelaySpindle::set_rpm(float rpm) { + if (_output_pin == UNDEFINED_PIN) + return rpm; + + sys.spindle_speed = rpm; + + if (rpm == 0) { + sys.spindle_speed = 0.0; + set_pwm(0); + } else { + sys.spindle_speed = rpm; + set_pwm(1); + } + + return rpm; +} + void RelaySpindle::set_pwm(uint32_t duty) { #ifdef INVERT_SPINDLE_PWM duty = (duty == 0); // flip duty #endif + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Relay output %d", duty > 0); digitalWrite(_output_pin, duty > 0); // anything greater } \ No newline at end of file diff --git a/Grbl_Esp32/tools/SpindleClass.cpp b/Grbl_Esp32/tools/SpindleClass.cpp index 0ea289d5..6436697a 100644 --- a/Grbl_Esp32/tools/SpindleClass.cpp +++ b/Grbl_Esp32/tools/SpindleClass.cpp @@ -26,8 +26,7 @@ TODO Consider breaking into one file per class. - Get rid of dependance on machine definition #defines - SPINDLE_PWM_BIT_PRECISION + Get rid of dependance on machine definition #defines SPINDLE_PWM_PIN SPINDLE_ENABLE_PIN SPINDLE_DIR_PIN diff --git a/Grbl_Esp32/tools/SpindleClass.h b/Grbl_Esp32/tools/SpindleClass.h index 5620cc19..4ff7a508 100644 --- a/Grbl_Esp32/tools/SpindleClass.h +++ b/Grbl_Esp32/tools/SpindleClass.h @@ -104,6 +104,8 @@ class RelaySpindle : public PWMSpindle { public: void init(); void config_message(); + float set_rpm(float rpm); + protected: void set_pwm(uint32_t duty); }; From e4ae0c6e3453377f1ffe655ca31de52fd740961d Mon Sep 17 00:00:00 2001 From: bdring Date: Mon, 13 Apr 2020 13:47:43 -0500 Subject: [PATCH 14/32] Removed all #ifdef VARIABLE_SPINDLE statement it is always a variable spindle --- Grbl_Esp32/config.h | 6 ------ Grbl_Esp32/gcode.cpp | 4 ---- Grbl_Esp32/planner.cpp | 3 +-- Grbl_Esp32/planner.h | 2 +- Grbl_Esp32/protocol.cpp | 16 ++++++---------- Grbl_Esp32/report.cpp | 21 ++------------------- 6 files changed, 10 insertions(+), 42 deletions(-) diff --git a/Grbl_Esp32/config.h b/Grbl_Esp32/config.h index 4409d561..72cab998 100644 --- a/Grbl_Esp32/config.h +++ b/Grbl_Esp32/config.h @@ -447,12 +447,6 @@ Some features should not be changed. See notes below. // tool length offset value is subtracted from the current location. #define TOOL_LENGTH_OFFSET_AXIS Z_AXIS // Default z-axis. Valid values are X_AXIS, Y_AXIS, or Z_AXIS. -// Enables variable spindle output voltage for different RPM values. On the Arduino Uno, the spindle -// enable pin will output 5V for maximum RPM with 256 intermediate levels and 0V when disabled. -// NOTE: IMPORTANT for Arduino Unos! When enabled, the Z-limit pin D11 and spindle enable pin D12 switch! -// The hardware PWM output on pin D11 is required for variable spindle output voltages. -#define VARIABLE_SPINDLE // Don't edit this for Grbl_ESP32 - // Alters the behavior of the spindle enable pin. By default Grbl will not disable the enable pin if // spindle speed is zero and M3/4 is active, but still sets the PWM output to zero. This allows the users // to know if the spindle is active and use it as an additional control input. diff --git a/Grbl_Esp32/gcode.cpp b/Grbl_Esp32/gcode.cpp index 369f2b96..6c8e8a66 100644 --- a/Grbl_Esp32/gcode.cpp +++ b/Grbl_Esp32/gcode.cpp @@ -1088,16 +1088,12 @@ uint8_t gc_execute_line(char* line, uint8_t client) { // [4. Set spindle speed ]: if ((gc_state.spindle_speed != gc_block.values.s) || bit_istrue(gc_parser_flags, GC_PARSER_LASER_FORCE_SYNC)) { if (gc_state.modal.spindle != SPINDLE_DISABLE) { -#ifdef VARIABLE_SPINDLE if (bit_isfalse(gc_parser_flags, GC_PARSER_LASER_ISMOTION)) { if (bit_istrue(gc_parser_flags, GC_PARSER_LASER_DISABLE)) my_spindle->set_state(gc_state.modal.spindle, 0.0); else my_spindle->set_state(gc_state.modal.spindle, gc_block.values.s); } -#else - my_spindle->set_state(gc_state.modal.spindle, 0.0); -#endif } gc_state.spindle_speed = gc_block.values.s; // Update spindle speed state. } diff --git a/Grbl_Esp32/planner.cpp b/Grbl_Esp32/planner.cpp index c114288e..16130ab5 100644 --- a/Grbl_Esp32/planner.cpp +++ b/Grbl_Esp32/planner.cpp @@ -284,9 +284,8 @@ uint8_t plan_buffer_line(float* target, plan_line_data_t* pl_data) { plan_block_t* block = &block_buffer[block_buffer_head]; memset(block, 0, sizeof(plan_block_t)); // Zero all block values. block->condition = pl_data->condition; -#ifdef VARIABLE_SPINDLE block->spindle_speed = pl_data->spindle_speed; -#endif + #ifdef USE_LINE_NUMBERS block->line_number = pl_data->line_number; #endif diff --git a/Grbl_Esp32/planner.h b/Grbl_Esp32/planner.h index e4d5ec3e..68519779 100644 --- a/Grbl_Esp32/planner.h +++ b/Grbl_Esp32/planner.h @@ -81,7 +81,7 @@ typedef struct { float rapid_rate; // Axis-limit adjusted maximum rate for this block direction in (mm/min) float programmed_rate; // Programmed rate of this block (mm/min). - //#ifdef VARIABLE_SPINDLE + // Stored spindle speed data used by spindle overrides and resuming methods. float spindle_speed; // Block spindle speed. Copied from pl_line_data. //#endif diff --git a/Grbl_Esp32/protocol.cpp b/Grbl_Esp32/protocol.cpp index 2f3b825f..0a2cb6bc 100644 --- a/Grbl_Esp32/protocol.cpp +++ b/Grbl_Esp32/protocol.cpp @@ -535,7 +535,6 @@ static void protocol_exec_rt_suspend() { #endif plan_block_t* block = plan_get_current_block(); uint8_t restore_condition; -#ifdef VARIABLE_SPINDLE float restore_spindle_speed; if (block == NULL) { restore_condition = (gc_state.modal.spindle | gc_state.modal.coolant); @@ -548,10 +547,7 @@ static void protocol_exec_rt_suspend() { if (bit_istrue(settings.flags, BITFLAG_LASER_MODE)) system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_STOP); #endif -#else - if (block == NULL) restore_condition = (gc_state.modal.spindle | gc_state.modal.coolant); - else restore_condition = block->condition; -#endif + while (sys.suspend) { if (sys.abort) return; // Block until initial hold is complete and the machine has stopped motion. @@ -600,10 +596,10 @@ static void protocol_exec_rt_suspend() { pl_data->condition = (PL_COND_FLAG_SYSTEM_MOTION | PL_COND_FLAG_NO_FEED_OVERRIDE); pl_data->spindle_speed = 0.0; my_spindle->set_state((SPINDLE_DISABLE, 0.0); // De-energize - coolant_set_state(COOLANT_DISABLE); // De-energize - // Execute fast parking retract motion to parking target location. + coolant_set_state(COOLANT_DISABLE); // De-energize + // Execute fast parking retract motion to parking target location. if (parking_target[PARKING_AXIS] < PARKING_TARGET) { - parking_target[PARKING_AXIS] = PARKING_TARGET; + parking_target[PARKING_AXIS] = PARKING_TARGET; pl_data->feed_rate = PARKING_RATE; mc_parking_motion(parking_target, pl_data); } @@ -611,8 +607,8 @@ static void protocol_exec_rt_suspend() { // Parking motion not possible. Just disable the spindle and coolant. // NOTE: Laser mode does not start a parking motion to ensure the laser stops immediately. ->set_state((SPINDLE_DISABLE, 0.0); // De-energize - coolant_set_state(COOLANT_DISABLE); // De-energize - } + coolant_set_state(COOLANT_DISABLE); // De-energize + } #endif sys.suspend &= ~(SUSPEND_RESTART_RETRACT); sys.suspend |= SUSPEND_RETRACT_COMPLETE; diff --git a/Grbl_Esp32/report.cpp b/Grbl_Esp32/report.cpp index c189bbb9..af9a02d0 100644 --- a/Grbl_Esp32/report.cpp +++ b/Grbl_Esp32/report.cpp @@ -308,11 +308,8 @@ void report_grbl_settings(uint8_t client, uint8_t show_extended) { sprintf(setting, "$27=%4.3f\r\n", settings.homing_pulloff); strcat(rpt, setting); sprintf(setting, "$30=%4.3f\r\n", settings.rpm_max); strcat(rpt, setting); sprintf(setting, "$31=%4.3f\r\n", settings.rpm_min); strcat(rpt, setting); -#ifdef VARIABLE_SPINDLE sprintf(setting, "$32=%d\r\n", bit_istrue(settings.flags, BITFLAG_LASER_MODE)); strcat(rpt, setting); -#else - strcat(rpt, "$32=0\r\n"); -#endif + if (show_extended) { sprintf(setting, "$33=%5.3f\r\n", settings.spindle_pwm_freq); strcat(rpt, setting); sprintf(setting, "$34=%3.3f\r\n", settings.spindle_pwm_off_value); strcat(rpt, setting); @@ -473,10 +470,8 @@ void report_gcode_modes(uint8_t client) { else sprintf(temp, " F%.0f", gc_state.feed_rate); strcat(modes_rpt, temp); -#ifdef VARIABLE_SPINDLE sprintf(temp, " S%4.3f", gc_state.spindle_speed); strcat(modes_rpt, temp); -#endif strcat(modes_rpt, "]\r\n"); grbl_send(client, modes_rpt); } @@ -499,12 +494,8 @@ void report_build_info(char* line, uint8_t client) { strcpy(build_info, "[VER:" GRBL_VERSION "." GRBL_VERSION_BUILD ":"); strcat(build_info, line); strcat(build_info, "]\r\n[OPT:"); -#ifdef VARIABLE_SPINDLE - strcat(build_info, "V"); -#endif -#ifdef USE_LINE_NUMBERS + strcat(build_info, "V"); // variable spindle..always on now strcat(build_info, "N"); -#endif #ifdef COOLANT_MIST_PIN strcat(build_info, "M"); // TODO Need to deal with M8...it could be disabled #endif @@ -681,19 +672,11 @@ void report_realtime_status(uint8_t client) { #endif // Report realtime feed speed #ifdef REPORT_FIELD_CURRENT_FEED_SPEED -#ifdef VARIABLE_SPINDLE if (bit_istrue(settings.flags, BITFLAG_REPORT_INCHES)) sprintf(temp, "|FS:%.1f,%.0f", st_get_realtime_rate(), sys.spindle_speed / MM_PER_INCH); else sprintf(temp, "|FS:%.0f,%.0f", st_get_realtime_rate(), sys.spindle_speed); strcat(status, temp); -#else - if (bit_istrue(settings.flags, BITFLAG_REPORT_INCHES)) - sprintf(temp, "|F:%.1f", st_get_realtime_rate() / MM_PER_INCH); - else - sprintf(temp, "|F:%.0f", st_get_realtime_rate()); - strcat(status, temp); -#endif #endif #ifdef REPORT_FIELD_PIN_STATE uint8_t lim_pin_state = limits_get_state(); From 9cae3e7e2bc833acc6c0b218206446dbbda2db77 Mon Sep 17 00:00:00 2001 From: bdring Date: Mon, 13 Apr 2020 16:41:19 -0500 Subject: [PATCH 15/32] Playing with prefs ideas --- Grbl_Esp32/Grbl_Esp32.ino | 1 + Grbl_Esp32/grbl.h | 2 ++ Grbl_Esp32/grbl_preferences.cpp | 12 ++++++++++++ Grbl_Esp32/grbl_preferences.h | 9 +++++++++ Grbl_Esp32/tools/SpindleClass.cpp | 6 ++++++ Grbl_Esp32/tools/SpindleClass.h | 2 +- 6 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 Grbl_Esp32/grbl_preferences.cpp create mode 100644 Grbl_Esp32/grbl_preferences.h diff --git a/Grbl_Esp32/Grbl_Esp32.ino b/Grbl_Esp32/Grbl_Esp32.ino index 00d92839..dc055ed9 100644 --- a/Grbl_Esp32/Grbl_Esp32.ino +++ b/Grbl_Esp32/Grbl_Esp32.ino @@ -59,6 +59,7 @@ void setup() { grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Using machine:%s", MACHINE_STRING); #endif settings_init(); // Load Grbl settings from EEPROM + grbl_preferences_init(); stepper_init(); // Configure stepper pins and interrupt timers system_ini(); // Configure pinout pins and pin-change interrupt (Renamed due to conflict with esp32 files) memset(sys_position, 0, sizeof(sys_position)); // Clear machine position. diff --git a/Grbl_Esp32/grbl.h b/Grbl_Esp32/grbl.h index 067bcd55..933d7cea 100644 --- a/Grbl_Esp32/grbl.h +++ b/Grbl_Esp32/grbl.h @@ -28,6 +28,7 @@ #include #include #include +#include #include "driver/timer.h" @@ -38,6 +39,7 @@ #include "defaults.h" #include "settings.h" +#include "grbl_preferences.h" #include "system.h" #include "planner.h" diff --git a/Grbl_Esp32/grbl_preferences.cpp b/Grbl_Esp32/grbl_preferences.cpp new file mode 100644 index 00000000..dd3c980d --- /dev/null +++ b/Grbl_Esp32/grbl_preferences.cpp @@ -0,0 +1,12 @@ +#include "grbl.h" + +#define GRBL_PREFERENCES_NAMESPACE "Grbl_ESP32" + +Preferences grbL_preferences; + +void grbl_preferences_init() { + grbL_preferences.begin(GRBL_PREFERENCES_NAMESPACE, false); // readonly = false + spindle_read_prefs(grbL_preferences); // + grbL_preferences.end(); + +} \ No newline at end of file diff --git a/Grbl_Esp32/grbl_preferences.h b/Grbl_Esp32/grbl_preferences.h new file mode 100644 index 00000000..83c330a2 --- /dev/null +++ b/Grbl_Esp32/grbl_preferences.h @@ -0,0 +1,9 @@ + +#ifndef GRBL_PREFERENCES_H +#define GRBL_PREFERENCES_H + +#include "grbl.h" +void grbl_preferences_init(); + + +#endif \ No newline at end of file diff --git a/Grbl_Esp32/tools/SpindleClass.cpp b/Grbl_Esp32/tools/SpindleClass.cpp index 6436697a..208c4049 100644 --- a/Grbl_Esp32/tools/SpindleClass.cpp +++ b/Grbl_Esp32/tools/SpindleClass.cpp @@ -69,6 +69,12 @@ void spindle_select(uint8_t spindle_type) { my_spindle->init(); } +void spindle_read_prefs(Preferences &prefs) { + uint8_t foo = prefs.getUChar("SPIN_TYPE", SPINDLE_TYPE_PWM); +} + + + bool Spindle::isRateAdjusted() { return false; // default for basic spindles is false } diff --git a/Grbl_Esp32/tools/SpindleClass.h b/Grbl_Esp32/tools/SpindleClass.h index 4ff7a508..2ad3c669 100644 --- a/Grbl_Esp32/tools/SpindleClass.h +++ b/Grbl_Esp32/tools/SpindleClass.h @@ -137,6 +137,6 @@ extern Laser laser; extern DacSpindle dac_spindle; void spindle_select(uint8_t spindle_type); - +void spindle_read_prefs(Preferences &prefs); #endif From a6309198fa056d90db01a86a8315008614a8afc4 Mon Sep 17 00:00:00 2001 From: bdring Date: Mon, 13 Apr 2020 21:38:57 -0500 Subject: [PATCH 16/32] more work on prefs --- Grbl_Esp32/Grbl_Esp32.ino | 5 +++- Grbl_Esp32/grbl_preferences.cpp | 42 +++++++++++++++++++++++++++++---- Grbl_Esp32/grbl_preferences.h | 9 +++++-- Grbl_Esp32/nuts_bolts.cpp | 4 ++++ Grbl_Esp32/nuts_bolts.h | 1 + Grbl_Esp32/protocol.cpp | 17 +++++++++---- Grbl_Esp32/tools/PWMSpindle.cpp | 2 ++ 7 files changed, 67 insertions(+), 13 deletions(-) diff --git a/Grbl_Esp32/Grbl_Esp32.ino b/Grbl_Esp32/Grbl_Esp32.ino index dc055ed9..4add11ee 100644 --- a/Grbl_Esp32/Grbl_Esp32.ino +++ b/Grbl_Esp32/Grbl_Esp32.ino @@ -59,7 +59,7 @@ void setup() { grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Using machine:%s", MACHINE_STRING); #endif settings_init(); // Load Grbl settings from EEPROM - grbl_preferences_init(); + grbl_preferences.begin(GRBL_PREFERENCES_NAMESPACE, true); // readonly = false stepper_init(); // Configure stepper pins and interrupt timers system_ini(); // Configure pinout pins and pin-change interrupt (Renamed due to conflict with esp32 files) memset(sys_position, 0, sizeof(sys_position)); // Clear machine position. @@ -99,9 +99,11 @@ void setup() { bt_config.begin(); #endif inputBuffer.begin(); + grbl_preferences.end(); // everyone should have their prefs by now } void loop() { + grbl_preferences.begin(GRBL_PREFERENCES_NAMESPACE, true); // readonly = false // Reset system variables. uint8_t prior_state = sys.state; memset(&sys, 0, sizeof(system_t)); // Clear system struct variable. @@ -130,5 +132,6 @@ void loop() { // put your main code here, to run repeatedly: report_init_message(CLIENT_ALL); // Start Grbl main loop. Processes program inputs and executes them. + grbl_preferences.end(); // everyone should have their prefs by now protocol_main_loop(); } diff --git a/Grbl_Esp32/grbl_preferences.cpp b/Grbl_Esp32/grbl_preferences.cpp index dd3c980d..de7e0c79 100644 --- a/Grbl_Esp32/grbl_preferences.cpp +++ b/Grbl_Esp32/grbl_preferences.cpp @@ -1,12 +1,44 @@ #include "grbl.h" -#define GRBL_PREFERENCES_NAMESPACE "Grbl_ESP32" -Preferences grbL_preferences; + +Preferences grbl_preferences; void grbl_preferences_init() { - grbL_preferences.begin(GRBL_PREFERENCES_NAMESPACE, false); // readonly = false - spindle_read_prefs(grbL_preferences); // - grbL_preferences.end(); + grbl_preferences.begin(GRBL_PREFERENCES_NAMESPACE, false); // readonly = false + spindle_read_prefs(grbl_preferences); // + grbl_preferences.end(); +} + +bool grbl_prefs_change(const char* line, int* cmd, String& cmd_params) { + String buffer = line; + String key = ""; + String value = ""; + + // grbl_preferences.begin(GRBL_PREFERENCES_NAMESPACE, false); // readonly = false + + // TODO probably need more error checking + int close_bracket = buffer.indexOf("]", 2); // find the closing bracket + if (close_bracket > -1) { + key = buffer.substring(2, close_bracket); + if (close_bracket < buffer.length()) { + value = buffer.substring(close_bracket + 1); + } else { + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "no value found"); + return false; + } + } + + switch (buffer[2]) { + case 'S': + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Hey spindle please set key:%s to value:%s", key.c_str(), value.c_str()); + return true; + break; + default: + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Unknown setting prefix %c", buffer[2]); + } + // grbl_preferences.end(); + + return false; } \ No newline at end of file diff --git a/Grbl_Esp32/grbl_preferences.h b/Grbl_Esp32/grbl_preferences.h index 83c330a2..3e52deed 100644 --- a/Grbl_Esp32/grbl_preferences.h +++ b/Grbl_Esp32/grbl_preferences.h @@ -2,8 +2,13 @@ #ifndef GRBL_PREFERENCES_H #define GRBL_PREFERENCES_H -#include "grbl.h" -void grbl_preferences_init(); +#define GRBL_PREFERENCES_NAMESPACE "Grbl_ESP32" +#include "grbl.h" + +extern Preferences grbl_preferences; + +void grbl_preferences_init(); +bool grbl_prefs_change(const char* line, int* cmd, String& cmd_params); #endif \ No newline at end of file diff --git a/Grbl_Esp32/nuts_bolts.cpp b/Grbl_Esp32/nuts_bolts.cpp index 05c7b54a..19345f5b 100644 --- a/Grbl_Esp32/nuts_bolts.cpp +++ b/Grbl_Esp32/nuts_bolts.cpp @@ -166,4 +166,8 @@ float mapConstrain(float x, float in_min, float in_max, float out_min, float out return map_float(x, in_min, in_max, out_min, out_max); } +bool char_is_numeric(char value) { + return (value >= '0' && value <='9'); +} + diff --git a/Grbl_Esp32/nuts_bolts.h b/Grbl_Esp32/nuts_bolts.h index 0e3649bc..b31e2f9d 100644 --- a/Grbl_Esp32/nuts_bolts.h +++ b/Grbl_Esp32/nuts_bolts.h @@ -91,6 +91,7 @@ float mapConstrain(float x, float in_min, float in_max, float out_min, float out float map_float(float x, float in_min, float in_max, float out_min, float out_max); uint32_t map_uint32_t(uint32_t x, uint32_t in_min, uint32_t in_max, uint32_t out_min, uint32_t out_max); float constrain_float(float in, float min, float max); +bool char_is_numeric(char value); template void swap(T& a, T& b) { T c(a); a = b; b = c; diff --git a/Grbl_Esp32/protocol.cpp b/Grbl_Esp32/protocol.cpp index 0a2cb6bc..7827392e 100644 --- a/Grbl_Esp32/protocol.cpp +++ b/Grbl_Esp32/protocol.cpp @@ -118,11 +118,18 @@ void protocol_main_loop() { } else if (line[0] == '[') { int cmd = 0; String cmd_params; - if (COMMANDS::check_command(line, &cmd, cmd_params)) { - ESPResponseStream espresponse(client, true); - if (!COMMANDS::execute_internal_command(cmd, cmd_params, LEVEL_GUEST, &espresponse)) - report_status_message(STATUS_GCODE_UNSUPPORTED_COMMAND, CLIENT_ALL); - } else grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Unknow Command...%s", line); + if (line[1] == '$') { // it is a Grbl preference + if (!grbl_prefs_change(line, &cmd, cmd_params)){ + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Unknow Command...%s", line); + } + } else { // it might be a [ESP...] comamnd + if (COMMANDS::check_command(line, &cmd, cmd_params)) { + ESPResponseStream espresponse(client, true); + if (!COMMANDS::execute_internal_command(cmd, cmd_params, LEVEL_GUEST, &espresponse)) + report_status_message(STATUS_GCODE_UNSUPPORTED_COMMAND, CLIENT_ALL); + } else + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Unknow Command...%s", line); + } } else if (sys.state & (STATE_ALARM | STATE_JOG)) { // Everything else is gcode. Block if in alarm or jog mode. report_status_message(STATUS_SYSTEM_GC_LOCK, client); diff --git a/Grbl_Esp32/tools/PWMSpindle.cpp b/Grbl_Esp32/tools/PWMSpindle.cpp index f3b640ce..f4448dbe 100644 --- a/Grbl_Esp32/tools/PWMSpindle.cpp +++ b/Grbl_Esp32/tools/PWMSpindle.cpp @@ -31,6 +31,8 @@ void PWMSpindle::init() { return; // We cannot continue without the output pin } + _min_rpm = grbl_preferences.getFloat("SPIN_MAX_RPM", DEFAULT_SPINDLE_MIN_VALUE); + _pwm_freq = settings.spindle_pwm_freq; _pwm_period = ((1 << settings.spindle_pwm_precision_bits) - 1); From 1a8ff1f3a4d83fbef27e271669d62697c4d7a83e Mon Sep 17 00:00:00 2001 From: bdring Date: Fri, 17 Apr 2020 18:11:49 -0500 Subject: [PATCH 17/32] added settings class --- Grbl_Esp32/wmb_settings.cpp | 715 ++++++++++++++++++++++++++++++++++++ 1 file changed, 715 insertions(+) create mode 100644 Grbl_Esp32/wmb_settings.cpp diff --git a/Grbl_Esp32/wmb_settings.cpp b/Grbl_Esp32/wmb_settings.cpp new file mode 100644 index 00000000..095925a0 --- /dev/null +++ b/Grbl_Esp32/wmb_settings.cpp @@ -0,0 +1,715 @@ +#include +#include +#include +#include +#include +#include +#include "./defaults.h" +using namespace std; + +// These status values are just assigned at random, for testing +// they need to be synced with the rest of Grbl +typedef enum { + STATUS_OK = 0, + STATUS_INVALID_STATEMENT, + STATUS_NUMBER_RANGE, + STATUS_INVALID_VALUE, + STATUS_IDLE_ERROR, +} err_t; + +enum { + BITFLAG_INVERT_ST_ENABLE = 1, + BITFLAG_INVERT_LIMIT_PINS = 2, + BITFLAG_INVERT_PROBE_PIN = 4, + BITFLAG_REPORT_INCHES = 8, + BITFLAG_SOFT_LIMIT_ENABLE = 16, + BITFLAG_HARD_LIMIT_ENABLE = 32, + BITFLAG_HOMING_ENABLE = 64, + BITFLAG_LASER_MODE = 128, +}; +#define DEFAULT_SPINDLE_TYPE 0 +#define DEFAULT_SPINDLE_BIT_PRECISION 10 +enum { + STATE_IDLE = 0, + STATE_JOG, +}; +#define MAXLINE 128 +int client; + +struct { + int flags; +} settings; + +struct { + int state; +} sys; + +#define MAX_N_AXIS 6 +#define MESSAGE_RESTORE_DEFAULTS "restoring defaults" +enum { + SETTINGS_RESTORE_DEFAULTS, + SETTINGS_RESTORE_PARAMETERS, + SETTINGS_RESTORE_ALL, + SETTINGS_RESTORE_WIFI_SETTINGS, + SETTINGS_WIPE, +}; + +err_t my_spindle_init(); +err_t limits_init(); +err_t also_soft_limit(); +void settings_restore(int); +void report_feedback_message(const char *); +err_t report_normal_settings(uint8_t); +err_t report_extended_settings(uint8_t); +err_t report_gcode_modes(uint8_t); +err_t report_build_info(uint8_t); +err_t report_startup_lines(uint8_t); +err_t toggle_check_mode(uint8_t); +err_t disable_alarm_lock(uint8_t); +err_t report_ngc(uint8_t); +err_t home_all(uint8_t); +err_t home_x(uint8_t); +err_t home_y(uint8_t); +err_t home_z(uint8_t); +err_t home_a(uint8_t); +err_t home_b(uint8_t); +err_t home_c(uint8_t); +err_t sleep(uint8_t); +err_t gc_execute_line(char *line, uint8_t client); + +void mc_reset(); + +err_t check_motor_settings() { return STATUS_OK; } +err_t settings_spi_driver_init() { return STATUS_OK; } + +// SettingsList is a linked list of all settings, +// so common code can enumerate them. +class Setting; +Setting *SettingsList = NULL; + +// This abstract class defines the generic interface that +// is used to set and get values for all settings independent +// of their underlying data type. The values are always +// represented as human-readable strings. This generic +// interface is used for managing settings via the user interface. +class Setting { + public: + + // Add each constructed setting to the linked list + Setting *link; + Setting(const char* name) { + displayName = name; + link = SettingsList; + SettingsList = this; + } + const char* getName() { return displayName; }; + + // load() reads the backing store to get the current + // value of the setting. This could be slow so it + // should be done infrequently, typically once at startup. + virtual void load() =0; + + // commit() puts the current value of the setting into + // the backing store. + // virtual void commit() =0; + + virtual err_t setStringValue(string value) =0; + virtual string getStringValue() =0; + + private: + const char* displayName; +}; + +// This template class, derived from the generic abstract +// class, lets you store an individual setting as typed data. + +template +class TypedSetting : public Setting { + public: + TypedSetting(const char* name, T defVal, T minVal, T maxVal, err_t (*f)() = NULL) : + Setting(name), + defaultValue(defVal), + currentValue(defVal), + minValue(minVal), + maxValue(maxVal), + checker(f) + { } + void load() { + if (isfloat) { + //p storedValue = preferences.getFloat(displayName, defaultValue); + } else { + //p storedValue = preferences.getInt(displayName, defaultValue); + } // Read value from backing store + currentValue = storedValue; + } + void commit() { + if (storedValue != currentValue) { + if (storedValue == defaultValue) { + //p preferences.remove(displayName); + } else { + if (isfloat) { + //p preferences.putFloat(displayName, currentValue); + } else { + //p preferences.putInt(displayName, currentValue); + } + } + } + } + + T get() { return currentValue; } + err_t set(T value) { currentValue = value; return STATUS_OK; } + err_t string_to_value(string s, T &value) { + T convertedValue; + try { + convertedValue = stof(s); + } + catch (int e) { + return STATUS_INVALID_VALUE; + } + if (convertedValue < minValue || convertedValue > maxValue) { + return STATUS_NUMBER_RANGE; + } + value = convertedValue; + return STATUS_OK; + } + string value_to_string (T value) { + return to_string(value); + } + + // Standard methods of the abstract class "Setting" + err_t setStringValue(string s) { + T newValue; + err_t ret = string_to_value(s, newValue); + if (ret) return ret; + if (checker && (ret = checker())) return ret; + currentValue = newValue; + return ret; + } + string getStringValue () { + return to_string(get()); + } + + private: + T defaultValue; + T currentValue; + T storedValue; + T minValue; + T maxValue; + const bool isfloat = typeid(T) == typeid(float); + err_t (*checker)(); +}; + +typedef TypedSetting FloatSetting; +typedef TypedSetting IntSetting; + +class AxisSettings { + public: + string name; + FloatSetting steps_per_mm; + FloatSetting max_rate; + FloatSetting acceleration; + FloatSetting max_travel; + FloatSetting run_current; + FloatSetting hold_current; + IntSetting microsteps; + IntSetting stallguard; + AxisSettings(string axisName, float steps, float rate, float accel, float travel, + float run, float hold, int usteps, int stall) : + name(axisName), + steps_per_mm((axisName+"_STEPS_PER_MM").c_str(), steps, 1.0, 50000.0, check_motor_settings), + max_rate((axisName+"_MAX_RATE").c_str(), rate, 1.0, 1000000.0, check_motor_settings), + acceleration((axisName+"_ACCELERATION").c_str(), accel, 1.0, 100000.0), + max_travel((axisName+"_MAX_TRAVEL").c_str(), travel, 1.0, 100000.0), // Note! this values is entered as scaler but store negative + run_current((axisName+"_RUN_CURRENT").c_str(), run, 0.05, 20.0, settings_spi_driver_init), + hold_current((axisName+"_HOLD_CURRENT").c_str(), hold, 0.0, 100.0, settings_spi_driver_init), + microsteps((axisName+"_MICROSTEPS").c_str(), usteps, 1, 256, settings_spi_driver_init), + stallguard((axisName+"_STALLGUARD").c_str(), stall, 0, 100, settings_spi_driver_init) + {} +}; +AxisSettings x_axis_settings = { + "X", + DEFAULT_X_STEPS_PER_MM, + DEFAULT_X_MAX_RATE, + DEFAULT_X_ACCELERATION, + DEFAULT_X_MAX_TRAVEL, + DEFAULT_X_CURRENT, + DEFAULT_X_HOLD_CURRENT, + DEFAULT_X_MICROSTEPS, + DEFAULT_X_STALLGUARD +}; + +AxisSettings y_axis_settings = { + "Y", + DEFAULT_Y_STEPS_PER_MM, + DEFAULT_Y_MAX_RATE, + DEFAULT_Y_ACCELERATION, + DEFAULT_Y_MAX_TRAVEL, + DEFAULT_Y_CURRENT, + DEFAULT_Y_HOLD_CURRENT, + DEFAULT_Y_MICROSTEPS, + DEFAULT_Y_STALLGUARD +}; + +AxisSettings z_axis_settings = { + "Z", + DEFAULT_Z_STEPS_PER_MM, + DEFAULT_Z_MAX_RATE, + DEFAULT_Z_ACCELERATION, + DEFAULT_Z_MAX_TRAVEL, + DEFAULT_Z_CURRENT, + DEFAULT_Z_HOLD_CURRENT, + DEFAULT_Z_MICROSTEPS, + DEFAULT_Z_STALLGUARD +}; + +AxisSettings a_axis_settings = { + "A", + DEFAULT_A_STEPS_PER_MM, + DEFAULT_A_MAX_RATE, + DEFAULT_A_ACCELERATION, + DEFAULT_A_MAX_TRAVEL, + DEFAULT_A_CURRENT, + DEFAULT_A_HOLD_CURRENT, + DEFAULT_A_MICROSTEPS, + DEFAULT_A_STALLGUARD +}; + +AxisSettings b_axis_settings = { + "B", + DEFAULT_B_STEPS_PER_MM, + DEFAULT_B_MAX_RATE, + DEFAULT_B_ACCELERATION, + DEFAULT_B_MAX_TRAVEL, + DEFAULT_B_CURRENT, + DEFAULT_B_HOLD_CURRENT, + DEFAULT_B_MICROSTEPS, + DEFAULT_B_STALLGUARD +}; + +AxisSettings c_axis_settings = { + "C", + DEFAULT_C_STEPS_PER_MM, + DEFAULT_C_MAX_RATE, + DEFAULT_C_ACCELERATION, + DEFAULT_C_MAX_TRAVEL, + DEFAULT_C_CURRENT, + DEFAULT_C_HOLD_CURRENT, + DEFAULT_C_MICROSTEPS, + DEFAULT_C_STALLGUARD +}; + +AxisSettings axis_settings[] = { + x_axis_settings, + y_axis_settings, + z_axis_settings, + a_axis_settings, + b_axis_settings, + c_axis_settings, +}; + +class StringSetting : public Setting { + private: + string currentValue; + string storedValue; + string defaultValue; + + public: + StringSetting(const char* name, string defVal) : + Setting(name), + defaultValue(defVal), + currentValue(defVal) + { }; + void load() { + //p storedValue = preferences.getString(displayName, defaultValue); + currentValue = storedValue; + } + void commit() { + if (storedValue != currentValue) { + if (storedValue == defaultValue) { + //p preferences.remove(displayName); + } else { + //p preferences.putString(displayName, currentValue); + } + } + } + string get() { return currentValue; } + err_t set(string value) { currentValue = value; return STATUS_OK; } + err_t string_to_value(string s, string &value) { + value = s; + return STATUS_OK; + } + string value_to_string (string value) { return value; } + err_t setStringValue(string s) { + currentValue = s; + return STATUS_OK; + } + string getStringValue() { return currentValue; } +}; +StringSetting startup_line_0("N0", ""); +StringSetting startup_line_1("N1", ""); +StringSetting build_info("I", ""); + +// Single-use class for the $RST= command +// There is no underlying stored value +class SettingsReset : public Setting { + public: + SettingsReset(const char* name) : + Setting(name) + { } + void load() { + } + void commit() { + } + string get() { return 0; } + err_t set(int value) { + settings_restore(value); + report_feedback_message(MESSAGE_RESTORE_DEFAULTS); + mc_reset(); // Ensure settings are initialized correctly + return STATUS_OK; + } + err_t string_to_value(string s, int &value) { + switch (s[0]) { + case '$': value = SETTINGS_RESTORE_DEFAULTS; break; + case '#': value = SETTINGS_RESTORE_PARAMETERS; break; + case '*': value = SETTINGS_RESTORE_ALL; break; + case '@': value = SETTINGS_RESTORE_WIFI_SETTINGS; break; + case '!': value = SETTINGS_WIPE; break; + default: return STATUS_INVALID_VALUE; + } + return STATUS_OK; + } + err_t setStringValue(string s) { + int value; + err_t ret = string_to_value(s, value); + return ret ? ret : set(value); + } + string value_to_string (int value) { + switch(value) { + case SETTINGS_RESTORE_DEFAULTS: return "$"; break; + case SETTINGS_RESTORE_PARAMETERS: return "#"; break; + case SETTINGS_RESTORE_ALL: return "*"; break; + case SETTINGS_RESTORE_WIFI_SETTINGS: return "@"; break; + case SETTINGS_WIPE: return "!"; break; + default: return ""; + } + } + string getStringValue() { return ""; } +}; + +IntSetting pulse_microseconds("STEP_PULSE", DEFAULT_STEP_PULSE_MICROSECONDS, 3, 1000); +IntSetting stepper_idle_lock_time("STEPPER_IDLE_TIME", DEFAULT_STEPPER_IDLE_LOCK_TIME, 0, 255); + +IntSetting step_invert_mask("STEP_INVERT_MASK", DEFAULT_STEPPING_INVERT_MASK, 0, (1<init(); + +IntSetting status_mask("STATUS_MASK", DEFAULT_STATUS_REPORT_MASK, 0, 2); +FloatSetting junction_deviation("JUNCTION_DEVIATION", DEFAULT_JUNCTION_DEVIATION, 0, 10); +FloatSetting arc_tolerance("ARC_TOLERANCE", DEFAULT_ARC_TOLERANCE, 0, 1); + +FloatSetting homing_feed_rate("HOMING_FEED", DEFAULT_HOMING_FEED_RATE, 0, 10000); +FloatSetting homing_seek_rate("HOMING_SEEK", DEFAULT_HOMING_SEEK_RATE, 0, 10000); +FloatSetting homing_debounce("HOMING_DEBOUNCE", DEFAULT_HOMING_DEBOUNCE_DELAY, 0, 10000); +FloatSetting homing_pulloff("HOMING_PULLOFF", DEFAULT_HOMING_PULLOFF, 0, 1000); +FloatSetting spindle_pwm_freq("SPINDLE_PWM_FREQ", DEFAULT_SPINDLE_FREQ, 0, 100000); +FloatSetting rpm_max("RPM_MAX", DEFAULT_SPINDLE_RPM_MAX, 0, 100000); +FloatSetting rpm_min("RPM_MIN", DEFAULT_SPINDLE_RPM_MIN, 0, 100000); + +FloatSetting spindle_pwm_off_value("SPINDLE_PWM_OFF_VALUE", DEFAULT_SPINDLE_OFF_VALUE, 0.0, 100.0); // these are percentages +FloatSetting spindle_pwm_min_value("SPINDLE_PWM_MIN_VALUE", DEFAULT_SPINDLE_MIN_VALUE, 0.0, 100.0); +FloatSetting spindle_pwm_max_value("SPINDLE_PWM_MAX_VALUE", DEFAULT_SPINDLE_MAX_VALUE, 0.0, 100.0); +IntSetting spindle_pwm_bit_precision("SPINDLE_PWM_BIT_PRECISION", DEFAULT_SPINDLE_BIT_PRECISION, 1, 16); + +StringSetting spindle_type("SPINDLE_TYPE", DEFAULT_SPINDLE_TYPE); + +// The following table maps numbered settings to their settings +// objects, for backwards compatibility. It is used if the +// line is of the form "$key=value". If a key match is found, +// the object's setValueString method is invoked with the value +// as argument. If no match is found, the list of named settings +// is searched, with the same behavior on a match. + +// These are compatibily aliases for Classic GRBL +std::map numberedSettings = { + { "0", &pulse_microseconds }, + { "1", &stepper_idle_lock_time }, + { "2", &step_invert_mask }, + { "3", &dir_invert_mask }, + { "4", &step_enable_invert }, + { "5", &limit_invert }, + { "6", &probe_invert }, + { "10", &status_mask }, + { "11", &junction_deviation }, + { "12", &arc_tolerance }, + { "13", &report_inches }, + { "20", &soft_limits }, + { "21", &hard_limits }, + { "22", &homing_enable }, + { "23", &homing_dir_mask }, + { "24", &homing_feed_rate }, + { "25", &homing_seek_rate }, + { "26", &homing_debounce }, + { "27", &homing_pulloff }, + { "30", &rpm_max }, + { "31", &rpm_min }, + { "32", &laser_mode }, + { "100", &x_axis_settings.steps_per_mm }, + { "101", &y_axis_settings.steps_per_mm }, + { "102", &z_axis_settings.steps_per_mm }, + { "110", &x_axis_settings.max_rate }, + { "111", &y_axis_settings.max_rate }, + { "112", &z_axis_settings.max_rate }, + { "120", &x_axis_settings.acceleration }, + { "121", &y_axis_settings.acceleration }, + { "122", &z_axis_settings.acceleration }, + { "130", &x_axis_settings.max_travel }, + { "131", &y_axis_settings.max_travel }, + { "132", &z_axis_settings.max_travel }, +}; + +// FIXME - jog may need to be special-cased in the parser, since +// it is not really a setting and the entire line needs to be +// sent to gc_execute_line. It is probably also more time-critical +// than actual settings, which change infrequently, so handling +// it early is probably prudent. +uint8_t jog_set(uint8_t *value, uint8_t client) { + // Execute only if in IDLE or JOG states. + if (sys.state != STATE_IDLE && sys.state != STATE_JOG) return STATUS_IDLE_ERROR; + + // restore the $J= prefix because gc_execute_line() expects it + char line[MAXLINE]; + strcpy(line, "$J="); + strncat(line, (char *)value, MAXLINE-strlen("$J=")-1); + + return gc_execute_line(line, client); // NOTE: $J= is ignored inside g-code parser and used to detect jog motions. +} + +// The following table is used if the line is of the form "$key\n" +// i.e. dollar commands without "=" +// The key value is matched against the string and the corresponding +// function is called with no arguments. +// If there is no key match an error is reported +typedef err_t (*Command_t)(uint8_t); +std::map dollarCommands = { + { "$", report_normal_settings }, + { "+", report_extended_settings }, + { "G", report_gcode_modes }, + { "C", toggle_check_mode }, + { "X", disable_alarm_lock }, + { "#", report_ngc }, + { "H", home_all }, + { "HX", home_x }, + { "HY", home_y }, + { "HZ", home_z }, + { "HA", home_a }, + { "HB", home_b }, + { "HC", home_c }, + { "SLP", sleep }, + { "I", report_build_info }, + { "N", report_startup_lines }, +}; + +// normalize_key puts a key string into canonical form - +// upper case without whitespace. +// start points to a null-terminated string. +// Returns the first substring that does not contain whitespace, +// converted to upper case. +char *normalize_key(char *start) { + char c; + + // In the usual case, this loop will exit on the very first test, + // because the first character is likely to be non-white. + // Null ('\0') is not considered to be a space character. + while (isspace(c = *start) && c != '\0') { + ++start; + } + + // start now points to either a printable character or end of string + if (c == '\0') { + return start; + } + + // Having found the beginning of the printable string, + // we now scan forward, converting lower to upper case, + // until we find a space character. + char *end; + for (end = start; (c = *end) != '\0' && !isspace(c); end++) { + if (islower(c)) { + *end = toupper(c); + } + } + + // end now points to either a whitespace character of end of string + // In either case it is okay to place a null there + *end = '\0'; + + return start; +} + +// This is for changing settings with $key=value . +// Lookup key in the numberedSettings map. If found, execute +// the corresponding object's "set" method. Otherwise fail. +err_t do_setting(const char *key, char *value, uint8_t client) { + + // First search this numberedSettings array - aliases + // for the underlying named settings. + map::iterator it = numberedSettings.find(key); + if (it != numberedSettings.end()) { + return it->second->setStringValue(value); + } + + // Then search the list of named settings. + for (Setting *s = SettingsList; s; s = s->link) { + if (strcmp(s->getName(), key) == 0) { + return s->setStringValue(value); + } + } + + return STATUS_INVALID_STATEMENT; +} + +// This is for bare commands like "$RST" - no equals sign. +// Lookup key in the dollarCommands map. If found, execute +// the corresponding command. +// As an enhancement to Classic GRBL, if the key is not found +// in the commands map, look it up in the lists of settings +// and display the current value. +err_t do_command(const char *key, uint8_t client) { + + map::iterator i = dollarCommands.find(key); + if (i != dollarCommands.end()) { + return i->second(client); + } + + // Enhancement - not in Classic GRBL: + // If it is not a command, look up the key + // as a setting and display the value. + + map::iterator it = numberedSettings.find(key); + if (it != numberedSettings.end()) { + Setting *s = it->second; + cout << key << "=" << s->getStringValue() << '\n'; + return STATUS_OK; + } + + for (Setting *s = SettingsList; s; s = s->link) { + // if (s->getName().compare(k)) { + if (strcmp(s->getName(), key) == 0) { + cout << key << "=" << s->getStringValue() << '\n'; + return STATUS_OK; + } + } + + return STATUS_INVALID_STATEMENT; +} + +uint8_t system_execute_line(char* line, uint8_t client) { + char *value = strchr(line, '='); + + if (value) { + // Equals was found; replace it with null and skip it + *value++ = '\0'; + do_setting(normalize_key(line), value, client); + } else { + // No equals, so it must be a command + do_command(normalize_key(line), client); + } +} + +void list_settings() +{ + for (Setting *s = SettingsList; s; s = s->link) { + cout << s->getName() << " " << s->getStringValue() << '\n'; + } +} + +void list_numbered_settings() +{ + for (map::iterator it = numberedSettings.begin(); + it != numberedSettings.end(); + it++) { + cout << it->first << ": " << it->second->getStringValue() << '\n'; + } +} + +int main() +{ + list_settings(); +} From 2a0cf73d217d86a6869a557895fd2a7f02d49b98 Mon Sep 17 00:00:00 2001 From: bdring Date: Sat, 18 Apr 2020 11:24:04 -0500 Subject: [PATCH 18/32] Added a basic HuangyangSpinlde class - just basic features (CW, CCW and RPM) - no continuous monitoring during run yet. --- Grbl_Esp32/Machines/4axis_external_driver.h | 7 +- Grbl_Esp32/gcode.cpp | 10 +- Grbl_Esp32/machine.h | 2 +- Grbl_Esp32/report.cpp | 19 + Grbl_Esp32/report.h | 2 +- Grbl_Esp32/system.h | 1 + Grbl_Esp32/tools/DacSpindle.cpp | 5 +- Grbl_Esp32/tools/HuanyangSpindle.cpp | 243 +++++++ Grbl_Esp32/tools/NullSpindle.cpp | 1 + Grbl_Esp32/tools/PWMSpindle.cpp | 5 +- Grbl_Esp32/tools/RelaySpindle.cpp | 2 + Grbl_Esp32/tools/SpindleClass.cpp | 5 + Grbl_Esp32/tools/SpindleClass.h | 51 +- Grbl_Esp32/wmb_settings.cpp | 715 -------------------- 14 files changed, 331 insertions(+), 737 deletions(-) create mode 100644 Grbl_Esp32/tools/HuanyangSpindle.cpp delete mode 100644 Grbl_Esp32/wmb_settings.cpp diff --git a/Grbl_Esp32/Machines/4axis_external_driver.h b/Grbl_Esp32/Machines/4axis_external_driver.h index f88204ad..f093925c 100644 --- a/Grbl_Esp32/Machines/4axis_external_driver.h +++ b/Grbl_Esp32/Machines/4axis_external_driver.h @@ -43,9 +43,10 @@ #define SPINDLE_PWM_PIN GPIO_NUM_25 #define SPINDLE_ENABLE_PIN GPIO_NUM_22 -#define MODBUS_TX GPIO_NUM_17 -#define MODBUS_RX GPIO_NUM_4 -#define MODBUS_CTRL GPIO_NUM_16 +#define HUANYANG_TXD_PIN GPIO_NUM_17 +#define HUANYANG_RXD_PIN GPIO_NUM_4 +#define HUANYANG_RTS_PIN GPIO_NUM_16 + #define X_LIMIT_PIN GPIO_NUM_34 #define Y_LIMIT_PIN GPIO_NUM_35 diff --git a/Grbl_Esp32/gcode.cpp b/Grbl_Esp32/gcode.cpp index 6c8e8a66..ec3856bf 100644 --- a/Grbl_Esp32/gcode.cpp +++ b/Grbl_Esp32/gcode.cpp @@ -304,14 +304,10 @@ uint8_t gc_execute_line(char* line, uint8_t client) { gc_block.modal.spindle = SPINDLE_ENABLE_CW; break; case 4: // Supported if SPINDLE_DIR_PIN is defined or laser mode is on. -#ifndef SPINDLE_DIR_PIN - // if laser mode is not on then this is an unsupported command - if bit_isfalse(settings.flags, BITFLAG_LASER_MODE) { + if (my_spindle->is_reversable || bit_istrue(settings.flags, BITFLAG_LASER_MODE)) + gc_block.modal.spindle = SPINDLE_ENABLE_CCW; + else FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); - break; - } -#endif - gc_block.modal.spindle = SPINDLE_ENABLE_CCW; break; case 5: gc_block.modal.spindle = SPINDLE_DISABLE; diff --git a/Grbl_Esp32/machine.h b/Grbl_Esp32/machine.h index 1d49672e..d9bcc42f 100644 --- a/Grbl_Esp32/machine.h +++ b/Grbl_Esp32/machine.h @@ -8,7 +8,7 @@ // !!! For initial testing, start with test_drive.h which disables // all I/O pins -#include "Machines/3axis_v4.h" +#include "Machines/4axis_external_driver.h" // !!! For actual use, change the line above to select a board // from Machines/, for example: diff --git a/Grbl_Esp32/report.cpp b/Grbl_Esp32/report.cpp index af9a02d0..5d69eed2 100644 --- a/Grbl_Esp32/report.cpp +++ b/Grbl_Esp32/report.cpp @@ -775,4 +775,23 @@ void report_gcode_comment(char* comment) { msg[index - offset] = 0; // null terminate grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "GCode Comment...%s", msg); } +} + + +/* + Print a message in hex formate + Ex: report_hex_msg(msg, "Rx:", 6); + Would could print [MSG Rx: 0x01 0x03 0x01 0x08 0x31 0xbf] +*/ +void report_hex_msg(char* buf, const char *prefix, int len) { + char report[200]; + char temp[20]; + sprintf(report, "%s", prefix); + for (int i = 0; i < len; i++) { + sprintf(temp, " 0x%02X", buf[i]); + strcat(report, temp); + } + + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "%s", report); + } \ No newline at end of file diff --git a/Grbl_Esp32/report.h b/Grbl_Esp32/report.h index 5b546413..8f0042ea 100644 --- a/Grbl_Esp32/report.h +++ b/Grbl_Esp32/report.h @@ -170,6 +170,6 @@ void report_gcode_comment(char* comment); void report_realtime_debug(); #endif - +void report_hex_msg(char* buf, const char *prefix, int len); #endif diff --git a/Grbl_Esp32/system.h b/Grbl_Esp32/system.h index d282e4d4..6cf6758f 100644 --- a/Grbl_Esp32/system.h +++ b/Grbl_Esp32/system.h @@ -74,6 +74,7 @@ extern system_t sys; #define EXEC_ALARM_HOMING_FAIL_DOOR 7 #define EXEC_ALARM_HOMING_FAIL_PULLOFF 8 #define EXEC_ALARM_HOMING_FAIL_APPROACH 9 +#define EXEC_ALARM_SPINDLE_CONTROL 10 // Override bit maps. Realtime bitflags to control feed, rapid, spindle, and coolant overrides. // Spindle/coolant and feed/rapids are separated into two controlling flag variables. diff --git a/Grbl_Esp32/tools/DacSpindle.cpp b/Grbl_Esp32/tools/DacSpindle.cpp index 1410262d..2467080c 100644 --- a/Grbl_Esp32/tools/DacSpindle.cpp +++ b/Grbl_Esp32/tools/DacSpindle.cpp @@ -46,8 +46,11 @@ void DacSpindle :: init() { if (_enable_pin != UNDEFINED_PIN) pinMode(_enable_pin, OUTPUT); - if (_direction_pin != UNDEFINED_PIN) + if (_direction_pin != UNDEFINED_PIN) { pinMode(_direction_pin, OUTPUT); + } + is_reversable = (_direction_pin != UNDEFINED_PIN); + config_message(); } diff --git a/Grbl_Esp32/tools/HuanyangSpindle.cpp b/Grbl_Esp32/tools/HuanyangSpindle.cpp new file mode 100644 index 00000000..028a9edc --- /dev/null +++ b/Grbl_Esp32/tools/HuanyangSpindle.cpp @@ -0,0 +1,243 @@ +/* + HuanyangSpindle.cpp + + This is for a Huanyang VFD based spindle via RS485 Modbus. + + Part of Grbl_ESP32 + 2020 - Bart Dring + + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . + + // VFD frequencies are in Hz. Multiple by 60 for RPM + + // before using spindle, VFD must be setup for RS485 and match your spindle + PD001 2 RS485 Control of run commands + PD002 2 RS485 Control of operating frequency + PD005 400 Maximum frequency Hz + PD011 120 Min Speed (Recommend Aircooled=120 Water=100) + PD014 10 Acceleration time (Test to optimize) + PD015 10 Deceleration time (Test to optimize) + PD023 1 Reverse run enabled + PD142 3.7 Max current Amps (0.8kw=3.7 1.5kw=7.0) + PD163 1 RS485 Address: 1 + PD164 1 RS485 Baud rate: 9600 + PD165 3 RS485 Mode: RTU, 8N1 + + Some references.... + Manual: http://www.hy-electrical.com/bf/inverter.pdf + Reference: https://github.com/Smoothieware/Smoothieware/blob/edge/src/modules/tools/spindle/HuanyangSpindleControl.cpp + Refernece: https://gist.github.com/Bouni/803492ed0aab3f944066 + VFD settings: https://www.hobbytronics.co.za/Content/external/1159/Spindle_Settings.pdf + + TODO + Returning errors to Grbl and handling them in Grbl. + What happens if the VFD does not respond + Add periodic pinging of VFD in run mode to see if it is still at correct RPM +*/ + +#include "grbl.h" +#include "SpindleClass.h" +#include "driver/uart.h" + +#define HUANYANG_ADDR 0x01 +#define HUANYANG_UART_PORT UART_NUM_2 // hard coded for this port right now +#define ECHO_TEST_CTS UART_PIN_NO_CHANGE // CTS pin is not used +#define HUANYANG_BAUD_RATE 9600 // PD164 setting +#define HUANYANG_BUF_SIZE 127 +#define RESPONSE_WAIT_TICKS 80 // how long to wait for a response + +void HuanyangSpindle :: init() { + + // fail if numbers are not defined + if (!get_pin_numbers()) { + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Huanyang spindle errors"); + return; + } + + uart_driver_delete(HUANYANG_UART_PORT); // this allows us to init() more than once if settings have changed. + + uart_config_t uart_config = { + .baud_rate = HUANYANG_BAUD_RATE, + .data_bits = UART_DATA_8_BITS, + .parity = UART_PARITY_DISABLE, + .stop_bits = UART_STOP_BITS_1, + .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, + .rx_flow_ctrl_thresh = 122, + }; + + uart_param_config(HUANYANG_UART_PORT, &uart_config); + + uart_set_pin(HUANYANG_UART_PORT, + _txd_pin, + _rxd_pin, + _rts_pin, + UART_PIN_NO_CHANGE); + + uart_driver_install(HUANYANG_UART_PORT, + HUANYANG_BUF_SIZE * 2, + 0, + 0, + NULL, + 0); + + uart_set_mode(HUANYANG_UART_PORT, UART_MODE_RS485_HALF_DUPLEX); + + is_reversable = true; + + config_message(); +} + +// Checks for all the required pin definitions +// It returns a message for each missing pin +// Returns true if all pins are defined. +bool HuanyangSpindle :: get_pin_numbers() { + bool pins_ok = true; + +#ifdef HUANYANG_TXD_PIN + _txd_pin = HUANYANG_TXD_PIN; +#else + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Missing HUANYANG_TXD_PIN"); + pins_ok = false; +#endif + +#ifdef HUANYANG_RXD_PIN + _rxd_pin = HUANYANG_RXD_PIN; +#else + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "No HUANYANG_RXD_PIN"); + pins_ok = false; +#endif + +#ifdef HUANYANG_RTS_PIN + _rts_pin = HUANYANG_RTS_PIN; +#else + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "No HUANYANG_RTS_PIN"); + pins_ok = false; +#endif + + return pins_ok; +} + +void HuanyangSpindle :: config_message() { + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Huanyang Spindle Tx:%d Rx:%d RTS:%d", _txd_pin, _rxd_pin, _rts_pin); +} + +/* + ADDR CMD LEN DATA CRC + 0x01 0x03 0x01 0x01 0x31 0x88 Start spindle clockwise + 0x01 0x03 0x01 0x08 0xF1 0x8E Stop spindle + 0x01 0x03 0x01 0x11 0x30 0x44 Start spindle counter-clockwise +*/ +void HuanyangSpindle :: set_state(uint8_t state, float rpm) { + if (sys.abort) + return; // Block during abort. + + _state = state; // store locally for faster get_state() + + if (!set_mode(state)) { // try to set state. If it fails there is no need to try to set RPM + system_set_exec_alarm(EXEC_ALARM_SPINDLE_CONTROL); + return; + } + + if (state == SPINDLE_DISABLE) { + sys.spindle_speed = 0.0; + return; + } + + set_rpm(rpm); + sys.report_ovr_counter = 0; // Set to report change immediately +} + +bool HuanyangSpindle :: set_mode(uint8_t mode) { + char msg[6] = {HUANYANG_ADDR, 0x03, 0x01, 0x00, 0x00, 0x00}; + + if (mode == SPINDLE_ENABLE_CW) + msg[3] = 0x01; + else if (mode == SPINDLE_ENABLE_CCW) + msg[3] = 0x11; + else //SPINDLE_DISABLE + msg[3] = 0x08; + + add_ModRTU_CRC(msg, sizeof(msg)); + + //report_hex_msg(msg, "To VFD:", sizeof(msg)); // TODO for debugging comment out + + uart_write_bytes(HUANYANG_UART_PORT, msg, sizeof(msg)); + + return get_response(6); +} + + +bool HuanyangSpindle :: get_response(uint16_t length) { + uint8_t rx_message[10]; + + uint16_t read_length = uart_read_bytes(HUANYANG_UART_PORT, rx_message, length, RESPONSE_WAIT_TICKS); + if (read_length < length) { + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Spindle RS485 Unresponsive"); + return false; + } + // check CRC? + // Check address? + + return true; +} + +/* + ADDR CMD LEN DATA CRC + 0x01 0x05 0x02 0x09 0xC4 0xBF 0x0F Write Frequency (0x9C4 = 2500 = 25.00HZ) +*/ +float HuanyangSpindle :: set_rpm(float rpm) { + char msg[7] = {HUANYANG_ADDR, 0x05, 0x02, 0x00, 0x00, 0x00, 0x00}; + + // add data (rpm) bytes + uint16_t data = uint16_t(rpm / 60.0 * 100.0); // send Hz * 10 (Ex:1500 RPM = 25Hz .... Send 2500) + msg[3] = (data & 0xFF00) >> 8; + msg[4] = (data & 0xFF); + + add_ModRTU_CRC(msg, sizeof(msg)); + + //report_hex_msg(msg, "To VFD:", sizeof(msg)); // TODO for debugging comment out + + uart_write_bytes(HUANYANG_UART_PORT, msg, sizeof(msg)); + get_response(6); + + return rpm; +} + +void HuanyangSpindle ::stop() { + set_mode(SPINDLE_DISABLE); +} + +// state is cached rather than read right now to prevent delays +uint8_t HuanyangSpindle :: get_state() { + return _state; +} + +// Calculate the CRC on all of the byte except the last 2 +// It then added the CRC to those last 2 bytes +// full_msg_len This is the length of the message including the 2 crc bytes +// Source: https://ctlsys.com/support/how_to_compute_the_modbus_rtu_message_crc/ +void HuanyangSpindle :: add_ModRTU_CRC(char* buf, int full_msg_len) { + uint16_t crc = 0xFFFF; + for (int pos = 0; pos < full_msg_len - 2; pos++) { + crc ^= (uint16_t)buf[pos]; // XOR byte into least sig. byte of crc + for (int i = 8; i != 0; i--) { // Loop over each bit + if ((crc & 0x0001) != 0) { // If the LSB is set + crc >>= 1; // Shift right and XOR 0xA001 + crc ^= 0xA001; + } else // Else LSB is not set + crc >>= 1; // Just shift right + } + } + // add the calculated Crc to the message + buf[full_msg_len - 1] = (crc & 0xFF00) >> 8; + buf[full_msg_len - 2] = (crc & 0xFF); +} diff --git a/Grbl_Esp32/tools/NullSpindle.cpp b/Grbl_Esp32/tools/NullSpindle.cpp index 8be38ca6..73b94f23 100644 --- a/Grbl_Esp32/tools/NullSpindle.cpp +++ b/Grbl_Esp32/tools/NullSpindle.cpp @@ -25,6 +25,7 @@ // ======================= NullSpindle ============================== // NullSpindle is just bunch of do nothing (ignore) methods to be used when you don't want a spindle void NullSpindle :: init() { + is_reversable = false; config_message(); } float NullSpindle :: set_rpm(float rpm) { diff --git a/Grbl_Esp32/tools/PWMSpindle.cpp b/Grbl_Esp32/tools/PWMSpindle.cpp index f4448dbe..0af0e490 100644 --- a/Grbl_Esp32/tools/PWMSpindle.cpp +++ b/Grbl_Esp32/tools/PWMSpindle.cpp @@ -67,6 +67,8 @@ void PWMSpindle::init() { if (_direction_pin != UNDEFINED_PIN) pinMode(_direction_pin, OUTPUT); + is_reversable = (_direction_pin != UNDEFINED_PIN); + config_message(); } @@ -87,7 +89,7 @@ void PWMSpindle :: get_pin_numbers() { #endif #ifdef SPINDLE_DIR_PIN - _direction_pin = SPINDLE_DIR_PIN; + _direction_pin = SPINDLE_DIR_PIN; #else _direction_pin = UNDEFINED_PIN; #endif @@ -148,7 +150,6 @@ float PWMSpindle::set_rpm(float rpm) { } void PWMSpindle::set_state(uint8_t state, float rpm) { - if (sys.abort) return; // Block during abort. diff --git a/Grbl_Esp32/tools/RelaySpindle.cpp b/Grbl_Esp32/tools/RelaySpindle.cpp index 1b7bfc3f..f517e817 100644 --- a/Grbl_Esp32/tools/RelaySpindle.cpp +++ b/Grbl_Esp32/tools/RelaySpindle.cpp @@ -39,6 +39,8 @@ void RelaySpindle::init() { if (_direction_pin != UNDEFINED_PIN) pinMode(_direction_pin, OUTPUT); + is_reversable = (_direction_pin != UNDEFINED_PIN); + config_message(); } diff --git a/Grbl_Esp32/tools/SpindleClass.cpp b/Grbl_Esp32/tools/SpindleClass.cpp index 208c4049..21623ba6 100644 --- a/Grbl_Esp32/tools/SpindleClass.cpp +++ b/Grbl_Esp32/tools/SpindleClass.cpp @@ -39,12 +39,14 @@ #include "DacSpindle.cpp" #include "RelaySpindle.cpp" #include "Laser.cpp" +#include "HuanyangSpindle.cpp" NullSpindle null_spindle; PWMSpindle pwm_spindle; RelaySpindle relay_spindle; Laser laser; DacSpindle dac_spindle; +HuanyangSpindle huanyang_spindle; void spindle_select(uint8_t spindle_type) { @@ -61,6 +63,9 @@ void spindle_select(uint8_t spindle_type) { case SPINDLE_TYPE_DAC: my_spindle = &dac_spindle; break; + case SPINDLE_TYPE_HUANYANG: + my_spindle = &huanyang_spindle; + break; case SPINDLE_TYPE_NONE: default: my_spindle = &null_spindle; diff --git a/Grbl_Esp32/tools/SpindleClass.h b/Grbl_Esp32/tools/SpindleClass.h index 2ad3c669..444ff42a 100644 --- a/Grbl_Esp32/tools/SpindleClass.h +++ b/Grbl_Esp32/tools/SpindleClass.h @@ -26,17 +26,29 @@ #define SPINDLE_STATE_CW bit(0) #define SPINDLE_STATE_CCW bit(1) -#define SPINDLE_TYPE_NONE 0 -#define SPINDLE_TYPE_PWM 1 -#define SPINDLE_TYPE_RELAY 2 -#define SPINDLE_TYPE_LASER 4 -#define SPINDLE_TYPE_DAC 5 +#define SPINDLE_TYPE_NONE 0 +#define SPINDLE_TYPE_PWM 1 +#define SPINDLE_TYPE_RELAY 2 +#define SPINDLE_TYPE_LASER 3 +#define SPINDLE_TYPE_DAC 4 +#define SPINDLE_TYPE_HUANYANG 5 +/* +typedef enum { + SPINDLE_TYPE_NONE = 0, + SPINDLE_TYPE_PWM, + SPINDLE_TYPE_RELAY, + SPINDLE_TYPE_LASER, + SPINDLE_TYPE_DAC, + SPINDLE_TYPE_HUANGYANG, +} spindle_type_t; +*/ #ifndef SPINDLE_CLASS_H #define SPINDLE_CLASS_H #include "grbl.h" #include +#include "driver/uart.h" @@ -51,6 +63,8 @@ class Spindle { virtual void config_message(); virtual bool isRateAdjusted(); virtual void spindle_sync(uint8_t state, float rpm); + + bool is_reversable; }; // This is a dummy spindle that has no I/O. @@ -128,15 +142,38 @@ class DacSpindle : public PWMSpindle { void set_pwm(uint32_t duty); // sets DAC instead of PWM }; -extern Spindle *my_spindle; +class HuanyangSpindle : public Spindle { + public: + void init(); + void config_message(); + virtual void set_state(uint8_t state, float rpm); + uint8_t get_state(); + float set_rpm(float rpm); + void stop(); + + private: + bool get_response(uint16_t length); + uint16_t ModRTU_CRC(char* buf, int len); + void add_ModRTU_CRC(char* buf, int full_msg_len); + bool set_mode(uint8_t mode); + bool get_pin_numbers(); + + uint8_t _txd_pin; + uint8_t _rxd_pin; + uint8_t _rts_pin; + uint8_t _state; +}; + +extern Spindle* my_spindle; extern NullSpindle null_spindle; extern PWMSpindle pwm_spindle; extern RelaySpindle relay_spindle; extern Laser laser; extern DacSpindle dac_spindle; +extern HuanyangSpindle huanyang_spindle; void spindle_select(uint8_t spindle_type); -void spindle_read_prefs(Preferences &prefs); +void spindle_read_prefs(Preferences& prefs); #endif diff --git a/Grbl_Esp32/wmb_settings.cpp b/Grbl_Esp32/wmb_settings.cpp deleted file mode 100644 index 095925a0..00000000 --- a/Grbl_Esp32/wmb_settings.cpp +++ /dev/null @@ -1,715 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include "./defaults.h" -using namespace std; - -// These status values are just assigned at random, for testing -// they need to be synced with the rest of Grbl -typedef enum { - STATUS_OK = 0, - STATUS_INVALID_STATEMENT, - STATUS_NUMBER_RANGE, - STATUS_INVALID_VALUE, - STATUS_IDLE_ERROR, -} err_t; - -enum { - BITFLAG_INVERT_ST_ENABLE = 1, - BITFLAG_INVERT_LIMIT_PINS = 2, - BITFLAG_INVERT_PROBE_PIN = 4, - BITFLAG_REPORT_INCHES = 8, - BITFLAG_SOFT_LIMIT_ENABLE = 16, - BITFLAG_HARD_LIMIT_ENABLE = 32, - BITFLAG_HOMING_ENABLE = 64, - BITFLAG_LASER_MODE = 128, -}; -#define DEFAULT_SPINDLE_TYPE 0 -#define DEFAULT_SPINDLE_BIT_PRECISION 10 -enum { - STATE_IDLE = 0, - STATE_JOG, -}; -#define MAXLINE 128 -int client; - -struct { - int flags; -} settings; - -struct { - int state; -} sys; - -#define MAX_N_AXIS 6 -#define MESSAGE_RESTORE_DEFAULTS "restoring defaults" -enum { - SETTINGS_RESTORE_DEFAULTS, - SETTINGS_RESTORE_PARAMETERS, - SETTINGS_RESTORE_ALL, - SETTINGS_RESTORE_WIFI_SETTINGS, - SETTINGS_WIPE, -}; - -err_t my_spindle_init(); -err_t limits_init(); -err_t also_soft_limit(); -void settings_restore(int); -void report_feedback_message(const char *); -err_t report_normal_settings(uint8_t); -err_t report_extended_settings(uint8_t); -err_t report_gcode_modes(uint8_t); -err_t report_build_info(uint8_t); -err_t report_startup_lines(uint8_t); -err_t toggle_check_mode(uint8_t); -err_t disable_alarm_lock(uint8_t); -err_t report_ngc(uint8_t); -err_t home_all(uint8_t); -err_t home_x(uint8_t); -err_t home_y(uint8_t); -err_t home_z(uint8_t); -err_t home_a(uint8_t); -err_t home_b(uint8_t); -err_t home_c(uint8_t); -err_t sleep(uint8_t); -err_t gc_execute_line(char *line, uint8_t client); - -void mc_reset(); - -err_t check_motor_settings() { return STATUS_OK; } -err_t settings_spi_driver_init() { return STATUS_OK; } - -// SettingsList is a linked list of all settings, -// so common code can enumerate them. -class Setting; -Setting *SettingsList = NULL; - -// This abstract class defines the generic interface that -// is used to set and get values for all settings independent -// of their underlying data type. The values are always -// represented as human-readable strings. This generic -// interface is used for managing settings via the user interface. -class Setting { - public: - - // Add each constructed setting to the linked list - Setting *link; - Setting(const char* name) { - displayName = name; - link = SettingsList; - SettingsList = this; - } - const char* getName() { return displayName; }; - - // load() reads the backing store to get the current - // value of the setting. This could be slow so it - // should be done infrequently, typically once at startup. - virtual void load() =0; - - // commit() puts the current value of the setting into - // the backing store. - // virtual void commit() =0; - - virtual err_t setStringValue(string value) =0; - virtual string getStringValue() =0; - - private: - const char* displayName; -}; - -// This template class, derived from the generic abstract -// class, lets you store an individual setting as typed data. - -template -class TypedSetting : public Setting { - public: - TypedSetting(const char* name, T defVal, T minVal, T maxVal, err_t (*f)() = NULL) : - Setting(name), - defaultValue(defVal), - currentValue(defVal), - minValue(minVal), - maxValue(maxVal), - checker(f) - { } - void load() { - if (isfloat) { - //p storedValue = preferences.getFloat(displayName, defaultValue); - } else { - //p storedValue = preferences.getInt(displayName, defaultValue); - } // Read value from backing store - currentValue = storedValue; - } - void commit() { - if (storedValue != currentValue) { - if (storedValue == defaultValue) { - //p preferences.remove(displayName); - } else { - if (isfloat) { - //p preferences.putFloat(displayName, currentValue); - } else { - //p preferences.putInt(displayName, currentValue); - } - } - } - } - - T get() { return currentValue; } - err_t set(T value) { currentValue = value; return STATUS_OK; } - err_t string_to_value(string s, T &value) { - T convertedValue; - try { - convertedValue = stof(s); - } - catch (int e) { - return STATUS_INVALID_VALUE; - } - if (convertedValue < minValue || convertedValue > maxValue) { - return STATUS_NUMBER_RANGE; - } - value = convertedValue; - return STATUS_OK; - } - string value_to_string (T value) { - return to_string(value); - } - - // Standard methods of the abstract class "Setting" - err_t setStringValue(string s) { - T newValue; - err_t ret = string_to_value(s, newValue); - if (ret) return ret; - if (checker && (ret = checker())) return ret; - currentValue = newValue; - return ret; - } - string getStringValue () { - return to_string(get()); - } - - private: - T defaultValue; - T currentValue; - T storedValue; - T minValue; - T maxValue; - const bool isfloat = typeid(T) == typeid(float); - err_t (*checker)(); -}; - -typedef TypedSetting FloatSetting; -typedef TypedSetting IntSetting; - -class AxisSettings { - public: - string name; - FloatSetting steps_per_mm; - FloatSetting max_rate; - FloatSetting acceleration; - FloatSetting max_travel; - FloatSetting run_current; - FloatSetting hold_current; - IntSetting microsteps; - IntSetting stallguard; - AxisSettings(string axisName, float steps, float rate, float accel, float travel, - float run, float hold, int usteps, int stall) : - name(axisName), - steps_per_mm((axisName+"_STEPS_PER_MM").c_str(), steps, 1.0, 50000.0, check_motor_settings), - max_rate((axisName+"_MAX_RATE").c_str(), rate, 1.0, 1000000.0, check_motor_settings), - acceleration((axisName+"_ACCELERATION").c_str(), accel, 1.0, 100000.0), - max_travel((axisName+"_MAX_TRAVEL").c_str(), travel, 1.0, 100000.0), // Note! this values is entered as scaler but store negative - run_current((axisName+"_RUN_CURRENT").c_str(), run, 0.05, 20.0, settings_spi_driver_init), - hold_current((axisName+"_HOLD_CURRENT").c_str(), hold, 0.0, 100.0, settings_spi_driver_init), - microsteps((axisName+"_MICROSTEPS").c_str(), usteps, 1, 256, settings_spi_driver_init), - stallguard((axisName+"_STALLGUARD").c_str(), stall, 0, 100, settings_spi_driver_init) - {} -}; -AxisSettings x_axis_settings = { - "X", - DEFAULT_X_STEPS_PER_MM, - DEFAULT_X_MAX_RATE, - DEFAULT_X_ACCELERATION, - DEFAULT_X_MAX_TRAVEL, - DEFAULT_X_CURRENT, - DEFAULT_X_HOLD_CURRENT, - DEFAULT_X_MICROSTEPS, - DEFAULT_X_STALLGUARD -}; - -AxisSettings y_axis_settings = { - "Y", - DEFAULT_Y_STEPS_PER_MM, - DEFAULT_Y_MAX_RATE, - DEFAULT_Y_ACCELERATION, - DEFAULT_Y_MAX_TRAVEL, - DEFAULT_Y_CURRENT, - DEFAULT_Y_HOLD_CURRENT, - DEFAULT_Y_MICROSTEPS, - DEFAULT_Y_STALLGUARD -}; - -AxisSettings z_axis_settings = { - "Z", - DEFAULT_Z_STEPS_PER_MM, - DEFAULT_Z_MAX_RATE, - DEFAULT_Z_ACCELERATION, - DEFAULT_Z_MAX_TRAVEL, - DEFAULT_Z_CURRENT, - DEFAULT_Z_HOLD_CURRENT, - DEFAULT_Z_MICROSTEPS, - DEFAULT_Z_STALLGUARD -}; - -AxisSettings a_axis_settings = { - "A", - DEFAULT_A_STEPS_PER_MM, - DEFAULT_A_MAX_RATE, - DEFAULT_A_ACCELERATION, - DEFAULT_A_MAX_TRAVEL, - DEFAULT_A_CURRENT, - DEFAULT_A_HOLD_CURRENT, - DEFAULT_A_MICROSTEPS, - DEFAULT_A_STALLGUARD -}; - -AxisSettings b_axis_settings = { - "B", - DEFAULT_B_STEPS_PER_MM, - DEFAULT_B_MAX_RATE, - DEFAULT_B_ACCELERATION, - DEFAULT_B_MAX_TRAVEL, - DEFAULT_B_CURRENT, - DEFAULT_B_HOLD_CURRENT, - DEFAULT_B_MICROSTEPS, - DEFAULT_B_STALLGUARD -}; - -AxisSettings c_axis_settings = { - "C", - DEFAULT_C_STEPS_PER_MM, - DEFAULT_C_MAX_RATE, - DEFAULT_C_ACCELERATION, - DEFAULT_C_MAX_TRAVEL, - DEFAULT_C_CURRENT, - DEFAULT_C_HOLD_CURRENT, - DEFAULT_C_MICROSTEPS, - DEFAULT_C_STALLGUARD -}; - -AxisSettings axis_settings[] = { - x_axis_settings, - y_axis_settings, - z_axis_settings, - a_axis_settings, - b_axis_settings, - c_axis_settings, -}; - -class StringSetting : public Setting { - private: - string currentValue; - string storedValue; - string defaultValue; - - public: - StringSetting(const char* name, string defVal) : - Setting(name), - defaultValue(defVal), - currentValue(defVal) - { }; - void load() { - //p storedValue = preferences.getString(displayName, defaultValue); - currentValue = storedValue; - } - void commit() { - if (storedValue != currentValue) { - if (storedValue == defaultValue) { - //p preferences.remove(displayName); - } else { - //p preferences.putString(displayName, currentValue); - } - } - } - string get() { return currentValue; } - err_t set(string value) { currentValue = value; return STATUS_OK; } - err_t string_to_value(string s, string &value) { - value = s; - return STATUS_OK; - } - string value_to_string (string value) { return value; } - err_t setStringValue(string s) { - currentValue = s; - return STATUS_OK; - } - string getStringValue() { return currentValue; } -}; -StringSetting startup_line_0("N0", ""); -StringSetting startup_line_1("N1", ""); -StringSetting build_info("I", ""); - -// Single-use class for the $RST= command -// There is no underlying stored value -class SettingsReset : public Setting { - public: - SettingsReset(const char* name) : - Setting(name) - { } - void load() { - } - void commit() { - } - string get() { return 0; } - err_t set(int value) { - settings_restore(value); - report_feedback_message(MESSAGE_RESTORE_DEFAULTS); - mc_reset(); // Ensure settings are initialized correctly - return STATUS_OK; - } - err_t string_to_value(string s, int &value) { - switch (s[0]) { - case '$': value = SETTINGS_RESTORE_DEFAULTS; break; - case '#': value = SETTINGS_RESTORE_PARAMETERS; break; - case '*': value = SETTINGS_RESTORE_ALL; break; - case '@': value = SETTINGS_RESTORE_WIFI_SETTINGS; break; - case '!': value = SETTINGS_WIPE; break; - default: return STATUS_INVALID_VALUE; - } - return STATUS_OK; - } - err_t setStringValue(string s) { - int value; - err_t ret = string_to_value(s, value); - return ret ? ret : set(value); - } - string value_to_string (int value) { - switch(value) { - case SETTINGS_RESTORE_DEFAULTS: return "$"; break; - case SETTINGS_RESTORE_PARAMETERS: return "#"; break; - case SETTINGS_RESTORE_ALL: return "*"; break; - case SETTINGS_RESTORE_WIFI_SETTINGS: return "@"; break; - case SETTINGS_WIPE: return "!"; break; - default: return ""; - } - } - string getStringValue() { return ""; } -}; - -IntSetting pulse_microseconds("STEP_PULSE", DEFAULT_STEP_PULSE_MICROSECONDS, 3, 1000); -IntSetting stepper_idle_lock_time("STEPPER_IDLE_TIME", DEFAULT_STEPPER_IDLE_LOCK_TIME, 0, 255); - -IntSetting step_invert_mask("STEP_INVERT_MASK", DEFAULT_STEPPING_INVERT_MASK, 0, (1<init(); - -IntSetting status_mask("STATUS_MASK", DEFAULT_STATUS_REPORT_MASK, 0, 2); -FloatSetting junction_deviation("JUNCTION_DEVIATION", DEFAULT_JUNCTION_DEVIATION, 0, 10); -FloatSetting arc_tolerance("ARC_TOLERANCE", DEFAULT_ARC_TOLERANCE, 0, 1); - -FloatSetting homing_feed_rate("HOMING_FEED", DEFAULT_HOMING_FEED_RATE, 0, 10000); -FloatSetting homing_seek_rate("HOMING_SEEK", DEFAULT_HOMING_SEEK_RATE, 0, 10000); -FloatSetting homing_debounce("HOMING_DEBOUNCE", DEFAULT_HOMING_DEBOUNCE_DELAY, 0, 10000); -FloatSetting homing_pulloff("HOMING_PULLOFF", DEFAULT_HOMING_PULLOFF, 0, 1000); -FloatSetting spindle_pwm_freq("SPINDLE_PWM_FREQ", DEFAULT_SPINDLE_FREQ, 0, 100000); -FloatSetting rpm_max("RPM_MAX", DEFAULT_SPINDLE_RPM_MAX, 0, 100000); -FloatSetting rpm_min("RPM_MIN", DEFAULT_SPINDLE_RPM_MIN, 0, 100000); - -FloatSetting spindle_pwm_off_value("SPINDLE_PWM_OFF_VALUE", DEFAULT_SPINDLE_OFF_VALUE, 0.0, 100.0); // these are percentages -FloatSetting spindle_pwm_min_value("SPINDLE_PWM_MIN_VALUE", DEFAULT_SPINDLE_MIN_VALUE, 0.0, 100.0); -FloatSetting spindle_pwm_max_value("SPINDLE_PWM_MAX_VALUE", DEFAULT_SPINDLE_MAX_VALUE, 0.0, 100.0); -IntSetting spindle_pwm_bit_precision("SPINDLE_PWM_BIT_PRECISION", DEFAULT_SPINDLE_BIT_PRECISION, 1, 16); - -StringSetting spindle_type("SPINDLE_TYPE", DEFAULT_SPINDLE_TYPE); - -// The following table maps numbered settings to their settings -// objects, for backwards compatibility. It is used if the -// line is of the form "$key=value". If a key match is found, -// the object's setValueString method is invoked with the value -// as argument. If no match is found, the list of named settings -// is searched, with the same behavior on a match. - -// These are compatibily aliases for Classic GRBL -std::map numberedSettings = { - { "0", &pulse_microseconds }, - { "1", &stepper_idle_lock_time }, - { "2", &step_invert_mask }, - { "3", &dir_invert_mask }, - { "4", &step_enable_invert }, - { "5", &limit_invert }, - { "6", &probe_invert }, - { "10", &status_mask }, - { "11", &junction_deviation }, - { "12", &arc_tolerance }, - { "13", &report_inches }, - { "20", &soft_limits }, - { "21", &hard_limits }, - { "22", &homing_enable }, - { "23", &homing_dir_mask }, - { "24", &homing_feed_rate }, - { "25", &homing_seek_rate }, - { "26", &homing_debounce }, - { "27", &homing_pulloff }, - { "30", &rpm_max }, - { "31", &rpm_min }, - { "32", &laser_mode }, - { "100", &x_axis_settings.steps_per_mm }, - { "101", &y_axis_settings.steps_per_mm }, - { "102", &z_axis_settings.steps_per_mm }, - { "110", &x_axis_settings.max_rate }, - { "111", &y_axis_settings.max_rate }, - { "112", &z_axis_settings.max_rate }, - { "120", &x_axis_settings.acceleration }, - { "121", &y_axis_settings.acceleration }, - { "122", &z_axis_settings.acceleration }, - { "130", &x_axis_settings.max_travel }, - { "131", &y_axis_settings.max_travel }, - { "132", &z_axis_settings.max_travel }, -}; - -// FIXME - jog may need to be special-cased in the parser, since -// it is not really a setting and the entire line needs to be -// sent to gc_execute_line. It is probably also more time-critical -// than actual settings, which change infrequently, so handling -// it early is probably prudent. -uint8_t jog_set(uint8_t *value, uint8_t client) { - // Execute only if in IDLE or JOG states. - if (sys.state != STATE_IDLE && sys.state != STATE_JOG) return STATUS_IDLE_ERROR; - - // restore the $J= prefix because gc_execute_line() expects it - char line[MAXLINE]; - strcpy(line, "$J="); - strncat(line, (char *)value, MAXLINE-strlen("$J=")-1); - - return gc_execute_line(line, client); // NOTE: $J= is ignored inside g-code parser and used to detect jog motions. -} - -// The following table is used if the line is of the form "$key\n" -// i.e. dollar commands without "=" -// The key value is matched against the string and the corresponding -// function is called with no arguments. -// If there is no key match an error is reported -typedef err_t (*Command_t)(uint8_t); -std::map dollarCommands = { - { "$", report_normal_settings }, - { "+", report_extended_settings }, - { "G", report_gcode_modes }, - { "C", toggle_check_mode }, - { "X", disable_alarm_lock }, - { "#", report_ngc }, - { "H", home_all }, - { "HX", home_x }, - { "HY", home_y }, - { "HZ", home_z }, - { "HA", home_a }, - { "HB", home_b }, - { "HC", home_c }, - { "SLP", sleep }, - { "I", report_build_info }, - { "N", report_startup_lines }, -}; - -// normalize_key puts a key string into canonical form - -// upper case without whitespace. -// start points to a null-terminated string. -// Returns the first substring that does not contain whitespace, -// converted to upper case. -char *normalize_key(char *start) { - char c; - - // In the usual case, this loop will exit on the very first test, - // because the first character is likely to be non-white. - // Null ('\0') is not considered to be a space character. - while (isspace(c = *start) && c != '\0') { - ++start; - } - - // start now points to either a printable character or end of string - if (c == '\0') { - return start; - } - - // Having found the beginning of the printable string, - // we now scan forward, converting lower to upper case, - // until we find a space character. - char *end; - for (end = start; (c = *end) != '\0' && !isspace(c); end++) { - if (islower(c)) { - *end = toupper(c); - } - } - - // end now points to either a whitespace character of end of string - // In either case it is okay to place a null there - *end = '\0'; - - return start; -} - -// This is for changing settings with $key=value . -// Lookup key in the numberedSettings map. If found, execute -// the corresponding object's "set" method. Otherwise fail. -err_t do_setting(const char *key, char *value, uint8_t client) { - - // First search this numberedSettings array - aliases - // for the underlying named settings. - map::iterator it = numberedSettings.find(key); - if (it != numberedSettings.end()) { - return it->second->setStringValue(value); - } - - // Then search the list of named settings. - for (Setting *s = SettingsList; s; s = s->link) { - if (strcmp(s->getName(), key) == 0) { - return s->setStringValue(value); - } - } - - return STATUS_INVALID_STATEMENT; -} - -// This is for bare commands like "$RST" - no equals sign. -// Lookup key in the dollarCommands map. If found, execute -// the corresponding command. -// As an enhancement to Classic GRBL, if the key is not found -// in the commands map, look it up in the lists of settings -// and display the current value. -err_t do_command(const char *key, uint8_t client) { - - map::iterator i = dollarCommands.find(key); - if (i != dollarCommands.end()) { - return i->second(client); - } - - // Enhancement - not in Classic GRBL: - // If it is not a command, look up the key - // as a setting and display the value. - - map::iterator it = numberedSettings.find(key); - if (it != numberedSettings.end()) { - Setting *s = it->second; - cout << key << "=" << s->getStringValue() << '\n'; - return STATUS_OK; - } - - for (Setting *s = SettingsList; s; s = s->link) { - // if (s->getName().compare(k)) { - if (strcmp(s->getName(), key) == 0) { - cout << key << "=" << s->getStringValue() << '\n'; - return STATUS_OK; - } - } - - return STATUS_INVALID_STATEMENT; -} - -uint8_t system_execute_line(char* line, uint8_t client) { - char *value = strchr(line, '='); - - if (value) { - // Equals was found; replace it with null and skip it - *value++ = '\0'; - do_setting(normalize_key(line), value, client); - } else { - // No equals, so it must be a command - do_command(normalize_key(line), client); - } -} - -void list_settings() -{ - for (Setting *s = SettingsList; s; s = s->link) { - cout << s->getName() << " " << s->getStringValue() << '\n'; - } -} - -void list_numbered_settings() -{ - for (map::iterator it = numberedSettings.begin(); - it != numberedSettings.end(); - it++) { - cout << it->first << ": " << it->second->getStringValue() << '\n'; - } -} - -int main() -{ - list_settings(); -} From 7c2f2ec8596a8b1cdcd0863c880326a51f865b5a Mon Sep 17 00:00:00 2001 From: bdring Date: Sun, 19 Apr 2020 06:57:01 -0500 Subject: [PATCH 19/32] Removing test prefs stuff and adding BESCSpindle class --- Grbl_Esp32/Grbl_Esp32.ino | 6 +- Grbl_Esp32/Machines/3axis_v4.h | 2 +- Grbl_Esp32/Machines/4axis_external_driver.h | 8 +- Grbl_Esp32/defaults.h | 8 -- Grbl_Esp32/grbl.h | 1 - Grbl_Esp32/grbl_preferences.cpp | 44 ---------- Grbl_Esp32/grbl_preferences.h | 14 --- Grbl_Esp32/machine.h | 2 +- Grbl_Esp32/machine_common.h | 6 +- Grbl_Esp32/protocol.cpp | 17 ++-- Grbl_Esp32/report.cpp | 4 +- Grbl_Esp32/settings.cpp | 12 +-- Grbl_Esp32/settings.h | 2 - Grbl_Esp32/tools/BESCSpindle.cpp | 97 +++++++++++++++++++++ Grbl_Esp32/tools/HuanyangSpindle.cpp | 3 + Grbl_Esp32/tools/Laser.cpp | 2 +- Grbl_Esp32/tools/PWMSpindle.cpp | 77 ++++++++-------- Grbl_Esp32/tools/SpindleClass.cpp | 15 ++-- Grbl_Esp32/tools/SpindleClass.h | 29 +++--- 19 files changed, 184 insertions(+), 165 deletions(-) delete mode 100644 Grbl_Esp32/grbl_preferences.cpp delete mode 100644 Grbl_Esp32/grbl_preferences.h create mode 100644 Grbl_Esp32/tools/BESCSpindle.cpp diff --git a/Grbl_Esp32/Grbl_Esp32.ino b/Grbl_Esp32/Grbl_Esp32.ino index 4add11ee..ad3e0580 100644 --- a/Grbl_Esp32/Grbl_Esp32.ino +++ b/Grbl_Esp32/Grbl_Esp32.ino @@ -59,7 +59,6 @@ void setup() { grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Using machine:%s", MACHINE_STRING); #endif settings_init(); // Load Grbl settings from EEPROM - grbl_preferences.begin(GRBL_PREFERENCES_NAMESPACE, true); // readonly = false stepper_init(); // Configure stepper pins and interrupt timers system_ini(); // Configure pinout pins and pin-change interrupt (Renamed due to conflict with esp32 files) memset(sys_position, 0, sizeof(sys_position)); // Clear machine position. @@ -99,11 +98,9 @@ void setup() { bt_config.begin(); #endif inputBuffer.begin(); - grbl_preferences.end(); // everyone should have their prefs by now } void loop() { - grbl_preferences.begin(GRBL_PREFERENCES_NAMESPACE, true); // readonly = false // Reset system variables. uint8_t prior_state = sys.state; memset(&sys, 0, sizeof(system_t)); // Clear system struct variable. @@ -120,7 +117,7 @@ void loop() { // Reset Grbl primary systems. serial_reset_read_buffer(CLIENT_ALL); // Clear serial read buffer gc_init(); // Set g-code parser to default state - spindle_select(settings.spindle_type); + spindle_select(SPINDLE_TYPE); coolant_init(); limits_init(); probe_init(); @@ -132,6 +129,5 @@ void loop() { // put your main code here, to run repeatedly: report_init_message(CLIENT_ALL); // Start Grbl main loop. Processes program inputs and executes them. - grbl_preferences.end(); // everyone should have their prefs by now protocol_main_loop(); } diff --git a/Grbl_Esp32/Machines/3axis_v4.h b/Grbl_Esp32/Machines/3axis_v4.h index e16ecbfb..c73e28f3 100644 --- a/Grbl_Esp32/Machines/3axis_v4.h +++ b/Grbl_Esp32/Machines/3axis_v4.h @@ -52,4 +52,4 @@ #define CONTROL_FEED_HOLD_PIN GPIO_NUM_36 // labeled Hold, needs external pullup #define CONTROL_CYCLE_START_PIN GPIO_NUM_39 // labeled Start, needs external pullup -#define DEFAULT_SPINDLE_TYPE SPINDLE_TYPE_PWM +#define SPINDLE_TYPE SPINDLE_TYPE_BESC diff --git a/Grbl_Esp32/Machines/4axis_external_driver.h b/Grbl_Esp32/Machines/4axis_external_driver.h index f093925c..868b484a 100644 --- a/Grbl_Esp32/Machines/4axis_external_driver.h +++ b/Grbl_Esp32/Machines/4axis_external_driver.h @@ -43,10 +43,10 @@ #define SPINDLE_PWM_PIN GPIO_NUM_25 #define SPINDLE_ENABLE_PIN GPIO_NUM_22 -#define HUANYANG_TXD_PIN GPIO_NUM_17 -#define HUANYANG_RXD_PIN GPIO_NUM_4 -#define HUANYANG_RTS_PIN GPIO_NUM_16 - +#define SPINDLE_TYPE SPINDLE_TYPE_HUANYANG +#define HUANYANG_TXD_PIN GPIO_NUM_17 +#define HUANYANG_RXD_PIN GPIO_NUM_4 +#define HUANYANG_RTS_PIN GPIO_NUM_16 #define X_LIMIT_PIN GPIO_NUM_34 #define Y_LIMIT_PIN GPIO_NUM_35 diff --git a/Grbl_Esp32/defaults.h b/Grbl_Esp32/defaults.h index 808f4669..e3dad112 100644 --- a/Grbl_Esp32/defaults.h +++ b/Grbl_Esp32/defaults.h @@ -143,14 +143,6 @@ #define DEFAULT_SPINDLE_MAX_VALUE 100.0 // $36 Percent (extended set) #endif - #ifndef DEFAULT_SPINDLE_PWM_BIT_PRECISION // $37 - #define DEFAULT_SPINDLE_PWM_BIT_PRECISION 8 - #endif - - #ifndef DEFAULT_SPINDLE_TYPE // $38 - #define DEFAULT_SPINDLE_TYPE SPINDLE_TYPE_PWM - #endif - // ================ user settings ===================== #ifndef DEFAULT_USER_INT_80 #define DEFAULT_USER_INT_80 0 // $80 User integer setting diff --git a/Grbl_Esp32/grbl.h b/Grbl_Esp32/grbl.h index 933d7cea..8f448dc4 100644 --- a/Grbl_Esp32/grbl.h +++ b/Grbl_Esp32/grbl.h @@ -39,7 +39,6 @@ #include "defaults.h" #include "settings.h" -#include "grbl_preferences.h" #include "system.h" #include "planner.h" diff --git a/Grbl_Esp32/grbl_preferences.cpp b/Grbl_Esp32/grbl_preferences.cpp deleted file mode 100644 index de7e0c79..00000000 --- a/Grbl_Esp32/grbl_preferences.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#include "grbl.h" - - - -Preferences grbl_preferences; - -void grbl_preferences_init() { - grbl_preferences.begin(GRBL_PREFERENCES_NAMESPACE, false); // readonly = false - spindle_read_prefs(grbl_preferences); // - grbl_preferences.end(); - -} - -bool grbl_prefs_change(const char* line, int* cmd, String& cmd_params) { - String buffer = line; - String key = ""; - String value = ""; - - // grbl_preferences.begin(GRBL_PREFERENCES_NAMESPACE, false); // readonly = false - - // TODO probably need more error checking - int close_bracket = buffer.indexOf("]", 2); // find the closing bracket - if (close_bracket > -1) { - key = buffer.substring(2, close_bracket); - if (close_bracket < buffer.length()) { - value = buffer.substring(close_bracket + 1); - } else { - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "no value found"); - return false; - } - } - - switch (buffer[2]) { - case 'S': - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Hey spindle please set key:%s to value:%s", key.c_str(), value.c_str()); - return true; - break; - default: - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Unknown setting prefix %c", buffer[2]); - } - // grbl_preferences.end(); - - return false; -} \ No newline at end of file diff --git a/Grbl_Esp32/grbl_preferences.h b/Grbl_Esp32/grbl_preferences.h deleted file mode 100644 index 3e52deed..00000000 --- a/Grbl_Esp32/grbl_preferences.h +++ /dev/null @@ -1,14 +0,0 @@ - -#ifndef GRBL_PREFERENCES_H -#define GRBL_PREFERENCES_H - -#define GRBL_PREFERENCES_NAMESPACE "Grbl_ESP32" - -#include "grbl.h" - -extern Preferences grbl_preferences; - -void grbl_preferences_init(); -bool grbl_prefs_change(const char* line, int* cmd, String& cmd_params); - -#endif \ No newline at end of file diff --git a/Grbl_Esp32/machine.h b/Grbl_Esp32/machine.h index d9bcc42f..1d49672e 100644 --- a/Grbl_Esp32/machine.h +++ b/Grbl_Esp32/machine.h @@ -8,7 +8,7 @@ // !!! For initial testing, start with test_drive.h which disables // all I/O pins -#include "Machines/4axis_external_driver.h" +#include "Machines/3axis_v4.h" // !!! For actual use, change the line above to select a board // from Machines/, for example: diff --git a/Grbl_Esp32/machine_common.h b/Grbl_Esp32/machine_common.h index 4ac06ce4..17e6e7de 100644 --- a/Grbl_Esp32/machine_common.h +++ b/Grbl_Esp32/machine_common.h @@ -1,13 +1,15 @@ #ifndef _machine_common_h #define _machine_common_h -/* +#ifndef SPINDLE_TYPE + #define SPINDLE_TYPE SPINDLE_TYPE_PWM +#endif + #ifndef SPINDLE_PWM_BIT_PRECISION #define SPINDLE_PWM_BIT_PRECISION 8 #endif #define SPINDLE_PWM_MAX_VALUE ((1<init(); // update the spindle class break; - case 33: settings.spindle_pwm_freq = value; spindle_select(settings.spindle_type); break; // Re-initialize spindle pwm calibration - case 34: settings.spindle_pwm_off_value = value; spindle_select(settings.spindle_type); break; // Re-initialize spindle pwm calibration - case 35: settings.spindle_pwm_min_value = value; spindle_select(settings.spindle_type); break; // Re-initialize spindle pwm calibration - case 36: settings.spindle_pwm_max_value = value; spindle_select(settings.spindle_type); break; // Re-initialize spindle pwm calibration - case 37: settings.spindle_pwm_precision_bits = MIN(8, value);spindle_select(settings.spindle_type); break; - case 38: settings.spindle_type = value; spindle_select(settings.spindle_type); break; + case 33: settings.spindle_pwm_freq = value; spindle_select(SPINDLE_TYPE); break; // Re-initialize spindle pwm calibration + case 34: settings.spindle_pwm_off_value = value; spindle_select(SPINDLE_TYPE); break; // Re-initialize spindle pwm calibration + case 35: settings.spindle_pwm_min_value = value; spindle_select(SPINDLE_TYPE); break; // Re-initialize spindle pwm calibration + case 36: settings.spindle_pwm_max_value = value; spindle_select(SPINDLE_TYPE); break; // Re-initialize spindle pwm calibration case 80: case 81: case 82: diff --git a/Grbl_Esp32/settings.h b/Grbl_Esp32/settings.h index 54950682..a625438a 100644 --- a/Grbl_Esp32/settings.h +++ b/Grbl_Esp32/settings.h @@ -107,8 +107,6 @@ typedef struct { float spindle_pwm_off_value; // $34 Percent (extended set) float spindle_pwm_min_value; // $35 Percent (extended set) float spindle_pwm_max_value; // $36 Percent (extended set) - uint8_t spindle_pwm_precision_bits; // $37 PWM pwm precision in bits (extended set) - uint8_t spindle_type; // $38 The spindle class to be used (extended set) float rpm_max; float rpm_min; diff --git a/Grbl_Esp32/tools/BESCSpindle.cpp b/Grbl_Esp32/tools/BESCSpindle.cpp new file mode 100644 index 00000000..b85eacf9 --- /dev/null +++ b/Grbl_Esp32/tools/BESCSpindle.cpp @@ -0,0 +1,97 @@ +/* + Important ESC Settings + $33=50 // Hz this is the typical good frequency for an ESC + #define DEFAULT_SPINDLE_FREQ 5000.0 // $33 Hz (extended set) + + Determine the typical min and max pulse length of your ESC + min_pulse is typically 1ms (0.001 sec) or less + max_pulse is typically 2ms (0.002 sec) or more + + determine PWM_period. It is (1/freq) if freq = 50...period = 0.02 + + determine pulse length for min_pulse and max_pulse in percent. + + (pulse / PWM_period) + min_pulse = (0.001 / 0.02) = 0.05 = 5% so ... $34 and $35 = 5.0 + max_pulse = (0.002 / .02) = 0.1 = 10% so ... $36=10 +*/ + +#include "grbl.h" +#include "SpindleClass.h" + + +// don't change these +#define BESC_PWM_FREQ 50.0 // Hz +#define BESC_PWM_BIT_PRECISION 16 // bits +#define BESC_DEFAULT_MIN_PULSE 5.0 // percent +#define BESC_DEFAULT_MAX_PULSE 10.0 // percent + + +void BESCSpindle :: init() { + + get_pin_numbers(); + + if (_output_pin == UNDEFINED_PIN) { + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Warning: BESC output pin not defined"); + return; // We cannot continue without the output pin + } + + // override some settings to what is required for a BESC + _pwm_freq = BESC_PWM_FREQ; + _pwm_precision = 16; + + // to do make these tweakable using existing setting as percentages on these defaults + _pwm_off_value = BESC_DEFAULT_MIN_PULSE; + _pwm_min_value = BESC_DEFAULT_MIN_PULSE; + _pwm_max_value = BESC_DEFAULT_MAX_PULSE; + + ledcSetup(_spindle_pwm_chan_num, (double)_pwm_freq, _pwm_precision); // setup the channel + ledcAttachPin(_output_pin, _spindle_pwm_chan_num); // attach the PWM to the pin + + if (_enable_pin != UNDEFINED_PIN) + pinMode(_enable_pin, OUTPUT); + + config_message(); +} + +// prints the startup message of the spindle config +void BESCSpindle :: config_message() { + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "BESC spindle on GPIO %d", _output_pin); +} + +float BESCSpindle::set_rpm(float rpm) { + uint32_t pwm_value; + + if (_output_pin == UNDEFINED_PIN) + return rpm; + + // apply speed overrides + rpm *= (0.010 * sys.spindle_speed_ovr); // Scale by spindle speed override value (percent) + + // apply limits limits + if ((_min_rpm >= _max_rpm) || (rpm >= _max_rpm)) { + rpm = _max_rpm; + } else if (rpm != 0.0 && rpm <= _min_rpm) { + rpm = _min_rpm; + } + + sys.spindle_speed = rpm; + + // determine the pwm value + if (rpm == 0.0) { + pwm_value = _pwm_off_value; + } else if (rpm == _min_rpm) { + pwm_value = _pwm_min_value; + } else if (rpm == _max_rpm) { + pwm_value = _pwm_max_value; + } else { + pwm_value = floor((rpm - _min_rpm) * _pwm_gradient) + _pwm_min_value; + } + +#ifdef SPINDLE_ENABLE_OFF_WITH_ZERO_SPEED + set_enable_pin(rpm != 0); +#endif + + set_pwm(pwm_value); + return rpm; +} \ No newline at end of file diff --git a/Grbl_Esp32/tools/HuanyangSpindle.cpp b/Grbl_Esp32/tools/HuanyangSpindle.cpp index 028a9edc..ce13233e 100644 --- a/Grbl_Esp32/tools/HuanyangSpindle.cpp +++ b/Grbl_Esp32/tools/HuanyangSpindle.cpp @@ -195,6 +195,9 @@ bool HuanyangSpindle :: get_response(uint16_t length) { 0x01 0x05 0x02 0x09 0xC4 0xBF 0x0F Write Frequency (0x9C4 = 2500 = 25.00HZ) */ float HuanyangSpindle :: set_rpm(float rpm) { + + // TODO add in all the speed modifiers, like override and linearization + char msg[7] = {HUANYANG_ADDR, 0x05, 0x02, 0x00, 0x00, 0x00, 0x00}; // add data (rpm) bytes diff --git a/Grbl_Esp32/tools/Laser.cpp b/Grbl_Esp32/tools/Laser.cpp index 7f5037d1..68078f7d 100644 --- a/Grbl_Esp32/tools/Laser.cpp +++ b/Grbl_Esp32/tools/Laser.cpp @@ -37,6 +37,6 @@ void Laser :: config_message() { "Laser spindle on GPIO:%d, Freq:%.2fHz, Res:%dbits Laser mode:$32=%d", _output_pin, _pwm_freq, - settings.spindle_pwm_precision_bits, + SPINDLE_PWM_BIT_PRECISION, isRateAdjusted()); // the current mode } \ No newline at end of file diff --git a/Grbl_Esp32/tools/PWMSpindle.cpp b/Grbl_Esp32/tools/PWMSpindle.cpp index 0af0e490..e17f6979 100644 --- a/Grbl_Esp32/tools/PWMSpindle.cpp +++ b/Grbl_Esp32/tools/PWMSpindle.cpp @@ -17,7 +17,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Grbl. If not, see . - + */ #include "grbl.h" #include "SpindleClass.h" @@ -28,46 +28,19 @@ void PWMSpindle::init() { get_pin_numbers(); if (_output_pin == UNDEFINED_PIN) { + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Warning: Spindle output pin not defined"); return; // We cannot continue without the output pin } - _min_rpm = grbl_preferences.getFloat("SPIN_MAX_RPM", DEFAULT_SPINDLE_MIN_VALUE); - _pwm_freq = settings.spindle_pwm_freq; - _pwm_period = ((1 << settings.spindle_pwm_precision_bits) - 1); - - if (settings.spindle_pwm_min_value > settings.spindle_pwm_min_value) - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Warning: Spindle min pwm is greater than max. Check $35 and $36"); - - if ((F_TIMERS / _pwm_freq) < _pwm_period) - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Warning spindle PWM precision (%d bits) too high for frequency (%.2f Hz)", settings.spindle_pwm_precision_bits, _pwm_freq); - - // pre-caculate some PWM count values - _pwm_off_value = (_pwm_period * settings.spindle_pwm_off_value / 100.0); - _pwm_min_value = (_pwm_period * settings.spindle_pwm_min_value / 100.0); - _pwm_max_value = (_pwm_period * settings.spindle_pwm_max_value / 100.0); - -#ifdef ENABLE_PIECEWISE_LINEAR_SPINDLE - _min_rpm = RPM_MIN; - _max_rpm = RPM_MAX; -#else - _min_rpm = settings.rpm_min; - _max_rpm = settings.rpm_max; -#endif - // The pwm_gradient is the pwm duty cycle units per rpm - _pwm_gradient = (_pwm_max_value - _pwm_min_value) / (_max_rpm - _min_rpm); - - _spindle_pwm_chan_num = sys_get_next_PWM_chan_num(); - ledcSetup(_spindle_pwm_chan_num, (double)_pwm_freq, settings.spindle_pwm_precision_bits); // setup the channel - ledcAttachPin(_output_pin, _spindle_pwm_chan_num); // attach the PWM to the pin + ledcSetup(_spindle_pwm_chan_num, (double)_pwm_freq, _pwm_precision); // setup the channel + ledcAttachPin(_output_pin, _spindle_pwm_chan_num); // attach the PWM to the pin if (_enable_pin != UNDEFINED_PIN) pinMode(_enable_pin, OUTPUT); if (_direction_pin != UNDEFINED_PIN) - pinMode(_direction_pin, OUTPUT); - - is_reversable = (_direction_pin != UNDEFINED_PIN); + pinMode(_direction_pin, OUTPUT); config_message(); } @@ -93,23 +66,47 @@ void PWMSpindle :: get_pin_numbers() { #else _direction_pin = UNDEFINED_PIN; #endif + is_reversable = (_direction_pin != UNDEFINED_PIN); - if (_output_pin == UNDEFINED_PIN) - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Warning: Spindle output pin not defined"); + _pwm_freq = settings.spindle_pwm_freq; + _pwm_precision = SPINDLE_PWM_BIT_PRECISION; + _pwm_period = ((1 << _pwm_precision) - 1); + + + if (settings.spindle_pwm_min_value > settings.spindle_pwm_min_value) + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Warning: Spindle min pwm is greater than max. Check $35 and $36"); + + if ((F_TIMERS / _pwm_freq) < _pwm_period) + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Warning spindle PWM precision (%d bits) too high for frequency (%.2f Hz)", _pwm_precision, _pwm_freq); + + // pre-caculate some PWM count values + _pwm_off_value = (_pwm_period * settings.spindle_pwm_off_value / 100.0); + _pwm_min_value = (_pwm_period * settings.spindle_pwm_min_value / 100.0); + _pwm_max_value = (_pwm_period * settings.spindle_pwm_max_value / 100.0); + +#ifdef ENABLE_PIECEWISE_LINEAR_SPINDLE + _min_rpm = RPM_MIN; + _max_rpm = RPM_MAX; +#else + _min_rpm = settings.rpm_min; + _max_rpm = settings.rpm_max; +#endif + // The pwm_gradient is the pwm duty cycle units per rpm + _pwm_gradient = (_pwm_max_value - _pwm_min_value) / (_max_rpm - _min_rpm); + + _spindle_pwm_chan_num = sys_get_next_PWM_chan_num(); + } float PWMSpindle::set_rpm(float rpm) { if (_output_pin == UNDEFINED_PIN) - return rpm; - - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Spindle RPM:%5.2f Min:%5.2f Max:%5.2f", rpm, _min_rpm, _max_rpm); + return rpm; uint32_t pwm_value; // apply overrides and limits - rpm *= (0.010 * sys.spindle_speed_ovr); // Scale by spindle speed override value (percent) - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Spindle RPM 1:%5.2f", rpm); + rpm *= (0.010 * sys.spindle_speed_ovr); // Scale by spindle speed override value (percent) // Calculate PWM register value based on rpm max/min settings and programmed rpm. if ((_min_rpm >= _max_rpm) || (rpm >= _max_rpm)) { @@ -188,7 +185,7 @@ void PWMSpindle::stop() { // prints the startup message of the spindle config void PWMSpindle :: config_message() { - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "PWM spindle on GPIO %d, freq %.2fHz, Res %d bits", _output_pin, _pwm_freq, settings.spindle_pwm_precision_bits); + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "PWM spindle on GPIO %d, freq %.2fHz, Res %d bits", _output_pin, _pwm_freq, _pwm_precision); } diff --git a/Grbl_Esp32/tools/SpindleClass.cpp b/Grbl_Esp32/tools/SpindleClass.cpp index 21623ba6..61d8f7db 100644 --- a/Grbl_Esp32/tools/SpindleClass.cpp +++ b/Grbl_Esp32/tools/SpindleClass.cpp @@ -26,7 +26,7 @@ TODO Consider breaking into one file per class. - Get rid of dependance on machine definition #defines + Get rid of dependance on machine definition #defines SPINDLE_PWM_PIN SPINDLE_ENABLE_PIN SPINDLE_DIR_PIN @@ -40,6 +40,7 @@ #include "RelaySpindle.cpp" #include "Laser.cpp" #include "HuanyangSpindle.cpp" +#include "BESCSpindle.cpp" NullSpindle null_spindle; PWMSpindle pwm_spindle; @@ -47,11 +48,12 @@ RelaySpindle relay_spindle; Laser laser; DacSpindle dac_spindle; HuanyangSpindle huanyang_spindle; +BESCSpindle besc_spindle; void spindle_select(uint8_t spindle_type) { - + switch (spindle_type) { - case SPINDLE_TYPE_PWM: + case SPINDLE_TYPE_PWM: my_spindle = &pwm_spindle; break; case SPINDLE_TYPE_RELAY: @@ -64,7 +66,10 @@ void spindle_select(uint8_t spindle_type) { my_spindle = &dac_spindle; break; case SPINDLE_TYPE_HUANYANG: - my_spindle = &huanyang_spindle; + my_spindle = &huanyang_spindle; + break; + case SPINDLE_TYPE_BESC: + my_spindle = &besc_spindle; break; case SPINDLE_TYPE_NONE: default: @@ -74,7 +79,7 @@ void spindle_select(uint8_t spindle_type) { my_spindle->init(); } -void spindle_read_prefs(Preferences &prefs) { +void spindle_read_prefs(Preferences& prefs) { uint8_t foo = prefs.getUChar("SPIN_TYPE", SPINDLE_TYPE_PWM); } diff --git a/Grbl_Esp32/tools/SpindleClass.h b/Grbl_Esp32/tools/SpindleClass.h index 444ff42a..b24b3a55 100644 --- a/Grbl_Esp32/tools/SpindleClass.h +++ b/Grbl_Esp32/tools/SpindleClass.h @@ -33,16 +33,8 @@ #define SPINDLE_TYPE_LASER 3 #define SPINDLE_TYPE_DAC 4 #define SPINDLE_TYPE_HUANYANG 5 -/* -typedef enum { - SPINDLE_TYPE_NONE = 0, - SPINDLE_TYPE_PWM, - SPINDLE_TYPE_RELAY, - SPINDLE_TYPE_LASER, - SPINDLE_TYPE_DAC, - SPINDLE_TYPE_HUANGYANG, -} spindle_type_t; -*/ +#define SPINDLE_TYPE_BESC 6 + #ifndef SPINDLE_CLASS_H #define SPINDLE_CLASS_H @@ -90,10 +82,8 @@ class PWMSpindle : public Spindle { void config_message(); private: - int8_t _spindle_pwm_chan_num; + int32_t _current_pwm_duty; - float _pwm_gradient; // Precalulated value to speed up rpm to PWM conversions. - void set_spindle_dir_pin(bool Clockwise); protected: @@ -105,8 +95,11 @@ class PWMSpindle : public Spindle { uint8_t _output_pin; uint8_t _enable_pin; uint8_t _direction_pin; + int8_t _spindle_pwm_chan_num; float _pwm_freq; uint32_t _pwm_period; // how many counts in 1 period + uint8_t _pwm_precision; + float _pwm_gradient; // Precalulated value to speed up rpm to PWM conversions. virtual void set_pwm(uint32_t duty); void set_enable_pin(bool enable_pin); @@ -149,7 +142,7 @@ class HuanyangSpindle : public Spindle { virtual void set_state(uint8_t state, float rpm); uint8_t get_state(); float set_rpm(float rpm); - void stop(); + void stop(); private: bool get_response(uint16_t length); @@ -164,6 +157,13 @@ class HuanyangSpindle : public Spindle { uint8_t _state; }; +class BESCSpindle : public PWMSpindle { + public: + void init(); + void config_message(); + float set_rpm(float rpm); +}; + extern Spindle* my_spindle; extern NullSpindle null_spindle; @@ -172,6 +172,7 @@ extern RelaySpindle relay_spindle; extern Laser laser; extern DacSpindle dac_spindle; extern HuanyangSpindle huanyang_spindle; +extern BESCSpindle besc_spindle; void spindle_select(uint8_t spindle_type); void spindle_read_prefs(Preferences& prefs); From c76cc25853be69c9c33c3953ecf82850ad926f14 Mon Sep 17 00:00:00 2001 From: bdring Date: Sun, 19 Apr 2020 13:19:35 -0500 Subject: [PATCH 20/32] Updates - BESCSpindle changes - Spindle PWM channel is fixed at 0 now. - New channels start at 2 --- Grbl_Esp32/Machines/spindle_test.h | 45 ++++++++++++++++++ Grbl_Esp32/machine.h | 2 +- Grbl_Esp32/system.cpp | 11 ++++- Grbl_Esp32/tools/BESCSpindle.cpp | 76 ++++++++++++++++++++---------- Grbl_Esp32/tools/PWMSpindle.cpp | 11 ++++- Grbl_Esp32/tools/RelaySpindle.cpp | 2 +- 6 files changed, 115 insertions(+), 32 deletions(-) create mode 100644 Grbl_Esp32/Machines/spindle_test.h diff --git a/Grbl_Esp32/Machines/spindle_test.h b/Grbl_Esp32/Machines/spindle_test.h new file mode 100644 index 00000000..7c528232 --- /dev/null +++ b/Grbl_Esp32/Machines/spindle_test.h @@ -0,0 +1,45 @@ +/* + test_drive.h + Part of Grbl_ESP32 + + Pin assignments (or lack thereof) for testing Grbl_ESP32. + + It creates a basic 3 axis machine without actually driving + I/O pins. Grbl will report that axes are moving, but no physical + motor motion will occur. + + This can be uploaded to an unattached ESP32 or attached to + unknown hardware with no risk of pins trying to output signals + into a short, etc that could dmamge the ESP32 + + It can also be used to get the basic program running so OTA + (over the air) firmware loading can be done. + + 2018 - Bart Dring + 2020 - Mitch Bradley + + Grbl_ESP32 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grbl_ESP32. If not, see . +*/ + +#define MACHINE_NAME "Spindle Class Testing" + +#define SPINDLE_TYPE SPINDLE_TYPE_BESC +#define SPINDLE_PWM_PIN GPIO_NUM_27 + + +#define LIMIT_MASK 0 // no limit pins + +#ifdef USE_RMT_STEPS +#undef USE_RMT_STEPS // Suppress unused variable warning +#endif diff --git a/Grbl_Esp32/machine.h b/Grbl_Esp32/machine.h index 1d49672e..28a57e3b 100644 --- a/Grbl_Esp32/machine.h +++ b/Grbl_Esp32/machine.h @@ -8,7 +8,7 @@ // !!! For initial testing, start with test_drive.h which disables // all I/O pins -#include "Machines/3axis_v4.h" +#include "Machines/spindle_test.h" // !!! For actual use, change the line above to select a board // from Machines/, for example: diff --git a/Grbl_Esp32/system.cpp b/Grbl_Esp32/system.cpp index 635e6bee..cbfaaf2b 100644 --- a/Grbl_Esp32/system.cpp +++ b/Grbl_Esp32/system.cpp @@ -588,9 +588,16 @@ int8_t sys_get_next_RMT_chan_num() { return -1; } } - +/* + This returns an unused pwm channel. + The 8 channels share 4 timers, so pairs 0,1 & 2,3 , etc + have to be the same frequency. The spindle always uses channel 0 + so we start counting from 2. + There are still possible issues if requested channels use different frequencies + TODO: Make this more robust. +*/ int8_t sys_get_next_PWM_chan_num() { - static uint8_t next_PWM_chan_num = 0; // channels 0-7 are valid + static uint8_t next_PWM_chan_num = 2; // start at 2 to avoid spindle if (next_PWM_chan_num < 8) // 7 is the max PWM channel number return next_PWM_chan_num++; else { diff --git a/Grbl_Esp32/tools/BESCSpindle.cpp b/Grbl_Esp32/tools/BESCSpindle.cpp index b85eacf9..c0531695 100644 --- a/Grbl_Esp32/tools/BESCSpindle.cpp +++ b/Grbl_Esp32/tools/BESCSpindle.cpp @@ -1,31 +1,56 @@ /* - Important ESC Settings - $33=50 // Hz this is the typical good frequency for an ESC - #define DEFAULT_SPINDLE_FREQ 5000.0 // $33 Hz (extended set) + BESCSpindle.cpp - Determine the typical min and max pulse length of your ESC - min_pulse is typically 1ms (0.001 sec) or less - max_pulse is typically 2ms (0.002 sec) or more + This a special type of PWM spindle for RC type Brushless DC Speed + controllers. - determine PWM_period. It is (1/freq) if freq = 50...period = 0.02 + Part of Grbl_ESP32 + 2020 - Bart Dring - determine pulse length for min_pulse and max_pulse in percent. + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . + + + + Important ESC Settings + $33=50 // Hz this is the typical good frequency for an ESC + #define DEFAULT_SPINDLE_FREQ 5000.0 // $33 Hz (extended set) + + Determine the typical min and max pulse length of your ESC + min_pulse is typically 1ms (0.001 sec) or less + max_pulse is typically 2ms (0.002 sec) or more + + determine PWM_period. It is (1/freq) if freq = 50...period = 0.02 + + determine pulse length for min_pulse and max_pulse in percent. + + (pulse / PWM_period) + min_pulse = (0.001 / 0.02) = 0.05 = 5% + max_pulse = (0.002 / .02) = 0.1 = 10% - (pulse / PWM_period) - min_pulse = (0.001 / 0.02) = 0.05 = 5% so ... $34 and $35 = 5.0 - max_pulse = (0.002 / .02) = 0.1 = 10% so ... $36=10 */ #include "grbl.h" #include "SpindleClass.h" - // don't change these -#define BESC_PWM_FREQ 50.0 // Hz +#define BESC_PWM_FREQ 50.0f // Hz #define BESC_PWM_BIT_PRECISION 16 // bits -#define BESC_DEFAULT_MIN_PULSE 5.0 // percent -#define BESC_DEFAULT_MAX_PULSE 10.0 // percent - +#define BESC_PULSE_PERIOD (1.0 / BESC_PWM_FREQ) +// ok to tweak +#define BESC_MIN_PULSE_SECS 0.001f +#define BESC_MAX_PULSE_SECS 0.002f +//don't change +#define BESC_MIN_PULSE_CNT (uint16_t)(BESC_MIN_PULSE_SECS / BESC_PULSE_PERIOD * 65535.0) +#define BESC_MAX_PULSE_CNT (uint16_t)(BESC_MAX_PULSE_SECS / BESC_PULSE_PERIOD * 65535.0) void BESCSpindle :: init() { @@ -40,10 +65,11 @@ void BESCSpindle :: init() { _pwm_freq = BESC_PWM_FREQ; _pwm_precision = 16; - // to do make these tweakable using existing setting as percentages on these defaults - _pwm_off_value = BESC_DEFAULT_MIN_PULSE; - _pwm_min_value = BESC_DEFAULT_MIN_PULSE; - _pwm_max_value = BESC_DEFAULT_MAX_PULSE; + // override these settings + // to do make these tweakable + _pwm_off_value = BESC_MIN_PULSE_CNT; + _pwm_min_value = BESC_MIN_PULSE_CNT; + _pwm_max_value = BESC_MAX_PULSE_CNT; ledcSetup(_spindle_pwm_chan_num, (double)_pwm_freq, _pwm_precision); // setup the channel ledcAttachPin(_output_pin, _spindle_pwm_chan_num); // attach the PWM to the pin @@ -51,6 +77,8 @@ void BESCSpindle :: init() { if (_enable_pin != UNDEFINED_PIN) pinMode(_enable_pin, OUTPUT); + set_rpm(0); + config_message(); } @@ -80,13 +108,9 @@ float BESCSpindle::set_rpm(float rpm) { // determine the pwm value if (rpm == 0.0) { pwm_value = _pwm_off_value; - } else if (rpm == _min_rpm) { - pwm_value = _pwm_min_value; - } else if (rpm == _max_rpm) { - pwm_value = _pwm_max_value; } else { - pwm_value = floor((rpm - _min_rpm) * _pwm_gradient) + _pwm_min_value; - } + pwm_value = (uint16_t)map_float(rpm, _min_rpm, _max_rpm, _pwm_min_value, _pwm_max_value); + } #ifdef SPINDLE_ENABLE_OFF_WITH_ZERO_SPEED set_enable_pin(rpm != 0); diff --git a/Grbl_Esp32/tools/PWMSpindle.cpp b/Grbl_Esp32/tools/PWMSpindle.cpp index e17f6979..05cbf292 100644 --- a/Grbl_Esp32/tools/PWMSpindle.cpp +++ b/Grbl_Esp32/tools/PWMSpindle.cpp @@ -23,6 +23,10 @@ #include "SpindleClass.h" // ======================= PWMSpindle ============================== +/* + This gets called at startup or whenever a spindle setting changes + If the spindle is running it will stop and need to be restarted with M3Snnnn +*/ void PWMSpindle::init() { get_pin_numbers(); @@ -94,7 +98,7 @@ void PWMSpindle :: get_pin_numbers() { // The pwm_gradient is the pwm duty cycle units per rpm _pwm_gradient = (_pwm_max_value - _pwm_min_value) / (_max_rpm - _min_rpm); - _spindle_pwm_chan_num = sys_get_next_PWM_chan_num(); + _spindle_pwm_chan_num = 0; // Channel 0 is reserved for spindle use } @@ -180,7 +184,7 @@ uint8_t PWMSpindle::get_state() { void PWMSpindle::stop() { // inverts are delt with in methods set_enable_pin(false); - set_pwm(0); + set_pwm(_pwm_off_value); } // prints the startup message of the spindle config @@ -190,6 +194,9 @@ void PWMSpindle :: config_message() { void PWMSpindle::set_pwm(uint32_t duty) { + +grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Spindle set duty:%d", duty); + if (_output_pin == UNDEFINED_PIN) return; diff --git a/Grbl_Esp32/tools/RelaySpindle.cpp b/Grbl_Esp32/tools/RelaySpindle.cpp index f517e817..00ef60b4 100644 --- a/Grbl_Esp32/tools/RelaySpindle.cpp +++ b/Grbl_Esp32/tools/RelaySpindle.cpp @@ -34,7 +34,7 @@ void RelaySpindle::init() { pinMode(_output_pin, OUTPUT); if (_enable_pin != UNDEFINED_PIN) - pinMode(SPINDLE_ENABLE_PIN, OUTPUT); + pinMode(_enable_pin, OUTPUT); if (_direction_pin != UNDEFINED_PIN) pinMode(_direction_pin, OUTPUT); From 618b817c6f25cb3e0eb9a5cfb3e33d09bd8839ef Mon Sep 17 00:00:00 2001 From: bdring Date: Sun, 19 Apr 2020 21:25:09 -0500 Subject: [PATCH 21/32] Tweaking, Testing Refactoring - Change SPINDLE_PWM_PIN to SPINDLE_OUTPUT_PIN because it in not always PWM - Changed object name my_spindle to spindle - PWM precision is now auto calculated for highest resolution --- Grbl_Esp32/Grbl_Esp32.ino | 2 +- Grbl_Esp32/Machines/3axis_v3.h | 2 +- Grbl_Esp32/Machines/3axis_v4.h | 2 +- Grbl_Esp32/Machines/3axis_xyx.h | 2 +- Grbl_Esp32/Machines/4axis_external_driver.h | 2 +- Grbl_Esp32/Machines/add_esc_spindle.h | 2 -- Grbl_Esp32/Machines/espduino.h | 2 +- Grbl_Esp32/Machines/lowrider_v1p2.h | 4 +-- Grbl_Esp32/Machines/mpcnc_v1p1.h | 4 +-- Grbl_Esp32/Machines/mpcnc_v1p2.h | 4 +-- Grbl_Esp32/Machines/pen_laser.h | 4 +-- Grbl_Esp32/Machines/servo_axis.h | 4 +-- Grbl_Esp32/Machines/spi_daisy_4axis.h | 2 +- Grbl_Esp32/Machines/spindle_test.h | 20 +++++-------- Grbl_Esp32/Machines/template.h | 2 +- Grbl_Esp32/Machines/tmc2130_pen.h | 2 +- Grbl_Esp32/gcode.cpp | 12 ++++---- Grbl_Esp32/machine_common.h | 6 ---- Grbl_Esp32/motion_control.cpp | 2 +- Grbl_Esp32/protocol.cpp | 14 ++++----- Grbl_Esp32/report.cpp | 2 +- Grbl_Esp32/settings.cpp | 6 ++-- Grbl_Esp32/stepper.cpp | 6 ++-- Grbl_Esp32/tools/Laser.cpp | 2 +- Grbl_Esp32/tools/PWMSpindle.cpp | 32 ++++++++++++++------- Grbl_Esp32/tools/SpindleClass.cpp | 18 ++++++------ Grbl_Esp32/tools/SpindleClass.h | 3 +- 27 files changed, 81 insertions(+), 82 deletions(-) diff --git a/Grbl_Esp32/Grbl_Esp32.ino b/Grbl_Esp32/Grbl_Esp32.ino index ad3e0580..a3e38a72 100644 --- a/Grbl_Esp32/Grbl_Esp32.ino +++ b/Grbl_Esp32/Grbl_Esp32.ino @@ -36,7 +36,7 @@ volatile uint8_t sys_rt_exec_accessory_override; // Global realtime executor bit volatile uint8_t sys_rt_exec_debug; #endif -Spindle *my_spindle; +Spindle *spindle; diff --git a/Grbl_Esp32/Machines/3axis_v3.h b/Grbl_Esp32/Machines/3axis_v3.h index 76b0ec6e..407ce90f 100644 --- a/Grbl_Esp32/Machines/3axis_v3.h +++ b/Grbl_Esp32/Machines/3axis_v3.h @@ -40,7 +40,7 @@ // OK to comment out to use pin for other features #define STEPPERS_DISABLE_PIN GPIO_NUM_13 -#define SPINDLE_PWM_PIN GPIO_NUM_17 // labeled SpinPWM +#define SPINDLE_OUTPUT_PIN GPIO_NUM_17 // labeled SpinPWM #define SPINDLE_ENABLE_PIN GPIO_NUM_22 // labeled SpinEnbl #define COOLANT_MIST_PIN GPIO_NUM_21 // labeled Mist #define COOLANT_FLOOD_PIN GPIO_NUM_16 // labeled Flood diff --git a/Grbl_Esp32/Machines/3axis_v4.h b/Grbl_Esp32/Machines/3axis_v4.h index c73e28f3..a6b6bcfa 100644 --- a/Grbl_Esp32/Machines/3axis_v4.h +++ b/Grbl_Esp32/Machines/3axis_v4.h @@ -40,7 +40,7 @@ // OK to comment out to use pin for other features #define STEPPERS_DISABLE_PIN GPIO_NUM_13 -#define SPINDLE_PWM_PIN GPIO_NUM_25 // labeled SpinPWM +#define SPINDLE_OUTPUT_PIN GPIO_NUM_25 // labeled SpinPWM #define SPINDLE_ENABLE_PIN GPIO_NUM_22 // labeled SpinEnbl #define SPINDLE_DIR_PIN GPIO_NUM_21 //#define MIST_PIN GPIO_NUM_21 // labeled Mist diff --git a/Grbl_Esp32/Machines/3axis_xyx.h b/Grbl_Esp32/Machines/3axis_xyx.h index 1b345ce2..36b7164d 100644 --- a/Grbl_Esp32/Machines/3axis_xyx.h +++ b/Grbl_Esp32/Machines/3axis_xyx.h @@ -32,7 +32,7 @@ #define Y2_STEP_PIN GPIO_NUM_27 /* labeled Z */ #define Y2_DIRECTION_PIN GPIO_NUM_33 /* labeled Z */ -#define SPINDLE_PWM_PIN GPIO_NUM_2 +#define SPINDLE_OUTPUT_PIN GPIO_NUM_2 #define LIMIT_MASK B11 #define X_LIMIT_PIN GPIO_NUM_17 diff --git a/Grbl_Esp32/Machines/4axis_external_driver.h b/Grbl_Esp32/Machines/4axis_external_driver.h index 868b484a..ec6c4b3b 100644 --- a/Grbl_Esp32/Machines/4axis_external_driver.h +++ b/Grbl_Esp32/Machines/4axis_external_driver.h @@ -40,7 +40,7 @@ #define STEPPERS_DISABLE_PIN GPIO_NUM_13 -#define SPINDLE_PWM_PIN GPIO_NUM_25 +#define SPINDLE_OUTPUT_PIN GPIO_NUM_25 #define SPINDLE_ENABLE_PIN GPIO_NUM_22 #define SPINDLE_TYPE SPINDLE_TYPE_HUANYANG diff --git a/Grbl_Esp32/Machines/add_esc_spindle.h b/Grbl_Esp32/Machines/add_esc_spindle.h index 64996392..04c35573 100644 --- a/Grbl_Esp32/Machines/add_esc_spindle.h +++ b/Grbl_Esp32/Machines/add_esc_spindle.h @@ -35,8 +35,6 @@ #define SHOW_EXTENDED_SETTINGS -#define DEFAULT_SPINDLE_PWM_BIT_PRECISION 16 // 16 bit recommended for ESC (don't change) - /* Important ESC Settings $33=50 // Hz this is the typical good frequency for an ESC diff --git a/Grbl_Esp32/Machines/espduino.h b/Grbl_Esp32/Machines/espduino.h index c668f33e..687f9267 100644 --- a/Grbl_Esp32/Machines/espduino.h +++ b/Grbl_Esp32/Machines/espduino.h @@ -39,7 +39,7 @@ // OK to comment out to use pin for other features #define STEPPERS_DISABLE_PIN GPIO_NUM_12 -#define SPINDLE_PWM_PIN GPIO_NUM_19 +#define SPINDLE_OUTPUT_PIN GPIO_NUM_19 #define SPINDLE_DIR_PIN GPIO_NUM_18 #define COOLANT_FLOOD_PIN GPIO_NUM_34 diff --git a/Grbl_Esp32/Machines/lowrider_v1p2.h b/Grbl_Esp32/Machines/lowrider_v1p2.h index 67944058..6d74e92d 100644 --- a/Grbl_Esp32/Machines/lowrider_v1p2.h +++ b/Grbl_Esp32/Machines/lowrider_v1p2.h @@ -50,9 +50,9 @@ //#define USE_SPINDLE_RELAY #ifdef USE_SPINDLE_RELAY - #define SPINDLE_PWM_PIN GPIO_NUM_2 + #define SPINDLE_OUTPUT_PIN GPIO_NUM_2 #else - #define SPINDLE_PWM_PIN GPIO_NUM_16 + #define SPINDLE_OUTPUT_PIN GPIO_NUM_16 #define SPINDLE_ENABLE_PIN GPIO_NUM_32 #endif diff --git a/Grbl_Esp32/Machines/mpcnc_v1p1.h b/Grbl_Esp32/Machines/mpcnc_v1p1.h index d6c30bd2..6537c423 100644 --- a/Grbl_Esp32/Machines/mpcnc_v1p1.h +++ b/Grbl_Esp32/Machines/mpcnc_v1p1.h @@ -50,9 +50,9 @@ //#define USE_SPINDLE_RELAY #ifdef USE_SPINDLE_RELAY - #define SPINDLE_PWM_PIN GPIO_NUM_17 + #define SPINDLE_OUTPUT_PIN GPIO_NUM_17 #else - #define SPINDLE_PWM_PIN GPIO_NUM_16 + #define SPINDLE_OUTPUT_PIN GPIO_NUM_16 #define SPINDLE_ENABLE_PIN GPIO_NUM_32 #endif diff --git a/Grbl_Esp32/Machines/mpcnc_v1p2.h b/Grbl_Esp32/Machines/mpcnc_v1p2.h index 1ca36502..65452d32 100644 --- a/Grbl_Esp32/Machines/mpcnc_v1p2.h +++ b/Grbl_Esp32/Machines/mpcnc_v1p2.h @@ -51,9 +51,9 @@ //#define USE_SPINDLE_RELAY #ifdef USE_SPINDLE_RELAY - #define SPINDLE_PWM_PIN GPIO_NUM_2 + #define SPINDLE_OUTPUT_PIN GPIO_NUM_2 #else - #define SPINDLE_PWM_PIN GPIO_NUM_16 + #define SPINDLE_OUTPUT_PIN GPIO_NUM_16 #define SPINDLE_ENABLE_PIN GPIO_NUM_32 #endif diff --git a/Grbl_Esp32/Machines/pen_laser.h b/Grbl_Esp32/Machines/pen_laser.h index 036415eb..fd5714c5 100644 --- a/Grbl_Esp32/Machines/pen_laser.h +++ b/Grbl_Esp32/Machines/pen_laser.h @@ -49,9 +49,9 @@ #define Y_LIMIT_PIN GPIO_NUM_4 #define LIMIT_MASK B11 -// If SPINDLE_PWM_PIN is commented out, this frees up the pin, but Grbl will still +// If SPINDLE_OUTPUT_PIN is commented out, this frees up the pin, but Grbl will still // use a virtual spindle. Do not comment out the other parameters for the spindle. -#define SPINDLE_PWM_PIN GPIO_NUM_17 // Laser PWM +#define SPINDLE_OUTPUT_PIN GPIO_NUM_17 // Laser PWM #define USING_SERVO // uncomment to use this feature //#define USING_SOLENOID // uncomment to use this feature diff --git a/Grbl_Esp32/Machines/servo_axis.h b/Grbl_Esp32/Machines/servo_axis.h index 33e9448c..792c9c53 100644 --- a/Grbl_Esp32/Machines/servo_axis.h +++ b/Grbl_Esp32/Machines/servo_axis.h @@ -49,9 +49,9 @@ #define Y_LIMIT_PIN GPIO_NUM_4 #define LIMIT_MASK B11 -// If SPINDLE_PWM_PIN is commented out, this frees up the pin, but Grbl will still +// If SPINDLE_OUTPUT_PIN is commented out, this frees up the pin, but Grbl will still // use a virtual spindle. Do not comment out the other parameters for the spindle. -#define SPINDLE_PWM_PIN GPIO_NUM_17 // Laser PWM +#define SPINDLE_OUTPUT_PIN GPIO_NUM_17 // Laser PWM // PWM Generator is based on 80,000,000 Hz counter // Therefor the freq determines the resolution // 80,000,000 / freq = max resolution diff --git a/Grbl_Esp32/Machines/spi_daisy_4axis.h b/Grbl_Esp32/Machines/spi_daisy_4axis.h index abad6f48..d8c9015e 100644 --- a/Grbl_Esp32/Machines/spi_daisy_4axis.h +++ b/Grbl_Esp32/Machines/spi_daisy_4axis.h @@ -76,7 +76,7 @@ // Turn on with M7 and off with M9 #define COOLANT_MIST_PIN GPIO_NUM_21 -#define SPINDLE_PWM_PIN GPIO_NUM_25 +#define SPINDLE_OUTPUT_PIN GPIO_NUM_25 #define SPINDLE_ENABLE_PIN GPIO_NUM_4 // Relay operation diff --git a/Grbl_Esp32/Machines/spindle_test.h b/Grbl_Esp32/Machines/spindle_test.h index 7c528232..c85f1682 100644 --- a/Grbl_Esp32/Machines/spindle_test.h +++ b/Grbl_Esp32/Machines/spindle_test.h @@ -1,19 +1,10 @@ /* - test_drive.h + spindle_test.h Part of Grbl_ESP32 Pin assignments (or lack thereof) for testing Grbl_ESP32. - It creates a basic 3 axis machine without actually driving - I/O pins. Grbl will report that axes are moving, but no physical - motor motion will occur. - - This can be uploaded to an unattached ESP32 or attached to - unknown hardware with no risk of pins trying to output signals - into a short, etc that could dmamge the ESP32 - - It can also be used to get the basic program running so OTA - (over the air) firmware loading can be done. + This is just a minimal machine definition to test Spindle Classes 2018 - Bart Dring 2020 - Mitch Bradley @@ -34,8 +25,11 @@ #define MACHINE_NAME "Spindle Class Testing" -#define SPINDLE_TYPE SPINDLE_TYPE_BESC -#define SPINDLE_PWM_PIN GPIO_NUM_27 + +#define SPINDLE_TYPE SPINDLE_TYPE_PWM +//#define SPINDLE_TYPE SPINDLE_TYPE_BESC + +#define SPINDLE_OUTPUT_PIN GPIO_NUM_27 #define LIMIT_MASK 0 // no limit pins diff --git a/Grbl_Esp32/Machines/template.h b/Grbl_Esp32/Machines/template.h index e34e85a0..0d8ec6d4 100644 --- a/Grbl_Esp32/Machines/template.h +++ b/Grbl_Esp32/Machines/template.h @@ -102,7 +102,7 @@ // machine does not support one of these features, you can leave // the corresponding pin undefined. -// #define SPINDLE_PWM_PIN GPIO_NUM_2 // labeled SpinPWM +// #define SPINDLE_OUTPUT_PIN GPIO_NUM_2 // labeled SpinPWM // #define SPINDLE_ENABLE_PIN GPIO_NUM_22 // labeled SpinEnbl // #define COOLANT_MIST_PIN GPIO_NUM_21 // labeled Mist // #define COOLANT_FLOOD_PIN GPIO_NUM_25 // labeled Flood diff --git a/Grbl_Esp32/Machines/tmc2130_pen.h b/Grbl_Esp32/Machines/tmc2130_pen.h index 82900f8d..c7a5b844 100644 --- a/Grbl_Esp32/Machines/tmc2130_pen.h +++ b/Grbl_Esp32/Machines/tmc2130_pen.h @@ -68,7 +68,7 @@ // Comment out servo pin and uncomment spindle pwm pin to use the servo PWM to control a spindle /* -#define SPINDLE_PWM_PIN GPIO_NUM_27 +#define SPINDLE_OUTPUT_PIN GPIO_NUM_27 */ // #define X_LIMIT_PIN See version section diff --git a/Grbl_Esp32/gcode.cpp b/Grbl_Esp32/gcode.cpp index ec3856bf..d819663c 100644 --- a/Grbl_Esp32/gcode.cpp +++ b/Grbl_Esp32/gcode.cpp @@ -295,7 +295,7 @@ uint8_t gc_execute_line(char* line, uint8_t client) { case 3: case 4: case 5: -#ifndef SPINDLE_PWM_PIN +#ifndef SPINDLE_OUTPUT_PIN grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "No spindle pin defined"); #endif word_bit = MODAL_GROUP_M7; @@ -304,7 +304,7 @@ uint8_t gc_execute_line(char* line, uint8_t client) { gc_block.modal.spindle = SPINDLE_ENABLE_CW; break; case 4: // Supported if SPINDLE_DIR_PIN is defined or laser mode is on. - if (my_spindle->is_reversable || bit_istrue(settings.flags, BITFLAG_LASER_MODE)) + if (spindle->is_reversable || bit_istrue(settings.flags, BITFLAG_LASER_MODE)) gc_block.modal.spindle = SPINDLE_ENABLE_CCW; else FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); @@ -1086,9 +1086,9 @@ uint8_t gc_execute_line(char* line, uint8_t client) { if (gc_state.modal.spindle != SPINDLE_DISABLE) { if (bit_isfalse(gc_parser_flags, GC_PARSER_LASER_ISMOTION)) { if (bit_istrue(gc_parser_flags, GC_PARSER_LASER_DISABLE)) - my_spindle->set_state(gc_state.modal.spindle, 0.0); + spindle->set_state(gc_state.modal.spindle, 0.0); else - my_spindle->set_state(gc_state.modal.spindle, gc_block.values.s); + spindle->set_state(gc_state.modal.spindle, gc_block.values.s); } } gc_state.spindle_speed = gc_block.values.s; // Update spindle speed state. @@ -1110,7 +1110,7 @@ uint8_t gc_execute_line(char* line, uint8_t client) { // Update spindle control and apply spindle speed when enabling it in this block. // NOTE: All spindle state changes are synced, even in laser mode. Also, pl_data, // rather than gc_state, is used to manage laser state for non-laser motions. - my_spindle->set_state(gc_block.modal.spindle, pl_data->spindle_speed); + spindle->set_state(gc_block.modal.spindle, pl_data->spindle_speed); gc_state.modal.spindle = gc_block.modal.spindle; } pl_data->condition |= gc_state.modal.spindle; // Set condition flag for planner use. @@ -1286,7 +1286,7 @@ uint8_t gc_execute_line(char* line, uint8_t client) { if (!(settings_read_coord_data(gc_state.modal.coord_select, gc_state.coord_system))) FAIL(STATUS_SETTING_READ_FAIL); system_flag_wco_change(); // Set to refresh immediately just in case something altered. - my_spindle->set_state(SPINDLE_DISABLE, 0.0); + spindle->set_state(SPINDLE_DISABLE, 0.0); coolant_set_state(COOLANT_DISABLE); } report_feedback_message(MESSAGE_PROGRAM_END); diff --git a/Grbl_Esp32/machine_common.h b/Grbl_Esp32/machine_common.h index 17e6e7de..6eface1f 100644 --- a/Grbl_Esp32/machine_common.h +++ b/Grbl_Esp32/machine_common.h @@ -5,12 +5,6 @@ #define SPINDLE_TYPE SPINDLE_TYPE_PWM #endif -#ifndef SPINDLE_PWM_BIT_PRECISION - #define SPINDLE_PWM_BIT_PRECISION 8 -#endif - -#define SPINDLE_PWM_MAX_VALUE ((1<stop(); + spindle->stop(); coolant_stop(); // turn off all digital I/O sys_io_control(0xFF, false); diff --git a/Grbl_Esp32/protocol.cpp b/Grbl_Esp32/protocol.cpp index 0a2cb6bc..317df58d 100644 --- a/Grbl_Esp32/protocol.cpp +++ b/Grbl_Esp32/protocol.cpp @@ -560,7 +560,7 @@ static void protocol_exec_rt_suspend() { // Ensure any prior spindle stop override is disabled at start of safety door routine. sys.spindle_stop_ovr = SPINDLE_STOP_OVR_DISABLED; #ifndef PARKING_ENABLE - my_spindle->set_state(SPINDLE_DISABLE, 0.0); // De-energize + spindle->set_state(SPINDLE_DISABLE, 0.0); // De-energize coolant_set_state(COOLANT_DISABLE); // De-energize #else // Get current position and store restore location and spindle retract waypoint. @@ -595,7 +595,7 @@ static void protocol_exec_rt_suspend() { // NOTE: Clear accessory state after retract and after an aborted restore motion. pl_data->condition = (PL_COND_FLAG_SYSTEM_MOTION | PL_COND_FLAG_NO_FEED_OVERRIDE); pl_data->spindle_speed = 0.0; - my_spindle->set_state((SPINDLE_DISABLE, 0.0); // De-energize + spindle->set_state((SPINDLE_DISABLE, 0.0); // De-energize coolant_set_state(COOLANT_DISABLE); // De-energize // Execute fast parking retract motion to parking target location. if (parking_target[PARKING_AXIS] < PARKING_TARGET) { @@ -616,7 +616,7 @@ static void protocol_exec_rt_suspend() { if (sys.state == STATE_SLEEP) { report_feedback_message(MESSAGE_SLEEP_MODE); // Spindle and coolant should already be stopped, but do it again just to be sure. - my_spindle->set_state(SPINDLE_DISABLE, 0.0); // De-energize + spindle->set_state(SPINDLE_DISABLE, 0.0); // De-energize coolant_set_state(COOLANT_DISABLE); // De-energize st_go_idle(); // Disable steppers while (!(sys.abort)) protocol_exec_rt_system(); // Do nothing until reset. @@ -655,7 +655,7 @@ static void protocol_exec_rt_suspend() { // When in laser mode, ignore spindle spin-up delay. Set to turn on laser when cycle starts. bit_true(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_RPM); } else { - my_spindle->set_state((restore_condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)), restore_spindle_speed); + spindle->set_state((restore_condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)), restore_spindle_speed); delay_sec(SAFETY_DOOR_SPINDLE_DELAY, DELAY_MODE_SYS_SUSPEND); } } @@ -701,7 +701,7 @@ static void protocol_exec_rt_suspend() { // Handles beginning of spindle stop if (sys.spindle_stop_ovr & SPINDLE_STOP_OVR_INITIATE) { if (gc_state.modal.spindle != SPINDLE_DISABLE) { - my_spindle->set_state(SPINDLE_DISABLE, 0.0); // De-energize + spindle->set_state(SPINDLE_DISABLE, 0.0); // De-energize sys.spindle_stop_ovr = SPINDLE_STOP_OVR_ENABLED; // Set stop override state to enabled, if de-energized. } else { sys.spindle_stop_ovr = SPINDLE_STOP_OVR_DISABLED; // Clear stop override state @@ -714,7 +714,7 @@ static void protocol_exec_rt_suspend() { // When in laser mode, ignore spindle spin-up delay. Set to turn on laser when cycle starts. bit_true(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_RPM); } else - my_spindle->set_state((restore_condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)), restore_spindle_speed); + spindle->set_state((restore_condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)), restore_spindle_speed); } if (sys.spindle_stop_ovr & SPINDLE_STOP_OVR_RESTORE_CYCLE) { system_set_exec_state_flag(EXEC_CYCLE_START); // Set to resume program. @@ -725,7 +725,7 @@ static void protocol_exec_rt_suspend() { // Handles spindle state during hold. NOTE: Spindle speed overrides may be altered during hold state. // NOTE: STEP_CONTROL_UPDATE_SPINDLE_RPM is automatically reset upon resume in step generator. if (bit_istrue(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_RPM)) { - my_spindle->set_state((restore_condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)), restore_spindle_speed); + spindle->set_state((restore_condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)), restore_spindle_speed); bit_false(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_RPM); } } diff --git a/Grbl_Esp32/report.cpp b/Grbl_Esp32/report.cpp index f6700e8c..73115632 100644 --- a/Grbl_Esp32/report.cpp +++ b/Grbl_Esp32/report.cpp @@ -727,7 +727,7 @@ void report_realtime_status(uint8_t client) { } else sys.report_ovr_counter = (REPORT_OVR_REFRESH_IDLE_COUNT - 1); sprintf(temp, "|Ov:%d,%d,%d", sys.f_override, sys.r_override, sys.spindle_speed_ovr); strcat(status, temp); - uint8_t sp_state = my_spindle->get_state(); + uint8_t sp_state = spindle->get_state(); uint8_t cl_state = coolant_get_state(); if (sp_state || cl_state) { strcat(status, "|A:"); diff --git a/Grbl_Esp32/settings.cpp b/Grbl_Esp32/settings.cpp index 1e42df4e..f97f54bb 100644 --- a/Grbl_Esp32/settings.cpp +++ b/Grbl_Esp32/settings.cpp @@ -368,14 +368,14 @@ uint8_t settings_store_global_setting(uint8_t parameter, float value) { case 25: settings.homing_seek_rate = value; break; case 26: settings.homing_debounce_delay = int_value; break; case 27: settings.homing_pulloff = value; break; - case 30: settings.rpm_max = std::max(value, 1.0f); my_spindle->init(); break; // Re-initialize spindle rpm calibration (min of 1) - case 31: settings.rpm_min = value; my_spindle->init(); break; // Re-initialize spindle rpm calibration + case 30: settings.rpm_max = std::max(value, 1.0f); spindle->init(); break; // Re-initialize spindle rpm calibration (min of 1) + case 31: settings.rpm_min = value; spindle->init(); break; // Re-initialize spindle rpm calibration case 32: if (int_value) settings.flags |= BITFLAG_LASER_MODE; else settings.flags &= ~BITFLAG_LASER_MODE; - my_spindle->init(); // update the spindle class + spindle->init(); // update the spindle class break; case 33: settings.spindle_pwm_freq = value; spindle_select(SPINDLE_TYPE); break; // Re-initialize spindle pwm calibration case 34: settings.spindle_pwm_off_value = value; spindle_select(SPINDLE_TYPE); break; // Re-initialize spindle pwm calibration diff --git a/Grbl_Esp32/stepper.cpp b/Grbl_Esp32/stepper.cpp index ea560b9c..859e7d12 100644 --- a/Grbl_Esp32/stepper.cpp +++ b/Grbl_Esp32/stepper.cpp @@ -284,7 +284,7 @@ void IRAM_ATTR onStepperDriverTimer(void* para) { // ISR It is time to take a st // Set real-time spindle output as segment is loaded, just prior to the first step. //spindle_set_speed(st.exec_segment->spindle_rpm); //grbl_send(CLIENT_SERIAL, "A_"); - my_spindle->set_rpm(prep.current_spindle_rpm); + spindle->set_rpm(prep.current_spindle_rpm); } else { @@ -296,7 +296,7 @@ void IRAM_ATTR onStepperDriverTimer(void* para) { // ISR It is time to take a st if (st.exec_block->is_pwm_rate_adjusted) { //spindle_set_speed(spindle_pwm_off_value); //grbl_send(CLIENT_SERIAL, "B_"); - my_spindle->set_rpm(0.0); + spindle->set_rpm(0.0); } } @@ -991,7 +991,7 @@ void st_prep_buffer() { prep.current_speed = sqrt(pl_block->entry_speed_sqr); - if (my_spindle->isRateAdjusted() ){ // settings.flags & BITFLAG_LASER_MODE) { + if (spindle->isRateAdjusted() ){ // settings.flags & BITFLAG_LASER_MODE) { if (pl_block->condition & PL_COND_FLAG_SPINDLE_CCW) { // Pre-compute inverse programmed rate to speed up PWM updating per step segment. prep.inv_rate = 1.0 / pl_block->programmed_rate; diff --git a/Grbl_Esp32/tools/Laser.cpp b/Grbl_Esp32/tools/Laser.cpp index 68078f7d..36c15211 100644 --- a/Grbl_Esp32/tools/Laser.cpp +++ b/Grbl_Esp32/tools/Laser.cpp @@ -37,6 +37,6 @@ void Laser :: config_message() { "Laser spindle on GPIO:%d, Freq:%.2fHz, Res:%dbits Laser mode:$32=%d", _output_pin, _pwm_freq, - SPINDLE_PWM_BIT_PRECISION, + _pwm_precision, isRateAdjusted()); // the current mode } \ No newline at end of file diff --git a/Grbl_Esp32/tools/PWMSpindle.cpp b/Grbl_Esp32/tools/PWMSpindle.cpp index 05cbf292..0512847a 100644 --- a/Grbl_Esp32/tools/PWMSpindle.cpp +++ b/Grbl_Esp32/tools/PWMSpindle.cpp @@ -53,8 +53,8 @@ void PWMSpindle::init() { void PWMSpindle :: get_pin_numbers() { // setup all the pins -#ifdef SPINDLE_PWM_PIN - _output_pin = SPINDLE_PWM_PIN; +#ifdef SPINDLE_OUTPUT_PIN + _output_pin = SPINDLE_OUTPUT_PIN; #else _output_pin = UNDEFINED_PIN; #endif @@ -73,15 +73,11 @@ void PWMSpindle :: get_pin_numbers() { is_reversable = (_direction_pin != UNDEFINED_PIN); _pwm_freq = settings.spindle_pwm_freq; - _pwm_precision = SPINDLE_PWM_BIT_PRECISION; - _pwm_period = ((1 << _pwm_precision) - 1); - + _pwm_precision = calc_pwm_precision(_pwm_freq); // detewrmine the best precision + _pwm_period = (1 << _pwm_precision); if (settings.spindle_pwm_min_value > settings.spindle_pwm_min_value) - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Warning: Spindle min pwm is greater than max. Check $35 and $36"); - - if ((F_TIMERS / _pwm_freq) < _pwm_period) - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Warning spindle PWM precision (%d bits) too high for frequency (%.2f Hz)", _pwm_precision, _pwm_freq); + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Warning: Spindle min pwm is greater than max. Check $35 and $36"); // pre-caculate some PWM count values _pwm_off_value = (_pwm_period * settings.spindle_pwm_off_value / 100.0); @@ -225,4 +221,20 @@ void PWMSpindle::set_enable_pin(bool enable) { void PWMSpindle::set_spindle_dir_pin(bool Clockwise) { if (_direction_pin != UNDEFINED_PIN) digitalWrite(_direction_pin, Clockwise); -} \ No newline at end of file +} + + +/* + Calculate the best precision of a PWM base on the frequency in bits + + 80,000,000 / freq = period + determine the highest precision where (1 << precision) < period +*/ +uint8_t PWMSpindle :: calc_pwm_precision(float freq) { + uint8_t precision = 0; + + while ((1 << precision ) < (uint32_t)(80000000.0/ freq) && precision <= 16) + precision++; + + return precision - 1; +} diff --git a/Grbl_Esp32/tools/SpindleClass.cpp b/Grbl_Esp32/tools/SpindleClass.cpp index 61d8f7db..6f34d9f3 100644 --- a/Grbl_Esp32/tools/SpindleClass.cpp +++ b/Grbl_Esp32/tools/SpindleClass.cpp @@ -27,7 +27,7 @@ Consider breaking into one file per class. Get rid of dependance on machine definition #defines - SPINDLE_PWM_PIN + SPINDLE_OUTPUT_PIN SPINDLE_ENABLE_PIN SPINDLE_DIR_PIN @@ -54,29 +54,29 @@ void spindle_select(uint8_t spindle_type) { switch (spindle_type) { case SPINDLE_TYPE_PWM: - my_spindle = &pwm_spindle; + spindle = &pwm_spindle; break; case SPINDLE_TYPE_RELAY: - my_spindle = &relay_spindle; + spindle = &relay_spindle; break; case SPINDLE_TYPE_LASER: - my_spindle = &laser; + spindle = &laser; break; case SPINDLE_TYPE_DAC: - my_spindle = &dac_spindle; + spindle = &dac_spindle; break; case SPINDLE_TYPE_HUANYANG: - my_spindle = &huanyang_spindle; + spindle = &huanyang_spindle; break; case SPINDLE_TYPE_BESC: - my_spindle = &besc_spindle; + spindle = &besc_spindle; break; case SPINDLE_TYPE_NONE: default: - my_spindle = &null_spindle; + spindle = &null_spindle; break; } - my_spindle->init(); + spindle->init(); } void spindle_read_prefs(Preferences& prefs) { diff --git a/Grbl_Esp32/tools/SpindleClass.h b/Grbl_Esp32/tools/SpindleClass.h index b24b3a55..731f2830 100644 --- a/Grbl_Esp32/tools/SpindleClass.h +++ b/Grbl_Esp32/tools/SpindleClass.h @@ -104,6 +104,7 @@ class PWMSpindle : public Spindle { virtual void set_pwm(uint32_t duty); void set_enable_pin(bool enable_pin); void get_pin_numbers(); + uint8_t calc_pwm_precision(float freq); }; // This is for an on/off spindle all RPMs above 0 are on @@ -164,7 +165,7 @@ class BESCSpindle : public PWMSpindle { float set_rpm(float rpm); }; -extern Spindle* my_spindle; +extern Spindle* spindle; extern NullSpindle null_spindle; extern PWMSpindle pwm_spindle; From e83ff8d7f1058f02479218bfc32ce5b2886b24bb Mon Sep 17 00:00:00 2001 From: bdring Date: Mon, 20 Apr 2020 10:00:08 -0500 Subject: [PATCH 22/32] refactoring --- Grbl_Esp32/Machines/add_esc_spindle.h | 59 --------------------------- Grbl_Esp32/Machines/lowrider_v1p2.h | 2 + Grbl_Esp32/Machines/midtbot.h | 2 + Grbl_Esp32/Machines/mpcnc_v1p1.h | 2 + Grbl_Esp32/Machines/mpcnc_v1p2.h | 2 + Grbl_Esp32/Machines/pen_laser.h | 2 + Grbl_Esp32/Machines/polar_coaster.h | 2 + Grbl_Esp32/Machines/spi_daisy_4axis.h | 11 +++-- Grbl_Esp32/Machines/tmc2130_pen.h | 6 +-- Grbl_Esp32/report.cpp | 27 ++++++++++-- Grbl_Esp32/report.h | 2 + Grbl_Esp32/tools/BESCSpindle.cpp | 4 +- Grbl_Esp32/tools/DacSpindle.cpp | 6 +-- Grbl_Esp32/tools/HuanyangSpindle.cpp | 4 +- Grbl_Esp32/tools/PWMSpindle.cpp | 48 ++++++++++------------ Grbl_Esp32/tools/RelaySpindle.cpp | 10 ++--- Grbl_Esp32/tools/SpindleClass.h | 10 ++--- 17 files changed, 84 insertions(+), 115 deletions(-) delete mode 100644 Grbl_Esp32/Machines/add_esc_spindle.h diff --git a/Grbl_Esp32/Machines/add_esc_spindle.h b/Grbl_Esp32/Machines/add_esc_spindle.h deleted file mode 100644 index 04c35573..00000000 --- a/Grbl_Esp32/Machines/add_esc_spindle.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - add_esc_spindle.h - Part of Grbl_ESP32 - - This is an additional configuration fragment that can be - included after a base configuration file. The base file - establishes most settings and the add-on changes a few things. - For example, in machines.h, you would write: - #include "Machines/3axis_v4.h" // Basic pin assignments - #include "Machines/add_esc_spindle.h" // Add-ons for ESC spindle - - This uses a Brushless DC Hobby motor as a spindle motor. See: - https://github.com/bdring/Grbl_Esp32/wiki/BESC-Spindle-Feature - - 2019 - Bart Dring - 2020 - Mitch Bradley - - Grbl_ESP32 is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Grbl is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grbl_ESP32. If not, see . -*/ - - -// MACHINE_EXTRA is appended to MACHINE_NAME for startup message display -#define MACHINE_EXTRA "_ESC_SPINDLE" - -#define SHOW_EXTENDED_SETTINGS - -/* - Important ESC Settings - $33=50 // Hz this is the typical good frequency for an ESC - #define DEFAULT_SPINDLE_FREQ 5000.0 // $33 Hz (extended set) - - Determine the typical min and max pulse length of your ESC - min_pulse is typically 1ms (0.001 sec) or less - max_pulse is typically 2ms (0.002 sec) or more - - determine PWM_period. It is (1/freq) if freq = 50...period = 0.02 - - determine pulse length for min_pulse and max_pulse in percent. - - (pulse / PWM_period) - min_pulse = (0.001 / 0.02) = 0.05 = 5% so ... $34 and $35 = 5.0 - max_pulse = (0.002 / .02) = 0.1 = 10% so ... $36=10 -*/ - -#define DEFAULT_SPINDLE_FREQ 50.0 -#define DEFAULT_SPINDLE_OFF_VALUE 5.0 -#define DEFAULT_SPINDLE_MIN_VALUE 5.0 -#define DEFAULT_SPINDLE_MAX_VALUE 10.0 diff --git a/Grbl_Esp32/Machines/lowrider_v1p2.h b/Grbl_Esp32/Machines/lowrider_v1p2.h index 6d74e92d..def0aeac 100644 --- a/Grbl_Esp32/Machines/lowrider_v1p2.h +++ b/Grbl_Esp32/Machines/lowrider_v1p2.h @@ -50,8 +50,10 @@ //#define USE_SPINDLE_RELAY #ifdef USE_SPINDLE_RELAY + #define SPINDLE_TYPE SPINDLE_TYPE_PWM #define SPINDLE_OUTPUT_PIN GPIO_NUM_2 #else + #define SPINDLE_TYPE SPINDLE_TYPE_RELAY #define SPINDLE_OUTPUT_PIN GPIO_NUM_16 #define SPINDLE_ENABLE_PIN GPIO_NUM_32 #endif diff --git a/Grbl_Esp32/Machines/midtbot.h b/Grbl_Esp32/Machines/midtbot.h index 4654d986..9ee9715f 100644 --- a/Grbl_Esp32/Machines/midtbot.h +++ b/Grbl_Esp32/Machines/midtbot.h @@ -74,6 +74,8 @@ #define SERVO_PEN_PIN GPIO_NUM_27 +#define SPINDLE_TYPE SPINDLE_TYPE_NONE + // defaults #define DEFAULT_STEP_PULSE_MICROSECONDS 3 #define DEFAULT_STEPPER_IDLE_LOCK_TIME 255 // stay on diff --git a/Grbl_Esp32/Machines/mpcnc_v1p1.h b/Grbl_Esp32/Machines/mpcnc_v1p1.h index 6537c423..885fc7d0 100644 --- a/Grbl_Esp32/Machines/mpcnc_v1p1.h +++ b/Grbl_Esp32/Machines/mpcnc_v1p1.h @@ -50,8 +50,10 @@ //#define USE_SPINDLE_RELAY #ifdef USE_SPINDLE_RELAY + #define SPINDLE_TYPE SPINDLE_TYPE_RELAY #define SPINDLE_OUTPUT_PIN GPIO_NUM_17 #else + #define SPINDLE_TYPE SPINDLE_TYPE_PWM #define SPINDLE_OUTPUT_PIN GPIO_NUM_16 #define SPINDLE_ENABLE_PIN GPIO_NUM_32 #endif diff --git a/Grbl_Esp32/Machines/mpcnc_v1p2.h b/Grbl_Esp32/Machines/mpcnc_v1p2.h index 65452d32..0c14147a 100644 --- a/Grbl_Esp32/Machines/mpcnc_v1p2.h +++ b/Grbl_Esp32/Machines/mpcnc_v1p2.h @@ -51,8 +51,10 @@ //#define USE_SPINDLE_RELAY #ifdef USE_SPINDLE_RELAY + #define SPINDLE_TYPE SPINDLE_TYPE_RELAY #define SPINDLE_OUTPUT_PIN GPIO_NUM_2 #else + #define SPINDLE_TYPE SPINDLE_TYPE_PWM #define SPINDLE_OUTPUT_PIN GPIO_NUM_16 #define SPINDLE_ENABLE_PIN GPIO_NUM_32 #endif diff --git a/Grbl_Esp32/Machines/pen_laser.h b/Grbl_Esp32/Machines/pen_laser.h index fd5714c5..d3484bd4 100644 --- a/Grbl_Esp32/Machines/pen_laser.h +++ b/Grbl_Esp32/Machines/pen_laser.h @@ -68,6 +68,8 @@ #define SOLENOID_PEN_PIN GPIO_NUM_16 #endif +#define SPINDLE_TYPE SPINDLE_TYPE_NONE + // defaults #define DEFAULT_STEP_PULSE_MICROSECONDS 3 #define DEFAULT_STEPPER_IDLE_LOCK_TIME 250 // stay on diff --git a/Grbl_Esp32/Machines/polar_coaster.h b/Grbl_Esp32/Machines/polar_coaster.h index 0f6e0a7c..212753dd 100644 --- a/Grbl_Esp32/Machines/polar_coaster.h +++ b/Grbl_Esp32/Machines/polar_coaster.h @@ -57,6 +57,8 @@ #define X_LIMIT_PIN GPIO_NUM_4 #define LIMIT_MASK B1 +#define SPINDLE_TYPE SPINDLE_TYPE_NONE + #ifdef IGNORE_CONTROL_PINS // maybe set in config.h #undef IGNORE_CONTROL_PINS #endif diff --git a/Grbl_Esp32/Machines/spi_daisy_4axis.h b/Grbl_Esp32/Machines/spi_daisy_4axis.h index d8c9015e..9bb8a830 100644 --- a/Grbl_Esp32/Machines/spi_daisy_4axis.h +++ b/Grbl_Esp32/Machines/spi_daisy_4axis.h @@ -81,10 +81,15 @@ // Relay operation // Install Jumper near relay -// For spindle Use max RPM of 1 -// For PWM remove jumper and set MAX RPM to something higher ($30 setting) +// For PWM remove jumper to prevent relay damage // Interlock jumper along top edge needs to be installed for both versions -#define DEFAULT_SPINDLE_RPM_MAX 1 // Should be 1 for relay operation +#define USE_RELAY // comment out to use PWM + +#ifdef USE_RELAY + #define SPINDLE_TYPE SPINDLE_TYPE_RELAY +#else + #define SPINDLE_TYPE SPINDLE_TYPE_PWM +#endif #define PROBE_PIN GPIO_NUM_22 diff --git a/Grbl_Esp32/Machines/tmc2130_pen.h b/Grbl_Esp32/Machines/tmc2130_pen.h index c7a5b844..0ba7d64d 100644 --- a/Grbl_Esp32/Machines/tmc2130_pen.h +++ b/Grbl_Esp32/Machines/tmc2130_pen.h @@ -65,11 +65,7 @@ #define SERVO_Z_HOME_POS SERVO_Z_RANGE_MAX // move to max during homing #define SERVO_Z_MPOS false // will not use mpos, uses work coordinates - -// Comment out servo pin and uncomment spindle pwm pin to use the servo PWM to control a spindle -/* -#define SPINDLE_OUTPUT_PIN GPIO_NUM_27 -*/ +#define SPINDLE_TYPE SPINDLE_TYPE_RELAY // #define X_LIMIT_PIN See version section #define Y_LIMIT_PIN GPIO_NUM_4 diff --git a/Grbl_Esp32/report.cpp b/Grbl_Esp32/report.cpp index 73115632..fc9294a2 100644 --- a/Grbl_Esp32/report.cpp +++ b/Grbl_Esp32/report.cpp @@ -314,7 +314,7 @@ void report_grbl_settings(uint8_t client, uint8_t show_extended) { sprintf(setting, "$33=%5.3f\r\n", settings.spindle_pwm_freq); strcat(rpt, setting); sprintf(setting, "$34=%3.3f\r\n", settings.spindle_pwm_off_value); strcat(rpt, setting); sprintf(setting, "$35=%3.3f\r\n", settings.spindle_pwm_min_value); strcat(rpt, setting); - sprintf(setting, "$36=%3.3f\r\n", settings.spindle_pwm_max_value); strcat(rpt, setting); + sprintf(setting, "$36=%3.3f\r\n", settings.spindle_pwm_max_value); strcat(rpt, setting); for (uint8_t index = 0; index < USER_SETTING_COUNT; index++) { sprintf(setting, "$%d=%d\r\n", 80 + index, settings.machine_int16[index]); strcat(rpt, setting); } @@ -777,11 +777,11 @@ void report_gcode_comment(char* comment) { /* - Print a message in hex formate + Print a message in hex format Ex: report_hex_msg(msg, "Rx:", 6); - Would could print [MSG Rx: 0x01 0x03 0x01 0x08 0x31 0xbf] + Would would print something like ... [MSG Rx: 0x01 0x03 0x01 0x08 0x31 0xbf] */ -void report_hex_msg(char* buf, const char *prefix, int len) { +void report_hex_msg(char* buf, const char* prefix, int len) { char report[200]; char temp[20]; sprintf(report, "%s", prefix); @@ -792,4 +792,23 @@ void report_hex_msg(char* buf, const char *prefix, int len) { grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "%s", report); +} + +char report_get_axis_letter(uint8_t axis) { + switch (axis) { + case X_AXIS: + return 'X'; + case Y_AXIS: + return 'Y'; + case Z_AXIS: + return 'Z'; + case A_AXIS: + return 'A'; + case B_AXIS: + return 'B'; + case C_AXIS: + return 'C'; + default: + return '?'; + } } \ No newline at end of file diff --git a/Grbl_Esp32/report.h b/Grbl_Esp32/report.h index 8f0042ea..2f811013 100644 --- a/Grbl_Esp32/report.h +++ b/Grbl_Esp32/report.h @@ -172,4 +172,6 @@ void report_gcode_comment(char* comment); void report_hex_msg(char* buf, const char *prefix, int len); +char report_get_axis_letter(uint8_t axis); + #endif diff --git a/Grbl_Esp32/tools/BESCSpindle.cpp b/Grbl_Esp32/tools/BESCSpindle.cpp index c0531695..970cc0ba 100644 --- a/Grbl_Esp32/tools/BESCSpindle.cpp +++ b/Grbl_Esp32/tools/BESCSpindle.cpp @@ -54,7 +54,7 @@ void BESCSpindle :: init() { - get_pin_numbers(); + get_pins_and_settings(); if (_output_pin == UNDEFINED_PIN) { grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Warning: BESC output pin not defined"); @@ -116,6 +116,6 @@ float BESCSpindle::set_rpm(float rpm) { set_enable_pin(rpm != 0); #endif - set_pwm(pwm_value); + set_output(pwm_value); return rpm; } \ No newline at end of file diff --git a/Grbl_Esp32/tools/DacSpindle.cpp b/Grbl_Esp32/tools/DacSpindle.cpp index 2467080c..c0929016 100644 --- a/Grbl_Esp32/tools/DacSpindle.cpp +++ b/Grbl_Esp32/tools/DacSpindle.cpp @@ -27,7 +27,7 @@ // ======================================== DacSpindle ====================================== void DacSpindle :: init() { - get_pin_numbers(); + get_pins_and_settings(); if (_output_pin == UNDEFINED_PIN) return; @@ -97,12 +97,12 @@ float DacSpindle::set_rpm(float rpm) { set_enable_pin(rpm != 0); #endif - set_pwm(pwm_value); + set_output(pwm_value); return rpm; } -void DacSpindle :: set_pwm(uint32_t duty) { +void DacSpindle :: set_output(uint32_t duty) { if (_gpio_ok) { dacWrite(_output_pin, (uint8_t)duty); } diff --git a/Grbl_Esp32/tools/HuanyangSpindle.cpp b/Grbl_Esp32/tools/HuanyangSpindle.cpp index ce13233e..3f7213d4 100644 --- a/Grbl_Esp32/tools/HuanyangSpindle.cpp +++ b/Grbl_Esp32/tools/HuanyangSpindle.cpp @@ -58,7 +58,7 @@ void HuanyangSpindle :: init() { // fail if numbers are not defined - if (!get_pin_numbers()) { + if (!get_pins_and_settings()) { grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Huanyang spindle errors"); return; } @@ -99,7 +99,7 @@ void HuanyangSpindle :: init() { // Checks for all the required pin definitions // It returns a message for each missing pin // Returns true if all pins are defined. -bool HuanyangSpindle :: get_pin_numbers() { +bool HuanyangSpindle :: get_pins_and_settings() { bool pins_ok = true; #ifdef HUANYANG_TXD_PIN diff --git a/Grbl_Esp32/tools/PWMSpindle.cpp b/Grbl_Esp32/tools/PWMSpindle.cpp index 0512847a..fa4a1989 100644 --- a/Grbl_Esp32/tools/PWMSpindle.cpp +++ b/Grbl_Esp32/tools/PWMSpindle.cpp @@ -29,14 +29,13 @@ */ void PWMSpindle::init() { - get_pin_numbers(); + get_pins_and_settings(); if (_output_pin == UNDEFINED_PIN) { grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Warning: Spindle output pin not defined"); return; // We cannot continue without the output pin } - ledcSetup(_spindle_pwm_chan_num, (double)_pwm_freq, _pwm_precision); // setup the channel ledcAttachPin(_output_pin, _spindle_pwm_chan_num); // attach the PWM to the pin @@ -44,13 +43,13 @@ void PWMSpindle::init() { pinMode(_enable_pin, OUTPUT); if (_direction_pin != UNDEFINED_PIN) - pinMode(_direction_pin, OUTPUT); + pinMode(_direction_pin, OUTPUT); config_message(); } // Get the GPIO from the machine definition -void PWMSpindle :: get_pin_numbers() { +void PWMSpindle :: get_pins_and_settings() { // setup all the pins #ifdef SPINDLE_OUTPUT_PIN @@ -66,7 +65,7 @@ void PWMSpindle :: get_pin_numbers() { #endif #ifdef SPINDLE_DIR_PIN - _direction_pin = SPINDLE_DIR_PIN; + _direction_pin = SPINDLE_DIR_PIN; #else _direction_pin = UNDEFINED_PIN; #endif @@ -77,7 +76,7 @@ void PWMSpindle :: get_pin_numbers() { _pwm_period = (1 << _pwm_precision); if (settings.spindle_pwm_min_value > settings.spindle_pwm_min_value) - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Warning: Spindle min pwm is greater than max. Check $35 and $36"); + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Warning: Spindle min pwm is greater than max. Check $35 and $36"); // pre-caculate some PWM count values _pwm_off_value = (_pwm_period * settings.spindle_pwm_off_value / 100.0); @@ -95,18 +94,18 @@ void PWMSpindle :: get_pin_numbers() { _pwm_gradient = (_pwm_max_value - _pwm_min_value) / (_max_rpm - _min_rpm); _spindle_pwm_chan_num = 0; // Channel 0 is reserved for spindle use - + } float PWMSpindle::set_rpm(float rpm) { - if (_output_pin == UNDEFINED_PIN) - return rpm; - uint32_t pwm_value; - // apply overrides and limits - rpm *= (0.010 * sys.spindle_speed_ovr); // Scale by spindle speed override value (percent) + if (_output_pin == UNDEFINED_PIN) + return rpm; + + // apply override + rpm *= (0.010 * sys.spindle_speed_ovr); // Scale by spindle speed override value (percent) // Calculate PWM register value based on rpm max/min settings and programmed rpm. if ((_min_rpm >= _max_rpm) || (rpm >= _max_rpm)) { @@ -118,17 +117,15 @@ float PWMSpindle::set_rpm(float rpm) { sys.spindle_speed = 0.0; pwm_value = _pwm_off_value; } else { // Set minimum PWM output - rpm = _min_rpm; - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Spindle RPM 2:%5.2f", rpm); + rpm = _min_rpm; sys.spindle_speed = rpm; pwm_value = _pwm_min_value; - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Spindle RPM less than min RPM:%5.2f %d", rpm, pwm_value); } } else { // Compute intermediate PWM value with linear spindle speed model. // NOTE: A nonlinear model could be installed here, if required, but keep it VERY light-weight. sys.spindle_speed = rpm; - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Spindle RPM 3:%5.2f", rpm); + #ifdef ENABLE_PIECEWISE_LINEAR_SPINDLE pwm_value = piecewise_linear_fit(rpm); #else @@ -139,9 +136,8 @@ float PWMSpindle::set_rpm(float rpm) { #ifdef SPINDLE_ENABLE_OFF_WITH_ZERO_SPEED set_enable_pin(rpm != 0); #endif - - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Spindle RPM Final:%5.2f", rpm); - set_pwm(pwm_value); + + set_output(pwm_value); return rpm; } @@ -180,7 +176,7 @@ uint8_t PWMSpindle::get_state() { void PWMSpindle::stop() { // inverts are delt with in methods set_enable_pin(false); - set_pwm(_pwm_off_value); + set_output(_pwm_off_value); } // prints the startup message of the spindle config @@ -189,9 +185,7 @@ void PWMSpindle :: config_message() { } -void PWMSpindle::set_pwm(uint32_t duty) { - -grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Spindle set duty:%d", duty); +void PWMSpindle::set_output(uint32_t duty) { if (_output_pin == UNDEFINED_PIN) return; @@ -225,15 +219,15 @@ void PWMSpindle::set_spindle_dir_pin(bool Clockwise) { /* - Calculate the best precision of a PWM base on the frequency in bits + Calculate the highest precision of a PWM based on the frequency in bits 80,000,000 / freq = period - determine the highest precision where (1 << precision) < period + determine the highest precision where (1 << precision) < period */ uint8_t PWMSpindle :: calc_pwm_precision(float freq) { uint8_t precision = 0; - - while ((1 << precision ) < (uint32_t)(80000000.0/ freq) && precision <= 16) + + while ((1 << precision) < (uint32_t)(80000000.0 / freq) && precision <= 16) precision++; return precision - 1; diff --git a/Grbl_Esp32/tools/RelaySpindle.cpp b/Grbl_Esp32/tools/RelaySpindle.cpp index 00ef60b4..f75f4fe2 100644 --- a/Grbl_Esp32/tools/RelaySpindle.cpp +++ b/Grbl_Esp32/tools/RelaySpindle.cpp @@ -27,7 +27,8 @@ This is the same as a PWM spindle, but is a digital rather than PWM output */ void RelaySpindle::init() { - get_pin_numbers(); + get_pins_and_settings(); + if (_output_pin == UNDEFINED_PIN) return; @@ -57,19 +58,18 @@ float RelaySpindle::set_rpm(float rpm) { if (rpm == 0) { sys.spindle_speed = 0.0; - set_pwm(0); + set_output(0); } else { sys.spindle_speed = rpm; - set_pwm(1); + set_output(1); } return rpm; } -void RelaySpindle::set_pwm(uint32_t duty) { +void RelaySpindle::set_output(uint32_t duty) { #ifdef INVERT_SPINDLE_PWM duty = (duty == 0); // flip duty #endif - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Relay output %d", duty > 0); digitalWrite(_output_pin, duty > 0); // anything greater } \ No newline at end of file diff --git a/Grbl_Esp32/tools/SpindleClass.h b/Grbl_Esp32/tools/SpindleClass.h index 731f2830..ffffd2e6 100644 --- a/Grbl_Esp32/tools/SpindleClass.h +++ b/Grbl_Esp32/tools/SpindleClass.h @@ -101,9 +101,9 @@ class PWMSpindle : public Spindle { uint8_t _pwm_precision; float _pwm_gradient; // Precalulated value to speed up rpm to PWM conversions. - virtual void set_pwm(uint32_t duty); + virtual void set_output(uint32_t duty); void set_enable_pin(bool enable_pin); - void get_pin_numbers(); + void get_pins_and_settings(); uint8_t calc_pwm_precision(float freq); }; @@ -114,7 +114,7 @@ class RelaySpindle : public PWMSpindle { void config_message(); float set_rpm(float rpm); protected: - void set_pwm(uint32_t duty); + void set_output(uint32_t duty); }; // this is the same as a PWM spindle, but the M4 compensation is supported. @@ -133,7 +133,7 @@ class DacSpindle : public PWMSpindle { private: bool _gpio_ok; // DAC is on a valid pin protected: - void set_pwm(uint32_t duty); // sets DAC instead of PWM + void set_output(uint32_t duty); // sets DAC instead of PWM }; class HuanyangSpindle : public Spindle { @@ -150,7 +150,7 @@ class HuanyangSpindle : public Spindle { uint16_t ModRTU_CRC(char* buf, int len); void add_ModRTU_CRC(char* buf, int full_msg_len); bool set_mode(uint8_t mode); - bool get_pin_numbers(); + bool get_pins_and_settings(); uint8_t _txd_pin; uint8_t _rxd_pin; From eb1afb56d575af8b1fdc124879a24a665bd33f74 Mon Sep 17 00:00:00 2001 From: bdring Date: Mon, 20 Apr 2020 10:46:13 -0500 Subject: [PATCH 23/32] More cleanup --- Grbl_Esp32/tools/DacSpindle.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Grbl_Esp32/tools/DacSpindle.cpp b/Grbl_Esp32/tools/DacSpindle.cpp index c0929016..7a29f81d 100644 --- a/Grbl_Esp32/tools/DacSpindle.cpp +++ b/Grbl_Esp32/tools/DacSpindle.cpp @@ -39,7 +39,7 @@ void DacSpindle :: init() { if (_output_pin != GPIO_NUM_25 && _output_pin != GPIO_NUM_26) { // DAC can only be used on these pins _gpio_ok = false; - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "DAC spindle pin invalid GPIO_NUM_%d", _output_pin); + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "DAC spindle pin invalid GPIO_NUM_%d (pin 25 or 26 only)", _output_pin); return; } From d35e9836114381488cf3ea8f1912b64bde8be683 Mon Sep 17 00:00:00 2001 From: bdring Date: Mon, 20 Apr 2020 12:15:15 -0500 Subject: [PATCH 24/32] Made some messages and overrided methods more consistant --- Grbl_Esp32/tools/BESCSpindle.cpp | 4 ++-- Grbl_Esp32/tools/DacSpindle.cpp | 2 +- Grbl_Esp32/tools/PWMSpindle.cpp | 38 +++++++++++++------------------ Grbl_Esp32/tools/RelaySpindle.cpp | 2 +- 4 files changed, 20 insertions(+), 26 deletions(-) diff --git a/Grbl_Esp32/tools/BESCSpindle.cpp b/Grbl_Esp32/tools/BESCSpindle.cpp index 970cc0ba..cb4e82f7 100644 --- a/Grbl_Esp32/tools/BESCSpindle.cpp +++ b/Grbl_Esp32/tools/BESCSpindle.cpp @@ -84,7 +84,7 @@ void BESCSpindle :: init() { // prints the startup message of the spindle config void BESCSpindle :: config_message() { - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "BESC spindle on GPIO %d", _output_pin); + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "BESC spindle on Pin:%d", _output_pin); } float BESCSpindle::set_rpm(float rpm) { @@ -110,7 +110,7 @@ float BESCSpindle::set_rpm(float rpm) { pwm_value = _pwm_off_value; } else { pwm_value = (uint16_t)map_float(rpm, _min_rpm, _max_rpm, _pwm_min_value, _pwm_max_value); - } + } #ifdef SPINDLE_ENABLE_OFF_WITH_ZERO_SPEED set_enable_pin(rpm != 0); diff --git a/Grbl_Esp32/tools/DacSpindle.cpp b/Grbl_Esp32/tools/DacSpindle.cpp index 7a29f81d..9018c565 100644 --- a/Grbl_Esp32/tools/DacSpindle.cpp +++ b/Grbl_Esp32/tools/DacSpindle.cpp @@ -56,7 +56,7 @@ void DacSpindle :: init() { } void DacSpindle :: config_message() { - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "DAC spindle on GPIO %d", _output_pin); + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "DAC spindle on Pin:%d", _output_pin); } float DacSpindle::set_rpm(float rpm) { diff --git a/Grbl_Esp32/tools/PWMSpindle.cpp b/Grbl_Esp32/tools/PWMSpindle.cpp index fa4a1989..341d0585 100644 --- a/Grbl_Esp32/tools/PWMSpindle.cpp +++ b/Grbl_Esp32/tools/PWMSpindle.cpp @@ -107,31 +107,25 @@ float PWMSpindle::set_rpm(float rpm) { // apply override rpm *= (0.010 * sys.spindle_speed_ovr); // Scale by spindle speed override value (percent) - // Calculate PWM register value based on rpm max/min settings and programmed rpm. + // apply limits limits if ((_min_rpm >= _max_rpm) || (rpm >= _max_rpm)) { - // No PWM range possible. Set simple on/off spindle control pin state. - sys.spindle_speed = _max_rpm; - pwm_value = _pwm_max_value; - } else if (rpm <= _min_rpm) { - if (rpm == 0.0) { // S0 disables spindle - sys.spindle_speed = 0.0; - pwm_value = _pwm_off_value; - } else { // Set minimum PWM output - rpm = _min_rpm; - sys.spindle_speed = rpm; - pwm_value = _pwm_min_value; - } - } else { - // Compute intermediate PWM value with linear spindle speed model. - // NOTE: A nonlinear model could be installed here, if required, but keep it VERY light-weight. - sys.spindle_speed = rpm; + rpm = _max_rpm; + } else if (rpm != 0.0 && rpm <= _min_rpm) { + rpm = _min_rpm; + } + + sys.spindle_speed = rpm; #ifdef ENABLE_PIECEWISE_LINEAR_SPINDLE - pwm_value = piecewise_linear_fit(rpm); + pwm_value = piecewise_linear_fit(rpm); #else - pwm_value = floor((rpm - _min_rpm) * _pwm_gradient) + _pwm_min_value; -#endif - } + // Calculate PWM register value based on rpm max/min settings and programmed rpm. + if (rpm == 0.0) { + pwm_value = _pwm_off_value; + } else { + pwm_value = (uint16_t)map_float(rpm, _min_rpm, _max_rpm, _pwm_min_value, _pwm_max_value); + } +#endif #ifdef SPINDLE_ENABLE_OFF_WITH_ZERO_SPEED set_enable_pin(rpm != 0); @@ -181,7 +175,7 @@ void PWMSpindle::stop() { // prints the startup message of the spindle config void PWMSpindle :: config_message() { - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "PWM spindle on GPIO %d, freq %.2fHz, Res %d bits", _output_pin, _pwm_freq, _pwm_precision); + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "PWM spindle on Pin:%d, Freq:%.2fHz, Res:%dbits", _output_pin, _pwm_freq, _pwm_precision); } diff --git a/Grbl_Esp32/tools/RelaySpindle.cpp b/Grbl_Esp32/tools/RelaySpindle.cpp index f75f4fe2..cdc295c0 100644 --- a/Grbl_Esp32/tools/RelaySpindle.cpp +++ b/Grbl_Esp32/tools/RelaySpindle.cpp @@ -47,7 +47,7 @@ void RelaySpindle::init() { // prints the startup message of the spindle config void RelaySpindle :: config_message() { - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Relay spindle on GPIO %d", _output_pin); + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Relay spindle on Pin:%d", _output_pin); } float RelaySpindle::set_rpm(float rpm) { From 0461b45fc0a6f850a78170694dd1c40dcec4b303 Mon Sep 17 00:00:00 2001 From: bdring Date: Mon, 20 Apr 2020 14:49:17 -0500 Subject: [PATCH 25/32] Forgot to put test_drive.h as the default machine def. --- Grbl_Esp32/machine.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Grbl_Esp32/machine.h b/Grbl_Esp32/machine.h index 28a57e3b..d57814c4 100644 --- a/Grbl_Esp32/machine.h +++ b/Grbl_Esp32/machine.h @@ -8,7 +8,7 @@ // !!! For initial testing, start with test_drive.h which disables // all I/O pins -#include "Machines/spindle_test.h" +#include "Machines/test_drive.h" // !!! For actual use, change the line above to select a board // from Machines/, for example: From 16269ec117b7d8f45fc95b64b37cd1598af42c4f Mon Sep 17 00:00:00 2001 From: bdring Date: Tue, 21 Apr 2020 13:22:12 -0500 Subject: [PATCH 26/32] minor update to machine definition files - Got rid of MACHINE in names, that is already in the const prefix for that message - Add spindle tpyes....just a temporary method until prefs are ready - minor formatting --- Grbl_Esp32/Machines/3axis_v3.h | 4 +- Grbl_Esp32/Machines/3axis_v4.h | 4 +- Grbl_Esp32/Machines/3axis_xyx.h | 6 +- Grbl_Esp32/Machines/4axis_external_driver.h | 5 +- Grbl_Esp32/Machines/add_esc_spindle.h | 61 ---------- Grbl_Esp32/Machines/espduino.h | 3 +- Grbl_Esp32/Machines/foo_6axis.h | 9 +- Grbl_Esp32/Machines/midtbot.h | 9 +- Grbl_Esp32/Machines/mpcnc_v1p1.h | 4 +- Grbl_Esp32/Machines/mpcnc_v1p2.h | 4 +- Grbl_Esp32/Machines/pen_laser.h | 2 +- Grbl_Esp32/Machines/polar_coaster.h | 4 +- Grbl_Esp32/Machines/servo_axis.h | 120 -------------------- Grbl_Esp32/Machines/spi_daisy_4axis_xyyz.h | 1 + Grbl_Esp32/Machines/spi_daisy_4axis_xyz.h | 1 + Grbl_Esp32/Machines/template.h | 2 +- Grbl_Esp32/Machines/test_drive.h | 4 +- Grbl_Esp32/Machines/tmc2130_pen.h | 5 +- 18 files changed, 42 insertions(+), 206 deletions(-) delete mode 100644 Grbl_Esp32/Machines/add_esc_spindle.h delete mode 100644 Grbl_Esp32/Machines/servo_axis.h diff --git a/Grbl_Esp32/Machines/3axis_v3.h b/Grbl_Esp32/Machines/3axis_v3.h index 76b0ec6e..4209557d 100644 --- a/Grbl_Esp32/Machines/3axis_v3.h +++ b/Grbl_Esp32/Machines/3axis_v3.h @@ -23,7 +23,7 @@ along with Grbl_ESP32. If not, see . */ -#define MACHINE_NAME "MACHINE_ESP32_V3.5" +#define MACHINE_NAME "ESP32_V3.5" #define X_STEP_PIN GPIO_NUM_12 #define X_DIRECTION_PIN GPIO_NUM_26 @@ -40,8 +40,10 @@ // OK to comment out to use pin for other features #define STEPPERS_DISABLE_PIN GPIO_NUM_13 +#define SPINDLE_TYPE SPINDLE_TYPE_PWM #define SPINDLE_PWM_PIN GPIO_NUM_17 // labeled SpinPWM #define SPINDLE_ENABLE_PIN GPIO_NUM_22 // labeled SpinEnbl + #define COOLANT_MIST_PIN GPIO_NUM_21 // labeled Mist #define COOLANT_FLOOD_PIN GPIO_NUM_16 // labeled Flood #define PROBE_PIN GPIO_NUM_32 // labeled Probe diff --git a/Grbl_Esp32/Machines/3axis_v4.h b/Grbl_Esp32/Machines/3axis_v4.h index 14d1bde3..d6c0702a 100644 --- a/Grbl_Esp32/Machines/3axis_v4.h +++ b/Grbl_Esp32/Machines/3axis_v4.h @@ -23,7 +23,7 @@ along with Grbl_ESP32. If not, see . */ -#define MACHINE_NAME "MACHINE_ESP32_V4" +#define MACHINE_NAME "ESP32_V4" #define X_STEP_PIN GPIO_NUM_12 #define X_DIRECTION_PIN GPIO_NUM_14 @@ -40,8 +40,10 @@ // OK to comment out to use pin for other features #define STEPPERS_DISABLE_PIN GPIO_NUM_13 +#define SPINDLE_TYPE SPINDLE_TYPE_PWM #define SPINDLE_PWM_PIN GPIO_NUM_2 // labeled SpinPWM #define SPINDLE_ENABLE_PIN GPIO_NUM_22 // labeled SpinEnbl + #define MIST_PIN GPIO_NUM_21 // labeled Mist #define FLOOD_PIN GPIO_NUM_25 // labeled Flood #define PROBE_PIN GPIO_NUM_32 // labeled Probe diff --git a/Grbl_Esp32/Machines/3axis_xyx.h b/Grbl_Esp32/Machines/3axis_xyx.h index 1b345ce2..55c14b16 100644 --- a/Grbl_Esp32/Machines/3axis_xyx.h +++ b/Grbl_Esp32/Machines/3axis_xyx.h @@ -24,7 +24,7 @@ along with Grbl_ESP32. If not, see . */ -#define MACHINE_NAME "MACHINE_ESP32_V4_XYX" +#define MACHINE_NAME "ESP32_V4_XYX" #define X_STEP_PIN GPIO_NUM_26 /* labeled Y */ #define X_DIRECTION_PIN GPIO_NUM_15 /* labeled Y */ #define Y_STEP_PIN GPIO_NUM_12 /* labeled X */ @@ -32,7 +32,9 @@ #define Y2_STEP_PIN GPIO_NUM_27 /* labeled Z */ #define Y2_DIRECTION_PIN GPIO_NUM_33 /* labeled Z */ +#define SPINDLE_TYPE SPINDLE_TYPE_PWM #define SPINDLE_PWM_PIN GPIO_NUM_2 +#define SPINDLE_ENABLE_PIN GPIO_NUM_22 #define LIMIT_MASK B11 #define X_LIMIT_PIN GPIO_NUM_17 @@ -44,7 +46,7 @@ #define COOLANT_MIST_PIN GPIO_NUM_21 #define COOLANT_FLOOD_PIN GPIO_NUM_25 -#define SPINDLE_ENABLE_PIN GPIO_NUM_22 + // see versions for X and Z #define PROBE_PIN GPIO_NUM_32 diff --git a/Grbl_Esp32/Machines/4axis_external_driver.h b/Grbl_Esp32/Machines/4axis_external_driver.h index f88204ad..9f60e10b 100644 --- a/Grbl_Esp32/Machines/4axis_external_driver.h +++ b/Grbl_Esp32/Machines/4axis_external_driver.h @@ -39,10 +39,13 @@ #define A_DIRECTION_PIN GPIO_NUM_12 #define STEPPERS_DISABLE_PIN GPIO_NUM_13 - +/* +#define SPINDLE_TYPE SPINDLE_TYPE_PWM #define SPINDLE_PWM_PIN GPIO_NUM_25 #define SPINDLE_ENABLE_PIN GPIO_NUM_22 +*/ +#define SPINDLE_TYPE SPINDLE_TYPE_HUANYANG #define MODBUS_TX GPIO_NUM_17 #define MODBUS_RX GPIO_NUM_4 #define MODBUS_CTRL GPIO_NUM_16 diff --git a/Grbl_Esp32/Machines/add_esc_spindle.h b/Grbl_Esp32/Machines/add_esc_spindle.h deleted file mode 100644 index b1c078b4..00000000 --- a/Grbl_Esp32/Machines/add_esc_spindle.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - add_esc_spindle.h - Part of Grbl_ESP32 - - This is an additional configuration fragment that can be - included after a base configuration file. The base file - establishes most settings and the add-on changes a few things. - For example, in machines.h, you would write: - #include "Machines/3axis_v4.h" // Basic pin assignments - #include "Machines/add_esc_spindle.h" // Add-ons for ESC spindle - - This uses a Brushless DC Hobby motor as a spindle motor. See: - https://github.com/bdring/Grbl_Esp32/wiki/BESC-Spindle-Feature - - 2019 - Bart Dring - 2020 - Mitch Bradley - - Grbl_ESP32 is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Grbl is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grbl_ESP32. If not, see . -*/ - - -// MACHINE_EXTRA is appended to MACHINE_NAME for startup message display -#define MACHINE_EXTRA "_ESC_SPINDLE" - -#define SHOW_EXTENDED_SETTINGS - -#define SPINDLE_PWM_BIT_PRECISION 16 // 16 bit recommended for ESC (don't change) - -/* - Important ESC Settings - $33=50 // Hz this is the typical good frequency for an ESC - #define DEFAULT_SPINDLE_FREQ 5000.0 // $33 Hz (extended set) - - Determine the typical min and max pulse length of your ESC - min_pulse is typically 1ms (0.001 sec) or less - max_pulse is typically 2ms (0.002 sec) or more - - determine PWM_period. It is (1/freq) if freq = 50...period = 0.02 - - determine pulse length for min_pulse and max_pulse in percent. - - (pulse / PWM_period) - min_pulse = (0.001 / 0.02) = 0.05 = 5% so ... $34 and $35 = 5.0 - max_pulse = (0.002 / .02) = 0.1 = 10% so ... $36=10 -*/ - -#define DEFAULT_SPINDLE_FREQ 50.0 -#define DEFAULT_SPINDLE_OFF_VALUE 5.0 -#define DEFAULT_SPINDLE_MIN_VALUE 5.0 -#define DEFAULT_SPINDLE_MAX_VALUE 10.0 diff --git a/Grbl_Esp32/Machines/espduino.h b/Grbl_Esp32/Machines/espduino.h index c668f33e..e1141050 100644 --- a/Grbl_Esp32/Machines/espduino.h +++ b/Grbl_Esp32/Machines/espduino.h @@ -25,7 +25,7 @@ along with Grbl_ESP32. If not, see . */ -#define MACHINE_NAME "MACHINE_ESPDUINO_32" +#define MACHINE_NAME "ESPDUINO_32" #define X_STEP_PIN GPIO_NUM_26 #define X_DIRECTION_PIN GPIO_NUM_16 @@ -39,6 +39,7 @@ // OK to comment out to use pin for other features #define STEPPERS_DISABLE_PIN GPIO_NUM_12 +#define SPINDLE_TYPE SPINDLE_TYPE_PWM #define SPINDLE_PWM_PIN GPIO_NUM_19 #define SPINDLE_DIR_PIN GPIO_NUM_18 diff --git a/Grbl_Esp32/Machines/foo_6axis.h b/Grbl_Esp32/Machines/foo_6axis.h index 0426ac27..d2222f79 100644 --- a/Grbl_Esp32/Machines/foo_6axis.h +++ b/Grbl_Esp32/Machines/foo_6axis.h @@ -22,13 +22,15 @@ */ -#define MACHINE_NAME "MACHINE_FOO_6X" +#define MACHINE_NAME "FOO_6X" #ifdef N_AXIS #undef N_AXIS #endif #define N_AXIS 6 +#define SPINDLE_TYPE SPINDLE_TYPE_NONE + // stepper motors #define X_STEP_PIN GPIO_NUM_12 #define X_DIRECTION_PIN GPIO_NUM_26 @@ -122,11 +124,6 @@ #define DEFAULT_HOMING_DEBOUNCE_DELAY 250 // msec (0-65k) #define DEFAULT_HOMING_PULLOFF 3.0 // mm -#define DEFAULT_SPINDLE_RPM_MAX 1000.0 // rpm -#define DEFAULT_SPINDLE_RPM_MIN 0.0 // rpm - -#define DEFAULT_LASER_MODE 0 // false - #define DEFAULT_X_STEPS_PER_MM 400.0 #define DEFAULT_Y_STEPS_PER_MM 400.0 #define DEFAULT_Z_STEPS_PER_MM 100.0 // This is percent in servo mode diff --git a/Grbl_Esp32/Machines/midtbot.h b/Grbl_Esp32/Machines/midtbot.h index 7a030607..e2a3b5c1 100644 --- a/Grbl_Esp32/Machines/midtbot.h +++ b/Grbl_Esp32/Machines/midtbot.h @@ -22,7 +22,9 @@ along with Grbl_ESP32. If not, see . */ -#define MACHINE_NAME "MACHINE_MIDTBOT" +#define MACHINE_NAME "MIDTBOT" + +#define SPINDLE_TYPE SPINDLE_TYPE_NONE #define X_STEP_PIN GPIO_NUM_12 #define Y_STEP_PIN GPIO_NUM_14 @@ -98,11 +100,6 @@ #define DEFAULT_HOMING_DEBOUNCE_DELAY 250 // msec (0-65k) #define DEFAULT_HOMING_PULLOFF 3.0 // mm -#define DEFAULT_SPINDLE_RPM_MAX 1000.0 // rpm -#define DEFAULT_SPINDLE_RPM_MIN 0.0 // rpm - -#define DEFAULT_LASER_MODE 0 // false - #define DEFAULT_X_STEPS_PER_MM 200.0 #define DEFAULT_Y_STEPS_PER_MM 100.0 #define DEFAULT_Z_STEPS_PER_MM 100.0 // This is percent in servo mode diff --git a/Grbl_Esp32/Machines/mpcnc_v1p1.h b/Grbl_Esp32/Machines/mpcnc_v1p1.h index d6c30bd2..5d0d400d 100644 --- a/Grbl_Esp32/Machines/mpcnc_v1p1.h +++ b/Grbl_Esp32/Machines/mpcnc_v1p1.h @@ -25,7 +25,7 @@ // // Pin assignments for the Buildlog.net MPCNC controller -#define MACHINE_NAME "MACHINE_MPCNC_V1P1" +#define MACHINE_NAME "MPCNC_V1P1" #define USE_GANGED_AXES // allow two motors on an axis @@ -50,8 +50,10 @@ //#define USE_SPINDLE_RELAY #ifdef USE_SPINDLE_RELAY + #define SPINDLE_TYPE SPINDLE_TYPE_RELAY #define SPINDLE_PWM_PIN GPIO_NUM_17 #else + #define SPINDLE_TYPE SPINDLE_TYPE_PWM #define SPINDLE_PWM_PIN GPIO_NUM_16 #define SPINDLE_ENABLE_PIN GPIO_NUM_32 #endif diff --git a/Grbl_Esp32/Machines/mpcnc_v1p2.h b/Grbl_Esp32/Machines/mpcnc_v1p2.h index 1ca36502..aad1d24f 100644 --- a/Grbl_Esp32/Machines/mpcnc_v1p2.h +++ b/Grbl_Esp32/Machines/mpcnc_v1p2.h @@ -26,7 +26,7 @@ -#define MACHINE_NAME "MACHINE_MPCNC_V1P2" +#define MACHINE_NAME "MPCNC_V1P2" #define USE_GANGED_AXES // allow two motors on an axis @@ -51,8 +51,10 @@ //#define USE_SPINDLE_RELAY #ifdef USE_SPINDLE_RELAY + #define SPINDLE_TYPE SPINDLE_TYPE_RELAY #define SPINDLE_PWM_PIN GPIO_NUM_2 #else + #define SPINDLE_TYPE SPINDLE_TYPE_PWM #define SPINDLE_PWM_PIN GPIO_NUM_16 #define SPINDLE_ENABLE_PIN GPIO_NUM_32 #endif diff --git a/Grbl_Esp32/Machines/pen_laser.h b/Grbl_Esp32/Machines/pen_laser.h index eb405f2e..e1e082fe 100644 --- a/Grbl_Esp32/Machines/pen_laser.h +++ b/Grbl_Esp32/Machines/pen_laser.h @@ -26,7 +26,7 @@ along with Grbl_ESP32. If not, see . */ -#define MACHINE_NAME "MACHINE_PEN_LASER" +#define MACHINE_NAME "PEN_LASER" // Pick a board version //#define PEN_LASER_V1 diff --git a/Grbl_Esp32/Machines/polar_coaster.h b/Grbl_Esp32/Machines/polar_coaster.h index e4b35649..80a6bfdc 100644 --- a/Grbl_Esp32/Machines/polar_coaster.h +++ b/Grbl_Esp32/Machines/polar_coaster.h @@ -22,12 +22,14 @@ along with Grbl_ESP32. If not, see . */ -#define MACHINE_NAME "MACHINE_POLAR_COASTER" +#define MACHINE_NAME "POLAR_COASTER" // This causes the custom code file to be included in the build // via ../custom_code.cpp #define CUSTOM_CODE_FILENAME "Custom/polar_coaster.cpp" +#define SPINDLE_TYPE SPINDLE_TYPE_NONE + #define RADIUS_AXIS 0 #define POLAR_AXIS 1 diff --git a/Grbl_Esp32/Machines/servo_axis.h b/Grbl_Esp32/Machines/servo_axis.h deleted file mode 100644 index 33e9448c..00000000 --- a/Grbl_Esp32/Machines/servo_axis.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - servo_axis.h - Part of Grbl_ESP32 - - Pin assignments for the Buildlog.net pen laser controller V1 - using servos. - - For pen mode be sure to uncomment #define USE_PEN_SERVO in config.h - For solenoid mode be sure to uncomment #define USE_PEN_SERVO in config.h - For laser mode, you do not need to change anything - Note: You can use all 3 modes at the same time if you want - - 2018 - Bart Dring - 2020 - Mitch Bradley - - Grbl_ESP32 is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Grbl is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grbl_ESP32. If not, see . -*/ - -#define MACHINE_NAME "MACHINE_SERVO_AXIS" - -// Pick a board version -//#define PEN_LASER_V1 -#define PEN_LASER_V2 - -#define X_STEP_PIN GPIO_NUM_12 -#define X_DIRECTION_PIN GPIO_NUM_26 - -#define STEPPERS_DISABLE_PIN GPIO_NUM_13 - -#ifdef PEN_LASER_V1 - #define X_LIMIT_PIN GPIO_NUM_2 -#endif - -#ifdef PEN_LASER_V2 - #define X_LIMIT_PIN GPIO_NUM_15 -#endif - -#define Y_LIMIT_PIN GPIO_NUM_4 -#define LIMIT_MASK B11 - -// If SPINDLE_PWM_PIN is commented out, this frees up the pin, but Grbl will still -// use a virtual spindle. Do not comment out the other parameters for the spindle. -#define SPINDLE_PWM_PIN GPIO_NUM_17 // Laser PWM -// PWM Generator is based on 80,000,000 Hz counter -// Therefor the freq determines the resolution -// 80,000,000 / freq = max resolution -// For 5000 that is 80,000,000 / 5000 = 16000 -// round down to nearest bit count for SPINDLE_PWM_MAX_VALUE -//#define SPINDLE_PWM_BASE_FREQ 5000 // Hz -#define SPINDLE_PWM_OFF_VALUE 0 - -#ifndef SPINDLE_PWM_MIN_VALUE - #define SPINDLE_PWM_MIN_VALUE 1 // Must be greater than zero. -#endif - -#define SERVO_Y_PIN GPIO_NUM_14 -#define SERVO_Y_RANGE_MIN 0.0 -#define SERVO_Y_RANGE_MAX 30.0 - -#define SERVO_Z_PIN GPIO_NUM_27 -#define SERVO_Z_RANGE_MIN 0.0 -#define SERVO_Z_RANGE_MAX 20.0 - -// defaults -#define DEFAULT_STEP_PULSE_MICROSECONDS 3 -#define DEFAULT_STEPPER_IDLE_LOCK_TIME 250 // stay on - -#define DEFAULT_STEPPING_INVERT_MASK 0 // uint8_t -#define DEFAULT_DIRECTION_INVERT_MASK 0 // uint8_t -#define DEFAULT_INVERT_ST_ENABLE 0 // boolean -#define DEFAULT_INVERT_LIMIT_PINS 1 // boolean -#define DEFAULT_INVERT_PROBE_PIN 0 // boolean - -#define DEFAULT_STATUS_REPORT_MASK 1 - -#define DEFAULT_JUNCTION_DEVIATION 0.01 // mm -#define DEFAULT_ARC_TOLERANCE 0.002 // mm -#define DEFAULT_REPORT_INCHES 0 // false - -#define DEFAULT_SOFT_LIMIT_ENABLE 0 // false -#define DEFAULT_HARD_LIMIT_ENABLE 0 // false - -#define DEFAULT_HOMING_ENABLE 0 -#define DEFAULT_HOMING_DIR_MASK 0 // move positive dir Z, negative X,Y -#define DEFAULT_HOMING_FEED_RATE 200.0 // mm/min -#define DEFAULT_HOMING_SEEK_RATE 1000.0 // mm/min -#define DEFAULT_HOMING_DEBOUNCE_DELAY 250 // msec (0-65k) -#define DEFAULT_HOMING_PULLOFF 3.0 // mm - -#define DEFAULT_SPINDLE_RPM_MAX 1000.0 // rpm -#define DEFAULT_SPINDLE_RPM_MIN 0.0 // rpm - -#define DEFAULT_LASER_MODE 0 // false - -#define DEFAULT_X_STEPS_PER_MM 40 // half turn on a stepper -#define DEFAULT_Y_STEPS_PER_MM 100.0 // default calibration value -#define DEFAULT_Z_STEPS_PER_MM 100.0 // default calibration value - -#define DEFAULT_X_MAX_RATE 2000.0 // mm/min -#define DEFAULT_Y_MAX_RATE 2000.0 // mm/min -#define DEFAULT_Z_MAX_RATE 2000.0 // mm/min - -#define DEFAULT_X_ACCELERATION (50.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2 -#define DEFAULT_Y_ACCELERATION (50.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2 -#define DEFAULT_Z_ACCELERATION (50.0*60*60) - -#define DEFAULT_X_MAX_TRAVEL 300.0 // mm NOTE: Must be a positive value. -#define DEFAULT_Y_MAX_TRAVEL 100.0 // default calibration value -#define DEFAULT_Z_MAX_TRAVEL 100.0 // default calibration value diff --git a/Grbl_Esp32/Machines/spi_daisy_4axis_xyyz.h b/Grbl_Esp32/Machines/spi_daisy_4axis_xyyz.h index c279eeb6..1b3233f4 100644 --- a/Grbl_Esp32/Machines/spi_daisy_4axis_xyyz.h +++ b/Grbl_Esp32/Machines/spi_daisy_4axis_xyyz.h @@ -78,6 +78,7 @@ // Turn on with M7 and off with M9 #define COOLANT_MIST_PIN GPIO_NUM_21 +#define SPINDLE_TYPE SPINDLE_TYPE_PWM #define SPINDLE_PWM_PIN GPIO_NUM_25 #define SPINDLE_ENABLE_PIN GPIO_NUM_4 diff --git a/Grbl_Esp32/Machines/spi_daisy_4axis_xyz.h b/Grbl_Esp32/Machines/spi_daisy_4axis_xyz.h index 3a767be5..5a2021db 100644 --- a/Grbl_Esp32/Machines/spi_daisy_4axis_xyz.h +++ b/Grbl_Esp32/Machines/spi_daisy_4axis_xyz.h @@ -63,6 +63,7 @@ // Turn on with M7 and off with M9 #define COOLANT_MIST_PIN GPIO_NUM_21 +#define SPINDLE_TYPE SPINDLE_TYPE_PWM #define SPINDLE_PWM_PIN GPIO_NUM_25 #define SPINDLE_ENABLE_PIN GPIO_NUM_4 diff --git a/Grbl_Esp32/Machines/template.h b/Grbl_Esp32/Machines/template.h index e34e85a0..9289ba0a 100644 --- a/Grbl_Esp32/Machines/template.h +++ b/Grbl_Esp32/Machines/template.h @@ -56,7 +56,7 @@ // will be shown in a Grbl startup message to identify your // configuration. -#define MACHINE_NAME "MACHINE_TEMPLATE" +#define MACHINE_NAME "TEMPLATE" // If your machine requires custom code as described below in // Special Features, you must copy Custom/custom_code_template.cpp diff --git a/Grbl_Esp32/Machines/test_drive.h b/Grbl_Esp32/Machines/test_drive.h index 56a4aa5c..dd5854c4 100644 --- a/Grbl_Esp32/Machines/test_drive.h +++ b/Grbl_Esp32/Machines/test_drive.h @@ -32,10 +32,12 @@ along with Grbl_ESP32. If not, see . */ -#define MACHINE_NAME "MACHINE_DEFAULT - Demo Only No I/O!" +#define MACHINE_NAME "Test Drive - Demo Only No I/O!" #define LIMIT_MASK 0 // no limit pins +#define SPINDLE_TYPE SPINDLE_TYPE_NONE + #ifdef USE_RMT_STEPS #undef USE_RMT_STEPS // Suppress unused variable warning #endif diff --git a/Grbl_Esp32/Machines/tmc2130_pen.h b/Grbl_Esp32/Machines/tmc2130_pen.h index 059abcdd..d2113b09 100644 --- a/Grbl_Esp32/Machines/tmc2130_pen.h +++ b/Grbl_Esp32/Machines/tmc2130_pen.h @@ -61,6 +61,8 @@ //#define USE_SPINDLE #ifdef USE_SERVO_AXES + #define SPINDLE_TYPE SPINDLE_TYPE_NONE + #define SERVO_Z_PIN GPIO_NUM_27 // comment this out if PWM spindle/laser control. #define SERVO_Z_RANGE_MIN 0.0 #define SERVO_Z_RANGE_MAX 5.0 @@ -68,7 +70,8 @@ #define SERVO_Z_HOME_POS SERVO_Z_RANGE_MAX // move to max during homing #define SERVO_Z_MPOS false // will not use mpos, uses work coordinates #else - #define SPINDLE_PWM_PIN GPIO_NUM_27 + #define SPINDLE_TYPE SPINDLE_TYPE_PWM + #define SPINDLE_PWM_PIN GPIO_NUM_27 #endif // #define X_LIMIT_PIN See version section at beginning of file From 84d185e6725920716d7f7075647d97d815f6bd3f Mon Sep 17 00:00:00 2001 From: bdring Date: Wed, 22 Apr 2020 16:01:05 -0500 Subject: [PATCH 27/32] Minor fixes Fixing typo Include machine type MSG with $I response. Stop using the laser mode flag. You don't need it if laser is select by class. --- Grbl_Esp32/Grbl_Esp32.ino | 2 +- Grbl_Esp32/report.cpp | 5 +++++ Grbl_Esp32/report.h | 2 ++ Grbl_Esp32/tools/Laser.cpp | 3 +-- Grbl_Esp32/tools/PWMSpindle.cpp | 2 +- 5 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Grbl_Esp32/Grbl_Esp32.ino b/Grbl_Esp32/Grbl_Esp32.ino index a3e38a72..5eaa59a1 100644 --- a/Grbl_Esp32/Grbl_Esp32.ino +++ b/Grbl_Esp32/Grbl_Esp32.ino @@ -56,7 +56,7 @@ void setup() { #else #define MACHINE_STRING MACHINE_NAME #endif - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Using machine:%s", MACHINE_STRING); + report_machine_type(CLIENT_SERIAL); #endif settings_init(); // Load Grbl settings from EEPROM stepper_init(); // Configure stepper pins and interrupt timers diff --git a/Grbl_Esp32/report.cpp b/Grbl_Esp32/report.cpp index fc9294a2..8fa196ad 100644 --- a/Grbl_Esp32/report.cpp +++ b/Grbl_Esp32/report.cpp @@ -549,6 +549,7 @@ void report_build_info(char* line, uint8_t client) { // These will likely have a comma delimiter to separate them. strcat(build_info, "]\r\n"); grbl_send(client, build_info); // ok to send to all + report_machine_type(client); #if defined (ENABLE_WIFI) grbl_send(client, (char*)wifi_config.info()); #endif @@ -775,6 +776,10 @@ void report_gcode_comment(char* comment) { } } +void report_machine_type(uint8_t client) { + grbl_msg_sendf(client, MSG_LEVEL_INFO, "Using machine:%s", MACHINE_NAME); +} + /* Print a message in hex format diff --git a/Grbl_Esp32/report.h b/Grbl_Esp32/report.h index 2f811013..81c9570b 100644 --- a/Grbl_Esp32/report.h +++ b/Grbl_Esp32/report.h @@ -170,6 +170,8 @@ void report_gcode_comment(char* comment); void report_realtime_debug(); #endif +void report_machine_type(uint8_t client); + void report_hex_msg(char* buf, const char *prefix, int len); char report_get_axis_letter(uint8_t axis); diff --git a/Grbl_Esp32/tools/Laser.cpp b/Grbl_Esp32/tools/Laser.cpp index 36c15211..12abf5b9 100644 --- a/Grbl_Esp32/tools/Laser.cpp +++ b/Grbl_Esp32/tools/Laser.cpp @@ -27,8 +27,7 @@ bool Laser :: isRateAdjusted() { - // must be in $32=1 (laser mode) - return (settings.flags & BITFLAG_LASER_MODE); + return true; // can use M4 (CCW) laser mode. } void Laser :: config_message() { diff --git a/Grbl_Esp32/tools/PWMSpindle.cpp b/Grbl_Esp32/tools/PWMSpindle.cpp index 341d0585..b1fc820b 100644 --- a/Grbl_Esp32/tools/PWMSpindle.cpp +++ b/Grbl_Esp32/tools/PWMSpindle.cpp @@ -107,7 +107,7 @@ float PWMSpindle::set_rpm(float rpm) { // apply override rpm *= (0.010 * sys.spindle_speed_ovr); // Scale by spindle speed override value (percent) - // apply limits limits + // apply limits if ((_min_rpm >= _max_rpm) || (rpm >= _max_rpm)) { rpm = _max_rpm; } else if (rpm != 0.0 && rpm <= _min_rpm) { From f27f29ba998cb6a099ea1b09fb55edeb6474e8ea Mon Sep 17 00:00:00 2001 From: Mitch Bradley Date: Wed, 22 Apr 2020 14:51:48 -1000 Subject: [PATCH 28/32] Removed add-on configurations The new Spindle Class is a much better solution to the problem that add-on's were intended to address. --- Grbl_Esp32/machine.h | 14 -------------- build-all.ps1 | 14 ++------------ build-all.py | 6 +----- build-all.sh | 18 ++---------------- build-machine.py | 10 ++++------ builder.py | 16 ++++++---------- 6 files changed, 15 insertions(+), 63 deletions(-) diff --git a/Grbl_Esp32/machine.h b/Grbl_Esp32/machine.h index d57814c4..1f99481c 100644 --- a/Grbl_Esp32/machine.h +++ b/Grbl_Esp32/machine.h @@ -14,12 +14,6 @@ // from Machines/, for example: // #include "Machines/3axis_v4.h" -// Some configurations use two files, the first establishing a base -// configuration and the second providing additional customization, -// for example: -// #include "Machines/3axis_v4.h" -// #include "Machines/add_esc_spindle.h" - // === OEM Single File Configuration Option // OEMs that wish to publish source code that is configured for a // specific machine may put all of their configuration definitions @@ -49,14 +43,6 @@ #include MACHINE_PATHNAME_QUOTED(MACHINE_FILENAME) -// You can choose two-file configurations by also defining MACHINE_FILENAME2, -// for example: -// $env:PLATFORMIO_BUILD_FLAGS='-DMACHINE_FILENAME=3axis_v4.h -DMACHINE_FILENAME2=add_esc_spindle.h'; platformio run - -#ifdef MACHINE_FILENAME2 -#include MACHINE_PATHNAME_QUOTED(MACHINE_FILENAME2) -#endif - #endif // MACHINE_FILENAME #endif // _machine_h diff --git a/build-all.ps1 b/build-all.ps1 index a3f80810..113513d2 100644 --- a/build-all.ps1 +++ b/build-all.ps1 @@ -7,26 +7,16 @@ $env:PYTHONIOENCODING="utf-8" Function BuildMachine($names) { $basename = $names[0] - $addname = $names[1] $env:PLATFORMIO_BUILD_FLAGS = "-DMACHINE_FILENAME=$basename" $displayname = $basename - if ($addname -ne "") { - $env:PLATFORMIO_BUILD_FLAGS += " -DMACHINE_FILENAME2=$addname" - $displayname += " + $addname" - } Write-Output "Building machine $displayname" platformio run 2>&1 | Select-String error,Took Write-Output " " } -# First build all the base configurations with names that do not start with add_ -foreach ($filepath in Get-ChildItem -file .\Grbl_Esp32\Machines\* -Exclude add_*) { +# Build all the machines +foreach ($filepath in Get-ChildItem -file .\Grbl_Esp32\Machines\*) { BuildMachine($filepath.name, "") } -# Then build all of the add-ons on top of a single base -$base="3axis_v4.h" -foreach ($filepath in Get-ChildItem -file .\Grbl_Esp32\Machines\add_*) { - BuildMachine($base, $filepath.name) -} Remove-Item env:PLATFORMIO_BUILD_FLAGS diff --git a/build-all.py b/build-all.py index 24c646df..45f53df8 100755 --- a/build-all.py +++ b/build-all.py @@ -22,12 +22,8 @@ cmd = ['platformio','run'] verbose = '-v' in sys.argv numErrors = 0 -adderBase = '3axis_v4.h' for name in os.listdir('Grbl_Esp32/Machines'): - if name.startswith('add_'): - exitCode = buildMachine(adderBase, addName=name, verbose=verbose) - else: - exitCode = buildMachine(name, verbose=verbose) + exitCode = buildMachine(name, verbose=verbose) if exitCode != 0: numErrors += 1 diff --git a/build-all.sh b/build-all.sh index 7da6ca0a..f0644acf 100755 --- a/build-all.sh +++ b/build-all.sh @@ -17,14 +17,8 @@ NUM_ERRORS=0 BuildMachine () { basename=$1 - addname=$2 BF="\"-DMACHINE_FILENAME=$basename\"" displayname=$basename - if [ "$addname" != "" ] - then - BF="$BF \"-DMACHINE_FILENAME2=$addname\"" - displayname="$basename + $addname" - fi echo "Building machine $displayname" PLATFORMIO_BUILD_FLAGS=$BF platformio run 2>&1 | $FILTER local re=$? @@ -38,18 +32,10 @@ BuildMachine () { echo } -# First build all the base configurations with names that do not start with add_ -for file in `ls ./Grbl_Esp32/Machines/* | grep -v add_\*`; do +# Build all the machines +for file in `ls ./Grbl_Esp32/Machines/*`; do base=`basename $file` BuildMachine $base "" done -# Then build all of the add-ons on top of a single base -base="3axis_v4.h" -for file in `ls ./Grbl_Esp32/Machines/add_*` -do - adder=`basename $file` - BuildMachine $base $adder -done - exit $NUM_ERRORS diff --git a/build-machine.py b/build-machine.py index aa821e39..29f75597 100755 --- a/build-machine.py +++ b/build-machine.py @@ -26,13 +26,11 @@ if '-u' in sys.argv: exitCode = 255 if len(sys.argv) == 2: - exitCode = buildMachine(sys.argv[1], addName=None, verbose=verbose, extraArgs=extraArgs) -elif len(sys.argv) == 3: - exitCode = buildMachine(sys.argv[1], addName=sys.argv[2], verbose=verbose, extraArgs=extraArgs) + exitCode = buildMachine(sys.argv[1], verbose=verbose, extraArgs=extraArgs) else: - print("Usage: ./build-machine.py [-q] [-u] machine_name.h [add_name.h]") - print(' Build for the given machine and optional add-on regardless of machine.h') + print("Usage: ./build-machine.py [-q] [-u] machine_name.h") + print(' Build for the given machine regardless of machine.h') print(' -q suppresses most messages') print(' -u uploads to the target after compilation') -sys.exit(exitCode) \ No newline at end of file +sys.exit(exitCode) diff --git a/builder.py b/builder.py index ba3bdb6a..68f9d095 100755 --- a/builder.py +++ b/builder.py @@ -1,24 +1,20 @@ # This script is imported by build-machine.py and build-all.py -# It performs a platformio build with a given base machine file -# and an optional add-on file. The verbose argument controls -# whether the full output is displayed, or filtered to show -# only summary information. extraArgs can be used to perform -# uploading after compilation. +# It performs a platformio build with a given machine file. +# The verbose argument controls whether the full output is +# displayed, or filtered to show only summary information. +# extraArgs can be used to perform uploading after compilation. from __future__ import print_function import subprocess, os env = dict(os.environ) -def buildMachine(baseName, addName=None, verbose=True, extraArgs=None): +def buildMachine(baseName, verbose=True, extraArgs=None): cmd = ['platformio','run'] if extraArgs: cmd.append(extraArgs) displayName = baseName flags = '-DMACHINE_FILENAME=' + baseName - if addName: - displayName += ' + ' + addName - flags += ' -DMACHINE_FILENAME2=' + addName print('Building machine ' + displayName) env['PLATFORMIO_BUILD_FLAGS'] = flags if verbose: @@ -30,4 +26,4 @@ def buildMachine(baseName, addName=None, verbose=True, extraArgs=None): print(line, end='') app.wait() print() - return app.returncode \ No newline at end of file + return app.returncode From 2d21b6161d99a679a5ce0a8ef43559b5eb7d482e Mon Sep 17 00:00:00 2001 From: bdring Date: Thu, 23 Apr 2020 09:30:38 -0500 Subject: [PATCH 29/32] Update GRBL_VERSION_BUILD --- Grbl_Esp32/grbl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Grbl_Esp32/grbl.h b/Grbl_Esp32/grbl.h index 4f150261..3d85c632 100644 --- a/Grbl_Esp32/grbl.h +++ b/Grbl_Esp32/grbl.h @@ -21,7 +21,7 @@ // Grbl versioning system #define GRBL_VERSION "1.2a" -#define GRBL_VERSION_BUILD "20200420" +#define GRBL_VERSION_BUILD "20200423" //#include #include From f1baa6baa83e8f6e3e4ef2630281d6bc95eca766 Mon Sep 17 00:00:00 2001 From: bdring Date: Thu, 23 Apr 2020 10:17:22 -0500 Subject: [PATCH 30/32] Fixing pin name issue Somehow the rename of SPINDLE_PWM_PIN to SPINDLE_OUTPUT_PIN got lost in the merge. I think the confict resolution step was not done right. Removed template.h and spindle_test.h --- Grbl_Esp32/Machines/3axis_v3.h | 2 +- Grbl_Esp32/Machines/3axis_v4.h | 4 +- Grbl_Esp32/Machines/3axis_xyx.h | 2 +- Grbl_Esp32/Machines/4axis_external_driver.h | 2 +- Grbl_Esp32/Machines/custom_machine_template.h | 1 - Grbl_Esp32/Machines/espduino.h | 2 +- Grbl_Esp32/Machines/mpcnc_v1p1.h | 4 +- Grbl_Esp32/Machines/mpcnc_v1p2.h | 4 +- Grbl_Esp32/Machines/spi_daisy_4axis_xyyz.h | 2 +- Grbl_Esp32/Machines/spi_daisy_4axis_xyz.h | 2 +- Grbl_Esp32/Machines/spindle_test.h | 39 ------------------- Grbl_Esp32/Machines/tmc2130_pen.h | 2 +- Grbl_Esp32/machine.h | 2 +- 13 files changed, 13 insertions(+), 55 deletions(-) delete mode 100644 Grbl_Esp32/Machines/custom_machine_template.h delete mode 100644 Grbl_Esp32/Machines/spindle_test.h diff --git a/Grbl_Esp32/Machines/3axis_v3.h b/Grbl_Esp32/Machines/3axis_v3.h index 73b9af9d..0bfa1429 100644 --- a/Grbl_Esp32/Machines/3axis_v3.h +++ b/Grbl_Esp32/Machines/3axis_v3.h @@ -41,7 +41,7 @@ #define STEPPERS_DISABLE_PIN GPIO_NUM_13 #define SPINDLE_TYPE SPINDLE_TYPE_PWM -#define SPINDLE_PWM_PIN GPIO_NUM_17 // labeled SpinPWM +#define SPINDLE_OUTPUT_PIN GPIO_NUM_17 // labeled SpinPWM #define SPINDLE_ENABLE_PIN GPIO_NUM_22 // labeled SpinEnbl diff --git a/Grbl_Esp32/Machines/3axis_v4.h b/Grbl_Esp32/Machines/3axis_v4.h index f14e4712..bc5ff681 100644 --- a/Grbl_Esp32/Machines/3axis_v4.h +++ b/Grbl_Esp32/Machines/3axis_v4.h @@ -41,7 +41,7 @@ #define STEPPERS_DISABLE_PIN GPIO_NUM_13 #define SPINDLE_TYPE SPINDLE_TYPE_PWM -#define SPINDLE_PWM_PIN GPIO_NUM_2 // labeled SpinPWM +#define SPINDLE_OUTPUT_PIN GPIO_NUM_2 // labeled SpinPWM #define SPINDLE_ENABLE_PIN GPIO_NUM_22 // labeled SpinEnbl #define MIST_PIN GPIO_NUM_21 // labeled Mist @@ -52,5 +52,3 @@ #define CONTROL_RESET_PIN GPIO_NUM_34 // labeled Reset, needs external pullup #define CONTROL_FEED_HOLD_PIN GPIO_NUM_36 // labeled Hold, needs external pullup #define CONTROL_CYCLE_START_PIN GPIO_NUM_39 // labeled Start, needs external pullup - -#define SPINDLE_TYPE SPINDLE_TYPE_BESC diff --git a/Grbl_Esp32/Machines/3axis_xyx.h b/Grbl_Esp32/Machines/3axis_xyx.h index 55c14b16..288414cc 100644 --- a/Grbl_Esp32/Machines/3axis_xyx.h +++ b/Grbl_Esp32/Machines/3axis_xyx.h @@ -33,7 +33,7 @@ #define Y2_DIRECTION_PIN GPIO_NUM_33 /* labeled Z */ #define SPINDLE_TYPE SPINDLE_TYPE_PWM -#define SPINDLE_PWM_PIN GPIO_NUM_2 +#define SPINDLE_OUTPUT_PIN GPIO_NUM_2 #define SPINDLE_ENABLE_PIN GPIO_NUM_22 #define LIMIT_MASK B11 diff --git a/Grbl_Esp32/Machines/4axis_external_driver.h b/Grbl_Esp32/Machines/4axis_external_driver.h index 42458d8c..ecb4e409 100644 --- a/Grbl_Esp32/Machines/4axis_external_driver.h +++ b/Grbl_Esp32/Machines/4axis_external_driver.h @@ -41,7 +41,7 @@ /* #define SPINDLE_TYPE SPINDLE_TYPE_PWM -#define SPINDLE_PWM_PIN GPIO_NUM_25 +#define SPINDLE_OUTPUT_PIN GPIO_NUM_25 #define SPINDLE_ENABLE_PIN GPIO_NUM_22 */ diff --git a/Grbl_Esp32/Machines/custom_machine_template.h b/Grbl_Esp32/Machines/custom_machine_template.h deleted file mode 100644 index 7a594cc4..00000000 --- a/Grbl_Esp32/Machines/custom_machine_template.h +++ /dev/null @@ -1 +0,0 @@ -// See template.h diff --git a/Grbl_Esp32/Machines/espduino.h b/Grbl_Esp32/Machines/espduino.h index a58fbc80..28571e13 100644 --- a/Grbl_Esp32/Machines/espduino.h +++ b/Grbl_Esp32/Machines/espduino.h @@ -40,7 +40,7 @@ #define STEPPERS_DISABLE_PIN GPIO_NUM_12 #define SPINDLE_TYPE SPINDLE_TYPE_PWM -#define SPINDLE_PWM_PIN GPIO_NUM_19 +#define SPINDLE_OUTPUT_PIN GPIO_NUM_19 #define SPINDLE_DIR_PIN GPIO_NUM_18 diff --git a/Grbl_Esp32/Machines/mpcnc_v1p1.h b/Grbl_Esp32/Machines/mpcnc_v1p1.h index 288469fe..5e656a5d 100644 --- a/Grbl_Esp32/Machines/mpcnc_v1p1.h +++ b/Grbl_Esp32/Machines/mpcnc_v1p1.h @@ -51,10 +51,10 @@ #ifdef USE_SPINDLE_RELAY #define SPINDLE_TYPE SPINDLE_TYPE_RELAY - #define SPINDLE_PWM_PIN GPIO_NUM_17 + #define SPINDLE_OUTPUT_PIN GPIO_NUM_17 #else #define SPINDLE_TYPE SPINDLE_TYPE_PWM - #define SPINDLE_PWM_PIN GPIO_NUM_16 + #define SPINDLE_OUTPUT_PIN GPIO_NUM_16 #define SPINDLE_ENABLE_PIN GPIO_NUM_32 #endif diff --git a/Grbl_Esp32/Machines/mpcnc_v1p2.h b/Grbl_Esp32/Machines/mpcnc_v1p2.h index aa1ef105..b139d623 100644 --- a/Grbl_Esp32/Machines/mpcnc_v1p2.h +++ b/Grbl_Esp32/Machines/mpcnc_v1p2.h @@ -52,10 +52,10 @@ #ifdef USE_SPINDLE_RELAY #define SPINDLE_TYPE SPINDLE_TYPE_RELAY - #define SPINDLE_PWM_PIN GPIO_NUM_2 + #define SPINDLE_OUTPUT_PIN GPIO_NUM_2 #else #define SPINDLE_TYPE SPINDLE_TYPE_PWM - #define SPINDLE_PWM_PIN GPIO_NUM_16 + #define SPINDLE_OUTPUT_PIN GPIO_NUM_16 #define SPINDLE_ENABLE_PIN GPIO_NUM_32 #endif diff --git a/Grbl_Esp32/Machines/spi_daisy_4axis_xyyz.h b/Grbl_Esp32/Machines/spi_daisy_4axis_xyyz.h index 1b3233f4..5aa018c6 100644 --- a/Grbl_Esp32/Machines/spi_daisy_4axis_xyyz.h +++ b/Grbl_Esp32/Machines/spi_daisy_4axis_xyyz.h @@ -79,7 +79,7 @@ #define COOLANT_MIST_PIN GPIO_NUM_21 #define SPINDLE_TYPE SPINDLE_TYPE_PWM -#define SPINDLE_PWM_PIN GPIO_NUM_25 +#define SPINDLE_OUTPUT_PIN GPIO_NUM_25 #define SPINDLE_ENABLE_PIN GPIO_NUM_4 // Relay operation diff --git a/Grbl_Esp32/Machines/spi_daisy_4axis_xyz.h b/Grbl_Esp32/Machines/spi_daisy_4axis_xyz.h index 5a2021db..02732a2b 100644 --- a/Grbl_Esp32/Machines/spi_daisy_4axis_xyz.h +++ b/Grbl_Esp32/Machines/spi_daisy_4axis_xyz.h @@ -64,7 +64,7 @@ #define COOLANT_MIST_PIN GPIO_NUM_21 #define SPINDLE_TYPE SPINDLE_TYPE_PWM -#define SPINDLE_PWM_PIN GPIO_NUM_25 +#define SPINDLE_OUTPUT_PIN GPIO_NUM_25 #define SPINDLE_ENABLE_PIN GPIO_NUM_4 // Relay operation diff --git a/Grbl_Esp32/Machines/spindle_test.h b/Grbl_Esp32/Machines/spindle_test.h deleted file mode 100644 index c85f1682..00000000 --- a/Grbl_Esp32/Machines/spindle_test.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - spindle_test.h - Part of Grbl_ESP32 - - Pin assignments (or lack thereof) for testing Grbl_ESP32. - - This is just a minimal machine definition to test Spindle Classes - - 2018 - Bart Dring - 2020 - Mitch Bradley - - Grbl_ESP32 is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Grbl is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grbl_ESP32. If not, see . -*/ - -#define MACHINE_NAME "Spindle Class Testing" - - -#define SPINDLE_TYPE SPINDLE_TYPE_PWM -//#define SPINDLE_TYPE SPINDLE_TYPE_BESC - -#define SPINDLE_OUTPUT_PIN GPIO_NUM_27 - - -#define LIMIT_MASK 0 // no limit pins - -#ifdef USE_RMT_STEPS -#undef USE_RMT_STEPS // Suppress unused variable warning -#endif diff --git a/Grbl_Esp32/Machines/tmc2130_pen.h b/Grbl_Esp32/Machines/tmc2130_pen.h index 3b5e586f..59536f7e 100644 --- a/Grbl_Esp32/Machines/tmc2130_pen.h +++ b/Grbl_Esp32/Machines/tmc2130_pen.h @@ -72,7 +72,7 @@ #else #define SPINDLE_TYPE SPINDLE_TYPE_PWM - #define SPINDLE_PWM_PIN GPIO_NUM_27 + #define SPINDLE_OUTPUT_PIN GPIO_NUM_27 #endif // #define X_LIMIT_PIN See version section at beginning of file diff --git a/Grbl_Esp32/machine.h b/Grbl_Esp32/machine.h index d57814c4..1d49672e 100644 --- a/Grbl_Esp32/machine.h +++ b/Grbl_Esp32/machine.h @@ -8,7 +8,7 @@ // !!! For initial testing, start with test_drive.h which disables // all I/O pins -#include "Machines/test_drive.h" +#include "Machines/3axis_v4.h" // !!! For actual use, change the line above to select a board // from Machines/, for example: From 04fb0b0921f74fd2df91726dfd29a6afd221e431 Mon Sep 17 00:00:00 2001 From: bdring Date: Thu, 23 Apr 2020 17:19:17 -0500 Subject: [PATCH 31/32] Return to default machine and Was setup for test machine and fast compile --- Grbl_Esp32/config.h | 4 ++-- Grbl_Esp32/machine.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Grbl_Esp32/config.h b/Grbl_Esp32/config.h index 11443779..d7fec101 100644 --- a/Grbl_Esp32/config.h +++ b/Grbl_Esp32/config.h @@ -115,11 +115,11 @@ Some features should not be changed. See notes below. //#define CONNECT_TO_SSID "your SSID" //#define SSID_PASSWORD "your SSID password" //CONFIGURE_EYECATCH_BEGIN (DO NOT MODIFY THIS LINE) -//#define ENABLE_BLUETOOTH // enable bluetooth +#define ENABLE_BLUETOOTH // enable bluetooth #define ENABLE_SD_CARD // enable use of SD Card to run jobs -//#define ENABLE_WIFI //enable wifi +#define ENABLE_WIFI //enable wifi #define ENABLE_HTTP //enable HTTP and all related services #define ENABLE_OTA //enable OTA diff --git a/Grbl_Esp32/machine.h b/Grbl_Esp32/machine.h index a9291233..1f99481c 100644 --- a/Grbl_Esp32/machine.h +++ b/Grbl_Esp32/machine.h @@ -8,7 +8,7 @@ // !!! For initial testing, start with test_drive.h which disables // all I/O pins -#include "Machines/3axis_v4.h" +#include "Machines/test_drive.h" // !!! For actual use, change the line above to select a board // from Machines/, for example: From c0c27a3fbd5e600dc6894cb9e5f35e19999c1240 Mon Sep 17 00:00:00 2001 From: bdring Date: Mon, 27 Apr 2020 09:00:04 -0500 Subject: [PATCH 32/32] Removed #define IGNORE_CONTROL_PINS It was added before the test mode machine definition was created. People were loading other machine definitions to test drive without attached hardware. The floating, input only pins were typically used for control pins and creating a bad first experience. --- Grbl_Esp32/Machines/atari_1020.h | 4 ---- Grbl_Esp32/Machines/espduino.h | 1 - Grbl_Esp32/Machines/lowrider_v1p2.h | 1 - Grbl_Esp32/Machines/midtbot.h | 4 ---- Grbl_Esp32/Machines/mpcnc_v1p1.h | 9 --------- Grbl_Esp32/Machines/mpcnc_v1p2.h | 8 -------- Grbl_Esp32/Machines/polar_coaster.h | 4 ---- Grbl_Esp32/Machines/template.h | 5 ----- Grbl_Esp32/config.h | 5 ----- Grbl_Esp32/system.cpp | 8 +++----- 10 files changed, 3 insertions(+), 46 deletions(-) diff --git a/Grbl_Esp32/Machines/atari_1020.h b/Grbl_Esp32/Machines/atari_1020.h index faaf8c6c..5e4139eb 100644 --- a/Grbl_Esp32/Machines/atari_1020.h +++ b/Grbl_Esp32/Machines/atari_1020.h @@ -67,10 +67,6 @@ #define REED_SW_PIN GPIO_NUM_17 #define LIMIT_MASK 0 -#ifdef IGNORE_CONTROL_PINS // maybe set in config.h - #undef IGNORE_CONTROL_PINS -#endif - #ifndef ENABLE_CONTROL_SW_DEBOUNCE #define ENABLE_CONTROL_SW_DEBOUNCE #endif diff --git a/Grbl_Esp32/Machines/espduino.h b/Grbl_Esp32/Machines/espduino.h index 28571e13..2023ccfb 100644 --- a/Grbl_Esp32/Machines/espduino.h +++ b/Grbl_Esp32/Machines/espduino.h @@ -54,7 +54,6 @@ #define PROBE_PIN GPIO_NUM_39 -// comment out #define IGNORE_CONTROL_PINS in config.h to use control pins #define CONTROL_RESET_PIN GPIO_NUM_2 #define CONTROL_FEED_HOLD_PIN GPIO_NUM_4 #define CONTROL_CYCLE_START_PIN GPIO_NUM_35 // ESP32 needs external pullup diff --git a/Grbl_Esp32/Machines/lowrider_v1p2.h b/Grbl_Esp32/Machines/lowrider_v1p2.h index def0aeac..f742cd1f 100644 --- a/Grbl_Esp32/Machines/lowrider_v1p2.h +++ b/Grbl_Esp32/Machines/lowrider_v1p2.h @@ -80,7 +80,6 @@ #define INVERT_CONTROL_PIN_MASK B1110 -// Note: check the #define IGNORE_CONTROL_PINS is the way you want in config.h #define CONTROL_RESET_PIN GPIO_NUM_34 // needs external pullup #define CONTROL_FEED_HOLD_PIN GPIO_NUM_36 // needs external pullup #define CONTROL_CYCLE_START_PIN GPIO_NUM_39 // needs external pullup diff --git a/Grbl_Esp32/Machines/midtbot.h b/Grbl_Esp32/Machines/midtbot.h index f10c11d9..c7249897 100644 --- a/Grbl_Esp32/Machines/midtbot.h +++ b/Grbl_Esp32/Machines/midtbot.h @@ -51,10 +51,6 @@ #define SERVO_Z_HOME_POS SERVO_Z_RANGE_MAX // move to max during homing #define SERVO_Z_MPOS false // will not use mpos, uses work coordinates -#ifndef IGNORE_CONTROL_PINS // maybe set in config.h - #define IGNORE_CONTROL_PINS -#endif - // redefine some stuff from config.h #ifdef HOMING_CYCLE_0 #undef HOMING_CYCLE_0 diff --git a/Grbl_Esp32/Machines/mpcnc_v1p1.h b/Grbl_Esp32/Machines/mpcnc_v1p1.h index 5e656a5d..37eb3bf6 100644 --- a/Grbl_Esp32/Machines/mpcnc_v1p1.h +++ b/Grbl_Esp32/Machines/mpcnc_v1p1.h @@ -79,15 +79,6 @@ #define INVERT_CONTROL_PIN_MASK B1110 -// Note: default is #define IGNORE_CONTROL_PINS in config.h -// uncomment to these lines to use them - -/* -#ifdef IGNORE_CONTROL_PINS -#undef IGNORE_CONTROL_PINS -#endif -*/ - #define CONTROL_RESET_PIN GPIO_NUM_34 // needs external pullup #define CONTROL_FEED_HOLD_PIN GPIO_NUM_36 // needs external pullup #define CONTROL_CYCLE_START_PIN GPIO_NUM_39 // needs external pullup diff --git a/Grbl_Esp32/Machines/mpcnc_v1p2.h b/Grbl_Esp32/Machines/mpcnc_v1p2.h index b139d623..03212499 100644 --- a/Grbl_Esp32/Machines/mpcnc_v1p2.h +++ b/Grbl_Esp32/Machines/mpcnc_v1p2.h @@ -86,14 +86,6 @@ #define INVERT_CONTROL_PIN_MASK B1110 -// Note: default is #define IGNORE_CONTROL_PINS in config.h -// uncomment to these lines to use them - -/* -#ifdef IGNORE_CONTROL_PINS -#undef IGNORE_CONTROL_PINS -#endif -*/ #define CONTROL_RESET_PIN GPIO_NUM_34 // needs external pullup #define CONTROL_FEED_HOLD_PIN GPIO_NUM_36 // needs external pullup diff --git a/Grbl_Esp32/Machines/polar_coaster.h b/Grbl_Esp32/Machines/polar_coaster.h index 0ae39c84..125fbcf4 100644 --- a/Grbl_Esp32/Machines/polar_coaster.h +++ b/Grbl_Esp32/Machines/polar_coaster.h @@ -59,10 +59,6 @@ #define SPINDLE_TYPE SPINDLE_TYPE_NONE -#ifdef IGNORE_CONTROL_PINS // maybe set in config.h - #undef IGNORE_CONTROL_PINS -#endif - #ifndef ENABLE_CONTROL_SW_DEBOUNCE #define ENABLE_CONTROL_SW_DEBOUNCE #endif diff --git a/Grbl_Esp32/Machines/template.h b/Grbl_Esp32/Machines/template.h index 2aa7ca26..9c4272c6 100644 --- a/Grbl_Esp32/Machines/template.h +++ b/Grbl_Esp32/Machines/template.h @@ -175,11 +175,6 @@ // === Control Pins -// The control pins with names that begin with CONTROL_ are -// ignored by default, to avoid noise problems. To make them -// work, you must undefine IGNORE_CONTROL_PINS -// #undef IGNORE_CONTROL_PINS - // If some of the control pin switches are normally closed // (the default is normally open), you can invert some of them // with INVERT_CONTROL_PIN_MASK. The bits in the mask are diff --git a/Grbl_Esp32/config.h b/Grbl_Esp32/config.h index d7fec101..79fc7dfc 100644 --- a/Grbl_Esp32/config.h +++ b/Grbl_Esp32/config.h @@ -76,11 +76,6 @@ Some features should not be changed. See notes below. // For example B1101 will invert the function of the Reset pin. #define INVERT_CONTROL_PIN_MASK B1111 -// This allows control pins to be ignored. -// Since these are typically used on the pins that don't have pullups, they will float and cause -// problems if not externally pulled up. Ignoring will always return not activated when read. -#define IGNORE_CONTROL_PINS - #define ENABLE_CONTROL_SW_DEBOUNCE // Default disabled. Uncomment to enable. #define CONTROL_SW_DEBOUNCE_PERIOD 32 // in milliseconds default 32 microseconds diff --git a/Grbl_Esp32/system.cpp b/Grbl_Esp32/system.cpp index c3c94e73..2da179ce 100644 --- a/Grbl_Esp32/system.cpp +++ b/Grbl_Esp32/system.cpp @@ -26,7 +26,7 @@ bool debouncing = false; // debouncing in process void system_ini() { // Renamed from system_init() due to conflict with esp32 files // setup control inputs -#ifndef IGNORE_CONTROL_PINS + #ifdef CONTROL_SAFETY_DOOR_PIN pinMode(CONTROL_SAFETY_DOOR_PIN, INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(CONTROL_SAFETY_DOOR_PIN), isr_control_inputs, CHANGE); @@ -73,7 +73,7 @@ void system_ini() { // Renamed from system_init() due to conflict with esp32 fil 5, // priority NULL); #endif -#endif + //customize pin definition if needed #if (GRBL_SPI_SS != -1) || (GRBL_SPI_MISO != -1) || (GRBL_SPI_MOSI != -1) || (GRBL_SPI_SCK != -1) SPI.begin(GRBL_SPI_SCK, GRBL_SPI_MISO, GRBL_SPI_MOSI, GRBL_SPI_SS); @@ -453,10 +453,8 @@ uint8_t system_check_travel_limits(float* target) { // defined by the CONTROL_PIN_INDEX in the header file. uint8_t system_control_get_state() { uint8_t defined_pin_mask = 0; // a mask of defined pins -#ifdef IGNORE_CONTROL_PINS - return 0; -#endif uint8_t control_state = 0; + #ifdef CONTROL_SAFETY_DOOR_PIN defined_pin_mask |= CONTROL_PIN_INDEX_SAFETY_DOOR; if (digitalRead(CONTROL_SAFETY_DOOR_PIN)) control_state |= CONTROL_PIN_INDEX_SAFETY_DOOR;