update code base to Marlin 2.0.9.2
This commit is contained in:
File diff suppressed because it is too large
Load Diff
84
Marlin/src/module/delta.cpp
Executable file → Normal file
84
Marlin/src/module/delta.cpp
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
// For homing:
|
||||
#include "planner.h"
|
||||
#include "endstops.h"
|
||||
#include "../lcd/ultralcd.h"
|
||||
#include "../lcd/marlinui.h"
|
||||
#include "../MarlinCore.h"
|
||||
|
||||
#if HAS_BED_PROBE
|
||||
@@ -54,11 +54,12 @@ float delta_height;
|
||||
abc_float_t delta_endstop_adj{0};
|
||||
float delta_radius,
|
||||
delta_diagonal_rod,
|
||||
delta_segments_per_second;
|
||||
segments_per_second;
|
||||
abc_float_t delta_tower_angle_trim;
|
||||
xy_float_t delta_tower[ABC];
|
||||
abc_float_t delta_diagonal_rod_2_tower;
|
||||
float delta_clip_start_height = Z_MAX_POS;
|
||||
abc_float_t delta_diagonal_rod_trim;
|
||||
|
||||
float delta_safe_distance_from_top();
|
||||
|
||||
@@ -67,43 +68,20 @@ float delta_safe_distance_from_top();
|
||||
* settings have been changed (e.g., by M665).
|
||||
*/
|
||||
void recalc_delta_settings() {
|
||||
constexpr abc_float_t trt = DELTA_RADIUS_TRIM_TOWER,
|
||||
drt = DELTA_DIAGONAL_ROD_TRIM_TOWER;
|
||||
constexpr abc_float_t trt = DELTA_RADIUS_TRIM_TOWER;
|
||||
delta_tower[A_AXIS].set(cos(RADIANS(210 + delta_tower_angle_trim.a)) * (delta_radius + trt.a), // front left tower
|
||||
sin(RADIANS(210 + delta_tower_angle_trim.a)) * (delta_radius + trt.a));
|
||||
delta_tower[B_AXIS].set(cos(RADIANS(330 + delta_tower_angle_trim.b)) * (delta_radius + trt.b), // front right tower
|
||||
sin(RADIANS(330 + delta_tower_angle_trim.b)) * (delta_radius + trt.b));
|
||||
delta_tower[C_AXIS].set(cos(RADIANS( 90 + delta_tower_angle_trim.c)) * (delta_radius + trt.c), // back middle tower
|
||||
sin(RADIANS( 90 + delta_tower_angle_trim.c)) * (delta_radius + trt.c));
|
||||
delta_diagonal_rod_2_tower.set(sq(delta_diagonal_rod + drt.a),
|
||||
sq(delta_diagonal_rod + drt.b),
|
||||
sq(delta_diagonal_rod + drt.c));
|
||||
delta_diagonal_rod_2_tower.set(sq(delta_diagonal_rod + delta_diagonal_rod_trim.a),
|
||||
sq(delta_diagonal_rod + delta_diagonal_rod_trim.b),
|
||||
sq(delta_diagonal_rod + delta_diagonal_rod_trim.c));
|
||||
update_software_endstops(Z_AXIS);
|
||||
set_all_unhomed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a safe radius for calibration
|
||||
*/
|
||||
|
||||
#if EITHER(DELTA_AUTO_CALIBRATION, DELTA_CALIBRATION_MENU)
|
||||
|
||||
#if ENABLED(DELTA_AUTO_CALIBRATION)
|
||||
float calibration_radius_factor = 1;
|
||||
#endif
|
||||
|
||||
float delta_calibration_radius() {
|
||||
return calibration_radius_factor * (
|
||||
#if HAS_BED_PROBE
|
||||
FLOOR((DELTA_PRINTABLE_RADIUS) - _MAX(HYPOT(probe.offset_xy.x, probe.offset_xy.y), MIN_PROBE_EDGE))
|
||||
#else
|
||||
DELTA_PRINTABLE_RADIUS
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Delta Inverse Kinematics
|
||||
*
|
||||
@@ -121,8 +99,8 @@ void recalc_delta_settings() {
|
||||
*/
|
||||
|
||||
#define DELTA_DEBUG(VAR) do { \
|
||||
SERIAL_ECHOLNPAIR_P(PSTR("Cartesian X"), VAR.x, SP_Y_STR, VAR.y, SP_Z_STR, VAR.z); \
|
||||
SERIAL_ECHOLNPAIR("Delta A", delta.a, " B", delta.b, " C", delta.c); \
|
||||
SERIAL_ECHOLNPGM_P(PSTR("Cartesian X"), VAR.x, SP_Y_STR, VAR.y, SP_Z_STR, VAR.z); \
|
||||
SERIAL_ECHOLNPGM_P(PSTR("Delta A"), delta.a, SP_B_STR, delta.b, SP_C_STR, delta.c); \
|
||||
}while(0)
|
||||
|
||||
void inverse_kinematics(const xyz_pos_t &raw) {
|
||||
@@ -177,7 +155,7 @@ float delta_safe_distance_from_top() {
|
||||
*
|
||||
* The result is stored in the cartes[] array.
|
||||
*/
|
||||
void forward_kinematics_DELTA(const float &z1, const float &z2, const float &z3) {
|
||||
void forward_kinematics(const_float_t z1, const_float_t z2, const_float_t z3) {
|
||||
// Create a vector in old coordinates along x axis of new coordinate
|
||||
const float p12[3] = { delta_tower[B_AXIS].x - delta_tower[A_AXIS].x, delta_tower[B_AXIS].y - delta_tower[A_AXIS].y, z2 - z1 },
|
||||
|
||||
@@ -233,7 +211,8 @@ void forward_kinematics_DELTA(const float &z1, const float &z2, const float &z3)
|
||||
* This is like quick_home_xy() but for 3 towers.
|
||||
*/
|
||||
void home_delta() {
|
||||
if (DEBUGGING(LEVELING)) DEBUG_POS(">>> home_delta", current_position);
|
||||
DEBUG_SECTION(log_home_delta, "home_delta", DEBUGGING(LEVELING));
|
||||
|
||||
// Init the current position of all carriages to 0,0,0
|
||||
current_position.reset();
|
||||
destination.reset();
|
||||
@@ -241,27 +220,28 @@ void home_delta() {
|
||||
|
||||
// Disable stealthChop if used. Enable diag1 pin on driver.
|
||||
#if ENABLED(SENSORLESS_HOMING)
|
||||
sensorless_t stealth_states {
|
||||
tmc_enable_stallguard(stepperX),
|
||||
tmc_enable_stallguard(stepperY),
|
||||
tmc_enable_stallguard(stepperZ)
|
||||
};
|
||||
TERN_(X_SENSORLESS, sensorless_t stealth_states_x = start_sensorless_homing_per_axis(X_AXIS));
|
||||
TERN_(Y_SENSORLESS, sensorless_t stealth_states_y = start_sensorless_homing_per_axis(Y_AXIS));
|
||||
TERN_(Z_SENSORLESS, sensorless_t stealth_states_z = start_sensorless_homing_per_axis(Z_AXIS));
|
||||
TERN_(I_SENSORLESS, sensorless_t stealth_states_i = start_sensorless_homing_per_axis(I_AXIS));
|
||||
TERN_(J_SENSORLESS, sensorless_t stealth_states_j = start_sensorless_homing_per_axis(J_AXIS));
|
||||
TERN_(K_SENSORLESS, sensorless_t stealth_states_k = start_sensorless_homing_per_axis(K_AXIS));
|
||||
#endif
|
||||
|
||||
// Move all carriages together linearly until an endstop is hit.
|
||||
current_position.z = (delta_height + 10
|
||||
#if HAS_BED_PROBE
|
||||
- probe.offset.z
|
||||
#endif
|
||||
);
|
||||
current_position.z = DIFF_TERN(HAS_BED_PROBE, delta_height + 10, probe.offset.z);
|
||||
line_to_current_position(homing_feedrate(Z_AXIS));
|
||||
planner.synchronize();
|
||||
TERN_(HAS_DELTA_SENSORLESS_PROBING, endstops.report_states());
|
||||
|
||||
// Re-enable stealthChop if used. Disable diag1 pin on driver.
|
||||
#if ENABLED(SENSORLESS_HOMING)
|
||||
tmc_disable_stallguard(stepperX, stealth_states.x);
|
||||
tmc_disable_stallguard(stepperY, stealth_states.y);
|
||||
tmc_disable_stallguard(stepperZ, stealth_states.z);
|
||||
#if ENABLED(SENSORLESS_HOMING) && DISABLED(ENDSTOPS_ALWAYS_ON_DEFAULT)
|
||||
TERN_(X_SENSORLESS, end_sensorless_homing_per_axis(X_AXIS, stealth_states_x));
|
||||
TERN_(Y_SENSORLESS, end_sensorless_homing_per_axis(Y_AXIS, stealth_states_y));
|
||||
TERN_(Z_SENSORLESS, end_sensorless_homing_per_axis(Z_AXIS, stealth_states_z));
|
||||
TERN_(I_SENSORLESS, end_sensorless_homing_per_axis(I_AXIS, stealth_states_i));
|
||||
TERN_(J_SENSORLESS, end_sensorless_homing_per_axis(J_AXIS, stealth_states_j));
|
||||
TERN_(K_SENSORLESS, end_sensorless_homing_per_axis(K_AXIS, stealth_states_k));
|
||||
#endif
|
||||
|
||||
endstops.validate_homing_move();
|
||||
@@ -276,19 +256,17 @@ void home_delta() {
|
||||
// Do this here all at once for Delta, because
|
||||
// XYZ isn't ABC. Applying this per-tower would
|
||||
// give the impression that they are the same.
|
||||
LOOP_XYZ(i) set_axis_is_at_home((AxisEnum)i);
|
||||
LOOP_ABC(i) set_axis_is_at_home((AxisEnum)i);
|
||||
|
||||
sync_plan_position();
|
||||
|
||||
#if DISABLED(DELTA_HOME_TO_SAFE_ZONE) && defined(HOMING_BACKOFF_MM)
|
||||
constexpr xyz_float_t endstop_backoff = HOMING_BACKOFF_MM;
|
||||
#if DISABLED(DELTA_HOME_TO_SAFE_ZONE) && defined(HOMING_BACKOFF_POST_MM)
|
||||
constexpr xyz_float_t endstop_backoff = HOMING_BACKOFF_POST_MM;
|
||||
if (endstop_backoff.z) {
|
||||
current_position.z -= ABS(endstop_backoff.z) * Z_HOME_DIR;
|
||||
line_to_current_position(homing_feedrate(Z_AXIS));
|
||||
}
|
||||
#endif
|
||||
|
||||
if (DEBUGGING(LEVELING)) DEBUG_POS("<<< home_delta", current_position);
|
||||
}
|
||||
|
||||
#endif // DELTA
|
||||
|
24
Marlin/src/module/delta.h
Executable file → Normal file
24
Marlin/src/module/delta.h
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@@ -32,11 +32,12 @@ extern float delta_height;
|
||||
extern abc_float_t delta_endstop_adj;
|
||||
extern float delta_radius,
|
||||
delta_diagonal_rod,
|
||||
delta_segments_per_second;
|
||||
segments_per_second;
|
||||
extern abc_float_t delta_tower_angle_trim;
|
||||
extern xy_float_t delta_tower[ABC];
|
||||
extern abc_float_t delta_diagonal_rod_2_tower;
|
||||
extern float delta_clip_start_height;
|
||||
extern abc_float_t delta_diagonal_rod_trim;
|
||||
|
||||
/**
|
||||
* Recalculate factors used for delta kinematics whenever
|
||||
@@ -44,19 +45,6 @@ extern float delta_clip_start_height;
|
||||
*/
|
||||
void recalc_delta_settings();
|
||||
|
||||
/**
|
||||
* Get a safe radius for calibration
|
||||
*/
|
||||
#if ENABLED(DELTA_AUTO_CALIBRATION)
|
||||
extern float calibration_radius_factor;
|
||||
#else
|
||||
constexpr float calibration_radius_factor = 1;
|
||||
#endif
|
||||
|
||||
#if EITHER(DELTA_AUTO_CALIBRATION, DELTA_CALIBRATION_MENU)
|
||||
float delta_calibration_radius();
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Delta Inverse Kinematics
|
||||
*
|
||||
@@ -119,10 +107,10 @@ float delta_safe_distance_from_top();
|
||||
*
|
||||
* The result is stored in the cartes[] array.
|
||||
*/
|
||||
void forward_kinematics_DELTA(const float &z1, const float &z2, const float &z3);
|
||||
void forward_kinematics(const_float_t z1, const_float_t z2, const_float_t z3);
|
||||
|
||||
FORCE_INLINE void forward_kinematics_DELTA(const abc_float_t &point) {
|
||||
forward_kinematics_DELTA(point.a, point.b, point.c);
|
||||
FORCE_INLINE void forward_kinematics(const abc_float_t &point) {
|
||||
forward_kinematics(point.a, point.b, point.c);
|
||||
}
|
||||
|
||||
void home_delta();
|
||||
|
696
Marlin/src/module/endstops.cpp
Executable file → Normal file
696
Marlin/src/module/endstops.cpp
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -27,10 +27,9 @@
|
||||
#include "endstops.h"
|
||||
#include "stepper.h"
|
||||
|
||||
#include "../MarlinCore.h"
|
||||
#include "../sd/cardreader.h"
|
||||
#include "temperature.h"
|
||||
#include "../lcd/ultralcd.h"
|
||||
#include "../lcd/marlinui.h"
|
||||
|
||||
#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
|
||||
#include HAL_PATH(../HAL, endstop_interrupts.h)
|
||||
@@ -48,17 +47,21 @@
|
||||
#include "../feature/joystick.h"
|
||||
#endif
|
||||
|
||||
#if HAS_BED_PROBE
|
||||
#include "probe.h"
|
||||
#endif
|
||||
|
||||
Endstops endstops;
|
||||
|
||||
// private:
|
||||
|
||||
bool Endstops::enabled, Endstops::enabled_globally; // Initialized by settings.load()
|
||||
volatile uint8_t Endstops::hit_state;
|
||||
|
||||
Endstops::esbits_t Endstops::live_state = 0;
|
||||
volatile Endstops::endstop_mask_t Endstops::hit_state;
|
||||
Endstops::endstop_mask_t Endstops::live_state = 0;
|
||||
|
||||
#if ENDSTOP_NOISE_THRESHOLD
|
||||
Endstops::esbits_t Endstops::validated_live_state;
|
||||
Endstops::endstop_mask_t Endstops::validated_live_state;
|
||||
uint8_t Endstops::endstop_poll_count;
|
||||
#endif
|
||||
|
||||
@@ -256,6 +259,66 @@ void Endstops::init() {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAS_I_MIN
|
||||
#if ENABLED(ENDSTOPPULLUP_IMIN)
|
||||
SET_INPUT_PULLUP(I_MIN_PIN);
|
||||
#elif ENABLED(ENDSTOPPULLDOWN_IMIN)
|
||||
SET_INPUT_PULLDOWN(I_MIN_PIN);
|
||||
#else
|
||||
SET_INPUT(I_MIN_PIN);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAS_I_MAX
|
||||
#if ENABLED(ENDSTOPPULLUP_IMAX)
|
||||
SET_INPUT_PULLUP(I_MAX_PIN);
|
||||
#elif ENABLED(ENDSTOPPULLDOWN_IMAX)
|
||||
SET_INPUT_PULLDOWN(I_MAX_PIN);
|
||||
#else
|
||||
SET_INPUT(I_MAX_PIN);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAS_J_MIN
|
||||
#if ENABLED(ENDSTOPPULLUP_JMIN)
|
||||
SET_INPUT_PULLUP(J_MIN_PIN);
|
||||
#elif ENABLED(ENDSTOPPULLDOWN_IMIN)
|
||||
SET_INPUT_PULLDOWN(J_MIN_PIN);
|
||||
#else
|
||||
SET_INPUT(J_MIN_PIN);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAS_J_MAX
|
||||
#if ENABLED(ENDSTOPPULLUP_JMAX)
|
||||
SET_INPUT_PULLUP(J_MAX_PIN);
|
||||
#elif ENABLED(ENDSTOPPULLDOWN_JMAX)
|
||||
SET_INPUT_PULLDOWN(J_MAX_PIN);
|
||||
#else
|
||||
SET_INPUT(J_MAX_PIN);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAS_K_MIN
|
||||
#if ENABLED(ENDSTOPPULLUP_KMIN)
|
||||
SET_INPUT_PULLUP(K_MIN_PIN);
|
||||
#elif ENABLED(ENDSTOPPULLDOWN_KMIN)
|
||||
SET_INPUT_PULLDOWN(K_MIN_PIN);
|
||||
#else
|
||||
SET_INPUT(K_MIN_PIN);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAS_K_MAX
|
||||
#if ENABLED(ENDSTOPPULLUP_KMAX)
|
||||
SET_INPUT_PULLUP(K_MAX_PIN);
|
||||
#elif ENABLED(ENDSTOPPULLDOWN_KMIN)
|
||||
SET_INPUT_PULLDOWN(K_MAX_PIN);
|
||||
#else
|
||||
SET_INPUT(K_MAX_PIN);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if PIN_EXISTS(CALIBRATION)
|
||||
#if ENABLED(CALIBRATION_PIN_PULLUP)
|
||||
SET_INPUT_PULLUP(CALIBRATION_PIN);
|
||||
@@ -266,7 +329,7 @@ void Endstops::init() {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAS_CUSTOM_PROBE_PIN
|
||||
#if USES_Z_MIN_PROBE_PIN
|
||||
#if ENABLED(ENDSTOPPULLUP_ZMIN_PROBE)
|
||||
SET_INPUT_PULLUP(Z_MIN_PROBE_PIN);
|
||||
#elif ENABLED(ENDSTOPPULLDOWN_ZMIN_PROBE)
|
||||
@@ -276,27 +339,23 @@ void Endstops::init() {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
|
||||
setup_endstop_interrupts();
|
||||
#if ENABLED(PROBE_ACTIVATION_SWITCH)
|
||||
SET_INPUT(PROBE_ACTIVATION_SWITCH_PIN);
|
||||
#endif
|
||||
|
||||
TERN_(PROBE_TARE, probe.tare());
|
||||
|
||||
TERN_(ENDSTOP_INTERRUPTS_FEATURE, setup_endstop_interrupts());
|
||||
|
||||
// Enable endstops
|
||||
enable_globally(
|
||||
#if ENABLED(ENDSTOPS_ALWAYS_ON_DEFAULT)
|
||||
true
|
||||
#else
|
||||
false
|
||||
#endif
|
||||
);
|
||||
enable_globally(ENABLED(ENDSTOPS_ALWAYS_ON_DEFAULT));
|
||||
|
||||
} // Endstops::init
|
||||
|
||||
// Called at ~1KHz from Temperature ISR: Poll endstop state if required
|
||||
void Endstops::poll() {
|
||||
|
||||
#if ENABLED(PINS_DEBUGGING)
|
||||
run_monitor(); // report changes in endstop status
|
||||
#endif
|
||||
TERN_(PINS_DEBUGGING, run_monitor()); // Report changes in endstop status
|
||||
|
||||
#if DISABLED(ENDSTOP_INTERRUPTS_FEATURE)
|
||||
update();
|
||||
@@ -325,7 +384,7 @@ void Endstops::not_homing() {
|
||||
// If the last move failed to trigger an endstop, call kill
|
||||
void Endstops::validate_homing_move() {
|
||||
if (trigger_state()) hit_on_purpose();
|
||||
else kill(GET_TEXT(MSG_LCD_HOMING_FAILED));
|
||||
else kill(GET_TEXT(MSG_KILL_HOMING_FAILED));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -341,14 +400,9 @@ void Endstops::not_homing() {
|
||||
void Endstops::resync() {
|
||||
if (!abort_enabled()) return; // If endstops/probes are disabled the loop below can hang
|
||||
|
||||
#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
|
||||
update();
|
||||
#else
|
||||
safe_delay(2); // Wait for Temperature ISR to run at least once (runs at 1KHz)
|
||||
#endif
|
||||
#if ENDSTOP_NOISE_THRESHOLD
|
||||
while (endstop_poll_count) safe_delay(1);
|
||||
#endif
|
||||
// Wait for Temperature ISR to run at least once (runs at 1KHz)
|
||||
TERN(ENDSTOP_INTERRUPTS_FEATURE, update(), safe_delay(2));
|
||||
while (TERN0(ENDSTOP_NOISE_THRESHOLD, endstop_poll_count)) safe_delay(1);
|
||||
}
|
||||
|
||||
#if ENABLED(PINS_DEBUGGING)
|
||||
@@ -362,48 +416,60 @@ void Endstops::resync() {
|
||||
#endif
|
||||
|
||||
void Endstops::event_handler() {
|
||||
static uint8_t prev_hit_state; // = 0
|
||||
static endstop_mask_t prev_hit_state; // = 0
|
||||
if (hit_state == prev_hit_state) return;
|
||||
prev_hit_state = hit_state;
|
||||
if (hit_state) {
|
||||
#if HAS_SPI_LCD
|
||||
char chrX = ' ', chrY = ' ', chrZ = ' ', chrP = ' ';
|
||||
#if HAS_STATUS_MESSAGE
|
||||
char LINEAR_AXIS_LIST(chrX = ' ', chrY = ' ', chrZ = ' ', chrI = ' ', chrJ = ' ', chrK = ' '),
|
||||
chrP = ' ';
|
||||
#define _SET_STOP_CHAR(A,C) (chr## A = C)
|
||||
#else
|
||||
#define _SET_STOP_CHAR(A,C) ;
|
||||
#define _SET_STOP_CHAR(A,C) NOOP
|
||||
#endif
|
||||
|
||||
#define _ENDSTOP_HIT_ECHO(A,C) do{ \
|
||||
SERIAL_ECHOPAIR(" " STRINGIFY(A) ":", planner.triggered_position_mm(_AXIS(A))); \
|
||||
_SET_STOP_CHAR(A,C); }while(0)
|
||||
SERIAL_ECHOPGM(" " STRINGIFY(A) ":", planner.triggered_position_mm(_AXIS(A))); _SET_STOP_CHAR(A,C); }while(0)
|
||||
|
||||
#define _ENDSTOP_HIT_TEST(A,C) \
|
||||
if (TEST(hit_state, A ##_MIN) || TEST(hit_state, A ##_MAX)) \
|
||||
if (TERN0(HAS_##A##_MIN, TEST(hit_state, A##_MIN)) || TERN0(HAS_##A##_MAX, TEST(hit_state, A##_MAX))) \
|
||||
_ENDSTOP_HIT_ECHO(A,C)
|
||||
|
||||
#define ENDSTOP_HIT_TEST_X() _ENDSTOP_HIT_TEST(X,'X')
|
||||
#define ENDSTOP_HIT_TEST_Y() _ENDSTOP_HIT_TEST(Y,'Y')
|
||||
#define ENDSTOP_HIT_TEST_Z() _ENDSTOP_HIT_TEST(Z,'Z')
|
||||
#define ENDSTOP_HIT_TEST_I() _ENDSTOP_HIT_TEST(I,'I')
|
||||
#define ENDSTOP_HIT_TEST_J() _ENDSTOP_HIT_TEST(J,'J')
|
||||
#define ENDSTOP_HIT_TEST_K() _ENDSTOP_HIT_TEST(K,'K')
|
||||
|
||||
SERIAL_ECHO_START();
|
||||
SERIAL_ECHOPGM(STR_ENDSTOPS_HIT);
|
||||
ENDSTOP_HIT_TEST_X();
|
||||
ENDSTOP_HIT_TEST_Y();
|
||||
ENDSTOP_HIT_TEST_Z();
|
||||
LINEAR_AXIS_CODE(
|
||||
ENDSTOP_HIT_TEST_X(),
|
||||
ENDSTOP_HIT_TEST_Y(),
|
||||
ENDSTOP_HIT_TEST_Z(),
|
||||
_ENDSTOP_HIT_TEST(I,'I'),
|
||||
_ENDSTOP_HIT_TEST(J,'J'),
|
||||
_ENDSTOP_HIT_TEST(K,'K')
|
||||
);
|
||||
|
||||
#if HAS_CUSTOM_PROBE_PIN
|
||||
#if USES_Z_MIN_PROBE_PIN
|
||||
#define P_AXIS Z_AXIS
|
||||
if (TEST(hit_state, Z_MIN_PROBE)) _ENDSTOP_HIT_ECHO(P, 'P');
|
||||
#endif
|
||||
SERIAL_EOL();
|
||||
|
||||
#if HAS_SPI_LCD
|
||||
ui.status_printf_P(0, PSTR(S_FMT " %c %c %c %c"), GET_TEXT(MSG_LCD_ENDSTOPS), chrX, chrY, chrZ, chrP);
|
||||
#endif
|
||||
TERN_(HAS_STATUS_MESSAGE,
|
||||
ui.status_printf_P(0,
|
||||
PSTR(S_FMT GANG_N_1(LINEAR_AXES, " %c") " %c"),
|
||||
GET_TEXT(MSG_LCD_ENDSTOPS),
|
||||
LINEAR_AXIS_LIST(chrX, chrY, chrZ, chrI, chrJ, chrK), chrP
|
||||
)
|
||||
);
|
||||
|
||||
#if BOTH(SD_ABORT_ON_ENDSTOP_HIT, SDSUPPORT)
|
||||
if (planner.abort_on_endstop_hit) {
|
||||
card.endFilePrint();
|
||||
card.abortFilePrintNow();
|
||||
quickstop_stepper();
|
||||
thermalManager.disable_all_heaters();
|
||||
print_job_timer.stop();
|
||||
@@ -412,17 +478,23 @@ void Endstops::event_handler() {
|
||||
}
|
||||
}
|
||||
|
||||
#if GCC_VERSION <= 50000
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||
#endif
|
||||
|
||||
static void print_es_state(const bool is_hit, PGM_P const label=nullptr) {
|
||||
if (label) serialprintPGM(label);
|
||||
if (label) SERIAL_ECHOPGM_P(label);
|
||||
SERIAL_ECHOPGM(": ");
|
||||
serialprintPGM(is_hit ? PSTR(STR_ENDSTOP_HIT) : PSTR(STR_ENDSTOP_OPEN));
|
||||
SERIAL_EOL();
|
||||
SERIAL_ECHOLNPGM_P(is_hit ? PSTR(STR_ENDSTOP_HIT) : PSTR(STR_ENDSTOP_OPEN));
|
||||
}
|
||||
|
||||
#if GCC_VERSION <= 50000
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
void _O2 Endstops::report_states() {
|
||||
#if ENABLED(BLTOUCH)
|
||||
bltouch._set_SW_mode();
|
||||
#endif
|
||||
TERN_(BLTOUCH, bltouch._set_SW_mode());
|
||||
SERIAL_ECHOLNPGM(STR_M119_REPORT);
|
||||
#define ES_REPORT(S) print_es_state(READ(S##_PIN) != S##_ENDSTOP_INVERTING, PSTR(STR_##S))
|
||||
#if HAS_X_MIN
|
||||
@@ -473,43 +545,66 @@ void _O2 Endstops::report_states() {
|
||||
#if HAS_Z4_MAX
|
||||
ES_REPORT(Z4_MAX);
|
||||
#endif
|
||||
#if HAS_CUSTOM_PROBE_PIN
|
||||
print_es_state(READ(Z_MIN_PROBE_PIN) != Z_MIN_PROBE_ENDSTOP_INVERTING, PSTR(STR_Z_PROBE));
|
||||
#if HAS_I_MIN
|
||||
ES_REPORT(I_MIN);
|
||||
#endif
|
||||
#if HAS_FILAMENT_SENSOR
|
||||
#if NUM_RUNOUT_SENSORS == 1
|
||||
print_es_state(READ(FIL_RUNOUT_PIN) != FIL_RUNOUT_INVERTING, PSTR(STR_FILAMENT_RUNOUT_SENSOR));
|
||||
#else
|
||||
#define _CASE_RUNOUT(N) case N: pin = FIL_RUNOUT##N##_PIN; break;
|
||||
LOOP_S_LE_N(i, 1, NUM_RUNOUT_SENSORS) {
|
||||
pin_t pin;
|
||||
switch (i) {
|
||||
default: continue;
|
||||
REPEAT_S(1, INCREMENT(NUM_RUNOUT_SENSORS), _CASE_RUNOUT)
|
||||
}
|
||||
SERIAL_ECHOPGM(STR_FILAMENT_RUNOUT_SENSOR);
|
||||
if (i > 1) SERIAL_CHAR(' ', '0' + i);
|
||||
print_es_state(extDigitalRead(pin) != FIL_RUNOUT_INVERTING);
|
||||
#if HAS_I_MAX
|
||||
ES_REPORT(I_MAX);
|
||||
#endif
|
||||
#if HAS_J_MIN
|
||||
ES_REPORT(J_MIN);
|
||||
#endif
|
||||
#if HAS_J_MAX
|
||||
ES_REPORT(J_MAX);
|
||||
#endif
|
||||
#if HAS_K_MIN
|
||||
ES_REPORT(K_MIN);
|
||||
#endif
|
||||
#if HAS_K_MAX
|
||||
ES_REPORT(K_MAX);
|
||||
#endif
|
||||
#if BOTH(MARLIN_DEV_MODE, PROBE_ACTIVATION_SWITCH)
|
||||
print_es_state(probe_switch_activated(), PSTR(STR_PROBE_EN));
|
||||
#endif
|
||||
#if USES_Z_MIN_PROBE_PIN
|
||||
print_es_state(PROBE_TRIGGERED(), PSTR(STR_Z_PROBE));
|
||||
#endif
|
||||
#if MULTI_FILAMENT_SENSOR
|
||||
#define _CASE_RUNOUT(N) case N: pin = FIL_RUNOUT##N##_PIN; state = FIL_RUNOUT##N##_STATE; break;
|
||||
LOOP_S_LE_N(i, 1, NUM_RUNOUT_SENSORS) {
|
||||
pin_t pin;
|
||||
uint8_t state;
|
||||
switch (i) {
|
||||
default: continue;
|
||||
REPEAT_1(NUM_RUNOUT_SENSORS, _CASE_RUNOUT)
|
||||
}
|
||||
#undef _CASE_RUNOUT
|
||||
#endif
|
||||
#endif
|
||||
#if ENABLED(BLTOUCH)
|
||||
bltouch._reset_SW_mode();
|
||||
SERIAL_ECHOPGM(STR_FILAMENT);
|
||||
if (i > 1) SERIAL_CHAR(' ', '0' + i);
|
||||
print_es_state(extDigitalRead(pin) != state);
|
||||
}
|
||||
#undef _CASE_RUNOUT
|
||||
#elif HAS_FILAMENT_SENSOR
|
||||
print_es_state(READ(FIL_RUNOUT1_PIN) != FIL_RUNOUT1_STATE, PSTR(STR_FILAMENT));
|
||||
#endif
|
||||
|
||||
#if ENABLED(JOYSTICK_DEBUG)
|
||||
joystick.report();
|
||||
#endif
|
||||
TERN_(BLTOUCH, bltouch._reset_SW_mode());
|
||||
TERN_(JOYSTICK_DEBUG, joystick.report());
|
||||
|
||||
} // Endstops::report_states
|
||||
|
||||
// The following routines are called from an ISR context. It could be the temperature ISR, the
|
||||
// endstop ISR or the Stepper ISR.
|
||||
|
||||
#define _ENDSTOP(AXIS, MINMAX) AXIS ##_## MINMAX
|
||||
#define _ENDSTOP_PIN(AXIS, MINMAX) AXIS ##_## MINMAX ##_PIN
|
||||
#define _ENDSTOP_INVERTING(AXIS, MINMAX) AXIS ##_## MINMAX ##_ENDSTOP_INVERTING
|
||||
#if HAS_DELTA_SENSORLESS_PROBING
|
||||
#define __ENDSTOP(AXIS, ...) AXIS ##_MAX
|
||||
#define _ENDSTOP_PIN(AXIS, ...) AXIS ##_MAX_PIN
|
||||
#define _ENDSTOP_INVERTING(AXIS, ...) AXIS ##_MAX_ENDSTOP_INVERTING
|
||||
#else
|
||||
#define __ENDSTOP(AXIS, MINMAX) AXIS ##_## MINMAX
|
||||
#define _ENDSTOP_PIN(AXIS, MINMAX) AXIS ##_## MINMAX ##_PIN
|
||||
#define _ENDSTOP_INVERTING(AXIS, MINMAX) AXIS ##_## MINMAX ##_ENDSTOP_INVERTING
|
||||
#endif
|
||||
#define _ENDSTOP(AXIS, MINMAX) __ENDSTOP(AXIS, MINMAX)
|
||||
|
||||
// Check endstops - Could be called from Temperature ISR!
|
||||
void Endstops::update() {
|
||||
@@ -521,28 +616,23 @@ void Endstops::update() {
|
||||
#define UPDATE_ENDSTOP_BIT(AXIS, MINMAX) SET_BIT_TO(live_state, _ENDSTOP(AXIS, MINMAX), (READ(_ENDSTOP_PIN(AXIS, MINMAX)) != _ENDSTOP_INVERTING(AXIS, MINMAX)))
|
||||
#define COPY_LIVE_STATE(SRC_BIT, DST_BIT) SET_BIT_TO(live_state, DST_BIT, TEST(live_state, SRC_BIT))
|
||||
|
||||
#if ENABLED(G38_PROBE_TARGET) && PIN_EXISTS(Z_MIN_PROBE) && !(CORE_IS_XY || CORE_IS_XZ)
|
||||
// If G38 command is active check Z_MIN_PROBE for ALL movement
|
||||
if (G38_move) UPDATE_ENDSTOP_BIT(Z, MIN_PROBE);
|
||||
#if ENABLED(G38_PROBE_TARGET) && NONE(CORE_IS_XY, CORE_IS_XZ, MARKFORGED_XY)
|
||||
#define HAS_G38_PROBE 1
|
||||
// For G38 moves check the probe's pin for ALL movement
|
||||
if (G38_move) UPDATE_ENDSTOP_BIT(Z, TERN(USES_Z_MIN_PROBE_PIN, MIN_PROBE, MIN));
|
||||
#endif
|
||||
|
||||
// With Dual X, endstops are only checked in the homing direction for the active extruder
|
||||
#if ENABLED(DUAL_X_CARRIAGE)
|
||||
#define E0_ACTIVE stepper.movement_extruder() == 0
|
||||
#define X_MIN_TEST() ((X_HOME_DIR < 0 && E0_ACTIVE) || (X2_HOME_DIR < 0 && !E0_ACTIVE))
|
||||
#define X_MAX_TEST() ((X_HOME_DIR > 0 && E0_ACTIVE) || (X2_HOME_DIR > 0 && !E0_ACTIVE))
|
||||
#else
|
||||
#define X_MIN_TEST() true
|
||||
#define X_MAX_TEST() true
|
||||
#endif
|
||||
#define X_MIN_TEST() TERN1(DUAL_X_CARRIAGE, TERN0(X_HOME_TO_MIN, stepper.last_moved_extruder == 0) || TERN0(X2_HOME_TO_MIN, stepper.last_moved_extruder != 0))
|
||||
#define X_MAX_TEST() TERN1(DUAL_X_CARRIAGE, TERN0(X_HOME_TO_MAX, stepper.last_moved_extruder == 0) || TERN0(X2_HOME_TO_MAX, stepper.last_moved_extruder != 0))
|
||||
|
||||
// Use HEAD for core axes, AXIS for others
|
||||
#if CORE_IS_XY || CORE_IS_XZ
|
||||
#if ANY(CORE_IS_XY, CORE_IS_XZ, MARKFORGED_XY)
|
||||
#define X_AXIS_HEAD X_HEAD
|
||||
#else
|
||||
#define X_AXIS_HEAD X_AXIS
|
||||
#endif
|
||||
#if CORE_IS_XY || CORE_IS_YZ
|
||||
#if ANY(CORE_IS_XY, CORE_IS_YZ, MARKFORGED_XY)
|
||||
#define Y_AXIS_HEAD Y_HEAD
|
||||
#else
|
||||
#define Y_AXIS_HEAD Y_AXIS
|
||||
@@ -553,6 +643,10 @@ void Endstops::update() {
|
||||
#define Z_AXIS_HEAD Z_AXIS
|
||||
#endif
|
||||
|
||||
#define I_AXIS_HEAD I_AXIS
|
||||
#define J_AXIS_HEAD J_AXIS
|
||||
#define K_AXIS_HEAD K_AXIS
|
||||
|
||||
/**
|
||||
* Check and update endstops
|
||||
*/
|
||||
@@ -600,7 +694,7 @@ void Endstops::update() {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAS_Z_MIN && !Z_SPI_SENSORLESS
|
||||
#if HAS_Z_MIN && NONE(Z_SPI_SENSORLESS, Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN)
|
||||
UPDATE_ENDSTOP_BIT(Z, MIN);
|
||||
#if ENABLED(Z_MULTI_ENDSTOPS)
|
||||
#if HAS_Z2_MIN
|
||||
@@ -625,9 +719,10 @@ void Endstops::update() {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// When closing the gap check the enabled probe
|
||||
#if HAS_CUSTOM_PROBE_PIN
|
||||
UPDATE_ENDSTOP_BIT(Z, MIN_PROBE);
|
||||
#if HAS_BED_PROBE
|
||||
// When closing the gap check the enabled probe
|
||||
if (probe_switch_activated())
|
||||
UPDATE_ENDSTOP_BIT(Z, TERN(USES_Z_MIN_PROBE_PIN, MIN_PROBE, MIN));
|
||||
#endif
|
||||
|
||||
#if HAS_Z_MAX && !Z_SPI_SENSORLESS
|
||||
@@ -653,12 +748,90 @@ void Endstops::update() {
|
||||
COPY_LIVE_STATE(Z_MAX, Z4_MAX);
|
||||
#endif
|
||||
#endif
|
||||
#elif !HAS_CUSTOM_PROBE_PIN || Z_MAX_PIN != Z_MIN_PROBE_PIN
|
||||
#elif TERN1(USES_Z_MIN_PROBE_PIN, Z_MAX_PIN != Z_MIN_PROBE_PIN)
|
||||
// If this pin isn't the bed probe it's the Z endstop
|
||||
UPDATE_ENDSTOP_BIT(Z, MAX);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAS_I_MIN && !I_SPI_SENSORLESS
|
||||
#if ENABLED(I_DUAL_ENDSTOPS)
|
||||
UPDATE_ENDSTOP_BIT(I, MIN);
|
||||
#if HAS_I2_MIN
|
||||
UPDATE_ENDSTOP_BIT(I2, MAX);
|
||||
#else
|
||||
COPY_LIVE_STATE(I_MIN, I2_MIN);
|
||||
#endif
|
||||
#else
|
||||
UPDATE_ENDSTOP_BIT(I, MIN);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAS_I_MAX && !I_SPI_SENSORLESS
|
||||
#if ENABLED(I_DUAL_ENDSTOPS)
|
||||
UPDATE_ENDSTOP_BIT(I, MAX);
|
||||
#if HAS_I2_MAX
|
||||
UPDATE_ENDSTOP_BIT(I2, MAX);
|
||||
#else
|
||||
COPY_LIVE_STATE(I_MAX, I2_MAX);
|
||||
#endif
|
||||
#else
|
||||
UPDATE_ENDSTOP_BIT(I, MAX);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAS_J_MIN && !J_SPI_SENSORLESS
|
||||
#if ENABLED(J_DUAL_ENDSTOPS)
|
||||
UPDATE_ENDSTOP_BIT(J, MIN);
|
||||
#if HAS_J2_MIN
|
||||
UPDATE_ENDSTOP_BIT(J2, MIN);
|
||||
#else
|
||||
COPY_LIVE_STATE(J_MIN, J2_MIN);
|
||||
#endif
|
||||
#else
|
||||
UPDATE_ENDSTOP_BIT(J, MIN);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAS_J_MAX && !J_SPI_SENSORLESS
|
||||
#if ENABLED(J_DUAL_ENDSTOPS)
|
||||
UPDATE_ENDSTOP_BIT(J, MAX);
|
||||
#if HAS_J2_MAX
|
||||
UPDATE_ENDSTOP_BIT(J2, MAX);
|
||||
#else
|
||||
COPY_LIVE_STATE(J_MAX, J2_MAX);
|
||||
#endif
|
||||
#else
|
||||
UPDATE_ENDSTOP_BIT(J, MAX);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAS_K_MIN && !K_SPI_SENSORLESS
|
||||
#if ENABLED(K_DUAL_ENDSTOPS)
|
||||
UPDATE_ENDSTOP_BIT(K, MIN);
|
||||
#if HAS_K2_MIN
|
||||
UPDATE_ENDSTOP_BIT(K2, MIN);
|
||||
#else
|
||||
COPY_LIVE_STATE(K_MIN, K2_MIN);
|
||||
#endif
|
||||
#else
|
||||
UPDATE_ENDSTOP_BIT(K, MIN);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAS_K_MAX && !K_SPI_SENSORLESS
|
||||
#if ENABLED(K_DUAL_ENDSTOPS)
|
||||
UPDATE_ENDSTOP_BIT(K, MAX);
|
||||
#if HAS_K2_MAX
|
||||
UPDATE_ENDSTOP_BIT(K2, MAX);
|
||||
#else
|
||||
COPY_LIVE_STATE(K_MAX, K2_MAX);
|
||||
#endif
|
||||
#else
|
||||
UPDATE_ENDSTOP_BIT(K, MAX);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ENDSTOP_NOISE_THRESHOLD
|
||||
|
||||
/**
|
||||
@@ -671,7 +844,7 @@ void Endstops::update() {
|
||||
* still exist. The only way to reduce them further is to increase the number of samples.
|
||||
* To reduce the chance to 1% (1/128th) requires 7 samples (adding 7ms of delay).
|
||||
*/
|
||||
static esbits_t old_live_state;
|
||||
static endstop_mask_t old_live_state;
|
||||
if (old_live_state != live_state) {
|
||||
endstop_poll_count = ENDSTOP_NOISE_THRESHOLD;
|
||||
old_live_state = live_state;
|
||||
@@ -697,12 +870,21 @@ void Endstops::update() {
|
||||
} \
|
||||
}while(0)
|
||||
|
||||
// Core Sensorless Homing needs to test an Extra Pin
|
||||
#define CORE_DIAG(QQ,A,MM) (CORE_IS_##QQ && A##_SENSORLESS && !A##_SPI_SENSORLESS && HAS_##A##_##MM)
|
||||
#define PROCESS_CORE_ENDSTOP(A1,M1,A2,M2) do { \
|
||||
if (TEST_ENDSTOP(_ENDSTOP(A1,M1))) { \
|
||||
_ENDSTOP_HIT(A2,M2); \
|
||||
planner.endstop_triggered(_AXIS(A2)); \
|
||||
} \
|
||||
}while(0)
|
||||
|
||||
// Call the endstop triggered routine for dual endstops
|
||||
#define PROCESS_DUAL_ENDSTOP(A, MINMAX) do { \
|
||||
const byte dual_hit = TEST_ENDSTOP(_ENDSTOP(A, MINMAX)) | (TEST_ENDSTOP(_ENDSTOP(A##2, MINMAX)) << 1); \
|
||||
if (dual_hit) { \
|
||||
_ENDSTOP_HIT(A, MINMAX); \
|
||||
/* if not performing home or if both endstops were trigged during homing... */ \
|
||||
/* if not performing home or if both endstops were triggered during homing... */ \
|
||||
if (!stepper.separate_multi_axis || dual_hit == 0b11) \
|
||||
planner.endstop_triggered(_AXIS(A)); \
|
||||
} \
|
||||
@@ -712,7 +894,7 @@ void Endstops::update() {
|
||||
const byte triple_hit = TEST_ENDSTOP(_ENDSTOP(A, MINMAX)) | (TEST_ENDSTOP(_ENDSTOP(A##2, MINMAX)) << 1) | (TEST_ENDSTOP(_ENDSTOP(A##3, MINMAX)) << 2); \
|
||||
if (triple_hit) { \
|
||||
_ENDSTOP_HIT(A, MINMAX); \
|
||||
/* if not performing home or if both endstops were trigged during homing... */ \
|
||||
/* if not performing home or if both endstops were triggered during homing... */ \
|
||||
if (!stepper.separate_multi_axis || triple_hit == 0b111) \
|
||||
planner.endstop_triggered(_AXIS(A)); \
|
||||
} \
|
||||
@@ -722,7 +904,7 @@ void Endstops::update() {
|
||||
const byte quad_hit = TEST_ENDSTOP(_ENDSTOP(A, MINMAX)) | (TEST_ENDSTOP(_ENDSTOP(A##2, MINMAX)) << 1) | (TEST_ENDSTOP(_ENDSTOP(A##3, MINMAX)) << 2) | (TEST_ENDSTOP(_ENDSTOP(A##4, MINMAX)) << 3); \
|
||||
if (quad_hit) { \
|
||||
_ENDSTOP_HIT(A, MINMAX); \
|
||||
/* if not performing home or if both endstops were trigged during homing... */ \
|
||||
/* if not performing home or if both endstops were triggered during homing... */ \
|
||||
if (!stepper.separate_multi_axis || quad_hit == 0b1111) \
|
||||
planner.endstop_triggered(_AXIS(A)); \
|
||||
} \
|
||||
@@ -750,117 +932,249 @@ void Endstops::update() {
|
||||
#define PROCESS_ENDSTOP_Z(MINMAX) PROCESS_DUAL_ENDSTOP(Z, MINMAX)
|
||||
#endif
|
||||
|
||||
#if ENABLED(G38_PROBE_TARGET) && PIN_EXISTS(Z_MIN_PROBE) && !(CORE_IS_XY || CORE_IS_XZ)
|
||||
#if ENABLED(G38_PROBE_AWAY)
|
||||
#define _G38_OPEN_STATE (G38_move >= 4)
|
||||
#else
|
||||
#define _G38_OPEN_STATE LOW
|
||||
#endif
|
||||
// If G38 command is active check Z_MIN_PROBE for ALL movement
|
||||
if (G38_move && TEST_ENDSTOP(_ENDSTOP(Z, MIN_PROBE)) != _G38_OPEN_STATE) {
|
||||
if (stepper.axis_is_moving(X_AXIS)) { _ENDSTOP_HIT(X, MIN); planner.endstop_triggered(X_AXIS); }
|
||||
else if (stepper.axis_is_moving(Y_AXIS)) { _ENDSTOP_HIT(Y, MIN); planner.endstop_triggered(Y_AXIS); }
|
||||
else if (stepper.axis_is_moving(Z_AXIS)) { _ENDSTOP_HIT(Z, MIN); planner.endstop_triggered(Z_AXIS); }
|
||||
#if HAS_G38_PROBE
|
||||
#define _G38_OPEN_STATE TERN(G38_PROBE_AWAY, (G38_move >= 4), LOW)
|
||||
// For G38 moves check the probe's pin for ALL movement
|
||||
if (G38_move && TEST_ENDSTOP(_ENDSTOP(Z, TERN(USES_Z_MIN_PROBE_PIN, MIN_PROBE, MIN))) != _G38_OPEN_STATE) {
|
||||
if (stepper.axis_is_moving(X_AXIS)) { _ENDSTOP_HIT(X, TERN(X_HOME_TO_MIN, MIN, MAX)); planner.endstop_triggered(X_AXIS); }
|
||||
#if HAS_Y_AXIS
|
||||
else if (stepper.axis_is_moving(Y_AXIS)) { _ENDSTOP_HIT(Y, TERN(Y_HOME_TO_MIN, MIN, MAX)); planner.endstop_triggered(Y_AXIS); }
|
||||
#endif
|
||||
#if HAS_Z_AXIS
|
||||
else if (stepper.axis_is_moving(Z_AXIS)) { _ENDSTOP_HIT(Z, TERN(Z_HOME_TO_MIN, MIN, MAX)); planner.endstop_triggered(Z_AXIS); }
|
||||
#endif
|
||||
G38_did_trigger = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Now, we must signal, after validation, if an endstop limit is pressed or not
|
||||
// Signal, after validation, if an endstop limit is pressed or not
|
||||
|
||||
if (stepper.axis_is_moving(X_AXIS)) {
|
||||
if (stepper.motor_direction(X_AXIS_HEAD)) { // -direction
|
||||
#if HAS_X_MIN || (X_SPI_SENSORLESS && X_HOME_DIR < 0)
|
||||
#if HAS_X_MIN || (X_SPI_SENSORLESS && X_HOME_TO_MIN)
|
||||
PROCESS_ENDSTOP_X(MIN);
|
||||
#if CORE_DIAG(XY, Y, MIN)
|
||||
PROCESS_CORE_ENDSTOP(Y,MIN,X,MIN);
|
||||
#elif CORE_DIAG(XY, Y, MAX)
|
||||
PROCESS_CORE_ENDSTOP(Y,MAX,X,MIN);
|
||||
#elif CORE_DIAG(XZ, Z, MIN)
|
||||
PROCESS_CORE_ENDSTOP(Z,MIN,X,MIN);
|
||||
#elif CORE_DIAG(XZ, Z, MAX)
|
||||
PROCESS_CORE_ENDSTOP(Z,MAX,X,MIN);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
else { // +direction
|
||||
#if HAS_X_MAX || (X_SPI_SENSORLESS && X_HOME_DIR > 0)
|
||||
#if HAS_X_MAX || (X_SPI_SENSORLESS && X_HOME_TO_MAX)
|
||||
PROCESS_ENDSTOP_X(MAX);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (stepper.axis_is_moving(Y_AXIS)) {
|
||||
if (stepper.motor_direction(Y_AXIS_HEAD)) { // -direction
|
||||
#if HAS_Y_MIN || (Y_SPI_SENSORLESS && Y_HOME_DIR < 0)
|
||||
PROCESS_ENDSTOP_Y(MIN);
|
||||
#endif
|
||||
}
|
||||
else { // +direction
|
||||
#if HAS_Y_MAX || (Y_SPI_SENSORLESS && Y_HOME_DIR > 0)
|
||||
PROCESS_ENDSTOP_Y(MAX);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (stepper.axis_is_moving(Z_AXIS)) {
|
||||
if (stepper.motor_direction(Z_AXIS_HEAD)) { // Z -direction. Gantry down, bed up.
|
||||
|
||||
#if HAS_Z_MIN || (Z_SPI_SENSORLESS && Z_HOME_DIR < 0)
|
||||
if (true
|
||||
#if ENABLED(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN)
|
||||
&& z_probe_enabled
|
||||
#elif HAS_CUSTOM_PROBE_PIN
|
||||
&& !z_probe_enabled
|
||||
#endif
|
||||
) PROCESS_ENDSTOP_Z(MIN);
|
||||
#endif
|
||||
|
||||
// When closing the gap check the enabled probe
|
||||
#if HAS_CUSTOM_PROBE_PIN
|
||||
if (z_probe_enabled) PROCESS_ENDSTOP(Z, MIN_PROBE);
|
||||
#endif
|
||||
}
|
||||
else { // Z +direction. Gantry up, bed down.
|
||||
#if HAS_Z_MAX || (Z_SPI_SENSORLESS && Z_HOME_DIR > 0)
|
||||
#if ENABLED(Z_MULTI_ENDSTOPS)
|
||||
PROCESS_ENDSTOP_Z(MAX);
|
||||
#elif !HAS_CUSTOM_PROBE_PIN || Z_MAX_PIN != Z_MIN_PROBE_PIN // No probe or probe is Z_MIN || Probe is not Z_MAX
|
||||
PROCESS_ENDSTOP(Z, MAX);
|
||||
#if CORE_DIAG(XY, Y, MIN)
|
||||
PROCESS_CORE_ENDSTOP(Y,MIN,X,MAX);
|
||||
#elif CORE_DIAG(XY, Y, MAX)
|
||||
PROCESS_CORE_ENDSTOP(Y,MAX,X,MAX);
|
||||
#elif CORE_DIAG(XZ, Z, MIN)
|
||||
PROCESS_CORE_ENDSTOP(Z,MIN,X,MAX);
|
||||
#elif CORE_DIAG(XZ, Z, MAX)
|
||||
PROCESS_CORE_ENDSTOP(Z,MAX,X,MAX);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if HAS_Y_AXIS
|
||||
if (stepper.axis_is_moving(Y_AXIS)) {
|
||||
if (stepper.motor_direction(Y_AXIS_HEAD)) { // -direction
|
||||
#if HAS_Y_MIN || (Y_SPI_SENSORLESS && Y_HOME_TO_MIN)
|
||||
PROCESS_ENDSTOP_Y(MIN);
|
||||
#if CORE_DIAG(XY, X, MIN)
|
||||
PROCESS_CORE_ENDSTOP(X,MIN,Y,MIN);
|
||||
#elif CORE_DIAG(XY, X, MAX)
|
||||
PROCESS_CORE_ENDSTOP(X,MAX,Y,MIN);
|
||||
#elif CORE_DIAG(YZ, Z, MIN)
|
||||
PROCESS_CORE_ENDSTOP(Z,MIN,Y,MIN);
|
||||
#elif CORE_DIAG(YZ, Z, MAX)
|
||||
PROCESS_CORE_ENDSTOP(Z,MAX,Y,MIN);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
else { // +direction
|
||||
#if HAS_Y_MAX || (Y_SPI_SENSORLESS && Y_HOME_TO_MAX)
|
||||
PROCESS_ENDSTOP_Y(MAX);
|
||||
#if CORE_DIAG(XY, X, MIN)
|
||||
PROCESS_CORE_ENDSTOP(X,MIN,Y,MAX);
|
||||
#elif CORE_DIAG(XY, X, MAX)
|
||||
PROCESS_CORE_ENDSTOP(X,MAX,Y,MAX);
|
||||
#elif CORE_DIAG(YZ, Z, MIN)
|
||||
PROCESS_CORE_ENDSTOP(Z,MIN,Y,MAX);
|
||||
#elif CORE_DIAG(YZ, Z, MAX)
|
||||
PROCESS_CORE_ENDSTOP(Z,MAX,Y,MAX);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAS_Z_AXIS
|
||||
if (stepper.axis_is_moving(Z_AXIS)) {
|
||||
if (stepper.motor_direction(Z_AXIS_HEAD)) { // Z -direction. Gantry down, bed up.
|
||||
|
||||
#if HAS_Z_MIN || (Z_SPI_SENSORLESS && Z_HOME_TO_MIN)
|
||||
if ( TERN1(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN, z_probe_enabled)
|
||||
&& TERN1(USES_Z_MIN_PROBE_PIN, !z_probe_enabled)
|
||||
) PROCESS_ENDSTOP_Z(MIN);
|
||||
#if CORE_DIAG(XZ, X, MIN)
|
||||
PROCESS_CORE_ENDSTOP(X,MIN,Z,MIN);
|
||||
#elif CORE_DIAG(XZ, X, MAX)
|
||||
PROCESS_CORE_ENDSTOP(X,MAX,Z,MIN);
|
||||
#elif CORE_DIAG(YZ, Y, MIN)
|
||||
PROCESS_CORE_ENDSTOP(Y,MIN,Z,MIN);
|
||||
#elif CORE_DIAG(YZ, Y, MAX)
|
||||
PROCESS_CORE_ENDSTOP(Y,MAX,Z,MIN);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// When closing the gap check the enabled probe
|
||||
#if USES_Z_MIN_PROBE_PIN
|
||||
if (z_probe_enabled) PROCESS_ENDSTOP(Z, MIN_PROBE);
|
||||
#endif
|
||||
}
|
||||
else { // Z +direction. Gantry up, bed down.
|
||||
#if HAS_Z_MAX || (Z_SPI_SENSORLESS && Z_HOME_TO_MAX)
|
||||
#if ENABLED(Z_MULTI_ENDSTOPS)
|
||||
PROCESS_ENDSTOP_Z(MAX);
|
||||
#elif TERN1(USES_Z_MIN_PROBE_PIN, Z_MAX_PIN != Z_MIN_PROBE_PIN) // No probe or probe is Z_MIN || Probe is not Z_MAX
|
||||
PROCESS_ENDSTOP(Z, MAX);
|
||||
#endif
|
||||
#if CORE_DIAG(XZ, X, MIN)
|
||||
PROCESS_CORE_ENDSTOP(X,MIN,Z,MAX);
|
||||
#elif CORE_DIAG(XZ, X, MAX)
|
||||
PROCESS_CORE_ENDSTOP(X,MAX,Z,MAX);
|
||||
#elif CORE_DIAG(YZ, Y, MIN)
|
||||
PROCESS_CORE_ENDSTOP(Y,MIN,Z,MAX);
|
||||
#elif CORE_DIAG(YZ, Y, MAX)
|
||||
PROCESS_CORE_ENDSTOP(Y,MAX,Z,MAX);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LINEAR_AXES >= 4
|
||||
if (stepper.axis_is_moving(I_AXIS)) {
|
||||
if (stepper.motor_direction(I_AXIS_HEAD)) { // -direction
|
||||
#if HAS_I_MIN || (I_SPI_SENSORLESS && I_HOME_TO_MIN)
|
||||
PROCESS_ENDSTOP(I, MIN);
|
||||
#endif
|
||||
}
|
||||
else { // +direction
|
||||
#if HAS_I_MAX || (I_SPI_SENSORLESS && I_HOME_TO_MAX)
|
||||
PROCESS_ENDSTOP(I, MAX);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LINEAR_AXES >= 5
|
||||
if (stepper.axis_is_moving(J_AXIS)) {
|
||||
if (stepper.motor_direction(J_AXIS_HEAD)) { // -direction
|
||||
#if HAS_J_MIN || (J_SPI_SENSORLESS && J_HOME_TO_MIN)
|
||||
PROCESS_ENDSTOP(J, MIN);
|
||||
#endif
|
||||
}
|
||||
else { // +direction
|
||||
#if HAS_J_MAX || (J_SPI_SENSORLESS && J_HOME_TO_MAX)
|
||||
PROCESS_ENDSTOP(J, MAX);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LINEAR_AXES >= 6
|
||||
if (stepper.axis_is_moving(K_AXIS)) {
|
||||
if (stepper.motor_direction(K_AXIS_HEAD)) { // -direction
|
||||
#if HAS_K_MIN || (K_SPI_SENSORLESS && K_HOME_TO_MIN)
|
||||
PROCESS_ENDSTOP(K, MIN);
|
||||
#endif
|
||||
}
|
||||
else { // +direction
|
||||
#if HAS_K_MAX || (K_SPI_SENSORLESS && K_HOME_TO_MAX)
|
||||
PROCESS_ENDSTOP(K, MAX);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} // Endstops::update()
|
||||
|
||||
#if ENABLED(SPI_ENDSTOPS)
|
||||
|
||||
#define X_STOP (X_HOME_DIR < 0 ? X_MIN : X_MAX)
|
||||
#define Y_STOP (Y_HOME_DIR < 0 ? Y_MIN : Y_MAX)
|
||||
#define Z_STOP (Z_HOME_DIR < 0 ? Z_MIN : Z_MAX)
|
||||
|
||||
bool Endstops::tmc_spi_homing_check() {
|
||||
bool hit = false;
|
||||
#if X_SPI_SENSORLESS
|
||||
if (tmc_spi_homing.x && stepperX.test_stall_status()) {
|
||||
SBI(live_state, X_STOP);
|
||||
if (tmc_spi_homing.x && (stepperX.test_stall_status()
|
||||
#if ANY(CORE_IS_XY, MARKFORGED_XY) && Y_SPI_SENSORLESS
|
||||
|| stepperY.test_stall_status()
|
||||
#elif CORE_IS_XZ && Z_SPI_SENSORLESS
|
||||
|| stepperZ.test_stall_status()
|
||||
#endif
|
||||
)) {
|
||||
SBI(live_state, X_ENDSTOP);
|
||||
hit = true;
|
||||
}
|
||||
#endif
|
||||
#if Y_SPI_SENSORLESS
|
||||
if (tmc_spi_homing.y && stepperY.test_stall_status()) {
|
||||
SBI(live_state, Y_STOP);
|
||||
if (tmc_spi_homing.y && (stepperY.test_stall_status()
|
||||
#if ANY(CORE_IS_XY, MARKFORGED_XY) && X_SPI_SENSORLESS
|
||||
|| stepperX.test_stall_status()
|
||||
#elif CORE_IS_YZ && Z_SPI_SENSORLESS
|
||||
|| stepperZ.test_stall_status()
|
||||
#endif
|
||||
)) {
|
||||
SBI(live_state, Y_ENDSTOP);
|
||||
hit = true;
|
||||
}
|
||||
#endif
|
||||
#if Z_SPI_SENSORLESS
|
||||
if (tmc_spi_homing.z && stepperZ.test_stall_status()) {
|
||||
SBI(live_state, Z_STOP);
|
||||
if (tmc_spi_homing.z && (stepperZ.test_stall_status()
|
||||
#if CORE_IS_XZ && X_SPI_SENSORLESS
|
||||
|| stepperX.test_stall_status()
|
||||
#elif CORE_IS_YZ && Y_SPI_SENSORLESS
|
||||
|| stepperY.test_stall_status()
|
||||
#endif
|
||||
)) {
|
||||
SBI(live_state, Z_ENDSTOP);
|
||||
hit = true;
|
||||
}
|
||||
#endif
|
||||
#if I_SPI_SENSORLESS
|
||||
if (tmc_spi_homing.i && stepperI.test_stall_status()) {
|
||||
SBI(live_state, I_ENDSTOP);
|
||||
hit = true;
|
||||
}
|
||||
#endif
|
||||
#if J_SPI_SENSORLESS
|
||||
if (tmc_spi_homing.j && stepperJ.test_stall_status()) {
|
||||
SBI(live_state, J_ENDSTOP);
|
||||
hit = true;
|
||||
}
|
||||
#endif
|
||||
#if K_SPI_SENSORLESS
|
||||
if (tmc_spi_homing.k && stepperK.test_stall_status()) {
|
||||
SBI(live_state, K_ENDSTOP);
|
||||
hit = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (TERN0(ENDSTOP_INTERRUPTS_FEATURE, hit)) update();
|
||||
|
||||
return hit;
|
||||
}
|
||||
|
||||
void Endstops::clear_endstop_state() {
|
||||
#if X_SPI_SENSORLESS
|
||||
CBI(live_state, X_STOP);
|
||||
#endif
|
||||
#if Y_SPI_SENSORLESS
|
||||
CBI(live_state, Y_STOP);
|
||||
#endif
|
||||
#if Z_SPI_SENSORLESS
|
||||
CBI(live_state, Z_STOP);
|
||||
#endif
|
||||
TERN_(X_SPI_SENSORLESS, CBI(live_state, X_ENDSTOP));
|
||||
TERN_(Y_SPI_SENSORLESS, CBI(live_state, Y_ENDSTOP));
|
||||
TERN_(Z_SPI_SENSORLESS, CBI(live_state, Z_ENDSTOP));
|
||||
TERN_(I_SPI_SENSORLESS, CBI(live_state, I_ENDSTOP));
|
||||
TERN_(J_SPI_SENSORLESS, CBI(live_state, J_ENDSTOP));
|
||||
TERN_(K_SPI_SENSORLESS, CBI(live_state, K_ENDSTOP));
|
||||
}
|
||||
|
||||
#endif // SPI_ENDSTOPS
|
||||
@@ -937,9 +1251,27 @@ void Endstops::update() {
|
||||
#if HAS_Z4_MAX
|
||||
ES_GET_STATE(Z4_MAX);
|
||||
#endif
|
||||
#if HAS_I_MAX
|
||||
ES_GET_STATE(I_MAX);
|
||||
#endif
|
||||
#if HAS_I_MIN
|
||||
ES_GET_STATE(I_MIN);
|
||||
#endif
|
||||
#if HAS_J_MAX
|
||||
ES_GET_STATE(J_MAX);
|
||||
#endif
|
||||
#if HAS_J_MIN
|
||||
ES_GET_STATE(J_MIN);
|
||||
#endif
|
||||
#if HAS_K_MAX
|
||||
ES_GET_STATE(K_MAX);
|
||||
#endif
|
||||
#if HAS_K_MIN
|
||||
ES_GET_STATE(K_MIN);
|
||||
#endif
|
||||
|
||||
uint16_t endstop_change = live_state_local ^ old_live_state_local;
|
||||
#define ES_REPORT_CHANGE(S) if (TEST(endstop_change, S)) SERIAL_ECHOPAIR(" " STRINGIFY(S) ":", TEST(live_state_local, S))
|
||||
#define ES_REPORT_CHANGE(S) if (TEST(endstop_change, S)) SERIAL_ECHOPGM(" " STRINGIFY(S) ":", TEST(live_state_local, S))
|
||||
|
||||
if (endstop_change) {
|
||||
#if HAS_X_MIN
|
||||
@@ -993,6 +1325,24 @@ void Endstops::update() {
|
||||
#if HAS_Z4_MAX
|
||||
ES_REPORT_CHANGE(Z4_MAX);
|
||||
#endif
|
||||
#if HAS_I_MIN
|
||||
ES_REPORT_CHANGE(I_MIN);
|
||||
#endif
|
||||
#if HAS_I_MAX
|
||||
ES_REPORT_CHANGE(I_MAX);
|
||||
#endif
|
||||
#if HAS_J_MIN
|
||||
ES_REPORT_CHANGE(J_MIN);
|
||||
#endif
|
||||
#if HAS_J_MAX
|
||||
ES_REPORT_CHANGE(J_MAX);
|
||||
#endif
|
||||
#if HAS_K_MIN
|
||||
ES_REPORT_CHANGE(K_MIN);
|
||||
#endif
|
||||
#if HAS_K_MAX
|
||||
ES_REPORT_CHANGE(K_MAX);
|
||||
#endif
|
||||
SERIAL_ECHOLNPGM("\n");
|
||||
analogWrite(pin_t(LED_PIN), local_LED_status);
|
||||
local_LED_status ^= 255;
|
||||
|
130
Marlin/src/module/endstops.h
Executable file → Normal file
130
Marlin/src/module/endstops.h
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@@ -28,46 +28,96 @@
|
||||
#include "../inc/MarlinConfig.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#define __ES_ITEM(N) N,
|
||||
#define _ES_ITEM(K,N) TERN_(K,DEFER4(__ES_ITEM)(N))
|
||||
|
||||
enum EndstopEnum : char {
|
||||
X_MIN, Y_MIN, Z_MIN, Z_MIN_PROBE,
|
||||
X_MAX, Y_MAX, Z_MAX,
|
||||
X2_MIN, X2_MAX,
|
||||
Y2_MIN, Y2_MAX,
|
||||
Z2_MIN, Z2_MAX,
|
||||
Z3_MIN, Z3_MAX,
|
||||
Z4_MIN, Z4_MAX
|
||||
// Common XYZ (ABC) endstops. Defined according to USE_[XYZ](MIN|MAX)_PLUG settings.
|
||||
_ES_ITEM(HAS_X_MIN, X_MIN)
|
||||
_ES_ITEM(HAS_X_MAX, X_MAX)
|
||||
_ES_ITEM(HAS_Y_MIN, Y_MIN)
|
||||
_ES_ITEM(HAS_Y_MAX, Y_MAX)
|
||||
_ES_ITEM(HAS_Z_MIN, Z_MIN)
|
||||
_ES_ITEM(HAS_Z_MAX, Z_MAX)
|
||||
_ES_ITEM(HAS_I_MIN, I_MIN)
|
||||
_ES_ITEM(HAS_I_MAX, I_MAX)
|
||||
_ES_ITEM(HAS_J_MIN, J_MIN)
|
||||
_ES_ITEM(HAS_J_MAX, J_MAX)
|
||||
_ES_ITEM(HAS_K_MIN, K_MIN)
|
||||
_ES_ITEM(HAS_K_MAX, K_MAX)
|
||||
|
||||
// Extra Endstops for XYZ
|
||||
_ES_ITEM(HAS_X2_MIN, X2_MIN)
|
||||
_ES_ITEM(HAS_X2_MAX, X2_MAX)
|
||||
_ES_ITEM(HAS_Y2_MIN, Y2_MIN)
|
||||
_ES_ITEM(HAS_Y2_MAX, Y2_MAX)
|
||||
_ES_ITEM(HAS_Z2_MIN, Z2_MIN)
|
||||
_ES_ITEM(HAS_Z2_MAX, Z2_MAX)
|
||||
_ES_ITEM(HAS_Z3_MIN, Z3_MIN)
|
||||
_ES_ITEM(HAS_Z3_MAX, Z3_MAX)
|
||||
_ES_ITEM(HAS_Z4_MIN, Z4_MIN)
|
||||
_ES_ITEM(HAS_Z4_MAX, Z4_MAX)
|
||||
|
||||
// Bed Probe state is distinct or shared with Z_MIN (i.e., when the probe is the only Z endstop)
|
||||
#if !HAS_DELTA_SENSORLESS_PROBING
|
||||
_ES_ITEM(HAS_BED_PROBE, Z_MIN_PROBE IF_DISABLED(USES_Z_MIN_PROBE_PIN, = Z_MIN))
|
||||
#endif
|
||||
|
||||
// The total number of states
|
||||
NUM_ENDSTOP_STATES
|
||||
|
||||
// Endstops can be either MIN or MAX but not both
|
||||
#if HAS_X_MIN || HAS_X_MAX
|
||||
, X_ENDSTOP = TERN(X_HOME_TO_MAX, X_MAX, X_MIN)
|
||||
#endif
|
||||
#if HAS_Y_MIN || HAS_Y_MAX
|
||||
, Y_ENDSTOP = TERN(Y_HOME_TO_MAX, Y_MAX, Y_MIN)
|
||||
#endif
|
||||
#if HAS_Z_MIN || HAS_Z_MAX || HOMING_Z_WITH_PROBE
|
||||
, Z_ENDSTOP = TERN(Z_HOME_TO_MAX, Z_MAX, TERN(HOMING_Z_WITH_PROBE, Z_MIN_PROBE, Z_MIN))
|
||||
#endif
|
||||
#if HAS_I_MIN || HAS_I_MAX
|
||||
, I_ENDSTOP = TERN(I_HOME_TO_MAX, I_MAX, I_MIN)
|
||||
#endif
|
||||
#if HAS_J_MIN || HAS_J_MAX
|
||||
, J_ENDSTOP = TERN(J_HOME_TO_MAX, J_MAX, J_MIN)
|
||||
#endif
|
||||
#if HAS_K_MIN || HAS_K_MAX
|
||||
, K_ENDSTOP = TERN(K_HOME_TO_MAX, K_MAX, K_MIN)
|
||||
#endif
|
||||
};
|
||||
|
||||
#undef __ES_ITEM
|
||||
#undef _ES_ITEM
|
||||
|
||||
class Endstops {
|
||||
public:
|
||||
#if HAS_EXTRA_ENDSTOPS
|
||||
typedef uint16_t esbits_t;
|
||||
#if ENABLED(X_DUAL_ENDSTOPS)
|
||||
static float x2_endstop_adj;
|
||||
#endif
|
||||
#if ENABLED(Y_DUAL_ENDSTOPS)
|
||||
static float y2_endstop_adj;
|
||||
#endif
|
||||
#if ENABLED(Z_MULTI_ENDSTOPS)
|
||||
static float z2_endstop_adj;
|
||||
#endif
|
||||
#if ENABLED(Z_MULTI_ENDSTOPS) && NUM_Z_STEPPER_DRIVERS >= 3
|
||||
static float z3_endstop_adj;
|
||||
#endif
|
||||
#if ENABLED(Z_MULTI_ENDSTOPS) && NUM_Z_STEPPER_DRIVERS >= 4
|
||||
static float z4_endstop_adj;
|
||||
#endif
|
||||
#else
|
||||
typedef uint8_t esbits_t;
|
||||
|
||||
typedef IF<(NUM_ENDSTOP_STATES > 8), uint16_t, uint8_t>::type endstop_mask_t;
|
||||
|
||||
#if ENABLED(X_DUAL_ENDSTOPS)
|
||||
static float x2_endstop_adj;
|
||||
#endif
|
||||
#if ENABLED(Y_DUAL_ENDSTOPS)
|
||||
static float y2_endstop_adj;
|
||||
#endif
|
||||
#if ENABLED(Z_MULTI_ENDSTOPS)
|
||||
static float z2_endstop_adj;
|
||||
#endif
|
||||
#if ENABLED(Z_MULTI_ENDSTOPS) && NUM_Z_STEPPER_DRIVERS >= 3
|
||||
static float z3_endstop_adj;
|
||||
#endif
|
||||
#if ENABLED(Z_MULTI_ENDSTOPS) && NUM_Z_STEPPER_DRIVERS >= 4
|
||||
static float z4_endstop_adj;
|
||||
#endif
|
||||
|
||||
private:
|
||||
static bool enabled, enabled_globally;
|
||||
static esbits_t live_state;
|
||||
static volatile uint8_t hit_state; // Use X_MIN, Y_MIN, Z_MIN and Z_MIN_PROBE as BIT index
|
||||
static endstop_mask_t live_state;
|
||||
static volatile endstop_mask_t hit_state; // Use X_MIN, Y_MIN, Z_MIN and Z_MIN_PROBE as BIT index
|
||||
|
||||
#if ENDSTOP_NOISE_THRESHOLD
|
||||
static esbits_t validated_live_state;
|
||||
static endstop_mask_t validated_live_state;
|
||||
static uint8_t endstop_poll_count; // Countdown from threshold for polling
|
||||
#endif
|
||||
|
||||
@@ -83,11 +133,7 @@ class Endstops {
|
||||
* Are endstops or the probe set to abort the move?
|
||||
*/
|
||||
FORCE_INLINE static bool abort_enabled() {
|
||||
return (enabled
|
||||
#if HAS_BED_PROBE
|
||||
|| z_probe_enabled
|
||||
#endif
|
||||
);
|
||||
return enabled || TERN0(HAS_BED_PROBE, z_probe_enabled);
|
||||
}
|
||||
|
||||
static inline bool global_enabled() { return enabled_globally; }
|
||||
@@ -107,12 +153,12 @@ class Endstops {
|
||||
/**
|
||||
* Get Endstop hit state.
|
||||
*/
|
||||
FORCE_INLINE static uint8_t trigger_state() { return hit_state; }
|
||||
FORCE_INLINE static endstop_mask_t trigger_state() { return hit_state; }
|
||||
|
||||
/**
|
||||
* Get current endstops state
|
||||
*/
|
||||
FORCE_INLINE static esbits_t state() {
|
||||
FORCE_INLINE static endstop_mask_t state() {
|
||||
return
|
||||
#if ENDSTOP_NOISE_THRESHOLD
|
||||
validated_live_state
|
||||
@@ -122,6 +168,14 @@ class Endstops {
|
||||
;
|
||||
}
|
||||
|
||||
static inline bool probe_switch_activated() {
|
||||
return (true
|
||||
#if ENABLED(PROBE_ACTIVATION_SWITCH)
|
||||
&& READ(PROBE_ACTIVATION_SWITCH_PIN) == PROBE_ACTIVATION_SWITCH_STATE
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Report endstop hits to serial. Called from loop().
|
||||
*/
|
||||
@@ -170,7 +224,7 @@ class Endstops {
|
||||
typedef struct {
|
||||
union {
|
||||
bool any;
|
||||
struct { bool x:1, y:1, z:1; };
|
||||
struct { bool LINEAR_AXIS_LIST(x:1, y:1, z:1, i:1, j:1, k:1); };
|
||||
};
|
||||
} tmc_spi_homing_t;
|
||||
static tmc_spi_homing_t tmc_spi_homing;
|
||||
|
2118
Marlin/src/module/motion.cpp
Executable file → Normal file
2118
Marlin/src/module/motion.cpp
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
454
Marlin/src/module/motion.h
Executable file → Normal file
454
Marlin/src/module/motion.h
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@@ -34,25 +34,6 @@
|
||||
#include "scara.h"
|
||||
#endif
|
||||
|
||||
// Axis homed and known-position states
|
||||
extern uint8_t axis_homed, axis_known_position;
|
||||
constexpr uint8_t xyz_bits = _BV(X_AXIS) | _BV(Y_AXIS) | _BV(Z_AXIS);
|
||||
FORCE_INLINE bool no_axes_homed() { return !axis_homed; }
|
||||
FORCE_INLINE bool all_axes_homed() { return (axis_homed & xyz_bits) == xyz_bits; }
|
||||
FORCE_INLINE bool all_axes_known() { return (axis_known_position & xyz_bits) == xyz_bits; }
|
||||
FORCE_INLINE void set_all_unhomed() { axis_homed = 0; }
|
||||
FORCE_INLINE void set_all_unknown() { axis_known_position = 0; }
|
||||
|
||||
FORCE_INLINE bool homing_needed() {
|
||||
return !(
|
||||
#if ENABLED(HOME_AFTER_DEACTIVATE)
|
||||
all_axes_known()
|
||||
#else
|
||||
all_axes_homed()
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
// Error margin to work around float imprecision
|
||||
constexpr float fslop = 0.0001;
|
||||
|
||||
@@ -63,8 +44,8 @@ extern xyze_pos_t current_position, // High-level current tool position
|
||||
|
||||
// G60/G61 Position Save and Return
|
||||
#if SAVED_POSITIONS
|
||||
extern uint8_t saved_slots[(SAVED_POSITIONS + 7) >> 3];
|
||||
extern xyz_pos_t stored_position[SAVED_POSITIONS];
|
||||
extern uint8_t saved_slots[(SAVED_POSITIONS + 7) >> 3]; // TODO: Add support for LINEAR_AXES >= 4
|
||||
extern xyze_pos_t stored_position[SAVED_POSITIONS];
|
||||
#endif
|
||||
|
||||
// Scratch space for a cartesian result
|
||||
@@ -72,39 +53,57 @@ extern xyz_pos_t cartes;
|
||||
|
||||
// Until kinematics.cpp is created, declare this here
|
||||
#if IS_KINEMATIC
|
||||
extern abc_pos_t delta;
|
||||
extern abce_pos_t delta;
|
||||
#endif
|
||||
|
||||
#if HAS_ABL_NOT_UBL
|
||||
extern float xy_probe_feedrate_mm_s;
|
||||
extern feedRate_t xy_probe_feedrate_mm_s;
|
||||
#define XY_PROBE_FEEDRATE_MM_S xy_probe_feedrate_mm_s
|
||||
#elif defined(XY_PROBE_SPEED)
|
||||
#define XY_PROBE_FEEDRATE_MM_S MMM_TO_MMS(XY_PROBE_SPEED)
|
||||
#elif defined(XY_PROBE_FEEDRATE)
|
||||
#define XY_PROBE_FEEDRATE_MM_S MMM_TO_MMS(XY_PROBE_FEEDRATE)
|
||||
#else
|
||||
#define XY_PROBE_FEEDRATE_MM_S PLANNER_XY_FEEDRATE()
|
||||
#endif
|
||||
|
||||
#if ENABLED(Z_SAFE_HOMING)
|
||||
constexpr xy_float_t safe_homing_xy = { Z_SAFE_HOMING_X_POINT, Z_SAFE_HOMING_Y_POINT };
|
||||
#if HAS_BED_PROBE
|
||||
constexpr feedRate_t z_probe_fast_mm_s = MMM_TO_MMS(Z_PROBE_FEEDRATE_FAST);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Feed rates are often configured with mm/m
|
||||
* but the planner and stepper like mm/s units.
|
||||
*/
|
||||
extern const feedRate_t homing_feedrate_mm_s[XYZ];
|
||||
FORCE_INLINE feedRate_t homing_feedrate(const AxisEnum a) { return pgm_read_float(&homing_feedrate_mm_s[a]); }
|
||||
constexpr xyz_feedrate_t homing_feedrate_mm_m = HOMING_FEEDRATE_MM_M;
|
||||
FORCE_INLINE feedRate_t homing_feedrate(const AxisEnum a) {
|
||||
float v = TERN0(HAS_Z_AXIS, homing_feedrate_mm_m.z);
|
||||
#if DISABLED(DELTA)
|
||||
LINEAR_AXIS_CODE(
|
||||
if (a == X_AXIS) v = homing_feedrate_mm_m.x,
|
||||
else if (a == Y_AXIS) v = homing_feedrate_mm_m.y,
|
||||
else if (a == Z_AXIS) v = homing_feedrate_mm_m.z,
|
||||
else if (a == I_AXIS) v = homing_feedrate_mm_m.i,
|
||||
else if (a == J_AXIS) v = homing_feedrate_mm_m.j,
|
||||
else if (a == K_AXIS) v = homing_feedrate_mm_m.k
|
||||
);
|
||||
#endif
|
||||
return MMM_TO_MMS(v);
|
||||
}
|
||||
|
||||
feedRate_t get_homing_bump_feedrate(const AxisEnum axis);
|
||||
|
||||
/**
|
||||
* The default feedrate for many moves, set by the most recent move
|
||||
*/
|
||||
extern feedRate_t feedrate_mm_s;
|
||||
|
||||
/**
|
||||
* Feedrate scaling
|
||||
* Feedrate scaling is applied to all G0/G1, G2/G3, and G5 moves
|
||||
*/
|
||||
extern int16_t feedrate_percentage;
|
||||
#define MMS_SCALED(V) ((V) * 0.01f * feedrate_percentage)
|
||||
|
||||
// The active extruder (tool). Set with T<extruder> command.
|
||||
#if EXTRUDERS > 1
|
||||
#if HAS_MULTI_EXTRUDER
|
||||
extern uint8_t active_extruder;
|
||||
#else
|
||||
constexpr uint8_t active_extruder = 0;
|
||||
@@ -114,24 +113,35 @@ extern int16_t feedrate_percentage;
|
||||
extern float e_move_accumulator;
|
||||
#endif
|
||||
|
||||
FORCE_INLINE float pgm_read_any(const float *p) { return pgm_read_float(p); }
|
||||
FORCE_INLINE signed char pgm_read_any(const signed char *p) { return pgm_read_byte(p); }
|
||||
#ifdef __IMXRT1062__
|
||||
#define DEFS_PROGMEM
|
||||
#else
|
||||
#define DEFS_PROGMEM PROGMEM
|
||||
#endif
|
||||
|
||||
inline float pgm_read_any(const float *p) { return TERN(__IMXRT1062__, *p, pgm_read_float(p)); }
|
||||
inline int8_t pgm_read_any(const int8_t *p) { return TERN(__IMXRT1062__, *p, pgm_read_byte(p)); }
|
||||
|
||||
#define XYZ_DEFS(T, NAME, OPT) \
|
||||
extern const XYZval<T> NAME##_P; \
|
||||
FORCE_INLINE T NAME(AxisEnum axis) { return pgm_read_any(&NAME##_P[axis]); }
|
||||
|
||||
inline T NAME(const AxisEnum axis) { \
|
||||
static const XYZval<T> NAME##_P DEFS_PROGMEM = LINEAR_AXIS_ARRAY(X_##OPT, Y_##OPT, Z_##OPT, I_##OPT, J_##OPT, K_##OPT); \
|
||||
return pgm_read_any(&NAME##_P[axis]); \
|
||||
}
|
||||
XYZ_DEFS(float, base_min_pos, MIN_POS);
|
||||
XYZ_DEFS(float, base_max_pos, MAX_POS);
|
||||
XYZ_DEFS(float, base_home_pos, HOME_POS);
|
||||
XYZ_DEFS(float, max_length, MAX_LENGTH);
|
||||
XYZ_DEFS(float, home_bump_mm, HOME_BUMP_MM);
|
||||
XYZ_DEFS(signed char, home_dir, HOME_DIR);
|
||||
XYZ_DEFS(int8_t, home_dir, HOME_DIR);
|
||||
|
||||
inline float home_bump_mm(const AxisEnum axis) {
|
||||
static const xyz_pos_t home_bump_mm_P DEFS_PROGMEM = HOMING_BUMP_MM;
|
||||
return pgm_read_any(&home_bump_mm_P[axis]);
|
||||
}
|
||||
|
||||
#if HAS_WORKSPACE_OFFSET
|
||||
void update_workspace_offset(const AxisEnum axis);
|
||||
#else
|
||||
#define update_workspace_offset(x) NOOP
|
||||
inline void update_workspace_offset(const AxisEnum) {}
|
||||
#endif
|
||||
|
||||
#if HAS_HOTEND_OFFSET
|
||||
@@ -143,67 +153,167 @@ XYZ_DEFS(signed char, home_dir, HOME_DIR);
|
||||
constexpr xyz_pos_t hotend_offset[1] = { { 0 } };
|
||||
#endif
|
||||
|
||||
typedef struct { xyz_pos_t min, max; } axis_limits_t;
|
||||
#if HAS_SOFTWARE_ENDSTOPS
|
||||
extern bool soft_endstops_enabled;
|
||||
extern axis_limits_t soft_endstop;
|
||||
|
||||
typedef struct {
|
||||
bool _enabled, _loose;
|
||||
bool enabled() { return _enabled && !_loose; }
|
||||
|
||||
xyz_pos_t min, max;
|
||||
void get_manual_axis_limits(const AxisEnum axis, float &amin, float &amax) {
|
||||
amin = -100000; amax = 100000; // "No limits"
|
||||
#if HAS_SOFTWARE_ENDSTOPS
|
||||
if (enabled()) switch (axis) {
|
||||
case X_AXIS:
|
||||
TERN_(MIN_SOFTWARE_ENDSTOP_X, amin = min.x);
|
||||
TERN_(MAX_SOFTWARE_ENDSTOP_X, amax = max.x);
|
||||
break;
|
||||
#if HAS_Y_AXIS
|
||||
case Y_AXIS:
|
||||
TERN_(MIN_SOFTWARE_ENDSTOP_Y, amin = min.y);
|
||||
TERN_(MAX_SOFTWARE_ENDSTOP_Y, amax = max.y);
|
||||
break;
|
||||
#endif
|
||||
#if HAS_Z_AXIS
|
||||
case Z_AXIS:
|
||||
TERN_(MIN_SOFTWARE_ENDSTOP_Z, amin = min.z);
|
||||
TERN_(MAX_SOFTWARE_ENDSTOP_Z, amax = max.z);
|
||||
break;
|
||||
#endif
|
||||
#if LINEAR_AXES >= 4
|
||||
case I_AXIS:
|
||||
TERN_(MIN_SOFTWARE_ENDSTOP_I, amin = min.i);
|
||||
TERN_(MIN_SOFTWARE_ENDSTOP_I, amax = max.i);
|
||||
break;
|
||||
#endif
|
||||
#if LINEAR_AXES >= 5
|
||||
case J_AXIS:
|
||||
TERN_(MIN_SOFTWARE_ENDSTOP_J, amin = min.j);
|
||||
TERN_(MIN_SOFTWARE_ENDSTOP_J, amax = max.j);
|
||||
break;
|
||||
#endif
|
||||
#if LINEAR_AXES >= 6
|
||||
case K_AXIS:
|
||||
TERN_(MIN_SOFTWARE_ENDSTOP_K, amin = min.k);
|
||||
TERN_(MIN_SOFTWARE_ENDSTOP_K, amax = max.k);
|
||||
break;
|
||||
#endif
|
||||
default: break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} soft_endstops_t;
|
||||
|
||||
extern soft_endstops_t soft_endstop;
|
||||
void apply_motion_limits(xyz_pos_t &target);
|
||||
void update_software_endstops(const AxisEnum axis
|
||||
#if HAS_HOTEND_OFFSET
|
||||
, const uint8_t old_tool_index=0, const uint8_t new_tool_index=0
|
||||
#endif
|
||||
);
|
||||
#else
|
||||
constexpr bool soft_endstops_enabled = false;
|
||||
//constexpr axis_limits_t soft_endstop = {
|
||||
// { X_MIN_POS, Y_MIN_POS, Z_MIN_POS },
|
||||
// { X_MAX_POS, Y_MAX_POS, Z_MAX_POS } };
|
||||
#define apply_motion_limits(V) NOOP
|
||||
#define SET_SOFT_ENDSTOP_LOOSE(loose) (soft_endstop._loose = loose)
|
||||
|
||||
#else // !HAS_SOFTWARE_ENDSTOPS
|
||||
|
||||
typedef struct {
|
||||
bool enabled() { return false; }
|
||||
void get_manual_axis_limits(const AxisEnum axis, float &amin, float &amax) {
|
||||
// No limits
|
||||
amin = current_position[axis] - 1000;
|
||||
amax = current_position[axis] + 1000;
|
||||
}
|
||||
} soft_endstops_t;
|
||||
extern soft_endstops_t soft_endstop;
|
||||
#define apply_motion_limits(V) NOOP
|
||||
#define update_software_endstops(...) NOOP
|
||||
#endif
|
||||
#define SET_SOFT_ENDSTOP_LOOSE(V) NOOP
|
||||
|
||||
#endif // !HAS_SOFTWARE_ENDSTOPS
|
||||
|
||||
void report_real_position();
|
||||
void report_current_position();
|
||||
void report_current_position_projected();
|
||||
|
||||
#if ENABLED(AUTO_REPORT_POSITION)
|
||||
#include "../libs/autoreport.h"
|
||||
struct PositionReport { static void report() { report_current_position_projected(); } };
|
||||
extern AutoReporter<PositionReport> position_auto_reporter;
|
||||
#endif
|
||||
|
||||
#if EITHER(FULL_REPORT_TO_HOST_FEATURE, REALTIME_REPORTING_COMMANDS)
|
||||
#define HAS_GRBL_STATE 1
|
||||
/**
|
||||
* Machine states for GRBL or TinyG
|
||||
*/
|
||||
enum M_StateEnum : uint8_t {
|
||||
M_INIT = 0, // 0 machine is initializing
|
||||
M_RESET, // 1 machine is ready for use
|
||||
M_ALARM, // 2 machine is in alarm state (soft shut down)
|
||||
M_IDLE, // 3 program stop or no more blocks (M0, M1, M60)
|
||||
M_END, // 4 program end via M2, M30
|
||||
M_RUNNING, // 5 motion is running
|
||||
M_HOLD, // 6 motion is holding
|
||||
M_PROBE, // 7 probe cycle active
|
||||
M_CYCLING, // 8 machine is running (cycling)
|
||||
M_HOMING, // 9 machine is homing
|
||||
M_JOGGING, // 10 machine is jogging
|
||||
M_ERROR // 11 machine is in hard alarm state (shut down)
|
||||
};
|
||||
extern M_StateEnum M_State_grbl;
|
||||
M_StateEnum grbl_state_for_marlin_state();
|
||||
void report_current_grblstate_moving();
|
||||
void report_current_position_moving();
|
||||
|
||||
#if ENABLED(FULL_REPORT_TO_HOST_FEATURE)
|
||||
inline void set_and_report_grblstate(const M_StateEnum state) {
|
||||
M_State_grbl = state;
|
||||
report_current_grblstate_moving();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENABLED(REALTIME_REPORTING_COMMANDS)
|
||||
void quickpause_stepper();
|
||||
void quickresume_stepper();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void get_cartesian_from_steppers();
|
||||
void set_current_from_steppers_for_axis(const AxisEnum axis);
|
||||
|
||||
void quickstop_stepper();
|
||||
|
||||
/**
|
||||
* sync_plan_position
|
||||
*
|
||||
* Set the planner/stepper positions directly from current_position with
|
||||
* no kinematic translation. Used for homing axes and cartesian/core syncing.
|
||||
*/
|
||||
void sync_plan_position();
|
||||
void sync_plan_position_e();
|
||||
|
||||
#if HAS_EXTRUDERS
|
||||
void sync_plan_position_e();
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Move the planner to the current position from wherever it last moved
|
||||
* (or from wherever it has been told it is located).
|
||||
*/
|
||||
void line_to_current_position(const feedRate_t &fr_mm_s=feedrate_mm_s);
|
||||
void line_to_current_position(const_feedRate_t fr_mm_s=feedrate_mm_s);
|
||||
|
||||
#if EXTRUDERS
|
||||
void unscaled_e_move(const float &length, const feedRate_t &fr_mm_s);
|
||||
#if HAS_EXTRUDERS
|
||||
void unscaled_e_move(const_float_t length, const_feedRate_t fr_mm_s);
|
||||
#endif
|
||||
|
||||
void prepare_line_to_destination();
|
||||
|
||||
void _internal_move_to_destination(const feedRate_t &fr_mm_s=0.0f
|
||||
#if IS_KINEMATIC
|
||||
, const bool is_fast=false
|
||||
#endif
|
||||
);
|
||||
void _internal_move_to_destination(const_feedRate_t fr_mm_s=0.0f OPTARG(IS_KINEMATIC, const bool is_fast=false));
|
||||
|
||||
inline void prepare_internal_move_to_destination(const feedRate_t &fr_mm_s=0.0f) {
|
||||
inline void prepare_internal_move_to_destination(const_feedRate_t fr_mm_s=0.0f) {
|
||||
_internal_move_to_destination(fr_mm_s);
|
||||
}
|
||||
|
||||
#if IS_KINEMATIC
|
||||
void prepare_fast_move_to_destination(const feedRate_t &scaled_fr_mm_s=MMS_SCALED(feedrate_mm_s));
|
||||
void prepare_fast_move_to_destination(const_feedRate_t scaled_fr_mm_s=MMS_SCALED(feedrate_mm_s));
|
||||
|
||||
inline void prepare_internal_fast_move_to_destination(const feedRate_t &fr_mm_s=0.0f) {
|
||||
inline void prepare_internal_fast_move_to_destination(const_feedRate_t fr_mm_s=0.0f) {
|
||||
_internal_move_to_destination(fr_mm_s, true);
|
||||
}
|
||||
#endif
|
||||
@@ -211,46 +321,114 @@ inline void prepare_internal_move_to_destination(const feedRate_t &fr_mm_s=0.0f)
|
||||
/**
|
||||
* Blocking movement and shorthand functions
|
||||
*/
|
||||
void do_blocking_move_to(const float rx, const float ry, const float rz, const feedRate_t &fr_mm_s=0.0f);
|
||||
void do_blocking_move_to(const xy_pos_t &raw, const feedRate_t &fr_mm_s=0.0f);
|
||||
void do_blocking_move_to(const xyz_pos_t &raw, const feedRate_t &fr_mm_s=0.0f);
|
||||
void do_blocking_move_to(const xyze_pos_t &raw, const feedRate_t &fr_mm_s=0.0f);
|
||||
void do_blocking_move_to(LINEAR_AXIS_ARGS(const float), const_feedRate_t fr_mm_s=0.0f);
|
||||
void do_blocking_move_to(const xy_pos_t &raw, const_feedRate_t fr_mm_s=0.0f);
|
||||
void do_blocking_move_to(const xyz_pos_t &raw, const_feedRate_t fr_mm_s=0.0f);
|
||||
void do_blocking_move_to(const xyze_pos_t &raw, const_feedRate_t fr_mm_s=0.0f);
|
||||
|
||||
void do_blocking_move_to_x(const float &rx, const feedRate_t &fr_mm_s=0.0f);
|
||||
void do_blocking_move_to_y(const float &ry, const feedRate_t &fr_mm_s=0.0f);
|
||||
void do_blocking_move_to_z(const float &rz, const feedRate_t &fr_mm_s=0.0f);
|
||||
void do_blocking_move_to_x(const_float_t rx, const_feedRate_t fr_mm_s=0.0f);
|
||||
#if HAS_Y_AXIS
|
||||
void do_blocking_move_to_y(const_float_t ry, const_feedRate_t fr_mm_s=0.0f);
|
||||
#endif
|
||||
#if HAS_Z_AXIS
|
||||
void do_blocking_move_to_z(const_float_t rz, const_feedRate_t fr_mm_s=0.0f);
|
||||
#endif
|
||||
#if LINEAR_AXES >= 4
|
||||
void do_blocking_move_to_i(const_float_t ri, const_feedRate_t fr_mm_s=0.0f);
|
||||
void do_blocking_move_to_xyz_i(const xyze_pos_t &raw, const_float_t i, const_feedRate_t fr_mm_s=0.0f);
|
||||
#endif
|
||||
#if LINEAR_AXES >= 5
|
||||
void do_blocking_move_to_j(const_float_t rj, const_feedRate_t fr_mm_s=0.0f);
|
||||
void do_blocking_move_to_xyzi_j(const xyze_pos_t &raw, const_float_t j, const_feedRate_t fr_mm_s=0.0f);
|
||||
#endif
|
||||
#if LINEAR_AXES >= 6
|
||||
void do_blocking_move_to_k(const_float_t rk, const_feedRate_t fr_mm_s=0.0f);
|
||||
void do_blocking_move_to_xyzij_k(const xyze_pos_t &raw, const_float_t k, const_feedRate_t fr_mm_s=0.0f);
|
||||
#endif
|
||||
|
||||
void do_blocking_move_to_xy(const float &rx, const float &ry, const feedRate_t &fr_mm_s=0.0f);
|
||||
void do_blocking_move_to_xy(const xy_pos_t &raw, const feedRate_t &fr_mm_s=0.0f);
|
||||
FORCE_INLINE void do_blocking_move_to_xy(const xyz_pos_t &raw, const feedRate_t &fr_mm_s=0.0f) { do_blocking_move_to_xy(xy_pos_t(raw), fr_mm_s); }
|
||||
FORCE_INLINE void do_blocking_move_to_xy(const xyze_pos_t &raw, const feedRate_t &fr_mm_s=0.0f) { do_blocking_move_to_xy(xy_pos_t(raw), fr_mm_s); }
|
||||
#if HAS_Y_AXIS
|
||||
void do_blocking_move_to_xy(const_float_t rx, const_float_t ry, const_feedRate_t fr_mm_s=0.0f);
|
||||
void do_blocking_move_to_xy(const xy_pos_t &raw, const_feedRate_t fr_mm_s=0.0f);
|
||||
FORCE_INLINE void do_blocking_move_to_xy(const xyz_pos_t &raw, const_feedRate_t fr_mm_s=0.0f) { do_blocking_move_to_xy(xy_pos_t(raw), fr_mm_s); }
|
||||
FORCE_INLINE void do_blocking_move_to_xy(const xyze_pos_t &raw, const_feedRate_t fr_mm_s=0.0f) { do_blocking_move_to_xy(xy_pos_t(raw), fr_mm_s); }
|
||||
#endif
|
||||
|
||||
void do_blocking_move_to_xy_z(const xy_pos_t &raw, const float &z, const feedRate_t &fr_mm_s=0.0f);
|
||||
FORCE_INLINE void do_blocking_move_to_xy_z(const xyz_pos_t &raw, const float &z, const feedRate_t &fr_mm_s=0.0f) { do_blocking_move_to_xy_z(xy_pos_t(raw), z, fr_mm_s); }
|
||||
FORCE_INLINE void do_blocking_move_to_xy_z(const xyze_pos_t &raw, const float &z, const feedRate_t &fr_mm_s=0.0f) { do_blocking_move_to_xy_z(xy_pos_t(raw), z, fr_mm_s); }
|
||||
#if HAS_Z_AXIS
|
||||
void do_blocking_move_to_xy_z(const xy_pos_t &raw, const_float_t z, const_feedRate_t fr_mm_s=0.0f);
|
||||
FORCE_INLINE void do_blocking_move_to_xy_z(const xyz_pos_t &raw, const_float_t z, const_feedRate_t fr_mm_s=0.0f) { do_blocking_move_to_xy_z(xy_pos_t(raw), z, fr_mm_s); }
|
||||
FORCE_INLINE void do_blocking_move_to_xy_z(const xyze_pos_t &raw, const_float_t z, const_feedRate_t fr_mm_s=0.0f) { do_blocking_move_to_xy_z(xy_pos_t(raw), z, fr_mm_s); }
|
||||
#endif
|
||||
|
||||
void remember_feedrate_and_scaling();
|
||||
void remember_feedrate_scaling_off();
|
||||
void restore_feedrate_and_scaling();
|
||||
|
||||
//
|
||||
// Homing
|
||||
//
|
||||
#if HAS_Z_AXIS
|
||||
void do_z_clearance(const_float_t zclear, const bool lower_allowed=false);
|
||||
#else
|
||||
inline void do_z_clearance(float, bool=false) {}
|
||||
#endif
|
||||
|
||||
uint8_t axes_need_homing(uint8_t axis_bits=0x07);
|
||||
bool axis_unhomed_error(uint8_t axis_bits=0x07);
|
||||
/**
|
||||
* Homing and Trusted Axes
|
||||
*/
|
||||
typedef IF<(LINEAR_AXES > 8), uint16_t, uint8_t>::type linear_axis_bits_t;
|
||||
constexpr linear_axis_bits_t linear_bits = _BV(LINEAR_AXES) - 1;
|
||||
|
||||
void set_axis_is_at_home(const AxisEnum axis);
|
||||
|
||||
#if HAS_ENDSTOPS
|
||||
/**
|
||||
* axis_homed
|
||||
* Flags that each linear axis was homed.
|
||||
* XYZ on cartesian, ABC on delta, ABZ on SCARA.
|
||||
*
|
||||
* axis_trusted
|
||||
* Flags that the position is trusted in each linear axis. Set when homed.
|
||||
* Cleared whenever a stepper powers off, potentially losing its position.
|
||||
*/
|
||||
extern linear_axis_bits_t axis_homed, axis_trusted;
|
||||
void homeaxis(const AxisEnum axis);
|
||||
void set_axis_never_homed(const AxisEnum axis);
|
||||
linear_axis_bits_t axes_should_home(linear_axis_bits_t axis_bits=linear_bits);
|
||||
bool homing_needed_error(linear_axis_bits_t axis_bits=linear_bits);
|
||||
inline void set_axis_unhomed(const AxisEnum axis) { CBI(axis_homed, axis); }
|
||||
inline void set_axis_untrusted(const AxisEnum axis) { CBI(axis_trusted, axis); }
|
||||
inline void set_all_unhomed() { axis_homed = axis_trusted = 0; }
|
||||
inline void set_axis_homed(const AxisEnum axis) { SBI(axis_homed, axis); }
|
||||
inline void set_axis_trusted(const AxisEnum axis) { SBI(axis_trusted, axis); }
|
||||
inline void set_all_homed() { axis_homed = axis_trusted = linear_bits; }
|
||||
#else
|
||||
constexpr linear_axis_bits_t axis_homed = linear_bits, axis_trusted = linear_bits; // Zero-endstop machines are always homed and trusted
|
||||
inline void homeaxis(const AxisEnum axis) {}
|
||||
inline void set_axis_never_homed(const AxisEnum) {}
|
||||
inline linear_axis_bits_t axes_should_home(linear_axis_bits_t=linear_bits) { return false; }
|
||||
inline bool homing_needed_error(linear_axis_bits_t=linear_bits) { return false; }
|
||||
inline void set_axis_unhomed(const AxisEnum axis) {}
|
||||
inline void set_axis_untrusted(const AxisEnum axis) {}
|
||||
inline void set_all_unhomed() {}
|
||||
inline void set_axis_homed(const AxisEnum axis) {}
|
||||
inline void set_axis_trusted(const AxisEnum axis) {}
|
||||
inline void set_all_homed() {}
|
||||
#endif
|
||||
|
||||
inline bool axis_was_homed(const AxisEnum axis) { return TEST(axis_homed, axis); }
|
||||
inline bool axis_is_trusted(const AxisEnum axis) { return TEST(axis_trusted, axis); }
|
||||
inline bool axis_should_home(const AxisEnum axis) { return (axes_should_home() & _BV(axis)) != 0; }
|
||||
inline bool no_axes_homed() { return !axis_homed; }
|
||||
inline bool all_axes_homed() { return linear_bits == (axis_homed & linear_bits); }
|
||||
inline bool homing_needed() { return !all_axes_homed(); }
|
||||
inline bool all_axes_trusted() { return linear_bits == (axis_trusted & linear_bits); }
|
||||
|
||||
void home_if_needed(const bool keeplev=false);
|
||||
|
||||
#if ENABLED(NO_MOTION_BEFORE_HOMING)
|
||||
#define MOTION_CONDITIONS (IsRunning() && !axis_unhomed_error())
|
||||
#define MOTION_CONDITIONS (IsRunning() && !homing_needed_error())
|
||||
#else
|
||||
#define MOTION_CONDITIONS IsRunning()
|
||||
#endif
|
||||
|
||||
void set_axis_is_at_home(const AxisEnum axis);
|
||||
|
||||
void set_axis_not_trusted(const AxisEnum axis);
|
||||
|
||||
void homeaxis(const AxisEnum axis);
|
||||
#define BABYSTEP_ALLOWED() ((ENABLED(BABYSTEP_WITHOUT_HOMING) || all_axes_trusted()) && (ENABLED(BABYSTEP_ALWAYS_AVAILABLE) || printer_busy()))
|
||||
|
||||
/**
|
||||
* Workspace offsets
|
||||
@@ -289,16 +467,31 @@ void homeaxis(const AxisEnum axis);
|
||||
FORCE_INLINE void toNative(xyze_pos_t&) {}
|
||||
#endif
|
||||
#define LOGICAL_X_POSITION(POS) NATIVE_TO_LOGICAL(POS, X_AXIS)
|
||||
#define LOGICAL_Y_POSITION(POS) NATIVE_TO_LOGICAL(POS, Y_AXIS)
|
||||
#define LOGICAL_Z_POSITION(POS) NATIVE_TO_LOGICAL(POS, Z_AXIS)
|
||||
#define RAW_X_POSITION(POS) LOGICAL_TO_NATIVE(POS, X_AXIS)
|
||||
#define RAW_Y_POSITION(POS) LOGICAL_TO_NATIVE(POS, Y_AXIS)
|
||||
#define RAW_Z_POSITION(POS) LOGICAL_TO_NATIVE(POS, Z_AXIS)
|
||||
#if HAS_Y_AXIS
|
||||
#define LOGICAL_Y_POSITION(POS) NATIVE_TO_LOGICAL(POS, Y_AXIS)
|
||||
#define RAW_Y_POSITION(POS) LOGICAL_TO_NATIVE(POS, Y_AXIS)
|
||||
#endif
|
||||
#if HAS_Z_AXIS
|
||||
#define LOGICAL_Z_POSITION(POS) NATIVE_TO_LOGICAL(POS, Z_AXIS)
|
||||
#define RAW_Z_POSITION(POS) LOGICAL_TO_NATIVE(POS, Z_AXIS)
|
||||
#endif
|
||||
#if LINEAR_AXES >= 4
|
||||
#define LOGICAL_I_POSITION(POS) NATIVE_TO_LOGICAL(POS, I_AXIS)
|
||||
#define RAW_I_POSITION(POS) LOGICAL_TO_NATIVE(POS, I_AXIS)
|
||||
#endif
|
||||
#if LINEAR_AXES >= 5
|
||||
#define LOGICAL_J_POSITION(POS) NATIVE_TO_LOGICAL(POS, J_AXIS)
|
||||
#define RAW_J_POSITION(POS) LOGICAL_TO_NATIVE(POS, J_AXIS)
|
||||
#endif
|
||||
#if LINEAR_AXES >= 6
|
||||
#define LOGICAL_K_POSITION(POS) NATIVE_TO_LOGICAL(POS, K_AXIS)
|
||||
#define RAW_K_POSITION(POS) LOGICAL_TO_NATIVE(POS, K_AXIS)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* position_is_reachable family of functions
|
||||
*/
|
||||
|
||||
#if IS_KINEMATIC // (DELTA or SCARA)
|
||||
|
||||
#if HAS_SCARA_OFFSET
|
||||
@@ -306,10 +499,31 @@ void homeaxis(const AxisEnum axis);
|
||||
#endif
|
||||
|
||||
// Return true if the given point is within the printable area
|
||||
inline bool position_is_reachable(const float &rx, const float &ry, const float inset=0) {
|
||||
inline bool position_is_reachable(const_float_t rx, const_float_t ry, const float inset=0) {
|
||||
#if ENABLED(DELTA)
|
||||
|
||||
return HYPOT2(rx, ry) <= sq(DELTA_PRINTABLE_RADIUS - inset + fslop);
|
||||
|
||||
#elif ENABLED(POLARGRAPH)
|
||||
|
||||
const float x1 = rx - (X_MIN_POS), x2 = (X_MAX_POS) - rx, y = ry - (Y_MAX_POS),
|
||||
a = HYPOT(x1, y), b = HYPOT(x2, y);
|
||||
return a < (POLARGRAPH_MAX_BELT_LEN) + 1
|
||||
&& b < (POLARGRAPH_MAX_BELT_LEN) + 1
|
||||
&& (a + b) > _MIN(X_BED_SIZE, Y_BED_SIZE);
|
||||
|
||||
#elif ENABLED(AXEL_TPARA)
|
||||
|
||||
const float R2 = HYPOT2(rx - TPARA_OFFSET_X, ry - TPARA_OFFSET_Y);
|
||||
return (
|
||||
R2 <= sq(L1 + L2) - inset
|
||||
#if MIDDLE_DEAD_ZONE_R > 0
|
||||
&& R2 >= sq(float(MIDDLE_DEAD_ZONE_R))
|
||||
#endif
|
||||
);
|
||||
|
||||
#elif IS_SCARA
|
||||
|
||||
const float R2 = HYPOT2(rx - SCARA_OFFSET_X, ry - SCARA_OFFSET_Y);
|
||||
return (
|
||||
R2 <= sq(L1 + L2) - inset
|
||||
@@ -317,6 +531,7 @@ void homeaxis(const AxisEnum axis);
|
||||
&& R2 >= sq(float(MIDDLE_DEAD_ZONE_R))
|
||||
#endif
|
||||
);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -327,15 +542,15 @@ void homeaxis(const AxisEnum axis);
|
||||
#else // CARTESIAN
|
||||
|
||||
// Return true if the given position is within the machine bounds.
|
||||
inline bool position_is_reachable(const float &rx, const float &ry) {
|
||||
if (!WITHIN(ry, Y_MIN_POS - fslop, Y_MAX_POS + fslop)) return false;
|
||||
inline bool position_is_reachable(const_float_t rx, const_float_t ry) {
|
||||
if (!COORDINATE_OKAY(ry, Y_MIN_POS - fslop, Y_MAX_POS + fslop)) return false;
|
||||
#if ENABLED(DUAL_X_CARRIAGE)
|
||||
if (active_extruder)
|
||||
return WITHIN(rx, X2_MIN_POS - fslop, X2_MAX_POS + fslop);
|
||||
return COORDINATE_OKAY(rx, X2_MIN_POS - fslop, X2_MAX_POS + fslop);
|
||||
else
|
||||
return WITHIN(rx, X1_MIN_POS - fslop, X1_MAX_POS + fslop);
|
||||
return COORDINATE_OKAY(rx, X1_MIN_POS - fslop, X1_MAX_POS + fslop);
|
||||
#else
|
||||
return WITHIN(rx, X_MIN_POS - fslop, X_MAX_POS + fslop);
|
||||
return COORDINATE_OKAY(rx, X_MIN_POS - fslop, X_MAX_POS + fslop);
|
||||
#endif
|
||||
}
|
||||
inline bool position_is_reachable(const xy_pos_t &pos) { return position_is_reachable(pos.x, pos.y); }
|
||||
@@ -346,11 +561,7 @@ void homeaxis(const AxisEnum axis);
|
||||
* Duplication mode
|
||||
*/
|
||||
#if HAS_DUPLICATION_MODE
|
||||
extern bool extruder_duplication_enabled, // Used in Dual X mode 2
|
||||
mirrored_duplication_mode; // Used in Dual X mode 3
|
||||
#if ENABLED(MULTI_NOZZLE_DUPLICATION)
|
||||
extern uint8_t duplication_e_mask;
|
||||
#endif
|
||||
extern bool extruder_duplication_enabled; // Used in Dual X mode 2
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -366,29 +577,42 @@ void homeaxis(const AxisEnum axis);
|
||||
};
|
||||
|
||||
extern DualXMode dual_x_carriage_mode;
|
||||
extern float inactive_extruder_x_pos, // Used in mode 0 & 1
|
||||
duplicate_extruder_x_offset; // Used in mode 2 & 3
|
||||
extern xyz_pos_t raised_parked_position; // Used in mode 1
|
||||
extern bool active_extruder_parked; // Used in mode 1, 2 & 3
|
||||
extern millis_t delayed_move_time; // Used in mode 1
|
||||
extern int16_t duplicate_extruder_temp_offset; // Used in mode 2 & 3
|
||||
extern float inactive_extruder_x, // Used in mode 0 & 1
|
||||
duplicate_extruder_x_offset; // Used in mode 2 & 3
|
||||
extern xyz_pos_t raised_parked_position; // Used in mode 1
|
||||
extern bool active_extruder_parked; // Used in mode 1, 2 & 3
|
||||
extern millis_t delayed_move_time; // Used in mode 1
|
||||
extern celsius_t duplicate_extruder_temp_offset; // Used in mode 2 & 3
|
||||
extern bool idex_mirrored_mode; // Used in mode 3
|
||||
|
||||
FORCE_INLINE bool dxc_is_duplicating() { return dual_x_carriage_mode >= DXC_DUPLICATION_MODE; }
|
||||
FORCE_INLINE bool idex_is_duplicating() { return dual_x_carriage_mode >= DXC_DUPLICATION_MODE; }
|
||||
|
||||
float x_home_pos(const int extruder);
|
||||
float x_home_pos(const uint8_t extruder);
|
||||
|
||||
FORCE_INLINE int x_home_dir(const uint8_t extruder) { return extruder ? X2_HOME_DIR : X_HOME_DIR; }
|
||||
#define TOOL_X_HOME_DIR(T) ((T) ? X2_HOME_DIR : X_HOME_DIR)
|
||||
|
||||
void set_duplication_enabled(const bool dupe, const int8_t tool_index=-1);
|
||||
void idex_set_mirrored_mode(const bool mirr);
|
||||
void idex_set_parked(const bool park=true);
|
||||
|
||||
#else
|
||||
|
||||
#if ENABLED(MULTI_NOZZLE_DUPLICATION)
|
||||
extern uint8_t duplication_e_mask;
|
||||
enum DualXMode : char { DXC_DUPLICATION_MODE = 2 };
|
||||
FORCE_INLINE void set_duplication_enabled(const bool dupe) { extruder_duplication_enabled = dupe; }
|
||||
#endif
|
||||
|
||||
FORCE_INLINE int x_home_dir(const uint8_t) { return home_dir(X_AXIS); }
|
||||
#define TOOL_X_HOME_DIR(T) X_HOME_DIR
|
||||
|
||||
#endif
|
||||
|
||||
#if HAS_M206_COMMAND
|
||||
void set_home_offset(const AxisEnum axis, const float v);
|
||||
#endif
|
||||
|
||||
#if USE_SENSORLESS
|
||||
struct sensorless_t;
|
||||
sensorless_t start_sensorless_homing_per_axis(const AxisEnum axis);
|
||||
void end_sensorless_homing_per_axis(const AxisEnum axis, sensorless_t enable_stealth);
|
||||
#endif
|
||||
|
1793
Marlin/src/module/planner.cpp
Executable file → Normal file
1793
Marlin/src/module/planner.cpp
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
532
Marlin/src/module/planner.h
Executable file → Normal file
532
Marlin/src/module/planner.h
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@@ -32,11 +32,24 @@
|
||||
|
||||
#include "../MarlinCore.h"
|
||||
|
||||
#if ENABLED(JD_HANDLE_SMALL_SEGMENTS)
|
||||
// Enable this option for perfect accuracy but maximum
|
||||
// computation. Should be fine on ARM processors.
|
||||
//#define JD_USE_MATH_ACOS
|
||||
|
||||
// Disable this option to save 120 bytes of PROGMEM,
|
||||
// but incur increased computation and a reduction
|
||||
// in accuracy.
|
||||
#define JD_USE_LOOKUP_TABLE
|
||||
#endif
|
||||
|
||||
#include "motion.h"
|
||||
#include "../gcode/queue.h"
|
||||
|
||||
#if ENABLED(DELTA)
|
||||
#include "delta.h"
|
||||
#elif ENABLED(POLARGRAPH)
|
||||
#include "polargraph.h"
|
||||
#endif
|
||||
|
||||
#if ABL_PLANAR
|
||||
@@ -52,16 +65,25 @@
|
||||
#endif
|
||||
|
||||
#if HAS_CUTTER
|
||||
#include "../feature/spindle_laser.h"
|
||||
#include "../feature/spindle_laser_types.h"
|
||||
#endif
|
||||
|
||||
#if ENABLED(DIRECT_STEPPING)
|
||||
#include "../feature/direct_stepping.h"
|
||||
#define IS_PAGE(B) TEST(B->flag, BLOCK_BIT_IS_PAGE)
|
||||
#else
|
||||
#define IS_PAGE(B) false
|
||||
#endif
|
||||
|
||||
// Feedrate for manual moves
|
||||
#ifdef MANUAL_FEEDRATE
|
||||
constexpr xyze_feedrate_t _mf = MANUAL_FEEDRATE,
|
||||
manual_feedrate_mm_s { _mf.x / 60.0f, _mf.y / 60.0f, _mf.z / 60.0f, _mf.e / 60.0f };
|
||||
manual_feedrate_mm_s = LOGICAL_AXIS_ARRAY(_mf.e / 60.0f,
|
||||
_mf.x / 60.0f, _mf.y / 60.0f, _mf.z / 60.0f,
|
||||
_mf.i / 60.0f, _mf.j / 60.0f, _mf.k / 60.0f);
|
||||
#endif
|
||||
|
||||
#if IS_KINEMATIC && DISABLED(CLASSIC_JERK)
|
||||
#if IS_KINEMATIC && HAS_JUNCTION_DEVIATION
|
||||
#define HAS_DIST_MM_ARG 1
|
||||
#endif
|
||||
|
||||
@@ -79,15 +101,57 @@ enum BlockFlagBit : char {
|
||||
|
||||
// Sync the stepper counts from the block
|
||||
BLOCK_BIT_SYNC_POSITION
|
||||
|
||||
// Direct stepping page
|
||||
#if ENABLED(DIRECT_STEPPING)
|
||||
, BLOCK_BIT_IS_PAGE
|
||||
#endif
|
||||
|
||||
// Sync the fan speeds from the block
|
||||
#if ENABLED(LASER_SYNCHRONOUS_M106_M107)
|
||||
, BLOCK_BIT_SYNC_FANS
|
||||
#endif
|
||||
};
|
||||
|
||||
enum BlockFlag : char {
|
||||
BLOCK_FLAG_RECALCULATE = _BV(BLOCK_BIT_RECALCULATE),
|
||||
BLOCK_FLAG_NOMINAL_LENGTH = _BV(BLOCK_BIT_NOMINAL_LENGTH),
|
||||
BLOCK_FLAG_CONTINUED = _BV(BLOCK_BIT_CONTINUED),
|
||||
BLOCK_FLAG_SYNC_POSITION = _BV(BLOCK_BIT_SYNC_POSITION)
|
||||
BLOCK_FLAG_RECALCULATE = _BV(BLOCK_BIT_RECALCULATE)
|
||||
, BLOCK_FLAG_NOMINAL_LENGTH = _BV(BLOCK_BIT_NOMINAL_LENGTH)
|
||||
, BLOCK_FLAG_CONTINUED = _BV(BLOCK_BIT_CONTINUED)
|
||||
, BLOCK_FLAG_SYNC_POSITION = _BV(BLOCK_BIT_SYNC_POSITION)
|
||||
#if ENABLED(DIRECT_STEPPING)
|
||||
, BLOCK_FLAG_IS_PAGE = _BV(BLOCK_BIT_IS_PAGE)
|
||||
#endif
|
||||
#if ENABLED(LASER_SYNCHRONOUS_M106_M107)
|
||||
, BLOCK_FLAG_SYNC_FANS = _BV(BLOCK_BIT_SYNC_FANS)
|
||||
#endif
|
||||
};
|
||||
|
||||
#define BLOCK_MASK_SYNC ( BLOCK_FLAG_SYNC_POSITION | TERN0(LASER_SYNCHRONOUS_M106_M107, BLOCK_FLAG_SYNC_FANS) )
|
||||
|
||||
#if ENABLED(LASER_POWER_INLINE)
|
||||
|
||||
typedef struct {
|
||||
bool isPlanned:1;
|
||||
bool isEnabled:1;
|
||||
bool dir:1;
|
||||
bool Reserved:6;
|
||||
} power_status_t;
|
||||
|
||||
typedef struct {
|
||||
power_status_t status; // See planner settings for meaning
|
||||
uint8_t power; // Ditto; When in trapezoid mode this is nominal power
|
||||
#if ENABLED(LASER_POWER_INLINE_TRAPEZOID)
|
||||
uint8_t power_entry; // Entry power for the laser
|
||||
#if DISABLED(LASER_POWER_INLINE_TRAPEZOID_CONT)
|
||||
uint8_t power_exit; // Exit power for the laser
|
||||
uint32_t entry_per, // Steps per power increment (to avoid floats in stepper calcs)
|
||||
exit_per; // Steps per power decrement
|
||||
#endif
|
||||
#endif
|
||||
} block_laser_t;
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* struct block_t
|
||||
*
|
||||
@@ -114,14 +178,14 @@ typedef struct block_t {
|
||||
};
|
||||
uint32_t step_event_count; // The number of step events required to complete this block
|
||||
|
||||
#if EXTRUDERS > 1
|
||||
#if HAS_MULTI_EXTRUDER
|
||||
uint8_t extruder; // The extruder to move (if E move)
|
||||
#else
|
||||
static constexpr uint8_t extruder = 0;
|
||||
#endif
|
||||
|
||||
#if ENABLED(MIXING_EXTRUDER)
|
||||
MIXER_BLOCK_FIELD; // Normalized color for the mixing steppers
|
||||
mixer_comp_t b_color[MIXING_STEPPERS]; // Normalized color for the mixing steppers
|
||||
#endif
|
||||
|
||||
// Settings for the trapezoid generator
|
||||
@@ -138,7 +202,7 @@ typedef struct block_t {
|
||||
uint32_t acceleration_rate; // The acceleration rate used for acceleration calculation
|
||||
#endif
|
||||
|
||||
uint8_t direction_bits; // The direction bit set for this block (refers to *_DIRECTION_BIT in config.h)
|
||||
axis_bits_t direction_bits; // The direction bit set for this block (refers to *_DIRECTION_BIT in config.h)
|
||||
|
||||
// Advance extrusion
|
||||
#if ENABLED(LIN_ADVANCE)
|
||||
@@ -154,11 +218,15 @@ typedef struct block_t {
|
||||
final_rate, // The minimal rate at exit
|
||||
acceleration_steps_per_s2; // acceleration steps/sec^2
|
||||
|
||||
#if ENABLED(DIRECT_STEPPING)
|
||||
page_idx_t page_idx; // Page index used for direct stepping
|
||||
#endif
|
||||
|
||||
#if HAS_CUTTER
|
||||
cutter_power_t cutter_power; // Power level for Spindle, Laser, etc.
|
||||
#endif
|
||||
|
||||
#if FAN_COUNT > 0
|
||||
#if HAS_FAN
|
||||
uint8_t fan_speed[FAN_COUNT];
|
||||
#endif
|
||||
|
||||
@@ -166,7 +234,7 @@ typedef struct block_t {
|
||||
uint8_t valve_pressure, e_to_p_pressure;
|
||||
#endif
|
||||
|
||||
#if HAS_SPI_LCD
|
||||
#if HAS_WIRED_LCD
|
||||
uint32_t segment_time_us;
|
||||
#endif
|
||||
|
||||
@@ -174,17 +242,40 @@ typedef struct block_t {
|
||||
uint32_t sdpos;
|
||||
#endif
|
||||
|
||||
#if ENABLED(LASER_POWER_INLINE)
|
||||
block_laser_t laser;
|
||||
#endif
|
||||
|
||||
} block_t;
|
||||
|
||||
#define HAS_POSITION_FLOAT ANY(LIN_ADVANCE, SCARA_FEEDRATE_SCALING, GRADIENT_MIX, LCD_SHOW_E_TOTAL)
|
||||
#if ANY(LIN_ADVANCE, SCARA_FEEDRATE_SCALING, GRADIENT_MIX, LCD_SHOW_E_TOTAL)
|
||||
#define HAS_POSITION_FLOAT 1
|
||||
#endif
|
||||
|
||||
#define BLOCK_MOD(n) ((n)&(BLOCK_BUFFER_SIZE-1))
|
||||
|
||||
#if ENABLED(LASER_POWER_INLINE)
|
||||
typedef struct {
|
||||
/**
|
||||
* Laser status flags
|
||||
*/
|
||||
power_status_t status;
|
||||
/**
|
||||
* Laser power: 0 or 255 in case of PWM-less laser,
|
||||
* or the OCR (oscillator count register) value;
|
||||
*
|
||||
* Using OCR instead of raw power, because it avoids
|
||||
* floating point operations during the move loop.
|
||||
*/
|
||||
uint8_t power;
|
||||
} laser_state_t;
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint32_t max_acceleration_mm_per_s2[XYZE_N], // (mm/s^2) M201 XYZE
|
||||
uint32_t max_acceleration_mm_per_s2[DISTINCT_AXES], // (mm/s^2) M201 XYZE
|
||||
min_segment_time_us; // (µs) M205 B
|
||||
float axis_steps_per_mm[XYZE_N]; // (steps) M92 XYZE - Steps per millimeter
|
||||
feedRate_t max_feedrate_mm_s[XYZE_N]; // (mm/s) M203 XYZE - Max speeds
|
||||
float axis_steps_per_mm[DISTINCT_AXES]; // (steps) M92 XYZE - Steps per millimeter
|
||||
feedRate_t max_feedrate_mm_s[DISTINCT_AXES]; // (mm/s) M203 XYZE - Max speeds
|
||||
float acceleration, // (mm/s^2) M204 S - Normal acceleration. DEFAULT ACCELERATION for all printing moves.
|
||||
retract_acceleration, // (mm/s^2) M204 R - Retract acceleration. Filament pull-back and push-forward while standing still in the other axes
|
||||
travel_acceleration; // (mm/s^2) M204 T - Travel acceleration. DEFAULT ACCELERATION for all NON printing moves.
|
||||
@@ -192,6 +283,15 @@ typedef struct {
|
||||
min_travel_feedrate_mm_s; // (mm/s) M205 T - Minimum travel feedrate
|
||||
} planner_settings_t;
|
||||
|
||||
#if ENABLED(IMPROVE_HOMING_RELIABILITY)
|
||||
struct motion_state_t {
|
||||
TERN(DELTA, xyz_ulong_t, xy_ulong_t) acceleration;
|
||||
#if HAS_CLASSIC_JERK
|
||||
TERN(DELTA, xyz_float_t, xy_float_t) jerk_state;
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
||||
#if DISABLED(SKEW_CORRECTION)
|
||||
#define XY_SKEW_FACTOR 0
|
||||
#define XZ_SKEW_FACTOR 0
|
||||
@@ -212,6 +312,10 @@ typedef struct {
|
||||
#endif
|
||||
} skew_factor_t;
|
||||
|
||||
#if ENABLED(DISABLE_INACTIVE_EXTRUDER)
|
||||
typedef IF<(BLOCK_BUFFER_SIZE > 64), uint16_t, uint8_t>::type last_move_t;
|
||||
#endif
|
||||
|
||||
class Planner {
|
||||
public:
|
||||
|
||||
@@ -241,7 +345,12 @@ class Planner {
|
||||
static uint8_t last_extruder; // Respond to extruder change
|
||||
#endif
|
||||
|
||||
#if EXTRUDERS
|
||||
#if ENABLED(DIRECT_STEPPING)
|
||||
static uint32_t last_page_step_rate; // Last page step rate given
|
||||
static xyze_bool_t last_page_dir; // Last page direction given
|
||||
#endif
|
||||
|
||||
#if HAS_EXTRUDERS
|
||||
static int16_t flow_percentage[EXTRUDERS]; // Extrusion factor for each extruder
|
||||
static float e_factor[EXTRUDERS]; // The flow percentage and volumetric multiplier combine to scale E movement
|
||||
#endif
|
||||
@@ -253,28 +362,30 @@ class Planner {
|
||||
// May be auto-adjusted by a filament width sensor
|
||||
#endif
|
||||
|
||||
#if ENABLED(VOLUMETRIC_EXTRUDER_LIMIT)
|
||||
static float volumetric_extruder_limit[EXTRUDERS], // Maximum mm^3/sec the extruder can handle
|
||||
volumetric_extruder_feedrate_limit[EXTRUDERS]; // Feedrate limit (mm/s) calculated from volume limit
|
||||
#endif
|
||||
|
||||
static planner_settings_t settings;
|
||||
|
||||
static uint32_t max_acceleration_steps_per_s2[XYZE_N]; // (steps/s^2) Derived from mm_per_s2
|
||||
static float steps_to_mm[XYZE_N]; // Millimeters per step
|
||||
#if ENABLED(LASER_POWER_INLINE)
|
||||
static laser_state_t laser_inline;
|
||||
#endif
|
||||
|
||||
#if DISABLED(CLASSIC_JERK)
|
||||
static float junction_deviation_mm; // (mm) M205 J
|
||||
#if ENABLED(LIN_ADVANCE)
|
||||
static float max_e_jerk // Calculated from junction_deviation_mm
|
||||
#if ENABLED(DISTINCT_E_FACTORS)
|
||||
[EXTRUDERS]
|
||||
#endif
|
||||
;
|
||||
static uint32_t max_acceleration_steps_per_s2[DISTINCT_AXES]; // (steps/s^2) Derived from mm_per_s2
|
||||
static float mm_per_step[DISTINCT_AXES]; // Millimeters per step
|
||||
|
||||
#if HAS_JUNCTION_DEVIATION
|
||||
static float junction_deviation_mm; // (mm) M205 J
|
||||
#if HAS_LINEAR_E_JERK
|
||||
static float max_e_jerk[DISTINCT_E]; // Calculated from junction_deviation_mm
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAS_CLASSIC_JERK
|
||||
#if HAS_LINEAR_E_JERK
|
||||
static xyz_pos_t max_jerk; // (mm/s^2) M205 XYZ - The largest speed change requiring no acceleration.
|
||||
#else
|
||||
static xyze_pos_t max_jerk; // (mm/s^2) M205 XYZE - The largest speed change requiring no acceleration.
|
||||
#endif
|
||||
// (mm/s^2) M205 XYZ(E) - The largest speed change requiring no acceleration.
|
||||
static TERN(HAS_LINEAR_E_JERK, xyz_pos_t, xyze_pos_t) max_jerk;
|
||||
#endif
|
||||
|
||||
#if HAS_LEVELING
|
||||
@@ -312,6 +423,23 @@ class Planner {
|
||||
#if ENABLED(SD_ABORT_ON_ENDSTOP_HIT)
|
||||
static bool abort_on_endstop_hit;
|
||||
#endif
|
||||
#ifdef XY_FREQUENCY_LIMIT
|
||||
static int8_t xy_freq_limit_hz; // Minimum XY frequency setting
|
||||
static float xy_freq_min_speed_factor; // Minimum speed factor setting
|
||||
static int32_t xy_freq_min_interval_us; // Minimum segment time based on xy_freq_limit_hz
|
||||
static inline void refresh_frequency_limit() {
|
||||
//xy_freq_min_interval_us = xy_freq_limit_hz ?: LROUND(1000000.0f / xy_freq_limit_hz);
|
||||
if (xy_freq_limit_hz)
|
||||
xy_freq_min_interval_us = LROUND(1000000.0f / xy_freq_limit_hz);
|
||||
}
|
||||
static inline void set_min_speed_factor_u8(const uint8_t v255) {
|
||||
xy_freq_min_speed_factor = float(ui8_to_percent(v255)) / 100;
|
||||
}
|
||||
static inline void set_frequency_limit(const uint8_t hz) {
|
||||
xy_freq_limit_hz = constrain(hz, 0, 100);
|
||||
refresh_frequency_limit();
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
@@ -328,30 +456,19 @@ class Planner {
|
||||
/**
|
||||
* Limit where 64bit math is necessary for acceleration calculation
|
||||
*/
|
||||
static uint32_t cutoff_long;
|
||||
static uint32_t acceleration_long_cutoff;
|
||||
|
||||
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
|
||||
static float last_fade_z;
|
||||
#endif
|
||||
|
||||
#if ENABLED(DISABLE_INACTIVE_EXTRUDER)
|
||||
/**
|
||||
* Counters to manage disabling inactive extruders
|
||||
*/
|
||||
static uint8_t g_uc_extruder_last_move[EXTRUDERS];
|
||||
#endif // DISABLE_INACTIVE_EXTRUDER
|
||||
|
||||
#ifdef XY_FREQUENCY_LIMIT
|
||||
// Used for the frequency limit
|
||||
#define MAX_FREQ_TIME_US (uint32_t)(1000000.0 / XY_FREQUENCY_LIMIT)
|
||||
// Old direction bits. Used for speed calculations
|
||||
static unsigned char old_direction_bits;
|
||||
// Segment times (in µs). Used for speed calculations
|
||||
static xy_ulong_t axis_segment_time_us[3];
|
||||
// Counters to manage disabling inactive extruder steppers
|
||||
static last_move_t g_uc_extruder_last_move[E_STEPPERS];
|
||||
#endif
|
||||
|
||||
#if HAS_SPI_LCD
|
||||
volatile static uint32_t block_buffer_runtime_us; //Theoretical block buffer runtime in µs
|
||||
#if HAS_WIRED_LCD
|
||||
volatile static uint32_t block_buffer_runtime_us; // Theoretical block buffer runtime in µs
|
||||
#endif
|
||||
|
||||
public:
|
||||
@@ -368,28 +485,52 @@ class Planner {
|
||||
* Static (class) Methods
|
||||
*/
|
||||
|
||||
// Recalculate steps/s^2 accelerations based on mm/s^2 settings
|
||||
static void reset_acceleration_rates();
|
||||
|
||||
/**
|
||||
* Recalculate 'position' and 'mm_per_step'.
|
||||
* Must be called whenever settings.axis_steps_per_mm changes!
|
||||
*/
|
||||
static void refresh_positioning();
|
||||
static void set_max_acceleration(const uint8_t axis, float targetValue);
|
||||
static void set_max_feedrate(const uint8_t axis, float targetValue);
|
||||
static void set_max_jerk(const AxisEnum axis, float targetValue);
|
||||
|
||||
// For an axis set the Maximum Acceleration in mm/s^2
|
||||
static void set_max_acceleration(const uint8_t axis, float inMaxAccelMMS2);
|
||||
|
||||
#if EXTRUDERS
|
||||
// For an axis set the Maximum Feedrate in mm/s
|
||||
static void set_max_feedrate(const uint8_t axis, float inMaxFeedrateMMS);
|
||||
|
||||
// For an axis set the Maximum Jerk (instant change) in mm/s
|
||||
#if HAS_CLASSIC_JERK
|
||||
static void set_max_jerk(const AxisEnum axis, float inMaxJerkMMS);
|
||||
#else
|
||||
static inline void set_max_jerk(const AxisEnum, const_float_t) {}
|
||||
#endif
|
||||
|
||||
#if HAS_EXTRUDERS
|
||||
FORCE_INLINE static void refresh_e_factor(const uint8_t e) {
|
||||
e_factor[e] = (flow_percentage[e] * 0.01f
|
||||
#if DISABLED(NO_VOLUMETRICS)
|
||||
* volumetric_multiplier[e]
|
||||
#endif
|
||||
);
|
||||
e_factor[e] = flow_percentage[e] * 0.01f * TERN(NO_VOLUMETRICS, 1.0f, volumetric_multiplier[e]);
|
||||
}
|
||||
|
||||
static inline void set_flow(const uint8_t e, const int16_t flow) {
|
||||
flow_percentage[e] = flow;
|
||||
refresh_e_factor(e);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Manage fans, paste pressure, etc.
|
||||
static void check_axes_activity();
|
||||
|
||||
// Update multipliers based on new diameter measurements
|
||||
static void calculate_volumetric_multipliers();
|
||||
// Apply fan speeds
|
||||
#if HAS_FAN
|
||||
static void sync_fan_speeds(uint8_t (&fan_speed)[FAN_COUNT]);
|
||||
#if FAN_KICKSTART_TIME
|
||||
static void kickstart_fan(uint8_t (&fan_speed)[FAN_COUNT], const millis_t &ms, const uint8_t f);
|
||||
#else
|
||||
FORCE_INLINE static void kickstart_fan(uint8_t (&)[FAN_COUNT], const millis_t &, const uint8_t) {}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ENABLED(FILAMENT_WIDTH_SENSOR)
|
||||
void apply_filament_width_sensor(const int8_t encoded_ratio);
|
||||
@@ -402,10 +543,24 @@ class Planner {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENABLED(IMPROVE_HOMING_RELIABILITY)
|
||||
void enable_stall_prevention(const bool onoff);
|
||||
#endif
|
||||
|
||||
#if DISABLED(NO_VOLUMETRICS)
|
||||
|
||||
FORCE_INLINE static void set_filament_size(const uint8_t e, const float &v) {
|
||||
// Update multipliers based on new diameter measurements
|
||||
static void calculate_volumetric_multipliers();
|
||||
|
||||
#if ENABLED(VOLUMETRIC_EXTRUDER_LIMIT)
|
||||
// Update pre calculated extruder feedrate limits based on volumetric values
|
||||
static void calculate_volumetric_extruder_limit(const uint8_t e);
|
||||
static void calculate_volumetric_extruder_limits();
|
||||
#endif
|
||||
|
||||
FORCE_INLINE static void set_filament_size(const uint8_t e, const_float_t v) {
|
||||
filament_size[e] = v;
|
||||
if (v > 0) volumetric_area_nominal = CIRCLE_AREA(v * 0.5); //TODO: should it be per extruder
|
||||
// make sure all extruders have some sane value for the filament size
|
||||
LOOP_L_N(i, COUNT(filament_size))
|
||||
if (!filament_size[i]) filament_size[i] = DEFAULT_NOMINAL_FILAMENT_DIA;
|
||||
@@ -413,6 +568,13 @@ class Planner {
|
||||
|
||||
#endif
|
||||
|
||||
#if ENABLED(VOLUMETRIC_EXTRUDER_LIMIT)
|
||||
FORCE_INLINE static void set_volumetric_extruder_limit(const uint8_t e, const_float_t v) {
|
||||
volumetric_extruder_limit[e] = v;
|
||||
calculate_volumetric_extruder_limit(e);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
|
||||
|
||||
/**
|
||||
@@ -422,7 +584,7 @@ class Planner {
|
||||
* Returns 1.0 if planner.z_fade_height is 0.0.
|
||||
* Returns 0.0 if Z is past the specified 'Fade Height'.
|
||||
*/
|
||||
static inline float fade_scaling_factor_for_z(const float &rz) {
|
||||
static inline float fade_scaling_factor_for_z(const_float_t rz) {
|
||||
static float z_fade_factor = 1;
|
||||
if (!z_fade_height) return 1;
|
||||
if (rz >= z_fade_height) return 0;
|
||||
@@ -435,42 +597,42 @@ class Planner {
|
||||
|
||||
FORCE_INLINE static void force_fade_recalc() { last_fade_z = -999.999f; }
|
||||
|
||||
FORCE_INLINE static void set_z_fade_height(const float &zfh) {
|
||||
FORCE_INLINE static void set_z_fade_height(const_float_t zfh) {
|
||||
z_fade_height = zfh > 0 ? zfh : 0;
|
||||
inverse_z_fade_height = RECIPROCAL(z_fade_height);
|
||||
force_fade_recalc();
|
||||
}
|
||||
|
||||
FORCE_INLINE static bool leveling_active_at_z(const float &rz) {
|
||||
FORCE_INLINE static bool leveling_active_at_z(const_float_t rz) {
|
||||
return !z_fade_height || rz < z_fade_height;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
FORCE_INLINE static float fade_scaling_factor_for_z(const float&) { return 1; }
|
||||
FORCE_INLINE static float fade_scaling_factor_for_z(const_float_t) { return 1; }
|
||||
|
||||
FORCE_INLINE static bool leveling_active_at_z(const float&) { return true; }
|
||||
FORCE_INLINE static bool leveling_active_at_z(const_float_t) { return true; }
|
||||
|
||||
#endif
|
||||
|
||||
#if ENABLED(SKEW_CORRECTION)
|
||||
|
||||
FORCE_INLINE static void skew(float &cx, float &cy, const float &cz) {
|
||||
if (WITHIN(cx, X_MIN_POS + 1, X_MAX_POS) && WITHIN(cy, Y_MIN_POS + 1, Y_MAX_POS)) {
|
||||
FORCE_INLINE static void skew(float &cx, float &cy, const_float_t cz) {
|
||||
if (COORDINATE_OKAY(cx, X_MIN_POS + 1, X_MAX_POS) && COORDINATE_OKAY(cy, Y_MIN_POS + 1, Y_MAX_POS)) {
|
||||
const float sx = cx - cy * skew_factor.xy - cz * (skew_factor.xz - (skew_factor.xy * skew_factor.yz)),
|
||||
sy = cy - cz * skew_factor.yz;
|
||||
if (WITHIN(sx, X_MIN_POS, X_MAX_POS) && WITHIN(sy, Y_MIN_POS, Y_MAX_POS)) {
|
||||
if (COORDINATE_OKAY(sx, X_MIN_POS, X_MAX_POS) && COORDINATE_OKAY(sy, Y_MIN_POS, Y_MAX_POS)) {
|
||||
cx = sx; cy = sy;
|
||||
}
|
||||
}
|
||||
}
|
||||
FORCE_INLINE static void skew(xyz_pos_t &raw) { skew(raw.x, raw.y, raw.z); }
|
||||
|
||||
FORCE_INLINE static void unskew(float &cx, float &cy, const float &cz) {
|
||||
if (WITHIN(cx, X_MIN_POS, X_MAX_POS) && WITHIN(cy, Y_MIN_POS, Y_MAX_POS)) {
|
||||
FORCE_INLINE static void unskew(float &cx, float &cy, const_float_t cz) {
|
||||
if (COORDINATE_OKAY(cx, X_MIN_POS, X_MAX_POS) && COORDINATE_OKAY(cy, Y_MIN_POS, Y_MAX_POS)) {
|
||||
const float sx = cx + cy * skew_factor.xy + cz * skew_factor.xz,
|
||||
sy = cy + cz * skew_factor.yz;
|
||||
if (WITHIN(sx, X_MIN_POS, X_MAX_POS) && WITHIN(sy, Y_MIN_POS, Y_MAX_POS)) {
|
||||
if (COORDINATE_OKAY(sx, X_MIN_POS, X_MAX_POS) && COORDINATE_OKAY(sy, Y_MIN_POS, Y_MAX_POS)) {
|
||||
cx = sx; cy = sy;
|
||||
}
|
||||
}
|
||||
@@ -491,6 +653,9 @@ class Planner {
|
||||
unapply_leveling(raw);
|
||||
leveling_active = false;
|
||||
}
|
||||
#else
|
||||
FORCE_INLINE static void apply_leveling(xyz_pos_t&) {}
|
||||
FORCE_INLINE static void unapply_leveling(xyz_pos_t&) {}
|
||||
#endif
|
||||
|
||||
#if ENABLED(FWRETRACT)
|
||||
@@ -501,46 +666,16 @@ class Planner {
|
||||
#endif
|
||||
|
||||
#if HAS_POSITION_MODIFIERS
|
||||
FORCE_INLINE static void apply_modifiers(xyze_pos_t &pos
|
||||
#if HAS_LEVELING
|
||||
, bool leveling =
|
||||
#if PLANNER_LEVELING
|
||||
true
|
||||
#else
|
||||
false
|
||||
#endif
|
||||
#endif
|
||||
) {
|
||||
#if ENABLED(SKEW_CORRECTION)
|
||||
skew(pos);
|
||||
#endif
|
||||
#if HAS_LEVELING
|
||||
if (leveling) apply_leveling(pos);
|
||||
#endif
|
||||
#if ENABLED(FWRETRACT)
|
||||
apply_retract(pos);
|
||||
#endif
|
||||
FORCE_INLINE static void apply_modifiers(xyze_pos_t &pos, bool leveling=ENABLED(PLANNER_LEVELING)) {
|
||||
TERN_(SKEW_CORRECTION, skew(pos));
|
||||
if (leveling) apply_leveling(pos);
|
||||
TERN_(FWRETRACT, apply_retract(pos));
|
||||
}
|
||||
|
||||
FORCE_INLINE static void unapply_modifiers(xyze_pos_t &pos
|
||||
#if HAS_LEVELING
|
||||
, bool leveling =
|
||||
#if PLANNER_LEVELING
|
||||
true
|
||||
#else
|
||||
false
|
||||
#endif
|
||||
#endif
|
||||
) {
|
||||
#if ENABLED(FWRETRACT)
|
||||
unapply_retract(pos);
|
||||
#endif
|
||||
#if HAS_LEVELING
|
||||
if (leveling) unapply_leveling(pos);
|
||||
#endif
|
||||
#if ENABLED(SKEW_CORRECTION)
|
||||
unskew(pos);
|
||||
#endif
|
||||
FORCE_INLINE static void unapply_modifiers(xyze_pos_t &pos, bool leveling=ENABLED(PLANNER_LEVELING)) {
|
||||
TERN_(FWRETRACT, unapply_retract(pos));
|
||||
if (leveling) unapply_leveling(pos);
|
||||
TERN_(SKEW_CORRECTION, unskew(pos));
|
||||
}
|
||||
#endif // HAS_POSITION_MODIFIERS
|
||||
|
||||
@@ -589,13 +724,9 @@ class Planner {
|
||||
* Returns true if movement was buffered, false otherwise
|
||||
*/
|
||||
static bool _buffer_steps(const xyze_long_t &target
|
||||
#if HAS_POSITION_FLOAT
|
||||
, const xyze_pos_t &target_float
|
||||
#endif
|
||||
#if HAS_DIST_MM_ARG
|
||||
, const xyze_float_t &cart_dist_mm
|
||||
#endif
|
||||
, feedRate_t fr_mm_s, const uint8_t extruder, const float &millimeters=0.0
|
||||
OPTARG(HAS_POSITION_FLOAT, const xyze_pos_t &target_float)
|
||||
OPTARG(HAS_DIST_MM_ARG, const xyze_float_t &cart_dist_mm)
|
||||
, feedRate_t fr_mm_s, const uint8_t extruder, const_float_t millimeters=0.0
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -610,28 +741,26 @@ class Planner {
|
||||
*
|
||||
* Returns true is movement is acceptable, false otherwise
|
||||
*/
|
||||
static bool _populate_block(block_t * const block, bool split_move,
|
||||
const xyze_long_t &target
|
||||
#if HAS_POSITION_FLOAT
|
||||
, const xyze_pos_t &target_float
|
||||
#endif
|
||||
#if HAS_DIST_MM_ARG
|
||||
, const xyze_float_t &cart_dist_mm
|
||||
#endif
|
||||
, feedRate_t fr_mm_s, const uint8_t extruder, const float &millimeters=0.0
|
||||
static bool _populate_block(block_t * const block, bool split_move, const xyze_long_t &target
|
||||
OPTARG(HAS_POSITION_FLOAT, const xyze_pos_t &target_float)
|
||||
OPTARG(HAS_DIST_MM_ARG, const xyze_float_t &cart_dist_mm)
|
||||
, feedRate_t fr_mm_s, const uint8_t extruder, const_float_t millimeters=0.0
|
||||
);
|
||||
|
||||
/**
|
||||
* Planner::buffer_sync_block
|
||||
* Add a block to the buffer that just updates the position
|
||||
* Add a block to the buffer that just updates the position or in
|
||||
* case of LASER_SYNCHRONOUS_M106_M107 the fan pwm
|
||||
*/
|
||||
static void buffer_sync_block();
|
||||
static void buffer_sync_block(
|
||||
TERN_(LASER_SYNCHRONOUS_M106_M107, uint8_t sync_flag=BLOCK_FLAG_SYNC_POSITION)
|
||||
);
|
||||
|
||||
#if IS_KINEMATIC
|
||||
private:
|
||||
|
||||
// Allow do_homing_move to access internal functions, such as buffer_segment.
|
||||
friend void do_homing_move(const AxisEnum, const float, const feedRate_t);
|
||||
friend void do_homing_move(const AxisEnum, const float, const feedRate_t, const bool);
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -646,26 +775,11 @@ class Planner {
|
||||
* extruder - target extruder
|
||||
* millimeters - the length of the movement, if known
|
||||
*/
|
||||
static bool buffer_segment(const float &a, const float &b, const float &c, const float &e
|
||||
#if HAS_DIST_MM_ARG
|
||||
, const xyze_float_t &cart_dist_mm
|
||||
#endif
|
||||
, const feedRate_t &fr_mm_s, const uint8_t extruder, const float &millimeters=0.0
|
||||
static bool buffer_segment(const abce_pos_t &abce
|
||||
OPTARG(HAS_DIST_MM_ARG, const xyze_float_t &cart_dist_mm)
|
||||
, const_feedRate_t fr_mm_s, const uint8_t extruder=active_extruder, const_float_t millimeters=0.0
|
||||
);
|
||||
|
||||
FORCE_INLINE static bool buffer_segment(abce_pos_t &abce
|
||||
#if HAS_DIST_MM_ARG
|
||||
, const xyze_float_t &cart_dist_mm
|
||||
#endif
|
||||
, const feedRate_t &fr_mm_s, const uint8_t extruder, const float &millimeters=0.0
|
||||
) {
|
||||
return buffer_segment(abce.a, abce.b, abce.c, abce.e
|
||||
#if HAS_DIST_MM_ARG
|
||||
, cart_dist_mm
|
||||
#endif
|
||||
, fr_mm_s, extruder, millimeters);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
@@ -673,29 +787,19 @@ class Planner {
|
||||
* The target is cartesian. It's translated to
|
||||
* delta/scara if needed.
|
||||
*
|
||||
* rx,ry,rz,e - target position in mm or degrees
|
||||
* cart - target position in mm or degrees
|
||||
* fr_mm_s - (target) speed of the move (mm/s)
|
||||
* extruder - target extruder
|
||||
* millimeters - the length of the movement, if known
|
||||
* inv_duration - the reciprocal if the duration of the movement, if known (kinematic only if feeedrate scaling is enabled)
|
||||
*/
|
||||
static bool buffer_line(const float &rx, const float &ry, const float &rz, const float &e, const feedRate_t &fr_mm_s, const uint8_t extruder, const float millimeters=0.0
|
||||
#if ENABLED(SCARA_FEEDRATE_SCALING)
|
||||
, const float &inv_duration=0.0
|
||||
#endif
|
||||
static bool buffer_line(const xyze_pos_t &cart, const_feedRate_t fr_mm_s, const uint8_t extruder=active_extruder, const float millimeters=0.0
|
||||
OPTARG(SCARA_FEEDRATE_SCALING, const_float_t inv_duration=0.0)
|
||||
);
|
||||
|
||||
FORCE_INLINE static bool buffer_line(const xyze_pos_t &cart, const feedRate_t &fr_mm_s, const uint8_t extruder, const float millimeters=0.0
|
||||
#if ENABLED(SCARA_FEEDRATE_SCALING)
|
||||
, const float &inv_duration=0.0
|
||||
#endif
|
||||
) {
|
||||
return buffer_line(cart.x, cart.y, cart.z, cart.e, fr_mm_s, extruder, millimeters
|
||||
#if ENABLED(SCARA_FEEDRATE_SCALING)
|
||||
, inv_duration
|
||||
#endif
|
||||
);
|
||||
}
|
||||
#if ENABLED(DIRECT_STEPPING)
|
||||
static void buffer_page(const page_idx_t page_idx, const uint8_t extruder, const uint16_t num_steps);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Set the planner.position and individual stepper positions.
|
||||
@@ -710,9 +814,11 @@ class Planner {
|
||||
*
|
||||
* Clears previous speed values.
|
||||
*/
|
||||
static void set_position_mm(const float &rx, const float &ry, const float &rz, const float &e);
|
||||
FORCE_INLINE static void set_position_mm(const xyze_pos_t &cart) { set_position_mm(cart.x, cart.y, cart.z, cart.e); }
|
||||
static void set_e_position_mm(const float &e);
|
||||
static void set_position_mm(const xyze_pos_t &xyze);
|
||||
|
||||
#if HAS_EXTRUDERS
|
||||
static void set_e_position_mm(const_float_t e);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Set the planner.position and individual stepper positions.
|
||||
@@ -720,8 +826,7 @@ class Planner {
|
||||
* The supplied position is in machine space, and no additional
|
||||
* conversions are applied.
|
||||
*/
|
||||
static void set_machine_position_mm(const float &a, const float &b, const float &c, const float &e);
|
||||
FORCE_INLINE static void set_machine_position_mm(const abce_pos_t &abce) { set_machine_position_mm(abce.a, abce.b, abce.c, abce.e); }
|
||||
static void set_machine_position_mm(const abce_pos_t &abce);
|
||||
|
||||
/**
|
||||
* Get an axis position according to stepper position(s)
|
||||
@@ -730,12 +835,11 @@ class Planner {
|
||||
static float get_axis_position_mm(const AxisEnum axis);
|
||||
|
||||
static inline abce_pos_t get_axis_positions_mm() {
|
||||
const abce_pos_t out = {
|
||||
get_axis_position_mm(A_AXIS),
|
||||
get_axis_position_mm(B_AXIS),
|
||||
get_axis_position_mm(C_AXIS),
|
||||
get_axis_position_mm(E_AXIS)
|
||||
};
|
||||
const abce_pos_t out = LOGICAL_AXIS_ARRAY(
|
||||
get_axis_position_mm(E_AXIS),
|
||||
get_axis_position_mm(A_AXIS), get_axis_position_mm(B_AXIS), get_axis_position_mm(C_AXIS),
|
||||
get_axis_position_mm(I_AXIS), get_axis_position_mm(J_AXIS), get_axis_position_mm(K_AXIS)
|
||||
);
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -748,7 +852,14 @@ class Planner {
|
||||
// a Full Shutdown is required, or when endstops are hit)
|
||||
static void quick_stop();
|
||||
|
||||
// Called when an endstop is triggered. Causes the machine to stop inmediately
|
||||
#if ENABLED(REALTIME_REPORTING_COMMANDS)
|
||||
// Force a quick pause of the machine (e.g., when a pause is required in the middle of move).
|
||||
// NOTE: Hard-stops will lose steps so encoders are highly recommended if using these!
|
||||
static void quick_pause();
|
||||
static void quick_resume();
|
||||
#endif
|
||||
|
||||
// Called when an endstop is triggered. Causes the machine to stop immediately
|
||||
static void endstop_triggered(const AxisEnum axis);
|
||||
|
||||
// Triggered position of an axis in mm (not core-savvy)
|
||||
@@ -760,16 +871,9 @@ class Planner {
|
||||
// Wait for moves to finish and disable all steppers
|
||||
static void finish_and_disable();
|
||||
|
||||
// Periodic tick to handle cleaning timeouts
|
||||
// Periodic handler to manage the cleaning buffer counter
|
||||
// Called from the Temperature ISR at ~1kHz
|
||||
static void tick() {
|
||||
if (cleaning_buffer_counter) {
|
||||
--cleaning_buffer_counter;
|
||||
#if ENABLED(SD_FINISHED_STEPPERRELEASE) && defined(SD_FINISHED_RELEASECOMMAND)
|
||||
if (!cleaning_buffer_counter) queue.inject_P(PSTR(SD_FINISHED_RELEASECOMMAND));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
static void isr() { if (cleaning_buffer_counter) --cleaning_buffer_counter; }
|
||||
|
||||
/**
|
||||
* Does the buffer have any blocks queued?
|
||||
@@ -787,40 +891,46 @@ class Planner {
|
||||
static block_t* get_current_block();
|
||||
|
||||
/**
|
||||
* "Discard" the block and "release" the memory.
|
||||
* "Release" the current block so its slot can be reused.
|
||||
* Called when the current block is no longer needed.
|
||||
*/
|
||||
FORCE_INLINE static void discard_current_block() {
|
||||
FORCE_INLINE static void release_current_block() {
|
||||
if (has_blocks_queued())
|
||||
block_buffer_tail = next_block_index(block_buffer_tail);
|
||||
}
|
||||
|
||||
#if HAS_SPI_LCD
|
||||
#if HAS_WIRED_LCD
|
||||
static uint16_t block_buffer_runtime();
|
||||
static void clear_block_buffer_runtime();
|
||||
#endif
|
||||
|
||||
#if ENABLED(AUTOTEMP)
|
||||
static float autotemp_min, autotemp_max, autotemp_factor;
|
||||
static celsius_t autotemp_min, autotemp_max;
|
||||
static float autotemp_factor;
|
||||
static bool autotemp_enabled;
|
||||
static void getHighESpeed();
|
||||
static void autotemp_update();
|
||||
static void autotemp_M104_M109();
|
||||
static void autotemp_task();
|
||||
#endif
|
||||
|
||||
#if HAS_LINEAR_E_JERK
|
||||
FORCE_INLINE static void recalculate_max_e_jerk() {
|
||||
#define GET_MAX_E_JERK(N) SQRT(SQRT(0.5) * junction_deviation_mm * (N) * RECIPROCAL(1.0 - SQRT(0.5)))
|
||||
#if ENABLED(DISTINCT_E_FACTORS)
|
||||
LOOP_L_N(i, EXTRUDERS)
|
||||
max_e_jerk[i] = GET_MAX_E_JERK(settings.max_acceleration_mm_per_s2[E_AXIS_N(i)]);
|
||||
#else
|
||||
max_e_jerk = GET_MAX_E_JERK(settings.max_acceleration_mm_per_s2[E_AXIS]);
|
||||
#endif
|
||||
const float prop = junction_deviation_mm * SQRT(0.5) / (1.0f - SQRT(0.5));
|
||||
LOOP_L_N(i, EXTRUDERS)
|
||||
max_e_jerk[E_INDEX_N(i)] = SQRT(prop * settings.max_acceleration_mm_per_s2[E_INDEX_N(i)]);
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
#if ENABLED(AUTOTEMP)
|
||||
#if ENABLED(AUTOTEMP_PROPORTIONAL)
|
||||
static void _autotemp_update_from_hotend();
|
||||
#else
|
||||
static inline void _autotemp_update_from_hotend() {}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Get the index of the next / previous block in the ring buffer
|
||||
*/
|
||||
@@ -831,7 +941,7 @@ class Planner {
|
||||
* Calculate the distance (not time) it takes to accelerate
|
||||
* from initial_rate to target_rate using the given acceleration:
|
||||
*/
|
||||
static float estimate_acceleration_distance(const float &initial_rate, const float &target_rate, const float &accel) {
|
||||
static float estimate_acceleration_distance(const_float_t initial_rate, const_float_t target_rate, const_float_t accel) {
|
||||
if (accel == 0) return 0; // accel was 0, set acceleration distance to 0
|
||||
return (sq(target_rate) - sq(initial_rate)) / (accel * 2);
|
||||
}
|
||||
@@ -844,7 +954,7 @@ class Planner {
|
||||
* This is used to compute the intersection point between acceleration and deceleration
|
||||
* in cases where the "trapezoid" has no plateau (i.e., never reaches maximum speed)
|
||||
*/
|
||||
static float intersection_distance(const float &initial_rate, const float &final_rate, const float &accel, const float &distance) {
|
||||
static float intersection_distance(const_float_t initial_rate, const_float_t final_rate, const_float_t accel, const_float_t distance) {
|
||||
if (accel == 0) return 0; // accel was 0, set intersection distance to 0
|
||||
return (accel * 2 * distance - sq(initial_rate) + sq(final_rate)) / (accel * 4);
|
||||
}
|
||||
@@ -854,7 +964,7 @@ class Planner {
|
||||
* to reach 'target_velocity_sqr' using 'acceleration' within a given
|
||||
* 'distance'.
|
||||
*/
|
||||
static float max_allowable_speed_sqr(const float &accel, const float &target_velocity_sqr, const float &distance) {
|
||||
static float max_allowable_speed_sqr(const_float_t accel, const_float_t target_velocity_sqr, const_float_t distance) {
|
||||
return target_velocity_sqr - 2 * accel * distance;
|
||||
}
|
||||
|
||||
@@ -862,15 +972,15 @@ class Planner {
|
||||
/**
|
||||
* Calculate the speed reached given initial speed, acceleration and distance
|
||||
*/
|
||||
static float final_speed(const float &initial_velocity, const float &accel, const float &distance) {
|
||||
static float final_speed(const_float_t initial_velocity, const_float_t accel, const_float_t distance) {
|
||||
return SQRT(sq(initial_velocity) + 2 * accel * distance);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void calculate_trapezoid_for_block(block_t* const block, const float &entry_factor, const float &exit_factor);
|
||||
static void calculate_trapezoid_for_block(block_t * const block, const_float_t entry_factor, const_float_t exit_factor);
|
||||
|
||||
static void reverse_pass_kernel(block_t* const current, const block_t * const next);
|
||||
static void forward_pass_kernel(const block_t * const previous, block_t* const current, uint8_t block_index);
|
||||
static void reverse_pass_kernel(block_t * const current, const block_t * const next);
|
||||
static void forward_pass_kernel(const block_t * const previous, block_t * const current, uint8_t block_index);
|
||||
|
||||
static void reverse_pass();
|
||||
static void forward_pass();
|
||||
@@ -879,24 +989,28 @@ class Planner {
|
||||
|
||||
static void recalculate();
|
||||
|
||||
#if DISABLED(CLASSIC_JERK)
|
||||
#if HAS_JUNCTION_DEVIATION
|
||||
|
||||
FORCE_INLINE static void normalize_junction_vector(xyze_float_t &vector) {
|
||||
float magnitude_sq = 0;
|
||||
LOOP_XYZE(idx) if (vector[idx]) magnitude_sq += sq(vector[idx]);
|
||||
LOOP_LOGICAL_AXES(idx) if (vector[idx]) magnitude_sq += sq(vector[idx]);
|
||||
vector *= RSQRT(magnitude_sq);
|
||||
}
|
||||
|
||||
FORCE_INLINE static float limit_value_by_axis_maximum(const float &max_value, xyze_float_t &unit_vec) {
|
||||
FORCE_INLINE static float limit_value_by_axis_maximum(const_float_t max_value, xyze_float_t &unit_vec) {
|
||||
float limit_value = max_value;
|
||||
LOOP_XYZE(idx) if (unit_vec[idx]) // Avoid divide by zero
|
||||
NOMORE(limit_value, ABS(settings.max_acceleration_mm_per_s2[idx] / unit_vec[idx]));
|
||||
LOOP_LOGICAL_AXES(idx) {
|
||||
if (unit_vec[idx]) {
|
||||
if (limit_value * ABS(unit_vec[idx]) > settings.max_acceleration_mm_per_s2[idx])
|
||||
limit_value = ABS(settings.max_acceleration_mm_per_s2[idx] / unit_vec[idx]);
|
||||
}
|
||||
}
|
||||
return limit_value;
|
||||
}
|
||||
|
||||
#endif // !CLASSIC_JERK
|
||||
};
|
||||
|
||||
#define PLANNER_XY_FEEDRATE() (_MIN(planner.settings.max_feedrate_mm_s[X_AXIS], planner.settings.max_feedrate_mm_s[Y_AXIS]))
|
||||
#define PLANNER_XY_FEEDRATE() _MIN(planner.settings.max_feedrate_mm_s[X_AXIS], planner.settings.max_feedrate_mm_s[Y_AXIS])
|
||||
|
||||
extern Planner planner;
|
||||
|
26
Marlin/src/module/planner_bezier.cpp
Executable file → Normal file
26
Marlin/src/module/planner_bezier.cpp
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
* planner_bezier.cpp
|
||||
*
|
||||
* Compute and buffer movement commands for bezier curves
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../inc/MarlinConfig.h"
|
||||
@@ -36,7 +35,6 @@
|
||||
#include "temperature.h"
|
||||
|
||||
#include "../MarlinCore.h"
|
||||
#include "../core/language.h"
|
||||
#include "../gcode/queue.h"
|
||||
|
||||
// See the meaning in the documentation of cubic_b_spline().
|
||||
@@ -45,7 +43,7 @@
|
||||
#define SIGMA 0.1f
|
||||
|
||||
// Compute the linear interpolation between two real numbers.
|
||||
static inline float interp(const float &a, const float &b, const float &t) { return (1 - t) * a + t * b; }
|
||||
static inline float interp(const_float_t a, const_float_t b, const_float_t t) { return (1 - t) * a + t * b; }
|
||||
|
||||
/**
|
||||
* Compute a Bézier curve using the De Casteljau's algorithm (see
|
||||
@@ -53,7 +51,7 @@ static inline float interp(const float &a, const float &b, const float &t) { ret
|
||||
* easy to code and has good numerical stability (very important,
|
||||
* since Arudino works with limited precision real numbers).
|
||||
*/
|
||||
static inline float eval_bezier(const float &a, const float &b, const float &c, const float &d, const float &t) {
|
||||
static inline float eval_bezier(const_float_t a, const_float_t b, const_float_t c, const_float_t d, const_float_t t) {
|
||||
const float iab = interp(a, b, t),
|
||||
ibc = interp(b, c, t),
|
||||
icd = interp(c, d, t),
|
||||
@@ -66,7 +64,7 @@ static inline float eval_bezier(const float &a, const float &b, const float &c,
|
||||
* We approximate Euclidean distance with the sum of the coordinates
|
||||
* offset (so-called "norm 1"), which is quicker to compute.
|
||||
*/
|
||||
static inline float dist1(const float &x1, const float &y1, const float &x2, const float &y2) { return ABS(x1 - x2) + ABS(y1 - y2); }
|
||||
static inline float dist1(const_float_t x1, const_float_t y1, const_float_t x2, const_float_t y2) { return ABS(x1 - x2) + ABS(y1 - y2); }
|
||||
|
||||
/**
|
||||
* The algorithm for computing the step is loosely based on the one in Kig
|
||||
@@ -111,7 +109,7 @@ void cubic_b_spline(
|
||||
const xyze_pos_t &position, // current position
|
||||
const xyze_pos_t &target, // target position
|
||||
const xy_pos_t (&offsets)[2], // a pair of offsets
|
||||
const feedRate_t &scaled_fr_mm_s, // mm/s scaled by feedrate %
|
||||
const_feedRate_t scaled_fr_mm_s, // mm/s scaled by feedrate %
|
||||
const uint8_t extruder
|
||||
) {
|
||||
// Absolute first and second control points are recovered.
|
||||
@@ -183,11 +181,15 @@ void cubic_b_spline(
|
||||
t = new_t;
|
||||
|
||||
// Compute and send new position
|
||||
xyze_pos_t new_bez = {
|
||||
new_pos0, new_pos1,
|
||||
interp(position.z, target.z, t), // FIXME. These two are wrong, since the parameter t is
|
||||
interp(position.e, target.e, t) // not linear in the distance.
|
||||
};
|
||||
xyze_pos_t new_bez = LOGICAL_AXIS_ARRAY(
|
||||
interp(position.e, target.e, t), // FIXME. Wrong, since t is not linear in the distance.
|
||||
new_pos0,
|
||||
new_pos1,
|
||||
interp(position.z, target.z, t), // FIXME. Wrong, since t is not linear in the distance.
|
||||
interp(position.i, target.i, t), // FIXME. Wrong, since t is not linear in the distance.
|
||||
interp(position.j, target.j, t), // FIXME. Wrong, since t is not linear in the distance.
|
||||
interp(position.k, target.k, t) // FIXME. Wrong, since t is not linear in the distance.
|
||||
);
|
||||
apply_motion_limits(new_bez);
|
||||
bez_target = new_bez;
|
||||
|
||||
|
5
Marlin/src/module/planner_bezier.h
Executable file → Normal file
5
Marlin/src/module/planner_bezier.h
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@@ -25,7 +25,6 @@
|
||||
* planner_bezier.h
|
||||
*
|
||||
* Compute and buffer movement commands for Bézier curves
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../core/types.h"
|
||||
@@ -34,6 +33,6 @@ void cubic_b_spline(
|
||||
const xyze_pos_t &position, // current position
|
||||
const xyze_pos_t &target, // target position
|
||||
const xy_pos_t (&offsets)[2], // a pair of offsets
|
||||
const feedRate_t &scaled_fr_mm_s, // mm/s scaled by feedrate %
|
||||
const_feedRate_t scaled_fr_mm_s, // mm/s scaled by feedrate %
|
||||
const uint8_t extruder
|
||||
);
|
||||
|
47
Marlin/src/module/polargraph.cpp
Normal file
47
Marlin/src/module/polargraph.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2020 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 <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* polargraph.cpp
|
||||
*/
|
||||
|
||||
#include "../inc/MarlinConfig.h"
|
||||
|
||||
#if ENABLED(POLARGRAPH)
|
||||
|
||||
#include "polargraph.h"
|
||||
#include "motion.h"
|
||||
|
||||
// For homing:
|
||||
#include "planner.h"
|
||||
#include "endstops.h"
|
||||
#include "../lcd/marlinui.h"
|
||||
#include "../MarlinCore.h"
|
||||
|
||||
float segments_per_second; // Initialized by settings.load()
|
||||
|
||||
void inverse_kinematics(const xyz_pos_t &raw) {
|
||||
const float x1 = raw.x - (X_MIN_POS), x2 = (X_MAX_POS) - raw.x, y = raw.y - (Y_MAX_POS);
|
||||
delta.set(HYPOT(x1, y), HYPOT(x2, y), raw.z);
|
||||
}
|
||||
|
||||
#endif // POLARGRAPH
|
33
Marlin/src/module/polargraph.h
Normal file
33
Marlin/src/module/polargraph.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2020 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 <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* polargraph.h - Polargraph-specific functions
|
||||
*/
|
||||
|
||||
#include "../core/types.h"
|
||||
#include "../core/macros.h"
|
||||
|
||||
extern float segments_per_second;
|
||||
|
||||
void inverse_kinematics(const xyz_pos_t &raw);
|
113
Marlin/src/module/printcounter.cpp
Executable file → Normal file
113
Marlin/src/module/printcounter.cpp
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -41,6 +41,11 @@ Stopwatch print_job_timer; // Global Print Job Timer instance
|
||||
#include "../libs/buzzer.h"
|
||||
#endif
|
||||
|
||||
#if PRINTCOUNTER_SYNC
|
||||
#include "../module/planner.h"
|
||||
#warning "To prevent step loss, motion will pause for PRINTCOUNTER auto-save."
|
||||
#endif
|
||||
|
||||
// Service intervals
|
||||
#if HAS_SERVICE_INTERVALS
|
||||
#if SERVICE_INTERVAL_1 > 0
|
||||
@@ -70,19 +75,14 @@ millis_t PrintCounter::lastDuration;
|
||||
bool PrintCounter::loaded = false;
|
||||
|
||||
millis_t PrintCounter::deltaDuration() {
|
||||
#if ENABLED(DEBUG_PRINTCOUNTER)
|
||||
debug(PSTR("deltaDuration"));
|
||||
#endif
|
||||
|
||||
TERN_(DEBUG_PRINTCOUNTER, debug(PSTR("deltaDuration")));
|
||||
millis_t tmp = lastDuration;
|
||||
lastDuration = duration();
|
||||
return lastDuration - tmp;
|
||||
}
|
||||
|
||||
void PrintCounter::incFilamentUsed(float const &amount) {
|
||||
#if ENABLED(DEBUG_PRINTCOUNTER)
|
||||
debug(PSTR("incFilamentUsed"));
|
||||
#endif
|
||||
TERN_(DEBUG_PRINTCOUNTER, debug(PSTR("incFilamentUsed")));
|
||||
|
||||
// Refuses to update data if object is not loaded
|
||||
if (!isLoaded()) return;
|
||||
@@ -91,9 +91,7 @@ void PrintCounter::incFilamentUsed(float const &amount) {
|
||||
}
|
||||
|
||||
void PrintCounter::initStats() {
|
||||
#if ENABLED(DEBUG_PRINTCOUNTER)
|
||||
debug(PSTR("initStats"));
|
||||
#endif
|
||||
TERN_(DEBUG_PRINTCOUNTER, debug(PSTR("initStats")));
|
||||
|
||||
loaded = true;
|
||||
data = { 0, 0, 0, 0, 0.0
|
||||
@@ -121,7 +119,7 @@ void PrintCounter::initStats() {
|
||||
inline bool _service_warn(const char * const msg) {
|
||||
_print_divider();
|
||||
SERIAL_ECHO_START();
|
||||
serialprintPGM(msg);
|
||||
SERIAL_ECHOPGM_P(msg);
|
||||
SERIAL_ECHOLNPGM("!");
|
||||
_print_divider();
|
||||
return true;
|
||||
@@ -129,9 +127,7 @@ void PrintCounter::initStats() {
|
||||
#endif
|
||||
|
||||
void PrintCounter::loadStats() {
|
||||
#if ENABLED(DEBUG_PRINTCOUNTER)
|
||||
debug(PSTR("loadStats"));
|
||||
#endif
|
||||
TERN_(DEBUG_PRINTCOUNTER, debug(PSTR("loadStats")));
|
||||
|
||||
// Check if the EEPROM block is initialized
|
||||
uint8_t value = 0;
|
||||
@@ -164,36 +160,34 @@ void PrintCounter::loadStats() {
|
||||
}
|
||||
|
||||
void PrintCounter::saveStats() {
|
||||
#if ENABLED(DEBUG_PRINTCOUNTER)
|
||||
debug(PSTR("saveStats"));
|
||||
#endif
|
||||
TERN_(DEBUG_PRINTCOUNTER, debug(PSTR("saveStats")));
|
||||
|
||||
// Refuses to save data if object is not loaded
|
||||
if (!isLoaded()) return;
|
||||
|
||||
TERN_(PRINTCOUNTER_SYNC, planner.synchronize());
|
||||
|
||||
// Saves the struct to EEPROM
|
||||
persistentStore.access_start();
|
||||
persistentStore.write_data(address + sizeof(uint8_t), (uint8_t*)&data, sizeof(printStatistics));
|
||||
persistentStore.access_finish();
|
||||
|
||||
#if ENABLED(EXTENSIBLE_UI)
|
||||
ExtUI::onConfigurationStoreWritten(true);
|
||||
#endif
|
||||
TERN_(EXTENSIBLE_UI, ExtUI::onConfigurationStoreWritten(true));
|
||||
}
|
||||
|
||||
#if HAS_SERVICE_INTERVALS
|
||||
inline void _service_when(char buffer[], const char * const msg, const uint32_t when) {
|
||||
SERIAL_ECHOPGM(STR_STATS);
|
||||
serialprintPGM(msg);
|
||||
SERIAL_ECHOLNPAIR(" in ", duration_t(when).toString(buffer));
|
||||
SERIAL_ECHOPGM_P(msg);
|
||||
SERIAL_ECHOLNPGM(" in ", duration_t(when).toString(buffer));
|
||||
}
|
||||
#endif
|
||||
|
||||
void PrintCounter::showStats() {
|
||||
char buffer[21];
|
||||
char buffer[22];
|
||||
|
||||
SERIAL_ECHOPGM(STR_STATS);
|
||||
SERIAL_ECHOLNPAIR(
|
||||
SERIAL_ECHOLNPGM(
|
||||
"Prints: ", data.totalPrints,
|
||||
", Finished: ", data.finishedPrints,
|
||||
", Failed: ", data.totalPrints - data.finishedPrints
|
||||
@@ -203,21 +197,21 @@ void PrintCounter::showStats() {
|
||||
SERIAL_ECHOPGM(STR_STATS);
|
||||
duration_t elapsed = data.printTime;
|
||||
elapsed.toString(buffer);
|
||||
SERIAL_ECHOPAIR("Total time: ", buffer);
|
||||
SERIAL_ECHOPGM("Total time: ", buffer);
|
||||
#if ENABLED(DEBUG_PRINTCOUNTER)
|
||||
SERIAL_ECHOPAIR(" (", data.printTime);
|
||||
SERIAL_ECHOPGM(" (", data.printTime);
|
||||
SERIAL_CHAR(')');
|
||||
#endif
|
||||
|
||||
elapsed = data.longestPrint;
|
||||
elapsed.toString(buffer);
|
||||
SERIAL_ECHOPAIR(", Longest job: ", buffer);
|
||||
SERIAL_ECHOPGM(", Longest job: ", buffer);
|
||||
#if ENABLED(DEBUG_PRINTCOUNTER)
|
||||
SERIAL_ECHOPAIR(" (", data.longestPrint);
|
||||
SERIAL_ECHOPGM(" (", data.longestPrint);
|
||||
SERIAL_CHAR(')');
|
||||
#endif
|
||||
|
||||
SERIAL_ECHOPAIR("\n" STR_STATS "Filament used: ", data.filamentUsed / 1000);
|
||||
SERIAL_ECHOPGM("\n" STR_STATS "Filament used: ", data.filamentUsed / 1000);
|
||||
SERIAL_CHAR('m');
|
||||
SERIAL_EOL();
|
||||
|
||||
@@ -237,11 +231,12 @@ void PrintCounter::tick() {
|
||||
|
||||
millis_t now = millis();
|
||||
|
||||
static uint32_t update_next; // = 0
|
||||
static millis_t update_next; // = 0
|
||||
if (ELAPSED(now, update_next)) {
|
||||
#if ENABLED(DEBUG_PRINTCOUNTER)
|
||||
debug(PSTR("tick"));
|
||||
#endif
|
||||
update_next = now + updateInterval;
|
||||
|
||||
TERN_(DEBUG_PRINTCOUNTER, debug(PSTR("tick")));
|
||||
|
||||
millis_t delta = deltaDuration();
|
||||
data.printTime += delta;
|
||||
|
||||
@@ -254,22 +249,20 @@ void PrintCounter::tick() {
|
||||
#if SERVICE_INTERVAL_3 > 0
|
||||
data.nextService3 -= _MIN(delta, data.nextService3);
|
||||
#endif
|
||||
|
||||
update_next = now + updateInterval * 1000;
|
||||
}
|
||||
|
||||
static uint32_t eeprom_next; // = 0
|
||||
if (ELAPSED(now, eeprom_next)) {
|
||||
eeprom_next = now + saveInterval * 1000;
|
||||
saveStats();
|
||||
}
|
||||
#if PRINTCOUNTER_SAVE_INTERVAL > 0
|
||||
static millis_t eeprom_next; // = 0
|
||||
if (ELAPSED(now, eeprom_next)) {
|
||||
eeprom_next = now + saveInterval;
|
||||
saveStats();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// @Override
|
||||
bool PrintCounter::start() {
|
||||
#if ENABLED(DEBUG_PRINTCOUNTER)
|
||||
debug(PSTR("start"));
|
||||
#endif
|
||||
TERN_(DEBUG_PRINTCOUNTER, debug(PSTR("start")));
|
||||
|
||||
bool paused = isPaused();
|
||||
|
||||
@@ -284,30 +277,25 @@ bool PrintCounter::start() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// @Override
|
||||
bool PrintCounter::stop() {
|
||||
#if ENABLED(DEBUG_PRINTCOUNTER)
|
||||
debug(PSTR("stop"));
|
||||
#endif
|
||||
bool PrintCounter::_stop(const bool completed) {
|
||||
TERN_(DEBUG_PRINTCOUNTER, debug(PSTR("stop")));
|
||||
|
||||
if (super::stop()) {
|
||||
data.finishedPrints++;
|
||||
const bool did_stop = super::stop();
|
||||
if (did_stop) {
|
||||
data.printTime += deltaDuration();
|
||||
|
||||
if (duration() > data.longestPrint)
|
||||
data.longestPrint = duration();
|
||||
|
||||
saveStats();
|
||||
return true;
|
||||
if (completed) {
|
||||
data.finishedPrints++;
|
||||
if (duration() > data.longestPrint)
|
||||
data.longestPrint = duration();
|
||||
}
|
||||
}
|
||||
else return false;
|
||||
saveStats();
|
||||
return did_stop;
|
||||
}
|
||||
|
||||
// @Override
|
||||
void PrintCounter::reset() {
|
||||
#if ENABLED(DEBUG_PRINTCOUNTER)
|
||||
debug(PSTR("stop"));
|
||||
#endif
|
||||
TERN_(DEBUG_PRINTCOUNTER, debug(PSTR("stop")));
|
||||
|
||||
super::reset();
|
||||
lastDuration = 0;
|
||||
@@ -331,6 +319,7 @@ void PrintCounter::reset() {
|
||||
}
|
||||
|
||||
bool PrintCounter::needsService(const int index) {
|
||||
if (!loaded) loadStats();
|
||||
switch (index) {
|
||||
#if SERVICE_INTERVAL_1 > 0
|
||||
case 1: return data.nextService1 == 0;
|
||||
@@ -352,7 +341,7 @@ void PrintCounter::reset() {
|
||||
void PrintCounter::debug(const char func[]) {
|
||||
if (DEBUGGING(INFO)) {
|
||||
SERIAL_ECHOPGM("PrintCounter::");
|
||||
serialprintPGM(func);
|
||||
SERIAL_ECHOPGM_P(func);
|
||||
SERIAL_ECHOLNPGM("()");
|
||||
}
|
||||
}
|
||||
|
38
Marlin/src/module/printcounter.h
Executable file → Normal file
38
Marlin/src/module/printcounter.h
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@@ -28,12 +28,8 @@
|
||||
// Print debug messages with M111 S2
|
||||
//#define DEBUG_PRINTCOUNTER
|
||||
|
||||
#if USE_WIRED_EEPROM
|
||||
// round up address to next page boundary (assuming 32 byte pages)
|
||||
#define STATS_EEPROM_ADDRESS 0x40
|
||||
#else
|
||||
#define STATS_EEPROM_ADDRESS 0x32
|
||||
#endif
|
||||
// Round up I2C / SPI address to next page boundary (assuming 32 byte pages)
|
||||
#define STATS_EEPROM_ADDRESS TERN(USE_WIRED_EEPROM, 0x40, 0x32)
|
||||
|
||||
struct printStatistics { // 16 bytes
|
||||
//const uint8_t magic; // Magic header, it will always be 0x16
|
||||
@@ -57,7 +53,7 @@ class PrintCounter: public Stopwatch {
|
||||
private:
|
||||
typedef Stopwatch super;
|
||||
|
||||
#if USE_WIRED_EEPROM || defined(CPU_32_BIT)
|
||||
#if EITHER(USE_WIRED_EEPROM, CPU_32_BIT)
|
||||
typedef uint32_t eeprom_address_t;
|
||||
#else
|
||||
typedef uint16_t eeprom_address_t;
|
||||
@@ -75,19 +71,18 @@ class PrintCounter: public Stopwatch {
|
||||
* @brief Interval in seconds between counter updates
|
||||
* @details This const value defines what will be the time between each
|
||||
* accumulator update. This is different from the EEPROM save interval.
|
||||
*
|
||||
* @note The max value for this option is 60(s), otherwise integer
|
||||
* overflow will happen.
|
||||
*/
|
||||
static constexpr uint16_t updateInterval = 10;
|
||||
static constexpr millis_t updateInterval = SEC_TO_MS(10);
|
||||
|
||||
/**
|
||||
* @brief Interval in seconds between EEPROM saves
|
||||
* @details This const value defines what will be the time between each
|
||||
* EEPROM save cycle, the development team recommends to set this value
|
||||
* no lower than 3600 secs (1 hour).
|
||||
*/
|
||||
static constexpr uint16_t saveInterval = 3600;
|
||||
#if PRINTCOUNTER_SAVE_INTERVAL > 0
|
||||
/**
|
||||
* @brief Interval in seconds between EEPROM saves
|
||||
* @details This const value defines what will be the time between each
|
||||
* EEPROM save cycle, the development team recommends to set this value
|
||||
* no lower than 3600 secs (1 hour).
|
||||
*/
|
||||
static constexpr millis_t saveInterval = MIN_TO_MS(PRINTCOUNTER_SAVE_INTERVAL);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Timestamp of the last call to deltaDuration()
|
||||
@@ -180,7 +175,10 @@ class PrintCounter: public Stopwatch {
|
||||
* The following functions are being overridden
|
||||
*/
|
||||
static bool start();
|
||||
static bool stop();
|
||||
static bool _stop(const bool completed);
|
||||
static inline bool stop() { return _stop(true); }
|
||||
static inline bool abort() { return _stop(false); }
|
||||
|
||||
static void reset();
|
||||
|
||||
#if HAS_SERVICE_INTERVALS
|
||||
|
555
Marlin/src/module/probe.cpp
Executable file → Normal file
555
Marlin/src/module/probe.cpp
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -36,9 +36,9 @@
|
||||
#include "endstops.h"
|
||||
|
||||
#include "../gcode/gcode.h"
|
||||
#include "../lcd/ultralcd.h"
|
||||
#include "../lcd/marlinui.h"
|
||||
|
||||
#include "../MarlinCore.h" // for stop(), disable_e_steppers, wait_for_user
|
||||
#include "../MarlinCore.h" // for stop(), disable_e_steppers(), wait_for_user_response()
|
||||
|
||||
#if HAS_LEVELING
|
||||
#include "../feature/bedlevel/bedlevel.h"
|
||||
@@ -48,8 +48,17 @@
|
||||
#include "delta.h"
|
||||
#endif
|
||||
|
||||
#if ENABLED(BABYSTEP_ZPROBE_OFFSET)
|
||||
#include "planner.h"
|
||||
#if ANY(HAS_QUIET_PROBING, USE_SENSORLESS)
|
||||
#include "stepper/indirection.h"
|
||||
#if BOTH(HAS_QUIET_PROBING, PROBING_ESTEPPERS_OFF)
|
||||
#include "stepper.h"
|
||||
#endif
|
||||
#if USE_SENSORLESS
|
||||
#include "../feature/tmc_util.h"
|
||||
#if ENABLED(IMPROVE_HOMING_RELIABILITY)
|
||||
#include "planner.h"
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ENABLED(MEASURE_BACKLASH_WHEN_PROBING)
|
||||
@@ -68,17 +77,10 @@
|
||||
#include "servo.h"
|
||||
#endif
|
||||
|
||||
#if ENABLED(SENSORLESS_PROBING)
|
||||
#include "stepper.h"
|
||||
#include "../feature/tmc_util.h"
|
||||
#endif
|
||||
|
||||
#if QUIET_PROBING
|
||||
#include "stepper/indirection.h"
|
||||
#endif
|
||||
|
||||
#if ENABLED(EXTENSIBLE_UI)
|
||||
#include "../lcd/extui/ui_api.h"
|
||||
#elif ENABLED(DWIN_CREALITY_LCD_ENHANCED)
|
||||
#include "../lcd/e3v2/enhanced/dwin.h"
|
||||
#endif
|
||||
|
||||
#define DEBUG_OUT ENABLED(DEBUG_LEVELING_FEATURE)
|
||||
@@ -89,7 +91,11 @@ Probe probe;
|
||||
xyz_pos_t Probe::offset; // Initialized by settings.load()
|
||||
|
||||
#if HAS_PROBE_XY_OFFSET
|
||||
const xyz_pos_t &Probe::offset_xy = Probe::offset;
|
||||
const xy_pos_t &Probe::offset_xy = Probe::offset;
|
||||
#endif
|
||||
|
||||
#if ENABLED(SENSORLESS_PROBING)
|
||||
Probe::sense_bool_t Probe::test_sensitivity;
|
||||
#endif
|
||||
|
||||
#if ENABLED(Z_PROBE_SLED)
|
||||
@@ -105,7 +111,7 @@ xyz_pos_t Probe::offset; // Initialized by settings.load()
|
||||
* If true, move to MAX_X and release the solenoid
|
||||
*/
|
||||
static void dock_sled(const bool stow) {
|
||||
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("dock_sled(", stow, ")");
|
||||
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("dock_sled(", stow, ")");
|
||||
|
||||
// Dock sled a bit closer to ensure proper capturing
|
||||
do_blocking_move_to_x(X_MAX_POS + SLED_DOCKING_OFFSET - ((stow) ? 1 : 0));
|
||||
@@ -134,10 +140,8 @@ xyz_pos_t Probe::offset; // Initialized by settings.load()
|
||||
LCD_MESSAGEPGM(MSG_MANUAL_DEPLOY_TOUCHMI);
|
||||
ui.return_to_status();
|
||||
|
||||
#if ENABLED(HOST_PROMPT_SUPPORT)
|
||||
host_prompt_do(PROMPT_USER_CONTINUE, PSTR("Deploy TouchMI"), CONTINUE_STR);
|
||||
#endif
|
||||
wait_for_user_response();
|
||||
TERN_(HOST_PROMPT_SUPPORT, host_prompt_do(PROMPT_USER_CONTINUE, PSTR("Deploy TouchMI"), CONTINUE_STR));
|
||||
TERN_(HAS_RESUME_CONTINUE, wait_for_user_response());
|
||||
ui.reset_status();
|
||||
ui.goto_screen(prev_screen);
|
||||
|
||||
@@ -154,8 +158,8 @@ xyz_pos_t Probe::offset; // Initialized by settings.load()
|
||||
inline void run_stow_moves_script() {
|
||||
const xyz_pos_t oldpos = current_position;
|
||||
endstops.enable_z_probe(false);
|
||||
do_blocking_move_to_z(TOUCH_MI_RETRACT_Z, MMM_TO_MMS(HOMING_FEEDRATE_Z));
|
||||
do_blocking_move_to(oldpos, MMM_TO_MMS(HOMING_FEEDRATE_Z));
|
||||
do_blocking_move_to_z(TOUCH_MI_RETRACT_Z, homing_feedrate(Z_AXIS));
|
||||
do_blocking_move_to(oldpos, homing_feedrate(Z_AXIS));
|
||||
}
|
||||
|
||||
#elif ENABLED(Z_PROBE_ALLEN_KEY)
|
||||
@@ -238,52 +242,49 @@ xyz_pos_t Probe::offset; // Initialized by settings.load()
|
||||
|
||||
#endif // Z_PROBE_ALLEN_KEY
|
||||
|
||||
#if QUIET_PROBING
|
||||
#if HAS_QUIET_PROBING
|
||||
|
||||
void Probe::set_probing_paused(const bool p) {
|
||||
#if ENABLED(PROBING_HEATERS_OFF)
|
||||
thermalManager.pause(p);
|
||||
#ifndef DELAY_BEFORE_PROBING
|
||||
#define DELAY_BEFORE_PROBING 25
|
||||
#endif
|
||||
|
||||
void Probe::set_probing_paused(const bool dopause) {
|
||||
TERN_(PROBING_HEATERS_OFF, thermalManager.pause_heaters(dopause));
|
||||
TERN_(PROBING_FANS_OFF, thermalManager.set_fans_paused(dopause));
|
||||
TERN_(PROBING_ESTEPPERS_OFF, if (dopause) stepper.disable_e_steppers());
|
||||
#if ENABLED(PROBING_STEPPERS_OFF) && DISABLED(DELTA)
|
||||
static uint8_t old_trusted;
|
||||
if (dopause) {
|
||||
old_trusted = axis_trusted;
|
||||
stepper.disable_axis(X_AXIS);
|
||||
stepper.disable_axis(Y_AXIS);
|
||||
}
|
||||
else {
|
||||
if (TEST(old_trusted, X_AXIS)) stepper.enable_axis(X_AXIS);
|
||||
if (TEST(old_trusted, Y_AXIS)) stepper.enable_axis(Y_AXIS);
|
||||
axis_trusted = old_trusted;
|
||||
}
|
||||
#endif
|
||||
#if ENABLED(PROBING_FANS_OFF)
|
||||
thermalManager.set_fans_paused(p);
|
||||
#endif
|
||||
#if ENABLED(PROBING_STEPPERS_OFF)
|
||||
disable_e_steppers();
|
||||
#if NONE(DELTA, HOME_AFTER_DEACTIVATE)
|
||||
DISABLE_AXIS_X(); DISABLE_AXIS_Y();
|
||||
#endif
|
||||
#endif
|
||||
if (p) safe_delay(
|
||||
#if DELAY_BEFORE_PROBING > 25
|
||||
DELAY_BEFORE_PROBING
|
||||
#else
|
||||
25
|
||||
#endif
|
||||
);
|
||||
if (dopause) safe_delay(_MAX(DELAY_BEFORE_PROBING, 25));
|
||||
}
|
||||
|
||||
#endif // QUIET_PROBING
|
||||
#endif // HAS_QUIET_PROBING
|
||||
|
||||
/**
|
||||
* Raise Z to a minimum height to make room for a probe to move
|
||||
*/
|
||||
void Probe::do_z_raise(const float z_raise) {
|
||||
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("Probe::move_z(", z_raise, ")");
|
||||
|
||||
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Probe::do_z_raise(", z_raise, ")");
|
||||
float z_dest = z_raise;
|
||||
if (offset.z < 0) z_dest -= offset.z;
|
||||
|
||||
NOMORE(z_dest, Z_MAX_POS);
|
||||
|
||||
if (z_dest > current_position.z)
|
||||
do_blocking_move_to_z(z_dest);
|
||||
do_z_clearance(z_dest);
|
||||
}
|
||||
|
||||
FORCE_INLINE void probe_specific_action(const bool deploy) {
|
||||
#if ENABLED(PAUSE_BEFORE_DEPLOY_STOW)
|
||||
do {
|
||||
#if ENABLED(PAUSE_PROBE_DEPLOY_WHEN_TRIGGERED)
|
||||
if (deploy == (READ(Z_MIN_PROBE_PIN) == Z_MIN_PROBE_ENDSTOP_INVERTING)) break;
|
||||
if (deploy != PROBE_TRIGGERED()) break;
|
||||
#endif
|
||||
|
||||
BUZZ(100, 659);
|
||||
@@ -292,25 +293,15 @@ FORCE_INLINE void probe_specific_action(const bool deploy) {
|
||||
PGM_P const ds_str = deploy ? GET_TEXT(MSG_MANUAL_DEPLOY) : GET_TEXT(MSG_MANUAL_STOW);
|
||||
ui.return_to_status(); // To display the new status message
|
||||
ui.set_status_P(ds_str, 99);
|
||||
serialprintPGM(ds_str);
|
||||
SERIAL_EOL();
|
||||
SERIAL_ECHOLNPGM_P(ds_str);
|
||||
|
||||
#if ENABLED(HOST_PROMPT_SUPPORT)
|
||||
host_prompt_do(PROMPT_USER_CONTINUE, PSTR("Stow Probe"), CONTINUE_STR);
|
||||
#endif
|
||||
#if ENABLED(EXTENSIBLE_UI)
|
||||
ExtUI::onUserConfirmRequired_P(PSTR("Stow Probe"));
|
||||
#endif
|
||||
wait_for_user_response();
|
||||
TERN_(HOST_PROMPT_SUPPORT, host_prompt_do(PROMPT_USER_CONTINUE, PSTR("Stow Probe"), CONTINUE_STR));
|
||||
TERN_(EXTENSIBLE_UI, ExtUI::onUserConfirmRequired_P(PSTR("Stow Probe")));
|
||||
TERN_(DWIN_CREALITY_LCD_ENHANCED, DWIN_Popup_Confirm(ICON_BLTouch, PSTR("Stow Probe"), CONTINUE_STR));
|
||||
TERN_(HAS_RESUME_CONTINUE, wait_for_user_response());
|
||||
ui.reset_status();
|
||||
|
||||
} while(
|
||||
#if ENABLED(PAUSE_PROBE_DEPLOY_WHEN_TRIGGERED)
|
||||
true
|
||||
#else
|
||||
false
|
||||
#endif
|
||||
);
|
||||
} while (ENABLED(PAUSE_PROBE_DEPLOY_WHEN_TRIGGERED));
|
||||
|
||||
#endif // PAUSE_BEFORE_DEPLOY_STOW
|
||||
|
||||
@@ -324,15 +315,13 @@ FORCE_INLINE void probe_specific_action(const bool deploy) {
|
||||
|
||||
dock_sled(!deploy);
|
||||
|
||||
#elif ENABLED(BLTOUCH)
|
||||
|
||||
deploy ? bltouch.deploy() : bltouch.stow();
|
||||
|
||||
#elif HAS_Z_SERVO_PROBE
|
||||
|
||||
#if DISABLED(BLTOUCH)
|
||||
MOVE_SERVO(Z_PROBE_SERVO_NR, servo_angles[Z_PROBE_SERVO_NR][deploy ? 0 : 1]);
|
||||
#elif ENABLED(BLTOUCH_HS_MODE)
|
||||
// In HIGH SPEED MODE, use the normal retractable probe logic in this code
|
||||
// i.e. no intermediate STOWs and DEPLOYs in between individual probe actions
|
||||
if (deploy) bltouch.deploy(); else bltouch.stow();
|
||||
#endif
|
||||
MOVE_SERVO(Z_PROBE_SERVO_NR, servo_angles[Z_PROBE_SERVO_NR][deploy ? 0 : 1]);
|
||||
|
||||
#elif EITHER(TOUCH_MI_PROBE, Z_PROBE_ALLEN_KEY)
|
||||
|
||||
@@ -349,6 +338,59 @@ FORCE_INLINE void probe_specific_action(const bool deploy) {
|
||||
#endif
|
||||
}
|
||||
|
||||
#if EITHER(PREHEAT_BEFORE_PROBING, PREHEAT_BEFORE_LEVELING)
|
||||
|
||||
#if ENABLED(PREHEAT_BEFORE_PROBING)
|
||||
#ifndef PROBING_NOZZLE_TEMP
|
||||
#define PROBING_NOZZLE_TEMP 0
|
||||
#endif
|
||||
#ifndef PROBING_BED_TEMP
|
||||
#define PROBING_BED_TEMP 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Do preheating as required before leveling or probing.
|
||||
* - If a preheat input is higher than the current target, raise the target temperature.
|
||||
* - If a preheat input is higher than the current temperature, wait for stabilization.
|
||||
*/
|
||||
void Probe::preheat_for_probing(const celsius_t hotend_temp, const celsius_t bed_temp) {
|
||||
#if HAS_HOTEND && (PROBING_NOZZLE_TEMP || LEVELING_NOZZLE_TEMP)
|
||||
#define WAIT_FOR_NOZZLE_HEAT
|
||||
#endif
|
||||
#if HAS_HEATED_BED && (PROBING_BED_TEMP || LEVELING_BED_TEMP)
|
||||
#define WAIT_FOR_BED_HEAT
|
||||
#endif
|
||||
|
||||
DEBUG_ECHOPGM("Preheating ");
|
||||
|
||||
#if ENABLED(WAIT_FOR_NOZZLE_HEAT)
|
||||
const celsius_t hotendPreheat = hotend_temp > thermalManager.degTargetHotend(0) ? hotend_temp : 0;
|
||||
if (hotendPreheat) {
|
||||
DEBUG_ECHOPGM("hotend (", hotendPreheat, ")");
|
||||
thermalManager.setTargetHotend(hotendPreheat, 0);
|
||||
}
|
||||
#elif ENABLED(WAIT_FOR_BED_HEAT)
|
||||
constexpr celsius_t hotendPreheat = 0;
|
||||
#endif
|
||||
|
||||
#if ENABLED(WAIT_FOR_BED_HEAT)
|
||||
const celsius_t bedPreheat = bed_temp > thermalManager.degTargetBed() ? bed_temp : 0;
|
||||
if (bedPreheat) {
|
||||
if (hotendPreheat) DEBUG_ECHOPGM(" and ");
|
||||
DEBUG_ECHOPGM("bed (", bedPreheat, ")");
|
||||
thermalManager.setTargetBed(bedPreheat);
|
||||
}
|
||||
#endif
|
||||
|
||||
DEBUG_EOL();
|
||||
|
||||
TERN_(WAIT_FOR_NOZZLE_HEAT, if (hotend_temp > thermalManager.wholeDegHotend(0) + (TEMP_WINDOW)) thermalManager.wait_for_hotend(0));
|
||||
TERN_(WAIT_FOR_BED_HEAT, if (bed_temp > thermalManager.wholeDegBed() + (TEMP_BED_WINDOW)) thermalManager.wait_for_bed_heating());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Attempt to deploy or stow the probe
|
||||
*
|
||||
@@ -358,7 +400,7 @@ bool Probe::set_deployed(const bool deploy) {
|
||||
|
||||
if (DEBUGGING(LEVELING)) {
|
||||
DEBUG_POS("Probe::set_deployed", current_position);
|
||||
DEBUG_ECHOLNPAIR("deploy: ", deploy);
|
||||
DEBUG_ECHOLNPGM("deploy: ", deploy);
|
||||
}
|
||||
|
||||
if (endstops.z_probe_enabled == deploy) return false;
|
||||
@@ -367,27 +409,16 @@ bool Probe::set_deployed(const bool deploy) {
|
||||
// Fix-mounted probe should only raise for deploy
|
||||
// unless PAUSE_BEFORE_DEPLOY_STOW is enabled
|
||||
#if EITHER(FIX_MOUNTED_PROBE, NOZZLE_AS_PROBE) && DISABLED(PAUSE_BEFORE_DEPLOY_STOW)
|
||||
const bool deploy_stow_condition = deploy;
|
||||
const bool z_raise_wanted = deploy;
|
||||
#else
|
||||
constexpr bool deploy_stow_condition = true;
|
||||
constexpr bool z_raise_wanted = true;
|
||||
#endif
|
||||
|
||||
// For beds that fall when Z is powered off only raise for trusted Z
|
||||
#if ENABLED(UNKNOWN_Z_NO_RAISE)
|
||||
const bool unknown_condition = TEST(axis_known_position, Z_AXIS);
|
||||
#else
|
||||
constexpr float unknown_condition = true;
|
||||
#endif
|
||||
|
||||
if (deploy_stow_condition && unknown_condition)
|
||||
if (z_raise_wanted)
|
||||
do_z_raise(_MAX(Z_CLEARANCE_BETWEEN_PROBES, Z_CLEARANCE_DEPLOY_PROBE));
|
||||
|
||||
#if EITHER(Z_PROBE_SLED, Z_PROBE_ALLEN_KEY)
|
||||
if (axis_unhomed_error(
|
||||
#if ENABLED(Z_PROBE_SLED)
|
||||
_BV(X_AXIS)
|
||||
#endif
|
||||
)) {
|
||||
if (homing_needed_error(TERN_(Z_PROBE_SLED, _BV(X_AXIS)))) {
|
||||
SERIAL_ERROR_MSG(STR_STOP_UNHOMED);
|
||||
stop();
|
||||
return true;
|
||||
@@ -397,23 +428,15 @@ bool Probe::set_deployed(const bool deploy) {
|
||||
const xy_pos_t old_xy = current_position;
|
||||
|
||||
#if ENABLED(PROBE_TRIGGERED_WHEN_STOWED_TEST)
|
||||
#if HAS_CUSTOM_PROBE_PIN
|
||||
#define PROBE_STOWED() (READ(Z_MIN_PROBE_PIN) != Z_MIN_PROBE_ENDSTOP_INVERTING)
|
||||
#else
|
||||
#define PROBE_STOWED() (READ(Z_MIN_PIN) != Z_MIN_ENDSTOP_INVERTING)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef PROBE_STOWED
|
||||
|
||||
// Only deploy/stow if needed
|
||||
if (PROBE_STOWED() == deploy) {
|
||||
if (PROBE_TRIGGERED() == deploy) {
|
||||
if (!deploy) endstops.enable_z_probe(false); // Switch off triggered when stowed probes early
|
||||
// otherwise an Allen-Key probe can't be stowed.
|
||||
probe_specific_action(deploy);
|
||||
}
|
||||
|
||||
if (PROBE_STOWED() == deploy) { // Unchanged after deploy/stow action?
|
||||
if (PROBE_TRIGGERED() == deploy) { // Unchanged after deploy/stow action?
|
||||
if (IsRunning()) {
|
||||
SERIAL_ERROR_MSG("Z-Probe failed");
|
||||
LCD_ALERTMESSAGEPGM_P(PSTR("Err: ZPROBE"));
|
||||
@@ -428,21 +451,14 @@ bool Probe::set_deployed(const bool deploy) {
|
||||
|
||||
#endif
|
||||
|
||||
// If preheating is required before any probing...
|
||||
TERN_(PREHEAT_BEFORE_PROBING, if (deploy) preheat_for_probing(PROBING_NOZZLE_TEMP, PROBING_BED_TEMP));
|
||||
|
||||
do_blocking_move_to(old_xy);
|
||||
endstops.enable_z_probe(deploy);
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef Z_AFTER_PROBING
|
||||
// After probing move to a preferred Z position
|
||||
void Probe::move_z_after_probing() {
|
||||
if (current_position.z != Z_AFTER_PROBING) {
|
||||
do_blocking_move_to_z(Z_AFTER_PROBING);
|
||||
current_position.z = Z_AFTER_PROBING;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Used by run_z_probe to do a single Z probe move.
|
||||
*
|
||||
@@ -461,67 +477,60 @@ bool Probe::set_deployed(const bool deploy) {
|
||||
*
|
||||
* @return TRUE if the probe failed to trigger.
|
||||
*/
|
||||
bool Probe::probe_down_to_z(const float z, const feedRate_t fr_mm_s) {
|
||||
if (DEBUGGING(LEVELING)) DEBUG_POS(">>> Probe::probe_down_to_z", current_position);
|
||||
bool Probe::probe_down_to_z(const_float_t z, const_feedRate_t fr_mm_s) {
|
||||
DEBUG_SECTION(log_probe, "Probe::probe_down_to_z", DEBUGGING(LEVELING));
|
||||
|
||||
#if HAS_HEATED_BED && ENABLED(WAIT_FOR_BED_HEATER)
|
||||
#if BOTH(HAS_HEATED_BED, WAIT_FOR_BED_HEATER)
|
||||
thermalManager.wait_for_bed_heating();
|
||||
#endif
|
||||
|
||||
#if ENABLED(BLTOUCH) && DISABLED(BLTOUCH_HS_MODE)
|
||||
if (bltouch.deploy()) return true; // DEPLOY in LOW SPEED MODE on every probe action
|
||||
#if BOTH(HAS_TEMP_HOTEND, WAIT_FOR_HOTEND)
|
||||
thermalManager.wait_for_hotend_heating(active_extruder);
|
||||
#endif
|
||||
|
||||
if (TERN0(BLTOUCH_SLOW_MODE, bltouch.deploy())) return true; // Deploy in LOW SPEED MODE on every probe action
|
||||
|
||||
// Disable stealthChop if used. Enable diag1 pin on driver.
|
||||
#if ENABLED(SENSORLESS_PROBING)
|
||||
sensorless_t stealth_states { false };
|
||||
#if ENABLED(DELTA)
|
||||
stealth_states.x = tmc_enable_stallguard(stepperX);
|
||||
stealth_states.y = tmc_enable_stallguard(stepperY);
|
||||
#if HAS_DELTA_SENSORLESS_PROBING
|
||||
if (probe.test_sensitivity.x) stealth_states.x = tmc_enable_stallguard(stepperX); // Delta watches all DIAG pins for a stall
|
||||
if (probe.test_sensitivity.y) stealth_states.y = tmc_enable_stallguard(stepperY);
|
||||
#endif
|
||||
stealth_states.z = tmc_enable_stallguard(stepperZ);
|
||||
if (probe.test_sensitivity.z) stealth_states.z = tmc_enable_stallguard(stepperZ); // All machines will check Z-DIAG for stall
|
||||
endstops.enable(true);
|
||||
set_homing_current(true); // The "homing" current also applies to probing
|
||||
#endif
|
||||
|
||||
#if QUIET_PROBING
|
||||
set_probing_paused(true);
|
||||
#endif
|
||||
TERN_(HAS_QUIET_PROBING, set_probing_paused(true));
|
||||
|
||||
// Move down until the probe is triggered
|
||||
do_blocking_move_to_z(z, fr_mm_s);
|
||||
|
||||
// Check to see if the probe was triggered
|
||||
const bool probe_triggered =
|
||||
#if BOTH(DELTA, SENSORLESS_PROBING)
|
||||
endstops.trigger_state() & (_BV(X_MIN) | _BV(Y_MIN) | _BV(Z_MIN))
|
||||
#if HAS_DELTA_SENSORLESS_PROBING
|
||||
endstops.trigger_state() & (_BV(X_MAX) | _BV(Y_MAX) | _BV(Z_MAX))
|
||||
#else
|
||||
TEST(endstops.trigger_state(),
|
||||
#if ENABLED(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN)
|
||||
Z_MIN
|
||||
#else
|
||||
Z_MIN_PROBE
|
||||
#endif
|
||||
)
|
||||
TEST(endstops.trigger_state(), Z_MIN_PROBE)
|
||||
#endif
|
||||
;
|
||||
|
||||
#if QUIET_PROBING
|
||||
set_probing_paused(false);
|
||||
#endif
|
||||
TERN_(HAS_QUIET_PROBING, set_probing_paused(false));
|
||||
|
||||
// Re-enable stealthChop if used. Disable diag1 pin on driver.
|
||||
#if ENABLED(SENSORLESS_PROBING)
|
||||
endstops.not_homing();
|
||||
#if ENABLED(DELTA)
|
||||
tmc_disable_stallguard(stepperX, stealth_states.x);
|
||||
tmc_disable_stallguard(stepperY, stealth_states.y);
|
||||
#if HAS_DELTA_SENSORLESS_PROBING
|
||||
if (probe.test_sensitivity.x) tmc_disable_stallguard(stepperX, stealth_states.x);
|
||||
if (probe.test_sensitivity.y) tmc_disable_stallguard(stepperY, stealth_states.y);
|
||||
#endif
|
||||
tmc_disable_stallguard(stepperZ, stealth_states.z);
|
||||
if (probe.test_sensitivity.z) tmc_disable_stallguard(stepperZ, stealth_states.z);
|
||||
set_homing_current(false);
|
||||
#endif
|
||||
|
||||
#if ENABLED(BLTOUCH) && DISABLED(BLTOUCH_HS_MODE)
|
||||
if (probe_triggered && bltouch.stow()) return true; // STOW in LOW SPEED MODE on trigger on every probe action
|
||||
#endif
|
||||
if (probe_triggered && TERN0(BLTOUCH_SLOW_MODE, bltouch.stow())) // Stow in LOW SPEED MODE on every trigger
|
||||
return true;
|
||||
|
||||
// Clear endstop flags
|
||||
endstops.hit_on_purpose();
|
||||
@@ -532,11 +541,46 @@ bool Probe::probe_down_to_z(const float z, const feedRate_t fr_mm_s) {
|
||||
// Tell the planner where we actually are
|
||||
sync_plan_position();
|
||||
|
||||
if (DEBUGGING(LEVELING)) DEBUG_POS("<<< Probe::probe_down_to_z", current_position);
|
||||
|
||||
return !probe_triggered;
|
||||
}
|
||||
|
||||
#if ENABLED(PROBE_TARE)
|
||||
|
||||
/**
|
||||
* @brief Init the tare pin
|
||||
*
|
||||
* @details Init tare pin to ON state for a strain gauge, otherwise OFF
|
||||
*/
|
||||
void Probe::tare_init() {
|
||||
OUT_WRITE(PROBE_TARE_PIN, !PROBE_TARE_STATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tare the Z probe
|
||||
*
|
||||
* @details Signal to the probe to tare itself
|
||||
*
|
||||
* @return TRUE if the tare cold not be completed
|
||||
*/
|
||||
bool Probe::tare() {
|
||||
#if BOTH(PROBE_ACTIVATION_SWITCH, PROBE_TARE_ONLY_WHILE_INACTIVE)
|
||||
if (endstops.probe_switch_activated()) {
|
||||
SERIAL_ECHOLNPGM("Cannot tare an active probe");
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
SERIAL_ECHOLNPGM("Taring probe");
|
||||
WRITE(PROBE_TARE_PIN, PROBE_TARE_STATE);
|
||||
delay(PROBE_TARE_TIME);
|
||||
WRITE(PROBE_TARE_PIN, !PROBE_TARE_STATE);
|
||||
delay(PROBE_TARE_DELAY);
|
||||
|
||||
endstops.hit_on_purpose();
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Probe at the current XY (possibly more than once) to find the bed Z.
|
||||
*
|
||||
@@ -546,54 +590,70 @@ bool Probe::probe_down_to_z(const float z, const feedRate_t fr_mm_s) {
|
||||
* @return The Z position of the bed at the current XY or NAN on error.
|
||||
*/
|
||||
float Probe::run_z_probe(const bool sanity_check/*=true*/) {
|
||||
DEBUG_SECTION(log_probe, "Probe::run_z_probe", DEBUGGING(LEVELING));
|
||||
|
||||
if (DEBUGGING(LEVELING)) DEBUG_POS(">>> Probe::run_z_probe", current_position);
|
||||
auto try_to_probe = [&](PGM_P const plbl, const_float_t z_probe_low_point, const feedRate_t fr_mm_s, const bool scheck, const float clearance) -> bool {
|
||||
// Tare the probe, if supported
|
||||
if (TERN0(PROBE_TARE, tare())) return true;
|
||||
|
||||
// Do a first probe at the fast speed
|
||||
const bool probe_fail = probe_down_to_z(z_probe_low_point, fr_mm_s), // No probe trigger?
|
||||
early_fail = (scheck && current_position.z > -offset.z + clearance); // Probe triggered too high?
|
||||
#if ENABLED(DEBUG_LEVELING_FEATURE)
|
||||
if (DEBUGGING(LEVELING) && (probe_fail || early_fail)) {
|
||||
DEBUG_ECHOPGM_P(plbl);
|
||||
DEBUG_ECHOPGM(" Probe fail! -");
|
||||
if (probe_fail) DEBUG_ECHOPGM(" No trigger.");
|
||||
if (early_fail) DEBUG_ECHOPGM(" Triggered early.");
|
||||
DEBUG_EOL();
|
||||
}
|
||||
#else
|
||||
UNUSED(plbl);
|
||||
#endif
|
||||
return probe_fail || early_fail;
|
||||
};
|
||||
|
||||
// Stop the probe before it goes too low to prevent damage.
|
||||
// If Z isn't known then probe to -10mm.
|
||||
const float z_probe_low_point = TEST(axis_known_position, Z_AXIS) ? -offset.z + Z_PROBE_LOW_POINT : -10.0;
|
||||
const float z_probe_low_point = axis_is_trusted(Z_AXIS) ? -offset.z + Z_PROBE_LOW_POINT : -10.0;
|
||||
|
||||
// Double-probing does a fast probe followed by a slow probe
|
||||
#if TOTAL_PROBING == 2
|
||||
|
||||
// Attempt to tare the probe
|
||||
if (TERN0(PROBE_TARE, tare())) return NAN;
|
||||
|
||||
// Do a first probe at the fast speed
|
||||
if (probe_down_to_z(z_probe_low_point, MMM_TO_MMS(Z_PROBE_SPEED_FAST)) // No probe trigger?
|
||||
|| (sanity_check && current_position.z > -offset.z + _MAX(Z_CLEARANCE_BETWEEN_PROBES, 4) / 2) // Probe triggered too high?
|
||||
) {
|
||||
if (DEBUGGING(LEVELING)) {
|
||||
DEBUG_ECHOLNPGM("FAST Probe fail!");
|
||||
DEBUG_POS("<<< run_z_probe", current_position);
|
||||
}
|
||||
return NAN;
|
||||
}
|
||||
if (try_to_probe(PSTR("FAST"), z_probe_low_point, z_probe_fast_mm_s,
|
||||
sanity_check, Z_CLEARANCE_BETWEEN_PROBES) ) return NAN;
|
||||
|
||||
const float first_probe_z = current_position.z;
|
||||
|
||||
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("1st Probe Z:", first_probe_z);
|
||||
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("1st Probe Z:", first_probe_z);
|
||||
|
||||
// Raise to give the probe clearance
|
||||
do_blocking_move_to_z(current_position.z + Z_CLEARANCE_MULTI_PROBE, MMM_TO_MMS(Z_PROBE_SPEED_FAST));
|
||||
do_blocking_move_to_z(current_position.z + Z_CLEARANCE_MULTI_PROBE, z_probe_fast_mm_s);
|
||||
|
||||
#elif Z_PROBE_SPEED_FAST != Z_PROBE_SPEED_SLOW
|
||||
#elif Z_PROBE_FEEDRATE_FAST != Z_PROBE_FEEDRATE_SLOW
|
||||
|
||||
// If the nozzle is well over the travel height then
|
||||
// move down quickly before doing the slow probe
|
||||
const float z = Z_CLEARANCE_DEPLOY_PROBE + 5.0 + (offset.z < 0 ? -offset.z : 0);
|
||||
if (current_position.z > z) {
|
||||
// Probe down fast. If the probe never triggered, raise for probe clearance
|
||||
if (!probe_down_to_z(z, MMM_TO_MMS(Z_PROBE_SPEED_FAST)))
|
||||
do_blocking_move_to_z(current_position.z + Z_CLEARANCE_BETWEEN_PROBES, MMM_TO_MMS(Z_PROBE_SPEED_FAST));
|
||||
if (!probe_down_to_z(z, z_probe_fast_mm_s))
|
||||
do_blocking_move_to_z(current_position.z + Z_CLEARANCE_BETWEEN_PROBES, z_probe_fast_mm_s);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef EXTRA_PROBING
|
||||
#if EXTRA_PROBING > 0
|
||||
float probes[TOTAL_PROBING];
|
||||
#endif
|
||||
|
||||
#if TOTAL_PROBING > 2
|
||||
float probes_z_sum = 0;
|
||||
for (
|
||||
#if EXTRA_PROBING
|
||||
#if EXTRA_PROBING > 0
|
||||
uint8_t p = 0; p < TOTAL_PROBING; p++
|
||||
#else
|
||||
uint8_t p = TOTAL_PROBING; p--;
|
||||
@@ -601,24 +661,18 @@ float Probe::run_z_probe(const bool sanity_check/*=true*/) {
|
||||
)
|
||||
#endif
|
||||
{
|
||||
// Probe downward slowly to find the bed
|
||||
if (probe_down_to_z(z_probe_low_point, MMM_TO_MMS(Z_PROBE_SPEED_SLOW)) // No probe trigger?
|
||||
|| (sanity_check && current_position.z > -offset.z + _MAX(Z_CLEARANCE_MULTI_PROBE, 4) / 2) // Probe triggered too high?
|
||||
) {
|
||||
if (DEBUGGING(LEVELING)) {
|
||||
DEBUG_ECHOLNPGM("SLOW Probe fail!");
|
||||
DEBUG_POS("<<< run_z_probe", current_position);
|
||||
}
|
||||
return NAN;
|
||||
}
|
||||
// If the probe won't tare, return
|
||||
if (TERN0(PROBE_TARE, tare())) return true;
|
||||
|
||||
#if ENABLED(MEASURE_BACKLASH_WHEN_PROBING)
|
||||
backlash.measure_with_probe();
|
||||
#endif
|
||||
// Probe downward slowly to find the bed
|
||||
if (try_to_probe(PSTR("SLOW"), z_probe_low_point, MMM_TO_MMS(Z_PROBE_FEEDRATE_SLOW),
|
||||
sanity_check, Z_CLEARANCE_MULTI_PROBE) ) return NAN;
|
||||
|
||||
TERN_(MEASURE_BACKLASH_WHEN_PROBING, backlash.measure_with_probe());
|
||||
|
||||
const float z = current_position.z;
|
||||
|
||||
#if EXTRA_PROBING
|
||||
#if EXTRA_PROBING > 0
|
||||
// Insert Z measurement into probes[]. Keep it sorted ascending.
|
||||
LOOP_LE_N(i, p) { // Iterate the saved Zs to insert the new Z
|
||||
if (i == p || probes[i] > z) { // Last index or new Z is smaller than this Z
|
||||
@@ -636,16 +690,16 @@ float Probe::run_z_probe(const bool sanity_check/*=true*/) {
|
||||
#if TOTAL_PROBING > 2
|
||||
// Small Z raise after all but the last probe
|
||||
if (p
|
||||
#if EXTRA_PROBING
|
||||
#if EXTRA_PROBING > 0
|
||||
< TOTAL_PROBING - 1
|
||||
#endif
|
||||
) do_blocking_move_to_z(z + Z_CLEARANCE_MULTI_PROBE, MMM_TO_MMS(Z_PROBE_SPEED_FAST));
|
||||
) do_blocking_move_to_z(z + Z_CLEARANCE_MULTI_PROBE, z_probe_fast_mm_s);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if TOTAL_PROBING > 2
|
||||
|
||||
#if EXTRA_PROBING
|
||||
#if EXTRA_PROBING > 0
|
||||
// Take the center value (or average the two middle values) as the median
|
||||
static constexpr int PHALF = (TOTAL_PROBING - 1) / 2;
|
||||
const float middle = probes[PHALF],
|
||||
@@ -669,7 +723,7 @@ float Probe::run_z_probe(const bool sanity_check/*=true*/) {
|
||||
|
||||
const float z2 = current_position.z;
|
||||
|
||||
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("2nd Probe Z:", z2, " Discrepancy:", first_probe_z - z2);
|
||||
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("2nd Probe Z:", z2, " Discrepancy:", first_probe_z - z2);
|
||||
|
||||
// Return a weighted average of the fast and slow probes
|
||||
const float measured_z = (z2 * 3.0 + first_probe_z * 2.0) * 0.2;
|
||||
@@ -681,8 +735,6 @@ float Probe::run_z_probe(const bool sanity_check/*=true*/) {
|
||||
|
||||
#endif
|
||||
|
||||
if (DEBUGGING(LEVELING)) DEBUG_POS("<<< run_z_probe", current_position);
|
||||
|
||||
return measured_z;
|
||||
}
|
||||
|
||||
@@ -695,12 +747,14 @@ float Probe::run_z_probe(const bool sanity_check/*=true*/) {
|
||||
* - Raise to the BETWEEN height
|
||||
* - Return the probed Z position
|
||||
*/
|
||||
float Probe::probe_at_point(const float &rx, const float &ry, const ProbePtRaise raise_after/*=PROBE_PT_NONE*/, const uint8_t verbose_level/*=0*/, const bool probe_relative/*=true*/, const bool sanity_check/*=true*/) {
|
||||
float Probe::probe_at_point(const_float_t rx, const_float_t ry, const ProbePtRaise raise_after/*=PROBE_PT_NONE*/, const uint8_t verbose_level/*=0*/, const bool probe_relative/*=true*/, const bool sanity_check/*=true*/) {
|
||||
DEBUG_SECTION(log_probe, "Probe::probe_at_point", DEBUGGING(LEVELING));
|
||||
|
||||
if (DEBUGGING(LEVELING)) {
|
||||
DEBUG_ECHOLNPAIR(
|
||||
">>> Probe::probe_at_point(", LOGICAL_X_POSITION(rx), ", ", LOGICAL_Y_POSITION(ry),
|
||||
", ", raise_after == PROBE_PT_RAISE ? "raise" : raise_after == PROBE_PT_STOW ? "stow" : "none",
|
||||
", ", int(verbose_level),
|
||||
DEBUG_ECHOLNPGM(
|
||||
"...(", LOGICAL_X_POSITION(rx), ", ", LOGICAL_Y_POSITION(ry),
|
||||
", ", raise_after == PROBE_PT_RAISE ? "raise" : raise_after == PROBE_PT_LAST_STOW ? "stow (last)" : raise_after == PROBE_PT_STOW ? "stow" : "none",
|
||||
", ", verbose_level,
|
||||
", ", probe_relative ? "probe" : "nozzle", "_relative)"
|
||||
);
|
||||
DEBUG_POS("", current_position);
|
||||
@@ -710,8 +764,8 @@ float Probe::probe_at_point(const float &rx, const float &ry, const ProbePtRaise
|
||||
if (bltouch.triggered()) bltouch._reset();
|
||||
#endif
|
||||
|
||||
// TODO: Adapt for SCARA, where the offset rotates
|
||||
xyz_pos_t npos = { rx, ry };
|
||||
// On delta keep Z below clip height or do_blocking_move_to will abort
|
||||
xyz_pos_t npos = { rx, ry, TERN(DELTA, _MIN(delta_clip_start_height, current_position.z), current_position.z) };
|
||||
if (probe_relative) { // The given position is in terms of the probe
|
||||
if (!can_reach(npos)) {
|
||||
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Position Not Reachable");
|
||||
@@ -721,47 +775,30 @@ float Probe::probe_at_point(const float &rx, const float &ry, const ProbePtRaise
|
||||
}
|
||||
else if (!position_is_reachable(npos)) return NAN; // The given position is in terms of the nozzle
|
||||
|
||||
npos.z =
|
||||
#if ENABLED(DELTA)
|
||||
// Move below clip height or xy move will be aborted by do_blocking_move_to
|
||||
_MIN(current_position.z, delta_clip_start_height)
|
||||
#else
|
||||
current_position.z
|
||||
#endif
|
||||
;
|
||||
|
||||
const float old_feedrate_mm_s = feedrate_mm_s;
|
||||
feedrate_mm_s = XY_PROBE_FEEDRATE_MM_S;
|
||||
|
||||
// Move the probe to the starting XYZ
|
||||
do_blocking_move_to(npos);
|
||||
do_blocking_move_to(npos, feedRate_t(XY_PROBE_FEEDRATE_MM_S));
|
||||
|
||||
float measured_z = NAN;
|
||||
if (!deploy()) measured_z = run_z_probe(sanity_check) + offset.z;
|
||||
if (!isnan(measured_z)) {
|
||||
const bool big_raise = raise_after == PROBE_PT_BIG_RAISE;
|
||||
if (big_raise || raise_after == PROBE_PT_RAISE)
|
||||
do_blocking_move_to_z(current_position.z + (big_raise ? 25 : Z_CLEARANCE_BETWEEN_PROBES), MMM_TO_MMS(Z_PROBE_SPEED_FAST));
|
||||
else if (raise_after == PROBE_PT_STOW)
|
||||
do_blocking_move_to_z(current_position.z + (big_raise ? 25 : Z_CLEARANCE_BETWEEN_PROBES), z_probe_fast_mm_s);
|
||||
else if (raise_after == PROBE_PT_STOW || raise_after == PROBE_PT_LAST_STOW)
|
||||
if (stow()) measured_z = NAN; // Error on stow?
|
||||
|
||||
if (verbose_level > 2) {
|
||||
SERIAL_ECHOPAIR_F("Bed X: ", LOGICAL_X_POSITION(rx), 3);
|
||||
SERIAL_ECHOPAIR_F( " Y: ", LOGICAL_Y_POSITION(ry), 3);
|
||||
SERIAL_ECHOLNPAIR_F( " Z: ", measured_z, 3);
|
||||
}
|
||||
if (verbose_level > 2)
|
||||
SERIAL_ECHOLNPGM("Bed X: ", LOGICAL_X_POSITION(rx), " Y: ", LOGICAL_Y_POSITION(ry), " Z: ", measured_z);
|
||||
}
|
||||
|
||||
feedrate_mm_s = old_feedrate_mm_s;
|
||||
|
||||
if (isnan(measured_z)) {
|
||||
stow();
|
||||
LCD_MESSAGEPGM(MSG_LCD_PROBING_FAILED);
|
||||
SERIAL_ERROR_MSG(STR_ERR_PROBING_FAILED);
|
||||
#if DISABLED(G29_RETRY_AND_RECOVER)
|
||||
SERIAL_ERROR_MSG(STR_ERR_PROBING_FAILED);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("<<< Probe::probe_at_point");
|
||||
|
||||
return measured_z;
|
||||
}
|
||||
|
||||
@@ -775,11 +812,101 @@ float Probe::probe_at_point(const float &rx, const float &ry, const ProbePtRaise
|
||||
* when starting up the machine or rebooting the board.
|
||||
* There's no way to know where the nozzle is positioned until
|
||||
* homing has been done - no homing with z-probe without init!
|
||||
*
|
||||
*/
|
||||
STOW_Z_SERVO();
|
||||
}
|
||||
|
||||
#endif // HAS_Z_SERVO_PROBE
|
||||
|
||||
#if USE_SENSORLESS
|
||||
|
||||
sensorless_t stealth_states { false };
|
||||
|
||||
/**
|
||||
* Disable stealthChop if used. Enable diag1 pin on driver.
|
||||
*/
|
||||
void Probe::enable_stallguard_diag1() {
|
||||
#if ENABLED(SENSORLESS_PROBING)
|
||||
#if HAS_DELTA_SENSORLESS_PROBING
|
||||
stealth_states.x = tmc_enable_stallguard(stepperX);
|
||||
stealth_states.y = tmc_enable_stallguard(stepperY);
|
||||
#endif
|
||||
stealth_states.z = tmc_enable_stallguard(stepperZ);
|
||||
endstops.enable(true);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-enable stealthChop if used. Disable diag1 pin on driver.
|
||||
*/
|
||||
void Probe::disable_stallguard_diag1() {
|
||||
#if ENABLED(SENSORLESS_PROBING)
|
||||
endstops.not_homing();
|
||||
#if HAS_DELTA_SENSORLESS_PROBING
|
||||
tmc_disable_stallguard(stepperX, stealth_states.x);
|
||||
tmc_disable_stallguard(stepperY, stealth_states.y);
|
||||
#endif
|
||||
tmc_disable_stallguard(stepperZ, stealth_states.z);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the current in the TMC drivers to N##_CURRENT_HOME. And we save the current configuration of each TMC driver.
|
||||
*/
|
||||
void Probe::set_homing_current(const bool onoff) {
|
||||
#define HAS_CURRENT_HOME(N) (defined(N##_CURRENT_HOME) && N##_CURRENT_HOME != N##_CURRENT)
|
||||
#if HAS_CURRENT_HOME(X) || HAS_CURRENT_HOME(Y) || HAS_CURRENT_HOME(Z)
|
||||
#if ENABLED(DELTA)
|
||||
static int16_t saved_current_X, saved_current_Y;
|
||||
#endif
|
||||
#if HAS_CURRENT_HOME(Z)
|
||||
static int16_t saved_current_Z;
|
||||
#endif
|
||||
#if ((ENABLED(DELTA) && (HAS_CURRENT_HOME(X) || HAS_CURRENT_HOME(Y))) || HAS_CURRENT_HOME(Z))
|
||||
auto debug_current_on = [](PGM_P const s, const int16_t a, const int16_t b) {
|
||||
if (DEBUGGING(LEVELING)) { DEBUG_ECHOPGM_P(s); DEBUG_ECHOLNPGM(" current: ", a, " -> ", b); }
|
||||
};
|
||||
#endif
|
||||
if (onoff) {
|
||||
#if ENABLED(DELTA)
|
||||
#if HAS_CURRENT_HOME(X)
|
||||
saved_current_X = stepperX.getMilliamps();
|
||||
stepperX.rms_current(X_CURRENT_HOME);
|
||||
debug_current_on(PSTR("X"), saved_current_X, X_CURRENT_HOME);
|
||||
#endif
|
||||
#if HAS_CURRENT_HOME(Y)
|
||||
saved_current_Y = stepperY.getMilliamps();
|
||||
stepperY.rms_current(Y_CURRENT_HOME);
|
||||
debug_current_on(PSTR("Y"), saved_current_Y, Y_CURRENT_HOME);
|
||||
#endif
|
||||
#endif
|
||||
#if HAS_CURRENT_HOME(Z)
|
||||
saved_current_Z = stepperZ.getMilliamps();
|
||||
stepperZ.rms_current(Z_CURRENT_HOME);
|
||||
debug_current_on(PSTR("Z"), saved_current_Z, Z_CURRENT_HOME);
|
||||
#endif
|
||||
TERN_(IMPROVE_HOMING_RELIABILITY, planner.enable_stall_prevention(true));
|
||||
}
|
||||
else {
|
||||
#if ENABLED(DELTA)
|
||||
#if HAS_CURRENT_HOME(X)
|
||||
stepperX.rms_current(saved_current_X);
|
||||
debug_current_on(PSTR("X"), X_CURRENT_HOME, saved_current_X);
|
||||
#endif
|
||||
#if HAS_CURRENT_HOME(Y)
|
||||
stepperY.rms_current(saved_current_Y);
|
||||
debug_current_on(PSTR("Y"), Y_CURRENT_HOME, saved_current_Y);
|
||||
#endif
|
||||
#endif
|
||||
#if HAS_CURRENT_HOME(Z)
|
||||
stepperZ.rms_current(saved_current_Z);
|
||||
debug_current_on(PSTR("Z"), Z_CURRENT_HOME, saved_current_Z);
|
||||
#endif
|
||||
TERN_(IMPROVE_HOMING_RELIABILITY, planner.enable_stall_prevention(false));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // SENSORLESS_PROBING || SENSORLESS_HOMING
|
||||
|
||||
#endif // HAS_BED_PROBE
|
||||
|
204
Marlin/src/module/probe.h
Executable file → Normal file
204
Marlin/src/module/probe.h
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@@ -33,33 +33,57 @@
|
||||
enum ProbePtRaise : uint8_t {
|
||||
PROBE_PT_NONE, // No raise or stow after run_z_probe
|
||||
PROBE_PT_STOW, // Do a complete stow after run_z_probe
|
||||
PROBE_PT_LAST_STOW, // Stow for sure, even in BLTouch HS mode
|
||||
PROBE_PT_RAISE, // Raise to "between" clearance after run_z_probe
|
||||
PROBE_PT_BIG_RAISE // Raise to big clearance after run_z_probe
|
||||
};
|
||||
#endif
|
||||
|
||||
#if USES_Z_MIN_PROBE_PIN
|
||||
#define PROBE_TRIGGERED() (READ(Z_MIN_PROBE_PIN) != Z_MIN_PROBE_ENDSTOP_INVERTING)
|
||||
#else
|
||||
#define PROBE_TRIGGERED() (READ(Z_MIN_PIN) != Z_MIN_ENDSTOP_INVERTING)
|
||||
#endif
|
||||
|
||||
#if ENABLED(PREHEAT_BEFORE_LEVELING)
|
||||
#ifndef LEVELING_NOZZLE_TEMP
|
||||
#define LEVELING_NOZZLE_TEMP 0
|
||||
#endif
|
||||
#ifndef LEVELING_BED_TEMP
|
||||
#define LEVELING_BED_TEMP 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
class Probe {
|
||||
public:
|
||||
|
||||
#if ENABLED(SENSORLESS_PROBING)
|
||||
typedef struct { bool x:1, y:1, z:1; } sense_bool_t;
|
||||
static sense_bool_t test_sensitivity;
|
||||
#endif
|
||||
|
||||
#if HAS_BED_PROBE
|
||||
|
||||
static xyz_pos_t offset;
|
||||
|
||||
static bool set_deployed(const bool deploy);
|
||||
#if EITHER(PREHEAT_BEFORE_PROBING, PREHEAT_BEFORE_LEVELING)
|
||||
static void preheat_for_probing(const celsius_t hotend_temp, const celsius_t bed_temp);
|
||||
#endif
|
||||
|
||||
static bool set_deployed(const bool deploy);
|
||||
|
||||
#if IS_KINEMATIC
|
||||
|
||||
#if HAS_PROBE_XY_OFFSET
|
||||
// Return true if the both nozzle and the probe can reach the given point.
|
||||
// Note: This won't work on SCARA since the probe offset rotates with the arm.
|
||||
static inline bool can_reach(const float &rx, const float &ry) {
|
||||
static bool can_reach(const_float_t rx, const_float_t ry) {
|
||||
return position_is_reachable(rx - offset_xy.x, ry - offset_xy.y) // The nozzle can go where it needs to go?
|
||||
&& position_is_reachable(rx, ry, ABS(MIN_PROBE_EDGE)); // Can the nozzle also go near there?
|
||||
&& position_is_reachable(rx, ry, ABS(PROBING_MARGIN)); // Can the nozzle also go near there?
|
||||
}
|
||||
#else
|
||||
FORCE_INLINE static bool can_reach(const float &rx, const float &ry) {
|
||||
return position_is_reachable(rx, ry, MIN_PROBE_EDGE);
|
||||
static bool can_reach(const_float_t rx, const_float_t ry) {
|
||||
return position_is_reachable(rx, ry, PROBING_MARGIN);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -72,40 +96,50 @@ public:
|
||||
* Example: For a probe offset of -10,+10, then for the probe to reach 0,0 the
|
||||
* nozzle must be be able to reach +10,-10.
|
||||
*/
|
||||
static inline bool can_reach(const float &rx, const float &ry) {
|
||||
static bool can_reach(const_float_t rx, const_float_t ry) {
|
||||
return position_is_reachable(rx - offset_xy.x, ry - offset_xy.y)
|
||||
&& WITHIN(rx, min_x() - fslop, max_x() + fslop)
|
||||
&& WITHIN(ry, min_y() - fslop, max_y() + fslop);
|
||||
&& COORDINATE_OKAY(rx, min_x() - fslop, max_x() + fslop)
|
||||
&& COORDINATE_OKAY(ry, min_y() - fslop, max_y() + fslop);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef Z_AFTER_PROBING
|
||||
static void move_z_after_probing();
|
||||
#endif
|
||||
static float probe_at_point(const float &rx, const float &ry, const ProbePtRaise raise_after=PROBE_PT_NONE, const uint8_t verbose_level=0, const bool probe_relative=true, const bool sanity_check=true);
|
||||
static inline float probe_at_point(const xy_pos_t &pos, const ProbePtRaise raise_after=PROBE_PT_NONE, const uint8_t verbose_level=0, const bool probe_relative=true, const bool sanity_check=true) {
|
||||
static void move_z_after_probing() {
|
||||
#ifdef Z_AFTER_PROBING
|
||||
do_z_clearance(Z_AFTER_PROBING, true); // Move down still permitted
|
||||
#endif
|
||||
}
|
||||
static float probe_at_point(const_float_t rx, const_float_t ry, const ProbePtRaise raise_after=PROBE_PT_NONE, const uint8_t verbose_level=0, const bool probe_relative=true, const bool sanity_check=true);
|
||||
static float probe_at_point(const xy_pos_t &pos, const ProbePtRaise raise_after=PROBE_PT_NONE, const uint8_t verbose_level=0, const bool probe_relative=true, const bool sanity_check=true) {
|
||||
return probe_at_point(pos.x, pos.y, raise_after, verbose_level, probe_relative, sanity_check);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static constexpr xyz_pos_t offset = xyz_pos_t({ 0, 0, 0 }); // See #16767
|
||||
static constexpr xyz_pos_t offset = xyz_pos_t(LINEAR_AXIS_ARRAY(0, 0, 0, 0, 0, 0)); // See #16767
|
||||
|
||||
static bool set_deployed(const bool) { return false; }
|
||||
|
||||
FORCE_INLINE static bool can_reach(const float &rx, const float &ry) { return position_is_reachable(rx, ry); }
|
||||
static bool can_reach(const_float_t rx, const_float_t ry) { return position_is_reachable(rx, ry); }
|
||||
|
||||
#endif
|
||||
|
||||
FORCE_INLINE static bool can_reach(const xy_pos_t &pos) { return can_reach(pos.x, pos.y); }
|
||||
static void move_z_after_homing() {
|
||||
#ifdef Z_AFTER_HOMING
|
||||
do_z_clearance(Z_AFTER_HOMING, true);
|
||||
#elif BOTH(Z_AFTER_PROBING, HAS_BED_PROBE)
|
||||
move_z_after_probing();
|
||||
#endif
|
||||
}
|
||||
|
||||
FORCE_INLINE static bool good_bounds(const xy_pos_t &lf, const xy_pos_t &rb) {
|
||||
static bool can_reach(const xy_pos_t &pos) { return can_reach(pos.x, pos.y); }
|
||||
|
||||
static bool good_bounds(const xy_pos_t &lf, const xy_pos_t &rb) {
|
||||
return (
|
||||
#if IS_KINEMATIC
|
||||
can_reach(lf.x, 0) && can_reach(rb.x, 0) && can_reach(0, lf.y) && can_reach(0, rb.y)
|
||||
can_reach(lf.x, 0) && can_reach(rb.x, 0) && can_reach(0, lf.y) && can_reach(0, rb.y)
|
||||
#else
|
||||
can_reach(lf) && can_reach(rb)
|
||||
can_reach(lf) && can_reach(rb)
|
||||
#endif
|
||||
);
|
||||
}
|
||||
@@ -113,85 +147,101 @@ public:
|
||||
// Use offset_xy for read only access
|
||||
// More optimal the XY offset is known to always be zero.
|
||||
#if HAS_PROBE_XY_OFFSET
|
||||
static const xyz_pos_t &offset_xy;
|
||||
static const xy_pos_t &offset_xy;
|
||||
#else
|
||||
static constexpr xy_pos_t offset_xy = xy_pos_t({ 0, 0 }); // See #16767
|
||||
#endif
|
||||
|
||||
static inline bool deploy() { return set_deployed(true); }
|
||||
static inline bool stow() { return set_deployed(false); }
|
||||
static bool deploy() { return set_deployed(true); }
|
||||
static bool stow() { return set_deployed(false); }
|
||||
|
||||
#if HAS_BED_PROBE || HAS_LEVELING
|
||||
#if IS_KINEMATIC
|
||||
static constexpr float printable_radius = (
|
||||
#if ENABLED(DELTA)
|
||||
DELTA_PRINTABLE_RADIUS
|
||||
#elif IS_SCARA
|
||||
SCARA_PRINTABLE_RADIUS
|
||||
#endif
|
||||
TERN_(DELTA, DELTA_PRINTABLE_RADIUS)
|
||||
TERN_(IS_SCARA, SCARA_PRINTABLE_RADIUS)
|
||||
);
|
||||
|
||||
static inline float probe_radius() {
|
||||
return printable_radius - _MAX(MIN_PROBE_EDGE, HYPOT(offset_xy.x, offset_xy.y));
|
||||
static constexpr float probe_radius(const xy_pos_t &probe_offset_xy = offset_xy) {
|
||||
return printable_radius - _MAX(PROBING_MARGIN, HYPOT(probe_offset_xy.x, probe_offset_xy.y));
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline float min_x() {
|
||||
return (
|
||||
#if IS_KINEMATIC
|
||||
(X_CENTER) - probe_radius()
|
||||
#else
|
||||
_MAX((X_MIN_BED) + (MIN_PROBE_EDGE_LEFT), (X_MIN_POS) + offset_xy.x)
|
||||
#endif
|
||||
static constexpr float _min_x(const xy_pos_t &probe_offset_xy = offset_xy) {
|
||||
return TERN(IS_KINEMATIC,
|
||||
(X_CENTER) - probe_radius(probe_offset_xy),
|
||||
_MAX((X_MIN_BED) + (PROBING_MARGIN_LEFT), (X_MIN_POS) + probe_offset_xy.x)
|
||||
);
|
||||
}
|
||||
static inline float max_x() {
|
||||
return (
|
||||
#if IS_KINEMATIC
|
||||
(X_CENTER) + probe_radius()
|
||||
#else
|
||||
_MIN((X_MAX_BED) - (MIN_PROBE_EDGE_RIGHT), (X_MAX_POS) + offset_xy.x)
|
||||
#endif
|
||||
static constexpr float _max_x(const xy_pos_t &probe_offset_xy = offset_xy) {
|
||||
return TERN(IS_KINEMATIC,
|
||||
(X_CENTER) + probe_radius(probe_offset_xy),
|
||||
_MIN((X_MAX_BED) - (PROBING_MARGIN_RIGHT), (X_MAX_POS) + probe_offset_xy.x)
|
||||
);
|
||||
}
|
||||
static inline float min_y() {
|
||||
return (
|
||||
#if IS_KINEMATIC
|
||||
(Y_CENTER) - probe_radius()
|
||||
#else
|
||||
_MAX((Y_MIN_BED) + (MIN_PROBE_EDGE_FRONT), (Y_MIN_POS) + offset_xy.y)
|
||||
#endif
|
||||
static constexpr float _min_y(const xy_pos_t &probe_offset_xy = offset_xy) {
|
||||
return TERN(IS_KINEMATIC,
|
||||
(Y_CENTER) - probe_radius(probe_offset_xy),
|
||||
_MAX((Y_MIN_BED) + (PROBING_MARGIN_FRONT), (Y_MIN_POS) + probe_offset_xy.y)
|
||||
);
|
||||
}
|
||||
static inline float max_y() {
|
||||
return (
|
||||
#if IS_KINEMATIC
|
||||
(Y_CENTER) + probe_radius()
|
||||
#else
|
||||
_MIN((Y_MAX_BED) - (MIN_PROBE_EDGE_BACK), (Y_MAX_POS) + offset_xy.y)
|
||||
#endif
|
||||
static constexpr float _max_y(const xy_pos_t &probe_offset_xy = offset_xy) {
|
||||
return TERN(IS_KINEMATIC,
|
||||
(Y_CENTER) + probe_radius(probe_offset_xy),
|
||||
_MIN((Y_MAX_BED) - (PROBING_MARGIN_BACK), (Y_MAX_POS) + probe_offset_xy.y)
|
||||
);
|
||||
}
|
||||
|
||||
static float min_x() { return _min_x() TERN_(NOZZLE_AS_PROBE, TERN_(HAS_HOME_OFFSET, - home_offset.x)); }
|
||||
static float max_x() { return _max_x() TERN_(NOZZLE_AS_PROBE, TERN_(HAS_HOME_OFFSET, - home_offset.x)); }
|
||||
static float min_y() { return _min_y() TERN_(NOZZLE_AS_PROBE, TERN_(HAS_HOME_OFFSET, - home_offset.y)); }
|
||||
static float max_y() { return _max_y() TERN_(NOZZLE_AS_PROBE, TERN_(HAS_HOME_OFFSET, - home_offset.y)); }
|
||||
|
||||
// constexpr helpers used in build-time static_asserts, relying on default probe offsets.
|
||||
class build_time {
|
||||
static constexpr xyz_pos_t default_probe_xyz_offset =
|
||||
#if HAS_BED_PROBE
|
||||
NOZZLE_TO_PROBE_OFFSET
|
||||
#else
|
||||
{ 0 }
|
||||
#endif
|
||||
;
|
||||
static constexpr xy_pos_t default_probe_xy_offset = { default_probe_xyz_offset.x, default_probe_xyz_offset.y };
|
||||
|
||||
public:
|
||||
static constexpr bool can_reach(float x, float y) {
|
||||
#if IS_KINEMATIC
|
||||
return HYPOT2(x, y) <= sq(probe_radius(default_probe_xy_offset));
|
||||
#else
|
||||
return COORDINATE_OKAY(x, _min_x(default_probe_xy_offset) - fslop, _max_x(default_probe_xy_offset) + fslop)
|
||||
&& COORDINATE_OKAY(y, _min_y(default_probe_xy_offset) - fslop, _max_y(default_probe_xy_offset) + fslop);
|
||||
#endif
|
||||
}
|
||||
|
||||
static constexpr bool can_reach(const xy_pos_t &point) { return can_reach(point.x, point.y); }
|
||||
};
|
||||
|
||||
#if NEEDS_THREE_PROBE_POINTS
|
||||
// Retrieve three points to probe the bed. Any type exposing set(X,Y) may be used.
|
||||
template <typename T>
|
||||
static inline void get_three_points(T points[3]) {
|
||||
static void get_three_points(T points[3]) {
|
||||
#if HAS_FIXED_3POINT
|
||||
points[0].set(PROBE_PT_1_X, PROBE_PT_1_Y);
|
||||
points[1].set(PROBE_PT_2_X, PROBE_PT_2_Y);
|
||||
points[2].set(PROBE_PT_3_X, PROBE_PT_3_Y);
|
||||
#define VALIDATE_PROBE_PT(N) static_assert(Probe::build_time::can_reach(xy_pos_t{PROBE_PT_##N##_X, PROBE_PT_##N##_Y}), \
|
||||
"PROBE_PT_" STRINGIFY(N) "_(X|Y) is unreachable using default NOZZLE_TO_PROBE_OFFSET and PROBING_MARGIN");
|
||||
VALIDATE_PROBE_PT(1); VALIDATE_PROBE_PT(2); VALIDATE_PROBE_PT(3);
|
||||
points[0] = xy_float_t({ PROBE_PT_1_X, PROBE_PT_1_Y });
|
||||
points[1] = xy_float_t({ PROBE_PT_2_X, PROBE_PT_2_Y });
|
||||
points[2] = xy_float_t({ PROBE_PT_3_X, PROBE_PT_3_Y });
|
||||
#else
|
||||
#if IS_KINEMATIC
|
||||
constexpr float SIN0 = 0.0, SIN120 = 0.866025, SIN240 = -0.866025,
|
||||
COS0 = 1.0, COS120 = -0.5 , COS240 = -0.5;
|
||||
points[0].set((X_CENTER) + probe_radius() * COS0, (Y_CENTER) + probe_radius() * SIN0);
|
||||
points[1].set((X_CENTER) + probe_radius() * COS120, (Y_CENTER) + probe_radius() * SIN120);
|
||||
points[2].set((X_CENTER) + probe_radius() * COS240, (Y_CENTER) + probe_radius() * SIN240);
|
||||
points[0] = xy_float_t({ (X_CENTER) + probe_radius() * COS0, (Y_CENTER) + probe_radius() * SIN0 });
|
||||
points[1] = xy_float_t({ (X_CENTER) + probe_radius() * COS120, (Y_CENTER) + probe_radius() * SIN120 });
|
||||
points[2] = xy_float_t({ (X_CENTER) + probe_radius() * COS240, (Y_CENTER) + probe_radius() * SIN240 });
|
||||
#else
|
||||
points[0].set(min_x(), min_y());
|
||||
points[1].set(max_x(), min_y());
|
||||
points[2].set((max_x() - min_x()) / 2, max_y());
|
||||
points[0] = xy_float_t({ min_x(), min_y() });
|
||||
points[1] = xy_float_t({ max_x(), min_y() });
|
||||
points[2] = xy_float_t({ (min_x() + max_x()) / 2, max_y() });
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
@@ -203,12 +253,24 @@ public:
|
||||
static void servo_probe_init();
|
||||
#endif
|
||||
|
||||
#if QUIET_PROBING
|
||||
#if HAS_QUIET_PROBING
|
||||
static void set_probing_paused(const bool p);
|
||||
#endif
|
||||
|
||||
#if ENABLED(PROBE_TARE)
|
||||
static void tare_init();
|
||||
static bool tare();
|
||||
#endif
|
||||
|
||||
// Basic functions for Sensorless Homing and Probing
|
||||
#if USE_SENSORLESS
|
||||
static void enable_stallguard_diag1();
|
||||
static void disable_stallguard_diag1();
|
||||
static void set_homing_current(const bool onoff);
|
||||
#endif
|
||||
|
||||
private:
|
||||
static bool probe_down_to_z(const float z, const feedRate_t fr_mm_s);
|
||||
static bool probe_down_to_z(const_float_t z, const_feedRate_t fr_mm_s);
|
||||
static void do_z_raise(const float z_raise);
|
||||
static float run_z_probe(const bool sanity_check=true);
|
||||
};
|
||||
|
285
Marlin/src/module/scara.cpp
Executable file → Normal file
285
Marlin/src/module/scara.cpp
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -32,79 +32,74 @@
|
||||
#include "motion.h"
|
||||
#include "planner.h"
|
||||
|
||||
float delta_segments_per_second = SCARA_SEGMENTS_PER_SECOND;
|
||||
#if ENABLED(AXEL_TPARA)
|
||||
#include "endstops.h"
|
||||
#include "../MarlinCore.h"
|
||||
#endif
|
||||
|
||||
void scara_set_axis_is_at_home(const AxisEnum axis) {
|
||||
if (axis == Z_AXIS)
|
||||
current_position.z = Z_HOME_POS;
|
||||
else {
|
||||
float segments_per_second = TERN(AXEL_TPARA, TPARA_SEGMENTS_PER_SECOND, SCARA_SEGMENTS_PER_SECOND);
|
||||
|
||||
/**
|
||||
* SCARA homes XY at the same time
|
||||
*/
|
||||
xyz_pos_t homeposition;
|
||||
LOOP_XYZ(i) homeposition[i] = base_home_pos((AxisEnum)i);
|
||||
#if EITHER(MORGAN_SCARA, MP_SCARA)
|
||||
|
||||
#if ENABLED(MORGAN_SCARA)
|
||||
// MORGAN_SCARA uses arm angles for AB home position
|
||||
// SERIAL_ECHOLNPAIR("homeposition A:", homeposition.a, " B:", homeposition.b);
|
||||
inverse_kinematics(homeposition);
|
||||
forward_kinematics_SCARA(delta.a, delta.b);
|
||||
current_position[axis] = cartes[axis];
|
||||
#else
|
||||
// MP_SCARA uses a Cartesian XY home position
|
||||
// SERIAL_ECHOPGM("homeposition");
|
||||
// SERIAL_ECHOLNPAIR_P(SP_X_LBL, homeposition.x, SP_Y_LBL, homeposition.y);
|
||||
current_position[axis] = homeposition[axis];
|
||||
#endif
|
||||
static constexpr xy_pos_t scara_offset = { SCARA_OFFSET_X, SCARA_OFFSET_Y };
|
||||
|
||||
// SERIAL_ECHOPGM("Cartesian");
|
||||
// SERIAL_ECHOLNPAIR_P(SP_X_LBL, current_position.x, SP_Y_LBL, current_position.y);
|
||||
update_software_endstops(axis);
|
||||
/**
|
||||
* Morgan SCARA Forward Kinematics. Results in 'cartes'.
|
||||
* Maths and first version by QHARLEY.
|
||||
* Integrated into Marlin and slightly restructured by Joachim Cerny.
|
||||
*/
|
||||
void forward_kinematics(const_float_t a, const_float_t b) {
|
||||
const float a_sin = sin(RADIANS(a)) * L1,
|
||||
a_cos = cos(RADIANS(a)) * L1,
|
||||
b_sin = sin(RADIANS(SUM_TERN(MP_SCARA, b, a))) * L2,
|
||||
b_cos = cos(RADIANS(SUM_TERN(MP_SCARA, b, a))) * L2;
|
||||
|
||||
cartes.x = a_cos + b_cos + scara_offset.x; // theta
|
||||
cartes.y = a_sin + b_sin + scara_offset.y; // phi
|
||||
|
||||
/*
|
||||
DEBUG_ECHOLNPGM(
|
||||
"SCARA FK Angle a=", a,
|
||||
" b=", b,
|
||||
" a_sin=", a_sin,
|
||||
" a_cos=", a_cos,
|
||||
" b_sin=", b_sin,
|
||||
" b_cos=", b_cos
|
||||
);
|
||||
DEBUG_ECHOLNPGM(" cartes (X,Y) = "(cartes.x, ", ", cartes.y, ")");
|
||||
//*/
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr xy_pos_t scara_offset = { SCARA_OFFSET_X, SCARA_OFFSET_Y };
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Morgan SCARA Forward Kinematics. Results in 'cartes'.
|
||||
* Maths and first version by QHARLEY.
|
||||
* Integrated into Marlin and slightly restructured by Joachim Cerny.
|
||||
*/
|
||||
void forward_kinematics_SCARA(const float &a, const float &b) {
|
||||
#if ENABLED(MORGAN_SCARA)
|
||||
|
||||
const float a_sin = sin(RADIANS(a)) * L1,
|
||||
a_cos = cos(RADIANS(a)) * L1,
|
||||
b_sin = sin(RADIANS(b)) * L2,
|
||||
b_cos = cos(RADIANS(b)) * L2;
|
||||
void scara_set_axis_is_at_home(const AxisEnum axis) {
|
||||
if (axis == Z_AXIS)
|
||||
current_position.z = Z_HOME_POS;
|
||||
else {
|
||||
// MORGAN_SCARA uses a Cartesian XY home position
|
||||
xyz_pos_t homeposition = { X_HOME_POS, Y_HOME_POS, Z_HOME_POS };
|
||||
//DEBUG_ECHOLNPGM_P(PSTR("homeposition X"), homeposition.x, SP_Y_LBL, homeposition.y);
|
||||
|
||||
cartes.set(a_cos + b_cos + scara_offset.x, // theta
|
||||
a_sin + b_sin + scara_offset.y); // theta+phi
|
||||
delta = homeposition;
|
||||
forward_kinematics(delta.a, delta.b);
|
||||
current_position[axis] = cartes[axis];
|
||||
|
||||
/*
|
||||
SERIAL_ECHOLNPAIR(
|
||||
"SCARA FK Angle a=", a,
|
||||
" b=", b,
|
||||
" a_sin=", a_sin,
|
||||
" a_cos=", a_cos,
|
||||
" b_sin=", b_sin,
|
||||
" b_cos=", b_cos
|
||||
);
|
||||
SERIAL_ECHOLNPAIR(" cartes (X,Y) = "(cartes.x, ", ", cartes.y, ")");
|
||||
//*/
|
||||
}
|
||||
//DEBUG_ECHOLNPGM_P(PSTR("Cartesian X"), current_position.x, SP_Y_LBL, current_position.y);
|
||||
update_software_endstops(axis);
|
||||
}
|
||||
}
|
||||
|
||||
void inverse_kinematics(const xyz_pos_t &raw) {
|
||||
|
||||
#if ENABLED(MORGAN_SCARA)
|
||||
/**
|
||||
* Morgan SCARA Inverse Kinematics. Results in 'delta'.
|
||||
*
|
||||
* See http://forums.reprap.org/read.php?185,283327
|
||||
*
|
||||
* Maths and first version by QHARLEY.
|
||||
* Integrated into Marlin and slightly restructured by Joachim Cerny.
|
||||
*/
|
||||
/**
|
||||
* Morgan SCARA Inverse Kinematics. Results are stored in 'delta'.
|
||||
*
|
||||
* See https://reprap.org/forum/read.php?185,283327
|
||||
*
|
||||
* Maths and first version by QHARLEY.
|
||||
* Integrated into Marlin and slightly restructured by Joachim Cerny.
|
||||
*/
|
||||
void inverse_kinematics(const xyz_pos_t &raw) {
|
||||
float C2, S2, SK1, SK2, THETA, PSI;
|
||||
|
||||
// Translate SCARA to standard XY with scaling factor
|
||||
@@ -116,6 +111,8 @@ void inverse_kinematics(const xyz_pos_t &raw) {
|
||||
else
|
||||
C2 = (H2 - (L1_2 + L2_2)) / (2.0f * L1 * L2);
|
||||
|
||||
LIMIT(C2, -1, 1);
|
||||
|
||||
S2 = SQRT(1.0f - sq(C2));
|
||||
|
||||
// Unrotated Arm1 plus rotated Arm2 gives the distance from Center to End
|
||||
@@ -130,16 +127,41 @@ void inverse_kinematics(const xyz_pos_t &raw) {
|
||||
// Angle of Arm2
|
||||
PSI = ATAN2(S2, C2);
|
||||
|
||||
delta.set(DEGREES(THETA), DEGREES(THETA + PSI), raw.z);
|
||||
delta.set(DEGREES(THETA), DEGREES(SUM_TERN(MORGAN_SCARA, PSI, THETA)), raw.z);
|
||||
|
||||
/*
|
||||
DEBUG_POS("SCARA IK", raw);
|
||||
DEBUG_POS("SCARA IK", delta);
|
||||
SERIAL_ECHOLNPAIR(" SCARA (x,y) ", sx, ",", sy, " C2=", C2, " S2=", S2, " Theta=", THETA, " Phi=", PHI);
|
||||
DEBUG_ECHOLNPGM(" SCARA (x,y) ", sx, ",", sy, " C2=", C2, " S2=", S2, " Theta=", THETA, " Psi=", PSI);
|
||||
//*/
|
||||
}
|
||||
|
||||
#else // MP_SCARA
|
||||
#elif ENABLED(MP_SCARA)
|
||||
|
||||
void scara_set_axis_is_at_home(const AxisEnum axis) {
|
||||
if (axis == Z_AXIS)
|
||||
current_position.z = Z_HOME_POS;
|
||||
else {
|
||||
// MP_SCARA uses arm angles for AB home position
|
||||
#ifndef SCARA_OFFSET_THETA1
|
||||
#define SCARA_OFFSET_THETA1 12 // degrees
|
||||
#endif
|
||||
#ifndef SCARA_OFFSET_THETA2
|
||||
#define SCARA_OFFSET_THETA2 131 // degrees
|
||||
#endif
|
||||
ab_float_t homeposition = { SCARA_OFFSET_THETA1, SCARA_OFFSET_THETA2 };
|
||||
//DEBUG_ECHOLNPGM("homeposition A:", homeposition.a, " B:", homeposition.b);
|
||||
|
||||
inverse_kinematics(homeposition);
|
||||
forward_kinematics(delta.a, delta.b);
|
||||
current_position[axis] = cartes[axis];
|
||||
|
||||
//DEBUG_ECHOLNPGM_P(PSTR("Cartesian X"), current_position.x, SP_Y_LBL, current_position.y);
|
||||
update_software_endstops(axis);
|
||||
}
|
||||
}
|
||||
|
||||
void inverse_kinematics(const xyz_pos_t &raw) {
|
||||
const float x = raw.x, y = raw.y, c = HYPOT(x, y),
|
||||
THETA3 = ATAN2(y, x),
|
||||
THETA1 = THETA3 + ACOS((sq(c) + sq(L1) - sq(L2)) / (2.0f * c * L1)),
|
||||
@@ -150,14 +172,137 @@ void inverse_kinematics(const xyz_pos_t &raw) {
|
||||
/*
|
||||
DEBUG_POS("SCARA IK", raw);
|
||||
DEBUG_POS("SCARA IK", delta);
|
||||
SERIAL_ECHOLNPAIR(" SCARA (x,y) ", x, ",", y," Theta1=", THETA1, " Theta2=", THETA2);
|
||||
SERIAL_ECHOLNPGM(" SCARA (x,y) ", x, ",", y," Theta1=", THETA1, " Theta2=", THETA2);
|
||||
//*/
|
||||
}
|
||||
|
||||
#endif // MP_SCARA
|
||||
}
|
||||
#elif ENABLED(AXEL_TPARA)
|
||||
|
||||
static constexpr xyz_pos_t robot_offset = { TPARA_OFFSET_X, TPARA_OFFSET_Y, TPARA_OFFSET_Z };
|
||||
|
||||
void scara_set_axis_is_at_home(const AxisEnum axis) {
|
||||
if (axis == Z_AXIS)
|
||||
current_position.z = Z_HOME_POS;
|
||||
else {
|
||||
xyz_pos_t homeposition = { X_HOME_POS, Y_HOME_POS, Z_HOME_POS };
|
||||
//DEBUG_ECHOLNPGM_P(PSTR("homeposition X"), homeposition.x, SP_Y_LBL, homeposition.y, SP_Z_LBL, homeposition.z);
|
||||
|
||||
inverse_kinematics(homeposition);
|
||||
forward_kinematics(delta.a, delta.b, delta.c);
|
||||
current_position[axis] = cartes[axis];
|
||||
|
||||
//DEBUG_ECHOLNPGM_P(PSTR("Cartesian X"), current_position.x, SP_Y_LBL, current_position.y);
|
||||
update_software_endstops(axis);
|
||||
}
|
||||
}
|
||||
|
||||
// Convert ABC inputs in degrees to XYZ outputs in mm
|
||||
void forward_kinematics(const_float_t a, const_float_t b, const_float_t c) {
|
||||
const float w = c - b,
|
||||
r = L1 * cos(RADIANS(b)) + L2 * sin(RADIANS(w - (90 - b))),
|
||||
x = r * cos(RADIANS(a)),
|
||||
y = r * sin(RADIANS(a)),
|
||||
rho2 = L1_2 + L2_2 - 2.0f * L1 * L2 * cos(RADIANS(w));
|
||||
|
||||
cartes = robot_offset + xyz_pos_t({ x, y, SQRT(rho2 - sq(x) - sq(y)) });
|
||||
}
|
||||
|
||||
// Home YZ together, then X (or all at once). Based on quick_home_xy & home_delta
|
||||
void home_TPARA() {
|
||||
// Init the current position of all carriages to 0,0,0
|
||||
current_position.reset();
|
||||
destination.reset();
|
||||
sync_plan_position();
|
||||
|
||||
// Disable stealthChop if used. Enable diag1 pin on driver.
|
||||
#if ENABLED(SENSORLESS_HOMING)
|
||||
TERN_(X_SENSORLESS, sensorless_t stealth_states_x = start_sensorless_homing_per_axis(X_AXIS));
|
||||
TERN_(Y_SENSORLESS, sensorless_t stealth_states_y = start_sensorless_homing_per_axis(Y_AXIS));
|
||||
TERN_(Z_SENSORLESS, sensorless_t stealth_states_z = start_sensorless_homing_per_axis(Z_AXIS));
|
||||
#endif
|
||||
|
||||
//const int x_axis_home_dir = TOOL_X_HOME_DIR(active_extruder);
|
||||
|
||||
//const xy_pos_t pos { max_length(X_AXIS) , max_length(Y_AXIS) };
|
||||
//const float mlz = max_length(X_AXIS),
|
||||
|
||||
// Move all carriages together linearly until an endstop is hit.
|
||||
//do_blocking_move_to_xy_z(pos, mlz, homing_feedrate(Z_AXIS));
|
||||
|
||||
current_position.x = 0 ;
|
||||
current_position.y = 0 ;
|
||||
current_position.z = max_length(Z_AXIS) ;
|
||||
line_to_current_position(homing_feedrate(Z_AXIS));
|
||||
planner.synchronize();
|
||||
|
||||
// Re-enable stealthChop if used. Disable diag1 pin on driver.
|
||||
#if ENABLED(SENSORLESS_HOMING)
|
||||
TERN_(X_SENSORLESS, end_sensorless_homing_per_axis(X_AXIS, stealth_states_x));
|
||||
TERN_(Y_SENSORLESS, end_sensorless_homing_per_axis(Y_AXIS, stealth_states_y));
|
||||
TERN_(Z_SENSORLESS, end_sensorless_homing_per_axis(Z_AXIS, stealth_states_z));
|
||||
#endif
|
||||
|
||||
endstops.validate_homing_move();
|
||||
|
||||
// At least one motor has reached its endstop.
|
||||
// Now re-home each motor separately.
|
||||
homeaxis(A_AXIS);
|
||||
homeaxis(C_AXIS);
|
||||
homeaxis(B_AXIS);
|
||||
|
||||
// Set all carriages to their home positions
|
||||
// Do this here all at once for Delta, because
|
||||
// XYZ isn't ABC. Applying this per-tower would
|
||||
// give the impression that they are the same.
|
||||
LOOP_LINEAR_AXES(i) set_axis_is_at_home((AxisEnum)i);
|
||||
|
||||
sync_plan_position();
|
||||
}
|
||||
|
||||
void inverse_kinematics(const xyz_pos_t &raw) {
|
||||
const xyz_pos_t spos = raw - robot_offset;
|
||||
|
||||
const float RXY = SQRT(HYPOT2(spos.x, spos.y)),
|
||||
RHO2 = NORMSQ(spos.x, spos.y, spos.z),
|
||||
//RHO = SQRT(RHO2),
|
||||
LSS = L1_2 + L2_2,
|
||||
LM = 2.0f * L1 * L2,
|
||||
|
||||
CG = (LSS - RHO2) / LM,
|
||||
SG = SQRT(1 - POW(CG, 2)), // Method 2
|
||||
K1 = L1 - L2 * CG,
|
||||
K2 = L2 * SG,
|
||||
|
||||
// Angle of Body Joint
|
||||
THETA = ATAN2(spos.y, spos.x),
|
||||
|
||||
// Angle of Elbow Joint
|
||||
//GAMMA = ACOS(CG),
|
||||
GAMMA = ATAN2(SG, CG), // Method 2
|
||||
|
||||
// Angle of Shoulder Joint, elevation angle measured from horizontal (r+)
|
||||
//PHI = asin(spos.z/RHO) + asin(L2 * sin(GAMMA) / RHO),
|
||||
PHI = ATAN2(spos.z, RXY) + ATAN2(K2, K1), // Method 2
|
||||
|
||||
// Elbow motor angle measured from horizontal, same frame as shoulder (r+)
|
||||
PSI = PHI + GAMMA;
|
||||
|
||||
delta.set(DEGREES(THETA), DEGREES(PHI), DEGREES(PSI));
|
||||
|
||||
//SERIAL_ECHOLNPGM(" SCARA (x,y,z) ", spos.x , ",", spos.y, ",", spos.z, " Rho=", RHO, " Rho2=", RHO2, " Theta=", THETA, " Phi=", PHI, " Psi=", PSI, " Gamma=", GAMMA);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void scara_report_positions() {
|
||||
SERIAL_ECHOLNPAIR("SCARA Theta:", planner.get_axis_position_degrees(A_AXIS), " Psi+Theta:", planner.get_axis_position_degrees(B_AXIS));
|
||||
SERIAL_ECHOLNPGM("SCARA Theta:", planner.get_axis_position_degrees(A_AXIS)
|
||||
#if ENABLED(AXEL_TPARA)
|
||||
, " Phi:", planner.get_axis_position_degrees(B_AXIS)
|
||||
, " Psi:", planner.get_axis_position_degrees(C_AXIS)
|
||||
#else
|
||||
, " Psi" TERN_(MORGAN_SCARA, "+Theta") ":", planner.get_axis_position_degrees(B_AXIS)
|
||||
#endif
|
||||
);
|
||||
SERIAL_EOL();
|
||||
}
|
||||
|
||||
|
29
Marlin/src/module/scara.h
Executable file → Normal file
29
Marlin/src/module/scara.h
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@@ -27,16 +27,27 @@
|
||||
|
||||
#include "../core/macros.h"
|
||||
|
||||
extern float delta_segments_per_second;
|
||||
extern float segments_per_second;
|
||||
|
||||
// Float constants for SCARA calculations
|
||||
float constexpr L1 = SCARA_LINKAGE_1, L2 = SCARA_LINKAGE_2,
|
||||
L1_2 = sq(float(L1)), L1_2_2 = 2.0 * L1_2,
|
||||
L2_2 = sq(float(L2));
|
||||
#if ENABLED(AXEL_TPARA)
|
||||
|
||||
void scara_set_axis_is_at_home(const AxisEnum axis);
|
||||
float constexpr L1 = TPARA_LINKAGE_1, L2 = TPARA_LINKAGE_2, // Float constants for Robot arm calculations
|
||||
L1_2 = sq(float(L1)), L1_2_2 = 2.0 * L1_2,
|
||||
L2_2 = sq(float(L2));
|
||||
|
||||
void forward_kinematics(const_float_t a, const_float_t b, const_float_t c);
|
||||
void home_TPARA();
|
||||
|
||||
#else
|
||||
|
||||
float constexpr L1 = SCARA_LINKAGE_1, L2 = SCARA_LINKAGE_2, // Float constants for SCARA calculations
|
||||
L1_2 = sq(float(L1)), L1_2_2 = 2.0 * L1_2,
|
||||
L2_2 = sq(float(L2));
|
||||
|
||||
void forward_kinematics(const_float_t a, const_float_t b);
|
||||
|
||||
#endif
|
||||
|
||||
void inverse_kinematics(const xyz_pos_t &raw);
|
||||
void forward_kinematics_SCARA(const float &a, const float &b);
|
||||
|
||||
void scara_set_axis_is_at_home(const AxisEnum axis);
|
||||
void scara_report_positions();
|
||||
|
10
Marlin/src/module/servo.cpp
Executable file → Normal file
10
Marlin/src/module/servo.cpp
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -39,19 +39,19 @@ HAL_SERVO_LIB servo[NUM_SERVOS];
|
||||
void servo_init() {
|
||||
#if NUM_SERVOS >= 1 && HAS_SERVO_0
|
||||
servo[0].attach(SERVO0_PIN);
|
||||
servo[0].detach(); // Just set up the pin. We don't have a position yet. Don't move to a random position.
|
||||
DETACH_SERVO(0); // Just set up the pin. We don't have a position yet. Don't move to a random position.
|
||||
#endif
|
||||
#if NUM_SERVOS >= 2 && HAS_SERVO_1
|
||||
servo[1].attach(SERVO1_PIN);
|
||||
servo[1].detach();
|
||||
DETACH_SERVO(1);
|
||||
#endif
|
||||
#if NUM_SERVOS >= 3 && HAS_SERVO_2
|
||||
servo[2].attach(SERVO2_PIN);
|
||||
servo[2].detach();
|
||||
DETACH_SERVO(2);
|
||||
#endif
|
||||
#if NUM_SERVOS >= 4 && HAS_SERVO_3
|
||||
servo[3].attach(SERVO3_PIN);
|
||||
servo[3].detach();
|
||||
DETACH_SERVO(3);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
5
Marlin/src/module/servo.h
Executable file → Normal file
5
Marlin/src/module/servo.h
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@@ -110,6 +110,7 @@
|
||||
#endif // HAS_SERVO_ANGLES
|
||||
|
||||
#define MOVE_SERVO(I, P) servo[I].move(P)
|
||||
#define DETACH_SERVO(I) servo[I].detach()
|
||||
|
||||
extern HAL_SERVO_LIB servo[NUM_SERVOS];
|
||||
extern void servo_init();
|
||||
void servo_init();
|
||||
|
3351
Marlin/src/module/settings.cpp
Normal file
3351
Marlin/src/module/settings.cpp
Normal file
File diff suppressed because it is too large
Load Diff
67
Marlin/src/module/configuration_store.h → Marlin/src/module/settings.h
Executable file → Normal file
67
Marlin/src/module/configuration_store.h → Marlin/src/module/settings.h
Executable file → Normal file
@@ -16,25 +16,30 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
//
|
||||
// settings.cpp - Settings and EEPROM storage
|
||||
//
|
||||
|
||||
#include "../inc/MarlinConfig.h"
|
||||
|
||||
#if ENABLED(EEPROM_SETTINGS)
|
||||
#include "../HAL/shared/eeprom_api.h"
|
||||
#endif
|
||||
|
||||
// PATCH START: Knutwurst
|
||||
#ifdef POWER_OUTAGE_TEST
|
||||
|
||||
static bool RestartFlag = false;
|
||||
void OutageSave();
|
||||
void OutageRead();
|
||||
extern float last_position[4];
|
||||
extern long last_sd_position[1];
|
||||
static bool RestartFlag = false;
|
||||
void OutageSave();
|
||||
void OutageRead();
|
||||
extern float last_position[4];
|
||||
extern long last_sd_position[1];
|
||||
#endif
|
||||
// PATCH END: Knutwurst
|
||||
|
||||
class MarlinSettings {
|
||||
public:
|
||||
@@ -47,9 +52,7 @@ class MarlinSettings {
|
||||
reset();
|
||||
#if ENABLED(EEPROM_SETTINGS)
|
||||
const bool success = save();
|
||||
#if ENABLED(EEPROM_CHITCHAT)
|
||||
if (success) report();
|
||||
#endif
|
||||
if (TERN0(EEPROM_CHITCHAT, success)) report();
|
||||
return success;
|
||||
#else
|
||||
return true;
|
||||
@@ -83,12 +86,15 @@ class MarlinSettings {
|
||||
//static void delete_mesh(); // necessary if we have a MAT
|
||||
//static void defrag_meshes(); // "
|
||||
#endif
|
||||
#else
|
||||
|
||||
#else // !EEPROM_SETTINGS
|
||||
|
||||
FORCE_INLINE
|
||||
static bool load() { reset(); report(); return true; }
|
||||
FORCE_INLINE
|
||||
static void first_load() { (void)load(); }
|
||||
#endif
|
||||
|
||||
#endif // !EEPROM_SETTINGS
|
||||
|
||||
#if DISABLED(DISABLE_M503)
|
||||
static void report(const bool forReplay=false);
|
||||
@@ -112,7 +118,42 @@ class MarlinSettings {
|
||||
|
||||
static bool _load();
|
||||
static bool size_error(const uint16_t size);
|
||||
#endif
|
||||
|
||||
static int eeprom_index;
|
||||
static uint16_t working_crc;
|
||||
|
||||
static bool EEPROM_START(int eeprom_offset) {
|
||||
if (!persistentStore.access_start()) { SERIAL_ECHO_MSG("No EEPROM."); return false; }
|
||||
eeprom_index = eeprom_offset;
|
||||
working_crc = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void EEPROM_FINISH(void) { persistentStore.access_finish(); }
|
||||
|
||||
template<typename T>
|
||||
static void EEPROM_SKIP(const T &VAR) { eeprom_index += sizeof(VAR); }
|
||||
|
||||
template<typename T>
|
||||
static void EEPROM_WRITE(const T &VAR) {
|
||||
persistentStore.write_data(eeprom_index, (const uint8_t *) &VAR, sizeof(VAR), &working_crc);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void EEPROM_READ(T &VAR) {
|
||||
persistentStore.read_data(eeprom_index, (uint8_t *) &VAR, sizeof(VAR), &working_crc, !validating);
|
||||
}
|
||||
|
||||
static void EEPROM_READ(uint8_t *VAR, size_t sizeof_VAR) {
|
||||
persistentStore.read_data(eeprom_index, VAR, sizeof_VAR, &working_crc, !validating);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void EEPROM_READ_ALWAYS(T &VAR) {
|
||||
persistentStore.read_data(eeprom_index, (uint8_t *) &VAR, sizeof(VAR), &working_crc);
|
||||
}
|
||||
|
||||
#endif // EEPROM_SETTINGS
|
||||
};
|
||||
|
||||
extern MarlinSettings settings;
|
2
Marlin/src/module/speed_lookuptable.h
Executable file → Normal file
2
Marlin/src/module/speed_lookuptable.h
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
1490
Marlin/src/module/stepper.cpp
Executable file → Normal file
1490
Marlin/src/module/stepper.cpp
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
293
Marlin/src/module/stepper.h
Executable file → Normal file
293
Marlin/src/module/stepper.h
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@@ -38,7 +38,7 @@
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Grbl. If not, see <http://www.gnu.org/licenses/>.
|
||||
* along with Grbl. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../inc/MarlinConfig.h"
|
||||
@@ -133,27 +133,6 @@
|
||||
|
||||
#endif
|
||||
|
||||
// Add time for each stepper
|
||||
#if HAS_X_STEP
|
||||
#define ISR_X_STEPPER_CYCLES ISR_STEPPER_CYCLES
|
||||
#else
|
||||
#define ISR_X_STEPPER_CYCLES 0UL
|
||||
#endif
|
||||
#if HAS_Y_STEP
|
||||
#define ISR_Y_STEPPER_CYCLES ISR_STEPPER_CYCLES
|
||||
#else
|
||||
#define ISR_START_Y_STEPPER_CYCLES 0UL
|
||||
#define ISR_Y_STEPPER_CYCLES 0UL
|
||||
#endif
|
||||
#if HAS_Z_STEP
|
||||
#define ISR_Z_STEPPER_CYCLES ISR_STEPPER_CYCLES
|
||||
#else
|
||||
#define ISR_Z_STEPPER_CYCLES 0UL
|
||||
#endif
|
||||
|
||||
// E is always interpolated, even for mixing extruders
|
||||
#define ISR_E_STEPPER_CYCLES ISR_STEPPER_CYCLES
|
||||
|
||||
// If linear advance is disabled, the loop also handles them
|
||||
#if DISABLED(LIN_ADVANCE) && ENABLED(MIXING_EXTRUDER)
|
||||
#define ISR_MIXING_STEPPER_CYCLES ((MIXING_STEPPERS) * (ISR_STEPPER_CYCLES))
|
||||
@@ -161,8 +140,31 @@
|
||||
#define ISR_MIXING_STEPPER_CYCLES 0UL
|
||||
#endif
|
||||
|
||||
// Add time for each stepper
|
||||
#if HAS_X_STEP
|
||||
#define ISR_X_STEPPER_CYCLES ISR_STEPPER_CYCLES
|
||||
#endif
|
||||
#if HAS_Y_STEP
|
||||
#define ISR_Y_STEPPER_CYCLES ISR_STEPPER_CYCLES
|
||||
#endif
|
||||
#if HAS_Z_STEP
|
||||
#define ISR_Z_STEPPER_CYCLES ISR_STEPPER_CYCLES
|
||||
#endif
|
||||
#if HAS_I_STEP
|
||||
#define ISR_I_STEPPER_CYCLES ISR_STEPPER_CYCLES
|
||||
#endif
|
||||
#if HAS_J_STEP
|
||||
#define ISR_J_STEPPER_CYCLES ISR_STEPPER_CYCLES
|
||||
#endif
|
||||
#if HAS_K_STEP
|
||||
#define ISR_K_STEPPER_CYCLES ISR_STEPPER_CYCLES
|
||||
#endif
|
||||
#if HAS_EXTRUDERS
|
||||
#define ISR_E_STEPPER_CYCLES ISR_STEPPER_CYCLES // E is always interpolated, even for mixing extruders
|
||||
#endif
|
||||
|
||||
// And the total minimum loop time, not including the base
|
||||
#define MIN_ISR_LOOP_CYCLES (ISR_X_STEPPER_CYCLES + ISR_Y_STEPPER_CYCLES + ISR_Z_STEPPER_CYCLES + ISR_E_STEPPER_CYCLES + ISR_MIXING_STEPPER_CYCLES)
|
||||
#define MIN_ISR_LOOP_CYCLES (ISR_MIXING_STEPPER_CYCLES LOGICAL_AXIS_GANG(+ ISR_E_STEPPER_CYCLES, + ISR_X_STEPPER_CYCLES, + ISR_Y_STEPPER_CYCLES, + ISR_Z_STEPPER_CYCLES, + ISR_I_STEPPER_CYCLES, + ISR_J_STEPPER_CYCLES, + ISR_K_STEPPER_CYCLES))
|
||||
|
||||
// Calculate the minimum MPU cycles needed per pulse to enforce, limited to the max stepper rate
|
||||
#define _MIN_STEPPER_PULSE_CYCLES(N) _MAX(uint32_t((F_CPU) / (MAXIMUM_STEPPER_RATE)), ((F_CPU) / 500000UL) * (N))
|
||||
@@ -191,7 +193,6 @@
|
||||
#error "Expected at least one of MINIMUM_STEPPER_PULSE or MAXIMUM_STEPPER_RATE to be defined"
|
||||
#endif
|
||||
|
||||
|
||||
// But the user could be enforcing a minimum time, so the loop time is
|
||||
#define ISR_LOOP_CYCLES (ISR_LOOP_BASE_CYCLES + _MAX(MIN_STEPPER_PULSE_CYCLES, MIN_ISR_LOOP_CYCLES))
|
||||
|
||||
@@ -230,8 +231,75 @@
|
||||
#define MAX_STEP_ISR_FREQUENCY_2X ((F_CPU) / ISR_EXECUTION_CYCLES(2))
|
||||
#define MAX_STEP_ISR_FREQUENCY_1X ((F_CPU) / ISR_EXECUTION_CYCLES(1))
|
||||
|
||||
// The minimum allowable frequency for step smoothing will be 1/10 of the maximum nominal frequency (in Hz)
|
||||
#define MIN_STEP_ISR_FREQUENCY MAX_STEP_ISR_FREQUENCY_1X
|
||||
// The minimum step ISR rate used by ADAPTIVE_STEP_SMOOTHING to target 50% CPU usage
|
||||
// This does not account for the possibility of multi-stepping.
|
||||
// Perhaps DISABLE_MULTI_STEPPING should be required with ADAPTIVE_STEP_SMOOTHING.
|
||||
#define MIN_STEP_ISR_FREQUENCY (MAX_STEP_ISR_FREQUENCY_1X / 2)
|
||||
|
||||
#define ENABLE_COUNT (LINEAR_AXES + E_STEPPERS)
|
||||
typedef IF<(ENABLE_COUNT > 8), uint16_t, uint8_t>::type ena_mask_t;
|
||||
|
||||
// Axis flags type, for enabled state or other simple state
|
||||
typedef struct {
|
||||
union {
|
||||
ena_mask_t bits;
|
||||
struct {
|
||||
bool LINEAR_AXIS_LIST(X:1, Y:1, Z:1, I:1, J:1, K:1);
|
||||
#if HAS_EXTRUDERS
|
||||
bool LIST_N(EXTRUDERS, E0:1, E1:1, E2:1, E3:1, E4:1, E5:1, E6:1, E7:1);
|
||||
#endif
|
||||
};
|
||||
};
|
||||
constexpr ena_mask_t linear_bits() { return _BV(LINEAR_AXES) - 1; }
|
||||
constexpr ena_mask_t e_bits() { return (_BV(EXTRUDERS) - 1) << LINEAR_AXES; }
|
||||
} axis_flags_t;
|
||||
|
||||
// All the stepper enable pins
|
||||
constexpr pin_t ena_pins[] = {
|
||||
LINEAR_AXIS_LIST(X_ENABLE_PIN, Y_ENABLE_PIN, Z_ENABLE_PIN, I_ENABLE_PIN, J_ENABLE_PIN, K_ENABLE_PIN),
|
||||
LIST_N(E_STEPPERS, E0_ENABLE_PIN, E1_ENABLE_PIN, E2_ENABLE_PIN, E3_ENABLE_PIN, E4_ENABLE_PIN, E5_ENABLE_PIN, E6_ENABLE_PIN, E7_ENABLE_PIN)
|
||||
};
|
||||
|
||||
// Index of the axis or extruder element in a combined array
|
||||
constexpr uint8_t index_of_axis(const AxisEnum axis E_OPTARG(const uint8_t eindex=0)) {
|
||||
return uint8_t(axis) + (E_TERN0(axis < LINEAR_AXES ? 0 : eindex));
|
||||
}
|
||||
//#define __IAX_N(N,V...) _IAX_##N(V)
|
||||
//#define _IAX_N(N,V...) __IAX_N(N,V)
|
||||
//#define _IAX_1(A) index_of_axis(A)
|
||||
//#define _IAX_2(A,B) index_of_axis(A E_OPTARG(B))
|
||||
//#define INDEX_OF_AXIS(V...) _IAX_N(TWO_ARGS(V),V)
|
||||
|
||||
#define INDEX_OF_AXIS(A,V...) index_of_axis(A E_OPTARG(V+0))
|
||||
|
||||
// Bit mask for a matching enable pin, or 0
|
||||
constexpr ena_mask_t ena_same(const uint8_t a, const uint8_t b) {
|
||||
return ena_pins[a] == ena_pins[b] ? _BV(b) : 0;
|
||||
}
|
||||
|
||||
// Recursively get the enable overlaps mask for a given linear axis or extruder
|
||||
constexpr ena_mask_t ena_overlap(const uint8_t a=0, const uint8_t b=0) {
|
||||
return b >= ENABLE_COUNT ? 0 : (a == b ? 0 : ena_same(a, b)) | ena_overlap(a, b + 1);
|
||||
}
|
||||
|
||||
// Recursively get whether there's any overlap at all
|
||||
constexpr bool any_enable_overlap(const uint8_t a=0) {
|
||||
return a >= ENABLE_COUNT ? false : ena_overlap(a) || any_enable_overlap(a + 1);
|
||||
}
|
||||
|
||||
// Array of axes that overlap with each
|
||||
// TODO: Consider cases where >=2 steppers are used by a linear axis or extruder
|
||||
// (e.g., CoreXY, Dual XYZ, or E with multiple steppers, etc.).
|
||||
constexpr ena_mask_t enable_overlap[] = {
|
||||
#define _OVERLAP(N) ena_overlap(INDEX_OF_AXIS(AxisEnum(N))),
|
||||
REPEAT(LINEAR_AXES, _OVERLAP)
|
||||
#if HAS_EXTRUDERS
|
||||
#define _E_OVERLAP(N) ena_overlap(INDEX_OF_AXIS(E_AXIS, N)),
|
||||
REPEAT(E_STEPPERS, _E_OVERLAP)
|
||||
#endif
|
||||
};
|
||||
|
||||
//static_assert(!any_enable_overlap(), "There is some overlap.");
|
||||
|
||||
//
|
||||
// Stepper class definition
|
||||
@@ -240,34 +308,44 @@ class Stepper {
|
||||
|
||||
public:
|
||||
|
||||
#if HAS_EXTRA_ENDSTOPS || ENABLED(Z_STEPPER_AUTO_ALIGN)
|
||||
#if EITHER(HAS_EXTRA_ENDSTOPS, Z_STEPPER_AUTO_ALIGN)
|
||||
static bool separate_multi_axis;
|
||||
#endif
|
||||
|
||||
#if HAS_MOTOR_CURRENT_PWM
|
||||
#ifndef PWM_MOTOR_CURRENT
|
||||
#define PWM_MOTOR_CURRENT DEFAULT_PWM_MOTOR_CURRENT
|
||||
#if HAS_MOTOR_CURRENT_SPI || HAS_MOTOR_CURRENT_PWM
|
||||
#if HAS_MOTOR_CURRENT_PWM
|
||||
#ifndef PWM_MOTOR_CURRENT
|
||||
#define PWM_MOTOR_CURRENT DEFAULT_PWM_MOTOR_CURRENT
|
||||
#endif
|
||||
#define MOTOR_CURRENT_COUNT LINEAR_AXES
|
||||
#elif HAS_MOTOR_CURRENT_SPI
|
||||
static constexpr uint32_t digipot_count[] = DIGIPOT_MOTOR_CURRENT;
|
||||
#define MOTOR_CURRENT_COUNT COUNT(Stepper::digipot_count)
|
||||
#endif
|
||||
static uint32_t motor_current_setting[3];
|
||||
static bool initialized;
|
||||
static uint32_t motor_current_setting[MOTOR_CURRENT_COUNT]; // Initialized by settings.load()
|
||||
#endif
|
||||
|
||||
// Last-moved extruder, as set when the last movement was fetched from planner
|
||||
#if HAS_MULTI_EXTRUDER
|
||||
static uint8_t last_moved_extruder;
|
||||
#else
|
||||
static constexpr uint8_t last_moved_extruder = 0;
|
||||
#endif
|
||||
|
||||
#if HAS_FREEZE_PIN
|
||||
static bool frozen; // Set this flag to instantly freeze motion
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
static block_t* current_block; // A pointer to the block currently being traced
|
||||
|
||||
static uint8_t last_direction_bits, // The next stepping-bits to be output
|
||||
axis_did_move; // Last Movement in the given direction is not null, as computed when the last movement was fetched from planner
|
||||
static axis_bits_t last_direction_bits, // The next stepping-bits to be output
|
||||
axis_did_move; // Last Movement in the given direction is not null, as computed when the last movement was fetched from planner
|
||||
|
||||
static bool abort_current_block; // Signals to the stepper that current block should be aborted
|
||||
|
||||
// Last-moved extruder, as set when the last movement was fetched from planner
|
||||
#if EXTRUDERS < 2
|
||||
static constexpr uint8_t last_moved_extruder = 0;
|
||||
#elif DISABLED(MIXING_EXTRUDER)
|
||||
static uint8_t last_moved_extruder;
|
||||
#endif
|
||||
|
||||
#if ENABLED(X_DUAL_ENDSTOPS)
|
||||
static bool locked_X_motor, locked_X2_motor;
|
||||
#endif
|
||||
@@ -303,7 +381,7 @@ class Stepper {
|
||||
decelerate_after, // The point from where we need to start decelerating
|
||||
step_event_count; // The total event count for the current block
|
||||
|
||||
#if EXTRUDERS > 1 || ENABLED(MIXING_EXTRUDER)
|
||||
#if EITHER(HAS_MULTI_EXTRUDER, MIXING_EXTRUDER)
|
||||
static uint8_t stepper_extruder;
|
||||
#else
|
||||
static constexpr uint8_t stepper_extruder = 0;
|
||||
@@ -334,28 +412,44 @@ class Stepper {
|
||||
static uint32_t nextBabystepISR;
|
||||
#endif
|
||||
|
||||
#if ENABLED(DIRECT_STEPPING)
|
||||
static page_step_state_t page_step_state;
|
||||
#endif
|
||||
|
||||
static int32_t ticks_nominal;
|
||||
#if DISABLED(S_CURVE_ACCELERATION)
|
||||
static uint32_t acc_step_rate; // needed for deceleration start point
|
||||
#endif
|
||||
|
||||
//
|
||||
// Exact steps at which an endstop was triggered
|
||||
//
|
||||
static xyz_long_t endstops_trigsteps;
|
||||
|
||||
//
|
||||
// Positions of stepper motors, in step units
|
||||
//
|
||||
static xyze_long_t count_position;
|
||||
|
||||
//
|
||||
// Current direction of stepper motors (+1 or -1)
|
||||
//
|
||||
// Current stepper motor directions (+1 or -1)
|
||||
static xyze_int8_t count_direction;
|
||||
|
||||
public:
|
||||
#if ENABLED(LASER_POWER_INLINE_TRAPEZOID)
|
||||
|
||||
typedef struct {
|
||||
bool enabled; // Trapezoid needed flag (i.e., laser on, planner in control)
|
||||
uint8_t cur_power; // Current laser power
|
||||
bool cruise_set; // Power set up for cruising?
|
||||
|
||||
#if ENABLED(LASER_POWER_INLINE_TRAPEZOID_CONT)
|
||||
uint16_t till_update; // Countdown to the next update
|
||||
#else
|
||||
uint32_t last_step_count, // Step count from the last update
|
||||
acc_step_count; // Bresenham counter for laser accel/decel
|
||||
#endif
|
||||
} stepper_laser_t;
|
||||
|
||||
static stepper_laser_t laser_trap;
|
||||
|
||||
#endif
|
||||
|
||||
public:
|
||||
// Initialize stepper hardware
|
||||
static void init();
|
||||
|
||||
@@ -400,20 +494,30 @@ class Stepper {
|
||||
#endif
|
||||
|
||||
// Check if the given block is busy or not - Must not be called from ISR contexts
|
||||
static bool is_block_busy(const block_t* const block);
|
||||
static bool is_block_busy(const block_t * const block);
|
||||
|
||||
// Get the position of a stepper, in steps
|
||||
static int32_t position(const AxisEnum axis);
|
||||
|
||||
// Set the current position in steps
|
||||
static void set_position(const int32_t &a, const int32_t &b, const int32_t &c, const int32_t &e);
|
||||
static inline void set_position(const xyze_long_t &abce) { set_position(abce.a, abce.b, abce.c, abce.e); }
|
||||
static void set_position(const xyze_long_t &spos);
|
||||
static void set_axis_position(const AxisEnum a, const int32_t &v);
|
||||
|
||||
// Report the positions of the steppers, in steps
|
||||
static void report_a_position(const xyz_long_t &pos);
|
||||
static void report_positions();
|
||||
|
||||
// Discard current block and free any resources
|
||||
FORCE_INLINE static void discard_current_block() {
|
||||
#if ENABLED(DIRECT_STEPPING)
|
||||
if (IS_PAGE(current_block))
|
||||
page_manager.free_page(current_block->page_idx);
|
||||
#endif
|
||||
current_block = nullptr;
|
||||
axis_did_move = 0;
|
||||
planner.release_current_block();
|
||||
}
|
||||
|
||||
// Quickly stop all steppers
|
||||
FORCE_INLINE static void quick_stop() { abort_current_block = true; }
|
||||
|
||||
@@ -423,24 +527,15 @@ class Stepper {
|
||||
// The last movement direction was not null on the specified axis. Note that motor direction is not necessarily the same.
|
||||
FORCE_INLINE static bool axis_is_moving(const AxisEnum axis) { return TEST(axis_did_move, axis); }
|
||||
|
||||
// The extruder associated to the last movement
|
||||
FORCE_INLINE static uint8_t movement_extruder() {
|
||||
return (0
|
||||
#if EXTRUDERS > 1 && DISABLED(MIXING_EXTRUDER)
|
||||
+ last_moved_extruder
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
// Handle a triggered endstop
|
||||
static void endstop_triggered(const AxisEnum axis);
|
||||
|
||||
// Triggered position of an axis in steps
|
||||
static int32_t triggered_position(const AxisEnum axis);
|
||||
|
||||
#if HAS_DIGIPOTSS || HAS_MOTOR_CURRENT_PWM
|
||||
static void digitalPotWrite(const int16_t address, const int16_t value);
|
||||
static void digipot_current(const uint8_t driver, const int16_t current);
|
||||
#if HAS_MOTOR_CURRENT_SPI || HAS_MOTOR_CURRENT_PWM
|
||||
static void set_digipot_value_spi(const int16_t address, const int16_t value);
|
||||
static void set_digipot_current(const uint8_t driver, const int16_t current);
|
||||
#endif
|
||||
|
||||
#if HAS_MICROSTEPS
|
||||
@@ -449,7 +544,7 @@ class Stepper {
|
||||
static void microstep_readings();
|
||||
#endif
|
||||
|
||||
#if HAS_EXTRA_ENDSTOPS || ENABLED(Z_STEPPER_AUTO_ALIGN)
|
||||
#if EITHER(HAS_EXTRA_ENDSTOPS, Z_STEPPER_AUTO_ALIGN)
|
||||
FORCE_INLINE static void set_separate_multi_axis(const bool state) { separate_multi_axis = state; }
|
||||
#endif
|
||||
#if ENABLED(X_DUAL_ENDSTOPS)
|
||||
@@ -461,7 +556,7 @@ class Stepper {
|
||||
FORCE_INLINE static void set_y2_lock(const bool state) { locked_Y2_motor = state; }
|
||||
#endif
|
||||
#if EITHER(Z_MULTI_ENDSTOPS, Z_STEPPER_AUTO_ALIGN)
|
||||
FORCE_INLINE static void set_z_lock(const bool state) { locked_Z_motor = state; }
|
||||
FORCE_INLINE static void set_z1_lock(const bool state) { locked_Z_motor = state; }
|
||||
FORCE_INLINE static void set_z2_lock(const bool state) { locked_Z2_motor = state; }
|
||||
#if NUM_Z_STEPPER_DRIVERS >= 3
|
||||
FORCE_INLINE static void set_z3_lock(const bool state) { locked_Z3_motor = state; }
|
||||
@@ -469,6 +564,16 @@ class Stepper {
|
||||
FORCE_INLINE static void set_z4_lock(const bool state) { locked_Z4_motor = state; }
|
||||
#endif
|
||||
#endif
|
||||
static inline void set_all_z_lock(const bool lock, const int8_t except=-1) {
|
||||
set_z1_lock(lock ^ (except == 0));
|
||||
set_z2_lock(lock ^ (except == 1));
|
||||
#if NUM_Z_STEPPER_DRIVERS >= 3
|
||||
set_z3_lock(lock ^ (except == 2));
|
||||
#if NUM_Z_STEPPER_DRIVERS >= 4
|
||||
set_z4_lock(lock ^ (except == 3));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENABLED(BABYSTEPPING)
|
||||
@@ -479,16 +584,58 @@ class Stepper {
|
||||
static void refresh_motor_power();
|
||||
#endif
|
||||
|
||||
// Set direction bits for all steppers
|
||||
static axis_flags_t axis_enabled; // Axis stepper(s) ENABLED states
|
||||
|
||||
static inline bool axis_is_enabled(const AxisEnum axis E_OPTARG(const uint8_t eindex=0)) {
|
||||
return TEST(axis_enabled.bits, INDEX_OF_AXIS(axis, eindex));
|
||||
}
|
||||
static inline void mark_axis_enabled(const AxisEnum axis E_OPTARG(const uint8_t eindex=0)) {
|
||||
SBI(axis_enabled.bits, INDEX_OF_AXIS(axis, eindex));
|
||||
}
|
||||
static inline void mark_axis_disabled(const AxisEnum axis E_OPTARG(const uint8_t eindex=0)) {
|
||||
CBI(axis_enabled.bits, INDEX_OF_AXIS(axis, eindex));
|
||||
}
|
||||
static inline bool can_axis_disable(const AxisEnum axis E_OPTARG(const uint8_t eindex=0)) {
|
||||
return !any_enable_overlap() || !(axis_enabled.bits & enable_overlap[INDEX_OF_AXIS(axis, eindex)]);
|
||||
}
|
||||
|
||||
static void enable_axis(const AxisEnum axis);
|
||||
static bool disable_axis(const AxisEnum axis);
|
||||
|
||||
#if HAS_EXTRUDERS
|
||||
static void enable_extruder(E_TERN_(const uint8_t eindex=0));
|
||||
static bool disable_extruder(E_TERN_(const uint8_t eindex=0));
|
||||
static void enable_e_steppers();
|
||||
static void disable_e_steppers();
|
||||
#else
|
||||
static inline void enable_extruder() {}
|
||||
static inline bool disable_extruder() {}
|
||||
static inline void enable_e_steppers() {}
|
||||
static inline void disable_e_steppers() {}
|
||||
#endif
|
||||
|
||||
#define ENABLE_EXTRUDER(N) enable_extruder(E_TERN_(N))
|
||||
#define DISABLE_EXTRUDER(N) disable_extruder(E_TERN_(N))
|
||||
#define AXIS_IS_ENABLED(N,V...) axis_is_enabled(N E_OPTARG(#V))
|
||||
|
||||
static void enable_all_steppers();
|
||||
static void disable_all_steppers();
|
||||
|
||||
// Update direction states for all steppers
|
||||
static void set_directions();
|
||||
|
||||
// Set direction bits and update all stepper DIR states
|
||||
static void set_directions(const axis_bits_t bits) {
|
||||
last_direction_bits = bits;
|
||||
set_directions();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// Set the current position in steps
|
||||
static void _set_position(const int32_t &a, const int32_t &b, const int32_t &c, const int32_t &e);
|
||||
FORCE_INLINE static void _set_position(const abce_long_t &spos) { _set_position(spos.a, spos.b, spos.c, spos.e); }
|
||||
static void _set_position(const abce_long_t &spos);
|
||||
|
||||
FORCE_INLINE static uint32_t calc_timer_interval(uint32_t step_rate, uint8_t* loops) {
|
||||
FORCE_INLINE static uint32_t calc_timer_interval(uint32_t step_rate, uint8_t *loops) {
|
||||
uint32_t timer;
|
||||
|
||||
// Scale the frequency, as requested by the caller
|
||||
@@ -525,7 +672,7 @@ class Stepper {
|
||||
// In case of high-performance processor, it is able to calculate in real-time
|
||||
timer = uint32_t(STEPPER_TIMER_RATE) / step_rate;
|
||||
#else
|
||||
constexpr uint32_t min_step_rate = F_CPU / 500000U;
|
||||
constexpr uint32_t min_step_rate = (F_CPU) / 500000U;
|
||||
NOLESS(step_rate, min_step_rate);
|
||||
step_rate -= min_step_rate; // Correct for minimal speed
|
||||
if (step_rate >= (8 * 256)) { // higher step rate
|
||||
@@ -553,7 +700,7 @@ class Stepper {
|
||||
static int32_t _eval_bezier_curve(const uint32_t curr_step);
|
||||
#endif
|
||||
|
||||
#if HAS_DIGIPOTSS || HAS_MOTOR_CURRENT_PWM
|
||||
#if HAS_MOTOR_CURRENT_SPI || HAS_MOTOR_CURRENT_PWM
|
||||
static void digipot_init();
|
||||
#endif
|
||||
|
||||
|
23
Marlin/src/module/stepper/L64xx.cpp
Executable file → Normal file
23
Marlin/src/module/stepper/L64xx.cpp
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -55,6 +55,15 @@
|
||||
#if AXIS_IS_L64XX(Z4)
|
||||
L64XX_CLASS(Z4) stepperZ4(L6470_CHAIN_SS_PIN);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(I)
|
||||
L64XX_CLASS(I) stepperI(L6470_CHAIN_SS_PIN);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(J)
|
||||
L64XX_CLASS(J) stepperJ(L6470_CHAIN_SS_PIN);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(K)
|
||||
L64XX_CLASS(K) stepperK(L6470_CHAIN_SS_PIN);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(E0)
|
||||
L64XX_CLASS(E0) stepperE0(L6470_CHAIN_SS_PIN);
|
||||
#endif
|
||||
@@ -196,6 +205,18 @@ void L64XX_Marlin::init_to_defaults() {
|
||||
#if AXIS_IS_L64XX(Z3)
|
||||
L6470_INIT_CHIP(Z3);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(Z4)
|
||||
L6470_INIT_CHIP(Z4);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(I)
|
||||
L6470_INIT_CHIP(I);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(J)
|
||||
L6470_INIT_CHIP(J);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(K)
|
||||
L6470_INIT_CHIP(K);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(E0)
|
||||
L6470_INIT_CHIP(E0);
|
||||
#endif
|
||||
|
108
Marlin/src/module/stepper/L64xx.h
Executable file → Normal file
108
Marlin/src/module/stepper/L64xx.h
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@@ -45,7 +45,7 @@
|
||||
#if AXIS_IS_L64XX(X)
|
||||
extern L64XX_CLASS(X) stepperX;
|
||||
#define X_ENABLE_INIT() NOOP
|
||||
#define X_ENABLE_WRITE(STATE) (STATE ? NOOP : stepperX.free())
|
||||
#define X_ENABLE_WRITE(STATE) (STATE ? stepperX.hardStop() : stepperX.free())
|
||||
#define X_ENABLE_READ() (stepperX.getStatus() & STATUS_HIZ)
|
||||
#if AXIS_DRIVER_TYPE_X(L6474)
|
||||
#define X_DIR_INIT() SET_OUTPUT(X_DIR_PIN)
|
||||
@@ -65,7 +65,7 @@
|
||||
#if AXIS_IS_L64XX(Y)
|
||||
extern L64XX_CLASS(Y) stepperY;
|
||||
#define Y_ENABLE_INIT() NOOP
|
||||
#define Y_ENABLE_WRITE(STATE) (STATE ? NOOP : stepperY.free())
|
||||
#define Y_ENABLE_WRITE(STATE) (STATE ? stepperY.hardStop() : stepperY.free())
|
||||
#define Y_ENABLE_READ() (stepperY.getStatus() & STATUS_HIZ)
|
||||
#if AXIS_DRIVER_TYPE_Y(L6474)
|
||||
#define Y_DIR_INIT() SET_OUTPUT(Y_DIR_PIN)
|
||||
@@ -85,7 +85,7 @@
|
||||
#if AXIS_IS_L64XX(Z)
|
||||
extern L64XX_CLASS(Z) stepperZ;
|
||||
#define Z_ENABLE_INIT() NOOP
|
||||
#define Z_ENABLE_WRITE(STATE) (STATE ? NOOP : stepperZ.free())
|
||||
#define Z_ENABLE_WRITE(STATE) (STATE ? stepperZ.hardStop() : stepperZ.free())
|
||||
#define Z_ENABLE_READ() (stepperZ.getStatus() & STATUS_HIZ)
|
||||
#if AXIS_DRIVER_TYPE_Z(L6474)
|
||||
#define Z_DIR_INIT() SET_OUTPUT(Z_DIR_PIN)
|
||||
@@ -105,7 +105,7 @@
|
||||
#if HAS_X2_ENABLE && AXIS_IS_L64XX(X2)
|
||||
extern L64XX_CLASS(X2) stepperX2;
|
||||
#define X2_ENABLE_INIT() NOOP
|
||||
#define X2_ENABLE_WRITE(STATE) (STATE ? NOOP : stepperX2.free())
|
||||
#define X2_ENABLE_WRITE(STATE) (STATE ? stepperX2.hardStop() : stepperX2.free())
|
||||
#define X2_ENABLE_READ() (stepperX2.getStatus() & STATUS_HIZ)
|
||||
#if AXIS_DRIVER_TYPE_X2(L6474)
|
||||
#define X2_DIR_INIT() SET_OUTPUT(X2_DIR_PIN)
|
||||
@@ -126,7 +126,7 @@
|
||||
#if HAS_Y2_ENABLE && AXIS_IS_L64XX(Y2)
|
||||
extern L64XX_CLASS(Y2) stepperY2;
|
||||
#define Y2_ENABLE_INIT() NOOP
|
||||
#define Y2_ENABLE_WRITE(STATE) (STATE ? NOOP : stepperY2.free())
|
||||
#define Y2_ENABLE_WRITE(STATE) (STATE ? stepperY2.hardStop() : stepperY2.free())
|
||||
#define Y2_ENABLE_READ() (stepperY2.getStatus() & STATUS_HIZ)
|
||||
#if AXIS_DRIVER_TYPE_Y2(L6474)
|
||||
#define Y2_DIR_INIT() SET_OUTPUT(Y2_DIR_PIN)
|
||||
@@ -147,7 +147,7 @@
|
||||
#if HAS_Z2_ENABLE && AXIS_IS_L64XX(Z2)
|
||||
extern L64XX_CLASS(Z2) stepperZ2;
|
||||
#define Z2_ENABLE_INIT() NOOP
|
||||
#define Z2_ENABLE_WRITE(STATE) (STATE ? NOOP : stepperZ2.free())
|
||||
#define Z2_ENABLE_WRITE(STATE) (STATE ? stepperZ2.hardStop() : stepperZ2.free())
|
||||
#define Z2_ENABLE_READ() (stepperZ2.getStatus() & STATUS_HIZ)
|
||||
#if AXIS_DRIVER_TYPE_Z2(L6474)
|
||||
#define Z2_DIR_INIT() SET_OUTPUT(Z2_DIR_PIN)
|
||||
@@ -168,7 +168,7 @@
|
||||
#if HAS_Z3_ENABLE && AXIS_IS_L64XX(Z3)
|
||||
extern L64XX_CLASS(Z3) stepperZ3;
|
||||
#define Z3_ENABLE_INIT() NOOP
|
||||
#define Z3_ENABLE_WRITE(STATE) (STATE ? NOOP : stepperZ3.free())
|
||||
#define Z3_ENABLE_WRITE(STATE) (STATE ? stepperZ3.hardStop() : stepperZ3.free())
|
||||
#define Z3_ENABLE_READ() (stepperZ3.getStatus() & STATUS_HIZ)
|
||||
#if AXIS_DRIVER_TYPE_Z3(L6474)
|
||||
#define Z3_DIR_INIT() SET_OUTPUT(Z3_DIR_PIN)
|
||||
@@ -189,7 +189,7 @@
|
||||
#if HAS_Z4_ENABLE && AXIS_IS_L64XX(Z4)
|
||||
extern L64XX_CLASS(Z4) stepperZ4;
|
||||
#define Z4_ENABLE_INIT() NOOP
|
||||
#define Z4_ENABLE_WRITE(STATE) (STATE ? NOOP : stepperZ4.free())
|
||||
#define Z4_ENABLE_WRITE(STATE) (STATE ? stepperZ4.hardStop() : stepperZ4.free())
|
||||
#define Z4_ENABLE_READ() (stepperZ4.getStatus() & STATUS_HIZ)
|
||||
#if AXIS_DRIVER_TYPE_Z4(L6474)
|
||||
#define Z4_DIR_INIT() SET_OUTPUT(Z4_DIR_PIN)
|
||||
@@ -206,11 +206,71 @@
|
||||
#define DISABLE_STEPPER_Z4() stepperZ4.free()
|
||||
#endif
|
||||
|
||||
// I Stepper
|
||||
#if AXIS_IS_L64XX(I)
|
||||
extern L64XX_CLASS(I) stepperI;
|
||||
#define I_ENABLE_INIT() NOOP
|
||||
#define I_ENABLE_WRITE(STATE) (STATE ? stepperI.hardStop() : stepperI.free())
|
||||
#define I_ENABLE_READ() (stepperI.getStatus() & STATUS_HIZ)
|
||||
#if AXIS_DRIVER_TYPE_I(L6474)
|
||||
#define I_DIR_INIT() SET_OUTPUT(I_DIR_PIN)
|
||||
#define I_DIR_WRITE(STATE) L6474_DIR_WRITE(I, STATE)
|
||||
#define I_DIR_READ() READ(I_DIR_PIN)
|
||||
#else
|
||||
#define I_DIR_INIT() NOOP
|
||||
#define I_DIR_WRITE(STATE) L64XX_DIR_WRITE(I, STATE)
|
||||
#define I_DIR_READ() (stepper##I.getStatus() & STATUS_DIR);
|
||||
#if AXIS_DRIVER_TYPE_I(L6470)
|
||||
#define DISABLE_STEPPER_I() stepperI.free()
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// J Stepper
|
||||
#if AXIS_IS_L64XX(J)
|
||||
extern L64XX_CLASS(J) stepperJ;
|
||||
#define J_ENABLE_INIT() NOOP
|
||||
#define J_ENABLE_WRITE(STATE) (STATE ? stepperJ.hardStop() : stepperJ.free())
|
||||
#define J_ENABLE_READ() (stepperJ.getStatus() & STATUS_HIZ)
|
||||
#if AXIS_DRIVER_TYPE_J(L6474)
|
||||
#define J_DIR_INIT() SET_OUTPUT(J_DIR_PIN)
|
||||
#define J_DIR_WRITE(STATE) L6474_DIR_WRITE(J, STATE)
|
||||
#define J_DIR_READ() READ(J_DIR_PIN)
|
||||
#else
|
||||
#define J_DIR_INIT() NOOP
|
||||
#define J_DIR_WRITE(STATE) L64XX_DIR_WRITE(J, STATE)
|
||||
#define J_DIR_READ() (stepper##J.getStatus() & STATUS_DIR);
|
||||
#if AXIS_DRIVER_TYPE_J(L6470)
|
||||
#define DISABLE_STEPPER_J() stepperJ.free()
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// K Stepper
|
||||
#if AXIS_IS_L64XX(K)
|
||||
extern L64XX_CLASS(K) stepperK;
|
||||
#define K_ENABLE_INIT() NOOP
|
||||
#define K_ENABLE_WRITE(STATE) (STATE ? stepperK.hardStop() : stepperK.free())
|
||||
#define K_ENABLE_READ() (stepperK.getStatus() & STATUS_HIZ)
|
||||
#if AXIS_DRIVER_TYPE_K(L6474)
|
||||
#define K_DIR_INIT() SET_OUTPUT(K_DIR_PIN)
|
||||
#define K_DIR_WRITE(STATE) L6474_DIR_WRITE(K, STATE)
|
||||
#define K_DIR_READ() READ(K_DIR_PIN)
|
||||
#else
|
||||
#define K_DIR_INIT() NOOP
|
||||
#define K_DIR_WRITE(STATE) L64XX_DIR_WRITE(K, STATE)
|
||||
#define K_DIR_READ() (stepper##K.getStatus() & STATUS_DIR);
|
||||
#if AXIS_DRIVER_TYPE_K(L6470)
|
||||
#define DISABLE_STEPPER_K() stepperK.free()
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// E0 Stepper
|
||||
#if AXIS_IS_L64XX(E0)
|
||||
extern L64XX_CLASS(E0) stepperE0;
|
||||
#define E0_ENABLE_INIT() NOOP
|
||||
#define E0_ENABLE_WRITE(STATE) (STATE ? NOOP : stepperE0.free())
|
||||
#define E0_ENABLE_WRITE(STATE) (STATE ? stepperE0.hardStop() : stepperE0.free())
|
||||
#define E0_ENABLE_READ() (stepperE0.getStatus() & STATUS_HIZ)
|
||||
#if AXIS_DRIVER_TYPE_E0(L6474)
|
||||
#define E0_DIR_INIT() SET_OUTPUT(E0_DIR_PIN)
|
||||
@@ -221,7 +281,7 @@
|
||||
#define E0_DIR_WRITE(STATE) L64XX_DIR_WRITE(E0, STATE)
|
||||
#define E0_DIR_READ() (stepper##E0.getStatus() & STATUS_DIR);
|
||||
#if AXIS_DRIVER_TYPE_E0(L6470)
|
||||
#define DISABLE_STEPPER_E0() do{ stepperE0.free(); CBI(axis_known_position, E_AXIS); }while(0)
|
||||
#define DISABLE_STEPPER_E0() do{ stepperE0.free(); }while(0)
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
@@ -230,7 +290,7 @@
|
||||
#if AXIS_IS_L64XX(E1)
|
||||
extern L64XX_CLASS(E1) stepperE1;
|
||||
#define E1_ENABLE_INIT() NOOP
|
||||
#define E1_ENABLE_WRITE(STATE) (STATE ? NOOP : stepperE1.free())
|
||||
#define E1_ENABLE_WRITE(STATE) (STATE ? stepperE1.hardStop() : stepperE1.free())
|
||||
#define E1_ENABLE_READ() (stepperE1.getStatus() & STATUS_HIZ)
|
||||
#if AXIS_DRIVER_TYPE_E1(L6474)
|
||||
#define E1_DIR_INIT() SET_OUTPUT(E1_DIR_PIN)
|
||||
@@ -241,7 +301,7 @@
|
||||
#define E1_DIR_WRITE(STATE) L64XX_DIR_WRITE(E1, STATE)
|
||||
#define E1_DIR_READ() (stepper##E1.getStatus() & STATUS_DIR);
|
||||
#if AXIS_DRIVER_TYPE_E1(L6470)
|
||||
#define DISABLE_STEPPER_E1() do{ stepperE1.free(); CBI(axis_known_position, E_AXIS); }while(0)
|
||||
#define DISABLE_STEPPER_E1() do{ stepperE1.free(); }while(0)
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
@@ -250,7 +310,7 @@
|
||||
#if AXIS_IS_L64XX(E2)
|
||||
extern L64XX_CLASS(E2) stepperE2;
|
||||
#define E2_ENABLE_INIT() NOOP
|
||||
#define E2_ENABLE_WRITE(STATE) (STATE ? NOOP : stepperE2.free())
|
||||
#define E2_ENABLE_WRITE(STATE) (STATE ? stepperE2.hardStop() : stepperE2.free())
|
||||
#define E2_ENABLE_READ() (stepperE2.getStatus() & STATUS_HIZ)
|
||||
#if AXIS_DRIVER_TYPE_E2(L6474)
|
||||
#define E2_DIR_INIT() SET_OUTPUT(E2_DIR_PIN)
|
||||
@@ -261,7 +321,7 @@
|
||||
#define E2_DIR_WRITE(STATE) L64XX_DIR_WRITE(E2, STATE)
|
||||
#define E2_DIR_READ() (stepper##E2.getStatus() & STATUS_DIR);
|
||||
#if AXIS_DRIVER_TYPE_E2(L6470)
|
||||
#define DISABLE_STEPPER_E2() do{ stepperE2.free(); CBI(axis_known_position, E_AXIS); }while(0)
|
||||
#define DISABLE_STEPPER_E2() do{ stepperE2.free(); }while(0)
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
@@ -270,7 +330,7 @@
|
||||
#if AXIS_IS_L64XX(E3)
|
||||
extern L64XX_CLASS(E3) stepperE3;
|
||||
#define E3_ENABLE_INIT() NOOP
|
||||
#define E3_ENABLE_WRITE(STATE) (STATE ? NOOP : stepperE3.free())
|
||||
#define E3_ENABLE_WRITE(STATE) (STATE ? stepperE3.hardStop() : stepperE3.free())
|
||||
#define E3_ENABLE_READ() (stepperE3.getStatus() & STATUS_HIZ)
|
||||
#if AXIS_DRIVER_TYPE_E3(L6474)
|
||||
#define E3_DIR_INIT() SET_OUTPUT(E3_DIR_PIN)
|
||||
@@ -287,7 +347,7 @@
|
||||
#if AXIS_IS_L64XX(E4)
|
||||
extern L64XX_CLASS(E4) stepperE4;
|
||||
#define E4_ENABLE_INIT() NOOP
|
||||
#define E4_ENABLE_WRITE(STATE) (STATE ? NOOP : stepperE4.free())
|
||||
#define E4_ENABLE_WRITE(STATE) (STATE ? stepperE4.hardStop() : stepperE4.free())
|
||||
#define E4_ENABLE_READ() (stepperE4.getStatus() & STATUS_HIZ)
|
||||
#if AXIS_DRIVER_TYPE_E4(L6474)
|
||||
#define E4_DIR_INIT() SET_OUTPUT(E4_DIR_PIN)
|
||||
@@ -298,7 +358,7 @@
|
||||
#define E4_DIR_WRITE(STATE) L64XX_DIR_WRITE(E4, STATE)
|
||||
#define E4_DIR_READ() (stepper##E4.getStatus() & STATUS_DIR);
|
||||
#if AXIS_DRIVER_TYPE_E4(L6470)
|
||||
#define DISABLE_STEPPER_E4() do{ stepperE4.free(); CBI(axis_known_position, E_AXIS); }while(0)
|
||||
#define DISABLE_STEPPER_E4() do{ stepperE4.free(); }while(0)
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
@@ -307,7 +367,7 @@
|
||||
#if AXIS_IS_L64XX(E5)
|
||||
extern L64XX_CLASS(E5) stepperE5;
|
||||
#define E5_ENABLE_INIT() NOOP
|
||||
#define E5_ENABLE_WRITE(STATE) (STATE ? NOOP : stepperE5.free())
|
||||
#define E5_ENABLE_WRITE(STATE) (STATE ? stepperE5.hardStop() : stepperE5.free())
|
||||
#define E5_ENABLE_READ() (stepperE5.getStatus() & STATUS_HIZ)
|
||||
#if AXIS_DRIVER_TYPE_E5(L6474)
|
||||
#define E5_DIR_INIT() SET_OUTPUT(E5_DIR_PIN)
|
||||
@@ -318,7 +378,7 @@
|
||||
#define E5_DIR_WRITE(STATE) L64XX_DIR_WRITE(E5, STATE)
|
||||
#define E5_DIR_READ() (stepper##E5.getStatus() & STATUS_DIR);
|
||||
#if AXIS_DRIVER_TYPE_E5(L6470)
|
||||
#define DISABLE_STEPPER_E5() do{ stepperE5.free(); CBI(axis_known_position, E_AXIS); }while(0)
|
||||
#define DISABLE_STEPPER_E5() do{ stepperE5.free(); }while(0)
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
@@ -327,7 +387,7 @@
|
||||
#if AXIS_IS_L64XX(E6)
|
||||
extern L64XX_CLASS(E6) stepperE6;
|
||||
#define E6_ENABLE_INIT() NOOP
|
||||
#define E6_ENABLE_WRITE(STATE) (STATE ? NOOP : stepperE6.free())
|
||||
#define E6_ENABLE_WRITE(STATE) (STATE ? stepperE6.hardStop() : stepperE6.free())
|
||||
#define E6_ENABLE_READ() (stepperE6.getStatus() & STATUS_HIZ)
|
||||
#if AXIS_DRIVER_TYPE_E6(L6474)
|
||||
#define E6_DIR_INIT() SET_OUTPUT(E6_DIR_PIN)
|
||||
@@ -338,7 +398,7 @@
|
||||
#define E6_DIR_WRITE(STATE) L64XX_DIR_WRITE(E6, STATE)
|
||||
#define E6_DIR_READ() (stepper##E6.getStatus() & STATUS_DIR);
|
||||
#if AXIS_DRIVER_TYPE_E6(L6470)
|
||||
#define DISABLE_STEPPER_E6() do{ stepperE6.free(); CBI(axis_known_position, E_AXIS); }while(0)
|
||||
#define DISABLE_STEPPER_E6() do{ stepperE6.free(); }while(0)
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
@@ -347,7 +407,7 @@
|
||||
#if AXIS_IS_L64XX(E7)
|
||||
extern L64XX_CLASS(E7) stepperE7;
|
||||
#define E7_ENABLE_INIT() NOOP
|
||||
#define E7_ENABLE_WRITE(STATE) (STATE ? NOOP : stepperE7.free())
|
||||
#define E7_ENABLE_WRITE(STATE) (STATE ? stepperE7.hardStop() : stepperE7.free())
|
||||
#define E7_ENABLE_READ() (stepperE7.getStatus() & STATUS_HIZ)
|
||||
#if AXIS_DRIVER_TYPE_E7(L6474)
|
||||
#define E7_DIR_INIT() SET_OUTPUT(E7_DIR_PIN)
|
||||
@@ -358,7 +418,7 @@
|
||||
#define E7_DIR_WRITE(STATE) L64XX_DIR_WRITE(E7, STATE)
|
||||
#define E7_DIR_READ() (stepper##E7.getStatus() & STATUS_DIR);
|
||||
#if AXIS_DRIVER_TYPE_E7(L6470)
|
||||
#define DISABLE_STEPPER_E7() do{ stepperE7.free(); CBI(axis_known_position, E_AXIS); }while(0)
|
||||
#define DISABLE_STEPPER_E7() do{ stepperE7.free(); }while(0)
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
24
Marlin/src/module/stepper/TMC26X.cpp
Executable file → Normal file
24
Marlin/src/module/stepper/TMC26X.cpp
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
//
|
||||
// TMC26X Driver objects and inits
|
||||
//
|
||||
#if HAS_DRIVER(TMC26X)
|
||||
#if HAS_TMC26X
|
||||
|
||||
#include "TMC26X.h"
|
||||
|
||||
@@ -60,6 +60,15 @@
|
||||
#if AXIS_DRIVER_TYPE_Z4(TMC26X)
|
||||
_TMC26X_DEFINE(Z4);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_I(TMC26X)
|
||||
_TMC26X_DEFINE(I);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_J(TMC26X)
|
||||
_TMC26X_DEFINE(J);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_K(TMC26X)
|
||||
_TMC26X_DEFINE(K);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E0(TMC26X)
|
||||
_TMC26X_DEFINE(E0);
|
||||
#endif
|
||||
@@ -115,6 +124,15 @@ void tmc26x_init_to_defaults() {
|
||||
#if AXIS_DRIVER_TYPE_Z4(TMC26X)
|
||||
_TMC26X_INIT(Z4);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_I(TMC26X)
|
||||
_TMC26X_INIT(I);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_J(TMC26X)
|
||||
_TMC26X_INIT(J);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_K(TMC26X)
|
||||
_TMC26X_INIT(K);
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_E0(TMC26X)
|
||||
_TMC26X_INIT(E0);
|
||||
#endif
|
||||
@@ -141,4 +159,4 @@ void tmc26x_init_to_defaults() {
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // TMC26X
|
||||
#endif // HAS_TMC26X
|
||||
|
32
Marlin/src/module/stepper/TMC26X.h
Executable file → Normal file
32
Marlin/src/module/stepper/TMC26X.h
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@@ -31,11 +31,7 @@
|
||||
// TMC26X drivers have STEP/DIR on normal pins, but ENABLE via SPI
|
||||
|
||||
#include <SPI.h>
|
||||
#if defined(STM32GENERIC) && defined(STM32F7)
|
||||
#include "../../HAL/STM32_F4_F7/STM32F7/TMC2660.h"
|
||||
#else
|
||||
#include <TMC26XStepper.h>
|
||||
#endif
|
||||
#include <TMC26XStepper.h>
|
||||
|
||||
void tmc26x_init_to_defaults();
|
||||
|
||||
@@ -103,6 +99,30 @@ void tmc26x_init_to_defaults();
|
||||
#define Z4_ENABLE_READ() stepperZ4.isEnabled()
|
||||
#endif
|
||||
|
||||
// I Stepper
|
||||
#if HAS_I_ENABLE && AXIS_DRIVER_TYPE_I(TMC26X)
|
||||
extern TMC26XStepper stepperI;
|
||||
#define I_ENABLE_INIT() NOOP
|
||||
#define I_ENABLE_WRITE(STATE) stepperI.setEnabled(STATE)
|
||||
#define I_ENABLE_READ() stepperI.isEnabled()
|
||||
#endif
|
||||
|
||||
// J Stepper
|
||||
#if HAS_J_ENABLE && AXIS_DRIVER_TYPE_J(TMC26X)
|
||||
extern TMC26XStepper stepperJ;
|
||||
#define J_ENABLE_INIT() NOOP
|
||||
#define J_ENABLE_WRITE(STATE) stepperJ.setEnabled(STATE)
|
||||
#define J_ENABLE_READ() stepperJ.isEnabled()
|
||||
#endif
|
||||
|
||||
// K Stepper
|
||||
#if HAS_K_ENABLE && AXIS_DRIVER_TYPE_K(TMC26X)
|
||||
extern TMC26XStepper stepperK;
|
||||
#define K_ENABLE_INIT() NOOP
|
||||
#define K_ENABLE_WRITE(STATE) stepperK.setEnabled(STATE)
|
||||
#define K_ENABLE_READ() stepperK.isEnabled()
|
||||
#endif
|
||||
|
||||
// E0 Stepper
|
||||
#if AXIS_DRIVER_TYPE_E0(TMC26X)
|
||||
extern TMC26XStepper stepperE0;
|
||||
|
25
Marlin/src/module/stepper/indirection.cpp
Executable file → Normal file
25
Marlin/src/module/stepper/indirection.cpp
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -33,21 +33,16 @@
|
||||
#include "indirection.h"
|
||||
|
||||
void restore_stepper_drivers() {
|
||||
#if HAS_TRINAMIC_CONFIG
|
||||
restore_trinamic_drivers();
|
||||
#endif
|
||||
TERN_(HAS_TRINAMIC_CONFIG, restore_trinamic_drivers());
|
||||
}
|
||||
|
||||
void reset_stepper_drivers() {
|
||||
#if HAS_DRIVER(TMC26X)
|
||||
tmc26x_init_to_defaults();
|
||||
#endif
|
||||
|
||||
#if HAS_L64XX
|
||||
L64xxManager.init_to_defaults();
|
||||
#endif
|
||||
|
||||
#if HAS_TRINAMIC_CONFIG
|
||||
reset_trinamic_drivers();
|
||||
#endif
|
||||
TERN_(HAS_TMC26X, tmc26x_init_to_defaults());
|
||||
TERN_(HAS_L64XX, L64xxManager.init_to_defaults());
|
||||
TERN_(HAS_TRINAMIC_CONFIG, reset_trinamic_drivers());
|
||||
}
|
||||
|
||||
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
|
||||
// Flags to optimize XYZ Enabled state
|
||||
xyz_bool_t axis_sw_enabled; // = { false, false, false }
|
||||
#endif
|
||||
|
336
Marlin/src/module/stepper/indirection.h
Executable file → Normal file
336
Marlin/src/module/stepper/indirection.h
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@@ -36,7 +36,7 @@
|
||||
#include "L64xx.h"
|
||||
#endif
|
||||
|
||||
#if HAS_DRIVER(TMC26X)
|
||||
#if HAS_TMC26X
|
||||
#include "TMC26X.h"
|
||||
#endif
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
#include "trinamic.h"
|
||||
#endif
|
||||
|
||||
void restore_stepper_drivers(); // Called by PSU_ON
|
||||
void restore_stepper_drivers(); // Called by powerManager.power_on()
|
||||
void reset_stepper_drivers(); // Called by settings.load / settings.reset
|
||||
|
||||
// X Stepper
|
||||
@@ -65,38 +65,42 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
|
||||
#define X_STEP_READ() bool(READ(X_STEP_PIN))
|
||||
|
||||
// Y Stepper
|
||||
#ifndef Y_ENABLE_INIT
|
||||
#define Y_ENABLE_INIT() SET_OUTPUT(Y_ENABLE_PIN)
|
||||
#define Y_ENABLE_WRITE(STATE) WRITE(Y_ENABLE_PIN,STATE)
|
||||
#define Y_ENABLE_READ() bool(READ(Y_ENABLE_PIN))
|
||||
#if HAS_Y_AXIS
|
||||
#ifndef Y_ENABLE_INIT
|
||||
#define Y_ENABLE_INIT() SET_OUTPUT(Y_ENABLE_PIN)
|
||||
#define Y_ENABLE_WRITE(STATE) WRITE(Y_ENABLE_PIN,STATE)
|
||||
#define Y_ENABLE_READ() bool(READ(Y_ENABLE_PIN))
|
||||
#endif
|
||||
#ifndef Y_DIR_INIT
|
||||
#define Y_DIR_INIT() SET_OUTPUT(Y_DIR_PIN)
|
||||
#define Y_DIR_WRITE(STATE) WRITE(Y_DIR_PIN,STATE)
|
||||
#define Y_DIR_READ() bool(READ(Y_DIR_PIN))
|
||||
#endif
|
||||
#define Y_STEP_INIT() SET_OUTPUT(Y_STEP_PIN)
|
||||
#ifndef Y_STEP_WRITE
|
||||
#define Y_STEP_WRITE(STATE) WRITE(Y_STEP_PIN,STATE)
|
||||
#endif
|
||||
#define Y_STEP_READ() bool(READ(Y_STEP_PIN))
|
||||
#endif
|
||||
#ifndef Y_DIR_INIT
|
||||
#define Y_DIR_INIT() SET_OUTPUT(Y_DIR_PIN)
|
||||
#define Y_DIR_WRITE(STATE) WRITE(Y_DIR_PIN,STATE)
|
||||
#define Y_DIR_READ() bool(READ(Y_DIR_PIN))
|
||||
#endif
|
||||
#define Y_STEP_INIT() SET_OUTPUT(Y_STEP_PIN)
|
||||
#ifndef Y_STEP_WRITE
|
||||
#define Y_STEP_WRITE(STATE) WRITE(Y_STEP_PIN,STATE)
|
||||
#endif
|
||||
#define Y_STEP_READ() bool(READ(Y_STEP_PIN))
|
||||
|
||||
// Z Stepper
|
||||
#ifndef Z_ENABLE_INIT
|
||||
#define Z_ENABLE_INIT() SET_OUTPUT(Z_ENABLE_PIN)
|
||||
#define Z_ENABLE_WRITE(STATE) WRITE(Z_ENABLE_PIN,STATE)
|
||||
#define Z_ENABLE_READ() bool(READ(Z_ENABLE_PIN))
|
||||
#if HAS_Z_AXIS
|
||||
#ifndef Z_ENABLE_INIT
|
||||
#define Z_ENABLE_INIT() SET_OUTPUT(Z_ENABLE_PIN)
|
||||
#define Z_ENABLE_WRITE(STATE) WRITE(Z_ENABLE_PIN,STATE)
|
||||
#define Z_ENABLE_READ() bool(READ(Z_ENABLE_PIN))
|
||||
#endif
|
||||
#ifndef Z_DIR_INIT
|
||||
#define Z_DIR_INIT() SET_OUTPUT(Z_DIR_PIN)
|
||||
#define Z_DIR_WRITE(STATE) WRITE(Z_DIR_PIN,STATE)
|
||||
#define Z_DIR_READ() bool(READ(Z_DIR_PIN))
|
||||
#endif
|
||||
#define Z_STEP_INIT() SET_OUTPUT(Z_STEP_PIN)
|
||||
#ifndef Z_STEP_WRITE
|
||||
#define Z_STEP_WRITE(STATE) WRITE(Z_STEP_PIN,STATE)
|
||||
#endif
|
||||
#define Z_STEP_READ() bool(READ(Z_STEP_PIN))
|
||||
#endif
|
||||
#ifndef Z_DIR_INIT
|
||||
#define Z_DIR_INIT() SET_OUTPUT(Z_DIR_PIN)
|
||||
#define Z_DIR_WRITE(STATE) WRITE(Z_DIR_PIN,STATE)
|
||||
#define Z_DIR_READ() bool(READ(Z_DIR_PIN))
|
||||
#endif
|
||||
#define Z_STEP_INIT() SET_OUTPUT(Z_STEP_PIN)
|
||||
#ifndef Z_STEP_WRITE
|
||||
#define Z_STEP_WRITE(STATE) WRITE(Z_STEP_PIN,STATE)
|
||||
#endif
|
||||
#define Z_STEP_READ() bool(READ(Z_STEP_PIN))
|
||||
|
||||
// X2 Stepper
|
||||
#if HAS_X2_ENABLE
|
||||
@@ -201,6 +205,63 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
|
||||
#define Z4_DIR_WRITE(STATE) NOOP
|
||||
#endif
|
||||
|
||||
// I Stepper
|
||||
#if LINEAR_AXES >= 4
|
||||
#ifndef I_ENABLE_INIT
|
||||
#define I_ENABLE_INIT() SET_OUTPUT(I_ENABLE_PIN)
|
||||
#define I_ENABLE_WRITE(STATE) WRITE(I_ENABLE_PIN,STATE)
|
||||
#define I_ENABLE_READ() bool(READ(I_ENABLE_PIN))
|
||||
#endif
|
||||
#ifndef I_DIR_INIT
|
||||
#define I_DIR_INIT() SET_OUTPUT(I_DIR_PIN)
|
||||
#define I_DIR_WRITE(STATE) WRITE(I_DIR_PIN,STATE)
|
||||
#define I_DIR_READ() bool(READ(I_DIR_PIN))
|
||||
#endif
|
||||
#define I_STEP_INIT() SET_OUTPUT(I_STEP_PIN)
|
||||
#ifndef I_STEP_WRITE
|
||||
#define I_STEP_WRITE(STATE) WRITE(I_STEP_PIN,STATE)
|
||||
#endif
|
||||
#define I_STEP_READ() bool(READ(I_STEP_PIN))
|
||||
#endif
|
||||
|
||||
// J Stepper
|
||||
#if LINEAR_AXES >= 5
|
||||
#ifndef J_ENABLE_INIT
|
||||
#define J_ENABLE_INIT() SET_OUTPUT(J_ENABLE_PIN)
|
||||
#define J_ENABLE_WRITE(STATE) WRITE(J_ENABLE_PIN,STATE)
|
||||
#define J_ENABLE_READ() bool(READ(J_ENABLE_PIN))
|
||||
#endif
|
||||
#ifndef J_DIR_INIT
|
||||
#define J_DIR_INIT() SET_OUTPUT(J_DIR_PIN)
|
||||
#define J_DIR_WRITE(STATE) WRITE(J_DIR_PIN,STATE)
|
||||
#define J_DIR_READ() bool(READ(J_DIR_PIN))
|
||||
#endif
|
||||
#define J_STEP_INIT() SET_OUTPUT(J_STEP_PIN)
|
||||
#ifndef J_STEP_WRITE
|
||||
#define J_STEP_WRITE(STATE) WRITE(J_STEP_PIN,STATE)
|
||||
#endif
|
||||
#define J_STEP_READ() bool(READ(J_STEP_PIN))
|
||||
#endif
|
||||
|
||||
// K Stepper
|
||||
#if LINEAR_AXES >= 6
|
||||
#ifndef K_ENABLE_INIT
|
||||
#define K_ENABLE_INIT() SET_OUTPUT(K_ENABLE_PIN)
|
||||
#define K_ENABLE_WRITE(STATE) WRITE(K_ENABLE_PIN,STATE)
|
||||
#define K_ENABLE_READ() bool(READ(K_ENABLE_PIN))
|
||||
#endif
|
||||
#ifndef K_DIR_INIT
|
||||
#define K_DIR_INIT() SET_OUTPUT(K_DIR_PIN)
|
||||
#define K_DIR_WRITE(STATE) WRITE(K_DIR_PIN,STATE)
|
||||
#define K_DIR_READ() bool(READ(K_DIR_PIN))
|
||||
#endif
|
||||
#define K_STEP_INIT() SET_OUTPUT(K_STEP_PIN)
|
||||
#ifndef K_STEP_WRITE
|
||||
#define K_STEP_WRITE(STATE) WRITE(K_STEP_PIN,STATE)
|
||||
#endif
|
||||
#define K_STEP_READ() bool(READ(K_STEP_PIN))
|
||||
#endif
|
||||
|
||||
// E0 Stepper
|
||||
#ifndef E0_ENABLE_INIT
|
||||
#define E0_ENABLE_INIT() SET_OUTPUT(E0_ENABLE_PIN)
|
||||
@@ -417,12 +478,15 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
|
||||
#define NORM_E_DIR(E) do{ E0_DIR_WRITE(E ? INVERT_E0_DIR : !INVERT_E0_DIR); }while(0)
|
||||
#define REV_E_DIR(E) do{ E0_DIR_WRITE(E ? !INVERT_E0_DIR : INVERT_E0_DIR); }while(0)
|
||||
#endif
|
||||
#elif ENABLED(PRUSA_MMU2)
|
||||
|
||||
#elif HAS_PRUSA_MMU2 // One multiplexed stepper driver
|
||||
|
||||
#define E_STEP_WRITE(E,V) E0_STEP_WRITE(V)
|
||||
#define NORM_E_DIR(E) E0_DIR_WRITE(!INVERT_E0_DIR)
|
||||
#define REV_E_DIR(E) E0_DIR_WRITE( INVERT_E0_DIR)
|
||||
|
||||
#elif ENABLED(MK2_MULTIPLEXER) // One multiplexed stepper driver, reversed on odd index
|
||||
#elif HAS_PRUSA_MMU1 // One multiplexed stepper driver, reversed on odd index
|
||||
|
||||
#define E_STEP_WRITE(E,V) E0_STEP_WRITE(V)
|
||||
#define NORM_E_DIR(E) do{ E0_DIR_WRITE(TEST(E, 0) ? !INVERT_E0_DIR: INVERT_E0_DIR); }while(0)
|
||||
#define REV_E_DIR(E) do{ E0_DIR_WRITE(TEST(E, 0) ? INVERT_E0_DIR: !INVERT_E0_DIR); }while(0)
|
||||
@@ -581,6 +645,11 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
|
||||
|
||||
#endif
|
||||
|
||||
#elif ENABLED(E_DUAL_STEPPER_DRIVERS)
|
||||
#define E_STEP_WRITE(E,V) do{ E0_STEP_WRITE(V); E1_STEP_WRITE(V); }while(0)
|
||||
#define NORM_E_DIR(E) do{ E0_DIR_WRITE(!INVERT_E0_DIR); E1_DIR_WRITE(!INVERT_E0_DIR ^ ENABLED(INVERT_E1_VS_E0_DIR)); }while(0)
|
||||
#define REV_E_DIR(E) do{ E0_DIR_WRITE( INVERT_E0_DIR); E1_DIR_WRITE( INVERT_E0_DIR ^ ENABLED(INVERT_E1_VS_E0_DIR)); }while(0)
|
||||
|
||||
#elif E_STEPPERS
|
||||
#define E_STEP_WRITE(E,V) E0_STEP_WRITE(V)
|
||||
#define NORM_E_DIR(E) E0_DIR_WRITE(!INVERT_E0_DIR)
|
||||
@@ -598,138 +667,87 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
|
||||
//
|
||||
|
||||
#ifndef ENABLE_STEPPER_X
|
||||
#if HAS_X_ENABLE
|
||||
#define ENABLE_STEPPER_X() X_ENABLE_WRITE( X_ENABLE_ON)
|
||||
#else
|
||||
#define ENABLE_STEPPER_X() NOOP
|
||||
#endif
|
||||
#define ENABLE_STEPPER_X() TERN(HAS_X_ENABLE, X_ENABLE_WRITE( X_ENABLE_ON), NOOP)
|
||||
#endif
|
||||
#ifndef DISABLE_STEPPER_X
|
||||
#if HAS_X_ENABLE
|
||||
#define DISABLE_STEPPER_X() X_ENABLE_WRITE(!X_ENABLE_ON)
|
||||
#else
|
||||
#define DISABLE_STEPPER_X() NOOP
|
||||
#endif
|
||||
#define DISABLE_STEPPER_X() TERN(HAS_X_ENABLE, X_ENABLE_WRITE(!X_ENABLE_ON), NOOP)
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_STEPPER_X2
|
||||
#if HAS_X2_ENABLE
|
||||
#define ENABLE_STEPPER_X2() X2_ENABLE_WRITE( X_ENABLE_ON)
|
||||
#else
|
||||
#define ENABLE_STEPPER_X2() NOOP
|
||||
#endif
|
||||
#define ENABLE_STEPPER_X2() TERN(HAS_X2_ENABLE, X2_ENABLE_WRITE( X_ENABLE_ON), NOOP)
|
||||
#endif
|
||||
#ifndef DISABLE_STEPPER_X2
|
||||
#if HAS_X2_ENABLE
|
||||
#define DISABLE_STEPPER_X2() X2_ENABLE_WRITE(!X_ENABLE_ON)
|
||||
#else
|
||||
#define DISABLE_STEPPER_X2() NOOP
|
||||
#endif
|
||||
#define DISABLE_STEPPER_X2() TERN(HAS_X2_ENABLE, X2_ENABLE_WRITE(!X_ENABLE_ON), NOOP)
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_STEPPER_Y
|
||||
#if HAS_Y_ENABLE
|
||||
#define ENABLE_STEPPER_Y() Y_ENABLE_WRITE( Y_ENABLE_ON)
|
||||
#else
|
||||
#define ENABLE_STEPPER_Y() NOOP
|
||||
#endif
|
||||
#define ENABLE_STEPPER_Y() TERN(HAS_Y_ENABLE, Y_ENABLE_WRITE( Y_ENABLE_ON), NOOP)
|
||||
#endif
|
||||
#ifndef DISABLE_STEPPER_Y
|
||||
#if HAS_Y_ENABLE
|
||||
#define DISABLE_STEPPER_Y() Y_ENABLE_WRITE(!Y_ENABLE_ON)
|
||||
#else
|
||||
#define DISABLE_STEPPER_Y() NOOP
|
||||
#endif
|
||||
#define DISABLE_STEPPER_Y() TERN(HAS_Y_ENABLE, Y_ENABLE_WRITE(!Y_ENABLE_ON), NOOP)
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_STEPPER_Y2
|
||||
#if HAS_Y2_ENABLE
|
||||
#define ENABLE_STEPPER_Y2() Y2_ENABLE_WRITE( Y_ENABLE_ON)
|
||||
#else
|
||||
#define ENABLE_STEPPER_Y2() NOOP
|
||||
#endif
|
||||
#define ENABLE_STEPPER_Y2() TERN(HAS_Y2_ENABLE, Y2_ENABLE_WRITE( Y_ENABLE_ON), NOOP)
|
||||
#endif
|
||||
#ifndef DISABLE_STEPPER_Y2
|
||||
#if HAS_Y2_ENABLE
|
||||
#define DISABLE_STEPPER_Y2() Y2_ENABLE_WRITE(!Y_ENABLE_ON)
|
||||
#else
|
||||
#define DISABLE_STEPPER_Y2() NOOP
|
||||
#endif
|
||||
#define DISABLE_STEPPER_Y2() TERN(HAS_Y2_ENABLE, Y2_ENABLE_WRITE(!Y_ENABLE_ON), NOOP)
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_STEPPER_Z
|
||||
#if HAS_Z_ENABLE
|
||||
#define ENABLE_STEPPER_Z() Z_ENABLE_WRITE( Z_ENABLE_ON)
|
||||
#else
|
||||
#define ENABLE_STEPPER_Z() NOOP
|
||||
#endif
|
||||
#define ENABLE_STEPPER_Z() TERN(HAS_Z_ENABLE, Z_ENABLE_WRITE( Z_ENABLE_ON), NOOP)
|
||||
#endif
|
||||
#ifndef DISABLE_STEPPER_Z
|
||||
#if HAS_Z_ENABLE
|
||||
#define DISABLE_STEPPER_Z() Z_ENABLE_WRITE(!Z_ENABLE_ON)
|
||||
#else
|
||||
#define DISABLE_STEPPER_Z() NOOP
|
||||
#endif
|
||||
#define DISABLE_STEPPER_Z() TERN(HAS_Z_ENABLE, Z_ENABLE_WRITE(!Z_ENABLE_ON), NOOP)
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_STEPPER_Z2
|
||||
#if HAS_Z2_ENABLE
|
||||
#define ENABLE_STEPPER_Z2() Z2_ENABLE_WRITE( Z_ENABLE_ON)
|
||||
#else
|
||||
#define ENABLE_STEPPER_Z2() NOOP
|
||||
#endif
|
||||
#define ENABLE_STEPPER_Z2() TERN(HAS_Z2_ENABLE, Z2_ENABLE_WRITE( Z_ENABLE_ON), NOOP)
|
||||
#endif
|
||||
#ifndef DISABLE_STEPPER_Z2
|
||||
#if HAS_Z2_ENABLE
|
||||
#define DISABLE_STEPPER_Z2() Z2_ENABLE_WRITE(!Z_ENABLE_ON)
|
||||
#else
|
||||
#define DISABLE_STEPPER_Z2() NOOP
|
||||
#endif
|
||||
#define DISABLE_STEPPER_Z2() TERN(HAS_Z2_ENABLE, Z2_ENABLE_WRITE(!Z_ENABLE_ON), NOOP)
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_STEPPER_Z3
|
||||
#if HAS_Z3_ENABLE
|
||||
#define ENABLE_STEPPER_Z3() Z3_ENABLE_WRITE( Z_ENABLE_ON)
|
||||
#else
|
||||
#define ENABLE_STEPPER_Z3() NOOP
|
||||
#endif
|
||||
#define ENABLE_STEPPER_Z3() TERN(HAS_Z3_ENABLE, Z3_ENABLE_WRITE( Z_ENABLE_ON), NOOP)
|
||||
#endif
|
||||
#ifndef DISABLE_STEPPER_Z3
|
||||
#if HAS_Z3_ENABLE
|
||||
#define DISABLE_STEPPER_Z3() Z3_ENABLE_WRITE(!Z_ENABLE_ON)
|
||||
#else
|
||||
#define DISABLE_STEPPER_Z3() NOOP
|
||||
#endif
|
||||
#define DISABLE_STEPPER_Z3() TERN(HAS_Z3_ENABLE, Z3_ENABLE_WRITE(!Z_ENABLE_ON), NOOP)
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_STEPPER_Z4
|
||||
#if HAS_Z4_ENABLE
|
||||
#define ENABLE_STEPPER_Z4() Z4_ENABLE_WRITE( Z_ENABLE_ON)
|
||||
#else
|
||||
#define ENABLE_STEPPER_Z4() NOOP
|
||||
#endif
|
||||
#define ENABLE_STEPPER_Z4() TERN(HAS_Z4_ENABLE, Z4_ENABLE_WRITE( Z_ENABLE_ON), NOOP)
|
||||
#endif
|
||||
#ifndef DISABLE_STEPPER_Z4
|
||||
#if HAS_Z4_ENABLE
|
||||
#define DISABLE_STEPPER_Z4() Z4_ENABLE_WRITE(!Z_ENABLE_ON)
|
||||
#else
|
||||
#define DISABLE_STEPPER_Z4() NOOP
|
||||
#endif
|
||||
#define DISABLE_STEPPER_Z4() TERN(HAS_Z4_ENABLE, Z4_ENABLE_WRITE(!Z_ENABLE_ON), NOOP)
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_STEPPER_I
|
||||
#define ENABLE_STEPPER_I() TERN(HAS_I_ENABLE, I_ENABLE_WRITE( I_ENABLE_ON), NOOP)
|
||||
#endif
|
||||
#ifndef DISABLE_STEPPER_I
|
||||
#define DISABLE_STEPPER_I() TERN(HAS_I_ENABLE, I_ENABLE_WRITE(!I_ENABLE_ON), NOOP)
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_STEPPER_J
|
||||
#define ENABLE_STEPPER_J() TERN(HAS_J_ENABLE, J_ENABLE_WRITE( J_ENABLE_ON), NOOP)
|
||||
#endif
|
||||
#ifndef DISABLE_STEPPER_J
|
||||
#define DISABLE_STEPPER_J() TERN(HAS_J_ENABLE, J_ENABLE_WRITE(!J_ENABLE_ON), NOOP)
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_STEPPER_K
|
||||
#define ENABLE_STEPPER_K() TERN(HAS_K_ENABLE, K_ENABLE_WRITE( K_ENABLE_ON), NOOP)
|
||||
#endif
|
||||
#ifndef DISABLE_STEPPER_K
|
||||
#define DISABLE_STEPPER_K() TERN(HAS_K_ENABLE, K_ENABLE_WRITE(!K_ENABLE_ON), NOOP)
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_STEPPER_E0
|
||||
#if HAS_E0_ENABLE
|
||||
#define ENABLE_STEPPER_E0() E0_ENABLE_WRITE( E_ENABLE_ON)
|
||||
#else
|
||||
#define ENABLE_STEPPER_E0() NOOP
|
||||
#endif
|
||||
#define ENABLE_STEPPER_E0() TERN(HAS_E0_ENABLE, E0_ENABLE_WRITE( E_ENABLE_ON), NOOP)
|
||||
#endif
|
||||
#ifndef DISABLE_STEPPER_E0
|
||||
#if HAS_E0_ENABLE
|
||||
#define DISABLE_STEPPER_E0() E0_ENABLE_WRITE(!E_ENABLE_ON)
|
||||
#else
|
||||
#define DISABLE_STEPPER_E0() NOOP
|
||||
#endif
|
||||
#define DISABLE_STEPPER_E0() TERN(HAS_E0_ENABLE, E0_ENABLE_WRITE(!E_ENABLE_ON), NOOP)
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_STEPPER_E1
|
||||
@@ -840,21 +858,71 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
|
||||
//
|
||||
// Axis steppers enable / disable macros
|
||||
//
|
||||
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
|
||||
// Avoid expensive calls to enable / disable steppers
|
||||
extern xyz_bool_t axis_sw_enabled;
|
||||
#define SHOULD_ENABLE(N) !axis_sw_enabled.N
|
||||
#define SHOULD_DISABLE(N) axis_sw_enabled.N
|
||||
#define AFTER_CHANGE(N,TF) axis_sw_enabled.N = TF
|
||||
#else
|
||||
#define SHOULD_ENABLE(N) true
|
||||
#define SHOULD_DISABLE(N) true
|
||||
#define AFTER_CHANGE(N,TF) NOOP
|
||||
#endif
|
||||
|
||||
#define ENABLE_AXIS_X() do{ ENABLE_STEPPER_X(); ENABLE_STEPPER_X2(); }while(0)
|
||||
#define DISABLE_AXIS_X() do{ DISABLE_STEPPER_X(); DISABLE_STEPPER_X2(); CBI(axis_known_position, X_AXIS); }while(0)
|
||||
#define ENABLE_AXIS_X() if (SHOULD_ENABLE(x)) { ENABLE_STEPPER_X(); ENABLE_STEPPER_X2(); AFTER_CHANGE(x, true); }
|
||||
#define DISABLE_AXIS_X() if (SHOULD_DISABLE(x)) { DISABLE_STEPPER_X(); DISABLE_STEPPER_X2(); AFTER_CHANGE(x, false); set_axis_untrusted(X_AXIS); }
|
||||
|
||||
#define ENABLE_AXIS_Y() do{ ENABLE_STEPPER_Y(); ENABLE_STEPPER_Y2(); }while(0)
|
||||
#define DISABLE_AXIS_Y() do{ DISABLE_STEPPER_Y(); DISABLE_STEPPER_Y2(); CBI(axis_known_position, Y_AXIS); }while(0)
|
||||
#if HAS_Y_AXIS
|
||||
#define ENABLE_AXIS_Y() if (SHOULD_ENABLE(y)) { ENABLE_STEPPER_Y(); ENABLE_STEPPER_Y2(); AFTER_CHANGE(y, true); }
|
||||
#define DISABLE_AXIS_Y() if (SHOULD_DISABLE(y)) { DISABLE_STEPPER_Y(); DISABLE_STEPPER_Y2(); AFTER_CHANGE(y, false); set_axis_untrusted(Y_AXIS); }
|
||||
#else
|
||||
#define ENABLE_AXIS_Y() NOOP
|
||||
#define DISABLE_AXIS_Y() NOOP
|
||||
#endif
|
||||
|
||||
#define ENABLE_AXIS_Z() do{ ENABLE_STEPPER_Z(); ENABLE_STEPPER_Z2(); ENABLE_STEPPER_Z3(); ENABLE_STEPPER_Z4(); }while(0)
|
||||
#define DISABLE_AXIS_Z() do{ DISABLE_STEPPER_Z(); DISABLE_STEPPER_Z2(); DISABLE_STEPPER_Z3(); DISABLE_STEPPER_Z4(); CBI(axis_known_position, Z_AXIS); }while(0)
|
||||
#if HAS_Z_AXIS
|
||||
#define ENABLE_AXIS_Z() if (SHOULD_ENABLE(z)) { ENABLE_STEPPER_Z(); ENABLE_STEPPER_Z2(); ENABLE_STEPPER_Z3(); ENABLE_STEPPER_Z4(); AFTER_CHANGE(z, true); }
|
||||
#define DISABLE_AXIS_Z() if (SHOULD_DISABLE(z)) { DISABLE_STEPPER_Z(); DISABLE_STEPPER_Z2(); DISABLE_STEPPER_Z3(); DISABLE_STEPPER_Z4(); AFTER_CHANGE(z, false); set_axis_untrusted(Z_AXIS); Z_RESET(); }
|
||||
#else
|
||||
#define ENABLE_AXIS_Z() NOOP
|
||||
#define DISABLE_AXIS_Z() NOOP
|
||||
#endif
|
||||
|
||||
#ifdef Z_IDLE_HEIGHT
|
||||
#define Z_RESET() do{ current_position.z = Z_IDLE_HEIGHT; sync_plan_position(); }while(0)
|
||||
#else
|
||||
#define Z_RESET()
|
||||
#endif
|
||||
|
||||
#if LINEAR_AXES >= 4
|
||||
#define ENABLE_AXIS_I() if (SHOULD_ENABLE(i)) { ENABLE_STEPPER_I(); AFTER_CHANGE(i, true); }
|
||||
#define DISABLE_AXIS_I() if (SHOULD_DISABLE(i)) { DISABLE_STEPPER_I(); AFTER_CHANGE(i, false); set_axis_untrusted(I_AXIS); }
|
||||
#else
|
||||
#define ENABLE_AXIS_I() NOOP
|
||||
#define DISABLE_AXIS_I() NOOP
|
||||
#endif
|
||||
#if LINEAR_AXES >= 5
|
||||
#define ENABLE_AXIS_J() if (SHOULD_ENABLE(j)) { ENABLE_STEPPER_J(); AFTER_CHANGE(j, true); }
|
||||
#define DISABLE_AXIS_J() if (SHOULD_DISABLE(j)) { DISABLE_STEPPER_J(); AFTER_CHANGE(j, false); set_axis_untrusted(J_AXIS); }
|
||||
#else
|
||||
#define ENABLE_AXIS_J() NOOP
|
||||
#define DISABLE_AXIS_J() NOOP
|
||||
#endif
|
||||
#if LINEAR_AXES >= 6
|
||||
#define ENABLE_AXIS_K() if (SHOULD_ENABLE(k)) { ENABLE_STEPPER_K(); AFTER_CHANGE(k, true); }
|
||||
#define DISABLE_AXIS_K() if (SHOULD_DISABLE(k)) { DISABLE_STEPPER_K(); AFTER_CHANGE(k, false); set_axis_untrusted(K_AXIS); }
|
||||
#else
|
||||
#define ENABLE_AXIS_K() NOOP
|
||||
#define DISABLE_AXIS_K() NOOP
|
||||
#endif
|
||||
|
||||
//
|
||||
// Extruder steppers enable / disable macros
|
||||
//
|
||||
|
||||
#if ENABLED(MIXING_EXTRUDER)
|
||||
|
||||
/**
|
||||
* Mixing steppers keep all their enable (and direction) states synchronized
|
||||
*/
|
||||
@@ -862,17 +930,23 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
|
||||
#define _CALL_DIS_E(N) DISABLE_STEPPER_E##N () ;
|
||||
#define ENABLE_AXIS_E0() { RREPEAT(MIXING_STEPPERS, _CALL_ENA_E) }
|
||||
#define DISABLE_AXIS_E0() { RREPEAT(MIXING_STEPPERS, _CALL_DIS_E) }
|
||||
|
||||
#elif ENABLED(E_DUAL_STEPPER_DRIVERS)
|
||||
|
||||
#define ENABLE_AXIS_E0() do{ ENABLE_STEPPER_E0(); ENABLE_STEPPER_E1(); }while(0)
|
||||
#define DISABLE_AXIS_E0() do{ DISABLE_STEPPER_E0(); DISABLE_STEPPER_E1(); }while(0)
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_AXIS_E0
|
||||
#if E_STEPPERS > 0 && HAS_E0_ENABLE
|
||||
#if E_STEPPERS && HAS_E0_ENABLE
|
||||
#define ENABLE_AXIS_E0() ENABLE_STEPPER_E0()
|
||||
#else
|
||||
#define ENABLE_AXIS_E0() NOOP
|
||||
#endif
|
||||
#endif
|
||||
#ifndef DISABLE_AXIS_E0
|
||||
#if E_STEPPERS > 0 && HAS_E0_ENABLE
|
||||
#if E_STEPPERS && HAS_E0_ENABLE
|
||||
#define DISABLE_AXIS_E0() DISABLE_STEPPER_E0()
|
||||
#else
|
||||
#define DISABLE_AXIS_E0() NOOP
|
||||
|
554
Marlin/src/module/stepper/trinamic.cpp
Executable file → Normal file
554
Marlin/src/module/stepper/trinamic.cpp
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -35,8 +35,10 @@
|
||||
#include <HardwareSerial.h>
|
||||
#include <SPI.h>
|
||||
|
||||
enum StealthIndex : uint8_t { STEALTH_AXIS_XY, STEALTH_AXIS_Z, STEALTH_AXIS_E };
|
||||
#define TMC_INIT(ST, STEALTH_INDEX) tmc_init(stepper##ST, ST##_CURRENT, ST##_MICROSTEPS, ST##_HYBRID_THRESHOLD, stealthchop_by_axis[STEALTH_INDEX])
|
||||
enum StealthIndex : uint8_t {
|
||||
LOGICAL_AXIS_LIST(STEALTH_AXIS_E, STEALTH_AXIS_X, STEALTH_AXIS_Y, STEALTH_AXIS_Z, STEALTH_AXIS_I, STEALTH_AXIS_J, STEALTH_AXIS_K)
|
||||
};
|
||||
#define TMC_INIT(ST, STEALTH_INDEX) tmc_init(stepper##ST, ST##_CURRENT, ST##_MICROSTEPS, ST##_HYBRID_THRESHOLD, stealthchop_by_axis[STEALTH_INDEX], chopper_timing_##ST, ST##_INTERPOLATE)
|
||||
|
||||
// IC = TMC model number
|
||||
// ST = Stepper object letter
|
||||
@@ -49,8 +51,12 @@ enum StealthIndex : uint8_t { STEALTH_AXIS_XY, STEALTH_AXIS_Z, STEALTH_AXIS_E };
|
||||
#define __TMC_SPI_DEFINE(IC, ST, L, AI) TMCMarlin<IC##Stepper, L, AI> stepper##ST(ST##_CS_PIN, float(ST##_RSENSE), ST##_CHAIN_POS)
|
||||
#endif
|
||||
|
||||
#define TMC_UART_HW_DEFINE(IC, ST, L, AI) TMCMarlin<IC##Stepper, L, AI> stepper##ST(&ST##_HARDWARE_SERIAL, float(ST##_RSENSE), ST##_SLAVE_ADDRESS)
|
||||
#define TMC_UART_SW_DEFINE(IC, ST, L, AI) TMCMarlin<IC##Stepper, L, AI> stepper##ST(ST##_SERIAL_RX_PIN, ST##_SERIAL_TX_PIN, float(ST##_RSENSE), ST##_SLAVE_ADDRESS, ST##_SERIAL_RX_PIN > -1)
|
||||
#if ENABLED(TMC_SERIAL_MULTIPLEXER)
|
||||
#define TMC_UART_HW_DEFINE(IC, ST, L, AI) TMCMarlin<IC##Stepper, L, AI> stepper##ST(&ST##_HARDWARE_SERIAL, float(ST##_RSENSE), ST##_SLAVE_ADDRESS, SERIAL_MUL_PIN1, SERIAL_MUL_PIN2)
|
||||
#else
|
||||
#define TMC_UART_HW_DEFINE(IC, ST, L, AI) TMCMarlin<IC##Stepper, L, AI> stepper##ST(&ST##_HARDWARE_SERIAL, float(ST##_RSENSE), ST##_SLAVE_ADDRESS)
|
||||
#endif
|
||||
#define TMC_UART_SW_DEFINE(IC, ST, L, AI) TMCMarlin<IC##Stepper, L, AI> stepper##ST(ST##_SERIAL_RX_PIN, ST##_SERIAL_TX_PIN, float(ST##_RSENSE), ST##_SLAVE_ADDRESS)
|
||||
|
||||
#define _TMC_SPI_DEFINE(IC, ST, AI) __TMC_SPI_DEFINE(IC, ST, TMC_##ST##_LABEL, AI)
|
||||
#define TMC_SPI_DEFINE(ST, AI) _TMC_SPI_DEFINE(ST##_DRIVER_TYPE, ST, AI##_AXIS)
|
||||
@@ -58,7 +64,7 @@ enum StealthIndex : uint8_t { STEALTH_AXIS_XY, STEALTH_AXIS_Z, STEALTH_AXIS_E };
|
||||
#define _TMC_UART_DEFINE(SWHW, IC, ST, AI) TMC_UART_##SWHW##_DEFINE(IC, ST, TMC_##ST##_LABEL, AI)
|
||||
#define TMC_UART_DEFINE(SWHW, ST, AI) _TMC_UART_DEFINE(SWHW, ST##_DRIVER_TYPE, ST, AI##_AXIS)
|
||||
|
||||
#if ENABLED(DISTINCT_E_FACTORS) && E_STEPPERS > 1
|
||||
#if ENABLED(DISTINCT_E_FACTORS)
|
||||
#define TMC_SPI_DEFINE_E(AI) TMC_SPI_DEFINE(E##AI, E##AI)
|
||||
#define TMC_UART_DEFINE_E(SWHW, AI) TMC_UART_DEFINE(SWHW, E##AI, E##AI)
|
||||
#else
|
||||
@@ -91,6 +97,15 @@ enum StealthIndex : uint8_t { STEALTH_AXIS_XY, STEALTH_AXIS_Z, STEALTH_AXIS_E };
|
||||
#if AXIS_HAS_SPI(Z4)
|
||||
TMC_SPI_DEFINE(Z4, Z);
|
||||
#endif
|
||||
#if AXIS_HAS_SPI(I)
|
||||
TMC_SPI_DEFINE(I, I);
|
||||
#endif
|
||||
#if AXIS_HAS_SPI(J)
|
||||
TMC_SPI_DEFINE(J, J);
|
||||
#endif
|
||||
#if AXIS_HAS_SPI(K)
|
||||
TMC_SPI_DEFINE(K, K);
|
||||
#endif
|
||||
#if AXIS_HAS_SPI(E0)
|
||||
TMC_SPI_DEFINE_E(0);
|
||||
#endif
|
||||
@@ -117,32 +132,84 @@ enum StealthIndex : uint8_t { STEALTH_AXIS_XY, STEALTH_AXIS_Z, STEALTH_AXIS_E };
|
||||
#endif
|
||||
|
||||
#ifndef TMC_BAUD_RATE
|
||||
#if HAS_TMC_SW_SERIAL
|
||||
// Reduce baud rate for boards not already overriding TMC_BAUD_RATE for software serial.
|
||||
// Testing has shown that 115200 is not 100% reliable on AVR platforms, occasionally
|
||||
// failing to read status properly. 32-bit platforms typically define an even lower
|
||||
// TMC_BAUD_RATE, due to differences in how SoftwareSerial libraries work on different
|
||||
// platforms.
|
||||
#define TMC_BAUD_RATE 57600
|
||||
#else
|
||||
#define TMC_BAUD_RATE 115200
|
||||
#endif
|
||||
// Reduce baud rate for boards not already overriding TMC_BAUD_RATE for software serial.
|
||||
// Testing has shown that 115200 is not 100% reliable on AVR platforms, occasionally
|
||||
// failing to read status properly. 32-bit platforms typically define an even lower
|
||||
// TMC_BAUD_RATE, due to differences in how SoftwareSerial libraries work on different
|
||||
// platforms.
|
||||
#define TMC_BAUD_RATE TERN(HAS_TMC_SW_SERIAL, 57600, 115200)
|
||||
#endif
|
||||
|
||||
#ifndef TMC_X_BAUD_RATE
|
||||
#define TMC_X_BAUD_RATE TMC_BAUD_RATE
|
||||
#endif
|
||||
#ifndef TMC_X2_BAUD_RATE
|
||||
#define TMC_X2_BAUD_RATE TMC_BAUD_RATE
|
||||
#endif
|
||||
#ifndef TMC_Y_BAUD_RATE
|
||||
#define TMC_Y_BAUD_RATE TMC_BAUD_RATE
|
||||
#endif
|
||||
#ifndef TMC_Y2_BAUD_RATE
|
||||
#define TMC_Y2_BAUD_RATE TMC_BAUD_RATE
|
||||
#endif
|
||||
#ifndef TMC_Z_BAUD_RATE
|
||||
#define TMC_Z_BAUD_RATE TMC_BAUD_RATE
|
||||
#endif
|
||||
#ifndef TMC_Z2_BAUD_RATE
|
||||
#define TMC_Z2_BAUD_RATE TMC_BAUD_RATE
|
||||
#endif
|
||||
#ifndef TMC_Z3_BAUD_RATE
|
||||
#define TMC_Z3_BAUD_RATE TMC_BAUD_RATE
|
||||
#endif
|
||||
#ifndef TMC_Z4_BAUD_RATE
|
||||
#define TMC_Z4_BAUD_RATE TMC_BAUD_RATE
|
||||
#endif
|
||||
#ifndef TMC_I_BAUD_RATE
|
||||
#define TMC_I_BAUD_RATE TMC_BAUD_RATE
|
||||
#endif
|
||||
#ifndef TMC_J_BAUD_RATE
|
||||
#define TMC_J_BAUD_RATE TMC_BAUD_RATE
|
||||
#endif
|
||||
#ifndef TMC_K_BAUD_RATE
|
||||
#define TMC_K_BAUD_RATE TMC_BAUD_RATE
|
||||
#endif
|
||||
#ifndef TMC_E0_BAUD_RATE
|
||||
#define TMC_E0_BAUD_RATE TMC_BAUD_RATE
|
||||
#endif
|
||||
#ifndef TMC_E1_BAUD_RATE
|
||||
#define TMC_E1_BAUD_RATE TMC_BAUD_RATE
|
||||
#endif
|
||||
#ifndef TMC_E2_BAUD_RATE
|
||||
#define TMC_E2_BAUD_RATE TMC_BAUD_RATE
|
||||
#endif
|
||||
#ifndef TMC_E3_BAUD_RATE
|
||||
#define TMC_E3_BAUD_RATE TMC_BAUD_RATE
|
||||
#endif
|
||||
#ifndef TMC_E4_BAUD_RATE
|
||||
#define TMC_E4_BAUD_RATE TMC_BAUD_RATE
|
||||
#endif
|
||||
#ifndef TMC_E5_BAUD_RATE
|
||||
#define TMC_E5_BAUD_RATE TMC_BAUD_RATE
|
||||
#endif
|
||||
#ifndef TMC_E6_BAUD_RATE
|
||||
#define TMC_E6_BAUD_RATE TMC_BAUD_RATE
|
||||
#endif
|
||||
#ifndef TMC_E7_BAUD_RATE
|
||||
#define TMC_E7_BAUD_RATE TMC_BAUD_RATE
|
||||
#endif
|
||||
|
||||
#if HAS_DRIVER(TMC2130)
|
||||
template<char AXIS_LETTER, char DRIVER_ID, AxisEnum AXIS_ID>
|
||||
void tmc_init(TMCMarlin<TMC2130Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth) {
|
||||
void tmc_init(TMCMarlin<TMC2130Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth, const chopper_timing_t &chop_init, const bool interpolate) {
|
||||
st.begin();
|
||||
|
||||
CHOPCONF_t chopconf{0};
|
||||
chopconf.tbl = 1;
|
||||
chopconf.toff = chopper_timing.toff;
|
||||
chopconf.intpol = INTERPOLATE;
|
||||
chopconf.hend = chopper_timing.hend + 3;
|
||||
chopconf.hstrt = chopper_timing.hstrt - 1;
|
||||
#if ENABLED(SQUARE_WAVE_STEPPING)
|
||||
chopconf.dedge = true;
|
||||
#endif
|
||||
chopconf.tbl = 0b01;
|
||||
chopconf.toff = chop_init.toff;
|
||||
chopconf.intpol = interpolate;
|
||||
chopconf.hend = chop_init.hend + 3;
|
||||
chopconf.hstrt = chop_init.hstrt - 1;
|
||||
TERN_(SQUARE_WAVE_STEPPING, chopconf.dedge = true);
|
||||
st.CHOPCONF(chopconf.sr);
|
||||
|
||||
st.rms_current(mA, HOLD_MULTIPLIER);
|
||||
@@ -160,11 +227,7 @@ enum StealthIndex : uint8_t { STEALTH_AXIS_XY, STEALTH_AXIS_Z, STEALTH_AXIS_E };
|
||||
pwmconf.pwm_ampl = 180;
|
||||
st.PWMCONF(pwmconf.sr);
|
||||
|
||||
#if ENABLED(HYBRID_THRESHOLD)
|
||||
st.set_pwm_thrs(hyb_thrs);
|
||||
#else
|
||||
UNUSED(hyb_thrs);
|
||||
#endif
|
||||
TERN(HYBRID_THRESHOLD, st.set_pwm_thrs(hyb_thrs), UNUSED(hyb_thrs));
|
||||
|
||||
st.GSTAT(); // Clear GSTAT
|
||||
}
|
||||
@@ -172,18 +235,16 @@ enum StealthIndex : uint8_t { STEALTH_AXIS_XY, STEALTH_AXIS_Z, STEALTH_AXIS_E };
|
||||
|
||||
#if HAS_DRIVER(TMC2160)
|
||||
template<char AXIS_LETTER, char DRIVER_ID, AxisEnum AXIS_ID>
|
||||
void tmc_init(TMCMarlin<TMC2160Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth) {
|
||||
void tmc_init(TMCMarlin<TMC2160Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth, const chopper_timing_t &chop_init, const bool interpolate) {
|
||||
st.begin();
|
||||
|
||||
CHOPCONF_t chopconf{0};
|
||||
chopconf.tbl = 1;
|
||||
chopconf.toff = chopper_timing.toff;
|
||||
chopconf.intpol = INTERPOLATE;
|
||||
chopconf.hend = chopper_timing.hend + 3;
|
||||
chopconf.hstrt = chopper_timing.hstrt - 1;
|
||||
#if ENABLED(SQUARE_WAVE_STEPPING)
|
||||
chopconf.dedge = true;
|
||||
#endif
|
||||
chopconf.tbl = 0b01;
|
||||
chopconf.toff = chop_init.toff;
|
||||
chopconf.intpol = interpolate;
|
||||
chopconf.hend = chop_init.hend + 3;
|
||||
chopconf.hstrt = chop_init.hstrt - 1;
|
||||
TERN_(SQUARE_WAVE_STEPPING, chopconf.dedge = true);
|
||||
st.CHOPCONF(chopconf.sr);
|
||||
|
||||
st.rms_current(mA, HOLD_MULTIPLIER);
|
||||
@@ -204,11 +265,7 @@ enum StealthIndex : uint8_t { STEALTH_AXIS_XY, STEALTH_AXIS_Z, STEALTH_AXIS_E };
|
||||
pwmconf.pwm_ofs = 36;
|
||||
st.PWMCONF(pwmconf.sr);
|
||||
|
||||
#if ENABLED(HYBRID_THRESHOLD)
|
||||
st.set_pwm_thrs(hyb_thrs);
|
||||
#else
|
||||
UNUSED(hyb_thrs);
|
||||
#endif
|
||||
TERN(HYBRID_THRESHOLD, st.set_pwm_thrs(hyb_thrs), UNUSED(hyb_thrs));
|
||||
|
||||
st.GSTAT(); // Clear GSTAT
|
||||
}
|
||||
@@ -221,225 +278,323 @@ enum StealthIndex : uint8_t { STEALTH_AXIS_XY, STEALTH_AXIS_Z, STEALTH_AXIS_E };
|
||||
#if AXIS_HAS_UART(X)
|
||||
#ifdef X_HARDWARE_SERIAL
|
||||
TMC_UART_DEFINE(HW, X, X);
|
||||
#define X_HAS_HW_SERIAL 1
|
||||
#else
|
||||
TMC_UART_DEFINE(SW, X, X);
|
||||
#define X_HAS_SW_SERIAL 1
|
||||
#endif
|
||||
#endif
|
||||
#if AXIS_HAS_UART(X2)
|
||||
#ifdef X2_HARDWARE_SERIAL
|
||||
TMC_UART_DEFINE(HW, X2, X);
|
||||
#define X2_HAS_HW_SERIAL 1
|
||||
#else
|
||||
TMC_UART_DEFINE(SW, X2, X);
|
||||
#define X2_HAS_SW_SERIAL 1
|
||||
#endif
|
||||
#endif
|
||||
#if AXIS_HAS_UART(Y)
|
||||
#ifdef Y_HARDWARE_SERIAL
|
||||
TMC_UART_DEFINE(HW, Y, Y);
|
||||
#define Y_HAS_HW_SERIAL 1
|
||||
#else
|
||||
TMC_UART_DEFINE(SW, Y, Y);
|
||||
#define Y_HAS_SW_SERIAL 1
|
||||
#endif
|
||||
#endif
|
||||
#if AXIS_HAS_UART(Y2)
|
||||
#ifdef Y2_HARDWARE_SERIAL
|
||||
TMC_UART_DEFINE(HW, Y2, Y);
|
||||
#define Y2_HAS_HW_SERIAL 1
|
||||
#else
|
||||
TMC_UART_DEFINE(SW, Y2, Y);
|
||||
#define Y2_HAS_SW_SERIAL 1
|
||||
#endif
|
||||
#endif
|
||||
#if AXIS_HAS_UART(Z)
|
||||
#ifdef Z_HARDWARE_SERIAL
|
||||
TMC_UART_DEFINE(HW, Z, Z);
|
||||
#define Z_HAS_HW_SERIAL 1
|
||||
#else
|
||||
TMC_UART_DEFINE(SW, Z, Z);
|
||||
#define Z_HAS_SW_SERIAL 1
|
||||
#endif
|
||||
#endif
|
||||
#if AXIS_HAS_UART(Z2)
|
||||
#ifdef Z2_HARDWARE_SERIAL
|
||||
TMC_UART_DEFINE(HW, Z2, Z);
|
||||
#define Z2_HAS_HW_SERIAL 1
|
||||
#else
|
||||
TMC_UART_DEFINE(SW, Z2, Z);
|
||||
#define Z2_HAS_SW_SERIAL 1
|
||||
#endif
|
||||
#endif
|
||||
#if AXIS_HAS_UART(Z3)
|
||||
#ifdef Z3_HARDWARE_SERIAL
|
||||
TMC_UART_DEFINE(HW, Z3, Z);
|
||||
#define Z3_HAS_HW_SERIAL 1
|
||||
#else
|
||||
TMC_UART_DEFINE(SW, Z3, Z);
|
||||
#define Z3_HAS_SW_SERIAL 1
|
||||
#endif
|
||||
#endif
|
||||
#if AXIS_HAS_UART(Z4)
|
||||
#ifdef Z4_HARDWARE_SERIAL
|
||||
TMC_UART_DEFINE(HW, Z4, Z);
|
||||
#define Z4_HAS_HW_SERIAL 1
|
||||
#else
|
||||
TMC_UART_DEFINE(SW, Z4, Z);
|
||||
#define Z4_HAS_SW_SERIAL 1
|
||||
#endif
|
||||
#endif
|
||||
#if AXIS_HAS_UART(I)
|
||||
#ifdef I_HARDWARE_SERIAL
|
||||
TMC_UART_DEFINE(HW, I, I);
|
||||
#define I_HAS_HW_SERIAL 1
|
||||
#else
|
||||
TMC_UART_DEFINE(SW, I, I);
|
||||
#define I_HAS_SW_SERIAL 1
|
||||
#endif
|
||||
#endif
|
||||
#if AXIS_HAS_UART(J)
|
||||
#ifdef J_HARDWARE_SERIAL
|
||||
TMC_UART_DEFINE(HW, J, J);
|
||||
#define J_HAS_HW_SERIAL 1
|
||||
#else
|
||||
TMC_UART_DEFINE(SW, J, J);
|
||||
#define J_HAS_SW_SERIAL 1
|
||||
#endif
|
||||
#endif
|
||||
#if AXIS_HAS_UART(K)
|
||||
#ifdef K_HARDWARE_SERIAL
|
||||
TMC_UART_DEFINE(HW, K, K);
|
||||
#define K_HAS_HW_SERIAL 1
|
||||
#else
|
||||
TMC_UART_DEFINE(SW, K, K);
|
||||
#define K_HAS_SW_SERIAL 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if AXIS_HAS_UART(E0)
|
||||
#ifdef E0_HARDWARE_SERIAL
|
||||
TMC_UART_DEFINE_E(HW, 0);
|
||||
#define E0_HAS_HW_SERIAL 1
|
||||
#else
|
||||
TMC_UART_DEFINE_E(SW, 0);
|
||||
#define E0_HAS_SW_SERIAL 1
|
||||
#endif
|
||||
#endif
|
||||
#if AXIS_HAS_UART(E1)
|
||||
#ifdef E1_HARDWARE_SERIAL
|
||||
TMC_UART_DEFINE_E(HW, 1);
|
||||
#define E1_HAS_HW_SERIAL 1
|
||||
#else
|
||||
TMC_UART_DEFINE_E(SW, 1);
|
||||
#define E1_HAS_SW_SERIAL 1
|
||||
#endif
|
||||
#endif
|
||||
#if AXIS_HAS_UART(E2)
|
||||
#ifdef E2_HARDWARE_SERIAL
|
||||
TMC_UART_DEFINE_E(HW, 2);
|
||||
#define E2_HAS_HW_SERIAL 1
|
||||
#else
|
||||
TMC_UART_DEFINE_E(SW, 2);
|
||||
#define E2_HAS_SW_SERIAL 1
|
||||
#endif
|
||||
#endif
|
||||
#if AXIS_HAS_UART(E3)
|
||||
#ifdef E3_HARDWARE_SERIAL
|
||||
TMC_UART_DEFINE_E(HW, 3);
|
||||
#define E3_HAS_HW_SERIAL 1
|
||||
#else
|
||||
TMC_UART_DEFINE_E(SW, 3);
|
||||
#define E3_HAS_SW_SERIAL 1
|
||||
#endif
|
||||
#endif
|
||||
#if AXIS_HAS_UART(E4)
|
||||
#ifdef E4_HARDWARE_SERIAL
|
||||
TMC_UART_DEFINE_E(HW, 4);
|
||||
#define E4_HAS_HW_SERIAL 1
|
||||
#else
|
||||
TMC_UART_DEFINE_E(SW, 4);
|
||||
#define E4_HAS_SW_SERIAL 1
|
||||
#endif
|
||||
#endif
|
||||
#if AXIS_HAS_UART(E5)
|
||||
#ifdef E5_HARDWARE_SERIAL
|
||||
TMC_UART_DEFINE_E(HW, 5);
|
||||
#define E5_HAS_HW_SERIAL 1
|
||||
#else
|
||||
TMC_UART_DEFINE_E(SW, 5);
|
||||
#define E5_HAS_SW_SERIAL 1
|
||||
#endif
|
||||
#endif
|
||||
#if AXIS_HAS_UART(E6)
|
||||
#ifdef E6_HARDWARE_SERIAL
|
||||
TMC_UART_DEFINE_E(HW, 6);
|
||||
#define E6_HAS_HW_SERIAL 1
|
||||
#else
|
||||
TMC_UART_DEFINE_E(SW, 6);
|
||||
#define E6_HAS_SW_SERIAL 1
|
||||
#endif
|
||||
#endif
|
||||
#if AXIS_HAS_UART(E7)
|
||||
#ifdef E7_HARDWARE_SERIAL
|
||||
TMC_UART_DEFINE_E(HW, 7);
|
||||
#define E7_HAS_HW_SERIAL 1
|
||||
#else
|
||||
TMC_UART_DEFINE_E(SW, 7);
|
||||
#define E7_HAS_SW_SERIAL 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define _EN_ITEM(N) , E##N
|
||||
enum TMCAxis : uint8_t { LINEAR_AXIS_LIST(X, Y, Z, I, J, K), X2, Y2, Z2, Z3, Z4 REPEAT(EXTRUDERS, _EN_ITEM), TOTAL };
|
||||
#undef _EN_ITEM
|
||||
|
||||
void tmc_serial_begin() {
|
||||
#if HAS_TMC_HW_SERIAL
|
||||
struct {
|
||||
const void *ptr[TMCAxis::TOTAL];
|
||||
bool began(const TMCAxis a, const void * const p) {
|
||||
LOOP_L_N(i, a) if (p == ptr[i]) return true;
|
||||
ptr[a] = p; return false;
|
||||
};
|
||||
} sp_helper;
|
||||
|
||||
#define HW_SERIAL_BEGIN(A) do{ if (!sp_helper.began(TMCAxis::A, &A##_HARDWARE_SERIAL)) \
|
||||
A##_HARDWARE_SERIAL.begin(TMC_##A##_BAUD_RATE); }while(0)
|
||||
#endif
|
||||
|
||||
#if AXIS_HAS_UART(X)
|
||||
#ifdef X_HARDWARE_SERIAL
|
||||
X_HARDWARE_SERIAL.begin(TMC_BAUD_RATE);
|
||||
HW_SERIAL_BEGIN(X);
|
||||
#else
|
||||
stepperX.beginSerial(TMC_BAUD_RATE);
|
||||
#endif
|
||||
#endif
|
||||
#if AXIS_HAS_UART(X2)
|
||||
#ifdef X2_HARDWARE_SERIAL
|
||||
X2_HARDWARE_SERIAL.begin(TMC_BAUD_RATE);
|
||||
HW_SERIAL_BEGIN(X2);
|
||||
#else
|
||||
stepperX2.beginSerial(TMC_BAUD_RATE);
|
||||
#endif
|
||||
#endif
|
||||
#if AXIS_HAS_UART(Y)
|
||||
#ifdef Y_HARDWARE_SERIAL
|
||||
Y_HARDWARE_SERIAL.begin(TMC_BAUD_RATE);
|
||||
HW_SERIAL_BEGIN(Y);
|
||||
#else
|
||||
stepperY.beginSerial(TMC_BAUD_RATE);
|
||||
#endif
|
||||
#endif
|
||||
#if AXIS_HAS_UART(Y2)
|
||||
#ifdef Y2_HARDWARE_SERIAL
|
||||
Y2_HARDWARE_SERIAL.begin(TMC_BAUD_RATE);
|
||||
HW_SERIAL_BEGIN(Y2);
|
||||
#else
|
||||
stepperY2.beginSerial(TMC_BAUD_RATE);
|
||||
#endif
|
||||
#endif
|
||||
#if AXIS_HAS_UART(Z)
|
||||
#ifdef Z_HARDWARE_SERIAL
|
||||
Z_HARDWARE_SERIAL.begin(TMC_BAUD_RATE);
|
||||
HW_SERIAL_BEGIN(Z);
|
||||
#else
|
||||
stepperZ.beginSerial(TMC_BAUD_RATE);
|
||||
#endif
|
||||
#endif
|
||||
#if AXIS_HAS_UART(Z2)
|
||||
#ifdef Z2_HARDWARE_SERIAL
|
||||
Z2_HARDWARE_SERIAL.begin(TMC_BAUD_RATE);
|
||||
HW_SERIAL_BEGIN(Z2);
|
||||
#else
|
||||
stepperZ2.beginSerial(TMC_BAUD_RATE);
|
||||
#endif
|
||||
#endif
|
||||
#if AXIS_HAS_UART(Z3)
|
||||
#ifdef Z3_HARDWARE_SERIAL
|
||||
Z3_HARDWARE_SERIAL.begin(TMC_BAUD_RATE);
|
||||
HW_SERIAL_BEGIN(Z3);
|
||||
#else
|
||||
stepperZ3.beginSerial(TMC_BAUD_RATE);
|
||||
#endif
|
||||
#endif
|
||||
#if AXIS_HAS_UART(Z4)
|
||||
#ifdef Z4_HARDWARE_SERIAL
|
||||
Z4_HARDWARE_SERIAL.begin(TMC_BAUD_RATE);
|
||||
HW_SERIAL_BEGIN(Z4);
|
||||
#else
|
||||
stepperZ4.beginSerial(TMC_BAUD_RATE);
|
||||
#endif
|
||||
#endif
|
||||
#if AXIS_HAS_UART(I)
|
||||
#ifdef I_HARDWARE_SERIAL
|
||||
HW_SERIAL_BEGIN(I);
|
||||
#else
|
||||
stepperI.beginSerial(TMC_BAUD_RATE);
|
||||
#endif
|
||||
#endif
|
||||
#if AXIS_HAS_UART(J)
|
||||
#ifdef J_HARDWARE_SERIAL
|
||||
HW_SERIAL_BEGIN(J);
|
||||
#else
|
||||
stepperJ.beginSerial(TMC_BAUD_RATE);
|
||||
#endif
|
||||
#endif
|
||||
#if AXIS_HAS_UART(K)
|
||||
#ifdef K_HARDWARE_SERIAL
|
||||
HW_SERIAL_BEGIN(K);
|
||||
#else
|
||||
stepperK.beginSerial(TMC_BAUD_RATE);
|
||||
#endif
|
||||
#endif
|
||||
#if AXIS_HAS_UART(E0)
|
||||
#ifdef E0_HARDWARE_SERIAL
|
||||
E0_HARDWARE_SERIAL.begin(TMC_BAUD_RATE);
|
||||
HW_SERIAL_BEGIN(E0);
|
||||
#else
|
||||
stepperE0.beginSerial(TMC_BAUD_RATE);
|
||||
#endif
|
||||
#endif
|
||||
#if AXIS_HAS_UART(E1)
|
||||
#ifdef E1_HARDWARE_SERIAL
|
||||
E1_HARDWARE_SERIAL.begin(TMC_BAUD_RATE);
|
||||
HW_SERIAL_BEGIN(E1);
|
||||
#else
|
||||
stepperE1.beginSerial(TMC_BAUD_RATE);
|
||||
#endif
|
||||
#endif
|
||||
#if AXIS_HAS_UART(E2)
|
||||
#ifdef E2_HARDWARE_SERIAL
|
||||
E2_HARDWARE_SERIAL.begin(TMC_BAUD_RATE);
|
||||
HW_SERIAL_BEGIN(E2);
|
||||
#else
|
||||
stepperE2.beginSerial(TMC_BAUD_RATE);
|
||||
#endif
|
||||
#endif
|
||||
#if AXIS_HAS_UART(E3)
|
||||
#ifdef E3_HARDWARE_SERIAL
|
||||
E3_HARDWARE_SERIAL.begin(TMC_BAUD_RATE);
|
||||
HW_SERIAL_BEGIN(E3);
|
||||
#else
|
||||
stepperE3.beginSerial(TMC_BAUD_RATE);
|
||||
#endif
|
||||
#endif
|
||||
#if AXIS_HAS_UART(E4)
|
||||
#ifdef E4_HARDWARE_SERIAL
|
||||
E4_HARDWARE_SERIAL.begin(TMC_BAUD_RATE);
|
||||
HW_SERIAL_BEGIN(E4);
|
||||
#else
|
||||
stepperE4.beginSerial(TMC_BAUD_RATE);
|
||||
#endif
|
||||
#endif
|
||||
#if AXIS_HAS_UART(E5)
|
||||
#ifdef E5_HARDWARE_SERIAL
|
||||
E5_HARDWARE_SERIAL.begin(TMC_BAUD_RATE);
|
||||
HW_SERIAL_BEGIN(E5);
|
||||
#else
|
||||
stepperE5.beginSerial(TMC_BAUD_RATE);
|
||||
#endif
|
||||
#endif
|
||||
#if AXIS_HAS_UART(E6)
|
||||
#ifdef E6_HARDWARE_SERIAL
|
||||
E6_HARDWARE_SERIAL.begin(TMC_BAUD_RATE);
|
||||
HW_SERIAL_BEGIN(E6);
|
||||
#else
|
||||
stepperE6.beginSerial(TMC_BAUD_RATE);
|
||||
#endif
|
||||
#endif
|
||||
#if AXIS_HAS_UART(E7)
|
||||
#ifdef E7_HARDWARE_SERIAL
|
||||
E7_HARDWARE_SERIAL.begin(TMC_BAUD_RATE);
|
||||
HW_SERIAL_BEGIN(E7);
|
||||
#else
|
||||
stepperE7.beginSerial(TMC_BAUD_RATE);
|
||||
#endif
|
||||
@@ -449,7 +604,7 @@ enum StealthIndex : uint8_t { STEALTH_AXIS_XY, STEALTH_AXIS_Z, STEALTH_AXIS_E };
|
||||
|
||||
#if HAS_DRIVER(TMC2208)
|
||||
template<char AXIS_LETTER, char DRIVER_ID, AxisEnum AXIS_ID>
|
||||
void tmc_init(TMCMarlin<TMC2208Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth) {
|
||||
void tmc_init(TMCMarlin<TMC2208Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth, const chopper_timing_t &chop_init, const bool interpolate) {
|
||||
TMC2208_n::GCONF_t gconf{0};
|
||||
gconf.pdn_disable = true; // Use UART
|
||||
gconf.mstep_reg_select = true; // Select microsteps with UART
|
||||
@@ -460,13 +615,11 @@ enum StealthIndex : uint8_t { STEALTH_AXIS_XY, STEALTH_AXIS_Z, STEALTH_AXIS_E };
|
||||
|
||||
TMC2208_n::CHOPCONF_t chopconf{0};
|
||||
chopconf.tbl = 0b01; // blank_time = 24
|
||||
chopconf.toff = chopper_timing.toff;
|
||||
chopconf.intpol = INTERPOLATE;
|
||||
chopconf.hend = chopper_timing.hend + 3;
|
||||
chopconf.hstrt = chopper_timing.hstrt - 1;
|
||||
#if ENABLED(SQUARE_WAVE_STEPPING)
|
||||
chopconf.dedge = true;
|
||||
#endif
|
||||
chopconf.toff = chop_init.toff;
|
||||
chopconf.intpol = interpolate;
|
||||
chopconf.hend = chop_init.hend + 3;
|
||||
chopconf.hstrt = chop_init.hstrt - 1;
|
||||
TERN_(SQUARE_WAVE_STEPPING, chopconf.dedge = true);
|
||||
st.CHOPCONF(chopconf.sr);
|
||||
|
||||
st.rms_current(mA, HOLD_MULTIPLIER);
|
||||
@@ -484,11 +637,7 @@ enum StealthIndex : uint8_t { STEALTH_AXIS_XY, STEALTH_AXIS_Z, STEALTH_AXIS_E };
|
||||
pwmconf.pwm_ofs = 36;
|
||||
st.PWMCONF(pwmconf.sr);
|
||||
|
||||
#if ENABLED(HYBRID_THRESHOLD)
|
||||
st.set_pwm_thrs(hyb_thrs);
|
||||
#else
|
||||
UNUSED(hyb_thrs);
|
||||
#endif
|
||||
TERN(HYBRID_THRESHOLD, st.set_pwm_thrs(hyb_thrs), UNUSED(hyb_thrs));
|
||||
|
||||
st.GSTAT(0b111); // Clear
|
||||
delay(200);
|
||||
@@ -497,7 +646,7 @@ enum StealthIndex : uint8_t { STEALTH_AXIS_XY, STEALTH_AXIS_Z, STEALTH_AXIS_E };
|
||||
|
||||
#if HAS_DRIVER(TMC2209)
|
||||
template<char AXIS_LETTER, char DRIVER_ID, AxisEnum AXIS_ID>
|
||||
void tmc_init(TMCMarlin<TMC2209Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth) {
|
||||
void tmc_init(TMCMarlin<TMC2209Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth, const chopper_timing_t &chop_init, const bool interpolate) {
|
||||
TMC2208_n::GCONF_t gconf{0};
|
||||
gconf.pdn_disable = true; // Use UART
|
||||
gconf.mstep_reg_select = true; // Select microsteps with UART
|
||||
@@ -508,13 +657,11 @@ enum StealthIndex : uint8_t { STEALTH_AXIS_XY, STEALTH_AXIS_Z, STEALTH_AXIS_E };
|
||||
|
||||
TMC2208_n::CHOPCONF_t chopconf{0};
|
||||
chopconf.tbl = 0b01; // blank_time = 24
|
||||
chopconf.toff = chopper_timing.toff;
|
||||
chopconf.intpol = INTERPOLATE;
|
||||
chopconf.hend = chopper_timing.hend + 3;
|
||||
chopconf.hstrt = chopper_timing.hstrt - 1;
|
||||
#if ENABLED(SQUARE_WAVE_STEPPING)
|
||||
chopconf.dedge = true;
|
||||
#endif
|
||||
chopconf.toff = chop_init.toff;
|
||||
chopconf.intpol = interpolate;
|
||||
chopconf.hend = chop_init.hend + 3;
|
||||
chopconf.hstrt = chop_init.hstrt - 1;
|
||||
TERN_(SQUARE_WAVE_STEPPING, chopconf.dedge = true);
|
||||
st.CHOPCONF(chopconf.sr);
|
||||
|
||||
st.rms_current(mA, HOLD_MULTIPLIER);
|
||||
@@ -532,11 +679,7 @@ enum StealthIndex : uint8_t { STEALTH_AXIS_XY, STEALTH_AXIS_Z, STEALTH_AXIS_E };
|
||||
pwmconf.pwm_ofs = 36;
|
||||
st.PWMCONF(pwmconf.sr);
|
||||
|
||||
#if ENABLED(HYBRID_THRESHOLD)
|
||||
st.set_pwm_thrs(hyb_thrs);
|
||||
#else
|
||||
UNUSED(hyb_thrs);
|
||||
#endif
|
||||
TERN(HYBRID_THRESHOLD, st.set_pwm_thrs(hyb_thrs), UNUSED(hyb_thrs));
|
||||
|
||||
st.GSTAT(0b111); // Clear
|
||||
delay(200);
|
||||
@@ -545,45 +688,38 @@ enum StealthIndex : uint8_t { STEALTH_AXIS_XY, STEALTH_AXIS_Z, STEALTH_AXIS_E };
|
||||
|
||||
#if HAS_DRIVER(TMC2660)
|
||||
template<char AXIS_LETTER, char DRIVER_ID, AxisEnum AXIS_ID>
|
||||
void tmc_init(TMCMarlin<TMC2660Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t, const bool) {
|
||||
void tmc_init(TMCMarlin<TMC2660Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t, const bool, const chopper_timing_t &chop_init, const bool interpolate) {
|
||||
st.begin();
|
||||
|
||||
TMC2660_n::CHOPCONF_t chopconf{0};
|
||||
chopconf.tbl = 1;
|
||||
chopconf.toff = chopper_timing.toff;
|
||||
chopconf.hend = chopper_timing.hend + 3;
|
||||
chopconf.hstrt = chopper_timing.hstrt - 1;
|
||||
chopconf.tbl = 0b01;
|
||||
chopconf.toff = chop_init.toff;
|
||||
chopconf.hend = chop_init.hend + 3;
|
||||
chopconf.hstrt = chop_init.hstrt - 1;
|
||||
st.CHOPCONF(chopconf.sr);
|
||||
|
||||
st.sdoff(0);
|
||||
st.rms_current(mA);
|
||||
st.microsteps(microsteps);
|
||||
#if ENABLED(SQUARE_WAVE_STEPPING)
|
||||
st.dedge(true);
|
||||
#endif
|
||||
st.intpol(INTERPOLATE);
|
||||
TERN_(SQUARE_WAVE_STEPPING, st.dedge(true));
|
||||
st.intpol(interpolate);
|
||||
st.diss2g(true); // Disable short to ground protection. Too many false readings?
|
||||
|
||||
#if ENABLED(TMC_DEBUG)
|
||||
st.rdsel(0b01);
|
||||
#endif
|
||||
TERN_(TMC_DEBUG, st.rdsel(0b01));
|
||||
}
|
||||
#endif // TMC2660
|
||||
|
||||
#if HAS_DRIVER(TMC5130)
|
||||
template<char AXIS_LETTER, char DRIVER_ID, AxisEnum AXIS_ID>
|
||||
void tmc_init(TMCMarlin<TMC5130Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth) {
|
||||
void tmc_init(TMCMarlin<TMC5130Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth, const chopper_timing_t &chop_init, const bool interpolate) {
|
||||
st.begin();
|
||||
|
||||
CHOPCONF_t chopconf{0};
|
||||
chopconf.tbl = 1;
|
||||
chopconf.toff = chopper_timing.toff;
|
||||
chopconf.intpol = INTERPOLATE;
|
||||
chopconf.hend = chopper_timing.hend + 3;
|
||||
chopconf.hstrt = chopper_timing.hstrt - 1;
|
||||
#if ENABLED(SQUARE_WAVE_STEPPING)
|
||||
chopconf.dedge = true;
|
||||
#endif
|
||||
chopconf.tbl = 0b01;
|
||||
chopconf.toff = chop_init.toff;
|
||||
chopconf.intpol = interpolate;
|
||||
chopconf.hend = chop_init.hend + 3;
|
||||
chopconf.hstrt = chop_init.hstrt - 1;
|
||||
TERN_(SQUARE_WAVE_STEPPING, chopconf.dedge = true);
|
||||
st.CHOPCONF(chopconf.sr);
|
||||
|
||||
st.rms_current(mA, HOLD_MULTIPLIER);
|
||||
@@ -601,11 +737,7 @@ enum StealthIndex : uint8_t { STEALTH_AXIS_XY, STEALTH_AXIS_Z, STEALTH_AXIS_E };
|
||||
pwmconf.pwm_ampl = 180;
|
||||
st.PWMCONF(pwmconf.sr);
|
||||
|
||||
#if ENABLED(HYBRID_THRESHOLD)
|
||||
st.set_pwm_thrs(hyb_thrs);
|
||||
#else
|
||||
UNUSED(hyb_thrs);
|
||||
#endif
|
||||
TERN(HYBRID_THRESHOLD, st.set_pwm_thrs(hyb_thrs), UNUSED(hyb_thrs));
|
||||
|
||||
st.GSTAT(); // Clear GSTAT
|
||||
}
|
||||
@@ -613,18 +745,16 @@ enum StealthIndex : uint8_t { STEALTH_AXIS_XY, STEALTH_AXIS_Z, STEALTH_AXIS_E };
|
||||
|
||||
#if HAS_DRIVER(TMC5160)
|
||||
template<char AXIS_LETTER, char DRIVER_ID, AxisEnum AXIS_ID>
|
||||
void tmc_init(TMCMarlin<TMC5160Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth) {
|
||||
void tmc_init(TMCMarlin<TMC5160Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth, const chopper_timing_t &chop_init, const bool interpolate) {
|
||||
st.begin();
|
||||
|
||||
CHOPCONF_t chopconf{0};
|
||||
chopconf.tbl = 1;
|
||||
chopconf.toff = chopper_timing.toff;
|
||||
chopconf.intpol = INTERPOLATE;
|
||||
chopconf.hend = chopper_timing.hend + 3;
|
||||
chopconf.hstrt = chopper_timing.hstrt - 1;
|
||||
#if ENABLED(SQUARE_WAVE_STEPPING)
|
||||
chopconf.dedge = true;
|
||||
#endif
|
||||
chopconf.tbl = 0b01;
|
||||
chopconf.toff = chop_init.toff;
|
||||
chopconf.intpol = interpolate;
|
||||
chopconf.hend = chop_init.hend + 3;
|
||||
chopconf.hstrt = chop_init.hstrt - 1;
|
||||
TERN_(SQUARE_WAVE_STEPPING, chopconf.dedge = true);
|
||||
st.CHOPCONF(chopconf.sr);
|
||||
|
||||
st.rms_current(mA, HOLD_MULTIPLIER);
|
||||
@@ -645,11 +775,7 @@ enum StealthIndex : uint8_t { STEALTH_AXIS_XY, STEALTH_AXIS_Z, STEALTH_AXIS_E };
|
||||
pwmconf.pwm_ofs = 36;
|
||||
st.PWMCONF(pwmconf.sr);
|
||||
|
||||
#if ENABLED(HYBRID_THRESHOLD)
|
||||
st.set_pwm_thrs(hyb_thrs);
|
||||
#else
|
||||
UNUSED(hyb_thrs);
|
||||
#endif
|
||||
TERN(HYBRID_THRESHOLD, st.set_pwm_thrs(hyb_thrs), UNUSED(hyb_thrs));
|
||||
st.GSTAT(); // Clear GSTAT
|
||||
}
|
||||
#endif // TMC5160
|
||||
@@ -679,6 +805,15 @@ void restore_trinamic_drivers() {
|
||||
#if AXIS_IS_TMC(Z4)
|
||||
stepperZ4.push();
|
||||
#endif
|
||||
#if AXIS_IS_TMC(I)
|
||||
stepperI.push();
|
||||
#endif
|
||||
#if AXIS_IS_TMC(J)
|
||||
stepperJ.push();
|
||||
#endif
|
||||
#if AXIS_IS_TMC(K)
|
||||
stepperK.push();
|
||||
#endif
|
||||
#if AXIS_IS_TMC(E0)
|
||||
stepperE0.push();
|
||||
#endif
|
||||
@@ -706,37 +841,23 @@ void restore_trinamic_drivers() {
|
||||
}
|
||||
|
||||
void reset_trinamic_drivers() {
|
||||
static constexpr bool stealthchop_by_axis[] = {
|
||||
#if ENABLED(STEALTHCHOP_XY)
|
||||
true
|
||||
#else
|
||||
false
|
||||
#endif
|
||||
,
|
||||
#if ENABLED(STEALTHCHOP_Z)
|
||||
true
|
||||
#else
|
||||
false
|
||||
#endif
|
||||
,
|
||||
#if ENABLED(STEALTHCHOP_E)
|
||||
true
|
||||
#else
|
||||
false
|
||||
#endif
|
||||
};
|
||||
static constexpr bool stealthchop_by_axis[] = LOGICAL_AXIS_ARRAY(
|
||||
ENABLED(STEALTHCHOP_E),
|
||||
ENABLED(STEALTHCHOP_XY), ENABLED(STEALTHCHOP_XY), ENABLED(STEALTHCHOP_Z),
|
||||
ENABLED(STEALTHCHOP_I), ENABLED(STEALTHCHOP_J), ENABLED(STEALTHCHOP_K)
|
||||
);
|
||||
|
||||
#if AXIS_IS_TMC(X)
|
||||
TMC_INIT(X, STEALTH_AXIS_XY);
|
||||
TMC_INIT(X, STEALTH_AXIS_X);
|
||||
#endif
|
||||
#if AXIS_IS_TMC(X2)
|
||||
TMC_INIT(X2, STEALTH_AXIS_XY);
|
||||
TMC_INIT(X2, STEALTH_AXIS_X);
|
||||
#endif
|
||||
#if AXIS_IS_TMC(Y)
|
||||
TMC_INIT(Y, STEALTH_AXIS_XY);
|
||||
TMC_INIT(Y, STEALTH_AXIS_Y);
|
||||
#endif
|
||||
#if AXIS_IS_TMC(Y2)
|
||||
TMC_INIT(Y2, STEALTH_AXIS_XY);
|
||||
TMC_INIT(Y2, STEALTH_AXIS_Y);
|
||||
#endif
|
||||
#if AXIS_IS_TMC(Z)
|
||||
TMC_INIT(Z, STEALTH_AXIS_Z);
|
||||
@@ -750,6 +871,15 @@ void reset_trinamic_drivers() {
|
||||
#if AXIS_IS_TMC(Z4)
|
||||
TMC_INIT(Z4, STEALTH_AXIS_Z);
|
||||
#endif
|
||||
#if AXIS_IS_TMC(I)
|
||||
TMC_INIT(I, STEALTH_AXIS_I);
|
||||
#endif
|
||||
#if AXIS_IS_TMC(J)
|
||||
TMC_INIT(J, STEALTH_AXIS_J);
|
||||
#endif
|
||||
#if AXIS_IS_TMC(K)
|
||||
TMC_INIT(K, STEALTH_AXIS_K);
|
||||
#endif
|
||||
#if AXIS_IS_TMC(E0)
|
||||
TMC_INIT(E0, STEALTH_AXIS_E);
|
||||
#endif
|
||||
@@ -777,39 +907,48 @@ void reset_trinamic_drivers() {
|
||||
|
||||
#if USE_SENSORLESS
|
||||
#if X_SENSORLESS
|
||||
#if AXIS_HAS_STALLGUARD(X)
|
||||
stepperX.homing_threshold(X_STALL_SENSITIVITY);
|
||||
stepperX.homing_threshold(X_STALL_SENSITIVITY);
|
||||
#if AXIS_HAS_STALLGUARD(X2)
|
||||
stepperX2.homing_threshold(CAT(TERN(X2_SENSORLESS, X2, X), _STALL_SENSITIVITY));
|
||||
#endif
|
||||
#if AXIS_HAS_STALLGUARD(X2) && !X2_SENSORLESS
|
||||
stepperX2.homing_threshold(X_STALL_SENSITIVITY);
|
||||
#endif
|
||||
#endif
|
||||
#if X2_SENSORLESS
|
||||
stepperX2.homing_threshold(X2_STALL_SENSITIVITY);
|
||||
#endif
|
||||
#if Y_SENSORLESS
|
||||
#if AXIS_HAS_STALLGUARD(Y)
|
||||
stepperY.homing_threshold(Y_STALL_SENSITIVITY);
|
||||
#endif
|
||||
stepperY.homing_threshold(Y_STALL_SENSITIVITY);
|
||||
#if AXIS_HAS_STALLGUARD(Y2)
|
||||
stepperY2.homing_threshold(Y_STALL_SENSITIVITY);
|
||||
stepperY2.homing_threshold(CAT(TERN(Y2_SENSORLESS, Y2, Y), _STALL_SENSITIVITY));
|
||||
#endif
|
||||
#endif
|
||||
#if Z_SENSORLESS
|
||||
#if AXIS_HAS_STALLGUARD(Z)
|
||||
stepperZ.homing_threshold(Z_STALL_SENSITIVITY);
|
||||
#endif
|
||||
stepperZ.homing_threshold(Z_STALL_SENSITIVITY);
|
||||
#if AXIS_HAS_STALLGUARD(Z2)
|
||||
stepperZ2.homing_threshold(Z_STALL_SENSITIVITY);
|
||||
stepperZ2.homing_threshold(CAT(TERN(Z2_SENSORLESS, Z2, Z), _STALL_SENSITIVITY));
|
||||
#endif
|
||||
#if AXIS_HAS_STALLGUARD(Z3)
|
||||
stepperZ3.homing_threshold(Z_STALL_SENSITIVITY);
|
||||
stepperZ3.homing_threshold(CAT(TERN(Z3_SENSORLESS, Z3, Z), _STALL_SENSITIVITY));
|
||||
#endif
|
||||
#if AXIS_HAS_STALLGUARD(Z4)
|
||||
stepperZ4.homing_threshold(Z_STALL_SENSITIVITY);
|
||||
stepperZ4.homing_threshold(CAT(TERN(Z4_SENSORLESS, Z4, Z), _STALL_SENSITIVITY));
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#if I_SENSORLESS
|
||||
stepperI.homing_threshold(I_STALL_SENSITIVITY);
|
||||
#if AXIS_HAS_STALLGUARD(I)
|
||||
stepperI.homing_threshold(CAT(TERN(I_SENSORLESS, I, I), _STALL_SENSITIVITY));
|
||||
#endif
|
||||
#endif
|
||||
#if J_SENSORLESS
|
||||
stepperJ.homing_threshold(J_STALL_SENSITIVITY);
|
||||
#if AXIS_HAS_STALLGUARD(J)
|
||||
stepperJ.homing_threshold(CAT(TERN(J_SENSORLESS, J, J), _STALL_SENSITIVITY));
|
||||
#endif
|
||||
#endif
|
||||
#if K_SENSORLESS
|
||||
stepperK.homing_threshold(K_STALL_SENSITIVITY);
|
||||
#if AXIS_HAS_STALLGUARD(K)
|
||||
stepperK.homing_threshold(CAT(TERN(K_SENSORLESS, K, K), _STALL_SENSITIVITY));
|
||||
#endif
|
||||
#endif
|
||||
#endif // USE SENSORLESS
|
||||
|
||||
#ifdef TMC_ADV
|
||||
TMC_ADV()
|
||||
@@ -818,4 +957,81 @@ void reset_trinamic_drivers() {
|
||||
stepper.set_directions();
|
||||
}
|
||||
|
||||
// TMC Slave Address Conflict Detection
|
||||
//
|
||||
// Conflict detection is performed in the following way. Similar methods are used for
|
||||
// hardware and software serial, but the implementations are independent.
|
||||
//
|
||||
// 1. Populate a data structure with UART parameters and addresses for all possible axis.
|
||||
// If an axis is not in use, populate it with recognizable placeholder data.
|
||||
// 2. For each axis in use, static_assert using a constexpr function, which counts the
|
||||
// number of matching/conflicting axis. If the value is not exactly 1, fail.
|
||||
|
||||
#if ANY_AXIS_HAS(HW_SERIAL)
|
||||
// Hardware serial names are compared as strings, since actually resolving them cannot occur in a constexpr.
|
||||
// Using a fixed-length character array for the port name allows this to be constexpr compatible.
|
||||
struct SanityHwSerialDetails { const char port[20]; uint32_t address; };
|
||||
#define TMC_HW_DETAIL_ARGS(A) TERN(A##_HAS_HW_SERIAL, STRINGIFY(A##_HARDWARE_SERIAL), ""), TERN0(A##_HAS_HW_SERIAL, A##_SLAVE_ADDRESS)
|
||||
#define TMC_HW_DETAIL(A) { TMC_HW_DETAIL_ARGS(A) }
|
||||
constexpr SanityHwSerialDetails sanity_tmc_hw_details[] = {
|
||||
TMC_HW_DETAIL(X), TMC_HW_DETAIL(X2),
|
||||
TMC_HW_DETAIL(Y), TMC_HW_DETAIL(Y2),
|
||||
TMC_HW_DETAIL(Z), TMC_HW_DETAIL(Z2), TMC_HW_DETAIL(Z3), TMC_HW_DETAIL(Z4),
|
||||
TMC_HW_DETAIL(I), TMC_HW_DETAIL(J), TMC_HW_DETAIL(K),
|
||||
TMC_HW_DETAIL(E0), TMC_HW_DETAIL(E1), TMC_HW_DETAIL(E2), TMC_HW_DETAIL(E3), TMC_HW_DETAIL(E4), TMC_HW_DETAIL(E5), TMC_HW_DETAIL(E6), TMC_HW_DETAIL(E7)
|
||||
};
|
||||
|
||||
// constexpr compatible string comparison
|
||||
constexpr bool str_eq_ce(const char * a, const char * b) {
|
||||
return *a == *b && (*a == '\0' || str_eq_ce(a+1,b+1));
|
||||
}
|
||||
|
||||
constexpr bool sc_hw_done(size_t start, size_t end) { return start == end; }
|
||||
constexpr bool sc_hw_skip(const char *port_name) { return !(*port_name); }
|
||||
constexpr bool sc_hw_match(const char *port_name, uint32_t address, size_t start, size_t end) {
|
||||
return !sc_hw_done(start, end) && !sc_hw_skip(port_name) && (address == sanity_tmc_hw_details[start].address && str_eq_ce(port_name, sanity_tmc_hw_details[start].port));
|
||||
}
|
||||
constexpr int count_tmc_hw_serial_matches(const char *port_name, uint32_t address, size_t start, size_t end) {
|
||||
return sc_hw_done(start, end) ? 0 : ((sc_hw_skip(port_name) ? 0 : (sc_hw_match(port_name, address, start, end) ? 1 : 0)) + count_tmc_hw_serial_matches(port_name, address, start + 1, end));
|
||||
}
|
||||
|
||||
#define TMC_HWSERIAL_CONFLICT_MSG(A) STRINGIFY(A) "_SLAVE_ADDRESS conflicts with another driver using the same " STRINGIFY(A) "_HARDWARE_SERIAL"
|
||||
#define SA_NO_TMC_HW_C(A) static_assert(1 >= count_tmc_hw_serial_matches(TMC_HW_DETAIL_ARGS(A), 0, COUNT(sanity_tmc_hw_details)), TMC_HWSERIAL_CONFLICT_MSG(A));
|
||||
SA_NO_TMC_HW_C(X); SA_NO_TMC_HW_C(X2);
|
||||
SA_NO_TMC_HW_C(Y); SA_NO_TMC_HW_C(Y2);
|
||||
SA_NO_TMC_HW_C(Z); SA_NO_TMC_HW_C(Z2); SA_NO_TMC_HW_C(Z3); SA_NO_TMC_HW_C(Z4);
|
||||
SA_NO_TMC_HW_C(I); SA_NO_TMC_HW_C(J); SA_NO_TMC_HW_C(K);
|
||||
SA_NO_TMC_HW_C(E0); SA_NO_TMC_HW_C(E1); SA_NO_TMC_HW_C(E2); SA_NO_TMC_HW_C(E3); SA_NO_TMC_HW_C(E4); SA_NO_TMC_HW_C(E5); SA_NO_TMC_HW_C(E6); SA_NO_TMC_HW_C(E7);
|
||||
#endif
|
||||
|
||||
#if ANY_AXIS_HAS(SW_SERIAL)
|
||||
struct SanitySwSerialDetails { int32_t txpin; int32_t rxpin; uint32_t address; };
|
||||
#define TMC_SW_DETAIL_ARGS(A) TERN(A##_HAS_SW_SERIAL, A##_SERIAL_TX_PIN, -1), TERN(A##_HAS_SW_SERIAL, A##_SERIAL_RX_PIN, -1), TERN0(A##_HAS_SW_SERIAL, A##_SLAVE_ADDRESS)
|
||||
#define TMC_SW_DETAIL(A) TMC_SW_DETAIL_ARGS(A)
|
||||
constexpr SanitySwSerialDetails sanity_tmc_sw_details[] = {
|
||||
TMC_SW_DETAIL(X), TMC_SW_DETAIL(X2),
|
||||
TMC_SW_DETAIL(Y), TMC_SW_DETAIL(Y2),
|
||||
TMC_SW_DETAIL(Z), TMC_SW_DETAIL(Z2), TMC_SW_DETAIL(Z3), TMC_SW_DETAIL(Z4),
|
||||
TMC_SW_DETAIL(I), TMC_SW_DETAIL(J), TMC_SW_DETAIL(K),
|
||||
TMC_SW_DETAIL(E0), TMC_SW_DETAIL(E1), TMC_SW_DETAIL(E2), TMC_SW_DETAIL(E3), TMC_SW_DETAIL(E4), TMC_SW_DETAIL(E5), TMC_SW_DETAIL(E6), TMC_SW_DETAIL(E7)
|
||||
};
|
||||
|
||||
constexpr bool sc_sw_done(size_t start, size_t end) { return start == end; }
|
||||
constexpr bool sc_sw_skip(int32_t txpin) { return txpin < 0; }
|
||||
constexpr bool sc_sw_match(int32_t txpin, int32_t rxpin, uint32_t address, size_t start, size_t end) {
|
||||
return !sc_sw_done(start, end) && !sc_sw_skip(txpin) && (txpin == sanity_tmc_sw_details[start].txpin || rxpin == sanity_tmc_sw_details[start].rxpin) && (address == sanity_tmc_sw_details[start].address);
|
||||
}
|
||||
constexpr int count_tmc_sw_serial_matches(int32_t txpin, int32_t rxpin, uint32_t address, size_t start, size_t end) {
|
||||
return sc_sw_done(start, end) ? 0 : ((sc_sw_skip(txpin) ? 0 : (sc_sw_match(txpin, rxpin, address, start, end) ? 1 : 0)) + count_tmc_sw_serial_matches(txpin, rxpin, address, start + 1, end));
|
||||
}
|
||||
|
||||
#define TMC_SWSERIAL_CONFLICT_MSG(A) STRINGIFY(A) "_SLAVE_ADDRESS conflicts with another driver using the same " STRINGIFY(A) "_SERIAL_RX_PIN or " STRINGIFY(A) "_SERIAL_TX_PIN"
|
||||
#define SA_NO_TMC_SW_C(A) static_assert(1 >= count_tmc_sw_serial_matches(TMC_SW_DETAIL_ARGS(A), 0, COUNT(sanity_tmc_sw_details)), TMC_SWSERIAL_CONFLICT_MSG(A));
|
||||
SA_NO_TMC_SW_C(X); SA_NO_TMC_SW_C(X2);
|
||||
SA_NO_TMC_SW_C(Y); SA_NO_TMC_SW_C(Y2);
|
||||
SA_NO_TMC_SW_C(Z); SA_NO_TMC_SW_C(Z2); SA_NO_TMC_SW_C(Z3); SA_NO_TMC_SW_C(Z4);
|
||||
SA_NO_TMC_SW_C(I); SA_NO_TMC_SW_C(J); SA_NO_TMC_SW_C(K);
|
||||
SA_NO_TMC_SW_C(E0); SA_NO_TMC_SW_C(E1); SA_NO_TMC_SW_C(E2); SA_NO_TMC_SW_C(E3); SA_NO_TMC_SW_C(E4); SA_NO_TMC_SW_C(E5); SA_NO_TMC_SW_C(E6); SA_NO_TMC_SW_C(E7);
|
||||
#endif
|
||||
|
||||
#endif // HAS_TRINAMIC_CONFIG
|
||||
|
205
Marlin/src/module/stepper/trinamic.h
Executable file → Normal file
205
Marlin/src/module/stepper/trinamic.h
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@@ -46,6 +46,10 @@
|
||||
#define TMC_Y_LABEL 'Y', '0'
|
||||
#define TMC_Z_LABEL 'Z', '0'
|
||||
|
||||
#define TMC_I_LABEL 'I', '0'
|
||||
#define TMC_J_LABEL 'J', '0'
|
||||
#define TMC_K_LABEL 'K', '0'
|
||||
|
||||
#define TMC_X2_LABEL 'X', '2'
|
||||
#define TMC_Y2_LABEL 'Y', '2'
|
||||
#define TMC_Z2_LABEL 'Z', '2'
|
||||
@@ -76,7 +80,27 @@ typedef struct {
|
||||
uint8_t hstrt;
|
||||
} chopper_timing_t;
|
||||
|
||||
static constexpr chopper_timing_t chopper_timing = CHOPPER_TIMING;
|
||||
#ifndef CHOPPER_TIMING_X
|
||||
#define CHOPPER_TIMING_X CHOPPER_TIMING
|
||||
#endif
|
||||
#if HAS_Y_AXIS && !defined(CHOPPER_TIMING_Y)
|
||||
#define CHOPPER_TIMING_Y CHOPPER_TIMING
|
||||
#endif
|
||||
#if HAS_Z_AXIS && !defined(CHOPPER_TIMING_Z)
|
||||
#define CHOPPER_TIMING_Z CHOPPER_TIMING
|
||||
#endif
|
||||
#if LINEAR_AXES >= 4 && !defined(CHOPPER_TIMING_I)
|
||||
#define CHOPPER_TIMING_I CHOPPER_TIMING
|
||||
#endif
|
||||
#if LINEAR_AXES >= 5 && !defined(CHOPPER_TIMING_J)
|
||||
#define CHOPPER_TIMING_J CHOPPER_TIMING
|
||||
#endif
|
||||
#if LINEAR_AXES >= 6 && !defined(CHOPPER_TIMING_K)
|
||||
#define CHOPPER_TIMING_K CHOPPER_TIMING
|
||||
#endif
|
||||
#if HAS_EXTRUDERS && !defined(CHOPPER_TIMING_E)
|
||||
#define CHOPPER_TIMING_E CHOPPER_TIMING
|
||||
#endif
|
||||
|
||||
#if HAS_TMC220x
|
||||
void tmc_serial_begin();
|
||||
@@ -90,22 +114,24 @@ void reset_trinamic_drivers();
|
||||
// X Stepper
|
||||
#if AXIS_IS_TMC(X)
|
||||
extern TMC_CLASS(X, X) stepperX;
|
||||
static constexpr chopper_timing_t chopper_timing_X = CHOPPER_TIMING_X;
|
||||
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
|
||||
#define X_ENABLE_INIT() NOOP
|
||||
#define X_ENABLE_WRITE(STATE) stepperX.toff((STATE)==X_ENABLE_ON ? chopper_timing.toff : 0)
|
||||
#define X_ENABLE_WRITE(STATE) stepperX.toff((STATE)==X_ENABLE_ON ? chopper_timing_X.toff : 0)
|
||||
#define X_ENABLE_READ() stepperX.isEnabled()
|
||||
#endif
|
||||
#if AXIS_HAS_SQUARE_WAVE(X)
|
||||
#define X_STEP_WRITE(STATE) do{ if(STATE) TOGGLE(X_STEP_PIN); }while(0)
|
||||
#define X_STEP_WRITE(STATE) do{ if (STATE) TOGGLE(X_STEP_PIN); }while(0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Y Stepper
|
||||
#if AXIS_IS_TMC(Y)
|
||||
extern TMC_CLASS(Y, Y) stepperY;
|
||||
static constexpr chopper_timing_t chopper_timing_Y = CHOPPER_TIMING_Y;
|
||||
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
|
||||
#define Y_ENABLE_INIT() NOOP
|
||||
#define Y_ENABLE_WRITE(STATE) stepperY.toff((STATE)==Y_ENABLE_ON ? chopper_timing.toff : 0)
|
||||
#define Y_ENABLE_WRITE(STATE) stepperY.toff((STATE)==Y_ENABLE_ON ? chopper_timing_Y.toff : 0)
|
||||
#define Y_ENABLE_READ() stepperY.isEnabled()
|
||||
#endif
|
||||
#if AXIS_HAS_SQUARE_WAVE(Y)
|
||||
@@ -116,181 +142,276 @@ void reset_trinamic_drivers();
|
||||
// Z Stepper
|
||||
#if AXIS_IS_TMC(Z)
|
||||
extern TMC_CLASS(Z, Z) stepperZ;
|
||||
static constexpr chopper_timing_t chopper_timing_Z = CHOPPER_TIMING_Z;
|
||||
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
|
||||
#define Z_ENABLE_INIT() NOOP
|
||||
#define Z_ENABLE_WRITE(STATE) stepperZ.toff((STATE)==Z_ENABLE_ON ? chopper_timing.toff : 0)
|
||||
#define Z_ENABLE_WRITE(STATE) stepperZ.toff((STATE)==Z_ENABLE_ON ? chopper_timing_Z.toff : 0)
|
||||
#define Z_ENABLE_READ() stepperZ.isEnabled()
|
||||
#endif
|
||||
#if AXIS_HAS_SQUARE_WAVE(Z)
|
||||
#define Z_STEP_WRITE(STATE) do{ if(STATE) TOGGLE(Z_STEP_PIN); }while(0)
|
||||
#define Z_STEP_WRITE(STATE) do{ if (STATE) TOGGLE(Z_STEP_PIN); }while(0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// X2 Stepper
|
||||
#if HAS_X2_ENABLE && AXIS_IS_TMC(X2)
|
||||
extern TMC_CLASS(X2, X) stepperX2;
|
||||
#ifndef CHOPPER_TIMING_X2
|
||||
#define CHOPPER_TIMING_X2 CHOPPER_TIMING_X
|
||||
#endif
|
||||
static constexpr chopper_timing_t chopper_timing_X2 = CHOPPER_TIMING_X2;
|
||||
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
|
||||
#define X2_ENABLE_INIT() NOOP
|
||||
#define X2_ENABLE_WRITE(STATE) stepperX2.toff((STATE)==X_ENABLE_ON ? chopper_timing.toff : 0)
|
||||
#define X2_ENABLE_WRITE(STATE) stepperX2.toff((STATE)==X_ENABLE_ON ? chopper_timing_X2.toff : 0)
|
||||
#define X2_ENABLE_READ() stepperX2.isEnabled()
|
||||
#endif
|
||||
#if AXIS_HAS_SQUARE_WAVE(X2)
|
||||
#define X2_STEP_WRITE(STATE) do{ if(STATE) TOGGLE(X2_STEP_PIN); }while(0)
|
||||
#define X2_STEP_WRITE(STATE) do{ if (STATE) TOGGLE(X2_STEP_PIN); }while(0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Y2 Stepper
|
||||
#if HAS_Y2_ENABLE && AXIS_IS_TMC(Y2)
|
||||
extern TMC_CLASS(Y2, Y) stepperY2;
|
||||
#ifndef CHOPPER_TIMING_Y2
|
||||
#define CHOPPER_TIMING_Y2 CHOPPER_TIMING_Y
|
||||
#endif
|
||||
static constexpr chopper_timing_t chopper_timing_Y2 = CHOPPER_TIMING_Y2;
|
||||
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
|
||||
#define Y2_ENABLE_INIT() NOOP
|
||||
#define Y2_ENABLE_WRITE(STATE) stepperY2.toff((STATE)==Y_ENABLE_ON ? chopper_timing.toff : 0)
|
||||
#define Y2_ENABLE_WRITE(STATE) stepperY2.toff((STATE)==Y_ENABLE_ON ? chopper_timing_Y2.toff : 0)
|
||||
#define Y2_ENABLE_READ() stepperY2.isEnabled()
|
||||
#endif
|
||||
#if AXIS_HAS_SQUARE_WAVE(Y2)
|
||||
#define Y2_STEP_WRITE(STATE) do{ if(STATE) TOGGLE(Y2_STEP_PIN); }while(0)
|
||||
#define Y2_STEP_WRITE(STATE) do{ if (STATE) TOGGLE(Y2_STEP_PIN); }while(0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Z2 Stepper
|
||||
#if HAS_Z2_ENABLE && AXIS_IS_TMC(Z2)
|
||||
extern TMC_CLASS(Z2, Z) stepperZ2;
|
||||
#if ENABLED(SOFTWARE_DRIVER_ENABLE) && AXIS_IS_TMC(Z2)
|
||||
#ifndef CHOPPER_TIMING_Z2
|
||||
#define CHOPPER_TIMING_Z2 CHOPPER_TIMING_Z
|
||||
#endif
|
||||
static constexpr chopper_timing_t chopper_timing_Z2 = CHOPPER_TIMING_Z2;
|
||||
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
|
||||
#define Z2_ENABLE_INIT() NOOP
|
||||
#define Z2_ENABLE_WRITE(STATE) stepperZ2.toff((STATE)==Z_ENABLE_ON ? chopper_timing.toff : 0)
|
||||
#define Z2_ENABLE_WRITE(STATE) stepperZ2.toff((STATE)==Z_ENABLE_ON ? chopper_timing_Z2.toff : 0)
|
||||
#define Z2_ENABLE_READ() stepperZ2.isEnabled()
|
||||
#endif
|
||||
#if AXIS_HAS_SQUARE_WAVE(Z2)
|
||||
#define Z2_STEP_WRITE(STATE) do{ if(STATE) TOGGLE(Z2_STEP_PIN); }while(0)
|
||||
#define Z2_STEP_WRITE(STATE) do{ if (STATE) TOGGLE(Z2_STEP_PIN); }while(0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Z3 Stepper
|
||||
#if HAS_Z3_ENABLE && AXIS_IS_TMC(Z3)
|
||||
extern TMC_CLASS(Z3, Z) stepperZ3;
|
||||
#ifndef CHOPPER_TIMING_Z3
|
||||
#define CHOPPER_TIMING_Z3 CHOPPER_TIMING_Z
|
||||
#endif
|
||||
static constexpr chopper_timing_t chopper_timing_Z3 = CHOPPER_TIMING_Z3;
|
||||
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
|
||||
#define Z3_ENABLE_INIT() NOOP
|
||||
#define Z3_ENABLE_WRITE(STATE) stepperZ3.toff((STATE)==Z_ENABLE_ON ? chopper_timing.toff : 0)
|
||||
#define Z3_ENABLE_WRITE(STATE) stepperZ3.toff((STATE)==Z_ENABLE_ON ? chopper_timing_Z3.toff : 0)
|
||||
#define Z3_ENABLE_READ() stepperZ3.isEnabled()
|
||||
#endif
|
||||
#if AXIS_HAS_SQUARE_WAVE(Z3)
|
||||
#define Z3_STEP_WRITE(STATE) do{ if(STATE) TOGGLE(Z3_STEP_PIN); }while(0)
|
||||
#define Z3_STEP_WRITE(STATE) do{ if (STATE) TOGGLE(Z3_STEP_PIN); }while(0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Z4 Stepper
|
||||
#if HAS_Z4_ENABLE && AXIS_IS_TMC(Z4)
|
||||
extern TMC_CLASS(Z4, Z) stepperZ4;
|
||||
#ifndef CHOPPER_TIMING_Z4
|
||||
#define CHOPPER_TIMING_Z4 CHOPPER_TIMING_Z
|
||||
#endif
|
||||
static constexpr chopper_timing_t chopper_timing_Z4 = CHOPPER_TIMING_Z4;
|
||||
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
|
||||
#define Z4_ENABLE_INIT() NOOP
|
||||
#define Z4_ENABLE_WRITE(STATE) stepperZ4.toff((STATE)==Z_ENABLE_ON ? chopper_timing.toff : 0)
|
||||
#define Z4_ENABLE_WRITE(STATE) stepperZ4.toff((STATE)==Z_ENABLE_ON ? chopper_timing_Z4.toff : 0)
|
||||
#define Z4_ENABLE_READ() stepperZ4.isEnabled()
|
||||
#endif
|
||||
#if AXIS_HAS_SQUARE_WAVE(Z4)
|
||||
#define Z4_STEP_WRITE(STATE) do{ if(STATE) TOGGLE(Z4_STEP_PIN); }while(0)
|
||||
#define Z4_STEP_WRITE(STATE) do{ if (STATE) TOGGLE(Z4_STEP_PIN); }while(0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// I Stepper
|
||||
#if AXIS_IS_TMC(I)
|
||||
extern TMC_CLASS(I, I) stepperI;
|
||||
static constexpr chopper_timing_t chopper_timing_I = CHOPPER_TIMING_I;
|
||||
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
|
||||
#define I_ENABLE_INIT() NOOP
|
||||
#define I_ENABLE_WRITE(STATE) stepperI.toff((STATE)==I_ENABLE_ON ? chopper_timing.toff : 0)
|
||||
#define I_ENABLE_READ() stepperI.isEnabled()
|
||||
#endif
|
||||
#if AXIS_HAS_SQUARE_WAVE(I)
|
||||
#define I_STEP_WRITE(STATE) do{ if (STATE) TOGGLE(I_STEP_PIN); }while(0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// J Stepper
|
||||
#if AXIS_IS_TMC(J)
|
||||
extern TMC_CLASS(J, J) stepperJ;
|
||||
static constexpr chopper_timing_t chopper_timing_J = CHOPPER_TIMING_J;
|
||||
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
|
||||
#define J_ENABLE_INIT() NOOP
|
||||
#define J_ENABLE_WRITE(STATE) stepperJ.toff((STATE)==J_ENABLE_ON ? chopper_timing.toff : 0)
|
||||
#define J_ENABLE_READ() stepperJ.isEnabled()
|
||||
#endif
|
||||
#if AXIS_HAS_SQUARE_WAVE(J)
|
||||
#define J_STEP_WRITE(STATE) do{ if (STATE) TOGGLE(J_STEP_PIN); }while(0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// K Stepper
|
||||
#if AXIS_IS_TMC(K)
|
||||
extern TMC_CLASS(K, K) stepperK;
|
||||
static constexpr chopper_timing_t chopper_timing_K = CHOPPER_TIMING_K;
|
||||
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
|
||||
#define K_ENABLE_INIT() NOOP
|
||||
#define K_ENABLE_WRITE(STATE) stepperK.toff((STATE)==K_ENABLE_ON ? chopper_timing.toff : 0)
|
||||
#define K_ENABLE_READ() stepperK.isEnabled()
|
||||
#endif
|
||||
#if AXIS_HAS_SQUARE_WAVE(K)
|
||||
#define K_STEP_WRITE(STATE) do{ if (STATE) TOGGLE(K_STEP_PIN); }while(0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// E0 Stepper
|
||||
#if AXIS_IS_TMC(E0)
|
||||
extern TMC_CLASS_E(0) stepperE0;
|
||||
#if ENABLED(SOFTWARE_DRIVER_ENABLE) && AXIS_IS_TMC(E0)
|
||||
#ifndef CHOPPER_TIMING_E0
|
||||
#define CHOPPER_TIMING_E0 CHOPPER_TIMING_E
|
||||
#endif
|
||||
static constexpr chopper_timing_t chopper_timing_E0 = CHOPPER_TIMING_E0;
|
||||
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
|
||||
#define E0_ENABLE_INIT() NOOP
|
||||
#define E0_ENABLE_WRITE(STATE) stepperE0.toff((STATE)==E_ENABLE_ON ? chopper_timing.toff : 0)
|
||||
#define E0_ENABLE_WRITE(STATE) stepperE0.toff((STATE)==E_ENABLE_ON ? chopper_timing_E0.toff : 0)
|
||||
#define E0_ENABLE_READ() stepperE0.isEnabled()
|
||||
#endif
|
||||
#if AXIS_HAS_SQUARE_WAVE(E0)
|
||||
#define E0_STEP_WRITE(STATE) do{ if(STATE) TOGGLE(E0_STEP_PIN); }while(0)
|
||||
#define E0_STEP_WRITE(STATE) do{ if (STATE) TOGGLE(E0_STEP_PIN); }while(0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// E1 Stepper
|
||||
#if AXIS_IS_TMC(E1)
|
||||
extern TMC_CLASS_E(1) stepperE1;
|
||||
#if ENABLED(SOFTWARE_DRIVER_ENABLE) && AXIS_IS_TMC(E1)
|
||||
#ifndef CHOPPER_TIMING_E1
|
||||
#define CHOPPER_TIMING_E1 CHOPPER_TIMING_E
|
||||
#endif
|
||||
static constexpr chopper_timing_t chopper_timing_E1 = CHOPPER_TIMING_E1;
|
||||
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
|
||||
#define E1_ENABLE_INIT() NOOP
|
||||
#define E1_ENABLE_WRITE(STATE) stepperE1.toff((STATE)==E_ENABLE_ON ? chopper_timing.toff : 0)
|
||||
#define E1_ENABLE_WRITE(STATE) stepperE1.toff((STATE)==E_ENABLE_ON ? chopper_timing_E1.toff : 0)
|
||||
#define E1_ENABLE_READ() stepperE1.isEnabled()
|
||||
#endif
|
||||
#if AXIS_HAS_SQUARE_WAVE(E1)
|
||||
#define E1_STEP_WRITE(STATE) do{ if(STATE) TOGGLE(E1_STEP_PIN); }while(0)
|
||||
#define E1_STEP_WRITE(STATE) do{ if (STATE) TOGGLE(E1_STEP_PIN); }while(0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// E2 Stepper
|
||||
#if AXIS_IS_TMC(E2)
|
||||
extern TMC_CLASS_E(2) stepperE2;
|
||||
#if ENABLED(SOFTWARE_DRIVER_ENABLE) && AXIS_IS_TMC(E2)
|
||||
#ifndef CHOPPER_TIMING_E2
|
||||
#define CHOPPER_TIMING_E2 CHOPPER_TIMING_E
|
||||
#endif
|
||||
static constexpr chopper_timing_t chopper_timing_E2 = CHOPPER_TIMING_E2;
|
||||
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
|
||||
#define E2_ENABLE_INIT() NOOP
|
||||
#define E2_ENABLE_WRITE(STATE) stepperE2.toff((STATE)==E_ENABLE_ON ? chopper_timing.toff : 0)
|
||||
#define E2_ENABLE_WRITE(STATE) stepperE2.toff((STATE)==E_ENABLE_ON ? chopper_timing_E2.toff : 0)
|
||||
#define E2_ENABLE_READ() stepperE2.isEnabled()
|
||||
#endif
|
||||
#if AXIS_HAS_SQUARE_WAVE(E2)
|
||||
#define E2_STEP_WRITE(STATE) do{ if(STATE) TOGGLE(E2_STEP_PIN); }while(0)
|
||||
#define E2_STEP_WRITE(STATE) do{ if (STATE) TOGGLE(E2_STEP_PIN); }while(0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// E3 Stepper
|
||||
#if AXIS_IS_TMC(E3)
|
||||
extern TMC_CLASS_E(3) stepperE3;
|
||||
#if ENABLED(SOFTWARE_DRIVER_ENABLE) && AXIS_IS_TMC(E3)
|
||||
#ifndef CHOPPER_TIMING_E3
|
||||
#define CHOPPER_TIMING_E3 CHOPPER_TIMING_E
|
||||
#endif
|
||||
static constexpr chopper_timing_t chopper_timing_E3 = CHOPPER_TIMING_E3;
|
||||
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
|
||||
#define E3_ENABLE_INIT() NOOP
|
||||
#define E3_ENABLE_WRITE(STATE) stepperE3.toff((STATE)==E_ENABLE_ON ? chopper_timing.toff : 0)
|
||||
#define E3_ENABLE_WRITE(STATE) stepperE3.toff((STATE)==E_ENABLE_ON ? chopper_timing_E3.toff : 0)
|
||||
#define E3_ENABLE_READ() stepperE3.isEnabled()
|
||||
#endif
|
||||
#if AXIS_HAS_SQUARE_WAVE(E3)
|
||||
#define E3_STEP_WRITE(STATE) do{ if(STATE) TOGGLE(E3_STEP_PIN); }while(0)
|
||||
#define E3_STEP_WRITE(STATE) do{ if (STATE) TOGGLE(E3_STEP_PIN); }while(0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// E4 Stepper
|
||||
#if AXIS_IS_TMC(E4)
|
||||
extern TMC_CLASS_E(4) stepperE4;
|
||||
#if ENABLED(SOFTWARE_DRIVER_ENABLE) && AXIS_IS_TMC(E4)
|
||||
#ifndef CHOPPER_TIMING_E4
|
||||
#define CHOPPER_TIMING_E4 CHOPPER_TIMING_E
|
||||
#endif
|
||||
static constexpr chopper_timing_t chopper_timing_E4 = CHOPPER_TIMING_E4;
|
||||
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
|
||||
#define E4_ENABLE_INIT() NOOP
|
||||
#define E4_ENABLE_WRITE(STATE) stepperE4.toff((STATE)==E_ENABLE_ON ? chopper_timing.toff : 0)
|
||||
#define E4_ENABLE_WRITE(STATE) stepperE4.toff((STATE)==E_ENABLE_ON ? chopper_timing_E4.toff : 0)
|
||||
#define E4_ENABLE_READ() stepperE4.isEnabled()
|
||||
#endif
|
||||
#if AXIS_HAS_SQUARE_WAVE(E4)
|
||||
#define E4_STEP_WRITE(STATE) do{ if(STATE) TOGGLE(E4_STEP_PIN); }while(0)
|
||||
#define E4_STEP_WRITE(STATE) do{ if (STATE) TOGGLE(E4_STEP_PIN); }while(0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// E5 Stepper
|
||||
#if AXIS_IS_TMC(E5)
|
||||
extern TMC_CLASS_E(5) stepperE5;
|
||||
#if ENABLED(SOFTWARE_DRIVER_ENABLE) && AXIS_IS_TMC(E5)
|
||||
#ifndef CHOPPER_TIMING_E5
|
||||
#define CHOPPER_TIMING_E5 CHOPPER_TIMING_E
|
||||
#endif
|
||||
static constexpr chopper_timing_t chopper_timing_E5 = CHOPPER_TIMING_E5;
|
||||
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
|
||||
#define E5_ENABLE_INIT() NOOP
|
||||
#define E5_ENABLE_WRITE(STATE) stepperE5.toff((STATE)==E_ENABLE_ON ? chopper_timing.toff : 0)
|
||||
#define E5_ENABLE_WRITE(STATE) stepperE5.toff((STATE)==E_ENABLE_ON ? chopper_timing_E5.toff : 0)
|
||||
#define E5_ENABLE_READ() stepperE5.isEnabled()
|
||||
#endif
|
||||
#if AXIS_HAS_SQUARE_WAVE(E5)
|
||||
#define E5_STEP_WRITE(STATE) do{ if(STATE) TOGGLE(E5_STEP_PIN); }while(0)
|
||||
#define E5_STEP_WRITE(STATE) do{ if (STATE) TOGGLE(E5_STEP_PIN); }while(0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// E6 Stepper
|
||||
#if AXIS_IS_TMC(E6)
|
||||
extern TMC_CLASS_E(6) stepperE6;
|
||||
#if ENABLED(SOFTWARE_DRIVER_ENABLE) && AXIS_IS_TMC(E6)
|
||||
#ifndef CHOPPER_TIMING_E6
|
||||
#define CHOPPER_TIMING_E6 CHOPPER_TIMING_E
|
||||
#endif
|
||||
static constexpr chopper_timing_t chopper_timing_E6 = CHOPPER_TIMING_E6;
|
||||
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
|
||||
#define E6_ENABLE_INIT() NOOP
|
||||
#define E6_ENABLE_WRITE(STATE) stepperE6.toff((STATE)==E_ENABLE_ON ? chopper_timing.toff : 0)
|
||||
#define E6_ENABLE_WRITE(STATE) stepperE6.toff((STATE)==E_ENABLE_ON ? chopper_timing_E6.toff : 0)
|
||||
#define E6_ENABLE_READ() stepperE6.isEnabled()
|
||||
#endif
|
||||
#if AXIS_HAS_SQUARE_WAVE(E6)
|
||||
#define E6_STEP_WRITE(STATE) do{ if(STATE) TOGGLE(E6_STEP_PIN); }while(0)
|
||||
#define E6_STEP_WRITE(STATE) do{ if (STATE) TOGGLE(E6_STEP_PIN); }while(0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// E7 Stepper
|
||||
#if AXIS_IS_TMC(E7)
|
||||
extern TMC_CLASS_E(7) stepperE7;
|
||||
#if ENABLED(SOFTWARE_DRIVER_ENABLE) && AXIS_IS_TMC(E7)
|
||||
#ifndef CHOPPER_TIMING_E7
|
||||
#define CHOPPER_TIMING_E7 CHOPPER_TIMING_E
|
||||
#endif
|
||||
static constexpr chopper_timing_t chopper_timing_E7 = CHOPPER_TIMING_E7;
|
||||
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
|
||||
#define E7_ENABLE_INIT() NOOP
|
||||
#define E7_ENABLE_WRITE(STATE) stepperE7.toff((STATE)==E_ENABLE_ON ? chopper_timing.toff : 0)
|
||||
#define E7_ENABLE_WRITE(STATE) stepperE7.toff((STATE)==E_ENABLE_ON ? chopper_timing_E7.toff : 0)
|
||||
#define E7_ENABLE_READ() stepperE7.isEnabled()
|
||||
#endif
|
||||
#if AXIS_HAS_SQUARE_WAVE(E7)
|
||||
#define E7_STEP_WRITE(STATE) do{ if(STATE) TOGGLE(E7_STEP_PIN); }while(0)
|
||||
#define E7_STEP_WRITE(STATE) do{ if (STATE) TOGGLE(E7_STEP_PIN); }while(0)
|
||||
#endif
|
||||
#endif
|
||||
|
3423
Marlin/src/module/temperature.cpp
Executable file → Normal file
3423
Marlin/src/module/temperature.cpp
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
747
Marlin/src/module/temperature.h
Executable file → Normal file
747
Marlin/src/module/temperature.h
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
4
Marlin/src/module/thermistor/thermistor_1.h
Executable file → Normal file
4
Marlin/src/module/thermistor/thermistor_1.h
Executable file → Normal file
@@ -16,13 +16,13 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// R25 = 100 kOhm, beta25 = 4092 K, 4.7 kOhm pull-up, bed thermistor
|
||||
const short temptable_1[][2] PROGMEM = {
|
||||
constexpr temp_entry_t temptable_1[] PROGMEM = {
|
||||
{ OV( 23), 300 },
|
||||
{ OV( 25), 295 },
|
||||
{ OV( 27), 290 },
|
||||
|
4
Marlin/src/module/thermistor/thermistor_10.h
Executable file → Normal file
4
Marlin/src/module/thermistor/thermistor_10.h
Executable file → Normal file
@@ -16,13 +16,13 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// R25 = 100 kOhm, beta25 = 3960 K, 4.7 kOhm pull-up, RS thermistor 198-961
|
||||
const short temptable_10[][2] PROGMEM = {
|
||||
constexpr temp_entry_t temptable_10[] PROGMEM = {
|
||||
{ OV( 1), 929 },
|
||||
{ OV( 36), 299 },
|
||||
{ OV( 71), 246 },
|
||||
|
6
Marlin/src/module/thermistor/thermistor_1010.h
Executable file → Normal file
6
Marlin/src/module/thermistor/thermistor_1010.h
Executable file → Normal file
@@ -16,13 +16,15 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#define REVERSE_TEMP_SENSOR_RANGE_1010 1
|
||||
|
||||
// Pt1000 with 1k0 pullup
|
||||
const short temptable_1010[][2] PROGMEM = {
|
||||
constexpr temp_entry_t temptable_1010[] PROGMEM = {
|
||||
PtLine( 0, 1000, 1000),
|
||||
PtLine( 25, 1000, 1000),
|
||||
PtLine( 50, 1000, 1000),
|
||||
|
12
Marlin/src/module/thermistor/thermistor_1047.h
Executable file → Normal file
12
Marlin/src/module/thermistor/thermistor_1047.h
Executable file → Normal file
@@ -16,13 +16,15 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#define REVERSE_TEMP_SENSOR_RANGE_1047 1
|
||||
|
||||
// Pt1000 with 4k7 pullup
|
||||
const short temptable_1047[][2] PROGMEM = {
|
||||
constexpr temp_entry_t temptable_1047[] PROGMEM = {
|
||||
// only a few values are needed as the curve is very flat
|
||||
PtLine( 0, 1000, 4700),
|
||||
PtLine( 50, 1000, 4700),
|
||||
@@ -30,5 +32,9 @@ const short temptable_1047[][2] PROGMEM = {
|
||||
PtLine(150, 1000, 4700),
|
||||
PtLine(200, 1000, 4700),
|
||||
PtLine(250, 1000, 4700),
|
||||
PtLine(300, 1000, 4700)
|
||||
PtLine(300, 1000, 4700),
|
||||
PtLine(350, 1000, 4700),
|
||||
PtLine(400, 1000, 4700),
|
||||
PtLine(450, 1000, 4700),
|
||||
PtLine(500, 1000, 4700)
|
||||
};
|
||||
|
4
Marlin/src/module/thermistor/thermistor_11.h
Executable file → Normal file
4
Marlin/src/module/thermistor/thermistor_11.h
Executable file → Normal file
@@ -16,13 +16,13 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// R25 = 100 kOhm, beta25 = 3950 K, 4.7 kOhm pull-up, QU-BD silicone bed QWG-104F-3950 thermistor
|
||||
const short temptable_11[][2] PROGMEM = {
|
||||
constexpr temp_entry_t temptable_11[] PROGMEM = {
|
||||
{ OV( 1), 938 },
|
||||
{ OV( 31), 314 },
|
||||
{ OV( 41), 290 },
|
||||
|
6
Marlin/src/module/thermistor/thermistor_110.h
Executable file → Normal file
6
Marlin/src/module/thermistor/thermistor_110.h
Executable file → Normal file
@@ -16,13 +16,15 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#define REVERSE_TEMP_SENSOR_RANGE_110 1
|
||||
|
||||
// Pt100 with 1k0 pullup
|
||||
const short temptable_110[][2] PROGMEM = {
|
||||
constexpr temp_entry_t temptable_110[] PROGMEM = {
|
||||
// only a few values are needed as the curve is very flat
|
||||
PtLine( 0, 100, 1000),
|
||||
PtLine( 50, 100, 1000),
|
||||
|
4
Marlin/src/module/thermistor/thermistor_12.h
Executable file → Normal file
4
Marlin/src/module/thermistor/thermistor_12.h
Executable file → Normal file
@@ -16,13 +16,13 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// R25 = 100 kOhm, beta25 = 4700 K, 4.7 kOhm pull-up, (personal calibration for Makibox hot bed)
|
||||
const short temptable_12[][2] PROGMEM = {
|
||||
constexpr temp_entry_t temptable_12[] PROGMEM = {
|
||||
{ OV( 35), 180 }, // top rating 180C
|
||||
{ OV( 211), 140 },
|
||||
{ OV( 233), 135 },
|
||||
|
4
Marlin/src/module/thermistor/thermistor_13.h
Executable file → Normal file
4
Marlin/src/module/thermistor/thermistor_13.h
Executable file → Normal file
@@ -16,13 +16,13 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// R25 = 100 kOhm, beta25 = 4100 K, 4.7 kOhm pull-up, Hisens thermistor
|
||||
const short temptable_13[][2] PROGMEM = {
|
||||
constexpr temp_entry_t temptable_13[] PROGMEM = {
|
||||
{ OV( 20.04), 300 },
|
||||
{ OV( 23.19), 290 },
|
||||
{ OV( 26.71), 280 },
|
||||
|
6
Marlin/src/module/thermistor/thermistor_147.h
Executable file → Normal file
6
Marlin/src/module/thermistor/thermistor_147.h
Executable file → Normal file
@@ -16,13 +16,15 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#define REVERSE_TEMP_SENSOR_RANGE_147 1
|
||||
|
||||
// Pt100 with 4k7 pullup
|
||||
const short temptable_147[][2] PROGMEM = {
|
||||
constexpr temp_entry_t temptable_147[] PROGMEM = {
|
||||
// only a few values are needed as the curve is very flat
|
||||
PtLine( 0, 100, 4700),
|
||||
PtLine( 50, 100, 4700),
|
||||
|
4
Marlin/src/module/thermistor/thermistor_15.h
Executable file → Normal file
4
Marlin/src/module/thermistor/thermistor_15.h
Executable file → Normal file
@@ -16,13 +16,13 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// 100k bed thermistor in JGAurora A5. Calibrated by Sam Pinches 21st Jan 2018 using cheap k-type thermocouple inserted into heater block, using TM-902C meter.
|
||||
const short temptable_15[][2] PROGMEM = {
|
||||
constexpr temp_entry_t temptable_15[] PROGMEM = {
|
||||
{ OV( 31), 275 },
|
||||
{ OV( 33), 270 },
|
||||
{ OV( 35), 260 },
|
||||
|
78
Marlin/src/module/thermistor/thermistor_17.h
Normal file
78
Marlin/src/module/thermistor/thermistor_17.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2020 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 <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// Dagoma NTC 100k white thermistor
|
||||
constexpr temp_entry_t temptable_17[] PROGMEM = {
|
||||
{ OV( 16), 309 },
|
||||
{ OV( 18), 307 },
|
||||
{ OV( 20), 300 },
|
||||
{ OV( 22), 293 },
|
||||
{ OV( 26), 284 },
|
||||
{ OV( 29), 272 },
|
||||
{ OV( 33), 266 },
|
||||
{ OV( 36), 260 },
|
||||
{ OV( 42), 252 },
|
||||
{ OV( 46), 247 },
|
||||
{ OV( 48), 244 },
|
||||
{ OV( 51), 241 },
|
||||
{ OV( 62), 231 },
|
||||
{ OV( 73), 222 },
|
||||
{ OV( 78), 219 },
|
||||
{ OV( 87), 212 },
|
||||
{ OV( 98), 207 },
|
||||
{ OV( 109), 201 },
|
||||
{ OV( 118), 197 },
|
||||
{ OV( 131), 191 },
|
||||
{ OV( 145), 186 },
|
||||
{ OV( 160), 181 },
|
||||
{ OV( 177), 175 },
|
||||
{ OV( 203), 169 },
|
||||
{ OV( 222), 164 },
|
||||
{ OV( 256), 156 },
|
||||
{ OV( 283), 151 },
|
||||
{ OV( 312), 145 },
|
||||
{ OV( 343), 140 },
|
||||
{ OV( 377), 131 },
|
||||
{ OV( 413), 125 },
|
||||
{ OV( 454), 119 },
|
||||
{ OV( 496), 113 },
|
||||
{ OV( 537), 108 },
|
||||
{ OV( 578), 102 },
|
||||
{ OV( 619), 97 },
|
||||
{ OV( 658), 92 },
|
||||
{ OV( 695), 87 },
|
||||
{ OV( 735), 81 },
|
||||
{ OV( 773), 75 },
|
||||
{ OV( 808), 70 },
|
||||
{ OV( 844), 64 },
|
||||
{ OV( 868), 59 },
|
||||
{ OV( 892), 54 },
|
||||
{ OV( 914), 49 },
|
||||
{ OV( 935), 42 },
|
||||
{ OV( 951), 38 },
|
||||
{ OV( 967), 32 },
|
||||
{ OV( 975), 28 },
|
||||
{ OV(1000), 20 },
|
||||
{ OV(1010), 10 },
|
||||
{ OV(1024), -273 } // for safety
|
||||
};
|
4
Marlin/src/module/thermistor/thermistor_18.h
Executable file → Normal file
4
Marlin/src/module/thermistor/thermistor_18.h
Executable file → Normal file
@@ -16,13 +16,13 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// ATC Semitec 204GT-2 (4.7k pullup) Dagoma.Fr - MKS_Base_DKU001327 - version (measured/tested/approved)
|
||||
const short temptable_18[][2] PROGMEM = {
|
||||
constexpr temp_entry_t temptable_18[] PROGMEM = {
|
||||
{ OV( 1), 713 },
|
||||
{ OV( 17), 284 },
|
||||
{ OV( 20), 275 },
|
||||
|
6
Marlin/src/module/thermistor/thermistor_2.h
Executable file → Normal file
6
Marlin/src/module/thermistor/thermistor_2.h
Executable file → Normal file
@@ -16,17 +16,17 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
//
|
||||
// R25 = 200 kOhm, beta25 = 4338 K, 4.7 kOhm pull-up, ATC Semitec 204GT-2
|
||||
// Verified by linagee. Source: http://shop.arcol.hu/static/datasheets/thermistors.pdf
|
||||
// Verified by linagee. Source: https://www.mouser.com/datasheet/2/362/semitec%20usa%20corporation_gtthermistor-1202937.pdf
|
||||
// Calculated using 4.7kohm pullup, voltage divider math, and manufacturer provided temp/resistance
|
||||
//
|
||||
const short temptable_2[][2] PROGMEM = {
|
||||
constexpr temp_entry_t temptable_2[] PROGMEM = {
|
||||
{ OV( 1), 848 },
|
||||
{ OV( 30), 300 }, // top rating 300C
|
||||
{ OV( 34), 290 },
|
||||
|
6
Marlin/src/module/thermistor/thermistor_20.h
Executable file → Normal file
6
Marlin/src/module/thermistor/thermistor_20.h
Executable file → Normal file
@@ -16,15 +16,15 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#define REVERSE_TEMP_SENSOR_RANGE
|
||||
#define REVERSE_TEMP_SENSOR_RANGE_20 1
|
||||
|
||||
// Pt100 with INA826 amp on Ultimaker v2.0 electronics
|
||||
const short temptable_20[][2] PROGMEM = {
|
||||
constexpr temp_entry_t temptable_20[] PROGMEM = {
|
||||
{ OV( 0), 0 },
|
||||
{ OV(227), 1 },
|
||||
{ OV(236), 10 },
|
||||
|
60
Marlin/src/module/thermistor/thermistor_2000.h
Normal file
60
Marlin/src/module/thermistor/thermistor_2000.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2021 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 <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// R25 = 100 KOhm, beta25 = 4550 K, 4.7 kOhm pull-up, TDK NTCG104LH104KT1 https://product.tdk.com/en/search/sensor/ntc/chip-ntc-thermistor/info?part_no=NTCG104LH104KT1
|
||||
constexpr temp_entry_t temptable_2000[] PROGMEM = {
|
||||
{ OV(313), 125 },
|
||||
{ OV(347), 120 },
|
||||
{ OV(383), 115 },
|
||||
{ OV(422), 110 },
|
||||
{ OV(463), 105 },
|
||||
{ OV(506), 100 },
|
||||
{ OV(549), 95 },
|
||||
{ OV(594), 90 },
|
||||
{ OV(638), 85 },
|
||||
{ OV(681), 80 },
|
||||
{ OV(722), 75 },
|
||||
{ OV(762), 70 },
|
||||
{ OV(799), 65 },
|
||||
{ OV(833), 60 },
|
||||
{ OV(863), 55 },
|
||||
{ OV(890), 50 },
|
||||
{ OV(914), 45 },
|
||||
{ OV(934), 40 },
|
||||
{ OV(951), 35 },
|
||||
{ OV(966), 30 },
|
||||
{ OV(978), 25 },
|
||||
{ OV(988), 20 },
|
||||
{ OV(996), 15 },
|
||||
{ OV(1002), 10 },
|
||||
{ OV(1007), 5 },
|
||||
{ OV(1012), 0 },
|
||||
{ OV(1015), -5 },
|
||||
{ OV(1017), -10 },
|
||||
{ OV(1019), -15 },
|
||||
{ OV(1020), -20 },
|
||||
{ OV(1021), -25 },
|
||||
{ OV(1022), -30 },
|
||||
{ OV(1023), -35 },
|
||||
{ OV(1023), -40 }
|
||||
};
|
6
Marlin/src/module/thermistor/thermistor_201.h
Executable file → Normal file
6
Marlin/src/module/thermistor/thermistor_201.h
Executable file → Normal file
@@ -16,15 +16,15 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#define REVERSE_TEMP_SENSOR_RANGE
|
||||
#define REVERSE_TEMP_SENSOR_RANGE_201 1
|
||||
|
||||
// Pt100 with LMV324 amp on Overlord v1.1 electronics
|
||||
const short temptable_201[][2] PROGMEM = {
|
||||
constexpr temp_entry_t temptable_201[] PROGMEM = {
|
||||
{ OV( 0), 0 },
|
||||
{ OV( 8), 1 },
|
||||
{ OV( 23), 6 },
|
||||
|
2
Marlin/src/module/thermistor/thermistor_202.h
Executable file → Normal file
2
Marlin/src/module/thermistor/thermistor_202.h
Executable file → Normal file
@@ -3,7 +3,7 @@
|
||||
// Temptable sent from dealer technologyoutlet.co.uk
|
||||
//
|
||||
|
||||
const short temptable_202[][2] PROGMEM = {
|
||||
constexpr temp_entry_t temptable_202[] PROGMEM = {
|
||||
{ OV( 1), 864 },
|
||||
{ OV( 35), 300 },
|
||||
{ OV( 38), 295 },
|
||||
|
9
Marlin/src/module/thermistor/thermistor_21.h
Executable file → Normal file
9
Marlin/src/module/thermistor/thermistor_21.h
Executable file → Normal file
@@ -16,18 +16,19 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#define REVERSE_TEMP_SENSOR_RANGE
|
||||
#define REVERSE_TEMP_SENSOR_RANGE_21 1
|
||||
|
||||
#undef OV_SCALE
|
||||
#define OV_SCALE(N) (float((N) * 5) / 3.3f)
|
||||
|
||||
// Pt100 with INA826 amp with 3.3v excitation based on "Pt100 with INA826 amp on Ultimaker v2.0 electronics"
|
||||
const short temptable_21[][2] PROGMEM = {
|
||||
// Pt100 with INA826 amplifier board with 5v supply based on Thermistor 20, with 3v3 ADC reference on the mainboard.
|
||||
// If the ADC reference and INA826 board supply voltage are identical, Thermistor 20 instead.
|
||||
constexpr temp_entry_t temptable_21[] PROGMEM = {
|
||||
{ OV( 0), 0 },
|
||||
{ OV(227), 1 },
|
||||
{ OV(236), 10 },
|
||||
|
72
Marlin/src/module/thermistor/thermistor_22.h
Normal file
72
Marlin/src/module/thermistor/thermistor_22.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2020 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 <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
// 100k hotend thermistor with 4.7k pull up to 3.3v and 220R to analog input as in GTM32 Pro vB
|
||||
constexpr temp_entry_t temptable_22[] PROGMEM = {
|
||||
{ OV( 1), 352 },
|
||||
{ OV( 6), 341 },
|
||||
{ OV( 11), 330 },
|
||||
{ OV( 16), 319 },
|
||||
{ OV( 20), 307 },
|
||||
{ OV( 26), 296 },
|
||||
{ OV( 31), 285 },
|
||||
{ OV( 40), 274 },
|
||||
{ OV( 51), 263 },
|
||||
{ OV( 61), 251 },
|
||||
{ OV( 72), 245 },
|
||||
{ OV( 77), 240 },
|
||||
{ OV( 82), 237 },
|
||||
{ OV( 87), 232 },
|
||||
{ OV( 91), 229 },
|
||||
{ OV( 94), 227 },
|
||||
{ OV( 97), 225 },
|
||||
{ OV( 100), 223 },
|
||||
{ OV( 104), 221 },
|
||||
{ OV( 108), 219 },
|
||||
{ OV( 115), 214 },
|
||||
{ OV( 126), 209 },
|
||||
{ OV( 137), 204 },
|
||||
{ OV( 147), 200 },
|
||||
{ OV( 158), 193 },
|
||||
{ OV( 167), 192 },
|
||||
{ OV( 177), 189 },
|
||||
{ OV( 197), 163 },
|
||||
{ OV( 230), 174 },
|
||||
{ OV( 267), 165 },
|
||||
{ OV( 310), 158 },
|
||||
{ OV( 336), 151 },
|
||||
{ OV( 379), 143 },
|
||||
{ OV( 413), 138 },
|
||||
{ OV( 480), 127 },
|
||||
{ OV( 580), 110 },
|
||||
{ OV( 646), 100 },
|
||||
{ OV( 731), 88 },
|
||||
{ OV( 768), 84 },
|
||||
{ OV( 861), 69 },
|
||||
{ OV( 935), 50 },
|
||||
{ OV( 975), 38 },
|
||||
{ OV(1001), 27 },
|
||||
{ OV(1011), 22 },
|
||||
{ OV(1015), 13 },
|
||||
{ OV(1020), 6 },
|
||||
{ OV(1023), 0 }
|
||||
};
|
128
Marlin/src/module/thermistor/thermistor_23.h
Normal file
128
Marlin/src/module/thermistor/thermistor_23.h
Normal file
@@ -0,0 +1,128 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2020 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 <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
// 100k hotbed thermistor with 4.7k pull up to 3.3v and 220R to analog input as in GTM32 Pro vB
|
||||
constexpr temp_entry_t temptable_23[] PROGMEM = {
|
||||
{ OV( 1), 938 },
|
||||
{ OV( 11), 423 },
|
||||
{ OV( 21), 351 },
|
||||
{ OV( 31), 314 },
|
||||
{ OV( 41), 290 },
|
||||
{ OV( 51), 272 },
|
||||
{ OV( 61), 258 },
|
||||
{ OV( 71), 247 },
|
||||
{ OV( 81), 237 },
|
||||
{ OV( 91), 229 },
|
||||
{ OV( 101), 221 },
|
||||
{ OV( 111), 215 },
|
||||
{ OV( 121), 209 },
|
||||
{ OV( 131), 204 },
|
||||
{ OV( 141), 199 },
|
||||
{ OV( 151), 195 },
|
||||
{ OV( 161), 190 },
|
||||
{ OV( 171), 187 },
|
||||
{ OV( 181), 183 },
|
||||
{ OV( 191), 179 },
|
||||
{ OV( 201), 176 },
|
||||
{ OV( 211), 173 },
|
||||
{ OV( 221), 170 },
|
||||
{ OV( 231), 167 },
|
||||
{ OV( 241), 165 },
|
||||
{ OV( 251), 162 },
|
||||
{ OV( 261), 160 },
|
||||
{ OV( 271), 157 },
|
||||
{ OV( 281), 155 },
|
||||
{ OV( 291), 153 },
|
||||
{ OV( 301), 150 },
|
||||
{ OV( 311), 148 },
|
||||
{ OV( 321), 146 },
|
||||
{ OV( 331), 144 },
|
||||
{ OV( 341), 142 },
|
||||
{ OV( 351), 140 },
|
||||
{ OV( 361), 139 },
|
||||
{ OV( 371), 137 },
|
||||
{ OV( 381), 135 },
|
||||
{ OV( 391), 133 },
|
||||
{ OV( 401), 131 },
|
||||
{ OV( 411), 130 },
|
||||
{ OV( 421), 128 },
|
||||
{ OV( 431), 126 },
|
||||
{ OV( 441), 125 },
|
||||
{ OV( 451), 123 },
|
||||
{ OV( 461), 122 },
|
||||
{ OV( 471), 120 },
|
||||
{ OV( 481), 119 },
|
||||
{ OV( 491), 117 },
|
||||
{ OV( 501), 116 },
|
||||
{ OV( 511), 114 },
|
||||
{ OV( 521), 113 },
|
||||
{ OV( 531), 111 },
|
||||
{ OV( 541), 110 },
|
||||
{ OV( 551), 108 },
|
||||
{ OV( 561), 107 },
|
||||
{ OV( 571), 105 },
|
||||
{ OV( 581), 104 },
|
||||
{ OV( 591), 102 },
|
||||
{ OV( 601), 101 },
|
||||
{ OV( 611), 100 },
|
||||
{ OV( 621), 98 },
|
||||
{ OV( 631), 97 },
|
||||
{ OV( 641), 95 },
|
||||
{ OV( 651), 94 },
|
||||
{ OV( 661), 92 },
|
||||
{ OV( 671), 91 },
|
||||
{ OV( 681), 90 },
|
||||
{ OV( 691), 88 },
|
||||
{ OV( 701), 87 },
|
||||
{ OV( 711), 85 },
|
||||
{ OV( 721), 84 },
|
||||
{ OV( 731), 82 },
|
||||
{ OV( 741), 81 },
|
||||
{ OV( 751), 79 },
|
||||
{ OV( 761), 77 },
|
||||
{ OV( 771), 76 },
|
||||
{ OV( 781), 74 },
|
||||
{ OV( 791), 72 },
|
||||
{ OV( 801), 71 },
|
||||
{ OV( 811), 69 },
|
||||
{ OV( 821), 67 },
|
||||
{ OV( 831), 65 },
|
||||
{ OV( 841), 63 },
|
||||
{ OV( 851), 62 },
|
||||
{ OV( 861), 60 },
|
||||
{ OV( 871), 57 },
|
||||
{ OV( 881), 55 },
|
||||
{ OV( 891), 53 },
|
||||
{ OV( 901), 51 },
|
||||
{ OV( 911), 48 },
|
||||
{ OV( 921), 45 },
|
||||
{ OV( 931), 42 },
|
||||
{ OV( 941), 39 },
|
||||
{ OV( 951), 36 },
|
||||
{ OV( 961), 32 },
|
||||
{ OV( 971), 28 },
|
||||
{ OV( 981), 25 },
|
||||
{ OV( 991), 23 },
|
||||
{ OV(1001), 21 },
|
||||
{ OV(1011), 19 },
|
||||
{ OV(1021), 5 }
|
||||
};
|
4
Marlin/src/module/thermistor/thermistor_3.h
Executable file → Normal file
4
Marlin/src/module/thermistor/thermistor_3.h
Executable file → Normal file
@@ -16,13 +16,13 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// R25 = 100 kOhm, beta25 = 4120 K, 4.7 kOhm pull-up, mendel-parts
|
||||
const short temptable_3[][2] PROGMEM = {
|
||||
constexpr temp_entry_t temptable_3[] PROGMEM = {
|
||||
{ OV( 1), 864 },
|
||||
{ OV( 21), 300 },
|
||||
{ OV( 25), 290 },
|
||||
|
66
Marlin/src/module/thermistor/thermistor_30.h
Normal file
66
Marlin/src/module/thermistor/thermistor_30.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2020 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 <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// R25 = 100 kOhm, beta25 = 3950 K, 4.7 kOhm pull-up
|
||||
// Resistance 100k Ohms at 25deg. C
|
||||
// Resistance Tolerance + / -1%
|
||||
// B Value 3950K at 25/50 deg. C
|
||||
// B Value Tolerance + / - 1%
|
||||
// Kis3d Silicone Heater 24V 200W/300W with 6mm Precision cast plate (EN AW 5083)
|
||||
// Temperature setting time 10 min to determine the 12Bit ADC value on the surface. (le3tspeak)
|
||||
constexpr temp_entry_t temptable_30[] PROGMEM = {
|
||||
{ OV( 1), 938 },
|
||||
{ OV( 298), 125 }, // 1193 - 125°
|
||||
{ OV( 321), 121 }, // 1285 - 121°
|
||||
{ OV( 348), 117 }, // 1392 - 117°
|
||||
{ OV( 387), 113 }, // 1550 - 113°
|
||||
{ OV( 411), 110 }, // 1644 - 110°
|
||||
{ OV( 445), 106 }, // 1780 - 106°
|
||||
{ OV( 480), 101 }, // 1920 - 101°
|
||||
{ OV( 516), 97 }, // 2064 - 97°
|
||||
{ OV( 553), 92 }, // 2212 - 92°
|
||||
{ OV( 591), 88 }, // 2364 - 88°
|
||||
{ OV( 628), 84 }, // 2512 - 84°
|
||||
{ OV( 665), 79 }, // 2660 - 79°
|
||||
{ OV( 702), 75 }, // 2808 - 75°
|
||||
{ OV( 736), 71 }, // 2945 - 71°
|
||||
{ OV( 770), 67 }, // 3080 - 67°
|
||||
{ OV( 801), 63 }, // 3204 - 63°
|
||||
{ OV( 830), 59 }, // 3320 - 59°
|
||||
{ OV( 857), 55 }, // 3428 - 55°
|
||||
{ OV( 881), 51 }, // 3524 - 51°
|
||||
{ OV( 902), 47 }, // 3611 - 47°
|
||||
{ OV( 922), 42 }, // 3688 - 42°
|
||||
{ OV( 938), 38 }, // 3754 - 38°
|
||||
{ OV( 952), 34 }, // 3811 - 34°
|
||||
{ OV( 964), 29 }, // 3857 - 29°
|
||||
{ OV( 975), 25 }, // 3900 - 25°
|
||||
{ OV( 980), 23 }, // 3920 - 23°
|
||||
{ OV( 991), 17 }, // 3964 - 17°
|
||||
{ OV(1001), 9 }, // Calculated
|
||||
{ OV(1004), 5 }, // Calculated
|
||||
{ OV(1008), 0 }, // Calculated
|
||||
{ OV(1012), -5 }, // Calculated
|
||||
{ OV(1016), -10 }, // Calculated
|
||||
{ OV(1020), -15 } // Calculated
|
||||
};
|
4
Marlin/src/module/thermistor/thermistor_331.h
Executable file → Normal file
4
Marlin/src/module/thermistor/thermistor_331.h
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@@ -24,7 +24,7 @@
|
||||
#define OVM(V) OV((V)*(0.327/0.5))
|
||||
|
||||
// R25 = 100 kOhm, beta25 = 4092 K, 4.7 kOhm pull-up, bed thermistor
|
||||
const short temptable_331[][2] PROGMEM = {
|
||||
constexpr temp_entry_t temptable_331[] PROGMEM = {
|
||||
{ OVM( 23), 300 },
|
||||
{ OVM( 25), 295 },
|
||||
{ OVM( 27), 290 },
|
||||
|
4
Marlin/src/module/thermistor/thermistor_332.h
Executable file → Normal file
4
Marlin/src/module/thermistor/thermistor_332.h
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@@ -24,7 +24,7 @@
|
||||
#define OVM(V) OV((V)*(0.327/0.327))
|
||||
|
||||
// R25 = 100 kOhm, beta25 = 4092 K, 4.7 kOhm pull-up, bed thermistor
|
||||
const short temptable_332[][2] PROGMEM = {
|
||||
constexpr temp_entry_t temptable_332[] PROGMEM = {
|
||||
{ OVM( 268), 150 },
|
||||
{ OVM( 293), 145 },
|
||||
{ OVM( 320), 141 },
|
||||
|
4
Marlin/src/module/thermistor/thermistor_4.h
Executable file → Normal file
4
Marlin/src/module/thermistor/thermistor_4.h
Executable file → Normal file
@@ -16,13 +16,13 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// R25 = 10 kOhm, beta25 = 3950 K, 4.7 kOhm pull-up, Generic 10k thermistor
|
||||
const short temptable_4[][2] PROGMEM = {
|
||||
constexpr temp_entry_t temptable_4[] PROGMEM = {
|
||||
{ OV( 1), 430 },
|
||||
{ OV( 54), 137 },
|
||||
{ OV( 107), 107 },
|
||||
|
6
Marlin/src/module/thermistor/thermistor_5.h
Executable file → Normal file
6
Marlin/src/module/thermistor/thermistor_5.h
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@@ -24,9 +24,9 @@
|
||||
// R25 = 100 kOhm, beta25 = 4267 K, 4.7 kOhm pull-up
|
||||
// 100k ParCan thermistor (104GT-2)
|
||||
// ATC Semitec 104GT-2/104NT-4-R025H42G (Used in ParCan)
|
||||
// Verified by linagee. Source: http://shop.arcol.hu/static/datasheets/thermistors.pdf
|
||||
// Verified by linagee. Source: https://www.mouser.com/datasheet/2/362/semitec%20usa%20corporation_gtthermistor-1202937.pdf
|
||||
// Calculated using 4.7kohm pullup, voltage divider math, and manufacturer provided temp/resistance
|
||||
const short temptable_5[][2] PROGMEM = {
|
||||
constexpr temp_entry_t temptable_5[] PROGMEM = {
|
||||
{ OV( 1), 713 },
|
||||
{ OV( 17), 300 }, // top rating 300C
|
||||
{ OV( 20), 290 },
|
||||
|
4
Marlin/src/module/thermistor/thermistor_501.h
Executable file → Normal file
4
Marlin/src/module/thermistor/thermistor_501.h
Executable file → Normal file
@@ -16,13 +16,13 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// 100k Zonestar thermistor. Adjusted By Hally
|
||||
const short temptable_501[][2] PROGMEM = {
|
||||
constexpr temp_entry_t temptable_501[] PROGMEM = {
|
||||
{ OV( 1), 713 },
|
||||
{ OV( 14), 300 }, // Top rating 300C
|
||||
{ OV( 16), 290 },
|
||||
|
60
Marlin/src/module/thermistor/thermistor_502.h
Normal file
60
Marlin/src/module/thermistor/thermistor_502.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2020 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 <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// Unknown thermistor for the Zonestar P802M hot bed. Adjusted By Nerseth
|
||||
// These were the shipped settings from Zonestar in original firmware: P802M_8_Repetier_V1.6_Zonestar.zip
|
||||
constexpr temp_entry_t temptable_502[] PROGMEM = {
|
||||
{ OV( 56.0 / 4), 300 },
|
||||
{ OV( 187.0 / 4), 250 },
|
||||
{ OV( 615.0 / 4), 190 },
|
||||
{ OV( 690.0 / 4), 185 },
|
||||
{ OV( 750.0 / 4), 180 },
|
||||
{ OV( 830.0 / 4), 175 },
|
||||
{ OV( 920.0 / 4), 170 },
|
||||
{ OV(1010.0 / 4), 165 },
|
||||
{ OV(1118.0 / 4), 160 },
|
||||
{ OV(1215.0 / 4), 155 },
|
||||
{ OV(1330.0 / 4), 145 },
|
||||
{ OV(1460.0 / 4), 140 },
|
||||
{ OV(1594.0 / 4), 135 },
|
||||
{ OV(1752.0 / 4), 130 },
|
||||
{ OV(1900.0 / 4), 125 },
|
||||
{ OV(2040.0 / 4), 120 },
|
||||
{ OV(2200.0 / 4), 115 },
|
||||
{ OV(2350.0 / 4), 110 },
|
||||
{ OV(2516.0 / 4), 105 },
|
||||
{ OV(2671.0 / 4), 98 },
|
||||
{ OV(2831.0 / 4), 92 },
|
||||
{ OV(2975.0 / 4), 85 },
|
||||
{ OV(3115.0 / 4), 76 },
|
||||
{ OV(3251.0 / 4), 72 },
|
||||
{ OV(3480.0 / 4), 62 },
|
||||
{ OV(3580.0 / 4), 52 },
|
||||
{ OV(3660.0 / 4), 46 },
|
||||
{ OV(3740.0 / 4), 40 },
|
||||
{ OV(3869.0 / 4), 30 },
|
||||
{ OV(3912.0 / 4), 25 },
|
||||
{ OV(3948.0 / 4), 20 },
|
||||
{ OV(4077.0 / 4), -20 },
|
||||
{ OV(4094.0 / 4), -55 }
|
||||
};
|
57
Marlin/src/module/thermistor/thermistor_503.h
Normal file
57
Marlin/src/module/thermistor/thermistor_503.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2020 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 <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// Zonestar (Z8XM2) Heated Bed thermistor. Added By AvanOsch
|
||||
// These are taken from the Zonestar settings in original Repetier firmware: Z8XM2_ZRIB_LCD12864_V51.zip
|
||||
constexpr temp_entry_t temptable_503[] PROGMEM = {
|
||||
{ OV( 12), 300 },
|
||||
{ OV( 27), 270 },
|
||||
{ OV( 47), 250 },
|
||||
{ OV( 68), 230 },
|
||||
{ OV( 99), 210 },
|
||||
{ OV( 120), 200 },
|
||||
{ OV( 141), 190 },
|
||||
{ OV( 171), 180 },
|
||||
{ OV( 201), 170 },
|
||||
{ OV( 261), 160 },
|
||||
{ OV( 321), 150 },
|
||||
{ OV( 401), 140 },
|
||||
{ OV( 451), 130 },
|
||||
{ OV( 551), 120 },
|
||||
{ OV( 596), 110 },
|
||||
{ OV( 626), 105 },
|
||||
{ OV( 666), 100 },
|
||||
{ OV( 697), 90 },
|
||||
{ OV( 717), 85 },
|
||||
{ OV( 798), 69 },
|
||||
{ OV( 819), 65 },
|
||||
{ OV( 870), 55 },
|
||||
{ OV( 891), 51 },
|
||||
{ OV( 922), 39 },
|
||||
{ OV( 968), 28 },
|
||||
{ OV( 980), 23 },
|
||||
{ OV( 991), 17 },
|
||||
{ OV( 1001), 9 },
|
||||
{ OV(1021), -27 },
|
||||
{ OV(1023), -200}
|
||||
};
|
4
Marlin/src/module/thermistor/thermistor_51.h
Executable file → Normal file
4
Marlin/src/module/thermistor/thermistor_51.h
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@@ -26,7 +26,7 @@
|
||||
// Verified by linagee.
|
||||
// Calculated using 1kohm pullup, voltage divider math, and manufacturer provided temp/resistance
|
||||
// Advantage: Twice the resolution and better linearity from 150C to 200C
|
||||
const short temptable_51[][2] PROGMEM = {
|
||||
constexpr temp_entry_t temptable_51[] PROGMEM = {
|
||||
{ OV( 1), 350 },
|
||||
{ OV( 190), 250 }, // top rating 250C
|
||||
{ OV( 203), 245 },
|
||||
|
4
Marlin/src/module/thermistor/thermistor_512.h
Executable file → Normal file
4
Marlin/src/module/thermistor/thermistor_512.h
Executable file → Normal file
@@ -16,13 +16,13 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
// 100k thermistor supplied with RPW-Ultra hotend, 4.7k pullup
|
||||
|
||||
const short temptable_512[][2] PROGMEM = {
|
||||
constexpr temp_entry_t temptable_512[] PROGMEM = {
|
||||
{ OV(26), 300 },
|
||||
{ OV(28), 295 },
|
||||
{ OV(30), 290 },
|
||||
|
6
Marlin/src/module/thermistor/thermistor_52.h
Executable file → Normal file
6
Marlin/src/module/thermistor/thermistor_52.h
Executable file → Normal file
@@ -16,17 +16,17 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// R25 = 200 kOhm, beta25 = 4338 K, 1 kOhm pull-up,
|
||||
// 200k ATC Semitec 204GT-2 (WITH 1kohm RESISTOR FOR PULLUP, R9 ON SANGUINOLOLU! NOT FOR 4.7kohm PULLUP! THIS IS NOT NORMAL!)
|
||||
// Verified by linagee. Source: http://shop.arcol.hu/static/datasheets/thermistors.pdf
|
||||
// Verified by linagee. Source: https://www.mouser.com/datasheet/2/362/semitec%20usa%20corporation_gtthermistor-1202937.pdf
|
||||
// Calculated using 1kohm pullup, voltage divider math, and manufacturer provided temp/resistance
|
||||
// Advantage: More resolution and better linearity from 150C to 200C
|
||||
const short temptable_52[][2] PROGMEM = {
|
||||
constexpr temp_entry_t temptable_52[] PROGMEM = {
|
||||
{ OV( 1), 500 },
|
||||
{ OV( 125), 300 }, // top rating 300C
|
||||
{ OV( 142), 290 },
|
||||
|
6
Marlin/src/module/thermistor/thermistor_55.h
Executable file → Normal file
6
Marlin/src/module/thermistor/thermistor_55.h
Executable file → Normal file
@@ -16,17 +16,17 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// R25 = 100 kOhm, beta25 = 4267 K, 1 kOhm pull-up,
|
||||
// 100k ATC Semitec 104GT-2 (Used on ParCan) (WITH 1kohm RESISTOR FOR PULLUP, R9 ON SANGUINOLOLU! NOT FOR 4.7kohm PULLUP! THIS IS NOT NORMAL!)
|
||||
// Verified by linagee. Source: http://shop.arcol.hu/static/datasheets/thermistors.pdf
|
||||
// Verified by linagee. Source: https://www.mouser.com/datasheet/2/362/semitec%20usa%20corporation_gtthermistor-1202937.pdf
|
||||
// Calculated using 1kohm pullup, voltage divider math, and manufacturer provided temp/resistance
|
||||
// Advantage: More resolution and better linearity from 150C to 200C
|
||||
const short temptable_55[][2] PROGMEM = {
|
||||
constexpr temp_entry_t temptable_55[] PROGMEM = {
|
||||
{ OV( 1), 500 },
|
||||
{ OV( 76), 300 },
|
||||
{ OV( 87), 290 },
|
||||
|
4
Marlin/src/module/thermistor/thermistor_6.h
Executable file → Normal file
4
Marlin/src/module/thermistor/thermistor_6.h
Executable file → Normal file
@@ -16,13 +16,13 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// R25 = 100 kOhm, beta25 = 4092 K, 8.2 kOhm pull-up, 100k Epcos (?) thermistor
|
||||
const short temptable_6[][2] PROGMEM = {
|
||||
constexpr temp_entry_t temptable_6[] PROGMEM = {
|
||||
{ OV( 1), 350 },
|
||||
{ OV( 28), 250 }, // top rating 250C
|
||||
{ OV( 31), 245 },
|
||||
|
4
Marlin/src/module/thermistor/thermistor_60.h
Executable file → Normal file
4
Marlin/src/module/thermistor/thermistor_60.h
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@@ -31,7 +31,7 @@
|
||||
// beta: 3950
|
||||
// min adc: 1 at 0.0048828125 V
|
||||
// max adc: 1023 at 4.9951171875 V
|
||||
const short temptable_60[][2] PROGMEM = {
|
||||
constexpr temp_entry_t temptable_60[] PROGMEM = {
|
||||
{ OV( 51), 272 },
|
||||
{ OV( 61), 258 },
|
||||
{ OV( 71), 247 },
|
||||
|
6
Marlin/src/module/thermistor/thermistor_61.h
Executable file → Normal file
6
Marlin/src/module/thermistor/thermistor_61.h
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@@ -30,8 +30,8 @@
|
||||
// Resistance Tolerance + / -1%
|
||||
// B Value 3950K at 25/50 deg. C
|
||||
// B Value Tolerance + / - 1%
|
||||
const short temptable_61[][2] PROGMEM = {
|
||||
{ OV( 2.00), 420 }, // Guestimate to ensure we dont lose a reading and drop temps to -50 when over
|
||||
constexpr temp_entry_t temptable_61[] PROGMEM = {
|
||||
{ OV( 2.00), 420 }, // Guestimate to ensure we don't lose a reading and drop temps to -50 when over
|
||||
{ OV( 12.07), 350 },
|
||||
{ OV( 12.79), 345 },
|
||||
{ OV( 13.59), 340 },
|
||||
|
4
Marlin/src/module/thermistor/thermistor_66.h
Executable file → Normal file
4
Marlin/src/module/thermistor/thermistor_66.h
Executable file → Normal file
@@ -16,13 +16,13 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// R25 = 2.5 MOhm, beta25 = 4500 K, 4.7 kOhm pull-up, DyzeDesign 500 °C Thermistor
|
||||
const short temptable_66[][2] PROGMEM = {
|
||||
constexpr temp_entry_t temptable_66[] PROGMEM = {
|
||||
{ OV( 17.5), 850 },
|
||||
{ OV( 17.9), 500 },
|
||||
{ OV( 21.7), 480 },
|
||||
|
5
Marlin/src/module/thermistor/thermistor_666.h
Executable file → Normal file
5
Marlin/src/module/thermistor/thermistor_666.h
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@@ -33,8 +33,7 @@
|
||||
* B: 0.00031362
|
||||
* C: -2.03978e-07
|
||||
*/
|
||||
#define NUMTEMPS 61
|
||||
const short temptable_666[NUMTEMPS][2] PROGMEM = {
|
||||
constexpr temp_entry_t temptable_666[] PROGMEM = {
|
||||
{ OV( 1), 794 },
|
||||
{ OV( 18), 288 },
|
||||
{ OV( 35), 234 },
|
||||
|
4
Marlin/src/module/thermistor/thermistor_67.h
Executable file → Normal file
4
Marlin/src/module/thermistor/thermistor_67.h
Executable file → Normal file
@@ -16,13 +16,13 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// R25 = 500 KOhm, beta25 = 3800 K, 4.7 kOhm pull-up, SliceEngineering 450 °C Thermistor
|
||||
const short temptable_67[][2] PROGMEM = {
|
||||
constexpr temp_entry_t temptable_67[] PROGMEM = {
|
||||
{ OV( 22 ), 500 },
|
||||
{ OV( 23 ), 490 },
|
||||
{ OV( 25 ), 480 },
|
||||
|
4
Marlin/src/module/thermistor/thermistor_7.h
Executable file → Normal file
4
Marlin/src/module/thermistor/thermistor_7.h
Executable file → Normal file
@@ -16,13 +16,13 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// R25 = 100 kOhm, beta25 = 3974 K, 4.7 kOhm pull-up, Honeywell 135-104LAG-J01
|
||||
const short temptable_7[][2] PROGMEM = {
|
||||
constexpr temp_entry_t temptable_7[] PROGMEM = {
|
||||
{ OV( 1), 941 },
|
||||
{ OV( 19), 362 },
|
||||
{ OV( 37), 299 }, // top rating 300C
|
||||
|
4
Marlin/src/module/thermistor/thermistor_70.h
Executable file → Normal file
4
Marlin/src/module/thermistor/thermistor_70.h
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@@ -26,7 +26,7 @@
|
||||
// ANENG AN8009 DMM with a K-type probe used for measurements.
|
||||
|
||||
// R25 = 100 kOhm, beta25 = 4100 K, 4.7 kOhm pull-up, bqh2 stock thermistor
|
||||
const short temptable_70[][2] PROGMEM = {
|
||||
constexpr temp_entry_t temptable_70[] PROGMEM = {
|
||||
{ OV( 18), 270 },
|
||||
{ OV( 27), 248 },
|
||||
{ OV( 34), 234 },
|
||||
|
4
Marlin/src/module/thermistor/thermistor_71.h
Executable file → Normal file
4
Marlin/src/module/thermistor/thermistor_71.h
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@@ -27,7 +27,7 @@
|
||||
// Beta = 3974
|
||||
// R1 = 0 Ohm
|
||||
// R2 = 4700 Ohm
|
||||
const short temptable_71[][2] PROGMEM = {
|
||||
constexpr temp_entry_t temptable_71[] PROGMEM = {
|
||||
{ OV( 35), 300 },
|
||||
{ OV( 51), 269 },
|
||||
{ OV( 59), 258 },
|
||||
|
4
Marlin/src/module/thermistor/thermistor_75.h
Executable file → Normal file
4
Marlin/src/module/thermistor/thermistor_75.h
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
//#define HIGH_TEMP_RANGE_75
|
||||
|
||||
const short temptable_75[][2] PROGMEM = { // Generic Silicon Heat Pad with NTC 100K MGB18-104F39050L32 thermistor
|
||||
constexpr temp_entry_t temptable_75[] PROGMEM = { // Generic Silicon Heat Pad with NTC 100K MGB18-104F39050L32 thermistor
|
||||
{ OV(111.06), 200 }, // v=0.542 r=571.747 res=0.501 degC/count
|
||||
|
||||
#ifdef HIGH_TEMP_RANGE_75
|
||||
|
4
Marlin/src/module/thermistor/thermistor_8.h
Executable file → Normal file
4
Marlin/src/module/thermistor/thermistor_8.h
Executable file → Normal file
@@ -16,13 +16,13 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// R25 = 100 kOhm, beta25 = 3950 K, 10 kOhm pull-up, NTCS0603E3104FHT
|
||||
const short temptable_8[][2] PROGMEM = {
|
||||
constexpr temp_entry_t temptable_8[] PROGMEM = {
|
||||
{ OV( 1), 704 },
|
||||
{ OV( 54), 216 },
|
||||
{ OV( 107), 175 },
|
||||
|
4
Marlin/src/module/thermistor/thermistor_9.h
Executable file → Normal file
4
Marlin/src/module/thermistor/thermistor_9.h
Executable file → Normal file
@@ -16,13 +16,13 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// R25 = 100 kOhm, beta25 = 3960 K, 4.7 kOhm pull-up, GE Sensing AL03006-58.2K-97-G1
|
||||
const short temptable_9[][2] PROGMEM = {
|
||||
constexpr temp_entry_t temptable_9[] PROGMEM = {
|
||||
{ OV( 1), 936 },
|
||||
{ OV( 36), 300 },
|
||||
{ OV( 71), 246 },
|
||||
|
5
Marlin/src/module/thermistor/thermistor_99.h
Executable file → Normal file
5
Marlin/src/module/thermistor/thermistor_99.h
Executable file → Normal file
@@ -16,15 +16,14 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// 100k bed thermistor with a 10K pull-up resistor - made by $ buildroot/share/scripts/createTemperatureLookupMarlin.py --rp=10000
|
||||
|
||||
const short temptable_99[][2] PROGMEM = {
|
||||
constexpr temp_entry_t temptable_99[] PROGMEM = {
|
||||
{ OV( 5.81), 350 }, // v=0.028 r= 57.081 res=13.433 degC/count
|
||||
{ OV( 6.54), 340 }, // v=0.032 r= 64.248 res=11.711 degC/count
|
||||
{ OV( 7.38), 330 }, // v=0.036 r= 72.588 res=10.161 degC/count
|
||||
|
4
Marlin/src/module/thermistor/thermistor_998.h
Executable file → Normal file
4
Marlin/src/module/thermistor/thermistor_998.h
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@@ -27,7 +27,7 @@
|
||||
#define DUMMY_THERMISTOR_998_VALUE 25
|
||||
#endif
|
||||
|
||||
const short temptable_998[][2] PROGMEM = {
|
||||
constexpr temp_entry_t temptable_998[] PROGMEM = {
|
||||
{ OV( 1), DUMMY_THERMISTOR_998_VALUE },
|
||||
{ OV(1023), DUMMY_THERMISTOR_998_VALUE }
|
||||
};
|
||||
|
4
Marlin/src/module/thermistor/thermistor_999.h
Executable file → Normal file
4
Marlin/src/module/thermistor/thermistor_999.h
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@@ -27,7 +27,7 @@
|
||||
#define DUMMY_THERMISTOR_999_VALUE 25
|
||||
#endif
|
||||
|
||||
const short temptable_999[][2] PROGMEM = {
|
||||
constexpr temp_entry_t temptable_999[] PROGMEM = {
|
||||
{ OV( 1), DUMMY_THERMISTOR_999_VALUE },
|
||||
{ OV(1023), DUMMY_THERMISTOR_999_VALUE }
|
||||
};
|
||||
|
461
Marlin/src/module/thermistor/thermistors.h
Executable file → Normal file
461
Marlin/src/module/thermistor/thermistors.h
Executable file → Normal file
@@ -16,17 +16,19 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
#define THERMISTOR_TABLE_ADC_RESOLUTION 1024
|
||||
#define THERMISTOR_TABLE_SCALE (HAL_ADC_RANGE / (THERMISTOR_TABLE_ADC_RESOLUTION))
|
||||
#define THERMISTOR_TABLE_ADC_RESOLUTION 10
|
||||
#define THERMISTOR_TABLE_SCALE (HAL_ADC_RANGE / _BV(THERMISTOR_TABLE_ADC_RESOLUTION))
|
||||
#if ENABLED(HAL_ADC_FILTERED)
|
||||
#define OVERSAMPLENR 1
|
||||
#elif HAL_ADC_RESOLUTION > 10
|
||||
#define OVERSAMPLENR (20 - HAL_ADC_RESOLUTION)
|
||||
#else
|
||||
#define OVERSAMPLENR 16
|
||||
#endif
|
||||
@@ -40,7 +42,19 @@
|
||||
#define OV_SCALE(N) (N)
|
||||
#define OV(N) int16_t(OV_SCALE(N) * (OVERSAMPLENR) * (THERMISTOR_TABLE_SCALE))
|
||||
|
||||
#define ANY_THERMISTOR_IS(n) (THERMISTOR_HEATER_0 == n || THERMISTOR_HEATER_1 == n || THERMISTOR_HEATER_2 == n || THERMISTOR_HEATER_3 == n || THERMISTOR_HEATER_4 == n || THERMISTOR_HEATER_5 == n || THERMISTOR_HEATER_6 == n || THERMISTOR_HEATER_7 == n || THERMISTORBED == n || THERMISTORCHAMBER == n || THERMISTORPROBE == n)
|
||||
#define TEMP_SENSOR_IS(n,H) (n == TEMP_SENSOR_##H)
|
||||
#define ANY_THERMISTOR_IS(n) ( TEMP_SENSOR_IS(n, 0) || TEMP_SENSOR_IS(n, 1) \
|
||||
|| TEMP_SENSOR_IS(n, 2) || TEMP_SENSOR_IS(n, 3) \
|
||||
|| TEMP_SENSOR_IS(n, 4) || TEMP_SENSOR_IS(n, 5) \
|
||||
|| TEMP_SENSOR_IS(n, 6) || TEMP_SENSOR_IS(n, 7) \
|
||||
|| TEMP_SENSOR_IS(n, BED) \
|
||||
|| TEMP_SENSOR_IS(n, CHAMBER) \
|
||||
|| TEMP_SENSOR_IS(n, COOLER) \
|
||||
|| TEMP_SENSOR_IS(n, PROBE) \
|
||||
|| TEMP_SENSOR_IS(n, BOARD) \
|
||||
|| TEMP_SENSOR_IS(n, REDUNDANT) )
|
||||
|
||||
typedef struct { int16_t value; celsius_t celsius; } temp_entry_t;
|
||||
|
||||
// Pt1000 and Pt100 handling
|
||||
//
|
||||
@@ -70,6 +84,12 @@
|
||||
#if ANY_THERMISTOR_IS(501) // 100K Zonestar thermistor
|
||||
#include "thermistor_501.h"
|
||||
#endif
|
||||
#if ANY_THERMISTOR_IS(502) // Unknown thermistor used by the Zonestar Průša P802M hot bed
|
||||
#include "thermistor_502.h"
|
||||
#endif
|
||||
#if ANY_THERMISTOR_IS(503) // Zonestar (Z8XM2) Heated Bed thermistor
|
||||
#include "thermistor_503.h"
|
||||
#endif
|
||||
#if ANY_THERMISTOR_IS(512) // 100k thermistor in RPW-Ultra hotend, Pull-up = 4.7 kOhm, "unknown model"
|
||||
#include "thermistor_512.h"
|
||||
#endif
|
||||
@@ -100,6 +120,9 @@
|
||||
#if ANY_THERMISTOR_IS(15) // JGAurora A5 thermistor calibration
|
||||
#include "thermistor_15.h"
|
||||
#endif
|
||||
#if ANY_THERMISTOR_IS(17) // Dagoma NTC 100k white thermistor
|
||||
#include "thermistor_17.h"
|
||||
#endif
|
||||
#if ANY_THERMISTOR_IS(18) // ATC Semitec 204GT-2 (4.7k pullup) Dagoma.Fr - MKS_Base_DKU001327
|
||||
#include "thermistor_18.h"
|
||||
#endif
|
||||
@@ -109,6 +132,15 @@
|
||||
#if ANY_THERMISTOR_IS(21) // Pt100 with INA826 amp with 3.3v excitation based on "Pt100 with INA826 amp on Ultimaker v2.0 electronics"
|
||||
#include "thermistor_21.h"
|
||||
#endif
|
||||
#if ANY_THERMISTOR_IS(22) // Thermistor in a Rostock 301 hot end, calibrated with a multimeter
|
||||
#include "thermistor_22.h"
|
||||
#endif
|
||||
#if ANY_THERMISTOR_IS(23) // By AluOne #12622. Formerly 22 above. May need calibration/checking.
|
||||
#include "thermistor_23.h"
|
||||
#endif
|
||||
#if ANY_THERMISTOR_IS(30) // Kis3d Silicone mat 24V 200W/300W with 6mm Precision cast plate (EN AW 5083)
|
||||
#include "thermistor_30.h"
|
||||
#endif
|
||||
#if ANY_THERMISTOR_IS(51) // beta25 = 4092 K, R25 = 100 kOhm, Pull-up = 1 kOhm, "EPCOS"
|
||||
#include "thermistor_51.h"
|
||||
#endif
|
||||
@@ -169,6 +201,9 @@
|
||||
#if ANY_THERMISTOR_IS(1047) // Pt1000 with 4k7 pullup
|
||||
#include "thermistor_1047.h"
|
||||
#endif
|
||||
#if ANY_THERMISTOR_IS(2000) // "Ultimachine Rambo TDK NTCG104LH104KT1 NTC100K motherboard Thermistor" https://product.tdk.com/en/search/sensor/ntc/chip-ntc-thermistor/info?part_no=NTCG104LH104KT1
|
||||
#include "thermistor_2000.h"
|
||||
#endif
|
||||
#if ANY_THERMISTOR_IS(998) // User-defined table 1
|
||||
#include "thermistor_998.h"
|
||||
#endif
|
||||
@@ -176,219 +211,341 @@
|
||||
#include "thermistor_999.h"
|
||||
#endif
|
||||
#if ANY_THERMISTOR_IS(1000) // Custom
|
||||
const short temptable_1000[][2] PROGMEM = { { 0, 0 } };
|
||||
constexpr temp_entry_t temptable_1000[] PROGMEM = { { 0, 0 } };
|
||||
#endif
|
||||
|
||||
#define _TT_NAME(_N) temptable_ ## _N
|
||||
#define TT_NAME(_N) _TT_NAME(_N)
|
||||
|
||||
#if THERMISTOR_HEATER_0
|
||||
#define HEATER_0_TEMPTABLE TT_NAME(THERMISTOR_HEATER_0)
|
||||
#define HEATER_0_TEMPTABLE_LEN COUNT(HEATER_0_TEMPTABLE)
|
||||
#elif defined(HEATER_0_USES_THERMISTOR)
|
||||
#error "No heater 0 thermistor table specified"
|
||||
#if TEMP_SENSOR_0 > 0
|
||||
#define TEMPTABLE_0 TT_NAME(TEMP_SENSOR_0)
|
||||
#define TEMPTABLE_0_LEN COUNT(TEMPTABLE_0)
|
||||
#else
|
||||
#define HEATER_0_TEMPTABLE nullptr
|
||||
#define HEATER_0_TEMPTABLE_LEN 0
|
||||
#define TEMPTABLE_0 nullptr
|
||||
#define TEMPTABLE_0_LEN 0
|
||||
#endif
|
||||
|
||||
#if THERMISTOR_HEATER_1
|
||||
#define HEATER_1_TEMPTABLE TT_NAME(THERMISTOR_HEATER_1)
|
||||
#define HEATER_1_TEMPTABLE_LEN COUNT(HEATER_1_TEMPTABLE)
|
||||
#elif defined(HEATER_1_USES_THERMISTOR)
|
||||
#error "No heater 1 thermistor table specified"
|
||||
#if TEMP_SENSOR_1 > 0
|
||||
#define TEMPTABLE_1 TT_NAME(TEMP_SENSOR_1)
|
||||
#define TEMPTABLE_1_LEN COUNT(TEMPTABLE_1)
|
||||
#else
|
||||
#define HEATER_1_TEMPTABLE nullptr
|
||||
#define HEATER_1_TEMPTABLE_LEN 0
|
||||
#define TEMPTABLE_1 nullptr
|
||||
#define TEMPTABLE_1_LEN 0
|
||||
#endif
|
||||
|
||||
#if THERMISTOR_HEATER_2
|
||||
#define HEATER_2_TEMPTABLE TT_NAME(THERMISTOR_HEATER_2)
|
||||
#define HEATER_2_TEMPTABLE_LEN COUNT(HEATER_2_TEMPTABLE)
|
||||
#elif defined(HEATER_2_USES_THERMISTOR)
|
||||
#error "No heater 2 thermistor table specified"
|
||||
#if TEMP_SENSOR_2 > 0
|
||||
#define TEMPTABLE_2 TT_NAME(TEMP_SENSOR_2)
|
||||
#define TEMPTABLE_2_LEN COUNT(TEMPTABLE_2)
|
||||
#else
|
||||
#define HEATER_2_TEMPTABLE nullptr
|
||||
#define HEATER_2_TEMPTABLE_LEN 0
|
||||
#define TEMPTABLE_2 nullptr
|
||||
#define TEMPTABLE_2_LEN 0
|
||||
#endif
|
||||
|
||||
#if THERMISTOR_HEATER_3
|
||||
#define HEATER_3_TEMPTABLE TT_NAME(THERMISTOR_HEATER_3)
|
||||
#define HEATER_3_TEMPTABLE_LEN COUNT(HEATER_3_TEMPTABLE)
|
||||
#elif defined(HEATER_3_USES_THERMISTOR)
|
||||
#error "No heater 3 thermistor table specified"
|
||||
#if TEMP_SENSOR_3 > 0
|
||||
#define TEMPTABLE_3 TT_NAME(TEMP_SENSOR_3)
|
||||
#define TEMPTABLE_3_LEN COUNT(TEMPTABLE_3)
|
||||
#else
|
||||
#define HEATER_3_TEMPTABLE nullptr
|
||||
#define HEATER_3_TEMPTABLE_LEN 0
|
||||
#define TEMPTABLE_3 nullptr
|
||||
#define TEMPTABLE_3_LEN 0
|
||||
#endif
|
||||
|
||||
#if THERMISTOR_HEATER_4
|
||||
#define HEATER_4_TEMPTABLE TT_NAME(THERMISTOR_HEATER_4)
|
||||
#define HEATER_4_TEMPTABLE_LEN COUNT(HEATER_4_TEMPTABLE)
|
||||
#elif defined(HEATER_4_USES_THERMISTOR)
|
||||
#error "No heater 4 thermistor table specified"
|
||||
#if TEMP_SENSOR_4 > 0
|
||||
#define TEMPTABLE_4 TT_NAME(TEMP_SENSOR_4)
|
||||
#define TEMPTABLE_4_LEN COUNT(TEMPTABLE_4)
|
||||
#else
|
||||
#define HEATER_4_TEMPTABLE nullptr
|
||||
#define HEATER_4_TEMPTABLE_LEN 0
|
||||
#define TEMPTABLE_4 nullptr
|
||||
#define TEMPTABLE_4_LEN 0
|
||||
#endif
|
||||
|
||||
#if THERMISTOR_HEATER_5
|
||||
#define HEATER_5_TEMPTABLE TT_NAME(THERMISTOR_HEATER_5)
|
||||
#define HEATER_5_TEMPTABLE_LEN COUNT(HEATER_5_TEMPTABLE)
|
||||
#elif defined(HEATER_5_USES_THERMISTOR)
|
||||
#error "No heater 5 thermistor table specified"
|
||||
#if TEMP_SENSOR_5 > 0
|
||||
#define TEMPTABLE_5 TT_NAME(TEMP_SENSOR_5)
|
||||
#define TEMPTABLE_5_LEN COUNT(TEMPTABLE_5)
|
||||
#else
|
||||
#define HEATER_5_TEMPTABLE nullptr
|
||||
#define HEATER_5_TEMPTABLE_LEN 0
|
||||
#define TEMPTABLE_5 nullptr
|
||||
#define TEMPTABLE_5_LEN 0
|
||||
#endif
|
||||
|
||||
#if THERMISTOR_HEATER_6
|
||||
#define HEATER_6_TEMPTABLE TT_NAME(THERMISTOR_HEATER_6)
|
||||
#define HEATER_6_TEMPTABLE_LEN COUNT(HEATER_6_TEMPTABLE)
|
||||
#elif defined(HEATER_6_USES_THERMISTOR)
|
||||
#error "No heater 6 thermistor table specified"
|
||||
#if TEMP_SENSOR_6 > 0
|
||||
#define TEMPTABLE_6 TT_NAME(TEMP_SENSOR_6)
|
||||
#define TEMPTABLE_6_LEN COUNT(TEMPTABLE_6)
|
||||
#else
|
||||
#define HEATER_6_TEMPTABLE nullptr
|
||||
#define HEATER_6_TEMPTABLE_LEN 0
|
||||
#define TEMPTABLE_6 nullptr
|
||||
#define TEMPTABLE_6_LEN 0
|
||||
#endif
|
||||
|
||||
#if THERMISTOR_HEATER_7
|
||||
#define HEATER_7_TEMPTABLE TT_NAME(THERMISTOR_HEATER_7)
|
||||
#define HEATER_7_TEMPTABLE_LEN COUNT(HEATER_7_TEMPTABLE)
|
||||
#elif defined(HEATER_7_USES_THERMISTOR)
|
||||
#error "No heater 7 thermistor table specified"
|
||||
#if TEMP_SENSOR_7 > 0
|
||||
#define TEMPTABLE_7 TT_NAME(TEMP_SENSOR_7)
|
||||
#define TEMPTABLE_7_LEN COUNT(TEMPTABLE_7)
|
||||
#else
|
||||
#define HEATER_7_TEMPTABLE nullptr
|
||||
#define HEATER_7_TEMPTABLE_LEN 0
|
||||
#define TEMPTABLE_7 nullptr
|
||||
#define TEMPTABLE_7_LEN 0
|
||||
#endif
|
||||
|
||||
#ifdef THERMISTORBED
|
||||
#define BED_TEMPTABLE TT_NAME(THERMISTORBED)
|
||||
#define BED_TEMPTABLE_LEN COUNT(BED_TEMPTABLE)
|
||||
#elif defined(HEATER_BED_USES_THERMISTOR)
|
||||
#error "No bed thermistor table specified"
|
||||
#if TEMP_SENSOR_BED > 0
|
||||
#define TEMPTABLE_BED TT_NAME(TEMP_SENSOR_BED)
|
||||
#define TEMPTABLE_BED_LEN COUNT(TEMPTABLE_BED)
|
||||
#else
|
||||
#define BED_TEMPTABLE_LEN 0
|
||||
#define TEMPTABLE_BED_LEN 0
|
||||
#endif
|
||||
|
||||
#ifdef THERMISTORCHAMBER
|
||||
#define CHAMBER_TEMPTABLE TT_NAME(THERMISTORCHAMBER)
|
||||
#define CHAMBER_TEMPTABLE_LEN COUNT(CHAMBER_TEMPTABLE)
|
||||
#elif defined(HEATER_CHAMBER_USES_THERMISTOR)
|
||||
#error "No chamber thermistor table specified"
|
||||
#if TEMP_SENSOR_CHAMBER > 0
|
||||
#define TEMPTABLE_CHAMBER TT_NAME(TEMP_SENSOR_CHAMBER)
|
||||
#define TEMPTABLE_CHAMBER_LEN COUNT(TEMPTABLE_CHAMBER)
|
||||
#else
|
||||
#define CHAMBER_TEMPTABLE_LEN 0
|
||||
#define TEMPTABLE_CHAMBER_LEN 0
|
||||
#endif
|
||||
#ifdef THERMISTORPROBE
|
||||
#define PROBE_TEMPTABLE TT_NAME(THERMISTORPROBE)
|
||||
#define PROBE_TEMPTABLE_LEN COUNT(PROBE_TEMPTABLE)
|
||||
|
||||
#if TEMP_SENSOR_COOLER > 0
|
||||
#define TEMPTABLE_COOLER TT_NAME(TEMP_SENSOR_COOLER)
|
||||
#define TEMPTABLE_COOLER_LEN COUNT(TEMPTABLE_COOLER)
|
||||
#else
|
||||
#define PROBE_TEMPTABLE_LEN 0
|
||||
#define TEMPTABLE_COOLER_LEN 0
|
||||
#endif
|
||||
|
||||
#if TEMP_SENSOR_PROBE > 0
|
||||
#define TEMPTABLE_PROBE TT_NAME(TEMP_SENSOR_PROBE)
|
||||
#define TEMPTABLE_PROBE_LEN COUNT(TEMPTABLE_PROBE)
|
||||
#else
|
||||
#define TEMPTABLE_PROBE_LEN 0
|
||||
#endif
|
||||
|
||||
#if TEMP_SENSOR_BOARD > 0
|
||||
#define TEMPTABLE_BOARD TT_NAME(TEMP_SENSOR_BOARD)
|
||||
#define TEMPTABLE_BOARD_LEN COUNT(TEMPTABLE_BOARD)
|
||||
#else
|
||||
#define TEMPTABLE_BOARD_LEN 0
|
||||
#endif
|
||||
|
||||
#if TEMP_SENSOR_REDUNDANT > 0
|
||||
#define TEMPTABLE_REDUNDANT TT_NAME(TEMP_SENSOR_REDUNDANT)
|
||||
#define TEMPTABLE_REDUNDANT_LEN COUNT(TEMPTABLE_REDUNDANT)
|
||||
#else
|
||||
#define TEMPTABLE_REDUNDANT_LEN 0
|
||||
#endif
|
||||
|
||||
// The SCAN_THERMISTOR_TABLE macro needs alteration?
|
||||
static_assert(
|
||||
HEATER_0_TEMPTABLE_LEN < 256 && HEATER_1_TEMPTABLE_LEN < 256
|
||||
&& HEATER_2_TEMPTABLE_LEN < 256 && HEATER_3_TEMPTABLE_LEN < 256
|
||||
&& HEATER_4_TEMPTABLE_LEN < 256 && HEATER_5_TEMPTABLE_LEN < 256
|
||||
&& HEATER_6_TEMPTABLE_LEN < 258 && HEATER_7_TEMPTABLE_LEN < 258
|
||||
&& BED_TEMPTABLE_LEN < 256 && CHAMBER_TEMPTABLE_LEN < 256
|
||||
&& PROBE_TEMPTABLE_LEN < 256,
|
||||
"Temperature conversion tables over 255 entries need special consideration."
|
||||
static_assert(255 > TEMPTABLE_0_LEN || 255 > TEMPTABLE_1_LEN || 255 > TEMPTABLE_2_LEN || 255 > TEMPTABLE_3_LEN
|
||||
|| 255 > TEMPTABLE_4_LEN || 255 > TEMPTABLE_5_LEN || 255 > TEMPTABLE_6_LEN || 255 > TEMPTABLE_7_LEN
|
||||
|| 255 > TEMPTABLE_BED_LEN
|
||||
|| 255 > TEMPTABLE_CHAMBER_LEN
|
||||
|| 255 > TEMPTABLE_COOLER_LEN
|
||||
|| 255 > TEMPTABLE_PROBE_LEN
|
||||
|| 255 > TEMPTABLE_BOARD_LEN
|
||||
|| 255 > TEMPTABLE_REDUNDANT_LEN
|
||||
, "Temperature conversion tables over 255 entries need special consideration."
|
||||
);
|
||||
|
||||
// Set the high and low raw values for the heaters
|
||||
// For thermistors the highest temperature results in the lowest ADC value
|
||||
// For thermocouples the highest temperature results in the highest ADC value
|
||||
#ifndef HEATER_0_RAW_HI_TEMP
|
||||
#if defined(REVERSE_TEMP_SENSOR_RANGE) || !defined(HEATER_0_USES_THERMISTOR)
|
||||
#define HEATER_0_RAW_HI_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#define HEATER_0_RAW_LO_TEMP 0
|
||||
|
||||
#define _TT_REV(N) REVERSE_TEMP_SENSOR_RANGE_##N
|
||||
#define TT_REV(N) TERN0(TEMP_SENSOR_##N##_IS_THERMISTOR, DEFER4(_TT_REV)(TEMP_SENSOR_##N))
|
||||
#define _TT_REVRAW(N) !TEMP_SENSOR_##N##_IS_THERMISTOR
|
||||
#define TT_REVRAW(N) (TT_REV(N) || _TT_REVRAW(N))
|
||||
|
||||
#ifdef TEMPTABLE_0
|
||||
#if TT_REV(0)
|
||||
#define TEMP_SENSOR_0_MINTEMP_IND 0
|
||||
#define TEMP_SENSOR_0_MAXTEMP_IND TEMPTABLE_0_LEN - 1
|
||||
#else
|
||||
#define HEATER_0_RAW_HI_TEMP 0
|
||||
#define HEATER_0_RAW_LO_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#define TEMP_SENSOR_0_MINTEMP_IND TEMPTABLE_0_LEN - 1
|
||||
#define TEMP_SENSOR_0_MAXTEMP_IND 0
|
||||
#endif
|
||||
#endif
|
||||
#ifndef HEATER_1_RAW_HI_TEMP
|
||||
#if defined(REVERSE_TEMP_SENSOR_RANGE) || !defined(HEATER_1_USES_THERMISTOR)
|
||||
#define HEATER_1_RAW_HI_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#define HEATER_1_RAW_LO_TEMP 0
|
||||
#ifdef TEMPTABLE_1
|
||||
#if TT_REV(1)
|
||||
#define TEMP_SENSOR_1_MINTEMP_IND 0
|
||||
#define TEMP_SENSOR_1_MAXTEMP_IND TEMPTABLE_1_LEN - 1
|
||||
#else
|
||||
#define HEATER_1_RAW_HI_TEMP 0
|
||||
#define HEATER_1_RAW_LO_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#define TEMP_SENSOR_1_MINTEMP_IND TEMPTABLE_1_LEN - 1
|
||||
#define TEMP_SENSOR_1_MAXTEMP_IND 0
|
||||
#endif
|
||||
#endif
|
||||
#ifndef HEATER_2_RAW_HI_TEMP
|
||||
#if defined(REVERSE_TEMP_SENSOR_RANGE) || !defined(HEATER_2_USES_THERMISTOR)
|
||||
#define HEATER_2_RAW_HI_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#define HEATER_2_RAW_LO_TEMP 0
|
||||
#ifdef TEMPTABLE_2
|
||||
#if TT_REV(2)
|
||||
#define TEMP_SENSOR_2_MINTEMP_IND 0
|
||||
#define TEMP_SENSOR_2_MAXTEMP_IND TEMPTABLE_2_LEN - 1
|
||||
#else
|
||||
#define HEATER_2_RAW_HI_TEMP 0
|
||||
#define HEATER_2_RAW_LO_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#define TEMP_SENSOR_2_MINTEMP_IND TEMPTABLE_2_LEN - 1
|
||||
#define TEMP_SENSOR_2_MAXTEMP_IND 0
|
||||
#endif
|
||||
#endif
|
||||
#ifndef HEATER_3_RAW_HI_TEMP
|
||||
#if defined(REVERSE_TEMP_SENSOR_RANGE) || !defined(HEATER_3_USES_THERMISTOR)
|
||||
#define HEATER_3_RAW_HI_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#define HEATER_3_RAW_LO_TEMP 0
|
||||
#ifdef TEMPTABLE_3
|
||||
#if TT_REV(3)
|
||||
#define TEMP_SENSOR_3_MINTEMP_IND 0
|
||||
#define TEMP_SENSOR_3_MAXTEMP_IND TEMPTABLE_3_LEN - 1
|
||||
#else
|
||||
#define HEATER_3_RAW_HI_TEMP 0
|
||||
#define HEATER_3_RAW_LO_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#define TEMP_SENSOR_3_MINTEMP_IND TEMPTABLE_3_LEN - 1
|
||||
#define TEMP_SENSOR_3_MAXTEMP_IND 0
|
||||
#endif
|
||||
#endif
|
||||
#ifndef HEATER_4_RAW_HI_TEMP
|
||||
#if defined(REVERSE_TEMP_SENSOR_RANGE) || !defined(HEATER_4_USES_THERMISTOR)
|
||||
#define HEATER_4_RAW_HI_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#define HEATER_4_RAW_LO_TEMP 0
|
||||
#ifdef TEMPTABLE_4
|
||||
#if TT_REV(4)
|
||||
#define TEMP_SENSOR_4_MINTEMP_IND 0
|
||||
#define TEMP_SENSOR_4_MAXTEMP_IND TEMPTABLE_4_LEN - 1
|
||||
#else
|
||||
#define HEATER_4_RAW_HI_TEMP 0
|
||||
#define HEATER_4_RAW_LO_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#define TEMP_SENSOR_4_MINTEMP_IND TEMPTABLE_4_LEN - 1
|
||||
#define TEMP_SENSOR_4_MAXTEMP_IND 0
|
||||
#endif
|
||||
#endif
|
||||
#ifndef HEATER_5_RAW_HI_TEMP
|
||||
#if defined(REVERSE_TEMP_SENSOR_RANGE) || !defined(HEATER_5_USES_THERMISTOR)
|
||||
#define HEATER_5_RAW_HI_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#define HEATER_5_RAW_LO_TEMP 0
|
||||
#ifdef TEMPTABLE_5
|
||||
#if TT_REV(5)
|
||||
#define TEMP_SENSOR_5_MINTEMP_IND 0
|
||||
#define TEMP_SENSOR_5_MAXTEMP_IND TEMPTABLE_5_LEN - 1
|
||||
#else
|
||||
#define HEATER_5_RAW_HI_TEMP 0
|
||||
#define HEATER_5_RAW_LO_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#define TEMP_SENSOR_5_MINTEMP_IND TEMPTABLE_5_LEN - 1
|
||||
#define TEMP_SENSOR_5_MAXTEMP_IND 0
|
||||
#endif
|
||||
#endif
|
||||
#ifndef HEATER_6_RAW_HI_TEMP
|
||||
#if defined(REVERSE_TEMP_SENSOR_RANGE) || !defined(HEATER_6_USES_THERMISTOR)
|
||||
#define HEATER_6_RAW_HI_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#define HEATER_6_RAW_LO_TEMP 0
|
||||
#ifdef TEMPTABLE_6
|
||||
#if TT_REV(6)
|
||||
#define TEMP_SENSOR_6_MINTEMP_IND 0
|
||||
#define TEMP_SENSOR_6_MAXTEMP_IND TEMPTABLE_6_LEN - 1
|
||||
#else
|
||||
#define HEATER_6_RAW_HI_TEMP 0
|
||||
#define HEATER_6_RAW_LO_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#define TEMP_SENSOR_6_MINTEMP_IND TEMPTABLE_6_LEN - 1
|
||||
#define TEMP_SENSOR_6_MAXTEMP_IND 0
|
||||
#endif
|
||||
#endif
|
||||
#ifndef HEATER_7_RAW_HI_TEMP
|
||||
#if defined(REVERSE_TEMP_SENSOR_RANGE) || !defined(HEATER_7_USES_THERMISTOR)
|
||||
#define HEATER_7_RAW_HI_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#define HEATER_7_RAW_LO_TEMP 0
|
||||
#ifdef TEMPTABLE_7
|
||||
#if TT_REV(7)
|
||||
#define TEMP_SENSOR_7_MINTEMP_IND 0
|
||||
#define TEMP_SENSOR_7_MAXTEMP_IND TEMPTABLE_7_LEN - 1
|
||||
#else
|
||||
#define HEATER_7_RAW_HI_TEMP 0
|
||||
#define HEATER_7_RAW_LO_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#endif
|
||||
#endif
|
||||
#ifndef HEATER_BED_RAW_HI_TEMP
|
||||
#if defined(REVERSE_TEMP_SENSOR_RANGE) || !defined(HEATER_BED_USES_THERMISTOR)
|
||||
#define HEATER_BED_RAW_HI_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#define HEATER_BED_RAW_LO_TEMP 0
|
||||
#else
|
||||
#define HEATER_BED_RAW_HI_TEMP 0
|
||||
#define HEATER_BED_RAW_LO_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#endif
|
||||
#endif
|
||||
#ifndef HEATER_CHAMBER_RAW_HI_TEMP
|
||||
#if defined(REVERSE_TEMP_SENSOR_RANGE) || !defined(HEATER_CHAMBER_USES_THERMISTOR)
|
||||
#define HEATER_CHAMBER_RAW_HI_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#define HEATER_CHAMBER_RAW_LO_TEMP 0
|
||||
#else
|
||||
#define HEATER_CHAMBER_RAW_HI_TEMP 0
|
||||
#define HEATER_CHAMBER_RAW_LO_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#define TEMP_SENSOR_7_MINTEMP_IND TEMPTABLE_7_LEN - 1
|
||||
#define TEMP_SENSOR_7_MAXTEMP_IND 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#undef REVERSE_TEMP_SENSOR_RANGE
|
||||
#ifndef TEMP_SENSOR_0_RAW_HI_TEMP
|
||||
#if TT_REVRAW(0)
|
||||
#define TEMP_SENSOR_0_RAW_HI_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#define TEMP_SENSOR_0_RAW_LO_TEMP 0
|
||||
#else
|
||||
#define TEMP_SENSOR_0_RAW_HI_TEMP 0
|
||||
#define TEMP_SENSOR_0_RAW_LO_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#endif
|
||||
#endif
|
||||
#ifndef TEMP_SENSOR_1_RAW_HI_TEMP
|
||||
#if TT_REVRAW(1)
|
||||
#define TEMP_SENSOR_1_RAW_HI_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#define TEMP_SENSOR_1_RAW_LO_TEMP 0
|
||||
#else
|
||||
#define TEMP_SENSOR_1_RAW_HI_TEMP 0
|
||||
#define TEMP_SENSOR_1_RAW_LO_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#endif
|
||||
#endif
|
||||
#ifndef TEMP_SENSOR_2_RAW_HI_TEMP
|
||||
#if TT_REVRAW(2)
|
||||
#define TEMP_SENSOR_2_RAW_HI_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#define TEMP_SENSOR_2_RAW_LO_TEMP 0
|
||||
#else
|
||||
#define TEMP_SENSOR_2_RAW_HI_TEMP 0
|
||||
#define TEMP_SENSOR_2_RAW_LO_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#endif
|
||||
#endif
|
||||
#ifndef TEMP_SENSOR_3_RAW_HI_TEMP
|
||||
#if TT_REVRAW(3)
|
||||
#define TEMP_SENSOR_3_RAW_HI_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#define TEMP_SENSOR_3_RAW_LO_TEMP 0
|
||||
#else
|
||||
#define TEMP_SENSOR_3_RAW_HI_TEMP 0
|
||||
#define TEMP_SENSOR_3_RAW_LO_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#endif
|
||||
#endif
|
||||
#ifndef TEMP_SENSOR_4_RAW_HI_TEMP
|
||||
#if TT_REVRAW(4)
|
||||
#define TEMP_SENSOR_4_RAW_HI_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#define TEMP_SENSOR_4_RAW_LO_TEMP 0
|
||||
#else
|
||||
#define TEMP_SENSOR_4_RAW_HI_TEMP 0
|
||||
#define TEMP_SENSOR_4_RAW_LO_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#endif
|
||||
#endif
|
||||
#ifndef TEMP_SENSOR_5_RAW_HI_TEMP
|
||||
#if TT_REVRAW(5)
|
||||
#define TEMP_SENSOR_5_RAW_HI_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#define TEMP_SENSOR_5_RAW_LO_TEMP 0
|
||||
#else
|
||||
#define TEMP_SENSOR_5_RAW_HI_TEMP 0
|
||||
#define TEMP_SENSOR_5_RAW_LO_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#endif
|
||||
#endif
|
||||
#ifndef TEMP_SENSOR_6_RAW_HI_TEMP
|
||||
#if TT_REVRAW(6)
|
||||
#define TEMP_SENSOR_6_RAW_HI_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#define TEMP_SENSOR_6_RAW_LO_TEMP 0
|
||||
#else
|
||||
#define TEMP_SENSOR_6_RAW_HI_TEMP 0
|
||||
#define TEMP_SENSOR_6_RAW_LO_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#endif
|
||||
#endif
|
||||
#ifndef TEMP_SENSOR_7_RAW_HI_TEMP
|
||||
#if TT_REVRAW(7)
|
||||
#define TEMP_SENSOR_7_RAW_HI_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#define TEMP_SENSOR_7_RAW_LO_TEMP 0
|
||||
#else
|
||||
#define TEMP_SENSOR_7_RAW_HI_TEMP 0
|
||||
#define TEMP_SENSOR_7_RAW_LO_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#endif
|
||||
#endif
|
||||
#ifndef TEMP_SENSOR_BED_RAW_HI_TEMP
|
||||
#if TT_REVRAW(BED)
|
||||
#define TEMP_SENSOR_BED_RAW_HI_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#define TEMP_SENSOR_BED_RAW_LO_TEMP 0
|
||||
#else
|
||||
#define TEMP_SENSOR_BED_RAW_HI_TEMP 0
|
||||
#define TEMP_SENSOR_BED_RAW_LO_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#endif
|
||||
#endif
|
||||
#ifndef TEMP_SENSOR_CHAMBER_RAW_HI_TEMP
|
||||
#if TT_REVRAW(CHAMBER)
|
||||
#define TEMP_SENSOR_CHAMBER_RAW_HI_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#define TEMP_SENSOR_CHAMBER_RAW_LO_TEMP 0
|
||||
#else
|
||||
#define TEMP_SENSOR_CHAMBER_RAW_HI_TEMP 0
|
||||
#define TEMP_SENSOR_CHAMBER_RAW_LO_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#endif
|
||||
#endif
|
||||
#ifndef TEMP_SENSOR_COOLER_RAW_HI_TEMP
|
||||
#if TT_REVRAW(COOLER)
|
||||
#define TEMP_SENSOR_COOLER_RAW_HI_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#define TEMP_SENSOR_COOLER_RAW_LO_TEMP 0
|
||||
#else
|
||||
#define TEMP_SENSOR_COOLER_RAW_HI_TEMP 0
|
||||
#define TEMP_SENSOR_COOLER_RAW_LO_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#endif
|
||||
#endif
|
||||
#ifndef TEMP_SENSOR_PROBE_RAW_HI_TEMP
|
||||
#if TT_REVRAW(PROBE)
|
||||
#define TEMP_SENSOR_PROBE_RAW_HI_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#define TEMP_SENSOR_PROBE_RAW_LO_TEMP 0
|
||||
#else
|
||||
#define TEMP_SENSOR_PROBE_RAW_HI_TEMP 0
|
||||
#define TEMP_SENSOR_PROBE_RAW_LO_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#endif
|
||||
#endif
|
||||
#ifndef TEMP_SENSOR_BOARD_RAW_HI_TEMP
|
||||
#if TT_REVRAW(BOARD)
|
||||
#define TEMP_SENSOR_BOARD_RAW_HI_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#define TEMP_SENSOR_BOARD_RAW_LO_TEMP 0
|
||||
#else
|
||||
#define TEMP_SENSOR_BOARD_RAW_HI_TEMP 0
|
||||
#define TEMP_SENSOR_BOARD_RAW_LO_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#endif
|
||||
#endif
|
||||
#ifndef TEMP_SENSOR_REDUNDANT_RAW_HI_TEMP
|
||||
#if TT_REVRAW(REDUNDANT)
|
||||
#define TEMP_SENSOR_REDUNDANT_RAW_HI_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#define TEMP_SENSOR_REDUNDANT_RAW_LO_TEMP 0
|
||||
#else
|
||||
#define TEMP_SENSOR_REDUNDANT_RAW_HI_TEMP 0
|
||||
#define TEMP_SENSOR_REDUNDANT_RAW_LO_TEMP MAX_RAW_THERMISTOR_VALUE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#undef __TT_REV
|
||||
#undef _TT_REV
|
||||
#undef TT_REV
|
||||
#undef _TT_REVRAW
|
||||
#undef TT_REVRAW
|
||||
|
1047
Marlin/src/module/tool_change.cpp
Executable file → Normal file
1047
Marlin/src/module/tool_change.cpp
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
67
Marlin/src/module/tool_change.h
Executable file → Normal file
67
Marlin/src/module/tool_change.h
Executable file → Normal file
@@ -16,22 +16,24 @@
|
||||
* 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/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../inc/MarlinConfigPre.h"
|
||||
#include "../core/types.h"
|
||||
#include "../inc/MarlinConfig.h"
|
||||
|
||||
#if EXTRUDERS > 1
|
||||
//#define DEBUG_TOOLCHANGE_MIGRATION_FEATURE
|
||||
|
||||
#if HAS_MULTI_EXTRUDER
|
||||
|
||||
typedef struct {
|
||||
#if ENABLED(TOOLCHANGE_FILAMENT_SWAP)
|
||||
float swap_length, extra_prime;
|
||||
int16_t prime_speed, retract_speed;
|
||||
float swap_length, extra_prime, extra_resume;
|
||||
int16_t prime_speed, retract_speed, unretract_speed, fan, fan_speed, fan_time;
|
||||
#endif
|
||||
#if ENABLED(TOOLCHANGE_PARK)
|
||||
bool enable_park;
|
||||
xy_pos_t change_point;
|
||||
#endif
|
||||
float z_raise;
|
||||
@@ -39,6 +41,27 @@
|
||||
|
||||
extern toolchange_settings_t toolchange_settings;
|
||||
|
||||
#if ENABLED(TOOLCHANGE_FILAMENT_SWAP)
|
||||
void tool_change_prime();
|
||||
#endif
|
||||
|
||||
#if ENABLED(TOOLCHANGE_FS_PRIME_FIRST_USED)
|
||||
extern bool enable_first_prime;
|
||||
#endif
|
||||
|
||||
#if ENABLED(TOOLCHANGE_FS_INIT_BEFORE_SWAP)
|
||||
extern bool toolchange_extruder_ready[EXTRUDERS];
|
||||
#endif
|
||||
|
||||
#if ENABLED(TOOLCHANGE_MIGRATION_FEATURE)
|
||||
typedef struct {
|
||||
uint8_t target, last;
|
||||
bool automode, in_progress;
|
||||
} migration_settings_t;
|
||||
constexpr migration_settings_t migration_defaults = { 0, 0, false, false };
|
||||
extern migration_settings_t migration;
|
||||
bool extruder_migration();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if DO_SWITCH_EXTRUDER
|
||||
@@ -56,19 +79,18 @@
|
||||
|
||||
#if ENABLED(PARKING_EXTRUDER)
|
||||
|
||||
#if ENABLED(PARKING_EXTRUDER_SOLENOIDS_INVERT)
|
||||
#define PE_MAGNET_ON_STATE !PARKING_EXTRUDER_SOLENOIDS_PINS_ACTIVE
|
||||
#else
|
||||
#define PE_MAGNET_ON_STATE PARKING_EXTRUDER_SOLENOIDS_PINS_ACTIVE
|
||||
#endif
|
||||
void pe_solenoid_set_pin_state(const uint8_t extruder_num, const uint8_t state);
|
||||
|
||||
void pe_set_solenoid(const uint8_t extruder_num, const uint8_t state);
|
||||
|
||||
inline void pe_activate_solenoid(const uint8_t extruder_num) { pe_set_solenoid(extruder_num, PE_MAGNET_ON_STATE); }
|
||||
inline void pe_deactivate_solenoid(const uint8_t extruder_num) { pe_set_solenoid(extruder_num, !PE_MAGNET_ON_STATE); }
|
||||
#define PE_MAGNET_ON_STATE TERN_(PARKING_EXTRUDER_SOLENOIDS_INVERT, !)PARKING_EXTRUDER_SOLENOIDS_PINS_ACTIVE
|
||||
inline void pe_solenoid_magnet_on(const uint8_t extruder_num) { pe_solenoid_set_pin_state(extruder_num, PE_MAGNET_ON_STATE); }
|
||||
inline void pe_solenoid_magnet_off(const uint8_t extruder_num) { pe_solenoid_set_pin_state(extruder_num, !PE_MAGNET_ON_STATE); }
|
||||
|
||||
void pe_solenoid_init();
|
||||
|
||||
extern bool extruder_parked;
|
||||
inline void parking_extruder_set_parked(const bool parked) { extruder_parked = parked; }
|
||||
bool parking_extruder_unpark_after_homing(const uint8_t final_tool, bool homed_towards_final_tool);
|
||||
|
||||
#elif ENABLED(MAGNETIC_PARKING_EXTRUDER)
|
||||
|
||||
typedef struct MPESettings {
|
||||
@@ -86,19 +108,16 @@
|
||||
|
||||
#endif
|
||||
|
||||
#if ENABLED(SINGLENOZZLE)
|
||||
extern uint16_t singlenozzle_temp[EXTRUDERS];
|
||||
#if FAN_COUNT > 0
|
||||
extern uint8_t singlenozzle_fan_speed[EXTRUDERS];
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ENABLED(ELECTROMAGNETIC_SWITCHING_TOOLHEAD)
|
||||
void est_init();
|
||||
#elif ENABLED(SWITCHING_TOOLHEAD)
|
||||
void swt_init();
|
||||
#endif
|
||||
|
||||
#if ENABLED(SWITCHING_TOOLHEAD)
|
||||
void swt_init();
|
||||
#if ENABLED(TOOL_SENSOR)
|
||||
uint8_t check_tool_sensor_stats(const uint8_t active_tool, const bool kill_on_error=false, const bool disable=false);
|
||||
#else
|
||||
inline uint8_t check_tool_sensor_stats(const uint8_t, const bool=false, const bool=false) { return 0; }
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user