|
$fn = $preview ? 32 : 128; |
|
eps = 0.01; |
|
gap = 0.2; |
|
|
|
m4_nominal_d = 4; |
|
m4_clearance_hole_d = 4.5; |
|
m4_dome_d = 7.4; |
|
m4_washer_dz = 0.8; |
|
m4_washer_od = 9; |
|
m4_washer_id = 4.3; |
|
|
|
IR = m4_clearance_hole_d / 2; |
|
OR = m4_washer_od / 2; |
|
|
|
leaf_dz = 5; |
|
socket_dx = 5; |
|
|
|
module plug() { |
|
difference() { |
|
union() { |
|
cylinder(h = leaf_dz, r = OR, center = true); |
|
translate([0, OR / 2, 0]) |
|
cube([OR * 2, OR, leaf_dz], center = true); |
|
} |
|
cylinder(h = leaf_dz + eps, r = IR, center = true); |
|
} |
|
} |
|
|
|
|
|
|
|
module socket() { |
|
module socket_leaf() { |
|
difference() { |
|
union() { |
|
cylinder(h = leaf_dz, r = OR, center = true); |
|
translate([0, - OR / 2 - gap, 0]) |
|
cube([OR * 2, OR + gap, leaf_dz], center = true); |
|
} |
|
cylinder(h = leaf_dz + eps, r = IR, center = true); |
|
} |
|
} |
|
|
|
translate([0, 0, leaf_dz + gap]) |
|
socket_leaf(); |
|
translate([0, 0, -leaf_dz - gap]) |
|
socket_leaf(); |
|
translate([0, - OR - socket_dx / 2 - gap, 0]) |
|
cube([2 * OR, leaf_dz, 3 * leaf_dz + 2 * gap], center = true); |
|
} |
|
|
|
module m4_bolt() { |
|
// TODO: Add head. |
|
cylinder(h = 30, d = m4_nominal_d, center = true); |
|
} |
|
|
|
module m4_washer() { |
|
difference() { |
|
cylinder(h = m4_washer_dz, d = m4_washer_od, center = true); |
|
cylinder(h = m4_washer_dz + eps, |
|
d = m4_washer_id, |
|
center = true); |
|
} |
|
} |
|
|
|
module assembled_bolt() { |
|
// The bolt itself |
|
m4_bolt(); |
|
|
|
// Top washer |
|
translate([0, 0, leaf_dz * 1.5 + m4_washer_dz / 2]) |
|
m4_washer(); |
|
|
|
// Bottom washer |
|
translate([0, 0, leaf_dz * -1.5 - m4_washer_dz / 2]) |
|
m4_washer(); |
|
} |
|
|
|
module ps_part(length = 30) { |
|
socket(); |
|
|
|
translate([0, - OR - length/2 - socket_dx, 0]) |
|
cube([2 * OR, length, 5], center = true); |
|
|
|
translate([0, - OR * 2 - length - socket_dx, 0]) |
|
plug(); |
|
} |
|
|
|
module pp_90_part(length = 5) { |
|
rotate([0, 0, 180]) |
|
plug(); |
|
|
|
translate([0, - OR - length/2, 0]) |
|
cube([2 * OR, length, 2 * OR], center = true); |
|
|
|
translate([0, - OR * 2 - length, 0]) |
|
rotate([0, 90, 0]) |
|
plug(); |
|
} |
|
|
|
module ps_90_part(length = 5) { |
|
rotate([0, 90, 0]) |
|
socket(); |
|
|
|
translate([0, - OR - length/2 - socket_dx - gap, 0]) |
|
cube([2 * OR, length, 5], center = true); |
|
|
|
translate([0, - OR * 2 - length - socket_dx - gap, 0]) |
|
plug(); |
|
} |
|
|
|
camera_dx = 23.9; |
|
camera_dy = 25; |
|
|
|
module camera() { |
|
difference() { |
|
cube([camera_dx, camera_dy, 1], center = true); |
|
for(pos = [[-camera_dx/2 + 2, -camera_dy/2 + 2, 0], |
|
[-camera_dx/2 + 2, camera_dy/2 - 2, 0], |
|
[-camera_dx/2 + 14.5, -camera_dy/2 + 2, 0], |
|
[-camera_dx/2 + 14.5, camera_dy/2 - 2, 0]]) { |
|
translate(pos) |
|
cylinder(1 + eps, d = 2.2, center = true); |
|
} |
|
} |
|
// Sensor |
|
translate([-camera_dx/2 + 17.8 - 8.5/2, 0, 3/2 + 1/2]) |
|
color([.7, 1., 0.7]) |
|
cube([8.5, 8.5, 3], center = true); |
|
// Connector on back |
|
translate([+camera_dx/2 - 5.4/2 - 0.5, 0, -2.5/2 - 1/2]) |
|
color([.7, 1., 0.7]) |
|
cube([5.4, 22, 2.5], center = true); |
|
} |
|
|
|
module camera_holder_front() { |
|
body_dz = 6; |
|
front_dz = 2; |
|
hole_dz = body_dz - front_dz; |
|
|
|
difference() { |
|
color([0.7, 0.7, 1.0, 0.5]) |
|
cube([camera_dx + 4, camera_dy + 4, body_dz], center = true); |
|
// Hollow out main body |
|
translate([0, 0, - body_dz/2 + front_dz - eps]) |
|
cube([camera_dx + 2 * gap, |
|
camera_dy + 2 * gap, |
|
body_dz - front_dz + eps], |
|
center = true); |
|
// Cut out sensor hole |
|
translate([-camera_dx/2 + 17.8 - 8.5/2, 0, 0]) |
|
cube([8.5 + 4 * gap, |
|
8.5 + 4 * gap, |
|
body_dz + eps], |
|
center = true); |
|
} |
|
|
|
// Rods for each hole on the camera module |
|
for(pos = [[-camera_dx/2 + 2, -camera_dy/2 + 2], |
|
[-camera_dx/2 + 2, camera_dy/2 - 2], |
|
[-camera_dx/2 + 14.5, -camera_dy/2 + 2], |
|
[-camera_dx/2 + 14.5, camera_dy/2 - 2]]) { |
|
translate([pos[0], pos[1], - body_dz/2 + 0.5/2]) |
|
cylinder(1.5, d = 2, center = true); |
|
translate([pos[0], pos[1], - 0.5]) |
|
cylinder(hole_dz - 1, d = 3, center = true); |
|
} |
|
|
|
// Right angle locator lugs |
|
for (pos = [[-camera_dx/2 - 1 - gap, -camera_dy/2 - 1, 0], |
|
[-camera_dx/2 - 1 - gap, +camera_dy/2 + 1, -90]]) { |
|
translate([pos[0], pos[1], -4]) |
|
rotate([0, 0, pos[2]]) { |
|
cube([8,1,1]); |
|
cube([1,8,1]); |
|
} |
|
} |
|
|
|
// Straight locator lugs |
|
for (pos = [[+camera_dx/2 + 1 + gap, -camera_dy/2 - 0, 180], |
|
[+camera_dx/2 + 1 + gap, +camera_dy/2 + 1, 180]]) { |
|
translate([pos[0], pos[1], -4]) |
|
rotate([0, 0, pos[2]]) |
|
cube([8,1,1]); |
|
} |
|
} |
|
|
|
module camera_holder_back() { |
|
body_dz = 5; |
|
front_dz = 2; |
|
hole_dz = body_dz - front_dz; |
|
|
|
difference() { |
|
color([0.7, 0.7, 1.0, 0.5]) |
|
cube([camera_dx + 4, camera_dy + 4, body_dz], center = true); |
|
// Hollow out main body |
|
translate([0, 0, + body_dz / 2 - hole_dz / 2 + eps]) |
|
cube([camera_dx + 2 * gap, |
|
camera_dy + 2 * gap, |
|
body_dz - front_dz + eps], |
|
center = true); |
|
// Cut out locator rim |
|
translate([0, 0, + body_dz/2 - 1/2 + eps]) |
|
cube([camera_dx + 2 * gap + 2, |
|
camera_dy + 2 * gap + 2, |
|
1 + eps], |
|
center = true); |
|
// Cut out cable hole |
|
translate([+camera_dx/2 + 2/2, 0, body_dz/2]) |
|
cube([2 + eps, |
|
22, |
|
3 + eps], |
|
center = true); |
|
} |
|
|
|
translate([0, 0, - socket_dx/2 - (2*OR)/2 - body_dz]) |
|
rotate([-90, 0, 0]) |
|
socket(); |
|
} |
|
|
|
module base() { |
|
base_dx = 35; |
|
hole_x = base_dx/2 - m4_clearance_hole_d/2 - 2.5; |
|
|
|
translate([0, 0, 2.5]) |
|
difference() { |
|
cube([base_dx, 10, 5], center = true); |
|
for(x = [hole_x, -hole_x]) { |
|
translate([x, 0, 0]) |
|
cylinder(h = 5 + eps, |
|
d = m4_clearance_hole_d, |
|
center = true); |
|
} |
|
} |
|
translate([0, 0, 14.5]) |
|
rotate([90, 0, 90]) |
|
socket(); |
|
} |
|
|
|
module camera_asm() { |
|
camera(); |
|
translate([0, 0, 6/2 - 1/2]) |
|
color([1., 1., .7, 0.6]) |
|
camera_holder_front(); |
|
|
|
translate([0, 0, -3]) |
|
color([.7, .7, 1., 0.6]) |
|
camera_holder_back(); |
|
|
|
} |
|
|
|
module arm_assembled() { |
|
ps_part(); |
|
translate([0, 30 + 2 * OR + socket_dx, 0]) |
|
ps_part(); |
|
assembled_bolt(); |
|
} |
|
|
|
module to_print() { |
|
translate([0, -40, OR]) |
|
rotate([0, 90, 90]) |
|
ps_part(length = 30); |
|
|
|
translate([0, 0, 6/2]) |
|
rotate([180, 0, 0]) |
|
camera_holder_front(); |
|
|
|
translate([0, 40, 5/2 + socket_dx + 2 * OR]) |
|
camera_holder_back(); |
|
|
|
translate([0, 80, 0]) |
|
base(); |
|
|
|
translate([80, 0, OR]) |
|
rotate([0, 0, 90]) |
|
pp_90_part(length = 5); |
|
|
|
translate([40, 0, OR]) |
|
rotate([0, 0, 90]) |
|
ps_90_part(length = 5); |
|
} |
|
|
|
translate([-50, 0, 0]) |
|
arm_assembled(); |
|
|
|
translate([50, 0, 0]) |
|
to_print(); |
|
|
|
translate([0, 0, 0]) |
|
camera_asm(); |