IPM Motor Simulation and FOC Software

Pete9008
Posts: 1801
Joined: Sun Apr 03, 2022 1:57 pm
Has thanked: 102 times
Been thanked: 347 times

Re: IPM Motor Simulation and FOC Software

Post by Pete9008 »

OK, think I've found it. My code was missing and FP_FROMINT cast on the value returned by the Mtpa() function, that would make the currents on mine 32x too small which looks about what was being seen.

That begs the question how did the original software work. I think this is because the is (total current) is read from the parameter file in the PwmGeneration class which uses 5bit decimals and passed into the Mtpa function within the FOC class which uses 15bit decimals without conversion. That should make it too small but is is then squared without using FP_MUL which actually fixes the problem (because a 5bit decimal point squared becomes a 10bit decimal). Clever bit of code but a little dangerous if either of the decimal bit widths are changed!

Has it worked - Maybe, all the control loops need tuning again!

Talking rubbish above, can't see how passing Is into the module works. Also looks like the Is squared term will overflow at currents above 360A :?

Edit - there are a number of problems here, the first is passing the current in (fixed) but then even with 15bit decimals rounding errors are still rendering the calculation meaningless (it uses the difference between small numbers (both with rounding errors) and then divides by a small number (also with rounding errors). All I can think is it was pot luck whether you got a sensible value or not depending on what value you had set for Is??
Pete9008
Posts: 1801
Joined: Sun Apr 03, 2022 1:57 pm
Has thanked: 102 times
Been thanked: 347 times

Re: IPM Motor Simulation and FOC Software

Post by Pete9008 »

Think it's at a point where I'm happy with it :)

The Mtpa() function has been tweaked to adjust the decimal places at various points along the calculation to maximise the precision so it shouldn't under or overflow. The results are as follows.

A plot with MTPA disabled for reference:
RevisedMTPA_0mH.png
A plot with Lq-Ld = 0.1mH:
RevisedMPTA_100uH.png
A plot with Lq-Ld = 0.5mH:
RevisedMTPA_500uH.png
And one with Lq-Ld = 1mH:
RevisedMTPA_1mH.png
What's interesting is how little Lq-Ld is needed to generate significant -Id, 0.1mH is enough to produce 100A rising to 200A by 1mH. I'm wondering whether the 5.8mH default in the original code is realistic? I'm now thinking that for tuning start at 0 and increase in 0.1mH steps rather than 1mH.

It's also worth noting that the -Id vs Lq-Ld curve flattens out quite quickly so high values of Lq-Ld don't give significantly higher -Id currents than seen above. The plot below shows the calculated -Id for various values of Lq-Ld for an Is of 300A (same as above plots):
Lq-LdvsIq.png
Lq-LdvsIq.png (11.57 KiB) Viewed 1557 times
It's also interesting that OpenOffice couldn't calculate the current for values of Lq-Ld of less than 0.4mH (underflow giving a divide by zero error) which goes to show it's not an easy calculation to get right in code!

