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.

SLAA577 - phase calibration and V->I phase shift calculation

Other Parts Discussed in Thread: MSP430F67791

Hello everyone,

I would like to have some information about how the SLAA577 firmware performs the phase calibration and how the V->I phase shift is calculated. I am using a MSP430F67791 micro.

Regarding the phase calibration, inside the firmware code a parameter expressed as "phase angle in 1/256th of a sample increments" is used.

(I am referring to line 623 of the "emeter-3ph-neutral-6779(A).h" file)

#define DEFAULT_BASE_PHASE_B_CORRECTION_LOW  40 /* Value is phase angle in 1/256th of a sample increments. */

What does exactly mean 1/256th of a sample increments? Is it bound to the nominal frequency or to the measured frequency? If, for example, I have as an input to my device, a sensor which cause a current phase shift of -2.7° and a -0.85° voltage phase shift, how do I have to change the calibration parameter? Also, doing some tests, I could see that it doesn't seem to be periodic (eg. 1 and 257 give very different results)

Regarding the V->I phase shift, given that the dedicated field is used inside the GUI released within the firmware but I cannot find any information about its calculation, am I right if I assume it to be  the arctangent of the ration between reactive and active power?”

Regards,
Alan

  • Hello Alan,

    I will try to bring in the authors of this Application Report to further comment on your questions. 1/256th of a sample increments refers to one sample, for which the SD24 is initialized to operate at an oversampling ratio (OSR of 256) resulting in four thousand samples-per-second (sps) at a modulation frequency of 1.048 MHz. For an input frequency of 60 Hz the resolution for every bit in the preload register is approximately 0.02° with a maximum of 5.25° (255 steps), but factoring in lead or lag puts the practical design limit to ±2.62°. Phase calibration is further explained in Section 6.3.3.2 of the Application Report and should be limited by GUI control as compared to firmware changes.

    Regards,
    Ryan
  • Hi Ryan,

    I am back in this issue after quite some time.

    I understand better how the phase calibrations works, but I still have some doubts:

    1) The DEFAULT_BASE_PHASE_X_CORRECTION_LOW values are used to compensate the phase shift between voltage and current by setting the preloader register for a specific channel. In the section 4.3.2 of the application note slaa577 and inside the code comments, its value can be set between 0 and 255 (whereas the preloader register can hold up to 1023).

    By setting the value up to 255, the voltage sample used to calculate the active power is always the 3rd to last

    Inside emeter-foreground.c
    void set_sd16_phase_correction(struct phase_correction_sd16_s *s, int ph, int correction) {
            static unsigned short volatile * const sd16_locations[NUM_CURRENT_CHANNELS] = {&SD16PRE_CURRENT_1, &SD16PRE_CURRENT_2, &SD16PRE_CURRENT_3,
                            #if defined(NEUTRAL_MONITOR_SUPPORT)
                            &SD16PRE_NEUTRAL
                            #endif
            };
            uint8_t bump;
            
            /* Only try to nudge the converter's timing when in normal operating mode. */
            if (operating_mode == OPERATING_MODE_NORMAL) {
                    if ((bump = s->sd16_preloaded_offset - (correction & 0xFF)))
                            *sd16_locations[ph] = bump;
            }
            /* Always store the required correction. */
            //as correction is at maximum 255, (correction >> 8) is always 0 and (I_HISTORY_STEPS - (correction >> 8)) is always 2
            s->step = I_HISTORY_STEPS - (correction >> 8);
            s->sd16_preloaded_offset = correction;
            
    }

    Inside emeter-background.c

    #if defined(PHASE_CORRECTION_SUPPORT)
    //phase->metrology.V_history_index holds the last received voltage sample V_corrected = phase->metrology.V_history[(phase->metrology.V_history_index - phase->metrology.current.in_phase_correction[use_stage].step) & V_HISTORY_MASK]; #else

    Is it supposed to be this way or am I missing something?

    2) About the reactive power calculation, as described in 4.2.1.2 of the application note, the voltage calculated by interpolating two voltage samples near 90° before the actual current sample and using a fir filter (emeter-background.c).

    #if defined(REACTIVE_POWER_BY_QUADRATURE_SUPPORT)
    			V_quad_corrected = (Q1_15_mul(phase->metrology.V_history[(phase->metrology.V_history_index - phase->metrology.current.quadrature_correction[use_stage].step - 1) & V_HISTORY_MASK], phase->metrology.current.quadrature_correction[use_stage].fir_beta) >> 1) + (phase->metrology.V_history[(phase->metrology.V_history_index - phase->metrology.current.quadrature_correction[use_stage].step) & V_HISTORY_MASK] >> 1);
    			mac_power(phase->metrology.current.dot_prod.P_reactive, V_quad_corrected, I_live_sample);     
    #endif

    And then the power gain is multiplied by the fir gain (emeter-foreground.c):

    		int64_t x = div_ac_power(phase->metrology.current.dot_prod_logged.P_reactive, phase->metrology.current.dot_prod_logged.sample_count);
    		int16_t i = Q1_15_mul(phase_nv->current.P_scale_factor[0], phase->metrology.current.quadrature_correction[0].fir_gain);


    How are the fir filter parameters calculated? Is there any formula that can be applied?

    3) I was trying to calibrate my device so I first set V and I in phase and could successfully set the gains.
    When I set a 45° phase difference between V and I, the arctg(Qx/Px) was of 37°, thus a correction of about 8° was needed. So, since the DEFAULT_BASE_PHASE_X_CORRECTION_LOW could not help as the maximum correction was of +-2.15° at 50Hz, I tried forcing the register at values bigger than 255.
    The expected value in the preload register was of 470 (given that 1 bit of the preload register gives a correction of 0.017°), but the actual correction was of about ~2.3°.
    Changing to even higher values seems to have little to no effect (I'll post a table with the precise result later). If it can help, the frequency measurement is accurate. 

    Have I misunderstood how the preloader register works or did I need to change something else in the code in order to apply a such big phase compensation?
    I'll post asap if I discover something else.

    Thanks for your attention,
    Alan

  • Hi Alan,

    What values are your anti-aliasing resistors on the positive and negative sides for the voltage input? If they increase the input impedance too much, they'll cause a large phase shift that your present configuration can't correct.

    Regards,

    James

    MSP Customer Applications

  • Hi James,

    This is the schematic of my application regarding the voltage and current input.

  • I've done some testing of the application by changing the values of the preload registers both for the voltage and the current. Here are the results:

    expected (°) measured (°) PRELOAD V PRELOAD I
    0 0 0 0
    0 0 25 0
    0 3,67 0 25
    0 1,82 128 0
    0 1,82 0 128
    0 0 256 0
    0 0 0 256
    0 0 281 0
    0 3,67 0 281
    0 1,82 384 0
    0 1,82 0 384
    ############ ############ ########### ###########
    30 25,64 0 0
    30 25,57 25 0
    30 22,48 0 25
    30 23,77 128 0
    30 23,77 0 128
    30 25,64 256 0
    30 25,64 0 256
    30 25,57 281 0
    30 22,48 0 281
    30 23,77 384 0
    30 23,77 0 384

    ############

    ############ ########### ###########
    45 38,58 0 0
    45 38,04 25 0
    45 34,99 0 25
    45 36,51 128 0
    45 36,51 0 128
    45 38,13 256 0
    45 38,13 0 256
    45 38,04 281 0
    45 34,99 0 281
    45 36,51 384 0
    45 36,51 0 384

    ############

    ############ ########### ###########
    60 51,16 0 0
    60 50,93 25 0
    60 47,77 0 25
    60 49,54 128 0
    60 49,54 0 128
    60 51,16 256 0
    60 51,16 0 256
    60 50,93 281 0
    60 47,77 0 281
    60 49,54 384 0
    60 49,54 0 384

    ############

    ############ ########### ###########
    -30 30,48 0 0
    -30 30,65 25 0
    -30 34,88 0 25
    -30 33,03 128 0
    -30 33,03 0 128
    -30 30,48 256 0
    -30 30,48 0 256
    -30 30,65 281 0
    -30 34,88 0 281
    -30 33,03 384 0
    -30 33,03 0 384
    ############ ############ ########### ###########
    -45 48,15 0 0
    -45 47,94 25 0
    -45 52,31 0 25
    -45 50,12 128 0
    -45 50,12 0 128
    -45 47,69 256 0
    -45 47,69 0 256
    -45 47,94 281 0
    -45 52,31 0 281
    -45 50,12 384 0
    -45 50,12 0 384

    ############

    ############ ########### ###########
    -60 65,64 0 0
    -60 66,11 25 0
    -60 70,34 0 25
    -60 68,11 128 0
    -60 68,11 0 128
    -60 65,64 256 0
    -60 65,64 0 256
    -60 66,11 281 0
    -60 70,34 0 281
    -60 68,11 384 0
    -60 68,11 0 384

    As you can see the measurements done with value 'x' inside the register are exactly the same when done at 'x+256'.
    As specified in slau461 (section 1.2.10) it is specified that the range for the preload register is 0-1023, instead in the slaa577 in 4.3.2 it is specified that the maximum step is 256.
    Do you have any suggestion on how to resolve this issue?

    Thanks for your help.

  • Hi Alan,

    Thank you for these measurements. It's very helpful for our discussion.

    The preload applies a fractional sampling delay, not full integer sampling delays. Since we're sampling the input signal (assuming it's a 50 Hz signal) at 4096 Hz, each sample takes 1 / 4096 Hz which equals 244 us per sample. Now, for one cycle of the 50 Hz signal, there's 360 degrees total, and it takes 1 / 50 Hz which equals 20 ms. Assuming you need a phase shift of 8 degrees, this equals 8 degrees * (20 ms / 360 degrees) which equals 444 us. Now, one sample takes 244 us, so 8 degrees phase shift essentially means you need to delay by 444 us / 244 us which equals 1.82 samples.

    Since the preload register can only delay by a fraction of a sample by utilizing the modulation clock (here it's 1.048576 MHz), a maximum preload value is 256 because one sample takes 244 us and 1 / 1048576 * 256 equals 244 us. As you can see below at an expected phase angle of 30 degrees, you measured 25.57 degrees both at preload values of 25 and 281 (which is 281 - 256 = 25). Basically, the preload value is overflowing because it's trying to delay more than 1 sample.

    Thus, I'd recommend manually delaying the samples for the full integer delays. If your current channel is 8 degrees behind the voltage channel, delay the voltage channel samples by one (manually in the code) and then the remaining 0.82 fractional samples using the preload register. In the code, I'd recommend storing the existing/present voltage sample and using the previous sample with the existing/present current sample to accomplish this. Does this make sense?

    Regards,

    James

    MSP Customer Applications

  • Hi James,

    I now understand better how the preload register works. I tried delaying the whole samples and there were improvements in the calculation.

    Thank you for your help!

**Attention** This is a public forum