Monday, 9 June 2014

Why slicers get the dimensions wrong

People using Slic3r often complain that holes come out too small, see forums.reprap.org. This blog post is in reply to the question here.

The issue is not just with round holes (which shrink for reasons I described here) but rectangular or hexagonal holes as well. I got my rectilinear dimensions correct with Skeinforge nearly three years ago and blogged the maths here. I now design exclusively in OpenScad using polyholes to get cylindrical holes the correct size as well.

I have tried Slic3r, Cura and Kisslicer but none of them print the Mendel90 calibration part the right size, so I have stuck with Skeinforge. It is looking a bit old now as Enrique seemed to stop developing it around the time people started saying "Slic3r is nicer", but at least it is stable and has very few bugs.

Looking at the G code produced by Slic3r and Cura, they both assume the extruded outlines have a rectangular cross section. I.e. if I work out the volume of plastic extruded from the E number and feedstock diameter and divide it by the length of the line then I get an area. This is equal to the layer height times the intended filament width and the outline is offset by half the intended filament width. The problem is the filament does not form a rectangle if the edges are not constrained. It forms a rectangle with semi circular ends due to surface tension. The actual width of an outline of a given area is therefore slightly more than it would be if it was a rectangle.
The cross sectional area of a filament with height h and width W is that of a circle with diameter h plus a rectangle of width (W - h) and height h. A = πh2/4 + h(W - h).

Solving for W gives W = A / h + h(1 - π/4).

But slicers output enough filament to fill the rectangle, so A = intended w × h. Substituting that value for A we get W = w + h(1 - π/4). So we have an additional width that is just a fixed multiple of the layer height.
I print a lot of things with 0.4mm layers, so the error is very significant. To fix it in Skeinforge I set the outline flow rate to be enough to fill the rounded rectangle, rather than the full rectangle. I achieve this by setting the "Perimeter Flow Rate Multiplier (ratio)" on the Speed tab. A value equal to the "Perimeter Feed Rate Multipler (ratio)" gives an area equal to the full rectangle. To correct for the fact that it is actually a rounded rectangle one has to multiply the feed rate by the ratio of the areas, which is 1 + (π/4 -1) h / w, a value which only depends on the w / h ratio.
As you can see, when the w / h ratio is high the reduction in flow rate necessary is only about 4%. I assume the reason a lot of people don't notice this is that they use a high w / h ratio and then calibrate a thin wall box, so that the flow rate is low enough to compensate without making the infill too sparse. I generally print with lower values of w / h and prefer to just put in numbers, rather than measure thin wall thickness.

An alternative way to compensate would be to keep the flow rate the same but offset the outline by W/2 instead of w/2. I.e. by an additional h(1 - π/4)/2.

If objects are printed with multiple outlines then the error appears much worse if the inner outlines are printed first working outwards (or the opposite for holes). Looking at the area of plastic this is not obvious mathematically because an additional area of plastic equal to w × h will extend the width by w, preserving the original error but not adding to it.

However, if you consider the practicalities of the process it is obvious that you can't squeeze viscous plastic into the infinitely sharp point under the overhang of the previous outline, particularly when the opposite edge is completely unconstrained. In practice I think you get something like this: -
The plastic that fails to fill the overhang causes the opposite edge to bulge a bit further and this effect then gives the cumulative error that I experience. I don't think the correction factor is easily calculated because it depends on the viscosity of the plastic as well as layer height, etc.

So if you want accurate dimensions and multiple outlines then do the outer perimeter first. For better seam hiding on objects where the dimensions don't matter do the inner perimeters first. I tend to print most things with one outline as you effectively get an extra one free with Skeinforge because it joins the ends of the infill, see hydraraptor.blogspot.co.uk/2008/04/python-beans-make-object.

Tuesday, 11 March 2014

Buried nuts and hanging holes

I needed to make some M4 nuts that could be finger tightened but I didn't have room for a standard wing-nut, so I decided to embed nuts in a printed plastic knob. I knocked up a simple design in OpenScad :-


M4 nuts are nominally 3.2mm thick. I made the base and lid 2.4mm and sliced it with 0.4mm layers. That meant the top of the nut would be flush with a layer boundary at 5.6mm and I confirmed that the first covering layer was at 6.0mm in Skeinlayer. So I needed to pause the build before the start of the layer at Z=6.0 and insert the nuts.

I run my USB machines using Raspberry PIs and OctoPrint (so that all my machines are connected via Ethernet) and noticed a post by the author, Gina Häußge, that said OctoPrint interprets an M0 in the gcode as a pause command. The host stops sending gcode until you press the pause button to un-pause it again. I believe other hosts use @PAUSE to do the same thing.

So M0 is exactly what I needed. The only problem is that up until then I mistakenly thought M0 meant end of program and placed it at the end of the PLA profiles that I distribute. Fortunately the version of Marlin I use ignores it but if you want to use the latest version, or OctoPrint, then you need to remove it from end.gcode, otherwise either the host or the firmware will pause at the end of the print and wait for a button press. Harmless but a bit confusing.

So, armed with a new appreciation of what M0 is, I searched my gcode for the first instance of Z6.0 which looks like this:

