uilleann

3d printable Uilleann bagpipes
git clone https://git.woozle.org/neale/uilleann.git

uilleann / daye / chanter.quiet
Neale Pickett  ·  2025-11-28

complete.scad

  1include <../common.scad>
  2use <MCAD/regular_shapes.scad>
  3
  4height = 360.0;
  5od = 16.0;
  6od_derlin = od + 0.5;
  7id_bot = 13.2;
  8id_top = 5.51;
  9cut_height = 155; // Where to cut it in half
 10axianov = false; // Axianov tone holes?
 11
 12rev = "preview";
 13stamp = str(rev);
 14
 15module tonehole_axianov(h=10, d=10, undercut=0) {
 16  r = d/2;
 17  area = PI*r*r;
 18
 19  rounding_r = 2;
 20  rounding_area = (1 - PI/4) * (rounding_r^2); // area lost to rounding
 21  goal_area = area + rounding_area;
 22
 23  w = 6.25; // Marat uses 6.25mm on every hole, so we will too
 24  l = goal_area / w;
 25  
 26  rotate([0, 0, -90]) {
 27    translate([od/2, 0, h]) {
 28      rotate([0, -90+undercut, 0]) {
 29        // Scoot it down a hair so it will penetrate the entire tube when rotated
 30        translate([0, 0, -od/2]) {
 31          render(convexity=2)
 32          intersection() {
 33            cube([l, w, 20]);
 34            union() {
 35              translate([r, r, 0]) cylinder(r=r, h=20, center=true);
 36              translate([r, 0, 0]) cube(20, center=true);
 37              translate([0, r, 0]) cube(20, center=true);
 38            }
 39          }
 40        }
 41      }
 42    }
 43  }
 44}
 45
 46module tonehole(h=10, d=10, undercut=0) {
 47  if (axianov) {
 48    tonehole_axianov(h, d, undercut);
 49  } else {
 50    rotate([0, 0, -90]) {
 51      translate([od/2, 0, h]) {
 52        rotate([0, -90+undercut, 0]) {
 53	  translate([0, 0, -od/2]) {
 54	    cylinder(d=d, h=20);
 55	  }
 56	}
 57      }
 58    }
 59  }
 60  // Cutaways. I don't like them, but if you do, uncomment this.
 61  // translate([0, -od/2 - 8, h]) rotate([0, 90, 0]) cylinder(r=10, h=50, center=true);
 62}
 63
 64
 65// Something like David Daye's Penny Chanter,
 66// based on my measurements and undercut hints on David's web site.
 67// This is symmetrical, so both pieces can be printed at the same time,
 68// with color changes
 69module chanter() {
 70  difference () {
 71    union() {
 72      // The core part of the instrument is this brass tube
 73      difference() {
 74        brass() cylinder(h=height, d=od);
 75
 76        // Seam guides
 77        translate([0, od/2, 0]) cylinder(d=1, h=400);
 78      }
 79
 80      // David adds this outer Derlin tube as an upgrade option
 81      difference() {
 82        derlin() translate([0, 0, 40.0]) cylinder(h=290, d=od_derlin);
 83
 84        // The slits up the sides serve three purposes:
 85        // 1. directs the slicer to place seams in it (and not on the face)
 86        // 2. provides alignment guides for attaching the two pieces
 87        // 3. looks like an intentional stylistic thing
 88        rotate([0, 0, 85]) translate([0, od_derlin/2, 0]) cylinder(d=1, h=cut_height+20); // overlap
 89        rotate([0, 0, -85]) translate([0, od_derlin/2, cut_height-20]) cylinder(d=1, h=400);
 90      }
 91
 92      // These little doodads are probably just to hide the Derlin seam
 93      ivory() translate([0, 0, 30.0]) {
 94        cylinder(h=3, d1=od, d2=22.0);
 95        translate([0, 0, 3]) cylinder(h=9, d=22.0);
 96      }
 97      ivory() translate([0, 0, height - 30.0 - 12]) {
 98        cylinder(h=12, d=22.0);
 99      }
100    }
101
102    // Seam guides
103    translate([0, 11, 0]) cylinder(d=1, h=400);
104
105    // Inner bore, which runs up to the place where the reed drops in
106    translate([0, 0,   0]) cylinder(h=337.01, d1=id_bot, d2=id_top);
107    translate([0, 0, 337]) cylinder(h=23.1, d1=id_top, d2=7.1);
108
109    // I totally dig David's minimalist aesthetic
110    translate([0, 0, 3]) rings(d=16.0);
111
112    // Sigil
113    translate([0, 0, 4]) intersection() {
114      cylinder_tube(50, od/2+0.5, 1);
115      union() {
116        translate([0, 0, 8]) rotate([90, 0, -90]) {
117          linear_extrude(height=d1, convexity=4) {
118            translate([-4, -5]) import("ruby.svg");
119          }
120        }
121        translate([0, 0, 4]) rotate([90, 90, -160]) {
122          linear_extrude(height=od, convexity=10) {
123            text(stamp, size=2, halign="right", valign="center");
124          }
125        }
126      }
127    }
128
129    // Tone Holes!
130    // XXX: Undercut angle should be taken into account here
131    tonehole(h=57.1, d=6.68); // E-
132    tonehole(h=87.0, d=4.25); // E
133    tonehole(h=118.0, d=8.33); // F#
134    tonehole(h=149.0, d=5.51, undercut=-15); // G
135    tonehole(h=184.5, d=7.75, undercut=15); // A
136    tonehole(h=184.5, d=7.75, undercut=-15); // A (wide undercut)
137    tonehole(h=219.0, d=6.72, undercut=15); // B
138    tonehole(h=250.0, d=5.50, undercut=30); // C
139    rotate([0, 0, 180]) tonehole(h=270.0, d=7.11, undercut=30); // D
140  }
141}
142
143module tenon(top=false, h=cut_height, od=od, depth=20, thickness=2) {
144  module cut() {
145        cylinder(h=cut_height+depth, d=od-thickness-clearance);
146        cylinder(h=cut_height, d=50);
147  }
148
149  if (top) {
150    difference() {
151      children();
152      cut();
153    }
154  } else {
155    intersection() {
156      children();
157      cut();
158    }
159  }
160}
161
162chanter();
163//translate([0, 50, 360]) rotate([180, 0, 0]) chanter();
164