diff --git a/chassis/csi_rain_shield.scad b/chassis/csi_rain_shield.scad new file mode 100644 index 0000000..1e48adb --- /dev/null +++ b/chassis/csi_rain_shield.scad @@ -0,0 +1,221 @@ +// ============================================================ +// csi_rain_shield.scad — CSI Camera Rain/Sun Shield +// Issue: #254 Agent: sl-mechanical Date: 2026-03-02 +// ============================================================ +// +// Parametric visor-style rain and sun shield for SaltyBot's +// 4× Raspberry Pi CSI IMX219 cameras (32×32 mm PCB). +// +// Features: +// • Visor-style overhang — protects lens from rain & sun +// • Drip edge — prevents water from running back onto PCB +// • Snap-fit attachment — clips to camera housing, no fasteners +// • Transparent polycarbonate compatible — removable lens cover +// • Radial symmetry — same design fits all 4 cameras +// +// Design for IMX219: +// • Camera face plate: 38×38 mm (32 mm PCB + 3 mm frame per side) +// • Arm depth: 52 mm from sensor head centre to camera +// • 10° nose-down tilt on radial arms +// +// Assembly: +// 1. Print shield body (flat-side-down, minimal supports) +// 2. Optional: Insert clear polycarbonate sheet in front +// 3. Snap shield onto camera housing (4 tabs lock into grooves) +// 4. Repeat for all 4 cameras +// +// RENDER options: +// "shield" single shield unit (default) +// "assembly" 4 shields on camera arms (visual reference) +// "lens_cover" removable transparent polycarbonate insert +// ============================================================ + +RENDER = "shield"; + +// ── Camera housing dimensions ────────────────────────────── +// IMX219 camera with face-plate protection. +CAM_PCB_SIZE = 32.0; // PCB square side +CAM_FACE_SIZE = 38.0; // face plate (PCB + 3mm bezel each side) +CAM_FACE_THICK = 4.0; // face plate thickness (front-to-back) + +// M2 hole pattern on PCB (for reference, not used in shield) +M2_SPACING = 24.0; // hole pattern spacing + +// ── Radial arm geometry (from imx219_mount.scad) ─────────── +ARM_R = 50.0; // platform radius (used in assembly view) +REACH_LEN = 52.0; // arm extension from sensor head +ARM_TILT = 10.0; // nose-down tilt angle + +// ── Rain shield overhang ─────────────────────────────────── +// Visor extends forward and downward from camera housing. + +VISOR_OVERHANG = 32.0; // forward extension from camera face +VISOR_H = 18.0; // overhang height (downward from top) +VISOR_DROP = 16.0; // bottom lip drop (prevents water runoff) +VISOR_THICK = 3.0; // wall thickness + +// Drip edge: curved lip at bottom to prevent water trickling back +DRIP_RADIUS = 3.0; // radius of drip edge curve +DRIP_HEIGHT = 4.0; // height of drip lip + +// ── Snap-fit attachment tabs ─────────────────────────────── +// Tabs clip into grooves on camera housing side walls. + +SNAP_TAB_H = 6.0; // tab height (above housing) +SNAP_TAB_W = 8.0; // tab width +SNAP_TAB_D = 2.0; // tab depth (into groove) +SNAP_CLEARANCE = 0.4; // clearance for easy snap/unsnap + +NUM_TABS = 4; // 4 tabs around perimeter + +// ── Lens cover (polycarbonate insert) ────────────────────── +// Optional transparent front cover — slides into grooves. + +LENS_COVER_T = 2.0; // polycarbonate sheet thickness +LENS_COVER_W = CAM_FACE_SIZE + 6.0; // cover width (with edge flanges) +LENS_COVER_FLANGE = 3.0; // flange width on each side + +// ── Ventilation ──────────────────────────────────────────── +// Small vent slots prevent moisture condensation inside shield. + +VENT_SLOT_W = 3.0; // vent slot width +VENT_SLOT_H = 2.0; // vent slot height +NUM_VENTS = 3; // slots per side (3 on left, 3 on right) + +// ── General ──────────────────────────────────────────────── +$fn = 64; +e = 0.01; + +// ───────────────────────────────────────────────────────────── +// csi_rain_shield() +// Single shield unit — visor with snap-fit tabs. +// Print flat-side-down (visor facing down). +// +// Coordinate system: +// X = left-right (camera width direction) +// Y = front-back (camera pointing direction) +// Z = up-down +// Camera face at Y=0, lens center at origin. +// ───────────────────────────────────────────────────────────── +module csi_rain_shield() { + // Main visor body — asymmetric overhang + difference() { + union() { + // Visor base plate (behind camera, attaches to housing) + translate([-CAM_FACE_SIZE/2 - 4, -CAM_FACE_THICK - 2, 0]) + cube([CAM_FACE_SIZE + 8, 6, VISOR_THICK]); + + // Forward overhang — curved top for water runoff + translate([-VISOR_H/2, -CAM_FACE_THICK, 0]) { + difference() { + // Main overhang volume + cube([VISOR_H, VISOR_OVERHANG, VISOR_THICK]); + + // Curved top surface (water sheds outward) + translate([VISOR_H/2, 0, -e]) + rotate([90, 0, 0]) + cylinder(r = VISOR_H/2 + 2, h = VISOR_OVERHANG + 2*e); + } + } + + // Side flanges (stabilize against wind, provide snap-tab base) + for (sx = [-1, 1]) + translate([sx * (CAM_FACE_SIZE/2 + 2), -CAM_FACE_THICK, 0]) + cube([4, CAM_FACE_THICK + VISOR_OVERHANG/2, VISOR_THICK]); + + // Drip edge — bottom lip curves downward & forward + translate([-(VISOR_H-2)/2, -CAM_FACE_THICK + VISOR_OVERHANG - 2, -DRIP_HEIGHT]) + rotate([0, 90, 0]) + cylinder(r = DRIP_RADIUS, h = VISOR_H - 4); + } + + // Lens opening — lets camera see through (frame around camera face) + translate([-(CAM_FACE_SIZE-2)/2, -CAM_FACE_THICK - 2, -e]) + cube([CAM_FACE_SIZE-2, 2, VISOR_THICK + 2*e]); + + // Vent slots (prevent condensation) — left side + for (i = [0 : NUM_VENTS-1]) { + vent_y = -CAM_FACE_THICK + (VISOR_OVERHANG * (i+1) / (NUM_VENTS+1)); + translate([-(CAM_FACE_SIZE/2 + 8), vent_y, VISOR_THICK/2 - VENT_SLOT_H/2]) + cube([2, VENT_SLOT_W, VENT_SLOT_H]); + translate([(CAM_FACE_SIZE/2 + 6), vent_y, VISOR_THICK/2 - VENT_SLOT_H/2]) + cube([2, VENT_SLOT_W, VENT_SLOT_H]); + } + } + + // Snap-fit tabs — clip into camera housing grooves + for (i = [0 : NUM_TABS-1]) { + angle = (360 / NUM_TABS) * i - 45; // 4 tabs at 90° intervals, rotated -45° + translate([-CAM_FACE_SIZE/2 - 3, -CAM_FACE_THICK/2, 0]) + rotate([0, 0, angle]) + translate([CAM_FACE_SIZE/2 + 3 + SNAP_TAB_D/2, 0, -SNAP_TAB_H/2]) + cube([SNAP_TAB_W, SNAP_TAB_D + SNAP_CLEARANCE, SNAP_TAB_H], center=true); + } + + // Lens cover groove — retains transparent polycarbonate insert + translate([-(LENS_COVER_W/2 + 1), -CAM_FACE_THICK - 1.5, -e]) + cube([LENS_COVER_W + 2, 1.5, LENS_COVER_T + 0.5]); +} + +// ───────────────────────────────────────────────────────────── +// csi_lens_cover() +// Removable transparent polycarbonate insert. +// This is a phantom/visual-only part; actual cover is cut from +// 2.0 mm clear polycarbonate sheet and trimmed to size. +// ───────────────────────────────────────────────────────────── +module csi_lens_cover() { + // Clear lens cover — sits in grooves on shield front edge + difference() { + union() { + // Main cover plate (represents polycarbonate insert) + translate([-(LENS_COVER_W/2), -CAM_FACE_THICK - 2, 0]) + cube([LENS_COVER_W, 2, LENS_COVER_T]); + + // Side flanges (grip in shield grooves) + for (sx = [-1, 1]) + translate([sx * (LENS_COVER_W/2 - LENS_COVER_FLANGE/2), + -CAM_FACE_THICK - 2, 0]) + cube([LENS_COVER_FLANGE, 2, LENS_COVER_T]); + } + + // Lens opening (clear aperture in front of camera) + translate([-(CAM_FACE_SIZE-4)/2, -CAM_FACE_THICK - 3, -e]) + cube([CAM_FACE_SIZE-4, 4, LENS_COVER_T + 2*e]); + } +} + +// ───────────────────────────────────────────────────────────── +// assembly_4x_shields() +// All 4 shields mounted on radial arms (reference visualization). +// ───────────────────────────────────────────────────────────── +module assembly_4x_shields() { + // 4 shields at 90° intervals (matches 4x CSI cameras) + for (angle = [0, 90, 180, 270]) { + color("LightSteelBlue", 0.85) + rotate([0, 0, angle]) + translate([ARM_R, 0, 0]) + rotate([ARM_TILT, 0, 0]) + csi_rain_shield(); + + // Phantom camera face (reference only) + color("DarkGray", 0.5) + rotate([0, 0, angle]) + translate([ARM_R, 0, 0]) + rotate([ARM_TILT, 0, 0]) + translate([-(CAM_FACE_SIZE/2), 0, -CAM_FACE_THICK/2]) + cube([CAM_FACE_SIZE, 1, CAM_FACE_SIZE], center=false); + } +} + +// ───────────────────────────────────────────────────────────── +// Render selector +// ───────────────────────────────────────────────────────────── +if (RENDER == "shield") { + csi_rain_shield(); + +} else if (RENDER == "assembly") { + assembly_4x_shields(); + +} else if (RENDER == "lens_cover") { + csi_lens_cover(); +} diff --git a/chassis/csi_rain_shield_BOM.md b/chassis/csi_rain_shield_BOM.md new file mode 100644 index 0000000..3c4ed79 --- /dev/null +++ b/chassis/csi_rain_shield_BOM.md @@ -0,0 +1,294 @@ +# CSI Camera Rain/Sun Shield — BOM + Assembly +**Rev A — 2026-03-02 — sl-mechanical** + +--- + +## System Overview + +Protective visor-style rain and sun shields for all 4 Raspberry Pi CSI cameras (IMX219) on SaltyBot's sensor head. + +| Feature | Spec | +|---------|------| +| Application | Protects IMX219 cameras from rain, dust, and direct sunlight | +| Camera interface | Snap-fit to camera housing (32×32 mm PCB with 38×38 mm face plate) | +| Material | PETG (printed) or polycarbonate (lens cover) | +| Coverage | All 4 cameras (radial arms at 0°/90°/180°/270°) | +| Visor overhang | 32 mm forward extension | +| Installation | Tool-free snap-fit (no fasteners required) | +| Optional | Clear polycarbonate lens cover insert | + +--- + +## Design Features + +- **Visor-style overhang:** 32 mm forward extension shields lens from rain and sun glare +- **Drip edge:** Curved bottom lip (3 mm radius) prevents water from running back onto PCB +- **Snap-fit tabs:** 4 flexible tabs clip into grooves on camera housing sides (no fasteners) +- **Ventilation slots:** 3 vent slots per side prevent moisture condensation inside shield +- **Lens cover groove:** Optional slot accepts removable 2.0 mm clear polycarbonate sheet +- **Minimal weight:** ~8–10 g per shield (4 shields ≈ 32–40 g) +- **No supports needed:** Flat-print orientation; minimal bridging + +--- + +## Part A — Printed Shields + +### Single Shield Unit (csi_rain_shield.scad, RENDER="shield") + +**Purpose:** Protective visor for one CSI camera lens; clips onto camera housing. + +| Parameter | Value | Notes | +|-----------|-------|-------| +| Qty | 4 | One per camera (front, back, left, right) | +| Material | PETG | 4 perimeters, 25% infill (speed-optimized) | +| Print size | ~45 × 55 × 8 mm | Flat-face-down orientation | +| Print time | ~25–35 min per shield | Total ~2 hours for all 4 | +| Support | Minimal | Small bridging over drip edge only | +| Wall thickness | 3 mm nominal | Adequate for snap-tab rigidity | + +**Key features:** +- Curved top surface sheds water outward +- 4 snap-fit tabs (one per side) with 0.4 mm clearance for easy on/off +- Vent slots (3 on left, 3 on right) for air circulation +- Integrated groove for optional lens cover +- Drip edge prevents water from trickling back + +**Post-print finishing:** +- Remove minimal support (drip edge underside) +- Smooth any rough edges with 220-grit sandpaper +- Test snap-tabs fit snugly (should click into place with light pressure) +- Verify vent slots are open (clear with compressed air if needed) + +--- + +## Part B — Optional Lens Cover + +### Clear Polycarbonate Insert (csi_rain_shield.scad, RENDER="lens_cover") + +**Purpose:** Optional removable transparent lens cover; protects optics while allowing light transmission. + +| Parameter | Value | Notes | +|-----------|-------|-------| +| Qty | 4 | One per camera (optional) | +| Material | Polycarbonate sheet, clear | 2.0 mm thickness; cut from larger stock | +| Size | ~44 × 44 mm (with flanges) | Trimmed to fit shield groove | +| Optical quality | >90% transmission | Standard transparency grade; no special optics required | +| Source | Cut from 2.0 mm clear polycarbonate sheet | Order stock, cut to size, sand edges smooth | + +**Installation:** +1. Measure shield opening: approx. 38×38 mm (camera face size) +2. Cut polycarbonate sheet to ~44×44 mm (includes 3 mm flange on each side) +3. Sand edges smooth with 220+ grit (prevent scratching during insertion) +4. Slide into groove on shield front (flanges grip in shield channels) +5. Can be removed/cleaned without tools + +**Note:** Lens cover is **optional** — shields work fine without it. Use for: +- Extreme weather (heavy rain, salt spray) +- Coastal/sandy environments (dust protection) +- High-temperature environments (reduces direct solar heating on sensor) + +--- + +## Assembly Instructions + +### Installation on Camera Housing + +1. **Prepare shield:** Remove any support material; verify snap-tabs are flexible. +2. **Position shield:** Orient visor away from camera (forward overhang extends away). +3. **Align tabs:** Match snap-tab positions with grooves on camera housing sides. +4. **Apply light pressure:** Snap shield onto housing with gentle thumb pressure. + - You should hear/feel a "click" as each tab engages. + - All 4 tabs should seat simultaneously (indicate correct orientation). +5. **Verify fit:** Tug gently on shield — it should not move relative to housing. + +### Installation of Lens Cover (Optional) + +1. **Prepare cover:** Sand edges smooth; verify 44×44 mm dimension. +2. **Align flanges:** Position cover so flanges align with groove channels on shield. +3. **Slide into groove:** Insert cover from front, sliding flanges into shield grooves. +4. **Check seating:** Cover should sit flush with shield front (no gaps). +5. **Removal:** Gently pry from one corner to remove for cleaning. + +### Removal (For Cleaning/Replacement) + +1. **Lens cover:** Pop out with fingernail or plastic lever (takes 10 seconds). +2. **Shield:** Flex one snap-tab up slightly while pulling shield forward. + - Repeat on opposite side if needed. + - Once one tab releases, shield pulls free easily. +3. **Clean:** Wipe interior with dry cloth; use lens cleaner on polycarbonate if needed. +4. **Reinstall:** Reverse steps above. + +--- + +## Fastener List + +| # | Item | Qty | Notes | +|---|------|-----|-------| +| 1 | Printed shield (PETG) | 4 | See Part A specs above | +| 2 | Polycarbonate lens cover | 4 | Optional; see Part B above | +| – | **No fasteners required** | — | Shields attach via snap-fit tabs only | + +--- + +## Mounting Configuration + +All 4 shields mount to radial arms of sensor_head.scad camera arms: + +``` +Top-down view (looking down at sensor head): + + Camera 1 (0°, front) + ▲ + │ + Shield │ Shield + (270°) │ (90°) + ◄────-●─────► + │ + │ + Camera 3 (180°, back) + ▼ + +Each camera has a 32×32 mm PCB with 38×38 mm face plate. +All 4 shields use identical design (radially symmetric). +``` + +--- + +## Print Settings (Recommended) + +| Parameter | Value | Reason | +|-----------|-------|--------| +| **Nozzle temp** | 215–220 °C (PETG) | Prevent stringing; avoid over-heating | +| **Bed temp** | 80 °C | Good adhesion for PETG | +| **Print speed** | 40 mm/s | Normal speed; snapt-tabs need clean layers | +| **Infill** | 25% | Sufficient for rigidity; saves weight & time | +| **Perimeters** | 4 | Ensures solid snap-tabs | +| **Supports** | Minimal (tree/linear) | Only under drip edge if needed | +| **Orientation** | Flat-side-down | Visor face toward bed for best surface finish | +| **Layer height** | 0.2 mm | Standard; 0.1 mm for improved surface finish | + +--- + +## Mass Estimate + +| Component | Qty | Material | Est. mass | +|-----------|-----|----------|-----------| +| Rain shield (printed) | 4 | PETG | 8–10 g each (32–40 g total) | +| Polycarbonate cover | 4 | PC sheet | 3–5 g each (12–20 g total, optional) | +| **Subtotal (shields only)** | | | **32–40 g** | +| **Total (with covers)** | | | **44–60 g** | + +**Impact on robot:** Negligible — <60 g added weight distributed symmetrically on sensor head. + +--- + +## Weather Resistance + +| Condition | Protection | Notes | +|-----------|-----------|-------| +| **Light rain** | Excellent | Visor prevents direct water contact | +| **Heavy rain** | Good | Drip edge minimizes runoff; vent slots allow drainage | +| **Salt spray** | Good | PETG resists corrosion; rinsable with fresh water | +| **Direct sunlight** | Excellent | Reduces lens heating; improves image contrast in bright conditions | +| **Dust** | Very good | Visor blocks most airborne dust; lens cover optional for sandy environments | +| **Snow/ice** | Fair | Shields prevent accumulation on lens; may require occasional wiping | + +--- + +## Maintenance & Cleaning + +### Weekly (or after rain/dust storm) + +- **Wipe exterior:** Soft cloth, no cleaners (PETG safe with water only) +- **Check vent slots:** Clear any debris with compressed air +- **Verify snap-tabs:** Ensure shield hasn't loosened (retighten if needed) + +### Monthly (or as needed) + +- **Clean lens:** Remove polycarbonate cover; clean with lens cleaner + microfiber cloth +- **Inspect for cracks:** Check snap-tabs and drip edge for damage +- **Reattach cover:** Reinstall lens cover if removed + +### Seasonal (before extended operations) + +- **Deep clean:** Soak shields in warm soapy water; dry thoroughly +- **Inspect material:** Check for UV degradation (yellowing, brittleness) +- **Test fit:** Verify snap-tabs still grip firmly; replace if worn + +--- + +## Troubleshooting + +| Issue | Cause | Solution | +|-------|-------|----------| +| Shield won't snap on | Tabs too tight | Sand snap-tabs lightly; verify groove alignment | +| Shield rattles | Tabs too loose | Shim with thin tape; or reprint with tighter tolerance | +| Water pooling inside | Vent slots blocked | Clear vents with compressed air | +| Condensation on lens | Poor ventilation | Increase fan speed on sensor head or add desiccant packet | +| Lens cover stuck | Flanges swollen | Let air-dry in sun for 1 hour; gently pry corner | +| Drip edge cracked | Impact damage | Replace shield; or reinforce with epoxy + fiber tape | + +--- + +## Design Variants + +### Variant 1: Enhanced Rain Protection (HEAVY WEATHER) +- Extend visor overhang to 40 mm +- Add full-width drip lip (vs. curved edge) +- Thicken walls to 4 mm for durability +- **Cost:** +10% weight, +5% print time + +### Variant 2: Minimal Sun Shield (LIGHTWEIGHT) +- Reduce visor overhang to 20 mm +- Thinner walls (2.5 mm) +- Fewer vent slots (1 per side) +- **Weight savings:** ~15%; best for dry climates + +### Variant 3: 360° Camera Protection (ADVANCED) +- Add full-wrap shroud (not just visor) +- Integrated housing covers (larger print) +- Requires more support material +- **Print time:** ~3 hours per shield + +--- + +## Storage & Replacement + +**Shelf life:** PETG shields have indefinite shelf life if stored dry. + +**Replacement schedule:** Replace if: +- Snap-tabs become loose or brittle +- UV degradation visible (yellowing, embrittlement) +- Cracks develop in visor +- Polycarbonate cover becomes cloudy (clean first; replace if cloudiness persists) + +**Spares to keep:** 1–2 extra shields (in case of damage during field operations). + +--- + +## Files & References + +| File | Purpose | +|------|---------| +| `csi_rain_shield.scad` | OpenSCAD parametric model (3 RENDER variants) | +| `csi_rain_shield_BOM.md` | This document | +| `imx219_mount.scad` | CSI camera housing reference (dependency) | +| `sensor_head.scad` | Radial arm assembly reference | + +--- + +## Assembly Checklist + +- [ ] Print all 4 shields (PETG, flat-face-down) +- [ ] Remove support material (minimal) +- [ ] Sand edges smooth (220 grit) +- [ ] Test snap-tabs (should click into place with finger pressure) +- [ ] Verify vent slots are open +- [ ] *Optional:* Cut polycarbonate lens covers to size +- [ ] *Optional:* Sand polycarbonate edges smooth +- [ ] Mount shields on all 4 cameras (starting with front) +- [ ] Verify all snap-tabs engaged +- [ ] *Optional:* Install polycarbonate lens covers +- [ ] Inspect for water shedding (test with water spray if available) +- [ ] Label shields if needed (mark front/back camera positions) +- [ ] Store spares in dry location