F12000.0
G1 X-9.082 Y3.907 Z6.0 F12000.0
G1 X-5.457 Y-3.937 Z6.0 F12000.0
G1 X-7.05 Y-3.803 Z6.0 F12000.0
G1 X-11.486 Y-4.991 Z6.0 F12000.0
G1 X-13.721 Y-10.229 Z6.0 F12000.0
G1 F1800.0
G1 E1.0
G1 F12000.0
M101
G1 X-12.65 Y-10.848 Z6.0 F1837.1615 E0.036

What we have is a sequence of non-extruding moves followed by an un-retract and the first extrusion. The moves are the result of the comb module and not really relevant if we are restarting after a pause, so I removed all but the last move and inserted my pause code:

M104 S100
G1 Z6.0
G1 X-100 Y-100 F9000
M0
G1 X10.0 Y98.0 F9000
G1 Z0.05
M109 S250
G92 E0
G1 E3 F50
G1 E-1 F1200
G1 X40.0 F4000
G1 Z6.0 F9000

G1 X-13.721 Y-10.229 Z6.0 F12000.0
G1 F1800.0
G1 E1.0
G1 F12000.0
M101
G1 X-12.65 Y-10.848 Z6.0 F1837.1615 E0.036

I set the extruder temperature to 100°C to minimise ooze and stop it discolouring while waiting for me to insert the nuts. The bed is left on so the half printed objects don't detach. It then moves up to Z = 6.0 to clear the objects before going to X = -100, Y =-100. That moves the bed to the front and the extruder to the far right on a Mendel90, giving the best access to the partially printed objects. M0 then pauses the program.

I threaded the nuts onto a screw to insert them easily without touching the hot plastic. 



After pressing the pause button to make OctoPrint resume, the print head moves to the front of the bed to do another ooze free warmup. The only difference from the start of the print is it parks the nozzle 10mm further left to avoid the blob it has already made and it moves to Z = 6.0 before resuming the print.

This all worked very well except for a slight snag. ABS does not stick to steel, so when it extruded the circular holes on top of the nuts it made a bit of a mess.



Normally I would use a one layer support diaphragm when printing suspended holes and drill it out afterwards. In this case it can't be drilled because the nut is in the way, so I developed a method of printing holes in mid air. 

The last layer of the nut trap looks like this: 



You can't print a smaller hole on the next layer as the outline would be printed in mid air. The infill is also only attached at one end. After a few layers it does sort itself out but leaves a mess. However, what you can do is print two bridges over the large hole with a gap between them equal to the diameter of the small hole:



This is done by cutting out a one layer rectangle clipped to the hexagon. It is rotated to match the layer's infill direction because Skeinforge fails to detect it as a bridge, probably because the bridged area is tiny.

On the next layer we can bridge in the opposite direction and close down the hole to a square:



Two sides are supported by the edges of the rectangle below and the other two span the gap. 

On the next layer we can approximate the hole with an octagon. Four edges are coincident with the square and the other four span small gaps:



It is now a good enough approximation to a circle for such a small hole so it continues up to the top as an octagon. The resulting print is much neater:



The cavity for the nut is made by subtracting a shape like this: 


Here is the OpenScad code. It needs various functions from the Mendel90 source tree.

//
// Smaller alternative to a wingnut
//
include <conf config.scad>

module hanging_hole(or, ir, ofn = 0) {
    union() {
        intersection() {
            if(ofn)
                cylinder(r = or, h = 3 * layer_height, center = true, $fn = ofn);
            else
                poly_cylinder(r = or, h = 3 * layer_height, center = true);
            rotate([0, 0, 90])
                cube([2 * or + 1, 2 * ir, 2 * layer_height], center = true);
        }
        rotate([0, 0, 90])
            cube([ir * 2, ir * 2, 4 * layer_height + 4 * eta], center = true);

        rotate([0, 0, 22.5])
            translate([0, 0, 2 * layer_height])
                cylinder(r = corrected_radius(ir, 8), h = 100, $fn = 8);
    }
}

base_thickness = 2.4;
lid_thickness = 2.4;

function nut_knob_height(nut) = base_thickness + nut_thickness(nut) + lid_thickness;

module nut_knob_stl(screw = M4_hex_screw, d = 14) {
    nut = screw_nut(screw);
    h = nut_knob_height(nut);
    flutes = 3;

    stl("nut_knob");
    rotate([0, 0, -45])
        difference() {
            cylinder(r = d / 2, h = h);                                                 // basic shape

            for(i = [0 : flutes - 1])                                                   // flutes for finger grip
                rotate([0, 0, i * 360 / flutes + 30])
                    translate([d * cos(90 / flutes), 0, base_thickness])
                        cylinder(r = d / 2, h = 100);

            union() {                                                                   // nut cavity
                difference() {
                    translate([0, 0, base_thickness + nut_thickness(nut)])
                        nut_trap(screw_clearance_radius(screw), nut_radius(nut), nut_thickness(nut));

                    translate([0, 0, base_thickness + nut_thickness(nut)])              // remove top of nut trap
                        cylinder(r = 20, h = 110);
                }

                translate([0, 0, base_thickness + nut_thickness(nut)])
                    hanging_hole(nut_radius(nut), screw_clearance_radius(screw), 6);    // replace with hanging hole
            }

        }
}

