📄 pwrfact.c
字号:
/***************************************************************************
* This code and information is provided "as is" without warranty of any *
* kind, either expressed or implied, including but not limited to the *
* implied warranties of merchantability and/or fitness for a particular *
* purpose. *
* *
* Copyright (C) 2005 Teridian Semiconductor Corp. All Rights Reserved. *
***************************************************************************/
//**************************************************************************
// DESCRIPTION: 71M652x POWER METER - Phase Angle Calculation.
//
// AUTHOR: MTF
//
// HISTORY: See end of file
//**************************************************************************
// File: PHASE_ANGLE.C
//
#include "options.h"
#if POWER_FACTOR
#include "mmath.h"
#include "library.h"
#include "lcd.h"
#include "meter.h"
#include "pwrfact.h" // test the interface against the originals
// MEASUREMENT_INTERVAL has to be the number of minutes in an interval.
// Typically it's 15 or 30. It should divide 60 evenly.
// for a 15-minute measurement interval
// If it's undefined, the code calculates instantaneous pwoer factor.
// #define MEASUREMENT_INTERVAL 15
#ifdef MEASUREMENT_INTERVAL
int8_t xdata Last_Meas_Min; // minute at which the last measurement occurred
#endif
#define PHASE_B_CALCULATED (PHASE_B_PRESENT || EQUATION == _1ELEMENT_3WIRE)
// External functions used by this module.
// See include files.
static void Display_Power_Factor (int16_t d);
void power_factor_lcd (uint8_t select_phase)
{
int16_t d;
switch (select_phase)
{
case 0: // fall through
#if PHASE_A_PRESENT
case 1: d = Pf_A; break;
#endif
#if PHASE_B_CALCULATED
case 2: d = Pf_B; break;
#endif
#if PHASE_C_PRESENT
case 3: d = Pf_C; break;
#endif
default: d = 0; break;
}
Display_Power_Factor (d);
}
static void Display_Power_Factor (int16_t d)
{
LCD_Number ((int32_t)d, 6, 3); // meter up to four digits (rounded).
LCD_3DP (); // Three (3) Decimal Points.
}
#ifdef MEASUREMENT_INTERVAL
SUM_t WhLAST_A;
SUM_t WhLAST_B;
SUM_t WhLAST_C;
SUM_t VAhLAST_A;
SUM_t VAhLAST_B;
SUM_t VAhLAST_C;
// calculate the power factor by intervals.
static int16_t pf_by_interval(
uint8x_t *pwh,
uint8x_t *pvah,
uint8x_t *pwhlast,
uint8x_t *pvahlast
)
{
SUM_t xdata diffX; // the difference register, in xdata
SUM_t pdata subP; // the subtrahend register, in pdata
float wh, vah; // delta watt-hours and va-hours for the interval
// Floating point underflow is not an issue with this design,
// because it uses 64 bit arithmetic to subtract, finding the
// change of register contents. After that, the math is division
// and multiplication- no underflow is possible, so it's done in
// floating point.
// get the difference in watt hours since the last run
memcpy_xx ( (uint8x_t*) &diffX, pwh, 8 );
memcpy_px ( (uint8p_t*) &subP, pwhlast, 8 );
memcpy_xx ( pwhlast, pwh, 8 ); // set for next interval
// 64 bit subtract, finds delta watt-hours without underflow
sub8_8 ( (uint8x_t *) &diffX, (uint8p_t *)&subP );
wh = s2f ( (uint8x_t *) &diffX ); // convert to floating point
// get the difference in VAR hours since the last run
memcpy_xx ( (uint8x_t*) &diffX, pvah, 8);
memcpy_px ( (uint8p_t*) &subP, pvahlast, 8);
memcpy_xx ( pvahlast, pvah, 8 ); // set for next interval
// 64 bit subtract, finds delta va-hours without underflow
sub8_8 ( (uint8x_t *) &diffX, (uint8p_t *)&subP );
vah = s2f ( (uint8x_t *) &diffX ); // convert to floating point
// calculate the power factor for the interval. LSB = 0.001%
return (int16_t)( lroundf ( 1000. * ( wh / vah )));
}
#endif
// computes the instantaneous or interval power factors, LSB = 0.001%
void Compute_Power_Factor (void)
{
// MEASUREMENT_INTERVAL has to be the number of minutes in an interval.
// Typically it's 15 or 30. It should divide 60 evenly.
#ifndef MEASUREMENT_INTERVAL
// Just calculate the instantaneous power factor,
// which is useful for installation.
if((Irms_A < VThrshld) || ((SAGA | CREEP) & Status))
Pf_A = 0;
else
Pf_A = (int16_t)lroundf(1000. * ((float)w0sum/(float)va0sum));
if((Irms_B < VThrshld) || ((SAGB | CREEP) & Status))
Pf_B = 0;
else
Pf_B = (int16_t)lroundf(1000. * ((float)w1sum/(float)va1sum));
#if PHASE_C_PRESENT
if((Irms_C < VThrshld) || ((SAGC | CREEP) & Status))
Pf_C = 0;
else
Pf_C = (int16_t)lroundf(1000. * ((float)w2sum/(float)va2sum));
#endif
#else
#if !VA_ELEMENT
#error power factor requires a calculation of Volt-Amperes
#endif
// Calculate the power factor once per interval for each element.
if (Rtc_Min % MEASUREMENT_INTERVAL == 0 && Rtc_Min != Last_Meas_Min)
{
Last_Meas_Min = Rtc_Min;
#if PHASE_A_PRESENT
Pf_A = pf_by_interval (
(uint8x_t *)&Wh_A,
(uint8x_t *)&WhLAST_A,
(uint8x_t *)&VAh_A,
(uint8x_t *)&VAhLAST_A);
#endif
#if PHASE_B_CALCULATED
Pf_B = pf_by_interval (
(uint8x_t *)&Wh_B,
(uint8x_t *)&WhLAST_B,
(uint8x_t *)&VAh_B,
(uint8x_t *)&VAhLAST_B);
#endif
#if PHASE_C_PRESENT
Pf_C = pf_by_interval (
(uint8x_t *)&Wh_C,
(uint8x_t *)&WhLAST_C,
(uint8x_t *)&VAh_C,
(uint8x_t *)&VAhLAST_C);
#endif
// this would be the place to record the maximum power factor,
// or save the value in some other way.
}
#endif
}
#endif
/***************************************************************************
* History:
* $Log: pwrfact.c,v $
* Revision 1.6 2006/10/11 20:46:48 tvander
* Fixed phase B accumulation and measurement for equation 1.
* Phase B is not part of the equation, but is very useful for calibration.
*
* Revision 1.5 2006/09/29 08:58:06 tvander
* Power factor display ought to be smaller.
*
* Revision 1.4 2006/09/12 02:45:09 gmikef
* *** empty log message ***
*
* Revision 1.3 2006/06/14 02:46:38 tvander
* Faster LCD display.
*
* Revision 1.2 2006/05/25 03:31:46 tvander
* Renamed variables so nonvolatile variables can be switched to other definitions
* of watt-hours (e.g. from absolute value to volt-amps or imports)
* (meter.c, meter.h, pulse_src.c)
* FIxed power factors so they zero correctly.
* Fixed RMS to work with different accumulation interval.
*
* Revision 1.1 2006/05/17 19:07:59 tvander
* Battery test works.
* Power factor works for instantaneous value. Periodic value compiles, but is
* untested.
*
*
* Copyright (C) 2006 Teridian Semiconductor Corp. All Rights Reserved. *
* this program is fully protected by the United States copyright *
* laws and is the property of Teridian Semiconductor Corporation. *
***************************************************************************/
/* pwrfact.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -