Created
March 26, 2022 18:34
-
-
Save mossprescott/06377e42bbbe4bd30925b1ae306928d7 to your computer and use it in GitHub Desktop.
OpenSCAD model of an interesting clock
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Crude copy of Fibonacci Clocks' "Hyperbola Clock" (https://www.youtube.com/watch?v=DgqTGXB9KNk). | |
Really needs an interesting shape for the face, but I'd rather come up with something | |
original than copy the original clock. Hmm... | |
*/ | |
/* [Special] */ | |
$fa = 1; | |
$fs = 0.2; | |
$t = 0; // [0:0.5:12.0] | |
/* [Base and Face] */ | |
length = 20; | |
height = 16.5; | |
face_angle = 90; | |
face_anchor = 0; | |
face_notch = 2.5; | |
face_extra = 0.2; // embedded in the base | |
label_scale = 0.075; // relative to h | |
/* [Post] */ | |
post_height = 22; | |
post_angle = 45; | |
post_offset = 1.875; // [0.5:0.125:2.0] | |
post_radius = 0.2; | |
/* [Time] */ | |
start_hour = 7; // [11] The hour that appears on the lower right | |
// Intersection points (empirical): | |
// These were manually adjusted to align with the intersection of | |
// the post with the front plane of the face. | |
/* [Path] */ | |
x1 = 0.7; | |
x2 = 0.265; | |
x3 = 0.2; | |
// TODO: re-calibrate these to be up from the rotor plate, not relative to the notch | |
cy = 0.67; | |
y2 = 0.185; | |
y3 = 0.05; | |
module base() { | |
translate([0, 0, 0.5]) | |
cube([length, length, 1], center = true); | |
} | |
module face() { | |
translate([0, -face_anchor, 0.5]) | |
rotate([face_angle, 0, 0]) | |
translate([0, face_notch, 0]) | |
difference() { | |
// Plank: | |
translate([-length/2, -(face_notch + face_extra), -0.5]) | |
cube([length, height + face_notch + face_extra, 0.5]); | |
// Notch: | |
translate([0, -face_notch/2 - 0.5, -0.25]) | |
cube([length - 2*1, face_notch+1, 1], center = true); | |
// Indicators: | |
translate([0, 0, -0.55]) | |
linear_extrude(0.6) | |
union() { | |
scale([length/2, length/2]) { | |
// Note: these positions aren't really completely | |
// independent of start_hour. That is, if the digits | |
// get shifted around, their positions will need adjustment. | |
digit(0, x1 - 0.18, cy - cy + 0.05, false); | |
digit(1, x2 - 0.08, cy - 1.2*y2, false); | |
digit(2, x3 - 0.08, cy - 1.3*y3, false); | |
digit(3, x3 - 0.08, cy + 1.3*y3, false); | |
digit(4, x2 - 0.08, cy + 1.2*y2, false); | |
digit(5, x1 - 0.10, cy + cy + 0.025, false); | |
digit(6, x1 - 0.18, cy - cy + 0.05, true); | |
digit(7, x2 - 0.08, cy - 1.2*y2, true); | |
digit(8, x3 - 0.08, cy - 1.3*y3, true); | |
digit(9, x3 - 0.08, cy + 1.3*y3, true); | |
digit(10, x2 - 0.08, cy + 1.2*y2, true); | |
digit(11, x1 - 0.10, cy + cy + 0.025, true); | |
} | |
// Bottom to top, right side: | |
/* 0 */ hole(x1, cy - cy); | |
/* 1 */ hole(x2, cy - y2); | |
/* 2 */ hole(x3, cy - y3); | |
/* 3 */ hole(x3, cy + y3); | |
/* 4 */ hole(x2, cy + y2); | |
/* 5 */ hole(x1, cy + cy); | |
// Left side: | |
/* 6 */ hole(-x1, cy - cy); | |
/* 7 */ hole(-x2, cy - y2); | |
/* 8 */ hole(-x3, cy - y3); | |
/* 9 */ hole(-x3, cy + y3); | |
/* 10 */ hole(-x2, cy + y2); | |
/* 11 */ hole(-x1, cy + cy); | |
path(); | |
mirror([1, 0]) | |
path(); | |
} | |
} | |
} | |
function hour_str(d) = | |
str((d-1+start_hour) % 12 + 1); | |
module digit(d, x, y, flip) { | |
translate([flip ? -x : x, y]) | |
text(hour_str(d), | |
size=label_scale, | |
halign = flip ? "left" : "right", | |
valign = "center"); | |
} | |
module path() { | |
x1_5 = (x1+x2)/2 - 0.02; | |
y1_5 = (cy + y2)/2; | |
q = 0.1; // how far past the last intersection point) | |
m = 0.025; // radius of the chamfer | |
e = 0.1/2-m; // width of the path (in x, not perpendicular) | |
scale([length/2, length/2]) | |
minkowski($fn = 20) { | |
circle(m); | |
polygon(points = [ | |
// start at the lower right (outside): | |
// [x1 + e, cy - cy - e], | |
[x1 + e, cy - cy], | |
[x1_5 + e, cy - y1_5], // a little bend in the long side | |
[x2 + e, cy - y2], | |
[x3 + e, cy - y3], | |
[x3 + e, cy + y3], | |
[x2 + e, cy + y2], | |
[x1_5 + e, cy + y1_5], // bend again | |
[x1 + e, cy + cy], | |
[x1 + q + e, cy + cy + q], // extend a bit to clear the post | |
// now back down around the left (inside): | |
[x1 + 1.3*q - e, cy + cy + 1.2*q], | |
[x1 - e, cy + cy], | |
[x1_5 - e, cy + y1_5], | |
[x2 - e, cy + y2], | |
[x3 - e, cy + y3], | |
[x3 - e, cy - y3], | |
[x2 - e, cy - y2], | |
[x1_5 - e, cy - y1_5], | |
[x1 - e, cy - cy], | |
// [x1 - e, cy - cy - e], // extend to chamfer the lower corner | |
]); | |
} | |
} | |
module hole(x, y) { | |
translate([length/2*x, length/2*y, 0]) | |
circle(r = 0.25); | |
} | |
module rotor(hr) { | |
rotate(-30*(hr - start_hour + 0.5)) { | |
// Plate | |
translate([0, 0, 1.5]) | |
cylinder(h = 1, r = length/2 - 1); | |
// Axle | |
translate([0, 0, 1.25]) | |
cylinder(h = 1.01, r = 0.5, center = true); | |
// Post | |
translate([length/2 - 2, post_offset, 1.7]) | |
rotate([0, -post_angle, 0]) | |
cylinder(h = post_height, r = post_radius, $fn = 20); | |
} | |
} | |
/* | |
Visualize the intersection points of the post with the front edge of the | |
clock face. | |
Note: this isn't working right, now that the face module is fancier. | |
*/ | |
module locate_hours() { | |
face(); | |
translate([0, -0.1, 0]) | |
color("red") | |
intersection() { | |
scale([1, 0.05, 1]) | |
face(); // Need a simple plane here; the face now been sliced up | |
for (i = [0:12]) { | |
rotor(i); | |
} | |
} | |
} | |
face(); | |
base(); | |
color("gray") | |
rotor($t); | |
//locate_hours(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment