# FOC Help Needed

mxlemming said:
You're not using the rotor electrical angle in that svpwm implementation.
OK, in the SVPWM routine itself the angle is not needed, as it is already represented in Ualpha and Ubeta, including the necessary advance angle....

regards
stancecoke

mxlemming said:
We do not feed the svpwm with currents.

Svpwm gets fed voltages, so where i wrote ia and ib that should be Va and Vb.

That's one of the things that no one seems to explain in all of the papers on FOC I've read. They'll have a diagram like this:

Where currents are measured, transformed, and then go into PID controllers where voltages magically pop out. In these papers the PID controllers are black boxes and it's never explained how currents get transformed into voltages.

Is the conversion to voltages simple, or does it rely on motor parameters such as phase resistance and inductance and is the voltage then calculated with something like V = IR + LdI/dt + BEMF?

To my previous point... The rotor electrical angle and the stator electrical angle are not the same. Using the rotor electrical angle for svpwm sector identification won't work.

Which angle should be used for SVPWM sector determination? The angle calculated using atan2(Vb,Va)?

I sidestepped this whole svpwm thing and used the inverse Clarke transform, svpwm is not intuitive and doesn't seem to be any more computationally efficient than the full transform.

Do you still use SVPWM after calculating the inverse Clarke, or do you do something simple like sine table lookups?

It still plays with my head that the voltage generated by the motor and the angle of the rotor are 90 degrees apart. It makes thinking about this quite hard.

Perhaps it's similar to how current lags voltage by 90° in an inductor. A motor, with its windings, is very much like an inductor.

Breville said:
Where currents are measured, transformed, and then go into PID controllers where voltages magically pop out.
That's no magic, just the normal principle of a controller. The currents id and iq are the values you want to control, the voltages ud and uq are the values you have to tune to influence the current.
That's the smart thing of FOC, that you can control the id and iq values independently from each other in the rotating frame...

regards
stancecoke

So how does a PID generate voltages from currents input into it? What is the relationship?

Breville said:
So how does a PID generate voltages from currents into it?
It takes the difference from the wanted current (setpoint) and the recent value (process variable) and calculates a proportional part, a differential part and an integral part. All parts are summed to the output voltage.

In very easy words: if the recent current is lower than the setpoint, increase the voltage, if the current is too high, decrease the voltage.

You can find a lot of literature about PID controller.

regards
stancecoke

stancecoke said:
In very easy words: if the recent current is lower than the setpoint, increase the voltage, if the current is too high, decrease the voltage.

I understand that, but where does the voltage that gets increased or decreased come from originally? Does it come directly from current via a calculation such as V = IR + LdI/dt + BEMF, or from somewhere else?

A PID will vary the voltage so the actual current matches the setpoint current, but how is the first voltage established at the beginning, before there are any measured currents to control?

Are you saying that you choose the PID gains (Kp, Ki, Kd) so that when applied to the current error the result can be treated as if it were a voltage?

Sorry to be so persistent here, but I think this is the primary point that’s holding me back.

Breville said:
but where does the voltage that gets increased or decreased come from originally?
The PID is stupid, it doesn't know if it controls an electric motor or a steam turbine, so it doesn't know anything about the general motor equation.

It starts at zero and tunes the output if a setpoint different than zero is wanted. It eves doesn't know, that the output represents a voltage (it isn't a voltage anyway, it's a duty cycle...)
Though, there are different approaches, some add the BEMF voltage to the output generally, so the PID has only to control the delta from the BEMF, others let simply the integrative part do it's job without adding the BEMF.
The motor constants like resistance, inductance and flux linkage can be used to set up the proportional, integral and differential factors in the control algorithm. Here you will see, that the output will get the unit of a voltage (I guess, I never checked that). I set them always by trial and error :wink:

regards
stancecoke

A pi controller takes an error input and outputs an estimate of the changed state needed to fix that error.

So it gets an error of x amps

From V=I(R+jwL) we can estimate that to amend the I error we would want to increase V by I(R+jwL)

We also know that the P term is effectively a transient effect as is inductance and the R term is constant with time like the I term

So a stable system would logically have the kp proportional to L and the ki proportional to R

You pick w so that it responds about as fast as you want. w MUST be slower than the PWM otherwise the system is unstable. I started out at w was equal to the PWM... It made a lot of white noise.

Typically you want a control bandwidth from 1k to 10k rads-1.

If you use a series PI controller you should set kp= wL and ki=R/L.

If you use parallel, well figure it out so you get the same overall gains (ki =wR)

Remember that in your integral term you have to include a time step.

You don't use theta for svpwm. You determine sector using comparisons... Atan2 is computationally intensive so it's avoided.

After inverse Clarke i usea midpoint clamp centering technique. This has an identical output to svpwm

You can also bottom clamp it which improves sampling time at the expense of hammering the low side MOSFETs.

Ah, the lightbulb in my head is finally lit. Thanks, stancecoke, that’s exactly the missing piece I needed. :thumb: :thumb:

