40 cent magnetic angle sensing technique

Hello Everyone,

I’m currently working on a project that needs very cheap contactless angular position sensing, and I ended up trying to develop a custom solution. SimpleFOC provided a convenient platform for prototyping the concept, so I thought it would be nice to write a sensor driver for this technique to let other people use it easily.

You can have a look at a rough draft for the documentation here if you want a detailed explanation, but this is the TLDR:

Two analog linear hall sensors placed very specifically around the outer edge of a bldc motor can pick up a non-symmetrical waveform from the motor’s own magnets, that the microcontroller can sample and use to find relative shaft angle


  • ~20 cents per sensor in single quantity, no cost for magnets
  • Off-axis from the motor’s axle


  • Specific sensor location for each motor part number (note: not each individual motor though)
  • Requires fast and frequent analog sampling
  • Requires a computationally expensive trig function
  • Many factors can degrade performance of the sensor

Here are some pictures of the setup:

Note the two sot23-3 packages on the perfboard suspended right above the motor, these are the two hall sensors

An oscilloscope trace of the raw analog output signals from the hall sensors

The digitized readings, converted to shaft angle (in degrees) of a motor spinning at constant velocity

Currently working on some pull requests, which can be found:
Here for some tweaks to SimpleFOC base code + sensor calibration routine
Here for the actual sensor driver code

I think the main functionality is roughly all implemented, but now it is time to test a bit, clean up the code, and write some documentation.



That’s very cool indeed! Could potentially be useful for portable wind turbine project down the line.


and with a montage like this


Interesting. Can you do absolute angle? How do you find the initial starting angle w.r.t. 0 degree ?

The sensor can only tell absolute angle within one electrical revolution, due to the way it uses the motor’s own magnets. This is not good enough for absolute shaft angle, so at best it acts exactly the same way as e.g. an incremental optical encoder does when interacting with SimpleFOC, which means a calibration routine upon every power-on.

How is this any different than from factory (built inside the coils) hall sensored motors then?

I definitely don’t have as much experience with brushless motors as some of the people here, so anyone who knows more can feel free to chime in. But the impression I get is that a vast majority of the brushless motors that have integrated sensing use digital hall sensors, which give you something like six counts per electrical revolution. This is great for trapezoidal commutation, as the hall signal can be used to define both the timing and the step number of the next step in the commutation sequence, even at very low speeds, but it’s practically useless for FOC commutation. Using linear analog hall sensors like above gives much finer angular resolution, which is much better suited for FOC.


I’m not sure I understand, are you suggesting to use the 74LS148 as an analog to digital converter?

I forgot this detail “relative shaft angle”
I will continue the evolution of my progress on the position that I have already opened
Hall effect sensors encoder

I don’t have much experience either, but I would like to be able to do without the initialization at the start and to be able to work with a hollow shaft motor

1 Like

yes, with input comparators and for initialization, I want to do an analog reading of the two sensors, I would not have an absolute angle, but personally it does not bother me for my use


Welcome to the community!

Awesome work, I think you have here one of the cheapest solutions that are good enough for position control. I think a lot of people here will find this work valuable and we’ll find it implemented in some projects soon. :smiley:

1 Like

Awesome! This may actually be less trouble in terms of sensor placement than digital hall sensors, since you don’t have to worry about the angular position of the sensors relative to the stator. Plus two sensors is two thirds the work soldering tiny wires and capacitors :slight_smile: EDIT: Even better, it looks like 49e hall sensors don’t even need filtering capacitors.

There are ways to do fast atan2 approximation to reduce CPU load, which should be plenty accurate for this. Here’s a good one with max error 0.28 degrees: How to Find a Fast Floating-Point atan2 Approximation - Nic Taylor

And you could switch to 8-bit ADC when the motor gets above a certain speed so you can use higher ADC clock rate to reduce the reading time. Lower precision values, but higher accuracy since less time delay means the values you have are closer to the actual rotor position.


If anyone needs sensors, let me know. I bought a pack of 100 on ebay because it was little more expensive than buying 10. It will take a couple weeks to get here though.

I found an older post on the forum about a DJI gimbal. It seems like it were utilizing this technique:

1 Like

What sort of range are you getting on the voltage throughout the cycle?

I’m getting very little range with the sensor placements shown in the pdf. Only about four counts out of 1024 with the sensor placed 3mm below the lip of a 35mm diameter 12N14P motor. If I hold it directly against the outside of the rotor and slide it around, I get about ten counts of range (0x20c to 0x216). Measuring with multimeter on the sensor pin I get 2.571-2.6v (working out the math by hand, that should be 0x20e to 0x214 on the ADC).

I also tried a 28mm motor which doesn’t have a ring on the base so I can get the sensor right against the underside of the lip, and it gives similar poor results. However if I push the sensor just a little farther inside the motor then I get much greater range, about 0x1dc-0x248 (108 counts). But I wonder if the output would still be sinusoidal in there, and if the field from the nearby stator coils would interfere too much.

Do you think my motors are just too well made and don’t leak enough flux to use this kind of sensor? Or do they come in different sensitivity ranges and I got the wrong kind? Any other ideas I could try?

This is what I bought, which doesn’t have any specs listed 100pcs 49E Hall element OH49E SS49E Hall sensor Hall Effect Sensor | eBay

Based on the picture in my initial post, it looks like I was getting somewhere in the vicinity of 0.7V amplitude, and my hall sensors came from aliexpress if it makes any difference.

Could you please post some pictures of your setup, or provide links to the motors you are using? Otherwise, the best feedback I can offer is that it is very likely that the back-iron on your motors is too thick to let any magnetic field through as you suspect. It is fairly easy to tell if a motor will work by checking whether something metal will stick to the rotor shell with any substantial force, and about half of my motors won’t even attract a paperclip.

I have also looked at the second sensor orientation with the oscilloscope, with the halls under the motor lip, and the waveform looked pretty decent to me. I think the magnetic field from the magnets dominates the magnetic field generated by the stator coils, but this is just anecdotal for now. The challenge with this sensor placement is the sharper curvature of the magnetic field in the area under the lip makes it much harder to achieve optimal positioning and signal amplitude.

The motors I’m using are Surpass 2814 (SURPASS HOBBY 2814 C3536 14 Poles Brushless Motor for RC Airplane Fixed-wing | eBay) and T-Motor 2208 (7uytjhgc nv 16 PCS T-MOTOR 2208 CW Brushless 1450kv, For Drones And RC Cars. | eBay). I have the 2208 stator mounted on a custom base with digital hall sensors, which doesn’t have anything blocking access to the underside of the rotor.

And yes, it looks like just not enough leakage flux on most motors to use this technique. The only one I have that feels at all magnetic on the outside is Racerstar BR4114. I’ll try the inside positioning and see what sort of signal quality I get, but it will have to wait until next time I’m machining a custom stator mount. I’ll include pockets for three digital hall sensors, plus a fourth pocket that’s positioned relative to one of the others for a second linear hall so I can test that first.

Thanks for the update, I actually also have the 2208 T-motor, and testing it with the linear halls shows basically zero output just as you have seen. All of the motors you are using have the unfortunate feature of a flux redirection plate on the bottom that blocks direct access to the magnets.

I hope the Racerstar motor works for you!

Alrighty, got my stator mount done, and this technique is looking more viable now. In the first photo with the sensors properly in the pockets, I get a total range of 96 counts out of 1024 on the ADC. That might work but still seems a little low, so I tried hot gluing a sensor up on top of the 1mm high pocket wall. That puts it very close to contacting the rotor, but gets 280 counts. Next time I think I’ll split the difference and raise the pockets up 0.5mm or a bit more (I made several mistakes in the machining of this one so it’s sort of a throwaway anyway).

Now there is the issue of how to actually read them. The DYS SN40A ESC that I’m currently using only has one unused ADC pin, so I’d have to irreversibly modify it to get both sensors readable. I also have a B-G431B-ESC1, but they don’t have easily accessible ADC pins either. There are two itsy bitsy solder pads, one labeled TP3 that connects to pin 18 (PB1/ADC1_IN12), and the other unlabeled but visibly connected to pin 10 (PA2/ADC1_IN3), but I’m not sure if I can hit them without taking out any other little SMD components.

Hopefully Valentine will come through with the Lepton board, with easily accessible ADC pins and even higher current capacity :slight_smile: I may just work with the digital hall sensors for now.