mirror of
https://github.com/nophead/Mendel90.git
synced 2025-01-16 20:38:15 +01:00
first commit
This commit is contained in:
commit
d22174869f
19
README.txt
Normal file
19
README.txt
Normal file
@ -0,0 +1,19 @@
|
||||
Limitations
|
||||
-----------
|
||||
Currently only supports mendel and sturdy machine varients, the huxley version needs more work.
|
||||
Only builds on Windows, using the version of openscad.exe included and the openscad_cl.exe wrapper.
|
||||
|
||||
|
||||
Use
|
||||
---
|
||||
To make all the files for a machine run
|
||||
make_machine.py machine_name
|
||||
|
||||
To make just the bom, sheets or stls run bom.py, sheets.py or stls.py
|
||||
|
||||
machine_name can be mendel or sturdy. To make your own variant copy scad\conf\mendel.scad or scad\conf\sturdy to yourname_config.scad.
|
||||
|
||||
To view the whole machine model open scad\main.scad. It will take about 8 miniutes to render but after that you can pan and zoom it
|
||||
at reasonable speed and changes takes less time to render.
|
||||
|
||||
To view a sub assembly open the inididual scad files. Set the exploded flag in config.scad to make exploded views.
|
10
_canute.bat
Normal file
10
_canute.bat
Normal file
@ -0,0 +1,10 @@
|
||||
|
||||
@ECHO OFF
|
||||
TITLE Canute
|
||||
CALL %TOOLSDRV%\BAT\SYSENV w:
|
||||
SET GNU=1
|
||||
IF ERRORLEVEL 1 GOTO :ERR
|
||||
IF NOT ERRORLEVEL 1 GOTO :DONE
|
||||
:ERR
|
||||
PAUSE
|
||||
:DONE
|
138
bom.py
Normal file
138
bom.py
Normal file
@ -0,0 +1,138 @@
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import shutil
|
||||
|
||||
class BOM():
|
||||
def __init__(self):
|
||||
self.count = 1
|
||||
self.vitamins = {}
|
||||
self.printed = {}
|
||||
self.assemblies = {}
|
||||
|
||||
def add_part(self, s):
|
||||
if s[-4:] == ".stl":
|
||||
parts = self.printed
|
||||
else:
|
||||
parts = self.vitamins
|
||||
if s in parts:
|
||||
parts[s] += 1
|
||||
else:
|
||||
parts[s] = 1
|
||||
|
||||
def add_assembly(self, ass):
|
||||
if ass in self.assemblies:
|
||||
self.assemblies[ass].count += 1
|
||||
else:
|
||||
self.assemblies[ass] = BOM()
|
||||
|
||||
def make_name(self, ass):
|
||||
if self.count == 1:
|
||||
return ass
|
||||
return ass.replace("assembly", "assemblies")
|
||||
|
||||
def print_bom(self, breakdown, file = None):
|
||||
if breakdown:
|
||||
longest = 0
|
||||
for ass in self.assemblies:
|
||||
name = ass.replace("_assembly","")
|
||||
longest = max(longest, len(name))
|
||||
for i in range(longest):
|
||||
print >> file, " " * 14,
|
||||
for ass in sorted(self.assemblies):
|
||||
name = ass.replace("_assembly","").replace("_"," ")
|
||||
if longest - i > len(name):
|
||||
print >> file, " ",
|
||||
else:
|
||||
print >> file, " %s" % name[i - (longest - len(name))],
|
||||
print >> file
|
||||
|
||||
print >> file, "Vitamins:"
|
||||
for part in sorted(self.vitamins):
|
||||
if ': ' in part:
|
||||
part_no, description = part.split(': ')
|
||||
else:
|
||||
part_no, description = "", part
|
||||
print >> file, "%3d %-10s" % (self.vitamins[part], part_no),
|
||||
if breakdown:
|
||||
for ass in sorted(self.assemblies):
|
||||
bom = self.assemblies[ass]
|
||||
if part in bom.vitamins:
|
||||
print >> file, "%2d" % bom.vitamins[part],
|
||||
else:
|
||||
print >> file, " ",
|
||||
|
||||
print >> file, description
|
||||
|
||||
print >> file
|
||||
print >> file, "Printed:"
|
||||
for part in sorted(self.printed):
|
||||
print >> file, "%3d" % self.printed[part],
|
||||
if breakdown:
|
||||
print >> file, " " * 10,
|
||||
for ass in sorted(self.assemblies):
|
||||
bom = self.assemblies[ass]
|
||||
if part in bom.printed:
|
||||
print >> file, "%2d" % bom.printed[part],
|
||||
else:
|
||||
print >> file, " ",
|
||||
|
||||
print >> file, part
|
||||
|
||||
print >> file
|
||||
if self.assemblies:
|
||||
print >> file, "Sub-assemblies:"
|
||||
for ass in sorted(self.assemblies):
|
||||
print >> file, "%3d %s" % (self.assemblies[ass].count, self.assemblies[ass].make_name(ass))
|
||||
|
||||
def boms(machine):
|
||||
bom_dir = machine + "/bom"
|
||||
if os.path.isdir(bom_dir):
|
||||
shutil.rmtree(bom_dir)
|
||||
os.makedirs(bom_dir)
|
||||
|
||||
f = open("scad/conf/machine.scad","wt")
|
||||
f. write("include <%s_config.scad>\n" % machine);
|
||||
f.close()
|
||||
|
||||
subprocess.call(["openscad_cl", "-o", "dummy.stl", "scad/bom.scad"])
|
||||
print "Generating bom ...",
|
||||
|
||||
main = BOM()
|
||||
stack = []
|
||||
|
||||
for line in open("openscad.log"):
|
||||
if line[:7] == 'ECHO: "':
|
||||
s = line[7:-2]
|
||||
if s[-1] == '/':
|
||||
ass = s[:-1]
|
||||
if stack:
|
||||
main.assemblies[stack[-1]].add_assembly(ass) #add to nested BOM
|
||||
stack.append(ass)
|
||||
main.add_assembly(ass) #add to flat BOM
|
||||
else:
|
||||
if s[0] == '/':
|
||||
if s[1:] != stack[-1]:
|
||||
raise Exception, "Mismatched assembly " + s[1:] + str(stack)
|
||||
stack.pop()
|
||||
else:
|
||||
main.add_part(s)
|
||||
main.assemblies[stack[-1]].add_part(s)
|
||||
|
||||
main.print_bom(True, open(bom_dir + "/bom.txt","wt"))
|
||||
|
||||
for ass in sorted(main.assemblies):
|
||||
f = open(bom_dir + "/" + ass + ".txt", "wt");
|
||||
bom = main.assemblies[ass]
|
||||
print >> f, bom.make_name(ass) + ":"
|
||||
bom.print_bom(False, f)
|
||||
f.close()
|
||||
|
||||
print " done"
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) > 1:
|
||||
boms(sys.argv[1])
|
||||
else:
|
||||
print "usage: bom [mendel|sturdy|your_machine]"
|
||||
sys.exit(1)
|
11
credits.txt
Normal file
11
credits.txt
Normal file
@ -0,0 +1,11 @@
|
||||
Fan model based on http://www.thingiverse.com/thing:8063 by MiseryBot, CC license.
|
||||
|
||||
Sangunino model http://www.thingiverse.com/thing:18606 by ax_the_b, CC license.
|
||||
|
||||
Spring taken from openscad example 20
|
||||
|
||||
x-end.scad and wade.scad uses some elements of the Prusa ones by Josef Prusa, GPL license.
|
||||
|
||||
z_couplings orginally based on http://www.thingiverse.com/thing:7153 by Griffin_Nicoll, GPL license.
|
||||
|
||||
Bearing holders originally based on http://www.thingiverse.com/thing:7755 by Jolijar, CC license.
|
132
dxf.py
Normal file
132
dxf.py
Normal file
@ -0,0 +1,132 @@
|
||||
from math import *
|
||||
from svg import *
|
||||
|
||||
def parse_dxf(fn):
|
||||
f = open(fn)
|
||||
|
||||
# skip to entities section
|
||||
s = f.next()
|
||||
while s.strip() != 'ENTITIES':
|
||||
s = f.next()
|
||||
|
||||
in_line = False
|
||||
in_circle = False
|
||||
|
||||
pt_list = []
|
||||
cir_list = []
|
||||
|
||||
for line in f:
|
||||
line = line.strip()
|
||||
# In ENTITIES section, iteration can cease when ENDSEC is reached
|
||||
if line == 'ENDSEC':
|
||||
break
|
||||
|
||||
elif in_line:
|
||||
keys = dict.fromkeys(['8','10','20','30','11','21','31'], 0.0)
|
||||
while line != '0':
|
||||
if line in keys:
|
||||
keys[line] = float(f.next().strip())
|
||||
line = f.next().strip()
|
||||
pt_list.append( ((keys['10'], keys['20']), (keys['11'], keys['21'])) )
|
||||
in_line = False
|
||||
|
||||
elif in_circle:
|
||||
keys = dict.fromkeys(['8','10','20','30','40'], 0.0)
|
||||
while line != '0':
|
||||
if line in keys:
|
||||
keys[line] = float(f.next().strip())
|
||||
line = f.next().strip()
|
||||
cir_list.append([[keys['10'], keys['20'], keys['30']], keys['40']])
|
||||
in_circle = False
|
||||
|
||||
else:
|
||||
if line == 'LINE':
|
||||
in_line = True
|
||||
elif line == 'CIRCLE' or line == 'ARC':
|
||||
in_circle = True
|
||||
f.close()
|
||||
return pt_list, cir_list
|
||||
|
||||
def is_circle(path):
|
||||
points = len(path)
|
||||
if points < 9:
|
||||
return None
|
||||
for i in range(points) :
|
||||
p1 = path[0]
|
||||
p2 = path[int(points /3 )]
|
||||
p3 = path[int(points * 2 / 3)]
|
||||
if p1[0] != p2[0] and p2[0] != p3[0]:
|
||||
ma = (p2[1] - p1[1]) / (p2[0] - p1[0])
|
||||
mb = (p3[1] - p2[1]) / (p3[0] - p2[0])
|
||||
if ma == mb:
|
||||
return None
|
||||
x = (ma * mb *(p1[1] - p3[1]) + mb * (p1[0] + p2[0]) - ma * (p2[0] + p3[0])) / (2 * (mb - ma))
|
||||
if ma == 0:
|
||||
y = -(x - (p2[0] + p3[0]) / 2) / mb + (p2[1] + p3[1]) / 2
|
||||
else:
|
||||
y = -(x - (p1[0] + p2[0]) / 2) / ma + (p1[1] + p2[1]) / 2
|
||||
r = sqrt((p1[0] - x) * (p1[0] - x) + (p1[1] - y) * (p1[1] - y))
|
||||
for p in path:
|
||||
if abs(sqrt((p[0] - x) * (p[0] - x) + (p[1] - y) * (p[1] - y)) - r) > 0.1:
|
||||
#print "error too big", abs(sqrt((p[0] - x) * (p[0] - x) + (p[1] - y) * (p[1] - y)) - r), points, 2 * r
|
||||
#print p, path
|
||||
return None
|
||||
return [x,y, 2 * r, points]
|
||||
path = path[1:] + path[:1] #rotate and try again
|
||||
return None
|
||||
|
||||
def dxf_to_svg(fn):
|
||||
ptList, cirList = parse_dxf(fn)
|
||||
|
||||
loops = []
|
||||
for pt1, pt2 in ptList:
|
||||
found = False
|
||||
for i in range(len(loops)):
|
||||
loop = loops[i]
|
||||
p0 = loop[0]
|
||||
p1 = loop[-1]
|
||||
if pt1 == p0:
|
||||
loops[i] = [pt2] + loop; found = True
|
||||
elif pt2 == p0:
|
||||
loops[i] = [pt1] + loop; found = True
|
||||
elif pt1 == p1:
|
||||
loops[i] = loop + [pt2]; found = True
|
||||
elif pt2 == p1:
|
||||
loops[i] = loop + [pt2]; found = True
|
||||
if not found:
|
||||
loops.append([pt1, pt2])
|
||||
|
||||
xmax = ymax = 0
|
||||
xmin = ymin = 99999999
|
||||
for loop in loops:
|
||||
if len(loop) < 4 or loop[0] != loop[-1]:
|
||||
raise Exception, "loop not closed " + str(loop)
|
||||
for point in loop:
|
||||
if point[0] > xmax: xmax = point[0]
|
||||
if point[0] < xmin: xmin = point[0]
|
||||
if point[1] > ymax: ymax = point[1]
|
||||
if point[1] < ymin: ymin = point[1]
|
||||
|
||||
def p(x, y): return (x - xmin, ymax - y)
|
||||
|
||||
print xmin, ymin, xmax, ymax
|
||||
scene = Scene(fn[:-4], ceil(ymax - ymin + 10), ceil(xmax - xmin + 10))
|
||||
for loop in loops:
|
||||
circle = is_circle(loop)
|
||||
if circle:
|
||||
x ,y, d, n = circle
|
||||
scene.add(Circle(p(x, y), d / 2, (255,0,0)))
|
||||
scene.add(Line( p(x + d, y), p(x - d, y) ))
|
||||
scene.add(Line( p(x, y + d), p(x, y - d) ))
|
||||
scene.add(Text( p(x + d / 2, y + d / 2), str(round(d,1)) ))
|
||||
#scene.add(Text( p(x + d, y - d - 3), "[%0.1f, %0.1f]" % (x, y), 12 ))
|
||||
else:
|
||||
last = loop[-1]
|
||||
for point in loop:
|
||||
scene.add(Line(p(last[0],last[1]),p(point[0],point[1])))
|
||||
last = point
|
||||
scene.write_svg()
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
dxf_to_svg(sys.argv[1])
|
37130
imported_stls/39t17p.stl
Normal file
37130
imported_stls/39t17p.stl
Normal file
File diff suppressed because it is too large
Load Diff
BIN
imported_stls/pulley.stl
Normal file
BIN
imported_stls/pulley.stl
Normal file
Binary file not shown.
4258
imported_stls/sanguinololu.stl
Normal file
4258
imported_stls/sanguinololu.stl
Normal file
File diff suppressed because it is too large
Load Diff
41988
imported_stls/wades_gear.stl
Normal file
41988
imported_stls/wades_gear.stl
Normal file
File diff suppressed because it is too large
Load Diff
17
make_machine.py
Normal file
17
make_machine.py
Normal file
@ -0,0 +1,17 @@
|
||||
import sys
|
||||
|
||||
from bom import boms
|
||||
from sheets import sheets
|
||||
from stls import stls
|
||||
|
||||
def make_machine(machine):
|
||||
boms(machine)
|
||||
sheets(machine)
|
||||
stls(machine)
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) > 1:
|
||||
make_machine(sys.argv[1])
|
||||
else:
|
||||
print "usage: make_machine [mendel|sturdy|your_machine]"
|
||||
sys.exit(1)
|
BIN
openscad.exe
Normal file
BIN
openscad.exe
Normal file
Binary file not shown.
BIN
openscad_cl.exe
Normal file
BIN
openscad_cl.exe
Normal file
Binary file not shown.
221
scad/bar-clamp.scad
Normal file
221
scad/bar-clamp.scad
Normal file
@ -0,0 +1,221 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// Rail supports
|
||||
//
|
||||
include <conf/config.scad>
|
||||
include <positions.scad>
|
||||
|
||||
nut_trap_meat = 4; // how much plastic above the nut trap
|
||||
wall = 3;
|
||||
tab_height = 5;
|
||||
|
||||
function bar_clamp_inner_rad(d) = d / 2;
|
||||
function bar_clamp_outer_rad(d) = bar_clamp_inner_rad(d) + bar_clamp_band;
|
||||
function bar_clamp_stem(d) = bar_clamp_inner_rad(d) + bar_clamp_outer_rad(d) + bar_clamp_tab - 2;
|
||||
function bar_clamp_length(d) = bar_clamp_tab + bar_clamp_stem(d) + bar_clamp_tab;
|
||||
function bar_rail_offset(d) = bar_clamp_tab + d / 2 + bar_clamp_band;
|
||||
|
||||
function bar_clamp_switch_y_offset() = 12;
|
||||
|
||||
function y_switch_x(w) = -w / 2 - bar_clamp_switch_y_offset();
|
||||
function y_switch_y(d) = bar_clamp_inner_rad(d) + microswitch_thickness() / 2 + 2;
|
||||
function y_switch_z(h) = h + microswitch_button_x_offset();
|
||||
|
||||
function bar_clamp_switch_x_offset() = y_switch_y(Y_bar_dia);
|
||||
function bar_clamp_switch_z_offset() = microswitch_button_x_offset();
|
||||
|
||||
module bar_clamp_holes(d)
|
||||
for(y = [bar_rail_offset(d) - bar_clamp_length(d) + 0.5 * bar_clamp_tab,
|
||||
bar_rail_offset(d) - 0.5 * bar_clamp_tab])
|
||||
translate([0, y, 0])
|
||||
child();
|
||||
|
||||
module bar_clamp(d, h, w, switch = false, yaxis = false) {
|
||||
gap = 1.5;
|
||||
inner_rad = bar_clamp_inner_rad(d);
|
||||
outer_rad = bar_clamp_outer_rad(d);
|
||||
stem = bar_clamp_stem(d);
|
||||
length = bar_clamp_length(d);
|
||||
rail_offset = bar_rail_offset(d);
|
||||
|
||||
cavity_l = stem - 2 * wall;
|
||||
cavity_h = h - nut_trap_meat - nut_trap_depth;
|
||||
cavity_w = w - 2 * wall;
|
||||
|
||||
sbracket_length = -y_switch_x(w) + 4;
|
||||
sbracket_thickness = 7;
|
||||
sbracket_height = microswitch_length();
|
||||
|
||||
color([0,1,0]) {
|
||||
translate([0, rail_offset, 0]) {
|
||||
union() {
|
||||
difference() {
|
||||
translate([0,-length/2,0]) rotate([90,0,90]) linear_extrude(height = w, center = true, convexity = 6) {
|
||||
difference() {
|
||||
union() {
|
||||
translate([0, tab_height / 2, 0])
|
||||
square([length, tab_height], center = true); // base
|
||||
translate([0, h / 2, 0])
|
||||
square([stem, h], center = true); // stem
|
||||
translate([(stem/2 - outer_rad), h, 0])
|
||||
circle(r = outer_rad, center = true); // band
|
||||
translate([-stem/2 ,h,0])
|
||||
square([stem - outer_rad, outer_rad]); // band tab
|
||||
|
||||
}
|
||||
translate([(stem/2 - outer_rad), h, 0])
|
||||
poly_circle(r = inner_rad, center = true); // bore
|
||||
|
||||
translate([-rail_offset, h, 0])
|
||||
square([stem, gap]); // gap
|
||||
|
||||
}
|
||||
}
|
||||
//
|
||||
// plastic saving cavity
|
||||
//
|
||||
translate([0, -cavity_l / 2 - bar_clamp_tab - wall, cavity_h / 2 - eta])
|
||||
cube([cavity_w, cavity_l, cavity_h], center = true);
|
||||
//
|
||||
// nut trap
|
||||
//
|
||||
translate([0,-length + 1.5 * bar_clamp_tab,0])
|
||||
rotate([0,0,90])
|
||||
nut_trap(screw_clearance_radius, nut_radius, h - nut_trap_meat, horizontal = true);
|
||||
//
|
||||
// mounting holes
|
||||
//
|
||||
translate([0, -rail_offset, 0])
|
||||
bar_clamp_holes(d)
|
||||
rotate([0,0,90])
|
||||
tearslot( h = 100, r = screw_clearance_radius(frame_screw), center = true, w = 2); // mounting screw
|
||||
|
||||
if(switch && !yaxis)
|
||||
translate([-w / 2 - axis_endstop_clearance,
|
||||
outer_rad + microswitch_thickness() / 2 - rail_offset,
|
||||
h - outer_rad + microswitch_first_hole_x_offset()])
|
||||
rotate([0, 90, 90])
|
||||
microswitch_holes();
|
||||
|
||||
*translate([0,-50,-1]) cube([100,100,100]); // cross section for debug
|
||||
}
|
||||
if(switch && yaxis) { // switch bracket
|
||||
difference() {
|
||||
union() {
|
||||
translate([w / 2 -sbracket_length,
|
||||
y_switch_y(d) + microswitch_thickness() / 2 - rail_offset,
|
||||
y_switch_z(h) - microswitch_button_x_offset() - microswitch_length() / 2])
|
||||
cube([sbracket_length, sbracket_thickness, sbracket_height]);
|
||||
|
||||
translate([w / 2 - eta - sbracket_thickness,
|
||||
y_switch_y(d) - microswitch_thickness() / 2 - rail_offset +0.5,
|
||||
y_switch_z(h) - microswitch_button_x_offset() - microswitch_length() / 2])
|
||||
cube([sbracket_thickness,
|
||||
y_switch_y(d) - outer_rad + microswitch_thickness() / 2 + 1,
|
||||
h - (y_switch_z(h) - microswitch_button_x_offset() - microswitch_length() / 2)]);
|
||||
}
|
||||
translate([y_switch_x(w), y_switch_y(d) - rail_offset, y_switch_z(h)])
|
||||
mirror([0,1,0]) rotate([0, 90, 90])
|
||||
microswitch_holes();
|
||||
|
||||
translate([0, - 0.5 * bar_clamp_tab - 0.5,0]) // screwdriver access
|
||||
rotate([0,0,90])
|
||||
teardrop(h = 100, r = 3, center = true, truncate = false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module bar_clamp_assembly(d, h, w, name, switch = false, yaxis = true) {
|
||||
inner_rad = bar_clamp_inner_rad(d);
|
||||
outer_rad = bar_clamp_outer_rad(d);
|
||||
length = bar_clamp_length(d);
|
||||
rail_offset = bar_rail_offset(d);
|
||||
|
||||
//assembly(name);
|
||||
stl(str(name, switch ? "_switch" : ""));
|
||||
color([0,1,0]) render() bar_clamp(d, h, w, switch, yaxis);
|
||||
//
|
||||
// screw and washer for clamp
|
||||
//
|
||||
translate([0, rail_offset - length + 1.5 * bar_clamp_tab, h + inner_rad + bar_clamp_band])
|
||||
screw_and_washer(cap_screw, screw_longer_than(outer_rad + nut_trap_meat + washer_thickness(washer) + nut_thickness(nut, true)));
|
||||
//
|
||||
// Captive nut
|
||||
//
|
||||
translate([0, rail_offset - length + 1.5 * bar_clamp_tab, h - nut_trap_meat])
|
||||
rotate([180, 0, 90])
|
||||
nut(nut, true);
|
||||
//
|
||||
// mounting screws and washers
|
||||
//
|
||||
for(y = [rail_offset - length + 0.5 * bar_clamp_tab, rail_offset - 0.5 * bar_clamp_tab])
|
||||
translate([0, y, tab_height])
|
||||
if(yaxis)
|
||||
base_screw();
|
||||
else
|
||||
frame_screw(tab_height);
|
||||
//
|
||||
// limit switch
|
||||
//
|
||||
if(switch)
|
||||
if(yaxis)
|
||||
translate([y_switch_x(w), y_switch_y(d), y_switch_z(h)])
|
||||
mirror([0,1,0]) rotate([0, 90, 90]) {
|
||||
microswitch();
|
||||
microswitch_hole_positions()
|
||||
screw_and_washer(No2_screw, 13);
|
||||
}
|
||||
else
|
||||
translate([-w / 2 - axis_endstop_clearance,
|
||||
outer_rad + microswitch_thickness() / 2,
|
||||
h - outer_rad + microswitch_first_hole_x_offset()])
|
||||
rotate([0, 90, 90]) {
|
||||
microswitch();
|
||||
microswitch_hole_positions()
|
||||
screw_and_washer(No2_screw, 13);
|
||||
}
|
||||
|
||||
//end(name);
|
||||
}
|
||||
|
||||
|
||||
module y_bar_clamp_assembly(d, h, w, switch = false) {
|
||||
bar_clamp_assembly(d, h, w, "y_bar_clamp", switch, yaxis = true);
|
||||
}
|
||||
|
||||
module z_bar_clamp_assembly(d, h, w, switch = false) {
|
||||
bar_clamp_assembly(d, h, w, "z_bar_clamp", switch, yaxis = false);
|
||||
}
|
||||
|
||||
//bar_clamp(Z_bar_dia, gantry_setback, bar_clamp_depth, true);
|
||||
|
||||
module y_bar_clamp_stl() translate([0,0,bar_clamp_depth/2]) rotate([0,90,0]) bar_clamp(Y_bar_dia, Y_bar_height, bar_clamp_depth, false, true);
|
||||
module y_bar_clamp_switch_stl() translate([0,0,bar_clamp_depth/2]) rotate([0,90,0]) bar_clamp(Y_bar_dia, Y_bar_height, bar_clamp_depth, true, true);
|
||||
|
||||
module z_bar_clamp_stl() translate([0,0,bar_clamp_depth/2]) rotate([0,90,0]) bar_clamp(Z_bar_dia, gantry_setback, bar_clamp_depth, false, false);
|
||||
module z_bar_clamp_switch_stl() translate([0,0,bar_clamp_depth/2]) rotate([0,90,0]) bar_clamp(Z_bar_dia, gantry_setback, bar_clamp_depth, true, false);
|
||||
|
||||
if(0) {
|
||||
z_bar_clamp_switch_stl();
|
||||
translate([gantry_setback + 15, 0, 0]) z_bar_clamp_stl() ;
|
||||
translate([10, 40, 0]) y_bar_clamp_switch_stl();
|
||||
translate([gantry_setback + 25, 40, 0]) y_bar_clamp_stl();
|
||||
translate([gantry_setback + 15, 80, 0]) y_bar_clamp_stl();
|
||||
translate([0, 80, 0]) y_bar_clamp_stl();
|
||||
}
|
||||
else {
|
||||
z_bar_clamp_assembly(Z_bar_dia, gantry_setback, bar_clamp_depth, true);
|
||||
//bar_clamp(Z_bar_dia, gantry_setback, bar_clamp_depth, true, false);
|
||||
|
||||
//translate([30, 0, 0]) y_bar_clamp_assembly(Y_bar_dia, Y_bar_height, bar_clamp_depth, true);
|
||||
//translate([30, 0, 0]) bar_clamp(Y_bar_dia, Y_bar_height, bar_clamp_depth, true, true);
|
||||
|
||||
}
|
60
scad/bearing-holder.scad
Normal file
60
scad/bearing-holder.scad
Normal file
@ -0,0 +1,60 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// Fastens the bearings to the Y-carriage
|
||||
//
|
||||
// Based on a design by Jeffrey Olijar (Jolijar)
|
||||
//
|
||||
include <conf/config.scad>
|
||||
|
||||
wall = 2.5; // wall thickness
|
||||
end_wall = 2.8;
|
||||
clearance = 0.2; // end clearance
|
||||
relief = 0.5; // clearance in the middle to stop the bearing rocking
|
||||
ziptie_clearance = 1;
|
||||
|
||||
ziptie = small_ziptie;
|
||||
|
||||
zipslot_width = ziptie_width(ziptie) + ziptie_clearance;
|
||||
zipslot_tickness = ziptie_thickness(ziptie) + ziptie_clearance;
|
||||
|
||||
function bearing_holder_length(bearing) = bearing[0] + 2 * (end_wall + clearance);
|
||||
function bearing_holder_width(bearing) = bearing[1] + wall * 2;
|
||||
|
||||
function bearing_ziptie_radius(bearing) = bearing[1] / 2 + wall + eta;
|
||||
|
||||
module bearing_holder(bearing, bar_height, populate = false) {
|
||||
bearing_length = bearing[0];
|
||||
bearing_dia = bearing[1];
|
||||
below = 5 * bearing_dia / 15;
|
||||
height = bar_height + bearing_dia/2 - below;
|
||||
offset = below + height / 2 - bearing_dia / 2;
|
||||
fence = 2.5;
|
||||
width = bearing_holder_width(bearing);
|
||||
length = bearing_holder_length(bearing);
|
||||
fence_offset = bearing_dia / 2 - fence + (fence + 1) /2;
|
||||
union(){
|
||||
difference() {
|
||||
translate([0, 0, -offset]) // Basic shape
|
||||
cube(size = [width, length, height], center = true);
|
||||
rotate([90,0,0]) {
|
||||
cylinder(h = length + 1, r = bearing_dia / 2, center=true); // Bearing Cutout
|
||||
cylinder(h = length / 2, r = bearing_dia / 2 + relief, center=true);// releave the center so does not rock
|
||||
tube(h = zipslot_width, ir = bearing_dia / 2 + wall,
|
||||
or = bearing_dia / 2 + wall + zipslot_tickness, fn=64); // ziptie slot
|
||||
|
||||
}
|
||||
}
|
||||
translate([0, (length - end_wall)/ 2, -fence_offset]) cube(size = [width,end_wall,fence + 1], center = true); // Blocks at the end to keep the bearing from sliding out
|
||||
translate([0, -(length - end_wall)/ 2, -fence_offset]) cube(size = [width,end_wall,fence + 1], center = true);
|
||||
}
|
||||
if(populate)
|
||||
rotate([0,0,90])
|
||||
linear_bearing(bearing);
|
||||
}
|
||||
|
||||
bearing_holder(LM8UU, 20);
|
52
scad/bed.scad
Normal file
52
scad/bed.scad
Normal file
@ -0,0 +1,52 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// Bed with glass and support pillars
|
||||
//
|
||||
include <conf/config.scad>
|
||||
|
||||
module bed_assembly() {
|
||||
|
||||
assembly("bed_assembly");
|
||||
|
||||
for(x = [-bed_holes / 2, bed_holes /2]) {
|
||||
translate([x, bed_holes / 2, 0])
|
||||
washer(M3_washer);
|
||||
|
||||
for(y = [-bed_holes / 2, bed_holes /2])
|
||||
translate([x, y, washer_thickness(M3_washer)]) {
|
||||
hex_pillar(bed_pillars);
|
||||
|
||||
translate([0,0, pillar_height(bed_pillars) + pcb_thickness]) {
|
||||
//star_washer(M3_washer);
|
||||
//translate([0,0, washer_thickness(M3_washer)])
|
||||
screw(M3_cap_screw, 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
translate([0, 0, washer_thickness(M3_washer)]) {
|
||||
vitamin(str("BED", bed_width, bed_depth,": PCB bed ", bed_width, " x ", bed_depth));
|
||||
translate([0,0, pillar_height(bed_pillars) + pcb_thickness / 2])
|
||||
color([0.7,0,0]) cube([bed_width, bed_depth, pcb_thickness], center = true);
|
||||
|
||||
translate([0,0, pillar_height(bed_pillars) + pcb_thickness + sheet_thickness(glass) / 2 + eta * 3])
|
||||
sheet(glass, bed_width, bed_depth - 12);
|
||||
|
||||
for(x = [-1, 1])
|
||||
for(y = [-1,1])
|
||||
translate([bed_width / 2 * x,
|
||||
((bed_depth - bulldog_length(small_bulldog)) / 2 - washer_diameter(M3_washer)) * y,
|
||||
pillar_height(bed_pillars) + (pcb_thickness + sheet_thickness(glass))/ 2])
|
||||
rotate([0, 0, 90 + x * 90])
|
||||
bulldog(small_bulldog, pcb_thickness + sheet_thickness(glass));
|
||||
}
|
||||
|
||||
end("bed_assembly");
|
||||
}
|
||||
|
||||
bed_assembly();
|
12
scad/bom.scad
Normal file
12
scad/bom.scad
Normal file
@ -0,0 +1,12 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// A dummy object to make a BOM
|
||||
//
|
||||
use <main.scad>
|
||||
|
||||
machine_assembly();
|
95
scad/cable_clip.scad
Normal file
95
scad/cable_clip.scad
Normal file
@ -0,0 +1,95 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// Cable clips to order
|
||||
//
|
||||
include <conf/config.scad>
|
||||
|
||||
wall = 2;
|
||||
thickness = 5;
|
||||
|
||||
function cable_clip_width(screw) = wall + 2 * screw_clearance_radius(screw) + wall;
|
||||
function cable_clip_height(cable) = max(cable_height(cable) + wall, thickness);
|
||||
function cable_clip_extent(screw, cable) = screw_clearance_radius(screw) + wall + cable_width(cable) + wall;
|
||||
function cable_clip_offset(screw, cable) = screw_clearance_radius(screw) + wall + cable_width(cable) / 2;
|
||||
|
||||
module single_cable_clip(cable, screw, h = 0) {
|
||||
screw_dia = 2 * screw_clearance_radius(screw);
|
||||
height = cable_clip_width(screw);
|
||||
depth = h ? h : cable_height(cable) + wall;
|
||||
width = wall + cable_width(cable) + wall + screw_dia + wall;
|
||||
hole_x = wall + cable_width(cable) + wall + screw_dia / 2;
|
||||
rad = min(wall + cable_wire_size(cable) / 2, depth / 2);
|
||||
translate([-hole_x, 0, 0]) difference() {
|
||||
linear_extrude(height = height)
|
||||
hull() {
|
||||
square([width, 1]);
|
||||
|
||||
translate([width - 1, 0])
|
||||
square([1, depth]);
|
||||
|
||||
translate([rad, depth - rad])
|
||||
circle(r = rad);
|
||||
}
|
||||
translate([wall + cable_width(cable) / 2, 0, 0])
|
||||
rounded_rectangle([cable_width(cable), cable_height(cable) * 2], cable_wire_size(cable) / 2, center = true);
|
||||
|
||||
translate([hole_x, depth / 2, height / 2])
|
||||
rotate([90,0,0])
|
||||
teardrop_plus(h = depth + 1, r = screw_dia / 2, center = true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module double_cable_clip(cable1, cable2, screw_dia) {
|
||||
h = max(cable_clip_height(cable1), cable_clip_height(cable2));
|
||||
union() {
|
||||
single_cable_clip(cable1, screw_dia, h);
|
||||
mirror([1,0,0]) single_cable_clip(cable2, screw_dia, h);
|
||||
}
|
||||
}
|
||||
|
||||
module cable_clip(screw, cable1, cable2 = 0) {
|
||||
if(cable2) {
|
||||
stl(str("cable_clip_", cable1[2], cable2[2]));
|
||||
double_cable_clip(cable1, cable2, screw);
|
||||
}
|
||||
else {
|
||||
stl(str("cable_clip_",2 * screw_radius(screw), cable1[2]));
|
||||
single_cable_clip(cable1, screw);
|
||||
}
|
||||
}
|
||||
|
||||
module cable_clip_assembly(screw, screw_length, cable1, cable2 = 0) {
|
||||
color([1,0,0]) render() translate([0, cable_clip_width(screw) / 2, 0]) rotate([90, 0, 0])
|
||||
cable_clip(screw, cable1, cable2);
|
||||
|
||||
translate([0, 0, max(cable_clip_height(cable1), cable_clip_height(cable2))])
|
||||
screw_and_washer(screw, screw_length);
|
||||
}
|
||||
|
||||
module cable_clip_AB_stl() cable_clip(base_clip_screw, endstop_wires, motor_wires);
|
||||
module cable_clip_AD_stl() cable_clip(frame_clip_screw, endstop_wires, fan_motor_wires);
|
||||
module cable_clip_CA_stl() cable_clip(base_clip_screw, thermistor_wires, bed_wires);
|
||||
|
||||
spacing = cable_clip_height(motor_wires) + 1;
|
||||
|
||||
if(1)
|
||||
cable_clip_assembly(base_clip_screw, base_screw_length, endstop_wires, motor_wires);
|
||||
else {
|
||||
translate([0, -cable_clip_height(bed_wires) - 1, 0])
|
||||
cable_clip(base_clip_screw, thermistor_wires, bed_wires);
|
||||
|
||||
for(i=[0:1])
|
||||
translate([0, spacing * i, 0])
|
||||
cable_clip(base_clip_screw, endstop_wires, motor_wires);
|
||||
|
||||
for(i=[2:3])
|
||||
translate([0, spacing * i, 0])
|
||||
cable_clip(frame_clip_screw, endstop_wires, fan_motor_wires);
|
||||
|
||||
}
|
34
scad/cal.scad
Normal file
34
scad/cal.scad
Normal file
@ -0,0 +1,34 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// A test object for calibration
|
||||
//
|
||||
include <conf/config.scad>
|
||||
|
||||
module cal() {
|
||||
difference() {
|
||||
union() {
|
||||
cube([10,40,5]);
|
||||
cube([40,10,6]);
|
||||
cube([20,20,10]);
|
||||
translate([10, 10])
|
||||
cylinder(r = 10, h = 15);
|
||||
}
|
||||
translate([10,10,15])
|
||||
nut_trap(Z_screw_dia / 2, Z_nut_radius, Z_nut_depth);
|
||||
|
||||
translate([5,30,5])
|
||||
rotate([0,0,90])
|
||||
nut_trap(M3_clearance_radius, M3_nut_radius, M3_nut_trap_depth);
|
||||
|
||||
translate([30,5,6])
|
||||
nut_trap(M4_clearance_radius, M4_nut_radius, M4_nut_trap_depth);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
cal();
|
148
scad/conf/config.scad
Normal file
148
scad/conf/config.scad
Normal file
@ -0,0 +1,148 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// Configuration file
|
||||
//
|
||||
bom = 2; // 0 no bom, 1 assemblies and stls, 2 vitamins as well
|
||||
exploded = false; // true for exploded view
|
||||
eta = 0.01; // small fudge factor to stop CSG barfing on coincident faces.
|
||||
$fa = 5;
|
||||
$fs = 0.5;
|
||||
//
|
||||
// Hole sizes
|
||||
//
|
||||
No2_pilot_radius = 1.7 / 2; // self tapper into ABS
|
||||
No4_pilot_radius = 2.0 / 2; // wood screw into soft wood
|
||||
No6_pilot_radius = 2.0 / 2; // wood screw into soft wood
|
||||
|
||||
No2_clearance_radius = 2.5 / 2;
|
||||
No4_clearance_radius = 3.5 / 2;
|
||||
No6_clearance_radius = 4.0 / 2;
|
||||
|
||||
M2p5_tap_radius = 2.05 / 2;
|
||||
M2p5_clearance_radius= 2.8 / 2; // M2.5
|
||||
|
||||
M3_tap_radius = 2.5 / 2;
|
||||
M3_clearance_radius = 3.3 / 2;
|
||||
M3_nut_radius = 6.5 / 2;
|
||||
M3_nut_trap_depth = 3;
|
||||
|
||||
M4_tap_radius = 3.3 / 2;
|
||||
M4_clearance_radius = 2.2;
|
||||
M4_nut_radius = 8.2 / 2;
|
||||
M4_nut_trap_depth = 4.5;
|
||||
|
||||
M6_tap_radius = 5 / 2;
|
||||
M6_clearance_radius = 6.4 / 2;
|
||||
M6_nut_radius = 11.6 / 2;
|
||||
M6_nut_depth = 5;
|
||||
|
||||
M8_tap_radius = 6.75 / 2;
|
||||
M8_clearance_radius = 8.4 / 2;
|
||||
M8_nut_radius = 15.4 / 2;
|
||||
M8_nut_depth = 6.5;
|
||||
|
||||
layer_height = 0.4;
|
||||
filament_width = layer_height * 1.5;
|
||||
min_wall = 2 * filament_width + eta;
|
||||
|
||||
pcb_thickness = 1.6;
|
||||
|
||||
include <utils.scad>
|
||||
include <vitamins.scad>
|
||||
|
||||
endstop_wires = [2, 1.4, "A"]; // 7 strands of 0.2
|
||||
motor_wires = [4, 1.4, "B"];
|
||||
bed_wires = [2, 2.8, "C"]; // 13A mains cable
|
||||
fan_motor_wires = [6, 1.4, "D"]; // fan and motor wires along top of gantry
|
||||
thermistor_wires = endstop_wires;
|
||||
|
||||
endstop_wires_hole_radius = wire_hole_radius(endstop_wires);
|
||||
motor_wires_hole_radius = wire_hole_radius(motor_wires);
|
||||
fan_motor_wires_hole_radius = wire_hole_radius(fan_motor_wires);
|
||||
bed_wires_hole_radius = wire_hole_radius(bed_wires);
|
||||
thermistor_wires_hole_radius = wire_hole_radius(thermistor_wires);
|
||||
|
||||
include <machine.scad> // this file is generated from the command line parameter to include one of the machine configs
|
||||
|
||||
screw_clearance_radius = screw_clearance_radius(cap_screw);
|
||||
nut = screw_nut(cap_screw);
|
||||
nut_radius = nut_radius(nut);
|
||||
nut_trap_depth = nut_trap_depth(nut);
|
||||
washer = screw_washer(cap_screw);
|
||||
|
||||
bearing_clamp_tab = washer_diameter(washer) + 2; // how much the lugs stick out and their width
|
||||
bearing_clamp_tab_height = 4; // thickness of the lugs
|
||||
|
||||
hole_edge_clearance = 5; // how close a hole can be to the edge of a sheet
|
||||
base_clearance = 2; // how close we get to the edge of the base
|
||||
axis_endstop_clearance = 2; // how close we get to the end of an axis
|
||||
X_carriage_clearance = 2; // how close the X carriage is to the XZ plane
|
||||
// how close the Y carriage is to the window in the XZ plane
|
||||
Y_carriage_clearance = 2 + bulldog_handle_length(small_bulldog) - (Y_carriage_width - bed_width) / 2;
|
||||
Z_clearance = 10; // How close the top of the object gets to the gantry
|
||||
belt_clearance = 0.2; // clearance of belt clamp slots
|
||||
|
||||
pulley_inner_radius = (14.4 / 2) - belt_thickness(T5x6); // measured from outer diameter
|
||||
|
||||
|
||||
X_bar_dia = X_bearings[2]; // rod sizes to match the bearings
|
||||
Y_bar_dia = Y_bearings[2];
|
||||
Z_bar_dia = Z_bearings[2];
|
||||
|
||||
Y_idler_bearing = BB624;
|
||||
X_idler_bearing = BB624;
|
||||
|
||||
extruder_ways = 4 + 4 + 2 + 1 + 1; // motor + heater(x2) + thermistor + probe + fan = 12
|
||||
x_end_ways = extruder_ways + 4 + 2 + 2; // motor plus limit switch and two guards = 20
|
||||
bed_ways = 20 + 2; // ten each way for the current plus a thermistor
|
||||
|
||||
function z_bar_offset() = round(NEMA_width(Z_motor)) / 2;
|
||||
|
||||
base_screw = sheet_is_soft(base) ? frame_soft_screw : frame_thick_screw;
|
||||
base_screw_length = screw_shorter_than(sheet_thickness(base) + 5 + 2 * washer_thickness(screw_washer(base_screw)));
|
||||
|
||||
base_clip_screw = base_screw;
|
||||
base_clip_screw_length = base_screw_length;
|
||||
|
||||
frame_screw = sheet_is_soft(frame) ? frame_soft_screw : frame_nuts ? frame_thin_screw : frame_thick_screw;
|
||||
frame_clip_screw = frame_screw;
|
||||
|
||||
frame_screw_length = frame_nuts ? screw_longer_than(sheet_thickness(frame) + 5 + 2 * washer_thickness(screw_washer(frame_screw)) +
|
||||
nut_thickness(screw_nut(frame_screw), true))
|
||||
: screw_shorter_than(sheet_thickness(frame) + 5 + 2 * washer_thickness(screw_washer(frame_screw)));
|
||||
frame_clip_screw_length = frame_screw_length;
|
||||
|
||||
echo("base screw length", base_screw_length);
|
||||
echo("frame screw length",frame_screw_length);
|
||||
|
||||
|
||||
module frame_screw(thickness) {
|
||||
screw_and_washer(frame_screw, frame_screw_length, !frame_nuts);
|
||||
if(frame_nuts)
|
||||
translate([0, 0, -sheet_thickness(frame) - thickness])
|
||||
rotate([180, 0, 0])
|
||||
nut_and_washer(screw_nut(frame_screw), true);
|
||||
}
|
||||
|
||||
module frame_screw_hole() {
|
||||
cylinder(r = frame_nuts ? screw_clearance_radius(frame_screw) :
|
||||
screw_pilot_hole(frame_screw), h = 100, center = true);
|
||||
|
||||
}
|
||||
|
||||
module base_screw() {
|
||||
screw_and_washer(base_screw, base_screw_length, true);
|
||||
}
|
||||
|
||||
module base_screw_hole() {
|
||||
cylinder(r = screw_pilot_hole(base_screw), h = 100, center = true);
|
||||
}
|
||||
|
||||
bar_clamp_depth = 4 + washer_diameter(screw_washer(base_screw)); // how thick the bar clamps are
|
||||
bar_clamp_tab = 3 + washer_diameter(screw_washer(base_screw)); // how much the lugs stick out
|
||||
bar_clamp_band = 3; // the thickness of the strap that clamps the bar.
|
73
scad/conf/huxley_config.scad
Normal file
73
scad/conf/huxley_config.scad
Normal file
@ -0,0 +1,73 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// Configuration file
|
||||
//
|
||||
echo("Huxley:");
|
||||
Z_bearings = LM6UU;
|
||||
Y_bearings = LM6UU;
|
||||
X_bearings = LM6UU;
|
||||
|
||||
X_motor = NEMA14;
|
||||
Y_motor = NEMA14;
|
||||
Z_motor = NEMA14;
|
||||
|
||||
X_travel = 140;
|
||||
Y_travel = 140;
|
||||
Z_travel = 110;
|
||||
|
||||
bed_depth = 150;
|
||||
bed_width = 150;
|
||||
bed_pillars = M3x20_pillar;
|
||||
bed_thickness = 1.6 + sheet_thickness(glass); // PCB heater plus glass sheet
|
||||
bed_holes = 146;
|
||||
|
||||
base = PMMA10; // Sheet material used for the base. Needs to be thick enough to screw into.
|
||||
base_corners = 50;
|
||||
|
||||
frame = PMMA6;
|
||||
frame_corners = 25;
|
||||
frame_nuts = false;
|
||||
|
||||
case_fan = fan80x38;
|
||||
|
||||
single_piece_frame = true;
|
||||
stays_from_window = false;
|
||||
|
||||
Y_carriage = PMMA6;
|
||||
|
||||
extruder_width = 30; // actually 28 but offset
|
||||
nozzle_x_offset = 16; // offset from centre of the extruder
|
||||
nozzle_length = 50; // from base of extruder to nozzle tip
|
||||
|
||||
X_belt = T5x6;
|
||||
Y_belt = T5x6;
|
||||
motor_shaft = 5;
|
||||
Z_screw_dia = 6; // Studding for Z axis
|
||||
|
||||
Y_carriage_depth = bed_depth + 10;
|
||||
Y_carriage_width = bed_width + 10;
|
||||
|
||||
Z_nut_radius = M6_nut_radius;
|
||||
Z_nut_depth = M6_nut_depth;
|
||||
Z_nut = M6_nut;
|
||||
//
|
||||
// Default screw use where size doesn't matter
|
||||
//
|
||||
cap_screw = M3_cap_screw;
|
||||
hex_screw = M3_hex_screw;
|
||||
//
|
||||
// Screw for the frame and base
|
||||
//
|
||||
frame_soft_screw = No4_screw; // Used when sheet material is soft, e.g. wood
|
||||
frame_thin_screw = M3_cap_screw; // Used with nuts when sheets are thin
|
||||
frame_thick_screw = M3_pan_screw; // Used with tapped holes when sheets are thick and hard, e.g. plastic or metal
|
||||
//
|
||||
// Feature sizes
|
||||
//
|
||||
default_wall = 3;
|
||||
thick_wall = 3;
|
76
scad/conf/mendel_config.scad
Normal file
76
scad/conf/mendel_config.scad
Normal file
@ -0,0 +1,76 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// Configuration file
|
||||
//
|
||||
echo("Mendel:");
|
||||
Z_bearings = LM8UU;
|
||||
Y_bearings = LM8UU;
|
||||
X_bearings = LM8UU;
|
||||
|
||||
X_motor = NEMA17;
|
||||
Y_motor = NEMA17;
|
||||
Z_motor = NEMA17;
|
||||
|
||||
X_travel = 200;
|
||||
Y_travel = 200;
|
||||
Z_travel = 140;
|
||||
|
||||
bed_depth = 214;
|
||||
bed_width = 214;
|
||||
bed_pillars = M3x20_pillar;
|
||||
bed_thickness = 1.6 + sheet_thickness(glass); // PCB heater plus glass sheet
|
||||
bed_holes = 209;
|
||||
|
||||
base = PMMA10; // Sheet material used for the base. Needs to be thick enough to screw into.
|
||||
base_corners = 50;
|
||||
|
||||
frame = PMMA6;
|
||||
frame_corners = 25;
|
||||
frame_nuts = false;
|
||||
|
||||
case_fan = fan80x38;
|
||||
psu = KY240W;
|
||||
|
||||
single_piece_frame = true;
|
||||
stays_from_window = false;
|
||||
|
||||
Y_carriage = PMMA6;
|
||||
|
||||
extruder_width = 30; // actually 28 but offset
|
||||
nozzle_x_offset = 16; // offset from centre of the extruder
|
||||
nozzle_length = 50; // from base of extruder to nozzle tip
|
||||
|
||||
X_belt = T5x6;
|
||||
Y_belt = T5x6;
|
||||
|
||||
motor_shaft = 5;
|
||||
Z_screw_dia = 8; // Studding for Z axis
|
||||
|
||||
Y_carriage_depth = bed_depth + 10;
|
||||
Y_carriage_width = bed_width + 10;
|
||||
|
||||
Z_nut_radius = M8_nut_radius;
|
||||
Z_nut_depth = M8_nut_depth;
|
||||
Z_nut = M8_nut;
|
||||
|
||||
//
|
||||
// Default screw use where size doesn't matter
|
||||
//
|
||||
cap_screw = M3_cap_screw;
|
||||
hex_screw = M3_hex_screw;
|
||||
//
|
||||
// Screw for the frame and base
|
||||
//
|
||||
frame_soft_screw = No6_screw; // Used when sheet material is soft, e.g. wood
|
||||
frame_thin_screw = M4_cap_screw; // Used with nuts when sheets are thin
|
||||
frame_thick_screw = M4_pan_screw; // Used with tapped holes when sheets are thick and hard, e.g. plastic or metal
|
||||
//
|
||||
// Feature sizes
|
||||
//
|
||||
default_wall = 3;
|
||||
thick_wall = 4;
|
48
scad/conf/positions.scad
Normal file
48
scad/conf/positions.scad
Normal file
@ -0,0 +1,48 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// Work out the positions and size of things
|
||||
//
|
||||
use <y-motor-bracket.scad>
|
||||
use <x-carriage.scad>
|
||||
use <x-end.scad>
|
||||
|
||||
|
||||
Y_carriage_height = y_motor_bracket_height() + X_carriage_clearance + sheet_thickness(Y_carriage) / 2;
|
||||
|
||||
bed_height = Y_carriage_height + sheet_thickness(Y_carriage) / 2 + pillar_height(bed_pillars) + washer_thickness(M3_washer) + bed_thickness;
|
||||
|
||||
Z0 = floor(bed_height + nozzle_length - x_carriage_offset());
|
||||
|
||||
height = Z0 + Z_travel + x_end_height() + bar_clamp_depth + axis_endstop_clearance + base_clearance;
|
||||
|
||||
gantry_thickness = height - max(bed_height + Z_travel + Z_clearance, Y_carriage_depth + 1);
|
||||
|
||||
gantry_setback = X_carriage_clearance + x_carriage_width() / 2;
|
||||
|
||||
Z_bar_spacing = X_travel + x_carriage_length() + 2 * (axis_endstop_clearance + Z_bearings[1] / 2);
|
||||
|
||||
base_width = base_clearance - x_idler_overhang() + Z_bar_spacing -x_motor_overhang() + base_clearance;
|
||||
|
||||
base_depth = Y_travel + Y_carriage_depth + 2 * base_clearance + 2 * axis_endstop_clearance;
|
||||
|
||||
window_width = Y_carriage_width + Y_carriage_clearance * 2;
|
||||
stay_depth = stays_from_window ? window_width / 2 : base_depth / 2 - (gantry_setback + sheet_thickness(frame));
|
||||
stay_height = single_piece_frame && !stays_from_window ? height : height - gantry_thickness - 1;
|
||||
|
||||
idler_end = -base_width / 2 + base_clearance - x_idler_overhang();
|
||||
motor_end = base_width / 2 - base_clearance + x_motor_overhang();
|
||||
X_origin = (idler_end + motor_end) / 2 + nozzle_x_offset;
|
||||
left_w = (base_width - window_width)/2 + X_origin;
|
||||
right_w = (base_width - window_width)/2 - X_origin;
|
||||
|
||||
|
||||
Y_belt_height = y_motor_height() + pulley_inner_radius + belt_thickness(Y_belt);
|
||||
|
||||
Y_bar_height = Y_belt_height;
|
||||
Y_belt_clamp_height = Y_carriage_height - Y_belt_height - sheet_thickness(Y_carriage) / 2;
|
||||
Y_bearing_holder_height = Y_carriage_height - Y_bar_height - sheet_thickness(Y_carriage) / 2;
|
76
scad/conf/sturdy_config.scad
Normal file
76
scad/conf/sturdy_config.scad
Normal file
@ -0,0 +1,76 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// Configuration file
|
||||
//
|
||||
echo("Sturdy:");
|
||||
Z_bearings = LM10UU;
|
||||
Y_bearings = LM10UU;
|
||||
X_bearings = LM10UU;
|
||||
|
||||
X_motor = NEMA17;
|
||||
Y_motor = NEMA17;
|
||||
Z_motor = NEMA17;
|
||||
|
||||
X_travel = 214;
|
||||
Y_travel = 218;
|
||||
Z_travel = 150;
|
||||
|
||||
bed_depth = 214;
|
||||
bed_width = 214;
|
||||
bed_pillars = M3x20_pillar;
|
||||
bed_thickness = 1.6 + sheet_thickness(glass); // PCB heater plus glass sheet
|
||||
bed_holes = 209;
|
||||
|
||||
base = MDF12;
|
||||
base_corners = 0;
|
||||
|
||||
frame = MDF12;
|
||||
frame_corners = 0;
|
||||
frame_nuts = false;
|
||||
|
||||
case_fan = fan80x38;
|
||||
psu = KY240W;
|
||||
|
||||
single_piece_frame = true;
|
||||
stays_from_window = false;
|
||||
|
||||
Y_carriage = DiBond;
|
||||
|
||||
extruder_width = 30; // actually 28 but offset
|
||||
nozzle_x_offset = 16; // offset from centre of the extruder
|
||||
nozzle_length = 50; // from base of extruder to nozzle tip
|
||||
|
||||
X_belt = T5x6;
|
||||
Y_belt = T5x6;
|
||||
|
||||
motor_shaft = 5;
|
||||
Z_screw_dia = 8; // Studding for Z axis
|
||||
|
||||
Y_carriage_depth = bed_depth + 10;
|
||||
Y_carriage_width = bed_width + 10;
|
||||
|
||||
Z_nut_radius = M8_nut_radius;
|
||||
Z_nut_depth = M8_nut_depth;
|
||||
Z_nut = M8_nut;
|
||||
|
||||
//
|
||||
// Default screw use where size doesn't matter
|
||||
//
|
||||
cap_screw = M4_cap_screw;
|
||||
hex_screw = M4_hex_screw;
|
||||
//
|
||||
// Screw for the frame and base
|
||||
//
|
||||
frame_soft_screw = No6_screw; // Used when sheet material is soft, e.g. wood
|
||||
frame_thin_screw = M4_cap_screw; // Used with nuts when sheets are thin
|
||||
frame_thick_screw = M4_pan_screw; // Used with tapped holes when sheets are thick and hard, e.g. plastic or metal
|
||||
//
|
||||
// Feature sizes
|
||||
//
|
||||
default_wall = 4;
|
||||
thick_wall = 4;
|
119
scad/conf/utils.scad
Normal file
119
scad/conf/utils.scad
Normal file
@ -0,0 +1,119 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// Utilities
|
||||
//
|
||||
include <../utils/bom.scad>
|
||||
include <../utils/polyholes.scad>
|
||||
include <../utils/teardrops.scad>
|
||||
include <../utils/cables.scad>
|
||||
|
||||
module slot(h, r, l, center = true)
|
||||
linear_extrude(height = h, convexity = 6, center = center)
|
||||
hull() {
|
||||
translate([l/2,0,0])
|
||||
circle(r = r, center = true);
|
||||
translate([-l/2,0,0])
|
||||
circle(r = r, center = true);
|
||||
}
|
||||
|
||||
module nut_trap(screw_r, nut_r, depth, horizontal = false) {
|
||||
union() {
|
||||
if(horizontal) {
|
||||
teardrop_plus(r = screw_r, h = 200, center = true);
|
||||
cylinder(r = nut_r + layer_height / 4, h = depth * 2, center = true, $fn = 6);
|
||||
}
|
||||
else {
|
||||
poly_cylinder(r = screw_r, h = 200, center = true);
|
||||
cylinder(r = nut_r, h = depth * 2, center = true, $fn = 6);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module fillet(r, h) {
|
||||
translate([r / 2, r / 2, 0])
|
||||
difference() {
|
||||
cube([r + eta, r + eta, h], center = true);
|
||||
translate([r/2, r/2, 0])
|
||||
cylinder(r = r, h = h + 1, center = true);
|
||||
}
|
||||
}
|
||||
|
||||
module right_triangle(width, height, h, center = true) {
|
||||
linear_extrude(height = h, center = center)
|
||||
polygon(points = [[0,0], [width, 0], [0, height]]);
|
||||
}
|
||||
|
||||
module rounded_square(w, h, r)
|
||||
{
|
||||
union() {
|
||||
square([w - 2 * r, h], center = true);
|
||||
square([w, h - 2 * r], center = true);
|
||||
for(x = [-w/2 + r, w/2 - r])
|
||||
for(y = [-h/2 + r, h/2 - r])
|
||||
translate([x, y])
|
||||
circle(r = r);
|
||||
}
|
||||
}
|
||||
|
||||
module rounded_rectangle(size, r, center = true)
|
||||
{
|
||||
w = size[0];
|
||||
h = size[1];
|
||||
linear_extrude(height = size[2], center = center)
|
||||
rounded_square(size[0], size[1], r);
|
||||
}
|
||||
|
||||
//
|
||||
// Cylinder with rounded ends
|
||||
//
|
||||
module rounded_cylinder(r, h, r2)
|
||||
{
|
||||
rotate_extrude()
|
||||
union() {
|
||||
square([r - r2, h]);
|
||||
square([r, h - r2]);
|
||||
translate([r - r2, h - r2])
|
||||
circle(r = r2);
|
||||
}
|
||||
}
|
||||
|
||||
module sector(r, a, h, , center = true) {
|
||||
linear_extrude(height = h, center = center)
|
||||
intersection() {
|
||||
circle(r = r, center = true);
|
||||
polygon(points = [
|
||||
[0, 0],
|
||||
[2 * r * cos(a / 2), 2 * r * sin(a / 2)],
|
||||
[2 * r * cos(a / 2), -2 * r * sin(a / 2)],
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
module tube(or, ir, h, center = true) {
|
||||
difference() {
|
||||
cylinder(r = or, h = h, center = center);
|
||||
cylinder(r = ir, h = h + 1, center = center);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Exploded view helper
|
||||
//
|
||||
module explode(v, offset = [0,0,0]) {
|
||||
if(exploded) {
|
||||
translate(v)
|
||||
child();
|
||||
render() hull() {
|
||||
sphere(0.2);
|
||||
translate(v + offset)
|
||||
sphere(0.2);
|
||||
}
|
||||
}
|
||||
else
|
||||
child();
|
||||
}
|
48
scad/conf/vitamins.scad
Normal file
48
scad/conf/vitamins.scad
Normal file
@ -0,0 +1,48 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// Off the shelf parts
|
||||
//
|
||||
include <../vitamins/washers.scad>
|
||||
include <../vitamins/nuts.scad>
|
||||
include <../vitamins/screws.scad>
|
||||
include <../vitamins/microswitch.scad>
|
||||
include <../vitamins/stepper-motors.scad>
|
||||
include <../vitamins/ball-bearings.scad>
|
||||
include <../vitamins/linear-bearings.scad>
|
||||
include <../vitamins/pillars.scad>
|
||||
include <../vitamins/belts.scad>
|
||||
include <../vitamins/sheet.scad>
|
||||
include <../vitamins/springs.scad>
|
||||
include <../vitamins/d-connectors.scad>
|
||||
include <../vitamins/ziptie.scad>
|
||||
include <../vitamins/bulldog.scad>
|
||||
include <../vitamins/cable_strip.scad>
|
||||
include <../vitamins/fans.scad>
|
||||
include <../vitamins/electronics.scad>
|
||||
|
||||
|
||||
module rod(d , l) {
|
||||
vitamin(str("RD", d, round(l), ": Smooth rod ", d, " x ", round(l)));
|
||||
color([0.8,0.8,0.8])
|
||||
cylinder(r = d / 2, h = l, center = true);
|
||||
}
|
||||
|
||||
module studding(d , l) {
|
||||
vitamin(str("ST", d, round(l),": Threaded rod ", d, " x ", round(l)));
|
||||
color([0.5,0.5,0.5])
|
||||
cylinder(r = d / 2, h = l, center = true);
|
||||
}
|
||||
|
||||
|
||||
module tubing(od, id, length) {
|
||||
vitamin(str("TB", od, id, length,": Tubing OD ",od, " ID ", id," x ",length));
|
||||
color([0.8, 0.8, 0.8, 0.75]) render() difference() {
|
||||
cylinder(r = od / 2, h = length, center = true);
|
||||
cylinder(r = id / 2, h = length + 1, center = true);
|
||||
}
|
||||
}
|
337
scad/d-motor_bracket.scad
Normal file
337
scad/d-motor_bracket.scad
Normal file
@ -0,0 +1,337 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// Bracket to mount 9 way D type to back of motor
|
||||
//
|
||||
include <conf/config.scad>
|
||||
use <ribbon_clamp.scad>
|
||||
|
||||
connector = DCONN9;
|
||||
|
||||
thickness = 2.4;
|
||||
lid_thickness = 2.4;
|
||||
|
||||
wall = 2;
|
||||
front_thickness = wall + No2_pilot_radius + washer_diameter(M2p5_washer) / 2 + 1;
|
||||
echo(front_thickness);
|
||||
slot_width = 21;
|
||||
inner_slot_width = 15.6;
|
||||
slot_height = 11;
|
||||
face_height = 13;
|
||||
flange_clearance = 0.2;
|
||||
flange_width = d_flange_length(connector) + 2 * flange_clearance;
|
||||
flange_height = d_flange_width(connector) + flange_clearance;
|
||||
flange_thickness = d_flange_thickness(connector) + flange_clearance;
|
||||
|
||||
|
||||
overlap = 5; // how much it overlaps the side of the motor
|
||||
length = overlap + thickness + 20;
|
||||
height = slot_height / 2 + face_height / 2 + thickness;
|
||||
d_width = flange_width + 2 * wall; //slot_width + 4 * (wall + No2_pilot_radius);
|
||||
nut_slot = nut_thickness(M3_nut) + 0.3;
|
||||
lug_depth = nut_slot + 3 * wall;
|
||||
lug_width = 2 * nut_flat_radius(M3_nut) + wall;
|
||||
lug_height = thickness + slot_height / 2 + M3_nut_radius;
|
||||
screw_x = length - wall - No2_pilot_radius;
|
||||
screw_y = (d_width + slot_width) / 4;
|
||||
pitch = d_width + 2 * nut_flat_radius(M3_nut);
|
||||
|
||||
|
||||
nut_x = length + flange_thickness + wall -lug_depth + wall;
|
||||
|
||||
//function d_motor_bracket_offset(motor) = NEMA_holes(motor)[1] + screw_head_radius(M3_cap_screw) - inner_slot_width / 2;
|
||||
function d_motor_bracket_offset(motor) = NEMA_holes(motor)[0] + (2.5 / cos(30)) / 2 + d_width / 2 + lug_width;
|
||||
//function d_motor_bracket_offset(motor) = (NEMA_width(motor) + 2 * thickness - d_width) / 2;
|
||||
|
||||
//
|
||||
// Lid to retain connector and nuts
|
||||
//
|
||||
module d_motor_bracket_lid_stl(motor = NEMA17, nuts = true) {
|
||||
if(nuts)
|
||||
stl("d_motor_bracket_lid");
|
||||
else
|
||||
stl("d_shell_lid");
|
||||
|
||||
lid_width = front_thickness + flange_thickness + wall;
|
||||
nut_cover_width = d_width + 2 * lug_width;
|
||||
nut_cover_height = height + lid_thickness - lug_height - flange_clearance;
|
||||
nut_cover_depth = lug_depth;
|
||||
|
||||
difference() {
|
||||
union() {
|
||||
translate([length - front_thickness + lid_width / 2, 0, 0])
|
||||
rounded_rectangle([lid_width, d_width, lid_thickness], 2, center = false);
|
||||
|
||||
if(nuts)
|
||||
translate([length - front_thickness + lid_width - nut_cover_depth / 2, 0, 0])
|
||||
rounded_rectangle([nut_cover_depth, nut_cover_width, nut_cover_height], 2, center = false);
|
||||
}
|
||||
|
||||
if(nuts)
|
||||
translate([length - nut_cover_depth, -d_width / 2 - flange_clearance, lid_thickness - eta])
|
||||
cube([nut_cover_depth * 2, d_width + 2 * flange_clearance, 10]);
|
||||
|
||||
for(side = [-1, 1])
|
||||
translate([screw_x, side * screw_y, 0])
|
||||
rotate([0, 0, -side * 360 / 20])
|
||||
poly_cylinder(r = No2_clearance_radius, h = 100, center = true);
|
||||
}
|
||||
}
|
||||
|
||||
module d_shell_lid_stl() d_motor_bracket_lid_stl(motor = NEMA17, nuts = false);
|
||||
//
|
||||
// Attaches to the motor
|
||||
//
|
||||
module d_motor_bracket_stl(motor = NEMA17) {
|
||||
stl("d_motor_bracket");
|
||||
|
||||
m_width = NEMA_width(motor) + 2 * thickness;
|
||||
offset = d_motor_bracket_offset(motor) + (m_width - d_width) / 2;
|
||||
mouth = pitch + 2 * M3_clearance_radius + layer_height / 2;
|
||||
|
||||
difference() {
|
||||
union() {
|
||||
linear_extrude(height = thickness, convexity = 5) // base
|
||||
polygon(points = [ [0, 0],
|
||||
[overlap, 0],
|
||||
[overlap, offset],
|
||||
[length - eta, offset],
|
||||
[length - eta, offset + d_width],
|
||||
[overlap, offset + d_width],
|
||||
[overlap, m_width],
|
||||
[0, m_width],
|
||||
]);
|
||||
|
||||
translate([overlap , 0, eta]) // motor wall
|
||||
cube([thickness, d_width + offset, height]);
|
||||
|
||||
for(y = [0, m_width - thickness]) // buttresses
|
||||
translate([overlap + eta, y, thickness - eta])
|
||||
rotate([90, 0, 180])
|
||||
right_triangle(width = overlap, height = height - thickness, h = thickness, center = false);
|
||||
|
||||
|
||||
difference() {
|
||||
union() {
|
||||
// connector wall
|
||||
translate([length - front_thickness, offset, eta])
|
||||
cube([front_thickness + flange_thickness + wall, d_width, height]);
|
||||
|
||||
// nut lugs
|
||||
translate([length + flange_thickness + wall - lug_depth / 2, offset + d_width / 2, eta])
|
||||
rounded_rectangle([lug_depth, d_width + 2 * lug_width, lug_height], r = 2, center = false);
|
||||
|
||||
// d side walls
|
||||
for(y = [0, d_width - thickness])
|
||||
translate([overlap, y + offset, eta])
|
||||
cube([length - overlap, thickness, height]);
|
||||
}
|
||||
|
||||
translate([length, offset + (d_width - flange_width) / 2, thickness + slot_height / 2 - flange_height / 2])
|
||||
cube([flange_thickness, flange_width, 20]); // slot for flange
|
||||
|
||||
translate([10, d_width / 2 - slot_width / 2 + offset, thickness + eta * 2]) //slot for connector body
|
||||
cube([30, slot_width, 20]);
|
||||
|
||||
|
||||
for(side = [-1, 1]) {
|
||||
translate([nut_x + nut_slot / 2, d_width / 2 - side * pitch / 2 + offset, thickness + slot_height / 2]) //connector screws
|
||||
rotate([90, 0, 90]) {
|
||||
rotate([0,0,30])
|
||||
nut_trap(1, M3_nut_radius, nut_slot / 2, true);
|
||||
|
||||
translate([0, 5, 0])
|
||||
cube([nut_flat_radius(M3_nut) * 2, 10, nut_slot], center = true);
|
||||
|
||||
teardrop_plus(r = M3_clearance_radius, h = 100, center = true);
|
||||
}
|
||||
|
||||
translate([screw_x, d_width / 2 - side * screw_y + offset, height + lid_thickness]) // lid screws holes
|
||||
rotate([0,0,180])
|
||||
poly_cylinder(r = No2_pilot_radius, h = 12 * 2, center = true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
for(y = NEMA_holes(motor)) // motor screws
|
||||
for(z = NEMA_holes(motor))
|
||||
translate([overlap - 1, m_width / 2 + y, NEMA_width(motor) / 2 + thickness + z])
|
||||
rotate([90,0,90])
|
||||
teardrop_plus(r = M3_clearance_radius, h = thickness + 2, center = false);
|
||||
}
|
||||
}
|
||||
//
|
||||
// Attaches connector to ribbon cable and plastic strip
|
||||
//
|
||||
cable_guide_width = 20;
|
||||
cable_guide_thickness = 4;
|
||||
cable_screw = M3_cap_screw;
|
||||
|
||||
shell_front = front_thickness;
|
||||
shell_length = shell_front + 12 + ribbon_clamp_width(cable_screw);
|
||||
shell_screw_x = shell_length - wall - No2_pilot_radius;
|
||||
|
||||
function d_motor_connector_offset(motor) = [
|
||||
NEMA_width(motor) / 2 + thickness - cable_guide_thickness,
|
||||
-NEMA_length(motor) + overlap - length - d_mate_distance(connector) - shell_length + ribbon_clamp_width(cable_screw),
|
||||
d_motor_bracket_offset(motor)
|
||||
];
|
||||
|
||||
module d_shell_stl() {
|
||||
stl("d_shell");
|
||||
|
||||
mouth = pitch + 2 * screw_clearance_radius(cable_screw) + layer_height / 2;
|
||||
rad = ribbon_clamp_width(cable_screw) / 2;
|
||||
clamp_pitch = ribbon_clamp_pitch(extruder_ways, cable_screw);
|
||||
|
||||
front = shell_front + flange_thickness + wall;
|
||||
union() {
|
||||
difference() {
|
||||
union() {
|
||||
translate([shell_length - shell_front, 0, 0]) // connector wall
|
||||
cube([front, d_width, height]);
|
||||
|
||||
// screw lugs
|
||||
translate([shell_length + flange_thickness + wall - front / 2, d_width / 2, eta])
|
||||
rounded_rectangle([front, d_width + 2 * lug_width,
|
||||
thickness + slot_height / 2 + washer_diameter(M3_washer) / 2 + 1], r = 2, center = false);
|
||||
|
||||
linear_extrude(height = cable_guide_thickness, convexity = 5)
|
||||
hull() {
|
||||
for(side = [-1,1])
|
||||
translate([rad, d_width / 2 + side * clamp_pitch / 2])
|
||||
circle(r = rad, center = true);
|
||||
translate([shell_length - shell_front, 0])
|
||||
square([1, d_width]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
translate([shell_length,(d_width - flange_width) / 2, thickness + slot_height / 2 - flange_height / 2])
|
||||
cube([flange_thickness, flange_width, 20]); // slot for flange
|
||||
|
||||
translate([rad * 2, d_width / 2 - slot_width / 2 , thickness - eta]) //slot for connector body
|
||||
cube([30, slot_width, 20]);
|
||||
|
||||
for(side = [-1, 1]) {
|
||||
translate([nut_x + nut_slot / 2, d_width / 2 - side * pitch / 2, thickness + slot_height / 2]) //connector screws
|
||||
rotate([90, 0, 90])
|
||||
teardrop_plus(r = M3_clearance_radius, h = 100, center = true);
|
||||
|
||||
translate([shell_screw_x, d_width / 2 - side * screw_y, height + lid_thickness]) // lid screws holes
|
||||
rotate([0,0,180])
|
||||
poly_cylinder(r = No2_pilot_radius, h = 12 * 2, center = true);
|
||||
}
|
||||
|
||||
//
|
||||
// clamp screw holes
|
||||
//
|
||||
translate([rad, d_width / 2, cable_guide_thickness / 2])
|
||||
rotate([0, 0, 90])
|
||||
ribbon_clamp_holes(extruder_ways, cable_screw)
|
||||
poly_cylinder(r = screw_clearance_radius(cable_screw), h = 100, center = true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module d_shell_assembly(motor) {
|
||||
translate([-NEMA_width(motor) / 2 + slot_height / 2, d_motor_bracket_offset(motor), -NEMA_length(motor) + overlap]) {
|
||||
translate([0, 0, -length - d_mate_distance(connector)])
|
||||
rotate([0, 0, 90])
|
||||
explode([0, -25, 0])
|
||||
d_socket(connector);
|
||||
}
|
||||
translate([-NEMA_width(NEMA17) / 2 - thickness,
|
||||
d_width / 2 + d_motor_bracket_offset(motor),
|
||||
-NEMA_length(NEMA17) - length - shell_length - d_mate_distance(connector) + overlap])
|
||||
rotate([0, -90, 180]) {
|
||||
color([0,1,0]) render() d_shell_stl();
|
||||
translate([0, d_width / 2, height + lid_thickness])
|
||||
translate([length, 0, 0])
|
||||
explode([0, 0, 40])
|
||||
translate([-length, 0, 0])
|
||||
color([1,0,0]) render() rotate([180, 0, 0]) d_shell_lid_stl(motor);
|
||||
|
||||
for(side = [-1, 1]) {
|
||||
translate([shell_length - shell_front, d_width / 2 - side * pitch / 2, thickness + slot_height / 2]) //connector screws
|
||||
rotate([90, 0, -90])
|
||||
screw_and_washer(M3_cap_screw, 20);
|
||||
|
||||
translate([shell_screw_x, d_width / 2 - side * screw_y, height + lid_thickness])
|
||||
//explode([0, 0, 40])
|
||||
screw_and_washer(No2_screw, 13);
|
||||
}
|
||||
translate([ribbon_clamp_width(M3_cap_screw) / 2, d_width / 2, cable_guide_thickness])
|
||||
rotate([0, 0, 90])
|
||||
ribbon_clamp_assembly(extruder_ways, cable_screw, 16, cable_guide_thickness, false, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module d_motor_bracket_assembly(motor) {
|
||||
rotate([0, 90, 0])
|
||||
translate([NEMA_length(NEMA17) - overlap, -NEMA_width(NEMA17) / 2 - thickness, -NEMA_width(NEMA17) / 2 - thickness]) {
|
||||
color([0,1,0]) render() d_motor_bracket_stl(NEMA17);
|
||||
translate([0, NEMA_width(NEMA17) / 2 + d_motor_bracket_offset(NEMA17) + thickness, height + lid_thickness])
|
||||
translate([length, 0, 0])
|
||||
explode([0, 0, 40])
|
||||
translate([-length, 0, 0])
|
||||
color([1,0,0]) render() rotate([180, 0, 0]) d_motor_bracket_lid_stl(motor);
|
||||
}
|
||||
|
||||
translate([-NEMA_width(motor) / 2 + slot_height / 2, d_motor_bracket_offset(motor), -NEMA_length(motor) + overlap]) {
|
||||
translate([0, 0, -length])
|
||||
rotate([180, 0, -90])
|
||||
explode([0, -25, 0])
|
||||
d_plug(connector);
|
||||
|
||||
for(side = [-1, 1]) {
|
||||
translate([0, pitch / 2 * side, -nut_x])
|
||||
rotate([180, 0, 0])
|
||||
explode([10,0,0])
|
||||
nut(M3_nut);
|
||||
|
||||
translate([height - slot_height / 2 - thickness + lid_thickness, side * screw_y, - screw_x])
|
||||
rotate([0, 90, 0])
|
||||
explode([0, 0, 40])
|
||||
screw_and_washer(No2_screw, 13);
|
||||
}
|
||||
}
|
||||
|
||||
for(y = NEMA_holes(motor)) // motor screws
|
||||
for(x = NEMA_holes(motor))
|
||||
if(x < 0)
|
||||
translate([x, y, -NEMA_length(motor) - thickness])
|
||||
rotate([180, 0, 0])
|
||||
screw_and_washer(M3_cap_screw, 45);
|
||||
}
|
||||
|
||||
|
||||
if(1) {
|
||||
NEMA(NEMA17);
|
||||
d_motor_bracket_assembly(NEMA17);
|
||||
translate([0, 0, exploded ? - 20 : 0])
|
||||
d_shell_assembly(NEMA17);
|
||||
|
||||
}
|
||||
else {
|
||||
d_motor_bracket_stl(NEMA17);
|
||||
translate([11, 35, 0])
|
||||
d_motor_bracket_lid_stl(NEMA17);
|
||||
|
||||
translate([22, 35, 0])
|
||||
d_shell_lid_stl(NEMA17);
|
||||
|
||||
translate([-32, 6, 0])
|
||||
d_shell_stl(NEMA17);
|
||||
|
||||
translate([25, 4, ribbon_clamp_thickness()])
|
||||
ribbon_clamp(extruder_ways, cable_screw);
|
||||
|
||||
}
|
51
scad/fan-guard.scad
Normal file
51
scad/fan-guard.scad
Normal file
@ -0,0 +1,51 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
//
|
||||
//
|
||||
include <conf/config.scad>
|
||||
|
||||
thickness = 2;
|
||||
wall = 2 * filament_width + eta;
|
||||
finger_width = 7;
|
||||
spokes = 4;
|
||||
|
||||
function fan_guard_thickness() = thickness;
|
||||
|
||||
module fan_guard(type) {
|
||||
stl("fan_guard");
|
||||
hole_pitch = fan_hole_pitch(type);
|
||||
screw = fan_screw(type);
|
||||
corner_radius = washer_diameter(screw_washer(screw)) / 2 + 1;
|
||||
width = max(2 * (hole_pitch + corner_radius), fan_bore(type) + 2 * wall);
|
||||
|
||||
hole = fan_bore(type) / 2;
|
||||
rings = ceil(hole / (wall + finger_width)) - 1;
|
||||
inner_ring = hole - rings * (wall + finger_width);
|
||||
|
||||
union() {
|
||||
difference() {
|
||||
rounded_rectangle([width, width, thickness], r = width / 2 - hole_pitch, center = false);
|
||||
fan_holes(type, true);
|
||||
}
|
||||
for(i = [1 : rings])
|
||||
difference() {
|
||||
cylinder(r = hole - i * (wall + finger_width) + wall / 2, h = thickness);
|
||||
cylinder(r = hole - i * (wall + finger_width) - wall / 2, h = 2 * thickness + 1, center = true);
|
||||
}
|
||||
for(i = [0 : spokes - 1])
|
||||
rotate([0, 0, i * 360 / spokes + 180 / spokes - 90])
|
||||
translate([inner_ring, -wall / 2, 0])
|
||||
cube([hole - inner_ring + eta, wall, thickness]);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
module fan_guard_stl() fan_guard(case_fan);
|
||||
|
||||
fan_guard(fan80x38);
|
||||
//fan_guard(fan60x25);
|
103
scad/fixing-block.scad
Normal file
103
scad/fixing-block.scad
Normal file
@ -0,0 +1,103 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// Brackets to fasten the frame together
|
||||
//
|
||||
include <conf/config.scad>
|
||||
|
||||
slot = 2;
|
||||
thickness = 5;
|
||||
thin_wall = filament_width * 2 + eta;
|
||||
wall = 3;
|
||||
|
||||
counter_bore_rad = washer_diameter(screw_washer(base_screw)) / 2 + 0.2;
|
||||
width = 2 * wall + 2 * thin_wall + 6 * counter_bore_rad;
|
||||
shear = min(counter_bore_rad - screw_clearance_radius(frame_screw), 2.5);
|
||||
|
||||
|
||||
hole_pitch = 2 * (2 * counter_bore_rad + thin_wall);
|
||||
depth = 2 * (thickness + counter_bore_rad) + slot - 2 * shear;
|
||||
height = depth;
|
||||
|
||||
hole_offset = depth / 2;
|
||||
corner_rad = 3;
|
||||
|
||||
counter_bore_depth = depth - thickness;
|
||||
|
||||
function fixing_block_width() = width;
|
||||
function fixing_block_height() = height;
|
||||
|
||||
module fixing_block_v_hole(h)
|
||||
translate([0, hole_offset, h])
|
||||
child();
|
||||
|
||||
module fixing_block_h_holes(h)
|
||||
for(end = [-1, 1])
|
||||
translate([end * hole_pitch / 2, h, hole_offset])
|
||||
rotate([90, 0, 180])
|
||||
child();
|
||||
|
||||
|
||||
module fixing_block_stl() {
|
||||
stl("fixing_block");
|
||||
difference() {
|
||||
translate([-(width - 2 * corner_rad) / 2, 0, 0])
|
||||
minkowski() {
|
||||
cube([width - 2 * corner_rad, depth- corner_rad, height -corner_rad]);
|
||||
intersection() {
|
||||
sphere(r = corner_rad);
|
||||
translate([0, 5, 5])
|
||||
cube([10, 10, 10], center = true);
|
||||
}
|
||||
}
|
||||
|
||||
translate([-width / 2 - 1, thickness, height + eta]) // diagonal slice of the front
|
||||
rotate([-45, 0, 0])
|
||||
cube([width + 2, depth * 2, height]);
|
||||
|
||||
|
||||
fixing_block_v_hole(height - counter_bore_depth)
|
||||
rotate([0,0,90])
|
||||
union() {
|
||||
slot(h = 100, r = screw_clearance_radius(frame_screw), l = slot, center = true);
|
||||
multmatrix(m = [ [1, 0, shear / counter_bore_depth, 0],
|
||||
[0, 1, 0, 0],
|
||||
[0, 0, 1, 0],
|
||||
[0, 0, 0, 1] ])
|
||||
slot(h = 100, r = counter_bore_rad, l = slot, center = false);
|
||||
}
|
||||
|
||||
|
||||
fixing_block_h_holes(depth - counter_bore_depth)
|
||||
rotate([0,0,0])
|
||||
union() {
|
||||
vertical_tearslot(h = 100, r = screw_clearance_radius(frame_screw), l = slot, center = true);
|
||||
multmatrix(m = [ [1, 0, 0, 0],
|
||||
[0, 1, shear / counter_bore_depth, 0],
|
||||
[0, 0, 1, 0],
|
||||
[0, 0, 0, 1] ])
|
||||
vertical_tearslot(h = 100, r = counter_bore_rad, l = slot, center = false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module fixing_block_assembly(front = false) {
|
||||
color([0,1,0]) render() fixing_block_stl();
|
||||
fixing_block_v_hole(height - counter_bore_depth)
|
||||
if(front)
|
||||
frame_screw(thickness);
|
||||
else
|
||||
base_screw();
|
||||
fixing_block_h_holes(depth - counter_bore_depth)
|
||||
frame_screw(thickness);
|
||||
}
|
||||
|
||||
if(0) {
|
||||
fixing_block_stl();
|
||||
}
|
||||
else
|
||||
fixing_block_assembly();
|
738
scad/main.scad
Normal file
738
scad/main.scad
Normal file
@ -0,0 +1,738 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// main assembly
|
||||
//
|
||||
include <conf/config.scad>
|
||||
use <bed.scad>
|
||||
use <z-screw_pointer.scad>
|
||||
use <bar-clamp.scad>
|
||||
use <pulley.scad>
|
||||
use <y-bearing-mount.scad>
|
||||
use <y-idler-bracket.scad>
|
||||
use <y-belt-anchor.scad>
|
||||
use <z-coupling.scad>
|
||||
use <z-motor-bracket.scad>
|
||||
use <z-limit-switch-bracket.scad>
|
||||
use <fixing-block.scad>
|
||||
use <ribbon_clamp.scad>
|
||||
use <fan-guard.scad>
|
||||
use <wade.scad>
|
||||
use <cable_clip.scad>
|
||||
use <pcb_spacer.scad>
|
||||
|
||||
include <positions.scad>
|
||||
|
||||
X = 0 * X_travel / 2; //sin(360 * $t) * bed_width / 2;
|
||||
Y = 0 * Y_travel / 2; //cos(360 * $t) * bed_depth / 2;
|
||||
Z = 0 * Z_travel;
|
||||
|
||||
|
||||
//
|
||||
// X axis
|
||||
//
|
||||
X_bar_length = motor_end - idler_end + 2 * x_end_bar_length();
|
||||
module x_axis_assembly(show_extruder) {
|
||||
X_belt_gap = x_carriage_belt_gap() - 10;
|
||||
|
||||
assembly("x_axis_assembly");
|
||||
for(side = [-1,1])
|
||||
translate([(idler_end + motor_end) / 2 + eta, side * x_bar_spacing() / 2, Z + Z0])
|
||||
rotate([0,90,0])
|
||||
rod(X_bar_dia, X_bar_length);
|
||||
|
||||
translate([-X + X_origin, 0, Z + Z0 + x_carriage_offset()])
|
||||
rotate([180, 0, 180])
|
||||
x_carriage_assembly(show_extruder);
|
||||
|
||||
translate([0, -gantry_setback - belt_width(X_belt) / 2, Z + Z0])
|
||||
rotate([90, 0, 0]) render()
|
||||
union() {
|
||||
difference() {
|
||||
twisted_belt(X_belt, idler_end + x_idler_offset(), 0, ball_bearing_diameter(X_idler_bearing) / 2,
|
||||
motor_end - x_motor_offset(), 0, pulley_inner_radius, X_belt_gap - x_belt_loop_length());
|
||||
|
||||
translate([-X + X_origin - nozzle_x_offset + (x_carriage_belt_gap() - X_belt_gap + 5) / 2,
|
||||
pulley_inner_radius + belt_thickness(X_belt)/2, 0])
|
||||
cube([X_belt_gap + 5, belt_thickness(X_belt) * 3, belt_width(X_belt) * 2], center = true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
elliptical_cable_strip(ribbon_clamp_slot(extruder_ways) - 1,
|
||||
[motor_end, 0, Z + Z0] + x_end_extruder_ribbon_clamp_offset(),
|
||||
[-X + X_origin, 0, Z + Z0 + x_carriage_offset()] + extruder_connector_offset(),
|
||||
[-X_travel / 2 + X_origin, 0, Z + Z0 + x_carriage_offset()] + extruder_connector_offset());
|
||||
end("x_axis_assembly");
|
||||
}
|
||||
|
||||
//
|
||||
// Z axis
|
||||
//
|
||||
Z_motor_length = NEMA_length(Z_motor);
|
||||
Z_bar_length = height - Z_motor_length - base_clearance;
|
||||
module z_end(motor_end) {
|
||||
Z_screw_length = Z0 + Z_travel + anti_backlash_height() + axis_endstop_clearance
|
||||
- (Z_motor_length + NEMA_shaft_length(Z_motor) + 2);
|
||||
|
||||
if(!motor_end)
|
||||
translate([-z_bar_offset(), gantry_setback, Z0 - x_end_thickness() / 2])
|
||||
z_limit_switch_assembly();
|
||||
|
||||
translate([-z_bar_offset(), 0, Z_motor_length]) {
|
||||
|
||||
z_motor_assembly(gantry_setback, motor_end);
|
||||
|
||||
translate([0, 0, NEMA_shaft_length(Z_motor) + 2 + Z_screw_length / 2]) {
|
||||
studding(d = Z_screw_dia, l = Z_screw_length);
|
||||
|
||||
translate([0, 0, -Z_screw_length / 2 + z_coupling_length() / 2 - 1])
|
||||
render() z_screw_pointer_stl();
|
||||
}
|
||||
|
||||
translate([z_bar_offset(), 0, Z_bar_length / 2])
|
||||
rod(Z_bar_dia, Z_bar_length);
|
||||
|
||||
translate([z_bar_offset(), gantry_setback, Z_bar_length - bar_clamp_depth / 2]) {
|
||||
rotate([90,motor_end ? 90 : - 90, 0])
|
||||
z_bar_clamp_assembly(Z_bar_dia, gantry_setback, bar_clamp_depth, !motor_end);
|
||||
}
|
||||
}
|
||||
translate([0, 0, Z + Z0])
|
||||
x_end_assembly(motor_end, true);
|
||||
}
|
||||
|
||||
module z_axis_assembly() {
|
||||
assembly("z_axis_assembly");
|
||||
translate([motor_end, 0, 0])
|
||||
mirror([1,0,0])
|
||||
z_end(true);
|
||||
translate([idler_end, 0, 0])
|
||||
z_end(false);
|
||||
end("z_axis_assembly");
|
||||
}
|
||||
|
||||
//
|
||||
// Y axis
|
||||
//
|
||||
Y_bar_length = Y_travel + Y_carriage_depth + 2 * axis_endstop_clearance;
|
||||
|
||||
Y_bar_length2 = Y_travel + bearing_mount_length(Y_bearings) + 2 * bar_clamp_depth + axis_endstop_clearance + bar_clamp_switch_y_offset();
|
||||
|
||||
Y_bar_spacing = Y_carriage_width - bearing_mount_width(Y_bearings);
|
||||
Y_bearing_inset = bearing_mount_length(Y_bearings) / 2 + bar_clamp_depth;
|
||||
|
||||
Y_belt_motor_offset = 13 + belt_width(Y_belt) / 2;
|
||||
|
||||
//Y_belt_line = min(X_origin,
|
||||
// X_origin + Y_bar_spacing / 2
|
||||
// - max(bar_rail_offset(Y_bar_dia), bearing_mount_width(Y_bearings) /2)
|
||||
// - NEMA_length(Y_motor) - Y_belt_motor_offset - X_carriage_clearance);
|
||||
Y_belt_line = X_origin - ribbon_clamp_slot(bed_ways) / 2 - y_belt_anchor_width() / 2 - 5;
|
||||
|
||||
Y_motor_end = -base_depth / 2 + y_motor_bracket_width() / 2 + base_clearance;
|
||||
Y_idler_end = base_depth / 2 - y_idler_offset() - base_clearance;
|
||||
Y_belt_anchor_m = Y_motor_end + NEMA_width(Y_motor) / 2 + Y_travel / 2;
|
||||
Y_belt_anchor_i = Y_idler_end - y_idler_clearance() - Y_travel / 2;
|
||||
Y_belt_end = 20;
|
||||
Y_belt_gap = Y_belt_anchor_i - Y_belt_anchor_m - 2 * Y_belt_end;
|
||||
|
||||
|
||||
//
|
||||
// supported bar
|
||||
//
|
||||
module rail(length, height, endstop) {
|
||||
translate([0, 0, height])
|
||||
rotate([90,0,0])
|
||||
rod(Y_bar_dia, length);
|
||||
|
||||
for(end = [-1, 1])
|
||||
translate([0, end * (length / 2 - bar_clamp_depth / 2), 0])
|
||||
rotate([0, 0, 90])
|
||||
y_bar_clamp_assembly(Y_bar_dia, height, bar_clamp_depth, endstop && end == 1);
|
||||
}
|
||||
|
||||
module y_rails() {
|
||||
offset = bar_clamp_switch_y_offset() - axis_endstop_clearance;
|
||||
|
||||
translate([-Y_bar_spacing / 2, 0, 0])
|
||||
rail(Y_bar_length, Y_bar_height);
|
||||
|
||||
rotate([0,0,180])
|
||||
translate([-Y_bar_spacing / 2, offset / 2, 0])
|
||||
rail(Y_bar_length2, Y_bar_height, true);
|
||||
}
|
||||
|
||||
module rail_holes(length) {
|
||||
for(end = [-1, 1])
|
||||
translate([0, end * (length / 2 - bar_clamp_depth / 2), 0])
|
||||
rotate([0, 0, 90])
|
||||
bar_clamp_holes(Y_bar_dia)
|
||||
base_screw_hole();
|
||||
}
|
||||
|
||||
module y_rail_holes() {
|
||||
offset = bar_clamp_switch_y_offset() - axis_endstop_clearance;
|
||||
|
||||
translate([-Y_bar_spacing / 2, 0, 0])
|
||||
rail_holes(Y_bar_length);
|
||||
|
||||
rotate([0,0,180])
|
||||
translate([-Y_bar_spacing / 2, offset / 2, 0])
|
||||
rail_holes(Y_bar_length2);
|
||||
}
|
||||
|
||||
cable_clamp_y = Y_carriage_depth / 2 - ribbon_clamp_width(cap_screw);
|
||||
|
||||
module y_carriage() {
|
||||
difference() {
|
||||
sheet(Y_carriage, Y_carriage_width, Y_carriage_depth, [3,3,3,3]);
|
||||
|
||||
translate([0, cable_clamp_y, 0])
|
||||
rotate([180, 0, 0])
|
||||
ribbon_clamp_holes(bed_ways, cap_screw)
|
||||
cylinder(r = screw_clearance_radius(cap_screw), h = 100, center = true);
|
||||
|
||||
translate([Y_bar_spacing / 2, 0, 0])
|
||||
rotate([0,180,0])
|
||||
bearing_mount_holes();
|
||||
|
||||
for(end = [-1, 1])
|
||||
translate([-Y_bar_spacing / 2, end * (Y_carriage_depth / 2 - Y_bearing_inset), 0])
|
||||
rotate([0,180,0])
|
||||
bearing_mount_holes();
|
||||
|
||||
for(end = [[Y_belt_anchor_m, 0], [Y_belt_anchor_i, 180]])
|
||||
translate([Y_belt_line - X_origin, end[0], 0])
|
||||
rotate([0, 180, end[1]])
|
||||
y_belt_anchor_holes();
|
||||
|
||||
for(x = [-bed_holes / 2, bed_holes / 2])
|
||||
for(y = [-bed_holes / 2, bed_holes / 2])
|
||||
translate([x, y, 0])
|
||||
cylinder(r = 2.5/2, h = 100, center = true);
|
||||
}
|
||||
}
|
||||
|
||||
module y_axis_assembly(show_bed) {
|
||||
carriage_bottom = Y_carriage_height - sheet_thickness(Y_carriage) / 2;
|
||||
carriage_top = Y_carriage_height + sheet_thickness(Y_carriage) / 2;
|
||||
|
||||
translate([X_origin, 0, 0]) {
|
||||
|
||||
assembly("y_axis_assembly");
|
||||
y_rails();
|
||||
|
||||
translate([Y_belt_line - X_origin, Y_motor_end, y_motor_height()]) rotate([90,0,-90]) {
|
||||
render() difference() {
|
||||
twisted_belt(Y_belt,
|
||||
Y_motor_end - Y_idler_end,
|
||||
pulley_inner_radius - ball_bearing_diameter(Y_idler_bearing) / 2,
|
||||
ball_bearing_diameter(Y_idler_bearing) / 2,
|
||||
0, 0, pulley_inner_radius, Y_belt_gap);
|
||||
translate([-(Y_belt_anchor_i + Y_belt_anchor_m) / 2 + Y_motor_end - Y, pulley_inner_radius + belt_thickness(Y_belt)/2, 0])
|
||||
cube([Y_belt_gap, belt_thickness(Y_belt) * 2, belt_width(Y_belt) * 2], center = true);
|
||||
}
|
||||
|
||||
translate([0, 0, -Y_belt_motor_offset])
|
||||
y_motor_assembly();
|
||||
}
|
||||
translate([Y_belt_line - X_origin, Y_idler_end, 0])
|
||||
y_idler_assembly();
|
||||
|
||||
end("y_axis_assembly");
|
||||
//
|
||||
// Y carriage
|
||||
//
|
||||
translate([0, Y, 0]) {
|
||||
assembly("y_carriage_assembly");
|
||||
|
||||
translate([Y_bar_spacing / 2, 0, Y_bar_height])
|
||||
rotate([0,180,0])
|
||||
y_bearing_assembly(Y_bearing_holder_height, true);
|
||||
|
||||
for(end = [-1, 1])
|
||||
translate([-Y_bar_spacing / 2, end * (Y_carriage_depth / 2 - Y_bearing_inset), Y_bar_height])
|
||||
rotate([0,180,0])
|
||||
y_bearing_assembly(Y_bearing_holder_height);
|
||||
|
||||
for(end = [[Y_belt_anchor_m, 0, false], [Y_belt_anchor_i, 180, true]])
|
||||
translate([Y_belt_line - X_origin, end[0], carriage_bottom])
|
||||
rotate([0, 180, end[1]])
|
||||
y_belt_anchor_assembly(Y_belt_clamp_height, end[2]);
|
||||
|
||||
translate([0, cable_clamp_y, carriage_top])
|
||||
rotate([180, 0, 0])
|
||||
color([1,0,0]) render() ribbon_clamp(bed_ways, cap_screw);
|
||||
|
||||
translate([0, cable_clamp_y, carriage_bottom])
|
||||
rotate([180, 0, 0])
|
||||
ribbon_clamp_assembly(bed_ways, cap_screw, 25, sheet_thickness(Y_carriage) + ribbon_clamp_thickness(), false, true);
|
||||
|
||||
if(show_bed)
|
||||
translate([0, 0, Y_carriage_height + sheet_thickness(Y_carriage) / 2])
|
||||
bed_assembly();
|
||||
|
||||
|
||||
translate([0, 0, Y_carriage_height + eta * 2])
|
||||
if(show_bed)
|
||||
y_carriage();
|
||||
else
|
||||
%y_carriage();
|
||||
|
||||
end("y_carriage_assembly");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module y_axis_screw_holes() {
|
||||
translate([X_origin, 0, 0]) {
|
||||
y_rail_holes();
|
||||
|
||||
translate([Y_belt_line - X_origin, Y_idler_end, 0])
|
||||
y_idler_screw_hole()
|
||||
base_screw_hole();
|
||||
|
||||
translate([Y_belt_line - X_origin, Y_motor_end, y_motor_height()])
|
||||
rotate([90,0,-90])
|
||||
translate([0, 0, -Y_belt_motor_offset])
|
||||
y_motor_bracket_holes()
|
||||
base_screw_hole();
|
||||
}
|
||||
}
|
||||
//
|
||||
// List of cable clips
|
||||
//
|
||||
left_stay_x = max(-base_width / 2 + left_w / 2,
|
||||
idler_end - z_bar_offset() + z_motor_bracket_hole_offset() + washer_diameter(M4_washer) / 2 + 1) + sheet_thickness(frame) / 2;
|
||||
|
||||
right_stay_x = max(base_width / 2 - right_w / 2,
|
||||
motor_end + z_bar_offset() + z_motor_bracket_hole_offset() + washer_diameter(M4_washer) / 2 + 1) + sheet_thickness(frame) / 2 ;
|
||||
|
||||
|
||||
z_gantry_wire_height = height - base_clearance - fixing_block_width() -fixing_block_height() -
|
||||
base_clearance - cable_clip_extent(base_clip_screw, endstop_wires);
|
||||
|
||||
cable_clips = [ // cable1, cable2 , position, vertical, rotation
|
||||
|
||||
// near to the Y limit switch
|
||||
[endstop_wires, motor_wires,
|
||||
[base_width / 2 - right_w - cable_clip_extent(base_clip_screw, motor_wires), -Y_bar_length2 / 2 + 20, 0], false, 0],
|
||||
// at the foot of the gantry
|
||||
[endstop_wires, motor_wires,
|
||||
[base_width / 2 - right_w - cable_clip_extent(base_clip_screw, motor_wires), gantry_setback + 20, 0], false, 0],
|
||||
// bed wires
|
||||
[bed_wires, thermistor_wires,
|
||||
[20, base_depth / 2 -2 * base_clearance - fixing_block_width() - cable_clip_extent(base_clip_screw, bed_wires), 0], false, -90],
|
||||
// Z axis left
|
||||
[endstop_wires, fan_motor_wires,
|
||||
[left_stay_x + 15, gantry_setback + sheet_thickness(frame), z_gantry_wire_height], true, 90],
|
||||
|
||||
// Z axis right
|
||||
[endstop_wires, fan_motor_wires,
|
||||
[right_stay_x - 15, gantry_setback + sheet_thickness(frame), z_gantry_wire_height], true, 90],
|
||||
|
||||
];
|
||||
|
||||
module place_cable_clips(holes = false) {
|
||||
for(clip = cable_clips) {
|
||||
translate(clip[2])
|
||||
rotate([clip[3] ? -90 : 0, 0, 0]) rotate([0, 0, clip[4]])
|
||||
if(holes)
|
||||
cylinder(r = clip[3] ? (frame_nuts ? screw_clearance_radius(frame_clip_screw) : screw_pilot_hole(frame_clip_screw)) :
|
||||
screw_pilot_hole(base_clip_screw), h = 100, center = true);
|
||||
else
|
||||
if(clip[3])
|
||||
cable_clip_assembly(frame_clip_screw, frame_clip_screw_length, clip[0], clip[1]);
|
||||
else
|
||||
cable_clip_assembly(base_clip_screw, base_clip_screw_length, clip[0], clip[1]);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Frame
|
||||
//
|
||||
module fixing_blocks(upper = false) {
|
||||
w = fixing_block_width();
|
||||
h = fixing_block_height();
|
||||
t = sheet_thickness(frame);
|
||||
|
||||
if(upper) { // all screws into frame
|
||||
translate([left_stay_x + t / 2, gantry_setback + t, stay_height - base_clearance - h - w / 2]) // top
|
||||
rotate([0,-90,-90])
|
||||
child();
|
||||
|
||||
translate([right_stay_x - t / 2, gantry_setback + t, stay_height - base_clearance - h - w / 2]) // top
|
||||
rotate([0,90, 90])
|
||||
child();
|
||||
|
||||
translate([left_stay_x + t / 2, gantry_setback + t, base_clearance + h + w / 2]) // front
|
||||
rotate([0,-90,-90])
|
||||
child();
|
||||
|
||||
translate([right_stay_x - t / 2, gantry_setback + t, base_clearance + h + w / 2]) // front
|
||||
rotate([0,90, 90])
|
||||
child();
|
||||
}
|
||||
else { // one screw in the base
|
||||
for(x = [-base_width/2 + base_clearance + w /2,
|
||||
base_width/2 - base_clearance - w /2,
|
||||
-base_width/2 - base_clearance - w /2 + left_w,
|
||||
base_width/2 + base_clearance + w /2 - right_w])
|
||||
translate([x, gantry_setback + t, 0])
|
||||
child();
|
||||
|
||||
translate([left_stay_x + t / 2, gantry_setback + t + stay_depth - base_clearance - w / 2, 0]) // back
|
||||
rotate([0, 0,-90])
|
||||
child();
|
||||
|
||||
translate([right_stay_x - t / 2, gantry_setback + t + stay_depth - base_clearance - w / 2, 0]) // back
|
||||
rotate([0,0, 90])
|
||||
child();
|
||||
}
|
||||
}
|
||||
|
||||
module fixing_block_holes() {
|
||||
fixing_blocks()
|
||||
group() {
|
||||
fixing_block_v_hole(0)
|
||||
base_screw_hole();
|
||||
fixing_block_h_holes(0)
|
||||
frame_screw_hole();
|
||||
}
|
||||
|
||||
fixing_blocks(true)
|
||||
group() {
|
||||
fixing_block_v_hole(0)
|
||||
frame_screw_hole();
|
||||
fixing_block_h_holes(0)
|
||||
frame_screw_hole();
|
||||
}
|
||||
}
|
||||
|
||||
module frame_base() {
|
||||
difference() {
|
||||
translate([0,0, -sheet_thickness(base) / 2])
|
||||
sheet(base, base_width, base_depth, [base_corners, base_corners, base_corners, base_corners]); // base
|
||||
|
||||
fixing_block_holes();
|
||||
y_axis_screw_holes();
|
||||
|
||||
translate([motor_end + z_bar_offset(), 0, 0]) // in case motor has second shaft
|
||||
cylinder(r = 4, h = 100, center = true);
|
||||
|
||||
translate([idler_end - z_bar_offset(), 0, 0])
|
||||
cylinder(r = 4, h = 100, center = true);
|
||||
|
||||
|
||||
translate([X_origin, cable_clamp_y,0])
|
||||
ribbon_clamp_holes(bed_ways, base_screw)
|
||||
base_screw_hole();
|
||||
|
||||
place_cable_clips(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module frame_gantry() {
|
||||
difference() {
|
||||
translate([0, gantry_setback + sheet_thickness(frame) / 2, height / 2])
|
||||
rotate([90,0,0])
|
||||
if(single_piece_frame)
|
||||
difference() {
|
||||
sheet(frame, base_width, height, [frame_corners, frame_corners, 0, 0]); // vertical plane
|
||||
translate([X_origin, -gantry_thickness, 0])
|
||||
rounded_rectangle([window_width, height, sheet_thickness(frame) + 1], r = 5, center = true);
|
||||
}
|
||||
else {
|
||||
translate([-base_width / 2 + left_w / 2, 0, 0])
|
||||
sheet(frame, left_w, height, [frame_corners, 0, 0, 0]); // left side
|
||||
|
||||
translate([ base_width / 2 - right_w / 2, 0, 0])
|
||||
sheet(frame, right_w, height, [0, frame_corners, 0, 0]); // right side
|
||||
|
||||
translate([0, height / 2 - gantry_thickness / 2, -sheet_thickness(frame)])
|
||||
sheet(frame, base_width, gantry_thickness, [frame_corners, frame_corners, 0, 0]); // top
|
||||
}
|
||||
|
||||
fixing_block_holes();
|
||||
|
||||
//
|
||||
// Z bar clamps
|
||||
//
|
||||
for(end = [idler_end, motor_end])
|
||||
translate([end, gantry_setback, height - base_clearance - bar_clamp_depth / 2])
|
||||
rotate([0, 90, 90])
|
||||
bar_clamp_holes(Z_bar_dia)
|
||||
frame_screw_hole();
|
||||
|
||||
//
|
||||
// Z motor bracket holes
|
||||
//
|
||||
for(side = [idler_end - z_bar_offset(), motor_end + z_bar_offset()])
|
||||
translate([side, 0, Z_motor_length])
|
||||
z_motor_bracket_holes(gantry_setback)
|
||||
frame_screw_hole();
|
||||
|
||||
//
|
||||
// Z limit switch holes
|
||||
//
|
||||
translate([idler_end -z_bar_offset(), gantry_setback, Z0 - x_end_thickness() / 2])
|
||||
z_limit_screw_positions()
|
||||
frame_screw_hole();
|
||||
//
|
||||
// X ribbon clamp
|
||||
//
|
||||
translate([motor_end - x_motor_offset(), gantry_setback, height - base_clearance - ribbon_clamp_width(frame_screw)])
|
||||
ribbon_clamp_holes(x_end_ways, frame_screw)
|
||||
rotate([90, 0, 0])
|
||||
frame_screw_hole();
|
||||
//
|
||||
// Wiring holes
|
||||
//
|
||||
translate([idler_end - bar_rail_offset(Z_bar_dia) + 0.5 * bar_clamp_tab,
|
||||
gantry_setback, height - base_clearance - bar_clamp_depth - endstop_wires_hole_radius - base_clearance])
|
||||
rotate([90, 0, 0])
|
||||
wire_hole(endstop_wires_hole_radius); // Z top endstop
|
||||
|
||||
translate([-base_width / 2 + base_clearance + fixing_block_width() + base_clearance + motor_wires_hole_radius,
|
||||
gantry_setback, motor_wires_hole_radius + hole_edge_clearance])
|
||||
rotate([90, 0, 0])
|
||||
wire_hole(motor_wires_hole_radius); // Z lhs motor
|
||||
|
||||
translate([max(motor_end + bar_rail_offset(Z_bar_dia),
|
||||
base_width / 2 - right_w + fixing_block_width() + 2 * base_clearance + motor_wires_hole_radius),
|
||||
gantry_setback, motor_wires_hole_radius + hole_edge_clearance])
|
||||
rotate([90, 0, 0])
|
||||
wire_hole(motor_wires_hole_radius); // Z rhs motor
|
||||
|
||||
translate([idler_end - bar_rail_offset(Z_bar_dia),
|
||||
gantry_setback, Z_motor_length + z_motor_bracket_height() + endstop_wires_hole_radius])
|
||||
rotate([90, 0, 0])
|
||||
wire_hole(endstop_wires_hole_radius); // bottom limit switch
|
||||
|
||||
place_cable_clips(true);
|
||||
}
|
||||
}
|
||||
|
||||
fan_y = gantry_setback + sheet_thickness(frame) + fixing_block_height() + fan_width(case_fan) / 2 + base_clearance;
|
||||
fan_z = Y_carriage_height + fan_width(case_fan) / 2;
|
||||
|
||||
sanguinololu_z = 10;
|
||||
sanguinololu_y = base_depth / 2 - 50 - sanguinololu_width(); // inset by 50 to leave room for USB plug
|
||||
|
||||
psu_z = height - psu_length(psu) / 2 - base_clearance;
|
||||
psu_y = gantry_setback + sheet_thickness(frame) + fixing_block_height() + psu_width(psu) / 2;
|
||||
|
||||
module frame_stay(left, bodge = 0) {
|
||||
x = left ? left_stay_x : right_stay_x;
|
||||
|
||||
difference() {
|
||||
translate([x, gantry_setback + sheet_thickness(frame) + stay_depth / 2, stay_height / 2])
|
||||
rotate([90,0,90])
|
||||
sheet(frame, stay_depth, stay_height, [0, frame_corners, 0, 0]);
|
||||
|
||||
fixing_block_holes();
|
||||
|
||||
if(left)
|
||||
translate([x + (sheet_thickness(frame) + fan_depth(case_fan)) / 2, fan_y, fan_z])
|
||||
rotate([0,90,0])
|
||||
scale([1 + bodge, 1 + bodge, 1]) fan_holes(case_fan); // scale prevents OpenCSG z buffer artifacts
|
||||
|
||||
else {
|
||||
//
|
||||
// Electronics mounting holes
|
||||
//
|
||||
translate([x, sanguinololu_y, sanguinololu_z])
|
||||
rotate([90, 0, 90])
|
||||
sanguinololu_screw_positions()
|
||||
cylinder(r = M3_tap_radius, h = 100, center = true);
|
||||
|
||||
translate([x, psu_y, psu_z])
|
||||
rotate([0, -90, 180])
|
||||
psu_screw_positions(psu)
|
||||
cylinder(r = M3_clearance_radius, h = 100, center = true);
|
||||
|
||||
//
|
||||
// Wiring holes
|
||||
//
|
||||
translate([x, gantry_setback + sheet_thickness(frame) + fixing_block_height() + motor_wires_hole_radius,
|
||||
hole_edge_clearance + motor_wires_hole_radius]) {
|
||||
rotate([0, 90, 0])
|
||||
wire_hole(motor_wires_hole_radius); // Z rhs motor at bottom
|
||||
|
||||
translate([0, motor_wires_hole_radius + hole_edge_clearance + motor_wires_hole_radius, 0]) {
|
||||
rotate([0, 90, 0])
|
||||
wire_hole(motor_wires_hole_radius); // Y motor wires at bottom
|
||||
|
||||
translate([0, motor_wires_hole_radius + hole_edge_clearance + endstop_wires_hole_radius,
|
||||
endstop_wires_hole_radius - motor_wires_hole_radius])
|
||||
rotate([0, 90, 0])
|
||||
wire_hole(endstop_wires_hole_radius); // Y endstop wires at bottom
|
||||
}
|
||||
}
|
||||
|
||||
translate([x, gantry_setback + sheet_thickness(frame) + stay_depth - 2 * base_clearance - fixing_block_width() - bed_wires_hole_radius,
|
||||
hole_edge_clearance + bed_wires_hole_radius]) {
|
||||
rotate([0, 90, 0])
|
||||
wire_hole(bed_wires_hole_radius); // Bed wires at bottom
|
||||
|
||||
translate([0, -bed_wires_hole_radius - hole_edge_clearance - thermistor_wires_hole_radius,
|
||||
thermistor_wires_hole_radius - bed_wires_hole_radius])
|
||||
rotate([0, 90, 0])
|
||||
wire_hole(thermistor_wires_hole_radius); // Bed thermistor wires
|
||||
}
|
||||
}
|
||||
translate([x, gantry_setback + sheet_thickness(frame) + endstop_wires_hole_radius + hole_edge_clearance, z_gantry_wire_height]) {
|
||||
translate([0, 0, cable_clip_offset(frame_clip_screw, endstop_wires)])
|
||||
rotate([0, 90, 0])
|
||||
wire_hole(endstop_wires_hole_radius); // Z endstop wires
|
||||
|
||||
translate([0, fan_motor_wires_hole_radius - endstop_wires_hole_radius,
|
||||
-cable_clip_offset(frame_clip_screw, fan_motor_wires)])
|
||||
rotate([0, 90, 0])
|
||||
wire_hole(fan_motor_wires_hole_radius); // Z motor wires
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module bed_fan_assembly() {
|
||||
assembly("bed_fan_assembly");
|
||||
translate([left_stay_x, fan_y, fan_z])
|
||||
rotate([0, -90, 0]) {
|
||||
translate([0, 0, -(sheet_thickness(frame) + fan_depth(case_fan)) / 2])
|
||||
fan_assembly(case_fan, sheet_thickness(frame) + fan_guard_thickness());
|
||||
|
||||
translate([0, 0, sheet_thickness(frame) / 2])
|
||||
color([0,1,0]) render() fan_guard(case_fan);
|
||||
}
|
||||
end("bed_fan_assembly");
|
||||
}
|
||||
|
||||
module electronics_assembly() {
|
||||
thickness = sheet_thickness(frame) + washer_thickness(M3_washer) * 2;
|
||||
psu_screw = screw_longer_than(thickness + 2);
|
||||
if(psu_screw > thickness + 5)
|
||||
echo("psu_screw too long");
|
||||
|
||||
assembly("electronics_assembly");
|
||||
translate([right_stay_x + sheet_thickness(frame) / 2, sanguinololu_y, sanguinololu_z])
|
||||
rotate([90, 0, 90]) {
|
||||
sanguinololu_screw_positions()
|
||||
pcb_spacer_assembly();
|
||||
|
||||
translate([0, 0, pcb_spacer_height()])
|
||||
sanguinololu();
|
||||
}
|
||||
|
||||
translate([right_stay_x + sheet_thickness(frame) / 2, psu_y, psu_z])
|
||||
rotate([0, -90, 180]) {
|
||||
psu_screw_positions(psu) group() {
|
||||
translate([0, 0, -sheet_thickness(frame)])
|
||||
rotate([180, 0, 0])
|
||||
screw_and_washer(M3_cap_screw, psu_screw, true);
|
||||
}
|
||||
psu(psu);
|
||||
}
|
||||
end("electronics_assembly");
|
||||
}
|
||||
|
||||
module frame_assembly(show_gantry = true) {
|
||||
assembly("frame_assembly");
|
||||
|
||||
ribbon_clamp_z = height - base_clearance - ribbon_clamp_width(frame_screw);
|
||||
|
||||
translate([motor_end - x_motor_offset(), gantry_setback, ribbon_clamp_z])
|
||||
rotate([90, 0, 0]) {
|
||||
if(frame_nuts)
|
||||
ribbon_clamp_assembly(x_end_ways, frame_screw, frame_screw_length, sheet_thickness(frame), false, true);
|
||||
else
|
||||
ribbon_clamp_assembly(x_end_ways, frame_screw, frame_screw_length);
|
||||
|
||||
translate([0, ribbon_clamp_width(frame_screw) / 2, 0])
|
||||
rotate([90, 0, 90])
|
||||
cable_strip(ribbon_clamp_slot(x_end_ways) - 1, gantry_setback - x_end_ribbon_clamp_y(),
|
||||
(Z_travel + (ribbon_clamp_z - (Z_travel + Z0 + x_end_ribbon_clamp_z()))) * 2,
|
||||
Z + Z0 + x_end_ribbon_clamp_z() - ribbon_clamp_z, 50);
|
||||
}
|
||||
|
||||
translate([X_origin, cable_clamp_y,0]) {
|
||||
ribbon_clamp_assembly(bed_ways, base_screw, base_screw_length);
|
||||
|
||||
translate([0, ribbon_clamp_width(base_screw), 0])
|
||||
rotate([90, 0, 90])
|
||||
cable_strip(ribbon_clamp_slot(bed_ways) - 1, Y_carriage_height - sheet_thickness(Y_carriage) / 2, Y_travel, Y);
|
||||
}
|
||||
|
||||
place_cable_clips();
|
||||
|
||||
frame_base();
|
||||
|
||||
if(show_gantry) {
|
||||
|
||||
fixing_blocks()
|
||||
fixing_block_assembly();
|
||||
|
||||
fixing_blocks(true)
|
||||
fixing_block_assembly(true);
|
||||
|
||||
frame_stay(true, eta);
|
||||
frame_stay(false);
|
||||
frame_gantry();
|
||||
}
|
||||
|
||||
end("frame_assembly");
|
||||
}
|
||||
|
||||
module machine_assembly() {
|
||||
assembly("machine_assembly");
|
||||
|
||||
show_bed = true;
|
||||
|
||||
translate([0,0, sheet_thickness(base)]) {
|
||||
bed_fan_assembly();
|
||||
electronics_assembly();
|
||||
|
||||
x_axis_assembly(true);
|
||||
z_axis_assembly();
|
||||
y_axis_assembly(show_bed);
|
||||
//
|
||||
// Draw the possibly transparent bits last
|
||||
//
|
||||
frame_assembly(true);
|
||||
}
|
||||
end("machine_assembly");
|
||||
}
|
||||
|
||||
|
||||
machine_assembly();
|
||||
//frame_assembly();
|
||||
|
||||
module frame_base_dxf() projection(cut = true) translate([0,0, sheet_thickness(base) / 2]) frame_base();
|
||||
|
||||
module frame_left_dxf() projection(cut = true) translate([0, -gantry_setback - sheet_thickness(frame), left_stay_x]) rotate([0, 90, 0]) frame_stay(true);
|
||||
|
||||
module frame_right_dxf() projection(cut = true) translate([0, -gantry_setback - sheet_thickness(frame), right_stay_x]) rotate([0, 90, 0]) frame_stay(false);;
|
||||
|
||||
module frame_gantry_and_y_carriage_dxf() projection(cut = true) {
|
||||
translate([0,0, gantry_setback + sheet_thickness(frame) / 2]) rotate([-90, 0, 0]) frame_gantry();
|
||||
translate([X_origin, height - gantry_thickness - Y_carriage_depth / 2 -1, 0]) y_carriage();
|
||||
}
|
||||
|
||||
module frame_gantry_dxf() projection(cut = true)
|
||||
translate([0,0, gantry_setback + sheet_thickness(frame) / 2]) rotate([-90, 0, 0]) frame_gantry();
|
||||
|
||||
module y_carriage_dxf() projection(cut = true) y_carriage();
|
||||
|
||||
|
||||
|
||||
|
||||
echo("Width: ", base_width, " Depth: ", base_depth, " Height: ", height + sheet_thickness(base));
|
||||
|
||||
echo(left_w, window_width, right_w);
|
||||
|
||||
echo("X bar: ", X_bar_length, " Y Bar 1: ", Y_bar_length, " Y Bar 2: ", Y_bar_length2, " Z Bar: ", Z_bar_length);
|
41
scad/pcb_spacer.scad
Normal file
41
scad/pcb_spacer.scad
Normal file
@ -0,0 +1,41 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
include <conf/config.scad>
|
||||
|
||||
pcb_screw_length = frame_nuts ?
|
||||
screw_longer_than(2 * washer_thickness(M3_washer) + pcb_thickness + sheet_thickness(frame) + nut_thickness(M3_nut, true)) : 16;
|
||||
|
||||
function pcb_spacer_height() = frame_nuts ? 3 : max(3, 16 - 2 * washer_thickness(M3_washer) - pcb_thickness - sheet_thickness(frame));
|
||||
|
||||
module pcb_spacer_stl(screw = M3_cap_screw, h = pcb_spacer_height()) {
|
||||
stl("pcb_spacer");
|
||||
|
||||
r = screw_clearance_radius(screw);
|
||||
|
||||
difference() {
|
||||
cylinder(r = corrected_diameter(r * 2) / 2 + 2, h = h, center = false);
|
||||
translate([0, 0, -0.5])
|
||||
poly_cylinder(r = r, h = h + 1, center = false);
|
||||
}
|
||||
}
|
||||
|
||||
module pcb_spacer_assembly() {
|
||||
color([0,1,0]) render() pcb_spacer_stl();
|
||||
translate([0,0, pcb_spacer_height() + pcb_thickness])
|
||||
screw_and_washer(M3_cap_screw, pcb_screw_length, !frame_nuts);
|
||||
|
||||
if(frame_nuts)
|
||||
translate([0, 0, -sheet_thickness(frame)])
|
||||
rotate([180, 0, 0])
|
||||
nut_and_washer(screw_nut(M3_cap_screw), true);
|
||||
}
|
||||
|
||||
if(0)
|
||||
pcb_spacer_stl();
|
||||
else
|
||||
pcb_spacer_assembly();
|
48
scad/positions.scad
Normal file
48
scad/positions.scad
Normal file
@ -0,0 +1,48 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// Work out the positions and size of things
|
||||
//
|
||||
use <y-motor-bracket.scad>
|
||||
use <x-carriage.scad>
|
||||
use <x-end.scad>
|
||||
|
||||
|
||||
Y_carriage_height = y_motor_bracket_height() + X_carriage_clearance + sheet_thickness(Y_carriage) / 2;
|
||||
|
||||
bed_height = Y_carriage_height + sheet_thickness(Y_carriage) / 2 + pillar_height(bed_pillars) + washer_thickness(M3_washer) + bed_thickness;
|
||||
|
||||
Z0 = floor(bed_height + nozzle_length - x_carriage_offset());
|
||||
|
||||
height = Z0 + Z_travel + x_end_height() + bar_clamp_depth + axis_endstop_clearance + base_clearance;
|
||||
|
||||
gantry_thickness = height - max(bed_height + Z_travel + Z_clearance, Y_carriage_depth + 1);
|
||||
|
||||
gantry_setback = X_carriage_clearance + x_carriage_width() / 2;
|
||||
|
||||
Z_bar_spacing = X_travel + x_carriage_length() + 2 * (axis_endstop_clearance + Z_bearings[1] / 2);
|
||||
|
||||
base_width = base_clearance - x_idler_overhang() + Z_bar_spacing -x_motor_overhang() + base_clearance;
|
||||
|
||||
base_depth = Y_travel + Y_carriage_depth + 2 * base_clearance + 2 * axis_endstop_clearance;
|
||||
|
||||
window_width = ceil(Y_carriage_width + Y_carriage_clearance * 2);
|
||||
stay_depth = stays_from_window ? window_width / 2 : base_depth / 2 - (gantry_setback + sheet_thickness(frame));
|
||||
stay_height = single_piece_frame && !stays_from_window ? height : height - gantry_thickness - 1;
|
||||
|
||||
idler_end = -base_width / 2 + base_clearance - x_idler_overhang();
|
||||
motor_end = base_width / 2 - base_clearance + x_motor_overhang();
|
||||
X_origin = (idler_end + motor_end) / 2 + nozzle_x_offset;
|
||||
left_w = ceil((base_width - window_width)/2 + X_origin);
|
||||
right_w = ceil((base_width - window_width)/2 - X_origin);
|
||||
|
||||
|
||||
Y_belt_height = y_motor_height() + pulley_inner_radius + belt_thickness(Y_belt);
|
||||
|
||||
Y_bar_height = Y_belt_height;
|
||||
Y_belt_clamp_height = Y_carriage_height - Y_belt_height - sheet_thickness(Y_carriage) / 2;
|
||||
Y_bearing_holder_height = Y_carriage_height - Y_bar_height - sheet_thickness(Y_carriage) / 2;
|
31
scad/pulley.scad
Normal file
31
scad/pulley.scad
Normal file
@ -0,0 +1,31 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
include <conf/config.scad>
|
||||
|
||||
module pulley_stl() {
|
||||
stl("pulley");
|
||||
color([1,0,0])
|
||||
translate([-10, -10, 0])
|
||||
import("../imported_stls/pulley.stl");
|
||||
}
|
||||
|
||||
module pulley_assembly() {
|
||||
color([1,0,0]) render() pulley_stl();
|
||||
rotate([90, 0, 0]) {
|
||||
translate([0, 4, -5/2 - 6])
|
||||
screw(M3_grub_screw, 6);
|
||||
translate([0, 4, -6])
|
||||
rotate([0,0,30])
|
||||
nut(M3_nut);
|
||||
}
|
||||
}
|
||||
|
||||
if(1)
|
||||
pulley_assembly();
|
||||
else
|
||||
pulley_stl();
|
91
scad/ribbon_clamp.scad
Normal file
91
scad/ribbon_clamp.scad
Normal file
@ -0,0 +1,91 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// Clamps for ribbon cable plus cable_strip
|
||||
//
|
||||
include <conf/config.scad>
|
||||
|
||||
thickness = 5;
|
||||
slot_depth = 1.3;
|
||||
min_gap = 1.5;
|
||||
|
||||
function ribbon_clamp_slot(ways) = ways * 0.05 * 25.4 + 2;
|
||||
function ribbon_clamp_pitch(ways, screw_type) = ribbon_clamp_slot(ways) + 2 * (screw_clearance_radius(screw_type) + min_gap);
|
||||
function ribbon_clamp_width(screw_type) = washer_diameter(screw_washer(screw_type)) + 2;
|
||||
function ribbon_clamp_length(ways, screw_type) = ribbon_clamp_pitch(ways, screw_type) + ribbon_clamp_width(screw_type);
|
||||
function ribbon_clamp_thickness() = thickness;
|
||||
|
||||
module ribbon_clamp_holes(ways, screw_type) {
|
||||
pitch = ribbon_clamp_pitch(ways, screw_type);
|
||||
for(end = [-1, 1])
|
||||
translate([end * pitch / 2, 0, 0])
|
||||
child();
|
||||
}
|
||||
|
||||
module ribbon_clamp(ways, screw_type) {
|
||||
hole_rad = screw_clearance_radius(screw_type);
|
||||
stl(str("ribbon_clamp_",ways,"_", 20 * hole_rad));
|
||||
rad = ribbon_clamp_width(screw_type) / 2;
|
||||
slot = ribbon_clamp_slot(ways);
|
||||
pitch = ribbon_clamp_pitch(ways, screw_type);
|
||||
translate([0,0, -thickness / 2]) difference() {
|
||||
//
|
||||
// body
|
||||
//
|
||||
slot(r = rad, l = pitch, h = thickness, center = true);
|
||||
//
|
||||
// screw holes
|
||||
//
|
||||
ribbon_clamp_holes(ways, screw_type)
|
||||
poly_cylinder(r = hole_rad, h = thickness + 1, center = true);
|
||||
//
|
||||
// Slot
|
||||
//
|
||||
translate([0, 0,thickness - slot_depth])
|
||||
cube([slot, 2 * rad + 1,thickness], center = true);
|
||||
}
|
||||
}
|
||||
|
||||
module ribbon_clamp_assembly(ways, screw_type, screw_length, panel_thickness = 0, vertical = false, washer = false) {
|
||||
color([1,0,0])
|
||||
render() rotate([180, 0, 0])
|
||||
ribbon_clamp(ways, screw_type);
|
||||
|
||||
translate([0,0, thickness])
|
||||
ribbon_clamp_holes(ways, screw_type)
|
||||
screw_and_washer(screw_type, screw_length);
|
||||
|
||||
if(panel_thickness != 0)
|
||||
translate([0,0, - panel_thickness])
|
||||
ribbon_clamp_holes(ways, screw_type)
|
||||
rotate([180, 0, vertical ? 90 : 0])
|
||||
if(washer)
|
||||
nut_and_washer(screw_nut(screw_type), true);
|
||||
else
|
||||
nut(screw_nut(screw_type), true);
|
||||
}
|
||||
|
||||
module ribbon_clamp_12_33_stl() translate([0,0,thickness]) ribbon_clamp(12, M3_cap_screw);
|
||||
module ribbon_clamp_20_33_stl() translate([0,0,thickness]) ribbon_clamp(20, M3_cap_screw);
|
||||
module ribbon_clamp_20_40_stl() translate([0,0,thickness]) ribbon_clamp(20, No6_screw);
|
||||
module ribbon_clamp_20_44_stl() translate([0,0,thickness]) ribbon_clamp(20, M4_cap_screw);
|
||||
module ribbon_clamp_22_33_stl() translate([0,0,thickness]) ribbon_clamp(22, M3_cap_screw);
|
||||
module ribbon_clamp_22_40_stl() translate([0,0,thickness]) ribbon_clamp(22, No6_screw);
|
||||
module ribbon_clamp_22_44_stl() translate([0,0,thickness]) ribbon_clamp(22, M4_cap_screw);
|
||||
|
||||
if(1)
|
||||
ribbon_clamp_assembly(20, M4_cap_screw, 20, 4);
|
||||
|
||||
else {
|
||||
translate([0,-12,0]) ribbon_clamp(bed_ways, cap_screw);
|
||||
translate([0,0,0]) ribbon_clamp(bed_ways, cap_screw);
|
||||
translate([0,12,0]) ribbon_clamp(bed_ways, base_screw);
|
||||
translate([0,25,0]) ribbon_clamp(x_end_ways, frame_screw);
|
||||
translate([0,37,0]) ribbon_clamp(x_end_ways, M3_cap_screw);
|
||||
translate([0,48,0]) ribbon_clamp(extruder_ways, M3_cap_screw);
|
||||
translate([0,59,0]) ribbon_clamp(extruder_ways, M3_cap_screw);
|
||||
}
|
28
scad/utils/bom.scad
Normal file
28
scad/utils/bom.scad
Normal file
@ -0,0 +1,28 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// BOM generation
|
||||
//
|
||||
module assembly(name) { // start an assembly
|
||||
if(bom > 0)
|
||||
echo(str(name, "/"));
|
||||
}
|
||||
|
||||
module end(name) { // end an assembly
|
||||
if(bom > 0)
|
||||
echo(str("/",name));
|
||||
}
|
||||
|
||||
module stl(name) { // name an stl
|
||||
if(bom > 0)
|
||||
echo(str(name,".stl"));
|
||||
}
|
||||
|
||||
module vitamin(name) { // name a vitamin
|
||||
if(bom > 1)
|
||||
echo(name);
|
||||
}
|
26
scad/utils/cables.scad
Normal file
26
scad/utils/cables.scad
Normal file
@ -0,0 +1,26 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// Cable sizes
|
||||
//
|
||||
function cable_wires(cable) = cable[0];
|
||||
function cable_wire_size(cable) = cable[1];
|
||||
|
||||
// numbers from http://mathworld.wolfram.com/CirclePacking.html
|
||||
function cable_radius(cable) = ceil([0, 1, 2, 2.15, 2.41, 2.7, 3, 3][cable_wires(cable)] * cable_wire_size(cable)) / 2; // radius of a bundle
|
||||
|
||||
function wire_hole_radius(cable) = cable_radius(cable) + 0.5;
|
||||
|
||||
module wire_hole(r) {
|
||||
cylinder(r = r, h = 100, center = true);
|
||||
}
|
||||
|
||||
// arrangement of bundle in flat cable clip
|
||||
function cable_bundle(cable) = [[0,0], [1,1], [2,1], [2, 0.5 + sin(60)], [2,2], [3, 0.5 + sin(60)], [3,2]][cable_wires(cable)];
|
||||
|
||||
function cable_width(cable) = cable_bundle(cable)[0] * cable_wire_size(cable); // width in flat clip
|
||||
function cable_height(cable) = cable_bundle(cable)[1] * cable_wire_size(cable); // height in flat clip
|
30
scad/utils/polyholes.scad
Normal file
30
scad/utils/polyholes.scad
Normal file
@ -0,0 +1,30 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// See http://hydraraptor.blogspot.com/2011/02/polyholes.html
|
||||
//
|
||||
function sides(r) = max(round(4 *r),3);
|
||||
function corrected_radius(r,n) = 0.1 + r / cos(180 / n);
|
||||
function corrected_diameter(d) = 0.2 + d / cos(180 / sides(d / 2));
|
||||
|
||||
module poly_circle(r, center = false) {
|
||||
n = sides(r);
|
||||
circle(r = corrected_radius(r,n), $fn = n, center = center);
|
||||
}
|
||||
|
||||
module poly_cylinder(r, h, center = false) {
|
||||
n = sides(r);
|
||||
cylinder(h = h, r = corrected_radius(r,n), $fn = n, center = center);
|
||||
}
|
||||
|
||||
module poly_d_cylinder(r, center = false) {
|
||||
n = sides(r);
|
||||
r = corrected_radius(r,n);
|
||||
cylinder(h = h, r = r, $fn = n, center = center);
|
||||
translate([0, -r, 0])
|
||||
cube([r, 2 * r, h]);
|
||||
}
|
46
scad/utils/teardrops.scad
Normal file
46
scad/utils/teardrops.scad
Normal file
@ -0,0 +1,46 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// For making horizontal holes that don't need support material
|
||||
// Small holes can get away without it but they print better with truncated teardrops
|
||||
//
|
||||
module teardrop_2D(r, truncate = true) {
|
||||
difference() {
|
||||
union() {
|
||||
circle(r = r, center = true);
|
||||
translate([0,r / sqrt(2),0])
|
||||
rotate([0,0,45])
|
||||
square([r, r], center = true);
|
||||
}
|
||||
if(truncate)
|
||||
translate([0, r * 2, 0])
|
||||
square([2 * r, 2 * r], center = true);
|
||||
}
|
||||
}
|
||||
|
||||
module teardrop(h, r, center, truncate = true)
|
||||
linear_extrude(height = h, convexity = 2, center = center)
|
||||
teardrop_2D(r, truncate);
|
||||
|
||||
module teardrop_plus(h, r, center, truncate = true)
|
||||
teardrop(h, r + layer_height / 4, center, truncate);
|
||||
|
||||
|
||||
module tearslot(h, r, w, center)
|
||||
linear_extrude(height = h, convexity = 6, center = center)
|
||||
hull() {
|
||||
translate([-w/2,0,0]) teardrop_2D(r, true);
|
||||
translate([ w/2,0,0]) teardrop_2D(r, true);
|
||||
}
|
||||
|
||||
module vertical_tearslot(h, r, l, center = true)
|
||||
linear_extrude(height = h, convexity = 6, center = center)
|
||||
hull() {
|
||||
translate([0, l / 2]) teardrop_2D(r, true);
|
||||
translate([0, -l / 2, 0])
|
||||
circle(r = r, center = true);
|
||||
}
|
29
scad/vitamins/ball-bearings.scad
Normal file
29
scad/vitamins/ball-bearings.scad
Normal file
@ -0,0 +1,29 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// Ball bearings
|
||||
//
|
||||
BB624 = [4, 13, 5, "624"]; // 624 ball bearing for idlers
|
||||
BB608 = [8, 22, 7, "608"]; // 608 bearings for wades
|
||||
|
||||
function ball_bearing_diameter(type) = type[1];
|
||||
function ball_bearing_width(type) = type[2];
|
||||
|
||||
module ball_bearing(type) {
|
||||
vitamin(str("BB",type[3],": Ball bearing ",type[3]," ",type[0], " x ", type[1], " x ", type[2]));
|
||||
rim = type[1] / 10;
|
||||
|
||||
color([0.7,0.7,0.7]) render() difference() {
|
||||
cylinder(r = type[1] / 2, h = type[2], center = true);
|
||||
cylinder(r = type[0] / 2, h = type[2] + 1, center = true);
|
||||
for(z = [-type[2] / 2, type[2] / 2])
|
||||
translate([0,0,z]) difference() {
|
||||
cylinder(r = (type[1] - rim) / 2, h = 2, center = true);
|
||||
cylinder(r = (type[0] + rim) / 2, 2, center = true);
|
||||
}
|
||||
}
|
||||
}
|
68
scad/vitamins/belts.scad
Normal file
68
scad/vitamins/belts.scad
Normal file
@ -0,0 +1,68 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// Belt model
|
||||
//
|
||||
T5x6 = [5, 6, 2.25];
|
||||
T5x10 = [5, 10, 2.25];
|
||||
|
||||
function belt_pitch(type) = type[0];
|
||||
function belt_width(type) = type[1];
|
||||
function belt_thickness(type) = type[2];
|
||||
|
||||
module belt(type, x1, y1, r1, x2, y2, r2, gap = 0) {
|
||||
width = belt_width(type);
|
||||
thickness = belt_thickness(type);
|
||||
|
||||
pi = 3.14159265;
|
||||
dx = x2 - x1;
|
||||
dy = y2 - y1;
|
||||
|
||||
length = pi * (r1 + r2) + 2 * sqrt(dx * dx + dy * dy) - gap;
|
||||
vitamin(str("BT", belt_pitch(type),width, round(length), ": Belt T", belt_pitch(type)," x ", width, " x ", round(length)));
|
||||
|
||||
linear_extrude(height = width, center = true, convexity = 6) {
|
||||
difference() {
|
||||
hull() { // outside of belt
|
||||
translate([x1,y1])
|
||||
circle(r = r1 + thickness, center = true);
|
||||
translate([x2,y2])
|
||||
circle(r = r2 + thickness, center = true);
|
||||
}
|
||||
hull() { // inside of belt
|
||||
translate([x1,y1])
|
||||
circle(r = r1, center = true);
|
||||
translate([x2,y2])
|
||||
circle(r = r2, center = true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module twisted_belt(type, x1, y1, r1, x2, y2, r2, gap = 0) {
|
||||
dx = x2 - x1;
|
||||
dy = y2 - y1;
|
||||
|
||||
angle = atan2(dy, dx) - atan2((r2 - r1), dx);
|
||||
|
||||
union() {
|
||||
difference() {
|
||||
belt(type, x1, y1, r1, x2, y2, r2, gap);
|
||||
translate([x1, y1 - r1 - belt_thickness(type) / 2, 0])
|
||||
rotate([0,0, angle])
|
||||
translate([dx / 2, 0, 0])
|
||||
cube([dx, belt_thickness(type) + 1 , belt_width(type) + 1], center = true);
|
||||
}
|
||||
translate([x1, y1 - r1 - belt_thickness(type) / 2, 0])
|
||||
rotate([0,90, angle])
|
||||
linear_extrude(height = dx, twist = 180)
|
||||
square([belt_width(type), belt_thickness(type)], center = true);
|
||||
}
|
||||
}
|
||||
|
||||
//twisted_belt(T5x6, 10, 11-4.87, 4.87, 200, 20, 11);
|
||||
//twisted_belt(T5x6, -374, -1.55, 6.5, 0, 0, 4.95);
|
71
scad/vitamins/bulldog.scad
Normal file
71
scad/vitamins/bulldog.scad
Normal file
@ -0,0 +1,71 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// Crude representation of a bulldog clip
|
||||
//
|
||||
small_bulldog = [19, 12, 8, 0.25, 2.67, 1, 16];
|
||||
|
||||
function bulldog_length(type) = type[0];
|
||||
function bulldog_depth(type) = type[1];
|
||||
function bulldog_height(type) = type[2];
|
||||
function bulldog_thickness(type) = type[3];
|
||||
function bulldog_tube(type) = type[4] / 2;
|
||||
function bulldog_radius(type) = type[5];
|
||||
function bulldog_handle_length(type) = type[6];
|
||||
|
||||
module bulldog_shape(depth, height, radius, open) {
|
||||
hull() {
|
||||
translate([-depth / 2 + radius, height / 2 - radius]) circle(radius);
|
||||
translate([-depth / 2 + radius, -height / 2 + radius]) circle(radius);
|
||||
translate([ depth / 2, 0]) square([0.1, open], center = true);
|
||||
}
|
||||
}
|
||||
|
||||
module shell(length, width, height, wall) {
|
||||
difference() {
|
||||
linear_extrude(height = height, center = true, convexity = 5)
|
||||
child();
|
||||
linear_extrude(height = height + 1, center = true, convexity = 5)
|
||||
difference() {
|
||||
square([length - 2 * wall, width - 2 * wall], center = true);
|
||||
minkowski() {
|
||||
difference() {
|
||||
square([length + 1, width + 1], center = true);
|
||||
translate([10,0])
|
||||
square([length + 1, 2 * wall + eta], center = true);
|
||||
child();
|
||||
}
|
||||
circle(r = wall, center = true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module bulldog(type, open = 4) {
|
||||
tube = bulldog_tube(type);
|
||||
thickness = bulldog_thickness(type);
|
||||
depth = bulldog_depth(type);
|
||||
gap = open + thickness * 2;
|
||||
|
||||
vitamin(str("BD00", bulldog_length(type), ": ", bulldog_length(type), "mm bulldog clip"));
|
||||
|
||||
render() translate([depth / 2 - thickness - eta, 0, 0])
|
||||
union() {
|
||||
difference() {
|
||||
rotate([90, 0, 0])
|
||||
shell(depth, bulldog_height(type), bulldog_length(type), thickness)
|
||||
bulldog_shape(depth, bulldog_height(type), bulldog_radius(type), gap);
|
||||
translate([depth - tube - eta, 0, 0])
|
||||
cube([depth, bulldog_length(type) + 1, 100], center = true);
|
||||
}
|
||||
for(side = [-1,1])
|
||||
translate([bulldog_depth(type) / 2 - tube, 0, side * (gap / 2 + tube)])
|
||||
rotate([90,0,0])
|
||||
tube(or = tube, ir = tube - thickness, h = bulldog_length(type));
|
||||
}
|
||||
}
|
96
scad/vitamins/cable_strip.scad
Normal file
96
scad/vitamins/cable_strip.scad
Normal file
@ -0,0 +1,96 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// A strip of polypropylene used with ribbon cable to make a cable flexible in one direction only.
|
||||
//
|
||||
module cable_strip(width, depth, travel, x, extra = 15) {
|
||||
|
||||
thickness = 0.5;
|
||||
|
||||
radius = depth / 2;
|
||||
|
||||
top = travel / 4 + extra + x / 2;
|
||||
bottom = travel / 4 + extra - x /2;
|
||||
|
||||
length = max(top, bottom);
|
||||
|
||||
total = ceil(top + bottom + PI * depth);
|
||||
w = ceil(width);
|
||||
|
||||
vitamin(str("PP", thickness * 10, w, total,": Polypropylene strip ", total, "mm x ", w, "mm x ", thickness, "mm"));
|
||||
|
||||
color([1,0,1]) render() linear_extrude(height = w, center = true, convexity = 4)
|
||||
difference() {
|
||||
union() {
|
||||
translate([-bottom, radius])
|
||||
circle(r = radius, center = true);
|
||||
|
||||
translate([-bottom, 0])
|
||||
square([length, depth]);
|
||||
}
|
||||
union() {
|
||||
translate([-bottom, radius])
|
||||
circle(r = radius - thickness, center = true);
|
||||
|
||||
translate([-bottom, thickness])
|
||||
square([length + 1, depth - thickness * 2]);
|
||||
}
|
||||
translate([0, -thickness / 2])
|
||||
square([travel, thickness * 2]);
|
||||
|
||||
translate([x, depth - thickness - thickness / 2])
|
||||
square([travel, thickness * 2]);
|
||||
}
|
||||
}
|
||||
|
||||
//cable_strip(20, 50, 200, -100);
|
||||
|
||||
module ellipse(xr, yr, center = true)
|
||||
{
|
||||
scale([1, yr / xr])
|
||||
circle(r = xr, center = center);
|
||||
}
|
||||
|
||||
module elliptical_cable_strip(width, p1, p2, pmax, extra = 15) {
|
||||
thickness = 0.5;
|
||||
w = ceil(width);
|
||||
|
||||
max_delta = pmax - p1;
|
||||
delta = p2 - p1;
|
||||
|
||||
A = abs(max_delta[0] / 2);
|
||||
B = 50;
|
||||
|
||||
length = ceil(PI * pow((pow(A,1.5) + pow(B,1.5))/2, 1/1.5));
|
||||
total = length + 2 * extra;
|
||||
|
||||
vitamin(str("PP", thickness * 10, w, total,": Polypropylene strip ", total, "mm x ", w, "mm x ", thickness, "mm"));
|
||||
|
||||
a = abs(delta[0] / 2);
|
||||
b = pow(2 * pow(length / PI, 1.5) - pow(a, 1.5), 1/1.5);
|
||||
|
||||
translate(p1 - [a, 0, 0])
|
||||
multmatrix(m = [ [1, 0, 0, 0],
|
||||
[delta[1] / delta[0], 1, 0, delta[1] / 2],
|
||||
[delta[2] / delta[0], 0, 1, delta[2] / 2],
|
||||
[0, 0, 0, 1] ])
|
||||
|
||||
color([1,0,1]) render() linear_extrude(height = w, center = true, convexity = 4)
|
||||
difference() {
|
||||
union() {
|
||||
square([(a + thickness) * 2, extra * 2], center = true);
|
||||
translate([0, -extra])
|
||||
ellipse((a + thickness), b + thickness);
|
||||
}
|
||||
translate([0, (b + 1) / 2])
|
||||
square([a * 2 + 1, b + 1], center = true);
|
||||
|
||||
square([a * 2, extra * 2], center = true);
|
||||
translate([0, -extra])
|
||||
ellipse(a, b);
|
||||
}
|
||||
}
|
136
scad/vitamins/d-connectors.scad
Normal file
136
scad/vitamins/d-connectors.scad
Normal file
@ -0,0 +1,136 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// D-connectors
|
||||
//
|
||||
|
||||
DCONN9 = [30.81, [18, 16.92], 24.99, [9.26, 8.36], 12.55, 10.72, 6.693, 1.12, 9];
|
||||
|
||||
function d_flange_length(type) = type[0];
|
||||
function d_flange_width(type) = type[4];
|
||||
function d_flange_thickness(type) = type[7];
|
||||
function d_mate_distance(type) = 8.5;
|
||||
|
||||
module d_pillar(type) {
|
||||
vitamin("DP0000: D-type connect pillar");
|
||||
rad = 5.37 / 2;
|
||||
height = 4.5;
|
||||
screw = 2.5;
|
||||
screw_length = 8;
|
||||
color([0.9,0.9,0.9]) render() translate([0,0, d_flange_thickness(type)]) difference() {
|
||||
union() {
|
||||
cylinder(r = rad, h = height, $fn = 6);
|
||||
translate([0,0, - screw_length + eta])
|
||||
cylinder(r = screw / 2, h = screw_length);
|
||||
}
|
||||
translate([0,0,1])
|
||||
cylinder(r = screw / 2, h = height);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
module d_plug(type, socket = false) {
|
||||
hole_r = 3.05 / 2;
|
||||
dwall = 0.5;
|
||||
|
||||
flange_length = d_flange_length(type);
|
||||
d_length = socket ? type[1][1] : type[1][0];
|
||||
hole_pitch = type[2];
|
||||
d_width = socket ? type[3][1] : type[3][0];
|
||||
flange_width = d_flange_width(type);
|
||||
d_height = type[6];
|
||||
back_height = type[5] - d_height;
|
||||
pins = type[8];
|
||||
|
||||
|
||||
if(socket)
|
||||
vitamin(str("DTYPES", pins, ": ", pins," way D socket"));
|
||||
else
|
||||
vitamin(str("DTYPEP", pins, ": ", pins," way D plug"));
|
||||
|
||||
module D(length, width, rad) {
|
||||
d = width / 2 - rad;
|
||||
offset = d * sin(10);
|
||||
|
||||
hull() {
|
||||
translate([-length / 2 + rad - offset, width / 2 - rad])
|
||||
circle(r = rad, center = true);
|
||||
translate([-length / 2 + rad + offset, -width / 2 + rad])
|
||||
circle(r = rad, center = true);
|
||||
|
||||
translate([length / 2 - rad + offset, width / 2 - rad])
|
||||
circle(r = rad, center = true);
|
||||
translate([length / 2 - rad - offset, -width / 2 + rad])
|
||||
circle(r = rad, center = true);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Shell
|
||||
//
|
||||
color([0.8, 0.8, 0.8]) render() difference() {
|
||||
union() {
|
||||
rounded_rectangle([flange_length, flange_width, d_flange_thickness(type)], 2, center = false);
|
||||
linear_extrude(height = d_height, convexity = 5)
|
||||
difference() {
|
||||
D(d_length, d_width, 2.5);
|
||||
D(d_length - 2 * dwall, d_width - 2 * dwall, 2.5 - dwall);
|
||||
}
|
||||
rotate([0,180,0])
|
||||
linear_extrude(height = back_height, convexity = 5)
|
||||
D(type[1][0] + 2 * dwall, type[3][0] + 2 * dwall, 2.5 + dwall);
|
||||
}
|
||||
|
||||
for(end = [-1, 1])
|
||||
translate([end * hole_pitch / 2, 0, 0])
|
||||
cylinder(r = hole_r, h = 10, center = true);
|
||||
}
|
||||
//
|
||||
// Insulator
|
||||
//
|
||||
color([0.2,0.2,0.2]) render() {
|
||||
translate([0,0, d_flange_thickness(type) + eta])
|
||||
rotate([0, 180, 0])
|
||||
linear_extrude(height = back_height + 1 + d_flange_thickness(type), convexity = 5)
|
||||
D(d_length - dwall, d_width - dwall, 2.5 - dwall/2);
|
||||
|
||||
if(socket)
|
||||
linear_extrude(height = d_height - eta, convexity = 5)
|
||||
difference() {
|
||||
D(d_length - dwall, d_width - dwall, 2.5 - dwall/2);
|
||||
for(i = [1 : pins])
|
||||
translate([(i - (pins + 1) / 2) * 2.77 / 2, (i % 2 - 0.5) * 2.84, 0])
|
||||
circle(r = 0.7);
|
||||
}
|
||||
|
||||
}
|
||||
//
|
||||
// Pins
|
||||
//
|
||||
render() for(i = [1 : pins])
|
||||
translate([(i - (pins + 1) / 2) * 2.77 / 2, (i % 2 - 0.5) * 2.84, 0]) {
|
||||
union() {
|
||||
if(!socket)
|
||||
translate([0,0, - 0.5])
|
||||
cylinder(r = 0.5, h = d_height);
|
||||
rotate([180, 0, 0])
|
||||
difference() {
|
||||
cylinder(r = 1, h = 8);
|
||||
cylinder(r = 0.45, h = 9);
|
||||
translate([0, (i % 2 - 0.5) * -4, 8])
|
||||
rotate([45, 0, 0])
|
||||
cube(3, center = true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module d_socket(connector) d_plug(connector, true);
|
||||
|
||||
//d_plug(DCONN9);
|
||||
//d_pillar();
|
51
scad/vitamins/electronics.scad
Normal file
51
scad/vitamins/electronics.scad
Normal file
@ -0,0 +1,51 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// Model by Václav 'ax' Hula
|
||||
//
|
||||
function sanguinololu_width() = 2 * 25.4;
|
||||
function sanguinololu_length() = 4 * 25.4;
|
||||
|
||||
|
||||
module sanguinololu() {
|
||||
vitamin("SANGUINOL: Electronics e.g. Sanguinolou");
|
||||
import("../imported_stls/sanguinololu.stl");
|
||||
}
|
||||
|
||||
module sanguinololu_screw_positions() {
|
||||
inset = 1.5 * 2.54;
|
||||
|
||||
for(x = [inset, sanguinololu_width() - inset])
|
||||
for(y = [inset, sanguinololu_length() - inset])
|
||||
translate([x, y, 0])
|
||||
child();
|
||||
}
|
||||
|
||||
KY240W = ["KY240W12L", 199, 110, 50, [[ 199 / 2 - 12, 110 / 2 - 93],
|
||||
[ 199 / 2 - 12, 110 / 2 - 9 ],
|
||||
[ 199 / 2 - 138, 110 / 2 - 93],
|
||||
[ 199 / 2 - 138, 110 / 2 - 9 ]]];
|
||||
|
||||
function psu_name(type) = type[0];
|
||||
function psu_length(type) = type[1];
|
||||
function psu_width(type) = type[2];
|
||||
function psu_height(type) = type[3];
|
||||
function psu_hole_list(type) = type[4];
|
||||
|
||||
module psu(type) {
|
||||
vitamin(str(psu_name(type),": PSU e.g. ", psu_name(type)));
|
||||
color([0.8, 0.8, 0.8])
|
||||
translate([0,0, psu_height(type) / 2])
|
||||
cube([psu_length(type), psu_width(type), psu_height(type)], center = true);
|
||||
|
||||
}
|
||||
|
||||
module psu_screw_positions(type) {
|
||||
for(point = psu_hole_list(type))
|
||||
translate(point)
|
||||
child();
|
||||
}
|
101
scad/vitamins/fans.scad
Normal file
101
scad/vitamins/fans.scad
Normal file
@ -0,0 +1,101 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
|
||||
// based on http://www.thingiverse.com/thing:8063 by MiseryBot, CC license
|
||||
|
||||
fan80x38 = [80, 38, 75, 35.75, M4_cap_screw, 40, 4.3, 84];
|
||||
fan60x25 = [60, 25, 57, 25, M3_cap_screw, 31.5, 3.6, 64];
|
||||
|
||||
function fan_width(type) = type[0];
|
||||
function fan_depth(type) = type[1];
|
||||
function fan_bore(type) = type[2];
|
||||
function fan_hole_pitch(type) = type[3];
|
||||
function fan_hub(type) = type[5];
|
||||
function fan_thickness(type) = type[6];
|
||||
function fan_outer_diameter(type) = type[7];
|
||||
|
||||
function fan_screw(type) = type[4];
|
||||
|
||||
module fan(type) {
|
||||
width = fan_width(type);
|
||||
depth = fan_depth(type);
|
||||
thickness = fan_thickness(type);
|
||||
hole_pitch = fan_hole_pitch(type);
|
||||
corner_radius = width / 2 - hole_pitch;
|
||||
screw = fan_screw(type);
|
||||
|
||||
vitamin(str("FAN", fan_width(type), fan_depth(type), ": Fan ", fan_width(type), " x ", fan_depth(type)));
|
||||
difference() {
|
||||
linear_extrude(height = depth, center = true, convexity = 4)
|
||||
difference() {
|
||||
//overall outside
|
||||
rounded_square(width, width, corner_radius);
|
||||
|
||||
//main inside bore, less hub
|
||||
difference() {
|
||||
circle(r = fan_bore(type) / 2, center = true);
|
||||
circle(r = fan_hub(type) / 2, center = true);
|
||||
}
|
||||
|
||||
//Mounting holes
|
||||
for(x = [-hole_pitch, hole_pitch])
|
||||
for(y = [-hole_pitch, hole_pitch])
|
||||
translate([x, y])
|
||||
circle(r = screw_clearance_radius(screw), center = true);
|
||||
}
|
||||
|
||||
//Remove outside ring
|
||||
difference() {
|
||||
cylinder(r = sqrt(2) * width / 2, h = depth - 2 * thickness, center = true);
|
||||
cylinder(r = fan_outer_diameter(type) / 2, h = depth - 2 * thickness + 0.2, center = true);
|
||||
}
|
||||
}
|
||||
|
||||
//Seven Blades
|
||||
linear_extrude(height = depth - 1, center = true, convexity = 4, twist = -30, slices = depth / 2)
|
||||
for(i= [0 : 6])
|
||||
rotate((360 * i) / 7)
|
||||
translate([0, -1.5 / 2])
|
||||
square([fan_bore(type) / 2 - 0.75, 1.5]);
|
||||
}
|
||||
|
||||
module fan_holes(type, poly = false) {
|
||||
//Mounting holes
|
||||
hole_pitch = fan_hole_pitch(type);
|
||||
screw = fan_screw(type);
|
||||
for(x = [-hole_pitch, hole_pitch])
|
||||
for(y = [-hole_pitch, hole_pitch])
|
||||
translate([x, y, 0])
|
||||
if(poly)
|
||||
poly_cylinder(r = screw_clearance_radius(screw), h = 100, center = true);
|
||||
else
|
||||
cylinder(r = screw_clearance_radius(screw), h = 100, center = true);
|
||||
|
||||
cylinder(r = fan_bore(type) / 2, h = 100, center = true);
|
||||
}
|
||||
|
||||
module fan_assembly(type, thickness) {
|
||||
color([0.2, 0.2, 0.2])
|
||||
render()
|
||||
fan(type);
|
||||
|
||||
hole_pitch = fan_hole_pitch(type);
|
||||
screw = fan_screw(type);
|
||||
washer = screw_washer(screw);
|
||||
nut = screw_nut(screw);
|
||||
for(x = [-hole_pitch, hole_pitch])
|
||||
for(y = [-hole_pitch, hole_pitch]) {
|
||||
translate([x, y, thickness + fan_depth(type) / 2])
|
||||
screw_and_washer(screw, screw_longer_than(thickness + fan_thickness(type) +
|
||||
washer_thickness(washer) + nut_thickness(nut, true)));
|
||||
translate([x, y, fan_depth(type) / 2 - fan_thickness(type)])
|
||||
rotate([180, 0, 0])
|
||||
nut(screw_nut(screw), true);
|
||||
}
|
||||
}
|
||||
|
||||
//fan(fan80x38);
|
||||
//fan(fan60x25);
|
21
scad/vitamins/linear-bearings.scad
Normal file
21
scad/vitamins/linear-bearings.scad
Normal file
@ -0,0 +1,21 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// Linear bearings
|
||||
//
|
||||
LM10UU = [29, 19, 10];
|
||||
LM8UU = [24, 15, 8];
|
||||
LM6UU = [19, 12, 6];
|
||||
LM4UU = [12, 8, 4];
|
||||
|
||||
module linear_bearing(type) {
|
||||
vitamin(str("LM",type[2],"UU: ","LM",type[2],"UU linear bearing"));
|
||||
color([0.7,0.7,0.7]) rotate([0,90,0]) difference() {
|
||||
cylinder(r = type[1] / 2, h = type[0], center = true);
|
||||
cylinder(r = type[2] / 2, h = type[0] + 1, center = true);
|
||||
}
|
||||
}
|
69
scad/vitamins/microswitch.scad
Normal file
69
scad/vitamins/microswitch.scad
Normal file
@ -0,0 +1,69 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// Microswitch used for endstops
|
||||
//
|
||||
|
||||
function microswitch_thickness() = 6.4;
|
||||
function microswitch_length() = 19.8;
|
||||
|
||||
function microswitch_first_hole_x_offset() = -2;
|
||||
|
||||
function microswitch_button_x_offset() = -(5.1 - microswitch_first_hole_x_offset()) + microswitch_length() / 2;
|
||||
function microswitch_hole_y_offset() = -8.4;
|
||||
|
||||
module microswitch_hole_positions()
|
||||
{
|
||||
for(x = [microswitch_first_hole_x_offset(), 7.5])
|
||||
translate([x, microswitch_hole_y_offset(), microswitch_thickness() / 2])
|
||||
child();
|
||||
}
|
||||
|
||||
module microswitch_holes(r = No2_pilot_radius, h = 7.5)
|
||||
{
|
||||
translate([0, 0, -microswitch_thickness() - h / 2])
|
||||
microswitch_hole_positions()
|
||||
teardrop_plus(r = r, h = h + 1, center = true);
|
||||
}
|
||||
|
||||
module microswitch_contact_space() {
|
||||
depth = 15;
|
||||
translate([-microswitch_first_hole_x_offset() + 0.75, -depth / 2 - 3, 0])
|
||||
cube([microswitch_length() - 2, depth, microswitch_thickness() - 2], center = true);
|
||||
}
|
||||
|
||||
module microswitch() {
|
||||
vitamin("SMMICRO: Microswitch");
|
||||
translate([-(5.1 + 9.5 - 7.5), -(8.4 + 2.5), -3.2 + (exploded ? 5 : 0)]) { // put operating point of button at the origin
|
||||
color([0,0,0]) render() difference() { // main body
|
||||
cube([19.8, 10.2, 6.4]);
|
||||
translate([10, 9.5, -1])
|
||||
cube([19.8, 10.2, 8]); // lower half of top
|
||||
translate([5.1, 2.5, -1])
|
||||
cylinder(r = 2.35 / 2, h = 8); // mounting holes
|
||||
translate([5.1 + 9.5, 2.5, -1])
|
||||
cylinder(r = 2.35 / 2, h = 8);
|
||||
}
|
||||
color([1,0.7,0]) render() // orange button
|
||||
translate([5.1 + 9.5 - 7.5,8.4 + 2.5 - 0.5,1.6])
|
||||
linear_extrude(height = 3.2)
|
||||
hull() {
|
||||
circle(r = 1);
|
||||
translate([0,-4])
|
||||
circle(r = 1);
|
||||
}
|
||||
color([1,1,0]) render() // yellow contacts
|
||||
for(x = [1.6, 1.6 + 8.8, 1.6 + 8.8 + 7.3])
|
||||
translate([x, 2.5 - 6.4, 1.6])
|
||||
difference() {
|
||||
cube([0.5, 7, 3.2]);
|
||||
translate([0, 1.6, 1.6])
|
||||
rotate([0,90,0])
|
||||
cylinder(r = 0.8, h = 5, center = true);
|
||||
}
|
||||
}
|
||||
}
|
93
scad/vitamins/nuts.scad
Normal file
93
scad/vitamins/nuts.scad
Normal file
@ -0,0 +1,93 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// Washers
|
||||
//
|
||||
M3_nut = [3, 6.4, 2.4, 4, M3_washer, M3_nut_trap_depth];
|
||||
M4_nut = [4, 8.1, 3.2, 5, M4_washer, M4_nut_trap_depth];
|
||||
M6_nut = [6, 11.5, 5, 8, M6_washer, M6_nut_depth];
|
||||
M8_nut = [8, 15, 6.5, 8, M8_washer, M8_nut_depth];
|
||||
|
||||
function nut_radius(type) = type[1] / 2;
|
||||
function nut_flat_radius(type) = nut_radius(type) * cos(30);
|
||||
function nut_thickness(type, nyloc = false) = nyloc ? type[3] : type[2];
|
||||
function nut_washer(type) = type[4];
|
||||
function nut_trap_depth(type) = type[5];
|
||||
|
||||
module nut(type, nyloc = false) {
|
||||
hole_rad = type[0] / 2;
|
||||
outer_rad = nut_radius(type);
|
||||
thickness = nut_thickness(type);
|
||||
nyloc_thickness = type[3];
|
||||
|
||||
if(nyloc)
|
||||
vitamin(str("NYLOCM", type[0], ": Nyloc nut M", type[0]));
|
||||
else
|
||||
vitamin(str("NUTM", type[0], ": Nut M", type[0]));
|
||||
|
||||
if(exploded && nyloc)
|
||||
cylinder(r = 0.2, h = 10);
|
||||
|
||||
color([0.7, 0.7, 0.7]) render() translate([0, 0, (exploded && nyloc) ? 10 : 0]) difference() {
|
||||
union() {
|
||||
cylinder(r = outer_rad, h = thickness, $fn = 6);
|
||||
if(nyloc)
|
||||
translate([0,0, eta])
|
||||
rounded_cylinder(r = outer_rad * cos(30) , h = nyloc_thickness, r2 = (nyloc_thickness - thickness) / 2);
|
||||
}
|
||||
translate([0,0,-1])
|
||||
cylinder(r = hole_rad, h = nyloc_thickness + 2);
|
||||
}
|
||||
}
|
||||
|
||||
module nut_and_washer(type, nyloc) {
|
||||
washer = nut_washer(type);
|
||||
translate([0, 0, exploded ? 7 : 0])
|
||||
washer(washer);
|
||||
translate([0,0, washer_thickness(washer)])
|
||||
nut(type, nyloc);
|
||||
}
|
||||
|
||||
M4_wingnut = [4, 10, 3.75, 8, M4_washer, 0, 22, 10, 6, 3];
|
||||
|
||||
module wingnut(type) {
|
||||
hole_rad = type[0] / 2;
|
||||
bottom_rad = nut_radius(type);
|
||||
top_rad = type[3] / 2;
|
||||
thickness = nut_thickness(type);
|
||||
wing_span = type[6];
|
||||
wing_height = type[7];
|
||||
wing_width = type[8];
|
||||
wing_thickness = type[9];
|
||||
|
||||
top_angle = asin((wing_thickness / 2) / top_rad);
|
||||
bottom_angle = asin((wing_thickness / 2) / bottom_rad);
|
||||
|
||||
vitamin(str("WING0", type[0], ": Wingnut M",type[0]));
|
||||
if(exploded)
|
||||
cylinder(r = 0.2, h = 10);
|
||||
|
||||
color([0.7,0.7,0.7]) render() translate([0, 0, exploded ? 10 : 0]) difference() {
|
||||
union() {
|
||||
cylinder(r1 = bottom_rad, r2 = top_rad, h = thickness);
|
||||
for(rot = [0, 180])
|
||||
rotate([90, 0, rot]) linear_extrude(height = wing_thickness, center = true)
|
||||
hull() {
|
||||
translate([wing_span / 2 - wing_width / 2, wing_height - wing_width / 2])
|
||||
circle(r = wing_width / 2, center = true);
|
||||
polygon([
|
||||
[bottom_rad * cos(top_angle) - eta, 0],
|
||||
[wing_span / 2 - wing_width / 2, wing_height - wing_width / 2],
|
||||
[top_rad * cos(top_angle) - eta, thickness],
|
||||
[bottom_rad * cos(top_angle) - eta, 0],
|
||||
]);
|
||||
}
|
||||
}
|
||||
translate([0,0,-1])
|
||||
cylinder(r = hole_rad, h = thickness + 2);
|
||||
}
|
||||
}
|
40
scad/vitamins/pillars.scad
Normal file
40
scad/vitamins/pillars.scad
Normal file
@ -0,0 +1,40 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// Nylon pillars
|
||||
//
|
||||
M3x13_pillar = [3, 13, 6.5, 6];
|
||||
M3x20_pillar = [3, 20, 5.5, 7];
|
||||
|
||||
function pillar_height(type) = type[1];
|
||||
|
||||
module pillar(type) {
|
||||
height = pillar_height(type);
|
||||
|
||||
vitamin(str("pillar M", type[0], "x", height));
|
||||
color([0.9,0.9,0.9]) render() difference() {
|
||||
cylinder(h = height, r = type[2] / 2);
|
||||
translate([0,0, height])
|
||||
cylinder(h = type[3] * 2, r = type[0] / 2, center = true);
|
||||
}
|
||||
color([1,1,0]) render() cylinder(h = type[3] * 2, r = type[0] / 2, center = true);
|
||||
|
||||
}
|
||||
|
||||
module hex_pillar(type) {
|
||||
height = pillar_height(type);
|
||||
|
||||
vitamin(str("HP0", type[0], height, " : Hex pillar M", type[0], " x ", height));
|
||||
color([0.9,0.9,0.9]) render() difference() {
|
||||
union() {
|
||||
cylinder(h = height, r = type[2] / 2, $fn = 6);
|
||||
cylinder(h = type[3] * 2, r = type[0] / 2, center = true);
|
||||
}
|
||||
translate([0,0, height])
|
||||
cylinder(h = type[3] * 2, r = type[0] / 2, center = true);
|
||||
}
|
||||
}
|
147
scad/vitamins/screws.scad
Normal file
147
scad/vitamins/screws.scad
Normal file
@ -0,0 +1,147 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// Screws
|
||||
//
|
||||
hs_cap = 0;
|
||||
hs_pan = 1;
|
||||
hs_cs = 2; // counter sunk
|
||||
hs_hex = 3;
|
||||
hs_grub= 4; // pulley set screw
|
||||
|
||||
M2p5_pan_screw = ["PS025", "M2.5 pan screw", hs_pan, 2.5, 4.7, 1.7, M2p5_washer, false, M2p5_tap_radius, M2p5_clearance_radius];
|
||||
|
||||
M2p5_cap_screw = ["CS025", "M2.5 cap screw", hs_cap, 2.5, 4.7, 2.0, M2p5_washer, false, M2p5_tap_radius, M2p5_clearance_radius];
|
||||
|
||||
M3_cap_screw = ["CS030", "M3 cap screw", hs_cap, 3, 5.5, 2.5, M3_washer, M3_nut, M3_tap_radius, M3_clearance_radius];
|
||||
M3_pan_screw = ["PS030", "M3 pan screw", hs_pan, 3, 5.4, 2.0, M3_washer, M3_nut, M3_tap_radius, M3_clearance_radius];
|
||||
M3_hex_screw = ["HX030", "M3 hex screw", hs_hex, 3, 6.4, 2.125, M3_washer, M3_nut, M3_tap_radius, M3_clearance_radius];
|
||||
M3_grub_screw = ["GB030", "M3 grub screw", hs_grub, 3, 1.6, 2.5, M3_washer, M3_nut, M3_tap_radius, M3_clearance_radius];
|
||||
|
||||
M4_cap_screw = ["CS040", "M4 cap screw", hs_cap, 4, 7.0, 3.0, M4_washer, M4_nut, M4_tap_radius, M4_clearance_radius];
|
||||
M4_hex_screw = ["HX040", "M4 hex screw", hs_hex, 4, 8.1, 2.925, M4_washer, M4_nut, M4_tap_radius, M4_clearance_radius];
|
||||
M4_pan_screw = ["PS040", "M4 pan screw", hs_pan, 4, 7.8, 3.3, M4_washer, M4_nut, M4_tap_radius, M4_clearance_radius];
|
||||
M8_hex_screw = ["HX080", "M8 hex screw", hs_hex, 8, 15, 5.65, M8_washer, M8_nut, M8_tap_radius, M8_clearance_radius];
|
||||
|
||||
No2_screw = ["PSW02", "No2 pan wood screw", hs_pan, 2.2, 4.2, 1.7, M2p5_washer, false, No2_pilot_radius, No2_clearance_radius];
|
||||
No4_screw = ["PSW04", "No4 pan wood screw", hs_pan, 3.0, 5.5, 2.0, M3p5_washer, false, No4_pilot_radius, No4_clearance_radius];
|
||||
No6_screw = ["PSW06", "No6 pan wood screw", hs_pan, 3.5, 6.7, 2.2, M4_washer, false, No6_pilot_radius, No6_clearance_radius];
|
||||
No6_cs_screw = ["PSW06", "No6 cs wood screw", hs_cs, 3.5, 7.0, 0, M4_washer, false, No6_pilot_radius, No6_clearance_radius];
|
||||
|
||||
function screw_washer(type) = type[6];
|
||||
function screw_nut(type) = type[7];
|
||||
function screw_pilot_hole(type) = type[8];
|
||||
function screw_clearance_radius(type) = type[9];
|
||||
function screw_radius(type) = type[3] / 2;
|
||||
function screw_head_radius(type) = type[4] / 2;
|
||||
|
||||
function screw_longer_than(x) = x <= 10 ? 10 :
|
||||
x <= 12 ? 12 :
|
||||
x <= 16 ? 16 :
|
||||
ceil(x / 5) * 5;
|
||||
|
||||
function screw_shorter_than(x) = x > 20 ? floor(x / 5) * 5 :
|
||||
x > 16 ? 16 :
|
||||
x > 12 ? 12 :
|
||||
10;
|
||||
|
||||
function screw_head_height(type) = type[2] == hs_cap ? type[4] :
|
||||
type[2] == hs_cs ? type[4] / 2 : type[5];
|
||||
|
||||
|
||||
module screw(type, length) {
|
||||
vitamin(str(type[0], length,": ",type[1], " x ", length));
|
||||
|
||||
head_type = type[2];
|
||||
rad = screw_radius(type) - eta;
|
||||
head_rad = screw_head_radius(type);
|
||||
if(exploded)
|
||||
cylinder(r = 0.2, h = 16);
|
||||
translate([0, 0, exploded ? length + 10 : 0]) {
|
||||
if(head_type == hs_cap) {
|
||||
assign(head_height = rad * 2,
|
||||
socket_rad = type[5] / cos(30) / 2,
|
||||
socket_depth = 2 * rad / 3)
|
||||
color([0.2,0.2,0.2]) render() difference() {
|
||||
union() {
|
||||
cylinder(r = head_rad, h = head_height);
|
||||
translate([0,0, - length + eta])
|
||||
cylinder(r = rad, h = length);
|
||||
}
|
||||
translate([0,0, head_height])
|
||||
cylinder(r = socket_rad, h = socket_depth * 2, $fn = 6, center = true);
|
||||
}
|
||||
}
|
||||
if(head_type == hs_grub) {
|
||||
assign(socket_rad = type[4] / 2,
|
||||
socket_depth = type[5])
|
||||
color([0.2,0.2,0.2]) render() difference() {
|
||||
cylinder(r = rad, h = length);
|
||||
cylinder(r = socket_rad, h = socket_depth * 2, $fn = 6, center = true);
|
||||
}
|
||||
}
|
||||
if(head_type == hs_hex) {
|
||||
assign(head_height =type[5])
|
||||
color([0.8,0.8,0.8]) render() union() {
|
||||
cylinder(r = head_rad, h = head_height, $fn = 6);
|
||||
translate([0,0, - length + eta])
|
||||
cylinder(r = rad, h = length);
|
||||
}
|
||||
}
|
||||
if(head_type == hs_pan) {
|
||||
assign(head_height = type[5],
|
||||
socket_rad = 0.6 * head_rad,
|
||||
socket_depth = 0.5 * type[5])
|
||||
color([0.8,0.8,0.4]) render() difference() {
|
||||
union() {
|
||||
rounded_cylinder(r = head_rad, h = head_height, r2 = head_height / 2);
|
||||
translate([0,0, - length + eta])
|
||||
cylinder(r = rad, h = length);
|
||||
}
|
||||
translate([0,0,head_height]) {
|
||||
cube([2 * socket_rad, 1, 2 * socket_depth], center = true);
|
||||
cube([1, 2 * socket_rad, 2 * socket_depth], center = true);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(head_type == hs_cs) {
|
||||
assign(head_height = head_rad,
|
||||
socket_rad = 0.6 * head_rad,
|
||||
socket_depth = 0.3 * head_rad,
|
||||
socket_width = 1)
|
||||
color([0.8,0.8,0.4]) render() difference() {
|
||||
union() {
|
||||
translate([0,0, -head_height])
|
||||
cylinder(h = head_height, r1 = 0, r2 = head_rad);
|
||||
translate([0,0, - length - eta])
|
||||
cylinder(r = rad, h = length);
|
||||
}
|
||||
translate([0,0,0]) {
|
||||
cube([2 * socket_rad, socket_width, 2 * socket_depth], center = true);
|
||||
cube([socket_width, 2 * socket_rad, 2 * socket_depth], center = true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module screw_and_washer(type, length, spring = false) {
|
||||
washer = screw_washer(type);
|
||||
translate([0, 0, exploded ? 6 : 0])
|
||||
washer(washer);
|
||||
translate([0,0, washer_thickness(washer)]) {
|
||||
if(spring) {
|
||||
translate([0, 0, exploded ? 8 : 0])
|
||||
star_washer(washer);
|
||||
translate([0,0, washer_thickness(washer)])
|
||||
screw(type, length);
|
||||
}
|
||||
else
|
||||
screw(type, length);
|
||||
}
|
||||
}
|
57
scad/vitamins/sheet.scad
Normal file
57
scad/vitamins/sheet.scad
Normal file
@ -0,0 +1,57 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// Flat sheets
|
||||
//
|
||||
MDF6 = [ "MD", "MDF sheet", 6, [0.4, 0.4, 0.2, 1 ], true];
|
||||
MDF10 = [ "MD", "MDF sheet", 10, [0.4, 0.4, 0.2, 1 ], true];
|
||||
MDF12 = [ "MD", "MDF sheet", 12, [0.4, 0.4, 0.2, 1 ], true];
|
||||
PMMA6 = [ "AC", "Acrylic sheet", 6, [1, 1, 1, 0.5 ], false];
|
||||
PMMA8 = [ "AC", "Acrylic sheet", 8, [1, 1, 1, 0.2 ], false];
|
||||
PMMA10 = [ "AC", "Acrylic sheet",10, [1, 1, 1, 0.2 ], false];
|
||||
glass = [ "GL", "Glass sheet", 2, [1, 1, 1, 0.25 ], false];
|
||||
DiBond = [ "DB", "Dibond sheet", 3, [0.5, 0.5, 0.5, 1 ], false];
|
||||
|
||||
function sheet_thickness(type) = type[2];
|
||||
function sheet_is_soft(type) = type[4];
|
||||
|
||||
module corner(r) {
|
||||
if(r > 0)
|
||||
translate([r, - r])
|
||||
circle(r, center = true);
|
||||
else
|
||||
if(r < 0)
|
||||
translate([-r, r])
|
||||
rotate([0,0,45])
|
||||
square(-r * sqrt(2), -r * sqrt(2), center = true);
|
||||
else
|
||||
translate([0.5, -0.5])
|
||||
square(1, center = true);
|
||||
}
|
||||
|
||||
module sheet(type, w, d, corners = [0, 0, 0, 0]) {
|
||||
t = sheet_thickness(type);
|
||||
vitamin(str(type[0], t, round(w), round(d),": ",type[1]," ", round(w), " x ", round(d), " x ", t));
|
||||
color(type[3])
|
||||
linear_extrude(height = t, center = true)
|
||||
hull() {
|
||||
translate([-w/2, d/2])
|
||||
corner(corners[0]);
|
||||
|
||||
translate([ w/2, d/2])
|
||||
rotate([0, 0, -90])
|
||||
corner(corners[1]);
|
||||
|
||||
translate([ w/2, -d/2])
|
||||
rotate([0, 0, -180])
|
||||
corner(corners[2]);
|
||||
|
||||
translate([-w/2, -d/2])
|
||||
rotate([0, 0, -270])
|
||||
corner(corners[3]);
|
||||
}
|
||||
}
|
61
scad/vitamins/springs.scad
Normal file
61
scad/vitamins/springs.scad
Normal file
@ -0,0 +1,61 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// Springs
|
||||
//
|
||||
|
||||
extruder_spring = [7, 1, 10, 5];
|
||||
hob_spring = [12, 0.75, 10, 6];
|
||||
|
||||
// taken from openscad example 20
|
||||
module coil(r1 = 100, r2 = 10, h = 100, twists)
|
||||
{
|
||||
hr = h / (twists * 2);
|
||||
stepsize = 1/16;
|
||||
module segment(i1, i2) {
|
||||
alpha1 = i1 * 360*r2/hr;
|
||||
alpha2 = i2 * 360*r2/hr;
|
||||
len1 = sin(acos(i1*2-1))*r2;
|
||||
len2 = sin(acos(i2*2-1))*r2;
|
||||
if (len1 < 0.01)
|
||||
polygon([
|
||||
[ cos(alpha1)*r1, sin(alpha1)*r1 ],
|
||||
[ cos(alpha2)*(r1-len2), sin(alpha2)*(r1-len2) ],
|
||||
[ cos(alpha2)*(r1+len2), sin(alpha2)*(r1+len2) ]
|
||||
]);
|
||||
if (len2 < 0.01)
|
||||
polygon([
|
||||
[ cos(alpha1)*(r1+len1), sin(alpha1)*(r1+len1) ],
|
||||
[ cos(alpha1)*(r1-len1), sin(alpha1)*(r1-len1) ],
|
||||
[ cos(alpha2)*r1, sin(alpha2)*r1 ],
|
||||
]);
|
||||
if (len1 >= 0.01 && len2 >= 0.01)
|
||||
polygon([
|
||||
[ cos(alpha1)*(r1+len1), sin(alpha1)*(r1+len1) ],
|
||||
[ cos(alpha1)*(r1-len1), sin(alpha1)*(r1-len1) ],
|
||||
[ cos(alpha2)*(r1-len2), sin(alpha2)*(r1-len2) ],
|
||||
[ cos(alpha2)*(r1+len2), sin(alpha2)*(r1+len2) ]
|
||||
]);
|
||||
}
|
||||
linear_extrude(height = h, twist = 180*h/hr,
|
||||
$fn = (hr/r2)/stepsize, convexity = 5) {
|
||||
for (i = [ stepsize : stepsize : 1+stepsize/2 ])
|
||||
segment(i-stepsize, min(i, 1));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module comp_spring(spring, l = 0) {
|
||||
l = (l == 0) ? spring[2] : l;
|
||||
|
||||
vitamin(str("SPR", spring[0], spring[1] * 100, spring[2], ": Spring ", spring[0], " x ", spring[1], " x ", spring[2] ));
|
||||
|
||||
color([0.2, 0.2, 0.2]) render() coil(r1 = (spring[0] - spring[1])/ 2, r2 = spring[1] / 2, h = l, twists = spring[3]);
|
||||
|
||||
}
|
||||
|
||||
//comp_spring(extruder_spring);
|
72
scad/vitamins/stepper-motors.scad
Normal file
72
scad/vitamins/stepper-motors.scad
Normal file
@ -0,0 +1,72 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// NEMA stepper motor model
|
||||
//
|
||||
|
||||
// corner body boss boss shaft
|
||||
// side, length, radius, radius, radius, depth, shaft, length, holes
|
||||
NEMA17 = [42.3, 47.5, 53.6/2, 25, 11, 2, 5, 24, 31 ];
|
||||
NEMA17S = [42.3, 34, 53.6/2, 25, 11, 2, 5, 24, 31 ];
|
||||
NEMA14 = [35.2, 36, 46.4/2, 21, 11, 2, 5, 21, 26 ];
|
||||
|
||||
function NEMA_width(motor) = motor[0];
|
||||
function NEMA_length(motor) = motor[1];
|
||||
function NEMA_radius(motor) = motor[2];
|
||||
function NEMA_holes(motor) = [-motor[8]/2, motor[8]/2];
|
||||
function NEMA_big_hole(motor) = motor[4] + 0.2;
|
||||
function NEMA_shaft_length(motor) = motor[7];
|
||||
|
||||
module NEMA(motor) {
|
||||
side = NEMA_width(motor);
|
||||
length = NEMA_length(motor);
|
||||
body_rad = motor[3];
|
||||
boss_rad = motor[4];
|
||||
boss_height = motor[5];
|
||||
shaft_rad = motor[6] / 2;
|
||||
cap = 8;
|
||||
vitamin(str("NEMA", round(motor[0] / 2.54), length * 10, ": NEMA", round(motor[0] / 2.54), " x ", length, " stepper motor"));
|
||||
union() {
|
||||
color([0,0,0]) render() // black laminations
|
||||
translate([0,0, -length / 2])
|
||||
intersection() {
|
||||
cube([side, side, length - cap * 2],center = true);
|
||||
cylinder(r = body_rad, h = 2 * length, center = true);
|
||||
}
|
||||
color([0.5,0.5,0.5]) render() { // aluminium end caps
|
||||
difference() {
|
||||
union() {
|
||||
intersection() {
|
||||
union() {
|
||||
translate([0,0, -cap / 2])
|
||||
cube([side,side,cap], center = true);
|
||||
translate([0,0, -length + cap / 2])
|
||||
cube([side,side,cap], center = true);
|
||||
}
|
||||
cylinder(r = NEMA_radius(motor), h = 3 * length, center = true);
|
||||
}
|
||||
difference() {
|
||||
cylinder(r = boss_rad, h = boss_height * 2, center = true); // raised boss
|
||||
cylinder(r = shaft_rad + 2, h = boss_height * 2 + 1, center = true);
|
||||
}
|
||||
cylinder(r = shaft_rad, h = NEMA_shaft_length(motor) * 2, center = true); // shaft
|
||||
}
|
||||
for(x = NEMA_holes(motor))
|
||||
for(y = NEMA_holes(motor))
|
||||
translate([x, y, 0])
|
||||
cylinder(r = 3/2, h = 9, center = true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module NEMA_screws(motor, n = 4) {
|
||||
for(a = [0: 90 : 90 * (n - 1)])
|
||||
rotate([0, 0, a])
|
||||
translate([motor[8]/2, motor[8]/2, 0])
|
||||
screw_and_washer(M3_pan_screw, 8, true);
|
||||
}
|
49
scad/vitamins/washers.scad
Normal file
49
scad/vitamins/washers.scad
Normal file
@ -0,0 +1,49 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// Washers
|
||||
//
|
||||
M2p5_washer= [2.5, 5, 0.5, false];
|
||||
M3_washer = [3, 7, 0.5, false];
|
||||
M3p5_washer = [3.5, 8, 0.5, false];
|
||||
M4_washer = [4, 9, 0.9, false];
|
||||
M5_penny_washer = [5, 20, 1.4, false];
|
||||
M6_washer = [6, 12, 1.5, false];
|
||||
M8_washer = [8, 16, 1.5, false];
|
||||
|
||||
M3_rubber_washer= [3, 10, 1.5, true];
|
||||
|
||||
function washer_diameter(type) = type[1];
|
||||
function washer_thickness(type) = type[2];
|
||||
function washer_soft(type) = type[3];
|
||||
|
||||
module washer(type) {
|
||||
if(washer_soft(type))
|
||||
vitamin(str("WR", type[0] * 10, type[1], type[2] * 10, ": Rubber washer M",type[0], " x ", type[1], " x ", type[2]));
|
||||
else
|
||||
vitamin(str("WA", type[0] * 10, type[1], type[2] * 10, ": Washer M",type[0], " x ", type[1], " x ", type[2]));
|
||||
color(washer_soft(type) ? [0.2,0.2,0.2] : [0.8,0.8,0.8]) render() difference() {
|
||||
cylinder(r = washer_diameter(type) / 2, h = washer_thickness(type));
|
||||
cylinder(r = type[0] / 2, h = 2 * washer_thickness(type) + 1, center = true);
|
||||
}
|
||||
}
|
||||
|
||||
module star_washer(type) {
|
||||
hole = type[0] / 2;
|
||||
rad = washer_diameter(type) / 2;
|
||||
inner = (hole + rad) / 2;
|
||||
spoke = rad - hole;
|
||||
vitamin(str("WS", type[0] * 10, type[1], type[2] * 10, ": Star washer M",type[0], " x ", type[1], " x ", type[2]));
|
||||
color([0.8,0.8,0.4]) render() difference() {
|
||||
cylinder(r = rad, h = washer_thickness(type));
|
||||
cylinder(r = hole, h = 2 * washer_thickness(type) + 1, center = true);
|
||||
for(a = [0:30:360])
|
||||
rotate([0, 0, a])
|
||||
translate([inner + spoke / 2, 0, 0.5])
|
||||
cube([spoke, 2 * 3.142 * inner / 36, washer_thickness(type) + 1], center = true);
|
||||
}
|
||||
}
|
36
scad/vitamins/ziptie.scad
Normal file
36
scad/vitamins/ziptie.scad
Normal file
@ -0,0 +1,36 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// Zipties
|
||||
//
|
||||
small_ziptie = [2.3, 1, [4.7, 4.25, 3], [1,1,1], 20];
|
||||
|
||||
function ziptie_width(type) = type[0];
|
||||
function ziptie_thickness(type) = type[1];
|
||||
|
||||
module ziptie(type, r)
|
||||
{
|
||||
latch = type[2];
|
||||
length = ceil(2 * PI * r + type[4] + latch[2] + 1);
|
||||
vitamin(str("ZT00", length, ": Ziptie ",length));
|
||||
|
||||
angle = asin((latch[0] / 2) / r) - asin(ziptie_thickness(type) / latch[0]);
|
||||
color(type[3]) render() union() {
|
||||
tube(ir = r, or = r + ziptie_thickness(type), h = ziptie_width(type));
|
||||
translate([0, -r, - latch[1] / 2])
|
||||
rotate([90, 0, angle]) {
|
||||
union() {
|
||||
cube(latch);
|
||||
translate([latch[0] / 2, latch[1] / 2, (latch[2] + 1) / 2])
|
||||
cube([ziptie_thickness(type), ziptie_width(type), latch[2] + 1], center = true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//ziptie(small_ziptie, 10);
|
355
scad/wade.scad
Normal file
355
scad/wade.scad
Normal file
@ -0,0 +1,355 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// Originally based on Josef Prusa's version but much hacked
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
include <conf/config.scad>
|
||||
use <d-motor_bracket.scad>
|
||||
|
||||
Stoffle15_10mm = [10, 13, 5, false];
|
||||
Stoffle15_16mm = [16.5, 10, 6, false];
|
||||
Mendel90_12mm = [12, 10, 6 + 3/2 - 1, false];
|
||||
|
||||
function insulator_diameter(type) = type[0];
|
||||
function insulator_depth(type) = type[1];
|
||||
function insulator_screw_pitch(type) = type[2];
|
||||
function insulator_clamped(type) = type[3];
|
||||
|
||||
hot_end = Mendel90_12mm;
|
||||
|
||||
clamp_width = 2 * (insulator_screw_pitch(hot_end) + screw_clearance_radius(M3_cap_screw) + min_wall);
|
||||
|
||||
module b608(h=7){
|
||||
difference(){
|
||||
union(){
|
||||
translate([0,0,3.5])
|
||||
cylinder(r=11.01,h=h,center=true);
|
||||
*translate([0,0,3.5])
|
||||
cylinder(r=6,h=7,center=true);
|
||||
}
|
||||
//translate([0,0,3.5]) cylinder(r=4,h=8,center=true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
screw_depth = 5;
|
||||
|
||||
motor_y = 31.5;
|
||||
motor_min = 26 + 5;
|
||||
motor_max = 36;
|
||||
motor_x = (motor_min + motor_max) / 2;
|
||||
motor_leeway = motor_max - motor_min;
|
||||
thickness = 5;
|
||||
base_thickness = 6;
|
||||
|
||||
filament_x = 75;
|
||||
filament_z = 15;
|
||||
|
||||
width = 28;
|
||||
mount_pitch = 25;
|
||||
|
||||
pscrew_x = 60;
|
||||
pscrew_y = [17.5, 45.5];
|
||||
pscrew_z = [8.5, 21.5];
|
||||
|
||||
driven_x = 70;
|
||||
driven_y = 31.5;
|
||||
|
||||
function extruder_connector_offset() = [-filament_x + motor_x, filament_z - thickness, motor_y] + d_motor_connector_offset(NEMA17);
|
||||
|
||||
module wades_block_stl() {
|
||||
stl("wades_block");
|
||||
|
||||
insulator = insulator_diameter(hot_end);
|
||||
screw_pitch = insulator_screw_pitch(hot_end);
|
||||
insulator_depth = insulator_depth(hot_end);
|
||||
|
||||
|
||||
difference(){
|
||||
union(){
|
||||
cube([81, 52, thickness]); // motor plate
|
||||
cube([filament_x + 25 - 3.5, base_thickness, 28]); // base
|
||||
translate([filament_x + 25 - 3.5, base_thickness / 2, filament_z])
|
||||
for(a = [-90, 90])
|
||||
rotate([a, 0, 0])
|
||||
teardrop(r = 10.6, h = base_thickness, truncate = false, center = true);
|
||||
|
||||
translate([57, 0, 0])
|
||||
cube([26, 52, width]); // bearing housing
|
||||
|
||||
translate([80,1,0]) // fillet
|
||||
cube([11,11, width]);
|
||||
}
|
||||
translate([91,base_thickness,-1])
|
||||
rotate([0,0,45])
|
||||
cube([9,9,30]); // chamfer on fillet
|
||||
|
||||
translate([-11,-1,30]) rotate([0,60,0]) cube([30, base_thickness + 2, 60]); // base chamfers
|
||||
translate([80, -1, width + eta]) cube([40, base_thickness + 2, 10]);
|
||||
|
||||
translate([filament_x, 20, filament_z])
|
||||
rotate([90,0,0])
|
||||
teardrop(h = 70, r=4/2, center=true); // filament
|
||||
|
||||
// mounting holes
|
||||
for(side = [-1, 1])
|
||||
translate([filament_x + mount_pitch * side, base_thickness, filament_z])
|
||||
rotate([90,0,0])
|
||||
nut_trap(M4_clearance_radius, M4_nut_radius, 3, true);
|
||||
|
||||
for(y = pscrew_y)
|
||||
for(z = pscrew_z) {
|
||||
translate([70, y, z]) rotate([90,0,90])teardrop(h=40,r=4.5/2, center=true); // pressure screws
|
||||
translate([pscrew_x - 5, y, z]) rotate([90,0,90])cylinder(h=10,r=M4_nut_radius, $fn=6, center=true); // nut traps
|
||||
}
|
||||
//
|
||||
// holes for motor
|
||||
//
|
||||
translate([motor_x, motor_y, -1]) {
|
||||
slot(r = NEMA_big_hole(NEMA17), l = motor_leeway, h = 10, center = false); // motor hub slot
|
||||
|
||||
for(x = NEMA_holes(NEMA17)) // motor screw slots
|
||||
for(y = NEMA_holes(NEMA17))
|
||||
translate([x,y,0])
|
||||
slot(r = M3_clearance_radius, l = motor_leeway, h = 10, center = false);
|
||||
}
|
||||
|
||||
//
|
||||
// remove fourth motor slot
|
||||
//
|
||||
translate([motor_x - 40 + motor_leeway / 2, motor_y - NEMA_big_hole(NEMA17), -1])
|
||||
cube([40,32,7]);
|
||||
translate([motor_x - 40 + motor_leeway / 2 + 6, motor_y, -1])
|
||||
cube([40,32,7]);
|
||||
|
||||
translate([-5,-1,-1]) cube([16,60,30]); // truncates tail
|
||||
|
||||
translate([driven_x, driven_y, 7.5]) poly_cylinder(r = M8_clearance_radius + 0.25,h=30); // hole for hobbed bolt
|
||||
|
||||
translate([driven_x, driven_y, 21.01]) b608(); // top bearing socket
|
||||
translate([83, driven_y, 11.5]) b608(8); // clearance for idler
|
||||
translate([driven_x, driven_y, -0.01]) b608(); // bottom bearing socket
|
||||
|
||||
//
|
||||
// Hole for hot end
|
||||
//
|
||||
translate([filament_x, -15 + insulator_depth, filament_z])
|
||||
rotate([90,0,0]) {
|
||||
teardrop(h = 30, r = insulator / 2, center=true); // insulator
|
||||
translate([0,0, -14.5])
|
||||
teardrop(h = 1 , r = insulator / 2 + 1, center=true); // relief to avoid radius so end is flat
|
||||
}
|
||||
|
||||
if(insulator_clamped(hot_end))
|
||||
translate([filament_x - clamp_width / 2, -eta, filament_z])
|
||||
cube([clamp_width, insulator_depth, 100]);
|
||||
|
||||
for(side = [-1, 1])
|
||||
translate([filament_x + screw_pitch * side, screw_depth, -1])
|
||||
cylinder(h = 30, r = (3.3 / 2), $fn = 9); // retaining screws
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
module wades_gear_spacer_stl() {
|
||||
stl("wades_gear_spacer");
|
||||
washer = M8_washer;
|
||||
|
||||
h = 5 * washer_thickness(washer);
|
||||
difference() {
|
||||
cylinder(r = washer_diameter(washer) / 2, h = h, center = false);
|
||||
translate([0,0, -0.5])
|
||||
poly_cylinder(r = M8_clearance_radius, h = h + 1, center = false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
bfbext=false;
|
||||
|
||||
*difference() {
|
||||
wadeblock(bfbext);
|
||||
*translate([-1,-1, filament_z])
|
||||
cube([200,100,100]);
|
||||
}
|
||||
|
||||
function extruder_connector_height() = motor_y - d_motor_bracket_offset(NEMA17);
|
||||
|
||||
module wades_big_gear_stl() {
|
||||
stl("wades_big_gear");
|
||||
color([0,1,0]) import("../imported_stls/39t17p.stl");
|
||||
}
|
||||
|
||||
module wades_small_gear_stl() {
|
||||
stl("wades_small_gear");
|
||||
color([1,0,0])
|
||||
translate([-10, -10, 0])
|
||||
import("../imported_stls/wades_gear.stl");
|
||||
}
|
||||
|
||||
module small_gear_assembly() {
|
||||
wades_small_gear_stl();
|
||||
rotate([90, 0, -24]) {
|
||||
translate([0, 4, -5/2 - 6])
|
||||
screw(M3_grub_screw, 6);
|
||||
translate([0, 4, -6])
|
||||
rotate([0,0,30])
|
||||
nut(M3_nut);
|
||||
}
|
||||
}
|
||||
|
||||
idler_height = 12;
|
||||
|
||||
module wades_idler_block_stl() {
|
||||
stl("wades_idler_block");
|
||||
|
||||
long_side = 37;
|
||||
short_side = 25;
|
||||
corners_diameter = 3;
|
||||
608_dia = 12;
|
||||
608_height = 9;
|
||||
|
||||
mounting_dia = 4.5;
|
||||
|
||||
difference(){
|
||||
// Main block
|
||||
rounded_rectangle([long_side, short_side, idler_height], corners_diameter, center = false);
|
||||
|
||||
// bearing cutout
|
||||
translate([0, 0, idler_height - 2]){
|
||||
rotate([90,0,0])
|
||||
cylinder(h = 608_height, r=608_dia, center=true);
|
||||
|
||||
rotate(a=[90,0,0])
|
||||
cylinder(h = short_side-2, r=8.6/2, center=true);
|
||||
}
|
||||
|
||||
//mounting holes
|
||||
for(x = pscrew_y)
|
||||
for(y = pscrew_z)
|
||||
translate([x - motor_y, y - filament_z, 0])
|
||||
poly_cylinder(h = idler_height * 2.1, r = mounting_dia / 2, center=true);
|
||||
}
|
||||
}
|
||||
|
||||
module wade_idler_assembly() {
|
||||
|
||||
color([0,1,0]) render() wades_idler_block_stl();
|
||||
|
||||
translate([0, 0, idler_height - 2])
|
||||
rotate([90, 0, 0]) {
|
||||
rod(d = 8, l = 22);
|
||||
ball_bearing(BB608);
|
||||
}
|
||||
}
|
||||
|
||||
module wades_assembly() {
|
||||
assembly("wades_assembly");
|
||||
|
||||
render() wades_block_stl();
|
||||
|
||||
// idler screws, washers and springs
|
||||
for(i = [0,1])
|
||||
translate([pscrew_x, pscrew_y[i], pscrew_z[i]])
|
||||
rotate([-90,0,90]) {
|
||||
screw(M4_hex_screw, 50);
|
||||
translate([0,0, -38]) {
|
||||
translate([0,0, -6]) {
|
||||
comp_spring(extruder_spring, 6);
|
||||
translate([0,0, -washer_thickness(M4_washer)]) {
|
||||
washer(M4_washer);
|
||||
translate([0,0, -nut_thickness(M4_nut)])
|
||||
nut(M4_nut);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// mounting screws
|
||||
for(side = [-1, 1])
|
||||
translate([filament_x + mount_pitch * side, base_thickness - 3, filament_z])
|
||||
rotate([-90,0,0])
|
||||
screw(M4_hex_screw, 20);
|
||||
|
||||
//idler
|
||||
translate([98, motor_y, filament_z])
|
||||
rotate([90, 0, -90])
|
||||
wade_idler_assembly();
|
||||
|
||||
// motor and gear
|
||||
translate([motor_x, motor_y, thickness + eta])
|
||||
rotate([0,180,0]) {
|
||||
NEMA(NEMA17);
|
||||
|
||||
translate([0,0, 3.5])
|
||||
small_gear_assembly();
|
||||
|
||||
translate([0, 0, thickness])
|
||||
rotate([0, 0, 90])
|
||||
NEMA_screws(NEMA17, 3);
|
||||
|
||||
assembly("D_connector_assembly");
|
||||
d_motor_bracket_assembly(NEMA17);
|
||||
d_shell_assembly(NEMA17);
|
||||
end("D_connector_assembly");
|
||||
}
|
||||
|
||||
// hobbed bolt and gear
|
||||
translate([driven_x, motor_y, 0]) {
|
||||
translate([0, 0, width - BB608[2] / 2])
|
||||
ball_bearing(BB608);
|
||||
|
||||
translate([0, 0, BB608[2] / 2])
|
||||
ball_bearing(BB608);
|
||||
|
||||
rotate([180, 0, 0])
|
||||
color([1,0,0]) render() wades_gear_spacer_stl();
|
||||
|
||||
translate([0, 0, -7.5])
|
||||
rotate([180, 0, 0])
|
||||
wades_big_gear_stl();
|
||||
|
||||
translate([0,0, -14])
|
||||
rotate([180, 0, 0])
|
||||
screw(M8_hex_screw, 60);
|
||||
|
||||
translate([0,0, width])
|
||||
washer(M8_washer);
|
||||
|
||||
translate([0,0, width + washer_thickness(M8_washer)]) {
|
||||
comp_spring(hob_spring, 8);
|
||||
translate([0, 0, 8])
|
||||
nut(M8_nut);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
translate([75, 5 - nozzle_length / 4, 15])
|
||||
rotate([-90, 0, 0]) {
|
||||
color([0.6, 0.5, 0.2]) cylinder(h = nozzle_length / 2 + 10, r = insulator_diameter(hot_end) / 2, center = true);
|
||||
translate([0, 0, -nozzle_length /2 - 5])
|
||||
color([1, 1, 0]) cylinder(h = nozzle_length / 2, r = 3, center = true);
|
||||
}
|
||||
|
||||
for(side = [-1, 1])
|
||||
translate([filament_x + insulator_screw_pitch(hot_end) * side, screw_depth, width])
|
||||
screw(M3_cap_screw, 30);
|
||||
|
||||
end("wades_assembly");
|
||||
}
|
||||
if(1)
|
||||
rotate([90, 0, 0])
|
||||
wades_assembly();
|
||||
|
||||
|
||||
else {
|
||||
|
||||
wades_block_stl();
|
||||
*wades_idler_block_stl();
|
||||
*wades_gear_spacer_stl();
|
||||
|
||||
}
|
458
scad/x-carriage.scad
Normal file
458
scad/x-carriage.scad
Normal file
@ -0,0 +1,458 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// X carriage, carries the extruder
|
||||
//
|
||||
|
||||
include <conf/config.scad>
|
||||
use <bearing-holder.scad>
|
||||
use <wade.scad>
|
||||
|
||||
hole = 36;
|
||||
width = hole + 2 * bearing_holder_width(X_bearings);
|
||||
|
||||
length = 97;
|
||||
top_thickness = 3;
|
||||
rim_thickness = 8;
|
||||
nut_trap_thickness = 8;
|
||||
corner_radius = 5;
|
||||
wall = 2.8;
|
||||
|
||||
base_offset = nozzle_x_offset; // offset of base from centre
|
||||
bar_offset = ceil(max(X_bearings[2] / 2 + rim_thickness + 1, // offset of carriage origin from bar centres
|
||||
nut_radius(M3_nut) * 2 + belt_thickness(X_belt) + pulley_inner_radius + 6 * layer_height));
|
||||
|
||||
echo(bar_offset);
|
||||
|
||||
mounting_holes = [90, 270];
|
||||
|
||||
function x_carriage_offset() = bar_offset;
|
||||
function x_bar_spacing() = hole + bearing_holder_width(X_bearings);
|
||||
function x_carriage_width() = width;
|
||||
function x_carriage_length() = length;
|
||||
function x_carriage_thickness() = rim_thickness;
|
||||
|
||||
bar_y = x_bar_spacing() / 2;
|
||||
bar_x = (length - bearing_holder_length(X_bearings)) / 2;
|
||||
|
||||
tooth_height = belt_thickness(X_belt) / 2;
|
||||
tooth_width = belt_pitch(X_belt) / 2;
|
||||
|
||||
lug_width = 2.5 * belt_pitch(X_belt);
|
||||
lug_depth = X_carriage_clearance + belt_width(X_belt) + belt_clearance + M3_clearance_radius + lug_width / 2;
|
||||
lug_screw = -(X_carriage_clearance + belt_width(X_belt) + belt_clearance + M3_clearance_radius);
|
||||
slot_y = -X_carriage_clearance - (belt_width(X_belt) + belt_clearance) / 2;
|
||||
|
||||
function x_carriage_belt_gap() = length - 2 * lug_width;
|
||||
|
||||
clamp_thickness = 3;
|
||||
dowel = 5;
|
||||
dowel_height = 2;
|
||||
|
||||
|
||||
module belt_lug(motor_end) {
|
||||
height = motor_end ? x_carriage_offset() - pulley_inner_radius:
|
||||
x_carriage_offset() - ball_bearing_diameter(X_idler_bearing) / 2;
|
||||
|
||||
height2 = motor_end ? height + clamp_thickness : height;
|
||||
width = lug_width;
|
||||
depth = lug_depth;
|
||||
extra = 0.5; // extra belt clearance
|
||||
|
||||
union() {
|
||||
difference() {
|
||||
union() {
|
||||
translate([width / 2, -depth + width / 2])
|
||||
cylinder(r = width / 2, h = height2 + (motor_end ? M3_nut_trap_depth : 0));
|
||||
translate([0, -(depth - width / 2)])
|
||||
cube([width, depth - width / 2, height2]);
|
||||
}
|
||||
|
||||
translate([width / 2, slot_y, height - belt_thickness(X_belt) / 2 + 2 * eta]) // slot for belt
|
||||
cube([width + 1, belt_width(X_belt) + belt_clearance, belt_thickness(X_belt)], center = true);
|
||||
|
||||
translate([width / 2, lug_screw, height2 + M3_nut_trap_depth + eta])
|
||||
nut_trap(M3_clearance_radius, M3_nut_radius, M3_nut_trap_depth);
|
||||
|
||||
// slot to join screw hole
|
||||
translate([width / 2, -(X_carriage_clearance + belt_width(X_belt) + belt_clearance),
|
||||
height - belt_thickness(X_belt) / 2 + extra /2])
|
||||
cube([M3_clearance_radius * 2, M3_clearance_radius * 2, belt_thickness(X_belt) + extra], center = true);
|
||||
|
||||
if(motor_end) {
|
||||
translate([width, slot_y, (height - belt_thickness(X_belt)) / 2]) // tensioning screw
|
||||
rotate([90, 0, 90])
|
||||
nut_trap(M3_clearance_radius, M3_nut_radius, M3_nut_trap_depth, true);
|
||||
|
||||
translate([width / 2, slot_y, height - (belt_thickness(X_belt) - extra) / 2 - eta]) // clearance slot for belt
|
||||
cube([width + 1, belt_width(X_belt) + extra, belt_thickness(X_belt) + extra], center = true);
|
||||
}
|
||||
}
|
||||
//
|
||||
// fillets
|
||||
//
|
||||
*translate([width, 0, height / 2])
|
||||
rotate([0, 0, -90])
|
||||
fillet(r = X_carriage_clearance, h = height);
|
||||
|
||||
if(motor_end)
|
||||
//
|
||||
// support membrane
|
||||
//
|
||||
translate([width / 2, lug_screw, height + extra + layer_height / 2 - eta])
|
||||
cylinder(r = M3_clearance_radius + 1, h = layer_height, center = true);
|
||||
else
|
||||
for(i = [-1:1]) // teeth to grip belt
|
||||
translate([width / 2 + i * belt_pitch(X_belt), slot_y, height- belt_thickness(X_belt) + tooth_height / 2 - eta ])
|
||||
cube([tooth_width, belt_width(X_belt) + belt_clearance + eta, tooth_height], center = true);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
module belt_loop() {
|
||||
d = x_carriage_offset() - pulley_inner_radius - belt_thickness(X_belt);
|
||||
height = d + 2 * belt_thickness(X_belt);
|
||||
length = lug_width + 12.5;
|
||||
translate([d / 2, 0, 0])
|
||||
linear_extrude(height = belt_width(X_belt), convexity = 5, center = true)
|
||||
difference() {
|
||||
union() {
|
||||
circle(r = height / 2, center = true);
|
||||
translate([0, -height / 2])
|
||||
square([length, height]);
|
||||
}
|
||||
union() {
|
||||
circle(r = d / 2, center = true);
|
||||
translate([0, -d / 2])
|
||||
square([length, d]);
|
||||
}
|
||||
translate([length - 12.5, -height])
|
||||
square([100, height]);
|
||||
}
|
||||
}
|
||||
|
||||
function x_belt_loop_length() = PI * (x_carriage_offset() - pulley_inner_radius - belt_thickness(X_belt) / 2) / 2 + lug_width + 15;
|
||||
|
||||
module x_belt_clamp_stl()
|
||||
{
|
||||
height = clamp_thickness;
|
||||
width = lug_width;
|
||||
depth = lug_depth;
|
||||
|
||||
stl("x_belt_clamp");
|
||||
union() {
|
||||
difference() {
|
||||
union() {
|
||||
translate([width / 2, -depth + width / 2])
|
||||
cylinder(r = width / 2, h = height + M3_nut_trap_depth);
|
||||
translate([0, -(depth - width / 2)])
|
||||
cube([width, depth - width / 2, height]);
|
||||
}
|
||||
translate([width / 2, lug_screw, height + M3_nut_trap_depth])
|
||||
nut_trap(M3_clearance_radius, M3_nut_radius, M3_nut_trap_depth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module x_belt_grip_stl()
|
||||
{
|
||||
height = clamp_thickness + belt_thickness(X_belt);
|
||||
width = lug_width;
|
||||
depth = lug_depth;
|
||||
|
||||
stl("x_belt_grip");
|
||||
union() {
|
||||
difference() {
|
||||
linear_extrude(height = height, convexity = 5)
|
||||
hull() {
|
||||
translate([width / 2, -depth + width / 2])
|
||||
circle(r = width / 2);
|
||||
translate([0, -(depth - width / 2 - dowel)])
|
||||
square([width, depth - width / 2]);
|
||||
}
|
||||
translate([width / 2, lug_screw, -1])
|
||||
poly_cylinder(r = M3_clearance_radius, h = height + 2); // clamp screw hole
|
||||
|
||||
translate([width / 2, -(X_carriage_clearance + belt_width(X_belt) + belt_clearance), height]) // slot to join screw hole
|
||||
cube([M3_clearance_radius * 2, M3_clearance_radius * 2, 2 * belt_thickness(X_belt)], center = true);
|
||||
|
||||
translate([width / 2, slot_y, height - belt_thickness(X_belt) / 2 + 2 * eta]) // slot for belt
|
||||
cube([width + 1, belt_width(X_belt) + belt_clearance, belt_thickness(X_belt)], center = true);
|
||||
}
|
||||
translate([width / 2, dowel / 2, eta])
|
||||
cylinder(r = dowel / 2 - 0.1, h = height + dowel_height);
|
||||
|
||||
for(i = [-1:1]) // teeth
|
||||
translate([width / 2 + i * belt_pitch(X_belt), slot_y, height - belt_thickness(X_belt) + tooth_height / 2 - eta ])
|
||||
cube([tooth_width, belt_width(X_belt) + belt_clearance + eta, tooth_height], center = true);
|
||||
}
|
||||
}
|
||||
belt_tensioner_rim = X_carriage_clearance;
|
||||
belt_tensioner_height = belt_tensioner_rim + belt_width(X_belt) + belt_clearance + belt_tensioner_rim;
|
||||
|
||||
module x_belt_tensioner_stl()
|
||||
{
|
||||
stl("x_belt_tensioner");
|
||||
|
||||
flat = 1;
|
||||
d = x_carriage_offset() - pulley_inner_radius - belt_thickness(X_belt);
|
||||
|
||||
module d(r, w) {
|
||||
difference() {
|
||||
union() {
|
||||
circle(r, center = true);
|
||||
translate([0, -r])
|
||||
square([w + 1, 2 * r]);
|
||||
}
|
||||
translate([w, - 50])
|
||||
square([100, 100]);
|
||||
}
|
||||
}
|
||||
|
||||
difference() {
|
||||
translate([d / 2, 0, 0]) union() {
|
||||
linear_extrude(height = belt_tensioner_height)
|
||||
d(d / 2, flat);
|
||||
|
||||
linear_extrude(height = belt_tensioner_rim)
|
||||
d(d / 2 + 2, flat);
|
||||
}
|
||||
translate([wall, 0, belt_tensioner_height / 2])
|
||||
rotate([90, 0, 90])
|
||||
teardrop(r = M3_clearance_radius, h = 100);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bearing_gap = 5;
|
||||
bearing_slit = 1;
|
||||
|
||||
hole_width = hole - wall - bearing_slit;
|
||||
hole_offset = (hole - hole_width) / 2;
|
||||
|
||||
|
||||
module base_shape() {
|
||||
difference() {
|
||||
hull() {
|
||||
translate([-length / 2, -width / 2])
|
||||
square();
|
||||
|
||||
translate([ length / 2 - 1, -width / 2])
|
||||
square();
|
||||
|
||||
translate([bearing_holder_length(X_bearings) / 2 + bearing_gap, width / 2 - corner_radius])
|
||||
circle(r = corner_radius, center = true);
|
||||
|
||||
translate([-bearing_holder_length(X_bearings) / 2 - bearing_gap, width / 2 - corner_radius])
|
||||
circle(r = corner_radius, center = true);
|
||||
|
||||
translate([-length / 2 + corner_radius, extruder_width / 2 ])
|
||||
circle(r = corner_radius, center = true);
|
||||
|
||||
translate([ length / 2 - corner_radius , extruder_width / 2])
|
||||
circle(r = corner_radius, center = true);
|
||||
}
|
||||
translate([0, width / 2 - (bearing_holder_width(X_bearings) + bearing_slit) / 2 + eta])
|
||||
square([bearing_holder_length(X_bearings) + 2 * bearing_gap,
|
||||
bearing_holder_width(X_bearings) + bearing_slit ], center = true);
|
||||
}
|
||||
}
|
||||
|
||||
module inner_base_shape() {
|
||||
difference() {
|
||||
square([length - 2 * wall, width - 2 * wall], center = true);
|
||||
minkowski() {
|
||||
difference() {
|
||||
square([length + 1, width + 1], center = true);
|
||||
translate([10,0])
|
||||
square([length + 1, 2 * wall + eta], center = true);
|
||||
base_shape();
|
||||
|
||||
}
|
||||
circle(r = wall, center = true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module x_carriage_stl(){
|
||||
|
||||
stl("x_carriage");
|
||||
|
||||
translate([base_offset, 0, top_thickness])
|
||||
difference(){
|
||||
union(){
|
||||
translate([0, 0, rim_thickness / 2 - top_thickness]) {
|
||||
difference() {
|
||||
union() {
|
||||
// base plate
|
||||
difference() {
|
||||
linear_extrude(height = rim_thickness, center = true, convexity = 5)
|
||||
base_shape();
|
||||
|
||||
translate([0, 0, top_thickness])
|
||||
linear_extrude(height = rim_thickness, center = true, convexity = 5)
|
||||
difference() {
|
||||
inner_base_shape();
|
||||
translate([-base_offset, -hole_offset])
|
||||
rounded_square(hole + 2 * wall, hole_width + 2 * wall, corner_radius + wall);
|
||||
|
||||
}
|
||||
}
|
||||
// ribs
|
||||
for(end = [-1,1])
|
||||
linear_extrude(height = rim_thickness, center = true, convexity = 5)
|
||||
hull() {
|
||||
translate([0, bar_y - bearing_holder_width(X_bearings) / 2 - bearing_slit- wall])
|
||||
circle(r = wall, center = true);
|
||||
|
||||
translate([end * bar_x, -bar_y + bearing_holder_width(X_bearings) / 2])
|
||||
circle(r = wall, center = true);
|
||||
}
|
||||
}
|
||||
//Holes for bearing holders
|
||||
translate([0, bar_y, rim_thickness - top_thickness - eta])
|
||||
cube([bearing_holder_length(X_bearings) - 2 * eta, bearing_holder_width(X_bearings) - 2 * eta, rim_thickness * 2], center = true);
|
||||
|
||||
translate([- bar_x, -bar_y, rim_thickness - top_thickness - eta])
|
||||
cube([bearing_holder_length(X_bearings) - 2 * eta, bearing_holder_width(X_bearings) - 2 * eta, rim_thickness * 2], center = true);
|
||||
|
||||
translate([+ bar_x, -bar_y, rim_thickness - top_thickness - eta])
|
||||
cube([bearing_holder_length(X_bearings) - 2 * eta, bearing_holder_width(X_bearings) - 2 * eta, rim_thickness * 2], center = true);
|
||||
}
|
||||
}
|
||||
//
|
||||
// Floating bearing springs
|
||||
//
|
||||
for(side = [-1, 1])
|
||||
translate([0, bar_y + side * (bearing_holder_width(X_bearings) - min_wall - eta) / 2, rim_thickness / 2 - top_thickness])
|
||||
cube([bearing_holder_length(X_bearings) + 2 * bearing_gap + 1, min_wall, rim_thickness], center = true);
|
||||
|
||||
// raised section for nut traps
|
||||
for(a = mounting_holes)
|
||||
translate([25 * sin(a) - base_offset, 25 * cos(a), (nut_trap_thickness - top_thickness) / 2])
|
||||
cylinder(r = 7, h = nut_trap_thickness - top_thickness, center = true);
|
||||
|
||||
// belt lugs
|
||||
translate([-length / 2, -width / 2 + eta, -top_thickness])
|
||||
belt_lug(true);
|
||||
|
||||
translate([ length / 2, -width / 2 + eta, -top_thickness])
|
||||
mirror([1,0,0])
|
||||
belt_lug(false);
|
||||
|
||||
//Bearing holders
|
||||
translate([0, bar_y, bar_offset - top_thickness]) rotate([0,0,90]) bearing_holder(X_bearings, bar_offset - eta);
|
||||
translate([- bar_x, -bar_y, bar_offset - top_thickness]) rotate([0,0,90]) bearing_holder(X_bearings, bar_offset - eta);
|
||||
translate([+ bar_x, -bar_y, bar_offset - top_thickness]) rotate([0,0,90]) bearing_holder(X_bearings, bar_offset - eta);
|
||||
|
||||
}
|
||||
translate([-base_offset, 0, 0]) {
|
||||
// hole to clear the hot end
|
||||
translate([0, - hole_offset])
|
||||
rounded_rectangle([hole, hole_width, 2 * rim_thickness], corner_radius);
|
||||
|
||||
// holes for connecting extruder
|
||||
for(a = mounting_holes)
|
||||
translate([25 * sin(a), 25 * cos(a), nut_trap_thickness - top_thickness]) {
|
||||
*cylinder(h = nut_trap_thickness, r = 7);
|
||||
rotate([0,0,-a])
|
||||
//nut_trap(M4_clearance_radius, M4_nut_radius, M4_nut_trap_depth);
|
||||
poly_cylinder(r = M4_clearance_radius, h = 50, center = true);
|
||||
}
|
||||
}
|
||||
//
|
||||
// Belt grip dowel hole
|
||||
//
|
||||
translate([-length / 2 + lug_width / 2, -width / 2 + dowel / 2, -top_thickness])
|
||||
cylinder(r = dowel / 2 + 0.1, h = dowel_height * 2, center = true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module x_carriage_assembly(show_extruder = false) {
|
||||
assembly("x_carriage_assembly");
|
||||
|
||||
color([1,0,0]) render() x_carriage_stl();
|
||||
|
||||
if(show_extruder)
|
||||
translate([75, 15, eta])
|
||||
rotate([-90,0,180])
|
||||
wades_assembly(false, true);
|
||||
|
||||
for(end = [-1, 1])
|
||||
translate([25 * end, 0, nut_trap_thickness])
|
||||
rotate([0,0, 45])
|
||||
wingnut(M4_wingnut);
|
||||
|
||||
translate([base_offset, bar_y, bar_offset]) {
|
||||
linear_bearing(X_bearings);
|
||||
rotate([0,-90,0])
|
||||
ziptie(small_ziptie, bearing_ziptie_radius(X_bearings));
|
||||
}
|
||||
for(end = [-1,1])
|
||||
translate([base_offset + bar_x * end, -bar_y, bar_offset]) {
|
||||
linear_bearing(X_bearings);
|
||||
rotate([90,-90,90])
|
||||
ziptie(small_ziptie, bearing_ziptie_radius(X_bearings));
|
||||
}
|
||||
//
|
||||
// Idler end belt clamp
|
||||
//
|
||||
translate([length / 2 + base_offset, -width / 2, x_carriage_offset() - ball_bearing_diameter(X_idler_bearing) / 2]) {
|
||||
mirror([1,0,0])
|
||||
color([0,1,0]) render() x_belt_clamp_stl();
|
||||
translate([-lug_width / 2, lug_screw, clamp_thickness])
|
||||
nut(M3_nut, true);
|
||||
}
|
||||
|
||||
translate([length / 2 + base_offset - lug_width / 2, -width / 2 + lug_screw, 0])
|
||||
rotate([180, 0, 0])
|
||||
screw_and_washer(M3_cap_screw, 20);
|
||||
//
|
||||
// Motor end belt clamp
|
||||
//
|
||||
translate([-length / 2 + base_offset, -width / 2, x_carriage_offset() - pulley_inner_radius])
|
||||
translate([lug_width / 2, lug_screw, clamp_thickness])
|
||||
nut(M3_nut, true);
|
||||
|
||||
translate([-length / 2 + base_offset, -width / 2, -(clamp_thickness + belt_thickness(X_belt))]) {
|
||||
color([0,1,0]) render() x_belt_grip_stl();
|
||||
translate([lug_width / 2, lug_screw, 0])
|
||||
rotate([180, 0, 0])
|
||||
screw_and_washer(M3_cap_screw, 25);
|
||||
}
|
||||
|
||||
translate([-length / 2 + base_offset - 7, -width / 2 + slot_y, (x_carriage_offset() - pulley_inner_radius - belt_thickness(X_belt)) /2]) {
|
||||
rotate([0, -90, 0])
|
||||
screw(M3_cap_screw, 25); // tensioning screw
|
||||
|
||||
translate([25 + wall, belt_tensioner_height / 2, 0])
|
||||
rotate([90, 180, 0])
|
||||
color([0,1,0]) render() x_belt_tensioner_stl();
|
||||
|
||||
translate([25 + wall, 0, 0])
|
||||
rotate([90, 180, 0])
|
||||
belt_loop();
|
||||
}
|
||||
|
||||
translate([-length / 2 + base_offset + lug_width - M3_nut_trap_depth, -width / 2 + slot_y, (x_carriage_offset() - pulley_inner_radius - belt_thickness(X_belt)) /2])
|
||||
rotate([90, 0, 90])
|
||||
nut(M3_nut, false); // tensioning nut
|
||||
|
||||
end("x_carriage_assembly");
|
||||
}
|
||||
|
||||
|
||||
if(0) {
|
||||
x_belt_clamp_stl();
|
||||
translate([-(lug_width + 2),0,0]) x_belt_grip_stl();
|
||||
x_carriage_stl();
|
||||
translate([6, 8, 0]) rotate([0, 0, -90]) x_belt_tensioner_stl();
|
||||
}
|
||||
else
|
||||
x_carriage_assembly(true);
|
||||
//belt_lug(false);
|
551
scad/x-end.scad
Normal file
551
scad/x-end.scad
Normal file
@ -0,0 +1,551 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// Ends of the X axis
|
||||
//
|
||||
include <conf/config.scad>
|
||||
|
||||
use <x-carriage.scad>
|
||||
use <pulley.scad>
|
||||
use <ribbon_clamp.scad>
|
||||
use <wade.scad>
|
||||
|
||||
bwall = 2.3;
|
||||
|
||||
bearing_dia = Z_bearings[1] + 0.2;
|
||||
bearing_width = bearing_dia + 2 * bwall;
|
||||
bearing_depth = bearing_width / 2 + 1;
|
||||
bearing_length = Z_bearings[0];
|
||||
bearing_height = min(65, 2.8 * bearing_length);
|
||||
|
||||
shelf_thickness = 2;
|
||||
shelf_clearance = 0.5;
|
||||
|
||||
shelves = [ shelf_thickness / 2,
|
||||
shelf_thickness + bearing_length + shelf_clearance + shelf_thickness / 2,
|
||||
bearing_height - shelf_thickness / 2,
|
||||
bearing_height - (shelf_thickness + bearing_length + shelf_clearance + shelf_thickness / 2) ];
|
||||
|
||||
actuator_width = 4;
|
||||
actuator_depth = 3;
|
||||
actuator_height = 10;
|
||||
|
||||
module z_linear_bearings(motor_end) {
|
||||
rod_dia = Z_bearings[2];
|
||||
opening = 2 * bearing_dia / 15.4;
|
||||
shelf_depth = bearing_depth - (rod_dia / 2 + 1);
|
||||
|
||||
union() {
|
||||
difference(){
|
||||
union(){
|
||||
//main vertical block
|
||||
translate([-bearing_depth / 2, 0, bearing_height / 2])
|
||||
cube([bearing_depth, bearing_width, bearing_height], center = true);
|
||||
|
||||
cylinder(h = bearing_height, r = bearing_width / 2);
|
||||
|
||||
if(!motor_end)
|
||||
*translate([-bearing_depth + eta, 0, bearing_height - eta])
|
||||
rotate([-90, 0, 0])
|
||||
right_triangle(width = -actuator_depth, height = actuator_height, h = actuator_width, center = true);
|
||||
|
||||
}
|
||||
//hole for bearings
|
||||
translate([0, 0, -1])
|
||||
cylinder(h = bearing_height + 2, r = bearing_dia / 2);
|
||||
|
||||
|
||||
//entry cut out
|
||||
translate([10 * sqrt(2) - opening, 0, bearing_height / 2])
|
||||
rotate([0, 0, 45])
|
||||
cube([20, 20, bearing_height + 1], center = true);
|
||||
|
||||
}
|
||||
//
|
||||
// shelves
|
||||
//
|
||||
for(y = shelves)
|
||||
translate([-bearing_depth + shelf_depth / 2 + eta, 0, y])
|
||||
cube([shelf_depth, bearing_width, shelf_thickness], center = true);
|
||||
}
|
||||
}
|
||||
|
||||
//z_linear_bearings();
|
||||
|
||||
wall = thick_wall; // 4mm on Mendel and Sturdy, 3mm on Huxley
|
||||
width = x_bar_spacing();
|
||||
back = -ceil(z_bar_offset() + Z_nut_radius + wall);
|
||||
front = -(Z_bar_dia / 2 + 1);
|
||||
length = front - back;
|
||||
thickness = X_bar_dia + 2 * wall;
|
||||
|
||||
clamp_wall = default_wall; // 4mm on Sturdy, 3mm on Mendel and Huxley
|
||||
nut_flat_radius = nut_radius * cos(30);
|
||||
clamp_width = 2 * (nut_radius + clamp_wall);
|
||||
clamp_height = washer_diameter(washer) / 2 + nut_flat_radius + clamp_wall;
|
||||
clamp_depth = wall + nut_trap_depth;
|
||||
clamp_thickness = 5;
|
||||
slit = 1;
|
||||
bar_y = x_bar_spacing() / 2;
|
||||
|
||||
belt_edge = -x_carriage_width() / 2 - X_carriage_clearance;
|
||||
idler_front = belt_edge - belt_width(X_belt) / 2 + ball_bearing_width(BB624) / 2 + washer_thickness(M4_washer) + washer_thickness(M5_penny_washer);
|
||||
idler_screw_length = 40;
|
||||
idler_depth = idler_screw_length - ball_bearing_width(BB624) - 2 * (washer_thickness(M4_washer) + washer_thickness(M5_penny_washer)) - 1;
|
||||
idler_back = idler_front + idler_depth;
|
||||
idler_width = ceil(2 * (M4_nut_radius + wall));
|
||||
|
||||
mbracket_thickness = 4;
|
||||
motor_angle = 45;
|
||||
motor_w = ceil(min(max(sin(motor_angle) + cos(motor_angle)) * NEMA_width(X_motor), NEMA_radius(X_motor) * 2) + 1);
|
||||
mbracket_width = motor_w + 2 * mbracket_thickness;
|
||||
mbracket_height = thickness / 2 + NEMA_radius(X_motor) + mbracket_thickness;
|
||||
mbracket_front = belt_edge + 14;
|
||||
mbracket_depth = NEMA_length(X_motor) + 2 * mbracket_thickness + 1;
|
||||
mbracket_centre = mbracket_front + mbracket_depth / 2 - mbracket_thickness;
|
||||
|
||||
switch_op_x = Z_bearings[1] / 2 + 2; // switch operates 2mm before carriage hits the bearing
|
||||
switch_op_z = x_carriage_offset() - x_carriage_thickness() / 2; // hit the edge of the carriage
|
||||
sbracket_top = switch_op_z + 12;
|
||||
sbracket_height = sbracket_top + thickness / 2;
|
||||
sbracket_depth = switch_op_x - 3 - front;
|
||||
sbracket_thickness = bar_y - (X_bar_dia / 2) * sin(45) - bearing_width / 2 - 1.5 - microswitch_thickness();
|
||||
sbracket_y = -bearing_width / 2 - 1 - sbracket_thickness / 2;
|
||||
|
||||
function x_motor_offset() = back - mbracket_thickness - motor_w / 2;
|
||||
function x_motor_overhang() = back - mbracket_width;
|
||||
function x_idler_offset() = back - idler_width / 2;
|
||||
function x_idler_overhang() = x_idler_offset() - washer_diameter(M5_penny_washer) / 2;
|
||||
function x_end_bar_length() = -back;
|
||||
function x_end_height() = bearing_height - thickness / 2;
|
||||
function x_end_thickness() = thickness;
|
||||
|
||||
ribbon_screw = M3_cap_screw;
|
||||
ribbon_nut = screw_nut(ribbon_screw);
|
||||
ribbon_nut_trap_depth = nut_trap_depth(ribbon_nut);
|
||||
ribbon_pillar_depth = 12;
|
||||
ribbon_pillar_thickness = wall + ribbon_nut_trap_depth;
|
||||
ribbon_clamp_x = back - ribbon_pillar_depth;
|
||||
ribbon_clamp_y = mbracket_front + washer_diameter(screw_washer(ribbon_screw)) / 2 + 2;
|
||||
//ribbon_clamp_z = x_carriage_offset() + extruder_connector_height();
|
||||
ribbon_clamp_z = mbracket_height + ribbon_clamp_length(extruder_ways, ribbon_screw) / 2 - thickness / 2 + 0.5;
|
||||
ribbon_pillar_width = nut_radius(ribbon_nut) * 2 + 2 * wall + 0.5;
|
||||
ribbon_pillar_top = ribbon_clamp_z + ribbon_clamp_length(extruder_ways, ribbon_screw) / 2;
|
||||
|
||||
function anti_backlash_height() = 24 + thickness / 2;
|
||||
anti_backlash_radius = Z_nut_radius + 0.2;
|
||||
anti_backlash_wall = 3;
|
||||
|
||||
function x_end_ribbon_clamp_y() = mbracket_front + mbracket_depth - mbracket_thickness;
|
||||
function x_end_ribbon_clamp_z() = mbracket_height - thickness / 2 - mbracket_thickness - nut_radius(ribbon_nut);
|
||||
|
||||
function x_end_extruder_ribbon_clamp_offset() = [-ribbon_clamp_x, ribbon_clamp_y + ribbon_clamp_width(ribbon_screw) / 2, ribbon_clamp_z];
|
||||
|
||||
module x_end_bracket(motor_end, assembly = false){
|
||||
|
||||
if(motor_end)
|
||||
stl("x_motor_bracket");
|
||||
else
|
||||
stl("x_idler_bracket");
|
||||
union(){
|
||||
translate([0, 0, - thickness / 2])
|
||||
z_linear_bearings(motor_end);
|
||||
|
||||
difference(){
|
||||
union(){
|
||||
// base
|
||||
translate([front - length / 2, 0, 0])
|
||||
cube([length, width, thickness], center = true);
|
||||
|
||||
//
|
||||
// Anti-backlash nut holder
|
||||
//
|
||||
translate([-z_bar_offset(), 0, thickness / 2 - eta])
|
||||
cylinder(r = anti_backlash_radius + anti_backlash_wall, h = anti_backlash_height() - thickness / 2, $fn = 6);
|
||||
|
||||
//
|
||||
// Webs from bearing holder
|
||||
//
|
||||
for(side = [-1, 1])
|
||||
if(motor_end)
|
||||
translate([back - eta, (bearing_width - wall - eta) / 2 * side, thickness / 2 - eta])
|
||||
rotate([90, 0, 0])
|
||||
linear_extrude(height = wall, center = true)
|
||||
polygon(points = [
|
||||
[0, 0],
|
||||
[-back - bearing_depth + 2 * eta, 0],
|
||||
[-back - bearing_depth + 2 * eta, bearing_height - thickness],
|
||||
[0, mbracket_height - thickness]
|
||||
],
|
||||
sides = [0, 1, 2, 3]
|
||||
);
|
||||
else
|
||||
translate([-bearing_depth + eta, (bearing_width - wall - eta) / 2 * side, thickness / 2 - eta])
|
||||
rotate([90, 0, 0])
|
||||
right_triangle(width = back + bearing_depth, height = bearing_height - thickness, h = wall);
|
||||
|
||||
for(side = [-1, 1]) {
|
||||
//
|
||||
// Bar holders
|
||||
//
|
||||
union() {
|
||||
translate([front - length / 2, bar_y * side, 0]) {
|
||||
rotate([90, 0, 90])
|
||||
teardrop(r = thickness / 2, h = length, center = true);
|
||||
rotate([-90, 0, 90])
|
||||
teardrop(r = thickness / 2, h = length, center = true);
|
||||
|
||||
rotate([90, 0, 90 * side])
|
||||
linear_extrude(height = length - 4 * eta, center = true)
|
||||
hull() {
|
||||
translate([slit / 2 + eta, thickness / 2 - 1])
|
||||
square([clamp_thickness - 2 * eta, 0.5]);
|
||||
circle(r = thickness / 2 - eta);
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
// Bar clamps
|
||||
//
|
||||
difference() {
|
||||
group() {
|
||||
translate([front - length / 2, side * (bar_y - clamp_depth / 2 - slit / 2), thickness / 2 + clamp_height / 2 -eta])
|
||||
cube([clamp_width, clamp_depth, clamp_height], center = true);
|
||||
|
||||
translate([front - length / 2, side * (bar_y + clamp_thickness / 2 + slit / 2) -eta, thickness / 2])
|
||||
rotate([90, 0, 0])
|
||||
linear_extrude(height = clamp_thickness, center = true)
|
||||
polygon(points = [
|
||||
[-length / 2 + eta, 0],
|
||||
[-length / 2 + eta, -thickness / 2],
|
||||
[ length / 2 - eta, -thickness / 2],
|
||||
[ length / 2 - eta, 0],
|
||||
[ clamp_width / 2, clamp_height],
|
||||
[-clamp_width / 2, clamp_height],
|
||||
]);
|
||||
}
|
||||
//
|
||||
// Bar clamp nut traps
|
||||
//
|
||||
translate([front - length / 2, side * (bar_y - clamp_depth - slit / 2), thickness / 2 + washer_diameter(washer) / 2])
|
||||
rotate([90,0,0])
|
||||
nut_trap(screw_clearance_radius, nut_radius, nut_trap_depth, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
// Cut out for bearing holder
|
||||
//
|
||||
cube([bearing_depth * 2 -eta, bearing_width - eta, thickness + 10], center = true);
|
||||
//
|
||||
// Hole for z leadscrew
|
||||
//
|
||||
translate([-z_bar_offset(), 0, -thickness / 2])
|
||||
nut_trap((Z_screw_dia + 1) / 2, Z_nut_radius, Z_nut_depth);
|
||||
|
||||
translate([-z_bar_offset(), 0, thickness / 2 + eta])
|
||||
cylinder(r = anti_backlash_radius, h = bearing_height, $fn = 6);
|
||||
|
||||
for(side = [-1, 1]) {
|
||||
//
|
||||
// Holes for x_bars
|
||||
//
|
||||
translate([front - length / 2, bar_y * side, 0]) {
|
||||
translate([0, 0, thickness / 2])
|
||||
cube([length + 1, slit, thickness + 1], center = true);
|
||||
rotate([90, 0, 90])
|
||||
teardrop_plus(r = X_bar_dia / 2, h = length + 1, center = true, truncate = false);
|
||||
}
|
||||
}
|
||||
//
|
||||
// cut out for bottom microswitch contact
|
||||
//
|
||||
if(motor_end)
|
||||
translate([switch_op_x,
|
||||
sbracket_y - sbracket_thickness / 2 - microswitch_thickness() / 2,
|
||||
switch_op_z])
|
||||
rotate([0, -90, -90])
|
||||
microswitch_contact_space();
|
||||
|
||||
}
|
||||
//
|
||||
// support membrane
|
||||
//
|
||||
translate([-z_bar_offset(), 0, Z_nut_depth + layer_height / 2 - thickness / 2 + eta])
|
||||
cylinder(r = (Z_screw_dia + 2) /2, h = layer_height, center = true);
|
||||
|
||||
if(motor_end) {
|
||||
difference() {
|
||||
//
|
||||
// Bracket
|
||||
//
|
||||
union() {
|
||||
translate([back - mbracket_width / 2 + eta, mbracket_centre, mbracket_height / 2 - thickness / 2]) {
|
||||
difference() {
|
||||
cube([mbracket_width, mbracket_depth, mbracket_height], center = true); // outside
|
||||
translate([0, 0, -mbracket_thickness])
|
||||
cube([mbracket_width - 2 * mbracket_thickness, // inside
|
||||
mbracket_depth - 2 * mbracket_thickness, mbracket_height], center = true);
|
||||
translate([0, 0, (mbracket_height - mbracket_thickness) / 2 + layer_height])
|
||||
cube([mbracket_width - 30, mbracket_depth - 30, assembly ? 10: mbracket_thickness], center = true); // open top
|
||||
|
||||
}
|
||||
//
|
||||
// Fillet to anchor the end wall to the bed while being printed
|
||||
//
|
||||
translate([-mbracket_width / 2 + mbracket_thickness - eta, 0, -mbracket_height / 2])
|
||||
rotate([90, 0, 0])
|
||||
right_triangle(width = 4, height = 4, h = mbracket_depth - eta, center = true);
|
||||
}
|
||||
//
|
||||
// ribbon clamp pillar
|
||||
//
|
||||
translate([ribbon_clamp_x,
|
||||
ribbon_clamp_y,
|
||||
mbracket_height + (ribbon_pillar_top - mbracket_height - thickness / 2) / 2 - eta])
|
||||
{
|
||||
translate([ribbon_pillar_thickness / 2, 0, 0])
|
||||
cube([ribbon_pillar_thickness,
|
||||
ribbon_pillar_width,
|
||||
ribbon_pillar_top - mbracket_height + thickness / 2], center = true);
|
||||
for(side = [-1, 1])
|
||||
translate([ribbon_pillar_thickness - eta, side * (ribbon_pillar_width - wall) / 2,
|
||||
-(ribbon_pillar_top - mbracket_height + thickness / 2) / 2 - eta])
|
||||
rotate([90,0,0])
|
||||
right_triangle(width = ribbon_pillar_depth - ribbon_pillar_thickness,
|
||||
height = ribbon_pillar_top - mbracket_height + thickness / 2,
|
||||
h = wall);
|
||||
}
|
||||
//
|
||||
// Ribbon clamp nut traps
|
||||
//
|
||||
translate([x_motor_offset(), mbracket_front + mbracket_depth - 2 * mbracket_thickness + eta, x_end_ribbon_clamp_z()])
|
||||
rotate([90, 180, 0])
|
||||
ribbon_clamp_holes(x_end_ways, ribbon_screw)
|
||||
difference() {
|
||||
teardrop(r = nut_radius(ribbon_nut) + 2, h = ribbon_nut_trap_depth, truncate = false);
|
||||
translate([0, (nut_radius(ribbon_nut) + 2) * sqrt(2), ribbon_nut_trap_depth + eta])
|
||||
rotate([0, 90, 180])
|
||||
right_triangle(width = ribbon_nut_trap_depth, height = ribbon_nut_trap_depth, h = 20);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
//
|
||||
// Slits to leave clamp free
|
||||
//
|
||||
for(side = [-1,1]) // both sides in case motor longer than bracket
|
||||
translate([back - slit / 2 + eta * 2, side * (-bar_y - thickness / 2 + slit / 2), 0])
|
||||
difference() {
|
||||
cube([slit, thickness, thickness + 2], center = true);
|
||||
translate([-1, 0, thickness / 2 + 1])
|
||||
rotate([0, 45, 0])
|
||||
cube([2, thickness + 1, 2], center = true);
|
||||
}
|
||||
//
|
||||
// Holes
|
||||
//
|
||||
translate([x_motor_offset(), mbracket_front, 0]) {
|
||||
//
|
||||
// big hole for motor boss
|
||||
//
|
||||
translate([0, 0, -50/2])
|
||||
rotate([90,0,0])
|
||||
vertical_tearslot(r = NEMA_big_hole(X_motor), h = 2 * mbracket_thickness + 1, l = 50, center = true);
|
||||
//
|
||||
// small hole for second shaft
|
||||
//
|
||||
translate([0, mbracket_depth - mbracket_thickness, -50/2])
|
||||
rotate([90,0,0])
|
||||
vertical_tearslot(r = 4, h = 2 * mbracket_thickness + 1, l = 50, center = true);
|
||||
//
|
||||
// Mounting holes
|
||||
//
|
||||
for(x = NEMA_holes(X_motor)) // motor screw holes
|
||||
for(z = NEMA_holes(X_motor))
|
||||
rotate([0, motor_angle, 0])
|
||||
translate([x,0,z])
|
||||
rotate([90, -motor_angle, 0]) {
|
||||
teardrop_plus(r = M3_clearance_radius, h = 2 * mbracket_thickness + 1, center = true);
|
||||
translate([0, 0, mbracket_thickness])
|
||||
teardrop_plus(r = (washer_diameter(M3_washer) + 1) / 2, h = 2 * (mbracket_thickness - 3.999), center = true);
|
||||
}
|
||||
}
|
||||
//
|
||||
// ribbon clamp holes
|
||||
//
|
||||
translate([x_motor_offset(),
|
||||
mbracket_front + mbracket_depth - 2 * mbracket_thickness - ribbon_nut_trap_depth,
|
||||
mbracket_height - thickness / 2 - mbracket_thickness - nut_radius(ribbon_nut)])
|
||||
rotate([90, 0, 0])
|
||||
ribbon_clamp_holes(x_end_ways, ribbon_screw)
|
||||
difference() {
|
||||
nut_trap(screw_clearance_radius(ribbon_screw), nut_radius(ribbon_nut), ribbon_nut_trap_depth, true);
|
||||
translate([0,0, 10])
|
||||
cylinder(r = 10, h =100);
|
||||
}
|
||||
|
||||
translate([ribbon_clamp_x + ribbon_pillar_thickness, ribbon_clamp_y, ribbon_clamp_z])
|
||||
rotate([-90,90,90])
|
||||
ribbon_clamp_holes(extruder_ways, ribbon_screw)
|
||||
rotate([0, 0, 90])
|
||||
nut_trap(screw_clearance_radius(ribbon_screw), nut_radius(ribbon_nut), ribbon_nut_trap_depth, true);
|
||||
//
|
||||
// Hole for switch wires
|
||||
//
|
||||
translate([back, -bearing_width / 2 - 3, thickness / 2 + 10])
|
||||
rotate([90, 0, 90])
|
||||
teardrop(r = 3, h = 2 * mbracket_thickness + 1, center = true);
|
||||
|
||||
}
|
||||
//
|
||||
// limit switch bracket
|
||||
//
|
||||
difference() {
|
||||
translate([front - eta, sbracket_y, - thickness / 2])
|
||||
rotate([90, 0, 0])
|
||||
linear_extrude(height = sbracket_thickness, center = true)
|
||||
polygon([
|
||||
[0, 0],
|
||||
[sbracket_depth, sbracket_height - microswitch_length() + 2],
|
||||
[sbracket_depth, sbracket_height],
|
||||
[sbracket_depth - 10, sbracket_height],
|
||||
//[-length / 2 + clamp_width / 2 - eta, thickness + clamp_height],
|
||||
[-length / 2 + clamp_width / 2 - eta, thickness - eta]
|
||||
]);
|
||||
translate([switch_op_x, sbracket_y + sbracket_thickness / 2 + microswitch_thickness() / 2, switch_op_z])
|
||||
rotate([0, -90, -90])
|
||||
microswitch_holes(h = sbracket_thickness);
|
||||
}
|
||||
}
|
||||
else {
|
||||
//
|
||||
// idler end
|
||||
//
|
||||
difference() {
|
||||
union() {
|
||||
translate([back - idler_width / 2 + eta - slit / 2, idler_back - idler_depth / 2, 0])
|
||||
rounded_rectangle([idler_width - slit, idler_depth, thickness], r = 2, center = true);
|
||||
|
||||
translate([back - 5, idler_back - (idler_back + bar_y - slit / 2) / 2, 0])
|
||||
cube([10, idler_back + bar_y - slit / 2, thickness], center = true);
|
||||
|
||||
translate([back, idler_back, 0])
|
||||
rotate([0, 0, 90])
|
||||
fillet(h = thickness, r = idler_width / 2);
|
||||
}
|
||||
|
||||
translate([back - idler_width / 2, -bar_y, 0])
|
||||
rotate([90, 0, 90])
|
||||
teardrop(r = X_bar_dia / 2 + 0.5, h = idler_width + 1, center = true);
|
||||
|
||||
translate([x_idler_offset(), idler_back, 0])
|
||||
rotate([90, 0, 0])
|
||||
nut_trap(M4_clearance_radius, M4_nut_radius, M4_nut_trap_depth);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module x_end_assembly(motor_end) {
|
||||
if(motor_end)
|
||||
assembly("x_motor_assembly");
|
||||
else
|
||||
assembly("x_idler_assembly");
|
||||
//
|
||||
// RP bit
|
||||
//
|
||||
color([0,1,0]) render() x_end_bracket(motor_end, true);
|
||||
//
|
||||
// bearings
|
||||
//
|
||||
for(i = [0,2])
|
||||
translate([0, 0, (shelves[i] + shelves[i+1])/2 - thickness / 2])
|
||||
rotate([0,90,0])
|
||||
linear_bearing(Z_bearings);
|
||||
//
|
||||
// lead nut
|
||||
//
|
||||
translate([-z_bar_offset(), 0 , -thickness / 2 + Z_nut_depth])
|
||||
rotate([180, 0, 0])
|
||||
nut(Z_nut);
|
||||
//
|
||||
// bearing clamp fasteners
|
||||
//
|
||||
for(side = [-1, 1]) {
|
||||
translate([front - length / 2, side * (bar_y + clamp_thickness + slit / 2), thickness / 2 + washer_diameter(washer) / 2])
|
||||
rotate([-90 * side,0,0])
|
||||
screw_and_washer(hex_screw, 16);
|
||||
|
||||
translate([front - length / 2, side * (bar_y - clamp_depth - slit / 2 + nut_trap_depth), thickness / 2 + washer_diameter(washer) / 2])
|
||||
rotate([90 * side,0,0])
|
||||
nut(nut, true);
|
||||
}
|
||||
if(motor_end) {
|
||||
translate([x_motor_offset(), mbracket_front + eta, 0]) {
|
||||
rotate([90, motor_angle, 0]) {
|
||||
NEMA(X_motor);
|
||||
translate([0,0, mbracket_thickness])
|
||||
NEMA_screws(X_motor, 3);
|
||||
translate([0, 0, 4])
|
||||
pulley_assembly();
|
||||
}
|
||||
}
|
||||
translate([switch_op_x, sbracket_y - sbracket_thickness / 2 - microswitch_thickness() / 2, switch_op_z])
|
||||
rotate([0, -90, -90]) {
|
||||
microswitch();
|
||||
microswitch_hole_positions()
|
||||
translate([0,0, -(microswitch_thickness())])
|
||||
rotate([180,0,0])
|
||||
screw_and_washer(No2_screw, 13);
|
||||
}
|
||||
//
|
||||
// ribbon clamps
|
||||
//
|
||||
translate([x_motor_offset(), x_end_ribbon_clamp_y(), x_end_ribbon_clamp_z()])
|
||||
rotate([-90, 0, 0])
|
||||
ribbon_clamp_assembly(x_end_ways, M3_hex_screw, 16, mbracket_thickness);
|
||||
|
||||
translate([ribbon_clamp_x, ribbon_clamp_y, ribbon_clamp_z])
|
||||
rotate([-90, 90, 90])
|
||||
ribbon_clamp_assembly(extruder_ways, ribbon_screw, 16, wall, true);
|
||||
}
|
||||
else {
|
||||
translate([x_idler_offset(), belt_edge - belt_width(X_belt) / 2, 0]) {
|
||||
rotate([90,0,0 ])
|
||||
ball_bearing(BB624);
|
||||
for(i = [-1, 1]) {
|
||||
translate([0, (ball_bearing_width(X_idler_bearing) / 2) * i, 0])
|
||||
rotate([-i * 90, 0, 0])
|
||||
washer(M4_washer);
|
||||
translate([0, (ball_bearing_width(X_idler_bearing) / 2 + washer_thickness(M4_washer)) * i, 0])
|
||||
rotate([-i * 90, 0, 0])
|
||||
washer(M5_penny_washer);
|
||||
}
|
||||
translate([0,-ball_bearing_width(X_idler_bearing) / 2 - washer_thickness(M4_washer) - washer_thickness(M5_penny_washer),0])
|
||||
rotate([90,0,0])
|
||||
screw(M4_cap_screw, idler_screw_length);
|
||||
}
|
||||
translate([x_idler_offset(), idler_back - M4_nut_trap_depth, 0])
|
||||
rotate([-90, 0, 0])
|
||||
nut(M4_nut, true);
|
||||
}
|
||||
if(motor_end)
|
||||
end("x_motor_assembly");
|
||||
else
|
||||
end("x_idler_assembly");
|
||||
}
|
||||
|
||||
module x_motor_bracket_stl() translate([0, 0, thickness / 2]) mirror ([1,0,0]) x_end_bracket(true);
|
||||
module x_idler_bracket_stl() translate([0, 0, thickness / 2]) x_end_bracket(false);
|
||||
|
||||
//x_end_bracket(false);
|
||||
//x_end_assembly(false);
|
||||
|
||||
//mirror ([1,0,0]) x_end_bracket(true);
|
||||
mirror ([1,0,0]) x_end_assembly(true);
|
103
scad/y-bearing-mount.scad
Normal file
103
scad/y-bearing-mount.scad
Normal file
@ -0,0 +1,103 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// For the y carriage
|
||||
//
|
||||
include <conf/config.scad>
|
||||
include <positions.scad>
|
||||
use <bearing-holder.scad>
|
||||
use <bar-clamp.scad>
|
||||
|
||||
slot = 2;
|
||||
tab_length = bearing_clamp_tab + slot;
|
||||
|
||||
function bearing_mount_width(bearing) = bearing_holder_width(bearing) + 2 * tab_length;
|
||||
function bearing_mount_length(bearing) = bearing_holder_length(bearing);
|
||||
|
||||
module tab() {
|
||||
linear_extrude(height = bearing_clamp_tab_height, center = false, convexity = 6)
|
||||
difference() {
|
||||
union() {
|
||||
translate([(bearing_clamp_tab / 2 + slot) / 2, 0])
|
||||
square([bearing_clamp_tab / 2 + slot, bearing_clamp_tab], center = true);
|
||||
translate([bearing_clamp_tab / 2 + slot ,0])
|
||||
circle(r = bearing_clamp_tab/ 2, center = true);
|
||||
}
|
||||
translate([bearing_clamp_tab / 2, 0])
|
||||
circle(r = screw_clearance_radius, center = true);
|
||||
translate([bearing_clamp_tab / 2 + slot, 0, 0])
|
||||
circle(r = screw_clearance_radius, center = true);
|
||||
translate([bearing_clamp_tab / 2 + slot / 2, 0])
|
||||
square([slot, screw_clearance_radius * 2], center = true);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
module bearing_mount(bearing, height, endstop) {
|
||||
|
||||
endstop_w = bar_clamp_switch_x_offset() + microswitch_thickness() / 2 - bearing_holder_width(bearing) / 2;
|
||||
endstop_d = 3;
|
||||
endstop_h = height - bar_clamp_switch_z_offset() + microswitch_thickness() / 4;
|
||||
|
||||
stl(str("y_bearing_mount", endstop ? "_switch" : ""));
|
||||
color([1,0,0]) union() {
|
||||
bearing_holder(bearing, height);
|
||||
for(end = [-1, 1])
|
||||
translate([end * (bearing_holder_width(bearing) / 2 - eta), -end * (bearing_holder_length(bearing) - bearing_clamp_tab)/2, -height])
|
||||
rotate([0,0,90 - end * 90])
|
||||
tab();
|
||||
if(endstop)
|
||||
translate([-(bearing_holder_width(bearing) / 2 + endstop_w / 2),
|
||||
-(bearing_holder_length(bearing) / 2 - endstop_d / 2),
|
||||
endstop_h / 2 - height])
|
||||
cube([endstop_w, endstop_d, endstop_h], center = true);
|
||||
}
|
||||
}
|
||||
|
||||
module bearing_mount_holes(height)
|
||||
for(end = [-1, 1])
|
||||
translate([end * (bearing_holder_width(Y_bearings) / 2 + tab_length / 2),
|
||||
-end * (bearing_holder_length(Y_bearings) - bearing_clamp_tab) / 2, 0])
|
||||
cylinder(r = screw_clearance_radius, h = 100, center = true);;
|
||||
|
||||
module y_bearing_assembly(height, endstop = false)
|
||||
{
|
||||
//assembly("y_bearing_assembly");
|
||||
|
||||
color([1,0,0]) render() bearing_mount(Y_bearings, height, endstop);
|
||||
|
||||
rotate([0,0,90]) {
|
||||
linear_bearing(Y_bearings);
|
||||
rotate([0,90,0])
|
||||
ziptie(small_ziptie, bearing_ziptie_radius(Y_bearings));
|
||||
}
|
||||
|
||||
//
|
||||
// Fasterners
|
||||
//
|
||||
for(end = [-1, 1])
|
||||
translate([end * (bearing_holder_width(Y_bearings) / 2 + tab_length / 2),
|
||||
-end * (bearing_holder_length(Y_bearings) - bearing_clamp_tab) / 2, -height + bearing_clamp_tab_height]) {
|
||||
nut_and_washer(nut, true);
|
||||
translate([0,0, -bearing_clamp_tab_height - sheet_thickness(Y_carriage)])
|
||||
rotate([180, 0, 0])
|
||||
screw_and_washer(cap_screw, 16);
|
||||
}
|
||||
|
||||
//end("y_bearing_assembly");
|
||||
}
|
||||
|
||||
module y_bearing_mount_stl() translate([0,0, Y_bearing_holder_height]) bearing_mount(Y_bearings, Y_bearing_holder_height, false);
|
||||
module y_bearing_mount_switch_stl() translate([0,0, Y_bearing_holder_height]) bearing_mount(Y_bearings, Y_bearing_holder_height, true);
|
||||
|
||||
if(1)
|
||||
y_bearing_assembly(Y_bearing_holder_height, false);
|
||||
else {
|
||||
y_bearing_mount_stl();
|
||||
translate([ bearing_mount_width(Y_bearings) - tab_length + 2, 0, 0]) y_bearing_mount_stl();
|
||||
translate([-(bearing_mount_width(Y_bearings) - tab_length + 2), 0, 0]) y_bearing_mount_switch_stl();
|
||||
};
|
147
scad/y-belt-anchor.scad
Normal file
147
scad/y-belt-anchor.scad
Normal file
@ -0,0 +1,147 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// Anchors the belt to the bottom of the y carriage
|
||||
//
|
||||
include <conf/config.scad>
|
||||
include <positions.scad>
|
||||
|
||||
wall = 2;
|
||||
|
||||
clearance = 2;
|
||||
thickness = M3_nut_trap_depth + wall;
|
||||
rad = 3;
|
||||
|
||||
clamp_thickness = 3;
|
||||
|
||||
width = belt_width(Y_belt) + 3 + washer_diameter(M3_washer) + clearance;
|
||||
inner_width = (M3_nut_radius + wall) * 2;
|
||||
depth = washer_diameter(M3_washer) + clearance;
|
||||
length = depth + 2 * (2 * M3_nut_radius * cos(30) + wall);
|
||||
|
||||
tooth_height = belt_thickness(Y_belt) / 2;
|
||||
tooth_width = belt_pitch(Y_belt) / 2;
|
||||
|
||||
function y_belt_anchor_width() = width;
|
||||
|
||||
module y_belt_anchor_holes() {
|
||||
for(side = [-1, 1])
|
||||
translate([0, side * (depth / 2 + M3_nut_radius * cos(30) + eta) + depth / 2, 0])
|
||||
cylinder(r = M3_clearance_radius, h = 100, center = true);
|
||||
|
||||
}
|
||||
|
||||
module y_belt_anchor(height, toothed) {
|
||||
h = height + belt_thickness(Y_belt) - belt_clearance;
|
||||
recess = length - depth;
|
||||
|
||||
stl(str("y_belt_anchor", toothed ? "_toothed" : ""));
|
||||
color([0,1,0]) union() {
|
||||
difference() {
|
||||
union() {
|
||||
translate([0, depth / 2, h / 2]) // tall bit
|
||||
rounded_rectangle([width, depth, h], r = rad);
|
||||
|
||||
translate([0, depth / 2, thickness / 2])
|
||||
rounded_rectangle([inner_width, length, thickness], r = rad); // wide bit
|
||||
|
||||
for(side = [-1, 1]) // webs
|
||||
for(end = [-1, 1])
|
||||
translate([side * (M3_nut_radius + wall / 2), eta + (end + 1) * (depth / 2 - 2 * eta), thickness - eta])
|
||||
rotate([90,0,90 * end])
|
||||
right_triangle(width = (length - depth) / 2 - rad, height = h - thickness, h = wall);
|
||||
}
|
||||
|
||||
|
||||
translate([0, depth / 2, height + (h - height) / 2 + 2 * eta]) // slot for belt
|
||||
cube([belt_width(Y_belt) + belt_clearance, depth + 1, h - height], center = true);
|
||||
|
||||
for(side = [-1, 1]) { // clamp screw nut traps
|
||||
translate([side * (belt_width(Y_belt) / 2 + M3_clearance_radius), depth / 2, 0 ])
|
||||
rotate([0,0,90/7 * (side + 1)])
|
||||
nut_trap(M3_clearance_radius, M3_nut_radius, height - clamp_thickness);
|
||||
|
||||
translate([0, side * (depth / 2 + M3_nut_radius * cos(30) + eta) + depth / 2, thickness]) // mounting screw nut traps
|
||||
nut_trap(M3_clearance_radius, M3_nut_radius, M3_nut_trap_depth);
|
||||
|
||||
}
|
||||
translate([0, depth / 2, height + (h - height) / 2 + 2 * eta]) // slot to join screw holes
|
||||
cube([belt_width(Y_belt) + M3_clearance_radius * 2, corrected_diameter(M3_clearance_radius * 2), h - height], center = true);
|
||||
}
|
||||
|
||||
for(side = [-1, 1]) // blind the nut traps
|
||||
translate([side * (belt_width(Y_belt) / 2 + M3_clearance_radius), depth / 2, height - clamp_thickness])
|
||||
cylinder(r = M3_clearance_radius + 0.5, h = layer_height + eta);
|
||||
|
||||
if(toothed)
|
||||
translate([0,depth / 2, height - eta + tooth_height / 2])
|
||||
cube([belt_width(Y_belt), tooth_width, tooth_height], center = true);
|
||||
}
|
||||
}
|
||||
|
||||
module y_belt_clip(toothed) {
|
||||
stl(str("y_belt_clip", toothed ? "_toothed" : ""));
|
||||
|
||||
color([1, 0, 0]) union() {
|
||||
translate([0, 0, clamp_thickness / 2]) difference() {
|
||||
rounded_rectangle([width, depth, clamp_thickness], r = rad);
|
||||
|
||||
for(side = [-1, 1]) // screw holes
|
||||
translate([side * (belt_width(Y_belt) / 2 + M3_clearance_radius), 0, 0 ])
|
||||
poly_cylinder(r = M3_clearance_radius, h = clamp_thickness + 1, center = true);
|
||||
}
|
||||
if(toothed)
|
||||
translate([0,0, clamp_thickness - eta + tooth_height / 2])
|
||||
cube([belt_width(Y_belt), tooth_width, tooth_height], center = true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module y_belt_anchor_assembly(height, toothed) {
|
||||
//assembly("y_belt_anchor_assembly");
|
||||
|
||||
color([0, 1, 0]) render() y_belt_anchor(height, toothed);
|
||||
|
||||
translate([0, depth / 2, height + belt_thickness(Y_belt) + clamp_thickness]) {
|
||||
rotate([180, 0, 0])
|
||||
color([1, 0, 0]) render() y_belt_clip(!toothed);
|
||||
//
|
||||
// Clamp screws
|
||||
//
|
||||
for(side = [-1, 1])
|
||||
translate([side * (belt_width(Y_belt) / 2 + M3_clearance_radius), 0, 0]) {
|
||||
screw_and_washer(M3_cap_screw, 16);
|
||||
translate([0, 0, -2 * clamp_thickness - belt_thickness(Y_belt)])
|
||||
rotate([180, 0, 0])
|
||||
nut(M3_nut, true);
|
||||
}
|
||||
}
|
||||
for(side = [-1, 1])
|
||||
translate([0, side * (depth / 2 + M3_nut_radius * cos(30) + eta) + depth / 2, 0]) {
|
||||
translate([0, 0, thickness - M3_nut_trap_depth])
|
||||
nut(M3_nut, true);
|
||||
translate([0, 0, - sheet_thickness(Y_carriage)])
|
||||
rotate([180, 0, 0])
|
||||
screw_and_washer(M3_cap_screw, 16);
|
||||
}
|
||||
|
||||
//end("y_belt_anchor_assembly");
|
||||
}
|
||||
|
||||
module y_belt_anchor_stl() y_belt_anchor(Y_belt_clamp_height, false);
|
||||
module y_belt_anchor_toothed_stl() y_belt_anchor(Y_belt_clamp_height, true);
|
||||
module y_belt_clip_stl() y_belt_clip(false);
|
||||
module y_belt_clip_toothed_stl() y_belt_clip(true);
|
||||
|
||||
if(1)
|
||||
y_belt_anchor_assembly(Y_belt_clamp_height, true);
|
||||
else {
|
||||
translate([0, 0, 0]) y_belt_anchor_toothed_stl();
|
||||
translate([0, 25, 0]) y_belt_anchor_stl();
|
||||
translate([15, 5, 0]) rotate([0,0,90])y_belt_clip_toothed_stl();
|
||||
translate([15,30, 0]) rotate([0,0,90]) y_belt_clip_stl();
|
||||
}
|
115
scad/y-idler-bracket.scad
Normal file
115
scad/y-idler-bracket.scad
Normal file
@ -0,0 +1,115 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// Holds the idler pulley
|
||||
//
|
||||
include <conf/config.scad>
|
||||
use <y-motor-bracket.scad>
|
||||
|
||||
slot = 10;
|
||||
axel_height = y_motor_height() + pulley_inner_radius - ball_bearing_diameter(Y_idler_bearing) / 2;
|
||||
base_thickness = 5;
|
||||
wall = default_wall;
|
||||
|
||||
clearance = 1;
|
||||
dia = washer_diameter(M5_penny_washer) + 2 * clearance;
|
||||
tab_length = washer_diameter(screw_washer(base_screw)) + 2 * clearance + slot;
|
||||
length = dia + wall + tab_length;
|
||||
|
||||
function y_idler_clearance() = dia / 2 + slot;
|
||||
function y_idler_offset() = dia / 2 + wall + tab_length;
|
||||
|
||||
width = (wall + washer_thickness(M5_penny_washer) + washer_thickness(M4_washer) + ball_bearing_width(Y_idler_bearing)) * 2;
|
||||
back_width = washer_diameter(screw_washer(base_screw)) + 2 * clearance + 2 * wall;
|
||||
|
||||
height = axel_height + dia / 2;
|
||||
|
||||
module y_idler_bracket_stl() {
|
||||
stl("y_idler_bracket");
|
||||
|
||||
color([0,1,0]) intersection() {
|
||||
difference() {
|
||||
rotate([90, 0, 90])
|
||||
linear_extrude(height = width, center = true) //side profile
|
||||
hull() {
|
||||
translate([0, axel_height])
|
||||
circle(dia / 2);
|
||||
|
||||
translate([-dia / 2 , 0])
|
||||
square([length, base_thickness]); // base
|
||||
|
||||
square([dia / 2 + wall, height]); // upright
|
||||
}
|
||||
|
||||
translate([0, - dia / 2, height + base_thickness]) // cavity for bearing
|
||||
rotate([0, 90, 0])
|
||||
rounded_rectangle(size = [height * 2, dia * 2, width - 2 * wall], r = dia / 2);
|
||||
|
||||
translate([0, dia / 2 + wall + tab_length / 2 + eta, height / 2 + base_thickness + eta]) // cavity for screw slot
|
||||
cube([back_width - 2 * wall, tab_length, height], center = true);
|
||||
|
||||
translate([0, dia / 2 + wall + slot / 2 + washer_diameter(screw_washer(base_screw)) / 2 + clearance , 0]) // screw slot
|
||||
rotate([0,0,90])
|
||||
slot(r = screw_clearance_radius(base_screw), l = slot, h = 2 * base_thickness + 1, center = true);
|
||||
|
||||
translate([0, 0, axel_height]) // hole for axel
|
||||
rotate([90, 0, 90])
|
||||
teardrop_plus(r = M4_clearance_radius, h = width + 1, center = true);
|
||||
}
|
||||
union() { // plan profile
|
||||
translate([0, (length - tab_length) / 2 - dia / 2, -1])
|
||||
rounded_rectangle([width - eta, length - tab_length - eta, height + 2], r = 2, center = false);
|
||||
|
||||
translate([0, length - (tab_length + 5) / 2 - dia / 2 - eta, -1])
|
||||
rounded_rectangle([back_width, tab_length + 5, height + 2], r = 2, center = false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module y_idler_screw_hole()
|
||||
translate([0, dia / 2 + wall + tab_length / 2 - slot / 2,0])
|
||||
child();
|
||||
|
||||
|
||||
module y_idler_assembly() {
|
||||
assembly("y_idler_assembly");
|
||||
|
||||
color([0,1,0]) render() y_idler_bracket_stl();
|
||||
|
||||
translate([0, 0, axel_height]) rotate([0, -90, 0]) {
|
||||
|
||||
for(side = [-1, 1]) {
|
||||
translate([0, 0, (ball_bearing_width(Y_idler_bearing) / 2) * side])
|
||||
ball_bearing(BB624);
|
||||
translate([0, 0, ball_bearing_width(Y_idler_bearing) * side])
|
||||
rotate([0, side * 90 - 90, 0])
|
||||
washer(M4_washer);
|
||||
translate([0, 0, (ball_bearing_width(Y_idler_bearing) + washer_thickness(M4_washer)) * side])
|
||||
rotate([0, side * 90 - 90, 0])
|
||||
washer(M5_penny_washer);
|
||||
}
|
||||
translate([0, 0, width / 2])
|
||||
screw_and_washer(M4_cap_screw, 40); // could be 30mm but would be the only one, 40 is used on the idler
|
||||
|
||||
translate([0, 0, -width / 2])
|
||||
rotate([180, 0, 0])
|
||||
nut_and_washer(M4_nut, true);
|
||||
}
|
||||
|
||||
y_idler_screw_hole()
|
||||
translate([0, 0, base_thickness])
|
||||
base_screw();
|
||||
|
||||
end("y_idler_assembly");
|
||||
}
|
||||
|
||||
|
||||
if(1)
|
||||
y_idler_assembly();
|
||||
else
|
||||
y_idler_bracket_stl();
|
105
scad/y-motor-bracket.scad
Normal file
105
scad/y-motor-bracket.scad
Normal file
@ -0,0 +1,105 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// Fastens the Y motor to the base
|
||||
//
|
||||
include <conf/config.scad>
|
||||
use <pulley.scad>
|
||||
|
||||
thickness = 4;
|
||||
tab = 2 + washer_diameter(screw_washer(base_screw));
|
||||
foot = 5;
|
||||
holes = tab / 2 + 1;
|
||||
|
||||
function y_motor_bracket_height() = round(NEMA_width(Y_motor)) + 2;
|
||||
function y_motor_height() = y_motor_bracket_height() / 2;
|
||||
function y_motor_bracket_width() = y_motor_bracket_height() + 2 * (tab + thickness);
|
||||
function y_motor_bracket_top_width() = y_motor_bracket_width() - 2 * tab;
|
||||
|
||||
depth = y_motor_bracket_height() + thickness - foot;
|
||||
|
||||
module y_motor_bracket() {
|
||||
height = y_motor_bracket_height();
|
||||
width = y_motor_bracket_width();
|
||||
|
||||
stl("y_motor_bracket");
|
||||
color([0,1,0]) {
|
||||
difference() {
|
||||
translate([0, 0, thickness - depth / 2]) // main body
|
||||
cube([width, height, depth], center = true);
|
||||
|
||||
cylinder(r = NEMA_big_hole(Y_motor), h = thickness * 2 + 1, center = true); // hole for stepper locating boss
|
||||
|
||||
translate([0, 0, - depth / 2])
|
||||
cube([depth, height + 1, depth], center = true); // space for motor
|
||||
|
||||
translate([-width / 2, foot, 0])
|
||||
cube([tab * 2, height, depth * 2], center = true); // cut outs for lugs
|
||||
|
||||
translate([width / 2, foot, 0])
|
||||
cube([tab * 2, height, depth * 2], center = true);
|
||||
|
||||
translate([0, - height / 2 + foot, - depth + thickness]) // sloping sides
|
||||
rotate([45,0,0])
|
||||
translate([0,0, - depth / 2])
|
||||
cube([width, 3 * height, depth], center = true);
|
||||
|
||||
for(x = NEMA_holes(Y_motor)) // motor screw holes
|
||||
for(y = NEMA_holes(Y_motor))
|
||||
translate([x,y,0])
|
||||
poly_cylinder(r = M3_clearance_radius, h = 2 * thickness + 1, center = true);
|
||||
//
|
||||
// mounting screw holes
|
||||
//
|
||||
for(side = [-1, 1])
|
||||
for(z = [thickness - depth + holes, thickness - holes])
|
||||
translate([side * (width / 2 - tab / 2), - height / 2, z])
|
||||
rotate([-90, 0, 0]) teardrop_plus(r = screw_clearance_radius(base_screw), h = foot * 2 + 1, center = true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module y_motor_bracket_holes()
|
||||
for(side = [-1, 1])
|
||||
for(z = [thickness - depth + holes, thickness - holes])
|
||||
translate([side * (y_motor_bracket_width() / 2 - tab / 2), -y_motor_bracket_height() / 2 + foot, z])
|
||||
rotate([-90, 0, 0])
|
||||
child();
|
||||
|
||||
|
||||
|
||||
module y_motor_assembly() {
|
||||
assembly("y_motor_assembly");
|
||||
|
||||
color([0,1,0]) render() y_motor_bracket();
|
||||
//
|
||||
// Mounting screws and washers
|
||||
//
|
||||
y_motor_bracket_holes()
|
||||
base_screw();
|
||||
|
||||
//
|
||||
// Motor and screws
|
||||
//
|
||||
NEMA(Y_motor);
|
||||
translate([0,0, thickness])
|
||||
NEMA_screws(Y_motor);
|
||||
//
|
||||
// Pulley
|
||||
//
|
||||
translate([0, 0, 4])
|
||||
pulley_assembly();
|
||||
|
||||
end("y_motor_assembly");
|
||||
}
|
||||
|
||||
module y_motor_bracket_stl() translate([0, 0, thickness]) rotate([0,180,0]) y_motor_bracket();
|
||||
|
||||
if(1)
|
||||
y_motor_assembly();
|
||||
else
|
||||
y_motor_bracket_stl();
|
114
scad/z-coupling.scad
Normal file
114
scad/z-coupling.scad
Normal file
@ -0,0 +1,114 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// Couples the leadscrews to the motor
|
||||
//
|
||||
include <conf/config.scad>
|
||||
|
||||
studding_dia = Z_screw_dia;
|
||||
shaft_dia = 7; // includes tubing
|
||||
holeR = M3_clearance_radius;
|
||||
nutR = M3_nut_radius;
|
||||
nutH = M3_nut_trap_depth;
|
||||
corner_cut = 26;
|
||||
wall = 2;
|
||||
|
||||
holeX = 7.5;
|
||||
holeY2 = studding_dia / 2 + M3_clearance_radius;
|
||||
holeY1 = shaft_dia / 2 + M3_clearance_radius;
|
||||
|
||||
nut_flat_radius = M3_nut_radius * cos(30);
|
||||
width = 2 * (max(holeY2, holeY1) + nut_flat_radius + wall);
|
||||
length = 30;
|
||||
|
||||
function z_coupling_length() = length;
|
||||
|
||||
depth = 8;
|
||||
centre_line = depth / 2 + 0.5;
|
||||
|
||||
rad = M3_nut_radius + wall;
|
||||
|
||||
module z_coupling_stl(){
|
||||
stl("z_coupling");
|
||||
|
||||
color([1,0,0]) translate([0, 0, depth / 2]) union() {
|
||||
difference(){
|
||||
linear_extrude(height = depth, center = true)
|
||||
hull() {
|
||||
polygon([
|
||||
[ length / 2, shaft_dia / 2 + 1],
|
||||
[ length / 2, -shaft_dia / 2 - 1],
|
||||
[-length / 2, -studding_dia / 2 - 1],
|
||||
[-length / 2, studding_dia / 2 + 1]
|
||||
]);
|
||||
translate([holeX, holeY1])
|
||||
circle(r = rad, center = true);
|
||||
translate([holeX, -holeY1])
|
||||
circle(r = rad, center = true);
|
||||
translate([-holeX, holeY2])
|
||||
circle(r = rad, center = true);
|
||||
translate([-holeX, -holeY2])
|
||||
circle(r = rad, center = true);
|
||||
}
|
||||
|
||||
//nut holes
|
||||
translate([ holeX, holeY1, nutH/2 - 4.01]) rotate([0,0, 30]) cylinder(h = nutH, r=nutR, $fn=6, center=true);
|
||||
translate([-holeX, holeY2, nutH/2 - 4.01]) rotate([0,0,-30]) cylinder(h = nutH, r=nutR, $fn=6, center=true);
|
||||
|
||||
//shaft groves
|
||||
translate([ -17, 0, centre_line]) rotate([0,90,0]) cylinder(h = 16, r=studding_dia / 2);
|
||||
translate([ 1, 0, centre_line]) rotate([0,90,0]) cylinder(h = 16, r=shaft_dia / 2);
|
||||
|
||||
//screw holes
|
||||
for(y = [-1, 1]) {
|
||||
translate([ holeX, y * holeY1, -10]) rotate([0,0, y * 360/28]) poly_cylinder(h = 20, r=holeR);
|
||||
translate([-holeX, y * holeY2, -10]) rotate([0,0, y * 360/28]) poly_cylinder(h = 20, r=holeR);
|
||||
}
|
||||
//slots to prevent screw holes beading into the shaft holes
|
||||
translate([holeX, 0, centre_line])
|
||||
cube([2 * holeR, 2 * holeY1, shaft_dia], center = true);
|
||||
|
||||
translate([-holeX, 0, centre_line])
|
||||
cube([2 * holeR, 2 * holeY2, studding_dia], center = true);
|
||||
|
||||
}
|
||||
// bridge
|
||||
translate([ holeX, holeY1, nutH-3.9]) cylinder(h = 0.4, r=nutR+0.1, $fn=6, center=true);
|
||||
translate([-holeX, holeY2, nutH-3.9]) cylinder(h = 0.4, r=nutR+0.1, $fn=6, center=true);
|
||||
}
|
||||
}
|
||||
|
||||
module z_coupler_assembly() {
|
||||
//assembly("z_coupler_assembly");
|
||||
|
||||
for(side = [-1, 1])
|
||||
explode([10 * side, 0, 0])
|
||||
translate([centre_line * side, 0, 0])
|
||||
rotate([0, 90, 90 * side + 90]) {
|
||||
color([1,0,0]) render() translate([0, 0, -depth/2]) z_coupling_stl();
|
||||
for(pos = [[holeX, -holeY1], [-holeX, -holeY2]])
|
||||
translate([pos[0], pos[1], -depth/2])
|
||||
rotate([180, 0, 0])
|
||||
screw_and_washer(M3_cap_screw, 20);
|
||||
|
||||
for(pos = [[holeX, holeY1], [-holeX, holeY2]])
|
||||
translate([pos[0], pos[1], -depth/2 + nutH])
|
||||
rotate([180, 0, 0])
|
||||
nut(M3_nut, true);
|
||||
|
||||
}
|
||||
|
||||
translate([0,0, -9])
|
||||
tubing(shaft_dia, 5, 16);
|
||||
|
||||
//end("z_coupler_assembly");
|
||||
}
|
||||
|
||||
if(0)
|
||||
z_coupling_stl();
|
||||
else
|
||||
z_coupler_assembly();
|
167
scad/z-limit-switch-bracket.scad
Normal file
167
scad/z-limit-switch-bracket.scad
Normal file
@ -0,0 +1,167 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// Adjustable bottom limit switch
|
||||
//
|
||||
include <conf/config.scad>
|
||||
include <positions.scad>
|
||||
|
||||
wall = 2;
|
||||
thickness = 5;
|
||||
adjustment = 20;
|
||||
down_adjustment = 10;
|
||||
hinge_length = 2;
|
||||
hinge_post = 4;
|
||||
switch_boss = 7;
|
||||
washers = 2;
|
||||
|
||||
switch_y = max(14 - microswitch_thickness() / 2, gantry_setback - x_bar_spacing() / 2);
|
||||
|
||||
switch_mount_height = switch_y - microswitch_thickness() / 2;
|
||||
|
||||
hinge_height = thickness + washer_diameter(M3_washer) + 2;
|
||||
|
||||
centre = max(washer_diameter(M3_washer), 2 * (nut_radius(M3_nut) + wall));
|
||||
screw_spacing = adjustment + centre + washer_diameter(screw_washer(frame_screw)) + 2;
|
||||
hinge_thickness = 2 * filament_width + eta;
|
||||
|
||||
leg_width = 1 + washer_diameter(screw_washer(frame_screw));
|
||||
leg_length = adjustment + screw_spacing + leg_width + hinge_post;
|
||||
|
||||
lever_width = 4;
|
||||
lever_length = leg_length / 2 + centre / 2 + hinge_post / 2;
|
||||
|
||||
|
||||
bottom_z = microswitch_hole_y_offset() - switch_boss / 2;
|
||||
|
||||
slot_x = -x_end_bar_length() + z_bar_offset() -lever_width - hinge_length - leg_width / 2 -base_clearance;
|
||||
screw_x = slot_x + leg_width / 2 + hinge_length + lever_width;
|
||||
screw_y = hinge_height - washer_diameter(M3_washer) / 2 - 2;
|
||||
screw_z = bottom_z + leg_length / 2 + hinge_post / 2;
|
||||
center_thickness = leg_width - washer_thickness(M3_washer) - nut_thickness(M3_nut, true);
|
||||
|
||||
module z_limit_screw_positions() {
|
||||
for(z = [0, screw_spacing])
|
||||
translate([slot_x, -thickness, bottom_z + hinge_post + leg_width / 2 + adjustment - down_adjustment + z])
|
||||
rotate([90, 0, 0])
|
||||
child();
|
||||
}
|
||||
|
||||
|
||||
module z_limit_switch_bracket_stl() {
|
||||
stl("z_limit_switch_bracket");
|
||||
difference() {
|
||||
union() {
|
||||
//
|
||||
// Boss for switch screws
|
||||
//
|
||||
translate([0, 0, -microswitch_thickness() / 2])
|
||||
hull() {
|
||||
microswitch_hole_positions()
|
||||
cylinder(h = switch_mount_height, r = switch_boss / 2);
|
||||
translate([slot_x + leg_width / 2 + hinge_length, microswitch_hole_y_offset() - switch_boss / 2, microswitch_thickness() / 2])
|
||||
cube([1, switch_boss, switch_mount_height]);
|
||||
}
|
||||
//
|
||||
// Screw slot
|
||||
//
|
||||
linear_extrude(height = thickness, convexity = 5) {
|
||||
difference() {
|
||||
hull() {
|
||||
translate([slot_x, bottom_z + leg_length - leg_width / 2])
|
||||
circle(r = leg_width / 2, center = true);
|
||||
|
||||
translate([slot_x - leg_width / 2, bottom_z])
|
||||
square([leg_width, hinge_post]);
|
||||
}
|
||||
hull()
|
||||
for(z = [bottom_z + screw_spacing, bottom_z + screw_spacing + adjustment])
|
||||
translate([slot_x, z + hinge_post + leg_width / 2])
|
||||
circle(r = screw_radius(frame_screw), center = true);
|
||||
hull()
|
||||
for(z = [bottom_z, bottom_z + adjustment])
|
||||
translate([slot_x, z + hinge_post + leg_width / 2])
|
||||
circle(r = screw_radius(frame_screw), center = true);
|
||||
}
|
||||
}
|
||||
//
|
||||
// Hinge
|
||||
//
|
||||
translate([slot_x, bottom_z + hinge_post / 2, hinge_height / 2])
|
||||
cube([leg_width, hinge_post, hinge_height], center = true);
|
||||
|
||||
translate([slot_x + hinge_length / 2, bottom_z + hinge_thickness / 2, hinge_height / 2])
|
||||
cube([leg_width + hinge_length + eta, hinge_thickness, hinge_height], center = true);
|
||||
//
|
||||
// Lever
|
||||
//
|
||||
translate([slot_x + leg_width / 2 + hinge_length, bottom_z, 0])
|
||||
cube([lever_width, lever_length, hinge_height]);
|
||||
//
|
||||
// Adjuster screw bracket
|
||||
//
|
||||
translate([slot_x + leg_width / 2 -center_thickness / 2, screw_z, hinge_height / 2])
|
||||
cube([center_thickness, centre, hinge_height], center = true);
|
||||
|
||||
}
|
||||
translate([slot_x - leg_width / 2 - eta, screw_z, screw_y])
|
||||
rotate([0, 90, 0])
|
||||
cylinder(r = screw_y - 3, h = leg_width - center_thickness);
|
||||
|
||||
translate([screw_x, screw_z, screw_y])
|
||||
rotate([90, 0, 90])
|
||||
nut_trap(M3_clearance_radius, M3_nut_radius, screw_head_height(M3_hex_screw), true);
|
||||
|
||||
microswitch_hole_positions()
|
||||
poly_cylinder(h = 100, r = No2_pilot_radius, center = true);
|
||||
}
|
||||
}
|
||||
|
||||
module z_limit_switch_assembly() {
|
||||
assembly("z_limit_switch_assembly");
|
||||
pos = 0;
|
||||
screw_length = 16;
|
||||
washer_thickness = hinge_length / washers;
|
||||
|
||||
translate([0, 0, pos]) {
|
||||
rotate([90, 0, 0])
|
||||
color([0, 1, 0]) render()
|
||||
z_limit_switch_bracket_stl();
|
||||
|
||||
translate([screw_x - screw_head_height(M3_hex_screw), -screw_y, screw_z])
|
||||
rotate([0, 90, 0])
|
||||
screw(M3_hex_screw, 16);
|
||||
|
||||
for(i = [0 : washers - 1])
|
||||
translate([slot_x + leg_width / 2 + i * washer_thickness, -screw_y, screw_z])
|
||||
explode([i * 1, 0, 15], [washer_thickness / 2, 0, - washer_diameter(M3_rubber_washer) / 2])
|
||||
rotate([0, 90, 0])
|
||||
scale([1, 1, washer_thickness / washer_thickness(M3_rubber_washer)]) // squash it
|
||||
washer(M3_rubber_washer);
|
||||
|
||||
translate([slot_x + leg_width / 2 - center_thickness, -screw_y, screw_z])
|
||||
rotate([0, -90, 0])
|
||||
nut_and_washer(M3_nut, true);
|
||||
|
||||
translate([0, -switch_y, 0])
|
||||
rotate([90, 0, 0]) {
|
||||
microswitch();
|
||||
microswitch_hole_positions()
|
||||
screw_and_washer(No2_screw, 13);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
z_limit_screw_positions()
|
||||
frame_screw(thickness);
|
||||
end("z_limit_switch_assembly");
|
||||
}
|
||||
|
||||
if(1)
|
||||
z_limit_switch_assembly();
|
||||
else
|
||||
z_limit_switch_bracket_stl();
|
182
scad/z-motor-bracket.scad
Normal file
182
scad/z-motor-bracket.scad
Normal file
@ -0,0 +1,182 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// Fastens the Z motor to the gantry
|
||||
//
|
||||
include <conf/config.scad>
|
||||
include <positions.scad>
|
||||
use <z-coupling.scad>
|
||||
|
||||
corner_rad = 5;
|
||||
length = ceil(NEMA_width(Z_motor));
|
||||
thickness = 4;
|
||||
back_thickness = 5;
|
||||
back_height = 24;
|
||||
big_hole = NEMA_big_hole(Z_motor);
|
||||
clamp_height = washer_diameter(washer) + 3;
|
||||
clamp_thickness = bar_clamp_band;
|
||||
clamp_screw_clearance = 2;
|
||||
clamp_length = Z_bar_dia / 2 + bar_clamp_tab - 2;
|
||||
gap = 1.5;
|
||||
|
||||
clamp_width = Z_bar_dia + 2 * clamp_thickness;
|
||||
slot_inset = max((washer_diameter(screw_washer(frame_screw)) + 2),
|
||||
length / 2 - NEMA_holes(Z_motor)[1] + washer_diameter(M3_washer) / 2 + 1) / 2;
|
||||
|
||||
clamp_x = z_bar_offset() + clamp_length - bar_clamp_tab / 2;
|
||||
|
||||
function z_motor_bracket_height() = back_height;
|
||||
|
||||
module z_motor_bracket(y_offset, rhs) {
|
||||
width = y_offset + length / 2;
|
||||
cutout = y_offset - length / 2 - back_thickness;
|
||||
|
||||
stl(rhs? "z_motor_bracket_rhs" : "z_motor_bracket_lhs");
|
||||
color([0,1,0]) {
|
||||
difference() {
|
||||
union() {
|
||||
//
|
||||
// main body
|
||||
//
|
||||
translate([0, width / 2 - length / 2, back_height / 2])
|
||||
difference() {
|
||||
cube([length, width, back_height], center = true);
|
||||
translate([0, -back_thickness, thickness])
|
||||
cube([length + 1, width, back_height], center = true);
|
||||
}
|
||||
//
|
||||
// Bracing webs
|
||||
//
|
||||
for(x = [length / 2 - 2 * slot_inset - thickness / 2, -(length / 2 - 2 * slot_inset - thickness / 2)])
|
||||
translate([x, y_offset - back_thickness + eta, eta])
|
||||
rotate([90, 0, -90])
|
||||
right_triangle(width = y_offset - big_hole, height = back_height, h = thickness);
|
||||
//
|
||||
// bar clamp
|
||||
//
|
||||
translate([z_bar_offset() + clamp_length / 2 - eta, 0, clamp_height / 2 + eta])
|
||||
cube([clamp_length, clamp_width, clamp_height], center = true);
|
||||
translate([z_bar_offset(), 0, clamp_height / 2 + eta])
|
||||
cylinder(h = clamp_height, r = Z_bar_dia/2 + clamp_thickness, center = true);
|
||||
}
|
||||
//
|
||||
// front corners rounded
|
||||
//
|
||||
translate([-length / 2, - length / 2, thickness / 2])
|
||||
fillet(r = corner_rad, h = thickness + 1);
|
||||
translate([ length / 2, - length / 2, thickness / 2])
|
||||
rotate([0,0, 90])
|
||||
fillet(r = corner_rad, h = thickness + 1);
|
||||
//
|
||||
// Cut out between webs
|
||||
//
|
||||
translate([0, length / 2 + cutout / 2, thickness / 2])
|
||||
rounded_rectangle([length - 4 * slot_inset - 2 * thickness, cutout, thickness + 1], r = corner_rad / 2, center = true);
|
||||
//
|
||||
// motor holes
|
||||
//
|
||||
poly_cylinder(r = big_hole, h = thickness * 2 + 1, center = true); // hole for stepper locating boss
|
||||
|
||||
for(x = NEMA_holes(Z_motor)) // motor screw holes
|
||||
for(y = NEMA_holes(Z_motor))
|
||||
translate([x,y,0])
|
||||
poly_cylinder(r = M3_clearance_radius, h = 2 * thickness + 1, center = true);
|
||||
//
|
||||
// bar clamp
|
||||
//
|
||||
translate([z_bar_offset() + clamp_length / 2, 0, 0]) // clamp slot
|
||||
cube([clamp_length, gap, clamp_height * 2 + 1], center = true);
|
||||
|
||||
translate([clamp_x, Z_bar_dia / 2 + clamp_thickness, clamp_height / 2])
|
||||
rotate([90, 0, 0])
|
||||
nut_trap(screw_clearance_radius, nut_radius, nut_trap_depth, horizontal = true); // clamp screw
|
||||
|
||||
translate([z_bar_offset(), 0, 0])
|
||||
poly_cylinder(r = Z_bar_dia / 2, h = clamp_height * 2 + 1, center = true); // hole for z rod
|
||||
|
||||
//
|
||||
// screw slots in the back
|
||||
//
|
||||
for(side = [-1, 1])
|
||||
translate([side * (length / 2 - slot_inset), width - length / 2 - back_thickness / 2, back_height / 2 + thickness / 2])
|
||||
rotate([90, 0, 0])
|
||||
vertical_tearslot(h = back_thickness + 1, l = back_height - thickness - 2 * slot_inset,
|
||||
r = screw_clearance_radius(frame_screw), center = true);
|
||||
//
|
||||
// rounded corners on the back
|
||||
//
|
||||
translate([-length / 2, width - length / 2 - back_thickness / 2, back_height])
|
||||
rotate([-90, 0, 0])
|
||||
fillet(r = corner_rad, h = back_thickness + 1);
|
||||
|
||||
translate([length / 2, width - length / 2 - back_thickness / 2, back_height])
|
||||
rotate([-90, 90, 0])
|
||||
fillet(r = corner_rad, h = back_thickness + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function z_motor_bracket_hole_offset() = length / 2 - slot_inset;
|
||||
|
||||
module z_motor_bracket_holes(gantry_setback)
|
||||
for(side = [-1, 1])
|
||||
translate([side * z_motor_bracket_hole_offset(), gantry_setback - back_thickness, back_height / 2 + thickness / 2])
|
||||
rotate([90, 0, 0])
|
||||
child();
|
||||
|
||||
|
||||
module z_motor_assembly(gantry_setback, rhs, standalone = false) {
|
||||
assembly("z_motor_assembly");
|
||||
|
||||
color([0,1,0]) render() z_motor_bracket(gantry_setback, rhs);
|
||||
//
|
||||
// Clamp screw and washer
|
||||
//
|
||||
translate([clamp_x, -clamp_width / 2, clamp_height / 2])
|
||||
rotate([90, 0, 0])
|
||||
screw_and_washer(cap_screw, screw_longer_than(clamp_width + washer_thickness(screw_washer(cap_screw))));
|
||||
//
|
||||
// Clamp nyloc
|
||||
//
|
||||
translate([clamp_x, clamp_width / 2 - nut_trap_depth, clamp_height / 2])
|
||||
rotate([-90, 0, 0])
|
||||
nut(nut, true);
|
||||
|
||||
//
|
||||
// Mounting screws
|
||||
//
|
||||
if(!standalone)
|
||||
z_motor_bracket_holes(gantry_setback)
|
||||
frame_screw(back_thickness);
|
||||
//
|
||||
// Motor and screws
|
||||
//
|
||||
NEMA(Z_motor);
|
||||
translate([0,0, thickness])
|
||||
NEMA_screws(Z_motor);
|
||||
|
||||
//
|
||||
// The coupling assembly
|
||||
//
|
||||
explode([0, 0, 30])
|
||||
translate([0, 0, NEMA_shaft_length(Z_motor) + 1])
|
||||
rotate([0,0,45])
|
||||
z_coupler_assembly();
|
||||
|
||||
end("z_motor_assembly");
|
||||
|
||||
}
|
||||
|
||||
module z_motor_bracket_lhs_stl() z_motor_bracket(gantry_setback, false);
|
||||
module z_motor_bracket_rhs_stl()mirror([1,0,0]) z_motor_bracket(gantry_setback, true);
|
||||
|
||||
if(0) {
|
||||
translate([length + 2, 0, 0]) z_motor_bracket_lhs_stl();
|
||||
z_motor_bracket_rhs_stl();
|
||||
}
|
||||
else
|
||||
z_motor_assembly(gantry_setback, false);
|
39
scad/z-screw_pointer.scad
Normal file
39
scad/z-screw_pointer.scad
Normal file
@ -0,0 +1,39 @@
|
||||
//
|
||||
// Mendel90
|
||||
//
|
||||
// GNU GPL v2
|
||||
// nop.head@gmail.com
|
||||
// hydraraptor.blogspot.com
|
||||
//
|
||||
// Pointers on the Z screws
|
||||
//
|
||||
include <conf/config.scad>
|
||||
|
||||
function z_screw_pointer_height() = 5;
|
||||
|
||||
module z_screw_pointer_stl() {
|
||||
wall = 2.4;
|
||||
height = z_screw_pointer_height();
|
||||
|
||||
inner_rad = (((Z_screw_dia == 6) ? M6_tap_radius : M8_tap_radius) + Z_bar_dia / 2) / 2; // half depth thread
|
||||
outer_rad = inner_rad + wall;
|
||||
|
||||
pointer = z_bar_offset() - Z_bar_dia / 2 - 1;
|
||||
|
||||
stl("z_screw_pointer");
|
||||
difference() {
|
||||
union() {
|
||||
linear_extrude(height = wall)
|
||||
hull() {
|
||||
circle(r = outer_rad, center = true);
|
||||
translate([pointer - filament_width, 0, 0])
|
||||
square(filament_width * 2, center = true);
|
||||
}
|
||||
translate([0,0, eta])
|
||||
cylinder(r = outer_rad, h = height);
|
||||
}
|
||||
poly_cylinder(r = inner_rad, h = 2 * height + 1, center = true);
|
||||
}
|
||||
}
|
||||
|
||||
z_screw_pointer_stl();
|
60
sheets.py
Normal file
60
sheets.py
Normal file
@ -0,0 +1,60 @@
|
||||
import os
|
||||
import subprocess
|
||||
import shutil
|
||||
import sys
|
||||
from dxf import *
|
||||
|
||||
source_dir = "scad"
|
||||
|
||||
|
||||
|
||||
def sheets(machine):
|
||||
#
|
||||
# Make the target directory
|
||||
#
|
||||
target_dir = machine + "/sheets"
|
||||
if os.path.isdir(target_dir):
|
||||
shutil.rmtree(target_dir)
|
||||
os.makedirs(target_dir)
|
||||
|
||||
#
|
||||
# Set the target machine
|
||||
#
|
||||
f = open("scad/conf/machine.scad","wt")
|
||||
f. write("include <%s_config.scad>\n" % machine);
|
||||
f.close()
|
||||
|
||||
#
|
||||
# Find all the scad files
|
||||
#
|
||||
for filename in os.listdir(source_dir):
|
||||
if filename[-5:] == ".scad":
|
||||
#
|
||||
# find any modules ending in _dxf
|
||||
#
|
||||
for line in open(source_dir + "/" + filename, "r").readlines():
|
||||
words = line.split()
|
||||
if(len(words) and words[0] == "module"):
|
||||
module = words[1].split('(')[0]
|
||||
if module[-4:] == "_dxf":
|
||||
#
|
||||
# make a file to use the module
|
||||
#
|
||||
dxf_maker_name = target_dir + "/" + module + ".scad"
|
||||
f = open(dxf_maker_name, "w")
|
||||
f.write("use <%s/%s>\n" % (source_dir, filename))
|
||||
f.write("%s();\n" % module);
|
||||
f.close()
|
||||
#
|
||||
# Run openscad on the created file
|
||||
#
|
||||
dxf_name = target_dir + "/" + module[:-4] + ".dxf"
|
||||
subprocess.call(["openscad_cl", "-o", dxf_name, dxf_maker_name])
|
||||
dxf_to_svg(dxf_name)
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) > 1:
|
||||
sheets(sys.argv[1])
|
||||
else:
|
||||
print "usage: sheets [mendel|sturdy|your_machine]"
|
||||
sys.exit(1)
|
75
stls.py
Normal file
75
stls.py
Normal file
@ -0,0 +1,75 @@
|
||||
import os
|
||||
import subprocess
|
||||
import shutil
|
||||
import sys
|
||||
|
||||
source_dir = "scad"
|
||||
|
||||
def stls(machine):
|
||||
#
|
||||
# Make the target directory
|
||||
#
|
||||
target_dir = machine + "/stls"
|
||||
if os.path.isdir(target_dir):
|
||||
shutil.rmtree(target_dir)
|
||||
os.makedirs(target_dir)
|
||||
|
||||
#
|
||||
# Set the target machine
|
||||
#
|
||||
f = open("scad/conf/machine.scad","wt")
|
||||
f. write("include <%s_config.scad>\n" % machine);
|
||||
f.close()
|
||||
|
||||
#
|
||||
# Make a list of all the stls in the BOM
|
||||
#
|
||||
targets = []
|
||||
for line in open(machine + "/bom/bom.txt", "rt").readlines():
|
||||
words = line.split()
|
||||
if words:
|
||||
last_word = words[-1]
|
||||
if len(last_word) > 4 and last_word[-4:] == ".stl":
|
||||
targets.append(last_word.replace(".stl", "_stl"))
|
||||
|
||||
|
||||
#
|
||||
# Find all the scad files
|
||||
#
|
||||
for filename in os.listdir(source_dir):
|
||||
if filename[-5:] == ".scad":
|
||||
#
|
||||
# find any modules ending in _stl
|
||||
#
|
||||
for line in open(source_dir + "/" + filename, "r").readlines():
|
||||
words = line.split()
|
||||
if(len(words) and words[0] == "module"):
|
||||
module = words[1].split('(')[0]
|
||||
if module in targets:
|
||||
#
|
||||
# make a file to use the module
|
||||
#
|
||||
stl_maker_name = source_dir + "/stl.scad"
|
||||
f = open(stl_maker_name, "w")
|
||||
f.write("use <%s/%s>\n" % (source_dir, filename))
|
||||
f.write("%s();\n" % module);
|
||||
f.close()
|
||||
#
|
||||
# Run openscad on the created file
|
||||
#
|
||||
stl_name = target_dir + "/" + module[:-4] + ".stl"
|
||||
subprocess.call(["openscad_cl", "-o", stl_name, stl_maker_name])
|
||||
targets.remove(module)
|
||||
|
||||
#
|
||||
# List the ones we didn't find
|
||||
#
|
||||
for module in targets:
|
||||
print "Could not find", module
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) > 1:
|
||||
stls(sys.argv[1])
|
||||
else:
|
||||
print "usage: stls [mendel|sturdy|your_machine]"
|
||||
sys.exit(1)
|
112
svg.py
Normal file
112
svg.py
Normal file
@ -0,0 +1,112 @@
|
||||
## {{{ http://code.activestate.com/recipes/325823/ (r1)
|
||||
#!/usr/bin/env python
|
||||
"""\
|
||||
SVG.py - Construct/display SVG scenes.
|
||||
|
||||
The following code is a lightweight wrapper around SVG files. The metaphor
|
||||
is to construct a scene, add objects to it, and then write it to a file
|
||||
to display it.
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
class Scene:
|
||||
def __init__(self,name="svg",height=400,width=400):
|
||||
self.name = name
|
||||
self.items = []
|
||||
self.height = height
|
||||
self.width = width
|
||||
return
|
||||
|
||||
def add(self,item): self.items.append(item)
|
||||
|
||||
def strarray(self):
|
||||
var = ["<?xml version=\"1.0\"?>\n",
|
||||
'<svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="%dmm" width="%dmm" >\n' % (self.height,self.width),
|
||||
' <g style="fill-opacity:1.0; stroke:black; stroke-width:1;">\n'
|
||||
]
|
||||
for item in self.items: var += item.strarray()
|
||||
var += [" </g>\n</svg>\n"]
|
||||
return var
|
||||
|
||||
def write_svg(self,filename=None):
|
||||
if filename:
|
||||
self.svgname = filename
|
||||
else:
|
||||
self.svgname = self.name + ".svg"
|
||||
file = open(self.svgname,'w')
|
||||
file.writelines(self.strarray())
|
||||
file.close()
|
||||
return
|
||||
|
||||
def display(self):
|
||||
os.system("%s" % (self.svgname))
|
||||
return
|
||||
|
||||
|
||||
class Line:
|
||||
def __init__(self,start,end):
|
||||
self.start = start #xy tuple
|
||||
self.end = end #xy tuple
|
||||
return
|
||||
|
||||
def strarray(self):
|
||||
return [' <line x1="%fmm" y1="%fmm" x2="%fmm" y2="%fmm" />\n' % (self.start[0],self.start[1],self.end[0],self.end[1])]
|
||||
|
||||
|
||||
class Circle:
|
||||
def __init__(self,center,radius,color):
|
||||
self.center = center #xy tuple
|
||||
self.radius = radius
|
||||
self.color = color #rgb tuple in range(0,256)
|
||||
return
|
||||
|
||||
def strarray(self):
|
||||
return [' <circle cx="%fmm" cy="%fmm" r="%fmm" fill="none"/>\n' % (self.center[0],self.center[1],self.radius)]
|
||||
|
||||
class Rectangle:
|
||||
def __init__(self,origin,height,width,color):
|
||||
self.origin = origin
|
||||
self.height = height
|
||||
self.width = width
|
||||
self.color = color
|
||||
return
|
||||
|
||||
def strarray(self):
|
||||
return [' <rect x="%dmm" y="%dmm" height="%dmm"\n' % (self.origin[0],self.origin[1],self.height),
|
||||
' width="%dmm" style="fill:%s;" />\n' % (self.width,colorstr(self.color))]
|
||||
|
||||
class Text:
|
||||
def __init__(self,origin,text,size=24):
|
||||
self.origin = origin
|
||||
self.text = text
|
||||
self.size = size
|
||||
return
|
||||
|
||||
def strarray(self):
|
||||
return [' <text x="%dmm" y="%dmm" font-size="%d">\n' % (self.origin[0],self.origin[1],self.size),
|
||||
' %s\n' % self.text,
|
||||
' </text>\n']
|
||||
|
||||
|
||||
def colorstr(rgb): return "#%x%x%x" % (rgb[0]/16,rgb[1]/16,rgb[2]/16)
|
||||
|
||||
def test():
|
||||
scene = Scene('test')
|
||||
scene.add(Rectangle((50,50),100,100,(0,255,255)))
|
||||
scene.add(Line((100,100),(150,100)))
|
||||
scene.add(Line((100,100),( 50,100)))
|
||||
scene.add(Line((100,100),(100,150)))
|
||||
scene.add(Line((100,100),(100, 50)))
|
||||
scene.add(Circle((100,100),15,(0,0,255)))
|
||||
scene.add(Circle((100,150),15,(0,255,0)))
|
||||
scene.add(Circle((150,100),15,(255,0,0)))
|
||||
scene.add(Circle(( 50,100),15,(255,255,0)))
|
||||
scene.add(Circle((100, 50),15,(255,0,255)))
|
||||
scene.add(Text((25,25),"Testing SVG"))
|
||||
scene.write_svg()
|
||||
scene.display()
|
||||
return
|
||||
|
||||
if __name__ == '__main__': test()
|
||||
## end of http://code.activestate.com/recipes/325823/ }}}
|
Loading…
x
Reference in New Issue
Block a user