This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TIDM-THREEPHASEMETER-F6779: emeter-backgroud.c

Part Number: TIDM-THREEPHASEMETER-F6779

Dear TI,

i was going through the firmware provided with slaa577,

and try to understand below lines of code,

In the function ISR(SD24B, adc_interrupt)

can you help understand below 

if (abs(V_sample - phase->metrology.last_V_sample) <= phase->metrology.since_last*MAX_PER_SAMPLE_VOLTAGE_SLEW)
{
/* This doesn't look like a spike - do mains cycle detection, and
estimate the precise mains period */
if (V_sample < 0)
{
/* Log the sign of the signal */
phase->status &= ~V_POS;
}
else
{
if (!(phase->status & V_POS))
{
#if defined(MAINS_FREQUENCY_SUPPORT)
/* Apply limits to the sample count, to avoid spikes or dying power lines disturbing the
frequency reading too much */
/* The mains should be <40Hz or >70Hz to fail this test! */
if (256*SAMPLES_PER_10_SECONDS/700 <= phase->metrology.cycle_sample_count && phase->metrology.cycle_sample_count <= 256*SAMPLES_PER_10_SECONDS/400)
{
/* A mains frequency measurement procedure based on interpolating zero crossings,
to get a fast update rate for step changes in the mains frequency */
/* Interpolate the zero crossing by successive approx. */
z = V_sample - phase->metrology.last_V_sample;
x = 0;
y = 0;
for (k = 0; k < 8; k++)
{
y <<= 1;
z >>= 1;
x += z;
if (x > V_sample)
x -= z;
else
y |= 1;
}
/* Now we need to allow for skipped samples, due to spike detection */
z = y;
while (phase->metrology.since_last > 1)
{
z += y;
phase->metrology.since_last--;
}
/* z is now the fraction of a sample interval between the zero
crossing and the current sample, in units of 1/256 of a sample */
/* A lightly damped filter should now be enough to remove noise and get a
stable value for the frequency */
phase->metrology.mains_period += ((int32_t) (phase->metrology.cycle_sample_count - z) << 12) - (phase->metrology.mains_period >> 4);
/* Start the next cycle with the residual fraction of a sample */
phase->metrology.cycle_sample_count = z;
}
else
{
phase->metrology.cycle_sample_count = 0;
}

I need to know how the frequency is calculated in this routine, specifically what these below lines of code doing 

z = V_sample - phase->metrology.last_V_sample;
x = 0;
y = 0;
for (k = 0; k < 8; k++)
{
y <<= 1;
z >>= 1;
x += z;
if (x > V_sample)
x -= z;
else
y |= 1;
}

can you pls, help to explain

regards

  • Hi lakh,

    This portion of the code is trying to determine the exact timing of the zero crossing. By taking two sample values we know a zero crossing occurred at some point between the two samples. However, we don't know exactly when between the two samples. 

    This code is trying to determine with 8 bit resolution what fraction of the interval between the last two samples should be assigned to the previous cycle vs. the next next cycle.

    In the end, y stores an 8 bit value. A value of 0xFF means that the entire sample interval should be assigned to the next frequency calculation. A value of 0x00 in y means that the entire sample interval should be applied to the current frequency calculation.

    This is done by taking the difference between two consecutive sample values, stored in z, to begin with. Then half the difference (z>>1 is the same as z/2 ), is used to determine if the MSB of y should be 1 or 0. The next cycle a quarter of the difference between the sample values is used to determine the next bit of y and so on.

    Regards,

    Muhammad 

**Attention** This is a public forum