diff --git a/bike-lights/case/battery_enclosure.scad b/bike-lights/case/battery_enclosure.scad new file mode 100644 index 0000000..7ffd77d --- /dev/null +++ b/bike-lights/case/battery_enclosure.scad @@ -0,0 +1,158 @@ +$fn = 50; +threshold = 0.1; +half_threshold = threshold / 2; +bevel = 0.5; + +wire_radius = 1; + +wall_thickness = 2; +cutout_threshold = 1; + +battery_length = 71; +battery_width = 18.75; + +cell_holder_length = battery_length + wall_thickness * 2; +cell_holder_width = battery_width + wall_thickness * 2; +cell_holder_height = battery_width + wall_thickness; + +battery_contact_thickness = .6; +// battery_contact_thickness = 1; +battery_contact_width = 11; +battery_contact_length = 12.8; +battery_contact_spring_height = 10.5; +battery_contact_flange_height = 1.9; + +converter_width = 11.25; +converter_length = 22.25; +converter_height = 5; + + +include <./common.scad>; + +// box(20, 10, 10); +// color("blue", 0.5) cube([10, 20, 10], center = true); + +module cell_cradle(width, height) { + difference() { + translate([0, 0, -height / 2]) cube([width, + wall_thickness, + height], + center = true); + color("red", 1) translate([0, 0, 0]) + rotate([90, 0, 0]) + cylinder(h = wall_thickness + cutout_threshold, + r = width / 2, + center = true); + } +} + +module cell_box() { + union() { + channel(cell_holder_length, cell_holder_width, cell_holder_height); + translate([0, -battery_length / 6, wall_thickness]) cell_cradle(cell_holder_width, cell_holder_height / 2); + translate([0, battery_length / 6, wall_thickness]) cell_cradle(cell_holder_width, cell_holder_height / 2); + } +} + +module contact_box() { + contact_thickness = battery_contact_flange_height * .75; + cutout_width = battery_contact_width * .8; + // box_thickness = contact_thickness_ + wall_thickness * 2; + // box_height = width + wall_thickness; + + difference() { + box(wall_thickness * 2 + contact_thickness, cell_holder_width, cell_holder_height); + translate([0, contact_thickness, wall_thickness * 2]) + cube([battery_contact_width, + wall_thickness * 2, + battery_contact_length + threshold], + center = true); + + color("red", 1) translate([0, + -(wall_thickness + contact_thickness + threshold) / 2, + cell_holder_height / 2]) + cube([5, wall_thickness + threshold * 2, cell_holder_height], center = true); + + translate([0, + -(wall_thickness + contact_thickness + threshold) / 2 - wire_radius, + 0]) + rotate([0, 90, 0]) + cylinder(h = cell_holder_width, r = wire_radius, center = true); + + color("green", 1) translate([-cell_holder_width / 2, 0, cell_holder_height / 2]) + rotate([0, 90, 0]) + cylinder(h = 5, r = contact_thickness / 2, center = true); + + color("green", 1) translate([cell_holder_width / 2, 0, cell_holder_height / 2]) + rotate([0, 90, 0]) + cylinder(h = 5, r = contact_thickness / 2, center = true); + } +} + +module battery_slot() { + difference() { + union() { + translate([0, -cell_holder_length / 2, 0]) contact_box(); + translate([0, wall_thickness, 0]) cell_box(); + translate([0, cell_holder_length / 2 + wall_thickness * 2, 0]) + rotate([0, 0, 180]) + contact_box(); + } + translate([cell_holder_width / 2, 1, 0]) rotate([90, 0, 0]) cylinder(h = cell_holder_length + wall_thickness * 4 + battery_contact_flange_height * 2, r = wire_radius, center = true); + translate([-cell_holder_width / 2, 1, 0]) rotate([90, 0, 0]) cylinder(h = cell_holder_length + wall_thickness * 4 + battery_contact_flange_height * 2, r = wire_radius, center = true); + } +} + +module converter_box() { + box_length = wall_thickness * 2 + converter_height; + box_width = cell_holder_width * 2 - wall_thickness; + difference() { + box(box_length, box_width, cell_holder_height); + + translate([cell_holder_width - wire_radius, 0, 0]) + rotate([90, 0, 0]) + cylinder(h = box_length, r = wire_radius, center = true); + translate([cell_holder_width - wire_radius * 2, 0, 0]) + rotate([0, 90, 0]) + cylinder(h = wall_thickness + threshold, r = wire_radius, center = true); + + translate([-cell_holder_width + wire_radius, 0, 0]) + rotate([90, 0, 0]) + cylinder(h = box_length, r = wire_radius, center = true); + translate([-cell_holder_width + wire_radius * 2, 0, 0]) + rotate([0, 90, 0]) + cylinder(h = wall_thickness + threshold, r = wire_radius, center = true); + + translate([0, -box_length / 2, 0]) + rotate([0, 90, 0]) + cylinder(h = cell_holder_width * 2 + wall_thickness, r = wire_radius, center = true); + + translate([-cell_holder_width * .75, (-box_length + wall_thickness) / 2, 0]) + rotate([90, 0, 0]) + cylinder(h = wall_thickness * 2, r = wire_radius, center = true); + + translate([cell_holder_width * .75, (-box_length + wall_thickness) / 2, 0]) + rotate([90, 0, 0]) + cylinder(h = wall_thickness * 2, r = wire_radius, center = true); + + color("red", 1) translate([-box_width / 4, -(converter_height + wall_thickness) / 2, cell_holder_height / 2]) + cube([5, wall_thickness + threshold * 2, cell_holder_height], center = true); + color("red", 1) translate([box_width / 4, -(converter_height + wall_thickness) / 2, cell_holder_height / 2]) + cube([5, wall_thickness + threshold * 2, cell_holder_height], center = true); + } +} + +module battery_case() { + union() { + translate([-cell_holder_width / 2, 0, 0]) battery_slot(); + translate([cell_holder_width / 2 - wall_thickness, 0, 0]) battery_slot(); + translate([-wall_thickness / 2, + cell_holder_length / 2 + wall_thickness * 2 + battery_contact_flange_height + wall_thickness * 2 + wall_thickness / 2, + 0]) + converter_box(); + } +} + + +battery_case(); + diff --git a/bike-lights/case/common.scad b/bike-lights/case/common.scad new file mode 100644 index 0000000..75ba697 --- /dev/null +++ b/bike-lights/case/common.scad @@ -0,0 +1,57 @@ +module pill(length, bevel) { + hull() { + translate([0, 0, (-length / 2) + bevel]) sphere(r = bevel); + translate([0, 0, (length / 2) - bevel]) sphere(r = bevel); + } +} + +module box_face(dimensions, bevel = 0) { + x = dimensions[0]; + y = dimensions[1]; + z = dimensions[2]; + + if (bevel > 0) { + translate([0, 0, z / 2]) + hull() { + pill(z, bevel); + translate([x, 0, 0]) + pill(z, bevel); + translate([x, y, 0]) + pill(z, bevel); + translate([0, y, 0]) + pill(z, bevel); + } + } else { + cube(dimensions); + } +} + +module channel(length, width, height, bevel) { + union() { + box_face([length, width, wall_thickness], bevel); + + translate([0, wall_thickness - bevel, bevel]) + rotate([90, 0, 0]) + box_face([length, height, wall_thickness], bevel); + + translate([0, width + bevel, bevel]) + rotate([90, 0, 0]) + box_face([length, height, wall_thickness], bevel); + } +} + +module box(length, width, height, bevel = 0) { + union() { + channel(length, width, height, bevel); + + translate([-bevel, 0, bevel]) + rotate([90, 0, 0]) + rotate([0, 90, 0]) + box_face([width, height, wall_thickness], bevel); + translate([length - wall_thickness + bevel, 0, bevel]) + rotate([90, 0, 0]) + rotate([0, 90, 0]) + box_face([width, height, wall_thickness], bevel); + } +} + diff --git a/bike-lights/case/control_panel.scad b/bike-lights/case/control_panel.scad new file mode 100644 index 0000000..de323bc --- /dev/null +++ b/bike-lights/case/control_panel.scad @@ -0,0 +1,95 @@ +$fn = 50; +threshold = 0.1; + +board_length = 92; +board_width = 72; +board_height = 21.5; +wall_thickness = 2; +bevel = 0.5; + +hinge_radius = 2.5; + +case_width = board_width + wall_thickness * 2; +case_length = board_length + wall_thickness * 2; +case_height = board_height + wall_thickness; + +include <./common.scad>; + +module hinge(length) { + difference() { + union() { + cylinder(h = length, r = hinge_radius); + translate([0, -hinge_radius, 0]) + cube([hinge_radius, hinge_radius * 2, length]); + } + translate([0, 0, -threshold / 2]) cylinder(h = length + threshold, r = 1); + } +} + +module main_case() { + hinge_length = board_length / 4; + hinge_y_offset = board_width + wall_thickness + hinge_radius; + hinge_z_offset = board_height; + + difference() { + union() { + box(case_length, + case_width, + case_height, + bevel); + + translate([0, -hinge_radius - bevel + threshold, hinge_z_offset + bevel]) + rotate([90, 0, 0]) + rotate([0, 90, 0]) + hinge(case_length / 4); + + translate([case_length - hinge_length, -hinge_radius - bevel + threshold, hinge_z_offset + bevel]) + rotate([90, 0, 0]) + rotate([0, 90, 0]) + hinge(case_length / 4); + + translate([43, case_width, wall_thickness + 8]) + rotate([90, 0, 0]) + rotate([0, 180, 0]) + linear_extrude(1) + text("lights", size = 3); + + translate([67, case_width, wall_thickness + 8]) + rotate([90, 0, 0]) + rotate([0, 180, 0]) + linear_extrude(1) + text("left", size = 3); + + translate([55, case_width, wall_thickness + 8]) + rotate([90, 0, 0]) + rotate([0, 180, 0]) + linear_extrude(1) + text("right", size = 3); + } + + color("green", 1) translate([8.5 + wall_thickness, case_width - wall_thickness - threshold, wall_thickness]) + cube([60, wall_thickness * 2, 7]); + } +} + +module lid() { + lid_width = case_width + hinge_radius * 2 + wall_thickness; + union() { + difference() { + box_face([case_length, + lid_width, + wall_thickness], + bevel); + translate([(case_length - 60) / 2, 14 + hinge_radius * 2, -threshold / 2]) + cube([60, 16, wall_thickness + threshold]); + } + + translate([case_length / 4 + 1, hinge_radius - 0.4, -hinge_radius]) + rotate([180, 0, 0]) + rotate([0, 90, 0]) hinge(case_length / 2 - 2); + } +} + +// main_case(); +// color("red", 1) translate([0, 0, case_height + wall_thickness / 2]) lid(); +// color("red", 1) translate([0, 0, 40]) lid(); diff --git a/bike-lights/case/control_panel_case.scad b/bike-lights/case/control_panel_case.scad new file mode 100644 index 0000000..9ba0bf7 --- /dev/null +++ b/bike-lights/case/control_panel_case.scad @@ -0,0 +1,4 @@ + +include <./control_panel.scad> + +main_case(); diff --git a/bike-lights/case/control_panel_lid.scad b/bike-lights/case/control_panel_lid.scad new file mode 100644 index 0000000..6824eca --- /dev/null +++ b/bike-lights/case/control_panel_lid.scad @@ -0,0 +1,5 @@ + +include <./control_panel.scad> + +lid(); +