@@ -0,0 +1,14 @@ | |||
// animation | |||
function get_anim_keys() = [ | |||
0, // initial | |||
0.1, // resting | |||
0.3, // holodisk inserted | |||
0.4, // laser raised | |||
0.5, // start playing | |||
0.7, // stop playing | |||
0.8, // laser lowered, holodisk removing | |||
1 // final | |||
]; | |||
function anim(key_from, key_to, KEYS=get_anim_keys()) | |||
= max(0, min(($t - KEYS[key_from]) / (KEYS[key_to] - KEYS[key_from]), 1)); |
@@ -6,48 +6,10 @@ | |||
* Related: http://cedmagic.com/history/holotape.html | |||
*/ | |||
width=55; | |||
depth=100; | |||
height=16; | |||
wall=3; | |||
plate=3; | |||
top_rim=2; | |||
bolt_headtype="hex"; | |||
front_body_depth=12; | |||
front_body_bolt_offset=8; | |||
back_bumpers_radius=5; | |||
back_bumpers_bolt_size=3; | |||
tape_height=5; | |||
tape_thickness=0.2; | |||
spool_tape_tolerance=1; | |||
spool_inner_height=tape_height+spool_tape_tolerance; | |||
spool_inner_radius=4; | |||
spool_outer_radius=18; | |||
spool_plate_height=2; | |||
spool_plate_holes=3; | |||
spool_plate_hole_angle=360/spool_plate_holes * 0.5; | |||
spool_plate_hole_inner_rim=1; | |||
spool_plate_hole_outer_rim=4; | |||
spool_slit_depth=0.8; | |||
spool1_depth=depth*0.77; | |||
spool2_depth=depth*0.40; | |||
spool3_depth=(spool1_depth+spool2_depth)/2; | |||
spool4_depth=depth*0.16; | |||
main_spools_x=width * 0.45; | |||
aux_spools_right_x=main_spools_x + spool_outer_radius + 1; | |||
aux_spools_left_x=main_spools_x - 13; | |||
middle_spool_in_r=2; | |||
middle_spool_out_r=7; | |||
aux_spool_plate_hole_inner_rim=2; | |||
aux_spool_plate_hole_outer_rim=2; | |||
spindle_diam=2; | |||
spindle_diam_tolerance=0.2; | |||
tape_z=plate+spool_plate_height; | |||
// dependency: https://github.com/revarbat/BOSL | |||
use <BOSL/transforms.scad> | |||
use <BOSL/metric_screws.scad> | |||
use <BOSL/masks.scad> | |||
use <holodisk_spec.scad> | |||
use <anim.scad> | |||
include <holodisk.scad> | |||
include <reader.scad> |
@@ -1,11 +1,55 @@ | |||
// dependency: https://github.com/revarbat/BOSL | |||
use <BOSL/transforms.scad> | |||
use <BOSL/metric_screws.scad> | |||
//use <BOSL/metric_screws.scad> | |||
use <BOSL/masks.scad> | |||
use <holodisk_spec.scad> | |||
use <anim.scad> | |||
include <tape.scad> | |||
module frame() { | |||
disk_size = get_holodisk_size(); | |||
holodisk_size = get_holodisk_size(); | |||
wall=3; | |||
plate=3; | |||
top_rim=2; | |||
bolt_headtype="hex"; | |||
front_body_depth=12; | |||
front_body_bolt_offset=8; | |||
back_bumpers_radius=5; | |||
back_bumpers_bolt_size=3; | |||
tape_height=5; | |||
tape_thickness=0.2; | |||
spool_tape_tolerance=1; | |||
spool_inner_height=tape_height+spool_tape_tolerance; | |||
spool_inner_radius=4; | |||
spool_outer_radius=18; | |||
spool_plate_height=2; | |||
spool_plate_holes=3; | |||
spool_plate_hole_angle=360/spool_plate_holes * 0.5; | |||
spool_plate_hole_inner_rim=1; | |||
spool_plate_hole_outer_rim=4; | |||
spool_slit_depth=0.8; | |||
spool1_depth=disk_size.y*0.77; | |||
spool2_depth=disk_size.y*0.40; | |||
spool3_depth=(spool1_depth+spool2_depth)/2; | |||
spool4_depth=disk_size.y*0.16; | |||
main_spools_x=disk_size.x*0.45; | |||
aux_spools_right_x=main_spools_x + spool_outer_radius + 1; | |||
aux_spools_left_x=main_spools_x - 13; | |||
middle_spool_in_r=2; | |||
middle_spool_out_r=7; | |||
aux_spool_plate_hole_inner_rim=2; | |||
aux_spool_plate_hole_outer_rim=2; | |||
spindle_diam=2; | |||
spindle_diam_tolerance=0.2; | |||
tape_z=plate+spool_plate_height; | |||
module frame(size) { | |||
width=size.x; | |||
depth=size.y; | |||
height=size.z; | |||
tr=top_rim; | |||
tc=tr*1.5; | |||
fbd=front_body_depth; | |||
@@ -76,21 +120,64 @@ module frame() { | |||
} | |||
} | |||
module slides() { | |||
slide_size = get_holodisk_slide_size(); | |||
slide_pos = get_holodisk_slide_pos(); | |||
slide_plate_size = [0.1, slide_size.y, slide_size.z]; | |||
sliding_size = get_holodisk_slide_sliding_size(); | |||
sliding_pos = get_holodisk_slide_sliding_pos(); | |||
module slide() { | |||
hull() { | |||
translate(sliding_pos) cube(sliding_size); | |||
translate(slide_pos) cube(slide_plate_size); | |||
} | |||
} | |||
module slider() { | |||
slider_size = get_holodisk_slide_slider_size(); | |||
slider_pos = get_holodisk_slide_slider_pos(); | |||
slider_plate_size = [0.1, slider_size.y, slider_size.z]; | |||
slider_top_size = [slider_size.x, slider_size.y, sliding_size.z]; | |||
hull() { | |||
up((slider_size.z-sliding_size.z)/2) translate(slider_pos) cube(slider_top_size); | |||
translate(slider_pos) cube(slider_plate_size); | |||
} | |||
} | |||
right(get_holodisk_size().x) { | |||
slide(); | |||
slider(); | |||
} | |||
scale([-1,1,1]) { | |||
slide(); | |||
slider(); | |||
} | |||
} | |||
module bottom_cover() { | |||
linear_extrude(height=plate) { | |||
back_bumpers(); | |||
square([width, depth]); | |||
difference() { | |||
linear_extrude(height=plate) { | |||
back_bumpers(); | |||
square([width, depth]); | |||
} | |||
down(0.1) translate(get_holodisk_laser_cutout_pos()) cube(get_holodisk_laser_cutout_size()); | |||
} | |||
} | |||
color("SaddleBrown") top_cover(); | |||
color("grey") walls(); | |||
color("Silver") slides(); | |||
color("SaddleBrown") bottom_cover(); | |||
color("silver") back_bolts(); | |||
color("silver") front_bolts(); | |||
//color("silver") back_bolts(); | |||
//color("silver") front_bolts(); | |||
} | |||
module mechanism() { | |||
module mechanism(size) { | |||
width=size.x; | |||
depth=size.y; | |||
height=size.z; | |||
module spool(r_in, r_out, in_rim, out_rim) { | |||
module spindle(d, h) { | |||
color("Sienna") cylinder(h=h, d=d); | |||
@@ -180,9 +267,12 @@ module mechanism() { | |||
tapes(); | |||
} | |||
module holodisk() { | |||
#frame(); | |||
mechanism(); | |||
module holodisk(size) { | |||
frame(size); | |||
mechanism(size); | |||
} | |||
holodisk(); | |||
retraction=holodisk_size.y+10; | |||
back((1-anim(1, 2)) * retraction) // anim insert | |||
back((anim(len(get_anim_keys())-2, len(get_anim_keys())-1)) * retraction) // anim remove | |||
holodisk(holodisk_size); |
@@ -0,0 +1,61 @@ | |||
/* | |||
* Technical Specification for Wattz Electronics Holodisk (AKA Holotape or THT) | |||
* | |||
*/ | |||
// -- core dimensions -- | |||
function get_holodisk_size() = [55, 100, 16]; | |||
// -- tape -- | |||
function get_holodisk_tape_height() = 5; | |||
// -- slide -- | |||
spz = 8; | |||
function get_holodisk_slide_size() = [2, 35, get_holodisk_size().z - spz]; | |||
function get_holodisk_slide_pos() = [0, 15, spz/2]; | |||
sy = 2; | |||
sz = 4; | |||
function get_holodisk_slide_sliding_size() = [get_holodisk_slide_size().x, get_holodisk_slide_size().y - sy, get_holodisk_slide_size().z - sz]; | |||
function get_holodisk_slide_sliding_pos() = [get_holodisk_slide_pos().x, get_holodisk_slide_pos().y + sy/2, get_holodisk_slide_pos().z + sz/2]; | |||
srx = 2; | |||
srz = 2; | |||
function get_holodisk_slide_slider_size() = [get_holodisk_slide_size().x + srx, 15, get_holodisk_slide_size().z + srz]; | |||
function get_holodisk_slide_slider_pos() = [get_holodisk_slide_sliding_pos().x, get_holodisk_slide_sliding_pos().y, get_holodisk_slide_sliding_pos().z - get_holodisk_slide_slider_size().z/2 + srz]; | |||
// -- laser -- | |||
function get_holodisk_laser_cutout_size() = [15, 9, 20]; | |||
function get_holodisk_laser_cutout_pos() = [ | |||
get_holodisk_size().x/2 - get_holodisk_laser_cutout_size().x/2, | |||
12, | |||
0]; | |||
function get_holodisk_laser_cutout_pos_center() = [ | |||
get_holodisk_laser_cutout_pos().x + get_holodisk_laser_cutout_size().x/2, | |||
get_holodisk_laser_cutout_pos().y + get_holodisk_laser_cutout_size().y/2, | |||
get_holodisk_laser_cutout_pos().z + get_holodisk_laser_cutout_size().z/2]; | |||
// -- laser-window -- | |||
function get_holodisk_laserwindow_pos_center() = [ | |||
get_holodisk_laser_cutout_pos_center().x, | |||
0, | |||
6.5 | |||
]; | |||
function get_holodisk_laserwindow_size() = [ | |||
get_holodisk_laser_cutout_size().x, | |||
30, | |||
get_holodisk_tape_height() + 2 | |||
]; | |||
// -- END -- |
@@ -1,52 +1,53 @@ | |||
// dependency: https://github.com/revarbat/BOSL | |||
use <BOSL/transforms.scad> | |||
use <holodisk_spec.scad> | |||
include <anim.scad> | |||
// outside config | |||
width=60; | |||
height=15; | |||
depth=100; | |||
tape_height=5; | |||
tape_z=4; | |||
// local config | |||
frame=5; | |||
head_frame=2; | |||
head_size=[14, 10, tape_height+head_frame*2]; | |||
head_pos=[width/2, -frame+2, tape_z-head_frame]; | |||
laser_size=[10, 2, tape_height]; | |||
laser_pos=[head_pos.x, head_pos.y + 10 + head_size.y, tape_z]; | |||
laser_tower_size=[laser_size.x+2, laser_size.y+1, 15]; | |||
module reader() { | |||
module reader(disk_size) { | |||
width=disk_size.x; | |||
depth=disk_size.y; | |||
height=disk_size.z; | |||
laser_cutout_size = get_holodisk_laser_cutout_size(); | |||
laser_cutout_pos = get_holodisk_laser_cutout_pos_center(); | |||
frame=5; | |||
head_frame=2; | |||
head_size=[14, 10, tape_height+head_frame*2]; | |||
head_pos=[laser_cutout_pos.x, -frame+2, tape_z-head_frame]; | |||
laser_size=[10, 2, tape_height]; | |||
laser_offset=3; | |||
laser_pos=[laser_cutout_pos.x, laser_cutout_pos.y + laser_offset, tape_z]; | |||
laser_tower_size=[laser_cutout_size.x - 1, laser_cutout_size.y - 1 - laser_offset, 15]; | |||
module laser(corner=0.1) { | |||
up(laser_size.z/2) | |||
up(corner) | |||
color("Red") | |||
minkowski() { | |||
s=[laser_size.x, laser_size.y, laser_size.z-corner*2]; | |||
cube(s, center=true); | |||
sphere(corner); | |||
} | |||
fwd(laser_cutout_size.y/3) cube(laser_size, center=true); | |||
} | |||
module laser_tower(corner=2) { | |||
module laser_tower(corner=1) { | |||
color("DarkSlateBlue") | |||
back(laser_tower_size.y-laser_size.y) | |||
difference() { | |||
minkowski() { | |||
s=[laser_tower_size.x, laser_tower_size.y, laser_tower_size.z-corner*2]; | |||
up(laser_size.z/2) | |||
cube(s, center=true); | |||
sphere(corner); | |||
} | |||
fwd(laser_tower_size.y) scale(1.05) laser(); | |||
up(laser_size.z/2) | |||
fwd(laser_offset/2) scale(0.99) cube(laser_tower_size, center=true); | |||
fwd(laser_size.y/3) scale(1.1) laser(); | |||
} | |||
} | |||
module head_space() { | |||
stube=[head_size.x-head_frame*2, head_size.y+head_frame*3, head_size.z-head_frame*2]; | |||
/*stube=[head_size.x-head_frame*2, head_size.y+head_frame*3, head_size.z-head_frame*2]; | |||
up(head_size.z/4 + head_frame) | |||
cube(stube, center=true); | |||
cube(stube, center=true);*/ | |||
translate(get_holodisk_laserwindow_pos_center()) cube(get_holodisk_laserwindow_size(), center=true); | |||
} | |||
module head(corner=0.5) { | |||
@@ -57,14 +58,19 @@ module reader() { | |||
s=[head_size[0], head_size[1] + frame, head_size[2]-corner*2]; | |||
difference() { | |||
up(head_size.z/2) cube(s, center=true); | |||
translate(head_pos) up(head_size.z/2) cube(s, center=true); | |||
head_space(); | |||
} | |||
sphere(corner); | |||
} | |||
} | |||
translate(head_pos) head(); | |||
head(); | |||
retraction=laser_tower_size.z; | |||
down(retraction) | |||
up(anim(2, 3)*retraction) | |||
down(anim(5, 6)*retraction) | |||
translate(laser_pos) { | |||
laser(); | |||
laser_tower(); | |||
@@ -73,10 +79,12 @@ module reader() { | |||
color("DarkSlateBlue") { | |||
difference() { | |||
fwd(frame) cube([width, frame, height]); | |||
translate(head_pos) head_space(); | |||
head_space(); | |||
} | |||
fwd(frame) down(frame) cube([width, depth + frame, frame]); | |||
} | |||
} | |||
reader(); | |||
holodisk_size = is_undef(disk_size) ? [50, 100, 20] : disk_size; | |||
reader(holodisk_size); |