BLDC Motor with Hall sensor refuses to move in closed loop velocity (but works in open-loop velocity)

Hi All, I have a NEMA17 motor (42BLS02) which works well in open-loop velocity mode, but refuses to move in closeloop velocity mode. I’m using voltage feedback. When I set a target velocity, I can see a commanded voltage(a voltage which is enough to move the motor in close-loop), but the motor does’t budge, and I see no modulated sinsoid on the scope whatsoever (just steady carriers)

-The indicated angle seems to be correct in magnitude(I rotate once, and it increases by 6.28), though I’m not 100% sure if the direction is right?

-I’m pretty experienced at PID tuning and I don’t think it’s that (I start with a very small “P” gain which gives some commanded voltage(a voltage which WILL move the motor in open-loop mode) but there’s no movement.

-I’ve never used Hall sensors (I normally use AS5600), so I might be doing somthing stupid.

Controller: NUCLEO-64 G431
Driver: SimpleFOC
Motor: 42BLS02, 4PP, 18V
Sensor: Hall 3phase.

#include <SimpleFOC.h>

// encoder instance
//MagneticSensorI2C sensor = MagneticSensorI2C(AS5600_I2C);

HallSensor sensor = HallSensor(3, 2, 4, 4);
void doA(){sensor.handleA();}
void doB(){sensor.handleB();}
void doC(){sensor.handleC();}

BLDCMotor motor = BLDCMotor(4, 1, 250);
BLDCDriver3PWM driver = BLDCDriver3PWM(9, 5, 6, 8);

// commander communication instance
Commander command = Commander(Serial);
// void doMotor(char* cmd) { command.motor(&motor, cmd); }
void doTarget(char* cmd) {command.scalar(&, cmd);}
void doLimit(char* cmd) {command.scalar(&motor.voltage_limit, cmd);}
void doMotor(char* cmd) { command.motor(&motor, cmd); }

void setup() {

sensor.enableInterrupts(doA, doB, doC);

// link the motor to the sensor

// driver config
// power supply voltage [V]
driver.voltage_power_supply = 12;
driver.voltage_limit = 4;
// link driver
// link current sense and the driver

//motor.controller = MotionControlType::torque;
motor.controller = MotionControlType::velocity;
// default voltage_power_supply
motor.voltage_sensor_align = 2;
motor.voltage_limit = 2;
motor.current_limit = 10;
motor.velocity_limit = 20;
// contoller configuration based on the controll type
motor.PID_velocity.P = 0.1;
motor.PID_velocity.I = 0.0;
motor.PID_velocity.D = 0;
motor.PID_velocity.output_ramp = 100;
motor.PID_velocity.limit = 20;
// angle loop controller
motor.P_angle.P = 20;
motor.LPF_velocity.Tf = 1;

// set the inital target value = 0;

Serial.begin(921600); // WARNING: low value like 115200 cause distorted FOC
motor.monitor_variables = _MON_TARGET | _MON_VOLT_Q | _MON_VOLT_D | _MON_CURR_Q | _MON_CURR_D | _MON_VEL | _MON_ANGLE; // monitor target velocity and angle

//motor.foc_modulation = SpaceVectorPWM;
// initialise motor
// align encoder and start FOC
// commnads
command.add(‘T’, doTarget, “target”); // ssss space
command.add(‘L’, doLimit, “voltage limit”);

void loop() {

// iterative setting FOC phase voltage
// iterative function setting the outter loop target
// motor monitoring
// user communication;


The only thing that really stands out to me is the large low-pass time factor. Usually it should be around 0.01 to 0.05.

Try running in torque mode first. That will rule out any issues with the tuning parameters.

You could use motor.foc_modulation = FOCModulationType::Trapezoid_120, or try adjusting motor.zero_electric_angle. The automatic calibration routine doesn’t work very well for hall sensors. The zero angle it calculates is only within ±30 electrical degrees (±0.52 radians) of what it should be, which works for trapezoid120 but is usually not quite right for the default SinePWM.

I have 1s cuz the hall sensor resolution is very very low and “steppy” and the 1s time constant smooths it out nice.
But I’ve tried all values between 0 to 1, and I’ve used 1s on other configs.
Yes I’ll try torque mode and also tool it up for the as5600

  1. Torque mode doesn’t work either… Same things I get a carrier but no sinusoidal modulation whatsoever.

  2. When I rig the motor up to AS5600 magnetic sensor, all close-loop modes works great (see below for run with velocity mode). I changed nothing but the sensor type.

So I have Hall sensor which is giving a clean, correct angle reading, but for some reason when it’s used, ALL closed-loop modes completely break

Figure: Velocity (closed loop) with AS5600 Sensor

Ok, I’ve gotten the system to produce a sinusoid phase in close-loop velocity mode by:
-setting the velocity setpoint to 0
-physically turning the motor shaft by hand
When I do this, the PID control system tries to counter the shaft motion to keep the velocity at 0.

My gut feeling is that the problem here is the very low resolution (15 degrees) of the hall Sensor setup due to the low polecount and hall-sensor type. I think when I set a veclocity it quickly tries and gives up beefore the shaft can move enough to register(even though it does pass the initial sensor align test).

-Does anyone else use Hall sensor with a low polecount motor?

-What diagnostics can I look at to troubleshoot this??

9N12P (6 pole pairs) is the lowest I’ve used.

It shouldn’t ever “give up”. The PID will keep commanding torque whether the rotor moves or not.

Have you tried higher voltage limit? Assuming the 1 ohm resistance passed to BLDCMotor constructor is correct, your 2 volt limit can only produce 2 amps max. I’ve been fussing with a 2814 motor that seems to need 2 amps before it will move at all.

Yes, absolutely I’ve tried all the way up to full supply voltage and everything in betwee, BUT…

The reason I believe it’s “given up” or someting simmilar, is that there is no modulated sinusoid on the phases, just the PWM carrier(which the PID will raise the duty-cycle of to the max allowable motor voltage). If the voltage were too low to move the shaft, I’d still see sinusoid modulation.

Even at max voltage, there’s no trace of any sinusoid modulation when I command a velocity, so something is making it stop.
-It works in velocity_openloop, even at 1v
-If I simply change to the AS5600 and change nothing else, it works perfectly in close-loop velocity
-The Hall sensor is returning a valid angle, but has a resolution of 15 degrees.

Have you tried the smoothing sensor?
And are you sure all hall sensors are working ?

Ok, I think I figured this out… I’m not sure where, but somewhere (either the SimpleFOC board, my motors Hall sensor wiring) the phases A and C were flipped. When I swapped the A and C motor wires it started working.

The next problem though is I cannot get the motor to run smoothly with the hall sensor. It runs but it runs very very rough despite my efforts to tune it and play with the LPF value.

Have you tried the smoothing sensor?

What is this?


There is a discussion in the forum you can follow.
For hall sensors you will need to add this:

smooth.phase_correction = -_PI_6;

Thanks, I’ll give this a try

Ok, this worked quite well, thank you. But interesingly, it worked alot better for negative (counterclockwise) directions than CW directions… I get smooth motion in CW until about velocity 80 or so, and motion starts to get very rough.
In the CCW direction, I can to all the way to ~-400, where I believe the voltage is the limitation.

That’s the zero angle tuning I mentioned before. Adjust motor.zero_electric_angle until both directions reach the same max speed.

Thanks dekutree64, I’ll try this

zero_offset angle is ~5.5 when I start the system with PhsA/HallA aligned. In this state, the motor works well at negative velocities(shaft moves CW), but freezes when I command a positive velocity.

If I change the zero_offfset_angle to ~4, the system works well at positive velocities (shaft moves CCW), but freezes when I command negative velocities.

However, I can find no setting between 4 and 5.5 in which works for both positive and negative velocities :frowning:

4.0 - 4.7 : positive velocities work
4.75 - 5.5 : negative velocities work

There’s a tiny band ~4.71 to 4.72 where both negative and positive velocities work, but they both work very badly (motor vibration and harmonics)

Is there anything else I can try? (Trapezoidal modulation had pretty much identical issue)

Just make sure the motor runs at same speed in both direction with correct phase/hall combination.

Then if you are in voltage mode, providing the phase inductance will help with efficiency at higher speeds thanks to lag compensation.

It was discussed here:

Is it a motor like this with external hall sensors?

Candas1, sorry I think I’ve caused some confusion.

When I discovered that the motor worked well with negative velocities without smoothSensor, I stopped using it (I want to try to figure out what’s going on without that extra layer of complexity). I may go back to SmoothSensor when I figure out what the hecks going on.

So to restate the current situation:
When I wire the Hall and Motor phases consistently, I can set negative velocities/Torques in closed-loop mode and get good motor performance, but setting positive velocity/Torque results in motor not moving.

Is it a motor like this with external hall sensors?

Yes, my motor is exactly like that. With the sensors in an evenly spaced ring, which I thought was odd… But again I’m new to using this sensor type.

I think the problem is with the external magnet ring. Did you try to shift the hall sensor pcb?
As far as I remember that didnt work for me.
Thats why I have linked the thread above.
Askuric wrote some code to shift the zero electric angle.
If it works perfect in one direction, you can only change it in the other direction.