diff --git a/Grbl_Esp32/src/GCode.cpp b/Grbl_Esp32/src/GCode.cpp index 63eef347..bc2950b6 100644 --- a/Grbl_Esp32/src/GCode.cpp +++ b/Grbl_Esp32/src/GCode.cpp @@ -475,7 +475,7 @@ Error gc_execute_line(char* line, uint8_t client) { gc_block.modal.spindle = SpindleState::Cw; break; case 4: // Supported if SPINDLE_DIR_PIN is defined or laser mode is on. - if (spindle->is_reversable || laser_mode->get()) { + if (spindle->is_reversable || MachineConfig::instance()->_laserMode) { gc_block.modal.spindle = SpindleState::Ccw; } else { FAIL(Error::GcodeUnsupportedCommand); @@ -1292,7 +1292,7 @@ Error gc_execute_line(char* line, uint8_t client) { return status; } // If in laser mode, setup laser power based on current and past parser conditions. - if (laser_mode->get()) { + if (MachineConfig::instance()->_laserMode) { if (!((gc_block.modal.motion == Motion::Linear) || (gc_block.modal.motion == Motion::CwArc) || (gc_block.modal.motion == Motion::CcwArc))) { gc_parser_flags |= GCParserLaserDisable; diff --git a/Grbl_Esp32/src/MachineConfig.cpp b/Grbl_Esp32/src/MachineConfig.cpp index 8b43478c..baf233c0 100644 --- a/Grbl_Esp32/src/MachineConfig.cpp +++ b/Grbl_Esp32/src/MachineConfig.cpp @@ -296,7 +296,7 @@ Axes::~Axes() { } } -void I2SO::validate() const { +void I2SOBus::validate() const { if (!_bck.undefined() || !_data.undefined() || !_ws.undefined()) { Assert(!_bck.undefined(), "I2SO BCK pin should be configured once."); Assert(!_data.undefined(), "I2SO Data pin should be configured once."); @@ -304,19 +304,37 @@ void I2SO::validate() const { } } -void I2SO::handle(Configuration::HandlerBase& handler) { +void I2SOBus::handle(Configuration::HandlerBase& handler) { handler.handle("bck", _bck); handler.handle("data", _data); handler.handle("ws", _ws); } +void SPIBus::validate() const { + if (!_ss.undefined() || !_miso.undefined() || !_mosi.undefined() || !_sck.undefined()) { + Assert(!_ss.undefined(), "SPI SS pin should be configured once."); + Assert(!_miso.undefined(), "SPI MISO pin should be configured once."); + Assert(!_mosi.undefined(), "SPI MOSI pin should be configured once."); + Assert(!_sck.undefined(), "SPI SCK pin should be configured once."); + } +} + +void SPIBus::handle(Configuration::HandlerBase& handler) { + handler.handle("ss", _ss); + handler.handle("miso", _miso); + handler.handle("mosi", _mosi); + handler.handle("mosi", _sck); +} + void MachineConfig::validate() const {} void MachineConfig::handle(Configuration::HandlerBase& handler) { handler.handle("axes", _axes); handler.handle("i2so", _i2so); + handler.handle("spi", _spi); handler.handle("coolant", _coolant); handler.handle("probe", _probe); + handler.handle("laser_mode", _laserMode); } bool MachineConfig::load(const char* filename) { diff --git a/Grbl_Esp32/src/MachineConfig.h b/Grbl_Esp32/src/MachineConfig.h index 9c854de0..7f5c5496 100644 --- a/Grbl_Esp32/src/MachineConfig.h +++ b/Grbl_Esp32/src/MachineConfig.h @@ -98,7 +98,7 @@ class Axes : public Configuration::Configurable { public: Axes(); - int _numberAxis = 3; + int _numberAxis = 3; Axis* _axis[MAX_NUMBER_AXIS]; // Some small helpers to find the axis index and axis ganged index for a given motor. This @@ -123,9 +123,9 @@ public: ~Axes(); }; -class I2SO : public Configuration::Configurable { +class I2SOBus : public Configuration::Configurable { public: - I2SO() = default; + I2SOBus() = default; Pin _bck; Pin _data; @@ -134,16 +134,33 @@ public: void validate() const override; void handle(Configuration::HandlerBase& handler) override; - ~I2SO() {} + ~I2SOBus() = default; +}; + +class SPIBus : public Configuration::Configurable { +public: + SPIBus() = default; + + Pin _ss; + Pin _miso; + Pin _mosi; + Pin _sck; + + void validate() const override; + void handle(Configuration::HandlerBase& handler) override; + + ~SPIBus() = default; }; class MachineConfig : public Configuration::Configurable { public: - MachineConfig() = default; - Axes* _axes = nullptr; - I2SO* _i2so = nullptr; - CoolantControl* _coolant = nullptr; - Probe* _probe = nullptr; + MachineConfig() = default; + Axes* _axes = nullptr; + SPIBus* _spi = nullptr; + I2SOBus* _i2so = nullptr; + CoolantControl* _coolant = nullptr; + Probe* _probe = nullptr; + bool _laserMode = false; static MachineConfig*& instance() { static MachineConfig* instance = nullptr; diff --git a/Grbl_Esp32/src/Motors/Dynamixel2.cpp b/Grbl_Esp32/src/Motors/Dynamixel2.cpp index d9d6672f..3f5c5aa5 100644 --- a/Grbl_Esp32/src/Motors/Dynamixel2.cpp +++ b/Grbl_Esp32/src/Motors/Dynamixel2.cpp @@ -197,8 +197,10 @@ namespace Motors { if (_has_errors) { return false; } + + auto axis = MachineConfig::instance()->_axes->_axis[_axis_index]; sys_position[_axis_index] = - axis_settings[_axis_index]->home_mpos->get() * axis_settings[_axis_index]->steps_per_mm->get(); // convert to steps + axis->_homing->_mpos * axis->_stepsPerMm; // convert to steps set_disable(false); set_location(); // force the PWM to update now @@ -229,8 +231,10 @@ namespace Motors { read_settings(); - int32_t pos_min_steps = lround(limitsMinPosition(_axis_index) * axis_settings[_axis_index]->steps_per_mm->get()); - int32_t pos_max_steps = lround(limitsMaxPosition(_axis_index) * axis_settings[_axis_index]->steps_per_mm->get()); + auto axis = MachineConfig::instance()->_axes->_axis[_axis_index]; + + int32_t pos_min_steps = lround(limitsMinPosition(_axis_index) * axis->_stepsPerMm); + int32_t pos_max_steps = lround(limitsMaxPosition(_axis_index) * axis->_stepsPerMm); int32_t temp = map(dxl_position, DXL_COUNT_MIN, DXL_COUNT_MAX, pos_min_steps, pos_max_steps); diff --git a/Grbl_Esp32/src/Motors/RcServo.cpp b/Grbl_Esp32/src/Motors/RcServo.cpp index 40ace5a5..34cb6e04 100644 --- a/Grbl_Esp32/src/Motors/RcServo.cpp +++ b/Grbl_Esp32/src/Motors/RcServo.cpp @@ -29,6 +29,7 @@ */ #include "RcServo.h" +#include "../MachineConfig.h" namespace Motors { // RcServo::RcServo(Pin pwm_pin) : Servo(), _pwm_pin(pwm_pin) {} @@ -36,15 +37,6 @@ namespace Motors { void RcServo::init() { _axis_index = axis_index(); - // TODO FIXME: This is leaking if init() is called multiple times. - char* setting_cal_min = (char*)malloc(20); - snprintf(setting_cal_min, 20, "%c/RcServo/Cal/Min", report_get_axis_letter(_axis_index)); - rc_servo_cal_min = new FloatSetting(EXTENDED, WG, NULL, setting_cal_min, 1.0, 0.5, 2.0); - - char* setting_cal_max = (char*)malloc(20); - snprintf(setting_cal_max, 20, "%c/RcServo/Cal/Max", report_get_axis_letter(_axis_index)); - rc_servo_cal_max = new FloatSetting(EXTENDED, WG, NULL, setting_cal_max, 1.0, 0.5, 2.0); - auto pwmNative = _pwm_pin.getNative(Pin::Capabilities::PWM); read_settings(); @@ -92,8 +84,8 @@ namespace Motors { // Homing justs sets the new system position and the servo will move there bool RcServo::set_homing_mode(bool isHoming) { - sys_position[_axis_index] = - axis_settings[_axis_index]->home_mpos->get() * axis_settings[_axis_index]->steps_per_mm->get(); // convert to steps + auto axis = MachineConfig::instance()->_axes->_axis[_axis_index]; + sys_position[_axis_index] = axis->_homing->_mpos * axis->_stepsPerMm; // convert to steps set_location(); // force the PWM to update now vTaskDelay(750); // give time to move @@ -130,8 +122,8 @@ namespace Motors { } void RcServo::read_settings() { - _pwm_pulse_min = SERVO_MIN_PULSE * rc_servo_cal_min->get(); - _pwm_pulse_max = SERVO_MAX_PULSE * rc_servo_cal_max->get(); + _pwm_pulse_min = SERVO_MIN_PULSE * _cal_min; + _pwm_pulse_max = SERVO_MAX_PULSE * _cal_max; if (bitnum_istrue(dir_invert_mask->get(), _axis_index)) { // normal direction swap(_pwm_pulse_min, _pwm_pulse_max); @@ -139,8 +131,7 @@ namespace Motors { } // Configuration registration - namespace - { + namespace { MotorFactory::InstanceBuilder registration("rc_servo"); } } diff --git a/Grbl_Esp32/src/Motors/RcServo.h b/Grbl_Esp32/src/Motors/RcServo.h index 45767240..aaa7021f 100644 --- a/Grbl_Esp32/src/Motors/RcServo.h +++ b/Grbl_Esp32/src/Motors/RcServo.h @@ -42,8 +42,8 @@ namespace Motors { bool _disabled; - FloatSetting* rc_servo_cal_min; - FloatSetting* rc_servo_cal_max; + float _cal_min; + float _cal_max; int _axis_index = -1; @@ -66,6 +66,8 @@ namespace Motors { void handle(Configuration::HandlerBase& handler) override { handler.handle("pwm", _pwm_pin); + handler.handle("cal_min", _cal_min); + handler.handle("cal_max", _cal_max); } // Name of the configurable. Must match the name registered in the cpp file. diff --git a/Grbl_Esp32/src/Motors/TrinamicDriver.cpp b/Grbl_Esp32/src/Motors/TrinamicDriver.cpp index af435de5..521658dc 100644 --- a/Grbl_Esp32/src/Motors/TrinamicDriver.cpp +++ b/Grbl_Esp32/src/Motors/TrinamicDriver.cpp @@ -90,10 +90,12 @@ namespace Motors { config_message(); - auto ssPin = SPISSPin->get().getNative(Pin::Capabilities::Output | Pin::Capabilities::Native); - auto mosiPin = SPIMOSIPin->get().getNative(Pin::Capabilities::Output | Pin::Capabilities::Native); - auto sckPin = SPISCKPin->get().getNative(Pin::Capabilities::Output | Pin::Capabilities::Native); - auto misoPin = SPIMISOPin->get().getNative(Pin::Capabilities::Input | Pin::Capabilities::Native); + auto spiConfig = MachineConfig::instance()->_spi; + + auto ssPin = spiConfig->_ss.getNative(Pin::Capabilities::Output | Pin::Capabilities::Native); + auto mosiPin = spiConfig->_mosi.getNative(Pin::Capabilities::Output | Pin::Capabilities::Native); + auto sckPin = spiConfig->_sck.getNative(Pin::Capabilities::Output | Pin::Capabilities::Native); + auto misoPin = spiConfig->_miso.getNative(Pin::Capabilities::Input | Pin::Capabilities::Native); SPI.begin(sckPin, misoPin, mosiPin, ssPin); // this will get called for each motor, but does not seem to hurt anything @@ -197,18 +199,18 @@ namespace Motors { return; } - uint16_t run_i_ma = (uint16_t)(axis_settings[axis_index()]->run_current->get() * 1000.0); + uint16_t run_i_ma = (uint16_t)(_run_current * 1000.0); float hold_i_percent; - if (axis_settings[axis_index()]->run_current->get() == 0) { + if (_run_current == 0) { hold_i_percent = 0; } else { - hold_i_percent = axis_settings[axis_index()]->hold_current->get() / axis_settings[axis_index()]->run_current->get(); + hold_i_percent = _hold_current / _run_current; if (hold_i_percent > 1.0) hold_i_percent = 1.0; } - tmcstepper->microsteps(axis_settings[axis_index()]->microsteps->get()); + tmcstepper->microsteps(_microsteps); tmcstepper->rms_current(run_i_ma, hold_i_percent); } @@ -250,14 +252,18 @@ namespace Motors { break; case TrinamicMode ::StallGuard: //grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Stallguard"); - tmcstepper->en_pwm_mode(false); - tmcstepper->pwm_autoscale(false); - tmcstepper->TCOOLTHRS(calc_tstep(homing_feed_rate->get(), 150.0)); - tmcstepper->THIGH(calc_tstep(homing_feed_rate->get(), 60.0)); - tmcstepper->sfilt(1); - tmcstepper->diag1_stall(true); // stallguard i/o is on diag1 - tmcstepper->sgt(axis_settings[axis_index()]->stallguard->get()); - break; + { + auto feedrate = MachineConfig::instance()->_axes->_axis[axis_index()]->_homing->_feedRate; + + tmcstepper->en_pwm_mode(false); + tmcstepper->pwm_autoscale(false); + tmcstepper->TCOOLTHRS(calc_tstep(feedrate, 150.0)); + tmcstepper->THIGH(calc_tstep(feedrate, 60.0)); + tmcstepper->sfilt(1); + tmcstepper->diag1_stall(true); // stallguard i/o is on diag1 + tmcstepper->sgt(_stallguard); + break; + } default: grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "TRINAMIC_MODE_UNDEFINED"); } @@ -284,7 +290,7 @@ namespace Motors { tmcstepper->stallguard(), tmcstepper->sg_result(), feedrate, - axis_settings[axis_index()]->stallguard->get()); + _stallguard); TMC2130_n ::DRV_STATUS_t status { 0 }; // a useful struct to access the bits. status.sr = tmcstepper->DRV_STATUS(); @@ -308,9 +314,8 @@ namespace Motors { // This is used to set the stallguard window from the homing speed. // The percent is the offset on the window uint32_t TrinamicDriver::calc_tstep(float speed, float percent) { - double tstep = - speed / 60.0 * axis_settings[axis_index()]->steps_per_mm->get() * (256.0 / axis_settings[axis_index()]->microsteps->get()); - tstep = TRINAMIC_FCLK / tstep * percent / 100.0; + double tstep = speed / 60.0 * MachineConfig::instance()->_axes->_axis[axis_index()]->_stepsPerMm * (256.0 / _microsteps); + tstep = TRINAMIC_FCLK / tstep * percent / 100.0; return static_cast(tstep); } @@ -431,8 +436,7 @@ namespace Motors { } // Configuration registration - namespace - { + namespace { MotorFactory::InstanceBuilder registration_2130("tmc_2130"); MotorFactory::InstanceBuilder registration_5160("tmc_5160"); } diff --git a/Grbl_Esp32/src/Motors/TrinamicDriver.h b/Grbl_Esp32/src/Motors/TrinamicDriver.h index c38c3105..60b6175d 100644 --- a/Grbl_Esp32/src/Motors/TrinamicDriver.h +++ b/Grbl_Esp32/src/Motors/TrinamicDriver.h @@ -82,6 +82,11 @@ namespace Motors { bool _has_errors; bool _disabled; + float _run_current = 0.25; + float _hold_current = 0.25; + int _microsteps = 256; + int _stallguard = 0; + TrinamicMode _mode = TrinamicMode::None; bool test(); void set_mode(bool isHoming); @@ -128,6 +133,10 @@ namespace Motors { void handle(Configuration::HandlerBase& handler) override { handler.handle("cs", _cs_pin); handler.handle("r_sense", _r_sense); + handler.handle("run_current", _run_current); + handler.handle("hold_current", _hold_current); + handler.handle("microsteps", _microsteps); + handler.handle("stallguard", _stallguard); StandardStepper::handle(handler); } diff --git a/Grbl_Esp32/src/Protocol.cpp b/Grbl_Esp32/src/Protocol.cpp index 4b22bd7a..2fb2b046 100644 --- a/Grbl_Esp32/src/Protocol.cpp +++ b/Grbl_Esp32/src/Protocol.cpp @@ -98,7 +98,7 @@ bool can_park() { #ifdef ENABLE_PARKING_OVERRIDE_CONTROL sys.override_ctrl == Override::ParkingMotion && #endif - homing_enable->get() && !laser_mode->get(); + homing_enable->get() && !MachineConfig::instance()->_laserMode; } /* @@ -560,7 +560,7 @@ static void protocol_exec_rt_suspend() { restore_spindle_speed = block->spindle_speed; } #ifdef DISABLE_LASER_DURING_HOLD - if (laser_mode->get()) { + if (MachineConfig::instance()->_laserMode) { sys_rt_exec_accessory_override.bit.spindleOvrStop = true; } #endif @@ -663,7 +663,7 @@ static void protocol_exec_rt_suspend() { if (gc_state.modal.spindle != SpindleState::Disable) { // Block if safety door re-opened during prior restore actions. if (!sys.suspend.bit.restartRetract) { - if (laser_mode->get()) { + if (MachineConfig::instance()->_laserMode) { // When in laser mode, ignore spindle spin-up delay. Set to turn on laser when cycle starts. sys.step_control.updateSpindleRpm = true; } else { @@ -719,7 +719,7 @@ static void protocol_exec_rt_suspend() { } else if (sys.spindle_stop_ovr.bit.restore || sys.spindle_stop_ovr.bit.restoreCycle) { if (gc_state.modal.spindle != SpindleState::Disable) { report_feedback_message(Message::SpindleRestore); - if (laser_mode->get()) { + if (MachineConfig::instance()->_laserMode) { // When in laser mode, ignore spindle spin-up delay. Set to turn on laser when cycle starts. sys.step_control.updateSpindleRpm = true; } else { diff --git a/Grbl_Esp32/src/SDCard.cpp b/Grbl_Esp32/src/SDCard.cpp index 7e94d81b..1298b86e 100644 --- a/Grbl_Esp32/src/SDCard.cpp +++ b/Grbl_Esp32/src/SDCard.cpp @@ -19,6 +19,7 @@ */ #include "SDCard.h" +#include "MachineConfig.h" File myFile; bool SD_ready_next = false; // Grbl has processed a line and is waiting for another @@ -130,11 +131,14 @@ uint8_t sd_state = SDCARD_IDLE; uint8_t get_sd_state(bool refresh) { // Before we use the SD library, we *must* make sure SPI is properly initialized. Re-initialization // fortunately doesn't change any of the settings. - auto ssPin = SPISSPin->get().getNative(Pin::Capabilities::Output | Pin::Capabilities::Native); - auto mosiPin = SPIMOSIPin->get().getNative(Pin::Capabilities::Output | Pin::Capabilities::Native); - auto sckPin = SPISCKPin->get().getNative(Pin::Capabilities::Output | Pin::Capabilities::Native); - auto misoPin = SPIMISOPin->get().getNative(Pin::Capabilities::Input | Pin::Capabilities::Native); - SPI.begin(sckPin, misoPin, mosiPin, ssPin); + auto spiConfig = MachineConfig::instance()->_spi; + + auto ssPin = spiConfig->_ss.getNative(Pin::Capabilities::Output | Pin::Capabilities::Native); + auto mosiPin = spiConfig->_mosi.getNative(Pin::Capabilities::Output | Pin::Capabilities::Native); + auto sckPin = spiConfig->_sck.getNative(Pin::Capabilities::Output | Pin::Capabilities::Native); + auto misoPin = spiConfig->_miso.getNative(Pin::Capabilities::Input | Pin::Capabilities::Native); + + SPI.begin(sckPin, misoPin, mosiPin, ssPin); // this will get called for each motor, but does not seem to hurt anything //no need to go further if SD detect is not correct if (SDCardDetPin->get() != Pin::UNDEFINED) { diff --git a/Grbl_Esp32/src/Spindles/VFDSpindle.cpp b/Grbl_Esp32/src/Spindles/VFDSpindle.cpp index 0af76e49..1ca694c2 100644 --- a/Grbl_Esp32/src/Spindles/VFDSpindle.cpp +++ b/Grbl_Esp32/src/Spindles/VFDSpindle.cpp @@ -33,6 +33,7 @@ */ #include "VFDSpindle.h" +#include "../MachineConfig.h" const uart_port_t VFD_RS485_UART_PORT = UART_NUM_2; // hard coded for this port right now const int VFD_RS485_BUF_SIZE = 127; @@ -318,7 +319,7 @@ namespace Spindles { pins_settings_ok = false; } - if (laser_mode->get()) { + if (MachineConfig::instance()->_laserMode) { grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "VFD spindle disabled in laser mode. Set $GCode/LaserMode=Off and restart"); pins_settings_ok = false; } diff --git a/Grbl_Esp32/src/Stepper.cpp b/Grbl_Esp32/src/Stepper.cpp index a6dbd72d..149acc88 100644 --- a/Grbl_Esp32/src/Stepper.cpp +++ b/Grbl_Esp32/src/Stepper.cpp @@ -554,7 +554,7 @@ void st_prep_buffer() { prep.current_speed = sqrt(pl_block->entry_speed_sqr); } - if (spindle->isRateAdjusted()) { // laser_mode->get() { + if (spindle->isRateAdjusted()) { // MachineConfig::instance()->_laserMode { if (pl_block->spindle == SpindleState::Ccw) { // Pre-compute inverse programmed rate to speed up PWM updating per step segment. prep.inv_rate = 1.0 / pl_block->programmed_rate;