Files
ft-parts/flexrail.scad
T
2026-04-05 20:11:23 +02:00

274 lines
10 KiB
OpenSCAD

// ----------------------------------------------------------------
// Customizable flexrails
//
// inspired by:
// https://www.printables.com/model/146321-fischertechnik-compatible-flex-rail-flexschiene-15/files
//
// This package contains straight and circle flexrails.
// The straight flexrail has a customizable length and height.
// The circular flexrail has acustomizable radius and angle and,
// in addition, the outer wall can be set to an other value than
// the inner wall
/* [Flexrail options] */
// Type
Flexrail_type = 0; // [0 : no output, 1:Straight flexrail, 2:Circular flexrail, 3 : Pair of pins]
// Outer height of the wall, may be used for circular flexrails
Outer_height = 5.5;
// Inner height of the wall, also used for both walls of the straight flexrail
Inner_height = 5.5;
// Add the required pins?
Set_pins = true;
/* [Options for the straight flexrail] */
// Length of the flexrail, uses standard ft lengths
Length = 60; // [30, 45, 60, 75, 90, 105, 120, 135, 150, 165, 180]
/* [Options for the circular flexrail] */
// The outer radius of the flexrail
Radius = 45;
// The angle of the flexrail
Angle = 270; // [30 : 15 : 345]
/* [Options for the flexrail pins] */
// The number of rows and columns of pins
Count = [5, 4];
/* [Hidden] */
// **********************
// ** Static Settings: **
// **********************
include<ft_util.scad>
$fn=104;
// The thickness of the flexrail base and walls
thickness = 1.5;
// The width of the flexrail
flex_width = FT_GRID_SIZE;
// width of the pin plate
Pin_width = 9.1;
// Length of the pin plate
Pin_length = 7.1;
// length and width of the quadratic hole through the flexrail
Pin_hole = 5.01;
// *********************
// ** Helper Modules: **
// *********************
// --------------------------------------------------------------------
// Cutout for the pins. The pins are separated from the rails to avoid
// the need for support when printing the rail.
// The pins may be glued into their cutouts, but hey, it's then
// difficult to replace them ;-)
// --------------------------------------------------------------------
module cutout(base_width = FT_GRID_SIZE, width = Pin_width, length = Pin_length, height = thickness, hole = Pin_hole, up = 0 ) {
cutout_height = 1.5;
offset = height / 2;
union() {
translate([base_width / 2 - hole / 2, base_width / 2 - hole / 2, -MANIFOLD_CORRECTION / 2])
cube([hole, hole, cutout_height]);
if (up == 1)
translate([base_width / 2 - width / 2, base_width / 2 - length / 2, offset])
cube([width, length, cutout_height]);
else
translate([base_width / 2 - length / 2, base_width / 2 - width / 2, offset])
cube([length, width, cutout_height]);
}
}
// --------------------------------------------------------------------
// the slots in the rail
// --------------------------------------------------------------------
module slot(slot_width, slot_length, slot_height) {
translate([0, -MANIFOLD_CORRECTION / 2, -MANIFOLD_CORRECTION / 2])
cube([slot_width, slot_length, slot_height]);
}
// --------------------------------------------------------------------
// A slice of a circle to cut a piece out of the circle rail
// --------------------------------------------------------------------
module slice(r = 10, deg = 30) {
degn = (deg % 360 > 0) ? deg % 360 : deg % 360 + 360;
difference() {
circle(r);
if (degn > 180)
intersection_for(a = [0, 180 - degn])
rotate(a)
translate([-r, 0, 0])
square(r * 2);
else
union()
for(a = [0, 180 - degn])
rotate(a)
translate([-r, 0, 0])
square(r * 2);
}
}
// ***********************
// ** Flexrail Modules: **
// ***********************
// --------------------------------------------------------------------
// A plate with a pin fitting in the cutouts of the flexrails .
// They may be glued into the pin hole, but hey: It is difficult to
// remove them again whenever maintainance is needed ;-)
// --------------------------------------------------------------------
module flexrail_pin(width = Pin_width, length = Pin_length, height = thickness, hole = 5) {
correction = 0.5;
translate([0, 0,height])
union() {
translate([0, 0,-(height / 4)])
union() {
cube ([hole - correction, hole - correction, height / 2], center = true);
translate([0, 0, -(height / 2)])
cube ([width - correction, length - correction, height / 2], center = true);
}
pin();
}
}
// --------------------------------------------------------------------
// A straight flexrail
// --------------------------------------------------------------------
module flexrail(length = Length, height = Inner_height) {
wall_thickness = thickness;
width = flex_width;
y_center = width / 2;
slot_width = 1.1;
slot_length = width - wall_thickness + MANIFOLD_CORRECTION;
slot_height = height + MANIFOLD_CORRECTION;
slot_distance = 10.0;
difference() {
cube([length, width, height]);
// cut out the inner rail part
translate([-MANIFOLD_CORRECTION / 2, wall_thickness, wall_thickness])
cube([length + MANIFOLD_CORRECTION, width - 2 * wall_thickness, height]);
// then cut out the holes for the pins on both ends
cutout();
translate([length - width, 0, 0])
cutout();
// finally cut out the slots on both sides, but leave a bit
// of the flexrail before the wall (substract or add the
// MANIFOLD_CORRECTION to the y-axis)
for(i=[width : slot_distance : length -width]) {
translate([i, -MANIFOLD_CORRECTION, 0])
slot(slot_width, slot_length, slot_height);
}
for(i=[width + slot_distance / 2 : slot_distance : length -width]) {
translate([i, wall_thickness + MANIFOLD_CORRECTION, 0])
slot(slot_width, slot_length, slot_height);
}
}
}
// --------------------------------------------------------------------
// a circle rail without cutouts
// --------------------------------------------------------------------
module circle_rail(radius = 40, outer_height = Outer_height, inner_height = Inner_height, width = flex_width, angle = 270) {
v_wall_thickness = thickness;
bottom_thickness = thickness;
difference() {
union() {
difference() {
cylinder(r = radius, h = outer_height);
translate([0, 0, bottom_thickness])
cylinder(r = radius - v_wall_thickness, h = outer_height);
}
cylinder(r = radius - width + v_wall_thickness, h = inner_height);
}
translate([0, 0,-MANIFOLD_CORRECTION / 2])
cylinder(r = radius - width, h = inner_height + MANIFOLD_CORRECTION);
// finally substract a a slice so that the remaining circle covers
// the angle given as parameter
if (angle % 360 != 0)
translate([0, 0, -MANIFOLD_CORRECTION / 2])
linear_extrude(outer_height + MANIFOLD_CORRECTION*2)
slice(r = radius + MANIFOLD_CORRECTION , deg = 360 - angle);
}
}
// --------------------------------------------------------------------
// cut slots into the circular flex rail
// --------------------------------------------------------------------
module slot_circle(radius = 40.0, height = Inner_height, width = flex_width, start_angle = 30, end_angle = 270, segment_angle = 30, offset = 0) {
wall_thickness = 1.5;
slot_width = 1.1;
slot_length = width - wall_thickness + MANIFOLD_CORRECTION + 1.4;
slot_height = height + MANIFOLD_CORRECTION;
for(i=[start_angle : segment_angle : end_angle]) {
// echo(i);
rotate([0, 0,i])
translate([radius - slot_length + offset, 0, -MANIFOLD_CORRECTION / 2])
cube([slot_length, slot_width, slot_height]);
}
}
// --------------------------------------------------------------------
// Draw a slotted circular flexrail with pin cutouts.
// --------------------------------------------------------------------
module circle_flexrail(radius = 40, outer_height = outer_height, inner_height = inner_height, width = flex_width, angle = 360) {
seg_angle = 900 / radius;
difference() {
circle_rail(radius = radius, outer_height = outer_height, inner_height = inner_height, width = width, angle = angle);
// cut out the pin holes
translate([radius - width, 0, 0])
cutout(up = 1);
rotate([0, 0, angle])
translate([radius - width, -width, 0])
cutout(up = 1);
// cut out the slots on both sides, but leave a bit of the
// flexrail before the wall (that's what the offset is for)
slot_circle(radius = radius, height = inner_height, width = width, start_angle = seg_angle * 1.5, end_angle = angle - seg_angle, segment_angle = seg_angle, offset = -1.8);
slot_circle(radius = radius, height = outer_height, width = width, start_angle = seg_angle * 2, end_angle = angle - seg_angle * 1.5, segment_angle = seg_angle, offset = 2.0);
}
}
// ********************
// ** Build section: **
// ********************
module main() {
if (Flexrail_type == 1) {
flexrail(length = Length, height = Inner_height);
if(Set_pins) {
translate([-10, 7.5, 0])
rotate([0, 0, 90])
flexrail_pin();
translate([Length + 10, 7.5, 0])
rotate([0, 0, 90])
flexrail_pin();
}
}
else if (Flexrail_type == 2) {
circle_flexrail(radius = Radius, angle = Angle, outer_height = Outer_height, inner_height = Inner_height);
if (Set_pins) {
translate([-5, 5, 0])
rotate([0, 0, 90])
flexrail_pin();
translate([5, 5, 0])
rotate([0, 0, 90])
flexrail_pin();
}
}
else if (Flexrail_type == 3) {
for (i = [0 : 10 : (Count[1] - 1) * 10])
for (j = [0 : 10 : (Count[0] - 1) * 10])
translate([i, j, 0])
flexrail_pin();
}
}
main();