1
0
mirror of https://github.com/bdring/Grbl_Esp32.git synced 2025-08-30 17:49:56 +02:00

Moved most trinamic code to a common base class.

This commit is contained in:
Stefan de Bruijn
2021-06-21 21:27:57 +02:00
parent d68a19e865
commit d26178aeb0
7 changed files with 191 additions and 224 deletions

View File

@@ -31,8 +31,8 @@
#define N_AXIS 4
#define TRINAMIC_UART_RUN_MODE TrinamicUartMode :: StealthChop
#define TRINAMIC_UART_HOMING_MODE TrinamicUartMode :: StallGuard
#define TRINAMIC_RUN_MODE TrinamicMode :: StealthChop
#define TRINAMIC_HOMING_MODE TrinamicMode :: StallGuard
#define TMC_UART UART_NUM_1
#define TMC_UART_RX "gpio.21"

View File

@@ -0,0 +1,73 @@
/*
TrinamicBase.cpp
Part of Grbl_ESP32
2021 - Stefan de Bruijn
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 <http://www.gnu.org/licenses/>.
*/
#include "TrinamicBase.h"
#include "../MachineConfig.h"
#include <atomic>
namespace Motors {
TrinamicBase* TrinamicBase::List = NULL; // a static list of all drivers for stallguard reporting
uint8_t TrinamicBase::get_next_index() {
static uint8_t index = 1; // they start at 1
return index++;
}
// Prints StallGuard data that is useful for tuning.
void TrinamicBase::readSgTask(void* pvParameters) {
auto trinamicDriver = static_cast<TrinamicBase*>(pvParameters);
TickType_t xLastWakeTime;
const TickType_t xreadSg = 200; // in ticks (typically ms)
auto n_axis = config->_axes->_numberAxis;
xLastWakeTime = xTaskGetTickCount(); // Initialise the xLastWakeTime variable with the current time.
while (true) { // don't ever return from this or the task dies
std::atomic_thread_fence(std::memory_order::memory_order_seq_cst); // read fence for settings
if (sys.state == State::Cycle || sys.state == State::Homing || sys.state == State::Jog) {
for (TrinamicBase* p = List; p; p = p->link) {
if (p->_stallguardDebugMode) {
//info_serial("SG:%d", p->_stallguardDebugMode);
p->debug_message();
}
}
} // sys.state
vTaskDelayUntil(&xLastWakeTime, xreadSg);
static UBaseType_t uxHighWaterMark = 0;
#ifdef DEBUG_TASK_STACK
reportTaskStackSize(uxHighWaterMark);
#endif
}
}
// calculate a tstep from a rate
// tstep = TRINAMIC_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;
return static_cast<uint32_t>(tstep);
}
}

View File

@@ -0,0 +1,84 @@
#pragma once
/*
TrinamicBase.h
Part of Grbl_ESP32
2021 - Stefan de Bruijn
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 <http://www.gnu.org/licenses/>.
*/
#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,
};
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;
float _run_current = 0.25;
float _hold_current = 0.25;
int _microsteps = 256;
int _stallguard = 0;
bool _stallguardDebugMode = false;
TrinamicMode _mode = TrinamicMode::None;
uint8_t get_next_index();
// Linked list of Trinamic driver instances, used by the
// StallGuard reporting task.
static TrinamicBase* List;
TrinamicBase* link;
static void readSgTask(void*);
const double TRINAMIC_FCLK = 12700000.0; // Internal clock Approx (Hz) used to calculate TSTEP from homing rate
public:
TrinamicBase(uint16_t partNumber) : StandardStepper(), _driver_part_number(partNumber), _homing_mode(TRINAMIC_HOMING_MODE) {}
void group(Configuration::HandlerBase& handler) override {
handler.item("r_sense", _r_sense);
handler.item("run_current", _run_current);
handler.item("hold_current", _hold_current);
handler.item("microsteps", _microsteps);
handler.item("stallguard", _stallguard);
handler.item("stallguardDebugMode", _stallguardDebugMode);
StandardStepper::group(handler);
}
};
}

View File

@@ -61,18 +61,9 @@ void TMC2130Stepper::switchCSpin(bool state) {
}
namespace Motors {
uint8_t TrinamicDriver::get_next_index() {
#ifdef TRINAMIC_DAISY_CHAIN
static uint8_t index = 1; // they start at 1
return index++;
#else
return -1;
#endif
}
TrinamicDriver* TrinamicDriver::List = NULL;
TrinamicDriver::TrinamicDriver(uint16_t driver_part_number, int8_t spi_index) :
StandardStepper(), _homing_mode(TRINAMIC_HOMING_MODE), _driver_part_number(driver_part_number), _spi_index(spi_index) {}
TrinamicBase(driver_part_number),
_spi_index(spi_index) {}
void TrinamicDriver::init() {
_has_errors = false;
@@ -325,17 +316,6 @@ o Read setting and send them to the driver. Called at init() and whenever rel
// tmcstepper->GSTAT());
}
// calculate a tstep from a rate
// tstep = TRINAMIC_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 TrinamicDriver::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;
return static_cast<uint32_t>(tstep);
}
// 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 TrinamicDriver::set_disable(bool disable) {
@@ -366,35 +346,6 @@ o Read setting and send them to the driver. Called at init() and whenever rel
// This would be for individual motors, not the single pin for all motors.
}
// Prints StallGuard data that is useful for tuning.
void TrinamicDriver::readSgTask(void* pvParameters) {
auto trinamicDriver = static_cast<TrinamicDriver*>(pvParameters);
TickType_t xLastWakeTime;
const TickType_t xreadSg = 200; // in ticks (typically ms)
auto n_axis = config->_axes->_numberAxis;
xLastWakeTime = xTaskGetTickCount(); // Initialise the xLastWakeTime variable with the current time.
while (true) { // don't ever return from this or the task dies
std::atomic_thread_fence(std::memory_order::memory_order_seq_cst); // read fence for settings
if (sys.state == State::Cycle || sys.state == State::Homing || sys.state == State::Jog) {
for (TrinamicDriver* p = List; p; p = p->link) {
if (p->_stallguardDebugMode) {
//info_serial("SG:%d", p->_stallguardDebugMode);
p->debug_message();
}
}
} // sys.state
vTaskDelayUntil(&xLastWakeTime, xreadSg);
static UBaseType_t uxHighWaterMark = 0;
#ifdef DEBUG_TASK_STACK
reportTaskStackSize(uxHighWaterMark);
#endif
}
}
// =========== Reporting functions ========================
bool TrinamicDriver::report_open_load(TMC2130_n ::DRV_STATUS_t status) {

View File

@@ -20,7 +20,7 @@
*/
#include "Motor.h"
#include "StandardStepper.h"
#include "TrinamicBase.h"
#include <TMCStepper.h> // https://github.com/teemuatlut/TMCStepper
@@ -36,18 +36,8 @@ const int NORMAL_THIGH = 0;
const int TRINAMIC_SPI_FREQ = 100000;
const double TRINAMIC_FCLK = 12700000.0; // Internal clock Approx (Hz) used to calculate TSTEP from homing rate
// ==== defaults OK to define them in your machine definition ====
#ifndef TRINAMIC_RUN_MODE
# define TRINAMIC_RUN_MODE TrinamicMode ::StealthChop
#endif
#ifndef TRINAMIC_HOMING_MODE
# define TRINAMIC_HOMING_MODE TRINAMIC_RUN_MODE
#endif
#ifndef TRINAMIC_TOFF_DISABLE
# define TRINAMIC_TOFF_DISABLE 0
#endif
@@ -62,51 +52,22 @@ const double TRINAMIC_FCLK = 12700000.0; // Internal clock Approx (Hz) used to
namespace Motors {
enum class TrinamicMode : uint8_t {
None = 0, // not for machine defs!
StealthChop = 1,
CoolStep = 2,
StallGuard = 3,
};
class TrinamicDriver : public StandardStepper {
class TrinamicDriver : public TrinamicBase {
private:
uint32_t calc_tstep(float speed, float percent);
TMC2130Stepper* tmcstepper; // all other driver types are subclasses of this one
TrinamicMode _homing_mode;
Pin _cs_pin; // The chip select pin (can be the same for daisy chain)
uint16_t _driver_part_number; // example: use 2130 for TMC2130
float _r_sense;
Pin _cs_pin; // The chip select pin (can be the same for daisy chain)
int8_t _spi_index;
bool _has_errors;
bool _disabled;
float _run_current = 0.25;
float _hold_current = 0.25;
int _microsteps = 256;
int _stallguard = 0;
bool _stallguardDebugMode = false;
TrinamicMode _mode = TrinamicMode::None;
bool test();
void set_mode(bool isHoming);
void trinamic_test_response();
void trinamic_stepper_enable(bool enable);
bool test();
void set_mode(bool isHoming);
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);
uint8_t get_next_index();
// Linked list of Trinamic driver instances, used by the
// StallGuard reporting task.
static TrinamicDriver* List;
TrinamicDriver* link;
static void readSgTask(void*);
protected:
void config_message() override;
@@ -129,17 +90,7 @@ namespace Motors {
StandardStepper::validate();
}
void group(Configuration::HandlerBase& handler) override {
handler.item("spi_cs", _cs_pin);
handler.item("r_sense", _r_sense);
handler.item("run_current", _run_current);
handler.item("hold_current", _hold_current);
handler.item("microsteps", _microsteps);
handler.item("stallguard", _stallguard);
handler.item("stallguardDebugMode", _stallguardDebugMode);
StandardStepper::group(handler);
}
void group(Configuration::HandlerBase& handler) override { 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,16 +34,10 @@ namespace Motors {
bool TrinamicUartDriver::_uart_started = false;
TrinamicUartDriver* TrinamicUartDriver::List = NULL; // a static list of all drivers for stallguard reporting
uint8_t TrinamicUartDriver::get_next_index() {
static uint8_t index = 1; // they start at 1
return index++;
}
/* HW Serial Constructor. */
TrinamicUartDriver::TrinamicUartDriver(uint16_t driver_part_number, uint8_t addr) :
StandardStepper(), _driver_part_number(driver_part_number), _addr(addr) {}
TrinamicBase(driver_part_number), _addr(addr) {}
void TrinamicUartDriver::init() {
if (!_uart_started) {
@@ -208,7 +202,7 @@ namespace Motors {
return;
}
TrinamicUartMode newMode = isHoming ? TRINAMIC_UART_HOMING_MODE : TRINAMIC_UART_RUN_MODE;
TrinamicMode newMode = isHoming ? TRINAMIC_HOMING_MODE : TRINAMIC_RUN_MODE;
if (newMode == _mode) {
return;
@@ -216,18 +210,18 @@ namespace Motors {
_mode = newMode;
switch (_mode) {
case TrinamicUartMode ::StealthChop:
case TrinamicMode ::StealthChop:
//info_serial("StealthChop");
tmcstepper->en_spreadCycle(false);
tmcstepper->pwm_autoscale(true);
break;
case TrinamicUartMode ::CoolStep:
case TrinamicMode ::CoolStep:
//info_serial("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 TrinamicUartMode ::StallGuard: //TODO: check all configurations for stallguard
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;
@@ -278,17 +272,6 @@ namespace Motors {
// tmcstepper->GSTAT());
}
// calculate a tstep from a rate
// tstep = TRINAMIC_UART_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 TrinamicUartDriver::calc_tstep(float speed, float percent) {
double tstep = speed / 60.0 * config->_axes->_axis[axis_index()]->_stepsPerMm * (256.0 / _microsteps);
tstep = TRINAMIC_UART_FCLK / tstep * percent / 100.0;
return static_cast<uint32_t>(tstep);
}
// 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) {
@@ -308,7 +291,7 @@ namespace Motors {
if (_disabled) {
tmcstepper->toff(TRINAMIC_UART_TOFF_DISABLE);
} else {
if (_mode == TrinamicUartMode::StealthChop) {
if (_mode == TrinamicMode::StealthChop) {
tmcstepper->toff(TRINAMIC_UART_TOFF_STEALTHCHOP);
} else {
tmcstepper->toff(TRINAMIC_UART_TOFF_COOLSTEP);
@@ -319,33 +302,6 @@ namespace Motors {
// This would be for individual motors, not the single pin for all motors.
}
// Prints StallGuard data that is useful for tuning.
void TrinamicUartDriver::readSgTask(void* pvParameters) {
TickType_t xLastWakeTime;
const TickType_t xreadSg = 200; // in ticks (typically ms)
auto n_axis = config->_axes->_numberAxis;
xLastWakeTime = xTaskGetTickCount(); // Initialise the xLastWakeTime variable with the current time.
while (true) { // don't ever return from this or the task dies
std::atomic_thread_fence(std::memory_order::memory_order_seq_cst); // read fence for settings
if (sys.state == State::Cycle || sys.state == State::Homing || sys.state == State::Jog) {
for (TrinamicUartDriver* p = List; p; p = p->link) {
if (p->_stallguardDebugMode) {
//info_serial("SG:%d", _stallguardDebugMode);
p->debug_message();
}
}
} // sys.state
vTaskDelayUntil(&xLastWakeTime, xreadSg);
static UBaseType_t uxHighWaterMark = 0;
#ifdef DEBUG_TASK_STACK
reportTaskStackSize(uxHighWaterMark);
#endif
}
}
// =========== Reporting functions ========================
bool TrinamicUartDriver::report_open_load(TMC2208_n ::DRV_STATUS_t status) {
@@ -395,7 +351,7 @@ namespace Motors {
// Configuration registration
namespace {
MotorFactory::InstanceBuilder<TMC2008> registration_2008("tmc_2008");
MotorFactory::InstanceBuilder<TMC2009> registration_2009("tmc_2009");
MotorFactory::InstanceBuilder<TMC2208> registration_2208("tmc_2208");
MotorFactory::InstanceBuilder<TMC2209> registration_2209("tmc_2209");
}
}

View File

@@ -20,7 +20,7 @@
*/
#include "Motor.h"
#include "StandardStepper.h"
#include "TrinamicBase.h"
#include "../Uart.h"
#include <TMCStepper.h> // https://github.com/teemuatlut/TMCStepper
@@ -28,18 +28,8 @@
const float TMC2208_RSENSE_DEFAULT = 0.11f;
const float TMC2209_RSENSE_DEFAULT = 0.11f;
const double TRINAMIC_UART_FCLK = 12700000.0; // Internal clock Approx (Hz) used to calculate TSTEP from homing rate
// ==== defaults OK to define them in your machine definition ====
#ifndef TRINAMIC_UART_RUN_MODE
# define TRINAMIC_UART_RUN_MODE TrinamicUartMode ::StealthChop
#endif
#ifndef TRINAMIC_UART_HOMING_MODE
# define TRINAMIC_UART_HOMING_MODE TRINAMIC_UART_RUN_MODE
#endif
#ifndef TRINAMIC_UART_TOFF_DISABLE
# define TRINAMIC_UART_TOFF_DISABLE 0
#endif
@@ -70,51 +60,22 @@ extern Uart tmc_serial;
namespace Motors {
enum class TrinamicUartMode : uint8_t {
None = 0, // not for machine defs!
StealthChop = 1,
CoolStep = 2,
StallGuard = 3,
};
class TrinamicUartDriver : public StandardStepper {
class TrinamicUartDriver : public TrinamicBase {
private:
static bool _uart_started;
uint32_t calc_tstep(float speed, float percent);
TMC2209Stepper* tmcstepper; // all other driver types are subclasses of this one
TMC2209Stepper* tmcstepper; // all other driver types are subclasses of this one
TrinamicUartMode _homing_mode;
uint16_t _driver_part_number; // example: use 2209 for TMC2209
float _r_sense;
bool _has_errors;
bool _disabled;
float _run_current = 0.25;
float _hold_current = 0.25;
int _microsteps = 256;
int _stallguard = 0;
bool _stallguardDebugMode = false;
TrinamicUartMode _mode = TrinamicUartMode::None;
bool test();
void set_mode(bool isHoming);
void trinamic_test_response();
void trinamic_stepper_enable(bool enable);
bool test();
void set_mode(bool isHoming);
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);
uint8_t get_next_index();
// Linked list of Trinamic driver instances, used by the
// StallGuard reporting task. TODO: verify if this is really used/useful.
static TrinamicUartDriver* List;
TrinamicUartDriver* link;
static void readSgTask(void*);
protected:
void config_message() override;
@@ -137,34 +98,25 @@ namespace Motors {
// Configuration handlers:
void validate() const override { StandardStepper::validate(); }
void group(Configuration::HandlerBase& handler) override {
handler.item("r_sense", _r_sense);
handler.item("run_current", _run_current);
handler.item("hold_current", _hold_current);
handler.item("microsteps", _microsteps);
handler.item("stallguard", _stallguard);
handler.item("stallguardDebugMode", _stallguardDebugMode);
StandardStepper::group(handler);
}
void group(Configuration::HandlerBase& handler) override { TrinamicBase::group(handler); }
// Name of the configurable. Must match the name registered in the cpp file.
const char* name() const override { return "trinamic_uart"; }
};
class TMC2008 : public TrinamicUartDriver {
class TMC2208 : public TrinamicUartDriver {
public:
TMC2008() : TrinamicUartDriver(2008) {}
TMC2208() : TrinamicUartDriver(2208) {}
// Name of the configurable. Must match the name registered in the cpp file.
const char* name() const override { return "tmc_2008"; }
const char* name() const override { return "tmc_2208"; }
};
class TMC2009 : public TrinamicUartDriver {
class TMC2209 : public TrinamicUartDriver {
public:
TMC2009() : TrinamicUartDriver(2009) {}
TMC2209() : TrinamicUartDriver(2209) {}
// Name of the configurable. Must match the name registered in the cpp file.
const char* name() const override { return "tmc_2009"; }
const char* name() const override { return "tmc_2209"; }
};
}