<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="sodnpoo.xsl" type="text/xsl"?>
<xml page="/?t=3d+printing"><a href="http://sodnpoo.com/?x=html">HTML version</a><post>
  <tag value="3d printing"/>
  <tag value="scad"/>
  <title>parametric paint shelf for clarke cwr50 metal tool board</title>
  <date>10 Jun 2017</date>
  <p>
  </p>
  <image src="/posts.assets/paint_shelf1.jpg"/>
  <p>
(<a href="https://www.thingiverse.com/thing:2376451">thingiverse</a> / <a href="https://www.thingiverse.com/apps/customizer/run?thing_id=2376451">customiser</a>)
  </p>
  <p>
Simple 3D scad model for the <a href="http://amzn.to/2sdSF6x">Clarke CWR50 tool board</a> - to hold small paint tubes. The shelves are angled back a little, so the tubes won't fall off. With some minor modifications I guess it would be useful for small tools etc as well.
  </p>
  <image src="/posts.assets/paint_shelf2.jpg"/>
  <p>
The design is fully parametric, and you can specify the number of hook perforations wide you want the shelf to be (num), the size (paint_slot_width) and spacing (paint_slot_spacing) between the centres of the paint slots. The scad code will then squeeze in as many as possible.
  </p>
  <p>
Ours were printed to be six hook perforations wide; that's widest I can print on my <a href="http://amzn.to/2rLFJn8">Wanhao i3</a>, and conveniently the longest rows on the tool board were 18 wide, so I could print three per row. The paint tubes also happen to be almost the same width as the perforations too, so there's six slots.
  </p>
  <image src="/posts.assets/paint_shelf3.jpg"/>
  <p>
The hooks that came with the board slot into the ends of the shelves. They only go in half way though, so the hook can be shared between two adjacent shelves.
  </p>
  <image src="/posts.assets/paint_shelf4.jpg"/>
  <p>
Scad code:
  </p>
  <pre>
$fn = 0 + 0;
$fs = 0.1 + 0; // HQ cylinders
$fa = 4 + 0; // HQ spheres/hulls

// number of hooks wide
num = 6; // [1:18]

// width of the slots
paint_slot_width = 14.5;
// space between the slot centres
paint_slot_spacing = 31;

// space between the hook centres
hook_spacing = 31;

shelf_height = 6;
shelf_thickness = 2;
shelf_width = hook_spacing * num;

hook_width = 8.5;
hook_depth = 34.5;
hook_height = 1;

usable_shelf_width = shelf_width-(hook_width*1.5) -1;
usable_num_slots = round(usable_shelf_width/paint_slot_spacing);

num_slots = usable_num_slots;
shelf_centre = (shelf_width/2);
holes_width = (paint_slot_spacing * (num_slots-1)) ;
holes_centre = (shelf_centre - (holes_width/2));

module paint_slot(){
    hull(){
        cylinder(r=paint_slot_width/2, h=30);
            translate([0, hook_depth/4, 0])
                cylinder(r=paint_slot_width/2, h=30);
    }    
}

rotate([-90, 0, 0]){
//rotate([0, 0, 0]){

    difference(){
        cube([shelf_width, hook_depth, shelf_height]);

        //paint slots
        translate([holes_centre, 0, -10]){
            for(i=[0:num_slots-1]){
                translate([paint_slot_spacing*i, 0, 0])
                    paint_slot();
            }
        }

        //tilt neg
        rotate([-3.3, 0, 0]){
            translate([((hook_width*1.5)/2), 0-(1/2)-10, shelf_height])
                cube([shelf_width-(hook_width*1.5), hook_depth+1, shelf_height]);
            translate([((hook_width*1.5)/2), 0-(1/2)-10, 0-shelf_thickness ])
                cube([shelf_width-(hook_width*1.5), hook_depth+1, shelf_height]);
        }

        translate([0-(hook_width/2), 0-1, (shelf_height-hook_height)/2])
            cube([hook_width, hook_depth+(1*2), hook_height]);

        translate([shelf_width-(hook_width/2), 0-1, (shelf_height-hook_height)/2])
            cube([hook_width, hook_depth+(1*2), hook_height]);
    }
}
  </pre>
  <image src="/posts.assets/paint_shelf5.png"/>
  <p>
  </p>
</post><post>
  <tag value="3d printing"/>
  <tag value="scad"/>
  <title>picam mod for rspb camera feeder housing</title>
  <date>12 May 2017</date>
  <p>
  </p>
  <image src="/posts.assets/rspb_mount_3.jpg"/>
  <p>
(<a href="http://www.thingiverse.com/thing:2314935">thingiverse link</a>)
  </p>
  <p>
This is a drop-in raspberry pi camera mount for the <a href="http://shopping.rspb.org.uk/birds-wildlife/nestboxes/nestbox-cameras/camera-feeder-housing.html">RSPB's camera feeder housing</a>. It uses the same screw and screw holes the supplied bracket uses, no modifications are required to the housing. The angle of the 'head' is adjustable, using a bolt and nut from <a href="http://www.thingiverse.com/thing:193647">Mike Mattala's nut job</a>. 
  </p>
  <p>
The camera board is attached using the screws used to hold the lense mount; they are simply removed, then fed through the back of the head, before going through the board and into the lense mount. The camera board I'm using 
is the <a href="https://www.amazon.co.uk/gp/product/B00KM6XBF8">Waveshare OV5647</a>, although the scad file is easily adjusted to suit most boards. (The official rpi foundation camera boards might need a pair of small nuts and bolts as they come with a small, glued down, mobile phone-type lense mount.)
  </p>
  <p>
The raspberry pi is slotted into two arms at the rear. Power is provided via a <a href="https://www.amazon.co.uk/gp/product/B00EYT1DWW">LM2596 based buck converter</a> board, sat on a +5v and a ground on the 40 pin header.
  </p>
  <image src="/posts.assets/rspb_mount_1.jpg"/>
  <p>
  </p>
  <image src="/posts.assets/rspb_mount_2.jpg"/>
  <p>
  </p>
  <image src="/posts.assets/rspb_cam_head.png"/>
  <p>
Scad code for the head - adjust 'lens_screw_space' as required:
  </p>
  <pre>
$fn = 0;
$fs = 0.1; // HQ cylinders
$fa = 4; // HQ spheres/hulls

cam_w = 35;
cam_d = 35;

lens_screw_space = 20;
//lens_screw_space = 18;

plate_w = cam_w;
plate_d = cam_d;
plate_h = 0.5;

screw_hole = 2;
screw_head = 4;
screw_flange = 1;
screw_h = 10 + 0.1;

lid_w = 35;
lid_d = 10;
lid_h = 1;
lid_z = 10;

tilthole = 5;

module screw(){
    cylinder(r=screw_head/2, h=screw_h);
    translate([0, 0, 0-2])
        cylinder(r=screw_hole/2, h=screw_h);    
}

module screws(){
    translate([cam_w/2, cam_d/2, screw_flange]){
        translate([lens_screw_space/2, 0, 0])
            screw();

        translate([0-(lens_screw_space/2), 0, 0])
            screw();
    }    
}

module tilt(){
    rotate([0, 90, 0])
        translate([0-(lid_z/2), plate_d/2, 0-(((cam_w*1.2)-plate_w)/2)])
            cylinder(r=tilthole/2, h=cam_w*1.2);    
}

module body(){
    hull(){
        cube([plate_w, plate_d, plate_h]);
        
        translate([(cam_w-lid_w)/2, (cam_d-lid_d)/2, lid_z-1])
            cube([lid_w, lid_d, lid_h]);
    }    
}

difference(){
    body();
    
    tilt();
    screws();
}
  </pre>
  <image src="/posts.assets/rspb_cam_base.png"/>
  <p>
Scad code for the base - if you find that the screw holes in the feeder are off centre (mine were), you can adjust 'h_offset' to shift the bracket left or right:
  </p>
  <pre>
$fn = 0;
$fs = 0.1; // HQ cylinders
$fa = 4; // HQ spheres/hulls

block_w = 35;
block_h = 25;

slot_base_extra_d = 26;

base_w = 55;
//base_d = 40;
base_d = 40 + 26;
base_h = 5;

bracket_h = 36;
bracket_d = 10;
bracket_w = block_w + (2 * 6.5);

tilthole = 5;
tilthole_l = base_w;

mount_hole_space = 40;
mount_hole_from_edge = (base_w - mount_hole_space ) /2;
mount_hole_screw_head = 10;
mount_hole_screw = 5;
mount_hole_from_end = 15;

h_offset = 0; //offet the bracket, if the holes are off centre

slot_w = 56.5;
slot_d = 1.5;
slot_h = 85;

holder_w = slot_w + 4;
holder_d = slot_d + 4;
holder_h = 26;

bottom_h = 5;

chopout_w = slot_w - 2;
chopout_d = holder_d * 2;
chopout_h = holder_h + 0.1;

module pislot(){
    difference(){
        cube([holder_w, holder_d, holder_h+bottom_h]);

        translate([(holder_w-slot_w)/2, (holder_d-slot_d)/2, bottom_h])
            cube([slot_w, slot_d, slot_h]);

        translate([(holder_w-chopout_w)/2, (holder_d-chopout_d)/2, bottom_h])
            cube([chopout_w, chopout_d, chopout_h]);
    }
}

module mount_hole(){
    translate([0, 0, 1.5])
        cylinder(h=100, r=mount_hole_screw_head/2);
    translate([0, 0, -1])
        cylinder(h=100, r=mount_hole_screw/2);    
}

module mount_holes(){
    translate([0, base_d-mount_hole_from_end, 0]){
        translate([mount_hole_from_edge, 0, 0])
            mount_hole();
        
        translate([base_w-mount_hole_from_edge, 0, 0])
            mount_hole();        
    }
}

module base(){
    difference(){
        cube([base_w, base_d, base_h]);
        mount_holes();
    }    
}

module tilt_bracket(){
    difference(){
        translate([((base_w-bracket_w)/2)+h_offset, 0, 0])
            cube([bracket_w, bracket_d, bracket_h]);

        translate([((base_w-block_w)/2)+h_offset, 0-(block_w/4), bracket_h-block_h+0.1])
            cube([block_w, block_w, block_h]);
            
        rotate([0, 90, 0])
            translate([0-bracket_h+tilthole, bracket_d/2, 0])
                cylinder(r=tilthole/2, h=tilthole_l);
    }    
}

translate([(holder_w-base_w)/2, 0, 0]){
    base();
    translate([0, slot_base_extra_d, 0])
        tilt_bracket();
}
pislot();
  </pre>
  <p>
  </p>
</post><post>
  <tag value="3d printing"/>
  <tag value="scad"/>
  <title>picam and generic ir array holder</title>
  <date>27 Sept 2015</date>
  <p/>
  <image src="/posts.assets/picam_irarray_birdbox1.jpg"/>
  <p>
Before the new bird box goes up, it needs a camera so we can monitor any nesting activity. I like to use the raspberry pi and their camera boards; they're cheap, highly customisable (a full Linux is a very useful thing) and the rpi2 is fast enough to live stream the video.
  </p>
  <p>
The box has only a small hole for the birds to enter through and will be pretty dark most of the time. The 'NoIR' version on the picam is used along with a very cheap, generic, doughnut-shaped, CCTV IR LED array to deal with the lack of light. (The LED array should also provide a little extra warmth for the birds - and bugs.)
  </p>
  <image src="/posts.assets/picam_irarray_birdbox3.png"/>
  <p>
The scad code itself is split into three modules: slidein_picam(), irholder() and bracket(). Hopefully this will make things easy when I inevitably want to install another picam elsewhere. This is just the IR holder and slide in module, with just a picam installed:
  </p>
  <image src="/posts.assets/picam_irarray_birdbox2.jpg"/>
  <p>
The IR array is a very snug fit and is held in place by the small amount of springiness in the two left/right 'lobes' - to install mine I needed to slightly bend the lobes out, which gives it a good, solid grip.
  </p>
  <image src="/posts.assets/picam_irarray_birdbox4.jpg"/>
  <p>
Finally, the bracket is a simple 'L' shape, with a 45 degree counter sunk screw hole, and two short forks that fit into grooves already cut in the bird box (in the attached scad and stl I've set them to zero length as I'm imagining a flat surface is of more use to most people).
  </p>
  <p>
Scad file <a href="/posts.assets/picam_birdbox.scad">here</a>.
  </p>
  <p>
STL file <a href="/posts.assets/picam_birdbox.stl">here</a>.
  </p>
