276 lines
11 KiB
OpenSCAD
276 lines
11 KiB
OpenSCAD
// --------------------------------------------------------------------
|
|
// A collection of useful modules to create Fischertechnik parts,
|
|
// mainly grooves, holes and pins to be added or substracted
|
|
// --------------------------------------------------------------------
|
|
// Please be aware that OpenSCAD approximates the size of a hole by
|
|
// using a polygon according to the $fn variable. The corner points of
|
|
// the polygon are lying on the circle. Thus the resulting hole is
|
|
// always smaller than the diameter of the hole! Increasing the $fn
|
|
// variable helps but increases calculation time. The best is to try
|
|
// out the size and adopt the settings accordingly. It does not help
|
|
// to size the final parts in the slicer, because all of the part will
|
|
// be resized, not only the hole!
|
|
// See https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Other_Language_Features#Circle_resolution:_$fa,_$fs,_and_$fn
|
|
// for details.
|
|
|
|
// Constants used throughout the fischertechnik files. Although all
|
|
// values in OpenSCAD are constants technically spoken, these are some
|
|
// kind of special. They define standard values used everywhere and
|
|
// changing them might influence how a part is redered and exported
|
|
// to the final stl file for printing.
|
|
|
|
// The standard grid size of fischertechnik parts is 15 mm. Most
|
|
// parts fit into that grid.
|
|
FT_GRID_SIZE = 15;
|
|
// The basic block has the same size as the grid. The constant name
|
|
// is just for convinience
|
|
BASIC_BLOCK_SIZE = FT_GRID_SIZE;
|
|
// Half of the block size is used quite often, so it has its own
|
|
// constant
|
|
BASIC_BLOCK_HALF = BASIC_BLOCK_SIZE / 2;
|
|
//
|
|
WALL_THICKNESS = 2;
|
|
// The Length of the groove is the same as the grid/basic block size.
|
|
GROOVE_LENGTH = FT_GRID_SIZE;
|
|
|
|
// For values from different people see:
|
|
// https://forum.ftcommunity.de/viewtopic.php?f=38&t=3709
|
|
|
|
// The radius of a groove, makes a diameter of 4.5 mm
|
|
// GROOVE_RADIUS = 2.25;
|
|
// GROOVE_DIAMETER = GROOVE_RADIUS * 2;
|
|
GROOVE_RADIUS = 2.1;
|
|
GROOVE_DIAMETER = GROOVE_RADIUS * 2;
|
|
|
|
GROOVE_CENTER = 2.4;
|
|
GROOVE_BREAKTHROUGH = 3.0;
|
|
|
|
FLAT_GROOVE_OFFSET = 0.6;
|
|
|
|
PIN_DIAMETER = 4;
|
|
PIN_BASE_WIDTH = 3;
|
|
// PIN_BASE_LENGTH = 1.2;
|
|
PIN_BASE_LENGTH = 1.0;
|
|
|
|
PLATE_HOLE_DIAMETER = 4.2;
|
|
PLATE_BREAKTHROUGH = 3.2;
|
|
PLATE_HOLE_CORRECTION = 0.8;
|
|
PLATE_CUTOFF_HEIGHT = 2.8;
|
|
|
|
// those settings work for the U-girder,
|
|
// but not for the base plate where
|
|
// PLATE_CO_TOP_LENGTH is too long!
|
|
PLATE_CO_TOP_WIDTH = 3.0;
|
|
PLATE_CO_TOP_LENGTH = 6.0;
|
|
PLATE_CO_BOTTOM_WIDTH = 4.3;
|
|
PLATE_CO_BOTTOM_LENGTH = 4.3;
|
|
PLATE_CO_CIRCLE_DIAMETER = 4.1;
|
|
PLATE_CO_CIRCLE_OFFSET = 0.2;
|
|
|
|
EYELET_HEIGHT = 2.5;
|
|
|
|
|
|
MANIFOLD_CORRECTION = 0.1;
|
|
|
|
$fn=104;
|
|
|
|
// --------------------------------------------------------------------
|
|
// part for cutting out a clip axle hole
|
|
// --------------------------------------------------------------------
|
|
module clip_axle_hole(length = BASIC_BLOCK_HALF, diameter = PLATE_HOLE_DIAMETER, thickness = 2.7, hor_cutout = 0)
|
|
{
|
|
cliplen_without_dome = 5;
|
|
intersection() {
|
|
cylinder(length + MANIFOLD_CORRECTION, d = diameter, center = true);
|
|
cube([diameter, thickness, length + MANIFOLD_CORRECTION], center = true);
|
|
}
|
|
if (hor_cutout != 0) {
|
|
// position the horizontal cutout in a way that it is 5mm from the top
|
|
// so that the cone part of the axle can get some grip
|
|
translate([0,0, -(length - diameter) / 2 + cliplen_without_dome])
|
|
intersection() {
|
|
cylinder(diameter + MANIFOLD_CORRECTION, d = hor_cutout, center = true);
|
|
cube([hor_cutout + MANIFOLD_CORRECTION, thickness, diameter], center = true);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
// A round groove to be substracted from other solids
|
|
// Optionally with a cube on each end of the groove
|
|
// The groove is centered on x and the z axis while it is slightly
|
|
// moved to a negative y value
|
|
// For the cutout rotate, translate and difference the groove
|
|
// --------------------------------------------------------------------
|
|
module round_groove(len = GROOVE_LENGTH, endcube=0)
|
|
{
|
|
// although the union is implicit, it doesn't do any harm and
|
|
// handles the groove as an entity
|
|
union()
|
|
{
|
|
// first, the groove itselve
|
|
translate([0, GROOVE_CENTER, 0] )
|
|
cylinder(r = GROOVE_RADIUS, h = len + 2 * MANIFOLD_CORRECTION, center=true);
|
|
// Do we have cubes at either end of the groove?
|
|
// Required if we have horzontal and vertical grooves
|
|
if (endcube == 1 || endcube == 3)
|
|
translate([0, GROOVE_CENTER - 2 * MANIFOLD_CORRECTION, -(len - GROOVE_DIAMETER) / 2 - MANIFOLD_CORRECTION] )
|
|
cube([GROOVE_DIAMETER, GROOVE_DIAMETER + 4 * MANIFOLD_CORRECTION, GROOVE_DIAMETER], center=true);
|
|
if (endcube == 2 || endcube == 3)
|
|
translate([0, GROOVE_CENTER - 2 * MANIFOLD_CORRECTION, (len - GROOVE_DIAMETER) / 2 + MANIFOLD_CORRECTION] )
|
|
cube([GROOVE_DIAMETER, GROOVE_DIAMETER + 4 * MANIFOLD_CORRECTION, GROOVE_DIAMETER], center=true);
|
|
// now the 3 mm breakthrough for the grooves
|
|
translate([0, 0.5, 0] )
|
|
cube([GROOVE_BREAKTHROUGH, 1.5, len + 2 * MANIFOLD_CORRECTION], center = true);
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
// a flat groove to be substracted from other solids
|
|
// --------------------------------------------------------------------
|
|
module flat_groove(len = GROOVE_LENGTH, endcube=0)
|
|
{
|
|
difference() {
|
|
// make a round groove and cut off the top part
|
|
round_groove(len, endcube);
|
|
translate([-GROOVE_RADIUS, GROOVE_CENTER + FLAT_GROOVE_OFFSET, -len / 2 - (MANIFOLD_CORRECTION + 0.01)] )
|
|
cube([GROOVE_DIAMETER, GROOVE_CENTER - FLAT_GROOVE_OFFSET, len + 2 * (MANIFOLD_CORRECTION + 0.01)]);
|
|
}
|
|
}
|
|
|
|
|
|
// Apply a size correction to the eyelets which are printed on
|
|
// the build plate of the 3D printer?
|
|
// On my Ender 3 the eyelets on the build plate are too tall so
|
|
// I needed to widen them. The eyelets on the vertical wall of the
|
|
// girder are ok, they need no correction.
|
|
function apply_correction(val, correctionVal = 0.0, correction=false) = correction == true ? val + correctionVal : val;
|
|
|
|
|
|
// --------------------------------------------------------------------
|
|
// a single eyelet for the girders and struts
|
|
// --------------------------------------------------------------------
|
|
module eyelet(height = EYELET_HEIGHT, radius=2.05,
|
|
cube_len = 7.2, cube_width = 3.1,
|
|
correctionVal = 0.0)
|
|
{
|
|
// Currently used only in the lugs.scad file
|
|
// See strut_eyelet to decide whether that one can be refactored
|
|
// or replaced by this library module.
|
|
|
|
render()
|
|
union()
|
|
{
|
|
|
|
cylinder(h = height, r = radius, center = true);
|
|
cube([cube_width, cube_len, height], center = true);
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
// a row of eyelets
|
|
// --------------------------------------------------------------------
|
|
module eyelet_row(len = 1, height = EYELET_HEIGHT, eyelet_dist = FT_GRID_SIZE)
|
|
{
|
|
// removed correction
|
|
cnt = len / eyelet_dist;
|
|
for (i = [0 : eyelet_dist : (cnt - 1) * eyelet_dist])
|
|
{
|
|
translate([eyelet_dist / 2, eyelet_dist / 2 + i, 0])
|
|
eyelet(height = height);
|
|
}
|
|
}
|
|
|
|
|
|
// --------------------------------------------------------------------
|
|
// The cutout for plates, girders and the like
|
|
// --------------------------------------------------------------------
|
|
module plate_cutout(w1 = PLATE_CO_TOP_WIDTH, l1 = PLATE_CO_TOP_LENGTH,
|
|
w2 = PLATE_CO_BOTTOM_WIDTH, l2 = PLATE_CO_BOTTOM_LENGTH,
|
|
r = PLATE_CO_CIRCLE_DIAMETER, o = PLATE_CO_CIRCLE_OFFSET) {
|
|
union () {
|
|
translate([0,-0.01,0]) {
|
|
translate([-w1/2, 0, 0])
|
|
cube([w1, r, l1]);
|
|
translate([-w2/2, 0, l1])
|
|
cube([w2, r, l2]);
|
|
translate([0, r / 2 + o, 0])
|
|
cylinder(h = l1 + l2, d = r);
|
|
}
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
// A cube with attached cylinder to cut out holes for the pins of the
|
|
// basic blocks. Centered on the zero point of the coordinate system.
|
|
// Supports the four directions up, down, left and right.
|
|
// The build plate must be face down in the coordinate system to cut
|
|
// out the holes with this module.
|
|
// if the holes are too tall, adjust width (the width and height of
|
|
// the larger square hole) or the segment width s (the width of the
|
|
// the smaller rectangle)
|
|
// Used by u_girder and build_plate.
|
|
// --------------------------------------------------------------------
|
|
module cube_with_cylinder(w1 = PLATE_CO_TOP_WIDTH, l1 = PLATE_CO_TOP_LENGTH,
|
|
w2 = PLATE_CO_BOTTOM_WIDTH, l2 = PLATE_CO_BOTTOM_LENGTH,
|
|
r = PLATE_CO_CIRCLE_DIAMETER, o = PLATE_CO_CIRCLE_OFFSET, dir = "up")
|
|
{
|
|
if (dir == "up")
|
|
{
|
|
translate([0,(l1+l2)/2,0])
|
|
rotate([90,0,0])
|
|
plate_cutout(w1, l1, w2, l2, r, o);
|
|
}
|
|
else if (dir == "down")
|
|
{
|
|
translate([0,-(l1+l2)/2,0])
|
|
rotate([90,0,180])
|
|
plate_cutout(w1, l1, w2, l2, r, o);
|
|
}
|
|
else if (dir == "left")
|
|
{
|
|
translate([(l1+l2)/2,0,0])
|
|
rotate([90,0,270])
|
|
plate_cutout(w1, l1, w2, l2, r, o);
|
|
}
|
|
else if (dir == "right")
|
|
{
|
|
translate([-(l1+l2)/2,0,0])
|
|
rotate([90,0,90])
|
|
plate_cutout(w1, l1, w2, l2, r, o);
|
|
}
|
|
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
// Pin which fits into the round and flat grooves.
|
|
// The base_length is for pins placed on blocks or plates
|
|
// Parameters:
|
|
// diameter: the diameter of the hole for the pin
|
|
// base_width: the width and length of the pin base
|
|
// base_length: the height of the pin base
|
|
// The pin is centered at the x and y axis while the z origin is 0
|
|
// --------------------------------------------------------------------
|
|
module pin(diameter = PIN_DIAMETER, base_width = PIN_BASE_WIDTH, base_length = PIN_BASE_LENGTH) {
|
|
// check the whole thing!
|
|
rotate([90,0,0])
|
|
translate([0, (base_width + base_length) / 2, 0])
|
|
union() {
|
|
difference() {
|
|
// build the rounded part of the pin
|
|
intersection() {
|
|
cylinder(d = diameter, h = diameter, center = true);
|
|
rotate([0, 90, 0])
|
|
cylinder(d = diameter, h = diameter, center = true);
|
|
}
|
|
// cut off the top
|
|
translate([0, diameter / 2 + 0.6, 0])
|
|
cube([diameter, diameter, diameter], center = true );
|
|
}
|
|
// add the base below the rounded part
|
|
translate([0, -(base_width / 2), 0])
|
|
cube([base_width, base_length, base_width], center = true );
|
|
}
|
|
}
|