Does SimpleFOC implement anti cogging feature? The motor does not running very smoothly.
I’ve been on a bit of a journey with cogging too.
My advise would be to try to first establish how much of what you are seeing is cogging and how much is PID oscillations as they are similar.
To do this run an open loop sketch at slow speed with reasonable torque for your motor. E.g a gimbal motor might be set to 3v. The open loop will directly update electrical angle so PID is not used.
You may see that it runs better in openloop. This is your ‘best case’ smoothness performance without anti cogging algorithm.
When you introduce velocity control then the feed back loop needs to have low latency and needs to be well tuned and the sensor needs high resolution and low noise. Something that is imho difficult to do on an atmel328p.
I created a pull request which adds an ‘alignment and cogging’ test last week:
I’d like to see an anti cogging feature at some point but for me simplefoc is likely already good enough with low cogging gimbal motors for my needs
You might also see some small difference in cogging between the two foc_modulation patterns you can apply to the motor
smooth movement depends on your motor. Motors with lower KV run better at low speed then motors with high KV.
Which motor, encoder and microcontroller are you using?
For example I’m using the ESP32 with OMRON encoder (ABI interface) 1024 ppm and a very cheap gimbal motor 5010 360KV. With the right parameters tuning I can spin the motor at only
0.1 rad/s very smoothly.
Some time ago I tried to implement an anti-cogging algorithm in the SimpleFOC library. The algorithm is based on this procedure:
I created an array
anti_cogging_array[pos] = voltage_q for each encoder position (quadrature encoder, so 4096). For my test i tried only in one direction.
At the end of this procedure, I added the value of the
voltage_q as a feedforward term to compensate the cogging torque (in the loopFOC):
voltage_q = velocityPI(commandVelocity - actualVelocity) + (anti_cogging_array[position]);
This is a very simplified explanation of the anti cogging algorithm I tried to implement and it can be greatly improved but, at the end, I didn’t notice any substantial difference in the behavior of the motor with and without the anti-cogging algorithm.
At the moment I have stopped the development also because the implementation has an impact on the RAM and, for gimbal motors, it is unnecessary.
In the future I will buy different types of motors to understand if the algorithm can be useful or not.
One last thing: in my opinion
Space Vector Modulation improves the motor performance and it is most noticeable at low speeds.
Hi guys, very interesting topic.
I am not sure that I understand really what the background of this problem is. I am not really familiar with the term cogging, except the nozzle cogging in 3D printers
Is what you are referring, the misalignment of the electric and permanent magnet fields, the imperfections of the motor mechanics or something else?
Cogging torque, also known as detent torque, comes
from the rotor’s permanent magnets’ attraction to the salient portions of the stator.
Cogging torque is a function of position and it depends on the poor construction quality of the motors and the number of poles.
There is an interesting publication about torque ripple problem:
M. Piccoli and M. Yim, “Anticogging: torque ripple suppression, modeling, and parameter selection,” The international journal of robotics research
Yes, as you said it runs quite well in a low KV gimbal motor, such as what I have are 5222 and a small gimbal motor, but it is not good when driving a 5045 motor that is the popular motor using in longboard, with a CUI AMT102 encoder setting to 1024 ppr. I run the simpleFOC in arduino UNO, and I will try to understand your suggestion, thanks you very much!
Did you notice the not very smooth movement in velocity or position loop?
Yes, I can feel it when holding the motor in hand.
During my tests, in angle loop control I obtain the best results in terms of low speed performance.
I’m not sure, but this almost certainly happens because I changed the position loop by introducing the
Trapezoidal Motion Planner (it works but I need to improve it). I think for fine positionings, a Motion Planner is needed.
Below a video that shows the position control loop at
0.1 rad/s with Motion Planner:
It seems very good, but it is hard to show it in video, can you hold the motor to feel how smooth it is?
What is the velocity you are trying to achieve?
Ok, I see what you mean. But with low enough sample time closed loop control should be able to get around this. I mean it depends of the sample time and how great is the influence of the imperfections.
Can you explain what is trapezoidal motion planner.
Do you control velocity using the angle control loop?
Does that mean that you integrate velocity into an angle and then make motor follow it?
I have actually had this functionality on the beginning but I removed it because I thought that it just makes people confused.
Or you are thinking of making trapezoidal target trajectories instead of instantaneous changes introduced by user?
first of all thank you for you great library.
Now, I try to explain what I mean with Motion Planner.
Trapezoidal I mean the velocity profile. From Google:
How you can see, with this motion profile we can limit the acceleration and so we can avoid discontinuity (so high current peaks). For high level application, you can find the S-curve profile and so you can limit even the Jerk.
Ok, I’ll stop .
Without a motion planner, you say to the motor: from
0.0 rad, try to reach
6.28 rad. If you have a load with high inertia, you can’t control the trajectory and so you can have a lot of overshoot during the positioning. One solution can be trying to increase gains, but you can make system unstable.
What I do with the motion planner is: set max speed, acceleration and deceleration of the movement. By dividing the “trip” in a lot of steps, the setpoint position is not
6.28 rad, but setpoint is each step in order to reach your final destination by making the motor follow a particular trajectory. In this way to have 2 advantages:
- You can increase gains and so you can improve the system response;
- The smoother the profile, the more dynamically better the system is (with a trapezoidal trajectory, you are avoiding acceleration discontinuity).
I hope I’ve been sufficiently clear. In the next few days (work permitting) I will try to post what I have implemented for the trapezoidal planner.
With the ESP32 the result is excellent because it is a really powerful microcontroller.
Hey @DomenicoGiampetruzzi, you’ve been perfectly clear!
I understand your idea, I have not implemented this and you are right that this would be a nice feature. I have implemented the voltage ramp feature with more or less the same idea.
My idea was if I limit the voltage spikes I will limit the currents as well and I don’t need to make a high level functionality such as the one you are suggesting. Because these current peaks can be problematic for torque control as well and velocity control. So I was searching for a simple way to solve all of them.
The other feature that I implemented before, but removed later, was the target value low pass filter. That more or less does the same thing as S function or trapezoidal profile, but its a bit simpler to implement.
If you have time and if you are really motivated you can try cahnging the
voltage_ramp value and see the difference in behavior.
You can set it during config with:
motor.PI_velocity.voltage_ramp = 1000; // default is 1000V/s or 1V/ms
Or if you run motor commands you can set it with command
Regarding the anti-cogging feature, it is an interesting idea and I would be in to implement it. But as you said earlier, I am not sure that naive solutions will do the trick since the library is pretty close to reaching the memory limitations.
Please correct me if I’m wrong, but from what I learned in my robotics class I think motion planning is outside of the job of the controller. I totally agree that motion planning is necessary for robotics and will give you a lot of parameters to play with and better overall control of the robots response. For my Five Bar Parallel Robot I used a Matlab model of the robot to plan the robot’s motion (trajectory) and then I tuned the controller (SimpleFOC library) to give me the the less error over time, in other words, the best trajectory following.
I wouldn’t object adding this feature to the library since it would totally save time for most applications, but I still think the best way to do motion planning is with the model of the robot/ device.
@Antun_Skuric, it is a great library that make it simple to use FOC function in many CPU, and it runs very good in most of the time, thank you very much. I am just testing and learning how to use this library, there is no a target volicity.
And here is a great community I got many help here.
thank you for you very cool projects!
I believe that every way of interpreting the motion planning is correct. According to my point of view, it is necessary to separate the motion planner of the single axis from the coordinated axes movement. Trapezoidal planning (for example) is not only a way to make the motor follow a specific trajectory in space, but is also closely linked to the electrical / mechanical variables of the motor and driver. An S-curve allows you high performance not only in positioning per se, but also in obtaining excellent results in terms of absorption peaks and drive efficiency. Furthermore, for a high performance motion planning, you need to be computationally as fast as possible and therefore I believe that inserting the trajectory inside the loop for field oriented control is the best choice. Obviously you need more powerful hardware like the ESP32. Arduino Uno I don’t think could handle it.
In robotics, on the other hand, I understand the motion planner as that series of mathematical operations (direct and inverse kinematics) to ensure that the axes, in synchronized movements, reach a certain position. In this case I would see it as something external to the motor driver. I’m not a robotics expert, but that’s my idea of motion planning.
Hi all, this is a really exciting discussion.
The BLDC-intrinsic flaws like cogging and torque-ripple had been the reason for me to leaf the BLDC path and move to another (similar) principle.
As mentioned, cogging is intrinsic. Magnetic iron meets strong magnets. The result is attraction. The approach to minimize this is to add more and more poles. That reduces but not eliminates the effect.
The second flaw is the torque ripple coming from the usual block-commutation. That is well reduced by sinusoidal commutation. This is the reason, why we are here in the community.
To prove everything that was posted here I set up a little experiment. I took my worst motor. A 52BL02 with 4 magnet (2PP) and 3 slots. Then I tuned the PI. First I changed the encoder. From 9 to 12 and at last to 14 bit. Antun is absolutely right: its a matter of timing. The higher the resolution the higher the smoothness. The disadvantage is the higher MCU-load. I used a Nucleo, so the problem is not to big.
So I kept the AS5048 at 14bit and played with the torque. And also Owens advice was absolutely correct. The higher the positioning torque the higher the smoothness.
The good thing is that even bad motors can be made smooth by adjusting the system a little. I reached a good behavior at 0.05 rad/s. I made a short video to show you the result:
You pay for the good behavior with inefficiency. You can not use the torque you need to run the motor, only. You have to add some energy to overcome the cogging. But this is not important for positioning.
There is another option. To vary the energy (current) related to the motor geometry(poles/slots) and rotation angle. Not a big deal but it makes the setup much more difficult and reduces the execution speed. I guess that is called anti-cogging algorithm.