So this seems to be a general solution to printing holes in mid air without any support material. The only downside is that it is a bit weaker than using a membrane and drilling it out. In this case no strength above the nut was required. In general you can just make it two layers thicker.

Saturday, 5 October 2013

Mendel90 design improvements

I temporarily suspended kit production for a few weeks in order to have some time to make some improvements to the design. The following improvements apply to kits currently being shipped.

Hot End

It came to light during the hot summer that the top of the J-Head can get too hot for extruding PLA. The problem seems to manifest itself when extruding slowly because it takes longer for the filament to pass through the hex grub screw (which is the Achilles heel of the J-Head because it is wider than the rest of the filament path) and so has enough time to soften and buckle. Ironically it is also more of a problem when extruding at lower temperatures because the filament gets harder to push and so buckles at a lower temperature.

On investigation I found what I had suspected for a long time: that the heat at the top is mainly due to convection rather than conduction. This is easily demonstrated by running the extruder on its side. A lot of people add a second fan but a simple solution is to insulate the heater block. I now wrap it in two turns of silicone "self amalgamating" or "self fusing" tape, which is rated for 260°C. There are several brands but I use E-Z Fuse Tape which is 25mm wide. I stretch 110mm of it around the bottom of the PEEK, just below the bottom vent slots. I then trim it flush with the bottom of the heater block with a pair of scissors.


This makes enough difference to allow it to extrude very slowly without jamming. To cool it further I added a small hole to the fan duct.

A small airflow makes a big difference because it disrupts the convection but it is only active after the first layer when the fan is on.

It is possible to drill the hole to upgrade an old fan duct but straight drilling will spit the layers apart as it is a very thin wall. The way I did it was to melt a hole using a soldering iron with a conical bit set to 200°C. At that temperature you can wipe the ABS off the bit before it has chance to burn and make a mess of it. I then clean up the hole by drilling the melted ring it with a 4.5mm drill and then trim it flush with a penknife.

Another mod I made was to apply a bit more pressure to the idler by adding washers to each end of the springs. The same effect can be achieved by tightening the screws so they go about 1.5mm past the back of the bearing block but I like them flush with the block for an easier reference point.


These three little changes made a big difference and I can now extrude PLA at 185°C, which gives better print quality. I have updated the android gcode I include on the SD card and I have put the new Skeinforge settings on Github.

Settings

Other improvements I made to the settings are: -
The PLA settings were erroneously under the ABS profile, sorry for the confusion. The un-configured profiles have been removed and two new ones: PLA0.3 and PLA0.2 have been added. The android sample is sliced with the 0.3mm layer profile because it is easier to get the Z calibration right with the highest layer height possible with PLA. The 0.2mm profile gives a much nicer print.
The ooze free unattended start was not very reliable with PLA. Lowering the temperature helped but I also improved the extruder priming by extruding a very fat line along the front edge of the bed instead of a blob.
I have come to realise that you get better prints if you do the outlines at the same speed as the infill and looking back I think that is what I have seen commercial machines do. The old profiles had the outlines at 25mm/s and infill at 50mm/s. I now do both at 40mm/s.
The reason it works better is because when the extruder rewinds at the end of one run and then fast forwards the same distance to start another it will restore the same nozzle pressure as it had on the previous run. That means the initial flow rate will be the same, so if the speed has changed it will be too fast or too slow. This leads to blobs on the outline after doing faster infill and gaps at the start of infill after doing slow outlines. 
Another advantage is with a constant flow rate the plug of plastic that forms at the hot end transition zone will be a constant length. If the speed increases the length reduces, which means less of the barrel has plastic expanded to the barrel's diameter and more has it at the original filament diameter. This implies there is less plastic in the barrel, so an excess must have been extruded while the plug was shortening. Conversely when the extrusion rate drops the plug extends so too little plastic will be extruded during that time.
Yet another advantage of using constant flow rate is that the die swell will be constant, so the plastic is always stretched by the same amount. When outlines are done slower the die swell is less, so they are stretched less, and so don't span gaps as well as the infill.
I have set the outline flow rates slightly lower than the infill. Skeinforge's volumetric calculations fill a rectangle equal to the filament width and layer height. This is OK for the infill but the outline does not have a rectangular profile, it has rounded sides, so it comes out a little wider than intended. The error is less when the filament path is wide compared to its height. The correct value is 1 + (π/4 - 1) / (w / h). Using this formula I get dimensionally correct prints instead of outlines that are too big and holes that are too small.
PLA prints better when cooled by the fan but you don't want it cooling the print surface when the first layer is being laid down. Ironically print cooling seems to be more important when extruding at 185°C than at 220°C for reasons I can't yet explain. To be able to automatically turn the fan on at a specified layer I had to incorporate an update to the Cool plugin by DeuxVis and Joost-b plus my own little bug fix. I have put the patched version of Skeinforge50 that I include on the SD card onto Github.

Firmware

