Seed Starter Tray
A tray of thin-walled square cells for starting seedlings. Each cell tapers toward the bottom, so a seedling slides out with its root ball when the cell is pressed from below, and every cell has a drain hole; a flange across the top ties the cells into one tray. The default is 4 by 6 cells on a 40 mm pitch, 45 mm deep, and measures 240 x 160 x 45 mm. Prints standing on the cell bottoms with no supports, since the taper is well under 45 degrees. Adjustable parameters: rows, cells per row, pitch, depth, wall thickness, taper angle and drain hole diameter.
# Seed Starter Tray - a grid of tapered cells with drain holes, joined by a top flange
#
# Each cell is a thin-walled square pot that tapers toward the bottom, so a seedling
# slides out with its root ball when the cell is pressed from below. A drain hole in
# every cell bottom and a flange across the top tie the cells into one tray. Prints
# standing on the cell bottoms with no supports (the taper is well under 45 deg).
@param 2..6 step:1 group:"Grid" desc:"Rows of cells"
$rows = 4
@param 2..8 step:1 group:"Grid" desc:"Cells per row"
$cols = 6
@param 30..60 step:2 group:"Cell" desc:"Cell pitch (mm)"
$pitch = 40
@param 30..55 step:1 group:"Cell" desc:"Cell depth (mm)"
$depth = 45
@param 1.2..2.4 step:0.2 group:"Cell" desc:"Wall thickness (mm)"
$wall = 1.6
@param 2..10 step:1 group:"Cell" desc:"Taper of each cell wall (deg)"
$taper = 5
@param 4..10 step:1 group:"Cell" desc:"Drain hole diameter (mm)"
$drain = 6
$top = $pitch - 4 # outer size of a cell at the top
$bottom = $top - 2 * $depth * tan($taper) # outer size at the floor
assert $bottom > $drain + 2 * $wall + 6
$flange_t = 2
$len = $cols * $pitch
$wid = $rows * $pitch
$cx = [$pitch * (($i % $cols) + 0.5) for $i in range($rows * $cols)]
$cy = [$pitch * (floor($i / $cols) + 0.5) for $i in range($rows * $cols)]
# one cell: outer frustum minus inner frustum (both widen upward), floor left at the bottom
$outer = rect $bottom $bottom | extrude $depth draft:(-$taper)
$inner = rect ($bottom - 2 * $wall) ($bottom - 2 * $wall) | extrude ($depth + 1) draft:(-$taper) | translate 0 0 $wall
$cell = ($outer - $inner) - (cylinder ($drain / 2) ($wall + 2) | translate 0 0 ($wall / 2))
assert $cell.solids == 1
assert $cell.bbox.x ~ $top tol:0.2 # the draft widens the cell to the pitch minus the gap
$cells = union [$cell | translate ($cx[$i]) ($cy[$i]) 0 for $i in range($rows * $cols)]
# flange: a plate across the top with each cell's opening cut out
$openings = union [box ($top - 2 * $wall) ($top - 2 * $wall) ($flange_t + 2) at:($cx[$i], $cy[$i]) for $i in range($rows * $cols)]
$flange = (box $len $wid $flange_t center:(false, false, false) | edges =Z | fillet 4 | translate 0 0 ($depth - $flange_t)) - ($openings | translate 0 0 ($depth - $flange_t - 1))
$tray = $cells + $flange
assert $tray.solids == 1
assert $tray.bbox.x ~ $len
assert $tray.bbox.y ~ $wid
assert $tray.bbox.z ~ $depth
assert $tray.volume < $cells.volume + $flange.volume
print "tray" $tray.bbox
print "cell top / bottom (mm)" $top $bottom
$tray