Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
2ad1dbb2bThis file is pinned to the selected release. Download the original to open it in your design tool.
/*
Copyright 2015-2016 Scott Bezek and the splitflap contributors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
use<28byj-48.scad>;
use<assert.scad>;
use<label.scad>;
use<projection_renderer.scad>;
use<publicDomainGearV1.1.scad>;
use<roboto/RobotoCondensed-Regular.ttf>;
use<rough7380.scad>;
use<spool.scad>;
// ##### RENDERING OPTIONS #####
render_3d = true;
// 3d parameters:
render_enclosure = 2; // 0=invisible; 1=translucent; 2=opaque color;
render_flaps = 1; // 0=invisible; 1=front flap only; 2=all flaps
render_flap_area = 0; // 0=invisible; 1=collapsed flap exclusion; 2=collapsed+extended flap exclusion
render_letters = "4";
render_units = len(render_letters);
render_unit_separation = 0.1;
render_pcb = true;
render_bolts = true;
render_motor = true;
// 2d parameters:
render_index = -1;
render_etch = false;
// Version label:
render_revision = "deadbeef";
render_date = "YYYY-MM-DD";
spool_explosion = 0; // 0-1
spool_strut_explosion = lookup(spool_explosion, [
[0, 0],
[0.2, 0],
[1, 30],
]);
spool_horizontal_explosion = lookup(spool_explosion, [
[0, 0],
[1, 8],
]);
// Kerf based off http://blog.ponoko.com/2011/07/12/figuring-out-kerf-for-precision-parts/
// It's better to underestimate (looser fit) than overestimate (no fit)
kerf_value = 0.19 - 0.01;
kerf_width = render_etch ? -kerf_value : kerf_value;
// MDF, .125in nominal
// http://www.ponoko.com/make-and-sell/show-material/64-mdf-natural
thickness = 3.2;
eps=.01;
// M4 bolts
m4_hole_diameter = 4.5;
m4_bolt_length = 12;
m4_button_head_diameter = 7.6 + .2;
m4_button_head_length = 2.2 + .2;
m4_nut_width_flats = 7 + .2;
m4_nut_width_corners = 7/cos(180/6);
m4_nut_width_corners_padded = m4_nut_width_corners + .2;
m4_nut_length = 3.2;
m4_nut_length_padded = m4_nut_length + .2;
captive_nut_inset=6;
assembly_inner_radius = m4_hole_diameter/2;
assembly_color = [.76, .60, .42];
assembly_color1 = [.882, .694, .486]; //"e1b17c";
assembly_color2 = [.682, .537, .376]; //"ae8960";
assembly_color3 = [.416, .325, .227]; //"6A533A";
assembly_color4 = [.204, .161, .114]; //"34291D";
flap_width = 54;
flap_height = 43;
flap_thickness = 30 / 1000 * 25.4; // 30 mil
flap_corner_radius = 3.1; // 2.88-3.48mm (used just for display)
flap_rendered_angle = 90;
letter_height = flap_height * 0.75 * 2;
// Amount of slop of the flap side to side between the 2 spools
flap_width_slop = 0.5;
// Amount of slop for the spool assembly side-to-side inside the enclosure
spool_width_slop = 0.5;
num_flaps = 40;
flap_hole_radius = 1.2;
flap_gap = 1;
flap_spool_outset = flap_hole_radius;
flap_pitch_radius = flap_spool_pitch_radius(num_flaps, flap_hole_radius, flap_gap); //num_flaps * (flap_hole_radius*2 + flap_gap) / (2*PI);
spool_outer_radius = flap_spool_outer_radius(num_flaps, flap_hole_radius, flap_gap, flap_spool_outset); //flap_pitch_radius + 2*flap_hole_radius;
// Radius where flaps are expected to flap in their *most collapsed* (90 degree) state
exclusion_radius = sqrt(flap_height*flap_height + flap_pitch_radius*flap_pitch_radius);
// Radius where flaps are expected to flap in their *most extended* state
outer_exclusion_radius = flap_pitch_radius + flap_height + 2;
front_forward_offset = flap_pitch_radius + flap_thickness/2;
flap_notch = sqrt(spool_outer_radius*spool_outer_radius - flap_pitch_radius*flap_pitch_radius);
echo(flap_notch=flap_notch);
flap_pin_width = flap_hole_radius*2 - 1;
spool_strut_tabs = 3;
spool_strut_tab_width=8;
spool_strut_tab_outset=8;
spool_strut_width = (spool_strut_tab_outset + thickness/2) * 2;
spool_strut_length_inset = 0;
spool_strut_length = flap_width + flap_width_slop - (2 * spool_strut_length_inset);
spool_strut_inner_length = flap_width + flap_width_slop - 3 * thickness;
spool_strut_exclusion_radius = sqrt((spool_strut_tab_outset+thickness/2)*(spool_strut_tab_outset+thickness/2) + (spool_strut_tab_width/2)*(spool_strut_tab_width/2));
ir_reflectance_hole_radius = 2.5;
// PCB parameters
pcb_offset_radius = spool_strut_exclusion_radius + ir_reflectance_hole_radius + 1;
pcb_height = 48;
pcb_length = 48;
pcb_thickness = 1.6;
pcb_mount_inset_vertical = 4;
pcb_mount_inset_horizontal = 8;
pcb_mount_slot_delta = 4;
pcb_mount_hole_radius = m4_hole_diameter/2;
pcb_reference_horizontal = -pcb_length - pcb_offset_radius;
pcb_reference_vertical = -4;
pcb_sensor_horizontal_inset = 1.8; // how far in the sensor is from the edge of the PCB
pcb_connector_height = 3.2;
ir_reflectance_hole_offset = pcb_offset_radius + pcb_sensor_horizontal_inset;
28byj48_bracket_thickness = 0.8;
28byj48_chassis_height = 19;
28byj48_chassis_height_slop = 1;
enclosure_wall_to_wall_width = thickness + spool_width_slop/2 + flap_width_slop/2 + flap_width + flap_width_slop/2 + spool_width_slop/2 + max(28byj48_bracket_thickness + m4_button_head_length, pcb_thickness + pcb_connector_height, pcb_thickness + m4_button_head_length) + thickness;
enclosure_width = enclosure_wall_to_wall_width + 28byj48_chassis_height + 28byj48_chassis_height_slop - thickness - 28byj48_bracket_thickness;
enclosure_horizontal_inset = (enclosure_width - enclosure_wall_to_wall_width)/2;
front_window_upper_base = (flap_height - flap_pin_width/2);
front_window_overhang = 3;
front_window_upper = front_window_upper_base - front_window_overhang;
front_window_lower = sqrt(outer_exclusion_radius*outer_exclusion_radius - front_forward_offset*front_forward_offset);
front_window_slop = 0;
front_window_width = spool_width_slop + flap_width + flap_width_slop + front_window_slop;
front_window_right_inset = thickness - front_window_slop/2;
enclosure_vertical_margin = 10; // gap between top/bottom of flaps and top/bottom of enclosure
enclosure_vertical_inset = thickness*1.5; // distance from top of sides to top of the top piece
enclosure_height_upper = exclusion_radius + enclosure_vertical_margin + thickness + enclosure_vertical_inset;
enclosure_height_lower = flap_pitch_radius + flap_height + enclosure_vertical_margin + thickness + enclosure_vertical_inset;
enclosure_height = enclosure_height_upper + enclosure_height_lower;
enclosure_horizontal_rear_margin = thickness; // minumum distance between the farthest feature and the rear
enclosure_length = front_forward_offset + pcb_reference_vertical + pcb_height - pcb_mount_inset_vertical + pcb_mount_slot_delta + pcb_mount_hole_radius + enclosure_horizontal_rear_margin;
motor_mount_separation = 35; // 28byj-48 mount hole separation
motor_mount_shaft_offset = 8;
motor_shaft_radius = 2.5;
motor_shaft_under_radius = 0.1;
motor_slop_radius = 3;
// Enclosure connector tabs: front/back
num_front_tabs = 2;
front_tab_width = (enclosure_wall_to_wall_width - 2*thickness) / (num_front_tabs*2 - 1);
enclosure_length_right = front_forward_offset + m4_hole_diameter/2 + 2;
num_side_tabs = 5;
side_tab_width = enclosure_length_right / 4;
side_tab_width_fraction = 0.5;
backstop_bolt_vertical_offset = - (exclusion_radius + outer_exclusion_radius)/2;
backstop_bolt_forward_range = 14;
connector_bolt_offset = 40;
motor_mount_hole_radius = m4_hole_diameter/2;
motor_chassis_width = 28;
motor_shaft_offset = 8;
motor_backpack_extent = 18;
motor_hole_slop = 1;
echo(enclosure_height=enclosure_height);
echo(enclosure_height_upper=enclosure_height_upper);
echo(enclosure_height_lower=enclosure_height_lower);
echo(enclosure_width=enclosure_width);
echo(enclosure_wall_to_wall_width=enclosure_wall_to_wall_width);
echo(enclosure_length=enclosure_length);
echo(enclosure_length_right=enclosure_length_right);
echo(enclosure_length_real=enclosure_length+thickness);
echo(spool_strut_inner_length=spool_strut_inner_length);
echo(front_window_width=front_window_width);
echo(front_window_upper=front_window_upper);
echo(front_window_lower=front_window_lower);
echo(front_window_height=front_window_lower+front_window_upper);
echo(front_forward_offset=front_forward_offset);
module standard_m4_bolt(nut_distance=-1) {
if (render_bolts) {
roughM4_7380(12);
}
if (nut_distance >= 0) {
color([0.70, 0.70, 0.72]) {
translate([0, 0, nut_distance]) {
linear_extrude(m4_nut_length) {
difference() {
circle(r=m4_nut_width_corners/2, $fn=6);
circle(r=m4_hole_diameter/2, $fn=20);
}
}
}
}
}
}
// ##### CAPTIVE NUT NEGATIVE #####
// Centered in the x dimension
module captive_nut(bolt_diameter, bolt_length, nut_width, nut_length, nut_inset) {
union() {
translate([-bolt_diameter/2, 0, 0])
square([bolt_diameter, bolt_length]);
translate([-nut_width/2, nut_inset, 0])
square([nut_width, nut_length]);
}
}
module m4_captive_nut(bolt_length=m4_bolt_length) {
captive_nut(m4_hole_diameter, bolt_length + 1, m4_nut_width_flats, m4_nut_length_padded, captive_nut_inset);
}
// ##### Struts for bracing spool #####
module spool_strut_tab_hole() {
square([thickness, spool_strut_tab_width], center=true);
}
module spool_strut_tab_holes() {
for (i=[0:3]) {
angle = 90*i;
translate([cos(angle)*spool_strut_tab_outset, sin(angle)*spool_strut_tab_outset])
rotate([0,0,angle])
spool_strut_tab_hole();
}
}
module spool_strut() {
joint_tab_width = spool_strut_inner_length / spool_strut_tabs;
linear_extrude(thickness, center=true) {
union() {
translate([spool_strut_length_inset, -spool_strut_tab_width / 2]) {
square([spool_strut_length, spool_strut_tab_width]);
}
translate([thickness*2, -spool_strut_width / 2]) {
difference() {
square([spool_strut_inner_length, spool_strut_width]);
// subtract out tabs
union() {
for (i = [0:2:spool_strut_tabs-1]) {
translate([i*joint_tab_width, -eps])
square([joint_tab_width, thickness+eps]);
}
for (i = [1:2:spool_strut_tabs-1]) {
translate([i*joint_tab_width, spool_strut_width - thickness])
square([joint_tab_width, thickness+eps]);
}
}
}
}
}
}
}
module spool_struts() {
for (i=[0:3]) {
angle = 90*i;
//color([i < 2 ? 0 : 1, i == 0 || i == 2 ? 0 : 1, 0])
color(i % 2 == 0 ? assembly_color2 : assembly_color3)
translate([0, sin(angle)*(spool_strut_tab_outset + spool_strut_explosion), cos(angle)*(spool_strut_tab_outset + spool_strut_explosion)])
rotate([-angle, 0, 0])
spool_strut();
}
}
module flap_spool_complete(captive_nut=false, motor_shaft=false, ir_detector_hole=false) {
linear_extrude(thickness) {
difference() {
flap_spool(num_flaps, flap_hole_radius, flap_gap, flap_spool_outset,
height=0);
spool_strut_tab_holes();
if (captive_nut) {
circle(r=m4_nut_width_corners_padded/2, $fn=6);
}
if (motor_shaft) {
rotate([0, 0, 90]) {
motor_shaft();
}
}
if (ir_detector_hole) {
// Hole for IR reflectance sensor to detect
translate([ir_reflectance_hole_offset, 0]) {
circle(r=ir_reflectance_hole_radius, $fn=15);
}
}
}
}
}
module spool_retaining_wall(m4_bolt_hole=false) {
linear_extrude(thickness) {
difference() {
square([spool_strut_width, spool_strut_width], center=true);
spool_strut_tab_holes();
if (m4_bolt_hole) {
circle(r=m4_hole_diameter/2, $fn=30);
}
}
}
}
module flap() {
color([1, 1, 1])
translate([0, -flap_pin_width/2, -flap_thickness/2])
linear_extrude(height=flap_thickness) {
difference() {
union() {
square([flap_width, flap_height - flap_corner_radius + eps]);
// rounded corners
hull() {
translate([flap_corner_radius, flap_height - flap_corner_radius])
circle(r=flap_corner_radius, $fn=40);
translate([flap_width - flap_corner_radius, flap_height - flap_corner_radius])
circle(r=flap_corner_radius, $fn=40);
}
}
translate([-eps, flap_pin_width])
square([eps + thickness, flap_notch]);
translate([flap_width - thickness, flap_pin_width])
square([eps + thickness, flap_notch]);
}
}
}
module translated_flap() {
translate([0, flap_pitch_radius, 0]) {
rotate([flap_rendered_angle, 0, 0]) {
flap();
}
}
}
// double-flatted motor shaft of 28byj-48 motor (2D)
module motor_shaft() {
union() {
intersection() {
circle(r=motor_shaft_radius-motor_shaft_under_radius, $fn=50);
square([motor_shaft_radius*2, 3], center=true);
}
square([motor_shaft_radius/3, motor_shaft_radius*4], center=true);
}
}
module front_tabs_negative() {
for (i = [0 : num_front_tabs-1]) {
translate([thickness + (i*2+0.5) * front_tab_width, 0, 0])
square([front_tab_width, thickness], center=true);
}
for (i = [0 : num_front_tabs-2]) {
translate([thickness + (i*2+1.5) * front_tab_width, 0, 0])
circle(r=m4_hole_diameter/2, $fn=30);
}
}
module enclosure_front() {
linear_extrude(height=thickness) {
difference() {
translate([-enclosure_horizontal_inset, 0, 0]) {
square([enclosure_width, enclosure_height]);
}
// Viewing window cutout
translate([front_window_right_inset, enclosure_height_lower - front_window_lower])
square([front_window_width, front_window_lower + front_window_upper]);
// Front lower tabs
translate([0, thickness * 0.5 + enclosure_vertical_inset, 0])
front_tabs_negative();
// Front upper tabs
translate([0, enclosure_height - thickness * 0.5 - enclosure_vertical_inset, 0])
front_tabs_negative();
}
}
}
// holes for 28byj-48 motor, centered around motor shaft
module motor_mount() {
circle(r=motor_shaft_radius+motor_slop_radius, center=true, $fn=30);
translate([-motor_mount_separation/2, -8]) {
circle(r=motor_mount_hole_radius, center=true, $fn=30);
}
translate([motor_mount_separation/2, -8]) {
circle(r=motor_mount_hole_radius, center=true, $fn=30);
}
translate([-motor_chassis_width/2 - motor_hole_slop/2, -motor_shaft_offset - motor_backpack_extent - motor_hole_slop/2, 0]) {
square([motor_chassis_width + motor_hole_slop, motor_chassis_width/2 + motor_backpack_extent + motor_hole_slop]);
}
}
module side_tabs_negative(hole_sizes=[], extend_last_tab=false) {
for (i = [0 : len(hole_sizes)]) {
length = (extend_last_tab && i == len(hole_sizes)) ? side_tab_width * side_tab_width_fraction + eps : side_tab_width * side_tab_width_fraction;
translate([-thickness / 2, thickness + (i*2) * side_tab_width + side_tab_width * (1 - side_tab_width_fraction)/2, 0])
square([thickness, length]);
}
for (i = [0 : len(hole_sizes) - 1]) {
hole_size = hole_sizes[i];
if (hole_size > 0) {
bolt_head_hole = hole_size == 2;
translate([0, thickness + (i*2 + 1.5) * side_tab_width, 0])
circle(r=(bolt_head_hole ? m4_button_head_diameter : m4_hole_diameter)/2, $fn=30);
}
}
}
module backstop_bolt_slot(radius) {
hull() {
circle(r=radius, $fn=15);
translate([0, backstop_bolt_forward_range]) {
circle(r=radius, $fn=15);
}
}
}
module enclosure_left() {
linear_extrude(height=thickness) {
difference() {
square([enclosure_height, enclosure_length]);
translate([enclosure_height_lower, enclosure_length - front_forward_offset, 0])
circle(r=m4_hole_diameter/2, center=true, $fn=30);
translate([enclosure_height_lower, enclosure_length - front_forward_offset]) {
rotate([0, 0, 90]) {
motor_mount();
}
}
// bottom side tabs
translate([thickness * 0.5 + enclosure_vertical_inset, enclosure_length, 0])
mirror([0, 1, 0])
side_tabs_negative(hole_sizes=[1]);
// top side tabs
translate([enclosure_height - thickness * 0.5 - enclosure_vertical_inset, enclosure_length, 0])
mirror([0, 1, 0])
side_tabs_negative(hole_sizes=[1]);
// PCB mounting holes
translate([enclosure_height_lower, enclosure_length - front_forward_offset]) {
rotate([0, 0, -90]) {
translate([pcb_reference_vertical, pcb_reference_horizontal]) {
pcb_mounting_holes(slots = true);
}
}
}
}
}
}
module shaft_centered_motor_hole() {
margin = 5;
width = motor_mount_separation + 3.5*2 + margin*2;
length = 18 + 14 + margin*2;
translate([-width/2, -(margin + 18 + 8)])
square([width, length]);
}
module enclosure_right() {
linear_extrude(height=thickness) {
difference() {
square([enclosure_height, enclosure_length_right]);
translate([enclosure_height_upper, enclosure_length_right - front_forward_offset, 0])
circle(r=m4_hole_diameter/2, center=true, $fn=30);
// backstop bolt slot
translate([enclosure_height_upper - backstop_bolt_vertical_offset, enclosure_length_right - front_forward_offset, 0]) {
backstop_bolt_slot(radius = m4_hole_diameter/2);
}
// top side tabs
translate([0.5*thickness + enclosure_vertical_inset, enclosure_length_right, 0])
mirror([0, 1, 0])
side_tabs_negative(hole_sizes=[1]);
// bottom side tabs
translate([enclosure_height - 0.5*thickness - enclosure_vertical_inset, enclosure_length_right, 0])
mirror([0, 1, 0])
side_tabs_negative(hole_sizes=[1]);
}
}
}
module front_back_tabs() {
for (i = [0 : 2 : num_front_tabs*2-2]) {
translate([i * front_tab_width, -eps, 0])
square([front_tab_width, thickness + eps]);
}
}
module side_tabs(tabs) {
for (i = [0 : 2 : tabs*2-2]) {
translate([-eps, i * side_tab_width + side_tab_width * (1 - side_tab_width_fraction)/2, 0])
square([thickness + eps, side_tab_width * side_tab_width_fraction]);
}
}
module front_back_captive_nuts() {
for (i = [0 : 2 : num_front_tabs-1]) {
translate([(i*2 + 1.5) * front_tab_width, -thickness, 0])
m4_captive_nut();
}
}
module side_captive_nuts(hole_types=[]) {
for (i = [0 : len(hole_types)-1]) {
hole_type = hole_types[i];
translate([-thickness, (i*2 + 1.5) * side_tab_width, 0]) {
rotate([0, 0, -90]) {
if (hole_type == 2) {
} else if (hole_type == 1) {
m4_captive_nut();
}
}
}
}
}
module enclosure_top() {
// note, this is flipped upside down (around the x axis) when assembled so the clean side faces out
linear_extrude(height = thickness) {
translate([thickness, 0, 0]) {
difference() {
union() {
square([enclosure_wall_to_wall_width - 2 * thickness, enclosure_length_right]);
// front tabs
mirror([0, 1, 0])
front_back_tabs();
// left tabs
translate([enclosure_wall_to_wall_width - 2 * thickness, thickness, 0])
side_tabs(2);
// right tabs
mirror([1, 0, 0])
translate([0, thickness, 0])
side_tabs(2);
}
// front captive nuts
front_back_captive_nuts();
// right captive nuts
translate([0, thickness, 0])
side_captive_nuts(hole_types = [1]);
// left captive nuts
translate([enclosure_wall_to_wall_width - 2 * thickness, thickness, 0])
mirror([1, 0, 0])
side_captive_nuts(hole_types = [1]);
}
}
}
}
module enclosure_bottom() {
linear_extrude(height = thickness) {
translate([thickness, 0, 0]) {
difference() {
union() {
square([enclosure_wall_to_wall_width - 2 * thickness, enclosure_length_right]);
// front tabs
translate([0, enclosure_length_right, 0])
front_back_tabs();
// left tabs
translate([enclosure_wall_to_wall_width - 2 * thickness, enclosure_length_right - thickness, 0])
mirror([0, 1, 0])
side_tabs(2);
// right tabs
translate([0, enclosure_length_right - thickness, 0])
mirror([0, 1, 0])
mirror([1, 0, 0])
side_tabs(2);
}
// front captive nuts
translate([0, enclosure_length_right, 0])
mirror([0,1,0])
front_back_captive_nuts();
// right captive nuts
translate([0, enclosure_length_right - thickness, 0])
mirror([0, 1, 0])
side_captive_nuts(hole_types = [1]);
// left captive nuts
translate([enclosure_wall_to_wall_width - 2 * thickness, enclosure_length_right - thickness, 0])
mirror([0, 1, 0])
mirror([1, 0, 0])
side_captive_nuts(hole_types = [1]);
}
}
}
}
module enclosure_bottom_etch() {
color([0, 0, 0])
linear_extrude(height=2, center=true) {
translate([captive_nut_inset + m4_nut_length + 1, 1, thickness]) {
text_label([str("rev. ", render_revision), render_date, "github.com/scottbez1/splitflap"]);
}
}
}
module pcb_mounting_holes(slots=false) {
module mounting_hole() {
if (slots) {
hull() {
translate([-pcb_mount_slot_delta, 0]) {
circle(r=pcb_mount_hole_radius, $fn=15);
}
translate([pcb_mount_slot_delta, 0]) {
circle(r=pcb_mount_hole_radius, $fn=15);
}
}
} else {
circle(r=pcb_mount_hole_radius, $fn=15);
}
}
translate([pcb_mount_inset_vertical, pcb_mount_inset_horizontal]) {
mounting_hole();
}
translate([pcb_height - pcb_mount_inset_vertical, pcb_mount_inset_horizontal]) {
mounting_hole();
}
}
module pcb() {
color([0, 0.5, 0]) {
linear_extrude(height=pcb_thickness) {
difference() {
square([pcb_height, pcb_length]);
pcb_mounting_holes(slots=false);
}
}
}
translate([10, 20, pcb_thickness]) {
color([0, 0, 0]) {
cube([16, 8, pcb_connector_height]);
}
}
translate([0, 0, pcb_thickness]) {
translate([pcb_mount_inset_vertical, pcb_mount_inset_horizontal]) {
rotate([180, 0, 0]) {
standard_m4_bolt(nut_distance=thickness+pcb_thickness);
}
}
translate([pcb_height - pcb_mount_inset_vertical, pcb_mount_inset_horizontal]) {
rotate([180, 0, 0]) {
standard_m4_bolt(nut_distance=thickness+pcb_thickness);
}
}
}
}
module split_flap_3d(letter) {
module positioned_front() {
translate([0, front_forward_offset + thickness, -enclosure_height_lower])
rotate([90, 0, 0])
enclosure_front();
}
module positioned_left() {
translate([enclosure_wall_to_wall_width, -enclosure_length + front_forward_offset, -enclosure_height_lower])
rotate([0, -90, 0])
enclosure_left();
}
module positioned_right() {
translate([0, -enclosure_length_right + front_forward_offset, enclosure_height_upper])
rotate([0, 90, 0])
enclosure_right();
}
module positioned_top() {
translate([0, front_forward_offset, enclosure_height_upper - enclosure_vertical_inset])
rotate([180, 0, 0])
enclosure_top();
}
module positioned_bottom() {
translate([0, front_forward_offset - enclosure_length_right, -enclosure_height_lower + enclosure_vertical_inset]) {
enclosure_bottom();
}
}
module positioned_bottom_etch() {
translate([0, front_forward_offset - enclosure_length_right, -enclosure_height_lower + enclosure_vertical_inset]) {
translate([0, 0, thickness]) {
enclosure_bottom_etch();
}
}
}
module positioned_enclosure() {
if (render_enclosure == 2) {
color(assembly_color1)
positioned_front();
color(assembly_color2)
positioned_left();
color(assembly_color2)
positioned_right();
color(assembly_color3)
positioned_top();
color(assembly_color3)
positioned_bottom();
positioned_bottom_etch();
} else if (render_enclosure == 1) {
%positioned_front();
%positioned_left();
%positioned_right();
%positioned_top();
%positioned_bottom();
%positioned_bottom_etch();
}
}
positioned_enclosure();
if (render_pcb) {
rotate([90, 0, 0])
translate([enclosure_wall_to_wall_width - thickness, pcb_reference_horizontal, pcb_reference_vertical])
rotate([0, -90, 0])
pcb();
}
module letter_top_half() {
rotate([-90, 0, 0]) {
rotate([0, 0, 180]) {
linear_extrude(height=0.1, center=true) {
translate([-flap_width / 2, -flap_pin_width/2]) {
difference() {
text(text=letter, size=letter_height, font="RobotoCondensed", halign="center", valign="center");
translate([-flap_width, -flap_height - eps]) {
square([2 * flap_width, flap_height]);
}
}
}
}
}
}
}
module letter_bottom_half() {
rotate([-90, 0, 0]) {
rotate([0, 0, 180]) {
linear_extrude(height=0.1, center=true) {
translate([-flap_width / 2, flap_pin_width/2]) {
difference() {
text(text=letter, size=letter_height, font="RobotoCondensed", halign="center", valign="center");
translate([-flap_width, eps]) {
square([2 * flap_width, flap_height]);
}
}
}
}
}
}
}
translate([spool_width_slop/2 + thickness, 0, 0]) {
// Flap area
if (render_flaps > 0) {
echo(flap_exclusion_radius=exclusion_radius);
rotate([0, 90, 0]) {
if (render_flap_area >= 1) {
translate([0, 0, thickness]) {
cylinder(r=exclusion_radius, h=flap_width - 2*thickness);
}
}
if (render_flap_area >= 2) {
translate([0, 0, thickness + (flap_width - 2*thickness)/4]) {
cylinder(r=outer_exclusion_radius, h=(flap_width - 2*thickness)/2);
}
}
}
translate([flap_width_slop/2, 0, 0]) {
// Collapsed flaps on the top
for (i=[0:num_flaps/2 - 1]) {
if (i == 0 || render_flaps == 2) {
rotate([360/num_flaps * i, 0, 0]) translated_flap();
}
if (i == 0) {
color([0,0,0]) {
translate([0, flap_pitch_radius + flap_thickness/2, 0]) {
letter_top_half();
}
}
}
}
for (i=[1:num_flaps/2]) {
angle = -360/num_flaps*i;
translate([0, flap_pitch_radius*cos(angle), flap_pitch_radius * sin(angle)]) {
if (i == 1 || render_flaps == 2) {
rotate([-90, 0, 0]) {
flap();
}
}
if (i == 1) {
color([0,0,0]) {
translate([0, flap_thickness/2, 0]) {
letter_bottom_half();
}
}
}
}
}
}
}
spool_struts();
// motor spool
color(assembly_color) {
translate([flap_width + flap_width_slop - thickness + 5*spool_horizontal_explosion, 0, 0]) {
rotate([0, 90, 0]) {
flap_spool_complete(motor_shaft=true, ir_detector_hole=true);
}
}
}
color(assembly_color1) {
translate([thickness - 3*spool_horizontal_explosion, 0, 0]) {
rotate([0, 90, 0]) {
spool_retaining_wall(m4_bolt_hole=true);
}
}
}
color(assembly_color) {
translate([-5*spool_horizontal_explosion, 0, 0]) {
rotate([0, 90, 0]) {
flap_spool_complete(captive_nut=true);
}
}
}
translate([thickness * 2, 0, 0]) {
rotate([0, -90, 0]) {
standard_m4_bolt(nut_distance=thickness + 7*spool_horizontal_explosion);
}
}
}
if (render_motor) {
translate([enclosure_wall_to_wall_width - thickness - 28byj48_bracket_thickness, 0, 0]) {
rotate([-90, 0, 0]) {
rotate([0, -90, 0]) {
Stepper28BYJ48();
}
translate([0, -motor_mount_shaft_offset, 0]) {
translate([0, 0, -motor_mount_separation/2]) {
rotate([0, 90, 0]) {
rotate([0, 0, 90]) {
standard_m4_bolt(nut_distance=thickness+28byj48_bracket_thickness);
}
}
}
translate([0, 0, motor_mount_separation/2]) {
rotate([0, 90, 0]) {
rotate([0, 0, 90]) {
standard_m4_bolt(nut_distance=thickness+28byj48_bracket_thickness);
}
}
}
}
}
}
}
}
module laser_etch() {
if (render_etch || render_index == -1) {
children();
}
}
if (render_3d) {
for (i = [0 : render_units - 1]) {
translate([-enclosure_width/2 + (-(render_units-1) / 2 + i)*(enclosure_width + render_unit_separation), 0, 0])
split_flap_3d(render_letters[render_units - 1 - i]);
}
} else {
sp = 5;
projection_renderer(render_index=render_index, kerf_width=kerf_width) {
translate([0, 0])
enclosure_left();
translate([0, enclosure_length + kerf_width])
enclosure_right();
translate([0, enclosure_length + kerf_width + enclosure_length_right + kerf_width + enclosure_width - enclosure_horizontal_inset])
rotate([0, 0, -90])
enclosure_front();
translate([enclosure_height + kerf_width + enclosure_length_right, enclosure_length + kerf_width + enclosure_length_right + kerf_width ])
rotate([0, 0, 90])
enclosure_top();
translate([enclosure_height + kerf_width, enclosure_length])
rotate([0, 0, -90])
enclosure_bottom();
laser_etch()
translate([enclosure_height + kerf_width, enclosure_length, thickness])
rotate([0, 0, -90])
enclosure_bottom_etch();
// Spool struts 2x2 above left/right sides
spool_strut_y_off = enclosure_length + enclosure_length_right + enclosure_width + sp + spool_strut_width / 2;
// Spool struts cut out of left/right sides
translate([thickness*2 + 5, enclosure_length + kerf_width + enclosure_length_right - spool_strut_width/2 - 3, thickness])
spool_strut();
translate([2, 32, thickness])
spool_strut();
translate([35, spool_strut_width/2 + 3, thickness])
spool_strut();
translate([91, 22, thickness])
spool_strut();
// Flap spools in window
flap_spool_y_off = enclosure_length + kerf_width + enclosure_length_right + kerf_width + enclosure_width - front_window_right_inset - enclosure_horizontal_inset - front_window_width/2;
flap_spool_x_off = spool_outer_radius + enclosure_height_lower - front_window_lower + kerf_width + 2;
translate([flap_spool_x_off, flap_spool_y_off])
flap_spool_complete(motor_shaft=true, ir_detector_hole=true);
translate([flap_spool_x_off + spool_outer_radius*2 + 2, flap_spool_y_off])
flap_spool_complete(captive_nut=true);
translate([enclosure_height_lower + motor_shaft_offset, enclosure_length - front_forward_offset])
spool_retaining_wall(m4_bolt_hole=true);
}
}