1
0
mirror of https://github.com/bdring/Grbl_Esp32.git synced 2025-09-01 02:21:46 +02:00

TMC2209 Stallguard (#748)

* TMC2209 Stallguard

- Added StallGuard homing support to TMC2209 (UART)
- Killed off TMC2208 for now. Too many conflicts with TMC2209. Will return with Diamond motor class hierarchy
- Increase StallGuard setting range for TMC2209. Constrianed in each class to actual limits
- Added a machine def to test TMC2209

* Update build date
This commit is contained in:
bdring
2021-01-21 19:32:22 -06:00
committed by GitHub
parent c8f4075565
commit 6c1cc3c4d1
6 changed files with 152 additions and 36 deletions

View File

@@ -23,7 +23,7 @@
// Grbl versioning system // Grbl versioning system
const char* const GRBL_VERSION = "1.3a"; const char* const GRBL_VERSION = "1.3a";
const char* const GRBL_VERSION_BUILD = "20210101"; const char* const GRBL_VERSION_BUILD = "20210121";
//#include <sdkconfig.h> //#include <sdkconfig.h>
#include <Arduino.h> #include <Arduino.h>

View File

@@ -0,0 +1,89 @@
#pragma once
// clang-format off
/*
TMC2209_4x.h
https://github.com/FYSETC/FYSETC-E4
2020-12-29 B. Dring
This is a machine definition file to use the FYSTEC E4 3D Printer controller
This is a 4 motor controller. This is setup for XYZA, but XYYZ, could also be used.
There are 5 inputs
The controller has outputs for a Fan, Hotbed and Extruder. There are mapped to
spindle, mist and flood coolant to drive an external relay.
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 <http://www.gnu.org/licenses/>.
*/
#define MACHINE_NAME "TMC2209 4x Controller"
#define N_AXIS 4
#define TRINAMIC_UART_RUN_MODE TrinamicUartMode :: StealthChop
#define TRINAMIC_UART_HOMING_MODE TrinamicUartMode :: StallGuard
#define TMC_UART UART_NUM_1
#define TMC_UART_RX GPIO_NUM_21
#define TMC_UART_TX GPIO_NUM_22
#define X_TRINAMIC_DRIVER 2209
#define X_STEP_PIN GPIO_NUM_26
#define X_DIRECTION_PIN GPIO_NUM_27
#define X_RSENSE TMC2209_RSENSE_DEFAULT
#define X_DRIVER_ADDRESS 0
#define DEFAULT_X_MICROSTEPS 16
#define Y_TRINAMIC_DRIVER 2209
#define Y_STEP_PIN GPIO_NUM_33
#define Y_DIRECTION_PIN GPIO_NUM_32
#define Y_RSENSE TMC2209_RSENSE_DEFAULT
#define Y_DRIVER_ADDRESS 1
#define DEFAULT_Y_MICROSTEPS 16
#define Z_TRINAMIC_DRIVER 2209
#define Z_STEP_PIN GPIO_NUM_2
#define Z_DIRECTION_PIN GPIO_NUM_4
#define Z_RSENSE TMC2209_RSENSE_DEFAULT
#define Z_DRIVER_ADDRESS 2
#define DEFAULT_Z_MICROSTEPS 16
#define A_TRINAMIC_DRIVER 2209
#define A_STEP_PIN GPIO_NUM_16
#define A_DIRECTION_PIN GPIO_NUM_17
#define A_RSENSE TMC2209_RSENSE_DEFAULT
#define A_DRIVER_ADDRESS 3
#define DEFAULT_A_MICROSTEPS 16
#define X_LIMIT_PIN GPIO_NUM_36
#define Y_LIMIT_PIN GPIO_NUM_39
#define Z_LIMIT_PIN GPIO_NUM_34
#define PROBE_PIN GPIO_NUM_35
// OK to comment out to use pin for other features
#define STEPPERS_DISABLE_PIN GPIO_NUM_25
// https://github.com/bdring/6-Pack_CNC_Controller/wiki/4x-5V-Buffered-Output-Module
// https://github.com/bdring/6-Pack_CNC_Controller/wiki/Quad-MOSFET-Module
#define USER_DIGITAL_PIN_0 GPIO_NUM_14 // M62 M63
#define USER_DIGITAL_PIN_1 GPIO_NUM_13 // M62 M63
#define USER_DIGITAL_PIN_2 GPIO_NUM_15 // M62 M63
#define USER_DIGITAL_PIN_3 GPIO_NUM_12 // M62 M63
// ===================== defaults ======================
// https://github.com/bdring/Grbl_Esp32/wiki/Setting-Defaults
#define DEFAULT_INVERT_PROBE_PIN 1

View File

@@ -258,7 +258,7 @@ namespace Motors {
tmcstepper->THIGH(calc_tstep(homing_feed_rate->get(), 60.0)); tmcstepper->THIGH(calc_tstep(homing_feed_rate->get(), 60.0));
tmcstepper->sfilt(1); tmcstepper->sfilt(1);
tmcstepper->diag1_stall(true); // stallguard i/o is on diag1 tmcstepper->diag1_stall(true); // stallguard i/o is on diag1
tmcstepper->sgt(axis_settings[_axis_index]->stallguard->get()); tmcstepper->sgt(constrain(axis_settings[_axis_index]->stallguard->get(), -64, 63));
break; break;
default: default:
grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "TRINAMIC_MODE_UNDEFINED"); grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "TRINAMIC_MODE_UNDEFINED");
@@ -286,7 +286,7 @@ namespace Motors {
tmcstepper->stallguard(), tmcstepper->stallguard(),
tmcstepper->sg_result(), tmcstepper->sg_result(),
feedrate, feedrate,
axis_settings[_axis_index]->stallguard->get()); constrain(axis_settings[_axis_index]->stallguard->get(), -64, 63));
TMC2130_n ::DRV_STATUS_t status { 0 }; // a useful struct to access the bits. TMC2130_n ::DRV_STATUS_t status { 0 }; // a useful struct to access the bits.
status.sr = tmcstepper->DRV_STATUS(); status.sr = tmcstepper->DRV_STATUS();

