How to build high precision (0.122µm resolution) linear actuator

had to change precision in title because of this posting further below

This posting is on how to build a high precision (3µm accuracy) linear actuator, and provides basic needed sketches.


The 28BYJ-48 stepper motor has 4096(!) half steps per revolution.
You can find the math behind the features of using 28BYJ-48 motor shaft itself as high precision linear actuator here:
https://www.raspberrypi.org/forums/viewtopic.php?f=43&t=210605&p=1563791#p1563791

Summary for this high precision linear actuator:

Operating range: 0..1mm [0..1038µm measured]
Steps: 604 [600 steps used for measurement]
Linear distance change per step: min=3nm, max=3.062µm, avg=1.655µm
Feedback from 0.001mm electronic micrometer allows for automatic 0° calibration.

This actuator is a cam type linear actuator.
Unlike normal linear actuators, the (linear) step width here is not constant (guaranteed <=3.062µm/step).
This is an advantage for microscpope type of application, since minimal step (just before 0°) is <=2.95nm(!!).

You can use the 2$ stepper motor alone as linear actuator, you need a lever with a spring only in this case.
I did build it onto 46$ 0.001mm resolution electronic micrometer for feedback:

I did wire the 28BYJ-48 stepper motor with an L293D on breadboard according this description with and Arduino Uno (I know that there might be problems with powering stepper motor from the Arduino 5V rail, but it works):
~~https://lastminuteengineers.com/stepper-motor-l293d-arduino-tutorial/~~

I did control the 28BYJ-48 stepper motor with ULN2003 motor driver and Arduino Uno (I know that there might be problems with powering stepper motor from the Arduino 5V rail, but it works).

I used this script for calibration. It uses AccelStepper library mainly because that supports half stepping. It asks for position on serial monitor, and when you input new position followed by return, it will move to that position and print the value you enterd into console output as well. Since with reset of any sketch the stepper motor current position is taken a 0, I did try different positions until motor was in 53.13° position. Then I pressed reset button to make that position the 0-position of stepper motor. The electronic micrometer reading is typically not 0 at 0-position set for stepper motor -- press ZERO button on electronic micrometer to change that:

#include <AccelStepper.h>

// ULN2003
AccelStepper stepper(AccelStepper::HALF4WIRE, 2, 4, 3, 5);

void setup()
{  
  stepper.setMaxSpeed(500);
  stepper.setAcceleration(50);
  Serial.begin(9600);
}

void loop()
{
  if (stepper.distanceToGo() == 0)
  {
    Serial.print("pos? ");
    while (!Serial.available()) { delay(50); }

    int pos = Serial.parseInt();
    if (Serial.read() == '\n') {
      Serial.println(pos);
      stepper.moveTo(pos);
    }
  }
    
  stepper.run();
}

I used this sketch for the demo video I uploaded to youtube. After the demo completed, sketch goes into endless loop at 0-position. You can upload another sketch, or press reset to start it again. The sketch moves to some positions, and waits for 2 seconds before moving on to next postion. The 2 seconds are needed to make notes of the values displayed by 0.001mm resolution electronic micrometer:

#include <AccelStepper.h>

// ULN2003
AccelStepper stepper(AccelStepper::HALF4WIRE, 2, 4, 3, 5);

int i=0;
int A[]={
  -600,0,
  -100,-200,-300,-400,-500,-600,0,
  -100,-200,-300,-400,-500,-600,0,
};

void setup()
{  
  stepper.setMaxSpeed(500);
  stepper.setAcceleration(50);
  Serial.begin(9600);
}

void loop()
{
  if (stepper.distanceToGo() == 0)
  {
    if (i == sizeof(A)/sizeof(A[0]))  for(;;){}

    Serial.print("moveto(");
    Serial.print(A[i]); Serial.println(")");
    delay(2000);
    stepper.moveTo(A[i++]);
  }
    
  stepper.run();
}

Youtube video is here:

Stepper motor starts at 0, then moves to 600, back to 0, and then two times to 100,200,300,400,500,600,0.
The micrometer measurents are repeatable for those positions (0/276/530/736/887/991/1038).
If you want to verify, you will have to look at youtube video, the animated gif shows 0,600,0,600,0,... only:

I never had to connect something to metal before. My favorite method of connecting anything is superglue. But I wanted to be able to remove the stepper motor, so it had to be screwed somehow. I decided to superglue two small Lego pieces onto metal, drill holes into them and screw the motor. There was a 0.2mm higher metal area on the left -- I decided to dremel away a bit from the Lego piece left. On the right the Lego piece did not fit 100%, so I used Dremel again to correct Lego piece:

I used M3x16 screws, and drilled 2mm diameter holes with Dremel:

I had to add two M4 screw nuts with those screws in order to be able to firmly screw stepper motor:

The addition of black cardboard above stepper motor was not needed fuctionally.
It allows to capture video without too much reflection by stepper motor metal surface:

P.S:
Need to figure out which serial cable is needed (for automatic 0° calibration, automatic reliability testing, graphing, ...):

P.P.S:
Seems to be this RJ11 6P4C Male to 4 Pin AV Screw Terminal Connector, will know tomorrow, just ordered it on Amazon Prime:

P.P.S:
RJ11 is too big, does not fit -- so what connector is needed?

Pop on a nautilus shaped hub and you could triple your resolution.
Even a offset bearing would double your possible resolution.

Shouldn't this be moved to the Exhibition / Gallery section ?

...R

Slumpert:
Pop on a nautilus shaped hub and you could triple your resolution.

Very interesting idea.
The mathematical term is logarithmic spiral:

Under "Properties" it is stated that the logarithmic spiral has constant(!) polar slope. That means that diffently to using stepper motor shaft itself (where max is 3.062µm and min is 3nm) the distance change per step would be identical for all steps!

On German Wikipedia page there is a formula for the radius of angles:

For operational range 0..1mm of the linear actuator this formula needs to be satisfied:
r(∝+2π)-r(∝)=1

With above formula and E=e^(2π):
E^k r(∝) - r(∝) = 1
(E^k-1)r=1
E^k=1/r+1
kln(E)=ln(1/r+1)
k
2π=ln(1/r+1)
k=ln(1/r+1)/2π

So choosing r=4mm gives k=0.0355:

$ bc -ql
pi=4*a(1)
r=4
l(1/r+1)/(2*pi)
.03551439921073648034

It will not be possible to get a full turn, but for easy calculation lets assume we get 4000 stepper motor steps. That means 1mm/4000=0.25µm per stepper motor step -- compared to 1.655µm on average now, factor 6.62 better.

But where can I get such a logarithmic spiral from?
Best would be metal.
Length of one slope per stepper motor step is roughly 2π*4.5/4000=7.07µm.
Even more, height difference per step is 0.25µm
I think that 3D printing is way too coarse for such structures.

Another point is that while step width of 250nm is fine, step widths down to 2.95nm at and near 0° are so much finer ...

P.S:
I just calculated how many steps will have linear distance change per stepper motor step less than 250nm with motor shaft method from initial posting. The answer is 41, from 3nm up to 247nm (formula from here):

a=3.67
r*(c(a*deg)-c((a+hstep)*deg))
.000247
a/360*4096
41.754624

The limiting factor will be the accuracy and backlash of the stepper's gear train. Backlash is eliminated by either pre-loading or only assuming accuracy in one direction. Wear and play in the gear train / bearing are probably going to gradually affect repeatability.

It would be interesting to see graphs of the behaviour for several cycles in a row and after hours of continuous operation.

MarkT:
The limiting factor will be the accuracy and backlash of the stepper's gear train. Backlash is eliminated by either pre-loading or only assuming accuracy in one direction. Wear and play in the gear train / bearing are probably going to gradually affect repeatability.

I have seen "accuracy in one direction":
If going from 0 to 100 to 200 ... (against pressure), all is fine.
Repeatability for 600 then 500 then 400 was not good.
I found workaround that was repeatable again, not sure how much overshoot is necessary.
For 600, 500, 400, ... insert auxiliary moves and repeatability is given again: 600, [450,] 500, [350,] 400, ...

It would be interesting to see graphs of the behaviour for several cycles in a row and after hours of continuous operation.

Definitely, but the RJ11 connector I did buy is too big.
I still have no idea what connector is needed for serial readout of measurements.
I don't want to solder thin wires into the electronic micrometer connector:

I used a new 28BYJ-48 stepper motor with electronic micrometer.
And I now used Raspberry move.c tool for controlling two servos (0 as 1st arg does not move the other):
https://www.raspberrypi.org/forums/viewtopic.php?f=33&t=256740&p=1565748#p1566020

It turned out that the motorshaft of this stepper motor is slightly different.
Maximal value after calibration is 992µm, and not 1038µm as with previous stepper motor.
And the move did need 5ms delay between successive steps in order to be repeatable.
So this are the commands to go up to 992µm and down to 0µm:

$ sudo ./move 0 -600 5000
$ sudo ./move 0 600 5000
$

P.S:
I did use Arduno sketch again, because that has absolute coordinates.
I did determine measurements for several succesive step numbers to prove that indeed each step of the 4096 steps per revolution has an effect:

step µm
-100 245
-101 249
-102 253
-103 255
-104 257
-105 261
-106 265
-107 268
-108 270
-109 272
-110 274
-111 276
-112 282
-113 286

P.P.S:

I had a wonderful idea and reduced 1.665µm average step width to nanometer range (6.5nm per step)!

"Lego Arduino (28BYJ48 stepper motor) nanometer xy positioning table":
https://forum.arduino.cc/index.php?topic=649270.0

I added a flexible 5x8mm motor shaft coupler to the game:

I used a flexible one because of the slit at the 8mm diameter end. I used that slit to fixate a small metallic pin by screwing . That pin is just outside of 8mm radius hole.It turned out that is lies on 9mm diameter circle. I learned that for what I did a stiff coupler would have been better.

Electronic nanometer resolution micrometer shows -2 for 0 half steps stepper motor position, 3673um after 1000 stepper half-steps and 9066us after 2000 half-steps.

Operational range is 9mm instead of 1mm before.
Average step width is 9000/2000=4.5um compared to 1.655um before.

P.S:
I measured manually that maximal width of a single stepper motor step (around middle of movement) is 8um.

When you are adventurous, you can drill a 1mm hole axial out of center in the shaft and mount a hardenend pin in it.

Oops, just saw, the shaft has 3mm diameter, you want it bigger.

I looked at the screws I had, and M3x25mm shoulder bolt was the one with smallest distance between successive shoulders. On Wikipedia I read that M3 has slope 0.5mm, which was what I measured as well.

Using a moving nut on that screw seems to be what standard linear actuators do. I did it because:

  • the linear distance for each step is identical
  • with 4096 half-steps per revolution, resolution is 500µm/4096=0.122µm(!)
  • operational range is even longer than the electronic micrometer allows

First the results, I took a 9min video, the 100,000 hsteps back from position 100,000 to 0 took more than 3 minutes at 500hsteps per second maximal speed.

Readings from µm resolution electronic micrometer:

Start at position 0(0µm)
stops at position 20,000(2423µm)
40,000(4857µm)
60,000(7295µm)
80,000(9730µm)
and 100,000(12177µm).
Then back to 0(13µm, wrong direction of move)
and 20000(2419µm).

M3x25 screw is not always parallel to moving direction, compensated by plastic piece superglued between screw and motor shaft:

It was impossible to superglue M3x25 screw onto motor shaft. But I was able to superglue both to small piece of plastic:

After I was done with complete building everything together for the 1st time, I realized that superglue accidently got between the micrometer probes. I had to disassemble and use an hot air air dryer and plies to get the probes separated. You can see superglue on right probe. The red and yellow Lego pieces are the only I did superglue together in order to achieve the needed stability:

The stepper motor did need to be placed nearer to the blue Lego piece than it would allow normally. I used my Dremel rotating disk to reduce the Lego piece a bit where needed:

This is current setup (the 4th! In 2nd setup superglue accidentially reached shoulder screw, 3rd did work but screw was skew):

The connection between M3x25 screw and (M5) motor shaft is not good.
I did order eight 3x5mm motor couplers at aliexpress:
https://www.aliexpress.com/item/4000221326289.html
And a single same model coupler on German amazon prime that does cost the same(!) as the 8, but will arrive here on Monday.

M3 does not have an outer diameter of 3mm, it's slightly smaller. If you tighten it with one setscrew, it'll be out of alignment. You can improve that by wrapping a 0.2mm copper wire in the groves of the screw.

zwieblum:
M3 does not have an outer diameter of 3mm, it's slightly smaller. If you tighten it with one setscrew, it'll be out of alignment. You can improve that by wrapping a 0.2mm copper wire in the groves of the screw.

Thanks, but the couplers ordered on aliexpress as well on amazon all have 4 screws.
Here you can see that the two holes on each side are opposite.
Adding copper wire might help in addition (on the 3mm side):

P.S:
I just looked up my aliexpress order list, did buy 100m of 0.2mm copper wire two years ago, and just found it on bookshelf.

P.P.S:
I used a 250m coil of 0.5mm copper wire at that time to try to get minimal delays for signals. I measured speed inside 0.5mm copper wire to be in 240,000-250,000km/s range (80%-83% of speed of light):
https://forum.arduino.cc/index.php?topic=291435.msg3140017#msg3140017

The motor coupler arrived early yesterday evening.
I did mount with the 4 screws on 5mm motor shaft and on M3x25mm side.
No copper wire yet.
But seeing the amount of play the motor shaft itself has, there seems to be no need to improve 1/10th of millimeter misalignement the M3 screw might have:

Operational range of the nut on M3x25 screw got reduced to 0..15mm.
But that is still enough for electronic micrometer:

Now I have to remove the previous motor from electronic micrometer.
And its superglue time for the new motor and screw.

Hm .. you'll nned real rigid rails on Z to decouple that :slight_smile:

I found a new place on electronic micrometer for supergluing Lego pieces, to which I superglued the stepper motor.
Now all is in place and works. Operational range is reduced slightly to 0..11,291µm (92,000 half-step positions):

Turning motor now sounds like a sewing machine for the first time.
I did amplify a short video 16× to make it audible:

Now its time to figure out how electronic micrometer serial interface works for automatic measurements: