Skip to content

Commit 1bd250d

Browse files
committed
HP: Allow custom and prism-like setups instead of just pyramid-like setups
- Change from bool to class and introduce None mode for custom (experimental) setups (all allowed) - refactor out IsInsidePyramidSides - refactor out IsInsidePrismSides - introduce HangprinterAnchorMode::LastOnTop for prism-like setups with all anchors on top - introduce a T parameter in M666 to configure the anchor mode
1 parent edb2844 commit 1bd250d

File tree

2 files changed

+53
-9
lines changed

2 files changed

+53
-9
lines changed

src/Movement/Kinematics/HangprinterKinematics.cpp

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ void HangprinterKinematics::Init() noexcept
9999
constexpr float DefaultTorqueConstants[HANGPRINTER_AXES] = { 0.0F };
100100

101101
ARRAY_INIT(anchors, DefaultAnchors);
102+
anchorMode = HangprinterAnchorMode::LastOnTop;
102103
printRadius = DefaultPrintRadius;
103104
spoolBuildupFactor = DefaultSpoolBuildupFactor;
104105
ARRAY_INIT(spoolRadii, DefaultSpoolRadii);
@@ -229,6 +230,12 @@ bool HangprinterKinematics::Configure(unsigned int mCode, GCodeBuffer& gb, const
229230
}
230231
else if (mCode == 666)
231232
{
233+
// 0=None, 1=last-top, 2=all-top, 3-half-top, etc
234+
uint32_t unsignedAnchorMode = (uint32_t)anchorMode;
235+
gb.TryGetUIValue('T', unsignedAnchorMode, seen);
236+
if (unsignedAnchorMode <= (uint32_t)HangprinterAnchorMode::AllOnTop) {
237+
anchorMode = (HangprinterAnchorMode)unsignedAnchorMode;
238+
}
232239
gb.TryGetFValue('Q', spoolBuildupFactor, seen);
233240
gb.TryGetFloatArray('R', HANGPRINTER_AXES, spoolRadii, seen);
234241
gb.TryGetUIArray('U', HANGPRINTER_AXES, mechanicalAdvantage, seen);
@@ -248,7 +255,7 @@ bool HangprinterKinematics::Configure(unsigned int mCode, GCodeBuffer& gb, const
248255
}
249256
else
250257
{
251-
reply.printf("M666 Q%.4f\n", (double)spoolBuildupFactor);
258+
reply.printf("M666 T%u Q%.4f\n", (unsigned)anchorMode, (double)spoolBuildupFactor);
252259
reply.lcat("R:Spool r ");
253260
for (size_t i = 0; i < HANGPRINTER_AXES; ++i)
254261
{
@@ -470,25 +477,51 @@ static bool isSameSide(float const v0[3], float const v1[3], float const v2[3],
470477
return dot0*dot1 > 0.0F;
471478
}
472479

473-
// For each triangle side in a pseudo-pyramid, check if the point is inside the pyramid (Except for the base)
474-
// Also check that any point below the line between two exterior anchors (all anchors are exterior except for the last one)
475-
// is in the "inside part" all the way down to min_Z, however low it may be.
476-
// To further limit the movements in the X and Y axes one can simply set a smaller print radius.
477-
bool HangprinterKinematics::IsReachable(float axesCoords[MaxAxes], AxesBitmap axes) const noexcept /*override*/
480+
bool HangprinterKinematics::IsInsidePyramidSides(float const coords[3]) const noexcept
478481
{
479-
float const coords[3] = {axesCoords[X_AXIS], axesCoords[Y_AXIS], axesCoords[Z_AXIS]};
480482
bool reachable = true;
481483

482484
// Check all the planes defined by triangle sides in the pyramid
483485
for (size_t i = 0; reachable && i < HANGPRINTER_AXES - 1; ++i) {
484486
reachable = reachable && isSameSide(anchors[i], anchors[(i+1) % (HANGPRINTER_AXES - 1)], anchors[HANGPRINTER_AXES - 1], anchors[(i+2) % (HANGPRINTER_AXES - 1)], coords);
485487
}
488+
return reachable;
489+
}
490+
491+
bool HangprinterKinematics::IsInsidePrismSides(float const coords[3], unsigned const discount_last) const noexcept
492+
{
493+
bool reachable = true;
486494

487495
// For each side of the base, check the plane formed by side and another point bellow them in z.
488-
for (size_t i = 0; reachable && i < HANGPRINTER_AXES - 1; ++i) {
496+
for (size_t i = 0; reachable && i < HANGPRINTER_AXES - discount_last; ++i) {
489497
float const lower_point[3] = {anchors[i][0], anchors[i][1], anchors[i][2] - 1};
490498
reachable = reachable && isSameSide(anchors[i], anchors[(i+1) % (HANGPRINTER_AXES - 1)], lower_point, anchors[(i+2) % (HANGPRINTER_AXES - 1)], coords);
491499
}
500+
return reachable;
501+
}
502+
503+
// For each triangle side in a pseudo-pyramid, check if the point is inside the pyramid (Except for the base)
504+
// Also check that any point below the line between two exterior anchors (all anchors are exterior except for the last one)
505+
// is in the "inside part" all the way down to min_Z, however low it may be.
506+
// To further limit the movements in the X and Y axes one can simply set a smaller print radius.
507+
bool HangprinterKinematics::IsReachable(float axesCoords[MaxAxes], AxesBitmap axes) const noexcept /*override*/
508+
{
509+
float const coords[3] = {axesCoords[X_AXIS], axesCoords[Y_AXIS], axesCoords[Z_AXIS]};
510+
bool reachable = true;
511+
512+
switch (anchorMode) {
513+
case HangprinterAnchorMode::None:
514+
return true;
515+
516+
// This reaches a pyramid on top of the lower prism if the bed is below the lower anchors
517+
case HangprinterAnchorMode::LastOnTop:
518+
default:
519+
reachable = reachable && IsInsidePyramidSides(coords);
520+
reachable = reachable && IsInsidePrismSides(coords, 1);
521+
522+
case HangprinterAnchorMode::AllOnTop:
523+
reachable = reachable && IsInsidePrismSides(coords, 0);
524+
};
492525

493526
return reachable;
494527
}
@@ -612,7 +645,7 @@ bool HangprinterKinematics::WriteCalibrationParameters(FileStore *f) const noexc
612645
ok = f->Write(scratchString.c_str());
613646
if (!ok) return false;
614647

615-
scratchString.printf("M666 Q%.6f ", (double)spoolBuildupFactor);
648+
scratchString.printf("M666 T%u Q%.6f ", (unsigned)anchorMode, (double)spoolBuildupFactor);
616649
ok = f->Write(scratchString.c_str());
617650
if (!ok) return false;
618651

src/Movement/Kinematics/HangprinterKinematics.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@
1212

1313
#if SUPPORT_HANGPRINTER
1414

15+
// Different modes can be configured for different tradeoffs in terms of printing volumes and speeds
16+
enum class HangprinterAnchorMode {
17+
None, // All is reacheable in None anchor mode as printing volume
18+
LastOnTop, // (Default) Rsults in a pyramid plus a prism below if the lower anchors are above the printing bed
19+
AllOnTop, // Result in a prism (speeds get limited, specially going down in Z)
20+
};
21+
1522
class HangprinterKinematics : public RoundBedKinematics
1623
{
1724
public:
@@ -55,6 +62,9 @@ class HangprinterKinematics : public RoundBedKinematics
5562
protected:
5663
DECLARE_OBJECT_MODEL_WITH_ARRAYS
5764

65+
bool IsInsidePyramidSides(float const coords[3]) const noexcept;
66+
bool IsInsidePrismSides(float const coords[3], unsigned const discount_last) const noexcept;
67+
5868
private:
5969
// Basic facts about movement system
6070
const char* ANCHOR_CHARS = "ABCD";
@@ -72,6 +82,7 @@ class HangprinterKinematics : public RoundBedKinematics
7282
void PrintParameters(const StringRef& reply) const noexcept; // Print all the parameters for debugging
7383

7484
// The real defaults are in the cpp file
85+
HangprinterAnchorMode anchorMode = HangprinterAnchorMode::LastOnTop;
7586
float printRadius = 0.0F;
7687
float anchors[HANGPRINTER_AXES][3] = {{ 0.0, 0.0, 0.0},
7788
{ 0.0, 0.0, 0.0},

0 commit comments

Comments
 (0)