</post><post>
  <tag value="3d printing"/>
  <tag value="scad"/>
  <title>parametric pole clamp</title>
  <date>31 May 2015</date>
  <p>
  (Update: <a href="http://www.thingiverse.com/apps/customizer/run?thing_id=857569">Thingiverse customiser</a>.)
  </p>
  <p/>
  <image src="/posts.assets/parametric_pole_clamp1.jpg"/>
  <p>
    I put this openscad design together to allow me to mount some of our wildlife cameras on the same pole that the bird feeders hang from. It's been through a few iterations but this final(?) version - printed with 50% infill - is able to take the weight of a fat pigeon on the other end of the 13mm x 500mm horizontal pole. (Image of early versions at the bottom of this post.)
  </p>
  <image src="/posts.assets/parametric_pole_clamp2.png"/>
  <p>
    The code is highly parametric and should be suitable for a wide range of pole, bolt and nut (either square or hex, with captive holes) sizes. The hinge code is taken from benjaminedwardmorgan's <a href="http://www.thingiverse.com/thing:628781"> parametric hinge</a>. It opens to ~270 degrees; the number of hinges will be calculated automatically based on the height.
  </p>
  <p>
    The code to generate the horizontal pole and tabs (pole_with_tabs() and pole_with_tabs_neg()) has been split into it's own modules so I can easily attach other objects to the same pole - it's my first attempt at a non-trivial openscad module and if I'm honest, usage of it feels a little clunky; I'm sure there must be a better way to deal with removing the negative image.
  </p>
  <image src="/posts.assets/parametric_pole_clamp3.jpg"/>
  <p>
    The available parameters are:
    <ul>
      <li>clamp_height - height of the clamp part</li>
      <li>pole_diam - vertical pole diameter</li>
      <li>screw_hole_diam - diameter of the screw holes</li>
      <li>screw_recess_diam - diameter of the screw head/nut recess</li>
      <li>nut_type -  number of faces the nut has (4=square head, 6=hex)</li>
      <li>horiz_pole_diam - the diameter of the horizontal pole</li>
    </ul>
    Expect to tweak your tolerences a little if you need things to be tightly held.
  </p>
  <pre>
$fn = 0;

//$fs = 0.1; // HQ cylinders
//$fa = 4; // HQ spheres/hulls
render_hinges = true;

//$fs = 2; // default
//$fa = 12; // default
//render_hinges = false;

clamp_height = 30;
pole_diam = 25 +0.5;
screw_hole_diam = 4.5;
screw_recess_diam = 9;
nut_type = 4; // 4=square, 6=hex
horiz_pole_diam = 13 +0.2;

hinged_pole_clamp(
  height=clamp_height,
  hole_diam=screw_hole_diam,
  hole_recess_diam=screw_recess_diam,
  horiz_diam=horiz_pole_diam,
  nut_type=nut_type,
  pole_diam=pole_diam);


module hinged_pole_clamp(
    height,
    hole_diam,
    pole_diam,
    hole_recess_diam,
    horiz_diam,
    horiz_tab_angle=40,
    horiz_thick=3,
    nut_type=6
){
  hinge_fill_x = 23.6; //hardcoded to fit the hinge footprint
  hinge_fill_y = 20;
  hinge_fill_z = height;
  hole_r = hole_diam/2;
  pole_r = pole_diam/2;
  hole_recess_r = hole_recess_diam/2;

  hpole_r = horiz_diam/2;

  half_space = 0.5; // gap between the two halfs
  half_width = pole_diam * 1.2;
  half_depth = pole_diam * 0.6;

  flap_width = 1;
  flap_height = hole_recess_diam*1.5;

  hinge_r1 = 5;
  num_hinges = clamp_height/(hinge_r1*2) - 1;

  difference (){

    union(){


      //one half
      hull(){
        translate([
            hinge_fill_x,
            0-(half_depth-((hinge_fill_y+half_space)/2)),
            0])
            cube(size=[half_width*0.8, half_depth, hinge_fill_z]);

        translate([
            hinge_fill_x+(half_width*0.8),
            (0-(half_depth-((hinge_fill_y+half_space)/2)))+half_depth-flap_width,
            0])
            cube(size=[
              (half_width*0.2)+(hole_recess_diam*1.5),
              flap_width,
              hinge_fill_z
            ]);

      }

      difference(){
        hull(){
          translate([
            hinge_fill_x,
            0-(half_depth-((hinge_fill_y+half_space)/2)),
            0])
              cube(size=[half_width*0.8, half_depth, hinge_fill_z]);

          translate([
              hinge_fill_x,
              0-(pole_diam/2)+(horiz_thick)-(hpole_r),
              height/2])
            pole_with_tabs_neg(
              width=half_width*0.8,
              pole_r=hpole_r,
              pole_thick=horiz_thick,
              hole_diam=screw_hole_diam,
              tab=false,
              tab_angle=horiz_tab_angle);
        }

        translate([
            hinge_fill_x-(pole_diam*0.1),
            0-(pole_diam/2)+(horiz_thick)-(hpole_r),
            height/2])
          pole_with_tabs_neg(
            width=half_width*0.9,
            pole_r=hpole_r,
            pole_thick=horiz_thick,
            hole_diam=screw_hole_diam,
            tab=true,
            tab_angle=horiz_tab_angle);

      }
      //hinge fill
      translate([0, 0, 0])
          cube(size=[hinge_fill_x, hinge_fill_y+half_space, hinge_fill_z]);

      //the other half
      hull(){
        translate([
          hinge_fill_x, (0-(half_depth-((hinge_fill_y+half_space)/2)))+half_depth+half_space,
          0
        ])
          cube(size=[half_width*0.8, half_depth, hinge_fill_z]);

        translate([
          hinge_fill_x+(half_width*0.8),
          (0-(half_depth-((hinge_fill_y+half_space)/2)))+half_depth+half_space,
          0
        ])
          cube(size=[
            (half_width*0.2)+(hole_recess_diam*1.5),
            flap_width,
            hinge_fill_z
          ]);
      }

      translate([
          hinge_fill_x,
          //0-(hinge_fill_y/2)-(hinge_fill_y-half_depth)+(horiz_thick/2),
          0-(pole_diam/2)+(horiz_thick)-(hpole_r),
          height/2])
        pole_with_tabs(
          width=half_width*0.8,
          pole_r=hpole_r,
          pole_thick=horiz_thick,
          hole_diam=screw_hole_diam,
          hole_recess_diam=screw_recess_diam,
          nut_type=nut_type,
          tab_angle=horiz_tab_angle);

    }

    translate([
        hinge_fill_x+(half_width*1)+(hole_recess_diam*0.75),

        (0-(half_depth-((hinge_fill_y+half_space)/2)))+half_depth+half_space,
        height/2]){

      rotate(a=90, v=[1,0,0]){
        cylinder(h=pole_diam*1.5, r=hole_r, center=true);

        translate([0,0,0+(half_depth/2)+3])
          cylinder(h=half_depth, r=hole_recess_r, center=true, $fn=nut_type);

        translate([0,0,0-(half_depth/2)-3])
          cylinder(h=half_depth, r=hole_recess_r, center=true);
      }
    }

    //pole hole
    translate([hinge_fill_x+(half_width/2), (hinge_fill_y+half_space)/2, -(((height*1.1)-hinge_fill_z)/2)]) {
      rotate(a=90, v=[0,0,0])
        cylinder(h=(height*1.1), r=pole_r);
    }

    //hinges
    if(render_hinges)
      translate([10, (hinge_fill_y+(half_space*2))/2 ,0])
        rotate(a=(-45/2), v=[0,0,1])
          vertical_hinge_negative(theta0=45, height=(hinge_fill_z/num_hinges), n=num_hinges, r1=hinge_r1);

  }
}

/*
* tol - the smallest distance allowable between interlocking parts of your 3d printer. This gap is the
vertical (and horizontal) distance between the cones inside the hinge and is also the diameter and height of the
small support structure between hinge elements
* r1 - the outer radius of the hinge. the surface of your part should not be farther away from the center of
the hinge than this disntace.
* r2 - the furthest radius from the hinge where material is removed from the part.
* height - the height of each hinge element. The total height of the hinge is n*height. (the cut will extent
beyond this distance by height/2 on both sides. The part where you are creating the hinge should have a height
of n*height) the height must be greater than 2*r1
* n - the number of hinge elements. One hinge element is divided between the top and bottom.
* theta0 - the angle at which the hinge is printed
* theta1 - the internal angle formed when the hinge is turned to its limit in one direction (the x- part of the
hinge_test_1 example when rotated clockwise as viewed from above)
* theta2 - the internal angle formed when the hinge is turned to its limit in the opposite direction
*/
module vertical_hinge_negative(tol=0.5,r1=5,r2=15,height=15,n=2,theta0=180,theta1=45,theta2=45) {

    arm_width=2*r1;
    union() {
        for(i=[0:n])
            translate([0,0,(i-0.5)*height])
                difference() {

                    //cone between hinges and cuts around the hinge
                    rotate_extrude()
                        polygon([[r1,0],[r1,height],[tol/2,height-r1+tol/2],
                                [tol/2,height-r1+1.5*tol],[r1,height+tol],
                                [r2,height+tol],[r2,0]]);


                    //exclude a rectangular shape for the arm the connects the hinge to the body
                    rotate((i%2)*theta0)
                        difference() {
                            translate([0,-arm_width/2,-height])
                                cube(size=[r2*2,arm_width,height*2]);

                            translate([0,0,height-r1])
                                cylinder(r1=0,r2=height,h=height);
                        }

                    //exclude a triangular shape that limits the motion of the arms on the side of the hinge
                    for(i=[0,1])
                        mirror([0,i,0])
                            rotate(-i*theta0)
                                translate([0,0,-tol])
                                    linear_extrude(height=height+3*tol)
                                        intersection() {
                                            circle(r=2*r2);

                                            rotate(theta0+180+theta2)
                                                translate([0,r2*3+arm_width/2+tol])
                                                    square(size=[r2*6,r2*6],center=true);

                                            rotate(theta0-theta1)
                                                translate([0,r2*3+arm_width/2+tol])
                                                    square(size=[r2*6,r2*6],center=true);

                                            rotate(theta0)
                                                translate([r2*3,0])
                                                    square(size=[r2*6,r2*6],center=true);
                                        }
            }
       }
}




