Saturday, November 9, 2019

Attempting to Automatically Clean a 3D Printer Nozzle Using a Wire Brush

I want to print more lamp shades using UMMD with clear ABS or PETG filament.  The only problem with these very large, long prints is that eventually, charred crud that builds up on the extruder nozzle deposits itself in the print.  I had a small, dense wire brush for nozzle cleaning from an old Stratasys printer, so I ran a couple experiments to try to use it to clean UMMD's nozzle.

After a couple quick measurements on the printer, I printed a bracket to hold the brush:

Printed bracket to hold the brush near the front edge of the bed.  The screw allows the height of the brush to be adjusted.

I heated up the nozzle and manually moved it back and forth over the brush.  The brush height is adjustable so I played with it a little to see if there was any particular setting that was better than any other.  It didn't seem to make much difference if I really buried the nozzle in the brush or just gently touched it.

Then I went into PrusaSlicer and modified the printer settings by adding some custom gcode that would run on every layer change.

The "After layer change G-code" tells the nozzle where the wire brush is located.

I ran multiple test prints (all ABS) to see if I could get the brush to clean the nozzle but found it just left blobs on the nozzle that eventually found their way into the print.  I played with it quite a bit and couldn't find any combo of zig-zag path and brush height that would get the nozzle clean every time.  Sometimes it did manage to dislodge a blob of molten plastic, but the nozzle picked it back up again on its next pass over/through the brush.

Here's some slo-mo video of the nozzle going through the brush.  You can see blobs of plastic on the brush and nozzle before it goes into the brush, and one gets picked up by the nozzle as it leaves the brush.

Better video of 3D printer nozzle encounter with a wire brush. from Mark Rehorst on Vimeo.
Nozzle brush in slow motion from Mark Rehorst on Vimeo.

A little of the plastic sticks to the brush, but that blob may get picked up by the nozzle on a future pass through the brush, and end up on the print.

Not my idea of a clean nozzle...

I don't know how or if Stratasys actually makes this work, but I can't seem to get it to work.  Maybe the shape of the nozzle is the problem- the brush came from a stratasys printer that had very shallow, rounded nozzles, not the sharp, pointy type that fit the E3D hot-ends.

Maybe a motorized spinning brush will work if it spins fast enough to fling the plastic it scrapes off the nozzle away so that it doesn't just redeposit on the nozzle and eventually the print.

Maybe I'll come back to this later, until then, score one for entropy...

If anyone has any success with this sort of thing, I'd like to hear how you make it work.

Monday, November 4, 2019

Trimify2x: a Post-Processing Program to Improve Sandify Sand Table Patterns

The Spice Must Flow sand table is one of my favorite projects.  It uses a magnetically driven steel ball to draw patterns in sand.  The patterns that drive the table are stored as gcode files generated by a great program called Sandify.

A pattern created using Sandify, drawn on The Spice Must Flow.

I like to run the table fast, typically with maximum speed set to 500 mm/sec, so that it's interesting to watch as it draws patterns.  Here's a short video of it erasing at 1m/sec:

Many people who have seen it say that they could stand and watch it all day, and I have to agree.  It's mesmerizing.  I've been working on making the mechanism run quietly at 500 mm/sec and largely succeeded, but there was one remaining problem.

Something I noticed almost as soon as the table was working over a year ago was that when the pattern being drawn exceeds the size of the table, the ball zips around on the edges of the table, sometimes back and forth along one or two edges, for quite a while before it gets back to drawing lines on the table. It's a problem because it takes a lot of extra time, increases wear on the mechanism, and it's not nearly as interesting to watch as lines being drawn on the table.

Here's a video that shows some of the wasted back-and-forth motion along the edges (watch from about 0:50 to 1:30):

As in a 3D printer, the ball's motion on the sand table is subject to acceleration and deceleration.  That means that short line segments never reach the maximum firmware-allowed speed.  All that crawling around on the edges of the table can really slow things down because it is very often short back and forth motion before the ball finally goes back out on the table and starts drawing in the sand.

I decided to write a program that will read the Sandify pattern file and strip out the lines that have the ball running back and forth along the edges.  The edited version of the pattern file will generate the exact same pattern with minimal time wasted along the edges of the table.

Sandify Pattern File Structure

The Sandify pattern files are just text files that start with a header that includes the file name, the parameters that are used by the Sandify program to generate the patterns including the dimensions of the pattern.  The rest of the file is the actual pattern in the form of a long series of G01 commands (basic gcode) with X,Y coordinates.

Here's a typical, but shortened, Sandify pattern file:

; Created by Sandify


;   Sandify Version: 0.1.3

