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

📄 emeter-background.c

📁 msp430F437三相电表DEMO(编译器 IAR 3.42A)
💻 C
📖 第 1 页 / 共 4 页
字号:
                      + phase->V_history[(phase->V_history_index - phase->current.in_phase_phase_correction_step[use_stage]) & V_HISTORY_MASK];
    #else
            corrected = phase->V_history[(phase->V_history_index - phase->current.in_phase_phase_correction_step[use_stage]) & V_HISTORY_MASK];
    #endif
#else
            corrected = V_sample;
#endif
            accum48(phase->current.P_accum[use_stage], imul16(corrected, I_live_sample));
#if defined(REACTIVE_POWER_BY_QUADRATURE_SUPPORT)
            corrected = (Q1_15_mul(phase->V_history[(phase->V_history_index - phase->current.quadrature_phase_correction_step - 1) & V_HISTORY_MASK], phase->current.quadrature_fir_beta) >> 1)
                      + (phase->V_history[(phase->V_history_index - phase->current.quadrature_phase_correction_step) & V_HISTORY_MASK] >> 1);
            accum48(phase->current.P_reactive_accum[use_stage], imul16(corrected, I_live_sample));
#endif
        }
        ++phase->current.sample_count;

#if defined(SINGLE_PHASE)  &&  defined(NEUTRAL_MONITOR_SUPPORT)
        I_neutral_sample = phase->neutral.I_history[0][0];
        phase->neutral.I_history[0][0] = phase->neutral.I_history[0][1];
        corrected = adc_buffer[++adc_ptr];
        if ((corrected >= ADC_MAX  ||  corrected <= ADC_MIN)  &&  phase->neutral.I_endstops)
            phase->neutral.I_endstops--;
    #if defined(__MSP430_HAS_SD16_3__)
        phase->neutral.I_history[0][1] = corrected;
    #else
        //phase->neutral.I_history[0][1] = corrected - adc_buffer[++adc_ptr];
        phase->neutral.I_history0[0][1] = corrected;
    #endif
        I_neutral_sample = dc_filter(&phase->neutral.I_dc_estimate, I_neutral_sample);
    #if defined(IRMS_SUPPORT)  ||  defined(POWER_FACTOR_SUPPORT)
        accum48(phase->neutral.I_sq_accum[0], imul16(I_neutral_sample, I_neutral_sample));
    #endif
        if (operating_mode == OPERATING_MODE_NORMAL)
        {
    #if defined(PHASE_CORRECTION_SUPPORT)
        #if defined(__MSP430_HAS_ADC12__)  ||  defined(__MSP430_HAS_ADC10__)
            corrected = Q1_15_mulq(phase->V_history[(phase->V_history_index - phase->neutral.in_phase_phase_correction_step - 1) & V_HISTORY_MASK], phase->neutral.in_phase_fir_beta)
                      + phase->V_history[(phase->V_history_index - phase->neutral.in_phase_phase_correction_step) & V_HISTORY_MASK];
        #else
            corrected = phase->V_history[(phase->V_history_index - phase->neutral.in_phase_phase_correction_step) & V_HISTORY_MASK];
        #endif
    #else
            corrected = V_sample;
    #endif
            accum48(phase->neutral.P_accum[0], imul16(corrected, I_neutral_sample));
    #if defined(REACTIVE_POWER_BY_QUADRATURE_SUPPORT)
            corrected = (Q1_15_mulq(phase->V_history[(phase->V_history_index - phase->neutral.quadrature_phase_correction_step - 1) & V_HISTORY_MASK], phase->neutral.quadrature_fir_beta) >> 1)
                      + (phase->V_history[(phase->V_history_index - phase->neutral.quadrature_phase_correction_step) & V_HISTORY_MASK] >> 1);
            accum48(phase->neutral.P_reactive_accum[0], imul16(corrected, I_neutral_sample));
    #endif
        }
        ++phase->neutral.sample_count[0];
#endif
#if defined(REACTIVE_POWER_BY_QUADRATURE_SUPPORT)  ||  defined(PHASE_CORRECTION_SUPPORT)
        phase->V_history_index = (phase->V_history_index + 1) & V_HISTORY_MASK;
#endif
        ++phase->sample_count;

#if defined(PER_PHASE_ENERGY_SUPPORT)
        /* We now play the last measurement interval's power level, evaluated
           in the foreground, through this measurement interval. In this way
           we can evenly pace the pulsing of the LED. The only error produced
           by this is the ambiguity in the number of samples per measurement.
           This should not exceed 1 or 2 in over 4000. */
    #if defined(LIMP_MODE_SUPPORT)
        if (operating_mode == OPERATING_MODE_NORMAL)
        {
    #endif
    #if defined(INHIBIT_NEGATIVE_PHASE_POWER_ACCUMULATION)
            if (phase->power > 0  &&  (phase->power_counter += phase->power) >= PHASE_ENERGY_PULSE_THRESHOLD)
    #else
            if ((phase->power_counter += phase->power) >= PHASE_ENERGY_PULSE_THRESHOLD)
    #endif
            {
                phase->power_counter -= PHASE_ENERGY_PULSE_THRESHOLD;
                ++phase->consumed_energy;
                /* Ideally we want to log the energy each kWh unit, but doing
                   it with a mask here is good enough and faster. */
                if ((phase->consumed_energy & 0x3FF) == 0)
                    phase->status |= ENERGY_LOGABLE;
                /* Pulse the LED. Long pulses may not be reliable, as at full
                   power we may be pulsing several times per second. People may
                   check the meter's calibration with an instrument that counts
                   the pulsing rate, so it is important the pulses are clear,
                   distinct, and exactly at the rate of one per
                   1/ENERGY_PULSES_PER_KW_HOUR kW/h. */
    #if !defined(SINGLE_PHASE)
                switch (j)
                {
                case 0:
                    set_phase_1_energy_pulse_indicator();
                    break;
                case 1:
                    set_phase_2_energy_pulse_indicator();
                    break;
                case 2:
                    set_phase_3_energy_pulse_indicator();
                    break;
                }
    #else
                set_energy_pulse_indicator();
    #endif
                phase->energy_pulse_remaining_time = ENERGY_PULSE_DURATION;
            }
            if (phase->energy_pulse_remaining_time  &&  --phase->energy_pulse_remaining_time == 0)
            {
    #if !defined(SINGLE_PHASE)
                switch (j)
                {
                case 0:
                    clr_phase_1_energy_pulse_indicator();
                    break;
                case 1:
                    clr_phase_2_energy_pulse_indicator();
                    break;
                case 2:
                    clr_phase_3_energy_pulse_indicator();
                    break;
                }
    #else
                clr_energy_pulse_indicator();
    #endif
            }
    #if defined(LIMP_MODE_SUPPORT)
        }
        else
        {
            if ((phase->power_counter += LIMP_SAMPLING_RATIO*phase->power) >= PHASE_ENERGY_PULSE_THRESHOLD)
            {
                phase->power_counter -= PHASE_ENERGY_PULSE_THRESHOLD;
                ++phase->consumed_energy;
                if ((phase->consumed_energy & 0x3FF) == 0)
                    phase->status |= ENERGY_LOGABLE;
        #if !defined(SINGLE_PHASE)
                switch (j)
                {
                case 0:
                    set_phase_1_energy_pulse_indicator();
                    break;
                case 1:
                    set_phase_2_energy_pulse_indicator();
                    break;
                case 2:
                    set_phase_3_energy_pulse_indicator();
                    break;
                }
        #else
                set_energy_pulse_indicator();
        #endif
                phase->energy_pulse_remaining_time = ENERGY_PULSE_DURATION;
            }
            if (phase->energy_pulse_remaining_time  &&  (phase->energy_pulse_remaining_time -= LIMP_SAMPLING_RATIO) == 0)
            {
        #if !defined(SINGLE_PHASE)
                switch (j)
                {
                case 0:
                    clr_phase_1_energy_pulse_indicator();
                    break;
                case 1:
                    clr_phase_2_energy_pulse_indicator();
                    break;
                case 2:
                    clr_phase_3_energy_pulse_indicator();
                    break;
                }
        #else
                clr_energy_pulse_indicator();
        #endif
            }
        }
    #endif
