Linear Motor Based 3D Printer

I have found very little information on existing 3D printers using linear motors. At least in principle this seems like a good idea, and there is some discussion here:,513603

and one working unit here:

There are advantages that make me want to build a 3D printer using linear motor based linear actuators:

- Linear motors can run very fast

- The actuators I consider are very stiff, both electronically and mechanically

- They are servo motors, so I can directly measure under and overshoot

- The encoders go down into the nanometer regime

I did check that last fact already by using the laser interferometer to check on some moves I did with a Parker MX 80 like this one:

A quick test with some moves over a few cm yielded at least 150 nm positioning accuracy and repeatability - good enough for what I have in mind.

The base for the printer will be an optical breadboard. These are flat, stiff, nicely anodized and have a lot of mounting holes from the get-go.

For the vertical axis, I found some linear actuators on eBay that use ball screws, stepper motors with encoders and can mount vertically. I will use two of these.

For the X axis, I found a Parker I-Force Ironless 110 linear motor mounted on a linear guide rail together with a Renishaw RGH24 encoder. The part number on the encoder is RGH24 X15F00A

That implies a 1um step size.

I made some adapter pieces that allow me to mount the X actuator on the Z actuators:

Putting these pieces together looks like this:

The linear encoder in the Parker MX80L is a Renishaw RGH24B00Z01A

This implies a 1Vpp SinCos analog signal. Often external interpolator boxes are used to turn that into a digital encoder signal, but the type of motor drive I chose can use these signals directly.

I bought some IONI drives from Granite Devices when they were introduced in a Indiegogo campaign. They can do 16, 64 or 256 times interpolation of the SinCos signal. The scale period is 20 um, so that should be 1.25, 0.3125, or 0.078125 um steps. I don't think this is in quadrature yet, so actual positional resolution may be 4 times that. We'll see.

These same drives can also use digital encoders, which is what is on the X axis, so that is very convenient here. With the IONI servo drives themselves, I also got an IONICube 4x, which allows me to interface them to the motors and feedback and control devices.

The IONICube takes 24V to drive it's logic components and allows motor drive voltages from 5-52 V.

I decided on a DuetWifi board to act as printer controller.

The Duet can run on a 12-24V input. This could be quite convenient. I can run the heatbed, nozzle heater, Duet and IONICube, and motors on 24V. If I don't like the performance of the linear motors, I can increase the voltage for those up to 52V. However, the heatbed I chose is made for 12V, and so the PWM controller of the Duet has to be carefully set to not heat it up too fast. I will probably add a fuse to be safe. The Duet documentation here:

states that the PWM can be limited to a maximum duty cycle. So I will use a combination of that and a fuse.

So, to start, I put all the major components on a literal breadboard:

From there I proceeded to update the firmware on the IONI drives. They still had the initial firmware on them...

Next, the linear motors need to be connected to the IONICube and the drives need to be configured.

The pinout of the RGH24B in the Parker stage is:

The Parker stage has 3 cables coming out of it.

This seems like a straight forward connector swap, since the feedback connector for the IONICube is also a 15 pin one.

An important note on shielding: Signal ground and earth ground should not be connected together. The proper way to connect the shield on an encoder cable is as explained here:

If there is only one shield, then that needs to be connected to earth ground.

The feedback pinout on the IONICube is:

Pin #

















Pin layout

Pin name

















Electrical type (in most feedback device modes)

Alternate electrical type (in some feedback device modes, i.e. SinCos encoder)

Connection with various feedback devices

Feedback cable shield

Hall sensor input, phase W

Hall sensor input, phase V

Hall sensor input, phase U

Quadrature encoder (B channel)/SinCos/serial encoder/resolver input

Quadrature encoder (A channel)/SinCos/serial encoder/resolver input

Encoder power supply

Connect normally closed (NC) limit switch between this pin and GND pin

Connect normally closed (NC) limit switch between this pin and GND pin

Connect normally closed (NC) limit switch between this pin and GND pin

Quadrature encoder index channel (Z channel)/serial encoder input


Digital input W

Digital input V

Digital input U

Encoder supply ground

Differential input B-

Differential input B+

Differential input A-

Differential input A+

SinCos input B-

SinCos input B+

SinCos input A-

SinCos input A+

Encoder supply 5V output

Encoder supply ground

Axis negative direction end limit switch (optional)

Axis positive direction end limit switch (optional)

Axis home switch switch (optional)

Differential input C-

Differential input C+

Female D-sub 15 connector as it appears from outside of drive. Note: counterpart (male) connector has mirrored pin layout if viewed from pin side, and same layout if viewed from soldering side.

So here is the parker cable assignment for the first test:

The limit switches come, as described above, from a second cable. The IONICube supports hard homing, so I am not sure right now whether I want to use the limit switches or not.

And the motor pinout on the IONICube is:

And the example for 3 phase motors is given as:


To check the encoder parameters, I set the interpolation to 256x and moved the actuator its whole range of about 154 mm. The reading was about 7840000. 154000/7840000 comes out to about 0.0196 um.

Above, I estimated 0.078125 um steps at 256x interpolation of the 20um scale. It looks like I get another 4x from quadrature interpolation as 0.078125/4 = 0.01953125.

This runs at a top speed of just 1000 mm/s, but only when doing full range moves:

I did get a standard Prusa style bracket to hold the heated build plate and mounted that on the MX80L. Then, after some tuning here is what that works like. The moves are a bit more of what one would expect for 3D printing. The top speed of the fastest moves here is about 500 mm/s:

Analysis of tracking error of these moves shows that with the current tuning parameters the setup can hold position to within 4000 counts. That is equivalent to 0.01953125 * 4000 = 78.125 um worst case at maximum acceleration allowed by the servo controller settings. Lower accelerations provide higher accuracy, of course.

This is good enough to move on to the next axis.

The pinout of the RGH24 X15F00A is:

The 'A' at the end of the part number indicates that this sensor is set up for a reference mark, rather than a limit switch.

The motor itself has the following pinout:

Both, the motor and the encoder use connectors that fit onto a 10 pin IDC header.

So in the case of the encoder:

And for the motor:

But the IONI wants the encoder and hall signals on the same 15 pin connector:

Since I already have designed ICD to RJ45 adapter board for HEDL encoders, I decided to use those at for prototyping the servo:

The standard board would assign the RGH encoder signals onto the RJ45 pins like this:

which is not going to work. But the board has been designed to be easy to cut and jumper, so the pins will be reassigned:

The second adapter board connects to the motor. I have some concern about the ethernet cable being able to power the motor, but it's worth trying. Ethernet cables of category 5 should be between 22 and 24 AWG thickness, according to:

It looks like Cat5 and Cat6 cables are readily available in 22 AWG. The rated current for a conductor like this is shown here:

So depending on cooling the 22AWG ethernet cable should be good for 1-7A, and 24 AWG about half that. I suppose I can almost double that by doubling up on the conductors in a cable.

Unaltered, it maps the pins like this:

So it looks like it's sufficient to reroute pins 5 and 6:

Sanity checks: The encoder is supposed to resolve 1um steps. The electrical cycle length for the motor is specified as 60.96 mm. So I moved the motor up to a particular hall transition, marked the position, and then moved the motor until that transition repeated. The distance moved should match the electrical cycle length - and it does. The encoder count moved by 60150, which is very close the the theoretical 60960.

This works pretty well, as can be seen here:

However, there are some situations where the IONI is incable of holding any accuracy at all. When setting the maximum speed to 1000 mm/sec, most moves are problematic in one way or another depending on the tuning parameters. At 500 mm/sec maximum speed most moves can be made to have an acceptable tracking error, but there are some pathological cases where a resonance appears, like here:

There is a tracking error of about +-30000 (60mm) counts for a move of about 50000 counts (50 mm). This is pretty unacceptable.

I think I will have to look into adding friction to the linear rail to address this. Or maybe replacing the IONI with a better drive will solve the problem. Of course, it is also the case that usually there is a tracking error limit, so that the drive would set an error and disable itself with errors like that. However, most 3D printers run open loop anyway and I am more interested in what my tracking errors are like over time than in canceling the print.

Another problem is that these drives are very noisy and generate a constant hiss even when idle. I have 2 more IONI drives in a Roland PNC retrofit mill. There, too, the drives are very noisy. So this is a good opportunity to test the Granite Devices support. First, I sent a message to their online forum here:

I got some feedback within a day, which was not helpful. But since they can't know if I know anything about servo tuning at all, it was reasonable advice. Then I replied that their advice was not helping the situation. Then.....crickets.

After 20 more days of no reply, I gave up on the online forum and sent out a formal tech support request through their website, adding a short video with the noise.

On Feb 2 I sent this:

"Hi, I am using IONI drives for linear motors. 2 of them are in a milling machine and 2 are in a 3D printer. They are noisy. There is a constant hissing. I have been building CNC machines for years, so I have experience tuning drives, but I don't claim to be an expert. Messing with the torque bandwidth is ineffective.

I am attaching a video with the noise. There is no way to convey the correct loudness of course, but you can hear the nature of the noise."

Anyway, how can I remove the hissing?"

On Feb 5 I got this reply:

"Hi Jan

What revision of the IONI card are you using? The first revision had some cross-talk noise that was somewhat reduced in the second revision.

Also, if the tuning is very tight, it also causes some hissing."

So on the same day I replied:

"I tried very tight and very very loose tuning. Noise still very audible.

All 5 of my IONI drives are from the original Indiegogo campaign."

Then, within a few hours, I got the following reply:

"What firmware version are you using? We implemented at one point a noise reducing filter when TBW < 680 Hz.

Also, you can lower the resistance and inductance values, although that would affect the tuning."

To which I replied:

"I am using the latest firmware.

The TBW only ever changes the pitch of the noise, but not the loudness, though I can clearly tell when I go below 680 Hz by a lowering of the pitch.

