Extending usability to 3 hall sensor BLDC motors


Can we use library with Hall sensored BLDC motors? I am talking in terms of usage in high power motors which comes with built in 3 hall sensors. (6 distinct pulses in one ERPM. 24 in one rotation)
I am building a motor controller using Atmega328 and power stage. I was planning to use trapezoidal control. But having FOC onto Atmega328 would be exciting.

Position control is not important for application. But having control over torque and speed (current limited) is objective.

Please let me know if we can use SimpleFOC library for my project?

thank you so much,

Hi all,
I would also be interested in running bldc with halls and simpleFOC. This would reduce the overhead of sensor communication. Unfortunately there are just 2 hw-interrupt pins on Atmega328. Or I’m wrong?




3 hall sensors, 6 distinct pulses !

When you are between two adjacent states, you can collect the time of state transition. Because the angle of the two adjacent states is known, you can divide the time to calculate the speed. With this speed, you can estimate the position information in the next state transition process

But this position information is used to estimate the position in the next state transition process by the rate of the previous state process (rate * time = position)

In any case, atmega328 is unlikely to cope with this kind of high-speed acquisition and real-time calculation. Moreover, this kind of estimation is accurate

Hi guys!
Honestly the biggest reason why I didn’t implement hall sensors at the first place is because the position control with them doesn’t make sense really, and will not provide a smooth rotation on low velocities which was kind of the idea to show.

Now since there are some people which would be interested I will implement it for the next version. I hope in two weeks.
But even if you want to implement it yourselves it is not too complicated.

As @Juxo said atmega 328 doesn’t have enough interrupts so we would have to go with the software interrupt versions. Which will work ok, I suppose. We will have to test that. I’ll make it like the encoder class, where you can use software/hardware or combination of interrupts.

Regarding the performance, as @blackblue007 explained, there are some choices to be done but honestly I think that atmega328 is going to be able to handle it. I found for example for quadrature mode, that atmega had a limit of 20000 interrupts to push the loop time above 2ms (which becomes too much)
But you will be able to run the same code on the other devices as well.

If you have some other ideas let me know

Thanks for reply and consideration. I agree due to accuracy difference between encoder and Hall sensors reading, I raised this particular request. To make it clear, I have limited knowledge of electronics. But following are few thoughts from my side.

  1. For Atmega328 we have use delay function to read speed and then estimate rotor position. For low rotor speed, delay time could be as much as 7 ms for 10 RPM (24 pulses in one rotation). So we will have MCU calculation black out for so much time and it may hamper the commutation signals to power stage of motor controller.
  2. To avoid negative effect of this black out, we could even have lower speed threshold above which only FOC will kick in. e.g. only above 100 RPM of motor speed, FOC algorithm will start. Below 100 RPM, trapezoidal control of rotor.
  3. We could take motor speed as input to motor controller through any analog pin. That is rotor speed calculation is done externally and provided to Atmega328 as analog voltage. This will not require use of delay function in Atmega328 and I think it will work at low speeds as well.
  4. For bigger motors, due to rotor inertia, commutation black out for few ms anyway will not be noticeable. Though it may create noise, so I feel it should be okay considering limitations.

Please let me know if my understanding is correct. SimpleFOC library is really going to prove helpful in multiple projects that many people do using Arduino.

Thank you for your efforts.

@Antun_Skuric Position control with hall sensors is more or less the same idea as a stepper motor, but without the fear of missed steps. You need some way to identify the home position, and then count commutations (6 for each north-south rotor magnet pair, so 3x number of rotor magnets for a full rotation) to keep track of the position. For leadscrews and things with high gear ratio it’s plenty of resolution.

It might be better to make a separate project for it though since it’s not FOC. Keep the SimpleFOC source code un-cluttered.

@Neha_Mishrikotkar There is no need for MCU blackout to measure speed. You only need to have a timer running and read the value when the hall state changes. Compare to time at last hall change and you can calculate speed. Either make a high resolution timer (tick up a 32-bit value when the hardware timer overflows) or make a variable that you reset when the hall state changes, and if the timer overflows twice before the next state change then consider the motor to be not moving.

Hey guys.
@dekutree64 I agree completely. In general you still jave some resolution I agree, but you don’t have smoothness. But you are right that it might be enough for some usecases.
I also agree that SimpleFOC is already a bit cloutered and it tried to solve a lot of problems at once. I will try to impelemnt it as minimal as possible and then we will see.
Sensorwise, it is not a problem, just additional ‘Sensor’ class instance. And speed calculation is also not a big problem, time in between counts + filtering (+ maybe interpolation) and it’s going to be fine. But it seems that I will need a new modulation type (to add to SinePWM and SpaceVectorPWM) only for hall sensors and that might be a bit complicated to use.

As @Neha_Mishrikotkar pointed out I’m his post, there are many ways to improve the hall sensors FOC, but in my opinion their place will not be in the* off the shelf* SimpleFOC. At least in the near future. To switch the commutation from trapezoidal to hall sensors foc is probably a good idea, as well are the external smooth measurement of the velocity, but these types of solutions are too specific at least in my opinion. And their performance is not so great that the simplicity of the code should be sacrificed. At least in my opinion.

So I will definitely write one version of the code for the use with the new ‘HallSensors’ class which you can ‘linkSensor()’. And I’ll make sure that the sine and space vector FOC work fine with it. if not I’ll implement one of the modulation tables from some paper.

Yeah, it’s definitely not smooth at low speed, but neither are hobby servos and you can still do some cool stuff with them.

I’m making tiny linear actuators (here’s a picture https://i.imgur.com/RSxqmd4.jpg) and have been trying to get position control working with hall sensors and custom firmware for common drone ESC’s. I like that they’re cheap and come in small sizes, but debugging is very difficult when the only output is beep noises made by jittering the rotor back and forth :slight_smile:

This Hextronik 10g motor is 9N12P, so only 36 commutations per revolution. But turning an m2 leadscrew (0.4mm pitch) that’s 90 steps per mm, which is more than enough. FOC would be even better, but I don’t think there’s any good way to get an encoder on it.

Very cool!
I can imagine that drone escs are a bit problematic. Are there some esc that use hall sensors for commutation purposes or you are using back emf ones? For those ones it very hard to control position really.
I I am not sure how exactly you are mounting the actuators, but as you said encoders are often pretty bulky. You can maybe try with these magnetic ones, they tend to be easier to mount.
But anyway, I think that in your case position control with hall sensors only, when you add a big gear ratio such as a ball screw, it will smooth things out.

I am interested, what is your current approach. You control the esc with the pwm and measure position with hall sensors separately and close the loop with that measurement?
Do you think there is a way to integrate the FOC or SimpleFoc into this?

Here’s another angle to show the mounting holes https://i.imgur.com/mfDKwRe.jpg
I think I’d have to have some structure reach around the motor and hold an encoder over the axis, which would increase the width and length significantly.

This ESC is the back EMF type, but the solder pads for firmware flashing give access to pins which can also be used for reading hall sensors. No interrupts on them though, so the main loop needs to be fast enough not to miss sensor changes.

Right now it simply sets the active transistor pair according to the current hall state and desired direction, and PWM duty based on the most recent measured motor speed. PWM on the transistor pins is done using a timer interrupt (they are not hardware PWM output pins).

For integrating, I don’t think it would be easy to run SimpleFOC on this kind of hardware since it uses ATmega8A rather than Arduino’s ATmega328P. But you’re welcome to pluck any bits from my code that you want https://pastebin.com/RtXm6RgV
But do keep in mind that it doesn’t work very well yet. Not too bad just turning a motor, but under load it often fails to get the rotor moving or is very twitchy, depending on how much power I give it. And the twitchy motion causes it to miss steps, which leads to uncontrolled high speed spinning (at least I think that’s what’s causing it). I can probably add some code to recover from missed steps, but ideally I’d like to avoid it happening in the first place.

Hey Guys,

I need your help for testing the Hall sensor implementation of the FOC.
Unfortunately, I do not hove on my hands a motor+hall sensor combination, so I cannot really test this implementation.

I have a magnetic sensor that can emulate the UVW signals (but only 7 pole pairs - my motors have 11 and 14).

I will make a new branch with the hall sensor implementation + new commutation for this sensor type and it would really help me a lot if someone can test it and give me some feedback about it.
It would definitely speed up the process. :smiley:

Otherwise, I will just order a set of hall sensors or <7 pole pairs motor to implement it better.

I’m going to test the library this week with a standard bldc and report the results here. Unfortunately it will take the whole week because I’m a little short in time.


Hey @Juxo, thanks a lot for the support.
Unfortunately, I have not yet had time to develop everything I need for the hall sensor implementation.
I will let you know once when the testing branch it is online.

You may recognise the motor in pic as coming out of a hoverboard. It has hall sensors. In the uk you can pick up a broken hoverboard up on ebay for about £40. The VescTool has a calibration step where it turns the motor in open loop mode to discover the electrical position of the hall sensor. I think it stores 6 values in a “hall sensor table” even though there are 3 hall sensors. Probably up/down transition. Might need something similar. Those balance boards are pretty smooth so i wouldn’t give up hope on doing coarse position control with just hall sensors.
I’m willing to do some testing or light development.


@Antun_Skuric I’ve got a working hall sensor implementation which is largely refactored from your Encoder.cpp. It works in voltage, velocity and angle control.
It needs tidying up and has an occasional calibration quirk. 50% of the time it’ll calibrate properly and 50% of the time it’ll be out by 1 commutation (causing erratic behaviour). I can correct this by sending a command in loop() which does: motor.zero_electric_angle ±= _2PI / 6.0;

I’m finding the integral term needs to be 1/10 of normal (e.g. 2 not 20) which I put down to low resolution - my hall sensor is effectively 90cpr! (15pp x 6 commutations). It therefore has a tendency to overshoot. Any reason why you don’t use a derivative constant in your angle PID loop?

I can tidy it up and do a pull request if you want.

1 Like

My “in progress” hall sensor can be seen on my fork on hall_sensor branch:

It work very well apart from not being able to calibrate. I’ll take a look at some of the following methods which I don’t currently understand:
needsAbsoluteZeroSearch, hasAbsoluteZero, initRelativeZero, initAbsoluteZero

In theory I should be able to calibrate this by trial and error (trying each of the 6 possibilties) but am not sure if this is possible.

Hey @Owen_Williams, that sounds perfect!
You are moving very fast, at the moment I am not able to follow you with testing and integrating. I will not be able to do so for one week more, but I am in for a pull request. Until then, this is a great option for the people to try out!

You can check the FOC implementation docs for calibration purposes:

And the Sensor docs for more info about the functions in question:

// initialize counter to zero
float HallSensor::initRelativeZero(){
    // this one you need to implement 
   return 0;

The relative zero init you will need to implement.

I also am not sure that we will be able to use SinePWM and SpaceVectorPWM modulation with Hall sensors because with hall sensor you use only three sampled values of the sine wave. positive and negative maximum and zero. But they need to be well sampled, otherwise you might have some strange behavior. I was planning to introduce a new simplified modulation technique, only for the hall sensors which would use effectively square waves. But it will have to wait at least one week.

I can implement full PID, up to now, I did not have requests to do it and I did not really have problems with it but it is a simple mod and you are right that it might be interesting for some applications.

@Antun_Skuric - I’ve got initRelativeZero working at least using esp32 + SimpleFOC shield + hall_sensor + hoverboard motor. I’m hoping it’ll work smaller motors but can’t test.
I’ve create a PR for this. Please DON’T MERGE until you look at the code as I’ve made changes to ‘core’ in order to better auto tune for hall sensors. I’ve not tested whether these changes effect other setups. The ‘core’ changes include:

  1. alignSensor does a ‘wiggle’ rather than ‘move and hold’. This helps ‘lock on’ to hall sensors.
  2. I’ve implemented auto-direction detection - it can detect whether motor and hall agree on direction. Auto detection only supported on hall sensors but other sensors could be refactored.
    You might have better ideas about some of these experimental features. Feel free to remove or change to suit your vision.

Hey @Owen_Williams, I’ve passed through the code and it is well written and the changes/choices seem reasonable. I will merge it with the development branch, so that everyone who is interested can use it:

Owen has provided the example codes, you can find it in

       > motion_control
                > torque_voltage_control 
                    > hall sensor
                > position_motion_control 
                    > hall sensor
                > velocity_motion_control 
                    > hall sensor

I will merge this and all the other planned changes in master when I can test everything.

Thanks Owen!

If you do try development branch, you’ll notice that calibration is different. Rather than just holding on 3/2 PI, it starts there and clicks through 1 electrical rotation clockwise, then 1 electrical rotation ccw, ending at 3/2 Pi. Please shout if this startup behaviour is problematic. In doing this openloop ‘wiggle’ we can detect more things about sensor/motor.