#endif
        /* Do the power cycle start detection */
        /* There is no hysteresis used here, but since the signal is
           changing rapidly at the zero crossings, and is always of
           large amplitude, miscounting cycles due to general noise
           should not occur. Spikes are another matter. A large spike
           could cause the power cycles to be miscounted, but does not
           matter very much. The cycle counting is not critical to power
           or energy measurement. */
#if defined(MAINS_FREQUENCY_SUPPORT)
    #if defined(LIMP_MODE_SUPPORT)
        if (operating_mode == OPERATING_MODE_LIMP)
            phase->cycle_sample_count += LIMP_SAMPLING_RATIO*256;
        else
    #endif
            phase->cycle_sample_count += 256;
#endif
        if (abs(V_sample - phase->last_V_sample) <= phase->since_last*4000)
        {
            /* This doesn't look like a spike - do mains cycle detection, and
               estimate the precise mains period */
            if (V_sample < 0)
            {
                /* Log the sign of the signal */
                phase->status &= ~V_POS;
                phase->since_last = 0;
                phase->last_V_sample = V_sample;
            }
            else
            {
                if (!(phase->status & V_POS))
                {
#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->cycle_sample_count  &&  phase->cycle_sample_count <= 256*SAMPLES_PER_10_SECONDS/400)
                    {
                        /* A mains frequency measurement procedure based on interpolating zero crossings,
                           to get a fast update rate for step changes in the mains frequency */
                        /* Interpolate the zero crossing by successive approx. */
                        z = V_sample - phase->last_V_sample;
                        x = 0;
                        y = 0;
                        for (k = 0;  k < 8;  k++)
                        {
                            y <<= 1;
                            z >>= 1;
                            x += z;
                            if (x > V_sample)
                                x -= z;
                            else
                                y |= 1;
                        }
                        /* Now we need to allow for skipped samples, due to spike detection */
                        z = y;
                        while (phase->since_last > 1)
                        {
                            z += y;
                            phase->since_last--;
                        }
                        /* z is now the fraction of a sample interval between the zero
                           crossing and the current sample, in units of 1/256 of a sample */
                        /* A lightly damped filter should now be enough to remove noise and get a
                           stable value for the frequency */
                        phase->mains_period += ((int32_t) (phase->cycle_sample_count - z) << 12) - (phase->mains_period >> 4);
                        /* Start the next cycle with the residual fraction of a sample */
                        phase->cycle_sample_count = z;
                    }
                    else
                    {
                        phase->cycle_sample_count = 0;
                    }
#endif
                }
                /* Log the sign of the signal */
                phase->status |= V_POS;
                phase->since_last = 0;
                phase->last_V_sample = V_sample;

#if defined(POWER_FACTOR_SUPPORT)
                /* Determine whether the current leads or lags, in a noise tolerant manner.
                   Testing 50 cycles means we will respond in about one second to a genuine
                   swap between lead and lag. Since that is also about the length of our
                   measurement blocks, this seems a sensible response time. */
                if (I_live_sample < V_sample)
                {
                    if (phase->current.leading > -50)
                        phase->current.leading--;
                }
                else
                {
                    if (phase->current.leading < 50)
                        phase->current.leading++;
                }
    #if defined(SINGLE_PHASE)  &&  defined(NEUTRAL_MONITOR_SUPPORT)
                if (I_neutral_sample < V_sample)
                {
                    if (phase->neutral.leading > -50)
                        phase->neutral.leading--;
                }
                else
                {
                    if (phase->neutral.leading < 50)
                        phase->neutral.leading++;
                }
    #endif
#endif
                /* 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->sample_count >= samples_per_second)
                {
#if defined(SINGLE_PHASE)
                    log_parameters();
#else
                    log_parameters(phase);
#endif
#if defined(__MSP430__)
                    /* The foreground may be conserving power (e.g. in limp mode), so we
                       need to kick it. */
                    _BIC_SR_IRQ(LPM0_bits);
#else
                    /* When run as a host program there is no RTC, but we still need to
                       kick the foreground somehow. */
                    meter_status |= TICKER;
#endif
                }
            }
        }
        phase->since_last++;

        if (phase->sample_count >= samples_per_second + 200)
        {
            /* We don't seem to be detecting the end of a mains cycle, so force
               the end of processing block condition. */
#if defined(SINGLE_PHASE)
            log_parameters();
#else
            log_parameters(phase);
#endif
#if defined(__MSP430__)
            /* The foreground may be conserving power (e.g. in limp mode), so we
               need to kick it. */
            _BIC_SR_IRQ(LPM0_bits);
#else
            /* When run as a host program there is no RTC, but we still need to
               kick the foreground somehow. */
            meter_status |= TICKER;
#endif
        }
