No Touch Change Dispenser

Copy and paste the following code into your OpenSCAD editor:



// No Touch Change Dispenser

// Version 0.61;

////////////////////////////////////////////////////////////////////////////////////
//
//    Licence:
//
//    Creative Commons - Attribution
//
//    You may use this file in any way you wish save
//    only that every instance must include a link to 
//    http://www.half-baked-idea.co.uk/
//
////////////////////////////////////////////////////////////////////////////////////

// START of user adjustable settings

explode=0; // set to 0 for built view, 1 for printable parts

//  Uncomment just one set of coins

//  Full Sterling - width on print bed 274mm
//coins=[["£2",28.4,2.5],["£1",23.43,2.8],["50p",27.3,1.78],["20p",21.4,1.7],["10p",24.5,1.85],["5p",18,1.7],["2p",25.9,2.03],["1p",20.3,1.65]];

//  Short Sterling - width on print bed 235mm
coins=[["£1",23.43,2.8],["50p",27.3,1.78],["20p",21.4,1.7],["10p",24.5,1.85],["5p",18,1.7],["2p",25.9,2.03],["1p",20.3,1.65]];

//  Full Euro - width on print bed  - 256mm  reduce 'sideallowance' to 1.5 to fit 250mm printbed
//coins=[["€2",25.75,2.2],["€1",23.25,2.33],["50c",24.25,2.38],["20c",22.25,2.14],["10c",19.75,1.93],["5c",21.25,1.67],["2c",18.75,1.67],["1c",16.25,1.67]];

//  Short Euro - width on print bed 200mm  reduce 'sideallowance' to 1.75 to fit 200mm printbed
//coins=[["€2",25.75,2.2],["€1",23.25,2.33],["50c",24.25,2.38],["20c",22.25,2.14],["10c",19.75,1.93],["5c",21.25,1.67]];

// Short USA - width on print bed 125mm
//coins=[["25¢",24.26,1.75],["10¢",17.91,1.35],["5¢",21.21,1.95],["1¢",19.05,1.52]];

// Add new coin sets at bottom, works with coins up to 5mm thick.
// Format is: [ "Printable_Label" , diameter_mm , thickness_mm ]

towerht=100;        //  Height of coin stack (range 50 - 150)
sideallowance=2;  //  Larger is stronger but wider

cointolerance=1;   // allow coins to move freely
slidelen=80;          // Increase for large diameter coins

pushplate=10;      // Height of push plate

pushedgerad=3;   // Edge softening

$fn=50;                 //  Increase for higher curve precision
   
exp0=0;                //  Exploded spacings, ...
exp1=85;              //  ...may need...
exp2=170;            //  ...increasing if slidelen... 
exp3=50;              //  ...is changed

// END of user adjustable settings

tbary=2.5;
tbarx=5;
pinholerad=2;
pintolerance=0.25;
sepwidth=pinholerad+0.5;
slidetolerance=0.25;

bandpostrad=pinholerad;
bandpostlen=8;
bandpathradius=4;

baseheight=50;

widths=[for (v=[0:len(coins)-1]) coins[v][1] ];
maxy=sum(widths,len(widths)-1)+len(coins)*((sepwidth*2)+(2*sideallowance)+cointolerance+(2*slidetolerance))-5.5+(2*slidetolerance);
totwidth=maxy+5.5;
maxwidth=max(widths);
maxslidewid=maxwidth+cointolerance+4;

echo();
echo(str("     ",state(explode)));
echo();
echo(str("     Width on build plate=",totwidth));
echo();

thicknesses=[for (v=[0:len(coins)-1]) coins[v][2] ];
maxthick=max(thicknesses);

// one slide per denomination
for (c=[0:len(coins)-1]){
    space=sum(widths,c-1)+widths[c]/2+(((sepwidth*2)+(2*sideallowance)+cointolerance+slidetolerance*2)*c);
    translate([exp1*explode,space,0]){
        slide(coins[c]);
    }
}

