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.

MSP430F67791A: Metering data required in 100 msec for SLAA577G Code library

Part Number: MSP430F67791A
Other Parts Discussed in Thread: MSP430I2040

Hello,

We have an old designed product based on MSP430F67791A. Apart from Metering parameter the product has few
special function , decision for which would be based on metering data.The metering code base was TI slaa577g code library.

As per the code and application note SLAA577G ....the Power,Current,Voltage samples are getting updated
or loogged at 1 sec interval in emeter-background.c.

Now Our Customer asking an added feature in same product which requires us to get voltage,Current,Power,PF &
Frequency data within 100msec interval.And we want to complete the add-on feature by using the same existing code base.


I tried following in emeter-structs.h.

#define SAMPLE_RATE 409 // 4096
#define ADC_BITS 16
#define SAMPLES_PER_10_SECONDS 4090 // 40960ul

But it did not work for me.I think ...here SAMPLE_RATE = 409 means 409 samples in 1 sec time interval.And it will not solve my purpose.Correct me if i am wrong.


Can any one pls help in this regard ...what are the changes required (and which files ) in slaa577g code library to get the required metering data in every <100msec.

Thanks & Regards

  • Hello Ars,

    Thanks for your detailed post. Changing those two variables is a good start, and it looks like they are correct. However, 100 ms is much much shorter than a 1 second period, so before reducing by so much, I would recommend trying half the original values to see if the communication/functionality still works. If it does, that's good.

    However, for your case, you need faster reporting which means that code that uses SAMPLES_PER_10_SECONDS (you can find that code by searching for this variable in the project files) may not work correctly for such a low value. Also, you may be overrunning things such as the communication speed or even the amount of time required to calculate the parameters for each phase. You may need to increase the communication and/or CPU speed to ensure the data is getting sent out fast enough to allow the calculations to be performed.

    Regards,

    James

  • Hello James,

    Thanks for your response.I need your help to get the things resolved.

    Please note , my application uses Single phase Voltage and  Current .And % metering Error i can go upto 2%.

    In the said application,System Clock running at 16MHz and as per Application Report SLAA577 , the clock to the ΣΔ24 adc is is chosen as 1.048576 MHz, resulting in a sampling frequency of 4.096 ksps. i.e 4096 samples per second. Hence,  each ΣΔ24 ADC sample interrupt is happening at 244 uSec.

    My First option :

     following MACROS defined  in emeter-structs.h

    #define SAMPLE_RATE  4096
    #define ADC_BITS 16
    #define SAMPLES_PER_10_SECONDS 40960ul

    I still feel that just changing SAMPLE_RATE  &  SAMPLES_PER_10_SECONDS to it's 1/10th value i.e 409 and 4090 will not give me the result at 100msec.Because My understanding is , as per the macro name suggest  ,SAMPLE_RATE macro defines the no of samples to be accumulated in 1 sec time interval. Hence if I make it to 409 , it  appears to me that now sample data equivalent to 409 samples will be accumulated in 1 sec and so sample data updation  rate is not going to get reduced ( in my case i want it in 100msec ). Instead no of samples in 1sec interval will get reduced.so is the result.

    Please comment !

    Instead of the above , 2nd option what I thought is : to call  log_parameters(phase) function ( from ADC ISR routine in emeter-background.c )at reduced sample count  i.e 409 in this case.

          

     // if(phase->metrology.dot_prod.sample_count >= samples_per_second)  // Original Code
     if(phase->metrology.dot_prod.sample_count >= 409)     //  Changes done hoping to get the data @100 msec
     {
         log_parameters(phase);
         _BIC_SR_IRQ(LPM0_bits);
         /* When run as a host program there is no RTC, but we still need to kick the foreground somehow. */
     }
    
      ..............
      ..............
    // if (phase->metrology.dot_prod.sample_count >= samples_per_second + 200) // Original Code
    if (phase->metrology.dot_prod.sample_count >= (409 + 10)) //  Changes done hoping to get the data @100 msec
    {
         /* We don't seem to be detecting the end of a mains cycle, so force
         the end of processing block condition. */
         log_parameters(phase);
         _BIC_SR_IRQ(LPM0_bits);
    }

    But i am not aware of the side effect(s) of the above changes. is this 2nd approach going to give me data at 100msec ?Is this 2nd option correct ?

    samples_per_second = SAMPLES_PER_10_SECONDS / 10

     " SAMPLES_PER_10_SECONDS "  value used in emeter-setup.c and emeter-background.c.What i can make out is that it is used to check the frequency band between 40 to 70 Hz.

    As we are more focused on our application side code and taking TI Metering code library as it is , I request if ,TI Expert team of yours can give a proper solution to get it work at 100mSec.   

    Thanks & Regards,

    Ars

     

     

  • Hello James and TI Team,

    1. can i have any further help on my above application requirement and my explanation above.

    2. There is a library file Emeter-fir-table.c  in the project.and there is a FIR coefficients table to correct phase shift.

    const int16_t fir_coeffs[][2] =
    {
    { 32767, 8198 }, // 2.1973 deg
    { 31761, 8326 }, // 2.1629 deg

    ........................

    };

    If  system clock frequency get changed or Sample frequency get changed other than 4096 Hz , i assume this table has to be changed. does TI provide any calculator to generate  fir table other than sample frequency of 4096 Hz.

    3.  is this the only function which decided Sample Frequency ...found in Emeter-setup.c

         In the below code , I wanted to have System Clock Frequency = 25 MHz ( External Crystal used = 32.768 kHz ) and Sample Frequency = 4096 Hz

    static __inline__ void init_analog_front_end_normal(void)
    {
            
          int i;
          REFCTL0 = REFMSTR + REFVSEL_1 + REFON;         /* Enabale Reference = 2.0V */
          SD24BCTL1 &= ~SD24GRP0SC;     
            
        
          #if MCLK_DEF == 25
              SD24BCTL0 = SD24SSEL__SMCLK  /* Clock is SMCLK */
                     | SD24PDIV_3          /* Divide by 8 => ADC clock: 2MHz */
                     | SD24DIV1
                     | SD24REFS;           /* Use internal reference */
         #endif
             
        
         
         SD16INCTL_CURRENT_1 = CURRENT_PHASE_GAIN;        /* Set gain for channel 1 */
         SD16CCTL_CURRENT_1 = SD24DF_1  | SD24SCS_4; 
         SD16BOSR_CURRENT_1 = 256 - 1;
    //   SD16BOSR_CURRENT_1 = 512 - 1;  
         SD16PRE_CURRENT_1 = 0;
          
         SD16INCTL_CURRENT_2 =  CURRENT_PHASE_GAIN;        /* Set gain for channel 2 */
         SD16CCTL_CURRENT_2 = SD24DF_1  | SD24SCS_4;       /* Set oversampling ratio to 256 (default) */
         SD16BOSR_CURRENT_2 = 256 - 1;
    //   SD16BOSR_CURRENT_2 = 512 - 1;  
         SD16PRE_CURRENT_2 = 0;
          
         
         SD16INCTL_CURRENT_3 =  CURRENT_PHASE_GAIN;        /* Set gain for channel 3 */
         SD16CCTL_CURRENT_3 = SD24DF_1  | SD24SCS_4;//| SD16IE;       /* Set oversampling ratio to 256 (default) */
         SD16BOSR_CURRENT_3 = 256 - 1;
    //   SD16BOSR_CURRENT_3 = 512 - 1; 
         SD16PRE_CURRENT_3 = 0;
          
         SD16INCTL_NEUTRAL =  CURRENT_NEUTRAL_GAIN;        /* Set gain for channel neutral */
         SD16CCTL_NEUTRAL = SD24DF_1  | SD24SCS_4;         /* Set oversampling ratio to 256 (default) */
         SD16BOSR_NEUTRAL = 256 - 1;
         SD16PRE_NEUTRAL = 0;
    
    //   SD16BOSR_NEUTRAL = 512 - 1; 
              
              
         /* Configure analog front-end channel 2 - Voltage */
          SD16INCTL_VOLTAGE_1 =  VOLTAGE_GAIN;
          SD16CCTL_VOLTAGE_1 = SD24DF_1 | SD24ALGN | SD24SCS_4;
          SD16BOSR_VOLTAGE_1 = 256 - 1;
    //    SD16BOSR_VOLTAGE_1 = 512 - 1;
          SD16PRE_VOLTAGE_1 = DEFAULT_V_PRESCALE_FACTOR;
              
    //    SD16PRE_VOLTAGE_1 = DEFAULT_V_PRESCALE_FACTOR_A;
          
          SD16INCTL_VOLTAGE_2 = VOLTAGE_GAIN;
          SD16CCTL_VOLTAGE_2 = SD24DF_1 | SD24ALGN | SD24SCS_4;
          SD16BOSR_VOLTAGE_2 = 256 - 1;
    //    SD16PRE_VOLTAGE_2 = DEFAULT_V_PRESCALE_FACTOR_B;
    //    SD16BOSR_VOLTAGE_2 = 512 - 1; 
          SD16PRE_VOLTAGE_2 = DEFAULT_V_PRESCALE_FACTOR;
          
          SD16INCTL_VOLTAGE_3 =  VOLTAGE_GAIN;
          SD16CCTL_VOLTAGE_3 = SD24DF_1 | SD24ALGN | SD24SCS_4;
          SD16BOSR_VOLTAGE_3 = 256 - 1;
    //    SD16BOSR_VOLTAGE_3 = 512 - 1; 
          SD16PRE_VOLTAGE_3 = DEFAULT_V_PRESCALE_FACTOR;
    //    SD16PRE_VOLTAGE_3 = DEFAULT_V_PRESCALE_FACTOR_C;
    
    
          for (i = 0;  i < NUM_PHASES;  i++)
               chan[i].metrology.current.in_phase_correction[0].sd16_preloaded_offset = 0;
              
            SD24BIE=0x7F;
            SD24BCTL1 |= SD24GRP0SC;
           
    }

    Regards,

    ars

  • In 'emeter-background.c', this code determines when to trigger the foreground process which finishes the calculations and sends out the data. Changing SAMPLES_PER_10_SECONDS will cause this to trigger faster or slower. You should be able to use Option 1 which should automatically do Option 2 for you.

    /* See if a sufficiently long measurement interval has been
    recorded, and catch the start of the next cycle. We do not
    really care how many cycles there are, as long as the block
    is a reasonable length. Setting a minimum of 1 second is
    better than counting cycles, as it is not affected by noise
    spikes. Synchronising to a whole number of cycles reduces
    block to block jitter, though it doesn't affect the long
    term accuracy of the measurements. */
    if (phase->metrology.dot_prod.sample_count >= samples_per_second)
    {
       log_parameters(phase);
       _BIC_SR_IRQ(LPM0_bits);
       /* When run as a host program there is no RTC, but we still need to
          kick the foreground somehow. */

    Ars said:
     " SAMPLES_PER_10_SECONDS "  value used in emeter-setup.c and emeter-background.c.What i can make out is that it is used to check the frequency band between 40 to 70 Hz.

    That's correct. Because you're adjusting SAMPLES_PER_10_SECONDS, you'll need to adjust that code accordingly. What's happening is your sample count is not incrementing because the code thinks the AC mains input frequency is out of range.

    #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)
                        {
                            <code deleted>
                        }
                        else
                        {
                            phase->metrology.cycle_sample_count = 0;

    The FIR table would need to get regenerated for a different sampling rate. TI does not provide that calculator.

    The sampling rate is determined by dividing the ADC source clock by the oversampling rate (OSR). You can verify that rate by toggling a GPIO in the ADC ISR.

    Regards,

    James

  • Hello James,

    Thanks for your direction.

    1) I have followed  option 1:   following MACROS defined  in emeter-structs.h were changed

    #define SAMPLE_RATE  409     // 4096
    #define ADC_BITS 16
    #define SAMPLES_PER_10_SECONDS 4096ul     // 40960ul

    and below code section was changed . Plz Correct me if  anything wrong.

    #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)
        // changed to .....
        if(256*SAMPLES_PER_10_SECONDS/70 <= phase->metrology.cycle_sample_count  &&  phase->metrology.cycle_sample_count <= 256*SAMPLES_PER_10_SECONDS/40)
        {
                            <code deleted>
        }
        else
        {
                            phase->metrology.cycle_sample_count = 0;
        }

    Voltage and Current  measurement reading was acceptable to my application .but what i observed is that REVERSE current detection taking much time at lower power. For Example . if i wish to detect reverse current at 100watt , at injection of 105watt it takes 500 msec but if i inject around 200watt it detects at 180 msec.Can you guide me here to reduce the detection time.

    i have changed this macro thinking it will reduce the time.

    /*! This is the number of successive measurement blocks which must agree the

    reversed current status has changed before we accept it. */
    #define PHASE_REVERSED_PERSISTENCE_CHECK    2    // 5

    2) Why log_parameters(phase) function was called twice in the ADC ISR routine in emeter-background.c

     
     if(phase->metrology.dot_prod.sample_count >= samples_per_second)     //  Changes done hoping to get the data @100 msec
     {
         log_parameters(phase);
         _BIC_SR_IRQ(LPM0_bits);
         /* When run as a host program there is no RTC, but we still need to kick the foreground somehow. */
     }
    
      ..............
      ..............
    
    if (phase->metrology.dot_prod.sample_count >= (samples_per_second + 200)) //  Changes done hoping to get the data @100 msec
    {
         /* We don't seem to be detecting the end of a mains cycle, so force
         the end of processing block condition. */
         log_parameters(phase);
         _BIC_SR_IRQ(LPM0_bits);
    }

    I wish to drop 2nd log_parameters(phase)  function.is it okay ?

    Thanks & regards,

    Ars

     

  • Ars said:

    1) I have followed  option 1:   following MACROS defined  in emeter-structs.h were changed

    #define SAMPLE_RATE  409     // 4096
    #define ADC_BITS 16
    #define SAMPLES_PER_10_SECONDS 4096ul     // 40960ul

    and below code section was changed . Plz Correct me if  anything wrong.

    That looks right.

    Ars said:
    Voltage and Current  measurement reading was acceptable to my application .but what i observed is that REVERSE current detection taking much time at lower power. For Example . if i wish to detect reverse current at 100watt , at injection of 105watt it takes 500 msec but if i inject around 200watt it detects at 180 msec.Can you guide me here to reduce the detection time.

    I'm assuming you're adjusting that level by changing PHASE_REVERSED_THRESHOLD_POWER. Are you enabling POWER_BALANCE_DETECTION_SUPPORT?

    There's also a POWER_BALANCE_DETECTION_SUPPORT that could be affecting your results. Those parameters may need PHASE_UNBALANCED_PERSISTENCE_CHECK to be adjusted too.

    Do you have NEUTRAL_MONITOR_SUPPORT defined as 1?

    /*! This is the number of successive measurement blocks which must agree the
        unbalanced status has changed before we accept it. */
    #define PHASE_UNBALANCED_PERSISTENCE_CHECK          5
    
    /*! This enables monitoring of the balance between the current in the live and neutral
        leads, for tamper detection. */
    #define POWER_BALANCE_DETECTION_SUPPORT
    
    /*! This is the minimum current level (limp mode) and minimum power level (normal
        mode) at which we will make checks for the earthed condition. Very small
        readings lack the accuracy and resolution needed to make meaningfulF comparisons
        between live and neutral. */
    #define PHASE_UNBALANCED_THRESHOLD_CURRENT          500
    #define PHASE_UNBALANCED_THRESHOLD_POWER            2000

    Looking at 'emeter-foreground.c', there's some code before where "current_reversed" gets checked. That code seems to be depend on NEUTRAL_MONITOR_SUPPORT and POWER_BALANCE_DETECTION_SUPPORT.

    #if defined(POWER_BALANCE_DETECTION_SUPPORT)
            #if defined(SINGLE_PHASE)
        x = test_phase_balance(x, y, PHASE_UNBALANCED_THRESHOLD_POWER);
            #else
        x = test_phase_balance(phase, x, y, PHASE_UNBALANCED_THRESHOLD_POWER);
            #endif
        if ((phase->status & PHASE_UNBALANCED))
        {
            /* When the phase is unbalanced we only look for reversed current in the 
               lead with the higher current. If we do not impose this restriction, coupling
               through a parasitic CT power supply transformer can cause the reverse condition
               to be raised incorrectly. If there is no parasitic supply this test is probably
               a waste of time. */
            if ((phase->status & CURRENT_FROM_NEUTRAL))
                reversed = phase->status & I_NEUTRAL_REVERSED;
            else
                reversed = phase->status & I_REVERSED;
        }
        #endif

    Ars said:
    2) Why log_parameters(phase) function was called twice in the ADC ISR routine in emeter-background.c

    This is called twice as a timeout in case the input frequency is outside of 40 to 70 Hz. If you're not applying anything, the results will get updated (while they may be just noise) by the second call. This could also be applicable when measuring DC signals which won't have a frequency or zero crossings.

    Regards,

    James

  • Thanks James for your support !

    James Evans said:
    I'm assuming you're adjusting that level by changing PHASE_REVERSED_THRESHOLD_POWER. Are you enabling POWER_BALANCE_DETECTION_SUPPORT?

    Yes. You are correct.I have changed the macro value to 50

    #define PHASE_REVERSED_THRESHOLD_POWER              50  // changed

    As I am not checking any unbalance i have commented the below also.

    /*! This enables monitoring of the balance between the current in the live and neutral
    leads, for tamper detection. */

    // #define POWER_BALANCE_DETECTION_SUPPORT

    My result was with the above action in code.

    /*! This is the number of successive measurement blocks which must agree the
    unbalanced status has changed before we accept it. */

    #define PHASE_UNBALANCED_PERSISTENCE_CHECK 5

    However I have changed in the below code 

    /*! This is the number of successive measurement blocks which must agree the

    reversed current status has changed before we accept it. */

    #define PHASE_REVERSED_PERSISTENCE_CHECK    2    // 5

     

    James Evans said:
    Do you have NEUTRAL_MONITOR_SUPPORT defined as 1?

    NO. My Application doesn't require Neutral monitoring or tamper detection. so I have undefined it

    #undef NEUTRAL_MONITOR_SUPPORT

    #define PHASE_UNBALANCED_THRESHOLD_CURRENT          500

    #define PHASE_UNBALANCED_THRESHOLD_POWER            2000


    James Evans said:
    This is called twice as a timeout in case the input frequency is outside of 40 to 70 Hz. If you're not applying anything, the results will get updated (while they may be just noise) by the second call. This could also be applicable when measuring DC signals which won't have a frequency or zero crossings.

    OK. Noted. I have observed some times there is a quite a delay in measurement update.. say 5- 8 sec . when i switch off the measuring input to the device. For Example I have injected 220 V AC measuring input and after sometimes i stopped 220 VAC. It should have been ZERO within 100-200 msec. But some times i see it takes 5 to 8 secs to become ZERO.what could be possible reason ?

    Thanks & Regards,

    Ars

  • Hello James and TI Team,

    In addition to my last post few more observation i would like to share that also need to be addressed in the application.

    I like to take action depending on active power value beyond a set programmable threshold.

    1 . For example, If i set threshold as 100 watt ....and in application check time it takes to cross 100 watt.

    Case a : I inject 102 watt , it takes the code approx 520 - 540 mSec to decide it crosses 100 Watt mark.This is not acceptable to the requirement.

    Case b:  I inject 250 watt , it takes the code approx 120 - 140  mSec to decide it crosses 100 Watt mark.

    I suspect that within 100 msec time the code was not able to detect 100 Watt worth of active power when injected only 100 Watt . but it detects when injected power is higher(case b). What changes required in library code to address this ?

    2.  In the below code segment , pls help me to understand why 256 is added in every adc interrupt ?

     #if defined(MAINS_FREQUENCY_SUPPORT)
    
          phase->metrology.cycle_sample_count += 256;
    
     #endif

    Appreciate your support.

    Regards,

    Ars

  • Hello James and TI Team ,

    Can I have any update on last posts.Still i am not able to achieve the result.

    I would like to appreciate your help on the library....though I understand that TI has moved to new EMDC.

    During my search on TI web I have seen an  application report  SLAA638   : Single Phase and DC Embedded Metering (Power Monitor)
    Using MSP430I2040  which speaks  about .. Readings update every 4 AC cycles i.e 80 msec  for 50 Hz signal. This is similar to my requirement. I believe metering code associated this note is in library file format.

    Can TI able to provide library in similar line....for the mcu part i am using.or any consolidated detailed guidelines.

     

    Thanks and Regards,

    Ars

  • Ars said:
    1 . For example, If i set threshold as 100 watt ....and in application check time it takes to cross 100 watt.

    I'm not sure why there's a difference between the detection times. Unfortunately, so of these macros may have been implemented as a reference but not fully tested across all scenarios. However, I'm suspecting that the level you're setting is actually a level closer to 250W rather than 100W. Perhaps you can lower the level until it triggers within 100 ms.

    Obviously, there may be a lower limit due to noise, so you may be approaching that point. Perhaps you could calibrate your system at a lower current and see if that improves things. Hopefully you're using a GAIN setting that allows you to leverage the entire full-scale range.

    Ars said:
    2.  In the below code segment , pls help me to understand why 256 is added in every adc interrupt ?

    This value depends on the OSR. There are 256 (preload) steps between each ADC sample. This is important when aligning the voltage and current samples during phase calibration.

    Regarding the other library, they are probably similar. I'm not sure what's different between them, but you may be able to port over some of the APIs.

    And yes, we recommend EMDC for new designs since the Design Center makes everything easier to configure, calibrate and evaluate. Plus, CCS is now supported by the new library which is free to use.

    Regards,

    James

**Attention** This is a public forum