mxlemming said:
Typically you want a control bandwidth from 1k to 10k rads-1.

If you use a series PI controller you should set kp= wL and ki=R/L.

So what is wL? Let’s see:

L = kg m^2 / s^2 A^2

and w = s^-1

so wL = kg m^2 / s^3 A^2

and that’s voltage, so it looks like that would work. Ditto for R/L.

My motor has a spec sheet that includes values of “line-to-line resistance” and “line-to-line inductance”. Can I use those directly for R and L?

You use the star connected equivalent, which is half the phase to phase values.

Here’s another question: With the current sensing arrangement shown in the first image in the first post in this thread, what’s the polarity of the current? Is there a convention?

For example, when I read the ADCs and calculate the currents, should I use them as-is or negate them?

Breville said:
Here’s another question: With the current sensing arrangement shown in the first image in the first post in this thread, what’s the polarity of the current? Is there a convention?

For example, when I read the ADCs and calculate the currents, should I use them as-is or negate them?

They should be negated. Convention that makes sense is that current into the motor is positive. That way
Vstator= Vbemf+Ri+Ldi/dt

You can make it work the other way but it gets confusing.

That’s what I thought. Thanks for the confirmation.

I was rummaging around in the closet in my lab when I came across a TI BOOSTXL-DRV8301 board, which I think I used a few years ago to test a DC motor. It’s a 240 watt board, so that should help running the motor on my dyno, which is about 3x as large as the motor I’ve been working with. It has programmable gains on the built-in opamps, so that should give me a wider spread on the current measurements. Unfortunately, it has built-in current sense amps with programmable gain for only two of the phases—the third phase has an external opamp with fixed 10x gain, so I’ll have to replace some resistors to get the gain up to something reasonable.

I’ve got this board connected to an STM32F7 board, which is 2.5x faster in CPU clock rate than the STM32F401, in addition to the Cortex-M7 improvements. And it has three ADCs so it’ll convert all three phases in parallel rather than sequentially.

The problem with my present setup is that the difference between 0 current and the typical 0.25A I run the motor is only ~45 ADC counts, which represents only about 1% of the range of the ADC, so I’m using very little of the ADC’s dynamic range.

If you read papers on FOC, one of the touted advantages is that Id and Iq behave like DC quantities, making them easier to control with PID controllers, but in my case they look more like random noise, which makes it difficult for the PID controllers to keep up. Heavily filtering them helps, but it introduces lag, which probably isn’t good.

Breville said:
That’s what I thought. Thanks for the confirmation.

I was rummaging around in the closet in my lab when I came across a TI BOOSTXL-DRV8301 board, which I think I used a few years ago to test a DC motor. It’s a 240 watt board, so that should help running the motor on my dyno, which is about 3x as large as the motor I’ve been working with. It has programmable gains on the built-in opamps, so that should give me a wider spread on the current measurements. Unfortunately, it has built-in current sense amps with programmable gain for only two of the phases—the third phase has an external opamp with fixed 10x gain, so I’ll have to replace some resistors to get the gain up to something reasonable.

I’ve got this board connected to an STM32F7 board, which is 2.5x faster in CPU clock rate than the STM32F401, in addition to the Cortex-M7 improvements. And it has three ADCs so it’ll convert all three phases in parallel rather than sequentially.

The problem with my present setup is that the difference between 0 current and the typical 0.25A I run the motor is only ~45 ADC counts, which represents only about 1% of the range of the ADC, so I’m using very little of the ADC’s dynamic range.

If you read papers on FOC, one of the touted advantages is that Id and Iq behave like DC quantities, making them easier to control with PID controllers, but in my case they look more like random noise, which makes it difficult for the PID controllers to keep up. Heavily filtering them helps, but it introduces lag, which probably isn’t good.

How is this going?

To your noise problem above, you need to consider the ripple you get due to the pwm. With a roughly 12V Vq and 100uH inductance you can expect ripple on the scale of di=12/2/100x1/(20kx4) = 0.75A. this varies depending on where in the sin wave you are, motor characteristics... Etc... But you get the idea. The ripple could easily be larger than the current you're controlling to so you would expect the noise to be significant.

I find at low currents the sin wave is barely visible on the scope, looking at the currents sampled by the MCU is more visible, but as you load the motor the sin wave becomes much clearer. Typically in my application, I'll be running a large outrunner motor with 20uH inductance, 48V bus and I'll see 10A or so of ripple noise on the scope. It looks terrible.

But when I load it up like it's propelling my bike with 140A it produces lovely sin waves. With 10A ripple superimposed.

I haven't had a chance to post recently as I've been busy working on the TI board and have recently received a new board.

The TI board requires a lot of point-to-point wiring to the Nucleo board, and it looks like this:

I got an ST STSPIN32G4 board yesterday. This board has a chip that integrates the STM32G4 MCU, gate drivers, and opamps and comparators for current sensing and overvoltage protection. It's a lot cleaner, needing only the three motor phases, the encoder signals, and DC power as external connections. I spent several hours this morning porting the STM32F7 code over to the STM32G4 and resolving the differences.

The first thing I did when I got the board up and running was to test the encoder inputs. This is some simple code that just reads the encoder inputs in a loop and prints the current value on a serial terminal. When I hooked up the motor's Hall encoder output to the board, I was getting only even numbers displayed: 2, 4, 6, and the forbidden 0. That implied that Hall #1 was stuck low. I checked my code thoroughly and didn't find anything wrong. Next I checked the board itself.

The Hall #1 input has continuity from the connector pin on the board all the way to the pin on the STSPIN32G4 chip--so far so good. But when I powered up the board and looked at voltages the issue became clear. The board has 10K pull-ups on all three Hall inputs (for some reason they're pulled up to 3.3v rather than the 5v that's on the "Hall PWR" pin), so I was expecting all three Hall inputs at the MCU to be 3.3v with nothing connected to the Hall inputs on the board. That was true for Hall #2 and #3, but Hall #1 was at 1.25v. Looking at the datasheet, the input threshold for a logic high is 1.88v, which explains why I'm only seeing a low on Hall #1, even when I tie it directly to Vdd at the Hall #1 connector pin on the board.

Here's the schematic of the sensor input section of the board:

When I Tie Hall #1 (H1) high, I measure 5v at Point A and 1.72v at Point B. Measuring Hall #2 and Hall #3 at equivalent points in their circuits gives 5v at both points. R81 is dropping 3.28v, which it shouldn't be, because it connects directly to port PB6 on the MCU, which is an input and therefore high impedance. I suspect a partial short to ground somewhere. It's not a direct short, or Point B would measure 0v. R85 isn't populated on the board, so it's not that. I'm suspecting that C34 is bad or perhaps there's a short somewhere on the board (or on an inner layer). I looked at the board pretty closely and didn't see anything obvious.

Anyone have any suggestions for what to look at and/or try next? I could send the board back and request a replacement, but it's a holiday weekend here and I'd like to get some work done with it.

@mxlemming: With my small motor, calculated ripple current is ~88 mA, which is 2x the drive current. Now that I have a dyno, I can put some load on the motor and drive it up to current levels several times the ripple current and I'm hoping the measured current will look less like noise!

Are you tieing hall 1 high with a resistor or straight to 3.3 or 5v?

Looking like you have a 5k in line with the 10k to ground or something clamping to 1.72v.
I'd check D12 to make sure it's not backwards, shorted, clamping, or the wrong device. R85 is out but you could check for solder or flux that might be causing a short on it's pads, same for d12. If you're careful you might be able to use an adjustable power supply and see the current start to go up at 1.72v likely pointing to clamping.

Last I can think of is if the solderless breadboard and or jumper wires are well used you might have a very weak connection that shows ok floating but can't handle the tiny power of the hall sensor when connected.

It's not a lot of power but you might be able to see the culprit with a thermal camera if you let it sit for a while.

I find that holding the reset pin low is good for things like this, then the pin should be tristated so pull up pull down with external resistors should work.

If it then works ok... Software problem. Else... Hardware problem. I think.

Read the errata sheet for the g4, it is a bit off-putting. All workable but there used to be things like "the first ADC reading in a sequence is garbage". Hopefully that ones fine by now.

This is definitely a hardware problem. There’s a leakage path on the board that’s pulling Hall #1 towards ground strongly enough to overcome the pull-up or even connecting Hall #1 directly to 5v.

I’d try replacing the pull-ups with lower resistance resistors, but the parts on the board are 0201 and the smallest I have on hand are 0603. I can try removing the diode and cap in the circuit and see if one of those is the culprit. I’ll also see if ST makes the Gerbers for the board available and check those. The components are tightly packed on this board, so surgery is going to be delicate (if I even attempt it at all—this is a new board and I should just return it and ask for a replacement).

I have read the G4 errata. Yes, there are some nasties there, but nothing I have’t dealt with before. It’s nowhere near as bad as the PIC32MZ was in its first version. :lol:

No joy with the EVSPIN32G4 board. I’ll eventually send it back, as soon as Mouser gets around to talking with ST and figuring out what to do about it. I suspect this will take weeks before I have a working board. I guess the days of “Your brand new board doesn’t work? No problem! We’ll send a new one out this afternoon and you can send the bad one back when you get it” are gone.

In the mean time, I have a TI DRV8305 board arriving today to keep me busy until the ST board issue is resolved.

Mouser finally authorized me to return the defective board and I shipped it last Saturday. Since Mouser said they'd send the board back to ST for evaluation, I expect at least another month of delay until I get a replacement board, probably more.

Replies
20
Views
481
Replies
18
Views
1,638
Replies
6
Views
841
Replies
8
Views
321
Replies
5
Views
1,554