A Tale of Two CNC Routers (Part 3)

Welcome to the conclusion of my CNC router saga.

I had a newly minted “OX” CNC router, a.k.a. the “Mark 2”, but there were still things to do before I could begin using it for actual projects (like the Crokinole board I wanted to build).

Adding an Encoder

On the Mark 1 I tried to determine if it was missing steps by commanding a move and then measuring the position change of the router using a ruler. This was good for gross positioning errors, but that was about it. For the Mark 2, I wanted to find out exactly how many steps were being dropped when milling.

A few months back I had a wild hair to add encoders to the steppers on the Mark 1 with the end goal of building a “poor man’s” servo system using a microcontroller, stepper and encoder. I looked around and bought some $20 Chinese 400 step/rev encoders. When they showed up, I connected them to an Arduino and LCD display using a contributed encoder library. I pretty much ignored them after that. Now that the Mark 2 was built, however, I decided to connect an encoder up to an X-axis stepper and see how it was working.

I cobbled together out of a piece of plywood, dowels and zip ties what has to be the sketchiest mount in history for an encoder:

The Frankencoder
The Frankencoder

As it turned out, it was good enough for my needs. Because the encoder had quadrature signalling, it gave me a positional resolution of 1600 counts/rev. This was more than adequate since I was only 4x microstepping my 200 step/rev steppers. The encoder connected up to a Sparkfun Inventor Kit I had laying around:


Feeds and Speeds

With my kludged-together encoder ready to go, I proceeded to start testing how deep and how fast I could mill solid cherry stock. I used the same 1/4 inch spiral end mill I had used earlier in the Mark 1 when I tried to make my Crokinole board. I wrote by hand a simple g-code program to drop the end mill X mm into the work piece and then mill a 10 cm groove at a feed rate of Y mm/min. One issue I thought of with the encoder is that if the machine reliably drops steps when moving in both positive and negative directions then the encoder won’t show a problem – it would read 0 when returning to the start position either way. I addressed this in my G-code file by returning the end mill back to the start position with the end mill raised above the work piece. Presumably if it was going to drop steps, it would drop more when it was under load while it was milling than when moving through air. I tried a number of X and Y values:


If you look carefully at the above photo, you will see a large amount of chattering, especially at the larger depths and faster feed rates. This was disheartening until I realized that I hadn’t tightened the clamp holding the router to the Z stage. After I tightened it, I tried again:


There was virtually no chatter on this attempt. Also, no steps were being dropped at any feed rate and depth. This was a huge improvement over the Mark 1. All of these tests were done on the X-axis. Because I never saw any steps being dropped, I figured testing the Y-axis wasn’t worth my time even though it only had a single stepper driving its motion (as opposed to the two driving the X-axis). On the other hand, the Y-axis stepper was moving less mass than the X-axis steppers.

The Z-axis was a different matter. Unfortunately, since the new stepper I bought for the Z-axis didn’t have a double-ended shaft, I couldn’t easily add my encoder. What’s more, when I measured the depth of cuts on my two test pieces, I saw a consistent increase of depth from cut to cut – implying that the Z-axis was skipping steps when moving in the positive direction (raising). This wasn’t too surprising since this was the direction that put the most load on the drive. It had to fight gravity. After playing around with it for a bit, I dramatically decreased the acceleration parameter in the configuration file. I made another series of test cuts (not shown) that demonstrated a consistent depth of cut.

My testing with the encoder was done and the Mark 2 was exceeding my expectations.

Configuring Soft-limits

Next up was to determine what soft-limits to add to the configuration file. Soft-limits are positive and negative values for each axis that software will avoid moving past. This is independent of any limit switches connected to the setup. I set the maximum limits for X and Y by moving each axis until the positive limit switch was about to be triggered. The minimum limits were initially set to 0 for the X and Y axis. Since the Z axis only had a limit/home switch on the positive direction, I set the maximum limit to 0 and estimated the minimum limit using a ruler. I soon discovered that I couldn’t reliably “turn a corner” when an axis was at the maximum or minimum value. I suspect that LinuxCNC/MachineKit has small rounding errors when moving multiple axis at the same time. I solved this by reducing the minimums and increasing the maximums by 0.1 mm.

Engraving the Build Area

I wanted to mark the build area on my spoil-board for two reasons:

  1. I wanted to be able to see exactly what the usable range of the machine was when I was clamping a work piece to the spoil-board.
  2. I wanted to have parallel lines marked in the X and Y directions in order to orient my work pieces correctly.

I put a vee-groove bit into the router and wrote by hand another g-code file to accomplish this (I should have written a perl program to write the g-code). It was actually during the testing of this g-code that I discovered the issues around my initial soft-limits. Since I hadn’t tested feed rates with this setup I took a guess as to how fast the router could engrave a 1mm deep line. I was wildly optimistic as to how fast it could move while engraving. When I ran the g-code for the first time, it engraved the first X line fine, but it started dropping steps on the Y line. I then scaled back the feed rate and tried again. This time it worked fine. Each of the grid lines had a spacing of 5 cm. This exercise showed that it will probably be worthwhile to connect the Frankencoder to the Y-axis stepper and run tests on the Y-axis. Some day.

Engraving grid lines on the spoil-board

Building a Dust Shoe

Another feature on the Mark 1 that could have stood improving was the dust collection. The Mark 1 featured a dust collection inlet in proximity to the router bit, but it was far from fully effective. It really needed a skirt of some sort to contain and control the sawdust (can it be called “swarf” with wood?).

While casting about on the interwebs, I found an Instructable to build a dust shoe for a ShopBot. It consisted of a number of layers made of 3/8″ clear polycarbonate held together with rare earth magnets. The top layer is designed to clamp to the router/spindle and connect to the dust collection hose. The bottom layer has a dust skirt made of clear thick vinyl. Intermediate layers can be added to adapt to the length of the end-mill. The Instructable provided a dxf file in addition to instructions on building the shoe. Because of differences in router and dust host diameters, I wound up designing my own from scratch, using the dxf file as as reference.

As all of my good shop experiences tend to be, building this was a learning experience. Lesson 1 was that finding speeds and feeds for cherry hardware was no help in determining how fast to mill polycarbonate. The internet provided some ideas: in order to avoid melting the plastic you have to make shallow cuts using a fast feed rate.  Lesson 2 was much bigger however – Don’t use a down-spiral bit when cutting polycarbonate. Guess how I figured this out:

This is what you get with the wrong kind of end-mill.
This is what you get with the wrong kind of end-mill

The down spiral end-mill jammed the plastic chips down into the cut where it would melt and make a hardened mess, getting worse with each pass. I couldn’t figure out what was happening – I could find anyone having similar problems on the internet. A little bit of thinking after having wasted half of my plastic stock revealed the problem. I dug up an up-cut end-mill and tried again:

All better
All better

On the above photo you can see that I also bored a hole and added a machine screw and nut. This formed the clamping mechanism that attaches the shoe to the bottom of my router. After friction fitting the 1/4″ diameter magnets, I stole the 2.5″ dust host fitting from the Mark 1 and bolted it to the shoe top. I attached a 2″ wide vinyl strip to the the shoe bottom with self-tapping screws.


The completed dust shoe
The completed dust shoe

I’m pretty happy with how it turned out. Many thanks to gerg for the design.

Configuring the Limit Switches

When I added the “homing” capability, I only used 3 out of the 5 limit switches I mounted on the machine and only 3 out of the 6 level-converted inputs. Homing used the Xmin, Ymin and Zmax switches and inputs. In addition, those switches were only used for homing, not as limits. I wanted to add “hard” limit switches so that the machine would shut down if it hit an (unexpected) limit. I wanted to add the Xmax and Ymax switches (the Zmin input was going to be used as an E-stop input, below) as limits as well as the existing Xmin, Ymin and Zmax switches. This turned out to be pretty easy with only a few edits to the HAL configuration file. I also had to edit the INI configuration file to tell the software to no shut down if the limits were hit while homing – otherwise the act of homing would shut the machine down as soon as the Xmin, Ymin or Zmax switches were triggered. After tracking down and fixing an open on the Xmax wire the configuration worked perfectly. Triggering any of the limit switches after homing now cause the machine to shut down.

Adding an E-Stop Switch

I wanted to add a physical “Emergency Stop” or E-Stop switch to my design. When things go south, it just takes to too long to click the equivalent button on the MachineKit GUI. Ideally this switch would both cut power to the steppers and spindle as well as tell MachineKit that the button was pushed. Fortunately, most E-Stop switches being sold have both a NC (normally closed) and a NO (normally open) contact pair. Such as this one:


I wired the NC contacts to the power cord that connected to my switch box that controlled the stepper drivers and the spindle. I wired the NO contacts to the sixth voltage-converted input – the Zmin input. I attached the E-Stop button to the middle of my support table with some scrap plywood:


Punching that button now kills the power to the steppers and router as well as tells MachineKit that I did so. Now I just have to remember that the button is there and use it.

Done for now

Like many projects, sometimes knowing when to stop can be the most difficult thing to figure out. My Mark2 is ready for some real work. Obviously there are things I wouldn’t mind doing – such as adding a relay to control the spindle from software, or rerunning the speeds and feeds characterization on the Y-axis. But what I have now is eminently usable. As I use it, I’m sure more things will show up on the to-do list.

But now, it’s time to start using it.

The Mark 2
The Mark 2