2023-12-24 13:16:23 -06:00
|
|
|
/** Parameters */
|
|
|
|
$camera_mount = true;
|
|
|
|
$base = true;
|
|
|
|
$screen_mount = true;
|
2023-12-24 13:37:46 -06:00
|
|
|
$arm_base = true;
|
2023-12-24 13:16:23 -06:00
|
|
|
$arm_pieces = 1;
|
|
|
|
$screws = 1;
|
|
|
|
$nuts = 1;
|
|
|
|
/** Scale nuts up slightly for easier fit and less friction. */
|
|
|
|
$nut_scale = 1.05;
|
|
|
|
$nut_bumps = false;
|
|
|
|
|
|
|
|
/** Code */
|
|
|
|
module __no_more_parameters() {};
|
|
|
|
|
2023-12-14 22:27:42 -06:00
|
|
|
$triangle_width = 65;
|
|
|
|
$triangle_height = 40;
|
|
|
|
$triangle_thickness = 5.87;
|
|
|
|
$triangle_screw_hole_diameter = 4.7;
|
|
|
|
|
|
|
|
$triangle_x_hole_gap = 40;
|
|
|
|
$triangle_y_hole_gap = 20;
|
|
|
|
$triangle_x_offset = 19;
|
|
|
|
$triangle_y_offset = 5;
|
|
|
|
|
2023-12-24 13:16:23 -06:00
|
|
|
$fn = $preview ? 8 : 360;
|
|
|
|
$steps_per_turn = $preview ? 8 : 128;
|
2023-12-14 22:27:42 -06:00
|
|
|
|
2023-12-17 12:40:52 -06:00
|
|
|
use <Thread_Library.scad>
|
|
|
|
|
2023-12-24 13:16:23 -06:00
|
|
|
if ($camera_mount) {
|
2023-12-24 13:37:46 -06:00
|
|
|
translate([-90, -40, 0])
|
2023-12-24 13:16:23 -06:00
|
|
|
camera_mount();
|
|
|
|
}
|
|
|
|
if ($base) {
|
|
|
|
translate([10, 0, 0]) attachment_point();
|
|
|
|
}
|
|
|
|
if ($screen_mount) {
|
|
|
|
translate([0, 40, 0]) screen_mount();
|
|
|
|
}
|
2023-12-17 12:40:52 -06:00
|
|
|
|
|
|
|
$camera_mount_thickness = 1;
|
|
|
|
$camera_screw_gap_y = 25.2;
|
|
|
|
$camera_screw_diameter = 2.75;
|
|
|
|
module camera_mount() {
|
|
|
|
difference() {
|
|
|
|
cylinder(h=$camera_mount_thickness, d=$camera_screw_gap_y);
|
|
|
|
translate([0, 0, -0.1])
|
|
|
|
cylinder(h=3 * $camera_mount_thickness, d=$camera_screw_gap_y - $camera_screw_diameter * 3);
|
|
|
|
rotate([0, 0, 90])
|
|
|
|
translate([$camera_screw_gap_y / 2 - $camera_screw_diameter / 1.33, 0, -0.1])
|
|
|
|
cylinder(h=3 * $camera_mount_thickness, d=$camera_screw_diameter);
|
|
|
|
rotate([0, 0, -90])
|
|
|
|
translate([$camera_screw_gap_y / 2 - $camera_screw_diameter / 1.33, 0, -0.1])
|
|
|
|
cylinder(h=3 * $camera_mount_thickness, d=$camera_screw_diameter);
|
|
|
|
translate([-1 * $camera_screw_gap_y - $camera_screw_diameter / 1.33, -1 * $camera_screw_gap_y / 2, -0.1])
|
|
|
|
cube([$camera_screw_gap_y, $camera_screw_gap_y, 3 * $camera_mount_thickness]);
|
|
|
|
};
|
2023-12-24 13:16:23 -06:00
|
|
|
|
|
|
|
$width = 20;
|
|
|
|
$thickness = 3;
|
|
|
|
$attachment_offset = 8.475;
|
|
|
|
|
|
|
|
difference() {
|
|
|
|
union() {
|
|
|
|
color("orange")
|
|
|
|
translate([$width + $attachment_offset, $thickness / 2, $width / 2])
|
|
|
|
rotate([90, 0, 0])
|
|
|
|
cylinder(d=$width, h=$thickness);
|
|
|
|
intersection() {
|
|
|
|
translate([$width + $attachment_offset, $thickness / 2, 0])
|
|
|
|
rotate([90, 0, 0])
|
|
|
|
cylinder(h=$thickness, d=$width * 2);
|
|
|
|
translate([$attachment_offset, -$thickness / 2, 0])
|
|
|
|
cube([$width, $thickness, $width]);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
translate([$width + $attachment_offset, $thickness / 2, $width / 2])
|
|
|
|
rotate([90, 0, 0])
|
|
|
|
thread_hole_punch();
|
|
|
|
};
|
2023-12-17 12:40:52 -06:00
|
|
|
}
|
2023-12-14 22:27:42 -06:00
|
|
|
|
|
|
|
module attachment_point() {
|
|
|
|
difference() {
|
|
|
|
linear_extrude($triangle_thickness)
|
|
|
|
polygon([[0, 0], [$triangle_width, $triangle_height], [$triangle_width, 0]]);
|
|
|
|
translate([$triangle_x_offset, $triangle_y_offset, 0])
|
|
|
|
union() {
|
|
|
|
hole_puncher();
|
|
|
|
translate([$triangle_x_hole_gap, 0, 0]) hole_puncher();
|
|
|
|
translate([$triangle_x_hole_gap, $triangle_y_hole_gap, 0]) hole_puncher();
|
|
|
|
};
|
|
|
|
translate([$rounded_nose, 4.234, -0.2])
|
|
|
|
rotate([0, 0, 120])
|
|
|
|
nose_rounding();
|
|
|
|
translate([0, $triangle_height - $triangle_y_offset * 1.5, -0.1])
|
|
|
|
cube([100, 100, $triangle_thickness * 3]);
|
|
|
|
translate([45, 12, -0.1])
|
|
|
|
cylinder(h=100, r=10);
|
|
|
|
translate([28, 8, -0.1])
|
|
|
|
cylinder(h=100, r=4);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
$screen_enter_diameter = 10;
|
|
|
|
$screen_lock_diameter = 6.25;
|
|
|
|
$screen_enter_gap = 30 + $screen_lock_diameter;
|
|
|
|
$screen_enter_y_offset = 14;
|
|
|
|
$screen_mount_width = 50;
|
|
|
|
$screen_mount_height = 60;
|
|
|
|
$screen_mount_thickness = 5;
|
|
|
|
$screen_side_cutout_size = 36;
|
|
|
|
|
|
|
|
module screen_mount() {
|
|
|
|
difference() {
|
|
|
|
cube([$screen_mount_width, $screen_mount_height, $screen_mount_thickness]);
|
|
|
|
translate([$screen_mount_width / 2, $screen_enter_y_offset, -0.1])
|
|
|
|
cylinder(h=$screen_mount_thickness * 2, d=$screen_enter_diameter);
|
|
|
|
translate([$screen_mount_width / 2, $screen_enter_y_offset + $screen_enter_gap, -0.1])
|
|
|
|
cylinder(h=$screen_mount_thickness * 2, d=$screen_enter_diameter);
|
|
|
|
for (i = [0:1:7]) {
|
|
|
|
mount_hole_puncher(i * -1);
|
|
|
|
};
|
|
|
|
translate([$screen_mount_width, $screen_mount_height / 2, -0.1])
|
|
|
|
cylinder(h=$screen_mount_thickness * 2, d=$screen_side_cutout_size);
|
|
|
|
translate([0, $screen_mount_height / 2, -0.1])
|
|
|
|
cylinder(h=$screen_mount_thickness * 2, d=$screen_side_cutout_size);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
module mount_hole_puncher($gap) {
|
|
|
|
translate([$screen_mount_width / 2, $screen_enter_y_offset + $gap, -0.1])
|
|
|
|
cylinder(h=$screen_mount_thickness * 2, d=$screen_lock_diameter);
|
|
|
|
translate([$screen_mount_width / 2, $screen_enter_y_offset + $screen_enter_gap + $gap, -0.1])
|
|
|
|
cylinder(h=$screen_mount_thickness * 2, d=$screen_lock_diameter);
|
|
|
|
};
|
|
|
|
|
|
|
|
module hole_puncher() {
|
|
|
|
translate([0, 0, $triangle_thickness * -1])
|
|
|
|
cylinder(h=$triangle_thickness * 3, d=$triangle_screw_hole_diameter);
|
|
|
|
};
|
|
|
|
|
|
|
|
$rounded_nose = 25;
|
|
|
|
module nose_rounding() {
|
|
|
|
difference() {
|
|
|
|
color("red") cube([$rounded_nose, $rounded_nose, $triangle_thickness * 2]);
|
|
|
|
translate([-3, 0, $triangle_thickness / -2])
|
|
|
|
color("blue")
|
|
|
|
cylinder(h=$triangle_thickness * 3, d=$rounded_nose);
|
|
|
|
};
|
2023-12-24 13:16:23 -06:00
|
|
|
};
|
|
|
|
|
|
|
|
module thread(backlash=0.1) {
|
|
|
|
scale([0.5, 0.5, 0.5])
|
|
|
|
trapezoidThread(length=35, backlash=backlash, stepsPerTurn=$steps_per_turn);
|
|
|
|
}
|
|
|
|
|
|
|
|
$screw_head_diameter = 25;
|
|
|
|
$screw_head_thickness = 8;
|
|
|
|
$nut_head_bump_thickness = 0.5;
|
|
|
|
module nut_head(thickness=$screw_head_thickness) {
|
|
|
|
union() {
|
|
|
|
cylinder(d=$screw_head_diameter, h=thickness, $fn=6);
|
|
|
|
if ($nut_bumps)
|
|
|
|
translate([0, 0, thickness])
|
|
|
|
nut_bumps();
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
module nut_bumps() {
|
|
|
|
bump_length = $screw_head_diameter * 0.05;
|
|
|
|
bump_count = 24;
|
|
|
|
for (i = [0:1:bump_count - 1]) {
|
|
|
|
rotate([0, 0, i * (360 / bump_count)])
|
|
|
|
translate([$screw_head_diameter / 2 - bump_length * 3, 0, 0])
|
|
|
|
color("red")
|
|
|
|
cube([bump_length, $nut_head_bump_thickness, $nut_head_bump_thickness]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-24 13:37:46 -06:00
|
|
|
module screw() {
|
|
|
|
union() {
|
|
|
|
translate([0, 0, $screw_head_thickness - 4])
|
|
|
|
thread();
|
|
|
|
nut_head();
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2023-12-24 13:16:23 -06:00
|
|
|
for (i = [0:1:$screws - 1]) {
|
|
|
|
translate([-$screw_head_diameter, i * ($screw_head_diameter + 5), 0])
|
2023-12-24 13:37:46 -06:00
|
|
|
screw();
|
2023-12-24 13:16:23 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
for (i = [0:1:$nuts - 1]) {
|
|
|
|
translate([-$screw_head_diameter * 2 - 8, i * ($screw_head_diameter + 5), 0])
|
|
|
|
difference() {
|
|
|
|
nut_head();
|
|
|
|
scale([$nut_scale, $nut_scale, 1])
|
|
|
|
translate([0, 0, -4]) thread(backlash=-0.2);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
module arm_piece() {
|
|
|
|
union() {
|
|
|
|
$thickness = 3;
|
|
|
|
$length = 60;
|
|
|
|
$width = 20;
|
|
|
|
|
|
|
|
difference() {
|
|
|
|
union() {
|
|
|
|
cube([$length, $width, $thickness]);
|
|
|
|
translate([0, $width / 2, 0])
|
|
|
|
cylinder(h=$thickness, d=$width);
|
|
|
|
translate([$length, $width / 2, 0])
|
|
|
|
cylinder(h=$thickness, d=$width);
|
|
|
|
};
|
|
|
|
translate([0, $width / 2, 0])
|
|
|
|
thread_hole_punch();
|
|
|
|
translate([$length, $width / 2, 0])
|
|
|
|
thread_hole_punch();
|
|
|
|
}
|
|
|
|
if ($nut_bumps) {
|
|
|
|
translate([0, $width / 2, $thickness])
|
|
|
|
nut_bumps();
|
|
|
|
translate([$length, $width / 2, $thickness])
|
|
|
|
nut_bumps();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (i = [0:1:$arm_pieces - 1]) {
|
|
|
|
translate([0, (i + 1) * -40, 0])
|
|
|
|
arm_piece();
|
|
|
|
}
|
|
|
|
|
|
|
|
module thread_hole_punch(height=50) {
|
|
|
|
translate([0, 0, -0.1])
|
|
|
|
cylinder(d=13, h=height);
|
|
|
|
}
|
2023-12-24 13:37:46 -06:00
|
|
|
|
|
|
|
|
|
|
|
module arm_base() {
|
|
|
|
$width = 20;
|
|
|
|
$thickness = 3;
|
|
|
|
$screw_top = 24.46175;
|
|
|
|
$hole_height = $screw_top + $width / 2 + 1;
|
|
|
|
|
|
|
|
difference() {
|
|
|
|
union() {
|
|
|
|
translate([0, $thickness / 2, $hole_height])
|
|
|
|
rotate([90, 0, 0])
|
|
|
|
cylinder(d=$width, h=$thickness);
|
|
|
|
color("gray")
|
|
|
|
translate([-$width / 2, -$thickness / 2, $screw_top])
|
|
|
|
cube([$width, $thickness, $width / 2 + 1]);
|
|
|
|
};
|
|
|
|
translate([0, 2, $hole_height])
|
|
|
|
rotate([90, 0, 0])
|
|
|
|
thread_hole_punch();
|
|
|
|
}
|
|
|
|
color("brown")
|
|
|
|
translate([0, 0, $screw_top])
|
|
|
|
rotate([-180, 0, 0])
|
|
|
|
screw();
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($arm_base) {
|
|
|
|
translate([-30, -40, 0])
|
|
|
|
arm_base();
|
|
|
|
}
|