I made three small tweaks to the version of Marlin I distribute: -
I reduced the XY acceleration from 4000 to 2000 as the Y axis can lose steps due to resonance in high frequency infill otherwise.
I found that the Y axis would overshoot when homing if the X axis hits the end stop first. This was because the axis moves 40% faster on it own than when moving diagonally. I reduced the homing speeds but multiplied them by 1.4 when moving diagonally. The net effect is diagonal homing is the same speed as before but it now doesn't speed up when one axis stops.
I updated the PID constants for J-Head MK5B as I hadn't changed them from MK4B. It didn't seem to make much difference.

X ends

A few people started reporting the bar clamps on the X motor bracket and the X idler bracket had cracked. I am not sure why this became a problem after hundreds of kits. Some reported they could not get enough tension to pull the belt tight, so perhaps the belt got stiffer, or the plastic parts weaker. I built a kit myself to investigate using a problem belt that one of my customers returned. It was inconclusive because I managed to get the machine printing well without breaking the clamps but I think some belts are stiffer than they were in the first kits, despite coming from the same manufacturer and I also think the plastic parts might not be as strong as they used to be due to ABS supply changing. I tackled the problem from both sides by immediately switching to more flexible belt and then redesigning the X end clamps.

I switched to Brecoflex® belt which has more thinner wires in it and also boasts that it has a better arrangement of strands within each wire. This makes it more flexible without being less strong. The wires are also parallel, whereas cheaper belts have them in a spiral so they meet the edge every so often.

The clamps now only have plastic in compression so are much stronger. They do use a lot more fasteners but because the screws are accessible from above they no longer need to have hex heads, so that is one less type of screw required.


