OpenSCAD - scripted 3D CAD |
A common question in forum posts is "why bother", a point and click CAD program is easier to use. For me the advantages come down to these key reasons:
- Parametrization - Scripted CAD is at the core of the Thingiverse customiser and working with parameters is easy and natural to do when using a programming based approach.
- Code re-use - Useful elements of designs can be used again and again, as you would with a library of functions in a program. A change to the library can easily be cascaded down to designs which use it.
- Collaboration - The key advantage, tools like Git can be used to fork and merge the code. Many people can work on the same project in a robust way a method proven in software development.
Like everything its not perfect, I can see the following disadvantages in comparison to a point and click CAD program:
- Not intuitive to start with - If you are used to learning a program by clicking on stuff to see what happens, as I do for most programs, it can be frustrating.
- There is no simple way to import or export model files to other non scripted CAD programs other than as an .stl file - fine for 3d printing but not for people who want to use these other tools.
A preview of what the spool holder looks like mounted on the printer:
On to the example!
This worked example assumes you have downloaded and setup OpenSCAD to work on your computer. Load up OpenSCAD and save the new file "filament_holder.scad" somewhere you can find it later.
Filament Spool Holder Requirements
The first step I took was to define the requirements of the spool holder, these boiled down to:
- Accommodate spools through the full range of dimensions of those commonly used in 3D printing:
- Spool width of up to 120mm
- Spool central internal diameter of ~25mm to >50mm
- Accommodate spools weighing up to 3kg
- Be very smooth running, if using bearings then either 624 or 608
- Be simple, quick to print and attachable to the Lasercut Mendel90 frame with minimum number of fastenings
These requirements led to a long and relatively fruitless thingiverse search - I would rather not have to reinvent the wheel. Nothing met my requirements completely, but the search did confirm the basic form the filament holder would take; a simple peg like arm from the side of the printer. The initial sketch:
I have broken the design process down into a number of steps that make it easier to follow and use in your own designs. there are links within the code examples to the relevant part of the OpenScad documentation so the syntax of each function is not repeated here.
Step 1 - Define the variables
Before starting to design the object, I first defined the variables that will be used for various dimensions. This allows for quick modification later and for easily assigning a new dimension based on existing ones.
//variable defines, all in mm
//##overall spool dimensions##
max_spool_width=120;
min_spool_id=25; //id =internal diameter
spool_id_clearance=1; //minimum clearance between the spool holder and the inside of a spool
//##bearing variables##
bearing_od=13; //624ZZ bearing
bearing_id=4; //624ZZ bearing
bearing_thickness=5;
bearing_washer_thickness=0.5; //M4 washer
bearing_washer_radius=9/2; //M4 washer
bearing_clearance=1; //clearance between the bearings and the spool holder
//a set of two bearings with a washer at each end as a spacer
bearing_stack_thickness=(2*bearing_thickness)+(2*bearing_washer_thickness);
bearing_stack_wall_thickness=2; //the printed ends of a bearing stack
//the bolt to hold the stack and plastic walls together
bearing_stack_bolt_length=bearing_stack_thickness+ bearing_stack_wall_thickness*2+10;
echo("bearing_stack_bolt_length: ", bearing_stack_bolt_length);
I have chosen to echo this information so I know what length of bolt will be required to hold the bearing stack together. The variables continue:
//##filament holder variables##
min_filament_holder_id = bearing_od+bearing_clearance;
max_filament_holder_od = min_spool_id-spool_id_clearance;
filament_holder_wall_thickness= max_filament_holder_od-min_filament_holder_id;
//overall length of the filament holder less the mounting plate
filament_holder_length=max_spool_width+bearing_stack_bolt_length;
echo("filament_holder_length: ", filament_holder_length);
//##mounting plate##
fastener_clearance_radius=3.3/2;
fastener_washer_clearance_radius=8/2;
mounting_plate_thickness=8;
mounting_plate_width=min_spool_id+fastener_washer_clearance_radius;
mounting_plate_height=min_spool_id+fastener_washer_clearance_radius*3;
//##miscellaneous##
fn_resolution=100; //quality vs render time
print_clearance=0.1; //additional clearance between two printed objects.
//variable defines, all in mm
//##overall spool dimensions##
max_spool_width=120;
min_spool_id=25; //id =internal diameter
spool_id_clearance=1; //minimum clearance between the spool holder and the inside of a spool
//##bearing variables##
bearing_od=13; //624ZZ bearing
bearing_id=4; //624ZZ bearing
bearing_thickness=5;
bearing_washer_thickness=0.5; //M4 washer
bearing_washer_radius=9/2; //M4 washer
bearing_clearance=1; //clearance between the bearings and the spool holder
//a set of two bearings with a washer at each end as a spacer
bearing_stack_thickness=(2*bearing_thickness)+(2*bearing_washer_thickness);
bearing_stack_wall_thickness=2; //the printed ends of a bearing stack
//the bolt to hold the stack and plastic walls together
bearing_stack_bolt_length=bearing_stack_thickness+ bearing_stack_wall_thickness*2+10;
echo("bearing_stack_bolt_length: ", bearing_stack_bolt_length);
I have chosen to echo this information so I know what length of bolt will be required to hold the bearing stack together. The variables continue:
//##filament holder variables##
min_filament_holder_id = bearing_od+bearing_clearance;
max_filament_holder_od = min_spool_id-spool_id_clearance;
filament_holder_wall_thickness= max_filament_holder_od-min_filament_holder_id;
//overall length of the filament holder less the mounting plate
filament_holder_length=max_spool_width+bearing_stack_bolt_length;
echo("filament_holder_length: ", filament_holder_length);
//##mounting plate##
fastener_clearance_radius=3.3/2;
fastener_washer_clearance_radius=8/2;
mounting_plate_thickness=8;
mounting_plate_width=min_spool_id+fastener_washer_clearance_radius;
mounting_plate_height=min_spool_id+fastener_washer_clearance_radius*3;
//##miscellaneous##
fn_resolution=100; //quality vs render time
print_clearance=0.1; //additional clearance between two printed objects.
Step 2 - Put the framework in place.
I find it easier to break a design into logical modules and the first step is to lay out the empty modules as a framework. In this design there is the main tube, the bearing stacks and a mounting plate. Splitting it up into parts makes the design easier to adapt in the future, for example if you wanted to use a different mounting method.
//The "peg" like tube the filament reel will sit on
module main_tube(){
}
//The plate that holds the main tube to the side of the printer
module mounting_plate(){
}
//each bearing stack has two printed ends
module bearing_end(){
}
//The layout for exporting as an .stl file
module spool_holder_stl(){
}
I use OpenSCAD both to design the parts of the object and also to virtually assemble it to confirm it fits together as I imagined it prior to printing it out. To that end I want two output options - one laid out for export as a .stl file and an assembly which shows the filament spool holder with all the parts as they fit together. I adopted this method of working from Nophead's file layout for the Mendel90.
//the printed bearing ends, washers and two bearings
module bearing_stack_assembly(){
}
//assembly to show how it all goes together.
module spool_holder_assembly(){
}
if(1)
spool_holder_assembly();
else
spool_holder_stl();
The final if statement just allows for quickly choosing either to see the assembly (1) or the stl layout (0).
Starting with the main tube, fill in the framework laid out above.
//The "peg" like tube the filament reel will sit on
module main_tube(){
//peg
cylinder(h=filament_holder_length,r=max_filament_holder_od/2,
$fn=fn_resolution,center=true);
}
The main element is a cylinder, the length of the filament holder specified in the variables, with a diameter of the maximum filament holder outer diameter.
The bearings should run inside this cylinder, so the next part is the shape to cut out from the object. The "difference()" function takes all the following parts away from the first part enclosed with the curly braces "{}".
//The "peg" like tube the filament reel will sit on
module main_tube(){
difference(){
//peg
cylinder(h=filament_holder_length,r=max_filament_holder_od/2,
$fn=fn_resolution,center=true);
//cut out for bearings
translate([0,(max_filament_holder_od-min_filament_holder_id),0])
cube([min_spool_id+5,
min_filament_holder_id/2,
filament_holder_length-bearing_stack_wall_thickness*2],
center=true);
translate([0,(max_filament_holder_od-min_filament_holder_id)/2,0])
cylinder(h=filament_holder_length-bearing_stack_wall_thickness*2,
r=min_filament_holder_id/2,$fn=fn_resolution,center=true);
translate([0,(max_filament_holder_od-min_filament_holder_id/2)/2,0])
cube([min_filament_holder_id,
min_filament_holder_id/2,
filament_holder_length-bearing_stack_wall_thickness*2],
center=true);
}
}
Translate moves the parts around by the amount specified in X, Y and Z respectively. Using variables here means we can put the cutout elements exactly where they are needed in relation to the cylinder and they will scale if we change the variables to fit a different requirement.
You will notice the "#" in front of each element - that is to make them visible. They are not displayed by default since they are the absence of anything in the space they occupy. Without the "#" debug operators the cylinder with the bearing space cutout is shown
This cylinder would print fine vertically (even the lip at the top would probably bridge right), but it suffers from a design problem due to the nature of the 3d printing process. Objects are much stronger perpendicular to the layers than parallel to the layers as they can split along layer boundaries. The simple sketch below illustrates this issue:
Given the weight of the filament reels (max ~3kg) this might not be a problem but it would be better to print this horizontally. To do that we add "rotate([90,0,0])" before the difference function which causes everything after it to be rotated by 90 degrees about the X axis.
A cylinder on its side is difficult to print without support as the first 1/4 has too flat an angle. To get over this we use a truncated teardrop, an idea which was first used to print horizontal holes without support and became the RepRap logo.
module main_tube(){
}
//The plate that holds the main tube to the side of the printer
module mounting_plate(){
}
//each bearing stack has two printed ends
module bearing_end(){
}
//The layout for exporting as an .stl file
module spool_holder_stl(){
}
I use OpenSCAD both to design the parts of the object and also to virtually assemble it to confirm it fits together as I imagined it prior to printing it out. To that end I want two output options - one laid out for export as a .stl file and an assembly which shows the filament spool holder with all the parts as they fit together. I adopted this method of working from Nophead's file layout for the Mendel90.
//the printed bearing ends, washers and two bearings
module bearing_stack_assembly(){
}
//assembly to show how it all goes together.
module spool_holder_assembly(){
}
if(1)
spool_holder_assembly();
else
spool_holder_stl();
The final if statement just allows for quickly choosing either to see the assembly (1) or the stl layout (0).
Step 3 - Design the main tube
//The "peg" like tube the filament reel will sit on
module main_tube(){
//peg
cylinder(h=filament_holder_length,r=max_filament_holder_od/2,
$fn=fn_resolution,center=true);
}
The main element is a cylinder, the length of the filament holder specified in the variables, with a diameter of the maximum filament holder outer diameter.
cylinder(h=filament_holder_length,r=max_filament_holder_od/2, $fn=fn_resolution,center=true);The $fn resolution setting allows quick renders using a circle with less sides, or to increase resolution for a smoother object for printing. Since we have defined this variable at the beginning we only need to change it there to increase the speed or quality of the render.
The bearings should run inside this cylinder, so the next part is the shape to cut out from the object. The "difference()" function takes all the following parts away from the first part enclosed with the curly braces "{}".
//The "peg" like tube the filament reel will sit on
module main_tube(){
difference(){
//peg
cylinder(h=filament_holder_length,r=max_filament_holder_od/2,
$fn=fn_resolution,center=true);
//cut out for bearings
translate([0,(max_filament_holder_od-min_filament_holder_id),0])
cube([min_spool_id+5,
min_filament_holder_id/2,
filament_holder_length-bearing_stack_wall_thickness*2],
center=true);
translate([0,(max_filament_holder_od-min_filament_holder_id)/2,0])
cylinder(h=filament_holder_length-bearing_stack_wall_thickness*2,
r=min_filament_holder_id/2,$fn=fn_resolution,center=true);
translate([0,(max_filament_holder_od-min_filament_holder_id/2)/2,0])
cube([min_filament_holder_id,
min_filament_holder_id/2,
filament_holder_length-bearing_stack_wall_thickness*2],
center=true);
}
}
You will notice the "#" in front of each element - that is to make them visible. They are not displayed by default since they are the absence of anything in the space they occupy. Without the "#" debug operators the cylinder with the bearing space cutout is shown
This cylinder would print fine vertically (even the lip at the top would probably bridge right), but it suffers from a design problem due to the nature of the 3d printing process. Objects are much stronger perpendicular to the layers than parallel to the layers as they can split along layer boundaries. The simple sketch below illustrates this issue:
3D Printed objects; stronger perpendicular to layers due to layers shearing |
Given the weight of the filament reels (max ~3kg) this might not be a problem but it would be better to print this horizontally. To do that we add "rotate([90,0,0])" before the difference function which causes everything after it to be rotated by 90 degrees about the X axis.
rotate([90,0,0])
difference(){........
A cylinder on its side is difficult to print without support as the first 1/4 has too flat an angle. To get over this we use a truncated teardrop, an idea which was first used to print horizontal holes without support and became the RepRap logo.
The truncated teardrop is not part of OpenSCAD but it is available in a library written by Nophead for the Mendel90 (and no doubt from many other sources). This exposes one of the most powerful aspects of OpenSCAD - re-using code. With this teardrop library file saved in the same directory as the filament holder file, using it is as simple as adding the use statement at the beginning of the filament_holde.scad file.
use <teardrops.scad>
looking inside the "teardrops.scad" file it has a number of modules, the one we want has the syntax:
module teardrop(h, r, center, truncate = true)
So to use it, change the cylinder line to:
rotate([0,0,180]) //truncated part facing down
//use a teardrop to make it printable without support.
teardrop(filament_holder_length, max_filament_holder_od/2,true,true);
//use a teardrop to make it printable without support.
teardrop(filament_holder_length, max_filament_holder_od/2,true,true);
Finally the full module code looks like this:
//The "peg" like tube the filament reel will sit on
module main_tube(){
rotate([90,0,0])
difference(){
rotate([0,0,180]) //truncated part facing down
//use a teardrop to make it printable without support.
teardrop(filament_holder_length, max_filament_holder_od/2,true,true);
//cut out for bearings
translate([0,(max_filament_holder_od-min_filament_holder_id),0])
cube([min_spool_id+5,
min_filament_holder_id/2,
filament_holder_length-bearing_stack_wall_thickness*2],
center=true);
translate([0,(max_filament_holder_od-min_filament_holder_id)/2,0])
cylinder(h=filament_holder_length-bearing_stack_wall_thickness*2,
r=min_filament_holder_id/2,
translate([0,(max_filament_holder_od-min_filament_holder_id/2)/2,0])
cube([min_filament_holder_id
min_filament_holder_id/2,
filament_holder_length-bearing_stack_wall_thickness*2],
center=true);
$fn=fn_resolution,center=true);
}
}
Step 4 - The mounting plate
The mounting plate should position the filament spool holder on the side of the printer using 4 screws or bolts. It is desirable that a M3 socket cap screw, of a length that is already used in the Mendel90 Lasercut assembly is chosen, M3x16mm and M3x20mm are good candidates.
At its simplest this could be a cube, thick enough to hold the weight of the filament against the screws:
module mounting_plate(){
difference(){
translate([0,(mounting_plate_width-max_filament_holder_od)/2,
-(filament_holder_length+mounting_plate_thickness)/2 +0.01])
cube([mounting_plate_height
mounting_plate_width,
mounting_plate_thickness-3],center=true);
//bolt holes
for(i=[-1,1])
for(j=[-1,1])
translate([j*mounting_plate_height/2 - j*fastener_washer_clearance_radius,
i*mounting_plate_width/2 -i*fastener_washer_clearance_radius
+ (mounting_plate_width-max_filament_holder_od)/2,
-(filament_holder_length+mounting_plate_thickness)/2])
{
teardrop(100, fastener_clearance_radius,true,true);
translate([0,0,(mounting_plate_thickness-2)/2+20])
teardrop(40, fastener_washer_clearance_radius,true,true);
}
}
}
A nice way to do the 4 bolt holes is to use two nested "for loops", this allows for the same transformations about the center to be applied with sign changes to space the holes out correctly.
The cube above would probably work but it is a bit basic. Sharp corners can encourage lifting due to plastic shrinkage and smooth transitions look nicer so I made the following changes:
In order to get the rounded corners I am going to use another of Nophead's libraries from the Mendel90. Place this line at the top of the file next to the other "use" command.
use <utils.scad>
The full code for the bearing holder is below. Three things have changed, firstly the "hull" command is used to make a smooth shape by combining a cylinder and the rounded rectangle. Hull is a powerful way to make complicated objects from simple ones. In this case I have defined a cylinder the same size as the main tube to combine with the rounded rectangle of the mounting plate, this will give a smooth transition from the mounting plate to the main tube.
The rounded rectangle is defined in "utils.scad" and takes the normal arguments for a cube, along with the radius of the corner, in this case I chose 2. Finally I have cut out the areas where the washers of the fixing screws will go to ensure they hold correctly.
//The plate that holds the main tube to the side of the printer
module mounting_plate(){
$fn=fn_resolution; //smooth rounded rectangle
difference(){
hull(){
translate([0,(mounting_plate_width-max_filament_holder_od)/2,
-(filament_holder_length+mounting_plate_thickness)/2])
//1 degree rotation to compensate for the distortion due to heavy reels
rotate([1,0,0])
rounded_rectangle([mounting_plate_height,
mounting_plate_width,
mounting_plate_thickness-3],
2,center=true); //2=radius of corners
translate([0,0,
-(filament_holder_length)/2 +bearing_stack_wall_thickness/2+0.5])
cylinder(h=1, r=max_filament_holder_od/2,
$fn=fn_resolution,center=true);
}
//bolt holes
for(i=[-1,1])
for(j=[-1,1])
translate([j*mounting_plate_height/2 - j*fastener_washer_clearance_radius,
i*mounting_plate_width/2 -i*fastener_washer_clearance_radius
+ (mounting_plate_width-max_filament_holder_od)/2,
-(filament_holder_length+mounting_plate_thickness)/2 +0.01])
{
teardrop(100, fastener_clearance_radius,true,true);
translate([0,0,(mounting_plate_thickness-2)/2+20])
teardrop(40, fastener_washer_clearance_radius,true,true);
}
}
}
The $fn parameter is repeated at the beginning of the file because the rounded rectangle does not have that as an option to pass as an argument. Setting it at the beginning means it applies to all cylinders and circles within that module.
Next the main tube and base plate can be put together as one object
//The layout for exporting as an .stl file
module spool_holder_stl(){
translate([0,0,max_filament_holder_od/2]){
main_tube();
rotate([90,0,0])
translate([0,0,-0.001]) //prevent intersecting faces
mounting_plate();
}
}
There is a small translate which is used to ensure the two objects overlap, rather than having co-incident faces which could cause problems with stl export later.
Step 5 - Bearing ends
Each pair of bearings is held between two printed ends. These will hold the bearings slightly away from the tube so they can rotate freely, and also stop the filament roll from sliding off the bearings.
This is a simple short cylinder with a slightly offset hole to achieve the clearance from the filament tube
//each bearing stack has two printed ends
module bearing_end(){
difference(){
cylinder(h=bearing_stack_wall_thickness,
r=min_filament_holder_id/2-print_clearance/2,
$fn=fn_resolution,center=true);
translate([bearing_clearance,0,0]) //offset the hole by the bearing clearance
cylinder(h=bearing_stack_bolt_length+10,
r=bearing_id/2+0.15,
$ fn=fn_resolution,center=true);
}
}
difference(){
cylinder(h=bearing_stack_wall_thickness,
r=min_filament_holder_id/2-print_clearance/2,
$fn=fn_resolution,center=true);
translate([bearing_clearance,0,0]) //offset the hole by the bearing clearance
cylinder(h=bearing_stack_bolt_length+10,
r=bearing_id/2+0.15,
$ fn=fn_resolution,center=true);
}
}
In order to prevent the filament holder falling off we want a ridge on the outer bearing ends but not the inner ones. I could make two separate modules, one for each but the advantage of using scripts is that arguments can be passed to them. I have already shown this in using both built in functions and external libraries. In order to have a modules accept an argument insert the name and a default value in the module definition. In this case the bearing_end module expects an edge to be either true or false.
//each bearing stack has two printed ends
module bearing_end(edge=true){
difference(){
if(edge) //the bearing end sticks up to prevent the filament roll from coming off
hull(){
cylinder(h=bearing_stack_wall_thickness,
r=min_filament_holder_id/2-print_clearance/2,
$fn=fn_resolution,center=true);
translate([6,0,0])
cube([6,6,bearing_stack_wall_thickness],center=true);
}
else
cylinder(h=bearing_stack_wall_thickness,
r=min_filament_holder_id/2-print_clearance/2,
$fn=fn_resolution,center=true);
translate([bearing_clearance,0,0]) //offset the hole by the bearing clearance
cylinder(h=bearing_stack_bolt_length+10,
r=bearing_id/2+0.15,
$fn=fn_resolution,center=true);
}
}
Calling bearing_end(false) gives the same result as before, but bearing_end(true) gives this object:
Two of each end are needed so they are added to the required output for printing.
//The layout for exporting as an .stl file
module spool_holder_stl(){
translate([0,0,max_filament_holder_od/2]){
main_tube();
rotate([90,0,0])
translate([0,0,-0.001]) //prevent intersecting faces
mounting_plate();
}
for(i=[-1,1])
translate([i*(max_filament_holder_od+min_filament_holder_id)/2,
0,bearing_stack_wall_thickness/2]){
bearing_end(false);
translate([0,min_filament_holder_id+2,0])
rotate([0,0,90])
bearing_end(true);
}
}
difference(){
if(edge) //the bearing end sticks up to prevent the filament roll from coming off
hull(){
cylinder(h=bearing_stack_wall_thickness,
r=min_filament_holder_id/2-print_clearance/2,
$fn=fn_resolution,center=true);
translate([6,0,0])
cube([6,6,bearing_stack_wall_thickness],center=true);
}
else
cylinder(h=bearing_stack_wall_thickness,
r=min_filament_holder_id/2-print_clearance/2,
$fn=fn_resolution,center=true);
translate([bearing_clearance,0,0]) //offset the hole by the bearing clearance
cylinder(h=bearing_stack_bolt_length+10,
r=bearing_id/2+0.15,
$fn=fn_resolution,center=true);
}
}
Calling bearing_end(false) gives the same result as before, but bearing_end(true) gives this object:
//The layout for exporting as an .stl file
module spool_holder_stl(){
translate([0,0,max_filament_holder_od/2]){
main_tube();
rotate([90,0,0])
translate([0,0,-0.001]) //prevent intersecting faces
mounting_plate();
}
for(i=[-1,1])
translate([i*(max_filament_holder_od+min_filament_holder_id)/2,
0,bearing_stack_wall_thickness/2]){
bearing_end(false);
translate([0,min_filament_holder_id+2,0])
rotate([0,0,90])
bearing_end(true);
}
}
Step 6 - Modelling
At this point all the individual elements of the design are complete. Before printing however it would be good to put it all together as confirmation that it fits together.
First the bearing stacks are assembled
//the printed bearing ends, washers and two bearings
module bearing_stack_assembly(){
bearing_end(false);
translate([0,0,bearing_stack_wall_thickness+
bearing_washer_thickness*2+bearing_thickness*2])
bearing_end(true);
//Bearings and washers
%translate([bearing_clearance,0,bearing_stack_wall_thickness/2+
bearing_washer_thickness+bearing_thickness])
difference(){
union(){
for(i=[-1,1])
translate([0,0,i*bearing_thickness+i*bearing_washer_thickness/2])
cylinder(h=bearing_washer_thickness,
r=bearing_washer_radius,
$fn=fn_resolution,center=true);
cylinder(h=bearing_thickness*2,
r=bearing_od/2,
$fn=fn_resolution,center=true);
}
cylinder(h=bearing_stack_thickness+5,
r=bearing_id/2,
$fn=fn_resolution,center=true);
}
}
Note the "%" background modifier at the beginning of the bearings section. This displays that part as transparent - useful for quickly visualising areas.
Putting it all together:
//assembly to show how it all goes together.
module spool_holder_assembly(){
main_tube();
rotate([90,0,0]){
mounting_plate();
translate([0,(max_filament_holder_od-min_filament_holder_id)/2,
-(max_spool_width/2- (bearing_stack_wall_thickness+
bearing_washer_thickness*2 +bearing_thickness*2))])
rotate([0,180,-90])
bearing_stack_assembly();
translate([0,(max_filament_holder_od-min_filament_holder_id)/2,
(max_spool_width/2- (bearing_stack_wall_thickness+
bearing_washer_thickness*2 +bearing_thickness*2))])
rotate([0,0,90])
bearing_stack_assembly();
}
}
Printing
I used ABS with 2 perimeters 0.4mm layers and 50% infill which makes the holder strong enough for the 2.3kg reels we use.
Other than the printed parts you need,
For the bearings:
4 624ZZ bearings, 4 M4 washers, 2 M4x30mm bolts and 2 M4 nyloc nuts
To mount:
4 M3x20mm bolts, 4 M3 washers, 4 M3 nyloc nuts.
Variations
The first version I printed was for the large 2.3kg reels we use for production printing:
Filament Spool Holder printed out and mounted on the Lasercut Mendel90 |
The Filament Spool Holder with a large reel (2.3kg) of 3mm filament |
The advantage of making the filament holder parametric though is that only one parameter needs changing:
max_spool_width=50;
To get a shorter tube for smaller rolls of filament:
Here are some pictures of it mounted on my test printer. For these smaller rolls the bearings are not actually required and this becomes a rather over engineered peg.
The complete source code is available on github, I hope this has been useful, please leave your feedback and suggestions for improvement in the comments!
Well written Tony, this must have taken a long time to put together. Definitely something which I will take the time to work through - I tried OpenSCAD once but I found it unnerving to draw by programming and quickly got frustrated. Top marks.
ReplyDeleteAlan
Yeah it took a bit of time to "get it" as far as defining the parameters and coding the shape. I clicked for me with a more complex design; changing a dimension and the whole design updates across multiple objects - pretty cool!
Delete