Screw-Lid Jar
A small round jar with a screw-on lid for screws, spices, beads or other small parts. Both parts carry a modelled single-start thread of about two turns with 45 deg flanks, a 4 mm pitch, 1.5 mm depth and 0.4 mm radial clearance, plus a chamfered lead-in so the lid catches easily. The jar is 57 mm across and 52 mm tall with a 50 x 50 mm interior, and the ridged lid is 64 mm across and 12 mm tall. Print the jar upright and the lid upside-down on its top; no supports are needed. Inner diameter, inner height, wall thickness, pitch, number of turns, thread clearance and the number of grip ridges can all be adjusted.
# Screw-Lid Jar - round container with a printed thread
#
# A small jar and its screw-on lid, printed as two separate parts.
# The jar prints upright; the lid prints upside-down (top on the bed) so
# its internal thread and grip ridges need no supports. To use: screw the
# lid on clockwise until it seats on the jar rim.
#
# Thread: single start, right-handed, 90 deg included angle (both flanks at
# 45 deg), flat crest, about two turns. Both ends of the jar thread are
# chamfered at 45 deg (lead-in on top, no overhang below) and the lid mouth
# has a 45 deg lead-in cone. The lid thread is the jar thread grown radially
# by the clearance, so the fit is the same all along the flanks.
@param 20..120 group:"Size" desc:"Inner diameter of the jar (mm)"
inner_d = 50
@param 15..150 group:"Size" desc:"Inner height of the jar, floor to rim (mm)"
inner_h = 50
@param 1.2..4 step:0.1 group:"Size" desc:"Wall thickness of jar and lid (mm)"
wall = 2.0
@param 2.5..6 step:0.5 group:"Thread" desc:"Thread pitch (mm)"
pitch = 4.0
@param 1..3 step:0.25 group:"Thread" desc:"Thread turns"
turns = 2.0
@param 0.1..0.8 step:0.05 group:"Thread" desc:"Radial clearance between jar and lid thread (mm)"
clearance = 0.4
@param 12..72 group:"Lid" desc:"Number of grip ridges on the lid"
ridges = 40
floor_t = 2.0 # jar floor
cap_t = 2.4 # lid top plate
depth = 1.5 # thread depth, crest to root
land = pitch - 2 * depth # crest flat; gives 45 deg flanks
gap = 10 # spacing between the parts on the bed
r_in = inner_d / 2
r_root = r_in + wall # jar wall outer radius = thread root
r_major = r_root + depth # jar thread crest
rim_z = floor_t + inner_h # jar rim height
band_h = turns * pitch # threaded band on the jar neck
band_z = rim_z - 0.5 - band_h # bottom of the band (0.5 plain at the rim)
lr_major = r_major + clearance # lid thread root (groove bottom)
lr_minor = lr_major - depth # lid thread crest
lr_out = lr_major + wall # lid outer radius (without ridges)
skirt_z = band_z - 1.0 # lower end of the lid skirt when screwed on
lid_h = rim_z + cap_t - skirt_z # overall lid height
# ---- Jar (assembled frame: floor on Z = 0) ----
$thread = thread r_major pitch band_h land:land depth:depth chamfer:(depth, depth) center:(true,true,false)
| translate 0 0 band_z
jar = (cylinder r_root rim_z center:(true,true,false)) + $thread
- (cylinder r_in inner_h center:(true,true,false) | translate 0 0 floor_t)
| edges <Z | chamfer 0.6
# ---- Lid in its screwed-on position ----
# The groove cutter starts a whole number of pitches below the jar band so
# both helices are in phase.
n_below = 2
cutter = thread lr_major pitch (band_h + 8 * pitch) land:land depth:depth center:(true,true,false)
| translate 0 0 (band_z - n_below * pitch)
skirt = (cylinder lr_out (rim_z - skirt_z) center:(true,true,false) | translate 0 0 skirt_z) - cutter
lead = cone (lr_major + 0.6) lr_minor (depth + 0.6) center:(true,true,false) | translate 0 0 skirt_z
cap = cylinder lr_out cap_t center:(true,true,false) | translate 0 0 rim_z
# grip ridges run down to the lid top so they sit on the bed when printed
grip = cylinder 1.2 (lid_h - 0.8) center:(true,true,false) | polar ridges lr_out | translate 0 0 (skirt_z + 0.8)
lid_on = skirt + cap + grip - lead
# ---- Fit checks (assembled) ----
assert jar.solids == 1
assert lid_on.solids == 1
assert clear(jar, lid_on)
# The gap is at least clearance - 0.05 everywhere: a jar thread grown by
# that much still clears the lid, one grown by clearance + 0.1 does not.
probe_in = thread (r_major + clearance - 0.05) pitch band_h land:land depth:depth center:(true,true,false) | translate 0 0 band_z
probe_out = thread (r_major + clearance + 0.1) pitch band_h land:land depth:depth center:(true,true,false) | translate 0 0 band_z
assert clear(probe_in, lid_on)
assert clear(probe_out, lid_on) == false
# ---- Print layout: jar upright, lid upside-down beside it ----
lid = lid_on | rotate 180 0 0 | floor | translate (r_root + lr_out + 1.2 + gap) 0 0
assert jar.bbox.z ~ rim_z
assert jar.bbox.x ~ 2 * r_major tol:0.2
assert lid.bbox.min[2] ~ 0 tol:0.01
assert lid.bbox.z ~ lid_h tol:0.01
print "jar" jar.bbox
print "lid" lid.bbox
print "lid_on" lid_on.bbox
jar + lid