From 9a7d05f29b731a7de609fd0e0adfdf67fa5f2238 Mon Sep 17 00:00:00 2001 From: bdring Date: Fri, 3 Apr 2020 12:40:54 -0500 Subject: [PATCH 01/31] 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/31] 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/31] 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/31] 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/31] 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/31] 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/31] 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/31] 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/31] 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/31] 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/31] 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/31] 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/31] 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/31] 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/31] 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/31] 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/31] 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/31] 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/31] 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/31] 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/31] 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/31] 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/31] 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/31] 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/31] 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/31] 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/31] 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/31] 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/31] 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/31] 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/31] 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: