pondělí 28. května 2012

OpenScad helper funcions for better tomorrow

While working on various reprapped projects I hacked together some useful functions/modules that I want to show and present their strengths. One of basic building blocks of RP parts are holes, and quite often you want them as accurate as possible - and thanks to nophead we now have formula to make them quite well at http://hydraraptor.blogspot.com/2011/02/polyholes.html

Code in blogpost is:

 
module polyhole(d,h) {
    n = max(round(2 * d),3);
    rotate([0,0,180])
        cylinder(h = h, r = (d / 2) / cos (180 / n), $fn = n);
}


which works, but is not programmer-friendly. Considering its cylinder replacement, it should really work that way - but cylinder has radius as argument, not diameter. Another thing is, its not tab-completition friendly - you have to remember another name, instead of just pressing tab and see. So my fix is

 
// make it interchangeable between this and cylinder
module cylinder_poly(r, h, center=false){
    polyhole(d=r*2, h=h, center=center);
}
 
Now when you have hole and realise that polyhole would fit better the change is as simple as it can be.

Another thing that you learn fast is that sharp coners are bad - they tend not to stick well on heatbed destroying overnight prints and tend to look ugly on high speed prints with quick acceleration, making waves on side that is extruded from corner. Good way (except slowing down prints, but who would want to do that? ;)) is corner rounding, or "fillet". As there is no direct way of rounding corners in OpenScad, some work is to be done. Basic building block here is

 
module fillet(radius, height=100, $fn=16) {                                     
    //this creates negative of fillet,
    //i.e. thing to be substracted from object
    translate([-radius, -radius, -height/2-0.01])
        difference() {
            cube([radius*2, radius*2, height+0.02]);
            cylinder(r=radius, h=height+0.02, $fn=16);
        }
}


Then miracle happens:

module cube_negative_fillet(
        size,
        radius=-1,
        vertical=[3,3,3,3], 
        top=[0,0,0,0],
        bottom=[0,0,0,0],
        $fn=0
    ){

    j=[1,0,1,0];

    for (i=[0:3]) {
        if (radius > -1) {
            rotate([0, 0, 90*i])
                translate([size[1-j[i]]/2, size[j[i]]/2, 0])
                    fillet(radius, size[2], $fn=$fn);
        } else {
            rotate([0, 0, 90*i])
                translate([size[1-j[i]]/2, size[j[i]]/2, 0])
                    fillet(vertical[i], size[2], $fn=$fn);
        }
        rotate([90*i, -90, 0])
            translate([size[2]/2, size[j[i]]/2, 0 ])
                fillet(top[i], size[1-j[i]], $fn=$fn);
        rotate([90*(4-i), 90, 0])
            translate([size[2]/2, size[j[i]]/2, 0])
                fillet(bottom[i], size[1-j[i]], $fn=$fn);
    }
}


and we have object to substract from your creations to round their corners, positioned in the same way as centered cube. By default, it will round vertical corners to 3mm radius. You can round all four vertical edges with parameter radius or, giving 4 member array to vertical, you can control which edge you  want to fillet and how much. You can fillet top side with parameter top too, and of course bottom is there too, even tho it probably will not be nicely printable. (You may use support or pass it $fn=4, then it will have 45deg. chamfer). In all cases, it starts in +x, +y quadrant and goes CCW (first top/bottom fillet crosses +x axis).

Of course, I am lazy so I prepared exact cube replacement:

 
module cube_fillet_inside(
         size,
        radius=-1,
        vertical=[3,3,3,3],
        top=[0,0,0,0],
        bottom=[0,0,0,0],
        $fn=0
    ){
    if (radius == 0) {
        cube(size, center=true);
    } else {
        difference() {
            cube(size, center=true);
            cube_negative_fillet(size, radius, vertical, top, bottom, $fn);
        }
    }
}


module cube_fillet(
        size,
        radius=-1,
        vertical=[3,3,3,3],
        top=[0,0,0,0],
        bottom=[0,0,0,0],
        center=false,
        $fn=0 
    ){
    if (center) {
        cube_fillet_inside(size, radius, vertical, top, bottom, $fn);
    } else {
        translate([size[0]/2, size[1]/2, size[2]/2])
            cube_fillet_inside(size, radius, vertical, top, bottom, $fn);
    }
}


Coming soon: Screws and NEMA stepper interface.
Thanks to nophead, vlnofka and josefprusa

středa 25. ledna 2012

Parcans Hotend, Next Generation

Recently I got my hands on ParCans hotend. Its preproduction version, final version is already on sale (we bought one too) with small cosmetic difference.
Here it is, straight from envelope. In two packs, already nearly assembled and with bunch of spare parts:
Note the PTFE tube sticking from the PEEK. Part of nozzle is inside the tube, pressing it against PEEK and sealing the junction. If you dont loosen your nozzle from heat barrier, that is. 
 
More hot(end)ness:


Wires from the thermistor are thin as hair and their isolation was not not glued well to heat block (at least on the preproduction sample. The final version had them glued/cemented bit better) so I managed to rip them off during installing. There is one spare, but I kapton-taped thermistor from makergear that I had at hand. I also drilled 4.5mm hole in extruder where filament goes and cut off half of the tube, so the filament enters the PTFE tube inside extruder body.

Then piece of wood to hold it in place and lets go!


Ok, not yet. Hotend is really short, around centimeter shorter than my old makergear (makergear extruders are now shorter than they used to be, but this one wins here anyway), so I had to cut my retaining screws.

Comparing to the old makergear hotend I had to go from 228 to 235 degrees to prevent filament stripping when printing infill.

úterý 24. ledna 2012

Future is green, at least at this moment

This is screenshot of experimental gcode viewer. Its based on Kliment's Printrun. Kliment has a version of this already, but as I sacrificed cylinders for speed this one starts quickly - 3 secons to load 60k lines of octocat. Next step is to get the lines colorful;)

Available in export branch here: https://github.com/AxTheB/Printrun

pondělí 16. ledna 2012

Combining infill of different density

Or, more precisely, 100% fill area with sparse infill without any loop in between. Skeinforge, at least I think, cheats here and uses dense infill from loop to loop. Slic3r, on the other hand, fills the areas independently. Its nice, as it saves time and plastic, but can it be done better? I think so.

(this is from x-carriage from Prusa-mendel Iteration II)

If the area is filled as indicated here, ie. first sparse inifill from loop to loop (red), then rest of the fully filled area, resulting part should be stronger, esp. in cases of lash on axes, where borders of independently filled areas may not touch at all. On the other hand it will most probably be uglier, and thus be reserved to "invisible layers".

neděle 8. ledna 2012

Adaptive infill

After hours and hours of watching our reprap at http://brmlab.cz two things come to my mind – first, skeinforge's standard infill pattern is way prettier than any of slic3r's and second - and more important - that none of the infill strategies actually take advantage of the models shape. After reading http://garyhodgson.com/reprap/2012/01/thoughts-on-fill-algorithms/, I decided to write my thoughts on how I think it should be done:

First, divide sliced object into cubes one layer high and for example three extrusion widths in remainig directions (this equals to 33% infill), then count how far is each cube from nearest surface (in all 3 dimensions). Divide cubes into regions, depending on how deep inside the object cubes are. In pictures here you can see 3 regions,[1-2], [3-6],[7-14 which I was too lazy to mark with numbers]


Infill density is then dictated by region, every region border will halve the density:


Next layer is then done same way, but rotated as usual:

Infill that stays in region 1 can then be extruded with lower flowrate (thinner) saving material and lines crossing higher groups can be made increasingly thicker, for really strong internal support. All this should assure that we have strong infill that supports ceilings well, but without using much material. This model can be developed further, for example cubes may be more layers high, making infill be naturally more layers thick – this is similar to what skeinforge does in “skin” plug-in, but as its done by grouping layers and not dividing, it will bring better results. EDIT: Slic3r can already do this with infill_every_layers option.