|
@ -20,15 +20,17 @@ |
|
|
* |
|
|
* |
|
|
*/ |
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
#include "../inc/MarlinConfig.h" |
|
|
|
|
|
|
|
|
|
|
|
#if ENABLED(NOZZLE_CLEAN_FEATURE) || ENABLED(NOZZLE_PARK_FEATURE) |
|
|
|
|
|
|
|
|
#include "nozzle.h" |
|
|
#include "nozzle.h" |
|
|
|
|
|
|
|
|
#include "../Marlin.h" |
|
|
#include "../Marlin.h" |
|
|
#include "../module/motion.h" |
|
|
#include "../module/motion.h" |
|
|
#include "point_t.h" |
|
|
#include "point_t.h" |
|
|
|
|
|
|
|
|
#if ENABLED(DELTA) |
|
|
#if ENABLED(NOZZLE_CLEAN_FEATURE) |
|
|
#include "../module/delta.h" |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
/**
|
|
|
* @brief Stroke clean pattern |
|
|
* @brief Stroke clean pattern |
|
@ -38,26 +40,13 @@ |
|
|
* @param end point_t defining the ending point |
|
|
* @param end point_t defining the ending point |
|
|
* @param strokes number of strokes to execute |
|
|
* @param strokes number of strokes to execute |
|
|
*/ |
|
|
*/ |
|
|
void Nozzle::stroke( |
|
|
void Nozzle::stroke(const point_t &start, const point_t &end, const uint8_t &strokes) { |
|
|
_UNUSED point_t const &start, |
|
|
|
|
|
_UNUSED point_t const &end, |
|
|
|
|
|
_UNUSED uint8_t const &strokes |
|
|
|
|
|
) { |
|
|
|
|
|
#if ENABLED(NOZZLE_CLEAN_FEATURE) |
|
|
|
|
|
|
|
|
|
|
|
#if ENABLED(NOZZLE_CLEAN_GOBACK) |
|
|
#if ENABLED(NOZZLE_CLEAN_GOBACK) |
|
|
// Store the current coords
|
|
|
const float ix = current_position[X_AXIS], iy = current_position[Y_AXIS], iz = current_position[Z_AXIS]; |
|
|
point_t const initial = { |
|
|
#endif |
|
|
current_position[X_AXIS], |
|
|
|
|
|
current_position[Y_AXIS], |
|
|
|
|
|
current_position[Z_AXIS], |
|
|
|
|
|
current_position[E_AXIS] |
|
|
|
|
|
}; |
|
|
|
|
|
#endif // NOZZLE_CLEAN_GOBACK
|
|
|
|
|
|
|
|
|
|
|
|
// Move to the starting point
|
|
|
// Move to the starting point
|
|
|
do_blocking_move_to_xy(start.x, start.y); |
|
|
do_blocking_move_to(start.x, start.y, start.z); |
|
|
do_blocking_move_to_z(start.z); |
|
|
|
|
|
|
|
|
|
|
|
// Start the stroke pattern
|
|
|
// Start the stroke pattern
|
|
|
for (uint8_t i = 0; i < (strokes >> 1); i++) { |
|
|
for (uint8_t i = 0; i < (strokes >> 1); i++) { |
|
@ -66,72 +55,55 @@ void Nozzle::stroke( |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
#if ENABLED(NOZZLE_CLEAN_GOBACK) |
|
|
#if ENABLED(NOZZLE_CLEAN_GOBACK) |
|
|
// Move the nozzle to the initial point
|
|
|
do_blocking_move_to(ix, iy, iz); |
|
|
do_blocking_move_to(initial.x, initial.y, initial.z); |
|
|
#endif |
|
|
#endif // NOZZLE_CLEAN_GOBACK
|
|
|
|
|
|
|
|
|
|
|
|
#endif // NOZZLE_CLEAN_FEATURE
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/**
|
|
|
/**
|
|
|
* @brief Zig-zag clean pattern |
|
|
* @brief Zig-zag clean pattern |
|
|
* @details Apply a zig-zag cleanning pattern |
|
|
* @details Apply a zig-zag cleaning pattern |
|
|
* |
|
|
* |
|
|
* @param start point_t defining the starting point |
|
|
* @param start point_t defining the starting point |
|
|
* @param end point_t defining the ending point |
|
|
* @param end point_t defining the ending point |
|
|
* @param strokes number of strokes to execute |
|
|
* @param strokes number of strokes to execute |
|
|
* @param objects number of objects to create |
|
|
* @param objects number of triangles to do |
|
|
*/ |
|
|
*/ |
|
|
void Nozzle::zigzag( |
|
|
void Nozzle::zigzag(const point_t &start, const point_t &end, const uint8_t &strokes, const uint8_t &objects) { |
|
|
_UNUSED point_t const &start, |
|
|
const float diffx = end.x - start.x, diffy = end.y - start.y; |
|
|
_UNUSED point_t const &end, |
|
|
if (!diffx || !diffy) return; |
|
|
_UNUSED uint8_t const &strokes, |
|
|
|
|
|
_UNUSED uint8_t const &objects |
|
|
|
|
|
) { |
|
|
|
|
|
#if ENABLED(NOZZLE_CLEAN_FEATURE) |
|
|
|
|
|
const float A = nozzle_clean_horizontal ? nozzle_clean_height : nozzle_clean_length, // [twice the] Amplitude
|
|
|
|
|
|
P = (nozzle_clean_horizontal ? nozzle_clean_length : nozzle_clean_height) / (objects << 1); // Period
|
|
|
|
|
|
|
|
|
|
|
|
// Don't allow impossible triangles
|
|
|
|
|
|
if (A <= 0.0f || P <= 0.0f ) return; |
|
|
|
|
|
|
|
|
|
|
|
#if ENABLED(NOZZLE_CLEAN_GOBACK) |
|
|
#if ENABLED(NOZZLE_CLEAN_GOBACK) |
|
|
// Store the current coords
|
|
|
const float ix = current_position[X_AXIS], iy = current_position[Y_AXIS], iz = current_position[Z_AXIS]; |
|
|
point_t const initial = { |
|
|
#endif |
|
|
current_position[X_AXIS], |
|
|
|
|
|
current_position[Y_AXIS], |
|
|
|
|
|
current_position[Z_AXIS], |
|
|
|
|
|
current_position[E_AXIS] |
|
|
|
|
|
}; |
|
|
|
|
|
#endif // NOZZLE_CLEAN_GOBACK
|
|
|
|
|
|
|
|
|
|
|
|
for (uint8_t j = 0; j < strokes; j++) { |
|
|
do_blocking_move_to(start.x, start.y, start.z); |
|
|
for (uint8_t i = 0; i < (objects << 1); i++) { |
|
|
|
|
|
float const x = start.x + ( nozzle_clean_horizontal ? i * P : (A/P) * (P - FABS(FMOD((i*P), (2*P)) - P)) ); |
|
|
|
|
|
float const y = start.y + (!nozzle_clean_horizontal ? i * P : (A/P) * (P - FABS(FMOD((i*P), (2*P)) - P)) ); |
|
|
|
|
|
|
|
|
|
|
|
do_blocking_move_to_xy(x, y); |
|
|
const uint8_t zigs = objects << 1; |
|
|
if (i == 0) do_blocking_move_to_z(start.z); |
|
|
const bool horiz = FABS(diffx) >= FABS(diffy); // Do a horizontal wipe?
|
|
|
|
|
|
const float P = (horiz ? diffx : diffy) / zigs; // Period of each zig / zag
|
|
|
|
|
|
const point_t *side; |
|
|
|
|
|
for (uint8_t j = 0; j < strokes; j++) { |
|
|
|
|
|
for (int8_t i = 0; i < zigs; i++) { |
|
|
|
|
|
side = (i & 1) ? &end : &start; |
|
|
|
|
|
if (horiz) |
|
|
|
|
|
do_blocking_move_to_xy(start.x + i * P, side->y); |
|
|
|
|
|
else |
|
|
|
|
|
do_blocking_move_to_xy(side->x, start.y + i * P); |
|
|
} |
|
|
} |
|
|
|
|
|
for (int8_t i = zigs; i >= 0; i--) { |
|
|
for (int i = (objects << 1); i > -1; i--) { |
|
|
side = (i & 1) ? &end : &start; |
|
|
float const x = start.x + ( nozzle_clean_horizontal ? i * P : (A/P) * (P - FABS(FMOD((i*P), (2*P)) - P)) ); |
|
|
if (horiz) |
|
|
float const y = start.y + (!nozzle_clean_horizontal ? i * P : (A/P) * (P - FABS(FMOD((i*P), (2*P)) - P)) ); |
|
|
do_blocking_move_to_xy(start.x + i * P, side->y); |
|
|
|
|
|
else |
|
|
do_blocking_move_to_xy(x, y); |
|
|
do_blocking_move_to_xy(side->x, start.y + i * P); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
#if ENABLED(NOZZLE_CLEAN_GOBACK) |
|
|
#if ENABLED(NOZZLE_CLEAN_GOBACK) |
|
|
// Move the nozzle to the initial point
|
|
|
do_blocking_move_to(ix, iy, iz); |
|
|
do_blocking_move_to_z(initial.z); |
|
|
#endif |
|
|
do_blocking_move_to_xy(initial.x, initial.y); |
|
|
|
|
|
#endif // NOZZLE_CLEAN_GOBACK
|
|
|
|
|
|
|
|
|
|
|
|
#endif // NOZZLE_CLEAN_FEATURE
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
/**
|
|
|
* @brief Circular clean pattern |
|
|
* @brief Circular clean pattern |
|
|
* @details Apply a circular cleaning pattern |
|
|
* @details Apply a circular cleaning pattern |
|
@ -140,62 +112,28 @@ void Nozzle::zigzag( |
|
|
* @param strokes number of strokes to execute |
|
|
* @param strokes number of strokes to execute |
|
|
* @param radius radius of circle |
|
|
* @param radius radius of circle |
|
|
*/ |
|
|
*/ |
|
|
void Nozzle::circle( |
|
|
void Nozzle::circle(const point_t &start, const point_t &middle, const uint8_t &strokes, const float &radius) { |
|
|
_UNUSED point_t const &start, |
|
|
|
|
|
_UNUSED point_t const &middle, |
|
|
|
|
|
_UNUSED uint8_t const &strokes, |
|
|
|
|
|
_UNUSED float const &radius |
|
|
|
|
|
) { |
|
|
|
|
|
#if ENABLED(NOZZLE_CLEAN_FEATURE) |
|
|
|
|
|
if (strokes == 0) return; |
|
|
if (strokes == 0) return; |
|
|
|
|
|
|
|
|
#if ENABLED(NOZZLE_CLEAN_GOBACK) |
|
|
#if ENABLED(NOZZLE_CLEAN_GOBACK) |
|
|
// Store the current coords
|
|
|
const float ix = current_position[X_AXIS], iy = current_position[Y_AXIS], iz = current_position[Z_AXIS]; |
|
|
point_t const initial = { |
|
|
#endif |
|
|
current_position[X_AXIS], |
|
|
|
|
|
current_position[Y_AXIS], |
|
|
|
|
|
current_position[Z_AXIS], |
|
|
|
|
|
current_position[E_AXIS] |
|
|
|
|
|
}; |
|
|
|
|
|
#endif // NOZZLE_CLEAN_GOBACK
|
|
|
|
|
|
|
|
|
|
|
|
if (start.z <= current_position[Z_AXIS]) { |
|
|
|
|
|
// Order of movement is pretty darn important here
|
|
|
|
|
|
do_blocking_move_to_xy(start.x, start.y); |
|
|
|
|
|
do_blocking_move_to_z(start.z); |
|
|
|
|
|
} |
|
|
|
|
|
else { |
|
|
|
|
|
do_blocking_move_to_z(start.z); |
|
|
|
|
|
do_blocking_move_to_xy(start.x, start.y); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
float x, y; |
|
|
do_blocking_move_to(start.x, start.y, start.z); |
|
|
for (uint8_t s = 0; s < strokes; s++) { |
|
|
|
|
|
for (uint8_t i = 0; i < NOZZLE_CLEAN_CIRCLE_FN; i++) { |
|
|
|
|
|
x = middle.x + sin((M_2_PI / NOZZLE_CLEAN_CIRCLE_FN) * i) * radius; |
|
|
|
|
|
y = middle.y + cos((M_2_PI / NOZZLE_CLEAN_CIRCLE_FN) * i) * radius; |
|
|
|
|
|
|
|
|
|
|
|
do_blocking_move_to_xy(x, y); |
|
|
for (uint8_t s = 0; s < strokes; s++) |
|
|
} |
|
|
for (uint8_t i = 0; i < NOZZLE_CLEAN_CIRCLE_FN; i++) |
|
|
} |
|
|
do_blocking_move_to_xy( |
|
|
|
|
|
middle.x + sin((M_2_PI / NOZZLE_CLEAN_CIRCLE_FN) * i) * radius, |
|
|
|
|
|
middle.y + cos((M_2_PI / NOZZLE_CLEAN_CIRCLE_FN) * i) * radius |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
// Let's be safe
|
|
|
// Let's be safe
|
|
|
do_blocking_move_to_xy(start.x, start.y); |
|
|
do_blocking_move_to_xy(start.x, start.y); |
|
|
|
|
|
|
|
|
#if ENABLED(NOZZLE_CLEAN_GOBACK) |
|
|
#if ENABLED(NOZZLE_CLEAN_GOBACK) |
|
|
// Move the nozzle to the initial point
|
|
|
do_blocking_move_to(ix, iy, iz); |
|
|
if (start.z <= initial.z) { |
|
|
#endif |
|
|
// As above order is important
|
|
|
|
|
|
do_blocking_move_to_z(initial.z); |
|
|
|
|
|
do_blocking_move_to_xy(initial.x, initial.y); |
|
|
|
|
|
} |
|
|
|
|
|
else { |
|
|
|
|
|
do_blocking_move_to_xy(initial.x, initial.y); |
|
|
|
|
|
do_blocking_move_to_z(initial.z); |
|
|
|
|
|
} |
|
|
|
|
|
#endif // NOZZLE_CLEAN_GOBACK
|
|
|
|
|
|
|
|
|
|
|
|
#endif // NOZZLE_CLEAN_FEATURE
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/**
|
|
|
/**
|
|
@ -205,61 +143,44 @@ void Nozzle::circle( |
|
|
* @param pattern one of the available patterns |
|
|
* @param pattern one of the available patterns |
|
|
* @param argument depends on the cleaning pattern |
|
|
* @param argument depends on the cleaning pattern |
|
|
*/ |
|
|
*/ |
|
|
void Nozzle::clean( |
|
|
void Nozzle::clean(const uint8_t &pattern, const uint8_t &strokes, const float &radius, const uint8_t &objects/*=0*/) { |
|
|
_UNUSED uint8_t const &pattern, |
|
|
|
|
|
_UNUSED uint8_t const &strokes, |
|
|
|
|
|
_UNUSED float const &radius, |
|
|
|
|
|
_UNUSED uint8_t const &objects |
|
|
|
|
|
) { |
|
|
|
|
|
#if ENABLED(NOZZLE_CLEAN_FEATURE) |
|
|
|
|
|
#if ENABLED(DELTA) |
|
|
|
|
|
if (current_position[Z_AXIS] > delta_clip_start_height) |
|
|
|
|
|
do_blocking_move_to_z(delta_clip_start_height); |
|
|
|
|
|
#endif |
|
|
|
|
|
switch (pattern) { |
|
|
switch (pattern) { |
|
|
case 1: |
|
|
case 1: |
|
|
Nozzle::zigzag( |
|
|
zigzag(NOZZLE_CLEAN_START_POINT, NOZZLE_CLEAN_END_POINT, strokes, objects); |
|
|
NOZZLE_CLEAN_START_POINT, |
|
|
|
|
|
NOZZLE_CLEAN_END_POINT, strokes, objects); |
|
|
|
|
|
break; |
|
|
break; |
|
|
|
|
|
|
|
|
case 2: |
|
|
case 2: |
|
|
Nozzle::circle( |
|
|
circle(NOZZLE_CLEAN_START_POINT, NOZZLE_CLEAN_CIRCLE_MIDDLE, strokes, radius); |
|
|
NOZZLE_CLEAN_START_POINT, |
|
|
|
|
|
NOZZLE_CLEAN_CIRCLE_MIDDLE, strokes, radius); |
|
|
|
|
|
break; |
|
|
break; |
|
|
|
|
|
|
|
|
default: |
|
|
default: |
|
|
Nozzle::stroke( |
|
|
stroke(NOZZLE_CLEAN_START_POINT, NOZZLE_CLEAN_END_POINT, strokes); |
|
|
NOZZLE_CLEAN_START_POINT, |
|
|
|
|
|
NOZZLE_CLEAN_END_POINT, strokes); |
|
|
|
|
|
} |
|
|
} |
|
|
#endif // NOZZLE_CLEAN_FEATURE
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void Nozzle::park( |
|
|
#endif // NOZZLE_CLEAN_FEATURE
|
|
|
_UNUSED uint8_t const &z_action |
|
|
|
|
|
) { |
|
|
|
|
|
#if ENABLED(NOZZLE_PARK_FEATURE) |
|
|
#if ENABLED(NOZZLE_PARK_FEATURE) |
|
|
float const z = current_position[Z_AXIS]; |
|
|
|
|
|
point_t const park = NOZZLE_PARK_POINT; |
|
|
void Nozzle::park(const uint8_t &z_action) { |
|
|
|
|
|
const point_t park = NOZZLE_PARK_POINT; |
|
|
|
|
|
|
|
|
switch (z_action) { |
|
|
switch (z_action) { |
|
|
case 1: // force Z-park height
|
|
|
case 1: // Go to Z-park height
|
|
|
do_blocking_move_to_z(park.z); |
|
|
do_blocking_move_to_z(park.z); |
|
|
break; |
|
|
break; |
|
|
|
|
|
|
|
|
case 2: // Raise by Z-park height
|
|
|
case 2: // Raise by Z-park height
|
|
|
do_blocking_move_to_z( |
|
|
do_blocking_move_to_z(min(current_position[Z_AXIS] + park.z, Z_MAX_POS)); |
|
|
(z + park.z > Z_MAX_POS) ? Z_MAX_POS : z + park.z); |
|
|
|
|
|
break; |
|
|
break; |
|
|
|
|
|
|
|
|
default: // Raise to Z-park height if lower
|
|
|
default: // Raise to at least the Z-park height
|
|
|
if (current_position[Z_AXIS] < park.z) |
|
|
do_blocking_move_to_z(max(park.z, current_position[Z_AXIS])); |
|
|
do_blocking_move_to_z(park.z); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
do_blocking_move_to_xy(park.x, park.y); |
|
|
do_blocking_move_to_xy(park.x, park.y); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
#endif // NOZZLE_PARK_FEATURE
|
|
|
#endif // NOZZLE_PARK_FEATURE
|
|
|
} |
|
|
|
|
|
|
|
|
#endif // NOZZLE_CLEAN_FEATURE || NOZZLE_PARK_FEATURE
|
|
|