Pot Saucer with Risers
A round drip tray for a plant pot, with three low round risers inside that the pot stands on. Draining water collects on the floor between the risers instead of soaking back into the pot, and air can reach the pot's base. With the default 120 mm pot base the saucer measures 140.8 x 140.8 x 15 mm, with an 8 mm deep water space under the pot and a smooth fillet where the floor meets the rim. Print it flat on its floor with no supports, and use enough solid bottom layers (at least 1.6 mm) and three or more perimeters so the tray stays watertight. You can change the pot bottom diameter, the gap to the rim, rim height, riser height, wall and floor thickness, and optionally add shallow air channels under the floor.
# Pot Saucer with Risers - drip tray whose three inner feet lift the pot for drainage and airflow
#
# Use: set the saucer on a shelf or windowsill and stand the plant pot on the three
# risers inside. Water draining from the pot collects on the floor below the pot
# instead of soaking back into its drain holes, and air reaches the pot's base.
# The risers are separate round pads 120 deg apart, so water flows freely between them.
#
# Print orientation: as modeled, floor flat on the bed (Z = 0), opening up. No supports.
# The floor has no holes; print it with enough solid bottom layers (>= 6 at 0.2 mm,
# or a bottom thickness >= 1.6 mm) and 3+ perimeters so the tray stays watertight.
#
# Optional under-floor air channels: shallow radial grooves in the underside so the
# tray does not seal against the table. They are narrow enough to bridge cleanly.
#
# The profile is drawn on the XZ plane as (radius, height) and revolved around Z.
@param 60..160 step:5 group:"Pot" desc:"Pot bottom diameter (mm)"
pot_d = 120
@param 4..20 step:1 group:"Pot" desc:"Radial gap between the pot base and the saucer wall (mm)"
margin = 8
@param 12..30 step:1 group:"Saucer" desc:"Rim height, overall saucer height (mm)"
rim_h = 15
@param 3..15 step:1 group:"Saucer" desc:"Riser height above the floor (mm)"
riser_h = 8
@param 1.6..4 step:0.2 group:"Saucer" desc:"Side wall thickness (mm)"
wall = 2.4
@param 1.6..4 step:0.2 group:"Saucer" desc:"Floor thickness (mm)"
floor_t = 2.4
@param group:"Saucer" desc:"Add shallow radial air channels under the floor"
under_channels = false
# --- Derived dimensions ----------------------------------------------
pot_r = pot_d / 2
ri = pot_r + margin # inner radius of the wall
ro = ri + wall # outer radius
fil = 5 # inner fillet between floor and wall
lip = 0.8 # 45 deg chamfer on the bottom outer edge (against elephant foot)
riser_d = 14 # riser pad diameter
riser_pc = pot_r * 0.65 # riser pitch radius (0.65 of the pot radius)
chan_w = 8 # under-floor channel width (bridged)
chan_d = 0.8 # under-floor channel depth
assert floor_t >= 1.6
assert rim_h - floor_t >= fil + 2 # the fillet fits below the rim
assert ro * 2 <= 210 # fits a 220 mm bed with a skirt
assert riser_pc + riser_d / 2 < pot_r - 3 # the pot rests fully on the risers
assert floor_t - (if under_channels then chan_d else 0) >= 1.6 - 0.001 # floor left above a channel
# --- Tray (revolved) ---------------------------------------------------
tray_body = workplane XZ
| sketch [(0, 0), (ro - lip, 0), (ro, lip), (ro, rim_h), (ri, rim_h),
(ri, floor_t + fil),
arc (ri, floor_t + fil) (ri - fil, floor_t) center:(ri - fil, floor_t + fil),
(0, floor_t)]
| revolve Z
# Three radial grooves through the center = six channels under the floor
chan = box (ro * 2 + 2) chan_w (chan_d + 1) | floor | translate 0 0 -1
channels = union [chan, chan | rotate 0 0 60, chan | rotate 0 0 120]
tray = if under_channels then (tray_body | diff channels) else tray_body
# --- Risers ------------------------------------------------------------
# Round pads standing on the floor, slightly sunk into it so they fuse
riser = cylinder (riser_d / 2) (riser_h + 0.5)
| floor
| edges >Z | fillet 1.5
| translate 0 0 (floor_t - 0.5)
risers = riser | polar 3 riser_pc
saucer = tray | union risers
assert saucer.solids == 1
assert saucer.bbox.x ~ ro * 2
assert saucer.bbox.y ~ ro * 2
assert saucer.bbox.z ~ max(rim_h, floor_t + riser_h)
print "riser top height (mm)" (floor_t + riser_h)
print "water depth below the pot (mm)" riser_h
saucer