The resistance and inductance values have a very positive impact. I lowered the resistance from the ~7.5

ohm to 5 and the inductance from ~2.2 mH to 1. It did noticeably quieter, but I did not want to push these values lower than that without knowing what I am doing.

I certainly don't mind retuning.

Am I endangering the motor or the drive by lowering these values? How am I affecting drive performance when lowering the resistance? The inductance?"

11 days later I sent them a reminder:


Hi, just a friendly reminder about the outstanding questions.

Thank you."

Then, 6 days after that, I noticed that the granite devices support online ticket tracker does not show my replies, so I re-submited the first reply there. Maybe they can send emails to me but not get any back?

They then came back with information on the forum that was pertinent:

I was able to get the drive quite quiet by putting the resistance and inductance values to ~ 1/10 of the real values. I originally thought that by measuring these values or putting in the manufacturers’ published values, that was the best for any use case. I think most others would think this too. I now consider these values to be just another tuning parameter, and I think they should be documented as such. Since there is no deadband filter, you lose performance if you don’t like hunting. The X axis was hunting ± 1 count (1 micron) and produced a quite annoying squeal. I reduced the gains to get rid of it, but of course the motor performance is lower than it could be.

Some small things that I hope GraniteDevices addresses in a future release:

  • the tracking error graph on the servo scope would be more useful to me if it showed distance units on the right hand side. This way I can tell what the worst case tracking error is without taking out the calculator.
  • I sure wish there were some frequency analysis available in the servo scope and maybe a bode plot together with one or more IIR filters in the IONI. I had to use my phone with an audio spectrum analyzer to get any idea at what frequency a filter should be set up. Of course, that only works if you manage to find a pathological case manually and get it to persist long enough to get a reading…

Also, the tech support is kind of hit and miss. Sometimes you get a great answer quickly. Sometimes you have to wait a number of days and still get an answer that is not very helpful. I actually had already given up hope on the support and ordered a Parker Compax 3 drive to solve the noise problem. Maybe I will still make the substitution to compare performance. My experience with Dynomotion has been way better. They usually come back with pertinent questions or very helpful suggestions within 24 hours. In any case, the X axis is now very quiet.

The Z axis actuators are driven by Vexta PK245-01BA stepper motors, and the Duet Wifi can drive them independently to correct for vertical misalignment of the build plate:

They came with some connector that I did not have a match for. And the X-Y stage I used for the PNC-300 retrofit came with cables using DB9 connectors, so I am going to use them for this project.

The motors have 6 leads, connected like this:

So, I am using the following pinout:

With the plan of using only 1/6 and 5/9.

To mount the connectors on the z axes I fused a 3D model of the bottom of a standard DB9 shell with a ring that fits on the existing mounting holes. Then I just screw the top of a standard DB9 shell to that and have the connector firmly mounted.

Since I don't plan to use the stepper drivers for the X and Y axes on the Duet Wifi, I am using them to drive the dual Z axis. Instead, I am going to use the step/direction signals on the expansion header and forward those to the servo drives. The Z axis can then be configured by changing the config.g file with the following lines:

M584 X8 Y9 Z0:1 E3 ; Apply custom drive mapping

M350 X16 Y16 Z128 E16 I1 ; Configure microstepping with interpolation

M92 X80 Y80 Z5120 E420 ; Set steps per mm

And that allows me to jog the z axis:

The stepper motors here are noisier than I had hoped, so I tried to change the connections to

2/6 and 4/9. The hissing is less, but still more than I like. I may replace the stepper driver with a servo driver at a later time...


The IONIcube has two connectors, X4 and X5, that will be used to connect to the DuetWifi.



And the DuetWifi Expansion connector has the following pinout:

The signal levels on the DuetWifi are 3.3V whereas on the IONI they are 5V. This requires some care.

In all, there are 8 signals that need some sort of level shifting:

- The 2 signals coming from the DuetWifi to the IONI to start homing

- The 2 signals coming from the DuetWifi to the IONI to take a step

- The 2 signals coming from the DuetWifi to the IONI to select direction

- The 2 signals coming from the IONI to the DuetWifi to signal that homing is done.

After rummaging through the parts bin, I decided to use a IL715 signal isolator as a level shifter. This also helps separate motor noise from the boards.

Three signals require a GPIO pin on the DuetWifi:

Before the IONI servo drive operates, an enable signal has to be set high. DuetWifi Pin 9 is labeled E3_STOP and has logical pin name 61. This will be the enable signal.

Pin 19 is labeled E5_STOP and has logical pin name 63. This will be the homing signal for the X axis.

Pin 14 is labeled E4_STOP and has logical pin name 62. This will be the homing signal for the Y axis.

The remaining pins can be used without manually toggling GPIOs. The connection map between the DuetWifi and IONI is as follows:

I am using a Bondtech BMG extruder, to use in a bowden configuration. This then feeds the left side of the chimera which is put in a custom mount. I also made a mount for a IR height sensor.

All this then allows for a first test print:

But of course, there is still a lot of cleanup work to be done: