1
0
mirror of https://github.com/bdring/Grbl_Esp32.git synced 2025-08-31 01:59:54 +02:00

Trinamic define elimination and factoring

This commit is contained in:
Mitch Bradley
2021-06-22 11:36:19 -10:00
parent 221900d201
commit a5af8d43f1
6 changed files with 140 additions and 217 deletions

View File

@@ -16,12 +16,16 @@
along with Grbl. If not, see <http://www.gnu.org/licenses/>.
*/
#include "TrinamicBase.h"
#include "../Machine/MachineConfig.h"
#include <atomic>
namespace Motors {
EnumItem trinamicModes[] = { { TrinamicMode::StealthChop, "StealthChop" },
{ TrinamicMode::CoolStep, "CoolStep" },
{ TrinamicMode::StallGuard, "StallGuard" },
EnumItem(TrinamicMode::StealthChop) };
TrinamicBase* TrinamicBase::List = NULL; // a static list of all drivers for stallguard reporting
uint8_t TrinamicBase::get_next_index() {
@@ -57,17 +61,52 @@ namespace Motors {
#endif
}
}
// calculate a tstep from a rate
// tstep = TRINAMIC_FCLK / (time between 1/256 steps)
// tstep = fclk / (time between 1/256 steps)
// This is used to set the stallguard window from the homing speed.
// The percent is the offset on the window
uint32_t TrinamicBase::calc_tstep(float speed, float percent) {
double tstep = speed / 60.0 * config->_axes->_axis[axis_index()]->_stepsPerMm * (256.0 / _microsteps);
tstep = TRINAMIC_FCLK / tstep * percent / 100.0;
tstep = fclk / tstep * percent / 100.0;
return static_cast<uint32_t>(tstep);
}
// =========== Reporting functions ========================
bool TrinamicBase::report_open_load(bool ola, bool olb) {
if (ola || olb) {
info_serial("%s Driver Open Load a:%s b:%s", reportAxisNameMsg(axis_index(), dual_axis_index()), ola ? "Y" : "N", olb ? "Y" : "N");
return true;
}
return false; // no error
}
bool TrinamicBase::report_short_to_ground(bool s2ga, bool s2gb) {
if (s2ga || s2gb) {
info_serial(
"%s Driver Short Coil a:%s b:%s", reportAxisNameMsg(axis_index(), dual_axis_index()), s2ga ? "Y" : "N", s2gb ? "Y" : "N");
return true;
}
return false; // no error
}
bool TrinamicBase::report_over_temp(bool ot, bool otpw) {
if (ot || otpw) {
info_serial(
"%s Driver Temp Warning:%s Fault:%s", reportAxisNameMsg(axis_index(), dual_axis_index()), otpw ? "Y" : "N", ot ? "Y" : "N");
return true;
}
return false; // no error
}
bool TrinamicBase::report_short_to_ps(bool vsa, bool vsb) {
// check for short to power supply
if (vsa || vsb) {
info_serial("%s Driver Short vsa:%s vsb:%s", reportAxisNameMsg(axis_index(), dual_axis_index()), vsa ? "Y" : "N", vsb ? "Y" : "N");
return true;
}
return false; // no error
}
}

View File

@@ -21,32 +21,30 @@
#include <cstdint>
#include "StandardStepper.h"
#ifndef TRINAMIC_RUN_MODE
# define TRINAMIC_RUN_MODE TrinamicMode ::StealthChop
#endif
#ifndef TRINAMIC_HOMING_MODE
# define TRINAMIC_HOMING_MODE TRINAMIC_RUN_MODE
#endif
namespace Motors {
enum class TrinamicMode : uint8_t {
None = 0, // not for machine defs!
StealthChop = 1,
CoolStep = 2,
StallGuard = 3,
enum TrinamicMode {
StealthChop = 1, // very quiet
CoolStep = 2, // cooler so higher current possible
StallGuard = 3, // coolstep plus stall indication
};
extern EnumItem trinamicModes[];
class TrinamicBase : public StandardStepper {
protected:
uint32_t calc_tstep(float speed, float percent);
uint16_t _driver_part_number; // example: use 2130 for TMC2130
TrinamicMode _homing_mode;
float _r_sense;
bool _has_errors;
bool _disabled;
uint16_t _driver_part_number; // example: use 2130 for TMC2130
bool _disabled = false;
TrinamicMode _mode = StealthChop;
// Configurable
int _homing_mode = StealthChop;
int _run_mode = StealthChop;
float _r_sense = 0.11;
bool _use_enable = false;
float _run_current = 0.25;
float _hold_current = 0.25;
@@ -54,7 +52,9 @@ namespace Motors {
int _stallguard = 0;
bool _stallguardDebugMode = false;
TrinamicMode _mode = TrinamicMode::None;
uint8_t _toff_disable = 0;
uint8_t _toff_stealthchop = 5;
uint8_t _toff_coolstep = 3;
uint8_t get_next_index();
@@ -64,10 +64,15 @@ namespace Motors {
TrinamicBase* link;
static void readSgTask(void*);
const double TRINAMIC_FCLK = 12700000.0; // Internal clock Approx (Hz) used to calculate TSTEP from homing rate
const double fclk = 12700000.0; // Internal clock Approx (Hz) used to calculate TSTEP from homing rate
bool report_open_load(bool ola, bool olb);
bool report_short_to_ground(bool s2ga, bool s2gb);
bool report_over_temp(bool ot, bool otpw);
bool report_short_to_ps(bool vsa, bool vsb);
public:
TrinamicBase(uint16_t partNumber) : StandardStepper(), _driver_part_number(partNumber), _homing_mode(TRINAMIC_HOMING_MODE) {}
TrinamicBase(uint16_t partNumber) : StandardStepper(), _driver_part_number(partNumber) {}
void group(Configuration::HandlerBase& handler) override {
handler.item("r_sense", _r_sense);
@@ -76,6 +81,12 @@ namespace Motors {
handler.item("microsteps", _microsteps);
handler.item("stallguard", _stallguard);
handler.item("stallguardDebugMode", _stallguardDebugMode);
handler.item("toff_disable", _toff_disable);
handler.item("toff_stealthchop", _toff_stealthchop);
handler.item("toff_coolstep", _toff_coolstep);
handler.item("run_mode", _run_mode, trinamicModes);
handler.item("homing_mode", _homing_mode, trinamicModes);
handler.item("use_enable", _use_enable);
StandardStepper::group(handler);
}

View File

@@ -62,8 +62,7 @@ void TMC2130Stepper::switchCSpin(bool state) {
namespace Motors {
TrinamicDriver::TrinamicDriver(uint16_t driver_part_number, int8_t spi_index) :
TrinamicBase(driver_part_number),
_spi_index(spi_index) {}
TrinamicBase(driver_part_number), _spi_index(spi_index) {}
void TrinamicDriver::init() {
_has_errors = false;
@@ -84,7 +83,7 @@ namespace Motors {
// use slower speed if I2S
if (_cs_pin.capabilities().has(Pin::Capabilities::I2S)) {
tmcstepper->setSPISpeed(TRINAMIC_SPI_FREQ);
tmcstepper->setSPISpeed(_spi_freq);
}
link = List;
@@ -174,18 +173,20 @@ namespace Motors {
bool err = false;
// look for errors
if (report_short_to_ground(status)) {
if (report_short_to_ground(status.s2ga, status.s2gb)) {
err = true;
}
if (report_over_temp(status)) {
if (report_over_temp(status.ot, status.otpw)) {
err = true;
}
if (report_short_to_ps(status)) {
if (report_short_to_ps(bit_istrue(status.sr, 12), bit_istrue(status.sr, 13))) {
err = true;
}
// XXX why not report_open_load(status.ola, status.olb) ?
if (err) {
return false;
}
@@ -196,12 +197,11 @@ namespace Motors {
}
/*
o Read setting and send them to the driver. Called at init() and whenever related settings change
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)
*/
*/
void TrinamicDriver::read_settings() {
if (_has_errors) {
return;
@@ -214,8 +214,9 @@ o Read setting and send them to the driver. Called at init() and whenever rel
hold_i_percent = 0;
} else {
hold_i_percent = _hold_current / _run_current;
if (hold_i_percent > 1.0)
if (hold_i_percent > 1.0) {
hold_i_percent = 1.0;
}
}
tmcstepper->microsteps(_microsteps);
@@ -231,7 +232,7 @@ o Read setting and send them to the driver. Called at init() and whenever rel
/*
There are ton of settings. I'll start by grouping then into modes for now.
Many people will want quiet and stallgaurd homing. Stallguard only run in
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 TrinamicDriver::set_mode(bool isHoming) {
@@ -239,7 +240,7 @@ o Read setting and send them to the driver. Called at init() and whenever rel
return;
}
TrinamicMode newMode = isHoming ? TRINAMIC_HOMING_MODE : TRINAMIC_RUN_MODE;
TrinamicMode newMode = static_cast<TrinamicMode>(trinamicModes[isHoming ? _homing_mode : _run_mode].value);
if (newMode == _mode) {
return;
@@ -274,8 +275,6 @@ o Read setting and send them to the driver. Called at init() and whenever rel
tmcstepper->sgt(constrain(_stallguard, -64, 63));
break;
}
default:
info_serial("TRINAMIC_MODE_UNDEFINED");
}
}
@@ -301,14 +300,16 @@ o Read setting and send them to the driver. Called at init() and whenever rel
feedrate,
constrain(_stallguard, -64, 63));
// The bit locations differ somewhat between different chips.
// The layout is very different between 2130 and 2208
TMC2130_n ::DRV_STATUS_t status { 0 }; // a useful struct to access the bits.
status.sr = tmcstepper->DRV_STATUS();
// these only report if there is a fault condition
report_open_load(status);
report_short_to_ground(status);
report_over_temp(status);
report_short_to_ps(status);
report_open_load(status.ola, status.olb);
report_short_to_ground(status.s2ga, status.s2gb);
report_over_temp(status.ot, status.otpw);
report_short_to_ps(bit_istrue(status.sr, 12), bit_istrue(status.sr, 13));
// info_serial("%s Status Register %08x GSTAT %02x",
// reportAxisNameMsg(axis_index(), dual_axis_index()),
@@ -331,68 +332,21 @@ o Read setting and send them to the driver. Called at init() and whenever rel
_disable_pin.write(_disabled);
#ifdef USE_TRINAMIC_ENABLE
if (_disabled) {
tmcstepper->toff(TRINAMIC_TOFF_DISABLE);
} else {
if (_mode == TrinamicMode::StealthChop) {
tmcstepper->toff(TRINAMIC_TOFF_STEALTHCHOP);
if (_use_enable) {
if (_disabled) {
tmcstepper->toff(_toff_disable);
} else {
tmcstepper->toff(TRINAMIC_TOFF_COOLSTEP);
if (_mode == TrinamicMode::StealthChop) {
tmcstepper->toff(_toff_stealthchop);
} else {
tmcstepper->toff(_toff_coolstep);
}
}
}
#endif
// the pin based enable could be added here.
// This would be for individual motors, not the single pin for all motors.
}
// =========== Reporting functions ========================
bool TrinamicDriver::report_open_load(TMC2130_n ::DRV_STATUS_t status) {
if (status.ola || status.olb) {
info_serial("%s Driver Open Load a:%s b:%s",
reportAxisNameMsg(axis_index(), dual_axis_index()),
status.ola ? "Y" : "N",
status.olb ? "Y" : "N");
return true;
}
return false; // no error
}
bool TrinamicDriver::report_short_to_ground(TMC2130_n ::DRV_STATUS_t status) {
if (status.s2ga || status.s2gb) {
info_serial("%s Driver Short Coil a:%s b:%s",
reportAxisNameMsg(axis_index(), dual_axis_index()),
status.s2ga ? "Y" : "N",
status.s2gb ? "Y" : "N");
return true;
}
return false; // no error
}
bool TrinamicDriver::report_over_temp(TMC2130_n ::DRV_STATUS_t status) {
if (status.ot || status.otpw) {
info_serial("%s Driver Temp Warning:%s Fault:%s",
reportAxisNameMsg(axis_index(), dual_axis_index()),
status.otpw ? "Y" : "N",
status.ot ? "Y" : "N");
return true;
}
return false; // no error
}
bool TrinamicDriver::report_short_to_ps(TMC2130_n ::DRV_STATUS_t status) {
// check for short to power supply
if ((status.sr & bit(12)) || (status.sr & bit(13))) {
info_serial("%s Driver Short vsa:%s vsb:%s",
reportAxisNameMsg(axis_index(), dual_axis_index()),
(status.sr & bit(12)) ? "Y" : "N",
(status.sr & bit(13)) ? "Y" : "N");
return true;
}
return false; // no error
}
// Configuration registration
namespace {
MotorFactory::InstanceBuilder<TMC2130> registration_2130("tmc_2130");

View File

@@ -24,36 +24,18 @@
#include <TMCStepper.h> // https://github.com/teemuatlut/TMCStepper
//#define TRINAMIC_MODE_STEALTHCHOP 0 // very quiet
//#define TRINAMIC_MODE_COOLSTEP 1 // everything runs cooler so higher current possible
//#define TRINAMIC_MODE_STALLGUARD 2 // coolstep plus generates stall indication
const float TMC2130_RSENSE_DEFAULT = 0.11f;
const float TMC5160_RSENSE_DEFAULT = 0.075f;
const int NORMAL_TCOOLTHRS = 0xFFFFF; // 20 bit is max
const int NORMAL_THIGH = 0;
const int TRINAMIC_SPI_FREQ = 100000;
// ==== defaults OK to define them in your machine definition ====
#ifndef TRINAMIC_TOFF_DISABLE
# define TRINAMIC_TOFF_DISABLE 0
#endif
#ifndef TRINAMIC_TOFF_STEALTHCHOP
# define TRINAMIC_TOFF_STEALTHCHOP 5
#endif
#ifndef TRINAMIC_TOFF_COOLSTEP
# define TRINAMIC_TOFF_COOLSTEP 3
#endif
namespace Motors {
class TrinamicDriver : public TrinamicBase {
private:
const int _spi_freq = 100000;
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)
int8_t _spi_index;
@@ -63,11 +45,6 @@ namespace Motors {
void trinamic_test_response();
void trinamic_stepper_enable(bool enable);
bool report_open_load(TMC2130_n ::DRV_STATUS_t status);
bool report_short_to_ground(TMC2130_n ::DRV_STATUS_t status);
bool report_over_temp(TMC2130_n ::DRV_STATUS_t status);
bool report_short_to_ps(TMC2130_n ::DRV_STATUS_t status);
protected:
void config_message() override;
@@ -90,7 +67,10 @@ namespace Motors {
StandardStepper::validate();
}
void group(Configuration::HandlerBase& handler) override { TrinamicBase::group(handler); }
void group(Configuration::HandlerBase& handler) override {
handler.item("cs", _cs_pin);
TrinamicBase::group(handler);
}
// Name of the configurable. Must match the name registered in the cpp file.
const char* name() const override { return "trinamic_spi"; }

View File

@@ -34,10 +34,8 @@ namespace Motors {
bool TrinamicUartDriver::_uart_started = false;
/* HW Serial Constructor. */
TrinamicUartDriver::TrinamicUartDriver(uint16_t driver_part_number, uint8_t addr) :
TrinamicBase(driver_part_number), _addr(addr) {}
TrinamicUartDriver::TrinamicUartDriver(uint16_t driver_part_number, uint8_t addr) : TrinamicBase(driver_part_number), _addr(addr) {}
void TrinamicUartDriver::init() {
if (!_uart_started) {
@@ -52,16 +50,16 @@ namespace Motors {
link = List;
List = this;
if (_has_errors) {
return;
}
// Display the stepper library version message once, before the first
// TMC config message. Link is NULL for the first TMC instance.
if (!link) {
info_serial("TMCStepper Library Ver. 0x%06x", TMCSTEPPER_VERSION);
}
if (_has_errors) {
return;
}
config_message();
tmcstepper->begin();
@@ -124,10 +122,10 @@ namespace Motors {
switch (tmcstepper->test_connection()) {
case 1:
info_serial("%s driver test failed. Check connection", reportAxisNameMsg(axis_index(), dual_axis_index()));
info_serial("%s Trinamic driver test failed. Check connection", reportAxisNameMsg(axis_index(), dual_axis_index()));
return false;
case 2:
info_serial("%s driver test failed. Check motor power", reportAxisNameMsg(axis_index(), dual_axis_index()));
info_serial("%s Trinamic driver test failed. Check motor power", reportAxisNameMsg(axis_index(), dual_axis_index()));
return false;
default:
// driver responded, so check for other errors from the DRV_STATUS register
@@ -138,23 +136,25 @@ namespace Motors {
bool err = false;
// look for errors
if (report_short_to_ground(status)) {
if (report_short_to_ground(status.s2ga, status.s2gb)) {
err = true;
}
if (report_over_temp(status)) {
if (report_over_temp(status.ot, status.otpw)) {
err = true;
}
if (report_short_to_ps(status)) {
if (report_short_to_ps(bit_istrue(status.sr, 12), bit_istrue(status.sr, 13))) {
err = true;
}
// XXX why not report_open_load(status.ola, status.olb) ?
if (err) {
return false;
}
info_serial("%s driver test passed", reportAxisNameMsg(axis_index(), dual_axis_index()));
info_serial("%s Trinamic driver test passed", reportAxisNameMsg(axis_index(), dual_axis_index()));
return true;
}
}
@@ -165,6 +165,7 @@ namespace Motors {
uint16_t run (mA)
float hold (as a percentage of run)
*/
// XXX Identical to TrinamicDriver::read_settings()
void TrinamicUartDriver::read_settings() {
if (_has_errors) {
return;
@@ -177,8 +178,9 @@ namespace Motors {
hold_i_percent = 0;
} else {
hold_i_percent = _hold_current / _run_current;
if (hold_i_percent > 1.0)
if (hold_i_percent > 1.0) {
hold_i_percent = 1.0;
}
}
tmcstepper->microsteps(_microsteps);
@@ -187,6 +189,7 @@ namespace Motors {
init_step_dir_pins();
}
// XXX Identical to TrinamicDriver::set_homing_mode()
bool TrinamicUartDriver::set_homing_mode(bool isHoming) {
set_mode(isHoming);
return true;
@@ -194,7 +197,7 @@ namespace Motors {
/*
There are ton of settings. I'll start by grouping then into modes for now.
Many people will want quiet and stallgaurd homing. Stallguard only run in
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) {
@@ -202,7 +205,7 @@ namespace Motors {
return;
}
TrinamicMode newMode = isHoming ? TRINAMIC_HOMING_MODE : TRINAMIC_RUN_MODE;
TrinamicMode newMode = static_cast<TrinamicMode>(trinamicModes[isHoming ? _homing_mode : _run_mode].value);
if (newMode == _mode) {
return;
@@ -244,6 +247,7 @@ namespace Motors {
if (_has_errors) {
return;
}
uint32_t tstep = tmcstepper->TSTEP();
if (tstep == 0xFFFFF || tstep < 1) { // if axis is not moving return
@@ -261,10 +265,10 @@ namespace Motors {
status.sr = tmcstepper->DRV_STATUS();
// these only report if there is a fault condition
report_open_load(status);
report_short_to_ground(status);
report_over_temp(status);
report_short_to_ps(status);
report_open_load(status.ola, status.olb);
report_short_to_ground(status.s2ga, status.s2gb);
report_over_temp(status.ot, status.otpw);
report_short_to_ps(bit_istrue(status.sr, 12), bit_istrue(status.sr, 13));
// info_serial("%s Status Register %08x GSTAT %02x",
// reportAxisNameMsg(axis_index(), dual_axis_index()),
@@ -272,6 +276,7 @@ namespace Motors {
// tmcstepper->GSTAT());
}
// 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 TrinamicUartDriver::set_disable(bool disable) {
@@ -287,68 +292,21 @@ namespace Motors {
_disable_pin.write(_disabled);
#ifdef USE_TRINAMIC_ENABLE
if (_disabled) {
tmcstepper->toff(TRINAMIC_UART_TOFF_DISABLE);
} else {
if (_mode == TrinamicMode::StealthChop) {
tmcstepper->toff(TRINAMIC_UART_TOFF_STEALTHCHOP);
if (_use_enable) {
if (_disabled) {
tmcstepper->toff(_toff_disable);
} else {
tmcstepper->toff(TRINAMIC_UART_TOFF_COOLSTEP);
if (_mode == TrinamicMode::StealthChop) {
tmcstepper->toff(_toff_stealthchop);
} else {
tmcstepper->toff(_toff_coolstep);
}
}
}
#endif
// the pin based enable could be added here.
// This would be for individual motors, not the single pin for all motors.
}
// =========== Reporting functions ========================
bool TrinamicUartDriver::report_open_load(TMC2208_n ::DRV_STATUS_t status) {
if (status.ola || status.olb) {
info_serial("%s Driver Open Load a:%s b:%s",
reportAxisNameMsg(axis_index(), dual_axis_index()),
status.ola ? "Y" : "N",
status.olb ? "Y" : "N");
return true;
}
return false; // no error
}
bool TrinamicUartDriver::report_short_to_ground(TMC2208_n ::DRV_STATUS_t status) {
if (status.s2ga || status.s2gb) {
info_serial("%s Driver Short Coil a:%s b:%s",
reportAxisNameMsg(axis_index(), dual_axis_index()),
status.s2ga ? "Y" : "N",
status.s2gb ? "Y" : "N");
return true;
}
return false; // no error
}
bool TrinamicUartDriver::report_over_temp(TMC2208_n ::DRV_STATUS_t status) {
if (status.ot || status.otpw) {
info_serial("%s Driver Temp Warning:%s Fault:%s",
reportAxisNameMsg(axis_index(), dual_axis_index()),
status.otpw ? "Y" : "N",
status.ot ? "Y" : "N");
return true;
}
return false; // no error
}
bool TrinamicUartDriver::report_short_to_ps(TMC2208_n ::DRV_STATUS_t status) {
// check for short to power supply
if ((status.sr & bit(12)) || (status.sr & bit(13))) {
info_serial("%s Driver Short vsa:%s vsb:%s",
reportAxisNameMsg(axis_index(), dual_axis_index()),
(status.sr & bit(12)) ? "Y" : "N",
(status.sr & bit(13)) ? "Y" : "N");
return true;
}
return false; // no error
}
// Configuration registration
namespace {
MotorFactory::InstanceBuilder<TMC2208> registration_2208("tmc_2208");

View File

@@ -28,20 +28,6 @@
const float TMC2208_RSENSE_DEFAULT = 0.11f;
const float TMC2209_RSENSE_DEFAULT = 0.11f;
// ==== defaults OK to define them in your machine definition ====
#ifndef TRINAMIC_UART_TOFF_DISABLE
# define TRINAMIC_UART_TOFF_DISABLE 0
#endif
#ifndef TRINAMIC_UART_TOFF_STEALTHCHOP
# define TRINAMIC_UART_TOFF_STEALTHCHOP 5
#endif
#ifndef TRINAMIC_UART_TOFF_COOLSTEP
# define TRINAMIC_UART_TOFF_COOLSTEP 3
#endif
#ifndef TMC_UART
# define TMC_UART UART_NUM_2
#endif
@@ -71,11 +57,6 @@ namespace Motors {
void trinamic_test_response();
void trinamic_stepper_enable(bool enable);
bool report_open_load(TMC2208_n ::DRV_STATUS_t status);
bool report_short_to_ground(TMC2208_n ::DRV_STATUS_t status);
bool report_over_temp(TMC2208_n ::DRV_STATUS_t status);
bool report_short_to_ps(TMC2208_n ::DRV_STATUS_t status);
protected:
void config_message() override;