diff --git a/FluidNC/src/Machine/Axis.h b/FluidNC/src/Machine/Axis.h index ae724274f..0b274a813 100644 --- a/FluidNC/src/Machine/Axis.h +++ b/FluidNC/src/Machine/Axis.h @@ -29,10 +29,10 @@ namespace Machine { Motor* _motors[MAX_MOTORS_PER_AXIS]; Homing* _homing = nullptr; - float _stepsPerMm = 320.0f; + float _stepsPerMm = 80.0f; float _maxRate = 1000.0f; float _acceleration = 25.0f; - float _maxTravel = 200.0f; + float _maxTravel = 1000.0f; bool _softLimits = false; // Configuration system helpers: diff --git a/FluidNC/src/Machine/Homing.cpp b/FluidNC/src/Machine/Homing.cpp index 2d8cb2157..dbcd35c31 100644 --- a/FluidNC/src/Machine/Homing.cpp +++ b/FluidNC/src/Machine/Homing.cpp @@ -15,8 +15,8 @@ namespace Machine { // Input: seek - the phase - true for the initial high-speed seek, false for the slow second phase // Output: axislock - the axes that actually participate, accounting // Output: target - the endpoint vector of the motion - // Output: rate - the feed rate - // Return: debounce - the maximum delay time of all the axes + // Output: rate - the feed rate + // Return: settle - the maximum delay time of all the axes // For multi-axis homing, we use the per-axis rates and travel limits to compute // a target vector and a feedrate as follows: @@ -39,7 +39,7 @@ namespace Machine { uint32_t Homing::plan_move(MotorMask motors, bool approach, bool seek, float customPulloff) { float maxSeekTime = 0.0; float limitingRate = 0.0; - uint32_t debounce = 0; + uint32_t settle = 0; float rate = 0.0; auto axes = config->_axes; @@ -62,7 +62,7 @@ namespace Machine { auto axisConfig = axes->_axis[axis]; auto homing = axisConfig->_homing; - debounce = std::max(debounce, homing->_debounce_ms); + settle = std::max(settle, homing->_settle_ms); float axis_rate = seek ? homing->_seekRate : homing->_feedRate; @@ -127,7 +127,7 @@ namespace Machine { Stepper::prep_buffer(); // Prep and fill segment buffer from newly planned block. Stepper::wake_up(); // Initiate motion - return debounce; + return settle; } void Homing::run(MotorMask remainingMotors, bool approach, bool seek, float customPulloff = 0) { @@ -300,8 +300,8 @@ namespace Machine { for (int axis = 0; axis < n_axis; axis++) { if (bitnum_is_true(motors, axis)) { auto axisConfig = config->_axes->_axis[axis]; - if(axisConfig->hasDualMotor()){ - pulloffOffset = axisConfig->pulloffOffset(); + if (axisConfig->hasDualMotor()) { + pulloffOffset = axisConfig->pulloffOffset(); if (pulloffOffset != 0) { //log_info("Pulloff offset needed on axis " << axis << " of " << pulloffOffset); // TODO Do it diff --git a/FluidNC/src/Machine/Homing.h b/FluidNC/src/Machine/Homing.h index b8ed05f06..c3c87fe33 100644 --- a/FluidNC/src/Machine/Homing.h +++ b/FluidNC/src/Machine/Homing.h @@ -32,7 +32,7 @@ namespace Machine { float _mpos = 0.0f; // After homing this will be the mpos of the switch location float _feedRate = 50.0f; // pulloff and second touch speed float _seekRate = 200.0f; // this first approach speed - uint32_t _debounce_ms = 250; // ms settling time for homing switches after motion + uint32_t _settle_ms = 250; // ms settling time for homing switches after motion float _seek_scaler = 1.1f; // multiplied by max travel for max homing distance on first touch float _feed_scaler = 1.1f; // multiplier to pulloff for moving to switch after pulloff @@ -45,7 +45,7 @@ namespace Machine { handler.item("mpos_mm", _mpos); handler.item("feed_mm_per_min", _feedRate); handler.item("seek_mm_per_min", _seekRate); - handler.item("debounce_ms", _debounce_ms); + handler.item("settle_ms", _settle_ms); handler.item("seek_scaler", _seek_scaler); handler.item("feed_scaler", _feed_scaler); } diff --git a/FluidNC/src/Machine/Motor.h b/FluidNC/src/Machine/Motor.h index 371f2b4cc..25356b935 100644 --- a/FluidNC/src/Machine/Motor.h +++ b/FluidNC/src/Machine/Motor.h @@ -33,7 +33,7 @@ namespace Machine { Pin _negPin; Pin _posPin; Pin _allPin; - bool _hardLimits = true; + bool _hardLimits = false; // Configuration system helpers: void group(Configuration::HandlerBase& handler) override; diff --git a/FluidNC/src/Motors/TrinamicBase.cpp b/FluidNC/src/Motors/TrinamicBase.cpp index ff3f926bf..d538ef62a 100644 --- a/FluidNC/src/Motors/TrinamicBase.cpp +++ b/FluidNC/src/Motors/TrinamicBase.cpp @@ -8,8 +8,7 @@ #include namespace MotorDrivers { - EnumItem trinamicModes[] = { { TrinamicMode::Unknown, "Unknown" }, - { TrinamicMode::StealthChop, "StealthChop" }, + EnumItem trinamicModes[] = { { TrinamicMode::StealthChop, "StealthChop" }, { TrinamicMode::CoolStep, "CoolStep" }, { TrinamicMode::StallGuard, "StallGuard" }, EnumItem(TrinamicMode::StealthChop) }; diff --git a/FluidNC/src/Motors/TrinamicBase.h b/FluidNC/src/Motors/TrinamicBase.h index 4932b3f2a..b149a378a 100644 --- a/FluidNC/src/Motors/TrinamicBase.h +++ b/FluidNC/src/Motors/TrinamicBase.h @@ -11,7 +11,6 @@ namespace MotorDrivers { enum TrinamicMode { - Unknown = 0, StealthChop = 1, // very quiet CoolStep = 2, // cooler so higher current possible StallGuard = 3, // coolstep plus stall indication @@ -26,7 +25,7 @@ namespace MotorDrivers { bool _has_errors; uint16_t _driver_part_number; // example: use 2130 for TMC2130 bool _disabled = false; - TrinamicMode _mode = TrinamicMode::Unknown; // no mode set yet + TrinamicMode _mode = TrinamicMode::StealthChop; // Configurable int _homing_mode = StealthChop; diff --git a/FluidNC/src/Motors/TrinamicSpiDriver.cpp b/FluidNC/src/Motors/TrinamicSpiDriver.cpp index bbb99fc6d..ad019d8bb 100644 --- a/FluidNC/src/Motors/TrinamicSpiDriver.cpp +++ b/FluidNC/src/Motors/TrinamicSpiDriver.cpp @@ -35,9 +35,9 @@ namespace MotorDrivers { if (_driver_part_number == 2130) { //log_info("ID: " << cs_id << " index:" << _spi_index); - tmcstepper = new TMC2130Stepper(cs_id, _r_sense, _spi_index); // TODO hardwired to non daisy chain index + tmc2130 = new TMC2130Stepper(cs_id, _r_sense, _spi_index); // TODO hardwired to non daisy chain index } else if (_driver_part_number == 5160) { - tmcstepper = new TMC5160Stepper(cs_id, _r_sense, _spi_index); + tmc5160 = new TMC5160Stepper(cs_id, _r_sense, _spi_index); } else { log_info(" Unsupported Trinamic part number TMC" << _driver_part_number); _has_errors = true; // This motor cannot be used @@ -48,7 +48,11 @@ namespace MotorDrivers { // use slower speed if I2S if (_cs_pin.capabilities().has(Pin::Capabilities::I2S)) { - tmcstepper->setSPISpeed(_spi_freq); + if (tmc2130) { + tmc2130->setSPISpeed(_spi_freq); + } else { + tmc5160->setSPISpeed(_spi_freq); + } } link = List; @@ -77,8 +81,11 @@ namespace MotorDrivers { } void TrinamicSpiDriver::config_motor() { - tmcstepper->begin(); - + if (tmc2130) { + tmc2130->begin(); + } else { + tmc5160->begin(); + } _has_errors = !test(); // Try communicating with motor. Prints an error if there is a problem. init_step_dir_pins(); @@ -99,7 +106,8 @@ namespace MotorDrivers { return false; } - switch (tmcstepper->test_connection()) { + uint8_t result = tmc2130 ? tmc2130->test_connection() : tmc5160->test_connection(); + switch (result) { case 1: log_info(axisName() << " driver test failed. Check connection"); return false; @@ -110,7 +118,7 @@ namespace MotorDrivers { // driver responded, so check for other errors from the DRV_STATUS register // TMC2130_n ::DRV_STATUS_t status { 0 }; // a useful struct to access the bits. - // status.sr = tmcstepper->DRV_STATUS(); + // status.sr = tmc2130 ? tmc2130stepper->DRV_STATUS() : tmc5160stepper->DRV_STATUS();; // bool err = false; @@ -139,10 +147,9 @@ namespace MotorDrivers { } /* - Read setting and send them to the driver. Called at init() and whenever related settings change - both are stored as float Amps, but TMCStepper library expects... - uint16_t run (mA) - float hold (as a percentage of run) + Run and hold current configuration items are in (float) Amps, + but the TMCStepper library expresses run current as (uint16_t) mA + and hold current as (float) fraction of run current. */ void TrinamicSpiDriver::read_settings() { if (_has_errors) { @@ -161,8 +168,13 @@ namespace MotorDrivers { } } - tmcstepper->microsteps(_microsteps); - tmcstepper->rms_current(run_i_ma, hold_i_percent); + if (tmc2130) { + tmc2130->microsteps(_microsteps); + tmc2130->rms_current(run_i_ma, hold_i_percent); + } else { + tmc5160->microsteps(_microsteps); + tmc5160->rms_current(run_i_ma, hold_i_percent); + } } bool TrinamicSpiDriver::set_homing_mode(bool isHoming) { @@ -170,79 +182,97 @@ namespace MotorDrivers { return true; } - /* - There are ton of settings. I'll start by grouping then into modes for now. - Many people will want quiet and stallguard homing. Stallguard only run in - Coolstep mode, so it will need to switch to Coolstep when homing - */ void TrinamicSpiDriver::set_mode(bool isHoming) { if (_has_errors) { return; } - TrinamicMode newMode = static_cast(trinamicModes[isHoming ? _homing_mode : _run_mode].value); + _mode = static_cast(trinamicModes[isHoming ? _homing_mode : _run_mode].value); - if (newMode == _mode) { - return; - } - _mode = newMode; - - switch (_mode) { - case TrinamicMode ::StealthChop: - //log_info("StealthChop"); - tmcstepper->en_pwm_mode(true); - tmcstepper->pwm_autoscale(true); - tmcstepper->diag1_stall(false); - break; - case TrinamicMode ::CoolStep: - //log_info("Coolstep"); - tmcstepper->en_pwm_mode(false); - tmcstepper->pwm_autoscale(false); - tmcstepper->TCOOLTHRS(NORMAL_TCOOLTHRS); // when to turn on coolstep - tmcstepper->THIGH(NORMAL_THIGH); - break; - case TrinamicMode ::StallGuard: - //log_info("Stallguard"); - { - auto feedrate = config->_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(constrain(_stallguard, -64, 63)); + if (tmc2130) { + switch (_mode) { + case TrinamicMode ::StealthChop: + //log_info("StealthChop"); + tmc2130->en_pwm_mode(true); + tmc2130->pwm_autoscale(true); + tmc2130->diag1_stall(false); break; - } - case TrinamicMode ::Unknown: - log_info("TrinamicMode ::Unknown"); - break; + case TrinamicMode ::CoolStep: + //log_info("Coolstep"); + tmc2130->en_pwm_mode(false); + tmc2130->pwm_autoscale(false); + tmc2130->TCOOLTHRS(NORMAL_TCOOLTHRS); // when to turn on coolstep + tmc2130->THIGH(NORMAL_THIGH); + break; + case TrinamicMode ::StallGuard: + //log_info("Stallguard"); + { + auto feedrate = config->_axes->_axis[axis_index()]->_homing->_feedRate; + + tmc2130->en_pwm_mode(false); + tmc2130->pwm_autoscale(false); + tmc2130->TCOOLTHRS(calc_tstep(feedrate, 150.0)); + tmc2130->THIGH(calc_tstep(feedrate, 60.0)); + tmc2130->sfilt(1); + tmc2130->diag1_stall(true); // stallguard i/o is on diag1 + tmc2130->sgt(constrain(_stallguard, -64, 63)); + break; + } + } + } else { + switch (_mode) { + case TrinamicMode ::StealthChop: + //log_info("StealthChop"); + tmc5160->en_pwm_mode(true); + tmc5160->pwm_autoscale(true); + tmc5160->diag1_stall(false); + break; + case TrinamicMode ::CoolStep: + //log_info("Coolstep"); + tmc5160->en_pwm_mode(false); + tmc5160->pwm_autoscale(false); + tmc5160->TCOOLTHRS(NORMAL_TCOOLTHRS); // when to turn on coolstep + tmc5160->THIGH(NORMAL_THIGH); + break; + case TrinamicMode ::StallGuard: + //log_info("Stallguard"); + { + auto feedrate = config->_axes->_axis[axis_index()]->_homing->_feedRate; + + tmc5160->en_pwm_mode(false); + tmc5160->pwm_autoscale(false); + tmc5160->TCOOLTHRS(calc_tstep(feedrate, 150.0)); + tmc5160->THIGH(calc_tstep(feedrate, 60.0)); + tmc5160->sfilt(1); + tmc5160->diag1_stall(true); // stallguard i/o is on diag1 + tmc5160->sgt(constrain(_stallguard, -64, 63)); + break; + } + } } } - /* - This is the stallguard tuning info. It is call debug, so it could be generic across all classes. -*/ + // Report diagnostic and tuning info void TrinamicSpiDriver::debug_message() { if (_has_errors) { return; } - uint32_t tstep = tmcstepper->TSTEP(); + uint32_t tstep = tmc2130 ? tmc2130->TSTEP() : tmc5160->TSTEP(); if (tstep == 0xFFFFF || tstep < 1) { // if axis is not moving return return; } float feedrate = Stepper::get_realtime_rate(); //* settings.microsteps[axis_index] / 60.0 ; // convert mm/min to Hz - log_info(axisName() << " Stallguard " << tmcstepper->stallguard() << " SG_Val:" << tmcstepper->sg_result() << " Rate:" << feedrate + log_info(axisName() << " Stallguard " << (tmc2130 ? tmc2130->stallguard() : tmc5160->stallguard()) + << " SG_Val:" << (tmc2130 ? tmc2130->sg_result() : tmc5160->sg_result()) << " Rate:" << feedrate << " mm/min SG_Setting:" << constrain(_stallguard, -64, 63)); // The bit locations differ somewhat between different chips. - // The layout is very different between 2130 and 2208 + // The layout is the same for TMC2130 and TMC5160 TMC2130_n ::DRV_STATUS_t status { 0 }; // a useful struct to access the bits. - status.sr = tmcstepper->DRV_STATUS(); + status.sr = tmc2130 ? tmc2130->DRV_STATUS() : tmc5160->DRV_STATUS(); // these only report if there is a fault condition report_open_load(status.ola, status.olb); @@ -250,11 +280,9 @@ namespace MotorDrivers { report_over_temp(status.ot, status.otpw); report_short_to_ps(bits_are_true(status.sr, 12), bits_are_true(status.sr, 13)); - // log_info(axisName() << " Status Register " << String(status.sr, HEX) << " GSTAT " << String(tmcstepper->GSTAT(), HEX)); + // log_info(axisName() << " Status Register " << String(status.sr, HEX) << " GSTAT " << String(tmc2130 ? tmc2130->GSTAT() : tmc5160->GSTAT(), HEX)); } - // this can use the enable feature over SPI. The dedicated pin must be in the enable mode, - // but that can be hardwired that way. void IRAM_ATTR TrinamicSpiDriver::set_disable(bool disable) { if (_has_errors) { return; @@ -269,18 +297,22 @@ namespace MotorDrivers { _disable_pin.synchronousWrite(_disabled); if (_use_enable) { + uint8_t toff_value; if (_disabled) { - tmcstepper->toff(_toff_disable); + toff_value = _toff_disable; } else { if (_mode == TrinamicMode::StealthChop) { - tmcstepper->toff(_toff_stealthchop); + toff_value = _toff_stealthchop; } else { - tmcstepper->toff(_toff_coolstep); + toff_value = _toff_coolstep; } } + if (tmc2130) { + tmc2130->toff(toff_value); + } else { + tmc5160->toff(toff_value); + } } - // the pin based enable could be added here. - // This would be for individual motors, not the single pin for all motors. } // Configuration registration diff --git a/FluidNC/src/Motors/TrinamicSpiDriver.h b/FluidNC/src/Motors/TrinamicSpiDriver.h index 48a652d9a..d0de21d6f 100644 --- a/FluidNC/src/Motors/TrinamicSpiDriver.h +++ b/FluidNC/src/Motors/TrinamicSpiDriver.h @@ -16,6 +16,7 @@ const int NORMAL_TCOOLTHRS = 0xFFFFF; // 20 bit is max const int NORMAL_THIGH = 0; class TMC2130Stepper; // Forward declaration +class TMC5160Stepper; // Forward declaration namespace MotorDrivers { @@ -26,10 +27,18 @@ namespace MotorDrivers { static pinnum_t daisy_chain_cs_id; static uint8_t spi_index_mask; - TMC2130Stepper* tmcstepper; // all other driver types are subclasses of this one - Pin _cs_pin; // The chip select pin (can be the same for daisy chain) - PinMapper _cs_mapping; - int32_t _spi_index = -1; + // It is really tempting to have a single pointer here because + // TMC2130 and TMC5160 share many methods with the same names + // and API. That does not work because the common methods are + // not virtual and their respective implementations are + // incompatible due to hardware differences. Therefore it is + // necessary to preserve the full type knowledge in the pointers. + TMC2130Stepper* tmc2130 = nullptr; + TMC5160Stepper* tmc5160 = nullptr; + + Pin _cs_pin; // The chip select pin (can be the same for daisy chain) + PinMapper _cs_mapping; + int32_t _spi_index = -1; bool test(); void set_mode(bool isHoming); diff --git a/FluidNC/src/Motors/TrinamicUartDriver.cpp b/FluidNC/src/Motors/TrinamicUartDriver.cpp index a76d59418..bad9e7481 100644 --- a/FluidNC/src/Motors/TrinamicUartDriver.cpp +++ b/FluidNC/src/Motors/TrinamicUartDriver.cpp @@ -49,8 +49,11 @@ namespace MotorDrivers { config_message(); - tmcstepper->begin(); - + if (tmc2208) { + tmc2208->begin(); + } else { + tmc2209->begin(); + } _has_errors = !test(); // Try communicating with motor. Prints an error if there is a problem. init_step_dir_pins(); @@ -72,8 +75,12 @@ namespace MotorDrivers { } bool TrinamicUartDriver::hw_serial_init() { + if (_driver_part_number == 2208) { + tmc2208 = new TMC2208Stepper(_uart, _r_sense); + return false; + } if (_driver_part_number == 2209) { - tmcstepper = new TMC2209Stepper(_uart, _r_sense, _addr); + tmc2209 = new TMC2209Stepper(_uart, _r_sense, _addr); return false; } log_info("Unsupported Trinamic motor p/n:" << _driver_part_number); @@ -93,7 +100,8 @@ namespace MotorDrivers { return false; } - switch (tmcstepper->test_connection()) { + uint8_t result = tmc2208 ? tmc2208->test_connection() : tmc2209->test_connection(); + switch (result) { case 1: log_info(" " << axisName() << " Trinamic driver test failed. Check connection"); return false; @@ -104,7 +112,7 @@ namespace MotorDrivers { // driver responded, so check for other errors from the DRV_STATUS register TMC2208_n ::DRV_STATUS_t status { 0 }; // a useful struct to access the bits. - status.sr = tmcstepper->DRV_STATUS(); + status.sr = tmc2208 ? tmc2208->DRV_STATUS() : tmc2209->DRV_STATUS(); bool err = false; @@ -133,12 +141,10 @@ namespace MotorDrivers { } /* - Read setting and send them to the driver. Called at init() and whenever related settings change - both are stored as float Amps, but TMCStepper library expects... - uint16_t run (mA) - float hold (as a percentage of run) + Run and hold current configuration items are in (float) Amps, + but the TMCStepper library expresses run current as (uint16_t) mA + and hold current as (float) fraction of run current. */ - // XXX Identical to TrinamicDriver::read_settings() void TrinamicUartDriver::read_settings() { if (_has_errors) { return; @@ -156,8 +162,13 @@ namespace MotorDrivers { } } - tmcstepper->microsteps(_microsteps); - tmcstepper->rms_current(run_i_ma, hold_i_percent); + if (tmc2208) { + tmc2208->microsteps(_microsteps); + tmc2208->rms_current(run_i_ma, hold_i_percent); + } else { + tmc2209->microsteps(_microsteps); + tmc2209->rms_current(run_i_ma, hold_i_percent); + } } // XXX Identical to TrinamicDriver::set_homing_mode() @@ -166,71 +177,71 @@ namespace MotorDrivers { return true; } - /* - There are ton of settings. I'll start by grouping then into modes for now. - Many people will want quiet and stallguard homing. Stallguard only run in - Coolstep mode, so it will need to switch to Coolstep when homing - */ void TrinamicUartDriver::set_mode(bool isHoming) { if (_has_errors) { return; } - TrinamicMode newMode = static_cast(trinamicModes[isHoming ? _homing_mode : _run_mode].value); - - if (newMode == _mode) { - return; - } - _mode = newMode; - - switch (_mode) { - case TrinamicMode ::StealthChop: - //log_info("StealthChop"); - tmcstepper->en_spreadCycle(false); - tmcstepper->pwm_autoscale(true); - break; - case TrinamicMode ::CoolStep: - //log_info("Coolstep"); - // tmcstepper->en_pwm_mode(false); //TODO: check if this is present in TMC2208/09 - tmcstepper->en_spreadCycle(true); - tmcstepper->pwm_autoscale(false); - break; - case TrinamicMode ::StallGuard: //TODO: check all configurations for stallguard - { - auto axisConfig = config->_axes->_axis[this->axis_index()]; - auto homingFeedRate = (axisConfig->_homing != nullptr) ? axisConfig->_homing->_feedRate : 200; - //log_info("Stallguard"); - tmcstepper->en_spreadCycle(false); - tmcstepper->pwm_autoscale(false); - tmcstepper->TCOOLTHRS(calc_tstep(homingFeedRate, 150.0)); - tmcstepper->SGTHRS(constrain(_stallguard, 0, 255)); - break; + TrinamicMode _mode = static_cast(trinamicModes[isHoming ? _homing_mode : _run_mode].value); + if (tmc2208) { + switch (_mode) { + case TrinamicMode ::StealthChop: + //log_info("StealthChop"); + tmc2208->en_spreadCycle(false); + tmc2208->pwm_autoscale(true); + break; + default: + log_info("Unsupported TMC2208 mode:" << _mode); + } + } else { + switch (_mode) { + case TrinamicMode ::StealthChop: + //log_info("StealthChop"); + tmc2209->en_spreadCycle(false); + tmc2209->pwm_autoscale(true); + break; + case TrinamicMode ::CoolStep: + //log_info("Coolstep"); + // tmc2209->en_pwm_mode(false); //TODO: check if this is present in TMC2208/09 + tmc2209->en_spreadCycle(true); + tmc2209->pwm_autoscale(false); + break; + case TrinamicMode ::StallGuard: //TODO: check all configurations for stallguard + { + auto axisConfig = config->_axes->_axis[this->axis_index()]; + auto homingFeedRate = (axisConfig->_homing != nullptr) ? axisConfig->_homing->_feedRate : 200; + //log_info("Stallguard"); + tmc2209->en_spreadCycle(false); + tmc2209->pwm_autoscale(false); + tmc2209->TCOOLTHRS(calc_tstep(homingFeedRate, 150.0)); + tmc2209->SGTHRS(constrain(_stallguard, 0, 255)); + break; + } } - default: - log_info("Unknown Trinamic mode:" << _mode); } } - /* - This is the stallguard tuning info. It is call debug, so it could be generic across all classes. - */ + // Report diagnostic and tuning info. void TrinamicUartDriver::debug_message() { if (_has_errors) { return; } - uint32_t tstep = tmcstepper->TSTEP(); + uint32_t tstep = tmc2208 ? tmc2208->TSTEP() : tmc2209->TSTEP(); if (tstep == 0xFFFFF || tstep < 1) { // if axis is not moving return return; } float feedrate = Stepper::get_realtime_rate(); //* settings.microsteps[axis_index] / 60.0 ; // convert mm/min to Hz - log_info(axisName() << " SG_Val: " << tmcstepper->SG_RESULT() << " Rate: " << feedrate - << " mm/min SG_Setting:" << constrain(_stallguard, -64, 63)); + // TMC2208 does not have StallGuard + if (tmc2209) { + log_info(axisName() << " SG_Val: " << tmc2209->SG_RESULT() << " Rate: " << feedrate + << " mm/min SG_Setting:" << constrain(_stallguard, -64, 63)); + } TMC2208_n ::DRV_STATUS_t status { 0 }; // a useful struct to access the bits. - status.sr = tmcstepper->DRV_STATUS(); + status.sr = tmc2208 ? tmc2208->DRV_STATUS() : tmc2209->DRV_STATUS(); // these only report if there is a fault condition report_open_load(status.ola, status.olb); @@ -238,12 +249,9 @@ namespace MotorDrivers { report_over_temp(status.ot, status.otpw); report_short_to_ps(bits_are_true(status.sr, 12), bits_are_true(status.sr, 13)); - // log_info(axisName()<<" Status Register "<GSTAT(),HEX)); + // log_info(axisName()<<" Status Register "<GSTAT() : tmc2209->GSTAT(),HEX)); } - // XXX Identical to TrinamicDriver::set_disable() - // this can use the enable feature over SPI. The dedicated pin must be in the enable mode, - // but that can be hardwired that way. void IRAM_ATTR TrinamicUartDriver::set_disable(bool disable) { if (_has_errors) { return; @@ -258,18 +266,22 @@ namespace MotorDrivers { _disable_pin.synchronousWrite(_disabled); if (_use_enable) { + uint8_t toff_value; if (_disabled) { - tmcstepper->toff(_toff_disable); + toff_value = _toff_disable; } else { if (_mode == TrinamicMode::StealthChop) { - tmcstepper->toff(_toff_stealthchop); + toff_value = _toff_stealthchop; } else { - tmcstepper->toff(_toff_coolstep); + toff_value = _toff_coolstep; } } + if (tmc2208) { + tmc2208->toff(toff_value); + } else { + tmc2209->toff(toff_value); + } } - // the pin based enable could be added here. - // This would be for individual motors, not the single pin for all motors. } // Configuration registration diff --git a/FluidNC/src/Motors/TrinamicUartDriver.h b/FluidNC/src/Motors/TrinamicUartDriver.h index 69e3381a2..b0e286bc5 100644 --- a/FluidNC/src/Motors/TrinamicUartDriver.h +++ b/FluidNC/src/Motors/TrinamicUartDriver.h @@ -10,6 +10,7 @@ #include +class TMC2208Stepper; // Forward declaration class TMC2209Stepper; // Forward declaration namespace MotorDrivers { @@ -20,7 +21,8 @@ namespace MotorDrivers { static bool _uart_started; - TMC2209Stepper* tmcstepper; // all other driver types are subclasses of this one + TMC2208Stepper* tmc2208; + TMC2209Stepper* tmc2209; bool test(); void set_mode(bool isHoming); diff --git a/FluidNC/src/Pin.h b/FluidNC/src/Pin.h index 769076ce3..aa6550e0d 100644 --- a/FluidNC/src/Pin.h +++ b/FluidNC/src/Pin.h @@ -14,8 +14,6 @@ #include #include "Assert.h" -// TODO: ENABLE_CONTROL_SW_DEBOUNCE should end up here with a shared task. - // #define DEBUG_PIN_DUMP // Pin debugging. WILL spam you with a lot of data! // Forward declarations: diff --git a/FluidNC/src/ProcessSettings.cpp b/FluidNC/src/ProcessSettings.cpp index 54e0946cb..a5f6d1e50 100644 --- a/FluidNC/src/ProcessSettings.cpp +++ b/FluidNC/src/ProcessSettings.cpp @@ -504,38 +504,38 @@ void make_user_commands() { new UserCommand("CD", "Config/Dump", dump_config, anyState); new UserCommand("", "Help", show_help, anyState); new UserCommand("T", "State", showState, anyState); - new UserCommand("J", "Jog", doJog, idleOrJog); - - new UserCommand("$", "GrblSettings/List", report_normal_settings, notCycleOrHold); - new UserCommand("L", "GrblNames/List", list_grbl_names, notCycleOrHold); - new UserCommand("Limits", "Limits/Show", show_limits, notCycleOrHold); - new UserCommand("S", "Settings/List", list_settings, notCycleOrHold); - new UserCommand("SC", "Settings/ListChanged", list_changed_settings, notCycleOrHold); - new UserCommand("CMD", "Commands/List", list_commands, notCycleOrHold); + new UserCommand("J", "Jog", doJog, notIdleOrJog); + + new UserCommand("$", "GrblSettings/List", report_normal_settings, cycleOrHold); + new UserCommand("L", "GrblNames/List", list_grbl_names, cycleOrHold); + new UserCommand("Limits", "Limits/Show", show_limits, cycleOrHold); + new UserCommand("S", "Settings/List", list_settings, cycleOrHold); + new UserCommand("SC", "Settings/ListChanged", list_changed_settings, cycleOrHold); + new UserCommand("CMD", "Commands/List", list_commands, cycleOrHold); new UserCommand("A", "Alarms/List", listAlarms, anyState); new UserCommand("E", "Errors/List", listErrors, anyState); new UserCommand("G", "GCode/Modes", report_gcode, anyState); new UserCommand("C", "GCode/Check", toggle_check_mode, anyState); new UserCommand("X", "Alarm/Disable", disable_alarm_lock, anyState); - new UserCommand("NVX", "Settings/Erase", Setting::eraseNVS, idleOrAlarm, WA); - new UserCommand("V", "Settings/Stats", Setting::report_nvs_stats, idleOrAlarm); - new UserCommand("#", "GCode/Offsets", report_ngc, idleOrAlarm); - new UserCommand("H", "Home", home_all, idleOrAlarm); - new UserCommand("MD", "Motor/Disable", motor_disable, idleOrAlarm); - - new UserCommand("HX", "Home/X", home_x, idleOrAlarm); - new UserCommand("HY", "Home/Y", home_y, idleOrAlarm); - new UserCommand("HZ", "Home/Z", home_z, idleOrAlarm); - new UserCommand("HA", "Home/A", home_a, idleOrAlarm); - new UserCommand("HB", "Home/B", home_b, idleOrAlarm); - new UserCommand("HC", "Home/C", home_c, idleOrAlarm); - - new UserCommand("SLP", "System/Sleep", go_to_sleep, idleOrAlarm); - new UserCommand("I", "Build/Info", get_report_build_info, idleOrAlarm); - new UserCommand("N", "GCode/StartupLines", report_startup_lines, idleOrAlarm); - new UserCommand("RST", "Settings/Restore", restore_settings, idleOrAlarm, WA); - - new UserCommand("32", "FakeLaserMode", fakeLaserMode, idleOrAlarm); + new UserCommand("NVX", "Settings/Erase", Setting::eraseNVS, notIdleOrAlarm, WA); + new UserCommand("V", "Settings/Stats", Setting::report_nvs_stats, notIdleOrAlarm); + new UserCommand("#", "GCode/Offsets", report_ngc, notIdleOrAlarm); + new UserCommand("H", "Home", home_all, notIdleOrAlarm); + new UserCommand("MD", "Motor/Disable", motor_disable, notIdleOrAlarm); + + new UserCommand("HX", "Home/X", home_x, notIdleOrAlarm); + new UserCommand("HY", "Home/Y", home_y, notIdleOrAlarm); + new UserCommand("HZ", "Home/Z", home_z, notIdleOrAlarm); + new UserCommand("HA", "Home/A", home_a, notIdleOrAlarm); + new UserCommand("HB", "Home/B", home_b, notIdleOrAlarm); + new UserCommand("HC", "Home/C", home_c, notIdleOrAlarm); + + new UserCommand("SLP", "System/Sleep", go_to_sleep, notIdleOrAlarm); + new UserCommand("I", "Build/Info", get_report_build_info, notIdleOrAlarm); + new UserCommand("N", "GCode/StartupLines", report_startup_lines, notIdleOrAlarm); + new UserCommand("RST", "Settings/Restore", restore_settings, notIdleOrAlarm, WA); + + new UserCommand("32", "FakeLaserMode", fakeLaserMode, notIdleOrAlarm); }; // normalize_key puts a key string into canonical form - diff --git a/FluidNC/src/Settings.cpp b/FluidNC/src/Settings.cpp index 93ab4aabb..64483569e 100644 --- a/FluidNC/src/Settings.cpp +++ b/FluidNC/src/Settings.cpp @@ -18,13 +18,13 @@ bool anyState() { return false; } -bool idleOrJog() { +bool notIdleOrJog() { return sys.state != State::Idle && sys.state != State::Jog; } -bool idleOrAlarm() { +bool notIdleOrAlarm() { return sys.state != State::Idle && sys.state != State::Alarm && sys.state != State::ConfigAlarm; } -bool notCycleOrHold() { +bool cycleOrHold() { return sys.state == State::Cycle && sys.state == State::Hold; } @@ -68,7 +68,7 @@ Setting::Setting( } Error Setting::check(char* s) { - if (sys.state != State::Idle && sys.state != State::Alarm) { + if (notIdleOrAlarm()) { return Error::IdleError; } if (!_checker) { diff --git a/FluidNC/src/Settings.h b/FluidNC/src/Settings.h index d19a79a47..ec8ce19a9 100644 --- a/FluidNC/src/Settings.h +++ b/FluidNC/src/Settings.h @@ -303,10 +303,10 @@ class EnumSetting : public Setting { int8_t get() { return _currentValue; } }; -extern bool idleOrJog(); -extern bool idleOrAlarm(); +extern bool notIdleOrJog(); +extern bool notIdleOrAlarm(); extern bool anyState(); -extern bool notCycleOrHold(); +extern bool cycleOrHold(); class IPaddrSetting : public Setting { private: @@ -362,7 +362,7 @@ class WebCommand : public Command { const char* grblName, const char* name, Error (*action)(char*, WebUI::AuthenticationLevel)) : - WebCommand(description, type, permissions, grblName, name, action, idleOrAlarm) {} + WebCommand(description, type, permissions, grblName, name, action, notIdleOrAlarm) {} Error action(char* value, WebUI::AuthenticationLevel auth_level, Print& response); }; diff --git a/FluidNC/src/WebUI/WebSettings.cpp b/FluidNC/src/WebUI/WebSettings.cpp index bd4caa331..8db1b65cb 100644 --- a/FluidNC/src/WebUI/WebSettings.cpp +++ b/FluidNC/src/WebUI/WebSettings.cpp @@ -302,7 +302,7 @@ namespace WebUI { } static Error showLocalFile(char* parameter, AuthenticationLevel auth_level) { // ESP701 - if (sys.state != State::Idle && sys.state != State::Alarm) { + if (notIdleOrAlarm()) { return Error::IdleError; } String path = trim(parameter); @@ -682,7 +682,7 @@ namespace WebUI { } static Error showSDFile(char* parameter, AuthenticationLevel auth_level) { // ESP221 - if (sys.state != State::Idle && sys.state != State::Alarm) { + if (notIdleOrAlarm()) { return Error::IdleError; } Error err;