//*********************************************************

module pole_with_tabs_neg(width, pole_r, pole_thick, hole_diam, tab=false, tab_angle=0, gap=1){
  rotate(a=90, v=[0,1,0]){
    cylinder(h=width, r=pole_r+pole_thick);
  }

  if(tab==true){
    // screw hole in tab
    rotate(a=tab_angle, v=[1,0,0])
      translate([width/2,
                 0,
                 pole_r+(pole_thick)+hole_diam ]) {
        // tab gap
        cube([width*1.1, gap, (hole_diam*2)+(pole_thick*3)], center=true);
      }
  }
}

module pole_with_tabs(width, pole_r, pole_thick, hole_diam, hole_recess_diam, nut_type=6, tab_angle=0, gap=1){
  hole_r = hole_diam/2;
  difference(){
    union(){
      rotate(a=90, v=[0,1,0]){
        cylinder(h=width, r=(pole_r+pole_thick)*1.01);
      }

      // tab block
      hull(){
        rotate(a=90, v=[0,1,0]){
          cylinder(h=width, r=(pole_r+pole_thick)*1.01);
        }
        rotate(a=tab_angle, v=[1,0,0])
          translate([width/2, 0, ((hole_recess_diam)+(pole_thick*2)+pole_r)/2]){
            cube([
              hole_recess_diam,
              (pole_thick*2)+gap,
              (hole_recess_diam)+(pole_thick*2)+pole_r],
              center=true);
          }
        }
    }

    // pole hole
    translate([0-(width*0.5), 0, 0])
      rotate(a=90, v=[0,1,0]){
        cylinder(h=width*2.0, r=pole_r);
      }

    // screw hole in tab
    rotate(a=tab_angle, v=[1,0,0])
      translate([width/2,
                 0,
                 pole_r+(pole_thick)+(hole_recess_diam/2) ]) {

        // screw hole
        rotate(a=90, v=[1,0,0]){
          cylinder(h=pole_r*3, r=hole_r, center=true);

          //nut/screw recesses
          translate([0, 0, 0+(pole_r/2)+(pole_thick+gap)]){
            cylinder(h=pole_r, r=hole_recess_diam/2, center=true);
          }
          translate([0, 0, 0-(pole_r/2)-(pole_thick+gap)]){
            cylinder(h=pole_r, r=hole_recess_diam/2, center=true, $fn=nut_type);
          }
        }

        // tab gap
        cube([width*1.1, gap, (hole_recess_diam*2)+(pole_thick*3)], center=true);
      }
  }

}
  </pre>
  <p>
  Early versions; too flimsy, couldn't take the weight of the fat pigeons:
  </p>
  <image src="/posts.assets/parametric_pole_clamp4.jpg"/>
</post><post>
  <tag value="3d printing"/>
  <tag value="scad"/>
  <title>parametric pole mount bird spikes</title>
  <date>11 Apr 2015</date>
  <p/>
  <image src="/posts.assets/parametric_pole_mount_bird_spikes1.jpg"/>
  <!--
  <p>
  (Update: <a href="http://www.thingiverse.com/apps/customizer/run?thing_id=758991">Thingiverse customiser</a>.)
  </p>
  -->
  <p>
Fat pidgeons kept disturbing my carefully positioned <a href="/birdcam/">birdcams</a>. To disuade them from landing on the most sensitive places I've knocked up some parametric clip on spikes.
  </p>
  <image src="/posts.assets/parametric_pole_mount_bird_spikes2.png"/>
  <p>
The available knobs to twiddle are:
<ul>
  <li>pole_dia - diameter of the pole</li>
  <li>pole_thick - thickness around the pole (3mm)</li>
  <li>pole_h - height of the pole clip (10mm)</li>
  <li>spike_l - spike length (60mm)</li>
  <li>spike_h - spike height (2mm)</li>
  <li>spike_w - spike width (3mm)</li>
</ul>
The clip part is pretty much the same as my <a href="/posts.xml/parametric_pole_cable_clip.xml">cable clip</a>.
  </p>
  <p>
Thingiverse customiser <a href="http://www.thingiverse.com/apps/customizer/run?thing_id=766818">here</a>.
  </p>
  <pre>
spike_l = 60; // spike length
spike_h = 2;  // spike height
spike_w = 3;  // spike width

pole_dia = 13;  // diameter of the pole
pole_thick = 3; // thickness of the clip
pole_h = 10;    // height of the clip

$fn = 48;

pole_r = pole_dia/2;

difference (){

  union(){
    translate([0-(spike_w/2), 0, 0]){

      rotate(a=-45, v=[0,0,1])
        cube([spike_w, spike_l, spike_h], center=false);

      rotate(a=-22.5, v=[0,0,1])
        cube([spike_w, spike_l, spike_h], center=false);

      cube([spike_w, spike_l, spike_h], center=false);

      rotate(a=22.5, v=[0,0,1])
        cube([spike_w, spike_l, spike_h], center=false);

      rotate(a=45, v=[0,0,1])
        cube([spike_w, spike_l, spike_h], center=false);
    }

    cylinder(r=pole_r+pole_thick, h=pole_h);
  }

  translate([0, 0, 0-(pole_h*0.1) ]){
    cylinder(r=pole_r, h=pole_h*1.2);

    translate([0, 0-pole_r-(pole_thick*2), 0])
      cylinder(r=pole_r+pole_thick, h=pole_h*1.2);
  }
}
  </pre>
</post><post>
  <tag value="3d printing"/>
  <tag value="scad"/>
  <title>parametric pole cable clip</title>
  <date>9 Apr 2015</date>
  <p/>
  <image src="/posts.assets/parametric_pole_cable_clip1.jpg"/>
  <p>
  (Update: <a href="http://www.thingiverse.com/apps/customizer/run?thing_id=758991">Thingiverse customiser</a>.)
  </p>
  <p>
For another project I needed to run various cables to some pole mounted kit. The poles are two different diameters, so I put together this parametric design so I would only need one model.
  </p>
  <image src="/posts.assets/parametric_pole_cable_clip3.png"/>
  <p>
The available knobs to twiddle are:
<ul>
  <li>pole_dia - diameter of the pole</li>
  <li>pole_thick - thickness around the pole (3mm)</li>
  <li>pole_h - height of the print (5mm)</li>
  <li>clip_thick - thickness of the cable clip part (2mm)</li>
  <li>clip_depth - depth of the clip space</li>
</ul>
Hopefully only the pole diameter needs to be changed; 3mm around the pole seems to hold firmly and 2mm for the clip gives enough flexibility to easily pop cables in and out. If the cables are fat then the clip depth can be increased as required.
  </p>
  <pre>
pole_dia = 24.5;
pole_r = pole_dia/2;
pole_thick = 3;
pole_h = 5;
clip_depth = 10;
clip_thick = 2;

$fn = 96;

clip_depth2 = clip_depth + pole_r;

difference (){

  union(){
    translate([pole_r, 0, 0]){
      cube([clip_thick, clip_depth2, pole_h]);
      
      translate([0+1, clip_depth2, 0]){
        rotate(a=180, v=[0,0,1]){
          cube([(pole_r*2), clip_thick, pole_h]);
          
          translate([(pole_r*2), 0, 0]){
            cube([clip_thick, clip_depth2/2, pole_h]);
          }
        }
      }      
    }
    
    cylinder(r=pole_r+pole_thick, h=pole_h);
  }

  translate([0, 0, 0-(pole_h*0.1) ]){
    cylinder(r=pole_r, h=pole_h*1.2);
    
    translate([0, 0-pole_r-(pole_thick*2), 0])
      cylinder(r=pole_r+pole_thick, h=pole_h*1.2);
  }
}
  </pre>
  <image src="/posts.assets/parametric_pole_cable_clip2.jpg"/>
  <p/>
  <image src="/posts.assets/parametric_pole_cable_clip4.jpg"/>
</post><post>
  <tag value="3d printing"/>
  <tag value="scad"/>
  <title>parametric tool rack for keyhole shelving</title>
  <date>22 Mar 2015</date>
  <p>
  </p>
  <image src="/posts.assets/tool_rack_1.png"/>
  <p>
(Update: uploaded to <a href="http://www.thingiverse.com/thing:735436">thingiverse</a> and <a href="http://www.thingiverse.com/apps/customizer/run?thing_id=735436">customiser</a>.)
  </p>
  <p>
A couple of months ago I bought a <a href="https://reprappro.com/shop/reprap-kits/huxley-duo-kit/">Reprap 3D printer</a>, and to make space for it in the lab I also brought a bunch of <a href="http://www.amazon.co.uk/gp/product/B00E0J7O7Y">keyhole shelving units</a>. For a while I'd been thinking it would be nice to print a simple hook that would fit the keyholes and while browsing thingiverse I found <a href="http://www.thingiverse.com/thing:15515">Timmytool's parametric hook</a>. Now I had somewhere to hang my favourite pair of pliers, but the hook was no good for my favourite screwdriver :)
  </p>
  <p>
The script I put together is based on Timmytool's scad file on thingiverse (and still mentions the 'hook' - I was being lazy and haven't unpicked all the original wedge logic) and configuring the keyhole dimensions is still the same:
    <ul>
      <li>key_big - diameter of the large round part of the key hole</li>
      <li>key_small - diameter of the small offshoot from the main key cylinder</li>
      <li>key_spacing - distance from one key hole to the same point in the next key hole</li>
      <li>key_thickness - thickness of the material the key holes are cut from</li>
    </ul>
Additionally, to configure the shelf and holes:
    <ul>
      <li>shelf_width - width of the 'shelf', centred around the keyhole</li>
      <li>shelf_hole_radius - radius of the holes</li>
      <li>num_holes - the number of holes</li>
    </ul>
The script will attempt to calculate the depth of the shelf and an even spacing between the holes.
  </p>
  <image src="/posts.assets/tool_rack_2.jpg"/>
  <p>
shelf_width=100, shelf_hole_radius=6, num_holes=4
  </p>
  <image src="/posts.assets/tool_rack_3.jpg"/>
  <p>
shelf_width=100, shelf_hole_radius=3, num_holes=8
  </p>
  <image src="/posts.assets/tool_rack_4.jpg"/>
  <p>
  </p>
  <pre>
//width of the shelf
shelf_width = 100;
//radius of the holes
shelf_hole_radius = 3;
//number of holes
num_holes = 8;


//diameter of the large round part of the key hole,make smaller then real (for clearances)
key_big = 11;
//diameter of the small offshoot from the main key cylinder,make smaller then real (for clearances)
key_small = 6;

//distance from one key hole to the same point in the next key hole, make slightly bigger then real (for clearances)
key_spacing = 39;
//thickness of the material the key holes are kut out of, make slightly bigger then real (for clearances)
key_thickness = 1.75;

//thickness of lugs and support bar
support_thickness = 4;

hook = 10;

//calculated
spacer = ((shelf_width - (shelf_hole_radius * 2 * num_holes)) / num_holes) / 2;
poke = (shelf_hole_radius*2)+hook;
hookStart = support_thickness*2+key_thickness;
angle = atan ( hook / poke);
hype = poke + hook;
KBR = key_big/2;
KSR = key_small/2;

module wedge()  {
	translate([0,-key_small,0]) difference() {
		cube([poke,key_small,hook]);
		rotate(a=[0,-angle,0])translate([0,-1,0])cube([hype,key_small+2,hook]);
	}
}

module betterjoints() {
	intersection(){
		translate([0,-KSR,0])cube([key_spacing,key_small,support_thickness*2+key_thickness]);
		cylinder(h= support_thickness*2+key_thickness ,r1 = KBR , r2 = KBR,$fn=36);
	}
}

translate([-KBR- key_spacing/2,-KBR,0]) {		//to centre item on the build platform

  difference() {
    //shelf
    translate([KBR, KBR - (shelf_width/2), hookStart]) {
	    cube([hook/2, shelf_width, poke]);
    }

    //holes
    for ( i = [1 : num_holes ] ) {
      translate([
	      (KBR/2)-(hook/2), 
	      KBR - (shelf_width/2) + (shelf_hole_radius + spacer)*(i *2-1), 
	      hype-(poke/2)+(key_small/2)]) {
	
	      rotate([0, 90, 0]) {
		      #cylinder(h = hook*2, r = shelf_hole_radius);
	      }
      }  
    }
  }


  translate([KBR,KBR - KSR,hookStart]) {		//support bar making and wedge
    translate([poke,0,0])rotate(a=[0,0,180]) wedge();
    translate([0,0,-support_thickness]) cube([key_spacing,key_small,support_thickness]);
  }

  translate([KBR,KBR,0]) {								//post 1
	  cylinder(h= hookStart + poke, r1 = KSR ,r2 = KSR,$fn=36);
	  cylinder(h= support_thickness ,r1 = KBR , r2 = KBR,$fn=36);
	  betterjoints();
	  translate([key_spacing,0,0]){						//post 2
		  cylinder(h= hookStart, r1 = KSR ,r2 = KSR,$fn=36);
		  cylinder(h= support_thickness ,r1 = KBR , r2 = KBR,$fn=36);
		  betterjoints();
		  }
	  }
}
  </pre>
</post></xml>
