📄 emeter-background.c
字号:
{ 129, 2038, 1961, 1810},
{ 129, 2038, 1961, 1809},
{ 129, 2038, 1960, 1808},
{ 128, 2038, 1960, 1807},
{ 128, 2038, 1960, 1806},
{ 128, 2038, 1959, 1805},
{ 128, 2038, 1959, 1804},
{ 127, 2038, 1959, 1803},
{ 127, 2038, 1958, 1802},
{ 127, 2038, 1958, 1802},
{ 127, 2038, 1958, 1801},
{ 126, 2038, 1957, 1800},
{ 126, 2038, 1957, 1799},
{ 126, 2038, 1957, 1798},
{ 126, 2038, 1956, 1797},
{ 125, 2038, 1956, 1796},
{ 125, 2038, 1956, 1795},
{ 125, 2038, 1955, 1794},
};
void goertzel_init(goertzel_state_t *s)
{
s->v2 =
s->v3 = 0;
}
void goertzel_update(goertzel_state_t *s, int16_t x, int16_t fac)
{
int32_t v1;
v1 = s->v2;
s->v2 = s->v3;
s->v3 = ((fac*s->v2) >> 10) - v1 + x;
}
int32_t goertzel_result(goertzel_state_t *s, int16_t fac)
{
int32_t v1;
int32_t v2;
int32_t v3;
/* Push a zero through the process to finish things off. */
v1 = s->v2;
s->v2 = s->v3;
s->v3 = ((fac*s->v2) >> 10) - v1;
/* Now calculate the non-recursive side of the filter. */
/* The result here is not scaled down to allow for the magnification
effect of the filter (the usual DFT magnification effect). */
v2 = s->v2 >> 5;
v3 = s->v3 >> 5;
return v3*v3 + v2*v2 - ((v2*v3) >> 10)*fac;
}
#if defined(SINGLE_PHASE)
static __inline__ void init_harmonics()
#else
static __inline__ void init_harmonics(struct phase_parms_s *phase)
#endif
{
goertzel_init(&(phase->current.harm_1));
goertzel_init(&(phase->current.harm_3));
goertzel_init(&(phase->current.harm_5));
phase->current.harmonic_step = phase->frequency/10 - 475;
phase->current.harmonic_samples = harm_factors[phase->current.harmonic_step][0];
}
#if defined(SINGLE_PHASE)
static __inline__ void harmonics(int16_t iamp)
#else
static __inline__ void harmonics(struct phase_parms_s *phase, int16_t iamp)
#endif
{
int step;
step = phase->current.harmonic_step;
goertzel_update(&(phase->current.harm_1), iamp, harm_factors[step][1]);
goertzel_update(&(phase->current.harm_3), iamp, harm_factors[step][2]);
goertzel_update(&(phase->current.harm_5), iamp, harm_factors[step][3]);
if (--phase->current.harmonic_samples <= 0)
{
phase->current.pow_1 = goertzel_result(&(phase->current.harm_1), harm_factors[step][1]);
phase->current.pow_3 = goertzel_result(&(phase->current.harm_3), harm_factors[step][2]);
phase->current.pow_5 = goertzel_result(&(phase->current.harm_5), harm_factors[step][3]);
#if defined(SINGLE_PHASE)
init_harmonics();
#else
init_harmonics(phase);
#endif
}
}
#endif
int16_t fred;
int16_t fred2;
/*---------------------------------------------------------------------------
This is the main interrupt routine where the main signal processing is done
---------------------------------------------------------------------------*/
#if defined(__MSP430__)
#if defined(__MSP430_HAS_SD16_3__)
ISR(SD16, adc_interrupt)
#endif
#if defined(__MSP430_HAS_ADC12__)
ISR(TIMERA0, adc_interrupt)
#endif
#else
void adc_interrupt(void)
#endif
{
#if defined(PWM_DITHERING_SUPPORT)
extern uint16_t rndnum;
#endif
int16_t V_sample;
int16_t corrected;
int16_t I_live_sample;
#if defined(SINGLE_PHASE) && defined(NEUTRAL_MONITOR_SUPPORT)
int16_t I_neutral_sample;
#endif
#if GAIN_STAGES > 1
int16_t use_stage;
#else
#define i 0
#endif
#if !defined(SINGLE_PHASE)
struct phase_parms_s *phase;
int j;
#endif
#if defined(__MSP430_HAS_ADC12__)
#if !defined(SINGLE_PHASE)
int16_t adc_buffer[10];
#else
int16_t adc_buffer[5];
#endif
int adc_ptr;
#endif
#if defined(__MSP430_HAS_SD16_3__)
static int16_t adc_buffer[3];
int adc_ptr;
#endif
#if !defined(__MSP430__)
int16_t adc_buffer[15];
int adc_ptr;
#endif
#if defined(FINE_ENERGY_PULSE_TIMING_SUPPORT)
int32_t xxx;
#endif
#if defined(MAINS_FREQUENCY_SUPPORT)
int k;
int x;
int y;
int z;
#endif
/**/ P3OUT &= ~0x04;
#if defined(__MSP430_HAS_SD16_3__)
if (!(SD16CCTL_VOLTAGE & SD16IFG))
{
/* We do not have a complete set of samples yet, but we may need to pick
up some current values at this time */
#if defined(SINGLE_PHASE) && defined(NEUTRAL_MONITOR_SUPPORT)
if ((SD16CCTL_NEUTRAL & SD16IFG))
{
adc_buffer[2] = SD16MEM_NEUTRAL;
SD16CCTL_NEUTRAL &= ~SD16IFG;
}
#endif
if ((SD16CCTL_LIVE & SD16IFG))
{
adc_buffer[1] = SD16MEM_LIVE;
SD16CCTL_LIVE &= ~SD16IFG;
}
return;
}
#endif
#if defined(FINE_ENERGY_PULSE_TIMING_SUPPORT)
/* Trigger the energy pulse, timed by timer A */
/* This needs to be at the start of the interrupt service routine so its timing is well defined in
relation to the counting of timer A */
if (fine_pulse_operation)
{
/* This early in the interrupt routine timer A's counter should still be at zero. If we request
a target compare match count of zero while the count is already zero, the output will change
immediately. Counts of 0 to 9 should, therefore, hit somewhere through the current ADC interrupt
period. A match of zero will not be as well timed as the others, as we will have missed the exact
moment when it should begin, but it is good enough. */
TACCTL2 = fine_pulse_operation;
fine_pulse_operation = 0;
}
#endif
/* Filter away the DC bias.
Do the phase lag compensation. Use a simple FIR approach,
and absorb the non-unity gain of the filter in the overall
current/power scaling later on. This is OK for the small
phase shifts we expect to get. It would cause dynamic
range problems for larger shifts. Note the some of this
phase shift is due to the operation of the ADC itself. It
performs sequential conversions of its 8 inputs, so there is
some time delay between sampling of the various sensors.
Accumulate power for each of the channels. These will
be divided by the number of samples at the end of the
measurement cycles, resulting in an average power
value for each source.
If RMS voltage and/or current readings are required, calculate the
dot products needed to evaluate these. */
#if defined(__MSP430_HAS_ADC12__)
//P2SEL &= ~BIT4;
//P2OUT |= BIT4;
ADC12CTL0 &= ~ENC;
if (operating_mode == OPERATING_MODE_NORMAL)
{
/* Start a new ADC scan sequence when Timer_B0 next triggers. */
ADC12CTL0 |= ENC;
}
else
{
ADC12CTL0 &= ~ADC12ON;
}
#if !defined(SINGLE_PHASE)
/* Grab the data quickly, in case it gets overwritten later in
this long interrupt routine. */
adc_buffer[0] = ADC12MEM[2]; //V1
adc_buffer[1] = ADC12MEM[0]; //L1
adc_buffer[2] = ADC12MEM[1]; //H1
adc_buffer[3] = ADC12MEM[5]; //V2
adc_buffer[4] = ADC12MEM[3]; //L2
adc_buffer[5] = ADC12MEM[4]; //H2
adc_buffer[6] = ADC12MEM[8]; //V3
adc_buffer[7] = ADC12MEM[6]; //L3
adc_buffer[8] = ADC12MEM[7]; //H3
#if defined(NEUTRAL_CURRENT_INPUT)
adc_buffer[9] = ADC12MEM[9]; //N
#if defined(TEMPERATURE_SUPPORT)
if (operating_mode == OPERATING_MODE_NORMAL)
temperature = temperature - (temperature >> 3) + ADC12MEM[10];
#endif
#else
#if defined(TEMPERATURE_SUPPORT)
if (operating_mode == OPERATING_MODE_NORMAL)
temperature = temperature - (temperature >> 3) + ADC12MEM[9];
#endif
#endif
#if 0
instant_Vcc = ADC12MEM[11];
instant_VeREF_plus = ADC12MEM[12];
instant_VeREF_minus = ADC12MEM[13];
#endif
#else
/* Grab the data quickly, in case it gets overwritten later in
this long interrupt routine. */
adc_buffer[0] = ADC12MEM[5]; //V
adc_buffer[1] = ADC12MEM[3]; //L
adc_buffer[2] = ADC12MEM[2]; //A(L)
adc_buffer[3] = ADC12MEM[1]; //N
adc_buffer[4] = ADC12MEM[0]; //A(N)
#if defined(BATTERY_MONITOR_SUPPORT)
if (battery_countdown)
{
if (--battery_countdown == 0)
{
if (ADC12MEM[6] > 0x800)
meter_status |= STATUS_BATTERY_OK;
else
meter_status &= ~(STATUS_BATTERY_OK);
/* Battery sensing control pin */
P3DIR &= ~(BIT1);
P3OUT |= (BIT1);
}
}
#endif
#if defined(TEMPERATURE_SUPPORT)
if (operating_mode == OPERATING_MODE_NORMAL)
temperature = temperature - (temperature >> 3) + ADC12MEM[7];
#endif
#endif
adc_ptr = -1;
#endif
#if defined(__MSP430_HAS_SD16_3__)
/* Voltage is available */
adc_buffer[0] = SD16MEM_VOLTAGE;
SD16CCTL_VOLTAGE &= ~SD16IFG;
/* Pick up any current samples which may have occurred a little before the
voltage sample, but not those which may have occurred just after the
voltage sample. */
#if defined(SINGLE_PHASE) && defined(NEUTRAL_MONITOR_SUPPORT)
if (phase->neutral.sd16_preloaded_offset < 128 && (SD16CCTL_NEUTRAL & SD16IFG))
{
adc_buffer[2] = SD16MEM_NEUTRAL;
SD16CCTL_NEUTRAL &= ~SD16IFG;
}
#endif
if (phase->current.sd16_preloaded_offset < 128 && (SD16CCTL_LIVE & SD16IFG))
{
adc_buffer[1] = SD16MEM_LIVE;
SD16CCTL_LIVE &= ~SD16IFG;
}
/* We have a complete set of samples. Process them. */
adc_ptr = -1;
#endif
#if !defined(__MSP430__)
get_sample(adc_buffer);
adc_ptr = -1;
#endif
kick_watchdog();
#if defined(__MSP430_HAS_ADC12__)
tpd_gen();
#endif
#if !defined(SINGLE_PHASE)
phase = chan;
for (j = 0; j < 3/*NUM_PHASES*/; j++)
{
#endif
V_sample = adc_buffer[++adc_ptr];
if ((V_sample >= ADC_MAX || V_sample <= ADC_MIN) && phase->V_endstops)
phase->V_endstops--;
#if defined(LIMP_MODE_SUPPORT)
V_sample = dc_filter(&phase->V_dc_estimate[(operating_mode == OPERATING_MODE_NORMAL) ? 0 : 1], V_sample);
#else
V_sample = dc_filter(&phase->V_dc_estimate, V_sample);
#endif
#if defined(VRMS_SUPPORT) || defined(POWER_FACTOR_SUPPORT)
accum48(phase->V_sq_accum, imul16(V_sample, V_sample));
#endif
#if defined(REACTIVE_POWER_BY_QUADRATURE_SUPPORT) || defined(PHASE_CORRECTION_SUPPORT)
/* We need to save the history of the voltage signal if we are performing phase correction, and/or
measuring the quadrature shifted power (to obtain an accurate measure of one form of the reactive power). */
phase->V_history[(int) phase->V_history_index] = V_sample;
#endif
I_live_sample = -dc_filter(&phase->current.I_dc_estimate[0], phase->current.I_history[0][0]);
phase->current.I_history[0][0] = phase->current.I_history[0][1];
corrected = adc_buffer[++adc_ptr];
#if GAIN_STAGES > 1
if ((corrected >= ADC_MAX || corrected <= ADC_MIN))
{
phase->current.stage_hits = 100;
phase->current.stage_in_use = 1;
}
else
{
if (phase->current.stage_hits)
{
if (--phase->current.stage_hits == 0)
phase->current.stage_in_use = 0;
}
}
use_stage = phase->current.stage_in_use;
#else
if ((corrected >= ADC_MAX || corrected <= ADC_MIN) && phase->current.I_endstops)
phase->current.I_endstops--;
#endif
#if defined(__MSP430_HAS_SD16_3__)
phase->current.I_history[0][1] = corrected;
#else
//phase->current.I_history[0][1] = corrected - adc_buffer[++adc_ptr];
phase->current.I_history[0][1] = corrected;
#endif
#if GAIN_STAGES > 1
corrected = dc_filter(&phase->current.I_dc_estimate[1], phase->current.I_history[1][0]);
if (use_stage)
I_live_sample = corrected;
phase->current.I_history[1][0] = phase->current.I_history[1][1];
corrected = adc_buffer[++adc_ptr];
if ((corrected >= ADC_MAX || corrected <= ADC_MIN) && phase->current.I_endstops)
phase->current.I_endstops--;
phase->current.I_history[1][1] = corrected;
#endif
#if defined(IRMS_SUPPORT) || defined(POWER_FACTOR_SUPPORT)
accum48(phase->current.I_sq_accum[use_stage], imul16(I_live_sample, I_live_sample));
#endif
if (operating_mode == OPERATING_MODE_NORMAL)
{
/* Perform phase shift compensation, to allow for the time
between ADC samplings, internal phase shifts in CTs, etc.
This uses a 1 tap FIR (basically an interpolator/extrapolator) */
#if defined(PHASE_CORRECTION_SUPPORT)
#if defined(__MSP430_HAS_ADC12__) || defined(__MSP430_HAS_ADC10__)
corrected = Q1_15_mul(phase->V_history[(phase->V_history_index - phase->current.in_phase_phase_correction_step[use_stage] - 1) & V_HISTORY_MASK], phase->current.in_phase_fir_beta[use_stage])
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -