Introduction: CNC Feed-rate Measuring Tool Made From Scrap

About: Electronics enthusiast

Has anyone ever wanted to measure the actual feed-rate on a CNC machine? Probably not, until the milling bits are intact after a CNC job... but when they start breaking on a regular basis, maybe it is time to investigate. In this instructable you can follow a quest in determining the actual feed-rate of a CNC machine. It will cover the reverse-engineering part of a printer, arduino firmware, PC software, and the results I got with the help of my colleagues, and a trash turned into treasure.

Step 1: Materials, Tools, Devices Used to Get the Project Running

When I began working on this, I thought out a short list of the things we will need:

  • disassembled printer carriage mechanism
  • hand tools to tweak that
  • soldering iron, solder, wires
  • multimeter
  • oscilloscope or logic analyzer - this is not absolutely necessary
  • power supply
  • microscope
  • Arduino nano + pinout
  • PC with Arduino IDE, Visual Studio 2008 Express + MS Charting tools installed
  • (MPU6050 - I ended up not using this)
  • willing to browse for everything you don't know how to do

At the beginning, I thought that an MPU6050 board will allow me to measure feed-rate on all three axes at once. Having the accelerometer inside it, I was sure that summing up accelerometer data will give me the desired value - the speed on each axis. After downloading and modifying an Arduino snippet that displayed raw data on the serial monitor, I wrote a small PC program in Visual Studio that processed the data, and plotted it on a chart for easier interpretation. I had to download both Visual Studio C# Express 2008 and the charting tools for this.

After coding a while and looking up all the things I needed for serial communication, I ended up with the values plotted, but no matter what I did, it wasn't usable. Small but sudden movements would result in huge spikes, while longer travels wouldn't even show up on the charts. After two days of hammering the MPU6050, I finally gave up and turned to something else - a disassembled printer's position feedback mechanism.

Step 2: Hardware Stuff That Needed to Be Done

Reverse Engineering

Of course, the printer mechanism had no part number I could have used to determine its exact properties, there was need for a little reverse-engineering to get where we wanted. After closely examining the mechanism and the electronics, I decided that the first thing has to be the identification of the optical sensor pins. This had to be done in order to interface the whole thing to the Arduino. I disassembled the black plastic part, extracted the PCB, and examined the sensor: it had ROHM RPI-2150 written on it. That got me happy, the hope was high that I'll find a datasheet. Unfortunately this is either an old, or a custom part - there was no datasheet to be found anywhere on the web. This meant that I had to take matters into own hands: knowing that these sensors usually have an infrared LED and two photo-transistors inside, I grabbed a multimeter, set it to diode measurement mode, and began measuring between pins.

The power pins are usually easy to find - they will have capacitors across them, and they are usually connected with wide traces on the PCB-s. Ground traces are often connected to multiple pads for better noise rejection.

The input and output pins are not that trivial, however. When measuring across a diode, the meter will show its forward voltage in one direction, and overload (infinite) in the other. I was able to identify four diodes between pins, I concluded that the fourth diode must be some kind of zener or TVS diode, as it was right between the power pins of the component. Locating the infrared emitter was easy, there was a 89R resistor in series with it. I got left with two diode measurements on the remaining two pins, those had to be the two receivers.

Note: These sensors have two receivers in order to be able to determine the direction of movement in addition to determining the position by counting the pulses. These two output waveforms are 90° out of phase, this is used to produce a count-up or a count-down pulse. By following the number of these pulses, the exact position of the printing head can be determined.

When the emitter and the two receivers were located, I soldered wires on their pins, so I can interface the sensor with the Arduino. Before doing that, I supplied the sensor with 3.3V, pulled the strip between the sensor a couple of times, and observed the square wave on the outputs. The frequency of the square wave varied with the movement speed, and I concluded that the measurement system is now ready to be connected to the Arduino.

Connecting the Arduino

Connecting this new 'sensor' is very easy. Just connect the sensor outputs to D2 and D3 (interrupt-capable pins!), and the power supply lines, and the coding can begin.

Step 3: Arduino Coding

The Arduino code is quite simple. I assigned a function that executes every time D2 sees a rising edge, this is the elapse function from the Arduino code I attached. If you take a look on the signals of a quadratic encoder, you will see this:

  • in one direction phase A is logic high on every phase B rising edge
  • in the other direction phase A is logic low on every phase B rising edge

This was the property of the encoder I took advantage: since the elapse function executes every time D2 has a rising edge, I just wrote an if that increments a counter when D3 is high, and decrements it when D3 is low. This worked at first try, I sent the counter value out to the serial monitor, and watched it increase/decrease when I moved the printer head on the shaft.

Long story short, the firmware does the following thing in the loop function:

  1. checks the serial receive buffer for any incoming data
  2. if there is incoming data, check if it's a '1' or not
  3. if it's a '1', it means that the PC software is requesting the counter value
  4. send the counter value to the PC via serial
  5. start over at 1.

With this, the ball is in the PC software's court now. Let's get into that!

Step 4: Visual Studio C# Software

The purpose of the VS C# program was to shift the computational burden from the Arduino to the PC. This software receives the data the Arduino is providing, computes and displays the speed in the form of a graph.

What I first did was to google how to do serial communication in C#. I found a lot of good info on along with a good example, then I just threw out what I didn't need - basically everything except the reading part. I set up the COM port and the speed to match with that of the Arduino, then just gave it a few tries and dumped everything that came on the serial port into a multi-line text box.

After the values were read, I could just use the readto & split functions to isolate one measurements from each other, and from delimiter characters. These were plotted on a Chart control, and the values began to appear on the screen.

If you can't see the Chart control in your VS toolbox, you can google the problem and find the solution here (look for answer #1): link

The measurement principle

To find the connection between the number of counts and the distance the head travels, we zeroed the count value, moved the printer head 100mm by hand, and observed the change in counts. We finally came up with the following proportion: 1 count = 0.17094mm.

Since we can query the distance and we can measure the time between the samples, we can calculate the rate at which the position shift happens - we can calculate the speed!

There is a rough software timing of 50ms thanks to TMR0, but we observed that these timings weren't too accurate. In fact, after some software speed measurements, we found that the timed 50ms isn't 50ms at all. This meant that the samples weren't taken at fixed interval, so the speed calculation couldn't use a fixed time-base either. Once we found this issue, it was easy to move on: we took the difference in distance and the difference in time and calculated the speed as D_distance/D_time (instead of D-distance/50ms).

Also, because our equation would return speed in units of mm/50ms, we need to multiply this by 1200 to get the distance the head would go in one minute, in [mm/minute].

Note: the Mach 3 CNC mill controlling software defines the feed-rates in units of [mm/minute]


From this point on, the measurements seemed to be pretty accurate, but there was some noise on the measured signal. We suspected that this was due to mechanical inconsistencies in the shaft, shaft coupling, etc, so decided to filter it out, to get a nice mean value of that what is measured.

Fine adjustments to the software

In order to change the sample rate and filter rate during runtime, scrollbars were added - one for each. Also, the ability to hide the plots was also introduced.

Step 5: Results

After the hardware and software parts were ready, we ran three sets of measurements with mach 3 + my software, you can see the results on the attached pictures.Later experiments showed better accuracy, with both filter and sample rates increased. The plots show the measured speed with solid red, and the average with dash-dotted blue.

That being said, it looks like Mach 3 handles these speed settings quite accurately, but now we know for sure:)

I hope you enjoyed this short instructable about reverse-engineering and turning water into wine!


Trash to Treasure

Participated in the
Trash to Treasure