spiral pattern self watering pot
This commit is contained in:
1 parent
6737bd36a0
commit
c8df6abdef
3 files changed
+334
No files matched your search
@@ -0,0 +1,225 @@
|
||||
// ====================================================================
|
||||
// Two-part self-watering flower pot, designed for PETG
|
||||
// ====================================================================
|
||||
// OUTER pot : watertight reservoir cup. Spiral ridges on the outside, smooth tapered inside, with a conical seat at the rim.
|
||||
// INNER pot : planter with drainage holes. Its conical underside rests on the seat, which leaves a water reservoir underneath. It lifts straight out (tapered fit, no snap that can jam).
|
||||
// ====================================================================
|
||||
|
||||
/* [What to render] */
|
||||
part = "print"; // [print:Both parts laid out for printing, outer:Outer pot only, inner:Inner pot only, assembly:Assembled preview, section:Assembled cut-away preview]
|
||||
|
||||
/* [Main dimensions (mm)] */
|
||||
// Outer diameter at the top, measured over the ridge crests
|
||||
pot_diameter = 100;
|
||||
// Height of the outer pot (rim included)
|
||||
pot_height = 100;
|
||||
// Bottom diameter / top diameter (1 = straight sides, lower = more taper)
|
||||
bottom_ratio = 0.8;
|
||||
|
||||
/* [Reservoir, walls and fit] */
|
||||
// Water space between the outer floor and the underside of the inner pot
|
||||
reservoir_depth = 25;
|
||||
// Wall thickness (6 x 0.4 mm lines)
|
||||
wall = 2.4;
|
||||
// Floor thickness of both parts
|
||||
base_thickness = 2.4;
|
||||
// Gap between the inner pot and the outer pot (raise for a looser fit)
|
||||
clearance = 0.4;
|
||||
// Height of the collar that stands above the outer rim (also your finger grip)
|
||||
collar_height = 1;
|
||||
// Horizontal width of the conical seat at the top of the outer pot
|
||||
seat = 1.4;
|
||||
// Steepness of the seat, measured from vertical (smaller = steeper = easier to print; max 50)
|
||||
seat_angle = 40;
|
||||
|
||||
/* [Spiral pattern] */
|
||||
// Number of ridges around the pot
|
||||
ridge_count = 12;
|
||||
// Peak-to-valley depth of the ridges
|
||||
ridge_depth = 2.4;
|
||||
// Total twist from bottom to top in degrees (negative = other direction)
|
||||
twist = 180;
|
||||
|
||||
/* [Drainage holes in the inner pot] */
|
||||
hole_diameter = 5;
|
||||
// Centre-to-centre distance between holes
|
||||
hole_spacing = 12;
|
||||
// Keep-out distance between holes and the wall
|
||||
hole_margin = 3;
|
||||
|
||||
/* [Hidden] */
|
||||
$fn = 1024;
|
||||
bottom_chamfer = 1.2; // height of the elephant-foot chamfer on the outer pot
|
||||
bottom_chamfer_run = 0.8; // its horizontal width (less than the height = under 45 degrees)
|
||||
inner_chamfer = 0.6; // horizontal width of the 1 mm high elephant-foot chamfer on the inner pot
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Derived geometry
|
||||
// ---------------------------------------------------------------------
|
||||
Rt = pot_diameter / 2; // crest radius at the top
|
||||
Rb = Rt * bottom_ratio; // crest radius at the bottom
|
||||
s_top = Rt / Rb; // scale applied by the twisted extrusion
|
||||
Rv = Rt * (1 - ridge_depth / Rb); // valley radius at the top
|
||||
Cb = Rb - ridge_depth - wall; // cavity radius at z = 0
|
||||
Ct = Rv - wall; // cavity radius at z = pot_height
|
||||
zb = base_thickness + reservoir_depth; // z of the inner pot's underside
|
||||
|
||||
m = (Ct - Cb) / pot_height; // slope of the cavity radius (taper)
|
||||
k = tan(seat_angle); // slope of the seat cone (radius per mm of height)
|
||||
seat_dz = seat / k; // vertical height of the seat
|
||||
z_seat = pot_height - seat_dz; // where the seat starts
|
||||
|
||||
function lerp_z(a, b, z) = a + (b - a) * z / pot_height;
|
||||
function cav(z) = lerp_z(Cb, Ct, z); // outer pot: inner (cavity) radius
|
||||
function rb(z) = cav(z) - clearance; // inner pot: outer radius
|
||||
function env(z) = lerp_z(Rb, Rt, z); // crest radius
|
||||
|
||||
r_seat_top = cav(z_seat) + seat; // seat radius at the rim height where the inner pot's wall meets the seat cone
|
||||
z1 = z_seat - clearance / (k - m);
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Sanity checks
|
||||
// ---------------------------------------------------------------------
|
||||
rim_flat = Rv - r_seat_top;
|
||||
overhang = atan((ridge_depth / 2) * ridge_count * (abs(twist) * PI / 180 / pot_height) * s_top
|
||||
+ (Rt - Rb) / pot_height);
|
||||
|
||||
assert(bottom_ratio > 0.4 && bottom_ratio <= 1, "bottom_ratio must be between 0.4 and 1");
|
||||
assert(pot_height > reservoir_depth + 2 * base_thickness + 30,
|
||||
"pot_height is too small for this reservoir_depth");
|
||||
assert(seat_angle > atan(m) + 5 && seat_angle <= 50,
|
||||
"seat_angle must be between about 10 and 50 degrees");
|
||||
assert(rim_flat >= 0.8,
|
||||
"Rim too thin: increase wall, or reduce seat / ridge_depth");
|
||||
assert(z1 > zb + 2,
|
||||
"Seat is too low for this reservoir_depth: reduce seat or increase pot_height");
|
||||
assert(Ct > hole_diameter, "pot_diameter is too small for these settings");
|
||||
|
||||
echo(str("Outer pot, steepest outward overhang: about ", round(overhang), " deg (PETG prints well up to ~40-45)"));
|
||||
echo(str("Inner pot, steepest overhang: ", seat_angle, " deg (seat cone); no flat underside"));
|
||||
if (overhang > 45)
|
||||
echo("WARNING: ridges too steep. Reduce twist, ridge_depth or ridge_count.");
|
||||
echo(str("Flat rim width: ", rim_flat, " mm"));
|
||||
echo(str("Reservoir volume: about ", round(PI * pow(cav(zb / 2), 2) * reservoir_depth / 1000), " ml"));
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// OUTER pot
|
||||
// ---------------------------------------------------------------------
|
||||
module wavy_profile() {
|
||||
n = ridge_count * 16;
|
||||
polygon([for (i = [0 : n - 1])
|
||||
let (a = 360 * i / n,
|
||||
r = Rb - ridge_depth / 2 + (ridge_depth / 2) * cos(ridge_count * a))
|
||||
[r * cos(a), r * sin(a)]]);
|
||||
}
|
||||
|
||||
module spiral_body() {
|
||||
linear_extrude(height = pot_height, twist = twist, scale = s_top,
|
||||
slices = max(ceil(pot_height / 2), ceil(abs(twist) / 2)),
|
||||
convexity = 10)
|
||||
wavy_profile();
|
||||
}
|
||||
|
||||
// Chamfers the bottom edge only; follows the crest line elsewhere.
|
||||
module envelope() {
|
||||
rotate_extrude()
|
||||
polygon([[0, 0],
|
||||
[env(bottom_chamfer) - bottom_chamfer_run + 0.05, 0],
|
||||
[env(bottom_chamfer) + 0.05, bottom_chamfer],
|
||||
[Rt + 0.05, pot_height],
|
||||
[0, pot_height]]);
|
||||
}
|
||||
|
||||
module outer_cavity() {
|
||||
rotate_extrude()
|
||||
polygon([[0, base_thickness],
|
||||
[cav(base_thickness), base_thickness],
|
||||
[cav(z_seat), z_seat],
|
||||
[r_seat_top + k, pot_height + 1], // conical seat, continued past the rim
|
||||
[0, pot_height + 1]]);
|
||||
}
|
||||
|
||||
module outer_part() {
|
||||
difference() {
|
||||
intersection() {
|
||||
spiral_body();
|
||||
envelope();
|
||||
}
|
||||
outer_cavity();
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// INNER pot
|
||||
// ---------------------------------------------------------------------
|
||||
// The outside widens along the seat cone from the wall (z1) up to the rim, then rises as a vertical collar. Nothing hangs out horizontally.
|
||||
module inner_profile() {
|
||||
polygon([[0, zb],
|
||||
[rb(zb + 1) - inner_chamfer, zb], // bottom chamfer, under 45 degrees
|
||||
[rb(zb + 1), zb + 1],
|
||||
[rb(z1), z1],
|
||||
[r_seat_top, pot_height], // rests on the outer pot's seat
|
||||
[r_seat_top, pot_height + collar_height],
|
||||
[0, pot_height + collar_height]]);
|
||||
}
|
||||
|
||||
module inner_cavity() {
|
||||
z0 = zb + base_thickness;
|
||||
rotate_extrude()
|
||||
polygon([[0, z0],
|
||||
[rb(z0) - wall, z0],
|
||||
[rb(pot_height) - wall, pot_height],
|
||||
[rb(pot_height) - wall, pot_height + collar_height + 1],
|
||||
[0, pot_height + collar_height + 1]]);
|
||||
}
|
||||
|
||||
module drain_holes() {
|
||||
fr = rb(zb) - wall - hole_margin;
|
||||
rings = floor((fr - hole_diameter / 2) / hole_spacing);
|
||||
translate([0, 0, zb - 1])
|
||||
linear_extrude(height = base_thickness + 2)
|
||||
union() {
|
||||
circle(d = hole_diameter, $fn = 24);
|
||||
if (rings >= 1)
|
||||
for (k = [1 : rings]) {
|
||||
r = k * hole_spacing;
|
||||
n = floor(2 * PI * r / hole_spacing);
|
||||
for (i = [0 : n - 1])
|
||||
rotate(i * 360 / n + (k % 2) * 180 / n)
|
||||
translate([r, 0])
|
||||
circle(d = hole_diameter, $fn = 24);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module inner_part() {
|
||||
difference() {
|
||||
rotate_extrude() inner_profile();
|
||||
inner_cavity();
|
||||
drain_holes();
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Output
|
||||
// ---------------------------------------------------------------------
|
||||
module assembled() {
|
||||
color("sienna") outer_part();
|
||||
color("seagreen") inner_part();
|
||||
}
|
||||
|
||||
if (part == "outer")
|
||||
outer_part();
|
||||
else if (part == "inner")
|
||||
translate([0, 0, -zb]) inner_part(); // sits on the bed
|
||||
else if (part == "assembly")
|
||||
assembled();
|
||||
else if (part == "section")
|
||||
difference() {
|
||||
assembled();
|
||||
translate([-400, -400, -10]) cube([800, 400, pot_height + 100]);
|
||||
}
|
||||
else { // "print"
|
||||
outer_part();
|
||||
translate([pot_diameter + 10, 0, -zb]) inner_part();
|
||||
}
|
||||
Reference in new issue
Block a user