⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 emeter-foreground.c

📁 msp430F437三相电表DEMO(编译器 IAR 3.42A)
💻 C
📖 第 1 页 / 共 4 页
字号:
        /* Half bit round */
        z++;
        i -= z;
    }
        #if defined(__MSP430_HAS_ADC12__)  ||  defined(__MSP430_HAS_ADC10__)
    /* We use a +/- 0.5 sample FIR interpolator to perform the phase correction. We use a set
       of coefficients from a table of 128 spread evenly across the +/- 0.5 sample range.
       We need to get the phase shift into range, and end up with an FIR table entry in the 
       range 0 (-0.5 samples) to 127 (+0.5 samples), and the number of whole sample steps
       to use inconjunction with it. */
    i += 128;
        #endif
    gain = 32767 - (gain << 2);
    /* Update the whole group quickly, so the interrupt routine uses a consistent pair of
       step and beta values. */
    phase->current.in_phase_phase_correction_step[0] = 2 + (i >> 8);
    i &= 0xFF;
        #if defined(__MSP430_HAS_ADC12__)  ||  defined(__MSP430_HAS_ADC10__)
    i >>= 1;
    phase->current.in_phase_fir_beta[0] = fir_coeffs[i][0];
    phase->current.in_phase_fir_gain[0] = Q1_15_mul(gain, fir_coeffs[i][1]);
        #elif defined(__MSP430_HAS_SD16_3__)
    if (operating_mode == OPERATING_MODE_NORMAL  &&  phase->current.sd16_preloaded_offset != i)
    {
        SD16PRE_LIVE = phase->current.sd16_preloaded_offset - i;
        phase->current.sd16_preloaded_offset = i;
    }
        #endif
    #endif
    #if defined(LIMP_MODE_SUPPORT)
    if (operating_mode == OPERATING_MODE_LIMP)
    {
        /* We need to work out for ourselves which is the relevant current
           to use. */
        #if defined(SINGLE_PHASE)  &&  defined(NEUTRAL_MONITOR_SUPPORT)  &&  POWER_BALANCE_DETECTION_SUPPORT
        x = test_phase_balance(x, y, PHASE_UNBALANCED_THRESHOLD_CURRENT);
          /* In limp mode we have no way to determine if the phase is reversed,
             so just say it is not. */
        phase->status &= ~PHASE_REVERSED;
        #endif
    }
    else
    #endif
    {
        /* The power calculation has provided us which is the appropriate
           current to use. */
    #if defined(SINGLE_PHASE)  &&  defined(NEUTRAL_MONITOR_SUPPORT)
        if ((phase->status & CURRENT_FROM_NEUTRAL))
               x = y;
    #endif
    }
    return  x;
}
#endif

#if !defined(SINGLE_PHASE)  &&  defined(NEUTRAL_MONITOR_SUPPORT)  &&  defined(IRMS_SUPPORT)
long int neutral_current(void)
{
    long int x;

    /* Calculate the RMS current in 1mA increments. Return -1 for overrange
       (i.e. ADC clip). A side effect of this routine is it updates the dynamic
       phase correction settings, based on the newly calculated current. */
    if ((neutral.status & I_OVERRANGE))
    {
        x = -1;
    }
    else
    {
    #if ADC_BITS == 16
        x = div48(neutral.I_sq_accum_logged[0], neutral.sample_count_logged);
    #else
        x = div_sh48(neutral.I_sq_accum_logged[0], 32 - 2*ADC_BITS, neutral.sample_count_logged);
    #endif
        x = isqrt32(x);
    #if defined(LIMP_MODE_SUPPORT)
        if (operating_mode == OPERATING_MODE_LIMP)
            x = (x >> 12)*nv_parms.seg_a.s.neutral.I_rms_limp_scale_factor;
        else
    #endif
            x = (x >> 12)*nv_parms.seg_a.s.neutral.I_rms_scale_factor;
        x >>= 14;
    }
    return  x;
}
#endif

long int fredx;
long int fredy;

#if defined(SINGLE_PHASE)
long int power(void)
#else
long int power(struct phase_parms_s *phase, struct phase_nv_parms_s const *phase_nv)
#endif
{
    long int x;
    long int y;
    int i;
#if defined(PHASE_REVERSED_DETECTION_SUPPORT)
    int reversed;
#endif

    /* We can only do real power assessment in full operating mode. */
    /* If we have neutral monitoring for a single phase meter, we need to measure
       both power levels, and decide between them. Issues to be assessed here are
       whether one or both leads show reverse power, and whether the power levels
       are balanced. */
#if defined(PHASE_REVERSED_DETECTION_SUPPORT)
    /* If we find a negative power level we may be genuinely feeding power to the grid,
       or we may be seeing a tamper condition. This is application dependant. */
    reversed = FALSE;
#endif

    x = div_sh48(phase->current.P_accum_logged[0], 27 - 2*ADC_BITS, phase->sample_count_logged);
    i = phase_nv->current.P_scale_factor[0];
#if defined(PHASE_CORRECTION_SUPPORT)  &&  (defined(__MSP430_HAS_ADC12__)  ||  defined(__MSP430_HAS_ADC10__))
    i = Q1_15_mul(i, phase->current.in_phase_fir_gain[0]);
#endif
    fredx = mul48(x, i);
    x = fredx;
#if GAIN_STAGES > 1
    y = div_sh48(phase->current.P_accum_logged[1], 27 - 2*ADC_BITS, phase->sample_count_logged);
    i = phase_nv->current.P_scale_factor[1];
#if defined(PHASE_CORRECTION_SUPPORT)  &&  (defined(__MSP430_HAS_ADC12__)  ||  defined(__MSP430_HAS_ADC10__))
    i = Q1_15_mul(i, phase->current.in_phase_fir_gain[1]);
#endif
    fredy = mul48(y, i);
    x += fredy;
#endif
#if defined(PRECALCULATED_PARAMETER_SUPPORT)
    phase->current.power = x;
#endif
#if defined(PHASE_REVERSED_DETECTION_SUPPORT)
    if (x < 0)
    {
    #if defined(PHASE_REVERSED_IS_TAMPERING)
        x = -x;
    #endif
        phase->status |= I_REVERSED;
        if (x > PHASE_REVERSED_THRESHOLD_POWER)
            reversed = TRUE;
    }
    else
    {
        phase->status &= ~I_REVERSED;   
    }
#endif
#if defined(SINGLE_PHASE)  &&  defined(NEUTRAL_MONITOR_SUPPORT)
    y = div_sh48(phase->neutral.P_accum_logged[0], 27 - 2*ADC_BITS, phase->sample_count_logged[0]);
    i = nv_parms.seg_a.s.neutral.P_scale_factor[0];
    #if defined(PHASE_CORRECTION_SUPPORT)  &&  (defined(__MSP430_HAS_ADC12__)  ||  defined(__MSP430_HAS_ADC10__))
    i = Q1_15_mul(i, phase->neutral.in_phase_fir_gain[0]);
    #endif
    y = mul48(y, i);
    #if defined(PRECALCULATED_PARAMETER_SUPPORT)
    phase->neutral.power = y;
    #endif
    #if defined(PHASE_REVERSED_DETECTION_SUPPORT)
    if (y < 0)
    {
    #if defined(PHASE_REVERSED_IS_TAMPERING)
        y = -y;
    #endif
        phase->status |= I_NEUTRAL_REVERSED;
        if (y > PHASE_REVERSED_THRESHOLD_POWER)
            reversed = TRUE;
    }
    else
    {
        phase->status &= ~I_NEUTRAL_REVERSED;  
    }
    #endif
    #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
#endif
#if defined(PHASE_REVERSED_DETECTION_SUPPORT)
    if ((phase->status & PHASE_REVERSED))
    {
        if (!reversed)
        {
            if (--current_reversed <= -PHASE_REVERSED_PERSISTENCE_CHECK)
            {
                phase->status &= ~PHASE_REVERSED;
                current_reversed = 0;
            }
        }
        else
        {
            current_reversed = 0;
        }
    }
    else
    {
        if (reversed)
        {
            if (++current_reversed >= PHASE_REVERSED_PERSISTENCE_CHECK)
            {
                phase->status |= PHASE_REVERSED;
                current_reversed = 0;
            }
        }
        else
        {
            current_reversed = 0;
        }
    }
#endif
    return  x;
}

#if REACTIVE_POWER_SUPPORT
    #if defined(SINGLE_PHASE)
int32_t reactive_power(void)
    #else
int32_t reactive_power(struct phase_parms_s *phase, struct phase_nv_parms_s const *phase_nv)
    #endif
{
    int32_t x;
    int16_t i;

    /* We can only do real power assessment in full operating mode. */
    #if defined(SINGLE_PHASE)  &&  defined(NEUTRAL_MONITOR_SUPPORT)
    /* If we have neutral monitoring for a single phase meter, we need to use whichever
       channel has been selected by the anti-tamper validation scheme. */
    if ((phase->status & CURRENT_FROM_NEUTRAL))
    {
        x = div_sh48(phase->neutral.P_reactive_accum_logged[0], 28 - 2*ADC_BITS, phase->sample_count_logged[0]);
        i = nv_parms.seg_a.s.neutral.P_scale_factor[0];
        #if REACTIVE_POWER_BY_QUADRATURE_SUPPORT
        i <<= 1;
        i = Q1_15_mul(i, phase->neutral.quadrature_fir_gain);
        #endif
    }
    else
    {
    #endif
        x = div_sh48(phase->current.P_reactive_accum_logged[0], 28 - 2*ADC_BITS, phase->sample_count_logged[0]);
        i = phase_nv->current.P_scale_factor[0];
    #if REACTIVE_POWER_BY_QUADRATURE_SUPPORT
        i <<= 1;
        i = Q1_15_mul(i, phase->current.quadrature_fir_gain);
    #endif
    #if defined(SINGLE_PHASE)  &&  defined(NEUTRAL_MONITOR_SUPPORT)
    }
    #endif
    x = mul48(x, i);
#if PHASE_REVERSED_DETECTION_SUPPORT
    if (x < 0)
    {
    #if PHASE_REVERSED_IS_TAMPERING
        x =- x;
    #endif
    }
#endif
    return  x;
}
#endif

#if defined(VA_POWER_SUPPORT)
    #if defined(SINGLE_PHASE)
int32_t VA_power(void)
    #else
int32_t VA_power(struct phase_parms_s *phase, struct phase_nv_parms_s const *phase_nv)
    #endif
{
    #if REACTIVE_POWER_BY_QUADRATURE_SUPPORT
    int32_t p;
    int32_t x;
    int shift;

    /* Calculate apparent (VA) power in 0.01W increments */
    p = labs(phase->power);
    x = labs(phase->reactive_power);
    /* Justify for optimal accuracy */
    shift = 0;
    while ((p & 0xFFFF8000)  ||  (x & 0xFFFF8000))
    {
        shift++;
        p >>= 1;
        x >>= 1;
    }
    x = isqrt32(p*p + x*x);
    x >>= (16 - shift);
    #else
    int16_t i;
    int32_t x;
    int32_t y;

    /* Calculate VA power in 0.01W increments */
        #if defined(SD16CCTL0_)
    x = div_sh48(phase->V_sq_accum_logged, -6, phase->sample_count_logged[0]);
        #else
    x = div_sh48(phase->V_sq_accum_logged, 2, phase->sample_count_logged[0]);
        #endif
        #if defined(LIMP_MODE_SUPPORT)
    if (operating_mode == OPERATING_MODE_LIMP)
        i = phase_nv->V_rms_limp_scale_factor;
    else
        #endif
        i = phase_nv->V_rms_scale_factor;
    x = isqrt32(x);
    x = (x >> 12)*i;
    x >>= 14;


        #if defined(SINGLE_PHASE)  &&  defined(NEUTRAL_MONITOR_SUPPORT)
    if ((phase->status & CURRENT_FROM_NEUTRAL))
    {
            #if defined(SD16CCTL0_)
        y = div48(phase->neutral.I_sq_accum_logged[0], phase->sample_count_logged[0]);
            #else
        y = div_sh48(phase->neutral.I_sq_accum_logged[0], 8, phase->sample_count_logged[0]);
            #endif
        y = isqrt32(y);
            #if defined(LIMP_MODE_SUPPORT)
        if (operating_mode == OPERATING_MODE_LIMP)
            y = (y >> 12)*nv_parms.s.neutral.I_rms_limp_scale_factor[0];
        else
            #endif
            y = (y >> 12)*nv_parms.s.neutral.I_rms_scale_factor[0];
        y >>= 14;
    }
    else
    {
        #endif
        #if defined(SD16CCTL0_)
        y = div48(phase->current.I_sq_accum_logged[0], phase->sample_count_logged[0]);
        #else
        y = div_sh48(phase->current.I_sq_accum_logged[0], 8, phase->sample_count_logged[0]);
        #endif
        y = isqrt32(y);
        #if defined(LIMP_MODE_SUPPORT)
        if (operating_mode == OPERATING_MODE_LIMP)
            y = (y >> 12)*phase_nv->current.I_rms_limp_scale_factor[0];
        else
        #endif
            y = (y >> 12)*phase_nv->current.I_rms_scale_factor[0];
        y >>= 14;
        #if defined(SINGLE_PHASE)  &&  defined(NEUTRAL_MONITOR_SUPPORT)
    }
        #endif
    x *= y;
    x /= 1000;
    #endif
    return  x;
}
#endif

#if defined(POWER_FACTOR_SUPPORT)
    #if defined(SINGLE_PHASE)
int power_factor(void)
    #else
int power_factor(struct phase_parms_s *phase, struct phase_nv_parms_s const *phase_nv)
    #endif
{
    long int p;
    long int x;

    p = labs(phase->power);
    x = labs(phase->VA_power);
    if (p  &&  x)
    {
        /* Justify for optimal accuracy */
        while ((p & 0x40000000) == 0  &&  (x & 0x40000000) == 0)
        {
            p <<= 1;
            x <<= 1;
        }
        x >>= 16;
        p /= x;
        p *= 10000;
        p >>= 16;
        /* Don't let a little imprecision cause strange answers */
        if (p > 10000)
            p = 10000;
    }
    else
    {
        p = 0;
    }
    /* Use a negative PF to indicate an inductive load */
    #if defined(SINGLE_PHASE)  &&  defined(NEUTRAL_MONITOR_SUPPORT)
    if ((phase->status & CURRENT_FROM_NEUTRAL))
    {
        if (phase->neutral.leading < 0)
            p = -p;
    }
    else
    #endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -