📄 wh.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 - Accumulation Routines.
//
// AUTHOR: RGV
//
// HISTORY: See end of file.
//**************************************************************************
// File: WH.C
//
#include "options.h"
#if WATT_ELEMENT
#include "mmath.h"
#include "meter.h"
#include "lcd.h"
#include "library.h"
#include "wh.h" // test the fn prototypes
/*** External functions referenced by this module ***/
/*** External variables referenced by this module ***/
// Refer to "ce652x.h" include file.
/*** Public variables declared within this module ***/
// None
/*** Private functions declared within this module ***/
#if VA_ELEMENT || NET_METER || AUTOCAL
void wh_sum_net (uint8x_t *s, int32p_t *w)
{
add8_4 (s, (uint8p_t *) w);
}
#endif
#if ABS_VALUE
void wh_sum_abs (uint8x_t *s, int32p_t *w)
{
if (*w < 0)
sub8_4 (s, (uint8p_t *) w);
else
add8_4 (s, (uint8p_t *) w);
}
#endif
#if IMPORT
void wh_sum_import (uint8x_t *s, int32p_t *w)
{
if (*w > 0)
add8_4 (s, (uint8p_t *) w);
}
#endif // imported power
#if EXPORT
void wh_sum_export (uint8x_t *s, int32p_t *w)
{
int32_t pdata nw;
if (*w < 0)
{
nw = - *w;
add8_4 (s, (uint8p_t *) &nw);
}
}
#endif // exported power
// Displays milliwatt hours. Milliwatt hours are absurdly small for a
// real meter, but really very good for demonstrations.
// Most meters will have to change this code in any case.
// The constants have to round -down-, so as not to cheat
// the rate-payers!
#if M6520 || TRACE11
#define WHR_SCALE 1884L // 6.6952E-12 * 2^48. (1884.53)
#elif TRACE13
#define WHR_SCALE 2647L // 9.4045E-12 * 2^48. (2647.13)
#else
#error unhandled device type
#endif
#define ONE_MILLION 1000000L
uint32_t wh_to_long (uint8x_t *val)
{
uint32_t pdata scale;
uint8_t pdata t[10];
uint8_t xdata x[13]; // Need extra digit for divide.
uint8_t xdata y[12];
// scale = [Vmax * 10E+01] * [Imax * 10E+01].
scale = (uint32_t) Vmax * (uint32_t) Imax;
// y = w * Vmax * Imax * 10E+02.
multiply_8_4 (y, val, (uint8p_t *) &scale);
// [LSB * 2^48 * 10E+01] (10E-03 Wh).
scale = WHR_SCALE;
// [x * 2^16] = [y / 2^32] * [LSB * 2^48] (mWh)..
multiply_8_4 (x + 1, y, (uint8p_t *) &scale);
//..dropped low-order 4-bytes of 'y'.
*( uint32x_t *) y = ONE_MILLION; // Modulo ONE_MILLION.
divide (x + 1, 10, (uint8x_t *) y, 4, t); // x / 1,000,000;
x[7] = 0; // Clear high order of 4-byte result.
return (* (uint32x_t *) &x[7]);
}
static void wh_mission_to_lcd (uint32_t l)
{
LCD_Number (l, 6, 3); // Display up to six digits (x % 1,000,000).
LCD_3DP (); // Three decimal places.
LCD_kWH ();
}
#if AUTOSLEEP
void wh_brownout_to_lcd (uint32_t l)
{
LCD_Number (l, 6, 3); // Display up to six digits (x % 1,000,000).
LCD_3DP (); // Three decimal places.
LCD_AutoSleep ();
LCD_kWH ();
}
#endif
void wh_lcd (uint8x_t *val)
{
wh_mission_to_lcd (wh_to_long (val));
}
#if DEMAND
// Displays mWATTs, mVARs or mVAs.
#if M6520 || TRACE11
#define WATT_SCALE (6.6952E-12 * 3600.)
#elif TRACE13
#define WATT_SCALE (9.4045E-12 * 3600.)
#else
#error unhandled device type
#endif
uint32_t w_to_long (uint32_t val)
{
return (lroundf ((float)(Vmax * Imax) * (float)(val) * WATT_SCALE));
}
static void w_mission_to_lcd (uint32_t l)
{
LCD_Number (l, 6, 3); // Display up to six digits.
LCD_3DP (); // Three decimal places.
LCD_kW ();
}
void w_lcd (uint32_t val)
{
w_mission_to_lcd (w_to_long (val));
}
#endif // DEMAND.
#ifdef EQUATION
#define PHASE_B_CALCULATED (PHASE_B_PRESENT || EQUATION == _1ELEMENT_3WIRE)
#define PHASE_C_CALCULATED (EQUATION == _2ELEMENT_4WIRE_DELTA || EQUATION == _3ELEMENT_4WIRE_WYE)
void wh_accumulate (void)
{
int32_t pdata wh0, wh1;
#if PHASE_C_CALCULATED
int32_t pdata wh2;
#endif
#if !TAMPER_RESISTANT
// no tampering
wh0 = w0sum;
wh1 = w1sum;
#if PHASE_C_CALCULATED
wh2 = w2sum;
#endif
#else
if (!MAGNETIC_TAMPER)
{
if (!NEUTRAL_DETECTED)
{
// no tampering
wh0 = w0sum;
wh1 = w1sum;
#if PHASE_C_CALCULATED
wh2 = w2sum;
#endif
}
else
{
// neutral current detected
#if M6520 || TRACE11
// 4.9e-5 is sqrt(6.6952e-13*3600)*10, from data sheet, def. Vcal
float Vnom = ((float)Vcal) / (4.90945e-5 * (float)Vmax);
#elif TRACE13
// 5.82e-5 is sqrt(9.4045e-13*3600)*10, from data sheet, def. Vcal
float Vnom = ((float)Vcal) / (5.81861e-5 * (float)Vmax);
#else
#error unknown device
#endif
#if PHASE_A_PRESENT
wh0 = Irms_A * Vnom;
#endif
#if PHASE_B_CALCULATED
wh1 = Irms_B * Vnom;
#endif
#if PHASE_C_CALCULATED
wh2 = Irms_C * Vnom;
#endif
}
}
else
{
// Magnetic tampering detected
#if M6520 || TRACE11
int32_t Whnom = (int32_t)(
((float)Vcal * (float)Ical)
/ (6.6952e-13 * (float)Vmax * (float)Imax * 3600.879)
);
#elif TRACE13
int32_t Whnom = (int32_t)(
((float)Vcal * (float)Ical)
/ (9.4045e-13 * (float)Vmax * (float)Imax * 3600.879)
);
#else
#error unknown device
#endif
wh0 = Whnom;
wh1 = Whnom;
#if PHASE_C_CALCULATED
wh2 = Whnom;
#endif
}
#if DEMAND
w0sum = wh0; // Tamper corrected values.
w1sum = wh1;
#if PHASE_C_CALCULATED
w2sum = wh2;
#endif
#endif // DEMAND.
#endif // tamper resistant
// Calculate net metering (also used in calibration)
#if NET_METER || AUTOCAL
#if PHASE_A_PRESENT
wh_sum_net (Whn_A, &wh0); // Watt hours phase A.
#endif // element A
#if PHASE_B_CALCULATED
wh_sum_net (Whn_B, &wh1); // Watt hours phase B.
#endif // element B
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -