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.

AC RMS measurement - DPLib



Hi folks,

I would like to measure an the RMS value of an AC signal that has an offset.

I am already using the F2802x DPLib and note the Sine Analyzer module included, though it seems like a bit overkill FWIW and also requires that signal be rectified.

Is this the best option or are there better alternative macros in other libs?

Also I note that the table on pages 16/17 of the DPLib users guide does not specify any details for the SineAnalyzer... is it known how many cycles it takes? What is its data and code size? etc

Thanks

  • Toby, 

    The module in digital power library is targeted for power applications where we need to update the RMS value accurately and the update rate matters, there can be several issues when implementing such algorithms i.e. noisy zero crossings etc.. if you can live with a slow update rate and are not necessarily measuring rms of a sine wave then you can use simpler methods where you will not need to worry about zero crossings.

    3286.SolarLib_SineAnalyzer.pdf

    #include "Solar_IQ.h"
    
    //*********** Structure Init Function ****//
    void SINEANALYZER_DIFF_wPWR_IQ_init(SINEANALYZER_DIFF_wPWR_IQ *v)
    {
    	v->Vin=0;
    	v->SampleFreq=0;
    	v->Threshold=0;
    	v->Vrms=0;
    	v->Vavg=0;
    	v->Vema=0;
    	v->SigFreq=0;
    	v->Iin=0;
    	v->Irms=0;
    	v->Prms=0;
    	v->ZCD=0;
    	v->sum_Vacc_avg=0;
    	v->sum_Vacc_rms=0;
    	v->sum_Vacc_ema=0;
    	v->sum_Iacc_rms=0;
    	v->sum_Pacc_rms=0;
    	v->curr_vin_norm=0;
    	v->curr_iin_norm=0;
    	v->prev_sign=1;
    	v->curr_sign=1;
    	v->nsamples=0;
    	v->nsamplesMin = 0;
    	v->nsamplesMax = 0;
    	v->inv_nsamples=0;
    	v->inv_sqrt_nsamples=0;
    	v->slew_power_update=0;
    	v->sum_Pacc_mul=0;
    }
    
    //*********** Function Definition ********//
    void SINEANALYZER_DIFF_wPWR_IQ_FUNC(SINEANALYZER_DIFF_wPWR_IQ *v)
    {
    	if ( v->Vin > v->Threshold)
    	{
    		v->curr_vin_norm = v->Vin;
    		v->curr_iin_norm = v->Iin;
    		v->curr_sign = 1;
    	}
    	else
    	{
    		v->curr_vin_norm = _IQ15abs(v->Vin);
    		v->curr_iin_norm = _IQ15abs(v->Iin);
    		v->curr_sign = 0;
    	}
    	if((v->prev_sign != v->curr_sign) && (v->curr_sign == 1))
    	{
    		v->ZCD=1;
    		v->inv_nsamples = _IQ15div(_IQ15(1.0), (v->nsamples<<15));
    		v->inv_sqrt_nsamples = _IQ15isqrt(v->nsamples<<15);
    		if(v->nsamplesMin < v->nsamples < v->nsamplesMax)
    		{
    			v->Vavg = _IQ15mpy(v->sum_Vacc_avg, v->inv_nsamples);
    			v->Vrms = _IQ15mpy(_IQ15sqrt(v->sum_Vacc_rms),v->inv_sqrt_nsamples);
    			v->Vema = v->sum_Vacc_ema;
    			v->Irms = _IQ15rmpy(_IQ15sqrt(v->sum_Iacc_rms),v->inv_sqrt_nsamples);
    			v->slew_power_update++ ;
    			if(v->slew_power_update >= 101)
    			{
    				v->slew_power_update=0;
    				v->Prms = _IQ15mpy(v->sum_Pacc_mul, _IQ15(0.01));
    				v->sum_Pacc_mul = 0;
    			}
    			else
    			{
    				v->sum_Pacc_mul = v->sum_Pacc_mul + _IQ15rmpy(v->sum_Pacc_rms, v->inv_nsamples);
    			}
    		}
    		else
    		{
        		v->Vavg = 0;
        		v->Vrms = 0;
        		v->Vema = 0;
        		v->Irms = 0;
        		v->Prms = 0;
    		}
    		v->SigFreq = (_IQ15mpy(v->SampleFreq, v->inv_nsamples)>>1);
    		v->prev_sign = v->curr_sign;
    		v->sum_Vacc_avg = 0;
    		v->sum_Vacc_rms = 0;
    		v->sum_Vacc_ema = 0;
    		v->sum_Iacc_rms = 0;
    		v->sum_Pacc_rms = 0;
    		v->nsamples=0;
    	}
    	else
    	{
    		v->nsamples++;
    		v->sum_Vacc_avg = v->sum_Vacc_avg+v->curr_vin_norm;
    		v->sum_Vacc_rms = v->sum_Vacc_rms+_IQ15rsmpy(v->curr_vin_norm,v->curr_vin_norm);
    		v->sum_Vacc_ema = v->sum_Vacc_ema+_IQ15rsmpy(_IQ15(0.01),(v->curr_vin_norm - v->sum_Vacc_ema));
    		v->sum_Iacc_rms = v->sum_Iacc_rms+_IQ15rsmpy(v->curr_iin_norm,v->curr_iin_norm);
    		v->sum_Pacc_rms = v->sum_Pacc_rms+_IQ15rsmpy(v->curr_iin_norm,v->curr_vin_norm);
    		v->ZCD=0;
    		v->prev_sign = v->curr_sign;
    	}
    }
    
    2727.SINEANALYZER_DIFF_wPWR_IQ.h

    Attached is the source code for a module that analyzes a sine waveform from voltage and current, and calculates the rms and avg values, it will take ~  200-250 cycles, you can choose to disable the sections that you are not concerned with and save extra cycles, but this is what we have as available.