Challenges going faster than certain rpm

Hi community,
First I want to say, thank you for being so awesome. The library is a great project and it’s amazing to see the involvement of everyone here on the forum.

I’ve been fidgeting with simplefoc, with different drivers, controllers, sensors and both BLDCs and stepper motors. And even though I get my motors to spin and get pretty good torque out of them, there are some aspects of which I’m not sure if it’s going as well as it should. Some of the main things being that the max rpm I’m getting is a bit lower than expected, and that the movement of the motors often doesn’t seem very smooth.

First off, my current setup:

  • Raspberry Pi Pico controller
  • Drivers : BTS7960B
  • Angle sensor: AS5600
  • Motor: cheap 14pole 360KV 5010 bldc from Ali-express
  • Current sensors: 2 x ACS712 hall sensor
  • powered from 2 li-ion cells (~7.4V)

I’m currently testing with voltage control mode. I’ve also gotten both of the current sense modes to work, but results were not necessarily better.

With this setup (and basically any other I’ve tried with the same motor), it seems that there is an ‘invisible wall’ to get the motor to spin at more than ~100 rad/s in closed loop velocity control or about 150 rad/s in closed loop torque control mode. Raising values above that just makes the motor more noisy, draw a lot more current and make rad/s more unstable or even go down.

In open loop velocity mode I can get it to around 200 rad/s, by manually stepping up both the target velocity and current limit. I haven’t tried to go above that as the sweet spot for the current limit becomes smaller and smaller, so it just becomes tedious.

I don’t think the limitation is the speed of the controller; my main loop runs at a fixed 2.5 kHz (both move and foc) I’ve read at other posts here that foc should work well with at least 4 loop iterations per pole pair (or was that per pole, so 8 per pair?), meaning that purely from that aspect I think I should be able to reach ~560 rad/s (2500hz / 7pp /4 its/pp * 2 * pi), so that’s quite a way to go from 100 or 150.

I think one issue I have is that the magnet is not perfectly aligned to the sensor. At low rpm there is a notable ‘pattern’ of different sounds and variation in velocity over the course of a motor rotation. However I don’t think this is the issue as with higher rpm the motor is actually running smoother and smoother.

So, 1: is there anything obvious that I should be doing differently?
And 2: could this possibly be an effect of the delay in the read-out of sensor values? I haven’t calculated or measured the actual delay, but as this is generally the limiting factor in loop iteration speed, I think it’s save to assume that by far most of the iteration time is spend in waiting for I2C communication back and forth, meaning that the sensor value was actually sensed around half of the iteration time earlier, let’s say 200uS in my case, by the time by the voltages are adjusted based on that reading. I would imagine that at low rpm this delay is no problem as it is only as small fraction of the time between two passing poles, but this fraction of course grows as rpm goes up and therefore time between passing poles reduces. Is there any compensation for this delay in the library?

That’s a bit pushing it. You may get better results if you go for SPI AS5047 sensor. AS5600 is a simple digital potentiometer (100RPM max), I’m surprised you got that far on it.

PS The AS5600 does not even list the RPM in the specs, it’s that low.

Hey @daniel,

Yes, your MCU is fast and you can have loop times even much higher than 2.5kHz if you use a different sensor. I2C based AS5600 is really not meant for high speeds or fast loop times. But even an ideal sensor you will still not be able to come to 500rad/s.

The open-loop control is really really fast. cca 10x-100x faster then the FOC and it makes a lot of difference.

Velocity control algorithm takes longer time to execute and that is probably the reason why you see such a high difference. Try using the motion downsampling to let more time to the FOC algorithm and less for your motion control as your task for the moment is very simple. With some motion downsampling you should be able to reach at least this 150rad/s.

You are using a timer?

There is part of the equation that influences a lot and that is power supply voltage. As when going faster your back-emf rises motor’s torque fill diminish and it will not be able to reach higher speeds. So one simple way you can increase your speed range would be to use a higher power-supply voltage.

We do not do the compensation of the delay in the library in this way. We do have the adaptive time sampling which will help in motion control applications but not in the field vector setting. There is something that you can do if you are motivated though, we do use the motor.zero_electric_angle which basically determines the calibrated offset in between sensor and the motor 0 angles. For higher velocities (due to this delay you are interested in) we will have a certain offset in between where the motor is and where we this it is which will depend on velocity.
So you could add your estimation of the offset to the motor.zero_electric_angle:

You could do something like this in your loop

float normal_zero_angle = motor.zero_electric_angle;
float alpha = 0.1; // something small - this is up to you to find depending on your motor and sensor
void loop (){
   motor.zero_electric_angle=normal_zero_angle + alpha*motor.shaft_velocty;

Thank you for your responses! I was not aware that there was anything like an RPM-limitation on the AS5600. I’ve just received some AS5048A boards, hopefully I’ll manage to print a mount for it this weekend and dome so testing with it. I’ll report back on the results!

I don’t necessarily need to reach 500 rad/sec, I think that for my application (biped robot legs with probably 1:9 reduction) should be okay with 200 rad/sec, maybe even less. I’m just very curious what the limiting factors are (and of course, getting higher speeds is more satisfying :wink: )

I had assumed the difference between velocity control and torque control would mostly be caused by poor PID/filter tuning. I will experiment more with downsampling as well. I have been testing with higher supply voltages (adding extra li-ion cells). I mostly got higher torques but I don’t think I got much higher speeds. Also with a simple ESC and two cells these motors reach much higher RPMs, so I didn’t think voltage should be the limiting factor. But perhaps speed on an ESC and with FOC is completely incomparable?

For now I’ve simply limited the loop iteration speed with a simple timing check (and tested that the slowest loop iterations finish well in time of course). I might play around with some interrupt-based options later.

I realize that indeed much higher speeds can be achieved with open-loop control, given it’s simplicity and non-dependence on slow sensors and noisy values etc. But with zero ability to deal with disturbances of course. Is it expected though that I need to manually adjust the current limit corresponding to the speed? IE, at low speeds it doesn’t work with a high current limit so I need to start out with low current limits, then as speed is going up it doesn’t work anymore with the low current limits so I need to crank up the limits.

I was already sniffing around in the library code to find a good spot to experiment with some sort of timing compensation based on current velocity, but your suggestion to adjust the zero_electric_angle is much simpler! I will definitely play around a bit with that :slight_smile:

Thanks again for your thoughts!

I tried with the AS5048 and it was a difference like day and night! The motor is running super smooth at both low as well as higher rpm and effortlessly reaches velocities well above 200 rad/s! I sort of feel like I’ve just been wasting a lot of time with the 5600 :stuck_out_tongue: although I do wonder if the difference is fully caused by the sensor itself, or if perhaps the alligment also plays a role, since the 5600 are not even centered on their boards properly (its the cheap white boards from Ali Express) and the cogging and alignment tests reported error distributions in the range of 30 degrees with the as5600 (after I got it to work, see

I did notice something weird with the 5048 though. In the sensor test example sketch it just worked flawlessly, but with I my own code it didn’t work. Somehow it gets a very low clock rate (~2kbps), at which it seems the chip just refuses to respond. After a lot of trial and error I noticed one difference between the senor test example and my code : the sensor test example uses the as5147 default config and my code used the as5048 default config. This turned out to be the key: when I changed my code to use the 5147 default config it immediately worked. I’m super puzzled over this though, because as far as I understand from checking out MagneticSensorSPI.cpp, the as5048 default config is literally a copy of the as5147 default config. They do clearly behave differently though, so there must be something going on.

It’s really mainly the I2C interface vs. SPI. That makes a huge speed difference, which is what is allowing you to reach higher RPMs. But it is certainly also true that the 10 vs 14 bits and the quality of the sensor PCB help get smoother, better results.

Thanks a lot for reporting the problems with the MagneticSensorSPI class. I’ve made an issue and we’ll investigate it.
In the meantime you could also try the MagneticSensorAS5048A class from our drivers repository. This is specific to the AS5048A, and also lets you read out the magnitude and diagnostic registers which you can’t get with the generic MagneticSensorSPI class.

1 Like