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

📄 pwrfact.c

📁 TDK 6521 SOC 芯片 DEMO程序
💻 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 + -