// ======================================================== // PARAMETRIC SEEDLING TRAY & PUSHABLE PLATES // ======================================================== /* [Grid Configuration] */ cols = 3; // Number of columns rows = 2; // Number of rows cell_size = 35; // Inner width/length of each square cell (mm) tray_height = 50; // Total height of the tray (mm) /* [Wall & Ledge Dimensions] */ wall_thickness = 1.6; // Thickness of the walls (mm) bottom_lip = 4.0; // Width of the bottom ledge holding the plate (mm) floor_thickness = 2.0; // Thickness of the bottom lip (mm) /* [Pusher Plate Settings] */ plate_thickness = 2.0; // Thickness of the pushable plate (mm) clearance = 0.4; // Gap between cell walls and plate for easy sliding (mm) drain_hole_dia = 4.5; // Diameter of drainage holes in the pushable plate (mm) /* [Render Mode] */ // ["both_layout", "assembled", "tray_only", "plates_only"] render_mode = "both_layout"; // --- DERIVED CALCULATIONS --- pitch = cell_size + wall_thickness; total_width = cols * pitch + wall_thickness; total_length = rows * pitch + wall_thickness; // --- MAIN DISPLAY --- if (render_mode == "tray_only") { seedling_tray(); } else if (render_mode == "plates_only") { plate_grid(); } else if (render_mode == "both_layout") { seedling_tray(); translate([0, total_length + 10, 0]) plate_grid(); } else if (render_mode == "assembled") { // Visual preview seedling_tray(); for (r = [0 : rows - 1]) { for (c = [0 : cols - 1]) { translate([ wall_thickness + c * pitch + clearance/2, wall_thickness + r * pitch + clearance/2, floor_thickness ]) pusher_plate(); } } } // ======================================================== // MODULES // ======================================================== // Main seedling tray body module seedling_tray() { difference() { // Outer solid volume cube([total_width, total_length, tray_height]); // Cut out each cell pocket and bottom push hole for (r = [0 : rows - 1]) { for (c = [0 : cols - 1]) { x_pos = wall_thickness + c * pitch; y_pos = wall_thickness + r * pitch; // 1. Main cell compartment translate([x_pos, y_pos, floor_thickness]) cube([cell_size, cell_size, tray_height]); // 2. Bottom push-through opening translate([x_pos + bottom_lip, y_pos + bottom_lip, -1]) cube([ cell_size - (2 * bottom_lip), cell_size - (2 * bottom_lip), floor_thickness + 2 ]); } } } } // Single pushable bottom plate module pusher_plate() { p_size = cell_size - clearance; offset_margin = p_size / 3.5; difference() { // Plate body cube([p_size, p_size, plate_thickness]); // 5-points drainage hole pattern translate([p_size / 2, p_size / 2, -1]) cylinder(h = plate_thickness + 2, d = drain_hole_dia, $fn = 20); for (dx = [offset_margin, p_size - offset_margin]) { for (dy = [offset_margin, p_size - offset_margin]) { translate([dx, dy, -1]) cylinder(h = plate_thickness + 2, d = drain_hole_dia, $fn = 20); } } } } // Plate grid module plate_grid() { p_size = cell_size - clearance; spacing = 2; for (r = [0 : rows - 1]) { for (c = [0 : cols - 1]) { translate([c * (p_size + spacing), r * (p_size + spacing), 0]) pusher_plate(); } } }