Add parametric Ring solar siding adapter model.
Track OpenSCAD sources and project notes; ignore generated STL exports.
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
*.stl
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
## Printer
|
||||||
|
|
||||||
|
**Bambu Lab P2S** — see `.cursor/skills/openscad-bosl2/references/bambu-p2s.md` for specs (general printer reference: `.cursor/skills/openscad-bosl2/references/printers.md`).
|
||||||
@@ -0,0 +1,136 @@
|
|||||||
|
// Ring Solar Charger — Vinyl Siding Adapter Plate
|
||||||
|
// BACKUP: flat upper rear + slow lower taper, no bead coping groove yet.
|
||||||
|
// Units: millimeters. Vanilla OpenSCAD only.
|
||||||
|
|
||||||
|
/* [Plate] */
|
||||||
|
plate_width = 93.1;
|
||||||
|
plate_height = 171.45;
|
||||||
|
min_wall_thickness = 3.0;
|
||||||
|
edge_round = 0;
|
||||||
|
|
||||||
|
/* [Siding Profile] */
|
||||||
|
siding_projection = 27.0;
|
||||||
|
face_inset_depth = 8.0;
|
||||||
|
flat_upper_ratio = 0.55;
|
||||||
|
course_pitch = 165.1;
|
||||||
|
profile_segments = 8;
|
||||||
|
profile_mode = "curved";
|
||||||
|
rear_clearance = 0.2;
|
||||||
|
|
||||||
|
/* [Mounting Holes] */
|
||||||
|
mount_hole_offset_top = 50.0;
|
||||||
|
mount_hole_offset_bottom = 44.7;
|
||||||
|
mount_hole_dia = 4.5;
|
||||||
|
mount_hole_x = 0;
|
||||||
|
|
||||||
|
/* [Export] */
|
||||||
|
part_mode = "full";
|
||||||
|
profile_strip_width = 20;
|
||||||
|
|
||||||
|
/* [Hidden] */
|
||||||
|
$fn = 64;
|
||||||
|
epsilon = 0.01;
|
||||||
|
|
||||||
|
function projection_z() = siding_projection - rear_clearance;
|
||||||
|
|
||||||
|
function face_inset_z() = projection_z() - face_inset_depth;
|
||||||
|
|
||||||
|
function face_y_flat_end() = plate_height * (1 - flat_upper_ratio);
|
||||||
|
|
||||||
|
function lower_curve_z(y) =
|
||||||
|
let(
|
||||||
|
y1 = face_y_flat_end(),
|
||||||
|
t = y / max(y1, epsilon),
|
||||||
|
ease = pow(sin(t * 90), 1.4),
|
||||||
|
z_bottom = projection_z(),
|
||||||
|
z_top = face_inset_z()
|
||||||
|
)
|
||||||
|
z_top + (z_bottom - z_top) * (1 - ease);
|
||||||
|
|
||||||
|
function stepped_rear_z(y) =
|
||||||
|
y >= face_y_flat_end() ? face_inset_z() : projection_z();
|
||||||
|
|
||||||
|
function rear_z_at(y) =
|
||||||
|
y >= face_y_flat_end() ? face_inset_z()
|
||||||
|
: profile_mode == "stepped" ? stepped_rear_z(y)
|
||||||
|
: lower_curve_z(y);
|
||||||
|
|
||||||
|
function rear_profile_points() =
|
||||||
|
let(step = plate_height / max(profile_segments * 12, 24))
|
||||||
|
[for (y = [0 : step : plate_height])
|
||||||
|
[y, rear_z_at(y)]];
|
||||||
|
|
||||||
|
function max_rear_z() =
|
||||||
|
let(pts = rear_profile_points())
|
||||||
|
max([for (p = pts) p[1]]);
|
||||||
|
|
||||||
|
function front_z() = max_rear_z() + min_wall_thickness;
|
||||||
|
|
||||||
|
function rear_y_min() =
|
||||||
|
min([for (p = rear_profile_points()) p[1]]);
|
||||||
|
|
||||||
|
function minkowski_active() =
|
||||||
|
edge_round > 0 && min_wall_thickness >= 2 * edge_round + 1;
|
||||||
|
|
||||||
|
function hole_y_min() =
|
||||||
|
rear_y_min() - (minkowski_active() ? edge_round : 0) - epsilon;
|
||||||
|
|
||||||
|
function hole_y_max() =
|
||||||
|
front_z() + (minkowski_active() ? edge_round : 0) + epsilon;
|
||||||
|
|
||||||
|
function cross_section_polygon() =
|
||||||
|
let(
|
||||||
|
rear_pts = rear_profile_points(),
|
||||||
|
fz = front_z()
|
||||||
|
)
|
||||||
|
[
|
||||||
|
for (p = rear_pts) p,
|
||||||
|
[plate_height, fz],
|
||||||
|
[0, fz]
|
||||||
|
];
|
||||||
|
|
||||||
|
module cross_section_2d() {
|
||||||
|
polygon(cross_section_polygon());
|
||||||
|
}
|
||||||
|
|
||||||
|
module adapter_body(width) {
|
||||||
|
linear_extrude(width, center = true)
|
||||||
|
cross_section_2d();
|
||||||
|
}
|
||||||
|
|
||||||
|
module mount_holes() {
|
||||||
|
y_min = hole_y_min();
|
||||||
|
y_max = hole_y_max();
|
||||||
|
hole_depth = y_max - y_min;
|
||||||
|
center_y = (y_min + y_max) / 2;
|
||||||
|
for (y_pos = [plate_height - mount_hole_offset_top, mount_hole_offset_bottom]) {
|
||||||
|
translate([y_pos, center_y, mount_hole_x])
|
||||||
|
rotate([90, 0, 0])
|
||||||
|
cylinder(h = hole_depth, d = mount_hole_dia, center = true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module rounded_body(width) {
|
||||||
|
if (minkowski_active()) {
|
||||||
|
minkowski() {
|
||||||
|
adapter_body(max(width - 2 * edge_round, 1));
|
||||||
|
sphere(r = edge_round);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
adapter_body(width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module adapter_plate() {
|
||||||
|
width = part_mode == "profile_strip" ? profile_strip_width : plate_width;
|
||||||
|
if (part_mode == "full") {
|
||||||
|
difference() {
|
||||||
|
rounded_body(width);
|
||||||
|
mount_holes();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rounded_body(width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
adapter_plate();
|
||||||
@@ -0,0 +1,185 @@
|
|||||||
|
// Ring Solar Charger — Vinyl Siding Adapter Plate
|
||||||
|
// Mounts the integrated Ring Solar Charger on horizontal beaded vinyl lap siding.
|
||||||
|
// Units: millimeters. Vanilla OpenSCAD only.
|
||||||
|
//
|
||||||
|
// Rear profile (y=0 bottom, y=plate_height top):
|
||||||
|
// TOP — bead coping cavity scooped into rear face (concave semicircle)
|
||||||
|
// MID — flat rear shelf continues downward
|
||||||
|
// BOTTOM — slow taper outward toward siding projection
|
||||||
|
//
|
||||||
|
// Backup (flat + taper only): ring-solar-siding-adapter.backup.scad
|
||||||
|
|
||||||
|
/* [Plate] */
|
||||||
|
plate_width = 93.1;
|
||||||
|
plate_height = 171.45;
|
||||||
|
min_wall_thickness = 5.0;
|
||||||
|
edge_round = 0;
|
||||||
|
|
||||||
|
/* [Siding Profile] */
|
||||||
|
siding_projection = 27.0;
|
||||||
|
face_inset_depth = 8.0;
|
||||||
|
bead_coping_radius = 10.00; // Semicircle radius for bead groove (measured on siding)
|
||||||
|
bead_coping_offset_top = 11.00; // Distance from plate top to groove center (tune on wall)
|
||||||
|
flat_upper_ratio = 0.55; // Fraction of plate height that stays flat at the top
|
||||||
|
bottom_taper_depth_ratio = 1.6; // Rear depth at plate bottom = min_wall_thickness * this (outward from flat shelf)
|
||||||
|
course_pitch = 165.1;
|
||||||
|
profile_segments = 8;
|
||||||
|
profile_mode = "curved"; // [curved, stepped]
|
||||||
|
rear_clearance = 0.2;
|
||||||
|
|
||||||
|
/* [Mounting Holes] */
|
||||||
|
mount_hole_offset_top = 50.0;
|
||||||
|
mount_hole_offset_bottom = 44.7;
|
||||||
|
mount_hole_dia = 4.5;
|
||||||
|
mount_hole_x = 0;
|
||||||
|
|
||||||
|
/* [Export] */
|
||||||
|
part_mode = "full"; // [full, profile_strip]
|
||||||
|
profile_strip_width = 20;
|
||||||
|
|
||||||
|
/* [Hidden] */
|
||||||
|
$fn = 64;
|
||||||
|
epsilon = 0.01;
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Siding rear-profile geometry
|
||||||
|
// OpenSCAD 2D polygon uses [plate_Y, plate_Z]; linear_extrude() goes along +Z (width).
|
||||||
|
// OpenSCAD 3D: X = plate height (y), Y = depth (z), Z = plate width.
|
||||||
|
// Lower depth Y = toward wall (back). Higher depth Y = toward Ring (front).
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function projection_z() = siding_projection - rear_clearance;
|
||||||
|
|
||||||
|
function face_inset_z() = projection_z() - face_inset_depth;
|
||||||
|
|
||||||
|
function bead_coping_y_center() = plate_height - bead_coping_offset_top;
|
||||||
|
|
||||||
|
// Bottom of flat rear shelf (flat_upper_ratio measured from plate top downward).
|
||||||
|
function face_y_flat_end() = plate_height * (1 - flat_upper_ratio);
|
||||||
|
|
||||||
|
// Rear depth where the bottom taper ends (outward from flat shelf, in wall-thickness units).
|
||||||
|
function bottom_rear_z() =
|
||||||
|
face_inset_z() + min_wall_thickness * bottom_taper_depth_ratio;
|
||||||
|
|
||||||
|
// Slow taper from bottom_rear_z at the plate bottom up to the flat shelf.
|
||||||
|
function lower_curve_z(y) =
|
||||||
|
let(
|
||||||
|
y1 = face_y_flat_end(),
|
||||||
|
t = y / max(y1, epsilon),
|
||||||
|
ease = pow(sin(t * 90), 1.4),
|
||||||
|
z_bottom = bottom_rear_z(),
|
||||||
|
z_top = face_inset_z()
|
||||||
|
)
|
||||||
|
z_top + (z_bottom - z_top) * (1 - ease);
|
||||||
|
|
||||||
|
function stepped_rear_z(y) =
|
||||||
|
y >= face_y_flat_end() ? face_inset_z() : bottom_rear_z();
|
||||||
|
|
||||||
|
// Concave bead coping on the rear face near the plate top.
|
||||||
|
// Flat chord at face_inset_z; arc scoops into the plate (toward the front).
|
||||||
|
function bead_coping_rear_z(y) =
|
||||||
|
let(
|
||||||
|
r = bead_coping_radius,
|
||||||
|
shelf = face_inset_z(),
|
||||||
|
dy = y - bead_coping_y_center(),
|
||||||
|
disc = r * r - dy * dy
|
||||||
|
)
|
||||||
|
disc >= 0 ? shelf + sqrt(disc) : shelf;
|
||||||
|
|
||||||
|
// Flat top shelf + bead cavity + lower taper.
|
||||||
|
function rear_z_at(y) =
|
||||||
|
y >= face_y_flat_end() ? bead_coping_rear_z(y)
|
||||||
|
: profile_mode == "stepped" ? stepped_rear_z(y)
|
||||||
|
: lower_curve_z(y);
|
||||||
|
|
||||||
|
function rear_profile_points() =
|
||||||
|
let(
|
||||||
|
step = plate_height / max(profile_segments * 12, 24),
|
||||||
|
yc = bead_coping_y_center(),
|
||||||
|
r = bead_coping_radius,
|
||||||
|
arc_step = r / 16
|
||||||
|
)
|
||||||
|
concat(
|
||||||
|
[for (y = [0 : step : max(yc - r - epsilon, 0)]) [y, rear_z_at(y)]],
|
||||||
|
[for (y = [yc - r : arc_step : yc + r]) [y, rear_z_at(y)]],
|
||||||
|
[for (y = [min(yc + r + step, plate_height) : step : plate_height]) [y, rear_z_at(y)]]
|
||||||
|
);
|
||||||
|
|
||||||
|
function max_rear_z() =
|
||||||
|
let(pts = rear_profile_points())
|
||||||
|
max([for (p = pts) p[1]]);
|
||||||
|
|
||||||
|
function front_z() = max_rear_z() + min_wall_thickness;
|
||||||
|
|
||||||
|
function rear_y_min() =
|
||||||
|
min([for (p = rear_profile_points()) p[1]]);
|
||||||
|
|
||||||
|
function minkowski_active() =
|
||||||
|
edge_round > 0 && min_wall_thickness >= 2 * edge_round + 1;
|
||||||
|
|
||||||
|
function hole_y_min() =
|
||||||
|
rear_y_min() - (minkowski_active() ? edge_round : 0) - epsilon;
|
||||||
|
|
||||||
|
function hole_y_max() =
|
||||||
|
front_z() + (minkowski_active() ? edge_round : 0) + epsilon;
|
||||||
|
|
||||||
|
function cross_section_polygon() =
|
||||||
|
let(
|
||||||
|
rear_pts = rear_profile_points(),
|
||||||
|
fz = front_z()
|
||||||
|
)
|
||||||
|
[
|
||||||
|
for (p = rear_pts) p,
|
||||||
|
[plate_height, fz],
|
||||||
|
[0, fz]
|
||||||
|
];
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Modules
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
module cross_section_2d() {
|
||||||
|
polygon(cross_section_polygon());
|
||||||
|
}
|
||||||
|
|
||||||
|
module adapter_body(width) {
|
||||||
|
linear_extrude(width, center = true)
|
||||||
|
cross_section_2d();
|
||||||
|
}
|
||||||
|
|
||||||
|
module mount_holes() {
|
||||||
|
y_min = hole_y_min();
|
||||||
|
y_max = hole_y_max();
|
||||||
|
hole_depth = y_max - y_min;
|
||||||
|
center_y = (y_min + y_max) / 2;
|
||||||
|
for (y_pos = [plate_height - mount_hole_offset_top, mount_hole_offset_bottom]) {
|
||||||
|
translate([y_pos, center_y, mount_hole_x])
|
||||||
|
rotate([90, 0, 0])
|
||||||
|
cylinder(h = hole_depth, d = mount_hole_dia, center = true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module rounded_body(width) {
|
||||||
|
if (minkowski_active()) {
|
||||||
|
minkowski() {
|
||||||
|
adapter_body(max(width - 2 * edge_round, 1));
|
||||||
|
sphere(r = edge_round);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
adapter_body(width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module adapter_plate() {
|
||||||
|
width = part_mode == "profile_strip" ? profile_strip_width : plate_width;
|
||||||
|
if (part_mode == "full") {
|
||||||
|
difference() {
|
||||||
|
rounded_body(width);
|
||||||
|
mount_holes();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rounded_body(width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
adapter_plate();
|
||||||
Reference in New Issue
Block a user