On all these plots the motor is set for low saliency (as I still don't trust the motor model here) and it's interesting to note that the MTPA algorithm just reduces the motor acceleration as it effectively limits the available Iq (the only torque generating component on low saliency motors). It does have a field weakening effect though so allows the motor to run to a higher top speed. On higher saliency motors the situation should be reversed.
User avatar
Bigpie
Posts: 1595
Joined: Wed Apr 10, 2019 8:11 pm
Location: South Yorkshire, UK
Has thanked: 75 times
Been thanked: 304 times

Re: IPM Motor Simulation and FOC Software

Post by Bigpie »

Got a diff of your changes to MTPA? I'll do a build and have a test :D Looking forward to having a play with the sim too, another bugbear for me is the sharp ending of braking regen when lifting off the pedal at slow speed, would be good to simulate and I can have a crack at fixing it.
VW Beetle 2003
Outlander front generator
Prius Gen 3 inverter (EVBMW logic board)
Outlander charger
3x Golf GTE batteries
Chademo Charging
Outlander water heater
Pete9008
Posts: 1801
Joined: Sun Apr 03, 2022 1:57 pm
Has thanked: 102 times
Been thanked: 347 times

Re: IPM Motor Simulation and FOC Software

Post by Pete9008 »

Bigpie wrote: Tue Aug 30, 2022 8:07 am Got a diff of your changes to MTPA? I'll do a build and have a test :D Looking forward to having a play with the sim too, another bugbear for me is the sharp ending of braking regen when lifting off the pedal at slow speed, would be good to simulate and I can have a crack at fixing it.
Sorry, should have added it last night but it but it was getting late. Changes are:

In stm32_sine.cpp add this at the top:

Code: Select all

#include "foc.h"
and the FOC line in the Param::Change function:

Code: Select all

         #if CONTROL == CTRL_FOC
         PwmGeneration::SetControllerGains(Param::GetInt(Param::curkp), Param::GetInt(Param::curki), Param::GetInt(Param::fwkp));
         Encoder::SwapSinCos((Param::GetInt(Param::pinswap) & SWAP_RESOLVER) > 0);
         FOC::SetMtpaParams();
         #endif // CONTROL
In foc.cpp replace the existing variable definitions at the top with these:

Code: Select all

static s32fp fluxLinkage = (Param::Get(Param::fluxlinkage)<<(CST_DIGITS-FRAC_DIGITS))/1000;
static u32fp fluxLinkage2 = FP_MUL(fluxLinkage, fluxLinkage);
static s32fp lqminusld = (Param::Get(Param::lqminusld)<<(CST_DIGITS-FRAC_DIGITS))/1000;
static u32fp lqminusldSquaredBs10 = FP_MUL(lqminusld<<14, lqminusld);//additional 14-bit left shift because otherwise it can't be represented
And the replace the FOC:Mtpa function with:

Code: Select all

/** \brief update the parameter values used by the MTPA routine, must be called from the Param::Change(Param::PARAM_NUM paramNum)
 */
void FOC::SetMtpaParams()
{
   fluxLinkage = (Param::Get(Param::fluxlinkage)<<(CST_DIGITS-FRAC_DIGITS))/1000;
   fluxLinkage2 = FP_MUL(fluxLinkage, fluxLinkage);
   lqminusld = (Param::Get(Param::lqminusld)<<(CST_DIGITS-FRAC_DIGITS))/1000;
   lqminusldSquaredBs10 = FP_MUL(lqminusld<<14, lqminusld);//additional 14-bit left shift because otherwise it can't be represented
}

/** \brief distribute motor current in magnetic torque and reluctance torque with the least total current
 *
 * \param[in] is int32_t total motor current
 * \param[out] idref int32_t& resulting direct current reference
 * \param[out] iqref int32_t& resulting quadrature current reference
 * Equation being used is Id = (1/(4 x (Lq-Ld))) x (λ - sqrt(λ2 + (8 x Is2 x (Lq-Ld)2))))
 */
void FOC::Mtpa(int32_t is, int32_t& idref, int32_t& iqref)
{
   uint32_t isSquared = (is * is);
   uint32_t isSquaredFP = isSquared<<(CST_DIGITS-11);  //convert to FP but less 1bits to prevent overflow
   int32_t sign = is < 0 ? -1 : 1;
   if(lqminusld != 0)
   {
       u32fp term1 = FP_MUL(lqminusldSquaredBs10,isSquaredFP); //Note - 11bit shift in current and 14bit in lqminusldSquaredBs10 gives x8 term)
       u32fp term2 = fpsqrt(fluxLinkage2 + term1);
       s32fp term3 = fluxLinkage - term2; 
       idref = term3/(lqminusld<<2); //no need for conversions here as FP_DIV and FP_TOINT cancel each other
   }
   else
       idref = 0;

   int32_t iSum = isSquared - (idref * idref);
   if(iSum < 0) //equation should mean never goes negative but just in case
   { //so set -Id to max and Iq to zero
       idref = -is;
       iqref = 0;
   }
   else
       iqref = sign * (int32_t)sqrt(isSquared - idref * idref);
}
And you will need the following MOTOR_PARAMETERS_FOC block in your param_prj.hfile

Code: Select all

#define MOTOR_PARAMETERS_FOC \
    PARAM_ENTRY(CAT_MOTOR,   curkp,       "",        0,      20000,  2000,   107 ) \
    PARAM_ENTRY(CAT_MOTOR,   curki,       "",        0,      100000, 50,    108 ) \
    PARAM_ENTRY(CAT_MOTOR,   curkifrqgain,"dig/Hz",  0,      1000,   50,     120 ) \
    PARAM_ENTRY(CAT_MOTOR,   fwkp,        "",        0,      10000,  32,     118 ) \
    PARAM_ENTRY(CAT_MOTOR,   fwki,        "",        0,      100000, 40,     141 ) \
    PARAM_ENTRY(CAT_MOTOR,   vlimkp,      "",        0,      1000,   1,      142 ) \
    PARAM_ENTRY(CAT_MOTOR,   vlimki,      "",        0,      10000,  0,      143 ) \
    PARAM_ENTRY(CAT_MOTOR,   ffwstart,    "Hz",      0,      1000,   199,    136 ) \
    PARAM_ENTRY(CAT_MOTOR,   syncofs,     "dig",     0,      65535,  0,      70  ) \
    PARAM_ENTRY(CAT_MOTOR,   syncadv,     "dig/Hz",  0,      65535,  10,     133 ) \
    PARAM_ENTRY(CAT_MOTOR,   lqminusld,   "mH",      0,      1000,   0,      139 ) \
    PARAM_ENTRY(CAT_MOTOR,   fluxlinkage, "mWeber",  0,      1000,   90,     140 )
These values work well in the simulation but may not be so good in the car!

Good luck with your testing :D
User avatar
Bigpie
Posts: 1595
Joined: Wed Apr 10, 2019 8:11 pm
Location: South Yorkshire, UK
Has thanked: 75 times
Been thanked: 304 times

Re: IPM Motor Simulation and FOC Software

Post by Bigpie »

Code: Select all

      static void SetMtpaParams();
Needs also adding to foc.h :D Build done, will test and report back
Attachments
stm32_foc.bin
(48.12 KiB) Downloaded 42 times
VW Beetle 2003
Outlander front generator
Prius Gen 3 inverter (EVBMW logic board)
Outlander charger
3x Golf GTE batteries
Chademo Charging
Outlander water heater
Pete9008
Posts: 1801
Joined: Sun Apr 03, 2022 1:57 pm
Has thanked: 102 times
Been thanked: 347 times

Re: IPM Motor Simulation and FOC Software

Post by Pete9008 »

While the control loops above seem to work pretty well I think they can be improved. I haven't got time to look at it now so will describe what I think will improve it here either to remind me in the future or for anyone else.

First I'll explain how the current algorithm works, then describe where it's not quite right and finally suggest how to improve it.

So how does it currently work (I'm not going to cover everything here, just the relevant control loop bits)? First thing the loop does is get motor currents, angles, calculate some values and do the Park/Clarke transform to get the instantaneous Id and Iq values. It then uses the Mtpa() function to calculate the target idref and iqref currents. It is worth noting that this calculation is based purely on throttle current (Is) and takes no account of field weakening. It then uses the values for idref and iqref to set the targets for the iq and id PI Control loops. Here it is worth noting that the target for the id loop is actually idref + fwIdRef (the field weakening current needed). The id control loop is then run and its output ud used along with the function FOC::GetQLimit(ud) to calculate the maximum available uq. This value is then used to set the limit for the iq control loop (effectively meaning that the total voltage requested by the two loops combined should never exceed the maximum possible pwm output voltage). The inverse Park/Clarke is then done and the output passed to the pwm outputs. Next the actual total output voltage is calculated from FOC::GetTotalVoltage(ud,uq) and this is used to drive the field weakening PI loop with a target of 'FOC::GetMaximumModulationIndex() - 2100' (note - now I come to write this I realise it is wrong - it's coming in too soon, it should be -200 say, will fix it and retest before releasing). The output from this loop controls fwIdRef mentioned earlier effectively adding additional -Id to provide field weakening. The last loop is the throttle back-off, this is another PI loop running of 'FOC::GetMaximumModulationIndex() - 2000' (note - also wrong, should be -100say) with the output backing off the throttle. The idea of this is that if we run out of field weakening current the only thing left to do is back off the throttle.

So that's what it does, what is the problem? Well the throttle back off loop is redundant. By calculating the available uq and using it to limit iq demand we are already doing the same thing. So why is this a problem? Well remember that the Mtpa calculation is done based just on throttle and knows nothing about fwIdRef so the Is value it is using is too high. This causes it to request too much id which then causes iq to be limited so we end up with slightly the wrong iq/id ratio.

The fix I would suggest is to change the field weakening controller so that it has a dynamic max output variable but also a dynamic max output variable. The max is set to the output from the Mtpa() function, the dynamic max is set to the limited value calculated from GetTotalVoltage(). The dynamic max is the one actually used for the control loop limiting but if the loop does hit the limit it then checks to see if the two max values are the same. If they are not (i.e. the loop can't fulfill the demand of Mtpa) it drives a new output variable indicating this. This new variable is then used to drive the throttle limit loop. The idea is that as soon as the iq loop hits the dynamic limit the throttle back-of controller starts to limit the throttle. On the next loop through this will result in Mtpa() getting a slightly smaller Is and so producing a slightly smaller Is and Id request that can hopefully be met by both iq and id controllers. This should result in the optimum balance if id/iq under all conditions. Note that the description for the max and dynamic max above isn't quite right as the it would actually need both min and max versions (as there is a sign change between pos and neg torque but you get the idea).

Is it worth doing the above? Don't know and won't without simulating it to see what kind of torque improvement it gives (unfortunately need to implement it to do this) but I would guess it might give another 5-10%???

Edit - Changes such as 'FOC::GetMaximumModulationIndex() - 100' don't provide any real benefit at the moment, think this is because of 'static const int32_t modMax = FP_DIV(FP_FROMINT(2U), sqrt3) - 1500;' in foc.cpp. Still work reviewing at some point but for now leave at old values.
Pete9008
Posts: 1801
Joined: Sun Apr 03, 2022 1:57 pm
Has thanked: 102 times
Been thanked: 347 times

Re: IPM Motor Simulation and FOC Software

Post by Pete9008 »

Bigpie wrote: Tue Aug 30, 2022 9:56 am

Code: Select all

      static void SetMtpaParams();
Needs also adding to foc.h :D Build done, will test and report back
Of course it does (and I already have) but had forgotten it!

Let me know how you get on?
Pete9008
Posts: 1801
Joined: Sun Apr 03, 2022 1:57 pm
Has thanked: 102 times
Been thanked: 347 times

Re: IPM Motor Simulation and FOC Software

Post by Pete9008 »

Bigpie wrote: Tue Aug 30, 2022 8:07 am another bugbear for me is the sharp ending of braking regen when lifting off the pedal at slow speed, would be good to simulate and I can have a crack at fixing it.
Forgot to say this may well be in the vehicle control part of OpenInverter which is above the level the simulator hooks in to (the PwmGeneration class only knows the torque comment and knows nothing about the brake pedal). It should be possible to add support in the simulator but afraid it won't do it at the moment.

Hope to get the simulator onto github later this week.
User avatar
johu
Site Admin
Posts: 5791
Joined: Thu Nov 08, 2018 10:52 pm
Location: Kassel/Germany
Has thanked: 157 times
Been thanked: 1025 times
Contact:

Re: IPM Motor Simulation and FOC Software

Post by johu »

Very well done. Some comments from my side:
1. Concerning MTPA not knowing FW current I did this MTPA function here which takes ifw as parameter: https://github.com/jsphuebner/libopenin ... oc.cpp#L83 and called here: https://github.com/jsphuebner/stm32-sin ... c.cpp#L122 . Not sure if I correctly understood the issue, would this fix it?
2. Can your simulation show the effects of non-synchronous sampling of motor current and rotor position? I'm afraid if we drop it into a car now, we still get the effect that you are commanding throttle-independent d-current and end up with a fraction of q-current because the rotor angle is lagging. And thus unwanted acceleration
3. Would (1) also fix the throttle reduction issue? As it also limits iq the more id comes in
4. Would do you reckon is more effective - basing the FW controller on the total amplitude or on the dynamic, remaining q-amplitude?

So much for now, I should be able to test it hopefully on Sunday as putting the Outlander charger into the car has priority - we need it for our upcoming holiday trip
Support R/D and forum on Patreon: https://patreon.com/openinverter - Subscribe on odysee: https://odysee.com/@openinverter:9
Pete9008
Posts: 1801
Joined: Sun Apr 03, 2022 1:57 pm
Has thanked: 102 times
Been thanked: 347 times

Re: IPM Motor Simulation and FOC Software

Post by Pete9008 »

johu wrote: Tue Aug 30, 2022 11:47 am 1. Concerning MTPA not knowing FW current I did this MTPA function here which takes ifw as parameter: https://github.com/jsphuebner/libopenin ... oc.cpp#L83 and called here: https://github.com/jsphuebner/stm32-sin ... c.cpp#L122 . Not sure if I correctly understood the issue, would this fix it?
I do remember looking at this and deciding that it wouldn't. Essentially Iq is cut back here rather than by the iq PI loop but either way it is still done after the Mtpa calculation so still end up with too much id and not enough iq.
johu wrote: Tue Aug 30, 2022 11:47 am 2. Can your simulation show the effects of non-synchronous sampling of motor current and rotor position? I'm afraid if we drop it into a car now, we still get the effect that you are commanding throttle-independent d-current and end up with a fraction of q-current because the rotor angle is lagging. And thus unwanted acceleration
I think so (if I've understood and implemented it right!). The motor control fields in the gui have a SyncDel value which causes the motor model to pre-offset the angle fed out (currently set to 280us) and the inverter control fields have the standard SyncAdv parameter. I set SyncAdv to the standard value of 10 and then adusted the SyncDel value till the controller and motor model both agreed on the Iq currents. This gave 280us which seems a bit high but I believe 113us of this represents the loop interval. I have tried changing these fields and could produce low levels unwanted accell/decel but not the problem levels.
johu wrote: Tue Aug 30, 2022 11:47 am 3. Would (1) also fix the throttle reduction issue? As it also limits iq the more id comes in
Again don't think so, if you ask for too much Is then just limiting iq messes up the id/iq ratio. You really need to request less Is instead until iq and id requests can both be satisfied.
johu wrote: Tue Aug 30, 2022 11:47 am 4. Would do you reckon is more effective - basing the FW controller on the total amplitude or on the dynamic, remaining q-amplitude?
I think the FW needs to be based on the total amplitude as the FW current more directly directly controls that via the reduced BEMF. Controlling it from the dynamic q makes one loop feed back into another which could cause greater stability issues?

I had some problems like this with one version of the code where the throttle limit loop and fw loop would fight each other. The throttle reduction loop would increase then the FW loop founf it had a little more headroom and would back off so the throttle reduction would increase again and so on leading to a large blip in the iq and id traces.[/quote]

Bear in mind I'm no control expert so could be completely wrong! I've had a fair bit of experience in keeping electronic feedback loops stable, which helps, but find a lot of it is still 'black magic'.
johu wrote: Tue Aug 30, 2022 11:47 am So much for now, I should be able to test it hopefully on Sunday as putting the Outlander charger into the car has priority - we need it for our upcoming holiday trip
That would be great, let me know if there is anything I can do to help.
Pete9008
Posts: 1801
Joined: Sun Apr 03, 2022 1:57 pm
Has thanked: 102 times
Been thanked: 347 times

Re: IPM Motor Simulation and FOC Software

Post by Pete9008 »

johu wrote: Tue Aug 30, 2022 11:47 am 2. Can your simulation show the effects of non-synchronous sampling of motor current and rotor position? I'm afraid if we drop it into a car now, we still get the effect that you are commanding throttle-independent d-current and end up with a fraction of q-current because the rotor angle is lagging. And thus unwanted acceleration
Better answer - just tested this again. The plot below shows accelerating up to full speed for 5sec with matched SyncDel and SyncAdv. Without changing anything else I then reduced SyncDel to 0 (so the model is simulating simultaneous angle and current sampling but the controller is still assuming early angle sampling) and ran for another second which gives acceleration (more field weakening)? Then set SyncDel to 560us and ran for another second, this produced strong deceleration. Lesson to learn here is don't adjust SyncAdv live while driving along above base speed!! (would the firmware even let you if you tried?)
SyncAdv Change.png
So I think the model correctly simulates the non-synchronous sampling and I believe that the SyncAdv features present in OpenInverter correctly account for it. I've seen no evidence that the non-simultaneous sampling is the cause of the unwanted acceleration.
User avatar
johu
Site Admin
Posts: 5791
Joined: Thu Nov 08, 2018 10:52 pm
Location: Kassel/Germany
Has thanked: 157 times
Been thanked: 1025 times
Contact:

Re: IPM Motor Simulation and FOC Software

Post by johu »

So just did a try run on my desktop and can confirm it does not crash and slightly increases CPU load from 33% to 39%. So that's a good start :)

Still puzzled by the large syncdly you have to program. Apart from that, why do you reckon people got better performance with high values for syncadv? I think values higher than just compensating the lag
Support R/D and forum on Patreon: https://patreon.com/openinverter - Subscribe on odysee: https://odysee.com/@openinverter:9
Pete9008
Posts: 1801
Joined: Sun Apr 03, 2022 1:57 pm
Has thanked: 102 times
Been thanked: 347 times

Re: IPM Motor Simulation and FOC Software

Post by Pete9008 »

johu wrote: Tue Aug 30, 2022 6:28 pm So just did a try run on my desktop and can confirm it does not crash and slightly increases CPU load from 33% to 39%. So that's a good start :)
That's good news (although I was hoping the processor load would be a little lower than that - there are probably a few places where efficiencies could be had if needed). How do you test it on the desktop? Do you have some kind of arm simulator or are you connecting to an OpenInverter board?
johu wrote: Tue Aug 30, 2022 6:28 pm Still puzzled by the large syncdly you have to program. Apart from that, why do you reckon people got better performance with high values for syncadv? I think values higher than just compensating the lag
Me too - another thing that is on the list to investigate when time's available. Fairly sure that 113us of it it due to the loop time, 50us for the non synced OpenInverter sampling but that leaves another 117 unaccounted for (which is suspiciously close to another loop period time). Not sure about the increased performance - could it be turning some of the excess Id back into Iq (or is that the wrong way round)? Is it possible that SyncAdv tuning is being affected by something else (say interaction with unmatched Lq-Ld parameters) and isn't actually being set right in the first place?

Edit - just clicked, desktop as in desk top not desktop as in desktop PC!
User avatar
johu
Site Admin
Posts: 5791
Joined: Thu Nov 08, 2018 10:52 pm
Location: Kassel/Germany
Has thanked: 157 times
Been thanked: 1025 times
Contact:

Re: IPM Motor Simulation and FOC Software

Post by johu »

Yes, like that:
1661887160186.jpg
Just wondered how hard it would be to run the motor model on another processor and generate signals. But that would be a whole lot of DACs! At least 4 anyway for resolver and 2 phase currents.

EDIT: hmm, the interface for the AD2S chip (resolver to digital) runs via SPI. So the 2 DACs of an STM32F4 would suffice!
Pete9008 wrote: Tue Aug 30, 2022 6:45 pm That's good news (although I was hoping the processor load would be a little lower than that - there are probably a few places where efficiencies could be had if needed).
Not unexpected, so sqrt loops and such. Would it be sufficient to run the FW controller in the 10ms loop i.e. in SetTorquePercent()? Or will that kill continuity?
Pete9008 wrote: Tue Aug 30, 2022 6:45 pm Not sure about the increased performance - could it be turning some of the excess Id back into Iq (or is that the wrong way round)? Is it possible that SyncAdv tuning is being affected by something else (say interaction with unmatched Lq-Ld parameters) and isn't actually being set right in the first place?
Yes maybe that shifts id/iq split back into something more performant
Support R/D and forum on Patreon: https://patreon.com/openinverter - Subscribe on odysee: https://odysee.com/@openinverter:9
Pete9008
Posts: 1801
Joined: Sun Apr 03, 2022 1:57 pm
Has thanked: 102 times
Been thanked: 347 times

Re: IPM Motor Simulation and FOC Software

Post by Pete9008 »

johu wrote: Tue Aug 30, 2022 8:05 pm Just wondered how hard it would be to run the motor model on another processor and generate signals. But that would be a whole lot of DACs! At least 4 anyway for resolver and 2 phase currents.

EDIT: hmm, the interface for the AD2S chip (resolver to digital) runs via SPI. So the 2 DACs of an STM32F4 would suffice!
I like that idea a lot :D It would be ideal for use on the bench giving you a fully configurable motor to test/develop with!

The model itself is only a few dozen lines of code (all variables are doubles) so would port easily enough, especially using your existing code for the transforms and fixed point maths.

The current outputs could just be done via PWM (possibly at a higher frequency but lower resolution than in the OpenInverter code, say 512bit at 100KHz to allow simple RC filters to get you back to analogue voltages to feed into the OpenInverter inputs). The resolver could be done using SPI but it might be more representative of typical installs to use the resolver. Either a F4 or the STM32F103RC/VC/ZC have 2 DACs which could do the sin and cos outputs. I'd do it by sampling the resolver drive waveform and using it to phase lock a local timer, the timer interrupt would then fire the DAC conversions to give the fairly fast output update rate needed for the resolver. The voltage outputs from the OpenInverter could either be low pass filtered and sampled on the ADCs or you could use the capture unit on the timers to measure the pwm duty cycles directly. Lots of possibilities.

Note - the phase locking approach mentioned above could also be used to eliminate the need for SyncAdv in the OpenInverter code (it's what is done inside most AD2S chips). I've used it before to pull low level frequency reference signals out of noisy signals and it's surprisingly effective.
johu wrote: Tue Aug 30, 2022 8:05 pm Not unexpected, so sqrt loops and such. Would it be sufficient to run the FW controller in the 10ms loop i.e. in SetTorquePercent()? Or will that kill continuity?
Not sure, might be a bit too slow, would have to try it. There is scope to reduce the number of computations in Mtpa by rearranging the equation but the square root has to stay. Is there a 1ms loop, if so that might be OK?
Pete9008
Posts: 1801
Joined: Sun Apr 03, 2022 1:57 pm
Has thanked: 102 times
Been thanked: 347 times

Re: IPM Motor Simulation and FOC Software

Post by Pete9008 »

johu wrote: Tue Aug 30, 2022 6:28 pm Still puzzled by the large syncdly you have to program. Apart from that, why do you reckon people got better performance with high values for syncadv? I think values higher than just compensating the lag
Had another look at my code and can't find see anything wrong (wondered if I had a factor of 2 missing anywhere but can't find it).

Looking at SyncAdv code:

Code: Select all

      uint16_t syncOfs = Param::GetInt(Param::syncofs);
      uint16_t rotorAngle = Encoder::GetRotorAngle();
      int syncadv = frqFiltered * Param::GetInt(Param::syncadv);
      syncadv = MAX(0, syncadv);

      //Compensate rotor movement that happened between sampling and processing
      syncOfs += FP_TOINT(dir * syncadv);

      angle = polePairRatio * rotorAngle + syncOfs;
So say at 1Hz (electrical) syncadv would be 1.0 x 10 = 10. If I understand the angles correctly this is (10/65536) degrees or 0.06degrees whic hat 1Hz corresponds to 167us. This would seem to tie in better with the 280us I'm setting for SyncDel (167 + 113 = 280). Is it possible that SyncAdv of 10 is a little high?

One other thought - on the last line should it be '(polePairRatio * rotorAngle) + syncOfs' or 'polePairRatio * (rotorAngle + syncOfs)'?
Pete9008
Posts: 1801
Joined: Sun Apr 03, 2022 1:57 pm
Has thanked: 102 times
Been thanked: 347 times

Re: IPM Motor Simulation and FOC Software

Post by Pete9008 »

Just had another look at that polePairRatio line. Thinking about it made me realise there was a problem in my code, went looking and I had the wrong resolver pole number setup (set to 1 not 4) in the param_prj.h file. With the right setting polePairRatio becomes 1 meaning that the order of the calculation no longer affects my code. Still not sure which order is right?

Unfortunately this hasn't fixed anything as I was also erroneously returning the motor position not the electrical position back from the motor (been looking for this problem for a while as I was sure it should return electrical but previously just couldn't make it work). Fixing both has got me back to where I started but at least things are set up right now! I still need 280 for SyncDel. Starting to wonder if SyncAdv is set too high
User avatar
johu
Site Admin
Posts: 5791
Joined: Thu Nov 08, 2018 10:52 pm
Location: Kassel/Germany
Has thanked: 157 times
Been thanked: 1025 times
Contact:

Re: IPM Motor Simulation and FOC Software

Post by johu »

Good question. So as soon as something is multiplied with polePairRatio it is converted from mechanical to electrical angle. Sort of, if both motor and resolver have the same number of pole pairs then we have electrical angle in the first place. I would argue that syncadv/syncofs is already an electrical angle and should therefor not be multiplied with polePairRatio

This whole subject of syncadv is getting more mysterious as I think about it. As opposed to what it says in the comment "Compensate rotor movement that happened between sampling and processing" what we should really be compensating is the rotor movement between sampling the currents and the position. Now the currents are sampled over the entire previous PWM period and averaged, the position is sampled 40 us into the period. Now what is the offset between the two?
Support R/D and forum on Patreon: https://patreon.com/openinverter - Subscribe on odysee: https://odysee.com/@openinverter:9
Pete9008
Posts: 1801
Joined: Sun Apr 03, 2022 1:57 pm
Has thanked: 102 times
Been thanked: 347 times

Re: IPM Motor Simulation and FOC Software

Post by Pete9008 »

johu wrote: Wed Aug 31, 2022 8:25 am Good question. So as soon as something is multiplied with polePairRatio it is converted from mechanical to electrical angle. Sort of, if both motor and resolver have the same number of pole pairs then we have electrical angle in the first place. I would argue that syncadv/syncofs is already an electrical angle and should therefor not be multiplied with polePairRatio
Struggling to get my head round it but think only really matters when calculating what the theoretical value should be (and as you say if the ratio is one it makes no difference).
johu wrote: Wed Aug 31, 2022 8:25 am This whole subject of syncadv is getting more mysterious as I think about it. As opposed to what it says in the comment "Compensate rotor movement that happened between sampling and processing" what we should really be compensating is the rotor movement between sampling the currents and the position. Now the currents are sampled over the entire previous PWM period and averaged, the position is sampled 40 us into the period. Now what is the offset between the two?
Interesting! I would say the current offset would be (period/2) and the angle offset would be (period - 40) so for the purposes of simultaneous sampling SyncAdv should be ((period-40) - period/2) so (99 - 57) or 42us. Still can't get my head round what that equates to in terms of a SyncAdv value though, by my sums suggest it would be around 2.5???

Edit - this does also mean that the values are both roughly half a period out of date by the time that the calculations are done. My model won't be taking any account of this - wonder whether it should be added?

Edit2 - The (period/2) assumes a smooth change in current. I think this is reasonable as the inductance of the motor should prevent rapid changes. Switching transients are another matter though!

Edit3 - For reference assuming 400V, 1mH (fairly extreme case) and a period of 113us gives a max change in Current of 45A in one period. Would expect a typical motor to be 10A or less.
User avatar
johu
Site Admin
Posts: 5791
Joined: Thu Nov 08, 2018 10:52 pm
Location: Kassel/Germany
Has thanked: 157 times
Been thanked: 1025 times
Contact:

Re: IPM Motor Simulation and FOC Software

Post by johu »

Pete9008 wrote: Tue Aug 30, 2022 10:07 pm Note - the phase locking approach mentioned above could also be used to eliminate the need for SyncAdv in the OpenInverter code (it's what is done inside most AD2S chips). I've used it before to pull low level frequency reference signals out of noisy signals and it's surprisingly effective.
What is "phase locking" in this case?
Pete9008 wrote: Wed Aug 31, 2022 8:35 am Interesting! I would say the current offset would be (period/2) and the angle offset would be (period - 40) so for the purposes of simultaneous sampling SyncAdv should be ((period-40) - period/2) so (99 - 57) or 42us. Still can't get my head round what that equates to in terms of a SyncAdv value though, by my sums suggest it would be around 2.5???
Erm period-40 would be 73 though. So 73-57=16 us
How far has the electrical angle advanced (neglecting acceleration) in those 16 us? E.g. 100 Hz equates to 100*65536 = 6553600 digits/second or 6553600*16/10000000 = 10 digits/16 us. So syncadv=0.1 would be correct here. Hmm
Pete9008 wrote: Wed Aug 31, 2022 8:35 am Edit - this does also mean that the values are both roughly half a period out of date by the time that the calculations are done. My model won't be taking any account of this - wonder whether it should be added?
yes, seems like it
EDIT: also take into account the calculations are done and put into the timer registers - but only when the timer has completed its round will they be applied
Pete9008 wrote: Wed Aug 31, 2022 8:35 am Edit2 - The (period/2) assumes a smooth change in current. I think this is reasonable as the inductance of the motor should prevent rapid changes. Switching transients are another matter though!
I am quite sure that a different sampling scheme caused lesser problems with unwanted regen, even with the current FW implementation: viewtopic.php?p=43809#p43809
Here I had sampling time set to 1.5 ADC clocks and returned the median of the last 3 samples. To calculate the maximum age we need
- n_c = number of channels (8)
- n_s = number of samples per channel (3)
- T_s = sampling time in ADC clocks (1.5)
- T_conv = total conversion time (12 clocks)
- f_adc = ADC clock (12 MHz)

So that would be (12 + 1.5) * 8 * 3 / 12 MHz = 27 us
Or (12 + 7.5) * 8 * 8 / 12 MHz = 104 us (the current settings)
Now syncadv should be 6553600*(113-40-13,5)/10000000=39 -> 3.9
The the 27 us variant was the one with less issues. I think syncadv was 10 back then.

EDIT: traditionally current control applications would sample both currents and the resolver at exactly the same instant in the middle of the period, where, with center aligned PWM, there is no switching going on. Needs 4 ADCs then, ideally.
Support R/D and forum on Patreon: https://patreon.com/openinverter - Subscribe on odysee: https://odysee.com/@openinverter:9
Pete9008
Posts: 1801
Joined: Sun Apr 03, 2022 1:57 pm
Has thanked: 102 times
Been thanked: 347 times

Re: IPM Motor Simulation and FOC Software

Post by Pete9008 »

johu wrote: Wed Aug 31, 2022 9:03 am What is "phase locking" in this case?
Probably a topic for a separate thread or at least post so as not to distract from this discussion
johu wrote: Wed Aug 31, 2022 9:03 am Erm period-40 would be 73 though. So 73-57=16 us
Ooops, absolutely correct. So that looks pretty good in terms of offset
johu wrote: Wed Aug 31, 2022 9:03 am How far has the electrical angle advanced (neglecting acceleration) in those 16 us? E.g. 100 Hz equates to 100*65536 = 6553600 digits/second or 6553600*16/10000000 = 10 digits/16 us. So syncadv=0.1 would be correct here. Hmm
Interesting isn't it! I don't think SyncAdv is an issue
johu wrote: Wed Aug 31, 2022 9:03 am yes, seems like it
EDIT: also take into account the calculations are done and put into the timer registers - but only when the timer has completed its round will they be applied
Where is this in the code? Must admit I haven't dug into any of the lower level timer or ADC stuff.
johu wrote: Wed Aug 31, 2022 9:03 am I am quite sure that a different sampling scheme caused lesser problems with unwanted regen, even with the current FW implementation: viewtopic.php?p=43809#p43809
Here I had sampling time set to 1.5 ADC clocks and returned the median of the last 3 samples. To calculate the maximum age we need
- n_c = number of channels (8)
- n_s = number of samples per channel (3)
- T_s = sampling time in ADC clocks (1.5)
- T_conv = total conversion time (12 clocks)
- f_adc = ADC clock (12 MHz)

So that would be (12 + 1.5) * 8 * 3 / 12 MHz = 27 us
Or (12 + 7.5) * 8 * 8 / 12 MHz = 104 us (the current settings)
Now syncadv should be 6553600*(113-40-13,5)/10000000=39 -> 3.9
The the 27 us variant was the one with less issues. I think syncadv was 10 back then.
That makes sense - I was wondering about changing the average to an IIR with the time constant roughly equal to the period which would move the weighting to wards the more recent samples and give a similar effect. Both will be a tradeoff of noise vs age on the signal. More recent is obviously better but not if the noise becomes too large.

I'm thinking the half period age of both current and angle might be an issue with control loop stability. At the very minimum I think the loop gains will need reducing from the simulation values. Not sure whether I'll get to it today but will try adding another parameter for the model to allow the sample age to be simulated and varied. Little more involved than the SyncDel as I'll need to calculate two sets of numbers, one for the internal model and one for the values reported back to the OpenInverter code. This is where your idea of a hardware simulator would be nice as it would include all these things (including any phase delays though filters or IO processing blocks)!
User avatar
johu
Site Admin
Posts: 5791
Joined: Thu Nov 08, 2018 10:52 pm
Location: Kassel/Germany
Has thanked: 157 times
Been thanked: 1025 times
Contact:

Re: IPM Motor Simulation and FOC Software

Post by johu »

Pete9008 wrote: Wed Aug 31, 2022 9:19 am Where is this in the code? Must admit I haven't dug into any of the lower level timer or ADC stuff.
It isn't really, it's in the hardware. The counter counts up and down to achieve the center aligned PWM. At 8.8 kHz the ISR is called as soon as it has reached the top value. Then you have 113 us of time to complete your calculations. After those 113us your new duty cycles will take effect
Pete9008 wrote: Wed Aug 31, 2022 9:19 am That makes sense - I was wondering about changing the average to an IIR with the time constant roughly equal to the period which would move the weighting to wards the more recent samples and give a similar effect. Both will be a tradeoff of noise vs age on the signal. More recent is obviously better but not if the noise becomes too large.
You mean IIR of the last N ADC samples instead of average?
Pete9008 wrote: Wed Aug 31, 2022 9:19 am This is where your idea of a hardware simulator would be nice as it would include all these things (including any phase delays though filters or IO processing blocks)!
I can try to add a STM32F4 variant of the template project. libopeninv for F4 already exists, so shouldn't be too hard.
viewtopic.php?t=1280
Support R/D and forum on Patreon: https://patreon.com/openinverter - Subscribe on odysee: https://odysee.com/@openinverter:9
Pete9008
Posts: 1801
Joined: Sun Apr 03, 2022 1:57 pm
Has thanked: 102 times
Been thanked: 347 times

Re: IPM Motor Simulation and FOC Software

Post by Pete9008 »

johu wrote: Wed Aug 31, 2022 9:33 am It isn't really, it's in the hardware. The counter counts up and down to achieve the center aligned PWM. At 8.8 kHz the ISR is called as soon as it has reached the top value. Then you have 113 us of time to complete your calculations. After those 113us your new duty cycles will take effect
Got you, that makes sense.
johu wrote: Wed Aug 31, 2022 9:33 am You mean IIR of the last N ADC samples instead of average?
Yes. Not sure whether it would be better or worse than the median idea though?
johu wrote: Wed Aug 31, 2022 9:33 am I can try to add a STM32F4 variant of the template project. libopeninv for F4 already exists, so shouldn't be too hard.
viewtopic.php?t=1280
It would be nice to have and F4 template, it's a MUCH better processor. LibopenCM3 is where the work would be as there are some significant differences. I used it a few years ago for a project involving a lot of FFTs and I was very amazed by how lazy I could be with optimisation of the floating point code! I'm still pondering on whether to use one on my inverter hardware; I had pretty much decided to but now, having been through more of the code doing the simulator, I'm not convinced it's necessary. All depends on plans for future additions to the code.

Unfortunately I don't have any F4 hardware now and they are still difficult to buy.
Pete9008
Posts: 1801
Joined: Sun Apr 03, 2022 1:57 pm
Has thanked: 102 times
Been thanked: 347 times

Re: IPM Motor Simulation and FOC Software

Post by Pete9008 »

johu wrote: Wed Aug 31, 2022 9:33 am It isn't really, it's in the hardware. The counter counts up and down to achieve the center aligned PWM. At 8.8 kHz the ISR is called as soon as it has reached the top value. Then you have 113 us of time to complete your calculations. After those 113us your new duty cycles will take effect
Another thought. Does that mean that the optimal time to do the current sampling from a noise point of view (i.e. the point at which no PWM switching should ever be happening due to the short pulse suppression) would be at the timer ISR trigger point? Could an injected conversion be triggered from the timer output to do the current sampling (either single or burst) and then the ADC injected ISR be used to trigger PwmGeneration::run()? The existing sampling could be left running in the background as regular conversions.

Edit: This would give a virtually zero age current value for the calculations.
Pete9008
Posts: 1801
Joined: Sun Apr 03, 2022 1:57 pm
Has thanked: 102 times
Been thanked: 347 times

Re: IPM Motor Simulation and FOC Software

Post by Pete9008 »

For the phase locking have a look at https://en.wikipedia.org/wiki/Phase-locked_loop

Where it refers to VCO think timer (input controls reload and output is the timer count value).

In the diagram at the top of the page imagine using the measured angle (at the point of measurement) as Vi and the timer count value (which would become the angle) as Vo. The loop filter keeps the two tracking. Once the system is in lock you can read the timer count value (independently of when the angle is actually sampled and the loop filter run) to get the instantaneous angle.
Post Reply