Skip to content

Instantly share code, notes, and snippets.

@fluffysquirrels
Last active August 26, 2021 16:10
Show Gist options
  • Save fluffysquirrels/10bc4fe7f66528ddc4f3525a03cc950e to your computer and use it in GitHub Desktop.
Save fluffysquirrels/10bc4fe7f66528ddc4f3525a03cc950e to your computer and use it in GitHub Desktop.
Flexible mount for Raspberry Pi camera module on aluminium 2020 v-slot extrusion

Camera mount

This is a flexible mount for Raspberry Pi camera module on aluminium 2020 v-slot extrusion.

the layout is probably a bit confusing
at 0,0,0 there's an assembled camera mount including a simplified model of the camera itself
at -50, 0, 0 there's an assembled hinge
at 50, 0, 0 and around it are different pieces that i printed in print layout
i used ! to select the parts to print (cunningly concealed in module to_print) to export .stl's
all parts in to_print are in the orientation to print them
i used circular cross sections for the joints so those needed support unfortunately
i think everything needs support except the front and the base modules
but the only one that needs much support is the camera back, which is like half support
i used cura defaults for support (zig-zag, 20% support infill)
i used 3 walls and 50% infill for the bodies i think, but it's probably not required
$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();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment