Initial commit

This commit is contained in:
Luke Hubmayer-Werner 2023-06-13 21:21:33 +09:30
commit dfdd8c480b
14 changed files with 1025 additions and 0 deletions

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "scad-utils"]
path = scad-utils
url = https://github.com/OskarLinde/scad-utils.git

26
2Banger Parts/compile.py Normal file
View File

@ -0,0 +1,26 @@
from subprocess import Popen
fret_pairs = [
# Old lengths that are unfortunately too long (Up Box caps out at 205mm tall!)
(-4, 0), # Bass
( 1, 7), # Start of guitar
( 8, 19), # Rougly similar length to above
# New shorter segmentation ~120mm tall max
(-4, -3), # 91.7217mm
(-2, 0), # 119.166mm
( 1, 3), # 100.206mm
( 4, 7), # 109.258mm
( 8, 12), # 105.444mm
(13, 19), # 104.732mm
(20, 30), # 98.839mm
# Alternates for testing
(0,0), # Just to see what it looks like, would redesign for 0-fret anyway
(20,20), # Short debug print
]
print("Compiling .stl files for fret pairs: ", fret_pairs)
processes = [Popen(["openscad", "-o", f"fret_tube_{i}_{j}.stl", "-D", f"I={i}", "-D", f"J={j}", "fret_tube_I_J.scad"]) for (i,j) in fret_pairs]
for p in processes:
p.wait()
print("Finished compiling!")

View File

@ -0,0 +1,5 @@
use <../2Banger_fret_tube.scad>
// I = 0; // Override with -D 'I=... J=...'
// J = 24; // Override with -D
echo(str("Called with I=", I, " J=", J))
tube(from_fret = I, to_fret = J);

33
2BangerCommon.scad Normal file
View File

@ -0,0 +1,33 @@
include <AluTCommon.scad>
$fn = $preview ? 32 : 512;
mink_fn = $preview ? 12 : 128;
mink_fn_2d = $preview ? 32 : 256;
function tang_points(a0 = -160, a1 = -90, r = 13) =
concat(
[[r*cos(a1), r*sin(a0)]],
[for (a = [a0:a1]) [r*cos(a), r*sin(a)]]
);
module tang_block(a0 = -160, a1 = -90, r = 13)
translate(T_circumcenter)
polygon(tang_points(a0=a0, a1=a1, r=r));
module tang_outline(offset = -0.1, base_width = 1) {
difference() {
offset((base_width+offset)/2) tang_block();
offset(-(base_width+offset)/2) tang_block();
}
}
module tapered_tang_groove(depth, taper = 1, offset = 0.1, base_width = 1) {
difference() {
hull() {
linear_extrude(depth) offset((base_width+offset)/2) tang_block();
translate([0,0,depth]) linear_extrude(taper) offset(-(base_width)/2) tang_block();
}
linear_extrude(depth + taper) offset(-(base_width+offset)/2) tang_block();
}
}

23
2Banger_cap.scad Normal file
View File

@ -0,0 +1,23 @@
include <2BangerCommon.scad>
module cap(length = 10) {
module solid_cap(cap_taper = 1) {
hull() {
minkowski($fn = mink_fn) {
sphere(cap_taper, $fn = mink_fn);
translate([0,0,cap_taper]) linear_extrude(0.01) offset(-1) cap_outline();
}
linear_extrude(0.01) offset(-1) cap_outline();
translate([0,0,cap_taper]) linear_extrude(length-cap_taper) cap_outline();
}
}
difference() {
solid_cap();
translate([0,0,Cap_Thick]) linear_extrude(length) T_hole();
tapered_T_hole(z0 = length-1, z1 = length, o0 = 0, o1 = 1);
translate([-10,10,length-0.5]) linear_extrude(1) text("04²", size=5, halign="center", valign="center", font="Noto Sans");
}
}
cap();

101
2Banger_fret_tube.scad Normal file
View File

@ -0,0 +1,101 @@
include <common.scad>
include <2BangerCommon.scad>
fret_width = 2.4; //2.8; // Jumbo = 0.11", 0.055" tall
module tube(from_fret, to_fret, tang_depth = 3) {
z_min = (fret_scale_length(to_fret) + fret_scale_length(to_fret+1))/2;
z_max = (fret_scale_length(from_fret) + fret_scale_length(from_fret-1))/2;
z_offset = z_min;
Cap_Length = z_max - z_min;
echo(str("Cap length from fret ", from_fret, " to ", to_fret, " is ", Cap_Length, "mm"));
module solid_tube(cap_taper = 1.5, fingerboard_min_thick = 2.5, fingerboard_max_thick = 5, fret_angle = 60) { // Fret angle of 45° is normal, anything over 60 will not work correctly
module fret_bumps(w=50) {
translate([0,0,-z_offset]) for (fret = [from_fret:to_fret])
translate([fingerboard_max_thick - fret_width/2, w/2, fret_scale_length(fret)])
rotate([90,0,0]) cylinder(h = w, r = fret_width/2);
}
module scallops(w=50) {
for (fret = [from_fret:to_fret+1])
let(
f_prev = fret_scale_length(fret-1) - z_offset,
f_next = fret_scale_length(fret) - z_offset,
o = fret_width/2 * sin(fret_angle),
x0 = f_prev - o,
x1 = f_next + o,
y0 = fingerboard_min_thick,
y1 = fingerboard_max_thick - (fret_width/2 * cos(fret_angle)),
pts = [[x0, y1], [x1, y1], [(x0+x1)/2, y0]],
cc = tri_circumcenter(pts),
r = norm([x0, y1] - cc)
) {
translate([0,-w/2,0])
rotate([-90,-90,0])
translate(cc) cylinder(h = w, r = r);
}
}
module basic_fretboard() {
intersection() {
hull() {
minkowski($fn = mink_fn) {
sphere(cap_taper, $fn = mink_fn);
translate([0,0,cap_taper]) linear_extrude(0.01) offset(-cap_taper)
cap_outline(fingerboard_min_thick = fingerboard_min_thick, fingerboard_max_thick = fingerboard_max_thick);
}
minkowski($fn = mink_fn) {
sphere(cap_taper, $fn = mink_fn);
translate([0,0,Cap_Length-cap_taper]) linear_extrude(0.01) offset(-cap_taper)
cap_outline(fingerboard_min_thick = fingerboard_min_thick, fingerboard_max_thick = fingerboard_max_thick);
}
linear_extrude(Cap_Length) offset(-1) cap_outline();
translate([0,0,cap_taper]) linear_extrude(Cap_Length-cap_taper*2)
cap_outline(fingerboard_min_thick = fingerboard_min_thick, fingerboard_max_thick = fingerboard_max_thick);
}
union() {
fret_bumps();
translate([-50,-50,0]) cube([50 + fingerboard_max_thick - (fret_width/2 * cos(fret_angle)), 100, Cap_Length]);
}
}
}
// Make a solid tube and then subtract the notches
difference() {
union() {
basic_fretboard();
translate([0,0,Cap_Length]) linear_extrude(tang_depth) tang_outline(-0.1);
}
difference() {
scallops();
fret_bumps();
}
tapered_tang_groove(depth = tang_depth + 0.5, taper = 0);
tapered_tang_groove(depth = 0.5, taper = 0, offset = 0.5);
}
// color("red") scallops();
}
difference() {
solid_tube(1.5);
linear_extrude(Cap_Length) T_hole();
tapered_T_hole(z0 = 0, z1 = 3);
tapered_T_hole(z0 = Cap_Length-3, z1 = Cap_Length+0.0001, o0 = 0, o1 = 1);
// Version number
translate([-10,10,Cap_Length-0.5]) linear_extrude(1) text("05²", size=5, halign="center", valign="center", font="Noto Sans");
// Fret number markers
for (fret = [from_fret:to_fret])
translate([-3,-16,fret_scale_length(fret)-z_offset]) rotate([90,25,16]) linear_extrude(100) text(str(fret), size=4, halign="center", valign="center", font="Noto Sans");
}
}
tube(from_fret = 0, to_fret = 0);
translate([50, 0]) tube(from_fret = -4, to_fret = -3);
translate([100, 0]) tube(from_fret = -2, to_fret = 0);
translate([150, 0]) tube(from_fret = 1, to_fret = 3);
translate([200, 0]) tube(from_fret = 4, to_fret = 7);
translate([250, 0]) tube(from_fret = 8, to_fret = 12);
translate([300, 0]) tube(from_fret = 13, to_fret = 19);
translate([350, 0]) tube(from_fret = 20, to_fret = 30);

74
AluTCommon.scad Normal file
View File

@ -0,0 +1,74 @@
include <common.scad>
use <skin.scad>
L_minor = 1/2 * 25.4;
L_major = 3/4 * 25.4;
L_thick = 1.8; //9/128 * 25.4; //1/16 * 25.4;
T_flat_top = L_minor * 2; // 1"
T_spine = L_major; // 3/4"
T_tolerance = 0.285;
// Cap_Length = 150;
Cap_Thick = 3;
Cap_Spine = T_spine + Cap_Thick;
points = [[-T_spine, 0], [0, -L_minor], [0, L_minor]];
function tri_circumcenter(pts) =
let(
v0 = pts[1] - pts[0],
v1 = pts[2] - pts[1],
d0 = (pts[1] + pts[0])/2 * v0,
d1 = (pts[2] + pts[1])/2 * v1,
det = -cross(v0, v1)
)
[cross([d1, d0], [v1.y, v0.y]), cross([d0, d1], [v0.x, v1.x])] / det;
T_circumcenter = tri_circumcenter(points);
tube_radius = Cap_Spine + T_circumcenter[0];
module cap_outline(radius = 1.5, fingerboard_min_thick = 2.5, fingerboard_max_thick = 5) {
minkowski($fn = mink_fn_2d) {
circle(r = radius);
difference() {
translate(T_circumcenter) circle(r = tube_radius - radius);
translate([fingerboard_max_thick - radius, -50]) square([100,100]);
}
}
}
function T_hole_points(r = 4, a_step = 5, offset = 0) =
let(
x0 = T_tolerance + offset,
x1 = x0 - L_thick - (T_tolerance*2) - (offset*2),
x2 = -T_spine - T_tolerance - offset,
y_out = L_minor + T_tolerance + offset,
y_in = L_thick + T_tolerance + offset,
top_points = [
[x1, -y_out],
[x0, -y_out],
[x0, y_out],
[x1, y_out]
],
bottom_points = [
[x2, y_in],
[x2, -y_in],
],
joint_corner_left = [x1, -y_in],
joint_corner_right = [x1, y_in],
join_points_left = [for (a = [0:a_step:90]) joint_corner_left + [-r * (1-sin(a)), -r * (1-cos(a))]],
join_points_right = [for (a = [0:a_step:90]) joint_corner_right + [-r * (1-cos(a)), r * (1-sin(a))]]
)
concat(top_points, join_points_right, bottom_points, join_points_left);
module T_hole(r = 4, a_step = 5, offset = 0)
polygon(T_hole_points(r=r, a_step=a_step, offset=offset));
module tapered_T_hole(z0 = 0, z1 = 4, o0 = 1, o1 = 0) {
// z1 must > z0 for faces to work
pts0 = [for (pt = T_hole_points(offset = o0)) concat(pt, z0)];
pts1 = [for (pt = T_hole_points(offset = o1)) concat(pt, z1)];
skin([pts0, pts1]);
}

199
BassTunerHolder.scad Normal file
View File

@ -0,0 +1,199 @@
Tuner_Spacing_4 = 64;
Post_Hole_Dia = 14.75; // 14 + tolerance
Post_Hole_Depth = 14;
Post_Top_Dia = 9;
Post_Top_Height = 17;
Tuner_Body_Dia = 17; // 16.5 + tolerance
Tuner_Body_R = Tuner_Body_Dia/2; // 16.5 + tolerance
Tuner_Body_Width = 21;
Tuner_Body_Thickness = 10; // 9.5 + tolerance
Tuner_Body_Rect_Len = Tuner_Body_Width-Tuner_Body_R;
Tuner_Tab_Angle = 60;
Tuner_Tab_Hole_Dia = 2.5;
Tuner_Tab_Thickness = 2;
Tuner_Tab_Total = 27.5;
Tuner_Tab_Hole_Inset = 2;
Tuner_Tab_Hole_Outset = (Tuner_Tab_Total-Tuner_Body_Rect_Len)-Tuner_Tab_Hole_Inset;
Engrave_String = "01γ";
// Font = "Ani";
Font = "GFS Didot";
// Font = "GFS Neohellenic";
// Font = "Liberation Mono";
// Font = "Noto Sans";
module cyl(d=10, z0=-100, z1=100, $fn=64)
translate([0,0,z0])
cylinder(h=z1-z0, r=d/2, $fn=$fn);
module c(d=10, z=0, $fn=64) // 3d circle
translate([0,0,z])
cylinder(h=0.00001, r=d/2, $fn=$fn);
module tuner_tab_hole(shrink=0) {
translate([0, -Tuner_Tab_Hole_Outset+Tuner_Tab_Hole_Dia/2])
circle((Tuner_Tab_Hole_Dia-shrink)/2, $fn=32);
}
module tuner_outline(shrink=0) {
union() {
hull() {
translate([0, -Tuner_Tab_Hole_Outset])
circle((Tuner_Tab_Hole_Dia+Tuner_Tab_Hole_Inset-shrink)/2, $fn=32);
circle(Tuner_Body_R-shrink/2, $fn=64);
}
translate([-Tuner_Body_R+shrink/2, 0])
square([Tuner_Body_Dia-shrink, Tuner_Body_Rect_Len-shrink/2]);
}
}
// color("blue") tuner_outline(-1.5);
// translate([0,0,0.001])
// color("red") tuner_outline(0);
module tuner_body() {
linear_extrude(Tuner_Body_Thickness) union() {
translate([-Tuner_Body_R, 0])
square([Tuner_Body_Dia, Tuner_Body_Rect_Len]);
circle(Tuner_Body_R, $fn=32);
}
translate([0, 0, Tuner_Body_Thickness-Tuner_Tab_Thickness])
linear_extrude(Tuner_Tab_Thickness) difference() {
hull() {
translate([0, -Tuner_Tab_Hole_Outset])
circle((Tuner_Tab_Hole_Dia+Tuner_Tab_Hole_Inset)/2, $fn=32);
circle(Tuner_Body_R, $fn=64);
}
tuner_tab_hole();
}
// handle
color(c = "red")
translate([0, Tuner_Body_Rect_Len-Tuner_Body_Thickness/2, Tuner_Body_Thickness/2])
rotate([0,-90,0])
cylinder(h = 40, r = Tuner_Body_Thickness/2);
}
module tuner_post() {
cylinder(h = Post_Hole_Depth, r = Post_Hole_Dia/2, $fn=64);
color("cyan")
translate([0, 0, Post_Hole_Depth])
difference() {
cylinder(h = Post_Top_Height, r = Post_Top_Dia/2);
translate([-1,-5, Post_Top_Height-6]) cube([2,10,7]);
}
}
module tuner() {
tuner_body();
translate([0, 0, Tuner_Body_Thickness])
tuner_post();
}
module tuner_arrange()
for (a = [90:30:180])
rotate([0,0,a])
translate([-31, 31, 0])
children();
module handle_cutouts() {
tuner_arrange()
translate([0, Tuner_Body_Rect_Len-Tuner_Body_Thickness/2, Tuner_Body_Thickness/2])
rotate([-90, 0, 90]) linear_extrude(40) hull() {
circle(Tuner_Body_Thickness/2, $fn=32);
translate([-Tuner_Body_Thickness/2, 0]) square([Tuner_Body_Thickness, 20]);
}
}
module retainer_outline()
// polygon([[-50, -10], [-45, -35], [-20, -55], [20, -55], [45, -35], [50, -10]]);
polygon(concat([for (i = [-52:1:45]) [60*sin(i), -60*cos(i)]], [[40,-5], [-40, -5], [-47, -18]]));
module part() {
module layer_bolt_holes_outer(dia=3.05, z0=-100, z1=100)
for (a = [-120:30:-60])
rotate([0,0,a])
translate([55,0,z0])
cylinder(h=z1-z0, r=dia/2, $fn=64);
module layer_bolt_holes_inner(dia=3.05, z0=-100, z1=100)
for (x = [-20,0,20])
translate([x,-10,z0])
cylinder(h=z1-z0, r=dia/2, $fn=64);
module bottom_engraving()
// translate([0,-26,1]) rotate([0,180,0]) linear_extrude(30)
translate([0,-28,1]) rotate([15,180,0]) linear_extrude(30)
text(text = Engrave_String, size = 5, halign="center", valign="center", font=Font);
// Top half
difference() {
color("blue")
translate([0, 0, Tuner_Body_Thickness])
linear_extrude(Post_Hole_Depth-0.001)
retainer_outline();
tuner_arrange() tuner();
// tuner screw holes
tuner_arrange()
linear_extrude(Tuner_Body_Thickness+Post_Hole_Depth-1)
tuner_tab_hole(shrink=0.5);
// layer bolt holes
layer_bolt_holes_outer();
layer_bolt_holes_outer(dia=7.05, z0=Tuner_Body_Thickness+Post_Hole_Depth-4); // 5.4 OD for bolt head, 7 for M3 washer
layer_bolt_holes_inner();
layer_bolt_holes_inner(dia=7.05, z0=Tuner_Body_Thickness+Post_Hole_Depth-4);
// engraving
translate([0,-20,Tuner_Body_Thickness+Post_Hole_Depth-1])
linear_extrude(5) text(text = Engrave_String, size = 12, halign="center", valign="center", font=Font);
}
// Bottom half
color("grey")
difference() {
linear_extrude(Tuner_Body_Thickness) difference() {
retainer_outline();
// tuner body holes
translate([0, 0, -20])
tuner_arrange()
tuner_outline(-1.5);
}
// layer bolt holes
layer_bolt_holes_outer();
layer_bolt_holes_outer(dia=5.1, z1=5+1.5); // Heat insert is 5mm tall, we will use 20mm bolt for these holes
layer_bolt_holes_inner();
// tuning handle finger bit
handle_cutouts();
// engraving
bottom_engraving();
}
// Mounting
color("aqua")
difference() {
translate([0,0,-12]) linear_extrude(12) difference() {
retainer_outline();
tuner_arrange() tuner_outline(-1.5);
}
// reinforcing layer bolt holes
layer_bolt_holes_inner();
layer_bolt_holes_inner(dia=7.05, z1=(Tuner_Body_Thickness+Post_Hole_Depth-4)-29+5); // Heat insert is 5mm tall, we will use 30mm bolt for these holes
// mounting holes
for (x = [-30, -10, 10, 30])
translate([x,0,-5])
rotate([90,0,0]) {
cylinder(h=100, r=2.5, $fn=32);
// translate([0,0,10]) cylinder(h=20, r=3.8, $fn=32); // Bolt head
// translate([0,0,11]) cylinder(h=20, r=4.7, $fn=32); // Washer
translate([0,0,11]) cylinder(h=20, r=2.55, $fn=32); // Heat Insert
}
// mounting hollow
cyl_offset = [0,-36,-13];
translate(cyl_offset) rotate([0,90,0]) cyl(d=28, $fn=128);
translate([-100,-100+cyl_offset[1],-50]) cube([200,100,100]);
for (i = [-1,1]) hull() {
translate([0,-18,-15]) rotate([0,90,0]) c(d=32, z=50*i, $fn=128);
translate(cyl_offset) rotate([0,90,0]) c(d=28, z=14*i, $fn=128);
translate(cyl_offset) rotate([0,90,0]) c(d=28, z=50*i, $fn=128);
}
bottom_engraving();
}
}
part();
// tuner_arrange() tuner();
// handle_cutouts();

181
GuitarFretboards.scad Normal file
View File

@ -0,0 +1,181 @@
// Fender standard is 25.5"
Guitar_Scale_Length_In = 25.5;
// Convert to mm (1" = 25.4mm)
//Guitar_Scale_Length_mm = Guitar_Scale_Length_In * 25.4;
// This conversion ends up with 647.7mm, but 648mm has nice round number 865mm on the -5 fret too! Regular P-bass is 864mm
Guitar_Scale_Length_mm = 648;
// Extending the Strat by 5 frets gives a P-Bass
Bass_Fret = -5;
PBass_Nut_Width_In = 1.625; // (43mm)
JBass_Nut_Width_In = 1.5; // (38mm)
Strat_Nut_Width_In = 1.65; // (42mm)
function fret_scale_length(n) = Guitar_Scale_Length_mm * 2^(-n/12);
function lerp(start, end, amount) = start + (end-start)*amount;
echo(str("Guitar scale length is ", fret_scale_length(0), "mm"));
echo(str("Bass scale length is ", fret_scale_length(Bass_Fret), "mm"));
// Our modules need to fit in our 25x20cm build area
// This can be obtained by [-5,0), [0,7), [7,19), [19,bridge] modules.
module radiused_chord(w, r, points=12) {
// w <= abs(r)*2
// Negative r possible for mirroring across y-axis
angle = asin(0.5*w/r);
angles = [
for (i = [0:points-1])
let (f = -0.5 + i/(points-1))
f * 2 * angle
];
x0 = r*cos(angle);
coords = [
for (th = angles)
let (
x = r*cos(th) - x0,
y = r*sin(th)
)
[x,y]
];
polygon(coords);
}
module c_text(s, size)
text(s, size=size, halign="center", valign="center", font="Noto Sans");
epsilon = 0.0001;
module to3d()
{linear_extrude(epsilon) children();}
nut_width = 38;
bridge_width = nut_width + 40;
fretboard_radius = 5.5*25.4;
neck_radius = 20;
color("red")
rotate([0,90]) hull(){
translate([0,0,fret_scale_length(Bass_Fret)/4])
to3d() radiused_chord(lerp(bridge_width, nut_width, 1/4), -fretboard_radius);
translate([0,0,fret_scale_length(Bass_Fret)])
to3d() radiused_chord(nut_width, -fretboard_radius);
}
// color("blue")
// rotate([0,90]) hull(){
// translate([0,-bridge_width/2,0])
// cube([20, bridge_width, 1]);
// translate([0,0,fret_scale_length(Bass_Fret)])
// to3d() scale([0.25,1]) radiused_chord(nut_width, neck_radius);
// }
module frets_and_markers(min_fret=-5, max_fret=36, width=bridge_width) {
// Fret wire placeholder model
for (x = [for (i = [min_fret:max_fret]) fret_scale_length(i)])
translate([x, -width/2, 0])
cube([1, width, 12]);
// Fret dots
for (octave = [0:3])
for (fret = [3, 5, 7, 9]) {
i = fret + (octave*12);
if (i > min_fret && i <= max_fret)
translate([(fret_scale_length(i)+fret_scale_length(i-1))/2,0,0])
//cylinder(h=10, r=4);
linear_extrude(10) c_text(str(fret), size=8);
}
// Octave markers
for (i = [0, 12, 24, 36]) if (i > min_fret && i <= max_fret) hull(){
translate([(fret_scale_length(i)+fret_scale_length(i-1))/2,20,0]) cylinder(h=10, r=3);
translate([(fret_scale_length(i)+fret_scale_length(i-1))/2,-20,0]) cylinder(h=10, r=1);
}
// Bass extension
if (min_fret < -1)
for (i = [min_fret+1:-1])
translate([(fret_scale_length(i)+fret_scale_length(i-1))/2,0,0])
linear_extrude(10) c_text(str(i), size=12);
}
Module_Length = 220; // Printer can do up to 250mm, the bass fret run is 217mm. Don't forget overlapping joins!
Module_Overhang = 20;
Module_Bridge_Offset = -15; //80 240
module Connector() {
translate([0,0,-15])
linear_extrude(10)
polygon([[0,5],[0,-5],[Module_Overhang,-15],[Module_Overhang,15]]);
}
module Body(thickness=20, width=90) {
color("blue", 0.5)
translate([Module_Bridge_Offset, -width/2, -thickness])
cube([Module_Length, width, thickness]);
frets_and_markers(20, 24);
translate([Module_Bridge_Offset+Module_Length, 0, 0]) Connector();
// Bridge
translate([-20, -bridge_width/2, 3])
cube([20, bridge_width, 10]);
}
module Neck1(thickness=18, width=70) {
color([0,0.5,1], 0.5)
translate([Module_Bridge_Offset+Module_Length, -width/2, -thickness])
cube([Module_Length, width, thickness]);
frets_and_markers(8, 20);
translate([Module_Bridge_Offset+Module_Length*2, 0, 0]) Connector();
}
module Neck2(thickness=17, width=60) {
color([0.5,0,1], 0.5)
translate([Module_Bridge_Offset+Module_Length*2, -width/2, -thickness])
cube([Module_Length, width, thickness]);
frets_and_markers(1, 7);
translate([Module_Bridge_Offset+Module_Length*3, 0, 0]) Connector();
}
module Neck_Bass(thickness=16, width=40) {
color([1,0,0.5], 0.5)
translate([Module_Bridge_Offset+Module_Length*3, -width/2, -thickness])
cube([Module_Length+Module_Overhang, width, thickness]);
frets_and_markers(-5, 0);
}
// Structural Aluminium
density_6063 = 2.7; // 6063 alloy is around 2.7g/cm3
echo(str("Weight of one 12mm x 3mm x 1m bar is ", density_6063*1.2*0.3*100, "g"));
echo(str("Weight of three 12mm x 3mm x 1m bar is ", density_6063*3.6*0.3*100, "g"));
echo(str("Weight of one 12x3 and two 10x3 x 1m bars is ", density_6063*3.2*0.3*100, "g"));
echo(str("Weight of one 12mm x 12mm x 1.5mm x 1m channel is roughly ", density_6063*1.2*0.15*100*3, "g"));
echo(str("Weight of one 16mm x 16mm x 1.5mm x 1m channel is roughly ", density_6063*1.6*0.15*100*3, "g"));
module Parallel_Bars(spacing=18, x0=-80) {
// for (y = [-1.5-spacing, -1.5, -1.5+spacing])
// translate([x0, y, -12]) cube([1000,3,12]); // 12mm x 3mm bar, 1m length
translate([x0, -1.5, -12]) cube([1000,3,12]); // 12mm x 3mm bar, 1m length
for (y = [-1.5-spacing, -1.5+spacing])
translate([x0, y, -10]) cube([1000,3,10]); // 12mm x 3mm bar, 1m length
}
module Alu_Channel(x0=-80) {
thickness = 1.5;
y0 = -thickness/2;
//12x12x1.5 channel
translate([x0, -6, -thickness]) cube([1000, 12, thickness]);
for (y = [y0-6, y0+6])
translate([x0, y, -12]) cube([1000, thickness, 12]);
}
// frets_and_markers(-5, 29);
Body(); Neck1(); Neck2();
Neck_Bass();
Parallel_Bars();
translate([0,150,0]) Body();
translate([0,250,0]) Neck1();
translate([0,150,0]) Neck2();
translate([0,250,0]) Neck_Bass();
translate([0,-150,0]) {
Body(); Neck1(); Neck2();
Alu_Channel();
}

232
PBassPickupHolder.scad Normal file
View File

@ -0,0 +1,232 @@
Pickup_Length = 58; // Tolerance
Pickup_Width = 28.5; // Tolerance
Pickup_Height = 20;
Pickup_Offset = -37.5;
Magnet_Height = 3;
Corner_Radius = 1.5; // Half-guessed
Hole_Spacing = 65;
Cavity_Width = 64; // Tolerance
Tang_Height = 1.5;
Tang_Groove_Height = Tang_Height + 0.25;
body_h = 20;
Engrave_String = "P01β²";
Font = "GFS Didot";
// Font_JP = "New Tegomin";
Font_JP = "Yuji Boku";
module cyl(d=10, z0=-100, z1=100, $fn=128)
translate([0,0,z0])
cylinder(h=z1-z0, r=d/2, $fn=$fn);
module circ(r=10) circle(r=r, $fn=128);
pl1 = Pickup_Length/2 - Corner_Radius;
pw1 = Pickup_Width/2 - Corner_Radius;
module half_pickup() {
difference() {
union() {
// translate([-Pickup_Length/2, -Pickup_Width/2, 0]) cube([Pickup_Length, Pickup_Width, Pickup_Height]);
color([0.3, 0.3, 0.3]) hull()
for (x = [-pl1, pl1])
for (y = [-pw1, pw1])
translate([x, y, 0])
cyl(d=Corner_Radius*2, z0=Magnet_Height, z1=Pickup_Height);
for (x = [-29, 29])
color([0.3, 0.3, 0.3])
translate([x, 0, 0])
cyl(d=12, z0=6, z1=16);
color([0.5, 0.5, 0.6])
translate([-20, -5, 0])
cube([40, 10, Magnet_Height]);
for (x = [-14.25:9.5:14.25])
color([0.7, 0.75, 0.8])
translate([x, 0, 0])
cyl(d=4, z0=Pickup_Height, z1=Pickup_Height+2);
}
for (x = [-Hole_Spacing/2, Hole_Spacing/2])
translate([x, 0, 0])
cyl(d=3);
}
}
module for_each_pickup() {
for (off = [[0, 0], [Pickup_Offset, Pickup_Width]]) translate(off) children();
}
module split_pickup() {
for_each_pickup() half_pickup();
}
module pickup_outline(grow=0.5) {
union() {
hull() {
for (x = [-pl1-grow, pl1+grow])
for (y = [-pw1-grow, pw1+grow])
translate([x, y])
circ(r=Corner_Radius);
}
for (x = [-29, 29])
translate([x, 0])
circ(r=6+grow);
}
}
module body_outline(shrink=0, body_r=8) {
union() {
hull() {
// Base Plate
for (x = [-60+body_r, 20-body_r])
for (y = [-18+body_r, Cavity_Width-18-body_r])
translate([x,y])
circ(body_r - shrink);
for (off = [[0, 0], [Pickup_Offset, Pickup_Width]]) translate(off)
for (x = [-29, 29]) translate([x, 0])
circ((12+5)/2 - shrink);
// Jack Plate
translate([-67, 20]) circ(6 - shrink);
// Pad pickup corners
dist = Pickup_Length/2 + 5 - body_r;
translate([dist, -18+body_r]) circ(body_r - shrink);
translate([Pickup_Offset - dist, Cavity_Width-18-body_r]) circ(body_r - shrink);
}
hull() {
translate([-67, 20]) circ(6 - shrink);
translate([-67, -9]) circ(6 - shrink);
translate([-60+body_r, -18+body_r]) circ(body_r - shrink);
}
}
}
module tang(margin=0.1) { // Negative margin as subtraction for the slot
difference() {
body_outline(shrink=1+margin);
body_outline(shrink=2-margin);
translate([45, 0]) square(40+margin, center=true);
translate([-83, 32]) square(40+margin, center=true);
};
translate([-60,11.5]) square([27-margin, 1-margin]);
translate([-6,17]) square([27-margin, 1-margin]);
}
// color("blue") translate([-60, -18, -1]) cube([80, Cavity_Width, 1]);
module lower() {
difference() {
union() {
taper = 5;
translate([0,0,taper]) minkowski($fn = $preview ? 8 : 64) {
sphere(r = taper, $fn = $preview ? 8 : 64);
linear_extrude(0.0001) body_outline(shrink=taper);
}
// hull() {
// linear_extrude(taper) body_outline(shrink=3);
translate([0,0,taper]) linear_extrude(body_h-taper) body_outline();
// }
// tang
color("blue")
translate([0,0,body_h])
linear_extrude(Tang_Height)
tang();
}
// Subtractions
// Jack cavity
hull() {
translate([-69, -10, 2.5]) cube([15, 20, 20]);
translate([-69, -10, 10]) cube([35, 20, 20]);
}
// Jack hole
translate([0,0,14]) rotate([0,-90,0]) cyl(d=11,z0=60);
// Wire channels
translate([0,0,5]) linear_extrude(body_h) union() {
translate([-35, 7]) square([25,6], center=true);
translate([-66, 13]) square([6,20], center=true);
}
// M4 holes to mount to body
for (off = [[Pickup_Offset-5, 0], [5, Pickup_Width]]) translate(off) {
cyl(d=4);
cyl(d=9.5, z0=5);
}
for_each_pickup() {
// Pickup adjustment brass insert holes
for (x = [-Hole_Spacing/2, Hole_Spacing/2])
translate([x, 0, 0]) {
cyl(5.1);
hull(){
cyl(5.25, z0=7, z1=10);
cyl(6, z0=9, z1=20);
}
}
// Pickup outlines
translate([0,0,10]) linear_extrude(100) pickup_outline();
}
translate([4, 38, body_h-2]) linear_extrude(5)
text(text = Engrave_String, size = 6, halign="center", valign="center", font=Font);
translate([14, 28, body_h-2]) linear_extrude(5)
text(text = "下", size = 8, halign="center", valign="center", font=Font_JP);
}
}
module upper(wall_height=3.5, roof_height=2.5) {
module elec_cavity() {
hull() {
for (off = [[-27, -11], [-52, -11], [-66, -8], [-66, 7], [-27, 7]])
translate(off) circ(r=2.5);
}
}
module walls() {
difference() {
body_outline();
for_each_pickup() pickup_outline();
elec_cavity();
}
}
module roof() {
difference() {
body_outline();
for_each_pickup() pickup_outline();
}
}
difference() {
union() {
linear_extrude(Tang_Groove_Height) difference() {
walls();
tang(-0.1);
}
h = wall_height - Tang_Groove_Height;
translate([0, 0, Tang_Groove_Height])
linear_extrude(h)
walls();
intersection() {
translate([0,0,wall_height]) linear_extrude(roof_height) roof();
translate([0,0,wall_height])
minkowski($fn = $preview ? 8 : 64) {
sphere(roof_height, $fn = $preview ? 8 : 64);
linear_extrude(0.001) body_outline(shrink=roof_height);
}
}
}
linear_extrude(100) for_each_pickup() pickup_outline();
// Engravings
translate([0, 0, wall_height+0.5]) linear_extrude(100) {
translate([-2,22])
text(text = "LHW", size = 4, font=Font);
translate([-6,17])
text(text = "2023-03-29", size = 4, font=Font);
translate([-50,0])
text(text = Engrave_String, size = 6, halign="center", valign="center", font=Font);
translate([-50,-8])
text(text = "上", size = 8, halign="center", valign="center", font=Font_JP);
}
// Jack hole
translate([0,0,14-body_h]) rotate([0,-90,0]) cyl(d=11+2,z0=60);
}
}
// lower();
upper();
// translate([0,0,10]) split_pickup();

69
Tiertime.gcode Normal file
View File

@ -0,0 +1,69 @@
;===========================;
; List of supported G-codes ;
;===========================;
; G0: linear Move
; G4: Dwell
; G28: Move to Origin (Home)
; G90: Set to Absolute Positioning
; G91: Set to Relative Positioning
; G92: Set Position, only support A axis reset.
; M0: Stop or Unconditional stop
; M1: Sleep or Conditional stop
; M2: Program End
; M25: Pause SD print
; M42: Switch I/O pin
; M73: Set build percentage
; M80: ATX Power On
; M81: ATX Power Off
; M82: Set extruder to absolute mode
; M83: Set extruder to relative mode
; M92: Set axis_steps_per_unit
; M104: Set Extruder Temperature
; M109: Set Extruder Temperature and Wait, Example M109 S215
; M140: Set Bed Temperature (Fast)
; M141: Set Chamber Temperature (Fast)
; M190: Wait for bed temperature to reach target temp
; M191: Wait for chamber temperature to reach target temp
; M204: Set default acceleration
; M206: Offset axes
;==========================;
; List of relevant G-codes ;
;==========================;
; M92: Set axis_steps_per_unit
; e.g. M92 X87.489 Y87.489 Z87.489 E420:420
; M204: Set default acceleration
; M206: Offset axes
;
; G90: Set to Absolute Positioning (default)
; G91: Set to Relative Positioning
; G92: Set Position, "only support A axis reset." - in other machines, this can set new absolute origin
; M82: Set extruder to absolute mode (default)
; M83: Set extruder to relative mode
;
; M190: Wait for bed temperature to reach target temp
; M109: Set Extruder Temperature and Wait, Example M109 S215
;
; G0: linear Move - this is rapid linear move on other systems, G1 is normal speed linear move for them
; e.g. G0 X000 Y000 Z000 E000 F000
; F is feed rate, E is extruder
; Traditionally, S is used for "power", which may be laser power or spindle speed. N/A here.
; G4: Dwell (ms)
; e.g. G4 P1000
; G28: Move to Origin (Home)
; e.g. G28
; e.g. G28 X Y
;
; M0: Stop or Unconditional stop
; M1: Sleep or Conditional stop
; M2: Program End
; M73: Set build percentage
; e.g. M73 P100
;
; M80: ATX Power On
; M81: ATX Power Off
;
;
; M140: Set Bed Temperature (Fast) - does not wait!
; e.g. M140 S65 R40 (set to 65°C, wait until 40°C)
; M104: Set Extruder Temperature

3
common.scad Normal file
View File

@ -0,0 +1,3 @@
Guitar_Scale_Length_mm = 648;
function fret_scale_length(n) = Guitar_Scale_Length_mm * 2^(-n/12);
function lerp(start, end, amount) = start + (end-start)*amount;

1
scad-utils Submodule

@ -0,0 +1 @@
Subproject commit 27c7ede3b7298f0a629553033e2a78e13e627bef

75
skin.scad Normal file
View File

@ -0,0 +1,75 @@
use <scad-utils/transformations.scad>
use <scad-utils/lists.scad>
// Skin a set of profiles with a polyhedral mesh
module skin(profiles, loop=false /* unimplemented */) {
P = max_len(profiles);
N = len(profiles);
profiles = [
for (p = profiles)
for (pp = augment_profile(to_3d(p),P))
pp
];
function quad(i,P,o) = [[o+i, o+i+P, o+i%P+P+1], [o+i, o+i%P+P+1, o+i%P+1]];
function profile_triangles(tindex) = [
for (index = [0:P-1])
let (qs = quad(index+1, P, P*(tindex-1)-1))
for (q = qs) q
];
triangles = [
for(index = [1:N-1])
for(t = profile_triangles(index))
t
];
start_cap = [range([0:P-1])];
end_cap = [range([P*N-1 : -1 : P*(N-1)])];
polyhedron(convexity=2, points=profiles, faces=concat(start_cap, triangles, end_cap));
}
// Augments the profile with steiner points making the total number of vertices n
function augment_profile(profile, n) =
subdivide(profile,insert_extra_vertices_0([profile_lengths(profile),dup(0,len(profile))],n-len(profile))[1]);
function subdivide(profile,subdivisions) = let (N=len(profile)) [
for (i = [0:N-1])
let(n = len(subdivisions)>0 ? subdivisions[i] : subdivisions)
for (p = interpolate(profile[i],profile[(i+1)%N],n+1))
p
];
function interpolate(a,b,subdivisions) = [
for (index = [0:subdivisions-1])
let(t = index/subdivisions)
a*(1-t)+b*t
];
function distribute_extra_vertex(lengths_count,ma_=-1) = ma_<0 ? distribute_extra_vertex(lengths_count, max_element(lengths_count[0])) :
concat([set(lengths_count[0],ma_,lengths_count[0][ma_] * (lengths_count[1][ma_]+1) / (lengths_count[1][ma_]+2))], [increment(lengths_count[1],max_element(lengths_count[0]),1)]);
function insert_extra_vertices_0(lengths_count,n_extra) = n_extra <= 0 ? lengths_count :
insert_extra_vertices_0(distribute_extra_vertex(lengths_count),n_extra-1);
// Find the index of the maximum element of arr
function max_element(arr,ma_,ma_i_=-1,i_=0) = i_ >= len(arr) ? ma_i_ :
i_ == 0 || arr[i_] > ma_ ? max_element(arr,arr[i_],i_,i_+1) : max_element(arr,ma_,ma_i_,i_+1);
function max_len(arr) = max([for (i=arr) len(i)]);
function increment(arr,i,x=1) = set(arr,i,arr[i]+x);
function profile_lengths(profile) = [
for (i = [0:len(profile)-1])
profile_segment_length(profile,i)
];
function profile_segment_length(profile,i) = norm(profile[(i+1)%len(profile)] - profile[i]);
// Generates an array with n copies of value (default 0)
function dup(value=0,n) = [for (i = [1:n]) value];