View File

@@ -98,7 +98,7 @@ namespace Motors {
private: private:
uint32_t calc_tstep(float speed, float percent); //TODO: see if this is useful/used. uint32_t calc_tstep(float speed, float percent); //TODO: see if this is useful/used.
TMC2208Stepper* tmcstepper; // all other driver types are subclasses of this one TMC2209Stepper* tmcstepper; // all other driver types are subclasses of this one
TrinamicUartMode _homing_mode; TrinamicUartMode _homing_mode;
uint16_t _driver_part_number; // example: use 2209 for TMC2209 uint16_t _driver_part_number; // example: use 2209 for TMC2209
float _r_sense; float _r_sense;

View File

@@ -7,6 +7,9 @@
2020 - The Ant Team 2020 - The Ant Team
2020 - Bart Dring 2020 - Bart Dring
TMC2209 Datasheet
https://www.trinamic.com/fileadmin/assets/Products/ICs_Documents/TMC2209_Datasheet_V103.pdf
Grbl is free software: you can redistribute it and/or modify Grbl is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
@@ -27,6 +30,8 @@ HardwareSerial tmc_serial(TMC_UART);
namespace Motors { namespace Motors {
TrinamicUartDriver* TrinamicUartDriver::List = NULL; // a static ist of all drivers for stallguard reporting
/* HW Serial Constructor. */ /* HW Serial Constructor. */
TrinamicUartDriver::TrinamicUartDriver( TrinamicUartDriver::TrinamicUartDriver(
uint8_t axis_index, uint8_t step_pin, uint8_t dir_pin, uint8_t disable_pin, uint16_t driver_part_number, float r_sense, uint8_t addr) : uint8_t axis_index, uint8_t step_pin, uint8_t dir_pin, uint8_t disable_pin, uint16_t driver_part_number, float r_sense, uint8_t addr) :
@@ -40,13 +45,13 @@ namespace Motors {
tmc_serial.begin(115200, SERIAL_8N1, TMC_UART_RX, TMC_UART_TX); tmc_serial.begin(115200, SERIAL_8N1, TMC_UART_RX, TMC_UART_TX);
tmc_serial.setRxBufferSize(128); tmc_serial.setRxBufferSize(128);
hw_serial_init(); hw_serial_init();
link = List;
List = this;
} }
void TrinamicUartDriver::hw_serial_init() { void TrinamicUartDriver::hw_serial_init() {
if (_driver_part_number == 2208) if (_driver_part_number == 2209)
// TMC 2208 does not use address, this field is 0
tmcstepper = new TMC2208Stepper(&tmc_serial, _r_sense);
else if (_driver_part_number == 2209)
tmcstepper = new TMC2209Stepper(&tmc_serial, _r_sense, addr); tmcstepper = new TMC2209Stepper(&tmc_serial, _r_sense, addr);
else { else {
grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Unsupported Trinamic motor p/n:%d", _driver_part_number); grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Unsupported Trinamic motor p/n:%d", _driver_part_number);
@@ -73,6 +78,20 @@ namespace Motors {
read_settings(); read_settings();
set_mode(false); set_mode(false);
} }
// After initializing all of the TMC drivers, create a task to
// display StallGuard data. List == this for the final instance.
if (List == this) {
xTaskCreatePinnedToCore(readSgTask, // task
"readSgTask", // name for task
4096, // size of task stack
NULL, // parameters
1, // priority
NULL,
SUPPORT_TASK_CORE // must run the task on same core
// core
);
}
} }
/* /*
@@ -192,38 +211,27 @@ namespace Motors {
if (newMode == _mode) { if (newMode == _mode) {
return; return;
} }
_mode = newMode; _mode = newMode;
switch (_mode) { switch (_mode) {
case TrinamicUartMode ::StealthChop: case TrinamicUartMode ::StealthChop:
//grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "StealthChop"); grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "StealthChop");
// tmcstepper->en_pwm_mode(true); //TODO: check if this is present in TMC2208/09
tmcstepper->en_spreadCycle(false); tmcstepper->en_spreadCycle(false);
tmcstepper->pwm_autoscale(true); tmcstepper->pwm_autoscale(true);
// if (_driver_part_number == 2209) {
// tmcstepper->diag1_stall(false); //TODO: check the equivalent in TMC2209
// }
break; break;
case TrinamicUartMode ::CoolStep: case TrinamicUartMode ::CoolStep:
//grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Coolstep"); grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Coolstep");
// tmcstepper->en_pwm_mode(false); //TODO: check if this is present in TMC2208/09 // tmcstepper->en_pwm_mode(false); //TODO: check if this is present in TMC2208/09
tmcstepper->en_spreadCycle(true); tmcstepper->en_spreadCycle(true);
tmcstepper->pwm_autoscale(false); tmcstepper->pwm_autoscale(false);
if (_driver_part_number == 2209) {
// tmcstepper->TCOOLTHRS(NORMAL_TCOOLTHRS); // when to turn on coolstep //TODO: add this solving compilation issue.
// tmcstepper->THIGH(NORMAL_THIGH); //TODO: this does not exist in TMC2208/09. verify and eventually remove.
}
break; break;
case TrinamicUartMode ::StallGuard: //TODO: check all configurations for stallguard case TrinamicUartMode ::StallGuard: //TODO: check all configurations for stallguard
//grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Stallguard"); grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Stallguard");
// tmcstepper->en_pwm_mode(false); //TODO: check if this is present in TMC2208/09
tmcstepper->en_spreadCycle(false); tmcstepper->en_spreadCycle(false);
tmcstepper->pwm_autoscale(false); tmcstepper->pwm_autoscale(false);
// tmcstepper->TCOOLTHRS(calc_tstep(homing_feed_rate->get(), 150.0)); tmcstepper->TCOOLTHRS(calc_tstep(homing_feed_rate->get(), 150.0));
// tmcstepper->THIGH(calc_tstep(homing_feed_rate->get(), 60.0)); tmcstepper->SGTHRS(constrain(axis_settings[_axis_index]->stallguard->get(),0,255));
// tmcstepper->sfilt(1);
// tmcstepper->diag1_stall(true); // stallguard i/o is on diag1
// tmcstepper->sgt(axis_settings[_axis_index]->stallguard->get());
break; break;
default: default:
grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Unknown Trinamic mode:d", _mode); grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Unknown Trinamic mode:d", _mode);
@@ -246,10 +254,9 @@ namespace Motors {
grbl_msg_sendf(CLIENT_SERIAL, grbl_msg_sendf(CLIENT_SERIAL,
MsgLevel::Info, MsgLevel::Info,
"%s Stallguard %d SG_Val: %04d Rate: %05.0f mm/min SG_Setting:%d", "%s SG_Val: %04d Rate: %05.0f mm/min SG_Setting:%d",
reportAxisNameMsg(_axis_index, _dual_axis_index), reportAxisNameMsg(_axis_index, _dual_axis_index),
0, // tmcstepper->stallguard(), // TODO: add this again solving the compilation issues tmcstepper->SG_RESULT(), // tmcstepper->sg_result(),
0, // tmcstepper->sg_result(),
feedrate, feedrate,
axis_settings[_axis_index]->stallguard->get()); axis_settings[_axis_index]->stallguard->get());
@@ -261,13 +268,6 @@ namespace Motors {
report_short_to_ground(status); report_short_to_ground(status);
report_over_temp(status); report_over_temp(status);
report_short_to_ps(status); report_short_to_ps(status);
// grbl_msg_sendf(CLIENT_SERIAL,
// MsgLevel::Info,
// "%s Status Register %08x GSTAT %02x",
// reportAxisNameMsg(_axis_index, _dual_axis_index),
// status.sr,
// tmcstepper->GSTAT());
} }
// calculate a tstep from a rate // calculate a tstep from a rate
@@ -367,4 +367,31 @@ namespace Motors {
return false; // no error return false; // no error
} }
// 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 = number_axis->get();
xLastWakeTime = xTaskGetTickCount(); // Initialise the xLastWakeTime variable with the current time.
while (true) { // don't ever return from this or the task dies
if (stallguard_debug_mask->get() != 0) {
if (sys.state == State::Cycle || sys.state == State::Homing || sys.state == State::Jog) {
for (TrinamicUartDriver* p = List; p; p = p->link) {
if (bitnum_istrue(stallguard_debug_mask->get(), p->_axis_index)) {
//grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "SG:%d", stallguard_debug_mask->get());
p->debug_message();
}
}
} // sys.state
} // if mask
vTaskDelayUntil(&xLastWakeTime, xreadSg);
static UBaseType_t uxHighWaterMark = 0;
#ifdef DEBUG_TASK_STACK
reportTaskStackSize(uxHighWaterMark);
#endif
}
}
} }

View File

@@ -258,7 +258,7 @@ void make_settings() {
for (axis = MAX_N_AXIS - 1; axis >= 0; axis--) { for (axis = MAX_N_AXIS - 1; axis >= 0; axis--) {
def = &axis_defaults[axis]; def = &axis_defaults[axis];
auto setting = auto setting =
new IntSetting(EXTENDED, WG, makeGrblName(axis, 170), makename(def->name, "StallGuard"), def->stallguard, -64, 63, postMotorSetting); new IntSetting(EXTENDED, WG, makeGrblName(axis, 170), makename(def->name, "StallGuard"), def->stallguard, -64, 255, postMotorSetting);
setting->setAxis(axis); setting->setAxis(axis);
axis_settings[axis]->stallguard = setting; axis_settings[axis]->stallguard = setting;
} }