L6470 SPI daisy chain support (#12895)
This commit is contained in:
@ -45,6 +45,10 @@
|
||||
|
||||
#include "../../lcd/ultralcd.h"
|
||||
|
||||
#if HAS_DRIVER(L6470) // set L6470 absolute position registers to counts
|
||||
#include "../../libs/L6470/L6470_Marlin.h"
|
||||
#endif
|
||||
|
||||
#if ENABLED(QUICK_HOME)
|
||||
|
||||
static void quick_home_xy() {
|
||||
@ -440,4 +444,12 @@ void GcodeSuite::G28(const bool always_home_all) {
|
||||
#if ENABLED(DEBUG_LEVELING_FEATURE)
|
||||
if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("<<< G28");
|
||||
#endif
|
||||
|
||||
#if HAS_DRIVER(L6470)
|
||||
// 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]));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ void GcodeSuite::M18_M84() {
|
||||
if (parser.seen('Y')) disable_Y();
|
||||
if (parser.seen('Z')) disable_Z();
|
||||
// Only disable on boards that have separate ENABLE_PINS or another method for disabling the driver
|
||||
#if (E0_ENABLE_PIN != X_ENABLE_PIN && E1_ENABLE_PIN != Y_ENABLE_PIN) || AXIS_DRIVER_TYPE(E0, TMC2660) || AXIS_DRIVER_TYPE(E1, TMC2660) || AXIS_DRIVER_TYPE(E2, TMC2660) || AXIS_DRIVER_TYPE(E3, TMC2660) || AXIS_DRIVER_TYPE(E4, TMC2660) || AXIS_DRIVER_TYPE(E5, TMC2660)
|
||||
#if (E0_ENABLE_PIN != X_ENABLE_PIN && E1_ENABLE_PIN != Y_ENABLE_PIN) || AXIS_DRIVER_TYPE_E0(TMC2660) || AXIS_DRIVER_TYPE_E1(TMC2660) || AXIS_DRIVER_TYPE_E2(TMC2660) || AXIS_DRIVER_TYPE_E3(TMC2660) || AXIS_DRIVER_TYPE_E4(TMC2660) || AXIS_DRIVER_TYPE_E5(TMC2660)
|
||||
if (parser.seen('E')) disable_e_steppers();
|
||||
#endif
|
||||
}
|
||||
|
115
Marlin/src/gcode/feature/L6470/M122.cpp
Normal file
115
Marlin/src/gcode/feature/L6470/M122.cpp
Normal file
@ -0,0 +1,115 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../../../inc/MarlinConfig.h"
|
||||
|
||||
#if HAS_DRIVER(L6470)
|
||||
|
||||
#include "../../gcode.h"
|
||||
#include "../../../libs/L6470/L6470_Marlin.h"
|
||||
#include "../../../module/stepper_indirection.h"
|
||||
|
||||
inline void echo_yes_no(const bool yes) { serialprintPGM(yes ? PSTR(" YES") : PSTR(" NO ")); }
|
||||
|
||||
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);
|
||||
#if ENABLED(L6470_CHITCHAT)
|
||||
char temp_buf[20];
|
||||
sprintf_P(temp_buf, PSTR(" status: %4x "), status);
|
||||
SERIAL_ECHO(temp_buf);
|
||||
print_bin(status);
|
||||
#endif
|
||||
SERIAL_ECHOPGM("\n...OUTPUT: ");
|
||||
serialprintPGM(status & STATUS_HIZ ? PSTR("OFF") : PSTR("ON "));
|
||||
SERIAL_ECHOPGM(" BUSY: "); echo_yes_no(!(status & STATUS_BUSY));
|
||||
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);
|
||||
SERIAL_EOL();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
|
||||
//if (parser.seen('S'))
|
||||
// tmc_set_report_status(parser.value_bool());
|
||||
//else
|
||||
|
||||
#if AXIS_DRIVER_TYPE_X(L6470)
|
||||
L6470_SAY_STATUS(X);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_X2(L6470)
|
||||
L6470_SAY_STATUS(X2);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_Y(L6470)
|
||||
L6470_SAY_STATUS(Y);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_Y2(L6470)
|
||||
L6470_SAY_STATUS(Y2);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_Z(L6470)
|
||||
L6470_SAY_STATUS(Z);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_Z2(L6470)
|
||||
L6470_SAY_STATUS(Z2);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_Z3(L6470)
|
||||
L6470_SAY_STATUS(Z3);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E0(L6470)
|
||||
L6470_SAY_STATUS(E0);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E1(L6470)
|
||||
L6470_SAY_STATUS(E1);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E2(L6470)
|
||||
L6470_SAY_STATUS(E2);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E3(L6470)
|
||||
L6470_SAY_STATUS(E3);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E4(L6470)
|
||||
L6470_SAY_STATUS(E4);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E5(L6470)
|
||||
L6470_SAY_STATUS(E5);
|
||||
#endif
|
||||
|
||||
L6470.spi_active = false; // done with all SPI transfers - clear handshake flags
|
||||
L6470.spi_abort = false;
|
||||
}
|
||||
|
||||
#endif // HAS_DRIVER(L6470)
|
259
Marlin/src/gcode/feature/L6470/M906.cpp
Normal file
259
Marlin/src/gcode/feature/L6470/M906.cpp
Normal file
@ -0,0 +1,259 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (C) 2018 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../../../inc/MarlinConfig.h"
|
||||
|
||||
#if HAS_DRIVER(L6470)
|
||||
|
||||
#include "../../gcode.h"
|
||||
#include "../../../libs/L6470/L6470_Marlin.h"
|
||||
#include "../../../module/stepper_indirection.h"
|
||||
#include "../../../module/planner.h"
|
||||
|
||||
/**
|
||||
*
|
||||
* M906: report or set KVAL_HOLD which sets the maximum effective voltage provided by the
|
||||
* PWMs to the steppers
|
||||
*
|
||||
* 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
|
||||
* 2 - monitor only X2, Y2, Z2 or E2
|
||||
* 3 - monitor only Z3 or E3
|
||||
* 4 - monitor only E4
|
||||
* 5 - monitor only E5
|
||||
* Xxxx, Yxxx, Zxxx, Exxx - axis to be monitored with displacement
|
||||
* xxx (1-255) is distance moved on either side of current position
|
||||
*
|
||||
* I - over current threshold
|
||||
* optional - will report current value from driver if not specified
|
||||
*
|
||||
* K - value for KVAL_HOLD (0 - 255) (optional)
|
||||
* optional - will report current value from driver if not specified
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Sets KVAL_HOLD wich affects the current being driven through the stepper.
|
||||
*
|
||||
* L6470 is used in the STEP-CLOCK mode. KVAL_HOLD is the only KVAL_xxx
|
||||
* that affects the effective voltage seen by the stepper.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* MACRO to fetch information on the items associated with current limiting
|
||||
* and maximum voltage output.
|
||||
*
|
||||
* L6470 can be setup to shutdown if either current threshold is exceeded.
|
||||
*
|
||||
* L6470 output current can not be set directly. It is set indirectly by
|
||||
* setting the maximum effective output voltage.
|
||||
*
|
||||
* Effective output voltage is set by PWM duty cycle.
|
||||
*
|
||||
* Maximum effective output voltage is affected by MANY variables. The main ones are:
|
||||
* KVAL_HOLD
|
||||
* KVAL_RUN
|
||||
* KVAL_ACC
|
||||
* KVAL_DEC
|
||||
* Vs compensation (if enabled)
|
||||
*/
|
||||
|
||||
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);
|
||||
SERIAL_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);
|
||||
sprintf_P(temp_buf, PSTR(" Stall Threshold: %2d (%7.2f mA)"), stall_threshold, (stall_threshold + 1) * 31.25);
|
||||
SERIAL_ECHO(temp_buf);
|
||||
SERIAL_ECHOPGM(" Motor Status: ");
|
||||
const char * const 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;
|
||||
}
|
||||
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"));
|
||||
sprintf_P(temp_buf, PSTR(" Compensation coefficient: ~%4.2f\n"), comp_coef * 0.01f);
|
||||
SERIAL_ECHO(temp_buf);
|
||||
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 = ");
|
||||
switch (motor_status) {
|
||||
case 0: sprintf_P(temp_buf, PSTR(" %4.1f%% (KVAL_HOLD)\n"), float(motor.GetParam(L6470_KVAL_HOLD)) * 100 / 256); break;
|
||||
case 1: sprintf_P(temp_buf, PSTR(" %4.1f%% (KVAL_RUN) \n"), float(motor.GetParam(L6470_KVAL_RUN)) * 100 / 256); break;
|
||||
case 2: sprintf_P(temp_buf, PSTR(" %4.1f%% (KVAL_ACC) \n"), float(motor.GetParam(L6470_KVAL_ACC)) * 100 / 256); break;
|
||||
case 3: sprintf_P(temp_buf, PSTR(" %4.1f%% (KVAL_DEC) \n"), float(motor.GetParam(L6470_KVAL_DEC)) * 100 / 256); break;
|
||||
}
|
||||
SERIAL_ECHO(temp_buf);
|
||||
}
|
||||
|
||||
void GcodeSuite::M906() {
|
||||
#define L6470_SET_KVAL_HOLD(Q) stepper##Q.SetParam(L6470_KVAL_HOLD, value)
|
||||
|
||||
L6470_ECHOLNPGM("M906");
|
||||
|
||||
bool report_current = true;
|
||||
|
||||
#if HAS_DRIVER(L6470)
|
||||
const uint8_t index = parser.byteval('I');
|
||||
#endif
|
||||
|
||||
LOOP_XYZE(i) if (uint8_t value = parser.byteval(axis_codes[i])) {
|
||||
|
||||
report_current = false;
|
||||
|
||||
if (planner.has_blocks_queued() || planner.cleaning_buffer_counter) {
|
||||
SERIAL_ECHOLNPGM("ERROR - can't set KVAL_HOLD while steppers are moving");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (i) {
|
||||
case X_AXIS:
|
||||
#if AXIS_DRIVER_TYPE_X(L6470)
|
||||
if (index == 0) L6470_SET_KVAL_HOLD(X);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_X2(L6470)
|
||||
if (index == 1) L6470_SET_KVAL_HOLD(X2);
|
||||
#endif
|
||||
break;
|
||||
case Y_AXIS:
|
||||
#if AXIS_DRIVER_TYPE_Y(L6470)
|
||||
if (index == 0) L6470_SET_KVAL_HOLD(Y);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_Y2(L6470)
|
||||
if (index == 1) L6470_SET_KVAL_HOLD(Y2);
|
||||
#endif
|
||||
break;
|
||||
case Z_AXIS:
|
||||
#if AXIS_DRIVER_TYPE_Z(L6470)
|
||||
if (index == 0) L6470_SET_KVAL_HOLD(Z);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_Z2(L6470)
|
||||
if (index == 1) L6470_SET_KVAL_HOLD(Z2);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_Z3(L6470)
|
||||
if (index == 2) L6470_SET_KVAL_HOLD(Z3);
|
||||
#endif
|
||||
break;
|
||||
case E_AXIS: {
|
||||
const int8_t target_extruder = get_target_extruder_from_command();
|
||||
if (target_extruder < 0) return;
|
||||
switch (target_extruder) {
|
||||
#if AXIS_DRIVER_TYPE_E0(L6470)
|
||||
case 0: L6470_SET_KVAL_HOLD(E0); break;
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E1(L6470)
|
||||
case 1: L6470_SET_KVAL_HOLD(E1); break;
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E2(L6470)
|
||||
case 2: L6470_SET_KVAL_HOLD(E2); break;
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E3(L6470)
|
||||
case 3: L6470_SET_KVAL_HOLD(E3); break;
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E4(L6470)
|
||||
case 4: L6470_SET_KVAL_HOLD(E4); break;
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E5(L6470)
|
||||
case 5: L6470_SET_KVAL_HOLD(E5); break;
|
||||
#endif
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
#if AXIS_DRIVER_TYPE_X(L6470)
|
||||
L6470_REPORT_CURRENT(X);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_X2(L6470)
|
||||
L6470_REPORT_CURRENT(X2);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_Y(L6470)
|
||||
L6470_REPORT_CURRENT(Y);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_Y2(L6470)
|
||||
L6470_REPORT_CURRENT(Y2);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_Z(L6470)
|
||||
L6470_REPORT_CURRENT(Z);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_Z2(L6470)
|
||||
L6470_REPORT_CURRENT(Z2);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_Z3(L6470)
|
||||
L6470_REPORT_CURRENT(Z3);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E0(L6470)
|
||||
L6470_REPORT_CURRENT(E0);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E1(L6470)
|
||||
L6470_REPORT_CURRENT(E1);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E2(L6470)
|
||||
L6470_REPORT_CURRENT(E2);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E3(L6470)
|
||||
L6470_REPORT_CURRENT(E3);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E4(L6470)
|
||||
L6470_REPORT_CURRENT(E4);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E5(L6470)
|
||||
L6470_REPORT_CURRENT(E5);
|
||||
#endif
|
||||
|
||||
L6470.spi_active = false; // done with all SPI transfers - clear handshake flags
|
||||
L6470.spi_abort = false;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // HAS_DRIVER(L6470)
|
544
Marlin/src/gcode/feature/L6470/M916-918.cpp
Normal file
544
Marlin/src/gcode/feature/L6470/M916-918.cpp
Normal file
@ -0,0 +1,544 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (C) 2018 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../../../inc/MarlinConfig.h"
|
||||
|
||||
#if HAS_DRIVER(L6470)
|
||||
|
||||
#include "../../gcode.h"
|
||||
#include "../../../module/stepper_indirection.h"
|
||||
#include "../../../module/planner.h"
|
||||
#include "../../../libs/L6470/L6470_Marlin.h"
|
||||
|
||||
/**
|
||||
*
|
||||
* M916: increase KVAL_HOLD until get thermal warning
|
||||
*
|
||||
*
|
||||
* 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, E1
|
||||
* 2 - monitor only X2, Y2, Z2, E2
|
||||
* 3 - monitor only Z3, E3
|
||||
*
|
||||
* Xxxx, Yxxx, Zxxx, Exxx - axis to be monitored with displacement
|
||||
* xxx (1-255) is distance moved on either side of current position
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* This routine is also useful for determining the approximate KVAL_HOLD
|
||||
* where the stepper stops losing steps. The sound will get noticeably quieter
|
||||
* as it stops losing steps.
|
||||
*/
|
||||
|
||||
void GcodeSuite::M916() {
|
||||
|
||||
L6470_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];
|
||||
uint16_t axis_status[3];
|
||||
uint8_t driver_count = 1;
|
||||
float position_max;
|
||||
float position_min;
|
||||
float final_feedrate;
|
||||
uint8_t kval_hold;
|
||||
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
|
||||
|
||||
uint8_t j; // general purpose counter
|
||||
|
||||
if (L6470.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
|
||||
|
||||
L6470_ECHOLNPAIR("feedrate = ", final_feedrate);
|
||||
|
||||
planner.synchronize(); // wait for all current movement commands to complete
|
||||
|
||||
for (j = 0; j < driver_count; j++)
|
||||
L6470.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;
|
||||
|
||||
L6470_ECHOLNPGM(".\n.");
|
||||
|
||||
do {
|
||||
|
||||
L6470_ECHOLNPAIR("kval_hold = ", kval_hold); // set & report KVAL_HOLD for this run
|
||||
|
||||
for (j = 0; j < driver_count; j++)
|
||||
L6470.set_param(axis_index[j], L6470_KVAL_HOLD, kval_hold);
|
||||
|
||||
// turn the motor(s) both directions
|
||||
sprintf_P(gcode_string, PSTR("G0 %s%4.3f F%4.3f"), temp_axis_string, position_min, final_feedrate);
|
||||
gcode.process_subcommands_now_P(gcode_string);
|
||||
|
||||
sprintf_P(gcode_string, PSTR("G0 %s%4.3f F%4.3f"), temp_axis_string, position_max, final_feedrate);
|
||||
gcode.process_subcommands_now_P(gcode_string);
|
||||
|
||||
// get the status after the motors have stopped
|
||||
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
|
||||
status_composite |= axis_status[j] ;
|
||||
}
|
||||
|
||||
if (status_composite && (status_composite & STATUS_UVLO)) {
|
||||
L6470_ECHOLNPGM("Test aborted (Undervoltage lockout active)");
|
||||
for (j = 0; j < driver_count; j++) {
|
||||
L6470_ECHOPGM("...");
|
||||
L6470.error_status_decode(axis_status[j], axis_index[j]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// increment KVAL_HOLD if not yet at thermal warning/shutdown
|
||||
if (!(status_composite & (STATUS_TH_WRN | STATUS_TH_SD)))
|
||||
kval_hold++;
|
||||
|
||||
} while (!(status_composite & (STATUS_TH_WRN | STATUS_TH_SD)) && kval_hold); // exit when kval_hold == 0 (rolls over)
|
||||
|
||||
L6470_ECHOPGM(".\n.\nThermal warning/shutdown ");
|
||||
if ((status_composite & (STATUS_TH_WRN | STATUS_TH_SD))) {
|
||||
L6470_ECHOLNPGM("has occurred");
|
||||
for (j = 0; j < driver_count; j++) {
|
||||
L6470_ECHOPGM("...");
|
||||
L6470.error_status_decode(axis_status[j], axis_index[j]);
|
||||
}
|
||||
}
|
||||
else
|
||||
L6470_ECHOLNPGM("(Unable to get)");
|
||||
|
||||
L6470_ECHOLNPGM(".");
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* M917: Find minimum current thresholds
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* 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, E1
|
||||
* 2 - monitor only X2, Y2, Z2, E2
|
||||
* Xxxx, Yxxx, Zxxx, Exxx - axis to be monitored with displacement
|
||||
* xxx (1-255) is distance moved on either side of current position
|
||||
*
|
||||
* F - feedrate
|
||||
* optional - will use default max feedrate from Configuration.h if not specified
|
||||
*
|
||||
* I - starting over-current threshold
|
||||
* 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)
|
||||
* optional - will report current value from driver if not specified
|
||||
*
|
||||
*/
|
||||
void GcodeSuite::M917() {
|
||||
|
||||
L6470_ECHOLNPGM("M917");
|
||||
|
||||
char axis_mon[3][3] = { " ", " ", " " }; // list of axes to be monitored
|
||||
uint8_t axis_index[3];
|
||||
uint16_t axis_status[3];
|
||||
uint8_t driver_count = 1;
|
||||
float position_max;
|
||||
float position_min;
|
||||
float final_feedrate;
|
||||
uint8_t kval_hold;
|
||||
uint8_t ocd_th_val = 0;
|
||||
uint8_t stall_th_val = 0;
|
||||
uint16_t over_current_threshold;
|
||||
constexpr bool 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_feedrate, kval_hold, over_current_flag, ocd_th_val, stall_th_val, over_current_threshold))
|
||||
return; // quit if invalid user input
|
||||
|
||||
L6470_ECHOLNPAIR("feedrate = ", final_feedrate);
|
||||
|
||||
planner.synchronize(); // wait for all current movement commands to complete
|
||||
for (j = 0; j < driver_count; j++)
|
||||
L6470.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;
|
||||
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
|
||||
L6470_ECHOPAIR(".\n.\n.\nover_current threshold : ", (ocd_th_val + 1) * 375); // first status display
|
||||
L6470_ECHOPAIR(" (OCD_TH: : ", ocd_th_val);
|
||||
L6470_ECHOPAIR(") Stall threshold: ", (stall_th_val + 1) * 31.25);
|
||||
L6470_ECHOPAIR(" (STALL_TH: ", stall_th_val);
|
||||
L6470_ECHOLNPGM(")");
|
||||
|
||||
do {
|
||||
|
||||
L6470_ECHOPAIR("STALL threshold : ", (stall_th_val + 1) * 31.25);
|
||||
L6470_ECHOLNPAIR(" OCD threshold : ", (ocd_th_val + 1) * 375);
|
||||
|
||||
sprintf_P(gcode_string, PSTR("G0 %s%4.3f F%4.3f"), temp_axis_string, position_min, final_feedrate);
|
||||
gcode.process_subcommands_now_P(gcode_string);
|
||||
|
||||
sprintf_P(gcode_string, PSTR("G0 %s%4.3f F%4.3f"), temp_axis_string, position_max, 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
|
||||
status_composite |= axis_status[j];
|
||||
}
|
||||
|
||||
if (status_composite && (status_composite & STATUS_UVLO)) {
|
||||
L6470_ECHOLNPGM("Test aborted (Undervoltage lockout active)");
|
||||
for (j = 0; j < driver_count; j++) {
|
||||
L6470_ECHOPGM("...");
|
||||
L6470.error_status_decode(axis_status[j], axis_index[j]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (status_composite & (STATUS_TH_WRN | STATUS_TH_SD)) {
|
||||
L6470_ECHOLNPGM("thermal problem - waiting for chip(s) to cool down ");
|
||||
uint16_t status_composite_temp = 0;
|
||||
uint8_t k = 0;
|
||||
do {
|
||||
k++;
|
||||
if (!(k % 4)) {
|
||||
kval_hold *= 0.95;
|
||||
L6470_EOL();
|
||||
L6470_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);
|
||||
}
|
||||
L6470_ECHOLNPGM(".");
|
||||
gcode.reset_stepper_timeout(); // reset_stepper_timeout to keep steppers powered
|
||||
watchdog_reset(); // 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
|
||||
status_composite_temp |= axis_status[j];
|
||||
}
|
||||
}
|
||||
while (status_composite_temp & (STATUS_TH_WRN | STATUS_TH_SD));
|
||||
L6470_EOL();
|
||||
}
|
||||
if (status_composite & (STATUS_STEP_LOSS_A | STATUS_STEP_LOSS_B | STATUS_OCD)) {
|
||||
switch (test_phase) {
|
||||
|
||||
case 0: {
|
||||
if (status_composite & STATUS_OCD) {
|
||||
// phase 0 with OCD warning - time to go to next phase
|
||||
if (ocd_th_val >=15) {
|
||||
ocd_th_val = 15; // limit to max
|
||||
test_phase = 2; // at highest value so skip phase 1
|
||||
L6470_ECHOLNPGM("LOGIC E0A OCD at highest - skip to 2");
|
||||
}
|
||||
else {
|
||||
ocd_th_val++; // normal exit to next phase
|
||||
test_phase = 1; // setup for first pass of phase 1
|
||||
L6470_ECHOLNPGM("LOGIC E0B - inc OCD & go to 1");
|
||||
}
|
||||
}
|
||||
else { // phase 0 without OCD warning - keep on decrementing if can
|
||||
if (ocd_th_val) {
|
||||
ocd_th_val--; // try lower value
|
||||
L6470_ECHOLNPGM("LOGIC E0C - dec OCD");
|
||||
}
|
||||
else {
|
||||
test_phase = 2; // at lowest value without warning so skip phase 1
|
||||
L6470_ECHOLNPGM("LOGIC E0D - OCD at latest - go to 2");
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case 1: {
|
||||
if (status_composite & STATUS_OCD) {
|
||||
// phase 1 with OCD warning - increment if can
|
||||
if (ocd_th_val >= 15) {
|
||||
ocd_th_val = 15; // limit to max
|
||||
test_phase = 2; // at highest value so go to next phase
|
||||
L6470_ECHOLNPGM("LOGIC E1A - OCD at max - go to 2");
|
||||
}
|
||||
else {
|
||||
ocd_th_val++; // try a higher value
|
||||
L6470_ECHOLNPGM("LOGIC E1B - inc OCD");
|
||||
}
|
||||
}
|
||||
else { // phase 1 without OCD warning - normal exit to phase 2
|
||||
test_phase = 2;
|
||||
L6470_ECHOLNPGM("LOGIC E1C - no OCD warning - go to 1");
|
||||
}
|
||||
} break;
|
||||
|
||||
case 2: {
|
||||
if (status_composite & (STATUS_STEP_LOSS_A | STATUS_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
|
||||
L6470_ECHOLNPGM("LOGIC E2A - STALL warning, STALL at max, quit");
|
||||
L6470_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
|
||||
L6470_ECHOLNPGM("LOGIC E2B - INC - STALL warning, inc Stall, go to 3");
|
||||
}
|
||||
}
|
||||
else { // phase 2 without stall warning - decrement if can
|
||||
if (stall_th_val) {
|
||||
stall_th_val--; // try a lower value
|
||||
L6470_ECHOLNPGM("LOGIC E2C - no STALL, dec STALL");
|
||||
}
|
||||
else {
|
||||
L6470_ECHOLNPGM("finished - STALL at lowest value but still do NOT have stall warning");
|
||||
test_phase = 4;
|
||||
L6470_ECHOLNPGM("LOGIC E2D - no STALL, at lowest so quit");
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case 3: {
|
||||
if (status_composite & (STATUS_STEP_LOSS_A | STATUS_STEP_LOSS_B)) {
|
||||
// phase 3 with stall warning - increment if can
|
||||
if (stall_th_val >= 127) {
|
||||
stall_th_val = 127; // limit to max
|
||||
L6470_ECHOLNPGM("finished - STALL at maximum value but still have stall warning");
|
||||
test_phase = 4;
|
||||
L6470_ECHOLNPGM("LOGIC E3A - STALL, at max so quit");
|
||||
}
|
||||
else {
|
||||
stall_th_val++; // still looking for passing value
|
||||
L6470_ECHOLNPGM("LOGIC E3B - STALL, inc stall");
|
||||
}
|
||||
}
|
||||
else { //phase 3 without stall warning but have OCD warning
|
||||
L6470_ECHOLNPGM("Hardware problem - OCD warning without STALL warning");
|
||||
test_phase = 4;
|
||||
L6470_ECHOLNPGM("LOGIC E3C - not STALLED, hardware problem (quit)");
|
||||
}
|
||||
} break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
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
|
||||
L6470_ECHOLNPGM("LOGIC N0A - DEC OCD");
|
||||
}
|
||||
else {
|
||||
test_phase = 2; // at lowest value without warning so skip phase 1
|
||||
L6470_ECHOLNPGM("LOGIC N0B - OCD at lowest (go to phase 2)");
|
||||
}
|
||||
} break;
|
||||
|
||||
case 1: L6470_ECHOLNPGM("LOGIC N1 (go directly to 2)"); // phase 1 without OCD warning - drop directly to phase 2
|
||||
|
||||
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)
|
||||
L6470_ECHOLNPGM("LOGIC N2B - dec STALL");
|
||||
}
|
||||
else {
|
||||
L6470_ECHOLNPGM("finished - STALL at lowest value but still no stall warning");
|
||||
test_phase = 4;
|
||||
L6470_ECHOLNPGM("LOGIC N2C - STALL at lowest (quit)");
|
||||
}
|
||||
} break;
|
||||
|
||||
case 3: { test_phase = 4;
|
||||
L6470_ECHOLNPGM("LOGIC N3 - 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) L6470_ECHOLNPGM("OCD mismatch");
|
||||
if (L6470.get_param(axis_index[j], L6470_STALL_TH) != stall_th_val) L6470_ECHOLNPGM("STALL mismatch");
|
||||
}
|
||||
}
|
||||
|
||||
} while (test_phase != 4);
|
||||
|
||||
if (status_composite) {
|
||||
L6470_ECHOLNPGM("Completed with errors");
|
||||
for (j = 0; j < driver_count; j++) {
|
||||
L6470_ECHOPGM("...");
|
||||
L6470.error_status_decode(axis_status[j], axis_index[j]);
|
||||
}
|
||||
}
|
||||
else
|
||||
L6470_ECHOLNPGM("Completed with no errors");
|
||||
|
||||
} // M917
|
||||
|
||||
/**
|
||||
*
|
||||
* M918: increase speed until error or max feedrate achieved (as shown in configuration.h))
|
||||
*
|
||||
* 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, E1
|
||||
* 2 - monitor only X2, Y2, Z2, E2
|
||||
* Xxxx, Yxxx, Zxxx, Exxx - axis to be monitored with displacement
|
||||
* xxx (1-255) is distance moved on either side of current position
|
||||
*
|
||||
* I - over current threshold
|
||||
* optional - will report current value from driver if not specified
|
||||
*
|
||||
* K - value for KVAL_HOLD (0 - 255) (optional)
|
||||
* optional - will report current value from driver if not specified
|
||||
*
|
||||
*/
|
||||
void GcodeSuite::M918() {
|
||||
|
||||
L6470_ECHOLNPGM("M918");
|
||||
|
||||
char axis_mon[3][3] = { " ", " ", " " }; // List of axes to monitor
|
||||
uint8_t axis_index[3];
|
||||
uint16_t axis_status[3];
|
||||
uint8_t driver_count = 1;
|
||||
float position_max, position_min;
|
||||
float final_feedrate;
|
||||
uint8_t kval_hold;
|
||||
uint8_t ocd_th_val = 0;
|
||||
uint8_t stall_th_val = 0;
|
||||
uint16_t over_current_threshold;
|
||||
constexpr bool 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_feedrate, kval_hold, over_current_flag, ocd_th_val, stall_th_val, over_current_threshold))
|
||||
return; // quit if invalid user input
|
||||
|
||||
uint8_t m_steps = parser.byteval('M');
|
||||
LIMIT(m_steps, 0, 128);
|
||||
L6470_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_bits >= 0) {
|
||||
const int micros = _BV(m_bits);
|
||||
if (micros < 100) { L6470_CHAR(' '); if (micros < 10) L6470_CHAR(' '); }
|
||||
L6470_ECHO(micros);
|
||||
L6470_ECHOPGM(" uSTEPS");
|
||||
}
|
||||
|
||||
for (j = 0; j < driver_count; j++)
|
||||
L6470.set_param(axis_index[j], L6470_STEP_MODE, m_bits); // set microsteps
|
||||
|
||||
L6470_ECHOLNPAIR("target (maximum) feedrate = ",final_feedrate);
|
||||
|
||||
float feedrate_inc = final_feedrate / 10, // start at 1/10 of max & go up by 1/10 per step)
|
||||
current_feedrate = 0;
|
||||
|
||||
planner.synchronize(); // wait for all current movement commands to complete
|
||||
|
||||
for (j = 0; j < driver_count; j++)
|
||||
L6470.get_status(axis_index[j]); // clear all error flags
|
||||
|
||||
char temp_axis_string[2];
|
||||
temp_axis_string[0] = axis_mon[0][0]; // need to have a string for use within sprintf format section
|
||||
temp_axis_string[1] = '\n';
|
||||
|
||||
char gcode_string[80];
|
||||
uint16_t status_composite = 0;
|
||||
L6470_ECHOLNPGM(".\n.\n."); // make the feedrate prints easier to see
|
||||
|
||||
do {
|
||||
current_feedrate += feedrate_inc;
|
||||
L6470_ECHOLNPAIR("...feedrate = ", current_feedrate);
|
||||
|
||||
sprintf_P(gcode_string, PSTR("G0 %s%4.3f F%4.3f"), temp_axis_string, position_min, current_feedrate);
|
||||
gcode.process_subcommands_now_P(gcode_string);
|
||||
|
||||
sprintf_P(gcode_string, PSTR("G0 %s%4.3f F%4.3f"), temp_axis_string, position_max, current_feedrate);
|
||||
gcode.process_subcommands_now_P(gcode_string);
|
||||
|
||||
planner.synchronize();
|
||||
|
||||
for (j = 0; j < driver_count; j++) {
|
||||
axis_status[j] = (~L6470.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
|
||||
} while (current_feedrate < final_feedrate * 0.99);
|
||||
|
||||
if (status_composite) {
|
||||
L6470_ECHOLNPGM("Completed with errors");
|
||||
for (j = 0; j < driver_count; j++) {
|
||||
L6470_ECHOPGM("...");
|
||||
L6470.error_status_decode(axis_status[j], axis_index[j]);
|
||||
}
|
||||
}
|
||||
else
|
||||
L6470_ECHOLNPGM("Completed with no errors");
|
||||
|
||||
} // M918
|
||||
|
||||
#endif // HAS_DRIVER(L6470)
|
@ -667,6 +667,14 @@ void GcodeSuite::process_parsed_command(
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAS_DRIVER(L6470)
|
||||
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
|
||||
case 917: M917(); break; // M917: L6470 tuning: Find minimum current thresholds
|
||||
case 918: M918(); break; // M918: L6470 tuning: Increase speed until max or error
|
||||
#endif
|
||||
|
||||
#if HAS_MICROSTEPS
|
||||
case 350: M350(); break; // M350: Set microstepping mode. Warning: Steps per unit remains unchanged. S code sets stepping mode for all drivers.
|
||||
case 351: M351(); break; // M351: Toggle MS1 MS2 pins directly, S# determines MS1 or MS2, X# sets the pin high/low.
|
||||
|
@ -240,6 +240,8 @@
|
||||
* M912 - Clear stepper driver overtemperature pre-warn condition flag. (Requires at least one _DRIVER_TYPE defined as TMC2130/TMC2208/TMC2660)
|
||||
* M913 - Set HYBRID_THRESHOLD speed. (Requires HYBRID_THRESHOLD)
|
||||
* M914 - Set StallGuard sensitivity. (Requires SENSORLESS_HOMING or SENSORLESS_PROBING)
|
||||
* M917 - L6470 tuning: Find minimum current thresholds
|
||||
* M918 - L6470 tuning: Increase speed until max or error
|
||||
*
|
||||
* M360 - SCARA calibration: Move to cal-position ThetaA (0 deg calibration)
|
||||
* M361 - SCARA calibration: Move to cal-position ThetaB (90 deg calibration - steps per degree)
|
||||
@ -812,6 +814,14 @@ private:
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAS_DRIVER(L6470)
|
||||
static void M122();
|
||||
static void M906();
|
||||
static void M916();
|
||||
static void M917();
|
||||
static void M918();
|
||||
#endif
|
||||
|
||||
#if HAS_DIGIPOTSS || HAS_MOTOR_CURRENT_PWM || ENABLED(DIGIPOT_I2C) || ENABLED(DAC_STEPPER_CURRENT)
|
||||
static void M907();
|
||||
#if HAS_DIGIPOTSS || ENABLED(DAC_STEPPER_CURRENT)
|
||||
|
@ -28,6 +28,12 @@
|
||||
|
||||
#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 "../../module/L6470/L6470_Marlin.h"
|
||||
#endif
|
||||
|
||||
void report_xyze(const float pos[], const uint8_t n = 4, const uint8_t precision = 3) {
|
||||
char str[12];
|
||||
for (uint8_t i = 0; i < n; i++) {
|
||||
@ -79,6 +85,62 @@
|
||||
|
||||
planner.synchronize();
|
||||
|
||||
#if HAS_DRIVER(L6470)
|
||||
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); \
|
||||
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); \
|
||||
L6470_ECHO(temp_buf); \
|
||||
}while(0)
|
||||
|
||||
L6470_ECHOPGM("\nL6470:");
|
||||
#if AXIS_DRIVER_TYPE_X(L6470)
|
||||
REPORT_ABSOLUTE_POS(X);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_X2(L6470)
|
||||
REPORT_ABSOLUTE_POS(X2);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_Y(L6470)
|
||||
REPORT_ABSOLUTE_POS(Y);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_Y2(L6470)
|
||||
REPORT_ABSOLUTE_POS(Y2);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_Z(L6470)
|
||||
REPORT_ABSOLUTE_POS(Z);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_Z2(L6470)
|
||||
REPORT_ABSOLUTE_POS(Z2);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_Z3(L6470)
|
||||
REPORT_ABSOLUTE_POS(Z3);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E0(L6470)
|
||||
REPORT_ABSOLUTE_POS(E0);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E1(L6470)
|
||||
REPORT_ABSOLUTE_POS(E1);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E2(L6470)
|
||||
REPORT_ABSOLUTE_POS(E2);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E3(L6470)
|
||||
REPORT_ABSOLUTE_POS(E3);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E4(L6470)
|
||||
REPORT_ABSOLUTE_POS(E4);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E5(L6470)
|
||||
REPORT_ABSOLUTE_POS(E5);
|
||||
#endif
|
||||
SERIAL_EOL();
|
||||
#endif // HAS_DRIVER(L6470)
|
||||
|
||||
SERIAL_ECHOPGM("Stepper:");
|
||||
LOOP_XYZE(i) {
|
||||
SERIAL_CHAR(' ');
|
||||
|
Reference in New Issue
Block a user