So everytime I look at the il1rms and il2rms values with a constant load and speed on my motor, the RMS current calculated by the software varies. For example, when I am spinning the motor with fmax = 50 with constant full throttle with no motor load, the clamp meter I put on one of the motor phases reads almost constant ~30Arms while the software reading gives constantly changing 20-40Arms. Then I decided to try reading a current from the wall socket, so I unplugged the DC bus cable from the inverter, wound a cable coming from the wall 10 times through my current sensor. Then I started the inverter operation, and I put some load (heater) on the wound cable. I noticed that the rms current readings were perfectly nice (10x the clamp meter), but only until I push the throttle. So it's possibly because of the gate drivers pulling too much current from the 5V line, causing some voltage drop on the current sensors, resulting in a small negative offset in the current.
Johannes' software calculates the rms current by finding the max/min current values through half a current period (say 50 hz), then an abs(1/sqrt(2)) operation is done. If we assume that the motor RMS current does not change within a period, we can change it to finding both the negative/positive rms values and averaging these two. Modified the code, and I got perfect rms reading on both the current through the wall and to the motor.
I'm not sure if anyone else was having this issue too, but if there is, the following code change (pwmgeneration.cpp) fixes the issue.
Code: Select all
static bool CalcRms(s32fp il, s32fp illast, s32fp& max, s32fp& rms, int& samples, s32fp prevRms)
{
const s32fp oneOverSqrt2 = FP_FROMFLT(0.707106781187);
bool signChanged = ((illast <= 0 && il > 0) || (illast > 0 && il <= 0)) && samples > 10;
if (signChanged)
{
//rms = FP_MUL(oneOverSqrt2, max); // original rms calculation
rms = FP_DIV((FP_MUL(oneOverSqrt2, max) + prevRms), FP_FROMFLT(2)); // average with previous rms reading
max = 0;
samples = 0;
}
il = ABS(il);
max = MAX(il, max);
samples++;
return signChanged;
}
static s32fp ProcessCurrents()
{
static s32fp currentMax[2];
static int samples[2] = { 0 };
s32fp il1 = GetCurrent(AnaIn::il1, ilofs[0], Param::Get(Param::il1gain));
s32fp il2 = GetCurrent(AnaIn::il2, ilofs[1], Param::Get(Param::il2gain));
s32fp rms;
s32fp il1PrevRms = Param::Get(Param::il1rms);
s32fp il2PrevRms = Param::Get(Param::il2rms);
if (CalcRms(il1, Param::Get(Param::il1), currentMax[0], rms, samples[0], il1PrevRms))
{
Param::SetFlt(Param::il1rms, rms);
if (opmode != MOD_BOOST || opmode != MOD_BUCK)
{
//rough approximation as we do not take power factor into account
s32fp idc = (SineCore::GetAmp() * rms) / SineCore::MAXAMP;
idc = FP_DIV(idc, FP_FROMFLT(1.2247)); //divide by sqrt(3)/sqrt(2)
idc *= fslip < 0 ? -1 : 1;
Param::SetFlt(Param::idc, idc);
}
}
if (CalcRms(il2, Param::Get(Param::il2), currentMax[1], rms, samples[1], il2PrevRms))
{
Param::SetFlt(Param::il2rms, rms);
}
Param::SetFlt(Param::il1, il1);
Param::SetFlt(Param::il2, il2);
return GetIlMax(il1, il2);
}