# Linearizing hall effect sensors outputs

I'm trying to find a robust solution to linearize four hall effect sensors outout to obtain a signal that I can use in a PID control scheme.

The output data is collect via 4 ADC channels on an ATmega328p chip (Arduino) by sliding a magnet with the south pole first, perpendicular across the sensors with a fixed velocity and distance

I then remove the offset, my idea is to look at the phase shift between the "sine waves" with the atan2(x,y) function

avgADC0 = ADC0-mean(ADC0);

phaserad = phase * pi/180;


The idea came from this application note Application note

The result is, very very poor :) Mostly because the sensors aren't spaced exactly 90 deg. but I would expect to see something that doesn't look like this and more in the style of what's refered to in the application note.

I'd love to end up with a nice curve, I can curve fit and feed into my control system? But how would you go about linearizing this signal, am I missing something?

The sensor data sheet is linked here

I realize the application note isn't targeted for my sensors, and usually I don't mix and match. But surely the method would still work regardless.

• Thank you
• you can start off by moving the magnet further away so they don't clip at max field, if it is indeed the Halls clipping. If they're still linear, then attenuating the signal into the ADCs. It won't solve the problem, but throwing away data at the start of the process is a good way to make it even worse. Commented Aug 27, 2019 at 12:57
• But the sensor outputs not nearly have sine wave like outputs, to use then atan2(), they are saturated also. You have to move the magnets away, as stated in the app note. Commented Aug 27, 2019 at 12:57
• You could also use a Halbach array or to shape the magnet flux so that it have sine waveform. Commented Aug 27, 2019 at 13:12
• Yeah i need to cut the legs of my testbench @Neil_UK :) Commented Aug 28, 2019 at 5:37
• Have you considered trying to fit it to a second degree 4 dimensional polynomial? Such as f(x,y,z,w) = (ax²+bx+c)(dy²+ey+1)(fz²+gz+1)(hw²+iw+1) where a to i are the coefficients and x,y,z,w are the 4 inputs? Commented Sep 2, 2019 at 20:26

Please check again application note! in this way the output overlap is very important! i thinks you must install the sensor closer than now ! please see this picture from application note.

I make simple result in excel File

please pay attention to this result it is output formula out = (4 * avgADC0 + 6 * avgADC1 + 6 * avgADC2 + 4 * avgADC3)/6

it is 75% overlap

it is 20% overlap

As Mahdi KhosroAnjom pointed out, there is a region in each curve where the output is fairly linear with position. If the sensors are spaced properly, then you will always have one of those regions to use. The way that your sensors are spaced, there are positions where none of the sensors are in a linear region. I've used arrays of Hall sensors in this way, but you still run into the problem of deciding which sensor is the right one to use.

You can get outputs from your four sensors that are nearly sinusoidal if you use an array of magnets. Instead of orienting the magnetic pole axis parallel to the motion axis, you use an array of magnets that alternatively have their pole axis pointing towards or away from the sensors. In reality, you wouldn't use a bunch of separate magnets, but use a magnetic strip that is already poled that way.

Here is an example from Adafruit. What is not obvious in the video is that the individual poles are alternating N up, S up, N up, S up, etc. Interestingly, the flexible magnetic tape that you can buy at office supply stores is also magnetized in that way, as are those flat sheets that get glued to business cards so that they'll stick to a refrigerator.

The output of the Hall sensors will be nearly sinusoidal as long as you are not near the end of the strip. Ideally, you will have four sensors that fit exactly in the length of one pole pair. In theory, you could get away with just two spaced 90 degrees apart. That would give you sine and cosine, then you could use ATAN() to find the "angle" just as you are trying to do now. The problem is that using the output of a single sensor for sin and another for cos becomes very inaccurate because the system becomes tremendously sensitive to the spacing between the magnets and the sensors. If you have four sensors, then you can position them 90 degrees apart and use them in differential pairs (180 degrees apart) and the whole thing suddenly becomes very immune to the distance between the magnet strip and the sensors.

The difficult part is that the sensors must lie exactly 90 degrees apart.To put it a different way: the pole spacing of the magnets must be exactly twice the distance between the sensors. Still another way: you want one pole pair (360 degrees) to cover the four magnets.

EDIT: I already said that the sensor outputs will be nearly sinusoidal provided you are not too close to the end of the strip of magnets. I just want to reiterate the importance of this. The sensors need to see what looks to them like an infinitely long array of magnets. As long as you always have at least one pair of magnets sticking out each end of the sensor array, this method of position sensing can be very accurate

This method is used for position sensing in many applications. This sensor from AMS has an array of eight sensors that reads a magnet with 2mm pole pairs. The use of eight sensors instead of four essentially allows for some averaging to improve accuracy.