Originally posted by
stevendhansen on Hacker News. Copy pasted here for reference, and further discussion.
Very impressive! I love to see this kind of thing on HN. I scanned through your code a bit on mobile, and here are a few quick suggestions:
- It looks like you are using field oriented control. This is used 99% of the time in industry, but if you really want high torque bandwidth you should check out alternate control techniques. My favorite is an up-and-coming algo developed at UW-Madison called Deadbeat Direct Torque and Flux Control (DB-DTFC when searching for papers). It uses an inverse motor model paired with rotor/stator flux estimators to produce a deadbeat (one timestep later) torque and flux response. I have heard apocryphal stories of people who implement DB-DTFC accidentally snapping motor shafts when they forget to limit the torque slew rate. It is a very high performance algorithm, and beats FOC and DTC hands down at the cost of a bit more complexity.
- If you are sticking with FOC for now, you can make a few quick improvements that will help a lot. First add qd-axis decoupling on you current loop commands (may have missed them, but I didn’t see them in your code). You will want reference frame speed (“omega”) decoupling multiplied by current and the transient inductance of the machine, which undoes a lot of the cross coupling that causes issues at high speeds or fast changes in torque. Flux decoupling will help with integrator wind-up, and stator resistance decoupling also helps lessen integrator wind-up at low speeds.
- Have you considered implementing a sensorless algorithm? It can be done with both FOC or DB-DTFC, although there are some constraints on changing your switching frequency on the fly. If you have a fixed switching frequency a common technique is to superimpose a high frequency carrier on top of your voltage commands and then demodulate the high frequency response in the currents. Since a BLDC has salient poles on the rotor, this technique lets you estimate speed even down to zero! Then you wouldn’t need encoder/resolver feedback which would be especially nice for robotics projects.
- If you really want to get all of the current out of those FETs check out discontinuous PWM strategies. This are especially helpful at low speeds when your applied voltage is low, and can lower your switching losses enough to give you an extra ~40% current rating.
Great work overall. The hardware looks really clean and well designed, and it is easy to tell you put a lot of thought and effort into the site and this project.
Similar to deadbeat strategies, predictive strategies for current control are really high performance, if enough computational power is available. Predictive strategies provide reliability when combined with a boundary value optimization algorithm like shooting optimization methods by accounting for current/voltage limits
As for high speeds, field weakening may be helpful.
I also heard about some projects where motors operate really slow, thus they use a combination of applied voltage and motor resistance/inductance for current estimation instead of current measurement.
While this is way over my head, I’m reading with excitement and interest.
I must admit that I am quite impressed about the project.
The main topic here is what do you want to do with the project…
I am saying this because (as far as I can see) you run the entire current loop at about 100-ish microseconds(which is kind of fast). If you want to go in the direction of “Model Based” control it will be painful from the CPU load point of view .(and let’s not forget that you control 2 motors).I believe that, even now, your CPU load is quite high .
(trying to be realistic here) …there are some things that could be added :
“decoupling controllers ” : there is not much additionally to do actually
pros : better decoupling = controller more stable .
Separating the “voltage calculation” (Bus Voltage compensation/limitation, Space vector modulation )from the current controller and you could try to move the “controller calculation” (together with current measurement) to a lower recurrence (this recurrence should be estimated considering the electrical time constant of the motor(s).)
pros : Lower CPU load without affecting the performance , more flexibility in the future if you want to add more “stuff” (Like a model based control algorithm) in it.
A Field Weakening algorithm will be great .
Some Current Battery Limitation algorithm :I was not able to find one in the code … so I suppose that there is none .(Am I wrong ?)
Discontinuous Space vector modulation : As far as I can tell (correctly if I am wrong ) the current implementation cannot set 0 and 100% PWM . As a result the maximum voltage amplitude is smaller . To compensate for this, a DSVM algorithm can be added (It is increasing the power but increasing also the number of harmonics in the current )
Dead time compensation . Currently … as far as I can tell there is none. → This will lead to a better behavior at low speeds … ( additionally for this it is needed a way to read the PWMs). This will also give more flexibility from the perspective of a developer which wants to try a certain algorithm .
“run time correction of the angle “ : basically from the moment of the measure until the command is set the motor is … you know … spinning. Because of this the command angle is not the measure angle (because motor moved in the mean time). Usually it is considered that the motor rotated with constant speed (due to the fact that we talk about a point between 100us measurement ).
What is interesting is that you are doing something similar here :
(low_level.c line 1048) but you need to move that line in front of 1053
(The comment for me is a little bit confusing … so I don’t know exactly what you meant there )
That will be all