The nut trap for the lead screw is now at the top (don't be fooled by the hexagonal hole at the bottom, that is just clearance to allow the nut to be fitted to the leadscrew first). This greatly increases the distance of the nut from the Z coupling when the Z axis is at the bottom. When the nut was at the bottom it got to within about 10mm so any eccentricity was magnified by about 20 at the top of the leadscrew.

Because holes can't be printed in mid air there are one layer thick support membranes at the bottom and the top of the nut trap. This creates a completely enclosed void which revealed a bug in OpenScad. It generates an STL with the internal faces facing the wrong way, i.e. outwards instead of inwards. Fortunately Skeinforge does not care and slices it correctly but Slic3r doesn't.

Another little tweak to the design was to angle the hole for the idler axle. It is a clearance hole so the belt tension pulls the front of the bolt to the right, which tends to make the belt run to the front of the idler pulley, requiring a shim under the back washer to correct it. The new design angles the bolt hole slightly to correct for this so doesn't require a shim. Here is a cross section showing that when the axle bolt is orthogonal the front rests against the right side of the hole and the nut at the back rests on the left side of its trap.


The X motor bracket has been simplified and made much easier to print. The previous design fastened the motor with three screws at the front and used a box construction to be stiff enough not to bend under the belt tension. The new design has one screw in the back of the motor so that only two are needed at the front leading to a much smaller bracket.


The length of stepper motors has a poor tolerance of ±1mm because it is made from a stack of laminations pressed together. For this reason I couldn't use a normal screw through the plastic. Instead the screw head is packed out with as many washers needed to fill the gap between the motor and the bracket. This will be one if the motor is top tolerance and five if it is bottom tolerance. The hole in the bracket is a snug fit for the head of the screw so it acts as a dowel.


Like the idler, the clearance screw holes for the motor would allow the front to be pulled to the left causing the belt to run to the front of the pulley. The motor holes have been offset by half their clearance to avoid this.

Z couplings

The original Z couplings worked well on all of my machines until I built another one that produced objects with some Z banding. Investigation with a dial gauge showed that the Z position was not increasing linearly leading to uneven layer heights. I found that the lead screw was eccentric leaving the coupling due to the bore of the PVC tubing not being central. Also PVC is more plastic than elastic, so when it is squeezed by the coupling it deforms permanently and does not give much flexibility. The couplings where designed with a gap so it was possible to over tighten them leading to too much constraint. The top needed to be fully closed because the studding has a smaller outside diameter than a normal M6 bolt would have.

To address these issues I switched to neoprene rubber tubing that seems to have the bore more central and is also a lot more flexible. I changed the plastic parts so they can be closed completely to give the correct pressure rather than relying on a gap being maintained. I also made the screw positions diagonally opposite which makes them a bit easier to tighten up.


The only downside to the neoprene is that it doesn't give enough grip to be able to turn the motor manually when it is enabled. To allow bed levelling I changed the Pronterface buttons for back left and back right to disable the motors. The new config file is on Github.

X carriage fan bracket

The length of the J-Head MK5B is incorrect in the Mendel90 model. This makes the fan duct too low and it hits the clips on the bed. A simple solution is to make the slots in the fan bracket deeper so it can be fitted a bit higher. I also added strengthening ribs as the old bracket allowed the duct to droop.

Tube end caps

I reversed the direction of the screws that hold the aluminium tubes onto the base. The nut is now trapped inside the tube by the end cap. This means the tube no longer needs the large holes for the screw head, which greatly reduces the amount of machining I need to do to make them.


The two extra washers are needed at the front to avoid using an additional screw length. The two rear fixing blocks are now different from the others because they don't have a nut trap in the middle position.

Y carriage heat shield

Instead of using aluminium foil to reflect heat I found that simply filling the gap under the bed with multiple layers of corrugated cardboard allows the bed to reach higher temperatures.

Spool Holders

These are now assembled with the large washer on the outside of the spool rather than the inside, requiring four more small washers. This is to accommodate spools that originate from Orbitech that are slightly wider than the ones I used to get.

Kits have been shipping with all these mods for a while now but the time out taken to make the changes led to a backlog and a large waiting list which we have been working flat out to clear and hope to get back to next day dispatch this week.

Friday, 7 December 2012

Mendel90 updates

It has been a long road but I am now in a position to sell complete kits for Mendel90. My original plan was to use laser cut acrylic but the companies I got quotes from could not guarantee the holes sizes would be accurate enough to be tapped. I also found out that 3mm Dibond is stiffer than 6mm acrylic as well as being a lot lighter and cheaper. The downside is that the polyethylene core is too soft and the aluminium wall too thin to tap a thread into reliably. That meant replacing all the screws with nuts and bolts, which made the machine fiddly to put together. To fix that I reversed all the bolts and put nut traps in the plastic parts. The design still supports the MDF and acrylic variants with screws, but I only sell the plastic parts for these.

Picture courtesy of  Alzibiff, a Mendel90 owner who is also a photographer: thefullpicture.co.uk 
Because the underside of the base now has screw heads protruding, the machine has to have some form of feet to raise it. I added two aluminium square tubes, which also provide stiffness as they are directly under the stays. An added  bonus is that the wires for the Y axis can now run underneath the base to improve the appearance. Another advantage is that the printed cable clips can now be replaced by zip ties that go through holes in the panels.

I changed the default electronics from Sanguinololu to Melzi because it includes the SD card interface and fan drive on board and uses screw connectors rather than friction fit. These are the only connectors I have found to be reliable in the long term and it will allow me to offer a no solder version of the kit. After a couple of false starts I now have a reliable source of these and they are 100% functionally tested using the same motors as I provide in the kit.


I also changed the PSU to an ATX500 because I can buy them in the UK with CE approval and they come with integral mains inlet and switch, obviating the need for the kit builder to do their own mains wiring.  It is also shorter, allowing room for the Melzi (which is very long and thin). The downside is it needs a pair of load resistors on the 5V and 3.3V to get the 12V rail to be close to 12V under load. These are provided in the kit.


To stop the deeper power supply sticking out beyond the base I moved the right hand stay inwards. It is now directly behind the  Z bar that it braces, which is better from a structural point of view and gives maximum space for the electronics bay. A couple of plastic brackets hold the ATX PSU in place.


The build height is increased to 200mm as there is very little downside to doing so and it makes room for the Melzi electronics.

I added a spool holder which suspends the spool between the stays on 608 bearings using a couple of triangular brackets.



In order to turn the filament through 90 degrees I use a PTFE Bowden tube. That also has the benefit of removing any drag on the head when the extruder pulls filament from the reel. The only force on the head is that required to bend the loop of filament and the tube, which has only a thin wall.

The end of the tube is terminated by a printed connector with a flange that just sits on top of the extruder. That allows the extruder to reverse without having to push the filament back up the tube.

There is dust wiper on entry to the tube which consists of a block of foam squeezed into a smaller box with the filament running through a slot in the middle. It prevents dust that settles on the spool being dragged into the extruder.


I made a few tweaks to the extruder. I now use J-Head nozzles so I integrated a groove mount into the Wade's block. The nozzle is a tight fit and I press it in with printed jig and a vice with rubber jaws.


After the first five kits I found I could no longer get the J-Head MK4B and had to switch to the MK5B. That isn't long enough for a machine like Mendel90 because the bottom of the carriage ends up too close to the bed. I had to extend the bottom of the Wades' block so that it now protrudes below the carriage. In order to do that I had to make it a little slimmer to fit through the hole and that had the side effect of making the bearing housing symmetrical about the filament path. I think the reason it wasn't before is because there isn't room for the bolt heads on the motor plate side. I solved that by turning the bolts around and using captive nuts in the bearing block. That also makes the springs much easier to fit as the nut engages before the spring has to be compressed. The hob position is now further up the bolt at 25mm meaning more of the shoulder enters the bearing.

Other minor changes were that I lowered the motor a few mm so that it traps the head of the mounting screw  making it easier to fit to the carriage. I also replaced the spring that I used to retain the nut on the hobbed bolt with a lock nut and a star washer. They only need to be finger tight.

In order to be able to offer a solder-less version of the kit I made a tiny break out PCB for the extruder motor and heater connections.


I also made the socket on the end of the X cable an IDC version. That meant the pin to wire connections had to be 1:1, so I had to increase the number of pins from 9 to 15. The heater wires were previously doubled up to handle 2 Amp heaters but now I have enough pins for three wires giving about 4 Amps. There are also wires for a fan and a Z probe.

I simplified the X ribbon cable layout. Previously I had a pair of grounded wires acting as guard between the X limit switch and the noisy motor wires. Instead I simply moved the limit switch wires to the other side of the cable, where the quiet signals are. It actually makes the X end wiring neater and gives me the extra two wires for the extruder heater so that the cable remains 20 way, which is a standard size.


On the subject of ribbon cables: I increased the one for the bed from 24 way to 26 way making that a standard size also and two extra wires for the bed heater is not a bad thing.

In order to be able to print small items and items with steep overhangs in PLA I took a leaf out of Richard Gain's book and added a ducted fan to the carriage. I couldn't use his design directly because he has a longer nozzle mounted in a different orientation. This is my compressed version.


 The exit of the duct produces a ring of air directed inwards. The idea is to direct the air onto the part close to where the new plastic is being laid down without cooling the nozzle.


Because the Melzi only has a single fan output I removed the bed cooling fan but left the hole and fan guard for it. It is something I use to speed up production by cooling the bed rapidly at the end of a build, but the 80mm high airflow fans are expensive. They used to be cheap when they were used in PCs but they have all switched to quiet ones nowadays with less flow. If you want to add one you can hack a MOSFET onto the expansion port of the Melzi and control it with M42 in Marlin.

The OpenScad model now includes everything in the kit, which is everything needed to build the machine apart from some sticky tape used to secure the PTFE tubing. Most things are visible in the rendering but a few generate BOM entries only. These are things like wires and ribbon cables, which are hard to draw. Resistors, thermistors, sleeving and heat shrink are all drawn in places close to where they are used.

Having everything in the model is the only way to keep the BOM 100% accurate. I also re-structured the sub assemblies so that they reflect the order things are assembled rather than their placement in the machine. For example the Z lead nuts were in the X end assemblies because that is where they end up, but when assembling they are fitted to the leadscrews and then inserted into the X ends, so they need to be part of the Z axis assembly.

I created a detailed build manual for the kit in OpenOffice format. It links to a lot of pictures generated by the model so that they automatically update. The manual is also checked into GitHub, so there is a version matching each revision of the machine. I had started with instructions in the Reprap wiki but that soon become impractical as it can only represent a single version and all the images need to be manually updated. It can't link to images on GitHub for instance. Although the manual is for the kit version of the machine, it will also be useful to people making the other versions. The main differences are that different fasteners are used. The PDF version is here.

The first five kits were commissioned for a build a weekend hosted by the GIST lab in Sheffield during the university's Festival of the Mind. Due to various supply problems I only just managed to get all the parts together in time and then only with a lot of help from a couple of friends. I ran out of time completely to do the instructions so I stayed up all night and hacked some together. Despite that the build weekend went well.

Two of the teams completed their machines on day one and were extruding plastic. By the end of day two all the machines were completed, two teams were printing items downloaded from Thingiverse, another was extruding. Unfortunately two were held up by faulty Melzis. I hadn't tested them beforehand because I had five spares, but it turned out one of the originals had a small fault and none of the spares worked at all. Needless to say I won't be using those suppliers again!

The Derby Makers team won the "Golden Spanner Award" awarded for "the best demonstration of the Craft and Magic of Technology". Here they are printing.

Picture courtesy of Derby Maker Glyn Smith.
More pictures of the weekend here.

The build weekend was very helpful for ironing out snags. This lead to tweaks in the design and the instructions being greatly expanded.

Kit details:

Specification

Build volume 200mm x 200mm x 200mm.
Filament 3mm.
Nozzle size 0.4mm.
Footprint 465mm x 419mm.
Height 400mm, with spool 609mm.

Contents

The kit contains everything needed to get printing including ~ 50m of Faberdashery PLA. You will need a PC and some tools to put it together and run it, details at the start of the manual. Some things included in the kit are: -

  • Melzi electronics with Atmega1284P, ROSC shorted for correct microstepping, tested and programmed with Marlin firmware configured for Mendel90
  • Micro SD card for pause free printing, comes pre-loaded with all the software needed to print on Windows (Linux equivalents can be downloaded) and a USB to SD adaptor for direct connection to a PC.
  • 0.4mm J-Head MK5B hot end for 3mm filament, pre-assembled with thermistor, resistor, wires and sleeving.
  • ATX500 PSU with quiet fan and dummy load resistors.
  • USB cable.
  • Prusa MK2 heated bed with 2mm glass sheet.
  • 3mm aluminium composite panels CNC cut and drilled.
  • 5 NEMA17 43Ncm stepper motors.
  • 8mm hardened high carbon rods with h6 tolerance as required by the linear bearings.
  • T2.5 metal pulleys and polyurethane belts with steel reinforcement.
  • CNC hobbed bolt.
  • Extruder break out PCB.
  • 1% thermistors to avoid the need for temperature calibration.
The complete BOM is here.

The big advantage of the design is that the axes need no alignment to ensure they are orthogonal. The only calibration required is bed levelling, Z height and extruder flow rate. Details in the manual.

The price of the kit is £499, plus VAT in the EU, plus shipping. For availability check the forum post here.

Sunday, 25 November 2012

More accurate thermistor tables

A couple of weeks ago I wanted to create some thermistor tables for Marlin. At that time it had a copy of createTemperatureLookup.py, which I think was written by Zach Smith based on my article "Measuring temperature the easy Way". It uses the simple two constant thermistor equation based on the resistance at 25°C and beta.

The two constant formula was adequate for my own software because I have separate constants for each thermistor that I use and I calibrate them against a thermocouple at the working temperature and room temperature. Marlin however has a thermistor table for each type of thermistor, so if you use the same thermistor for the bed and the hot end they share a table. The problem with the simple equation is that beta is not very constant and depends on temperature. There are several values given on the datasheet for different temperature ranges
, none of them very applicable to our application. If you have beta correct for the hot end at say 250°C it is about 7°C out at the bed temperature, say 130°C.

I decided to make a new script which uses the three constant Steinhart–Hart equation. The graph shows the difference between the two equations over a large temperature range: -
The two constant equation is only accurate around the two temperatures the constants are calculated at (in this case 25°C and 256°C). When these are at opposite ends of the thermistors range the error in the middle is quite large.

The script I made is MakeTempTable.py. Its parameters are resistances at three temperatures. The tables is makes look like this: -

    {     344,       300     }, // r=   101 adc=  21.47
    {     369,       295     }, // r=   108 adc=  23.08
    {     397,       290     }, // r=   117 adc=  24.83
    {     428,       285     }, // r=   126 adc=  26.75
    {     461,       280     }, // r=   136 adc=  28.84
    {     498,       275     }, // r=   147 adc=  31.12
    {     538,       270     }, // r=   160 adc=  33.63
    {     582,       265     }, // r=   173 adc=  36.37
    {     630,       260     }, // r=   188 adc=  39.38
    {     683,       255     }, // r=   205 adc=  42.69
    {     741,       250     }, // r=   223 adc=  46.32
    {     805,       245     }, // r=   243 adc=  50.31
    {     875,       240     }, // r=   266 adc=  54.71
    {     953,       235     }, // r=   290 adc=  59.55
    {    1038,       230     }, // r=   318 adc=  64.88
    {    1132,       225     }, // r=   349 adc=  70.77
    {    1236,       220     }, // r=   384 adc=  77.26
    {    1351,       215     }, // r=   423 adc=  84.42
    {    1477,       210     }, // r=   466 adc=  92.32
    {    1617,       205     }, // r=   515 adc= 101.05
    {    1771,       200     }, // r=   570 adc= 110.68
    {    1941,       195     }, // r=   632 adc= 121.30
    {    2128,       190     }, // r=   702 adc= 133.01
    {    2335,       185     }, // r=   782 adc= 145.91
    {    2562,       180     }, // r=   872 adc= 160.11
    {    2811,       175     }, // r=   975 adc= 175.70
    {    3085,       170     }, // r=  1092 adc= 192.81
    {    3384,       165     }, // r=  1225 adc= 211.53
    {    3711,       160     }, // r=  1378 adc= 231.95
    {    4066,       155     }, // r=  1554 adc= 254.15
    {    4451,       150     }, // r=  1756 adc= 278.21
    {    4866,       145     }, // r=  1989 adc= 304.15
    {    5312,       140     }, // r=  2258 adc= 331.99
    {    5787,       135     }, // r=  2570 adc= 361.68
    {    6290,       130     }, // r=  2934 adc= 393.15
    {    6820,       125     }, // r=  3357 adc= 426.25
    {    7373,       120     }, // r=  3852 adc= 460.80
    {    7945,       115     }, // r=  4433 adc= 496.54
    {    8531,       110     }, // r=  5116 adc= 533.16
    {    9125,       105     }, // r=  5921 adc= 570.31
    {    9722,       100     }, // r=  6875 adc= 607.60
    {   10314,        95     }, // r=  8007 adc= 644.61
    {   10895,        90     }, // r=  9356 adc= 680.92
    {   11458,        85     }, // r= 10968 adc= 716.13
    {   11998,        80     }, // r= 12903 adc= 749.86
    {   12509,        75     }, // r= 15234 adc= 781.80
    {   12987,        70     }, // r= 18051 adc= 811.66
    {   13428,        65     }, // r= 21469 adc= 839.27
    {   13832,        60     }, // r= 25635 adc= 864.50
    {   14197,        55     }, // r= 30732 adc= 887.30
    {   14523,        50     }, // r= 36995 adc= 907.68
    {   14811,        45     }, // r= 44725 adc= 925.72
    {   15064,        40     }, // r= 54309 adc= 941.52
    {   15284,        35     }, // r= 66249 adc= 955.23
    {   15472,        30     }, // r= 81195 adc= 967.02
    {   15633,        25     }, // r=100000 adc= 977.08
    {   15769,        20     }, // r=123783 adc= 985.58
    {   15883,        15     }, // r=154025 adc= 992.71
    {   15978,        10     }, // r=192694 adc= 998.64
    {   16057,         5     }, // r=242427 adc=1003.54
    {   16121,         0     }, // r=306773 adc=1007.56


The ADC values in the table are multiplied by 16 because Marlin uses oversampling to give four more bits of precision. The old tables just multiplied the integer ADC value by 16 but I multiply it before rounding it to an integer so the table has the same precision as the oversampled ADC reading.

The script can also take ADC values as parameters instead of resistances. This allows you to calibrate a thermistor in situ. If you set the temperature to a value in an existing table and let it settle and then measure it with a thermocouple you know that the ADC value for the measured temperature is the value in the table for the set temperature. You can then produce a new more accurate table.

Two days after I put it on Github ErikZalm added a new script to the official version of Marlin to do exactly the same thing: createTemperatureLookupMarlin.py, amazing coincidence! It is different code but I think it uses exactly the same maths to find the three coefficients using simultaneous equations that I lifted from here

Wednesday, 15 August 2012

Peel-able support?

One of the few advantages commercial FFF machines have over Reprap at the moment is that breakaway support works much better. In particular the UP printer from PP3DP is reputed to have easily removable support using only the same material it builds with, i.e. ABS.

Today I was redesigning the Mendel90 ribbon clamps to have nut traps to make assembly easier and came up with this design: -


I thought I could print it using the bridging ability to span the slot in the base but it failed abysmally. I think it is because it is so close to the heated bed the bridge sags a lot more that it would normally do.

I tried the support option in Skeinforge but I have never got it to work well. It puts a sparse zigzag under the bridge and the flow rate can be reduced to make it weak. The problem is then that when it is removed the top layer of the support bonds more strongly to the part above than that it does to the support below, so it gets left behind. Worse still the bottom layer of the object is more strongly attached to the top of the support than it is to the layer above, so it is very hard to remove just the support.

I think the reason for this is that when the support is sparse the layer above drapes down in between the gaps. That reduces its contact to the layer above and increases its contact to the layer below. This sketch illustrates my theory: -


When I watch videos of the UP printer it looks like the top of the support is solid and flat. This reminds me of the way I used to do rafts. I made the top layer of the raft almost solid and raised the bottom layer of the object a little to make it peel-able. Indeed support is just the same as a raft, it is just that it is elevated.

To test the theory I hacked my host software to load a separate file for the support so that it could be sliced as a normal object and so have a solid top. It also has a solid base of course, which is another advantage over Skeinforge's sparse support as that can easily become detached from the bed.


When extruding I did the support for each layer before the object's layer and did it a bit lower. I also missed off the outline to give a gap of one filament width at the ends. I worked out the diameter that the object's infill would be if it was not squashed into an oval. I offset the support downwards by the difference between that diameter and the normal layer height. That means that when extruding the underside of the object that is being supported the filament is not being squashed, so has minimum contact with the support. It doesn't droop though and the next object layer is squashed against it making the bond above stronger.

The bottom layer of the support is thinner than the rest because of the downwards offset, so I had to reduce the flow rate accordingly. 


It wasn't peel-able by hand but I could separate it cleanly with a penknife, something I have not been able to do before.


The bottom layer of the bridge has round filaments that do not touch (as they are not as wide as they should be) but that is always the case with bridges. The difference is they do not droop and are well bonded to the layer above.


They are of course a little lower than they should be. A better scheme might be to have the support at normal height and raise the head as it passes over it. That would give even better bonding to the layer above which would tend to fill in the gaps. It would need rapid Z movements though.

I would be interested to see what the bottom of a supported surface of an object from an UP printer looks like.

To test the idea further I tried making a sphere. I made the support in OpenScad by subtracting it from a cylinder. To get some lateral clearance I did a Minkowski sum of the sphere with a thin disk.
$fa = 10;

R = 20;
clearance = 0.5;
h = R - R * cos(60);

module sp()
    translate([0, 0, R])
        sphere(R);
 
if(0)
    sp();
else
    difference() {
        translate([0, 0, h / 2])
            cylinder(r = (R * sin(60) + 2), h = h, center = true);
        minkowski() {
            sp();
           cylinder(r = clearance, h = 0.01, center = true);
        }
    }
 
color("red") sp(); 




The support was pretty difficult to remove because it ended up quite dense as Skeinforge makes solid layers when there are shallow sloping sides. Also the sparse infill ends join up to make a complete outline. It is more a proof of concept rather than a practical way to make support.


This is the underside of the sphere where it met the support. It looks quite good but above it there is some distortion to the spherical shape that I cannot explain.

So I think having a solid top surface on top of sparse support is the way to go and a dense bottom layer to anchor it to the bed. In between it can be very sparse but it would then need several solid layers to become flat.

It still takes some effort to remove, so I don't know if it is as good as the UP support yet. The difference may be the plastic.

Tuesday, 31 July 2012

Melzi mod

In my previous post: StepStuck I described how Pololu stepper drivers (and the open source equivalent StepSticks) are not configured optimally for the typical motors used for RepRap. Not surprisingly Melzi suffers from the same problem as it just has the same circuit on board the single PCB.

This video is a good demonstration of the effect of enabling the A4988's "low current micro step mode". The Z axis is stepping slowly and you can hear a buzz with pauses in it. When I short out R20 it sounds a lot smoother, but still not perfect.



So I replaced all the ROSC resistors with 0R links.