#if defined(MAINS_FREQUENCY_SUPPORT)
        /* Monitor the cycles and frequency of the current sensors, as limp
           mode is based on these. */
    #if defined(LIMP_MODE_SUPPORT)
        if (operating_mode == OPERATING_MODE_LIMP)
            phase->current.cycle_sample_count += 256*LIMP_SAMPLING_RATIO;
        else
    #endif
            phase->current.cycle_sample_count += 256;
#endif
        if (I_live_sample < 0)
        {
            /* Log the sign of the signal */
            phase->status &= ~I_POS;
        }
        else
        {
            if (!(phase->status & I_POS))
            {
                /* A negative to positive transition has occurred. Trust it
                   blindly as a genuine zero crossing/start of cycle, even
                   though it might really be due to a noise spike. */
#if defined(MAINS_FREQUENCY_SUPPORT)
                if (SAMPLES_PER_10_SECONDS/700 <= phase->current.cycle_sample_count  &&  phase->current.cycle_sample_count <= SAMPLES_PER_10_SECONDS/400)
                    phase->current.mains_period += ((int32_t) phase->current.cycle_sample_count << 16) - (phase->current.mains_period >> 8);
                phase->current.cycle_sample_count = 0;
#endif
            }
            /* Log the sign of the signal */
            phase->status |= I_POS;
        }
#if defined(SINGLE_PHASE)  &&  defined(NEUTRAL_MONITOR_SUPPORT)
    #if defined(MAINS_FREQUENCY_SUPPORT)
        #if defined(LIMP_MODE_SUPPORT)
        if (operating_mode == OPERATING_MODE_LIMP)
            phase->neutral.cycle_sample_count += LIMP_SAMPLING_RATIO;
        else
        #endif
            phase->neutral.cycle_sample_count++;
    #endif
        if (I_neutral_sample < 0)
        {
            /* Log the sign of the signal */
            phase->status &= ~I_NEUTRAL_POS;
        }
        else
        {
            if (!(phase->status & I_NEUTRAL_POS))
            {
                /* A negative to positive transition has occurred. Trust it
                   blindly as a genuine zero crossing/start of cycle, even
                   though it might really be due to a noise spike. */
    #if defined(MAINS_FREQUENCY_SUPPORT)
                if (SAMPLES_PER_10_SECONDS/700 <= phase->neutral.cycle_sample_count  &&  phase->neutral.cycle_sample_count <= SAMPLES_PER_10_SECONDS/400)
                    phase->neutral.mains_period += ((int32_t) phase->neutral.cycle_sample_count << 16) - (phase->neutral.mains_period >> 8);
                phase->neutral.cycle_sample_count = 0;
    #endif
            }
            /* Log the sign of the signal */

⌨️ 快捷键说明

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