;   Machine Type: Rectangular
;     MinX: 5 MaxX: 710 MinY: 5 MaxY: 1570
;   Content Type: Shapes
;     Starting Size: 800
;     Offset: X: 382 Y: 261
;     Selected Shape: Polygon
;       Polygon Sides: 4
;     Number of Loops: 165
;     Spin: true
;       Spin Value: -4
;       Spin Switchbacks: 0
;     Grow: true
;       Grow Value: -2
;     Track: true
;       Track Count: -37
;       Track Size: 0.8
;       Track Grow: false
;   Path Reversed: false

; filename: 'square1.gcode'


G28 Y
G28 X
G01 F30000; END PRE
G01 X710.000 Y1570.000
G01 X154.163 Y1570.000
G01 X153.366 Y1570.000
G01 X132.599 Y489.079
G01 X710.000 Y460.418
There are about 1100 of the G1 command lines (this is a very small pattern file) and then the file comes to an end:

G01 X5.000 Y587.353
G01 X5.000 Y36.396
G01 X5.000 Y5.000
G01 X294.080 Y5.000
G01 X710.000 Y5.000
G01 X710.000 Y1570.000
G01 X5.000 Y1570.000
G01 X5.000 Y705.184


G04 S60
; square1.gcode; END POST

The line highlighted in yellow lists the dimensions of the pattern and will be useful later...
The patterns that move the ball are always a series of G01 commands which makes it easy to recognize those lines.  Each line such as "G01 X738.000 Y973.789" consists of a command (G01 - equivalent of a go-to statement) and coordinates of the point to which the ball should move (738.000, 973.789) from wherever the previous command left it.  If MinX=5, G01 commands that move the ball to/along the left edge will always contain X5.000, likewise the other axes.

After months spent thinking about how to process the files in a single pass, nothing was done. It seemed to require detecting all the possible transitions from one corner or edge to another, etc., and was a bit overwhelming. I was familiar with this uncomfortable state from my engineering days- it's the dreaded "analysis paralysis" in which one has too much information and too large a task to do anything.  

Stage 1

One day, after generating a particularly nice pattern for The Spice Must Flow (see photo above), I became really annoyed with the amount of time the ball spent moving around at the edges of the table.  I decided to try to manually edit the pattern file to cut that stuff out.

I looked for sequences of statements where the ball just went back and forth along an edge of the table.  What I realized was that those sequences are very easy to spot visually, so editing them out was also very easy.  I manually edited a couple pattern files (about an hour each!), stripping out the excess edge movement, first on one edge, then the next, etc., then ran the edited files on the table to see if they really improved performance.  Oh yeah!  The ratio of productive drawing time to useless edge movement was increased dramatically.

Since the files consist mainly of G01 commands, all I had to do was look for sequences like the one highlighted in blue and yellow, where X5.000 represents the left edge of the pattern:

G01 X15.000 Y23.000

G01 X5.000 Y100.000
G01 X5.000 Y230.000
G01 X5.000 Y110.000
G01 X5.000 Y321.000
G01 X5.000 Y16.000
G01 X15.000 Y21.000

and transform it to this by chopping out the stuff in yellow:

G01 X15.000 Y23.000

G01 X5.000 Y100.000
G01 X5.000 Y16.000
G01 X15.000 Y21.000

Some of those sequences are 100 statements long, and there may be hundreds or even thousands of those sequences in any given pattern file.  NotePad++ made it particularly easy to find the sequences by using the Search > Mark > Mark All function.

Sometimes the way out of analysis paralysis is to just start working on a piece of the problem and see where it takes you.  Buoyed by my new-found confidence in my ability to make an improvement, I decided to try to automate the edits I had done manually. A little research pointed me at Perl, a programming language specifically developed to process text files. I didn't know anything about programming in Perl, so I got a couple books and used some on-line searches.  As I studied the books and ran small test files, I kept thinking about how to scan the Sandify pattern files, what needed to be kept, and what could be thrown away.  It took about 4 days to get the first stage of the program working.

The first thing the program does is locate the statement in the header that contains the maximum and minimum values for each axis in the pattern. Next, it starts looking for and trimming sequences along pattern edges.

It's actually pretty easy (in hindsight, isn't everything?) to find those sequences that contain multiple statements along each edge- just examine three lines at a time and write the second line to the output file unless all three lines contain the edge value being checked.  That ensures that single and double instances of an edge statement pass through to the output file, but if there are three or more in sequence, only the first and last are written to the output file.  For more details, download the program and take a look at it.  I was very liberal with comments so it should be easy to see what's going on.

There is probably a way to have the program clean up all four edges in a single pass using an array, but I'm not much of a Perl programmer, so I wrote separate passes for each edge value, just as I had manually edited the files, creating intermediate files along the way and then deleting them just before the end of the program.

Processing the pattern files this way leads to a reduction in the file size (not that it matters much), a significant speed up in pattern completion, and much less boring edge motion.

Stage 2

The patterns I generate for the table frequently start with a very large base shape offset beyond the table's boundaries, and shrink and rotate it as the pattern cycles, letting it get to zero size and then allowing it to grow after that.  As the pattern grows it overwrites the stuff that was drawn as the pattern was shrinking.  That process leads to beautiful and interesting patterns that look different every few minutes throughout the drawing process but often contain a lot of unproductive, boring, edge and corner to corner motion.

Once all the excess edge motion was trimmed out, the pattern files now contained sequences of statements with corner coordinates.  Those sequences contain the remaining unproductive motion. The trimming program didn't add those corner statements - they were in the file the whole time, but buried among the useless motion along the edges. Now it was time to minimize unnecessary motion through the corners.  

If the ball leaves the table on one edge and reenters the table on the opposite edge, there are two paths it can take along the edges, both going through two corners of the table/pattern.  One way will usually be shorter than the other.

Two-corner path with the ball exiting the table on the left edge and reentering along the right edge.  Blue square is the edges of the pattern/table. Green is the ball.  Orange is the time wasting long path, black is the more desirable short path. 

Likewise, if the ball leaves the table along one edge and comes back on the table along an adjacent edge, there are two paths it can take.  One path goes the long way through three corners, and the other, shorter path, goes through only one corner.

A 3-corner path.  The path through the 4th corner (black) is always shorter than the path through 3 corners.

If the ball leaves the table on one edge and returns to the table along the same edge, sometimes it takes the long way between the two points and travels through all four corners of the table.  That's a silly waste of time!

A 4-corner path orange), a big time waster.  Simply deleting the 4-corner sequence forces the shorter (black) path.

Of course, sometimes the ball has to pass through a single corner and that's OK (the alternative is to take the longer, 3-corner path around the table- nope!).  There's no wasted motion there.

The second part of the optimizer program searches for the sequences of corner statements illustrated above, leaving single corners alone, checks two corner sequences and replaces the longer path with the shorter path through the other two corners, replaces three corner sequences with the shorter path through the fourth corner, and deletes sequences of four corners because they start and end on the same edge.

In the case of multiple loops around the table, as in the 7-corner path (orange) illustrated below, the first four corners will be deleted, and the remaining 3-corner path will be converted to the 1-corner path (black), greatly reducing the time wasted zipping around the edges of the table.

A 7-corner path (orange) that wastes a lot of time gets converted to the 1 corner path by first deleting the first four corners and then converting the remaining 3-corner path to the much faster 1-corner path (black).

I've run many test files and pattern and the trimming program seems to work reliably.  There's a minimal amount of wasted time zipping around the edges of the table now, which makes it much more interesting to watch as the patterns are drawn.

You can get the post-processing program here...

