Improved STMicro L64XX stepper driver support (#16452)
This commit is contained in:
@ -47,8 +47,8 @@
|
||||
|
||||
#include "../../lcd/ultralcd.h"
|
||||
|
||||
#if HAS_DRIVER(L6470) // set L6470 absolute position registers to counts
|
||||
#include "../../libs/L6470/L6470_Marlin.h"
|
||||
#if HAS_L64XX // set L6470 absolute position registers to counts
|
||||
#include "../../libs/L64XX/L64XX_Marlin.h"
|
||||
#endif
|
||||
|
||||
#define DEBUG_OUT ENABLED(DEBUG_LEVELING_FEATURE)
|
||||
@ -526,11 +526,18 @@ void GcodeSuite::G28(const bool always_home_all) {
|
||||
|
||||
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("<<< G28");
|
||||
|
||||
#if HAS_DRIVER(L6470)
|
||||
#if HAS_L64XX
|
||||
// Set L6470 absolute position registers to counts
|
||||
for (uint8_t j = 1; j <= L6470::chain[0]; j++) {
|
||||
const uint8_t cv = L6470::chain[j];
|
||||
L6470.set_param(cv, L6470_ABS_POS, stepper.position((AxisEnum)L6470.axis_xref[cv]));
|
||||
// constexpr *might* move this to PROGMEM.
|
||||
// If not, this will need a PROGMEM directive and an accessor.
|
||||
static constexpr AxisEnum L6470_axis_xref[MAX_L6470] = {
|
||||
X_AXIS, Y_AXIS, Z_AXIS,
|
||||
X_AXIS, Y_AXIS, Z_AXIS, Z_AXIS,
|
||||
E_AXIS, E_AXIS, E_AXIS, E_AXIS, E_AXIS, E_AXIS
|
||||
};
|
||||
for (uint8_t j = 1; j <= L64XX::chain[0]; j++) {
|
||||
const uint8_t cv = L64XX::chain[j];
|
||||
L64xxManager.set_param((L64XX_axis_t)cv, L6470_ABS_POS, stepper.position(L6470_axis_xref[cv]));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -22,36 +22,64 @@
|
||||
|
||||
#include "../../../inc/MarlinConfig.h"
|
||||
|
||||
#if HAS_DRIVER(L6470)
|
||||
#if HAS_L64XX
|
||||
|
||||
#include "../../gcode.h"
|
||||
#include "../../../libs/L6470/L6470_Marlin.h"
|
||||
#include "../../../libs/L64XX/L64XX_Marlin.h"
|
||||
#include "../../../module/stepper/indirection.h"
|
||||
|
||||
inline void echo_yes_no(const bool yes) { serialprintPGM(yes ? PSTR(" YES") : PSTR(" NO ")); }
|
||||
void echo_yes_no(const bool yes);
|
||||
|
||||
void L6470_status_decode(const uint16_t status, const uint8_t axis) {
|
||||
if (L6470.spi_abort) return; // don't do anything if set_directions() has occurred
|
||||
L6470.say_axis(axis);
|
||||
inline void L6470_say_status(const L64XX_axis_t axis) {
|
||||
if (L64xxManager.spi_abort) return;
|
||||
const L64XX_Marlin::L64XX_shadow_t &sh = L64xxManager.shadow;
|
||||
L64xxManager.get_status(axis);
|
||||
L64xxManager.say_axis(axis);
|
||||
#if ENABLED(L6470_CHITCHAT)
|
||||
char temp_buf[20];
|
||||
sprintf_P(temp_buf, PSTR(" status: %4x "), status);
|
||||
sprintf_P(temp_buf, PSTR(" status: %4x "), sh.STATUS_AXIS_RAW);
|
||||
SERIAL_ECHO(temp_buf);
|
||||
print_bin(status);
|
||||
print_bin(sh.STATUS_AXIS_RAW);
|
||||
switch (sh.STATUS_AXIS_LAYOUT) {
|
||||
case L6470_STATUS_LAYOUT: serialprintPGM(PSTR(" L6470")); break;
|
||||
case L6474_STATUS_LAYOUT: serialprintPGM(PSTR(" L6474")); break;
|
||||
case L6480_STATUS_LAYOUT: serialprintPGM(PSTR(" L6480/powerSTEP01")); break;
|
||||
}
|
||||
#endif
|
||||
SERIAL_ECHOPGM("\n...OUTPUT: ");
|
||||
serialprintPGM(status & STATUS_HIZ ? PSTR("OFF") : PSTR("ON "));
|
||||
SERIAL_ECHOPGM(" BUSY: "); echo_yes_no(!(status & STATUS_BUSY));
|
||||
serialprintPGM(sh.STATUS_AXIS & STATUS_HIZ ? PSTR("OFF") : PSTR("ON "));
|
||||
SERIAL_ECHOPGM(" BUSY: "); echo_yes_no((sh.STATUS_AXIS & STATUS_BUSY) == 0);
|
||||
SERIAL_ECHOPGM(" DIR: ");
|
||||
serialprintPGM((((status & STATUS_DIR) >> 4) ^ L6470.index_to_dir[axis]) ? PSTR("FORWARD") : PSTR("REVERSE"));
|
||||
SERIAL_ECHOPGM(" Last Command: ");
|
||||
if (status & STATUS_WRONG_CMD) SERIAL_ECHOPGM("IN");
|
||||
SERIAL_ECHOPGM("VALID ");
|
||||
serialprintPGM(status & STATUS_NOTPERF_CMD ? PSTR("Not PERFORMED") : PSTR("COMPLETED "));
|
||||
SERIAL_ECHOPAIR("\n...THERMAL: ", !(status & STATUS_TH_SD) ? "SHUTDOWN" : !(status & STATUS_TH_WRN) ? "WARNING " : "OK ");
|
||||
SERIAL_ECHOPGM(" OVERCURRENT:"); echo_yes_no(!(status & STATUS_OCD));
|
||||
SERIAL_ECHOPGM(" STALL:"); echo_yes_no(!(status & STATUS_STEP_LOSS_A) || !(status & STATUS_STEP_LOSS_B));
|
||||
SERIAL_ECHOPGM(" STEP-CLOCK MODE:"); echo_yes_no(status & STATUS_SCK_MOD);
|
||||
serialprintPGM((((sh.STATUS_AXIS & STATUS_DIR) >> 4) ^ L64xxManager.index_to_dir[axis]) ? PSTR("FORWARD") : PSTR("REVERSE"));
|
||||
if (sh.STATUS_AXIS_LAYOUT == L6480_STATUS_LAYOUT) {
|
||||
SERIAL_ECHOPGM(" Last Command: ");
|
||||
if (sh.STATUS_AXIS & sh.STATUS_AXIS_WRONG_CMD) SERIAL_ECHOPGM("VALID");
|
||||
else SERIAL_ECHOPGM("ERROR");
|
||||
SERIAL_ECHOPGM("\n...THERMAL: ");
|
||||
switch ((sh.STATUS_AXIS & (sh.STATUS_AXIS_TH_SD | sh.STATUS_AXIS_TH_WRN)) >> 11) {
|
||||
case 0: SERIAL_ECHOPGM("DEVICE SHUTDOWN"); break;
|
||||
case 1: SERIAL_ECHOPGM("BRIDGE SHUTDOWN"); break;
|
||||
case 2: SERIAL_ECHOPGM("WARNING "); break;
|
||||
case 3: SERIAL_ECHOPGM("OK "); break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
SERIAL_ECHOPGM(" Last Command: ");
|
||||
if (!(sh.STATUS_AXIS & sh.STATUS_AXIS_WRONG_CMD)) SERIAL_ECHOPGM("IN");
|
||||
SERIAL_ECHOPGM("VALID ");
|
||||
serialprintPGM(sh.STATUS_AXIS & sh.STATUS_AXIS_NOTPERF_CMD ? PSTR("COMPLETED ") : PSTR("Not PERFORMED"));
|
||||
SERIAL_ECHOPAIR("\n...THERMAL: ", !(sh.STATUS_AXIS & sh.STATUS_AXIS_TH_SD) ? "SHUTDOWN " : !(sh.STATUS_AXIS & sh.STATUS_AXIS_TH_WRN) ? "WARNING " : "OK ");
|
||||
}
|
||||
SERIAL_ECHOPGM(" OVERCURRENT:"); echo_yes_no((sh.STATUS_AXIS & sh.STATUS_AXIS_OCD) == 0);
|
||||
if (sh.STATUS_AXIS_LAYOUT != L6474_STATUS_LAYOUT) {
|
||||
SERIAL_ECHOPGM(" STALL:"); echo_yes_no((sh.STATUS_AXIS & sh.STATUS_AXIS_STEP_LOSS_A) == 0 || (sh.STATUS_AXIS & sh.STATUS_AXIS_STEP_LOSS_B) == 0);
|
||||
SERIAL_ECHOPGM(" STEP-CLOCK MODE:"); echo_yes_no((sh.STATUS_AXIS & sh.STATUS_AXIS_SCK_MOD) != 0);
|
||||
}
|
||||
else {
|
||||
SERIAL_ECHOPGM(" STALL: NA "
|
||||
" STEP-CLOCK MODE: NA"
|
||||
" UNDER VOLTAGE LOCKOUT: "); echo_yes_no((sh.STATUS_AXIS & sh.STATUS_AXIS_UVLO) == 0);
|
||||
}
|
||||
SERIAL_EOL();
|
||||
}
|
||||
|
||||
@ -59,57 +87,56 @@ void L6470_status_decode(const uint16_t status, const uint8_t axis) {
|
||||
* M122: Debug L6470 drivers
|
||||
*/
|
||||
void GcodeSuite::M122() {
|
||||
|
||||
L6470.spi_active = true; // let set_directions() know we're in the middle of a series of SPI transfers
|
||||
|
||||
#define L6470_SAY_STATUS(Q) L6470_status_decode(stepper##Q.getStatus(), Q)
|
||||
L64xxManager.pause_monitor(true); // Keep monitor_driver() from stealing status
|
||||
L64xxManager.spi_active = true; // Tell set_directions() a series of SPI transfers is underway
|
||||
|
||||
//if (parser.seen('S'))
|
||||
// tmc_set_report_interval(parser.value_bool());
|
||||
// tmc_set_report_interval(parser.value_bool());
|
||||
//else
|
||||
|
||||
#if AXIS_DRIVER_TYPE_X(L6470)
|
||||
L6470_SAY_STATUS(X);
|
||||
#if AXIS_IS_L64XX(X)
|
||||
L6470_say_status(X);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_X2(L6470)
|
||||
L6470_SAY_STATUS(X2);
|
||||
#if AXIS_IS_L64XX(X2)
|
||||
L6470_say_status(X2);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_Y(L6470)
|
||||
L6470_SAY_STATUS(Y);
|
||||
#if AXIS_IS_L64XX(Y)
|
||||
L6470_say_status(Y);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_Y2(L6470)
|
||||
L6470_SAY_STATUS(Y2);
|
||||
#if AXIS_IS_L64XX(Y2)
|
||||
L6470_say_status(Y2);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_Z(L6470)
|
||||
L6470_SAY_STATUS(Z);
|
||||
#if AXIS_IS_L64XX(Z)
|
||||
L6470_say_status(Z);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_Z2(L6470)
|
||||
L6470_SAY_STATUS(Z2);
|
||||
#if AXIS_IS_L64XX(Z2)
|
||||
L6470_say_status(Z2);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_Z3(L6470)
|
||||
L6470_SAY_STATUS(Z3);
|
||||
#if AXIS_IS_L64XX(Z3)
|
||||
L6470_say_status(Z3);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E0(L6470)
|
||||
L6470_SAY_STATUS(E0);
|
||||
#if AXIS_IS_L64XX(E0)
|
||||
L6470_say_status(E0);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E1(L6470)
|
||||
L6470_SAY_STATUS(E1);
|
||||
#if AXIS_IS_L64XX(E1)
|
||||
L6470_say_status(E1);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E2(L6470)
|
||||
L6470_SAY_STATUS(E2);
|
||||
#if AXIS_IS_L64XX(E2)
|
||||
L6470_say_status(E2);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E3(L6470)
|
||||
L6470_SAY_STATUS(E3);
|
||||
#if AXIS_IS_L64XX(E3)
|
||||
L6470_say_status(E3);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E4(L6470)
|
||||
L6470_SAY_STATUS(E4);
|
||||
#if AXIS_IS_L64XX(E4)
|
||||
L6470_say_status(E4);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E5(L6470)
|
||||
L6470_SAY_STATUS(E5);
|
||||
#if AXIS_IS_L64XX(E5)
|
||||
L6470_say_status(E5);
|
||||
#endif
|
||||
|
||||
L6470.spi_active = false; // done with all SPI transfers - clear handshake flags
|
||||
L6470.spi_abort = false;
|
||||
L64xxManager.spi_active = false; // done with all SPI transfers - clear handshake flags
|
||||
L64xxManager.spi_abort = false;
|
||||
L64xxManager.pause_monitor(false);
|
||||
}
|
||||
|
||||
#endif // HAS_DRIVER(L6470)
|
||||
#endif // HAS_L64XX
|
||||
|
@ -22,10 +22,10 @@
|
||||
|
||||
#include "../../../inc/MarlinConfig.h"
|
||||
|
||||
#if HAS_DRIVER(L6470)
|
||||
#if HAS_L64XX
|
||||
|
||||
#include "../../gcode.h"
|
||||
#include "../../../libs/L6470/L6470_Marlin.h"
|
||||
#include "../../../libs/L64XX/L64XX_Marlin.h"
|
||||
#include "../../../module/stepper/indirection.h"
|
||||
#include "../../../module/planner.h"
|
||||
|
||||
@ -37,6 +37,8 @@
|
||||
* M906: report or set KVAL_HOLD which sets the maximum effective voltage provided by the
|
||||
* PWMs to the steppers
|
||||
*
|
||||
* On L6474 this sets the TVAL register (same address).
|
||||
*
|
||||
* J - select which driver(s) to monitor on multi-driver axis
|
||||
* 0 - (default) monitor all drivers on the axis or E0
|
||||
* 1 - monitor only X, Y, Z or E1
|
||||
@ -81,89 +83,162 @@
|
||||
* KVAL_DEC
|
||||
* Vs compensation (if enabled)
|
||||
*/
|
||||
void L6470_report_current(L64XX &motor, const L64XX_axis_t axis) {
|
||||
|
||||
void L6470_report_current(L6470 &motor, const uint8_t axis) {
|
||||
if (L6470.spi_abort) return; // don't do anything if set_directions() has occurred
|
||||
const uint16_t status = motor.getStatus() ;
|
||||
const uint8_t overcurrent_threshold = (uint8_t)motor.GetParam(L6470_OCD_TH),
|
||||
stall_threshold = (uint8_t)motor.GetParam(L6470_STALL_TH),
|
||||
motor_status = (status & (STATUS_MOT_STATUS)) >> 13,
|
||||
adc_out = motor.GetParam(L6470_ADC_OUT),
|
||||
adc_out_limited = constrain(adc_out, 8, 24);
|
||||
const float comp_coef = 1600.0f / adc_out_limited;
|
||||
const int microsteps = _BV(motor.GetParam(L6470_STEP_MODE) & 0x07);
|
||||
char temp_buf[80];
|
||||
L6470.say_axis(axis);
|
||||
#if ENABLED(L6470_CHITCHAT)
|
||||
sprintf_P(temp_buf, PSTR(" status: %4x "), status);
|
||||
DEBUG_ECHO(temp_buf);
|
||||
print_bin(status);
|
||||
#endif
|
||||
sprintf_P(temp_buf, PSTR("\n...OverCurrent Threshold: %2d (%4d mA)"), overcurrent_threshold, (overcurrent_threshold + 1) * 375);
|
||||
SERIAL_ECHO(temp_buf);
|
||||
if (L64xxManager.spi_abort) return; // don't do anything if set_directions() has occurred
|
||||
|
||||
char numstr[11];
|
||||
dtostrf((stall_threshold + 1) * 31.25, 1, 2, numstr);
|
||||
sprintf_P(temp_buf, PSTR(" Stall Threshold: %2d (%s mA)"), stall_threshold, numstr);
|
||||
SERIAL_ECHO(temp_buf);
|
||||
const L64XX_Marlin::L64XX_shadow_t &sh = L64xxManager.shadow;
|
||||
const uint16_t status = L64xxManager.get_status(axis); //also populates shadow structure
|
||||
const uint8_t OverCurrent_Threshold = uint8_t(motor.GetParam(L6470_OCD_TH));
|
||||
|
||||
SERIAL_ECHOPGM(" Motor Status: ");
|
||||
const char *stat_str;
|
||||
switch (motor_status) {
|
||||
default:
|
||||
case 0: stat_str = PSTR("stopped"); break;
|
||||
case 1: stat_str = PSTR("accelerating"); break;
|
||||
case 2: stat_str = PSTR("decelerating"); break;
|
||||
case 3: stat_str = PSTR("at constant speed"); break;
|
||||
auto say_axis_status = [](const L64XX_axis_t axis, const uint16_t status) {
|
||||
L64xxManager.say_axis(axis);
|
||||
#if ENABLED(L6470_CHITCHAT)
|
||||
char tmp[10];
|
||||
sprintf_P(tmp, PSTR("%4x "), status);
|
||||
DEBUG_ECHOPAIR(" status: ", tmp);
|
||||
print_bin(status);
|
||||
#else
|
||||
UNUSED(status);
|
||||
#endif
|
||||
SERIAL_EOL();
|
||||
};
|
||||
|
||||
char temp_buf[10];
|
||||
|
||||
switch (sh.STATUS_AXIS_LAYOUT) {
|
||||
case L6470_STATUS_LAYOUT: // L6470
|
||||
case L6480_STATUS_LAYOUT: { // L6480 & powerstep01
|
||||
const uint16_t Stall_Threshold = (uint8_t)motor.GetParam(L6470_STALL_TH),
|
||||
motor_status = (status & (STATUS_MOT_STATUS)) >> 5,
|
||||
L6470_ADC_out = motor.GetParam(L6470_ADC_OUT),
|
||||
L6470_ADC_out_limited = constrain(L6470_ADC_out, 8, 24);
|
||||
const float comp_coef = 1600.0f / L6470_ADC_out_limited;
|
||||
const uint16_t MicroSteps = _BV(motor.GetParam(L6470_STEP_MODE) & 0x07);
|
||||
|
||||
say_axis_status(axis, status);
|
||||
|
||||
SERIAL_ECHOPGM("...OverCurrent Threshold: ");
|
||||
sprintf_P(temp_buf, PSTR("%2d ("), OverCurrent_Threshold);
|
||||
SERIAL_ECHO(temp_buf);
|
||||
SERIAL_ECHO((OverCurrent_Threshold + 1) * motor.OCD_CURRENT_CONSTANT_INV);
|
||||
SERIAL_ECHOPGM(" mA)");
|
||||
SERIAL_ECHOPGM(" Stall Threshold: ");
|
||||
sprintf_P(temp_buf, PSTR("%2d ("), Stall_Threshold);
|
||||
SERIAL_ECHO(temp_buf);
|
||||
SERIAL_ECHO((Stall_Threshold + 1) * motor.STALL_CURRENT_CONSTANT_INV);
|
||||
SERIAL_ECHOPGM(" mA)");
|
||||
SERIAL_ECHOPGM(" Motor Status: ");
|
||||
switch (motor_status) {
|
||||
case 0: SERIAL_ECHOPGM("stopped"); break;
|
||||
case 1: SERIAL_ECHOPGM("accelerating"); break;
|
||||
case 2: SERIAL_ECHOPGM("decelerating"); break;
|
||||
case 3: SERIAL_ECHOPGM("at constant speed"); break;
|
||||
}
|
||||
SERIAL_EOL();
|
||||
|
||||
SERIAL_ECHOPAIR("...MicroSteps: ", MicroSteps,
|
||||
" ADC_OUT: ", L6470_ADC_out);
|
||||
SERIAL_ECHOPGM(" Vs_compensation: ");
|
||||
serialprintPGM((motor.GetParam(sh.L6470_AXIS_CONFIG) & CONFIG_EN_VSCOMP) ? PSTR("ENABLED ") : PSTR("DISABLED"));
|
||||
SERIAL_ECHOLNPAIR(" Compensation coefficient: ~", comp_coef * 0.01f);
|
||||
|
||||
SERIAL_ECHOPAIR("...KVAL_HOLD: ", motor.GetParam(L6470_KVAL_HOLD),
|
||||
" KVAL_RUN : ", motor.GetParam(L6470_KVAL_RUN),
|
||||
" KVAL_ACC: ", motor.GetParam(L6470_KVAL_ACC),
|
||||
" KVAL_DEC: ", motor.GetParam(L6470_KVAL_DEC),
|
||||
" V motor max = ");
|
||||
switch (motor_status) {
|
||||
case 0: SERIAL_ECHO(motor.GetParam(L6470_KVAL_HOLD) * 100 / 256); SERIAL_ECHOPGM("% (KVAL_HOLD)"); break;
|
||||
case 1: SERIAL_ECHO(motor.GetParam(L6470_KVAL_RUN) * 100 / 256); SERIAL_ECHOPGM("% (KVAL_RUN)"); break;
|
||||
case 2: SERIAL_ECHO(motor.GetParam(L6470_KVAL_ACC) * 100 / 256); SERIAL_ECHOPGM("% (KVAL_ACC)"); break;
|
||||
case 3: SERIAL_ECHO(motor.GetParam(L6470_KVAL_DEC) * 100 / 256); SERIAL_ECHOPGM("% (KVAL_HOLD)"); break;
|
||||
}
|
||||
SERIAL_EOL();
|
||||
|
||||
#if ENABLED(L6470_CHITCHAT)
|
||||
DEBUG_ECHOPGM("...SLEW RATE: ");
|
||||
switch (sh.STATUS_AXIS_LAYOUT) {
|
||||
case L6470_STATUS_LAYOUT: {
|
||||
switch ((motor.GetParam(sh.L6470_AXIS_CONFIG) & CONFIG_POW_SR) >> CONFIG_POW_SR_BIT) {
|
||||
case 0: { DEBUG_ECHOLNPGM("320V/uS") ; break; }
|
||||
case 1: { DEBUG_ECHOLNPGM("75V/uS") ; break; }
|
||||
case 2: { DEBUG_ECHOLNPGM("110V/uS") ; break; }
|
||||
case 3: { DEBUG_ECHOLNPGM("260V/uS") ; break; }
|
||||
}
|
||||
break;
|
||||
}
|
||||
case L6480_STATUS_LAYOUT: {
|
||||
switch (motor.GetParam(L6470_GATECFG1) & CONFIG1_SR ) {
|
||||
case CONFIG1_SR_220V_us: { DEBUG_ECHOLNPGM("220V/uS") ; break; }
|
||||
case CONFIG1_SR_400V_us: { DEBUG_ECHOLNPGM("400V/uS") ; break; }
|
||||
case CONFIG1_SR_520V_us: { DEBUG_ECHOLNPGM("520V/uS") ; break; }
|
||||
case CONFIG1_SR_980V_us: { DEBUG_ECHOLNPGM("980V/uS") ; break; }
|
||||
default: { DEBUG_ECHOLNPGM("unknown") ; break; }
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
SERIAL_EOL();
|
||||
break;
|
||||
}
|
||||
|
||||
case L6474_STATUS_LAYOUT: { // L6474
|
||||
const uint16_t L6470_ADC_out = motor.GetParam(L6470_ADC_OUT) & 0x1F,
|
||||
L6474_TVAL_val = motor.GetParam(L6474_TVAL) & 0x7F;
|
||||
|
||||
say_axis_status(axis, status);
|
||||
|
||||
SERIAL_ECHOPGM("...OverCurrent Threshold: ");
|
||||
sprintf_P(temp_buf, PSTR("%2d ("), OverCurrent_Threshold);
|
||||
SERIAL_ECHO(temp_buf);
|
||||
SERIAL_ECHO((OverCurrent_Threshold + 1) * motor.OCD_CURRENT_CONSTANT_INV);
|
||||
SERIAL_ECHOPGM(" mA)");
|
||||
SERIAL_ECHOPGM(" TVAL: ");
|
||||
sprintf_P(temp_buf, PSTR("%2d ("), L6474_TVAL_val);
|
||||
SERIAL_ECHO(temp_buf);
|
||||
SERIAL_ECHO((L6474_TVAL_val + 1) * motor.STALL_CURRENT_CONSTANT_INV);
|
||||
SERIAL_ECHOLNPGM(" mA Motor Status: NA)");
|
||||
|
||||
const uint16_t MicroSteps = _BV(motor.GetParam(L6470_STEP_MODE) & 0x07); //NOMORE(MicroSteps, 16);
|
||||
SERIAL_ECHOLNPAIR("...MicroSteps: ", MicroSteps,
|
||||
" ADC_OUT: ", L6470_ADC_out);
|
||||
|
||||
SERIAL_ECHOLNPGM(" Vs_compensation: NA\n"
|
||||
"...KVAL_HOLD: NA"
|
||||
" KVAL_RUN : NA"
|
||||
" KVAL_ACC: NA"
|
||||
" KVAL_DEC: NA"
|
||||
" V motor max = NA");
|
||||
|
||||
#if ENABLED(L6470_CHITCHAT)
|
||||
DEBUG_ECHOPGM("...SLEW RATE: ");
|
||||
switch ((motor.GetParam(sh.L6470_AXIS_CONFIG) & CONFIG_POW_SR) >> CONFIG_POW_SR_BIT) {
|
||||
case 0: DEBUG_ECHOLNPGM("320V/uS") ; break;
|
||||
case 1: DEBUG_ECHOLNPGM("75V/uS") ; break;
|
||||
case 2: DEBUG_ECHOLNPGM("110V/uS") ; break;
|
||||
case 3: DEBUG_ECHOLNPGM("260V/uS") ; break;
|
||||
default: DEBUG_ECHOLNPAIR("slew rate: ", (motor.GetParam(sh.L6470_AXIS_CONFIG) & CONFIG_POW_SR) >> CONFIG_POW_SR_BIT); break;
|
||||
}
|
||||
#endif
|
||||
SERIAL_EOL();
|
||||
SERIAL_EOL();
|
||||
break;
|
||||
}
|
||||
}
|
||||
serialprintPGM(stat_str);
|
||||
SERIAL_EOL();
|
||||
|
||||
SERIAL_ECHOPAIR("...microsteps: ", microsteps);
|
||||
SERIAL_ECHOPAIR(" ADC_OUT: ", adc_out);
|
||||
SERIAL_ECHOPGM(" Vs_compensation: ");
|
||||
serialprintPGM((motor.GetParam(L6470_CONFIG) & CONFIG_EN_VSCOMP) ? PSTR("ENABLED ") : PSTR("DISABLED"));
|
||||
|
||||
SERIAL_ECHOLNPAIR(" Compensation coefficient: ", dtostrf(comp_coef * 0.01f, 7, 2, numstr));
|
||||
SERIAL_ECHOPAIR("...KVAL_HOLD: ", motor.GetParam(L6470_KVAL_HOLD));
|
||||
SERIAL_ECHOPAIR(" KVAL_RUN : ", motor.GetParam(L6470_KVAL_RUN));
|
||||
SERIAL_ECHOPAIR(" KVAL_ACC: ", motor.GetParam(L6470_KVAL_ACC));
|
||||
SERIAL_ECHOPAIR(" KVAL_DEC: ", motor.GetParam(L6470_KVAL_DEC));
|
||||
SERIAL_ECHOPGM(" V motor max = ");
|
||||
float val;
|
||||
PGM_P suf;
|
||||
switch (motor_status) {
|
||||
case 0:
|
||||
val = motor.GetParam(L6470_KVAL_HOLD);
|
||||
suf = PSTR("(KVAL_HOLD)");
|
||||
break;
|
||||
case 1:
|
||||
val = motor.GetParam(L6470_KVAL_RUN);
|
||||
suf = PSTR("(KVAL_RUN)");
|
||||
break;
|
||||
case 2:
|
||||
val = motor.GetParam(L6470_KVAL_ACC);
|
||||
suf = PSTR("(KVAL_ACC)");
|
||||
break;
|
||||
case 3:
|
||||
val = motor.GetParam(L6470_KVAL_DEC);
|
||||
suf = PSTR("(KVAL_DEC)");
|
||||
break;
|
||||
}
|
||||
SERIAL_ECHO(dtostrf(val * 100 / 256, 10, 2, numstr));
|
||||
SERIAL_ECHOPGM("%% ");
|
||||
serialprintPGM(suf);
|
||||
SERIAL_EOL();
|
||||
}
|
||||
|
||||
void GcodeSuite::M906() {
|
||||
|
||||
L64xxManager.pause_monitor(true); // Keep monitor_driver() from stealing status
|
||||
|
||||
#define L6470_SET_KVAL_HOLD(Q) stepper##Q.SetParam(L6470_KVAL_HOLD, value)
|
||||
|
||||
DEBUG_ECHOLNPGM("M906");
|
||||
|
||||
bool report_current = true;
|
||||
uint8_t report_current = true;
|
||||
|
||||
#if HAS_DRIVER(L6470)
|
||||
#if HAS_L64XX
|
||||
const uint8_t index = parser.byteval('I');
|
||||
#endif
|
||||
|
||||
@ -172,35 +247,35 @@ void GcodeSuite::M906() {
|
||||
report_current = false;
|
||||
|
||||
if (planner.has_blocks_queued() || planner.cleaning_buffer_counter) {
|
||||
SERIAL_ECHOLNPGM("!Can't set KVAL_HOLD with steppers moving");
|
||||
SERIAL_ECHOLNPGM("Test aborted. Can't set KVAL_HOLD while steppers are moving.");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (i) {
|
||||
case X_AXIS:
|
||||
#if AXIS_DRIVER_TYPE_X(L6470)
|
||||
#if AXIS_IS_L64XX(X)
|
||||
if (index == 0) L6470_SET_KVAL_HOLD(X);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_X2(L6470)
|
||||
#if AXIS_IS_L64XX(X2)
|
||||
if (index == 1) L6470_SET_KVAL_HOLD(X2);
|
||||
#endif
|
||||
break;
|
||||
case Y_AXIS:
|
||||
#if AXIS_DRIVER_TYPE_Y(L6470)
|
||||
#if AXIS_IS_L64XX(Y)
|
||||
if (index == 0) L6470_SET_KVAL_HOLD(Y);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_Y2(L6470)
|
||||
#if AXIS_IS_L64XX(Y2)
|
||||
if (index == 1) L6470_SET_KVAL_HOLD(Y2);
|
||||
#endif
|
||||
break;
|
||||
case Z_AXIS:
|
||||
#if AXIS_DRIVER_TYPE_Z(L6470)
|
||||
#if AXIS_IS_L64XX(Z)
|
||||
if (index == 0) L6470_SET_KVAL_HOLD(Z);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_Z2(L6470)
|
||||
#if AXIS_IS_L64XX(Z2)
|
||||
if (index == 1) L6470_SET_KVAL_HOLD(Z2);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_Z3(L6470)
|
||||
#if AXIS_IS_L64XX(Z3)
|
||||
if (index == 2) L6470_SET_KVAL_HOLD(Z3);
|
||||
#endif
|
||||
break;
|
||||
@ -208,22 +283,22 @@ void GcodeSuite::M906() {
|
||||
const int8_t target_extruder = get_target_extruder_from_command();
|
||||
if (target_extruder < 0) return;
|
||||
switch (target_extruder) {
|
||||
#if AXIS_DRIVER_TYPE_E0(L6470)
|
||||
#if AXIS_IS_L64XX(E0)
|
||||
case 0: L6470_SET_KVAL_HOLD(E0); break;
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E1(L6470)
|
||||
#if AXIS_IS_L64XX(E1)
|
||||
case 1: L6470_SET_KVAL_HOLD(E1); break;
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E2(L6470)
|
||||
#if AXIS_IS_L64XX(E2)
|
||||
case 2: L6470_SET_KVAL_HOLD(E2); break;
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E3(L6470)
|
||||
#if AXIS_IS_L64XX(E3)
|
||||
case 3: L6470_SET_KVAL_HOLD(E3); break;
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E4(L6470)
|
||||
#if AXIS_IS_L64XX(E4)
|
||||
case 4: L6470_SET_KVAL_HOLD(E4); break;
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E5(L6470)
|
||||
#if AXIS_IS_L64XX(E5)
|
||||
case 5: L6470_SET_KVAL_HOLD(E5); break;
|
||||
#endif
|
||||
}
|
||||
@ -234,51 +309,52 @@ void GcodeSuite::M906() {
|
||||
if (report_current) {
|
||||
#define L6470_REPORT_CURRENT(Q) L6470_report_current(stepper##Q, Q)
|
||||
|
||||
L6470.spi_active = true; // let set_directions() know we're in the middle of a series of SPI transfers
|
||||
L64xxManager.spi_active = true; // Tell set_directions() a series of SPI transfers is underway
|
||||
|
||||
#if AXIS_DRIVER_TYPE_X(L6470)
|
||||
#if AXIS_IS_L64XX(X)
|
||||
L6470_REPORT_CURRENT(X);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_X2(L6470)
|
||||
#if AXIS_IS_L64XX(X2)
|
||||
L6470_REPORT_CURRENT(X2);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_Y(L6470)
|
||||
#if AXIS_IS_L64XX(Y)
|
||||
L6470_REPORT_CURRENT(Y);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_Y2(L6470)
|
||||
#if AXIS_IS_L64XX(Y2)
|
||||
L6470_REPORT_CURRENT(Y2);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_Z(L6470)
|
||||
#if AXIS_IS_L64XX(Z)
|
||||
L6470_REPORT_CURRENT(Z);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_Z2(L6470)
|
||||
#if AXIS_IS_L64XX(Z2)
|
||||
L6470_REPORT_CURRENT(Z2);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_Z3(L6470)
|
||||
#if AXIS_IS_L64XX(Z3)
|
||||
L6470_REPORT_CURRENT(Z3);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E0(L6470)
|
||||
#if AXIS_IS_L64XX(E0)
|
||||
L6470_REPORT_CURRENT(E0);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E1(L6470)
|
||||
#if AXIS_IS_L64XX(E1)
|
||||
L6470_REPORT_CURRENT(E1);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E2(L6470)
|
||||
#if AXIS_IS_L64XX(E2)
|
||||
L6470_REPORT_CURRENT(E2);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E3(L6470)
|
||||
#if AXIS_IS_L64XX(E3)
|
||||
L6470_REPORT_CURRENT(E3);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E4(L6470)
|
||||
#if AXIS_IS_L64XX(E4)
|
||||
L6470_REPORT_CURRENT(E4);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E5(L6470)
|
||||
#if AXIS_IS_L64XX(E5)
|
||||
L6470_REPORT_CURRENT(E5);
|
||||
#endif
|
||||
|
||||
L6470.spi_active = false; // done with all SPI transfers - clear handshake flags
|
||||
L6470.spi_abort = false;
|
||||
L64xxManager.spi_active = false; // done with all SPI transfers - clear handshake flags
|
||||
L64xxManager.spi_abort = false;
|
||||
L64xxManager.pause_monitor(false);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // HAS_DRIVER(L6470)
|
||||
#endif // HAS_L64XX
|
||||
|
@ -20,35 +20,26 @@
|
||||
*
|
||||
*/
|
||||
|
||||
//
|
||||
// NOTE: All tests assume each axis uses matching driver chips.
|
||||
//
|
||||
|
||||
#include "../../../inc/MarlinConfig.h"
|
||||
|
||||
#if HAS_DRIVER(L6470)
|
||||
#if HAS_L64XX
|
||||
|
||||
#include "../../gcode.h"
|
||||
#include "../../../module/stepper/indirection.h"
|
||||
#include "../../../module/planner.h"
|
||||
#include "../../../libs/L6470/L6470_Marlin.h"
|
||||
#include "../../../libs/L64XX/L64XX_Marlin.h"
|
||||
|
||||
#define DEBUG_OUT ENABLED(L6470_CHITCHAT)
|
||||
#include "../../../core/debug_out.h"
|
||||
|
||||
static void jiggle_axis(const char axis_char, const float &min, const float &max, const feedRate_t &fr_mm_m) {
|
||||
char gcode_string[30], str1[11], str2[11];
|
||||
|
||||
// Turn the motor(s) both directions
|
||||
sprintf_P(gcode_string, PSTR("G0 %c%s F%s"), axis_char, dtostrf(min, 1, 3, str1), dtostrf(fr_mm_m, 1, 3, str2));
|
||||
gcode.process_subcommands_now(gcode_string);
|
||||
|
||||
sprintf_P(gcode_string, PSTR("G0 %c%s F%s"), axis_char, dtostrf(max, 1, 3, str1), str2);
|
||||
gcode.process_subcommands_now(gcode_string);
|
||||
|
||||
planner.synchronize();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* M916: Increase KVAL_HOLD until thermal warning
|
||||
*
|
||||
* M916: increase KVAL_HOLD until get thermal warning
|
||||
* NOTE - on L6474 it is TVAL that is used
|
||||
*
|
||||
* J - select which driver(s) to monitor on multi-driver axis
|
||||
* 0 - (default) monitor all drivers on the axis or E0
|
||||
@ -62,8 +53,14 @@ static void jiggle_axis(const char axis_char, const float &min, const float &max
|
||||
* F - feedrate
|
||||
* optional - will use default max feedrate from configuration.h if not specified
|
||||
*
|
||||
* K - starting value for KVAL_HOLD (0 - 255)
|
||||
* optional - will use & report current value from driver if not specified
|
||||
* T - current (mA) setting for TVAL (0 - 4A in 31.25mA increments, rounds down) - L6474 only
|
||||
* optional - will report current value from driver if not specified
|
||||
*
|
||||
* K - value for KVAL_HOLD (0 - 255) (ignored for L6474)
|
||||
* optional - will report current value from driver if not specified
|
||||
*
|
||||
* D - time (in seconds) to run each setting of KVAL_HOLD/TVAL
|
||||
* optional - defaults to zero (runs each setting once)
|
||||
*
|
||||
*/
|
||||
|
||||
@ -77,80 +74,115 @@ void GcodeSuite::M916() {
|
||||
|
||||
DEBUG_ECHOLNPGM("M916");
|
||||
|
||||
// Variables used by L6470_get_user_input function - some may not be used
|
||||
char axis_mon[3][3] = { " ", " ", " " }; // list of Axes to be monitored
|
||||
uint8_t axis_index[3];
|
||||
L64xxManager.pause_monitor(true); // Keep monitor_driver() from stealing status
|
||||
|
||||
// Variables used by L64xxManager.get_user_input function - some may not be used
|
||||
char axis_mon[3][3] = { {" "}, {" "}, {" "} }; // list of Axes to be monitored
|
||||
L64XX_axis_t axis_index[3];
|
||||
uint16_t axis_status[3];
|
||||
uint8_t driver_count = 1;
|
||||
float position_max;
|
||||
float position_min;
|
||||
feedRate_t final_fr_mm_m;
|
||||
float final_feedrate;
|
||||
uint8_t kval_hold;
|
||||
uint8_t ocd_th_val = 0;
|
||||
uint8_t stall_th_val = 0;
|
||||
uint8_t OCD_TH_val = 0;
|
||||
uint8_t STALL_TH_val = 0;
|
||||
uint16_t over_current_threshold;
|
||||
constexpr bool over_current_flag = false; // M916 doesn't play with the overcurrent thresholds
|
||||
constexpr uint8_t over_current_flag = false; // M916 doesn't play with the overcurrent thresholds
|
||||
|
||||
#define DRIVER_TYPE_L6474(Q) AXIS_DRIVER_TYPE_##Q(L6474)
|
||||
|
||||
uint8_t j; // general purpose counter
|
||||
|
||||
if (L6470.get_user_input(driver_count, axis_index, axis_mon, position_max, position_min, final_fr_mm_m, kval_hold, over_current_flag, ocd_th_val, stall_th_val, over_current_threshold))
|
||||
if (L64xxManager.get_user_input(driver_count, axis_index, axis_mon, position_max, position_min, final_feedrate, kval_hold, over_current_flag, OCD_TH_val, STALL_TH_val, over_current_threshold))
|
||||
return; // quit if invalid user input
|
||||
|
||||
DEBUG_ECHOLNPAIR("feedrate = ", final_fr_mm_m);
|
||||
DEBUG_ECHOLNPAIR("feedrate = ", final_feedrate);
|
||||
|
||||
planner.synchronize(); // Wait for moves to finish
|
||||
planner.synchronize(); // wait for all current movement commands to complete
|
||||
|
||||
const L64XX_Marlin::L64XX_shadow_t &sh = L64xxManager.shadow;
|
||||
for (j = 0; j < driver_count; j++)
|
||||
L6470.get_status(axis_index[j]); // Clear out error flags
|
||||
L64xxManager.get_status(axis_index[j]); // clear out any pre-existing error flags
|
||||
|
||||
char temp_axis_string[] = " ";
|
||||
temp_axis_string[0] = axis_mon[0][0]; // need to have a string for use within sprintf format section
|
||||
char gcode_string[80];
|
||||
uint16_t status_composite = 0;
|
||||
|
||||
uint16_t M91x_counter = kval_hold;
|
||||
uint16_t M91x_counter_max;
|
||||
if (sh.STATUS_AXIS_LAYOUT == L6474_STATUS_LAYOUT) {
|
||||
M91x_counter_max = 128; // TVAL is 7 bits
|
||||
LIMIT(M91x_counter, 0U, 127U);
|
||||
}
|
||||
else
|
||||
M91x_counter_max = 256; // KVAL_HOLD is 8 bits
|
||||
|
||||
uint8_t M91x_delay_s = parser.byteval('D'); // get delay in seconds
|
||||
millis_t M91x_delay_ms = M91x_delay_s * 60 * 1000;
|
||||
millis_t M91x_delay_end;
|
||||
|
||||
DEBUG_ECHOLNPGM(".\n.");
|
||||
|
||||
do {
|
||||
|
||||
DEBUG_ECHOLNPAIR("kval_hold = ", kval_hold); // set & report KVAL_HOLD for this run
|
||||
if (sh.STATUS_AXIS_LAYOUT == L6474_STATUS_LAYOUT)
|
||||
DEBUG_ECHOLNPAIR("TVAL current (mA) = ", (M91x_counter + 1) * sh.AXIS_STALL_CURRENT_CONSTANT_INV); // report TVAL current for this run
|
||||
else
|
||||
DEBUG_ECHOLNPAIR("kval_hold = ", M91x_counter); // report KVAL_HOLD for this run
|
||||
|
||||
for (j = 0; j < driver_count; j++)
|
||||
L6470.set_param(axis_index[j], L6470_KVAL_HOLD, kval_hold);
|
||||
L64xxManager.set_param(axis_index[j], L6470_KVAL_HOLD, M91x_counter); //set KVAL_HOLD or TVAL (same register address)
|
||||
|
||||
// Turn the motor(s) both directions
|
||||
jiggle_axis(axis_mon[0][0], position_min, position_max, final_fr_mm_m);
|
||||
M91x_delay_end = millis() + M91x_delay_ms;
|
||||
do {
|
||||
// turn the motor(s) both directions
|
||||
sprintf_P(gcode_string, PSTR("G0 %s%03d F%03d"), temp_axis_string, uint16_t(position_min), uint16_t(final_feedrate));
|
||||
gcode.process_subcommands_now_P(gcode_string);
|
||||
|
||||
status_composite = 0; // clear out the old bits
|
||||
sprintf_P(gcode_string, PSTR("G0 %s%03d F%03d"), temp_axis_string, uint16_t(position_max), uint16_t(final_feedrate));
|
||||
gcode.process_subcommands_now_P(gcode_string);
|
||||
|
||||
for (j = 0; j < driver_count; j++) {
|
||||
axis_status[j] = (~L6470.get_status(axis_index[j])) & L6470_ERROR_MASK; // bits of interest are all active low
|
||||
status_composite |= axis_status[j] ;
|
||||
}
|
||||
// get the status after the motors have stopped
|
||||
planner.synchronize();
|
||||
|
||||
status_composite = 0; // clear out the old bits
|
||||
|
||||
if (status_composite && (status_composite & STATUS_UVLO)) {
|
||||
DEBUG_ECHOLNPGM("Test aborted (Undervoltage lockout active)");
|
||||
for (j = 0; j < driver_count; j++) {
|
||||
DEBUG_ECHOPGM("...");
|
||||
L6470.error_status_decode(axis_status[j], axis_index[j]);
|
||||
axis_status[j] = (~L64xxManager.get_status(axis_index[j])) & sh.L6470_ERROR_MASK; // bits of interest are all active low
|
||||
status_composite |= axis_status[j] ;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// increment KVAL_HOLD if not yet at thermal warning/shutdown
|
||||
if (!(status_composite & (STATUS_TH_WRN | STATUS_TH_SD)))
|
||||
kval_hold++;
|
||||
if (status_composite) break;
|
||||
} while (millis() < M91x_delay_end);
|
||||
|
||||
} while (!(status_composite & (STATUS_TH_WRN | STATUS_TH_SD)) && kval_hold); // exit when kval_hold == 0 (rolls over)
|
||||
if (status_composite) break;
|
||||
|
||||
DEBUG_ECHOPGM(".\n.\nThermal warning/shutdown ");
|
||||
if ((status_composite & (STATUS_TH_WRN | STATUS_TH_SD))) {
|
||||
DEBUG_ECHOLNPGM("has occurred");
|
||||
for (j = 0; j < driver_count; j++) {
|
||||
DEBUG_ECHOPGM("...");
|
||||
L6470.error_status_decode(axis_status[j], axis_index[j]);
|
||||
}
|
||||
}
|
||||
else
|
||||
DEBUG_ECHOLNPGM("(Unable to get)");
|
||||
M91x_counter++;
|
||||
|
||||
} while (!(status_composite & (sh.STATUS_AXIS_TH_WRN | sh.STATUS_AXIS_TH_SD)) && (M91x_counter < M91x_counter_max));
|
||||
|
||||
DEBUG_ECHOLNPGM(".");
|
||||
|
||||
#if ENABLED(L6470_CHITCHAT)
|
||||
if (status_composite) {
|
||||
L64xxManager.error_status_decode(status_composite, axis_index[0],
|
||||
sh.STATUS_AXIS_TH_SD, sh.STATUS_AXIS_TH_WRN,
|
||||
sh.STATUS_AXIS_STEP_LOSS_A, sh.STATUS_AXIS_STEP_LOSS_B,
|
||||
sh.STATUS_AXIS_OCD, sh.STATUS_AXIS_LAYOUT);
|
||||
DEBUG_ECHOLNPGM(".");
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((status_composite & (sh.STATUS_AXIS_TH_WRN | sh.STATUS_AXIS_TH_SD)))
|
||||
DEBUG_ECHOLNPGM(".\n.\nTest completed normally - Thermal warning/shutdown has occurred");
|
||||
else if (status_composite)
|
||||
DEBUG_ECHOLNPGM(".\n.\nTest completed abnormally - non-thermal error has occured");
|
||||
else
|
||||
DEBUG_ECHOLNPGM(".\n.\nTest completed normally - Unable to get to thermal warning/shutdown");
|
||||
|
||||
L64xxManager.pause_monitor(false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -159,8 +191,8 @@ void GcodeSuite::M916() {
|
||||
*
|
||||
* Decrease OCD current until overcurrent error
|
||||
* Increase OCD until overcurrent error goes away
|
||||
* Decrease stall threshold until stall
|
||||
* Increase stall until stall error goes away
|
||||
* Decrease stall threshold until stall (not done on L6474)
|
||||
* Increase stall until stall error goes away (not done on L6474)
|
||||
*
|
||||
* J - select which driver(s) to monitor on multi-driver axis
|
||||
* 0 - (default) monitor all drivers on the axis or E0
|
||||
@ -176,7 +208,10 @@ void GcodeSuite::M916() {
|
||||
* optional - will report current value from driver if not specified
|
||||
* if there are multiple drivers on the axis then all will be set the same
|
||||
*
|
||||
* K - value for KVAL_HOLD (0 - 255)
|
||||
* T - current (mA) setting for TVAL (0 - 4A in 31.25mA increments, rounds down) - L6474 only
|
||||
* optional - will report current value from driver if not specified
|
||||
*
|
||||
* K - value for KVAL_HOLD (0 - 255) (ignored for L6474)
|
||||
* optional - will report current value from driver if not specified
|
||||
*
|
||||
*/
|
||||
@ -184,66 +219,85 @@ void GcodeSuite::M917() {
|
||||
|
||||
DEBUG_ECHOLNPGM("M917");
|
||||
|
||||
char axis_mon[3][3] = { " ", " ", " " }; // list of axes to be monitored
|
||||
uint8_t axis_index[3];
|
||||
L64xxManager.pause_monitor(true); // Keep monitor_driver() from stealing status
|
||||
|
||||
char axis_mon[3][3] = { {" "}, {" "}, {" "} }; // list of Axes to be monitored
|
||||
L64XX_axis_t axis_index[3];
|
||||
uint16_t axis_status[3];
|
||||
uint8_t driver_count = 1;
|
||||
float position_max;
|
||||
float position_min;
|
||||
feedRate_t final_fr_mm_m;
|
||||
float final_feedrate;
|
||||
uint8_t kval_hold;
|
||||
uint8_t ocd_th_val = 0;
|
||||
uint8_t stall_th_val = 0;
|
||||
uint8_t OCD_TH_val = 0;
|
||||
uint8_t STALL_TH_val = 0;
|
||||
uint16_t over_current_threshold;
|
||||
constexpr bool over_current_flag = true;
|
||||
constexpr uint8_t over_current_flag = true;
|
||||
|
||||
uint8_t j; // general purpose counter
|
||||
|
||||
if (L6470.get_user_input(driver_count, axis_index, axis_mon, position_max, position_min, final_fr_mm_m, kval_hold, over_current_flag, ocd_th_val, stall_th_val, over_current_threshold))
|
||||
if (L64xxManager.get_user_input(driver_count, axis_index, axis_mon, position_max, position_min, final_feedrate, kval_hold, over_current_flag, OCD_TH_val, STALL_TH_val, over_current_threshold))
|
||||
return; // quit if invalid user input
|
||||
|
||||
DEBUG_ECHOLNPAIR("feedrate = ", final_fr_mm_m);
|
||||
DEBUG_ECHOLNPAIR("feedrate = ", final_feedrate);
|
||||
|
||||
planner.synchronize(); // Wait for moves to finish
|
||||
planner.synchronize(); // wait for all current movement commands to complete
|
||||
|
||||
const L64XX_Marlin::L64XX_shadow_t &sh = L64xxManager.shadow;
|
||||
for (j = 0; j < driver_count; j++)
|
||||
L6470.get_status(axis_index[j]); // Clear out error flags
|
||||
L64xxManager.get_status(axis_index[j]); // clear error flags
|
||||
char temp_axis_string[] = " ";
|
||||
temp_axis_string[0] = axis_mon[0][0]; // need a sprintf format string
|
||||
char gcode_string[80];
|
||||
uint16_t status_composite = 0;
|
||||
uint8_t test_phase = 0;
|
||||
// 0 - decreasing OCD - exit when OCD warning occurs (ignore STALL)
|
||||
// 1 - increasing OCD - exit when OCD warning stops (ignore STALL) -
|
||||
// 2 - OCD finalized - decreasing STALL - exit when STALL warning happens
|
||||
// 3 - OCD finalized - increasing STALL - exit when STALL warning stop
|
||||
// 4 - all testing completed
|
||||
DEBUG_ECHOPAIR(".\n.\n.\nover_current threshold : ", (ocd_th_val + 1) * 375); // first status display
|
||||
DEBUG_ECHOPAIR(" (OCD_TH: : ", ocd_th_val);
|
||||
DEBUG_ECHOPAIR(") Stall threshold: ", (stall_th_val + 1) * 31.25);
|
||||
DEBUG_ECHOPAIR(" (STALL_TH: ", stall_th_val);
|
||||
uint8_t test_phase = 0; // 0 - decreasing OCD - exit when OCD warning occurs (ignore STALL)
|
||||
// 1 - increasing OCD - exit when OCD warning stops (ignore STALL)
|
||||
// 2 - OCD finalized - decreasing STALL - exit when STALL warning happens
|
||||
// 3 - OCD finalized - increasing STALL - exit when STALL warning stop
|
||||
// 4 - all testing completed
|
||||
DEBUG_ECHOPAIR(".\n.\n.\nover_current threshold : ", (OCD_TH_val + 1) * 375); // first status display
|
||||
DEBUG_ECHOPAIR(" (OCD_TH: : ", OCD_TH_val);
|
||||
if (sh.STATUS_AXIS_LAYOUT != L6474_STATUS_LAYOUT) {
|
||||
DEBUG_ECHOPAIR(") Stall threshold: ", (STALL_TH_val + 1) * 31.25);
|
||||
DEBUG_ECHOPAIR(" (STALL_TH: ", STALL_TH_val);
|
||||
}
|
||||
DEBUG_ECHOLNPGM(")");
|
||||
|
||||
do {
|
||||
|
||||
DEBUG_ECHOPAIR("STALL threshold : ", (stall_th_val + 1) * 31.25);
|
||||
DEBUG_ECHOLNPAIR(" OCD threshold : ", (ocd_th_val + 1) * 375);
|
||||
if (sh.STATUS_AXIS_LAYOUT != L6474_STATUS_LAYOUT) DEBUG_ECHOPAIR("STALL threshold : ", (STALL_TH_val + 1) * 31.25);
|
||||
DEBUG_ECHOLNPAIR(" OCD threshold : ", (OCD_TH_val + 1) * 375);
|
||||
|
||||
jiggle_axis(axis_mon[0][0], position_min, position_max, final_fr_mm_m);
|
||||
sprintf_P(gcode_string, PSTR("G0 %s%03d F%03d"), temp_axis_string, uint16_t(position_min), uint16_t(final_feedrate));
|
||||
gcode.process_subcommands_now_P(gcode_string);
|
||||
|
||||
sprintf_P(gcode_string, PSTR("G0 %s%03d F%03d"), temp_axis_string, uint16_t(position_max), uint16_t(final_feedrate));
|
||||
gcode.process_subcommands_now_P(gcode_string);
|
||||
|
||||
planner.synchronize();
|
||||
|
||||
status_composite = 0; // clear out the old bits
|
||||
|
||||
for (j = 0; j < driver_count; j++) {
|
||||
axis_status[j] = (~L6470.get_status(axis_index[j])) & L6470_ERROR_MASK; // bits of interest are all active low
|
||||
axis_status[j] = (~L64xxManager.get_status(axis_index[j])) & sh.L6470_ERROR_MASK; // bits of interest are all active low
|
||||
status_composite |= axis_status[j];
|
||||
}
|
||||
|
||||
if (status_composite && (status_composite & STATUS_UVLO)) {
|
||||
if (status_composite && (status_composite & sh.STATUS_AXIS_UVLO)) {
|
||||
DEBUG_ECHOLNPGM("Test aborted (Undervoltage lockout active)");
|
||||
for (j = 0; j < driver_count; j++) {
|
||||
DEBUG_ECHOPGM("...");
|
||||
L6470.error_status_decode(axis_status[j], axis_index[j]);
|
||||
}
|
||||
#if ENABLED(L6470_CHITCHAT)
|
||||
for (j = 0; j < driver_count; j++) {
|
||||
if (j) DEBUG_ECHOPGM("...");
|
||||
L64xxManager.error_status_decode(axis_status[j], axis_index[j],
|
||||
sh.STATUS_AXIS_TH_SD, sh.STATUS_AXIS_TH_WRN,
|
||||
sh.STATUS_AXIS_STEP_LOSS_A, sh.STATUS_AXIS_STEP_LOSS_B,
|
||||
sh.STATUS_AXIS_OCD, sh.STATUS_AXIS_LAYOUT);
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
if (status_composite & (STATUS_TH_WRN | STATUS_TH_SD)) {
|
||||
if (status_composite & (sh.STATUS_AXIS_TH_WRN | sh.STATUS_AXIS_TH_SD)) {
|
||||
DEBUG_ECHOLNPGM("thermal problem - waiting for chip(s) to cool down ");
|
||||
uint16_t status_composite_temp = 0;
|
||||
uint8_t k = 0;
|
||||
@ -251,118 +305,136 @@ void GcodeSuite::M917() {
|
||||
k++;
|
||||
if (!(k % 4)) {
|
||||
kval_hold *= 0.95;
|
||||
L6470_EOL();
|
||||
DEBUG_EOL();
|
||||
DEBUG_ECHOLNPAIR("Lowering KVAL_HOLD by about 5% to ", kval_hold);
|
||||
for (j = 0; j < driver_count; j++)
|
||||
L6470.set_param(axis_index[j], L6470_KVAL_HOLD, kval_hold);
|
||||
L64xxManager.set_param(axis_index[j], L6470_KVAL_HOLD, kval_hold);
|
||||
}
|
||||
DEBUG_ECHOLNPGM(".");
|
||||
reset_stepper_timeout(); // reset_stepper_timeout to keep steppers powered
|
||||
watchdog_refresh();
|
||||
gcode.reset_stepper_timeout(); // reset_stepper_timeout to keep steppers powered
|
||||
watchdog_refresh();; // beat the dog
|
||||
safe_delay(5000);
|
||||
status_composite_temp = 0;
|
||||
for (j = 0; j < driver_count; j++) {
|
||||
axis_status[j] = (~L6470.get_status(axis_index[j])) & L6470_ERROR_MASK; // bits of interest are all active low
|
||||
axis_status[j] = (~L64xxManager.get_status(axis_index[j])) & sh.L6470_ERROR_MASK; // bits of interest are all active low
|
||||
status_composite_temp |= axis_status[j];
|
||||
}
|
||||
}
|
||||
while (status_composite_temp & (STATUS_TH_WRN | STATUS_TH_SD));
|
||||
L6470_EOL();
|
||||
while (status_composite_temp & (sh.STATUS_AXIS_TH_WRN | sh.STATUS_AXIS_TH_SD));
|
||||
DEBUG_EOL();
|
||||
}
|
||||
if (status_composite & (STATUS_STEP_LOSS_A | STATUS_STEP_LOSS_B | STATUS_OCD)) {
|
||||
if (status_composite & (sh.STATUS_AXIS_STEP_LOSS_A | sh.STATUS_AXIS_STEP_LOSS_B | sh.STATUS_AXIS_OCD)) {
|
||||
switch (test_phase) {
|
||||
|
||||
case 0: {
|
||||
if (status_composite & STATUS_OCD) {
|
||||
if (status_composite & sh.STATUS_AXIS_OCD) {
|
||||
// phase 0 with OCD warning - time to go to next phase
|
||||
if (ocd_th_val >=15) {
|
||||
ocd_th_val = 15; // limit to max
|
||||
if (OCD_TH_val >= sh.AXIS_OCD_TH_MAX) {
|
||||
OCD_TH_val = sh.AXIS_OCD_TH_MAX; // limit to max
|
||||
test_phase = 2; // at highest value so skip phase 1
|
||||
DEBUG_ECHOLNPGM("LOGIC E0A OCD at highest - skip to 2");
|
||||
//DEBUG_ECHOLNPGM("LOGIC E0A OCD at highest - skip to 2");
|
||||
DEBUG_ECHOLNPGM("OCD at highest - OCD finalized");
|
||||
}
|
||||
else {
|
||||
ocd_th_val++; // normal exit to next phase
|
||||
OCD_TH_val++; // normal exit to next phase
|
||||
test_phase = 1; // setup for first pass of phase 1
|
||||
DEBUG_ECHOLNPGM("LOGIC E0B - inc OCD & go to 1");
|
||||
//DEBUG_ECHOLNPGM("LOGIC E0B - inc OCD & go to 1");
|
||||
DEBUG_ECHOLNPGM("inc OCD");
|
||||
}
|
||||
}
|
||||
else { // phase 0 without OCD warning - keep on decrementing if can
|
||||
if (ocd_th_val) {
|
||||
ocd_th_val--; // try lower value
|
||||
DEBUG_ECHOLNPGM("LOGIC E0C - dec OCD");
|
||||
if (OCD_TH_val) {
|
||||
OCD_TH_val--; // try lower value
|
||||
//DEBUG_ECHOLNPGM("LOGIC E0C - dec OCD");
|
||||
DEBUG_ECHOLNPGM("dec OCD");
|
||||
}
|
||||
else {
|
||||
test_phase = 2; // at lowest value without warning so skip phase 1
|
||||
DEBUG_ECHOLNPGM("LOGIC E0D - OCD at latest - go to 2");
|
||||
//DEBUG_ECHOLNPGM("LOGIC E0D - OCD at latest - go to 2");
|
||||
DEBUG_ECHOLNPGM("OCD finalized");
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case 1: {
|
||||
if (status_composite & STATUS_OCD) {
|
||||
if (status_composite & sh.STATUS_AXIS_OCD) {
|
||||
// phase 1 with OCD warning - increment if can
|
||||
if (ocd_th_val >= 15) {
|
||||
ocd_th_val = 15; // limit to max
|
||||
if (OCD_TH_val >= sh.AXIS_OCD_TH_MAX) {
|
||||
OCD_TH_val = sh.AXIS_OCD_TH_MAX; // limit to max
|
||||
test_phase = 2; // at highest value so go to next phase
|
||||
DEBUG_ECHOLNPGM("LOGIC E1A - OCD at max - go to 2");
|
||||
//DEBUG_ECHOLNPGM("LOGIC E1A - OCD at max - go to 2");
|
||||
DEBUG_ECHOLNPGM("OCD finalized");
|
||||
}
|
||||
else {
|
||||
ocd_th_val++; // try a higher value
|
||||
DEBUG_ECHOLNPGM("LOGIC E1B - inc OCD");
|
||||
OCD_TH_val++; // try a higher value
|
||||
//DEBUG_ECHOLNPGM("LOGIC E1B - inc OCD");
|
||||
DEBUG_ECHOLNPGM("inc OCD");
|
||||
}
|
||||
}
|
||||
else { // phase 1 without OCD warning - normal exit to phase 2
|
||||
test_phase = 2;
|
||||
DEBUG_ECHOLNPGM("LOGIC E1C - no OCD warning - go to 1");
|
||||
//DEBUG_ECHOLNPGM("LOGIC E1C - no OCD warning - go to 1");
|
||||
DEBUG_ECHOLNPGM("OCD finalized");
|
||||
}
|
||||
} break;
|
||||
|
||||
case 2: {
|
||||
if (status_composite & (STATUS_STEP_LOSS_A | STATUS_STEP_LOSS_B)) {
|
||||
if (sh.STATUS_AXIS_LAYOUT == L6474_STATUS_LAYOUT) { // skip all STALL_TH steps if L6474
|
||||
test_phase = 4;
|
||||
break;
|
||||
}
|
||||
if (status_composite & (sh.STATUS_AXIS_STEP_LOSS_A | sh.STATUS_AXIS_STEP_LOSS_B)) {
|
||||
// phase 2 with stall warning - time to go to next phase
|
||||
if (stall_th_val >= 127) {
|
||||
stall_th_val = 127; // limit to max
|
||||
DEBUG_ECHOLNPGM("LOGIC E2A - STALL warning, STALL at max, quit");
|
||||
if (STALL_TH_val >= 127) {
|
||||
STALL_TH_val = 127; // limit to max
|
||||
//DEBUG_ECHOLNPGM("LOGIC E2A - STALL warning, STALL at max, quit");
|
||||
DEBUG_ECHOLNPGM("finished - STALL at maximum value but still have stall warning");
|
||||
test_phase = 4;
|
||||
}
|
||||
else {
|
||||
test_phase = 3; // normal exit to next phase (found failing value of STALL)
|
||||
stall_th_val++; // setup for first pass of phase 3
|
||||
DEBUG_ECHOLNPGM("LOGIC E2B - INC - STALL warning, inc Stall, go to 3");
|
||||
STALL_TH_val++; // setup for first pass of phase 3
|
||||
//DEBUG_ECHOLNPGM("LOGIC E2B - INC - STALL warning, inc Stall, go to 3");
|
||||
DEBUG_ECHOLNPGM("inc Stall");
|
||||
}
|
||||
}
|
||||
else { // phase 2 without stall warning - decrement if can
|
||||
if (stall_th_val) {
|
||||
stall_th_val--; // try a lower value
|
||||
DEBUG_ECHOLNPGM("LOGIC E2C - no STALL, dec STALL");
|
||||
if (STALL_TH_val) {
|
||||
STALL_TH_val--; // try a lower value
|
||||
//DEBUG_ECHOLNPGM("LOGIC E2C - no STALL, dec STALL");
|
||||
DEBUG_ECHOLNPGM("dec STALL");
|
||||
}
|
||||
else {
|
||||
DEBUG_ECHOLNPGM("finished - STALL at lowest value but still do NOT have stall warning");
|
||||
test_phase = 4;
|
||||
DEBUG_ECHOLNPGM("LOGIC E2D - no STALL, at lowest so quit");
|
||||
//DEBUG_ECHOLNPGM("LOGIC E2D - no STALL, at lowest so quit");
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case 3: {
|
||||
if (status_composite & (STATUS_STEP_LOSS_A | STATUS_STEP_LOSS_B)) {
|
||||
if (sh.STATUS_AXIS_LAYOUT == L6474_STATUS_LAYOUT) { // skip all STALL_TH steps if L6474
|
||||
test_phase = 4;
|
||||
break;
|
||||
}
|
||||
if (status_composite & (sh.STATUS_AXIS_STEP_LOSS_A | sh.STATUS_AXIS_STEP_LOSS_B)) {
|
||||
// phase 3 with stall warning - increment if can
|
||||
if (stall_th_val >= 127) {
|
||||
stall_th_val = 127; // limit to max
|
||||
if (STALL_TH_val >= 127) {
|
||||
STALL_TH_val = 127; // limit to max
|
||||
DEBUG_ECHOLNPGM("finished - STALL at maximum value but still have stall warning");
|
||||
test_phase = 4;
|
||||
DEBUG_ECHOLNPGM("LOGIC E3A - STALL, at max so quit");
|
||||
//DEBUG_ECHOLNPGM("LOGIC E3A - STALL, at max so quit");
|
||||
}
|
||||
else {
|
||||
stall_th_val++; // still looking for passing value
|
||||
DEBUG_ECHOLNPGM("LOGIC E3B - STALL, inc stall");
|
||||
STALL_TH_val++; // still looking for passing value
|
||||
//DEBUG_ECHOLNPGM("LOGIC E3B - STALL, inc stall");
|
||||
DEBUG_ECHOLNPGM("inc stall");
|
||||
}
|
||||
}
|
||||
else { //phase 3 without stall warning but have OCD warning
|
||||
DEBUG_ECHOLNPGM("Hardware problem - OCD warning without STALL warning");
|
||||
test_phase = 4;
|
||||
DEBUG_ECHOLNPGM("LOGIC E3C - not STALLED, hardware problem (quit)");
|
||||
//DEBUG_ECHOLNPGM("LOGIC E3C - not STALLED, hardware problem (quit)");
|
||||
}
|
||||
} break;
|
||||
|
||||
@ -372,58 +444,81 @@ void GcodeSuite::M917() {
|
||||
else {
|
||||
switch (test_phase) {
|
||||
case 0: { // phase 0 without OCD warning - keep on decrementing if can
|
||||
if (ocd_th_val) {
|
||||
ocd_th_val--; // try lower value
|
||||
DEBUG_ECHOLNPGM("LOGIC N0A - DEC OCD");
|
||||
if (OCD_TH_val) {
|
||||
OCD_TH_val--; // try lower value
|
||||
//DEBUG_ECHOLNPGM("LOGIC N0A - DEC OCD");
|
||||
DEBUG_ECHOLNPGM("DEC OCD");
|
||||
}
|
||||
else {
|
||||
test_phase = 2; // at lowest value without warning so skip phase 1
|
||||
DEBUG_ECHOLNPGM("LOGIC N0B - OCD at lowest (go to phase 2)");
|
||||
//DEBUG_ECHOLNPGM("LOGIC N0B - OCD at lowest (go to phase 2)");
|
||||
DEBUG_ECHOLNPGM("OCD finalized");
|
||||
}
|
||||
} break;
|
||||
|
||||
case 1: DEBUG_ECHOLNPGM("LOGIC N1 (go directly to 2)"); // phase 1 without OCD warning - drop directly to phase 2
|
||||
case 1: //DEBUG_ECHOLNPGM("LOGIC N1 (go directly to 2)"); // phase 1 without OCD warning - drop directly to phase 2
|
||||
DEBUG_ECHOLNPGM("OCD finalized");
|
||||
|
||||
case 2: { // phase 2 without stall warning - keep on decrementing if can
|
||||
if (stall_th_val) {
|
||||
stall_th_val--; // try a lower value (stay in phase 2)
|
||||
DEBUG_ECHOLNPGM("LOGIC N2B - dec STALL");
|
||||
if (sh.STATUS_AXIS_LAYOUT == L6474_STATUS_LAYOUT) { // skip all STALL_TH steps if L6474
|
||||
test_phase = 4;
|
||||
break;
|
||||
}
|
||||
if (STALL_TH_val) {
|
||||
STALL_TH_val--; // try a lower value (stay in phase 2)
|
||||
//DEBUG_ECHOLNPGM("LOGIC N2B - dec STALL");
|
||||
DEBUG_ECHOLNPGM("dec STALL");
|
||||
}
|
||||
else {
|
||||
DEBUG_ECHOLNPGM("finished - STALL at lowest value but still no stall warning");
|
||||
test_phase = 4;
|
||||
DEBUG_ECHOLNPGM("LOGIC N2C - STALL at lowest (quit)");
|
||||
//DEBUG_ECHOLNPGM("LOGIC N2C - STALL at lowest (quit)");
|
||||
}
|
||||
} break;
|
||||
|
||||
case 3: { test_phase = 4;
|
||||
DEBUG_ECHOLNPGM("LOGIC N3 - finished!");
|
||||
case 3: {
|
||||
if (sh.STATUS_AXIS_LAYOUT == L6474_STATUS_LAYOUT) { // skip all STALL_TH steps if L6474
|
||||
test_phase = 4;
|
||||
break;
|
||||
}
|
||||
test_phase = 4;
|
||||
//DEBUG_ECHOLNPGM("LOGIC N3 - finished!");
|
||||
DEBUG_ECHOLNPGM("finished!");
|
||||
} break; // phase 3 without any warnings - desired exit
|
||||
} //
|
||||
} // end of status checks
|
||||
|
||||
if (test_phase != 4) {
|
||||
for (j = 0; j < driver_count; j++) { // update threshold(s)
|
||||
L6470.set_param(axis_index[j], L6470_OCD_TH, ocd_th_val);
|
||||
L6470.set_param(axis_index[j], L6470_STALL_TH, stall_th_val);
|
||||
if (L6470.get_param(axis_index[j], L6470_OCD_TH) != ocd_th_val) DEBUG_ECHOLNPGM("OCD mismatch");
|
||||
if (L6470.get_param(axis_index[j], L6470_STALL_TH) != stall_th_val) DEBUG_ECHOLNPGM("STALL mismatch");
|
||||
L64xxManager.set_param(axis_index[j], L6470_OCD_TH, OCD_TH_val);
|
||||
if (sh.STATUS_AXIS_LAYOUT != L6474_STATUS_LAYOUT) L64xxManager.set_param(axis_index[j], L6470_STALL_TH, STALL_TH_val);
|
||||
if (L64xxManager.get_param(axis_index[j], L6470_OCD_TH) != OCD_TH_val) DEBUG_ECHOLNPGM("OCD mismatch");
|
||||
if ((L64xxManager.get_param(axis_index[j], L6470_STALL_TH) != STALL_TH_val) && (sh.STATUS_AXIS_LAYOUT != L6474_STATUS_LAYOUT)) DEBUG_ECHOLNPGM("STALL mismatch");
|
||||
}
|
||||
}
|
||||
|
||||
} while (test_phase != 4);
|
||||
|
||||
DEBUG_ECHOLNPGM(".");
|
||||
if (status_composite) {
|
||||
#if ENABLED(L6470_CHITCHAT)
|
||||
for (j = 0; j < driver_count; j++) {
|
||||
if (j) DEBUG_ECHOPGM("...");
|
||||
L64xxManager.error_status_decode(axis_status[j], axis_index[j],
|
||||
sh.STATUS_AXIS_TH_SD, sh.STATUS_AXIS_TH_WRN,
|
||||
sh.STATUS_AXIS_STEP_LOSS_A, sh.STATUS_AXIS_STEP_LOSS_B,
|
||||
sh.STATUS_AXIS_OCD, sh.STATUS_AXIS_LAYOUT);
|
||||
}
|
||||
DEBUG_ECHOLNPGM(".");
|
||||
#endif
|
||||
DEBUG_ECHOLNPGM("Completed with errors");
|
||||
for (j = 0; j < driver_count; j++) {
|
||||
DEBUG_ECHOPGM("...");
|
||||
L6470.error_status_decode(axis_status[j], axis_index[j]);
|
||||
}
|
||||
}
|
||||
else
|
||||
DEBUG_ECHOLNPGM("Completed with no errors");
|
||||
DEBUG_ECHOLNPGM(".");
|
||||
|
||||
} // M917
|
||||
L64xxManager.pause_monitor(false);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
@ -439,7 +534,13 @@ void GcodeSuite::M917() {
|
||||
* I - over current threshold
|
||||
* optional - will report current value from driver if not specified
|
||||
*
|
||||
* K - value for KVAL_HOLD (0 - 255) (optional)
|
||||
* T - current (mA) setting for TVAL (0 - 4A in 31.25mA increments, rounds down) - L6474 only
|
||||
* optional - will report current value from driver if not specified
|
||||
*
|
||||
* K - value for KVAL_HOLD (0 - 255) (ignored for L6474)
|
||||
* optional - will report current value from driver if not specified
|
||||
*
|
||||
* M - value for microsteps (1 - 128) (optional)
|
||||
* optional - will report current value from driver if not specified
|
||||
*
|
||||
*/
|
||||
@ -447,83 +548,109 @@ void GcodeSuite::M918() {
|
||||
|
||||
DEBUG_ECHOLNPGM("M918");
|
||||
|
||||
char axis_mon[3][3] = { " ", " ", " " }; // List of axes to monitor
|
||||
uint8_t axis_index[3];
|
||||
L64xxManager.pause_monitor(true); // Keep monitor_driver() from stealing status
|
||||
|
||||
char axis_mon[3][3] = { {" "}, {" "}, {" "} }; // list of Axes to be monitored
|
||||
L64XX_axis_t axis_index[3];
|
||||
uint16_t axis_status[3];
|
||||
uint8_t driver_count = 1;
|
||||
float position_max, position_min;
|
||||
feedRate_t final_fr_mm_m;
|
||||
float final_feedrate;
|
||||
uint8_t kval_hold;
|
||||
uint8_t ocd_th_val = 0;
|
||||
uint8_t stall_th_val = 0;
|
||||
uint8_t OCD_TH_val = 0;
|
||||
uint8_t STALL_TH_val = 0;
|
||||
uint16_t over_current_threshold;
|
||||
constexpr bool over_current_flag = true;
|
||||
constexpr uint8_t over_current_flag = true;
|
||||
|
||||
const L64XX_Marlin::L64XX_shadow_t &sh = L64xxManager.shadow;
|
||||
|
||||
uint8_t j; // general purpose counter
|
||||
|
||||
if (L6470.get_user_input(driver_count, axis_index, axis_mon, position_max, position_min, final_fr_mm_m, kval_hold, over_current_flag, ocd_th_val, stall_th_val, over_current_threshold))
|
||||
if (L64xxManager.get_user_input(driver_count, axis_index, axis_mon, position_max, position_min, final_feedrate, kval_hold, over_current_flag, OCD_TH_val, STALL_TH_val, over_current_threshold))
|
||||
return; // quit if invalid user input
|
||||
|
||||
L64xxManager.get_status(axis_index[0]); // populate shadow array
|
||||
|
||||
uint8_t m_steps = parser.byteval('M');
|
||||
LIMIT(m_steps, 0, 128);
|
||||
DEBUG_ECHOLNPAIR("M = ", m_steps);
|
||||
|
||||
int8_t m_bits = -1;
|
||||
if (m_steps > 85) m_bits = 7; // 128 (no synch output)
|
||||
else if (m_steps > 42) m_bits = 6; // 64 (no synch output)
|
||||
else if (m_steps > 22) m_bits = 5; // 32 (no synch output)
|
||||
else if (m_steps > 12) m_bits = 4; // 16 (no synch output)
|
||||
else if (m_steps > 5) m_bits = 3; // 8 (no synch output)
|
||||
else if (m_steps > 2) m_bits = 2; // 4 (no synch output)
|
||||
else if (m_steps == 2) m_bits = 1; // 2 (no synch output)
|
||||
else if (m_steps == 1) m_bits = 0; // 1 (no synch output)
|
||||
else if (m_steps == 0) m_bits = 7; // 128 (no synch output)
|
||||
if (m_steps != 0) {
|
||||
LIMIT(m_steps, 1, sh.STATUS_AXIS_LAYOUT == L6474_STATUS_LAYOUT ? 16 : 128); // L6474
|
||||
|
||||
if (m_bits >= 0) {
|
||||
const int micros = _BV(m_bits);
|
||||
if (micros < 100) { DEBUG_CHAR(' '); if (micros < 10) DEBUG_CHAR(' '); }
|
||||
DEBUG_ECHO(micros);
|
||||
DEBUG_ECHOPGM(" uSTEPS");
|
||||
}
|
||||
uint8_t stepVal;
|
||||
for (stepVal = 0; stepVal < 8; stepVal++) { // convert to L64xx register value
|
||||
if (m_steps == 1) break;
|
||||
m_steps >>= 1;
|
||||
}
|
||||
|
||||
for (j = 0; j < driver_count; j++)
|
||||
L6470.set_param(axis_index[j], L6470_STEP_MODE, m_bits); // set microsteps
|
||||
|
||||
DEBUG_ECHOLNPAIR("target (maximum) feedrate = ", final_fr_mm_m);
|
||||
|
||||
planner.synchronize(); // Wait for moves to finish
|
||||
|
||||
for (j = 0; j < driver_count; j++)
|
||||
L6470.get_status(axis_index[j]); // Clear all error flags
|
||||
|
||||
uint16_t status_composite = 0;
|
||||
DEBUG_ECHOLNPGM(".\n.\n."); // Make the feedrate prints easier to see
|
||||
|
||||
constexpr uint8_t iterations = 10;
|
||||
for (uint8_t i = 1; i <= iterations; i++) {
|
||||
const feedRate_t fr_mm_m = i * final_fr_mm_m / iterations;
|
||||
DEBUG_ECHOLNPAIR("...feedrate = ", fr_mm_m);
|
||||
|
||||
jiggle_axis(axis_mon[0][0], position_min, position_max, fr_mm_m);
|
||||
if (sh.STATUS_AXIS_LAYOUT == L6474_STATUS_LAYOUT)
|
||||
stepVal |= 0x98; // NO SYNC
|
||||
else
|
||||
stepVal |= (!SYNC_EN) | SYNC_SEL_1 | stepVal;
|
||||
|
||||
for (j = 0; j < driver_count; j++) {
|
||||
axis_status[j] = (~L6470.get_status(axis_index[j])) & 0x0800; // bits of interest are all active low
|
||||
L64xxManager.set_param(axis_index[j], dSPIN_HARD_HIZ, 0); // can't write STEP register if stepper being powered
|
||||
// results in an extra NOOP being sent (data 00)
|
||||
L64xxManager.set_param(axis_index[j], L6470_STEP_MODE, stepVal); // set microsteps
|
||||
}
|
||||
}
|
||||
m_steps = L64xxManager.get_param(axis_index[0], L6470_STEP_MODE) & 0x07; // get microsteps
|
||||
|
||||
DEBUG_ECHOLNPAIR("Microsteps = ", _BV(m_steps));
|
||||
DEBUG_ECHOLNPAIR("target (maximum) feedrate = ", final_feedrate);
|
||||
|
||||
const float feedrate_inc = final_feedrate / 10, // Start at 1/10 of max & go up by 1/10 per step
|
||||
fr_limit = final_feedrate * 0.99f; // Rounding-safe comparison value
|
||||
float current_feedrate = 0;
|
||||
|
||||
planner.synchronize(); // Wait for moves to complete
|
||||
|
||||
for (j = 0; j < driver_count; j++)
|
||||
L64xxManager.get_status(axis_index[j]); // Clear error flags
|
||||
|
||||
char temp_axis_string[2] = " ";
|
||||
temp_axis_string[0] = axis_mon[0][0]; // Need a sprintf format string
|
||||
//temp_axis_string[1] = '\n';
|
||||
|
||||
char gcode_string[80];
|
||||
uint16_t status_composite = 0;
|
||||
DEBUG_ECHOLNPGM(".\n.\n."); // Make feedrate outputs easier to read
|
||||
|
||||
do {
|
||||
current_feedrate += feedrate_inc;
|
||||
DEBUG_ECHOLNPAIR("...feedrate = ", current_feedrate);
|
||||
|
||||
sprintf_P(gcode_string, PSTR("G0 %s%03d F%03d"), temp_axis_string, uint16_t(position_min), uint16_t(current_feedrate));
|
||||
gcode.process_subcommands_now_P(gcode_string);
|
||||
|
||||
sprintf_P(gcode_string, PSTR("G0 %s%03d F%03d"), temp_axis_string, uint16_t(position_max), uint16_t(current_feedrate));
|
||||
gcode.process_subcommands_now_P(gcode_string);
|
||||
|
||||
planner.synchronize();
|
||||
|
||||
for (j = 0; j < driver_count; j++) {
|
||||
axis_status[j] = (~L64xxManager.get_status(axis_index[j])) & 0x0800; // Bits of interest are all active LOW
|
||||
status_composite |= axis_status[j];
|
||||
}
|
||||
if (status_composite) break; // quit if any errors flags are raised
|
||||
}
|
||||
if (status_composite) break; // Break on any error
|
||||
} while (current_feedrate < fr_limit);
|
||||
|
||||
DEBUG_ECHOPGM("Completed with errors");
|
||||
DEBUG_ECHOPGM("Completed with ");
|
||||
if (status_composite) {
|
||||
DEBUG_ECHOLNPGM("errors");
|
||||
for (j = 0; j < driver_count; j++) {
|
||||
DEBUG_ECHOPGM("...");
|
||||
L6470.error_status_decode(axis_status[j], axis_index[j]);
|
||||
}
|
||||
#if ENABLED(L6470_CHITCHAT)
|
||||
for (j = 0; j < driver_count; j++) {
|
||||
if (j) DEBUG_ECHOPGM("...");
|
||||
L64xxManager.error_status_decode(axis_status[j], axis_index[j],
|
||||
sh.STATUS_AXIS_TH_SD, sh.STATUS_AXIS_TH_WRN,
|
||||
sh.STATUS_AXIS_STEP_LOSS_A, sh.STATUS_AXIS_STEP_LOSS_B,
|
||||
sh.STATUS_AXIS_OCD, sh.STATUS_AXIS_LAYOUT);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
DEBUG_ECHOLNPGM("no errors");
|
||||
|
||||
} // M918
|
||||
L64xxManager.pause_monitor(false);
|
||||
}
|
||||
|
||||
#endif // HAS_DRIVER(L6470)
|
||||
#endif // HAS_L64XX
|
||||
|
@ -786,7 +786,7 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAS_DRIVER(L6470)
|
||||
#if HAS_L64XX
|
||||
case 122: M122(); break; // M122: Report status
|
||||
case 906: M906(); break; // M906: Set or get motor drive level
|
||||
case 916: M916(); break; // M916: L6470 tuning: Increase drive level until thermal warning
|
||||
|
@ -896,7 +896,7 @@ private:
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAS_DRIVER(L6470)
|
||||
#if HAS_L64XX
|
||||
static void M122();
|
||||
static void M906();
|
||||
static void M916();
|
||||
|
@ -28,10 +28,8 @@
|
||||
|
||||
#if ENABLED(M114_DETAIL)
|
||||
|
||||
#if HAS_DRIVER(L6470)
|
||||
//C:\Users\bobku\Documents\GitHub\Marlin-Bob-2\Marlin\src\gcode\host\M114.cpp
|
||||
//C:\Users\bobku\Documents\GitHub\Marlin-Bob-2\Marlin\src\module\bob_L6470.cpp
|
||||
#include "../../libs/L6470/L6470_Marlin.h"
|
||||
#if HAS_L64XX
|
||||
#include "../../libs/L64XX/L64XX_Marlin.h"
|
||||
#define DEBUG_OUT ENABLED(L6470_CHITCHAT)
|
||||
#include "../../core/debug_out.h"
|
||||
#endif
|
||||
@ -88,13 +86,13 @@
|
||||
|
||||
planner.synchronize();
|
||||
|
||||
#if HAS_DRIVER(L6470)
|
||||
#if HAS_L64XX
|
||||
char temp_buf[80];
|
||||
int32_t temp;
|
||||
//#define ABS_POS_SIGN_MASK 0b1111 1111 1110 0000 0000 0000 0000 0000
|
||||
#define ABS_POS_SIGN_MASK 0b11111111111000000000000000000000
|
||||
#define REPORT_ABSOLUTE_POS(Q) do{ \
|
||||
L6470.say_axis(Q, false); \
|
||||
L64xxManager.say_axis(Q, false); \
|
||||
temp = L6470_GETPARAM(L6470_ABS_POS,Q); \
|
||||
if (temp & ABS_POS_SIGN_MASK) temp |= ABS_POS_SIGN_MASK; \
|
||||
sprintf_P(temp_buf, PSTR(":%8ld "), temp); \
|
||||
@ -102,47 +100,47 @@
|
||||
}while(0)
|
||||
|
||||
DEBUG_ECHOPGM("\nL6470:");
|
||||
#if AXIS_DRIVER_TYPE_X(L6470)
|
||||
#if AXIS_IS_L64XX(X)
|
||||
REPORT_ABSOLUTE_POS(X);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_X2(L6470)
|
||||
#if AXIS_IS_L64XX(X2)
|
||||
REPORT_ABSOLUTE_POS(X2);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_Y(L6470)
|
||||
#if AXIS_IS_L64XX(Y)
|
||||
REPORT_ABSOLUTE_POS(Y);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_Y2(L6470)
|
||||
#if AXIS_IS_L64XX(Y2)
|
||||
REPORT_ABSOLUTE_POS(Y2);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_Z(L6470)
|
||||
#if AXIS_IS_L64XX(Z)
|
||||
REPORT_ABSOLUTE_POS(Z);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_Z2(L6470)
|
||||
#if AXIS_IS_L64XX(Z2)
|
||||
REPORT_ABSOLUTE_POS(Z2);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_Z3(L6470)
|
||||
#if AXIS_IS_L64XX(Z3)
|
||||
REPORT_ABSOLUTE_POS(Z3);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E0(L6470)
|
||||
#if AXIS_IS_L64XX(E0)
|
||||
REPORT_ABSOLUTE_POS(E0);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E1(L6470)
|
||||
#if AXIS_IS_L64XX(E1)
|
||||
REPORT_ABSOLUTE_POS(E1);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E2(L6470)
|
||||
#if AXIS_IS_L64XX(E2)
|
||||
REPORT_ABSOLUTE_POS(E2);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E3(L6470)
|
||||
#if AXIS_IS_L64XX(E3)
|
||||
REPORT_ABSOLUTE_POS(E3);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E4(L6470)
|
||||
#if AXIS_IS_L64XX(E4)
|
||||
REPORT_ABSOLUTE_POS(E4);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E5(L6470)
|
||||
#if AXIS_IS_L64XX(E5)
|
||||
REPORT_ABSOLUTE_POS(E5);
|
||||
#endif
|
||||
SERIAL_EOL();
|
||||
#endif // HAS_DRIVER(L6470)
|
||||
#endif // HAS_L64XX
|
||||
|
||||
SERIAL_ECHOPGM("Stepper:");
|
||||
LOOP_XYZE(i) {
|
||||
|
Reference in New Issue
Block a user