discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

linear rail routines and modifications

HW
Harvey white
Mon, Apr 14, 2025 5:12 PM

When using a linear rail, there's no (that I know of) graceful way to
control the slide position.   The carriage can be positioned off the
rail at either end.  There's also no model for a dual carriage rail.

using the function limit, the following functions can be built. Note
that these functions take into account the carriage type.

A single carriage rail needs limit1:

function limit1(len, slide_position, carriage = MGN12H_carriage) =
    limit(len - limit(slide_position,0,len-1*carriage[1]), 0,
len)-len/2-carriage[1]/2 ;

where len is the slide length.

The carriage cannot be positioned beyond the ends, and the carriage
length is taken into account.

If the position is less than zero, then zero is used.  If position is
greater than the slide length, then the slide is positioned to the end.

a dual carriage needs to take into account both slides and the distance
between them.

function limit2(len, slide_position, carriage = MGN12H_carriage,
separation = 1) =
    limit(len - limit(slide_position,0,len-2*carriage[1]-separation/2),
0, len)-len/2-carriage[1]/2 ;

len is the slide length, the separation is the distance between the two
slides.

// ************************* single carriage calling example


// single carriage

// ypos is processed here.  xpos is passed to a cross slide (dual carriage)

module left_top_rail(ypos = 0, length = 550, slide = 500, xpos = 0)
{

    // allow reassignment, slide is total permissible travel of
carriage (ex: 500 mm slide, real travel is less)

    y1pos = limit1(slide, ypos);

    difference()
    {
        union()
        {
            color("DeepSkyBlue") translate([0.0 *
extrusion_width(E2040),0 *
extrusion_width(E2040),0*extrusion_width(E2040)])
                    rotate([0,0,0])Erail(E2040,length);

         // standard implementation of slide, where slide is as above,
y1pos is processed value

            translate([slide/2 + (length-slide)/2
,0,1*extrusion_width(E2040)])rotate([0,0,180])
                rail_assembly(MGN12H_carriage,slide, y1pos);

        // these are fixed to slide and move with carriage position
            translate([25 +slide/2 - y1pos,0,35])
            {
                belt_clamp_assembly(1);
                translate([0,0,11.9]) cross_clamp();
                translate([-0,-107,14.0]) rotate([0,0,90]) x_rail(xpos);
            }
        }
        union()
        {
        }
    }

}

// ************************* dual carriage calling example


module x_rail(xpos = 0, length = 700, slide = 500)
{
    x1pos = limit2 (slide, xpos, MGN12H_carriage, 20);

      translate([slide/2 + (length-slide)/2 +40
,0,1*extrusion_width(E2020)])rotate([0,0,180])
      // carriage, length, position, separation
      rail_assembly2(MGN12H_carriage,slide, x1pos, 10);
}

// ************************* code to add


// copied from nopSCADlib
function limit(x, min, max) = max(min(x, max), min);

// single slide limit
// given a linear slide of len, and a slide position from 0 to len
(maximum extent)
// keep slide from going below 0, and beyond end of rail. Compensate for
carriage length.

function limit1(len, slide_position, carriage = MGN12H_carriage,
separation = 0) =
    limit(len - limit(slide_position,0,len-1*carriage[1]), 0,
len)-len/2-carriage[1]/2 ;

// dual slide limit
// given a linear slide of len, and a slide position from 0 to len
(maximum extent)
// keep slide pair from going below 0, and beyond end of rail.
Compensate for carriage length and
// space between carriages.

function limit2(len, slide_position, carriage = MGN12H_carriage,
separation = 1) =
    limit(len - limit(slide_position,0,len-2*carriage[1]-separation/2),
0, len)-len/2-carriage[1]/2 ;

// does dual carriage linear rail
// same as rail_assembly, but
// parameters are carriage, length, position (as standard) but also add
separation (default = 1)
// change limit parameters to add carriage and separation

module rail_assembly2(carriage, length, pos = 0, separation = 1,
carriage_end_colour = grey(20), carriage_wiper_colour = grey(20))
{
    //! Rail and carriage assembly
    rail(carriage_rail(carriage), length);

    translate([(pos - (carriage[1] + separation)), 0])
        carriage(carriage, carriage_end_colour, carriage_wiper_colour);

    translate([pos, 0])
        carriage(carriage, carriage_end_colour, carriage_wiper_colour);
}

Hope this proves useful:  I'd like to see it added to the rails.scad
library.

Harvey

When using a linear rail, there's no (that I know of) graceful way to control the slide position.   The carriage can be positioned off the rail at either end.  There's also no model for a dual carriage rail. using the function limit, the following functions can be built. Note that these functions take into account the carriage type. A single carriage rail needs limit1: function limit1(len, slide_position, carriage = MGN12H_carriage) =     limit(len - limit(slide_position,0,len-1*carriage[1]), 0, len)-len/2-carriage[1]/2 ; where len is the slide length. The carriage cannot be positioned beyond the ends, and the carriage length is taken into account. If the position is less than zero, then zero is used.  If position is greater than the slide length, then the slide is positioned to the end. a dual carriage needs to take into account both slides and the distance between them. function limit2(len, slide_position, carriage = MGN12H_carriage, separation = 1) =     limit(len - limit(slide_position,0,len-2*carriage[1]-separation/2), 0, len)-len/2-carriage[1]/2 ; len is the slide length, the separation is the distance between the two slides. // ************************* single carriage calling example ********************************** // single carriage // ypos is processed here.  xpos is passed to a cross slide (dual carriage) module left_top_rail(ypos = 0, length = 550, slide = 500, xpos = 0) {     // allow reassignment, slide is total permissible travel of carriage (ex: 500 mm slide, real travel is less)     y1pos = limit1(slide, ypos);     difference()     {         union()         {             color("DeepSkyBlue") translate([0.0 * extrusion_width(E2040),0 * extrusion_width(E2040),0*extrusion_width(E2040)])                     rotate([0,0,0])Erail(E2040,length);          // standard implementation of slide, where slide is as above, y1pos is processed value             translate([slide/2 + (length-slide)/2 ,0,1*extrusion_width(E2040)])rotate([0,0,180])                 rail_assembly(MGN12H_carriage,slide, y1pos);         // these are fixed to slide and move with carriage position             translate([25 +slide/2 - y1pos,0,35])             {                 belt_clamp_assembly(1);                 translate([0,0,11.9]) cross_clamp();                 translate([-0,-107,14.0]) rotate([0,0,90]) x_rail(xpos);             }         }         union()         {         }     } } // ************************* dual carriage calling example ********************************** module x_rail(xpos = 0, length = 700, slide = 500) {     x1pos = limit2 (slide, xpos, MGN12H_carriage, 20);       translate([slide/2 + (length-slide)/2 +40 ,0,1*extrusion_width(E2020)])rotate([0,0,180])       // carriage, length, position, separation       rail_assembly2(MGN12H_carriage,slide, x1pos, 10); } // ************************* code to add *********************************************** // copied from nopSCADlib function limit(x, min, max) = max(min(x, max), min); // single slide limit // given a linear slide of len, and a slide position from 0 to len (maximum extent) // keep slide from going below 0, and beyond end of rail. Compensate for carriage length. function limit1(len, slide_position, carriage = MGN12H_carriage, separation = 0) =     limit(len - limit(slide_position,0,len-1*carriage[1]), 0, len)-len/2-carriage[1]/2 ; // dual slide limit // given a linear slide of len, and a slide position from 0 to len (maximum extent) // keep slide pair from going below 0, and beyond end of rail. Compensate for carriage length and // space between carriages. function limit2(len, slide_position, carriage = MGN12H_carriage, separation = 1) =     limit(len - limit(slide_position,0,len-2*carriage[1]-separation/2), 0, len)-len/2-carriage[1]/2 ; // does dual carriage linear rail // same as rail_assembly, but // parameters are carriage, length, position (as standard) but also add separation (default = 1) // change limit parameters to add carriage and separation module rail_assembly2(carriage, length, pos = 0, separation = 1, carriage_end_colour = grey(20), carriage_wiper_colour = grey(20)) {     //! Rail and carriage assembly     rail(carriage_rail(carriage), length);     translate([(pos - (carriage[1] + separation)), 0])         carriage(carriage, carriage_end_colour, carriage_wiper_colour);     translate([pos, 0])         carriage(carriage, carriage_end_colour, carriage_wiper_colour); } Hope this proves useful:  I'd like to see it added to the rails.scad library. Harvey
GH
gene heskett
Mon, Apr 14, 2025 6:59 PM

On 4/14/25 13:12, Harvey white via Discuss wrote:

When using a linear rail, there's no (that I know of) graceful way to
control the slide position.   The carriage can be positioned off the
rail at either end.  There's also no model for a dual carriage rail.

Niether is there a dual rail config, but I have 2 printers with dual
rails, top and bottom of a 20x20 carbon fiber tube. Takes no change in
the slicer or klipper.cfg because of that.

using the function limit, the following functions can be built. Note
that these functions take into account the carriage type.

A single carriage rail needs limit1:

function limit1(len, slide_position, carriage = MGN12H_carriage) =
    limit(len - limit(slide_position,0,len-1*carriage[1]), 0,
len)-len/2-carriage[1]/2 ;

where len is the slide length.

Why are you worried about that, this is a printer slicer & driver.cfg
problem. most drivers will, if properly configured for that printer,
either move an off bed gcode file back to the center of the bed, and
yell bloody murder if its still beyond the printers limits.   Configure
your slicer.  Use OpenSCAD to lay the part at 45 degrees on the bed to
gain additional length.

The carriage cannot be positioned beyond the ends, and the carriage
length is taken into account.

If the position is less than zero, then zero is used.  If position is
greater than the slide length, then the slide is positioned to the end.

a dual carriage needs to take into account both slides and the
distance between them.

function limit2(len, slide_position, carriage = MGN12H_carriage,
separation = 1) =
    limit(len -
limit(slide_position,0,len-2*carriage[1]-separation/2), 0,
len)-len/2-carriage[1]/2 ;

len is the slide length, the separation is the distance between the
two slides.

// ************************* single carriage calling example


// single carriage

// ypos is processed here.  xpos is passed to a cross slide (dual
carriage)

module left_top_rail(ypos = 0, length = 550, slide = 500, xpos = 0)
{

    // allow reassignment, slide is total permissible travel of
carriage (ex: 500 mm slide, real travel is less)

    y1pos = limit1(slide, ypos);

    difference()
    {
        union()
        {
            color("DeepSkyBlue") translate([0.0 *
extrusion_width(E2040),0 *
extrusion_width(E2040),0*extrusion_width(E2040)])
                    rotate([0,0,0])Erail(E2040,length);

         // standard implementation of slide, where slide is as above,
y1pos is processed value

            translate([slide/2 + (length-slide)/2
,0,1*extrusion_width(E2040)])rotate([0,0,180])
                rail_assembly(MGN12H_carriage,slide, y1pos);

        // these are fixed to slide and move with carriage position
            translate([25 +slide/2 - y1pos,0,35])
            {
                belt_clamp_assembly(1);
                translate([0,0,11.9]) cross_clamp();
                translate([-0,-107,14.0]) rotate([0,0,90]) x_rail(xpos);
            }
        }
        union()
        {
        }
    }

}

// ************************* dual carriage calling example


module x_rail(xpos = 0, length = 700, slide = 500)
{
    x1pos = limit2 (slide, xpos, MGN12H_carriage, 20);

      translate([slide/2 + (length-slide)/2 +40
,0,1*extrusion_width(E2020)])rotate([0,0,180])
      // carriage, length, position, separation
      rail_assembly2(MGN12H_carriage,slide, x1pos, 10);
}

// ************************* code to add


// copied from nopSCADlib
function limit(x, min, max) = max(min(x, max), min);

// single slide limit
// given a linear slide of len, and a slide position from 0 to len
(maximum extent)
// keep slide from going below 0, and beyond end of rail. Compensate
for carriage length.

function limit1(len, slide_position, carriage = MGN12H_carriage,
separation = 0) =
    limit(len - limit(slide_position,0,len-1*carriage[1]), 0,
len)-len/2-carriage[1]/2 ;

// dual slide limit
// given a linear slide of len, and a slide position from 0 to len
(maximum extent)
// keep slide pair from going below 0, and beyond end of rail.
Compensate for carriage length and
// space between carriages.

function limit2(len, slide_position, carriage = MGN12H_carriage,
separation = 1) =
    limit(len -
limit(slide_position,0,len-2*carriage[1]-separation/2), 0,
len)-len/2-carriage[1]/2 ;

// does dual carriage linear rail
// same as rail_assembly, but
// parameters are carriage, length, position (as standard) but also
add separation (default = 1)
// change limit parameters to add carriage and separation

module rail_assembly2(carriage, length, pos = 0, separation = 1,
carriage_end_colour = grey(20), carriage_wiper_colour = grey(20))
{
    //! Rail and carriage assembly
    rail(carriage_rail(carriage), length);

    translate([(pos - (carriage[1] + separation)), 0])
        carriage(carriage, carriage_end_colour, carriage_wiper_colour);

    translate([pos, 0])
        carriage(carriage, carriage_end_colour, carriage_wiper_colour);
}

Hope this proves useful:  I'd like to see it added to the rails.scad
library.

Harvey

If I ever needed more than one color, I'd put a box turtle on that printer.


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

Cheers, Gene Heskett, CET.

"There are four boxes to be used in defense of liberty:
soap, ballot, jury, and ammo. Please use in that order."
-Ed Howdershelt (Author, 1940)
If we desire respect for the law, we must first make the law respectable.

  • Louis D. Brandeis
On 4/14/25 13:12, Harvey white via Discuss wrote: > When using a linear rail, there's no (that I know of) graceful way to > control the slide position.   The carriage can be positioned off the > rail at either end.  There's also no model for a dual carriage rail. Niether is there a dual rail config, but I have 2 printers with dual rails, top and bottom of a 20x20 carbon fiber tube. Takes no change in the slicer or klipper.cfg because of that. > > > using the function limit, the following functions can be built. Note > that these functions take into account the carriage type. > > A single carriage rail needs limit1: > > function limit1(len, slide_position, carriage = MGN12H_carriage) = >     limit(len - limit(slide_position,0,len-1*carriage[1]), 0, > len)-len/2-carriage[1]/2 ; > > where len is the slide length. Why are you worried about that, this is a printer slicer & driver.cfg problem. most drivers will, if properly configured for that printer, either move an off bed gcode file back to the center of the bed, and yell bloody murder if its still beyond the printers limits.   Configure your slicer.  Use OpenSCAD to lay the part at 45 degrees on the bed to gain additional length. > > > The carriage cannot be positioned beyond the ends, and the carriage > length is taken into account. > > If the position is less than zero, then zero is used.  If position is > greater than the slide length, then the slide is positioned to the end. > > a dual carriage needs to take into account both slides and the > distance between them. > > function limit2(len, slide_position, carriage = MGN12H_carriage, > separation = 1) = >     limit(len - > limit(slide_position,0,len-2*carriage[1]-separation/2), 0, > len)-len/2-carriage[1]/2 ; > > len is the slide length, the separation is the distance between the > two slides. > > // ************************* single carriage calling example > ********************************** > > // single carriage > > // ypos is processed here.  xpos is passed to a cross slide (dual > carriage) > > module left_top_rail(ypos = 0, length = 550, slide = 500, xpos = 0) > { > >     // allow reassignment, slide is total permissible travel of > carriage (ex: 500 mm slide, real travel is less) > >     y1pos = limit1(slide, ypos); > > >     difference() >     { >         union() >         { >             color("DeepSkyBlue") translate([0.0 * > extrusion_width(E2040),0 * > extrusion_width(E2040),0*extrusion_width(E2040)]) >                     rotate([0,0,0])Erail(E2040,length); > >          // standard implementation of slide, where slide is as above, > y1pos is processed value > >             translate([slide/2 + (length-slide)/2 > ,0,1*extrusion_width(E2040)])rotate([0,0,180]) >                 rail_assembly(MGN12H_carriage,slide, y1pos); > >         // these are fixed to slide and move with carriage position >             translate([25 +slide/2 - y1pos,0,35]) >             { >                 belt_clamp_assembly(1); >                 translate([0,0,11.9]) cross_clamp(); >                 translate([-0,-107,14.0]) rotate([0,0,90]) x_rail(xpos); >             } >         } >         union() >         { >         } >     } > > } > > // ************************* dual carriage calling example > ********************************** > > module x_rail(xpos = 0, length = 700, slide = 500) > { >     x1pos = limit2 (slide, xpos, MGN12H_carriage, 20); > >       translate([slide/2 + (length-slide)/2 +40 > ,0,1*extrusion_width(E2020)])rotate([0,0,180]) >       // carriage, length, position, separation >       rail_assembly2(MGN12H_carriage,slide, x1pos, 10); > } > > // ************************* code to add > *********************************************** > > // copied from nopSCADlib > function limit(x, min, max) = max(min(x, max), min); > > // single slide limit > // given a linear slide of len, and a slide position from 0 to len > (maximum extent) > // keep slide from going below 0, and beyond end of rail. Compensate > for carriage length. > > function limit1(len, slide_position, carriage = MGN12H_carriage, > separation = 0) = >     limit(len - limit(slide_position,0,len-1*carriage[1]), 0, > len)-len/2-carriage[1]/2 ; > > // dual slide limit > // given a linear slide of len, and a slide position from 0 to len > (maximum extent) > // keep slide pair from going below 0, and beyond end of rail. > Compensate for carriage length and > // space between carriages. > > > function limit2(len, slide_position, carriage = MGN12H_carriage, > separation = 1) = >     limit(len - > limit(slide_position,0,len-2*carriage[1]-separation/2), 0, > len)-len/2-carriage[1]/2 ; > > > > // does dual carriage linear rail > // same as rail_assembly, but > // parameters are carriage, length, position (as standard) but also > add separation (default = 1) > // change limit parameters to add carriage and separation > > module rail_assembly2(carriage, length, pos = 0, separation = 1, > carriage_end_colour = grey(20), carriage_wiper_colour = grey(20)) > { >     //! Rail and carriage assembly >     rail(carriage_rail(carriage), length); > >     translate([(pos - (carriage[1] + separation)), 0]) >         carriage(carriage, carriage_end_colour, carriage_wiper_colour); > >     translate([pos, 0]) >         carriage(carriage, carriage_end_colour, carriage_wiper_colour); > } > > Hope this proves useful:  I'd like to see it added to the rails.scad > library. > > Harvey > If I ever needed more than one color, I'd put a box turtle on that printer. > > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org Cheers, Gene Heskett, CET. -- "There are four boxes to be used in defense of liberty: soap, ballot, jury, and ammo. Please use in that order." -Ed Howdershelt (Author, 1940) If we desire respect for the law, we must first make the law respectable. - Louis D. Brandeis
HW
Harvey white
Mon, Apr 14, 2025 7:56 PM

I see I did not explain myself well enough.

This is being used in a form/fit model of a pick and place machine.  I
do openSCAD models before I build something suitably mechanical.  Yes,
indeed, the real world mechanism has mechanical stops and optical
sensors for carriage (x, y, z) limits, both the home and limit types.

Slicer and the like do not apply in this design.  I do plan to use
OpenPNP to make things run.

The dual rail configuration can be easily done by simply specifying two
rails and feeding the same position to both.

This is a general solution to perhaps enhance the performance of a model
in the library.

Harvey

On 4/14/2025 2:59 PM, gene heskett via Discuss wrote:

On 4/14/25 13:12, Harvey white via Discuss wrote:

When using a linear rail, there's no (that I know of) graceful way to
control the slide position.   The carriage can be positioned off the
rail at either end.  There's also no model for a dual carriage rail.

Niether is there a dual rail config, but I have 2 printers with dual
rails, top and bottom of a 20x20 carbon fiber tube. Takes no change in
the slicer or klipper.cfg because of that.

using the function limit, the following functions can be built. Note
that these functions take into account the carriage type.

A single carriage rail needs limit1:

function limit1(len, slide_position, carriage = MGN12H_carriage) =
    limit(len - limit(slide_position,0,len-1*carriage[1]), 0,
len)-len/2-carriage[1]/2 ;

where len is the slide length.

Why are you worried about that, this is a printer slicer & driver.cfg
problem. most drivers will, if properly configured for that printer,
either move an off bed gcode file back to the center of the bed, and
yell bloody murder if its still beyond the printers limits. 
 Configure your slicer.  Use OpenSCAD to lay the part at 45 degrees on
the bed to gain additional length.

The carriage cannot be positioned beyond the ends, and the carriage
length is taken into account.

If the position is less than zero, then zero is used.  If position is
greater than the slide length, then the slide is positioned to the end.

a dual carriage needs to take into account both slides and the
distance between them.

function limit2(len, slide_position, carriage = MGN12H_carriage,
separation = 1) =
    limit(len -
limit(slide_position,0,len-2*carriage[1]-separation/2), 0,
len)-len/2-carriage[1]/2 ;

len is the slide length, the separation is the distance between the
two slides.

// ************************* single carriage calling example


// single carriage

// ypos is processed here.  xpos is passed to a cross slide (dual
carriage)

module left_top_rail(ypos = 0, length = 550, slide = 500, xpos = 0)
{

    // allow reassignment, slide is total permissible travel of
carriage (ex: 500 mm slide, real travel is less)

    y1pos = limit1(slide, ypos);

    difference()
    {
        union()
        {
            color("DeepSkyBlue") translate([0.0 *
extrusion_width(E2040),0 *
extrusion_width(E2040),0*extrusion_width(E2040)])
                    rotate([0,0,0])Erail(E2040,length);

         // standard implementation of slide, where slide is as
above, y1pos is processed value

            translate([slide/2 + (length-slide)/2
,0,1*extrusion_width(E2040)])rotate([0,0,180])
                rail_assembly(MGN12H_carriage,slide, y1pos);

        // these are fixed to slide and move with carriage position
            translate([25 +slide/2 - y1pos,0,35])
            {
                belt_clamp_assembly(1);
                translate([0,0,11.9]) cross_clamp();
                translate([-0,-107,14.0]) rotate([0,0,90]) x_rail(xpos);
            }
        }
        union()
        {
        }
    }

}

// ************************* dual carriage calling example


module x_rail(xpos = 0, length = 700, slide = 500)
{
    x1pos = limit2 (slide, xpos, MGN12H_carriage, 20);

      translate([slide/2 + (length-slide)/2 +40
,0,1*extrusion_width(E2020)])rotate([0,0,180])
      // carriage, length, position, separation
      rail_assembly2(MGN12H_carriage,slide, x1pos, 10);
}

// ************************* code to add


// copied from nopSCADlib
function limit(x, min, max) = max(min(x, max), min);

// single slide limit
// given a linear slide of len, and a slide position from 0 to len
(maximum extent)
// keep slide from going below 0, and beyond end of rail. Compensate
for carriage length.

function limit1(len, slide_position, carriage = MGN12H_carriage,
separation = 0) =
    limit(len - limit(slide_position,0,len-1*carriage[1]), 0,
len)-len/2-carriage[1]/2 ;

// dual slide limit
// given a linear slide of len, and a slide position from 0 to len
(maximum extent)
// keep slide pair from going below 0, and beyond end of rail.
Compensate for carriage length and
// space between carriages.

function limit2(len, slide_position, carriage = MGN12H_carriage,
separation = 1) =
    limit(len -
limit(slide_position,0,len-2*carriage[1]-separation/2), 0,
len)-len/2-carriage[1]/2 ;

// does dual carriage linear rail
// same as rail_assembly, but
// parameters are carriage, length, position (as standard) but also
add separation (default = 1)
// change limit parameters to add carriage and separation

module rail_assembly2(carriage, length, pos = 0, separation = 1,
carriage_end_colour = grey(20), carriage_wiper_colour = grey(20))
{
    //! Rail and carriage assembly
    rail(carriage_rail(carriage), length);

    translate([(pos - (carriage[1] + separation)), 0])
        carriage(carriage, carriage_end_colour, carriage_wiper_colour);

    translate([pos, 0])
        carriage(carriage, carriage_end_colour, carriage_wiper_colour);
}

Hope this proves useful:  I'd like to see it added to the rails.scad
library.

Harvey

If I ever needed more than one color, I'd put a box turtle on that
printer.


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

Cheers, Gene Heskett, CET.

I see I did not explain myself well enough. This is being used in a form/fit model of a pick and place machine.  I do openSCAD models before I build something suitably mechanical.  Yes, indeed, the real world mechanism has mechanical stops and optical sensors for carriage (x, y, z) limits, both the home and limit types. Slicer and the like do not apply in this design.  I do plan to use OpenPNP to make things run. The dual rail configuration can be easily done by simply specifying two rails and feeding the same position to both. This is a general solution to perhaps enhance the performance of a model in the library. Harvey On 4/14/2025 2:59 PM, gene heskett via Discuss wrote: > On 4/14/25 13:12, Harvey white via Discuss wrote: >> When using a linear rail, there's no (that I know of) graceful way to >> control the slide position.   The carriage can be positioned off the >> rail at either end.  There's also no model for a dual carriage rail. > Niether is there a dual rail config, but I have 2 printers with dual > rails, top and bottom of a 20x20 carbon fiber tube. Takes no change in > the slicer or klipper.cfg because of that. >> >> >> using the function limit, the following functions can be built. Note >> that these functions take into account the carriage type. >> >> A single carriage rail needs limit1: >> >> function limit1(len, slide_position, carriage = MGN12H_carriage) = >>     limit(len - limit(slide_position,0,len-1*carriage[1]), 0, >> len)-len/2-carriage[1]/2 ; >> >> where len is the slide length. > Why are you worried about that, this is a printer slicer & driver.cfg > problem. most drivers will, if properly configured for that printer, > either move an off bed gcode file back to the center of the bed, and > yell bloody murder if its still beyond the printers limits.  >  Configure your slicer.  Use OpenSCAD to lay the part at 45 degrees on > the bed to gain additional length. >> >> >> The carriage cannot be positioned beyond the ends, and the carriage >> length is taken into account. >> >> If the position is less than zero, then zero is used.  If position is >> greater than the slide length, then the slide is positioned to the end. >> >> a dual carriage needs to take into account both slides and the >> distance between them. >> >> function limit2(len, slide_position, carriage = MGN12H_carriage, >> separation = 1) = >>     limit(len - >> limit(slide_position,0,len-2*carriage[1]-separation/2), 0, >> len)-len/2-carriage[1]/2 ; >> >> len is the slide length, the separation is the distance between the >> two slides. >> >> // ************************* single carriage calling example >> ********************************** >> >> // single carriage >> >> // ypos is processed here.  xpos is passed to a cross slide (dual >> carriage) >> >> module left_top_rail(ypos = 0, length = 550, slide = 500, xpos = 0) >> { >> >>     // allow reassignment, slide is total permissible travel of >> carriage (ex: 500 mm slide, real travel is less) >> >>     y1pos = limit1(slide, ypos); >> >> >>     difference() >>     { >>         union() >>         { >>             color("DeepSkyBlue") translate([0.0 * >> extrusion_width(E2040),0 * >> extrusion_width(E2040),0*extrusion_width(E2040)]) >>                     rotate([0,0,0])Erail(E2040,length); >> >>          // standard implementation of slide, where slide is as >> above, y1pos is processed value >> >>             translate([slide/2 + (length-slide)/2 >> ,0,1*extrusion_width(E2040)])rotate([0,0,180]) >>                 rail_assembly(MGN12H_carriage,slide, y1pos); >> >>         // these are fixed to slide and move with carriage position >>             translate([25 +slide/2 - y1pos,0,35]) >>             { >>                 belt_clamp_assembly(1); >>                 translate([0,0,11.9]) cross_clamp(); >>                 translate([-0,-107,14.0]) rotate([0,0,90]) x_rail(xpos); >>             } >>         } >>         union() >>         { >>         } >>     } >> >> } >> >> // ************************* dual carriage calling example >> ********************************** >> >> module x_rail(xpos = 0, length = 700, slide = 500) >> { >>     x1pos = limit2 (slide, xpos, MGN12H_carriage, 20); >> >>       translate([slide/2 + (length-slide)/2 +40 >> ,0,1*extrusion_width(E2020)])rotate([0,0,180]) >>       // carriage, length, position, separation >>       rail_assembly2(MGN12H_carriage,slide, x1pos, 10); >> } >> >> // ************************* code to add >> *********************************************** >> >> // copied from nopSCADlib >> function limit(x, min, max) = max(min(x, max), min); >> >> // single slide limit >> // given a linear slide of len, and a slide position from 0 to len >> (maximum extent) >> // keep slide from going below 0, and beyond end of rail. Compensate >> for carriage length. >> >> function limit1(len, slide_position, carriage = MGN12H_carriage, >> separation = 0) = >>     limit(len - limit(slide_position,0,len-1*carriage[1]), 0, >> len)-len/2-carriage[1]/2 ; >> >> // dual slide limit >> // given a linear slide of len, and a slide position from 0 to len >> (maximum extent) >> // keep slide pair from going below 0, and beyond end of rail. >> Compensate for carriage length and >> // space between carriages. >> >> >> function limit2(len, slide_position, carriage = MGN12H_carriage, >> separation = 1) = >>     limit(len - >> limit(slide_position,0,len-2*carriage[1]-separation/2), 0, >> len)-len/2-carriage[1]/2 ; >> >> >> >> // does dual carriage linear rail >> // same as rail_assembly, but >> // parameters are carriage, length, position (as standard) but also >> add separation (default = 1) >> // change limit parameters to add carriage and separation >> >> module rail_assembly2(carriage, length, pos = 0, separation = 1, >> carriage_end_colour = grey(20), carriage_wiper_colour = grey(20)) >> { >>     //! Rail and carriage assembly >>     rail(carriage_rail(carriage), length); >> >>     translate([(pos - (carriage[1] + separation)), 0]) >>         carriage(carriage, carriage_end_colour, carriage_wiper_colour); >> >>     translate([pos, 0]) >>         carriage(carriage, carriage_end_colour, carriage_wiper_colour); >> } >> >> Hope this proves useful:  I'd like to see it added to the rails.scad >> library. >> >> Harvey >> > If I ever needed more than one color, I'd put a box turtle on that > printer. >> >> _______________________________________________ >> OpenSCAD mailing list >> To unsubscribe send an email to discuss-leave@lists.openscad.org > > Cheers, Gene Heskett, CET.
NH
nop head
Mon, Apr 14, 2025 8:27 PM

I use the rails in a 3D printer and the travel is calculated from the build
area and not the physical limits of the rail. I just assert if the required
travel is more than the rail can supply, which is available with
carriage_travel().

assert(X_travel <= carriage_travel(X_carriage, X_rail_length), "X rail too
short");
assert(Y_travel <= carriage_travel(Y_carriage, Y_rail_length), "Y rail too
short");

When it comes to adding extra carriages, etc, I don't think it should be in
the library because there are many ways of combining rails and carriages.

On Mon, 14 Apr 2025 at 20:57, Harvey white via Discuss <
discuss@lists.openscad.org> wrote:

I see I did not explain myself well enough.

This is being used in a form/fit model of a pick and place machine.  I
do openSCAD models before I build something suitably mechanical.  Yes,
indeed, the real world mechanism has mechanical stops and optical
sensors for carriage (x, y, z) limits, both the home and limit types.

Slicer and the like do not apply in this design.  I do plan to use
OpenPNP to make things run.

The dual rail configuration can be easily done by simply specifying two
rails and feeding the same position to both.

This is a general solution to perhaps enhance the performance of a model
in the library.

Harvey

On 4/14/2025 2:59 PM, gene heskett via Discuss wrote:

On 4/14/25 13:12, Harvey white via Discuss wrote:

When using a linear rail, there's no (that I know of) graceful way to
control the slide position.  The carriage can be positioned off the
rail at either end.  There's also no model for a dual carriage rail.

Niether is there a dual rail config, but I have 2 printers with dual
rails, top and bottom of a 20x20 carbon fiber tube. Takes no change in
the slicer or klipper.cfg because of that.

using the function limit, the following functions can be built. Note
that these functions take into account the carriage type.

A single carriage rail needs limit1:

function limit1(len, slide_position, carriage = MGN12H_carriage) =
limit(len - limit(slide_position,0,len-1*carriage[1]), 0,
len)-len/2-carriage[1]/2 ;

where len is the slide length.

Why are you worried about that, this is a printer slicer & driver.cfg
problem. most drivers will, if properly configured for that printer,
either move an off bed gcode file back to the center of the bed, and
yell bloody murder if its still beyond the printers limits.
Configure your slicer.  Use OpenSCAD to lay the part at 45 degrees on
the bed to gain additional length.

The carriage cannot be positioned beyond the ends, and the carriage
length is taken into account.

If the position is less than zero, then zero is used.  If position is
greater than the slide length, then the slide is positioned to the end.

a dual carriage needs to take into account both slides and the
distance between them.

function limit2(len, slide_position, carriage = MGN12H_carriage,
separation = 1) =
limit(len -
limit(slide_position,0,len-2*carriage[1]-separation/2), 0,
len)-len/2-carriage[1]/2 ;

len is the slide length, the separation is the distance between the
two slides.

// ************************* single carriage calling example


// single carriage

// ypos is processed here.  xpos is passed to a cross slide (dual
carriage)

module left_top_rail(ypos = 0, length = 550, slide = 500, xpos = 0)
{

 // allow reassignment, slide is total permissible travel of

carriage (ex: 500 mm slide, real travel is less)

 y1pos = limit1(slide, ypos);


 difference()
 {
     union()
     {
         color("DeepSkyBlue") translate([0.0 *

extrusion_width(E2040),0 *
extrusion_width(E2040),0*extrusion_width(E2040)])
rotate([0,0,0])Erail(E2040,length);

      // standard implementation of slide, where slide is as

above, y1pos is processed value

         translate([slide/2 + (length-slide)/2

,0,1*extrusion_width(E2040)])rotate([0,0,180])
rail_assembly(MGN12H_carriage,slide, y1pos);

     // these are fixed to slide and move with carriage position
         translate([25 +slide/2 - y1pos,0,35])
         {
             belt_clamp_assembly(1);
             translate([0,0,11.9]) cross_clamp();
             translate([-0,-107,14.0]) rotate([0,0,90]) x_rail(xpos);
         }
     }
     union()
     {
     }
 }

}

// ************************* dual carriage calling example


module x_rail(xpos = 0, length = 700, slide = 500)
{
x1pos = limit2 (slide, xpos, MGN12H_carriage, 20);

   translate([slide/2 + (length-slide)/2 +40

,0,1*extrusion_width(E2020)])rotate([0,0,180])
// carriage, length, position, separation
rail_assembly2(MGN12H_carriage,slide, x1pos, 10);
}

// ************************* code to add


// copied from nopSCADlib
function limit(x, min, max) = max(min(x, max), min);

// single slide limit
// given a linear slide of len, and a slide position from 0 to len
(maximum extent)
// keep slide from going below 0, and beyond end of rail. Compensate
for carriage length.

function limit1(len, slide_position, carriage = MGN12H_carriage,
separation = 0) =
limit(len - limit(slide_position,0,len-1*carriage[1]), 0,
len)-len/2-carriage[1]/2 ;

// dual slide limit
// given a linear slide of len, and a slide position from 0 to len
(maximum extent)
// keep slide pair from going below 0, and beyond end of rail.
Compensate for carriage length and
// space between carriages.

function limit2(len, slide_position, carriage = MGN12H_carriage,
separation = 1) =
limit(len -
limit(slide_position,0,len-2*carriage[1]-separation/2), 0,
len)-len/2-carriage[1]/2 ;

// does dual carriage linear rail
// same as rail_assembly, but
// parameters are carriage, length, position (as standard) but also
add separation (default = 1)
// change limit parameters to add carriage and separation

module rail_assembly2(carriage, length, pos = 0, separation = 1,
carriage_end_colour = grey(20), carriage_wiper_colour = grey(20))
{
//! Rail and carriage assembly
rail(carriage_rail(carriage), length);

 translate([(pos - (carriage[1] + separation)), 0])
     carriage(carriage, carriage_end_colour, carriage_wiper_colour);

 translate([pos, 0])
     carriage(carriage, carriage_end_colour, carriage_wiper_colour);

}

Hope this proves useful:  I'd like to see it added to the rails.scad
library.

Harvey

If I ever needed more than one color, I'd put a box turtle on that
printer.


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

Cheers, Gene Heskett, CET.


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

I use the rails in a 3D printer and the travel is calculated from the build area and not the physical limits of the rail. I just assert if the required travel is more than the rail can supply, which is available with carriage_travel(). assert(X_travel <= carriage_travel(X_carriage, X_rail_length), "X rail too short"); assert(Y_travel <= carriage_travel(Y_carriage, Y_rail_length), "Y rail too short"); When it comes to adding extra carriages, etc, I don't think it should be in the library because there are many ways of combining rails and carriages. On Mon, 14 Apr 2025 at 20:57, Harvey white via Discuss < discuss@lists.openscad.org> wrote: > I see I did not explain myself well enough. > > This is being used in a form/fit model of a pick and place machine. I > do openSCAD models before I build something suitably mechanical. Yes, > indeed, the real world mechanism has mechanical stops and optical > sensors for carriage (x, y, z) limits, both the home and limit types. > > Slicer and the like do not apply in this design. I do plan to use > OpenPNP to make things run. > > The dual rail configuration can be easily done by simply specifying two > rails and feeding the same position to both. > > This is a general solution to perhaps enhance the performance of a model > in the library. > > Harvey > > > > > On 4/14/2025 2:59 PM, gene heskett via Discuss wrote: > > On 4/14/25 13:12, Harvey white via Discuss wrote: > >> When using a linear rail, there's no (that I know of) graceful way to > >> control the slide position. The carriage can be positioned off the > >> rail at either end. There's also no model for a dual carriage rail. > > Niether is there a dual rail config, but I have 2 printers with dual > > rails, top and bottom of a 20x20 carbon fiber tube. Takes no change in > > the slicer or klipper.cfg because of that. > >> > >> > >> using the function limit, the following functions can be built. Note > >> that these functions take into account the carriage type. > >> > >> A single carriage rail needs limit1: > >> > >> function limit1(len, slide_position, carriage = MGN12H_carriage) = > >> limit(len - limit(slide_position,0,len-1*carriage[1]), 0, > >> len)-len/2-carriage[1]/2 ; > >> > >> where len is the slide length. > > Why are you worried about that, this is a printer slicer & driver.cfg > > problem. most drivers will, if properly configured for that printer, > > either move an off bed gcode file back to the center of the bed, and > > yell bloody murder if its still beyond the printers limits. > > Configure your slicer. Use OpenSCAD to lay the part at 45 degrees on > > the bed to gain additional length. > >> > >> > >> The carriage cannot be positioned beyond the ends, and the carriage > >> length is taken into account. > >> > >> If the position is less than zero, then zero is used. If position is > >> greater than the slide length, then the slide is positioned to the end. > >> > >> a dual carriage needs to take into account both slides and the > >> distance between them. > >> > >> function limit2(len, slide_position, carriage = MGN12H_carriage, > >> separation = 1) = > >> limit(len - > >> limit(slide_position,0,len-2*carriage[1]-separation/2), 0, > >> len)-len/2-carriage[1]/2 ; > >> > >> len is the slide length, the separation is the distance between the > >> two slides. > >> > >> // ************************* single carriage calling example > >> ********************************** > >> > >> // single carriage > >> > >> // ypos is processed here. xpos is passed to a cross slide (dual > >> carriage) > >> > >> module left_top_rail(ypos = 0, length = 550, slide = 500, xpos = 0) > >> { > >> > >> // allow reassignment, slide is total permissible travel of > >> carriage (ex: 500 mm slide, real travel is less) > >> > >> y1pos = limit1(slide, ypos); > >> > >> > >> difference() > >> { > >> union() > >> { > >> color("DeepSkyBlue") translate([0.0 * > >> extrusion_width(E2040),0 * > >> extrusion_width(E2040),0*extrusion_width(E2040)]) > >> rotate([0,0,0])Erail(E2040,length); > >> > >> // standard implementation of slide, where slide is as > >> above, y1pos is processed value > >> > >> translate([slide/2 + (length-slide)/2 > >> ,0,1*extrusion_width(E2040)])rotate([0,0,180]) > >> rail_assembly(MGN12H_carriage,slide, y1pos); > >> > >> // these are fixed to slide and move with carriage position > >> translate([25 +slide/2 - y1pos,0,35]) > >> { > >> belt_clamp_assembly(1); > >> translate([0,0,11.9]) cross_clamp(); > >> translate([-0,-107,14.0]) rotate([0,0,90]) x_rail(xpos); > >> } > >> } > >> union() > >> { > >> } > >> } > >> > >> } > >> > >> // ************************* dual carriage calling example > >> ********************************** > >> > >> module x_rail(xpos = 0, length = 700, slide = 500) > >> { > >> x1pos = limit2 (slide, xpos, MGN12H_carriage, 20); > >> > >> translate([slide/2 + (length-slide)/2 +40 > >> ,0,1*extrusion_width(E2020)])rotate([0,0,180]) > >> // carriage, length, position, separation > >> rail_assembly2(MGN12H_carriage,slide, x1pos, 10); > >> } > >> > >> // ************************* code to add > >> *********************************************** > >> > >> // copied from nopSCADlib > >> function limit(x, min, max) = max(min(x, max), min); > >> > >> // single slide limit > >> // given a linear slide of len, and a slide position from 0 to len > >> (maximum extent) > >> // keep slide from going below 0, and beyond end of rail. Compensate > >> for carriage length. > >> > >> function limit1(len, slide_position, carriage = MGN12H_carriage, > >> separation = 0) = > >> limit(len - limit(slide_position,0,len-1*carriage[1]), 0, > >> len)-len/2-carriage[1]/2 ; > >> > >> // dual slide limit > >> // given a linear slide of len, and a slide position from 0 to len > >> (maximum extent) > >> // keep slide pair from going below 0, and beyond end of rail. > >> Compensate for carriage length and > >> // space between carriages. > >> > >> > >> function limit2(len, slide_position, carriage = MGN12H_carriage, > >> separation = 1) = > >> limit(len - > >> limit(slide_position,0,len-2*carriage[1]-separation/2), 0, > >> len)-len/2-carriage[1]/2 ; > >> > >> > >> > >> // does dual carriage linear rail > >> // same as rail_assembly, but > >> // parameters are carriage, length, position (as standard) but also > >> add separation (default = 1) > >> // change limit parameters to add carriage and separation > >> > >> module rail_assembly2(carriage, length, pos = 0, separation = 1, > >> carriage_end_colour = grey(20), carriage_wiper_colour = grey(20)) > >> { > >> //! Rail and carriage assembly > >> rail(carriage_rail(carriage), length); > >> > >> translate([(pos - (carriage[1] + separation)), 0]) > >> carriage(carriage, carriage_end_colour, carriage_wiper_colour); > >> > >> translate([pos, 0]) > >> carriage(carriage, carriage_end_colour, carriage_wiper_colour); > >> } > >> > >> Hope this proves useful: I'd like to see it added to the rails.scad > >> library. > >> > >> Harvey > >> > > If I ever needed more than one color, I'd put a box turtle on that > > printer. > >> > >> _______________________________________________ > >> OpenSCAD mailing list > >> To unsubscribe send an email to discuss-leave@lists.openscad.org > > > > Cheers, Gene Heskett, CET. > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org >
GH
gene heskett
Mon, Apr 14, 2025 9:44 PM

On 4/14/25 15:57, Harvey white via Discuss wrote:

I see I did not explain myself well enough.

This is being used in a form/fit model of a pick and place machine.  I
do openSCAD models before I build something suitably mechanical.  Yes,
indeed, the real world mechanism has mechanical stops and optical
sensors for carriage (x, y, z) limits, both the home and limit types.

Slicer and the like do not apply in this design.  I do plan to use
OpenPNP to make things run.

The dual rail configuration can be easily done by simply specifying
two rails and feeding the same position to both.

This is a general solution to perhaps enhance the performance of a
model in the library.

Harvey

Better explanation involving stuff I've never used. Thank you.  My stuff
is sliced from a .3mf & sent directly to a printer which is unlike any
other printer on the planet. Was an Ender 5 plus 4 years ago, but the
only OEM parts are about 80% of the frame. All the Y parts are now
carbon fiber to reduce weight, X&Y motors are now closed loop
stepper/servo's running on 72 volts, bed now heated with an 800 watt 32
volt psu. Runs around 10x faster than OOTB. prints PC like it was PLA.

On 4/14/2025 2:59 PM, gene heskett via Discuss wrote:

On 4/14/25 13:12, Harvey white via Discuss wrote:

When using a linear rail, there's no (that I know of) graceful way
to control the slide position. The carriage can be positioned off
the rail at either end. There's also no model for a dual carriage rail.

Niether is there a dual rail config, but I have 2 printers with dual
rails, top and bottom of a 20x20 carbon fiber tube. Takes no change
in the slicer or klipper.cfg because of that.

using the function limit, the following functions can be built. Note
that these functions take into account the carriage type.

A single carriage rail needs limit1:

function limit1(len, slide_position, carriage = MGN12H_carriage) =
    limit(len - limit(slide_position,0,len-1*carriage[1]), 0,
len)-len/2-carriage[1]/2 ;

where len is the slide length.

Why are you worried about that, this is a printer slicer & driver.cfg
problem. most drivers will, if properly configured for that printer,
either move an off bed gcode file back to the center of the bed, and
yell bloody murder if its still beyond the printers limits. 
 Configure your slicer.  Use OpenSCAD to lay the part at 45 degrees
on the bed to gain additional length.

The carriage cannot be positioned beyond the ends, and the carriage
length is taken into account.

If the position is less than zero, then zero is used.  If position
is greater than the slide length, then the slide is positioned to
the end.

a dual carriage needs to take into account both slides and the
distance between them.

function limit2(len, slide_position, carriage = MGN12H_carriage,
separation = 1) =
    limit(len -
limit(slide_position,0,len-2*carriage[1]-separation/2), 0,
len)-len/2-carriage[1]/2 ;

len is the slide length, the separation is the distance between the
two slides.

// ************************* single carriage calling example


// single carriage

// ypos is processed here.  xpos is passed to a cross slide (dual
carriage)

module left_top_rail(ypos = 0, length = 550, slide = 500, xpos = 0)
{

    // allow reassignment, slide is total permissible travel of
carriage (ex: 500 mm slide, real travel is less)

    y1pos = limit1(slide, ypos);

    difference()
    {
        union()
        {
            color("DeepSkyBlue") translate([0.0 *
extrusion_width(E2040),0 *
extrusion_width(E2040),0*extrusion_width(E2040)])
                    rotate([0,0,0])Erail(E2040,length);

         // standard implementation of slide, where slide is as
above, y1pos is processed value

            translate([slide/2 + (length-slide)/2
,0,1*extrusion_width(E2040)])rotate([0,0,180])
                rail_assembly(MGN12H_carriage,slide, y1pos);

        // these are fixed to slide and move with carriage position
            translate([25 +slide/2 - y1pos,0,35])
            {
                belt_clamp_assembly(1);
                translate([0,0,11.9]) cross_clamp();
                translate([-0,-107,14.0]) rotate([0,0,90])
x_rail(xpos);
            }
        }
        union()
        {
        }
    }

}

// ************************* dual carriage calling example


module x_rail(xpos = 0, length = 700, slide = 500)
{
    x1pos = limit2 (slide, xpos, MGN12H_carriage, 20);

      translate([slide/2 + (length-slide)/2 +40
,0,1*extrusion_width(E2020)])rotate([0,0,180])
      // carriage, length, position, separation
      rail_assembly2(MGN12H_carriage,slide, x1pos, 10);
}

// ************************* code to add


// copied from nopSCADlib
function limit(x, min, max) = max(min(x, max), min);

// single slide limit
// given a linear slide of len, and a slide position from 0 to len
(maximum extent)
// keep slide from going below 0, and beyond end of rail. Compensate
for carriage length.

function limit1(len, slide_position, carriage = MGN12H_carriage,
separation = 0) =
    limit(len - limit(slide_position,0,len-1*carriage[1]), 0,
len)-len/2-carriage[1]/2 ;

// dual slide limit
// given a linear slide of len, and a slide position from 0 to len
(maximum extent)
// keep slide pair from going below 0, and beyond end of rail.
Compensate for carriage length and
// space between carriages.

function limit2(len, slide_position, carriage = MGN12H_carriage,
separation = 1) =
    limit(len -
limit(slide_position,0,len-2*carriage[1]-separation/2), 0,
len)-len/2-carriage[1]/2 ;

// does dual carriage linear rail
// same as rail_assembly, but
// parameters are carriage, length, position (as standard) but also
add separation (default = 1)
// change limit parameters to add carriage and separation

module rail_assembly2(carriage, length, pos = 0, separation = 1,
carriage_end_colour = grey(20), carriage_wiper_colour = grey(20))
{
    //! Rail and carriage assembly
    rail(carriage_rail(carriage), length);

    translate([(pos - (carriage[1] + separation)), 0])
        carriage(carriage, carriage_end_colour, carriage_wiper_colour);

    translate([pos, 0])
        carriage(carriage, carriage_end_colour, carriage_wiper_colour);
}

Hope this proves useful:  I'd like to see it added to the rails.scad
library.

Harvey

If I ever needed more than one color, I'd put a box turtle on that
printer.


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

Cheers, Gene Heskett, CET.


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

Cheers, Gene Heskett, CET.

"There are four boxes to be used in defense of liberty:
soap, ballot, jury, and ammo. Please use in that order."
-Ed Howdershelt (Author, 1940)
If we desire respect for the law, we must first make the law respectable.

  • Louis D. Brandeis
On 4/14/25 15:57, Harvey white via Discuss wrote: > I see I did not explain myself well enough. > > This is being used in a form/fit model of a pick and place machine.  I > do openSCAD models before I build something suitably mechanical.  Yes, > indeed, the real world mechanism has mechanical stops and optical > sensors for carriage (x, y, z) limits, both the home and limit types. > > Slicer and the like do not apply in this design.  I do plan to use > OpenPNP to make things run. > > The dual rail configuration can be easily done by simply specifying > two rails and feeding the same position to both. > > This is a general solution to perhaps enhance the performance of a > model in the library. > > Harvey Better explanation involving stuff I've never used. Thank you.  My stuff is sliced from a .3mf & sent directly to a printer which is unlike any other printer on the planet. Was an Ender 5 plus 4 years ago, but the only OEM parts are about 80% of the frame. All the Y parts are now carbon fiber to reduce weight, X&Y motors are now closed loop stepper/servo's running on 72 volts, bed now heated with an 800 watt 32 volt psu. Runs around 10x faster than OOTB. prints PC like it was PLA. > > On 4/14/2025 2:59 PM, gene heskett via Discuss wrote: >> On 4/14/25 13:12, Harvey white via Discuss wrote: >>> When using a linear rail, there's no (that I know of) graceful way >>> to control the slide position. The carriage can be positioned off >>> the rail at either end. There's also no model for a dual carriage rail. >> Niether is there a dual rail config, but I have 2 printers with dual >> rails, top and bottom of a 20x20 carbon fiber tube. Takes no change >> in the slicer or klipper.cfg because of that. >>> >>> >>> using the function limit, the following functions can be built. Note >>> that these functions take into account the carriage type. >>> >>> A single carriage rail needs limit1: >>> >>> function limit1(len, slide_position, carriage = MGN12H_carriage) = >>>     limit(len - limit(slide_position,0,len-1*carriage[1]), 0, >>> len)-len/2-carriage[1]/2 ; >>> >>> where len is the slide length. >> Why are you worried about that, this is a printer slicer & driver.cfg >> problem. most drivers will, if properly configured for that printer, >> either move an off bed gcode file back to the center of the bed, and >> yell bloody murder if its still beyond the printers limits.  >>  Configure your slicer.  Use OpenSCAD to lay the part at 45 degrees >> on the bed to gain additional length. >>> >>> >>> The carriage cannot be positioned beyond the ends, and the carriage >>> length is taken into account. >>> >>> If the position is less than zero, then zero is used.  If position >>> is greater than the slide length, then the slide is positioned to >>> the end. >>> >>> a dual carriage needs to take into account both slides and the >>> distance between them. >>> >>> function limit2(len, slide_position, carriage = MGN12H_carriage, >>> separation = 1) = >>>     limit(len - >>> limit(slide_position,0,len-2*carriage[1]-separation/2), 0, >>> len)-len/2-carriage[1]/2 ; >>> >>> len is the slide length, the separation is the distance between the >>> two slides. >>> >>> // ************************* single carriage calling example >>> ********************************** >>> >>> // single carriage >>> >>> // ypos is processed here.  xpos is passed to a cross slide (dual >>> carriage) >>> >>> module left_top_rail(ypos = 0, length = 550, slide = 500, xpos = 0) >>> { >>> >>>     // allow reassignment, slide is total permissible travel of >>> carriage (ex: 500 mm slide, real travel is less) >>> >>>     y1pos = limit1(slide, ypos); >>> >>> >>>     difference() >>>     { >>>         union() >>>         { >>>             color("DeepSkyBlue") translate([0.0 * >>> extrusion_width(E2040),0 * >>> extrusion_width(E2040),0*extrusion_width(E2040)]) >>>                     rotate([0,0,0])Erail(E2040,length); >>> >>>          // standard implementation of slide, where slide is as >>> above, y1pos is processed value >>> >>>             translate([slide/2 + (length-slide)/2 >>> ,0,1*extrusion_width(E2040)])rotate([0,0,180]) >>>                 rail_assembly(MGN12H_carriage,slide, y1pos); >>> >>>         // these are fixed to slide and move with carriage position >>>             translate([25 +slide/2 - y1pos,0,35]) >>>             { >>>                 belt_clamp_assembly(1); >>>                 translate([0,0,11.9]) cross_clamp(); >>>                 translate([-0,-107,14.0]) rotate([0,0,90]) >>> x_rail(xpos); >>>             } >>>         } >>>         union() >>>         { >>>         } >>>     } >>> >>> } >>> >>> // ************************* dual carriage calling example >>> ********************************** >>> >>> module x_rail(xpos = 0, length = 700, slide = 500) >>> { >>>     x1pos = limit2 (slide, xpos, MGN12H_carriage, 20); >>> >>>       translate([slide/2 + (length-slide)/2 +40 >>> ,0,1*extrusion_width(E2020)])rotate([0,0,180]) >>>       // carriage, length, position, separation >>>       rail_assembly2(MGN12H_carriage,slide, x1pos, 10); >>> } >>> >>> // ************************* code to add >>> *********************************************** >>> >>> // copied from nopSCADlib >>> function limit(x, min, max) = max(min(x, max), min); >>> >>> // single slide limit >>> // given a linear slide of len, and a slide position from 0 to len >>> (maximum extent) >>> // keep slide from going below 0, and beyond end of rail. Compensate >>> for carriage length. >>> >>> function limit1(len, slide_position, carriage = MGN12H_carriage, >>> separation = 0) = >>>     limit(len - limit(slide_position,0,len-1*carriage[1]), 0, >>> len)-len/2-carriage[1]/2 ; >>> >>> // dual slide limit >>> // given a linear slide of len, and a slide position from 0 to len >>> (maximum extent) >>> // keep slide pair from going below 0, and beyond end of rail. >>> Compensate for carriage length and >>> // space between carriages. >>> >>> >>> function limit2(len, slide_position, carriage = MGN12H_carriage, >>> separation = 1) = >>>     limit(len - >>> limit(slide_position,0,len-2*carriage[1]-separation/2), 0, >>> len)-len/2-carriage[1]/2 ; >>> >>> >>> >>> // does dual carriage linear rail >>> // same as rail_assembly, but >>> // parameters are carriage, length, position (as standard) but also >>> add separation (default = 1) >>> // change limit parameters to add carriage and separation >>> >>> module rail_assembly2(carriage, length, pos = 0, separation = 1, >>> carriage_end_colour = grey(20), carriage_wiper_colour = grey(20)) >>> { >>>     //! Rail and carriage assembly >>>     rail(carriage_rail(carriage), length); >>> >>>     translate([(pos - (carriage[1] + separation)), 0]) >>>         carriage(carriage, carriage_end_colour, carriage_wiper_colour); >>> >>>     translate([pos, 0]) >>>         carriage(carriage, carriage_end_colour, carriage_wiper_colour); >>> } >>> >>> Hope this proves useful:  I'd like to see it added to the rails.scad >>> library. >>> >>> Harvey >>> >> If I ever needed more than one color, I'd put a box turtle on that >> printer. >>> >>> _______________________________________________ >>> OpenSCAD mailing list >>> To unsubscribe send an email to discuss-leave@lists.openscad.org >> >> Cheers, Gene Heskett, CET. > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org Cheers, Gene Heskett, CET. -- "There are four boxes to be used in defense of liberty: soap, ballot, jury, and ammo. Please use in that order." -Ed Howdershelt (Author, 1940) If we desire respect for the law, we must first make the law respectable. - Louis D. Brandeis
HW
Harvey white
Mon, Apr 14, 2025 11:51 PM

I do at least three different things with openSCAD:

  1. more or less standard 3D model making.  Some of those pieces are
    parts of something else.

  2. treat openSCAD as a modeler without necessarily 3D printing much.  In
    the latest case, I'm using nophead's libraries with a bit of
    modification to generate mechanical visualizations of a design.  Quite
    useful to get an idea of what something will look like, whether the
    pieces interfere with each other, etc.  I can use openSCAD to design
    cases for PC board projects.

  3. the third is to take a .brd file from the EAGLE PC board designer,
    and produce an openSCAD model from that.  The model of the board can be
    used to design cases that properly fit the board.

Harvey

On 4/14/2025 5:44 PM, gene heskett via Discuss wrote:

On 4/14/25 15:57, Harvey white via Discuss wrote:

I see I did not explain myself well enough.

This is being used in a form/fit model of a pick and place machine. 
I do openSCAD models before I build something suitably mechanical. 
Yes, indeed, the real world mechanism has mechanical stops and
optical sensors for carriage (x, y, z) limits, both the home and
limit types.

Slicer and the like do not apply in this design.  I do plan to use
OpenPNP to make things run.

The dual rail configuration can be easily done by simply specifying
two rails and feeding the same position to both.

This is a general solution to perhaps enhance the performance of a
model in the library.

Harvey

Better explanation involving stuff I've never used. Thank you.  My
stuff is sliced from a .3mf & sent directly to a printer which is
unlike any other printer on the planet. Was an Ender 5 plus 4 years
ago, but the only OEM parts are about 80% of the frame. All the Y
parts are now carbon fiber to reduce weight, X&Y motors are now closed
loop stepper/servo's running on 72 volts, bed now heated with an 800
watt 32 volt psu. Runs around 10x faster than OOTB. prints PC like it
was PLA.

On 4/14/2025 2:59 PM, gene heskett via Discuss wrote:

On 4/14/25 13:12, Harvey white via Discuss wrote:

When using a linear rail, there's no (that I know of) graceful way
to control the slide position. The carriage can be positioned off
the rail at either end. There's also no model for a dual carriage
rail.

Niether is there a dual rail config, but I have 2 printers with dual
rails, top and bottom of a 20x20 carbon fiber tube. Takes no change
in the slicer or klipper.cfg because of that.

using the function limit, the following functions can be built.
Note that these functions take into account the carriage type.

A single carriage rail needs limit1:

function limit1(len, slide_position, carriage = MGN12H_carriage) =
    limit(len - limit(slide_position,0,len-1*carriage[1]), 0,
len)-len/2-carriage[1]/2 ;

where len is the slide length.

Why are you worried about that, this is a printer slicer &
driver.cfg problem. most drivers will, if properly configured for
that printer, either move an off bed gcode file back to the center
of the bed, and yell bloody murder if its still beyond the printers
limits.   Configure your slicer.  Use OpenSCAD to lay the part at 45
degrees on the bed to gain additional length.

The carriage cannot be positioned beyond the ends, and the carriage
length is taken into account.

If the position is less than zero, then zero is used.  If position
is greater than the slide length, then the slide is positioned to
the end.

a dual carriage needs to take into account both slides and the
distance between them.

function limit2(len, slide_position, carriage = MGN12H_carriage,
separation = 1) =
    limit(len -
limit(slide_position,0,len-2*carriage[1]-separation/2), 0,
len)-len/2-carriage[1]/2 ;

len is the slide length, the separation is the distance between the
two slides.

// ************************* single carriage calling example


// single carriage

// ypos is processed here.  xpos is passed to a cross slide (dual
carriage)

module left_top_rail(ypos = 0, length = 550, slide = 500, xpos = 0)
{

    // allow reassignment, slide is total permissible travel of
carriage (ex: 500 mm slide, real travel is less)

    y1pos = limit1(slide, ypos);

    difference()
    {
        union()
        {
            color("DeepSkyBlue") translate([0.0 *
extrusion_width(E2040),0 *
extrusion_width(E2040),0*extrusion_width(E2040)])
                    rotate([0,0,0])Erail(E2040,length);

         // standard implementation of slide, where slide is as
above, y1pos is processed value

            translate([slide/2 + (length-slide)/2
,0,1*extrusion_width(E2040)])rotate([0,0,180])
                rail_assembly(MGN12H_carriage,slide, y1pos);

        // these are fixed to slide and move with carriage position
            translate([25 +slide/2 - y1pos,0,35])
            {
                belt_clamp_assembly(1);
                translate([0,0,11.9]) cross_clamp();
                translate([-0,-107,14.0]) rotate([0,0,90])
x_rail(xpos);
            }
        }
        union()
        {
        }
    }

}

// ************************* dual carriage calling example


module x_rail(xpos = 0, length = 700, slide = 500)
{
    x1pos = limit2 (slide, xpos, MGN12H_carriage, 20);

      translate([slide/2 + (length-slide)/2 +40
,0,1*extrusion_width(E2020)])rotate([0,0,180])
      // carriage, length, position, separation
      rail_assembly2(MGN12H_carriage,slide, x1pos, 10);
}

// ************************* code to add


// copied from nopSCADlib
function limit(x, min, max) = max(min(x, max), min);

// single slide limit
// given a linear slide of len, and a slide position from 0 to len
(maximum extent)
// keep slide from going below 0, and beyond end of rail.
Compensate for carriage length.

function limit1(len, slide_position, carriage = MGN12H_carriage,
separation = 0) =
    limit(len - limit(slide_position,0,len-1*carriage[1]), 0,
len)-len/2-carriage[1]/2 ;

// dual slide limit
// given a linear slide of len, and a slide position from 0 to len
(maximum extent)
// keep slide pair from going below 0, and beyond end of rail.
Compensate for carriage length and
// space between carriages.

function limit2(len, slide_position, carriage = MGN12H_carriage,
separation = 1) =
    limit(len -
limit(slide_position,0,len-2*carriage[1]-separation/2), 0,
len)-len/2-carriage[1]/2 ;

// does dual carriage linear rail
// same as rail_assembly, but
// parameters are carriage, length, position (as standard) but also
add separation (default = 1)
// change limit parameters to add carriage and separation

module rail_assembly2(carriage, length, pos = 0, separation = 1,
carriage_end_colour = grey(20), carriage_wiper_colour = grey(20))
{
    //! Rail and carriage assembly
    rail(carriage_rail(carriage), length);

    translate([(pos - (carriage[1] + separation)), 0])
        carriage(carriage, carriage_end_colour,
carriage_wiper_colour);

    translate([pos, 0])
        carriage(carriage, carriage_end_colour,
carriage_wiper_colour);
}

Hope this proves useful:  I'd like to see it added to the
rails.scad library.

Harvey

If I ever needed more than one color, I'd put a box turtle on that
printer.


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

Cheers, Gene Heskett, CET.


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

Cheers, Gene Heskett, CET.

I do at least three different things with openSCAD: 1) more or less standard 3D model making.  Some of those pieces are parts of something else. 2) treat openSCAD as a modeler without necessarily 3D printing much.  In the latest case, I'm using nophead's libraries with a bit of modification to generate mechanical visualizations of a design.  Quite useful to get an idea of what something will look like, whether the pieces interfere with each other, etc.  I can use openSCAD to design cases for PC board projects. 3) the third is to take a .brd file from the EAGLE PC board designer, and produce an openSCAD model from that.  The model of the board can be used to design cases that properly fit the board. Harvey On 4/14/2025 5:44 PM, gene heskett via Discuss wrote: > On 4/14/25 15:57, Harvey white via Discuss wrote: >> I see I did not explain myself well enough. >> >> This is being used in a form/fit model of a pick and place machine.  >> I do openSCAD models before I build something suitably mechanical.  >> Yes, indeed, the real world mechanism has mechanical stops and >> optical sensors for carriage (x, y, z) limits, both the home and >> limit types. >> >> Slicer and the like do not apply in this design.  I do plan to use >> OpenPNP to make things run. >> >> The dual rail configuration can be easily done by simply specifying >> two rails and feeding the same position to both. >> >> This is a general solution to perhaps enhance the performance of a >> model in the library. >> >> Harvey > Better explanation involving stuff I've never used. Thank you.  My > stuff is sliced from a .3mf & sent directly to a printer which is > unlike any other printer on the planet. Was an Ender 5 plus 4 years > ago, but the only OEM parts are about 80% of the frame. All the Y > parts are now carbon fiber to reduce weight, X&Y motors are now closed > loop stepper/servo's running on 72 volts, bed now heated with an 800 > watt 32 volt psu. Runs around 10x faster than OOTB. prints PC like it > was PLA. >> >> On 4/14/2025 2:59 PM, gene heskett via Discuss wrote: >>> On 4/14/25 13:12, Harvey white via Discuss wrote: >>>> When using a linear rail, there's no (that I know of) graceful way >>>> to control the slide position. The carriage can be positioned off >>>> the rail at either end. There's also no model for a dual carriage >>>> rail. >>> Niether is there a dual rail config, but I have 2 printers with dual >>> rails, top and bottom of a 20x20 carbon fiber tube. Takes no change >>> in the slicer or klipper.cfg because of that. >>>> >>>> >>>> using the function limit, the following functions can be built. >>>> Note that these functions take into account the carriage type. > >>>> >>>> A single carriage rail needs limit1: >>>> >>>> function limit1(len, slide_position, carriage = MGN12H_carriage) = >>>>     limit(len - limit(slide_position,0,len-1*carriage[1]), 0, >>>> len)-len/2-carriage[1]/2 ; >>>> >>>> where len is the slide length. >>> Why are you worried about that, this is a printer slicer & >>> driver.cfg problem. most drivers will, if properly configured for >>> that printer, either move an off bed gcode file back to the center >>> of the bed, and yell bloody murder if its still beyond the printers >>> limits.   Configure your slicer.  Use OpenSCAD to lay the part at 45 >>> degrees on the bed to gain additional length. >>>> >>>> >>>> The carriage cannot be positioned beyond the ends, and the carriage >>>> length is taken into account. >>>> >>>> If the position is less than zero, then zero is used.  If position >>>> is greater than the slide length, then the slide is positioned to >>>> the end. >>>> >>>> a dual carriage needs to take into account both slides and the >>>> distance between them. >>>> >>>> function limit2(len, slide_position, carriage = MGN12H_carriage, >>>> separation = 1) = >>>>     limit(len - >>>> limit(slide_position,0,len-2*carriage[1]-separation/2), 0, >>>> len)-len/2-carriage[1]/2 ; >>>> >>>> len is the slide length, the separation is the distance between the >>>> two slides. >>>> >>>> // ************************* single carriage calling example >>>> ********************************** >>>> >>>> // single carriage >>>> >>>> // ypos is processed here.  xpos is passed to a cross slide (dual >>>> carriage) >>>> >>>> module left_top_rail(ypos = 0, length = 550, slide = 500, xpos = 0) >>>> { >>>> >>>>     // allow reassignment, slide is total permissible travel of >>>> carriage (ex: 500 mm slide, real travel is less) >>>> >>>>     y1pos = limit1(slide, ypos); >>>> >>>> >>>>     difference() >>>>     { >>>>         union() >>>>         { >>>>             color("DeepSkyBlue") translate([0.0 * >>>> extrusion_width(E2040),0 * >>>> extrusion_width(E2040),0*extrusion_width(E2040)]) >>>>                     rotate([0,0,0])Erail(E2040,length); >>>> >>>>          // standard implementation of slide, where slide is as >>>> above, y1pos is processed value >>>> >>>>             translate([slide/2 + (length-slide)/2 >>>> ,0,1*extrusion_width(E2040)])rotate([0,0,180]) >>>>                 rail_assembly(MGN12H_carriage,slide, y1pos); >>>> >>>>         // these are fixed to slide and move with carriage position >>>>             translate([25 +slide/2 - y1pos,0,35]) >>>>             { >>>>                 belt_clamp_assembly(1); >>>>                 translate([0,0,11.9]) cross_clamp(); >>>>                 translate([-0,-107,14.0]) rotate([0,0,90]) >>>> x_rail(xpos); >>>>             } >>>>         } >>>>         union() >>>>         { >>>>         } >>>>     } >>>> >>>> } >>>> >>>> // ************************* dual carriage calling example >>>> ********************************** >>>> >>>> module x_rail(xpos = 0, length = 700, slide = 500) >>>> { >>>>     x1pos = limit2 (slide, xpos, MGN12H_carriage, 20); >>>> >>>>       translate([slide/2 + (length-slide)/2 +40 >>>> ,0,1*extrusion_width(E2020)])rotate([0,0,180]) >>>>       // carriage, length, position, separation >>>>       rail_assembly2(MGN12H_carriage,slide, x1pos, 10); >>>> } >>>> >>>> // ************************* code to add >>>> *********************************************** >>>> >>>> // copied from nopSCADlib >>>> function limit(x, min, max) = max(min(x, max), min); >>>> >>>> // single slide limit >>>> // given a linear slide of len, and a slide position from 0 to len >>>> (maximum extent) >>>> // keep slide from going below 0, and beyond end of rail. >>>> Compensate for carriage length. >>>> >>>> function limit1(len, slide_position, carriage = MGN12H_carriage, >>>> separation = 0) = >>>>     limit(len - limit(slide_position,0,len-1*carriage[1]), 0, >>>> len)-len/2-carriage[1]/2 ; >>>> >>>> // dual slide limit >>>> // given a linear slide of len, and a slide position from 0 to len >>>> (maximum extent) >>>> // keep slide pair from going below 0, and beyond end of rail. >>>> Compensate for carriage length and >>>> // space between carriages. >>>> >>>> >>>> function limit2(len, slide_position, carriage = MGN12H_carriage, >>>> separation = 1) = >>>>     limit(len - >>>> limit(slide_position,0,len-2*carriage[1]-separation/2), 0, >>>> len)-len/2-carriage[1]/2 ; >>>> >>>> >>>> >>>> // does dual carriage linear rail >>>> // same as rail_assembly, but >>>> // parameters are carriage, length, position (as standard) but also >>>> add separation (default = 1) >>>> // change limit parameters to add carriage and separation >>>> >>>> module rail_assembly2(carriage, length, pos = 0, separation = 1, >>>> carriage_end_colour = grey(20), carriage_wiper_colour = grey(20)) >>>> { >>>>     //! Rail and carriage assembly >>>>     rail(carriage_rail(carriage), length); >>>> >>>>     translate([(pos - (carriage[1] + separation)), 0]) >>>>         carriage(carriage, carriage_end_colour, >>>> carriage_wiper_colour); >>>> >>>>     translate([pos, 0]) >>>>         carriage(carriage, carriage_end_colour, >>>> carriage_wiper_colour); >>>> } >>>> >>>> Hope this proves useful:  I'd like to see it added to the >>>> rails.scad library. >>>> >>>> Harvey >>>> >>> If I ever needed more than one color, I'd put a box turtle on that >>> printer. >>>> >>>> _______________________________________________ >>>> OpenSCAD mailing list >>>> To unsubscribe send an email to discuss-leave@lists.openscad.org >>> >>> Cheers, Gene Heskett, CET. >> _______________________________________________ >> OpenSCAD mailing list >> To unsubscribe send an email to discuss-leave@lists.openscad.org > > Cheers, Gene Heskett, CET.