(((note- there's an updated version linked near the bottom of this post)))))

You'll need Perl to run the program.  I used Strawberry Perl for Windows, but the program should work with any recent Perl 5 on any OS.  To run the program, just open the Perl command line app, point it at the directory where you keep the target Sandify pattern file, and type "perl" Type in the input file name when it asks, hit "enter", and you'll find the trimmed pattern in a file called clean.gcode.  That's it.

A Sample of the Results

The picture at the top of this post is a pattern file that starts with a heart shape that is larger than the table area.  With each cycle of the pattern, the heart shrinks a bit bringing it onto the table, first along only one edge.  With each cycle, the ball travels around the perimeter of the table including a little back-and-forth motion along one edge.  Here's video of the start of the pattern, as generated by Sandify:

Untrimmed pattern running on sand table from Mark Rehorst on Vimeo.

That looping around the table goes on for quite a while before it starts drawing anything at the opposite end of the table.

The next video is the start of the same pattern after it has been optimized using the  There are essentially two optimizations seen here.  First, the back-and-forth motion along one edge is eliminated.  The second, and much more important optimization in this case, is that looping around the edges of the table is eliminated, greatly speeding up pattern generation and improving watchability of the table.

The same pattern with wasted edge motion trimmed out from Mark Rehorst on Vimeo.

This is just one example of the improvement that comes from trimming the Sandify pattern files using  The original file, heartfuzz1.gcode was 359 kB long.  The trimmed file, heartfuzz1_clean.gcode is just 193 kB long.  The difference represents wasted motion along the edges of the table.  But how much wasted motion?  On my table, with acceleration set to 1000 mm/sec^2 and speed set to 500 mm/sec, the untrimmed file takes 59:20 to complete.  The trimmed file requires only 42:03 to complete the same pattern.  That's a difference of more than 17 minutes of the ball moving around the edges of the table, producing the exact same pattern.

I'm going to try to make a couple time-lapse videos of a pattern, one untrimmed and the other trimmed, and combine them into a single side by side video.  If and when I get it done, I'll post it here.

Making Sequences of Patterns

The RepRap Firmware that runs on the Duet controller boards has enabled the M98 gcode command.  That command allows you to create playlists of patterns to run on a sand table.  You put your pattern files (already cleaned by Trimify) on the uSD card on the controller board in the default /gcodes directory.  Then you create a sequence file and put it into the same directory.

The sequence file should look something like this:

M98 P"0:/gcodes/wipe0.gcode"

M98 P"0:/gcodes/heartfuzz1_clean.gcode"
G04 S90
M98 P"0:/gcodes/wipe0.gcode"
M98 P"0:/gcodes/mishegoss1_clean.gcode"
G04 S90
M98 P"0:/gcodes/wipe0.gcode"
M98 P"0:/gcodes/mishegoss2_clean.gcode"
G04 S90

This sequence will erase the table using the wipe0.gcode pattern, then run the heartfuzz1 pattern, then wait 90 seconds, then erase, then run the mishegoss1 pattern, etc.  You can make the sequence as long as you like.  You can even create files that call different sequences.  Unfortunately, there doesn't seem to be any way to automatically randomize the pattern sequence, so you'll have to do that yourself.

Name the sequence file something like "sequence_01.gcode".  You can then select that file to run using the web interface on the controller. 

UPDATE!  11/25/19

I have discovered that the "clean" pattern files occasionally still contain some useless motion along the corners/edges.  It seems to occur when the useless stuff in the pattern bends around a single corner.  Running Trimify a second time using the "clean" output file as input has fixed it in every case (which isn't many) I've seen.  I have run Trimify multiple times on some test files, and it has never damaged the files, so I will be modifying Trimify to automatically perform two passes on the input file and will post a link to the new version here as soon as it is done.

UPDATE!  11/30/19

The residue problem is now solved (I think), and I've made a couple additional tweaks to the program which is now called

The first change is that the output file is now named from whatever the input file is.  If you enter "mystars.gcode" for the input file name, the output file name will be "mystars_clean.gcode".  The second change is that program now makes two full passes over the input file and I believe completely eliminates any "residue" left from the first pass.

The compare plugin in notepad++ was extremely useful for checking operation of the program.  It compares and highlights differences between two files.  Here's a comparison of a sandify pattern called jazz2.gcode and the output of trimify called "clean.gcode" (click on the image and open in a new tab to make the text readable):

This is the notepad++ comparison of the original jazz2.gcode file (right) with the trimify output file clean.gcode (left).  All the stuff that's highlighted in green on the input file is gone in the output file.  Notice that line numbers 1570 and 1574 both contain G01 X710.000 Y5.000 and both end up in sequence in the output file.  
This is a comparison of the output from the original trimify - clean.gcode (left) and the output from trimify2x - jazz2_clean.gcode (right).  The useless motion that sends the ball to the corner of the table at X710.000 Y5.000 is now eliminated.  In this particular input file, that was the only change needed.  I have seen other pattern files with more of this sort of thing.
 In this particular example, the second pass of the maxx trimming is what takes out the duplicate and useless G01 X710.000 Y5.000 lines.  Trimify2x runs the whole process twice including all the edge and corner trimming and substitution.  I suspect that the corner trimming and substitution may never do anything on a second pass, but it was easy to include it so I did. is every bit as crude as  I was going to try to set it up to loop but found it much easier to just append a copy of the original stuff to the end of the program, then make a couple minor tweaks to the input and output file names.

I am not planning on making any more changes to the program unless someone points out a bug. is located here.

Here's a better example of before and after trimify2x.  First, the original pattern straight out of Sandify:

Sandify pattern running on The Spice Must Flow sand table. from Mark Rehorst on Vimeo.

And here is the result of running trimify2x on that pattern file:

Sandify pattern file cleaned by Trimify2x from Mark Rehorst on Vimeo.

This particular pattern went from taking 2 hours down to taking only 57 minutes.  Over an hour was wasted at the edges of the table in the original pattern file.


Trimify (and trimify2x) may give unexpected results if you string together a bunch of pattern files and then try to optimize them in one go.  The program only looks for the MinX, etc., declaration statement once.  If you change the dimensions from one pattern to another, the optimizer will probably screw things up.  It's best to optimize the patterns individually, before stringing them together.

Trimify (and trimify2x) is every bit as crudely coded as you would expect a first-time Perl programmer's code to be.  There's no error checking, range limiting, etc.  If you give it bad input it will try to process it.  I have found that occasionally I get compiler warnings about a variable getting assigned a string instead of an expected numeric value.  I have looked at the files that cause that warning to be generated and can't see any reason for the warning.  The resulting trimmed output files look and work fine on the table, so I'm not  really motivated to try to track down the source.

Now that the excess edge and corner motion has been eliminated, the edges of the pattern are sometimes left looking a little ragged once the pattern is complete.  That can easily be fixed by simply sending the ball on a single trip around the edges of the table.

Monday, October 14, 2019

Using Flanged Bearings as Pulleys

Flanged Pulleys

You can buy flanged pulleys for GT2 (and other) belts ready made with ball bearings press fit into them, but I usually try not to use those because the bearings are very tiny and I don't trust them to last very long.  Also, if the tooth side of the belt is contacting the pulley, there will be few teeth in contact with the belt and that may lead to a zipping noise at high speeds and possibly to defects in prints if the belt is in a 3D printer.

A toothed GT2 pulley with 5 mm bore.
A smooth pulley with 3 mm bore.  This is the type I used in The Spice Must Flow sand table.

I used eight of those small pulleys in The Spice Must Flow sand table, mainly because I needed the large flanges to help keep the very long belts on the pulleys.  I solved the zipping noise problem by twisting the belts so the smooth sides of the belts would contact the pulleys.

In UMMD I used stacked F608zz bearings as pulleys in all three axes.  I prefer this type of construction because the bearings are much larger and more likely to last longer under the load of the belt tension.  The problem is that the flanges of those pulleys are small, so they don't work so well for long belt runs.

One of the stacked F608zz bearings pulleys I used in UMMD.  The belt runs were relatively short so the bearing flanges were enough to keep the belt on the pulleys.

A Printable Solution

I have been looking at yet another redesign of the sand table mechanism and thinking I'd like the replace the tiny pulleys with larger ball bearings, but I had to figure out a way to get large enough flanges that would keep the belts on the pulleys.

6 mm wide GT2 belts are used in a lot of 3D printers and in The Spice Must Flow sand table.  If you're going to stack flanged bearings to use as pulleys, you need to know some critical dimensions.  The commonly used F608zz (as I used in UMMD) is a 22 mm diameter x 7 mm wide x 8 mm bore pulley.  However, the flange uses up about 1.5 mm of that 7 mm width, so stacking two F608zz bearings will have enough width to accommodate up to about 11 mm wide belt. This works well for 9 and 10 mm wide belts as long as the runs aren't too long.

The diameter of the flange is 25 mm and the thickness of the flange is 1.5 mm, so the flat surface for the belt is 5.5 mm wide.

Dimensions of an F608zz bearing.
Flanged bearing are available in many sizes and the same concept can be applied to any of them.  You can get the dimensions with a quick web search for something like "F608zz bearing dimensions" and then select "images".

What if you want to use a relatively large bearing for reliability but need a bigger flange to accommodate longer belt runs?  This is the problem I faced in redesigning the sand table mechanism to operate more reliably and quietly.

This is what I came up with:

3D printed flange adapters fit on the bearings.  This will take only a few minutes to print.

I want to use a printed flange that fits over an existing bearing. The bearing's flange will stop the printed flange from coming off the bearing.  Stacking a pair of these looks like this:

Stacked F608zz bearings with printed flanges (green) to extend the existing, small flanges.  The space between the flanges is now 9.8 mm, but can be adjusted by appropriate tweaks to the dimensions of the printed parts.
I'd probably apply a bit of superglue to bond the printed flanges to the bearings, though it probably isn't strictly necessary.  In this configuration, the belt will contact the bearing's steel surface.  This type of design can be applied to any size flanged bearings to make wide flanged pulleys.

Here's another idea:

This would print in 3 pieces without any support material- the two flanges (green) and the central tube (red).

Like the printed flanges, the tube that separates them can be made any size needed.  If the two bearings are clamped together (and they should be) by the mounting system, the flanges should stay in place without any need for glue, though it might be a good idea to bond the three printed pieces to each other.

When you print any of these, you need to print the parts so they fit closely on the bearings, and use a random seam location setting so that the layer start and end points will be distributed around the surface of the parts to provide best concentric fit.  Using concentric infill for the top and bottom layers would probably also be best. You may want to print a few of them at a time or add a sacrificial object to the bed to allow the prints to cool a little between layers for best print quality.

It might be a good idea to print a gauge with holes that match the size of the bearings you're using +/- 0.3 mm or so in 0.05 mm steps.  Then you can push a bearing into the holes in the gauge to see which printed hole size will fit best.  I used holes that were 0.3 mm larger than the bearing dimensions and they came out fitting well but not tightly.  I could probably get a slightly tighter fit by using holes that are 0.25 mm larger diameter than the bearings.

The Result

Assembled pulley with wide flanges printed in PETG.

The pieces, all print solid.

Assembled pulley.

It remains to be seen how long the flanges will last if a belt is rubbing against them.  It will depend on the material- both belt and printed parts, and the tension on the belt, and maybe the belt speed, too.  I'm not sure I'd use pulleys like these in a high accuracy/precision 3D printer, but in a sand table, why not?

I'll be updating the sand table design and expect to be using this sort of assembly to replace the small pulleys it currently uses.  I'll post an update when that happens.

The Fusion360 CAD file for the F608zz bearing version of this pulley is located here.

Wednesday, September 18, 2019

More Sand Table Updates- Making It Run Quietly

The Spice Must Flow sand table was working well and I liked running it at 500 mm/sec because that speed was fast enough to make it interesting to watch.  The problem was running it at 500 mm/sec was noisy.  Not vacuum cleaner noisy, but loud enough that you wouldn't want to have it running in your living room on a regular basis.

I decided to figure out where the noise was coming from and how to reduce it to an acceptable level.

I identified several sources of noise (in order from loudest to quietest):

  1. Motors
  2. Belt teeth hitting smooth pulleys
  3. Pulley bearings
  4. Sliding bearings in X and Y axes

I originally built the table with NEMA-23 motors because I had them on hand.  I tried switching to NEMA-17 motors but they turned out to be only about 1 dB quieter, as measured with a sound meter app running on my phone.

That was when I was driving the motors at 16:1 ustepping using the smoothieboard that was originally installed in the table.

Higher Microstepping Ratios

The next thing I did was switch to a Duet WiFi controller board to use high microstepping ratios to try to quiet the motor noise.  The result was mixed, but I was able to figure out from my tests what needed to be done.

Here's video of the table with the Duet WiFi board driving the NEMA-17 motors.  Notice that at 100 mm/sec, any microstepping ratio above 32:1 is pretty quiet.  In this drive configuration I could only get to 175 mm/sec at 256:1, so I ran it at 128:1 so I could at least get to 350 mm/sec, but it was still noisy.  It occurred to me that at 100 mm/sec, the motors were turning at 1.25 revs per sec and at 350 mm/sec they were turning at almost 4.5 revs/sec.  So the key to quiet motor operation seems to be keep the motors turning slowly even as the mechanism moves fast.

I ordered a set of loop belts and pulleys that would give a 1:5 step up so that when the motors were turning at 1.25 revs/sec, the mechanism would be moving at 500 mm/sec.  Stepping up the speed by 5x divides the torque by the same amount and I found the NEMA-17 motors I had weren't up to the task.  I also found that at high microstepping ratios, the NEMA-17 motors hissed loudly and playing with the driver parameters wouldn't fix it.

I redesigned the motor mounts for the NEMA-23 motors- the hissing noise went away, and now the mechanism was able to run at 500 mm/sec again.

NEMA-23 1:5 motor mount and corexy drive assembly.  There's an 80 tooth pulley on the motor shaft and a 16 tooth pulley on the corexy drive shaft.  The original 40 tooth pulley drives the corexy mechanism.  Two printed green spacers ensure proper position of the 40 tooth pulley for corexy stacked belt configuration.  The motor mount and drive pulley blocks are kept in place using t-nuts.

With the 1:5 step up, I am able to run the motors at 256:1 ustepping to well beyond 500 mm/sec (I took it up to 750 without any issues).  The mechanism ran relatively quietly but there was still a lot of zip-zip sound that seemed to be due to the belt teeth hitting the smooth pulleys.  I redesigned the Y axis pulley blocks and enlarged the belt pass-through holes so I could put a twist in the belts and keep the smooth back sides of the belts against the smooth pulleys.  The zipping noise disappeared completely.

This is the previous Y axis pulley block design with a relatively small belt pass-through hole that would not allow the belt to be twisted.

The new Y axis pulley block (yellow) design with the large belt pass-through hole that allows for a twist in the corexy drive belt.  The other side of the corexy mechanism is identical.

One other change I made was to remove the magnetic endstop switches and replace them with standard type microswitches with levers.  The Duet board motor drivers can detect when a motor stalls, so in theory it should be possible to home the machine without using any endstop switches, but I'll have to get the friction in the mechanism down before I start messing around with that.  I may be running the motors too slowly for stall detection to work.

The Milwaukee MakerFaire was coming up fast so a lot of this work was done in a couple late nights and there was no time to test the mechanism fully assembled with the sand box, so that had to be done at the MakerFaire.  The result was disappointing.  The Y axis moves very easily but there's a lot of friction in the X axis motion.  I tried sanding down the UHMW bearings to give them a little looser fit on the X axis tube, but UHMW doesn't sand well.  I applied some silicone lube to the X axis tube and it worked fine for a few hours, but eventually, the friction came back and the patterns started shifting.

The MakerFaire wasn't really a quiet environment, but most of the noise I heard coming from the assembled table was the quiet grinding sound of the ball moving through the sand (!) so I think I'm finally getting close to the end of the design process.

I'm going to rework the bearings for the X axis and see if I can get the friction down to an acceptable level.  I'm also working on a new design for the sandbox that will have a thinner bottom and will allow an air gap between the magnet and the bottom of the box to minimize any noise that might come from dragging the magnet against it.  That will also reduce friction a bit, which can't hurt.

More on the Duet WiFi Board

I would ultimately like to make this table into a piece of living room acceptable furniture.  One of the things I disliked about using the SmoothieBoard was having the control panel on the table in a place where I could easily (by crawling under the table) access it.  That's great for displaying it at a MakerFaire, but not so great when it's at home.  For a piece of furniture, I want to hide the controller completely and even try to minimize visibility of the power cord.

When I was home working on the mechanism, the Duet WiFi board was perfect.  I was able to tweak all the configuration settings, and generate and wirelessly upload pattern files to run.  However, when I was at the MakerFaire, the wifi at the venue was flaky and I was unable to set the board or even my laptop to communicate on the network.  After some panicked digging around the reprap firmware wiki, I found that the firmware includes an access point mode in which the wifi radio on the Duet board will act as a host and I was able to connect to it with my laptop and get the whole thing up and running.  The only problem with that is that you have to start the access point mode by connecting to the board via USB, so I found myself crawling under the table again to get the thing running. 

Fortunately, you only have to connect to the board using USB once to set up access point mode.  The wifi module will remember the settings (SSID, IP address, password) you used and will restart access point mode if you put an M552 S2 command in the config.g file that is run each time the board powers up.  Now when the machine powers up, I can connect my laptop by manually switching it to use the "network" that the Duet board is broadcasting.  No more crawling under the table to connect to the USB port!


256:1 microstepping, running the motors slowly using 1:5 drive step-up, and twisting the belts all contributed to reduced operating noise of the mechanism.  If you're going to build a sand table, and you want to run it fast, I recommend all the above to keep operation quiet.

Update!  Video, or it didn't happen!

More of The Spice Must Flow from Mark Rehorst on Vimeo.

The Spice Must Flow from Mark Rehorst on Vimeo.

The Spice Must Flow (again) from Mark Rehorst on Vimeo.

Monday, September 2, 2019

SoM Gets a Duet WiFi and PanelDue 5i Controller

A few months ago, the SmoothieBoard in SoM died when I managed to short something while working on the printer, so we installed an MKS Sbase board that one of the MakerSpace members had handy and also runs SmoothieWare.  Unfortunately, it was a piece of crap and didn't reliably read SD cards, and more recently, jogging the Z axis also moved the Y axis for some reason.  It had crappy DRV8825 drivers, too, that I never liked.

I decided to do the only sensible thing and install a Duet board, and since I had experience with the Ethernet version, I decided to try the WiFi board with a PanelDue 5i interface.

My experience with the Duet Ethernet board in UMMD has been mixed.  It has been very reliable, the drivers are really quiet, I like the Panel Due interface.  But I prefer to run printers from SD cards for reliability and not having to connect a computer to the printer.  The Panel Due 7i has a uSD slot along its bottom edge.  Unfortunately, the way the panel is installed in UMMD, I can't readily access the card slot and even if I could, it's a little too far from the controller board (you need to use a short ribbon cable to make the connection).  The Panel Due has the option of rotating the screen 180 degrees, so I could theoretically flip it over and make a hole in the top of the printer to access the uSD card slot, but then I'd have to worry about things falling into the slot and jamming it up.  Even though I have relatively small fingers, and mad hand skillz, handling a uSD card is a lot more difficult than an SD card.  I'm looking into fixes for that - maybe an outboard SD card slot that will plug directly into the Duet board.  With the Ethernet board and Panel Due 7i I found that I needed to keep a computer connected to the printer just to load gcode files.  That feels like a backward step to the bad old days when I was using Arduino/RAMPS and Pronterface to control the printer.  At least it uses a reliable network interface instead of USB with flaky drivers.

Sure, a Duet WiFi controller board would eliminate the need to have the computer physically connected, but if I take the machine to a MakerFaire or other location, I won't always have a reliable wifi connection to use, and I don't like having to waste time debugging flaky wireless connections.

I tested the Duet WiFi in the sand table before I installed it in SoM.  In the sand table the wifi controller is especially nice- I don't have to have any controls on the table which means I don't have to try to hide them.  I have ordered a Duet WiFi board for the sand table and will write a post on that when I get it installed.

Networking a 3D Printer?

Call me a Luddite, but I really don't see a big advantage to having a 3D printer on a network.  I clean the bed and verify that the filament spool that's loaded has enough filament to finish the job before every print.  If I have to go to the machine anyway, why not just plug in a card and start the print while I'm standing there?  The Duet's web server provides some data and control that is still missing from the Panel Due, but a lot of the data isn't particularly useful to me. The missing control capability in Panel Due can easily be added via macros, and I'm hoping that one day the Panel Due firmware will catch up to RepRap Firmware that runs on the Duet board.

Some people go out of their way to add a RPi running octoprint to network their printers.  If I were a baseball fan, I'd probably like staring at my printer while it's printing and enjoy the enormous amount of "stats" octoprint can produce, but I have better things to do I'm not impressed or entertained by data that isn't particularly useful, so I don't care too much for either baseball or octoprint.  I have no desire to try to impress people by starting prints using my phone, though it might be handy to be able to stop them when they fail (pretty rare).  It makes no sense to me to do the slicing on an RPi when I use CAD to design the parts I print on a higher powered, much faster laptop.  Maybe slicing on an RPi is OK for people who just download stl files to print, but I don't know many 3D printing people who remain at that stage for very long.  Sooner or later, almost everyone who gets into 3D printing wants to print their own designs.

Panel Due 5i Enclosure

I decided to try the Duet Wifi board to replace the controller in SoM.  Who knows, maybe I'll be impressed enough to change my mind about using SD cards and wireless networking.  But just in case I don't, I designed and printed an enclosure for the Panel Due 5i that leaves the uSD card slot accessible.  In SoM the Panel Due is close enough to the Duet board that the uSD ribbon cable works, so I have the option of using either the wireless network or the uSD slot to transfer gcode files to the printer.

The enclosure design was based on a GrabCAD model of the Panel Due 5i board.  Kudos to whoever uploaded the Panel Due 5i model because to my pleasant surprise, it was very accurate and my enclosure fit on the first attempt.  Even with the accurate model, I managed to spend far too much time designing the box.

This box was designed to allow easy access to the uSD card slot.

The top of the box has labels for the erase and reset switches that are used when updating the Panel Due's firmware.

The bottom of the box has holes for mounting it on a panel (I'll probably just use velcro tape) and slots that allow the ribbon cable and 4-wire cable (not shown) to pass through the wall of the box.

The circuit board is mounted on the top cover using 4 small plastic anchor screws.  The top cover snaps onto the bottom cover and holds securely.  The bottom cover has bosses that provide mechanical support for the top cover and circuit board.  I have since updated the bottom cover design to include some webbing to give it more rigidity.

The enclosure prints in 2 pieces without any support material.  The board screws to the top cover using 4 small screws, and the two halves snap tightly together and can be pulled apart as needed to access the the board for firmware updates, etc.  The Fusion360 CAD file is here.  It includes the GrabCAD model of the Panel Due 5i.


Before doing anything else, I updated the firmware in the Panel Due and added my own splash screen.  I used Irfanview to put red text on a green background (to match the color of the box), cropped it to 800 x 480, saved it as a .bmp file, compressed the .bmp file with escher3d.exe, then added it it to the firmware file using a "copy" command per the instructions, here.

I went through the cables in the printer and labeled them (probably should have done that years ago) as I pulled them off the MKS board so they'd be easy to identify and connect to the Duet board.  I replaced a bunch of the connectors with the much better quality ones that came with the Duet board.

I mounted the Duet board in the printer's electronics drawer on of the board mounts I designed and printed for UMMD.

Configuring the Duet Board

I used the online configurator and checked it against UMMD's config file to try to minimize problems.  I mounted the board and started hooking up the various connections, testing them as I went along to make sure they were working right and tweaking the config files as necessary.  It took about an hour getting everything working right, so it was pretty easy.

SoM had a DSP based driver and 32V power supply for the Y axis motor that was used back when it had a ball screw drive.  I did a couple experiments and found that the driver on the Duet board could deliver sufficient current to drive that motor, so I took out the DSP driver and power supply.  Simplification!

I ran into one problem after installing the Duet.  The X axis was making a lot of noise and vibrating.  Maybe it had been doing it for a long time and the noise was masked by the noisy ball screw that used to drive the Y axis.  I didn't pay much attention to it when I put the MKS board in the machine- that was a temporary measure to get it back up and running.  Now that the Duet was in and I was using high microstepping ratios, I expected quiet operation and was bothered by the noise.  I looked closely at test prints and found the vibration in the X axis was causing closely spaced vertical lines in the X parallel sizes of prints.

The problem had nothing to do with the Duet board.  It was a result of some small metal flakes getting into the motor and interfering with the motion of the rotor.  I wrote a separate blog post on that.  That problem was easily fixed, once I knew what was happening, and the X axis now runs quieter than it ever did thanks to the 128:1 ustepping in the Duet board.

Here's the inside of the electronics drawer now that the Duet is in place.  I know, it's ugly, but it's really easy to service, especially now that I have all the wires labeled.  I used this type of label- they are really tough.  I tried using them in a laser printer and found that the fuser heat distorted the labels and they tended to peel apart and even curl off the backing sheet, so I decided to just write on them with a permanent marker instead and had no further problems.  UMMD will get the same type labels the next time I have a reason to open the electronics enclosure.

Inside the drawer- no more 32V supply and DSP driver for the Y axis.  I used a custom splash screen that is displayed for a few seconds every time the printer is powered up.