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.

Negative values of V_fundamental in calculating Fundamental Voltage in MSP430F6779 Three Phase Watt-Hour meter

Other Parts Discussed in Thread: MSP430F6779

I implemented parts of the Energy Library (SLAA538) to add Voltage and Current THD calculation to our MSP430F6779 based Three Phase Watt-Hour meter (based on the SLAA577 EVM). 

The THD calculation uses the Fundamental Voltage value but in the fundamental_voltage function I get a negative values of the phase.metrology.dot_prod_logged.V_fundamental which causes the function to stop and return -1.

How can I fix it?

  • Hi,

    I've assigned your thread to a SME and hopefully the issue will be resolved shortly.

    Sincerely,
    Sean
  • Thank you Sean.

    I kept diving into the code and now I understand why I am getting the negative values:

    The fundamental voltage is accumulated after multiplyed with the Pure sinus value. The phase correction mechanizm supplys the phase shift of the signal.

    In the first and second quadrants both the voltage measurement and the sinus are positive and in the third and forth quadrants are negative.

    If they are synced then the production will be always positive.

    So, it seems that in my system they are not synced. I am now searching for the reason why the phase correction is wrong.

  • Hi Meir,

    Did not notice this thread is still open. Any updates to your problem? If there are, I can send another request to look into your problem.

    Sincerely,
    Sean

  • I found the reason for the problem and I fixed it:


    Problem in calculating fundamental voltage in the background interrupt.
    -------------------------------------------------------------------------------------------------
    Calculating the fundamental voltage uses the V_pure voltage that is returned
    from the dds_lookup function. This is a pure sinus voltage value that must
    be synchronized with the phase of the sampled voltage. The dds_lookup function
    gets the value from a table that holds only the first quarter of the full sinus
    cycle. The other 3 quarters are either a mirror value or negative same value.

    I found that the incorrect values are due to the IAR optimizer mistranslates
    of the C code. The optimizer at the emeter-toolkit project configuration is set
    to maximum optimization for speed.

    I added here the TI's Energy Library original code and my modified code that
    solved the problem (in ...\Device\emeter-toolkit\dds.c):


    #define SLENK 8
    #define DDS_STEPS (1 << SLENK)
    #define DDS_SHIFT (32 - 2 - SLENK)


       Original code
    ==============

      1  int16_t dds_lookup(uint32_t phase) 
      2  {
      3      int16_t amp;
      4      uint32_t step;
      5
      6      phase >>= DDS_SHIFT;
      7      step = phase & (DDS_STEPS - 1);
      8      if ((phase & DDS_STEPS))
      9           step = DDS_STEPS - step;
    10      amp = sine_table[step];
    11      if ((phase & (2*DDS_STEPS)))
    12           amp = -amp;
    13      return amp;
    14  }

    Optimizer problems:
    1. After the right shift in line 6, the values should be in the range of
         0 - 1023 (10 bits, because DDS_SHIFT = 22). Breaking after this shift
         shows much larger values.
    2. All values returned from the function are positive. Trying to place a
        break point at lines 11 or 12, failed. It means that the optimizer discards
        these lines.


    Solution:

    1. Copy and type cast the input 32-bit value "phase" into an internal 16-bit
        variable "ph" and use it instead of "phase". This change caused the
        optimiser to perform correct shift.
    2. Change the type of "step" to 16-bit.

    I also added comments to explain the calculations

       Modified code
    =============

      1 int16_t dds_lookup(uint32_t phase)
      2 {
      3     int16_t amp;
      4     uint16_t step;
      5     uint16_t ph;
      6
      7     ph = (uint16_t)(phase >> DDS_SHIFT);
      8     step = ph & (DDS_STEPS - 1);     // get place in quarter
      9     if ((ph & DDS_STEPS))                  // check if in 2nd or 4th quarters
    10          step = DDS_STEPS - step;      // yes, take a mirror value
    11     amp = sine_table[step];                 // Get the Sinus value from the table
    12     if ((ph & (2*DDS_STEPS)))           // check if in 3rd or 4th quarters
    13     {
    14          return (-amp);                             // yes, invert sign
    15     }
    16     return amp;
    17 }

  • Hi Meir,

    Glad you found the solution to your problem, I will ask someone on my team about issues to the preexisting code.

    Sincerely,
    Sean

**Attention** This is a public forum