// Seperate loops to make integrated parts

difference(){
    union(){
        for (c=[0:len(coins)-1]){
            space=sum(widths,c-1)+widths[c]/2+(((sepwidth*2)+(2*sideallowance)+cointolerance+slidetolerance*2)*c);
            translate([exp0*explode,space,2.25*explode]){
                slot(coins[c]);
            }
        }
    }
 // trim ends
    translate([exp0*explode-maxslidewid/2,-5.5-5,-2.25]){
        cube([slidelen,5,15]);
    }
    translate([exp0*explode-maxslidewid/2,maxy,-2.25]){
        cube([slidelen,5,15]);
    }               
}
difference(){
    union(){
        for (c=[0:len(coins)-1]){
            space=sum(widths,c-1)+widths[c]/2+(((sepwidth*2)+(2*sideallowance)+cointolerance+slidetolerance*2)*c);
            translate([exp2*explode,space,(towerht+5)*explode]){
                rotate([180*explode,0,180*explode]){
                    tower(coins[c]);
               }
            }
        }
    }
       translate([(maxwidth/2+1.5)*(explode?1:-1)+exp2*explode,0,(towerht+5)*explode]){
           rotate([0,270-180*explode,0]){
               textpane();
           }
       }

// trim ends
    translate([exp2*explode-maxwidth/2,-5.5-5,-10+(towerht-5)*explode]){
        cube([maxwidth,5,30]);
    }
    translate([exp2*explode-maxwidth/2,maxy,-10+(towerht-5)*explode]){
        cube([maxwidth,5,30]);
    }
}

base();

module base(){        
translate([-maxslidewid/2-exp3*explode,-5.5,-baseheight-2.25+(baseheight+2.25)*explode]){
    difference(){
        cube([maxslidewid*1.5,totwidth,baseheight]);

        translate([maxslidewid*1.5-9,0,0]){
            rotate([0,0,90]){
               fixrecess(baseheight*9/10);
            }
            translate([0,totwidth,0]){
                 rotate([0,0,270]){
                     fixrecess(baseheight*9/10);
                }
            }
        }

        for (c=[0:len(coins)-1]){
            slidewid=coins[c][1]+2*sideallowance+cointolerance;
            space=sum(widths,c-1)+widths[c]/2+(((sepwidth*2)+(2*sideallowance)+cointolerance+slidetolerance*2)*c);
            translate([0,space,0]){
                translate([8,-slidewid/2-sepwidth-slidetolerance+5.5,baseheight-12]){
                   cylinder(r=pinholerad,h=100);
                }
                translate([8,slidewid/2+sepwidth+slidetolerance+5.5,baseheight-12]){
                   cylinder(r=pinholerad,h=100);
               }
               translate([maxslidewid-5,-slidewid/2-sepwidth-slidetolerance+5.5,baseheight-12]){
                   cylinder(r=pinholerad,h=100);
               }
               translate([maxslidewid-5,slidewid/2+sepwidth+slidetolerance+5.5,baseheight-12]){
                   cylinder(r=pinholerad,h=100);
              }
          }
     }
}
translate([0,totwidth,0]){
    rotate([90,0,0]){
        // wide slope
         linear_extrude(height=totwidth, scale=[1.0,1.0]){
            polygon(points=[[0,0],[0,baseheight],[-maxslidewid/2,baseheight*7/8],[-maxslidewid/2,0]]);
        }
    }
}
frontrace=[[0,0],[0,baseheight*7/8],[totwidth/2-maxslidewid/2-2,baseheight*2/6],[totwidth/2-maxslidewid/2-2,0]];
difference(){
    union(){
translate([-maxslidewid*1.5-1,0,5]){  // overlap to make single part
    rotate([90,0,90]){
         linear_extrude(height=2){
            polygon(points=frontrace);
        }
        translate([0,-5,0]){
            linear_extrude(height=maxslidewid+2){
                polygon(points=frontrace);
            }           
        }
    }
}
translate([-maxslidewid*1.5-1,totwidth,5]){
    mirror([0,1,0]){
        rotate([90,0,90]){
             linear_extrude(height=2){
                 polygon(points=frontrace);
            }
            translate([0,-5,0]){
                linear_extrude(height=maxslidewid+2){
                    polygon(points=frontrace);
                }           
            }
        }
    }
}
}
        translate([-maxslidewid*1.5+7,0,0]){
            rotate([0,0,90]){
               fixrecess(baseheight*3/4);
            }
            translate([0,totwidth,0]){
                 rotate([0,0,270]){
                     fixrecess(baseheight*3/4);
                }
            }
        }
}
translate([-maxslidewid*0.5,totwidth/2-maxslidewid/2-2,0]){
    rotate([90,0,180]){
         linear_extrude(height=maxslidewid+4){
             polygon(points=[[0,0],[0,baseheight*2/6],[maxslidewid*3/2,2],[maxslidewid*3/2,0]]);
        }
    }
    translate([-maxslidewid*3/2,-2,0]){
        cube([maxslidewid*3/2,2,baseheight/6]);
        translate([0,maxslidewid+6,0]){
            cube([maxslidewid*3/2,2,baseheight/6]);
        }
    }
}
}
}

module slide(dims){
    label=dims[0];
    dia=dims[1]+cointolerance;
    thick=dims[2];
    slidewid=dia+(2*sideallowance);
    
   difference(){
       union(){
           translate([-maxslidewid/2,-slidewid/2-tbary,0]){
             cube([tbarx,slidewid+tbary*2,thick*1.2]);
          }
          //  Basic Slide
          translate([-maxslidewid/2,-slidewid/2,0]){
               cube([slidelen,slidewid,thick*1.2]);
          }
      }
      //  cut out
        cylinder(d=dia,h=thick*2);
       hull(){ //           long chamfer to seperate coins
           translate([0,0,thick*2/3]){
               cylinder(d=dia,h=thick*2);
               translate([thick*3,0,thick/2]){
                   cylinder(d=dia,h=thick*2);
               }
           }
        }
    }
    difference(){
        //  Push block
        translate([maxslidewid*1.5,-slidewid/2,thick*1.2]){
            cube([slidelen-maxslidewid*2,slidewid,pushplate-(thick*1.2)]);
        }
        //  Soften edge
        translate([slidelen-maxslidewid/2-pushedgerad,-slidewid/2,pushplate-pushedgerad]){
            difference(){
                cube([pushedgerad,slidewid,pushedgerad]);
                rotate([270,0,0]){
                    cylinder(r=pushedgerad,h=slidewid);
                }
            }
        }
        // bandpath
        translate([maxslidewid*1.5-pushplate/8,-slidewid/2,pushplate/2]){
            rotate([270,0,0]){
                cylinder(r=bandpathradius,h=slidewid);
            }
        }
        // chamfer bandpath
        translate([maxslidewid*1.5,-slidewid/2,pushplate/2]){
            rotate([270,0,45]){
                translate([0,0,-5]){
                cylinder(r=bandpathradius,h=10);
                }
            }
        }
        translate([maxslidewid*1.5,slidewid/2,pushplate/2]){
            rotate([270,0,135]){
                translate([0,0,-5]){
                cylinder(r=bandpathradius,h=10);
                }
            }
        }
        translate([maxslidewid*1.5-pushplate/8,-slidewid/2-pushplate/6,pushplate/2]){
             rotate([0,90,0]){
                 cylinder(r=bandpathradius,h=20);
             }
        }
                translate([maxslidewid*1.5-pushplate/8,slidewid/2+pushplate/6,pushplate/2]){
             rotate([0,90,0]){
                 cylinder(r=bandpathradius,h=20);
             }
        }
    }
    translate([slidelen-maxslidewid/2-10,0,pushplate]){
        rotate([0,0,90]){
            linear_extrude(height=0.5){
                text(label,size=5,halign="center",valign="center");
            }
        }
    }
}

module slot(dims){
    label=dims[0];
    dia=dims[1]+cointolerance;
    thick=dims[2];
    slidewid=dia+(2*sideallowance);
    difference(){
        union(){
            difference(){
                union(){
                    translate([-maxslidewid/2,-slidewid/2-sepwidth-slidetolerance-1,-2.25]){
                        cube([slidelen,slidewid+(sepwidth+slidetolerance+1)*2,2]); // overwide to fuse all into single plate
                    }
                    translate([-maxslidewid/2+tbarx+0.25,-slidewid/2-sepwidth-slidetolerance,-0.25]){
                        cube([slidelen-3.25,sepwidth,thick*1.2+0.5]);
                    }
                    translate([-maxslidewid/2+tbarx+0.25,slidewid/2+slidetolerance,-0.25]){
                        cube([slidelen-3.25,sepwidth,thick*1.2+0.5]);
                    }
                }
                translate([-maxslidewid/2+8,-slidewid/2-sepwidth-slidetolerance,-2.5]){
                    cylinder(r=pinholerad,h=10);
                }
                translate([-maxslidewid/2+8,slidewid/2+sepwidth+slidetolerance,-2.5]){
                    cylinder(r=pinholerad,h=10);
                }
                translate([maxslidewid/2-5,-slidewid/2-sepwidth-slidetolerance,-2.5]){
                    cylinder(r=pinholerad,h=10);
                }
                translate([maxslidewid/2-5,slidewid/2+sepwidth+slidetolerance,-2.5]){
                    cylinder(r=pinholerad,h=10);
               }
               hull(){  // finger bay
              translate([slidelen,0,-2.5]){
                  cylinder(d=dia+(2*sideallowance),h=10);
              }
              translate([slidelen-maxslidewid,0,-2.5]){
                  cylinder(d=dia,h=10);
              }
         }
    }

     translate([slidelen-maxslidewid/2-5-bandpostlen,-slidewid/2-sepwidth-slidetolerance,0]){
         cube([bandpostlen+5,sepwidth,maxthick*1.2+0.5]);
    }
    translate([slidelen-maxslidewid/2-5-bandpostlen+bandpostrad,-slidewid/2-sepwidth-slidetolerance,maxthick*1.2+0.5]){
        cylinder(r1=bandpostrad,r2=bandpostrad+0.5,h=4);
    }
    translate([slidelen-maxslidewid/2-5-bandpostlen+bandpostrad,-slidewid/2-slidetolerance-sepwidth,maxthick*1.2+0.5]){
        cube([bandpostlen,bandpostrad,4]);
        hull(){
            cube([bandpostlen,bandpostrad,1]);
            translate([2,0,3]){
                cube([bandpostlen,bandpostrad,1]);
            }
        }
    }
    translate([slidelen-maxslidewid/2-5-bandpostlen,slidewid/2+slidetolerance,0]){
         cube([bandpostlen+5,sepwidth,maxthick*1.2+0.5]);
    }
    translate([slidelen-maxslidewid/2-5-bandpostlen+bandpostrad,slidewid/2+sepwidth+slidetolerance,maxthick*1.2+0.5]){
        cylinder(r1=bandpostrad,r2=bandpostrad+0.5,h=4);
    }
    translate([slidelen-maxslidewid/2-5-bandpostlen+bandpostrad,slidewid/2+slidetolerance+0.5,maxthick*1.2+0.5]){
        cube([bandpostlen,bandpostrad,4]);
        hull(){
            cube([bandpostlen,bandpostrad,1]);
            translate([2,0,3]){
                cube([bandpostlen,bandpostrad,1]);
            }
        }    
    }
    }
    // soften edge
    translate([slidelen-maxslidewid/2-sepwidth-sideallowance,slidewid/2+sepwidth+slidetolerance,-2.5]){
        difference(){
            translate([0,-(sepwidth+sideallowance)*2,0]){
                cube([(sepwidth+sideallowance)*2,(sepwidth+sideallowance)*2,10]);
            }       
            intersection(){
            cylinder(r=sepwidth+sideallowance,h=10);
            translate([0,-(sepwidth+sideallowance)*2,0]){
                cube([(sepwidth+sideallowance)*2,(sepwidth+sideallowance)*2,10]);
            }
         }
      }
   }

   translate([slidelen-maxslidewid/2-sepwidth-sideallowance,-slidewid/2-sepwidth-slidetolerance,-2.5]){
       difference(){
           translate([0,0,0]){
               cube([(sepwidth+sideallowance)*2,(sepwidth+sideallowance)*2,10]);
           }           
           intersection(){        
             cylinder(r=sepwidth+sideallowance,h=10);
             translate([0,0,0]){
                 cube([(sepwidth+sideallowance)*2,(sepwidth+sideallowance)*2,10]);
             }
          }
       }
    }
 }
}

