From ac984445f9b51fb9754807c4c5e9195ec39e7468 Mon Sep 17 00:00:00 2001 From: Neale Pickett Date: Sat, 11 Jun 2022 22:58:34 -0600 Subject: [PATCH] Rework case to be rounded --- case/Makefile | 6 +- case/adapter-case.scad | 120 --------- case/adapter-lid.scad | 20 -- case/case.scad | 181 ++++++++++++++ case/case.stl | Bin 38084 -> 0 bytes case/paddles.scad | 521 --------------------------------------- case/seeed_xaio_case.stl | Bin 64884 -> 0 bytes case/seeed_xaio_lid.stl | Bin 34284 -> 0 bytes 8 files changed, 184 insertions(+), 664 deletions(-) delete mode 100644 case/adapter-case.scad delete mode 100644 case/adapter-lid.scad create mode 100644 case/case.scad delete mode 100644 case/case.stl delete mode 100644 case/paddles.scad delete mode 100644 case/seeed_xaio_case.stl delete mode 100644 case/seeed_xaio_lid.stl diff --git a/case/Makefile b/case/Makefile index 213c18e..22c2a8f 100644 --- a/case/Makefile +++ b/case/Makefile @@ -1,4 +1,4 @@ -default: adapter-case.stl adapter-lid.stl +default: body.stl cap.stl -%.stl: %.scad - openscad -o $@ $< +%.stl: case.scad + openscad -o $@ -D TARGET=\"$*\" $< diff --git a/case/adapter-case.scad b/case/adapter-case.scad deleted file mode 100644 index 6b99aa9..0000000 --- a/case/adapter-case.scad +++ /dev/null @@ -1,120 +0,0 @@ -// Make circles lovely and round -$fa = 1; $fs = 0.5; - -module stacker() { - translate([0, 0, -5]) { - difference() { - union() { - import("seeed_xaio_case.stl", convexity=3); - translate([-12.1, -2, 6]) cube([1.3, 4, 4]); // Plug up the component hole in the back - translate([11.45, 0, 5]) cube([1.3, 10, 4], center=true); // Plug up the USB hole - } - cube([30, 25, 10], center=true); - } - } -} - -module lid() { - intersection() { - import("seeed_xaio_case.stl", convexity=3); - cube([30, 30, 4], center=true); - } -} - -module trs_support() { - intersection() { - cube([12, 25, 12], center=true); - rotate(-45, [0, 1, 0]) cube([12, 25, 12], center=true); - } -} - -module pig_ear() { - intersection() { - cylinder(h=4, r1=2, r2=1, center=true); - translate([0, -10, 0]) cube([20, 20, 20]); - } -} - -difference() { - union() { - import("seeed_xaio_case.stl", convexity=3); - - translate([-12.1, -2, 6]) cube([1.3, 4, 4]); // Plug up the component hole in the back - - // Overlap these to get rid of the slots inside - translate([0, 0, 07.5]) stacker(); - translate([0, 0, 10.0]) stacker(); - translate([0, 0, 12.5]) stacker(); - translate([0, 0, 15.0]) stacker(); - translate([0, 0, 17.5]) stacker(); - translate([0, 0, 20.0]) stacker(); - translate([0, 0, 23]) lid(); - - // Add some support for inserting the TRS plug - intersection() { - union() { - translate([13, 10, 16]) rotate(60, [0, 0, 1]) trs_support(); - translate([13, -10, 16]) rotate(-60, [0, 0, 1]) trs_support(); - } - cube([21.8, 19, 60], center=true); - } - - // Shelf for board to rest against - difference() { - translate([-8, 0, 9.2]) cube([6, 19, 1], center=true); - translate([-6, 0, 9.2]) rotate(45, [0, 0, 1]) cube(15, center=true); - } - - // Pig Parts - translate([-12, 4, 22]) sphere(r=1.3); - translate([-12, -4, 22]) sphere(r=1.3); - if (false) { - translate([-8, 5, 25]) pig_ear(); - translate([-8, -5, 25]) pig_ear(); - } - } - - // Pig grin - intersection() { - translate([0, 0, 15]) rotate(90, [0, 1, 0]) { - difference() { - cylinder(h=50, d=20, center=true); - cylinder(h=50, d=19, center=true); - } - } - translate([-18.7, 0, 0]) cube(7); - } - - // Cut off the bottom - cube([30, 30, 4.01], center=true); - - // Channel in the back to make it easier to squeeze in the XIAO - translate([-4.5, 0, 7.6]) intersection() { - cube([13, 18.3, 1.8], center=true); - cylinder(d=21, h=300, center=true); - } - - // Channels for bottom insertion part thingy - translate([0, 0, 3.6]) cube([17, 18.8, 1.2], center=true); - - // Carve out above USB C port - translate([10, -4.79, 0]) cube([5, 9.58, 5]); - - // Paddle contacts - translate([0, 0, 12]) { - // 8-32x 1/4 screws - rotate(90, [1, 0, 0]) cylinder(h=30, d=4.0, center=true); - - // Hookup wire - translate([0, 0, -2.5]) cube([1, 30, 0.8], center=true); - } - - // 3.5mm TRS jack - translate([10, 0, 18]) rotate(90, [0, 1, 0]) cylinder(h=3, d=6.0); - - // Piezo buzzer - translate([0, 0, 13]) { - translate([-12, 3.5, 0]) cube([5, 1, 1], center=true); - translate([-12, -3.5, 0]) cube([5, 1, 1], center=true); - } -} diff --git a/case/adapter-lid.scad b/case/adapter-lid.scad deleted file mode 100644 index 78e52c7..0000000 --- a/case/adapter-lid.scad +++ /dev/null @@ -1,20 +0,0 @@ -// Make circles lovely and round -$fa = 1; $fs = 0.5; - -module fancycube(vec, h) { - translate([r / 2, r / 2, 0]) { - difference() { - cube([r + 0.01, r + 0.01, h], center = true); - - translate([r/2, r/2, 0]) - cylinder(r = r, h = h + 1, center = true); - - } - } -} - -union() { - translate([0, 0, 11]) rotate(180, [1, 0, 0]) import("seeed_xaio_lid.stl", convexity=3); - translate([2, -4.5, 0]) cube([8, 9, 4]); - fillet(200, 1); -} diff --git a/case/case.scad b/case/case.scad new file mode 100644 index 0000000..0d8637a --- /dev/null +++ b/case/case.scad @@ -0,0 +1,181 @@ +// Make circles lovely and round +$fa = 1; $fs = 0.1; + +outer_dimensions = [24.2, 21, 27]; +outer_radius = 3.7; +wall_width = [1.3, 1.3, 1.3]; +inner_dimensions = outer_dimensions - (wall_width * 2); +inner_radius = outer_radius * 0.64; +z_elevate = [[0, 0, 0], [0, 0, 0], [0, 0, 0.5]]; // Multiply by this to bring bottom to z=0 +center = [[-0.5, 0, 0], [0, -0.5, 0], [0, 0, 0]]; // Multiply by this to center something on the xy axes +xiao_elevation = 5.2; // Center of the PCB +pcb_thickness = 1.8; +channel = [16, 1, 1]; // Difensions of cap channel +channel_height = 2; // How far into the case the clips need to go +cap_thickness = 1.3; + +// More information: https://danielupshaw.com/openscad-rounded-corners/ +module roundedcube_simple(size=[1, 1, 1], center=false, r=0.5) { + // If single value, convert to [x, y, z] vector + size = (size[0] == undef) ? [size, size, size] : size; + + translate = (center == false) ? + [r, r, r] : + [ + r - (size[0] / 2), + r - (size[1] / 2), + r - (size[2] / 2) + ]; + + translate(v = translate) + minkowski() { + cube(size = [ + size[0] - (r * 2), + size[1] - (r * 2), + size[2] - (r * 2) + ]); + sphere(r = r); + } +} + +module trs_support() { + intersection() { + cube([10, 30, 12], center=true); + rotate(-45, [0, 1, 0]) cube([10, 30, 12], center=true); + } +} + +module usb_c() { + cube([10, 6.5, 3.15], center=true); + translate([0, -3.25, 0]) rotate(90, [0, 1, 0]) cylinder(d=3.15, h=10, center=true); + translate([0, 3.25, 0]) rotate(90, [0, 1, 0]) cylinder(d=3.15, h=10, center=true); +} + + +module case() { + difference() { + translate((outer_dimensions * z_elevate) + ([0, 0, -1] * outer_radius)) difference() { + roundedcube_simple(outer_dimensions, center=true, r=outer_radius); + roundedcube_simple(inner_dimensions, center=true, r=inner_radius); + translate(-outer_dimensions/2) cube([100, 100, outer_radius]); + } + + // USB C port + translate([inner_dimensions[0]/2, 0, 0]) { + translate([0, 0, xiao_elevation - 3.15/2]) usb_c(); + cube([10, 9.65, xiao_elevation*2 - 3.15], center=true); + } + + } +} + +module body() { + difference() { + union() { + case(); + + // Add some supports + intersection() { + union() { + translate([13, 10, 13]) rotate(60, [0, 0, 1]) trs_support(); + translate([13, -10, 13]) rotate(-60, [0, 0, 1]) trs_support(); + + // Shelf for board to rest against + difference() { + translate([-8, 0, xiao_elevation]) cube([6, 19, 4], center=true); + translate([-6, 0, xiao_elevation]) rotate(45, [0, 0, 1]) cube(15, center=true); + } + } + translate(outer_dimensions * center) roundedcube_simple(outer_dimensions, r=outer_radius); + } + + + // Eyes + translate([-12, 4, 18]) sphere(r=1.2); + translate([-12, -4, 18]) sphere(r=1.2); + } + + // Smirk grin + intersection() { + translate([0, 0, 11]) rotate(90, [0, 1, 0]) { + difference() { + cylinder(h=50, d=20, center=true); + cylinder(h=50, d=19, center=true); + } + } + translate([-18.7, 0, 0]) cube(7); + } + + // Channel in the back to make it easier to squeeze in the XIAO + translate([-4.5, 0, xiao_elevation]) intersection() { + cube([13, 100, pcb_thickness], center=true); + roundedcube_simple(inner_dimensions, center=true, r=inner_radius); + } + + // Channels for bottom insertion part thingy + for (i = [-0.5, 0.5]) { + translate([0, inner_dimensions[1]*i, channel_height-channel[2]/2]) { + cube(channel, center=true); + } + } + + // Paddle contacts + translate([0, 0, 10]) { + // 8-32x 1/4 screws + rotate(90, [1, 0, 0]) cylinder(h=30, d=4.0, center=true); + + // Hookup wire + translate([0, 0, -2.5]) cube([1, 30, 0.8], center=true); + } + + // 3.5mm TRS jack + translate([10, 0, 14]) rotate(90, [0, 1, 0]) cylinder(h=3, d=6.0); + + // Piezo buzzer + translate([0, 0, 10]) { + translate([-12, 3.5, 0]) cube([5, 1, 1], center=true); + translate([-12, -3.5, 0]) cube([5, 1, 1], center=true); + } + } +} + +module cap() { + inner = inner_dimensions * 0.97; // leave 5% slop + union() { + intersection() { + roundedcube_simple(outer_dimensions, center=true, r=outer_radius); + translate([0, 0, cap_thickness/2]) cube([100, 100, cap_thickness], center=true); + } + intersection() { + roundedcube_simple(inner, center=true, r=inner_radius); + translate(center * inner) cube([100, 100, cap_thickness+2.2]); + } + difference() { + union() { + for (i = [-0.5, 0.5]) { + translate([0, inner[1]*i, cap_thickness + channel_height - channel[2]*0.4]) { // 40% of channel z for slop + difference() { + cube(channel, center=true); + translate([0, channel[1]*i, channel[2]/2]) rotate(90*i, [1, 0, 0]) { + cube([channel[0], channel[1], channel[2]], center=true); + } + } + } + } + } + cube([5, 200, 200], center=true); + for (i = [-1, 1]) { + translate([9.5*i, 0, 0]) cube([5, 200, 200], center=true); + } + } + } +} + +if (TARGET == "body") { + body(); +} else if (TARGET == "cap") { + cap(); +} else { + color([0, 0.5, 0.5]) body(); + color([0.5, 0, 0.5]) translate([0, 0, -cap_thickness]) cap(); +} diff --git a/case/case.stl b/case/case.stl deleted file mode 100644 index b1bd881f92f6b2486a9e3ca8b0142ea601e9bd21..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 38084 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 COMPACT 3D-PRINTED PADDLES <<< - Torbjørn Skauli, LA4ZCA (tskauli@gmail.com) - v2.0, December 2018 -Iambic paddles designed for 3D-printing. The design is simple, but provides precise movement with adjustable force and travel. Design features include a printed rocker hinge, force adjustment by a sliding spring, travel adjustment using a modified screw, ergonomic grip and general simplicity and precision. -Changes in v2.0: The paddles have been made narrower, and the base is thinner. There is an option to remove the bottom mounting holes. The base extends under the paddles to protect them from being pushed upwards. The cable exit is on the side, to fit mounting on the QCX transceiver. -TODO: --Arms 1-2 mm higher, spring channel longer towards contacts? -Materials: -- 3 printed parts -- 2 screws M3x5mm, cylinder head, with washers for adjustment if needed -- 1 screw M4 x 18-20mm, cylinder head, with lockwasher and nut -- Compression spring, 6-8 mm in diameter -- Compression spring, 4-5 mm in diameter -- Cable with plug as required, up to 3.5 mm diameter -Note: Nickel plated brass screws have been found to give the most reliable contact operation. Dimensions of screws, springs and cable can be changed in the code. -Assembly: -- First, prepare the 3D-printed parts by removing support material in the arm spring well and in the ends of the cable holes. Also remove any protuding edges and bumps by gently filing the surfaces. -- Place the large spring so that it is held between the paddles approximately in the middle of the spring well. Also place the small spring in the holes at the hinge. Temporarily slide the two paddles in place. Check the spring force on the paddles and adjust as desired by either moving the spring along the well or by bending the spring to change its length. Make sure that the small spring keeps the arms in place at the hinges during use. -- Remove 6-8 cm of the outer isolation (if present) of the cable and 1 cm of the inner isolation of each wire. Insert the cable from the back through the diagonal hole, and temporarily pull it out from the side "window". Insert the cable back into the other hole and press the cable bend into the window so that the outer isolation ends in the interior wiring well. This forms a strain relief. -- Prepare a 18-20 mm M4 screw with cylindrical head by grinding the outer 5 mm to flatten two opposing sides. Preferably align the flattened screw end with the slot in the screw head. -- Enter two M3 screws with cylindrical heads into the paddle arms, with the heads facing inwards. Clamp the dot and dash wire ends under these screw heads. -- Enter the M4 screw from the bottom and clamp the ground wire underneath the lockwasher. Tighten the nut quite firmly, while allowing a small amount of adjustment of the screw angle to set the travel distance. -- Place the spring between the paddles and slide them in place. Adjust travel by rotating the M4 screw. If the travel is asymmetric, it may be necessary to correct the difference by placing a washer under the head of one of the M3 screws in the paddle arms. -*/ - -//*************** Rendering output control -mountholes=true;//Whether to have mounting holes in bottom -cacc=4; // accuracy of circles, multiplier for $fn. Use cacc=1 for dev/debug, =2-4 for final. -preview=0; // =0 for print layout, - // =1 or =2 for 1- or 2-arm assembly preview, - // =3 for base only - // =4 for arms print layout, - // =5 base+attachment preview - // =6 base modified for attachment to other cabinet - // =7 attachment for inclusion in other cabinet - // =8 rotation stopper for inclusion in other cabinet - -//**************** main parameters of the design -wxbase=24; // overall width, sets arm thickness etc. -lybasemin=40; // length excl. knobs (normally 40, made longer below for QCX) -hzarm=20; // height of main part of arm -wallt=2; // wall thikckness -wallmin=2; // min wall thickness under cable holes - -dfinger=30; // approx diameter of finger for curved knob. Also knob length. -lyknob=25; // total length of knob -rround=1; // radius of rounded edges on knob -txknobmin=2; // min. thickness of knob - -yhinge=6.5; // y position of hinge relative to back -dxwedge=4; // height of hinge wedge -ahinginn=50; // angles for inner and outer part of hinges -ahingout=80; -dstopper=1.5; // diameter of stopper on top of hinge that keeps arm down - -armsep=0.75; // arm separation from all walls -dyarmrests=2; // y width of resting and bounding surfaces for arms -minstroke=0.25; // minimum stroke length (at full dia of center screw) - -//**************** parameters for non-printed parts -dscrew1=4; // screw dia, also scales screw head height -dscrew2=3; // screw dia, also scales screw head height -hscrhrel=2/3; // screw head height and diam rel to diameter -dscrhrel=7/4; -dzcontact=0.1; // extra height of all screws -dzsprwell=-1; // height adjustment of spring well -dcable=4; // cable diameter -dspring=9.5; // spring diameter -dhingespring=5; // diameter of spring keeping hinge in place - -//*************** Parameters for cabinet attachment, needed to make integrated paddle -daxis=6; // Diameter of rotation axis tube -lyflange=22; // Length and height of flange on axis tube -hzflange=13; -atthick=1.5; -rotsnaph=1; // Height of snaps for paddle attachment rotation -rotstop=7; // Size of rotation stopper shelf - -//**************** parameters for rendering -gap=0.2; // gap for loose fit -tol=0.025; // general tolerance -nil=0.001; // Negligible distance, to correct rendering - - -lybase=lybasemin; // length of basee ex. knobs -echo("Length of base (mm):",lybase); -hzwall=hzarm+armsep; // total height of walls -hzbase=2*wallmin+dcable; // height of base under arms -ycontact=lybase-1*dscrew1; // position of contact screw - -wxarm=wxbase/2-wallt-armsep-hscrhrel*dscrew2-minstroke-dscrew1/2; // arm thickness is the remaining space after removing many contributions to total width -echo("Total height (mm):",hzwall+hzbase); -echo("Total width for QCX (mm):",wxbase+dcable); -echo("Max length of contact screws in arms (mm):",wxarm); -echo("Min length of contact screw in base (mm):",hzbase-hscrhrel*dscrew1+armsep+hzarm/2+dscrew2*dscrhrel/2); -echo("Min length to flatten contact screw in base (mm):",dscrew2*dscrhrel); -wxknob=wxarm+wallt+armsep+hscrhrel*dscrew2; -dxknob=hscrhrel*dscrew2; // x offset toward center rel to main arm -hzknob=hzarm; // height of knobs -lyarm=lybase-wallt-armsep/2; // knob spaced armsep/2 from base front - -y0sprwell=yhinge-wallt-armsep+dxwedge*tan(ahingout/2); // starting pos of spring channel -sprfloort=wallt; // thickness of floor underneath spring -sprlen=wxbase-2*(wallt+armsep+sprfloort); // length of spring - -dxtip=wxbase/4; // diameter of rounded tip with attachment hole -dytip=(wxbase-dxtip)/2; // length of tip ex rouned part -rtip=dxtip*sqrt(2)/2; // radius of tip -ycentip=lybase+dytip-rtip/sqrt(2); // center of rounded tip - -module teardropHole(lh,rh){ // Hole with 45-degree teardrop shape - rotate([90,0,0]) - rotate([0,0,45]) - union(){ - cylinder(h=lh,r1=rh,r2=rh,$fn=8*cacc); - cube([rh,rh,lh]); - }; -}; -module snap45(snaph,snapl){ // bumps to snap parts together, max angle 45 degrees -// snapl is length of bump, passed as parameter to allow tolerance -difference(){ - rsnap=snaph/(1-1/sqrt(2)); - translate([rsnap-snaph,-snapl/2,0]) - rotate([-90,0,0]) - cylinder(h=snapl,r=rsnap,$fn=5*cacc); - translate([nil,-snapl/2,-rsnap]) - cube([2*rsnap,snapl,2*rsnap]); -}; -}; // end snap -module wedge(a,wx,hz){ // Equilateral triangular block - //top angle a(deg), length hz and triangle height wx in x direction - linear_extrude(height=hz) - polygon([[0,0],[wx,wx*tan(a/2)],[wx,-wx*tan(a/2)]]); -}; -module cone45(dc){ // cone for stopper that keeps arm down, 45-degree slope - rotate([180,0,0]) - cylinder(d1=dc,d2=0,h=dc*1.0,$fn=8*cacc); -}; -module wedge_hinge(){ //wedge on wall for hinge, with cutout so that arm rests on top and bottom - // cutout for stopper cone - translate([0,0,hzwall]) - cone45(dstopper); - // wedge with cutout, centered on the edge between cone and armrest, - // to make arm better supported against up-down tilt - difference(){ - wedge(a=ahinginn,wx=dxwedge,hz=hzwall); - translate([-hzarm/2/sqrt(2),hzarm/2,hzarm/2+armsep-dstopper*0.75/2]) - rotate([90,0,0]) - cylinder(h=hzarm,d=hzarm,$fn=12*cacc); - }; -}; -module bump45(bumph){ // Spherical bump with at most 45 degree angle -rotate([0,180,0]) -difference(){ - amax=60; // max overhang angle on bump, not necessarily 45 degerees - rsnap=bumph/(1-cos(amax)); - translate([rsnap-bumph,0,0]) - sphere(r=rsnap,$fn=5*cacc); - translate([nil,-rsnap,-rsnap]) - cube([2*rsnap,2*rsnap,2*rsnap]); -}; -}; -module rotsnaps(snaph){ // Rotation snaps for paddle - rrot=(hzbase+hzwall)/2*sqrt(2)-snaph/(1-1/sqrt(2))-wallt; - for (a=[45:90:360]) - rotate([a,0,0]) - translate([0,rrot,0]) - bump45(snaph); -}; -module base_add(){ // parts of base that add to shape - // base plate - translate([-wxbase/2,0,0]) - cube([wxbase,lybase+lyknob-rround,hzbase]); - - //rounded front - translate([-wxbase/2+rround,lybase+lyknob-rround,0]) - minkowski(){ - cube([wxbase-2*rround,tol,hzbase]); - // rounding cy - cylinder(r=rround,h=tol,$fn=cacc*4); - }; - - // walls - translate([0,0,hzbase]) - difference(){ - translate([-wxbase/2,0,0]) - cube([wxbase,lybase,hzwall]); - translate([-wxbase/2+wallt,wallt,0]) - cube([wxbase-2*wallt,lybase,hzwall+tol]); - } - - //wedge 1 - translate([wxbase/2-wallt-dxwedge,yhinge,hzbase]) - wedge_hinge(); - //wedge 2 - translate([-(wxbase/2-wallt-dxwedge),yhinge,hzbase]) - rotate([0,0,180]) - wedge_hinge(); - - // bottom arm resting surface, height armsep above base top - translate([0,yhinge,hzbase]) - cube([wxbase-2*wallt-2*dxwedge-2,dyarmrests,2*armsep],center=true); - - // front arm lower resting surface, normally with 2*gap airgap - translate([-wxbase/2,lybase-dyarmrests,hzbase]) - cube([(wxbase-2*dscrew1)/2,dyarmrests,armsep-2*gap]); - translate([wxbase/2,lybase,hzbase]) - rotate([0,0,180]) - cube([(wxbase-2*dscrew1)/2,dyarmrests,armsep-2*gap]); - - // outer end stops, 2mm wide - translate([-(wxbase/2-wallt),lybase-dyarmrests,hzbase]) - cube([armsep,dyarmrests,hzwall]); - translate([(wxbase/2-wallt)-armsep,lybase-dyarmrests,hzbase]) - cube([armsep,dyarmrests,hzwall]); - - // extra column for center screw stability - translate([0,ycontact,hzbase]) - cylinder(d=dscrew1*dscrhrel*1.5,h=dscrew1/2+dzcontact,$fn=8*cacc); - - // QCX attachment: add 1x cable dia of wall thickness and rotation axis - if (preview>=5){ - - // Thicker wall - translate([wxbase/2,0,0]) - cube([dcable,lybase,hzbase+hzwall]); - - // Rotation stopper - translate([wxbase/2,lybase,0]) - cube([dcable,rotstop,hzbase]); - - // snaps for paddle rotation - translate([wxbase/2+dcable,lybase/2,(hzbase+hzwall)/2]) - rotsnaps(rotsnaph); - - }; - -}; -module base_sub(){ // parts of base that cut away from shape - - // center contact screw hole - translate([0,ycontact,0]) - cylinder(d=dscrew1,h=hzbase*9,$fn=8*cacc); - - // center contact screw head recess (20% enlarged) filled in by cylinder to avoid need for support - translate([0,ycontact,0]) - cylinder(d=dscrew1*dscrhrel*1.2,h=dscrew1*hscrhrel*1.2,$fn=8*cacc); - - // Front mounting screw hole with recess - if (mountholes && preview<5){ - translate([0,ycentip,0]) - cylinder(d=dscrew1+gap,h=hzbase,$fn=8*cacc); - translate([0,ycentip,wallt]) - cylinder(d=dscrew1*dscrhrel*1.2,h=hzbase,$fn=8*cacc); - }; - - // wire well - wellw=wxbase/2; // wire well width and length - translate([wellw/2,ycontact-2*dscrew1,wallt]) - rotate([0,0,180]) - cube([wellw,wellw,hzbase]); - - // Back mounting screw hole in well - if (mountholes && preview<5){ - translate([0,ycontact-2*dscrew1-wellw/2,0]) - cylinder(d=dscrew1+gap,h=hzbase,$fn=8*cacc); - }; - - //cable holes - if (preview<5) // Free standing paddle, no attachment - translate([-(wxbase/2-dcable/4),ycontact-2*dscrew1-wellw-dcable/2,dcable/2+wallmin]){ - // cable hole 1 - translate([0,-dcable/2,0]) - rotate([0,0,90]) - teardropHole(lh=wxbase*2,rh=dcable/2); - // cable hole 2 - rotate([0,0,45+90]) - teardropHole(lh=wxbase/sqrt(2)/2,rh=dcable/2); - //cable access opening - cube([dcable,2*dcable,dcable],center=true); - } - else{ // Cable routing for QCX - // cable hole from well - translate([0,lybase/2+dcable,dcable/2+wallmin]) - rotate([0,0,90]) - teardropHole(lh=wxbase,rh=dcable/2); - - //cable access opening, printable without support, using breakaway wall - for (i=[-1,1]) - translate([wxbase/2+0*wallt/2,lybase/2+i*(gap+dcable/2), wallmin]){ - cube([dcable,dcable,dcable]); - translate([0,dcable/2,1.5*dcable])rotate([0,90,0])wedge(90,dcable/2,dcable); - }; - - //vertical cable hole - translate([wxbase/2+dcable-(wallt+dcable)/2,lybase/2,wallmin]){ - hhole=hzbase+hzwall/2; - cylinder(d=dcable,h=hhole); // main hole - translate([0,0,hhole]) - cylinder(d1=dcable,d2=0,h=dcable); // tapered top to avoid support - }; - - // rotation axis - translate([wxbase/2-dcable,lybase/2,(hzbase+hzwall)/2]){ - // Axis hole - rotate([0,90,0]) - cylinder(d=daxis+gap,h=99,$fn=8*cacc); - // Rotation snap - }; - - // Room for square flange soldered onto rotation axis - translate([wxbase/2-wallt,(lybase-lyflange)/2,(hzbase+hzwall-hzflange)/2]){ - cube([dcable,lyflange,hzflange]); - translate([-tol,0,hzflange-tol]) - rotate([90,-135,180]) - wedge(90,dcable/sqrt(2),lyflange); - }; - - }; // End QCX attachment - -}; -module base(){ // complete base part - difference(){ - base_add(); - base_sub(); - }; -}; -module attachment(){ // attachment that can be included in QCX (or other) cabinet - difference(){ - union(){ - - // Attachment part of wall - translate([0,-2*rotstop,0]) - cube([atthick,2*rotstop+lybase,hzbase+hzwall]); - - }; // end union - - // Axis hole - translate([0,lybase/2,(hzbase+hzwall)/2]) - rotate([0,90,0]) - cylinder(d=daxis+gap,h=99,$fn=8*cacc); - - // snaps for paddle rotation, slightly tight to avoid play - translate([0,lybase/2,(hzbase+hzwall)/2]) - rotsnaps(rotsnaph-gap/3); - - }; // end difference -}; -module rotlimit(){ // Rotation stopper for attachment, to be included in cabinet - - limdim=wallt+dcable; // width of stopper cube, equal to stopper on paddle base - - // stopper knob - translate([-dcable,lybase/2-limdim/2,(hzbase+hzwall)/2-limdim/2])// move to hole - rotate([0*30,0,0]) // rotate if desired - translate([0,-lybase/2-limdim/2-rotstop,(hzbase+hzwall)/2-limdim/2]) - cube([dcable,limdim,limdim]); - -}; -module rotlimitEXPORT(){ // Rotation stopper for attachment, to be included in cabinet - translate([0,-lybase,-hzbase-hzwall]) - rotlimit(); -}; -module attachmentEXPORT(){ // Rotation stopper for attachment, to be included in cabinet - translate([0,-lybase,-hzbase-hzwall]) - attachment(); -}; -function attachHeightEXPORT()=hzbase+hzwall; // Export total height -module arm_add(){ // arm base shape, without knob - - // main arm - cube([wxarm,lyarm,hzarm]); - - // extra material for supporting hinge spring - translate([-dxknob,0,0]) - cube([dxknob,y0sprwell,hzarm]); - - // extra material near top of arm, for stiffness and appearance - hzarmextra=hzarm/2-dzcontact-(dscrew2*dscrhrel*1.3); - translate([-dxknob,0,hzarm-(hzarmextra-dxknob)]){ - cube([dxknob,lyarm,hzarmextra-dxknob]); - - // 45 deg underside of extra material, to avoid generation of support - translate([dxknob,0,0]) - rotate([90,45,180]) - wedge(90,dxknob/sqrt(2),lyarm); - } - -}; -module arm_sub(){ // arm shaping - // hinge groove - translate([wxarm-dxwedge+armsep,yhinge-wallt-armsep,0]) - wedge(a=ahingout,wx=dxwedge,hz=hzarm); - - // hinge stopper cutout - translate([wxarm-dxwedge+armsep,yhinge-wallt-armsep,hzarm]) - cone45(dstopper+2*gap); - - // tension spring channel - translate([0,y0sprwell,(hzarm-dspring)/2+dzsprwell]){ - cube([wxarm-sprfloort,ycontact-y0sprwell-2.5*dscrew1,dspring]); - translate([-tol,0,dspring-tol]) - rotate([90,-135,180]) - wedge(90,(wxarm-sprfloort)/sqrt(2),ycontact-y0sprwell-2.5*dscrew1); - }; - - // contact screw hole - translate([-tol,ycontact-wallt-armsep,hzarm/2+dzcontact]) - rotate([0,0,90]) - teardropHole(lh=wxarm*2,rh=dscrew2/2-gap); - - // hole for spring keeping hinge in place - translate([-dxknob-tol,yhinge-wallt-armsep,hzarm/2]) - rotate([0,0,90]) - teardropHole(lh=dxknob+wxarm-dxwedge+armsep-sprfloort+tol,rh=dhingespring/2); - - // extra space for center screw column - translate([-(wxbase/2-wallt-armsep-wxarm),ycontact-wallt-armsep,0]) - cylinder(d=dscrew1*dscrhrel*1.5+2*minstroke+dscrew1,h=dscrew1/2+dzcontact+dscrew1*hscrhrel*1.25,$fn=8*cacc); - - - }; - -module knob_curved(){ // finger-curved and rounded knob - intersection(){ // cutting to outer shape - minkowski(){ // rounding of edges - - // un-rounded knob shrunk by rounding radius - difference(){ // shaping finger rest - - // knob, to be shaped by subtraction - translate([-dxknob,lyarm,0]) - cube([wxknob-rround,lyknob-rround,hzknob-rround]); - - // shaping of knob - translate([-dxknob+txknobmin+dfinger/2,lyarm+0*wallt+dfinger/2,dfinger/2+0*wallt]) - minkowski(){ - cube([tol,wxbase,wxbase]); - sphere(r=dfinger/2,$fn=8*cacc); - }; - }; - // rounding sphere - sphere(r=rround,$fn=cacc*4); - }; - // outer bound of knob - translate([-dxknob,lyarm,0]) - cube([wxknob,dfinger,hzknob]); - }; - -}; -module arm(){ // Generate final shape according to preview and cacc settings - difference(){ - union(){ - knob_curved(); - arm_add(); - }; - arm_sub(); - }; -}; -module build_all(){ - - if(preview==1){ - base(); - translate([wxbase/2-wallt-armsep-wxarm,wallt+armsep,hzbase+armsep]) - arm(); - } - else if (preview==2){ - base(); - translate([wxbase/2-wallt-armsep-wxarm,wallt+armsep,hzbase+armsep]) - arm(); - - translate([-(wxbase/2-wallt-armsep-wxarm),wallt+armsep,hzbase+armsep]) - scale([-1,1,1]) - arm(); - } - else if (preview==3){ - base(); - } - else if (preview==4){ - translate([wxbase/2+wxknob+1,0,0]) - scale([-1,1,1]) - arm(); - - translate([wxbase/2+2*wxknob+2,0,0]) - arm(); - } - else if (preview==5){ - base(); - translate([wxbase/2+dcable+10,0,0]){ // spacing for rendering, for preview of fit - attachment(); - rotlimit(); - }; - } - else if (preview==6){ // Base with additions for attachment - base(); - } - else if (preview==7){ // Attachment for inclusion in cabinet - attachmentEXPORT(); - } - else if (preview==8){ // Rotation stopper for inclusion in cabinet - rotlimitEXPORT(); - } - else if (preview==9){ // Rotation stopper for inclusion in cabinet - attachmentEXPORT(); - rotlimitEXPORT(); - } - else{ - base(); - translate([wxbase/2+wxknob+1,0,0]) - scale([-1,1,1]) - arm(); - - translate([wxbase/2+2*wxknob+2,0,0]) - arm(); - - }; -}; -build_all(); diff --git a/case/seeed_xaio_case.stl b/case/seeed_xaio_case.stl deleted file mode 100644 index c0ea012b6794941fe9a24aaf2dde71a4f7b9bdf7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 64884 zcmb8Y3%nK6|Np<~B9(4R_w4HI-Cc;%?aUrsT&hzca+ea3!ih+iBP3Chl;}b_yHGBL zRN8a4LUchsYi7^+KK}n6kJDp4_UrvzueD~@thHul?X@qw zsPEZv`=Z|Q(@s65^C_pEa$1K@o#H+E_w9c{_ottJx-|a(_g{?)G5J>%ixoLHO{r|p z*jFnXi`B5*bOW8PR_?fL`^qQkbYX!YAXo_#GxoVOh$73QiVP96O}d6oyF|3?5gp{kuGWB4O7}d%32oor8kYI0JDn~^W;m>%;vBGg<54TiBAoM>zK89w(l*&C` zxr8YpA6;bc5~jRTsxSeM{O$YK{98InpA%CO_Z-N1HlN3dxbf#TX;%1rTs{7{YR6%K7$!%GufbYT39x z+;jt-R;994&2>6>eXzpB_Nm9&v-i1lVL`(W4!7A;uE#QU79A!yYD&>@cE0cNTBAYF zJb3Knr65>gV)=bss^dO5{DRvKiyT&%K$`1e+OAPzwn^8}X}2CYgD8#b5sR68%Obq% z1Ff(KRPNEmk&Xq9bg*aOBWh?S+)^QT{426J${gtkqDTWifitCBpLcxRI+>aeYS?-C z&u7nS2@kG0dzkZtQcc~lsOh$H8(M@3jxy&7M6ZUO+e)ceG3O&(Dlb}}liXwF*2$FC z^rHGK7O`UJu*b~pw|7=`&>p6?HEdIl8n|k`;}%!-IOn5*Ye4MkxBpdEm@xH2sm{4F zx%QvZNzV0MUU`iPjxt99#H5EWTL0?ONlxDDd25*9sM*(6v9I2VHil9i*Xfe=cNI_4 z^)Vx{$`!YxSjddoBTN5A*9ZO9tccR_wteT#O5Q<8& z5>3Ek`T46eb1RK@)L(!wbS$-H*-3W4?bSUGCRm9k;PH2lA2YM_hB@jl$%IMAQja%p zV1HS)n&-g;E71fzb_}lKOfIM{wkh_5SM*$Qi7Fe0v_usHFbVH z<{am{OmqMg2V#APgN# zHQ3U^etUS#^I(FNXaXMJS0CoIdHlyro5ycRFk#ZMRI6F7>?c3{Gv!``LhKs-VuF=u z0vMuYTI+p7GL|eOizwbN`AzHt5FprgJ z0v;Et(dPPLm#pviP}2Zm=vZp&mbUiyMPDcnCVn4qTOKPW9k&f#LLSN|;1Nw=9F%&X z=A4&F$8A$5cnE=-vl30fL(a$Qzj~K(bmO);H}DXmLC5QgSuuW0z(d+qlWV_P!h}i3 zZPUi!A;j_r_6FK+GyxB}KDu66Gs$_Gblf)A3Os~R*J0oqj3(e=uJbBM&da3Zwz=lv z!2~PO1UyWC)ilY3Nylx|cfo@RR-y@bl-2JVI&Paj7#>Wp5>3FPtntIpaoda~@DSqJ zd)Fsfi6-D7vpI&Pb}7Ca2`zXU7M1UzJ(IOD6o1B9XDp;@>gf^*Sm0v_slNoV!M zz)^oZ-}UZH-Mdtp@2YwT5r5%%CQ^L=NogWfPan7wHu=gk2f1Srk024JyRGn@7b4w% zMHWVY>!$WCNtM4k_2fL;Pvi45YxYawbNwu%hzU`cKw3U`iGfcPt$%UiBuA7fKkm>Y z8KRKJ=b7&>O|`vehw@mmvsWGyqDV=Emd^_d`p!Es@!c*f({AkD+Cvl&oW5h~@YMRg z|4|-et6WuF79mk6m81&`HqCgwcwDE2nOpBH)E=V1gVR@UxGhz8z;@*^XVu=kvIvQS zholP&j(?>^B2)TV##wy5_7DXgoUS{3Vk-662g>7_+gcWvMMxApB(0t^RJySEw>HN+ zyAp%7hbZvi^!BIkOZ9HLMR{C0bZ41_M8QMS>Q1=o(c-gCY3^K}>ZLtIfd{ASKmK5< zMx{;418u4-LZaXyX}4Xyyr7G7cYb^AAqqS=z3b@oRGYyYJdd&niGqiuU61t*`#bgS zI!Swo0uN3P+3;xU-n@+GQ5GRl@Q}3Yv3Srm&P~e>XIO!UL?M0Im$Os#C%>UQ4$SGA zEQ^pRltoAsJS6RUc+anjSmAu-^MMl=c^>k_ixnm$?GmeQdppl7ReltKD146ko!fYx z@(2^6aK1>(=YjK~Jw)Lsc;Gz!_3fthx3T1gHeQSd-}oBrd&o(B`6 zaK1>(=dOp>+O>x$90d`)ChQI0_!$AFwTCDi1rLmgP0k#yJk-c3ajmd5I=OVFGFST+f!4c(bJ(LZUzfW@IrTSV2i7Dp)Fa#)tol91xf%$}EiM zaPqm^5?!juL0+PWpUnD%b_rFg?rNT>>mhSd@soM!fh#X9agUXnC!*#)Aqo>n%jf>l z%~$h8?I8+Bp|t7J>q^{ne$L?4d1{{M6QVGIw0vGzFt}(J+Eu=qCu$E-I0_z*bh)j> zZM!&5Oo+k+((<``tkkS8U(FM>hbSBck8{47P~u*L-u2-VqA-E9eD2Q^Ej3Tn9-?p* zJZ`+=z7n@Dsaj*z64f*KgeXiPEuR+_T>eaN%o8m&Pt+cwa1=aV8Sr3<+b3SOu5OYE zQJ6qlJ})eox3ywY^`e%VCu$E-I0_zjuAW}v_U&Op6ef_C&kGAWPx>LDMgvRD6SapZ z90iX*Cq7zY#waF4VFGFS+&$-NRI}7PQICV7a1=a#n>)M2jI~UN!UWRtx$B`uXG_f! zwTCDi1&{Ckm{Vfr3`~f^1k&=k>!D_SmYOGO4^cP@9^D>!qQss1sF`Ik6QVGIw0y2- zOH0)J%2M-0?I8+B!DH%`^Gf^~S%46Q38dw7w;rlL)NiXfFOHJW&0N$YVyrMBX_xS3 zeW*t!ia-)*ZS#Qk|$ghU}HNf#FMI9z3k*I#K5Q8-_u(T}B54`*3Fe(R1>0bzDT1#_MZXddHrqt1AyM#Hj1?v%JvwuYdiF{l>!S!niT7Q1mvf1(D|$|}e$D=(36u&7 z=Zp0HXB~8k&aB{hv}rWndga5@GMpDj;qz_R{o<7SxuWNBPW`*Ap~;b&5QPb(w{7~# zdEm)Pp2vdx+pP_s%*r7o3LeG7_Bv0TUD@-v_mNwyrj1|HgeaUZ((&%QoOgCt@jNQk zxXJqP{r7VSiGs%)7k}<7yW<4UL8LKMyy=?%^U z&doLIdmie@TIvYr5E2ECFV~HA{`kuy)HPU|ug;<-MB#jq?$`2a=jgTuo`-57`KqPl z5E2ECyw7_%n;vTD)kC$yeAOB?AqwY973Yt(S3MLr~7)3 z=&G)!e05c6LKMyy>0Mv!&wO=iW6wifvH9xC%^@TT9uwQVo;l+okLap;g?!aJXhIau z7wM5ZCS(q677x|)bXPr44k1zS*fgtJ=DXj-13jqfNi`t~=Zo~XyZ`s*?o#pi`{GaA zsh%{4kSKV3eEl=s10L(eLln*z=^2Nu{6Ia{OFfv7D0o!wHa9dLoOC0G- zMB#jq{&n~qE6`s#(qAzlQSf-{KTlhMKGBgrQ54P>=^s};Zw2~YNBUhRBnlp%99?Av z`gTY9c2PKAr0-wyrWF`J92q~DkSKWEn%-yy#wbU|C{Z|Hq?iA-*$RwD0Jf5Ar&kD@p9GSz3!ucW{U;DEa zm?t`_C)Kk)CL{_TwVLg>0&`Kl;+GZ9SJIft`g2iu==rYX#ZgiZ%!A#z4|-6H2&^!H zG>*cQ*?)K*=s_{+gb9hl=QxH%t$y=7(1T)RV}VCY_^FR-Z*=3lJD145-vft%c&wx2KdQi+@S>b$#uJh)iIfO(ZC(LRC z9+>ZHLKMyyY0Q=b^}w7uhma_EV0IojR+zVILKMyyY0UZq=L7c!IfO*P19usLbB_BD zO^CwzB8|J3K)b>{P7Wba@W9B$o40wK}2~jv- zr1A7CFfYL~vK&I9;DM)Yfw>Q!!)Zbk&KGGs>kG`U@T@O~kSKV_vrKpVK+hv{I8iuX zq~(dHTIK!Qt&5s}cySVMe~_12!C#`D66<$2Z;tWP*`p`O%KpFBR(t021%?ns(KZqE zT>w0FcK^8^OvpC|%-YeI>Zu=`JS}KSX3ai`Q{Rdu%HRBKbJT+gjxsCo zLEKPt@}h747%nyEvinCtt>w+C?_gzB=@s$$DW4}7R6AaO50Vu=ZptsKzG+e75+4

ku^iy&B0tJSmWTWt}g5(Cs+t<%n`?+NOtGq={X z>&i8Iwtb$L5nJQM9lwJWU<0TW^q${ z#NbL11S?Ej@^usY>TQ)H2v(Rl`gKFQ+|jBL1S?E*US7}s^i#JTyYJQ9suWq=`nVnU zI=z}bZ(fRtE z^Z3Dp`Q{Tm+Rp8e9G6_3K&hDEDDyog5ZRS~Bu5?BM0>DezKIkr)y-GTO!hrILf3;m zm@wZlf=9!tja$sWZd^`1ILdru2*kf%{gnLc9=B&;#eC-{T&h`}XSbMq>nZx2bE%jx z-{yhGt;4QwaqM~D<&=t}R1fZb7a7FlYI9qB_-{|?+kHj#kKVVU!=+mF?WZk%dFB0_ zQZZq^Hv^9~=MHPRcx$#*_zZFse}`L*gUyaBZm>OfUc%px!E8WgIE4i-e2`hPrTY|p z23cX^rM+#lmpuP%N?m!XRHqbux#T~|shVJgi4l*r%??TJ^N0&)j!!;c{~X;XvckmC zoo%vn-}u!dzF9CkeZm!a`h2j$#EO-z)svzl9&zdV$;It2eMXmx6(%aRZk2uJP^m{8 zTc;q|=&1v`RID(u*=~_--wWSGM$Jz;d{6Ote`T}>D@^Pz&C7l~2;Yzf@zkb1$&o+0 zvkX?4IOnEj+3wBoy=@RI6&{?1p3V1v zu}Hf!a(w$t9V6#WMf5qwDP|>1m~|OKT(|S_973W%yLT4iu}*p1kSADIjj5{1uYZHr56P{bp5f7F5%q6B1=Ucdw`-XNMwgu0DAgE1WOVSZ67#Cf(MK3o%Sclo0ZL9JQm7^61m}G<`+M znoaS*s#4C$tp|?oM<4%(j+J|Vj(P}zqaf>EiyXA8zNIthSh<8m!2?HHR^t{qZzXs-9qR{fOvOBj_XzhDDHv9ufr)^mg*ySGOgO?$<&e zD?T3*1wx*kxa|u4Ri@`4O^CwzA}!y#aEXUmnq|T@*y| z_e~@xmq5)Y-8okuD^bFPd<(|ZWV0 z#GSkK`4A;c$ak7t0wWXeAFUsHr_fL6m$O3~9;9B`_LP+UmAl zQNo0LE6pVwMZ^!;IrWez(DMB_9y3my_BY18kbr~an?WZkah8qk$;Vgv>H<1}C?^jM`Nk>o@&x zeIkt`;;uc%Rf|@Vmu*bv+$AIm1dg=3k{kp)4t_sTdx(N4oO7%NN7^l|lnVWB{qdja z^C3!@K3G-<4peA$Umds-8MOG08btIK2DBRp)hP zg$a`r&R`Gau}*pX_S~=~OmLL>9K?gICpfKtt($-IrgJ)*s91`hu(6+d`r(XsUVF7! zeuGW#u3?3VoBwEIKhqJ<;3z|*RHItl>1>#Fcm9nd-&n&66XuB?h<{7( zaK4^7CI8@n%3WAtV&cBmcG1^(PK{E{U3rTWyYj{S`{w?$h6#=`&j8`E;`UL_5BA#p z%GFzSVTFnEceS$TpZ%BT@zK}AokM4Rl|Nu*{k2SRlzD0hkM^C1I-h^?bN=DRsV=NA zaY}Iuds7s)rUzSZ*9v(_@fQRc}cJkIRU%Q-Q>xz(=SC0$ry;+g%;?9bGmwysCb z{BF*kiS4Wt&g-_8363()GU2hHr9xhOo&9(akSsJ4<%%Ci42%vfmhu_Z0A$u(3E( ztK)4Ju5%_h$~-BCN59+0WE#%9(^9=pXI7Z_YD_h|{k3=^43Bre8j<<6>s^-W;npz0 zQRYc8JnqUKm$`ra1gqBct2(p71U)HM#MgT&WG>x00pE#>F~LzLjqd_b57*iBaIuu> ziDD`4y8=DjT2`3go+!}6b>=A36RCY51AQX(aBEp%f_tLE0_x$YPmHBZPZUc93F_h2 zvcd%SM1dZT`ovhu^hB{#kf0uJEh|iLPZa3ks85WgOivU`1qtfm*0RC`_e6yS)WcDq z7)zO+D3%Hm)WfZ1g$eG70zF(8jxs$_EEOcEhg-`E6WkL8dblneWqP7mDo9Wdx0V$q zxF-tqaMUNpQl=-0rGf z8R!$Khg-u66WkL8dN}G6RePm(X+ff6lPZ~Oo}OSeK4ZWdR+upTRg8MLCqJ2xE+Z-x zO`uOSitNUY-Z^fYoY3#mTr@E2GxO58&GSdSD{yzUBe13ZXy0?a^Oyg=&b-INXrT5H z_6b(ho2CdNrUlGcCE`-yY*V?FU^EW>m7T&)gtgQO>=kQRwAzEthUHk<26-o*A z4)#}}n9t#%cBiz|ZoT+R8>Iw00sE_7%xV~TFu_VR0S~pyrlof5#b25Ulh!--daHNf z!Gu|{Q-ZyN{S`arb9kuTLM^pZXukR@HcAP00`^x0nbkt@5F)?b@-!>a1U%HPr!Gj62608J!2m33*%;)e>JN8;?C*AG` z&pjb+loIR&?5|H#&l$4n2~vsb{)zZ}Y&Sfa@D-ERJN8nk#N(&JpRxb0uS63VKcpT@ zo-YXyhSodwdUfKOSDC*Y`|tWnGyxAeA8P;I0AXmo|1Px>Cd^smqss(5q+O{Ud-Iqu zX}x2w*Tzr}A%?d+5&Q4@N;Clvxjq(8`v!ab`h-dA9ee4j6(W2MMicNT>pC~rpx&|9 zyXH|3CQNU@*EtjLD679RbR0YOQZLE`E71fz%IbFwt#|D8`e4+93DY}szsm$X${Ifm zt#|CDQH=>R%J68w1U$+b2Mw)v?DfV()Po5#T9#l(e6J)-z{8B^!_rKcwBE6oW*JPF zQJ+U=Cg4%lyu{FY$6lH(F=1veJTGAa9%aq13?0Xgz25pu94jVRi6-Dt);!VBddFUG zbsIdGFtbUX^)UgDvgW&n=Giic#rq~%2U~yCZB~WV&!Vq&R~zXk+y2TUvvLTf5<*eW zvSR31%6uMEM5U7^S&x6ee7*Y1GfGJy%B(elhY$ys-;>9Rp<^lYIXpVFx!Yz!#( zR6Ajml0cMModgdiSTS@gWj=>T?~Y@vEsxF1th{n~!YCzyD6^gk9ztAL|M?^5_zHEl(L36qYc%(^Ui z7@}R0m1qJUH^y38H?*=H^%o!vty+n{#tR-yuo6wcoUP*qx({FbAo&HOJFmxaaX7(BGyxCOu6_v+hK}2& zjln~RwR>MlvJy?eL#~hWzFQU`46Wu2fvZ-C@HH4sz@x0|+~ga#%{7mDFu_VR0gtl! zD?`U^(|5sx309&Bc$C%e8ai&9J{TTMuo6wc!;BwwlT4U&+%{tgJcLNB9hzh%nt+Fl zgLe;21qegOZ8IjqLx}KL8%@BYtnu9B8@J8a4i6!&JJ=}AN;ClvnU{RFuuFh2v}#xW zDsOlQq2@nFm#;*B+`L3aPwhTi0T|5g9^tFC}u71;kdejg>ilM{5f}z&1Sm(EDxANn$DXd8G zzqg6B>^q0F`%DI<0+CWg#iu)ArIW9O3E4N!CC*jE_^DO3hvWr9qL7wd;9R1oA|`Af zg4H{|g0$@8hP34561^3Xd43002>D8wkR95L$MUn|+C%aJAyG)1o!C(GUdrS3du;6? z3Zi7kG^8ab*8{|D^~)z%2@|pxnkm(WE;VzGu0(;Boy`n!W}>zxL_w77O~&4)R9{|S zG3Qt@A-j$lV(m8vatMinhwLF{O7-a17wb}qf+*PqEVooRgQs6S{W(^`gzWF-dUR4m z(;Xe#gb9hl=d$;fsmH5-U7phtB?^Sxy}ATSm4Dg8tytlFk(Rx;OwFJB)Af+NI0|Xm zNz0UK&!8W5OB4lBvKJQ8l9M48e0&5e&wM3J$SzlgXqa8AJtQv>5{0zvS!L?caj$#T zih?NFbqZ<8$#`@)@jd*$ny-Wj*-y$4cNg}{DV0QlmffLDsY;Kpt6QQdh?4!C*xL|O zht$@Dls8Ps&P|5+^1Y!sghYXseVAMVJ=}jUtg2hPD2S4slyXajUUYl5lWvJzDkfx) zB-aBy^}730+Jgy+5;U)}ob&Qa#`m>O$A^iUoH-~E(YyI$Gv=L^E@Qv?F_IDgvl zbOv2QqCl8khon^h+kTgR(;y0>WZ$6NQrXI5)-O*}&0P;B%#J`(s;e5gLF3^Fgxj>RQ(k3 zukxIr{duUePQ2y)o52R!qq5H*P&psykB` z=<7rBLP;bFY1zxh)cn;glk~9?1yQma4bqa6OW^2^8{0`AD^bFP>@(vMsCm!AF}m$C zAyJ@Z*BF;TyPC7?30*2t5GDJ*YC1bXT%r!~_aq9984G6|OI(*38c&wFc#>qja>o_Ao z2#u&4Zf=^r_qk@ChY({Ic2BbsMSR_*lJclF=BLcTokOkZy*dU6p%L}s^NH*|6XKqS zAzm+LC5o6gu%hyq@zrt8@*{(-^^dIx5JDsBlvi72FFxGZ^AKX&DU;KzL=olcl~*36 zrS+Z9CiS&C4Zl4=2#u(7Cb!GJSFfSxA;h?O&C{$z5f{!nMtM{!ZS7RQFW*X!s23oF zM%0EAPRpLNude681S?U*!fF33EiAZaZ5QXAliOQ2)vuanLehx(Z~rs0J8r4%c`(6B z6mj3k|0$0pwa;@J-_pc7rRbkxCM1ohMQ3-)R#;WT^AMt0JU`7!6!G632bIV9zYTKI zv#VM|R<;ZfLLZ+cH5IcX_Rm@5hG3eu;lt=xpL!3*mI+VZrmA3+f(1_aA zyj!-;1C=}vCRm9g{=D^DPOb+N ztV9#=kn{0t?0=C*7xj>H<9aZ`it%Ft9@4IwJ(Y@VCGe0o=6W!}it%Ft9&&x)iekc~ zpC}d+?H$J^$?=x)ZYVrNi+cu>90mqsFmitOggT9u8@0CA;NuP zGy#vY`dyQ6+?GDrtp^jVL=*6k@dG0c6DA$EWh`+$m|!KEfJa&5prPZojESy?5KWU8 z1jgEE0veK*X=(sI&M%P1#@LV*SfJa&LU6XIzmbtI%!2~PO z1UzKkj+s6aCLOnB4)1y}!Adj%kFxGR3>~-SUc~h<#HM0aq6v7&eN^LfSQ-+ETuQ z^gj;}EB~2f2&FI~Y1iYb6!}npIk&##g)AWbD5g$1el9Y329uaNGX4!Cr69 zAjFebtWK~JNhrFo;IE1kt=Vt=)4lnohXRC8tEi6KQuf=64|pCzC~65Sk%abWG;N%< z;;IYs)n73aep*E>{>ZXB9gm%+Fi#ZXr)~AptV9ypqX~7-jw5ZEb$t={E!jpH@*9uj*!>RIh^PA;ipoW*4&( zNobGL|G3Vo`|qy&yZ&7jAbeUy)tcMIzT*b$W`$!V#OME3OtTV6XpcL0Uv6!0P|g~9 zVdDVd(<*9o)3fZ`reZfMcnI-qAYUsN;Ds!Ac~dJr4hIhV|bQ z&$OH`YowX*(<-X-&Qt6UCe`yiggCj+rD;|o3GGpSXu`@|-@}?X{>A{|(<X=X0m7$M)XtBZ z*h_wI=GB7+9H~Ys&LPAyWN&rdf$3w8#242Ig;_HO{*A_HzS-Pphcg)oyZK zPmt%LOt2D3Xpefg{oTD|)rr=TZhg{B_-Pe2w0Bke-6i6|1S^q*_UL$9i|(D?n`Hg@ zbl)@+ep*HOV{L#)Jb1ntYdK1dqCTyAALFs5m=!5uZGTe~{C{hxAtmj=WUNgh|J3zwgo>h6whF(F8oo>UT}P zaog{MwFeWdL=*5RYy2>D-1f&3?O}-d#jHdV@Q`uP`Eq7}Fm&AZ$3*QR1V&C)q6v7& zc)oZ+?*L)wxb2Va+CzxCBkl{#GNK81n0d*l0Acct+x{FydkFFCr!&&5L=*6k`PI+E z9u5$Oj@$lROM3`$-^PK(tV9#=ka^-=|8@uvhK}3*oKbriA~+X~Cg4%leAna~xBa=V z_7LK>-L2BBL=*6kdHdFdjRJ(BHICgJxQ{aVs{7i&-JKA9|NN(zm1qJUazFU{GhYP=L(|=)>Vw_4 zuQB!Stik_jfxAZ8iocHTwhUkeiw zh0kSQR+s3hJQh5BkuH@eh+-nJd#iPhA`bjAEP*Id!i4P0>U#85#5)}x!BcX7kJm6E z`?9)(t%zj#MY>d?gbCTB)g=lP@#^JIXb(}s1opY~cVe?ps$YvP(u62sLiS~KJuF3B zKK4;vDpA6O?9poKF{j-CO^6aEWM5X77@$1%UvQr;l_+6C_GNVmoWU+1Z%QIclrSOt zvbx0iikN@?b7@405+-DqRhPgyNBc#TC{cvJ@1Sla0}nQ+F9eh@fj0K$FHQ?nsyBaI zs_P-Uw+ewMq-9@LQ}arvzvI^fJGO=i*_YKNaC9%MGg;>)N|=y6T3rGyad~MU|9oIy z*DxXbvbqFX$-Q|qG$BfukbPNQ0xfZFz5cpXqJ#;wP=EJU3$6XgNwYN}N|=y+Sxr59 zH-A!>N|Z1m`?9)3Kjks-x@p=&lrSNCw7LXZ$+?rRC`ObhVM6w0bqTcH{(Ie{D@vG< zeOX;%NWWuWn=$Y2GY}<8n2>#0O{oUY|8pgxLZlC}Bc&ay9k%VCXQsQS|qC4HL32t4p9= zeN=g-u7@aLLiT8N3AFaf_q**%lrXVf?No^!f?WbFv2lsp?}`#8WM5WOs%KYSqDv)8 zn2@9s%RfA*kCiB4LUwXB_4x7mo|+IPOvt{hE`gq5=vQvPD@vGUxOcdw2v&i@jf60$1(xeH_0YP{M@l%jy#S716Wh1NwZ35+-DiR+m6a{C?HB zx|N6$CS)g9mq07&+-$lgLqC^Q3GOH~tsL|w$?jJue(b>EDiR5SJRzLbL~Z-Fw%wz5 z((_<~l_=tiI6Pk1I4!^YO?NmWn)OODA!$UNG_$^)_#@BrFvQzQR-%Y81CCc7<;JYa zfBmh|&XH|SfDjr{6&p9PPqmwS9zq;A;g$p|QN)|4R8k&ieEWI+pqsCE+O+EtAcRKL z*n67Ux3p{Oc?i+ri)l$#qKGx?D=LpmhQ+MScU|eM`1Za4AvB^Mc`a!#Sl`6+5Te^D zrzKg5B1%ikD~}Iutz~`x=Rl{)(G~$hXhdy#rL}$H;f9`v5G#({on$47SaIZ7<UkbQ41KC`l9ec8=nFCBQTd7vR_ytX&b+3z0))_r zy7&9j>`TVf@jQeWe){D}R-%YWXZ@|_)ZhPOTi;Y};oMeuZh#OPQB7-|X>WQPJCfoW z6r%6q3Q1O?h?f@~RvvSE_P4gBPI6wl{$PR$Nh7N5{!aEAJ5TUDgxJvUj3g^j#FcXn zDv!(SU2c6kqP#O=Z<7EaG@>3H-NiobMeKBodI<6Gmmeosi6Sm&u}^s%H|#oVN1yL9 zJ$JqqAcRKLnz`NV;tTP+Wbj~ul_=uGtG-hn?dy!P&TRK)=Fw?$5==-MQQusXZ-2QB zyBouU309(rw|jr7JbE^|-THX_W10Qej!ZBiX+*vMu4RAKAHVtr4ysbQ5duNjMV%Ik7)n6VHl13CpICGaOMB_#c@>r3y zUPTZnl@Jg8T`B0{G+ zheui0IY-Gg?|Lx7N;CnFvid7S$8G7mTn{E#i6-D7{VsZHCQLeROCRid7~+;d-yTiC z!;ByI2MCjI+?KJ#^)N(*z!()xz(dACjGUa8Nylv&6I~A`ScxX!QPy~FXtgItV3uKs z1qoK733$l7q{-2x0m9I6TjnTkJq!_?`$QA)C~JOY@{QXv*K$1!@k)Y~XaXKGPwbhu zCO{ZEZp)m}^$?=r&%=_eL=*6k`R<=9hXx2k$8DMWx*kHPIdy`SXaXKIZx0ZLR{QS; z?j{Toyf=s@;8E87hsjsHn+V($8RESJE71fz%zf160AXlz7l!^(ues~2*4#OpxAaY_ z_wre_<}Rz&+_m64FaPrZQSpg+hENIzs+ z)Z3G+T65=(=R#aDM`k0yHF z`2^lB`AQ_AJ=FUsN3FNZs5e*v!lzY~dN-9-YwkP`A?DxucOEN|g!WMH)f~0vE_3{t z_IOL?=jEqWlzPXORcr3Nd7=65=m$e^}g0oYwjHNzBWMkw2D&i zZnJ95o#$bQkFbKyS0V}Rq24RozPt-13&givqX6RboM+C!}aaMYSRN39$P5I(J<)S7^-T65=l zFu_VBp*_@k21l*Ab4o9mpJ2jIt0=X$A*86&>m`ChNITpIcm*afbeM* zrPgR<)tWocLx>e8j!Uu$?i{s(E96+%fS{IrTvYk#t8&7J4L z1S^q*_E77VGHT78qgK!*nefvpO08kasx^0>hY)I&UXqnaLVKw7R~fbD&Z#qaPJr-f z6{Xf=WnJg~HK^+0U-P;iLa6n-fxaY~fQR%~=;1golh$kQs23FiJ)GaGDfegs z9@6ikr)I*W^_n{x4TL~X?f1^gBbtDRj2~*1cYrXoUUNsI8Wa8~qdcMsc*r=YR?sDx zFloK!jz(u8)cW?MKUyk}XaXK)JTD(046WDP(JX@rf7DkV(F8nXUV@nn6DFDUWCZ9x_i<-_1xeVbXfd9nD^a2+u{M z33!w>-}UFB>KgRtzN)lAf|Y0j9%aqj4XxMQ`F8+@IDX7afqR2!0v_i6V|;+{?+sKv z{Cg2y4ZIRuIzMOHonCv=y)ALqIC95?%%RPVvCb}V|2gjN|Gl}pw6RC*Q^czWOYvqjD@vHa zH@)5aTJ>hs0r5rs#mmBkMB(!phpl{gyQTU`5r6&uvo4h=h+^WF{af?DI#meN zoqds|b zJFA8E5G73fI(&}R;OI#nv0v5W-!n((VdM6Y{3wcgoXg^28fZ8RZDnE0*g zx7GtsR`LkceCsd&YC@DS@!a?yt)eq4c*Gt>Ou1)#&9; zhrlil_#Cb0hBjY%9^WaV$DkJjig*Zt7Fze?ogRUsyLjpMx*np030wsOkKgVQIJ!08 ze@uIb5+-n^z3}x`s(GsW56uuIN|?aaJafqVQMRy*j z&$%dJ0=?4a1#gqbOJkO44^hGddcH;1Z}bRUAOG3)0ahXD-V#cfK!3cUbc09WoOf>D z0_%`g#hZN|?C+tb>l}Md5MRw#M2+lrZu4?S~xGQ)7&hzFm|k!i)x} zdHYAI>r#P$5+>knMx0+1acrZ%^%)c;OrU;dRKrXr@xvy4bVUghIEKNIQ;oISLzFOq z^JGS6w8W8*{h$d^!US56nE{|w%?>x$H5VmJpoN-Q29EA|(@)kOqJ#-t1!g7#V(ipj znh+&S;7T*IC0w;$b}Z6TD|pVZpA&Gt&iE-LJ1fR+!*lk|->=V%;O@6jvDLe!t(W9D<{G&!WPDX_+DElYd{V309ckU-l?0sNmd`UNB{T z4#82pXOa3n;VA>tqxvn?1S?GN4n%52%3od5CA*hvf)ytCH%$r)7Jk_weZzw<1yZY5*)=l5UJgh+I&(xu46`fu)+lY#*A7= z*6yd`R^!*@5FEuj5ET|w{cu@vw@*qm!3q<+pHN}Jt6h(6`N7Uwy0x>yMDW)mR4?uK z)J$*`??6;o@b(oImu)=wZZSp!R+uoqJ%MLSPyI7>$%Q{})b$7u{%=~C9f;f~MT_1( zxa6^YF2VZ|alYzzm~FK!k?j)aUOKvX_l;jILaCVGDD_Uq-6Kgq@#=g1jusPd?9~he zD@>?2G~TWes7IIbpD@>?g%d@ZES<5SxI|kzaB8v%*Qg3Ly-7nndaKaQ> ztT3T|_0JyNCCY;dj#6)Eyj?uP9;`5--nV#ri-ZYQm{7l7Xg50xJL&vi1V^d&E#4j} zVS*JV)bBRh{kB(+@L+^0pR~WMS}nqZ364_lTf9AM!XB(Jq28W& zJL!Z8R+vz~qiJv2UnQbcOmLKXd*bZ~6!u_+3H1x2cEvlfr_=vMaFlv`;_Yk{CRkxY z{SvA@?zM^$9!zkQdVAvS&=mGyg$echtoEMe#M@~q?7<2X>RpJp|5cb^ zg$earw)We@vGdpeMR1gQ7vk;X6((3=qSdTc_LHCfnacHGf}_;C5N|)Sum>wls9y@U zC(QUQ!h;EpQtv{%ebvGqtT3T|BiT-u`#Hjc364_lLcIOq!XB(Jp?gbV^^5Q6Ue`TxtHjlXf zq2fiA7P)tjtb_^Kf54qnPa#4SCXklTgR^jWh{934IzB|uN_!^WTF}X+q(SM2oEMWidV-6Jy>Dlvc0YB zy#uiZ67A~9+ud4xak#&3S4?meuZ}M)7;yb*OGp3noSt8?!bC}*miC6ye?5<%mY=%x zV0Cv+%>+mB>iEKf+pcc8v|@UT_F#pHo32jU$2@;*)~$#2V9TY4U*DWVa1^hOFD$sG z_7^Sg-f^$4IV((bOyt>v7Ga%b_&R5Tqj+_E@O-esL}qbQd&J;M5gtr%6t9jCda%O8 zC0{qOuijQU!h;Ep;??m%4_27qweCTJ6(){;-Ow&~v}#1DnBXX0>mKxAg^A9~>)D@v zS}nqZ36A2m?m-V$m}p*5$8IyUMuZ0w9K~zhgC49fapu;VcD*@R#TssjOmGyhbq{*5 z!UV5e4-%{}(d+bT_PkNGB1**sNAX(spa&~V+%%=KJ!4;#2NN6>T;G23eWQwdTw3K> zjDxH&!RznT_oLd5F79T#cXzBXq3*)6>V7by=1g!DufGe{oE0Ycx6pl}$h*7q);b1% zSDn}2`9ur^E1a*or}BO)p4yf6V1lD~{hjZj309ck)pS0gOT`Kk>Mks+?(Tv|S9>tQ zQM{Ti=)npT>Mks+?(QNynBXX0O&9cFg$Z>}l~s3l5gtr%6tAZ9J#@`kVS?Aj`Gh{Y ztT3VO!m{e_E}~RSa1^hN3wp4^gt`mMs=K=g4<h3PWg9(n}wQ;_OK7*_Bv z-Gyb<-Capw#L@L&f}?n)ThN0QCe&S6R^8o2crd|HywWY`!3q=VE-b6=?jk&x;3!_{ z7W80+33V5iRd;t09!zjl@GV))|EHdE`fKjuHWTW8$NQZ)^wi~dT-*GSHW#E--|om; zGH<1e|E*|zF6$=>3tIg=q;hOy>6RfnqY+qzx8Nh`L=7O zFP!y~CRky@Z_}Fit=^RBuXiXn9i?K03I9sdM3+mSoqo;cvo*mA6aMwDi9c3snf^_e zS(;#l3BQlgM0!Mp880{eRuil+;rD!+_~)v#W=xrI)(q5x6(;=tSQF2@`_PR0lf{}~ zg$aL@&_tuLf6bWiK>J7F!3q=p*rkcP7EZ5z>CqZBK(NAuKR#;W>DeE~_ue@~w|05M zi{JKTl#27>C|oQ0d5O0l znOwG-@D(Q1Rp36w$st%_LR|&!v!xt@6(-bG;6CxnAy{ETT?OuQxEz8NCe&5nJ{`;< zSYbk41@1G;9D)@l)K%a<7tJA9VM1L6?$g>Ff)yszRp35D&LLP~LR|&!lkFUW6(-bG z;6889Ay{ETT?Otl{TzZ7Ce-!ezG=uISYbk4UGDpj9D)@l{C6)o1S?GV?{{(tR+#YL zA>|OPFyX)1(nMK3gRIfOuZ;0EUs%8dD@@4h3-{O3$|5*Q)>62?;l>0jvKj)v6UW|V zmx>8l=ivU{9eZ$I93`t32I*hnV}cb~seoVl*!TrTT_TaoYO4cB_zoWORCcMDkhkRS@4o(9tIguu7GEkOr$4IkJdwx8!h-pOYbGZA zaIq$M3}-@~gt_~X4KAHkTzyJyO|Zg*Jh^vw1S)^*;Jl|h6yy@#8v#Vgb9i^3A|_ao zC+XM=iM`dFx(p8{PSdpjP*v;zyTdA0kr_t`NTjQz+sr?QU~6Y`|k-B*o0I4_Qp=f3W4Z%nWvPj0cJ9OtBV(&<_&@#-HF zb6SZ!BgI~N+(OkpEYnX+3_O2*0<%6=nDC!D>AC1Vmp4cpyJ)KRV1)^J!s_lK*z@&< ziGhcXO~Qi-j`E+KX^#rknk7E0IahnI!h}3wb$3IIjcT4)+M|c|V1lFkCwkiB=Txi2 zU&~+79;`4SPgvbu9owW^C$3-jg7#p7qx@%??y=g_KC$oR-?axTOvp1?>^rIUDZ1~p XM7uc;;H{;@1V^dafWH$;VZr|cF?5d? diff --git a/case/seeed_xaio_lid.stl b/case/seeed_xaio_lid.stl deleted file mode 100644 index 4a346979a0c5bab4fc17a5f5c893af2fe04302b5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 34284 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 EKTiwEuK)l5