Magnetic Shaft Encoder

15K10726

Intro: Magnetic Shaft Encoder

a.articles { font-size: 110.0%; font-weight: bold; font-style: italic; text-decoration: none; background-color: red; } a.articles:hover { background-color: black; }

This instructable explains how to make a magnetic shaft encoder using a 3mm x 6mm neodymium magnet, an MLX90393 3-axis magnetometer, and an Arduino UNO R3.

The encoder outputs the absolute angular shaft position in degrees.

Accuracy is excellent ... angles between 0~360 degrees plot a straight line.

Potential applications include measuring servo joint angles and DC motor position.

Arduino test code and STL files are included.

The estimated cost of the encoder, excluding the Arduino, is less than $10.00

STEP 1: Circuit Diagrams

The encoder circuit diagram is shown in photo 1.

A logic level-shifter reduces the 5 volt Arduino levels down to 3.3 volts for the MLX90393 sensor.

Photo 2 shows the optional “bipolar motor test jig” used for plotting the curves.

STEP 2: Theory

The MLX90303 is a 3-axis magnetometer with 12-bit angular resolution. [1]

The Earth’s magnetic field may be ignored when the MLX90393 3-axis sensor is in the presence of a strong magnetic field.

Quadrature X-axis and Y-axis sinewave outputs are obtained if a neodymium magnet is rotated directly above MLX90303 chip ... the Z-axis output remains constant. (photo 1)

To be of use the X-axis and Y-axis sinewaves must be scaled to the same amplitude and their midpoints centred about zero. (photo 2)

Once we have done this we can calculate the shaft angle using the following code segment. [2]

Angle = atan2(y, x)*RAD_TO_DEG;
if (Angle < 0) Angle += 360;


The green waveform in photo 2 shows the angle-of-rotation. The 0..360 degree amplitude has been scaled to 0..3600 for clarity.


References

[1]

https://cdn.sparkfun.com/assets/learn_tutorials/5/7/7/MLX90393-Datasheet-Melexis.PDF

[2]

Code line 2 is required as the atan2(y,x) function outputs -180 ~ 0 when the shaft angle rotates from 180 ~ 360 degrees.

STEP 3: Construction

Key construction points
  • Center the magnet over MLX90393 sensor chip.
  • Position the magnet close to the sensor to swamp any external magnetic field.
  • Maintain a constant distance between the magnet and the sensor.

The curves in photo 1 were obtained when a magnet attached to a motor shaft was rotated clockwise twice then counter-clockwise. These curves are smooth because the distance between the magnet and the MLX90393 sensor was constant.

The curves in photo 2 were obtained using the experimental test jig shown in photos 3 ~ 5. In this experiment the magnet was rotated by hand. The wiggles in the curves are due to a slight rocking motion as the magnet was turned.

STEP 4: Mounting Brackets

Photos 1 & 2 show the 3D brackets used for testing


File "GT2_encoder_pulley.stl" produces the GT2 test pulley shown in photo 1. A 6mm x 3mm neodymium magnet is inserted into the end “pocket”

File GT2_sensor_mount.stl" produces the MLX90303 mounting bracket shown in photo 2. The MLX90303 module is attached to the bracket using M3 bolts via the two M3 holes at the top right. The two lower-right holes are screwdriver access holes for attaching the bracket to the motor.

The STL files were created using FreeCAD 0.2.

Cura 4.13.1 was used to slice the models.

The models were printed on a Voxelab Aquila printer with a nozzle size of 0.2mm.

STEP 5: Software Installation

Install the library

  • Open your Arduino IDE (Integrated Developement Environment)
  • Click “Sketch | Install Library | Manage Libraries”
  • Wait for the Library Manager to appear.
  • Type “MLX90393” in the search bar (photo1)
  • Select the “Adafruit_MLX90393” library
  • Click “Install”

Install the encoder software

  • Download “MLX90393_encoder.ino”
  • Copy the contents into a new Arduino Sketch ... use a text editor such as Notepad++ ... not a word processor.
  • Save the sketch as "MLX90393_encoder" (without the quotes)
  • Compile and upload the sketch to your Arduino.

Calibrate the encoder

  • Attach the magnet and sensor bracket to a NEMA17 stepper motor.
  • Run “MLX90393_encoder.ino”
  • Open your Serial Monitor.
  • Manually rotate the motor shaft once ... this calibrates the sensor.
  • (Alternately run the motor code described below)
  • The absolute shaft angle will now be displayed on your monitor.

Optional motor software

Install the following software on a separate Arduino if you wish to rotate the motor using software:

  • Run another instance of your Arduino software
  • Select the COM port number for this second Arduino
  • Download “bipolar_motor_test.ino” and copy the contents into a new Arduino Sketch ... use a text editor such as Notepad++ ... not a word processor.
  • Save the sketch as "bipolar_motor_test" (without the quotes)
  • Compile and upload the sketch to your second Arduino.
  • Open your “Serial Monitor”
  • Set the Baud speed to 115200
  • Enter T3 in the Serial Monitor (photo 2)
  • Use the Q and W keys to rotate the motor clockwise and counter-clockwise (photo 3)


STEP 6: Summary

This instructable explains how to make a magnetic encoder using a 3mm x 6mm neodymium magnet, an MLX90393 3-axis magnetometer, and an Arduino UNO R3.

The encoder outputs the absolute angular shaft position in degrees.

The accuracy is excellent providing the distance separating the magnet from the magnetometer is constant.

The sensor is small, light weight, and cheap which makes it suitable for projects such as measuring servo joint angles or the rotation angle of DC motors.

Sample Arduino code and STL files are provided. 

  Click here   to view my other instructables.

22 Comments

I love this use of a hall sensor and am using it for inspiration for a flight sim control project. I am creating a helicopter collective (very like a traditional handbrake in a car) and would like to use the hall sensor to determine level position.

I can't calibrate on each use and the level won't travel 360 degrees. Could I use the calibration values from the first set up to replace the Xmax, Ymax, etc. in the sketch, and after that the arduino would always use them and zero degrees would always be when the lever is at it's lowest (assuming that is where I position the magnet orientation). Would that work?
Sorry for not answering sooner ... just came across your question.
Can't see why it wouldn't work providing the magnetic field lines cut the sensor at the right angle. Button magnets on their edge seem to work just as well as button magnets that have been magnetised NS across their flats. Haven't tried toroidal magnets.
Position the magnet further away If the magnetic field overloads the sensor.
I made one with the magnet mounted on the back end of the shaft. That way I can keep the electronics on the other end of the stepper. I glued a magnet on the opposite end of the shaft using 3D printed a jig to keep it centered on the shaft until the glue set. When I tested the accuracy it was within a ⅓ of a degree but varied +/- throughout a revolution. I was micro-stepping and using the number of steps as a reference. Apparently micro-steps aren’t that accurate and are dependent on the driver. This is documented somewhere on the internet.🙂
I wonder if the stepper magnetic field was affecting my measurements. Your method with the magnet further away might be more accurate.
I now have an optical encoder to use as a reference but haven’t gotten back to that project..☹️
Thank you for your interest in my project and for commenting :)

My stepper shaft doesn't protrude from the rear so was forced to attach the magnet to the front. Am only using the stepper for testing ... my intention is to use the magnetometer to eliminate the mechanical backlash inherent in hobby servos.

The magnetic field from motors may well affect the accuracy. In my case the motor shaft is non-magnetic which means that my sensor is well away from any stray fields.

Thinking ... providing your readings are repeatable it may be possible to use a lookup table to eliminate any errors due to stray fields and construction.
My stepper shaft didn’t protrude past the back either but I was able to glue the magnet to the exposed end.
I thought about a lookup table but the Uno doesn’t have enough memory. My intent is to use what I have on a gear indexer to just provide a warning if there is a position error.

PS I am using the AS5600 encoder.
Nice use of a sensor for a purpose it was probably not designed for, my only question is where do you get a neodinium magnet with north and south on the edges, the only ones I can find (at a reasonable price) would have to be mounted on edge (or at least significantly angled) to work.

Edit:- Having thought about it a bit more, due to the strength of the magnet and the purpose of the sensor a small angle would have the desired effect and would probably happen anyway, due to inaccuracies in construction.
Thank you for your interest in my project :)

I'm using a normal neodymium magnet that is magnetised North South across the flat surfaces and a three axis magnetometer. Only two of the magnetometer axes record any change when the magnet is rotated.

My guess is that a diametrically magnetised magnet will also work but with a different set of magnetometer axes.

Construction accuracy is important ... the magnet must be centered over the magnetometer.
O.K. clarifying what I meant by inaccuracies.
If the magnegtic axis is in line with the shaft axis, rotating the shaft will have no effect on the field, but if the magnetic axis of the disc-magnet does not run through its center or the magnet is not quite flat rotating the shaft will produce variations which will be detected.
As 3d prints are never completely as the model defines them and pushing or gluing the magnet into place will leave a bit of an angle, a design that in theory shouldn't work, will in practice.
I still love the ingenuity of recreating a sensor that exists, but at a lower cost using off-the-shelf items instead of a purpose built shaft encoder
Hmmm ... I see where you are coming from. This probably explains why the two sets of curves (step 2, photo 1) are displaced.

When I built this I had seen motors with magnets attached but wasn't aware that those sensors only had two axes and that the magnets were diametrically magnetised.

Photos 2..5 in step 3 show the results of my first attempt. Didn't know what to expect but I noticed that the waveforms looked vaguely sinusoidal so tidied things up with the STL brackets in step 4.

Appears that I've accidentally made something that works :)
You're not the first and you won't be the last, but the important thing is, it worked first time and would therefore most likely work for all. because of the strength of the magnet and the fact that the 3axis magnetometer you used is intended for use as a compass, the real problem is that too much offset either in angle or position relative to the center of the shaft would most likely saturate the sensor although it does have some internal gain adjustment, and increasing the gap would compensate for that, if it happened.
Now that’s a great idea for an absolute encoder with decent accuracy! I had never thought of using a compass chip and magnet, but it’s brilliant and simple.
Thank you for commenting :)
That's Brilliant!
Another example where you've come at a problem from a totally different angle to normal thinking.
Can this be used to remote adjust the direction of a TV antenna?
I am unclear as to what is happening, and why. Is there a magnet on that tiny shaft, or on the 3D printed part on the end of the shaft? Does the sensor detect the position of the shaft based on how far/close the magnet is to the sensor? So many questions...
Thank you for your interest in my project :)

Photo3 in the "Introduction" shows a small neodymium magnet attached to the end of the motor shaft. The bracket supporting the magnetometer in photo 1 centers the magnetometer over the magnet.

Inside the magnetometer there are three Hall Effect devices that respond to changing magnetic fields.

When the magnet rotates the output voltage from each Hall Effect device changes as the magnetic field rotates
Glad you like my instructable ... thank you for commenting :)
Look forwards to seeing the new instructable when you get the AS5600 running. By then I may have learnt how to spell resolution :-)
I've got a kyeboard like that too :)
More Comments