129 lines
4.6 KiB
OpenSCAD
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();
|