Refactor joystick support in ExtUI (#15318)
This commit is contained in:
parent
04e4eb35be
commit
8cbb5350ad
@ -77,13 +77,15 @@ Joystick joystick;
|
|||||||
if (READ(JOY_EN_PIN)) return;
|
if (READ(JOY_EN_PIN)) return;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
auto _normalize_joy = [](float &adc, const int16_t raw, const int16_t (&joy_limits)[4]) {
|
auto _normalize_joy = [](float &norm_jog, const int16_t raw, const int16_t (&joy_limits)[4]) {
|
||||||
if (WITHIN(raw, joy_limits[0], joy_limits[3])) {
|
if (WITHIN(raw, joy_limits[0], joy_limits[3])) {
|
||||||
// within limits, check deadzone
|
// within limits, check deadzone
|
||||||
if (raw > joy_limits[2])
|
if (raw > joy_limits[2])
|
||||||
adc = (raw - joy_limits[2]) / float(joy_limits[3] - joy_limits[2]);
|
norm_jog = (raw - joy_limits[2]) / float(joy_limits[3] - joy_limits[2]);
|
||||||
else if (raw < joy_limits[1])
|
else if (raw < joy_limits[1])
|
||||||
adc = (raw - joy_limits[1]) / float(joy_limits[1] - joy_limits[0]); // negative value
|
norm_jog = (raw - joy_limits[1]) / float(joy_limits[1] - joy_limits[0]); // negative value
|
||||||
|
// Map normal to jog value via quadratic relationship
|
||||||
|
norm_jog = SIGN(norm_jog) * sq(norm_jog);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -138,18 +140,22 @@ Joystick joystick;
|
|||||||
// with "jogging" encapsulated as a more general class.
|
// with "jogging" encapsulated as a more general class.
|
||||||
|
|
||||||
#if ENABLED(EXTENSIBLE_UI)
|
#if ENABLED(EXTENSIBLE_UI)
|
||||||
norm_jog[X_AXIS] = ExtUI::norm_jog[X_AXIS];
|
ExtUI::_joystick_update(norm_jog);
|
||||||
norm_jog[Y_AXIS] = ExtUI::norm_jog[Y_AXIS];
|
|
||||||
norm_jog[Z_AXIS] = ExtUI::norm_jog[Z_AXIS];
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Jogging value maps continuously (quadratic relationship) to feedrate
|
#if EITHER(ULTIPANEL, EXTENSIBLE_UI)
|
||||||
|
constexpr float manual_feedrate[XYZE] = MANUAL_FEEDRATE;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// norm_jog values of [-1 .. 1] maps linearly to [-feedrate .. feedrate]
|
||||||
float move_dist[XYZ] = { 0 }, hypot2 = 0;
|
float move_dist[XYZ] = { 0 }, hypot2 = 0;
|
||||||
LOOP_XYZ(i) if (norm_jog[i]) {
|
LOOP_XYZ(i) if (norm_jog[i]) {
|
||||||
move_dist[i] = seg_time * sq(norm_jog[i]) * planner.settings.max_feedrate_mm_s[i];
|
move_dist[i] = seg_time * norm_jog[i] *
|
||||||
// Very small movements disappear when printed as decimal with 4 digits of precision
|
#if EITHER(ULTIPANEL, EXTENSIBLE_UI)
|
||||||
NOLESS(move_dist[i], 0.0002f);
|
MMM_TO_MMS(manual_feedrate[i]);
|
||||||
if (norm_jog[i] < 0) move_dist[i] *= -1; // preserve sign
|
#else
|
||||||
|
planner.settings.max_feedrate_mm_s[i];
|
||||||
|
#endif
|
||||||
hypot2 += sq(move_dist[i]);
|
hypot2 += sq(move_dist[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,12 +105,10 @@
|
|||||||
namespace ExtUI {
|
namespace ExtUI {
|
||||||
static struct {
|
static struct {
|
||||||
uint8_t printer_killed : 1;
|
uint8_t printer_killed : 1;
|
||||||
uint8_t manual_motion : 1;
|
|
||||||
} flags;
|
|
||||||
|
|
||||||
#if ENABLED(JOYSTICK)
|
#if ENABLED(JOYSTICK)
|
||||||
float norm_jog[XYZ];
|
uint8_t jogging : 1;
|
||||||
#endif
|
#endif
|
||||||
|
} flags;
|
||||||
|
|
||||||
#ifdef __SAM3X8E__
|
#ifdef __SAM3X8E__
|
||||||
/**
|
/**
|
||||||
@ -197,14 +195,46 @@ namespace ExtUI {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void jog(float dx, float dy, float dz) {
|
|
||||||
#if ENABLED(JOYSTICK)
|
#if ENABLED(JOYSTICK)
|
||||||
norm_jog[X] = dx;
|
/**
|
||||||
norm_jog[Y] = dy;
|
* Jogs in the direction given by the vector (dx, dy, dz).
|
||||||
norm_jog[Z] = dz;
|
* The values range from -1 to 1 mapping to the maximum
|
||||||
#endif
|
* feedrate for an axis.
|
||||||
|
*
|
||||||
|
* The axis will continue to jog until this function is
|
||||||
|
* called with all zeros.
|
||||||
|
*/
|
||||||
|
void jog(float dx, float dy, float dz) {
|
||||||
|
// The "destination" variable is used as a scratchpad in
|
||||||
|
// Marlin by GCODE routines, but should remain untouched
|
||||||
|
// during manual jogging, allowing us to reuse the space
|
||||||
|
// for our direction vector.
|
||||||
|
destination[X] = dx;
|
||||||
|
destination[Y] = dy;
|
||||||
|
destination[Z] = dz;
|
||||||
|
flags.jogging = !NEAR_ZERO(dx) || !NEAR_ZERO(dy) || !NEAR_ZERO(dz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Called by the polling routine in "joystick.cpp"
|
||||||
|
void _joystick_update(float (&norm_jog)[XYZ]) {
|
||||||
|
if (flags.jogging) {
|
||||||
|
#define OUT_OF_RANGE(VALUE) (VALUE < -1.0f || VALUE > 1.0f)
|
||||||
|
|
||||||
|
if (OUT_OF_RANGE(destination[X_AXIS]) || OUT_OF_RANGE(destination[Y_AXIS]) || OUT_OF_RANGE(destination[Z_AXIS])) {
|
||||||
|
// If destination[] on any axis is out of range, it
|
||||||
|
// probably means the UI forgot to stop jogging and
|
||||||
|
// ran GCODE that wrote a position to destination[].
|
||||||
|
// To prevent a disaster, stop jogging.
|
||||||
|
flags.jogging = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
norm_jog[X_AXIS] = destination[X_AXIS];
|
||||||
|
norm_jog[Y_AXIS] = destination[Y_AXIS];
|
||||||
|
norm_jog[Z_AXIS] = destination[Z_AXIS];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool isHeaterIdle(const extruder_t extruder) {
|
bool isHeaterIdle(const extruder_t extruder) {
|
||||||
return false
|
return false
|
||||||
#if HOTENDS && HEATER_IDLE_HANDLER
|
#if HOTENDS && HEATER_IDLE_HANDLER
|
||||||
@ -288,13 +318,22 @@ namespace ExtUI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
float getAxisPosition_mm(const axis_t axis) {
|
float getAxisPosition_mm(const axis_t axis) {
|
||||||
return flags.manual_motion ? destination[axis] : current_position[axis];
|
return
|
||||||
|
#if ENABLED(JOYSTICK)
|
||||||
|
flags.jogging ? destination[axis] :
|
||||||
|
#endif
|
||||||
|
current_position[axis];
|
||||||
}
|
}
|
||||||
|
|
||||||
float getAxisPosition_mm(const extruder_t extruder) {
|
float getAxisPosition_mm(const extruder_t extruder) {
|
||||||
const extruder_t old_tool = getActiveTool();
|
const extruder_t old_tool = getActiveTool();
|
||||||
setActiveTool(extruder, true);
|
setActiveTool(extruder, true);
|
||||||
const float pos = flags.manual_motion ? destination[E_AXIS] : current_position[E_AXIS];
|
const float pos = (
|
||||||
|
#if ENABLED(JOYSTICK)
|
||||||
|
flags.jogging ? destination[E_AXIS] :
|
||||||
|
#endif
|
||||||
|
current_position[E_AXIS]
|
||||||
|
);
|
||||||
setActiveTool(old_tool, true);
|
setActiveTool(old_tool, true);
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
@ -343,54 +382,23 @@ namespace ExtUI {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
constexpr float max_manual_feedrate[XYZE] = MANUAL_FEEDRATE;
|
constexpr float manual_feedrate[XYZE] = MANUAL_FEEDRATE;
|
||||||
setFeedrate_mm_s(MMM_TO_MMS(max_manual_feedrate[axis]));
|
setFeedrate_mm_s(MMM_TO_MMS(manual_feedrate[axis]));
|
||||||
|
|
||||||
if (!flags.manual_motion) set_destination_from_current();
|
set_destination_from_current();
|
||||||
destination[axis] = constrain(position, min, max);
|
destination[axis] = constrain(position, min, max);
|
||||||
flags.manual_motion = true;
|
prepare_move_to_destination();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setAxisPosition_mm(const float position, const extruder_t extruder) {
|
void setAxisPosition_mm(const float position, const extruder_t extruder) {
|
||||||
setActiveTool(extruder, true);
|
setActiveTool(extruder, true);
|
||||||
|
|
||||||
constexpr float max_manual_feedrate[XYZE] = MANUAL_FEEDRATE;
|
constexpr float manual_feedrate[XYZE] = MANUAL_FEEDRATE;
|
||||||
setFeedrate_mm_s(MMM_TO_MMS(max_manual_feedrate[E_AXIS]));
|
setFeedrate_mm_s(MMM_TO_MMS(manual_feedrate[E_AXIS]));
|
||||||
if (!flags.manual_motion) set_destination_from_current();
|
|
||||||
|
set_destination_from_current();
|
||||||
destination[E_AXIS] = position;
|
destination[E_AXIS] = position;
|
||||||
flags.manual_motion = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _processManualMoveToDestination() {
|
|
||||||
// Lower max_response_lag makes controls more responsive, but makes CPU work harder
|
|
||||||
constexpr float max_response_lag = 0.1; // seconds
|
|
||||||
constexpr uint8_t segments_to_buffer = 4; // keep planner filled with this many segments
|
|
||||||
|
|
||||||
if (flags.manual_motion && planner.movesplanned() < segments_to_buffer) {
|
|
||||||
float saved_destination[XYZ];
|
|
||||||
COPY(saved_destination, destination);
|
|
||||||
// Compute direction vector from current_position towards destination.
|
|
||||||
destination[X_AXIS] -= current_position[X_AXIS];
|
|
||||||
destination[Y_AXIS] -= current_position[Y_AXIS];
|
|
||||||
destination[Z_AXIS] -= current_position[Z_AXIS];
|
|
||||||
const float inv_length = RSQRT(sq(destination[X_AXIS]) + sq(destination[Y_AXIS]) + sq(destination[Z_AXIS]));
|
|
||||||
// Find move segment length so that all segments can execute in less time than max_response_lag
|
|
||||||
const float scale = inv_length * feedrate_mm_s * max_response_lag / segments_to_buffer;
|
|
||||||
if (scale < 1) {
|
|
||||||
// Move a small bit towards the destination.
|
|
||||||
destination[X_AXIS] = scale * destination[X_AXIS] + current_position[X_AXIS];
|
|
||||||
destination[Y_AXIS] = scale * destination[Y_AXIS] + current_position[Y_AXIS];
|
|
||||||
destination[Z_AXIS] = scale * destination[Z_AXIS] + current_position[Z_AXIS];
|
|
||||||
prepare_move_to_destination();
|
prepare_move_to_destination();
|
||||||
COPY(destination, saved_destination);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// We are close enough to finish off the move.
|
|
||||||
COPY(destination, saved_destination);
|
|
||||||
prepare_move_to_destination();
|
|
||||||
flags.manual_motion = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setActiveTool(const extruder_t extruder, bool no_move) {
|
void setActiveTool(const extruder_t extruder, bool no_move) {
|
||||||
@ -1044,7 +1052,6 @@ void MarlinUI::update() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // SDSUPPORT
|
#endif // SDSUPPORT
|
||||||
ExtUI::_processManualMoveToDestination();
|
|
||||||
ExtUI::onIdle();
|
ExtUI::onIdle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,10 +46,6 @@
|
|||||||
|
|
||||||
namespace ExtUI {
|
namespace ExtUI {
|
||||||
|
|
||||||
#if ENABLED(JOYSTICK)
|
|
||||||
extern float norm_jog[];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// The ExtUI implementation can store up to this many bytes
|
// The ExtUI implementation can store up to this many bytes
|
||||||
// in the EEPROM when the methods onStoreSettings and
|
// in the EEPROM when the methods onStoreSettings and
|
||||||
// onLoadSettings are called.
|
// onLoadSettings are called.
|
||||||
@ -84,7 +80,10 @@ namespace ExtUI {
|
|||||||
void enableHeater(const heater_t);
|
void enableHeater(const heater_t);
|
||||||
void enableHeater(const extruder_t);
|
void enableHeater(const extruder_t);
|
||||||
|
|
||||||
|
#if ENABLED(JOYSTICK)
|
||||||
void jog(float dx, float dy, float dz);
|
void jog(float dx, float dy, float dz);
|
||||||
|
void _joystick_update(float (&norm_jog)[XYZ]);
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Getters and setters
|
* Getters and setters
|
||||||
|
Loading…
Reference in New Issue
Block a user