3d-printing/tapo-ceiling-mount/tapo_ceiling_outer_plate.scad

129 lines
4.6 KiB
OpenSCAD

// ============================================
// Tapo Ceiling Mount - Exterior Plate
// ============================================
// The visible plate below the ceiling. It covers the existing hole, carries
// the four M4 screws inside the hole diameter, provides a large central cable
// opening, and gives mounting points for the original TP-Link Tapo base.
//
// Print with the bottom (visible) face on the bed. The bosses and the
// centering lip point up. No support material is needed.
parameters_only = false;
include <tapo_ceiling_mount_parameters.scad>;
// Solid disc with a chamfered outer edge on the visible face.
module plate_disc() {
rotate_extrude()
polygon([
[0, 0],
[plate_r - plate_edge_chamfer, 0],
[plate_r, plate_edge_chamfer],
[plate_r, plate_thickness],
[0, plate_thickness]
]);
}
// Ring on the plate top that enters the ceiling hole and centers the plate.
module centering_lip() {
rotate_extrude()
translate([0, plate_thickness])
polygon([
[lip_inner_r, 0],
[lip_outer_r, 0],
[lip_outer_r - centering_lip_lead, centering_lip_height],
[lip_inner_r, centering_lip_height]
]);
}
// Local thickening on the plate top around one screw, for head bearing.
module screw_boss_top() {
cylinder(d = screw_boss_d, h = plate_thickness + screw_boss_h);
}
// Central cable opening (the pill), elongated along the cable-routing direction.
module central_opening() {
translate([0, 0, -1])
linear_extrude(plate_thickness + centering_lip_height + 2)
hull() {
for (s = [-1, 1])
translate([ s * cable_slot_reach * cos(cable_slot_angle),
s * cable_slot_reach * sin(cable_slot_angle) ])
circle(r = central_opening_r);
}
}
// Solid boss under one base mounting hole. It fills the opening locally.
module camera_boss() {
cylinder(d = camera_boss_d, h = plate_thickness);
}
// Pilot hole for one base mounting screw, drilled up from the bottom face.
module camera_pilot() {
translate([0, 0, -0.01])
cylinder(d = camera_mount_hole_diameter, h = camera_screw_depth);
}
// Ribs that tie each base boss to the solid plate ring across the opening.
module camera_ribs() {
for (p = camera_mount_xy) {
r = norm(p);
ang = atan2(p[1], p[0]);
ro = max(r + camera_boss_d / 2, central_opening_r + 5);
hull() {
translate([p[0], p[1], 0])
cylinder(d = camera_rib_w, h = plate_thickness);
translate([ro * cos(ang), ro * sin(ang), 0])
cylinder(d = camera_rib_w, h = plate_thickness);
}
}
}
// Screw clearance hole plus the head recess for one screw.
module plate_screw_hole() {
translate([0, 0, -1])
cylinder(d = m4_clearance_d, h = plate_thickness + screw_boss_h + 2);
translate([0, 0, -0.01])
cylinder(d = screw_head_recess_d, h = head_recess_depth);
if (head_type == "countersunk")
translate([0, 0, -0.01])
cylinder(d1 = csk_d, d2 = m4_clearance_d, h = csk_depth);
}
// The complete exterior plate.
// With enable_connector_interface = true the plate carries the bayonet ring
// for the modular collar. The collar wraps around the ring and hides it. The
// direct camera-base mount is then off. Set enable_connector_interface = false
// to keep the direct base mount.
module tapo_outer_plate() {
union() {
difference() {
union() {
// Disc, lip and screw bosses, central opening removed.
difference() {
union() {
plate_disc();
centering_lip();
for (p = screw_positions)
translate([p[0], p[1], 0]) screw_boss_top();
}
central_opening();
}
// Direct base mount only when no connector is used.
if (!enable_connector_interface) {
for (p = camera_mount_xy)
translate([p[0], p[1], 0]) camera_boss();
camera_ribs();
}
}
for (p = screw_positions)
translate([p[0], p[1], 0]) plate_screw_hole();
if (!enable_connector_interface)
for (p = camera_mount_xy)
translate([p[0], p[1], 0]) camera_pilot();
}
// Bayonet ring for the modular collar.
if (enable_connector_interface) plate_bayonet_ring();
}
}
tapo_outer_plate();