module tower(dims){
    label=dims[0];
    dia=dims[1]+cointolerance;
    thick=dims[2];
    slidewid=dia+(2*sideallowance);
    
    difference(){
        union(){
      translate([-maxslidewid/2,-slidewid/2-3+0.5,thick*1.2+0.25]){
        cube([maxslidewid+1,slidewid+(sepwidth+slidetolerance)*2-0.5,5-thick*1.2]);
    }        
        translate([-maxslidewid/2,-slidewid/2-3,5]){
             cube([maxslidewid+1,slidewid+(sepwidth+slidetolerance)*2,towerht]);
        }
    }
         cylinder(d=dia,h=towerht);                  //  bore
        translate([0,0,towerht]){
            cylinder(r1=dia/2,r2=dia/2+1,h=5); // flare
        }
        translate([maxslidewid/2,0,towerht/2]){
            rotate([90,0,90]){
                linear_extrude(height=2){
                    text(label,size=5,halign="center",valign="center");
                }
            }
        }
     }
    translate([-maxslidewid/2+8,-slidewid/2-sepwidth-slidetolerance,-7]){
        cylinder(r=pinholerad-pintolerance,h=15);
     }
     translate([-maxslidewid/2+8,slidewid/2+sepwidth+slidetolerance,-7]){
         cylinder(r=pinholerad-pintolerance,h=15);
     }
     translate([maxslidewid/2-5,-slidewid/2-sepwidth-slidetolerance,-7]){
         cylinder(r=pinholerad-pintolerance,h=15);
   }
     translate([maxslidewid/2-5,slidewid/2+sepwidth+slidetolerance,-7]){
         cylinder(r=pinholerad-pintolerance,h=15);
   }
}

module textpane(){
    translate([towerht*19/20,maxy-totwidth/20,0]){
        rotate([0,0,270]){
            linear_extrude(height=2){
                text("No Touch Change Dispenser",size=6,align="left",valign="center");
            }
       }
    }
    translate([towerht*4/20,maxy-(totwidth*19/20),0]){
        rotate([0,0,270]){
            linear_extrude(height=2){
                text("Free download",size=4,halign="right",valign="center");
            }
       }
    }
    translate([towerht*2/20,maxy-(totwidth*19/20),0]){
        rotate([0,0,270]){
            linear_extrude(height=2){
                text("www.half-baked-idea.co.uk/3d/",size=4,halign="right",valign="center");
            }
        }
    }
}  

module fixrecess(ht){
translate([0,0,2]){
    resize([28,14,ht]){
         cylinder(r=7,h=ht/3);
         translate([0,0,ht/3]){
             cylinder(r1=7,r2=0,h=ht*2/3);
         }
     }
     translate([7,0,-2]){
         cylinder(r=2.5,h=3);
     }
   }
}

function sum( vec, pos) =( pos<0 ?0:vec[pos]+sum(vec,pos-1));

function state(s)=(s==1?"Exploded to printable parts" : "Built view: Set explode (on line 19) to 1 for printable parts");