242 lines
8.4 KiB
C
242 lines
8.4 KiB
C
|
|
/* hlw8032.c - HLW8032 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>оƬ<D0BE><C6AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>UART5 ֻ<>գ<EFBFBD>4800 8E1<45><31>
|
|||
|
|
*
|
|||
|
|
* ֡<EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD>24 <EFBFBD>ֽڣ<EFBFBD>ÿ 50ms һ֡<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
* [0] ״̬<EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD> State REG 0x55=<EFBFBD><EFBFBD><EFBFBD><EFBFBD> / 0xAA=<EFBFBD><EFBFBD>ʧЧ / 0xFx=<EFBFBD>мĴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
* [1] <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD> Check REG <EFBFBD>̶<EFBFBD> 0x5A
|
|||
|
|
* [2:5] <EFBFBD><EFBFBD>ѹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD>鲻<EFBFBD>ã<EFBFBD>
|
|||
|
|
* [5:8] <EFBFBD><EFBFBD>ѹ<EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD>
|
|||
|
|
* [8:11] <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD>
|
|||
|
|
* [11:14]<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD>
|
|||
|
|
* [14:17]<EFBFBD><EFBFBD><EFBFBD>ʲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD> PowerPar оƬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD>
|
|||
|
|
* [17:20]<EFBFBD><EFBFBD><EFBFBD>ʼĴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD>
|
|||
|
|
* [20] <EFBFBD><EFBFBD><EFBFBD>ݸ<EFBFBD><EFBFBD>¼Ĵ<EFBFBD><EFBFBD><EFBFBD> bit7 = PF <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><EFBFBD>־
|
|||
|
|
* [21:23]PF <EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD> 16bit <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬʱ bit7 <EFBFBD><EFBFBD>ת
|
|||
|
|
* [23] У<EFBFBD><EFBFBD><EFBFBD><EFBFBD> [2]~[22] <EFBFBD><EFBFBD> 21 <EFBFBD>ֽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD> 8 λ
|
|||
|
|
*
|
|||
|
|
* <EFBFBD>ֲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD>
|
|||
|
|
* 1 <EFBFBD>ȵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> = (1/PowerPar) <EFBFBD><EFBFBD> (1/(<EFBFBD><EFBFBD>ѹϵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><EFBFBD>)) <EFBFBD><EFBFBD> 10^9 <EFBFBD><EFBFBD> 3600
|
|||
|
|
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>(kWh) = <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD> PowerPar <EFBFBD><EFBFBD> <EFBFBD><EFBFBD>ѹϵ<EFBFBD><EFBFBD> <EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><EFBFBD> / (10^9 <EFBFBD><EFBFBD> 3600)
|
|||
|
|
* <EFBFBD><EFBFBD>ѹ/<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> main.h<EFBFBD><EFBFBD>HLW_U_COEF / HLW_I_COEF<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ⱦ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
*
|
|||
|
|
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>PF <EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD> 16 λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ bit7 <EFBFBD><EFBFBD>ת<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ס bit7 <EFBFBD>ϴ<EFBFBD>ֵ<EFBFBD><EFBFBD>
|
|||
|
|
* ÿ֡<EFBFBD>ȶԣ<EFBFBD><EFBFBD><EFBFBD>תһ<EFBFBD><EFBFBD>˵<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>Σ<EFBFBD>+65536<EFBFBD><EFBFBD><EFBFBD><EFBFBD>50ms һ֡ vs <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҲҪ<EFBFBD><EFBFBD>Сʱ<EFBFBD><EFBFBD>
|
|||
|
|
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ֡<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Σ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>©<EFBFBD><EFBFBD>
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
#include "hlw8032.h"
|
|||
|
|
#include "uart.h"
|
|||
|
|
#include "24c02.h"
|
|||
|
|
#include "log.h"
|
|||
|
|
#include <string.h>
|
|||
|
|
|
|||
|
|
#define HLW_FRAME_LEN 24
|
|||
|
|
#define HLW_OVERFLOW_PULSES 65536u
|
|||
|
|
#define HLW_EEP_ADDR 164 /* EEPROM 164~171: uint64 <20>ۼ<EFBFBD><DBBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>132~157 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, 160 <20><>־<EFBFBD>ȼ<EFBFBD><C8BC><EFBFBD> */
|
|||
|
|
|
|||
|
|
static uint8_t s_frame[HLW_FRAME_LEN];
|
|||
|
|
static uint8_t s_idx = 0; /* ֡ͬ<D6A1><CDAC>״̬<D7B4><CCAC>0=<3D><><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD> 1=<3D><> 0x5A >=2=<3D>ռ<EFBFBD><D5BC><EFBFBD> */
|
|||
|
|
|
|||
|
|
static uint64_t s_total_pulses = 0; /* <20>ۼ<EFBFBD><DBBC><EFBFBD><EFBFBD>壨<EFBFBD><E5A3A8> EEPROM <20>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD>ʷֵ<CAB7><D6B5> */
|
|||
|
|
static uint64_t s_saved_pulses = 0; /* <20>ϴ<EFBFBD><CFB4><EFBFBD>д<EFBFBD><D0B4> EEPROM <20><>ֵ */
|
|||
|
|
static uint32_t s_power_par = 0; /* <20><><EFBFBD>ʲ<EFBFBD><CAB2><EFBFBD><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD>оƬ<D0BE><C6AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>յ<EFBFBD>֡<EFBFBD><D6A1><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD> */
|
|||
|
|
static uint32_t s_u_par = 0, s_u_reg = 0; /* <20><>ѹ<EFBFBD><D1B9><EFBFBD><EFBFBD>/<2F><>ѹ<EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE>ѹ<EFBFBD>ã<EFBFBD> */
|
|||
|
|
static uint32_t s_i_par = 0, s_i_reg = 0; /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>/<2F><><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD> */
|
|||
|
|
static uint32_t s_p_reg = 0; /* <20><><EFBFBD>ʼĴ<CABC><C4B4><EFBFBD> */
|
|||
|
|
static float s_u_f = 0, s_i_f = 0, s_p_f = 0; /* <20><>ѹ/<2F><><EFBFBD><EFBFBD>/<2F><><EFBFBD><EFBFBD> EMA <20>˲<EFBFBD>ֵ */
|
|||
|
|
|
|||
|
|
static uint32_t s_k = 0; /* <20><><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><CFB5><EFBFBD><EFBFBD><EFBFBD> bit7 <20><>ת<EFBFBD><D7AA>PF <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
|
|||
|
|
static uint8_t s_last_bit7 = 0;
|
|||
|
|
static uint32_t s_last_chip = 0; /* <20><>һ֡оƬ<D0BE><C6AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> k*65536+n */
|
|||
|
|
static uint8_t s_synced = 0; /* <20><>ȷ<EFBFBD><C8B7>ͬ<EFBFBD><CDAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч֡<D0A7><D6A1> */
|
|||
|
|
static uint8_t s_streak = 0; /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч֡<D0A7><D6A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC><EFBFBD><EFBFBD> */
|
|||
|
|
static uint32_t s_last_valid_tick = 0; /* <20><>һ<EFBFBD><D2BB>Ч֡ʱ<D6A1>̣<EFBFBD>֡<EFBFBD><D6A1><EFBFBD><EFBFBD>У<EFBFBD><D0A3><EFBFBD>ã<EFBFBD> */
|
|||
|
|
static uint32_t s_last_frame_tick = 0;
|
|||
|
|
|
|||
|
|
/*==== ֡У<D6A1><D0A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ۼƣ<DBBC><C6A3>ж<EFBFBD><D0B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>У<EFBFBD><D0A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>====*/
|
|||
|
|
static void hlw8032_parse(const uint8_t *f)
|
|||
|
|
{
|
|||
|
|
uint8_t sum = 0;
|
|||
|
|
for (uint8_t i = 2; i <= 22; i++) sum += f[i];
|
|||
|
|
if (sum != f[23]) return; /* У<><D0A3>ʧ<EFBFBD>ܶ<EFBFBD>֡ */
|
|||
|
|
|
|||
|
|
uint32_t power_par = ((uint32_t)f[14] << 16) | ((uint32_t)f[15] << 8) | f[16];
|
|||
|
|
if (power_par == 0) return; /* <20><><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD>쳣<EFBFBD><ECB3A3>֡<EFBFBD><D6A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
|
|||
|
|
s_power_par = power_par;
|
|||
|
|
|
|||
|
|
/* <20><>ѹ/<2F><><EFBFBD><EFBFBD>/<2F><><EFBFBD><EFBFBD>ԭʼ<D4AD>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>־<EFBFBD><D6BE>ʾ<EFBFBD><CABE> */
|
|||
|
|
s_u_par = ((uint32_t)f[2] << 16) | ((uint32_t)f[3] << 8) | f[4];
|
|||
|
|
s_u_reg = ((uint32_t)f[5] << 16) | ((uint32_t)f[6] << 8) | f[7];
|
|||
|
|
s_i_par = ((uint32_t)f[8] << 16) | ((uint32_t)f[9] << 8) | f[10];
|
|||
|
|
s_i_reg = ((uint32_t)f[11] << 16) | ((uint32_t)f[12] << 8) | f[13];
|
|||
|
|
s_p_reg = ((uint32_t)f[17] << 16) | ((uint32_t)f[18] << 8) | f[19];
|
|||
|
|
|
|||
|
|
uint8_t bit7 = f[20] & 0x80;
|
|||
|
|
uint16_t pf = ((uint16_t)f[21] << 8) | f[22];
|
|||
|
|
|
|||
|
|
if (!s_synced) {
|
|||
|
|
/* <20><>ֻ֡<D6A1><D6BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><D7BC><EFBFBD><EFBFBD><EFBFBD>ۼ<EFBFBD><DBBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
* <EFBFBD><EFBFBD>Ƭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>оƬһֱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>壨<EFBFBD><EFBFBD><EFBFBD>룬Լ<EFBFBD><EFBFBD><EFBFBD>㼸 Wh<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
|
|||
|
|
s_last_bit7 = bit7;
|
|||
|
|
s_k = 0;
|
|||
|
|
} else if (bit7 != s_last_bit7) {
|
|||
|
|
s_k++; /* PF <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB> */
|
|||
|
|
s_last_bit7 = bit7;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>оƬ 50ms һ֡<D2BB>ȶ<EFBFBD><C8B6><EFBFBD><EFBFBD>Ҫ<EFA3AC><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 3 ֡<>Ҽ<EFBFBD><D2BC><EFBFBD> 20~150ms <20><><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC><EFBFBD><EFBFBD>
|
|||
|
|
* PD2 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD>ĵ<EFBFBD><EFBFBD>Ÿ<EFBFBD><EFBFBD><EFBFBD>ż<EFBFBD><EFBFBD>Ҳ<EFBFBD>ܴճ<EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD>ļ<EFBFBD>֡<EFBFBD><EFBFBD>Լ 1/256<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 3 ֡<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 50ms <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
|
|||
|
|
{
|
|||
|
|
uint32_t now = HAL_GetTick();
|
|||
|
|
uint32_t gap = now - s_last_valid_tick;
|
|||
|
|
s_last_valid_tick = now;
|
|||
|
|
if (gap >= 20 && gap <= 150) {
|
|||
|
|
if (s_streak < 3) s_streak++;
|
|||
|
|
} else {
|
|||
|
|
s_streak = 1;
|
|||
|
|
}
|
|||
|
|
if (s_streak < 3) return; /* δȷ<CEB4><C8B7>ͬ<EFBFBD><CDAC><EFBFBD><EFBFBD>֡<EFBFBD><D6A1><EFBFBD><EFBFBD>һ<EFBFBD>ɲ<EFBFBD><C9B2><EFBFBD><EFBFBD><EFBFBD> */
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* EMA <20><><EFBFBD><EFBFBD>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD>ϵ<EFBFBD><CFB5> 1/8<><38>Լ 0.4s <20><>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD>ѹ<EFBFBD><D1B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>䣬
|
|||
|
|
* <EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD>ر仯<EFBFBD>ӳ<EFBFBD> <0.5s<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӱ<EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD> */
|
|||
|
|
{
|
|||
|
|
float u = s_u_reg ? (float)((double)s_u_par / (double)s_u_reg * HLW_U_COEF) : 0.0f;
|
|||
|
|
float a = s_i_reg ? (float)((double)s_i_par / (double)s_i_reg * HLW_I_COEF) : 0.0f;
|
|||
|
|
float w = s_p_reg ? (float)((double)s_power_par / (double)s_p_reg * HLW_U_COEF * HLW_I_COEF) : 0.0f;
|
|||
|
|
s_u_f += (u - s_u_f) * 0.125f;
|
|||
|
|
s_i_f += (a - s_i_f) * 0.125f;
|
|||
|
|
s_p_f += (w - s_p_f) * 0.125f;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
uint32_t chip_total = s_k * HLW_OVERFLOW_PULSES + pf;
|
|||
|
|
if (s_synced) {
|
|||
|
|
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С˵<D0A1><CBB5>оƬ<D0BE>ϵ<EFBFBD><CFB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㣩<EFBFBD><E3A3A9><EFBFBD>ӵ<EFBFBD>ǰֵ<C7B0><D6B5><EFBFBD><EFBFBD><EFBFBD>ۼ<EFBFBD> */
|
|||
|
|
uint32_t delta = (chip_total >= s_last_chip) ? (chip_total - s_last_chip) : chip_total;
|
|||
|
|
s_total_pulses += delta;
|
|||
|
|
}
|
|||
|
|
s_last_chip = chip_total;
|
|||
|
|
if (!s_synced) {
|
|||
|
|
s_synced = 1;
|
|||
|
|
log_info("> <20><><EFBFBD><EFBFBD>: HLW8032 <20><><EFBFBD><EFBFBD>, <20><><EFBFBD>ʲ<EFBFBD><CAB2><EFBFBD>=%lu", (unsigned long)s_power_par);
|
|||
|
|
}
|
|||
|
|
s_last_frame_tick = HAL_GetTick();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*==== UART5 <20>ж<EFBFBD><D0B6><EFBFBD><EFBFBD>ֽ<EFBFBD>ι<EFBFBD>룺<EFBFBD><EBA3BA><EFBFBD>ֽ<EFBFBD>ͬ<EFBFBD><CDAC> + 0x5A <20><><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7> + <20><><EFBFBD><EFBFBD> 24 <20>ֽڽ<D6BD><DABD><EFBFBD> ====*/
|
|||
|
|
void hlw8032_rx_byte(uint8_t b)
|
|||
|
|
{
|
|||
|
|
if (s_idx == 0) {
|
|||
|
|
/* <20><><EFBFBD>ֽں<D6BD>ѡ<EFBFBD><D1A1>0x55 / 0xAA / 0xFx */
|
|||
|
|
if (b == 0x55 || b == 0xAA || (b & 0xF0) == 0xF0) {
|
|||
|
|
s_frame[0] = b;
|
|||
|
|
s_idx = 1;
|
|||
|
|
}
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
if (s_idx == 1) {
|
|||
|
|
if (b == 0x5A) {
|
|||
|
|
s_frame[1] = b;
|
|||
|
|
s_idx = 2;
|
|||
|
|
} else {
|
|||
|
|
/* <20>ڶ<EFBFBD><DAB6>ֽڲ<D6BD><DAB2><EFBFBD> 0x5A<35><41>αͬ<CEB1><CDAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD> */
|
|||
|
|
s_idx = 0;
|
|||
|
|
if (b == 0x55 || b == 0xAA || (b & 0xF0) == 0xF0) {
|
|||
|
|
s_frame[0] = b;
|
|||
|
|
s_idx = 1;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
s_frame[s_idx++] = b;
|
|||
|
|
if (s_idx >= HLW_FRAME_LEN) {
|
|||
|
|
s_idx = 0;
|
|||
|
|
hlw8032_parse(s_frame);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*==== <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>EEPROM <20>ָ<EFBFBD><D6B8>ۼ<EFBFBD> + UART5 <20><><EFBFBD><EFBFBD> ====*/
|
|||
|
|
void hlw8032_init(void)
|
|||
|
|
{
|
|||
|
|
uint64_t v = 0;
|
|||
|
|
eepromReadData(HLW_EEP_ADDR, &v, sizeof(v));
|
|||
|
|
if (v == 0xFFFFFFFFFFFFFFFFULL) v = 0; /* <20>հ<EFBFBD> EEPROM<4F><4D><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 0xFF<46><46> */
|
|||
|
|
s_total_pulses = v;
|
|||
|
|
s_saved_pulses = v;
|
|||
|
|
|
|||
|
|
MX_UART5_UART_Init();
|
|||
|
|
UART5_StartRx();
|
|||
|
|
if (s_total_pulses) {
|
|||
|
|
log_info("> <20><><EFBFBD><EFBFBD>: HLW8032 <20><><EFBFBD><EFBFBD> (UART5 PD2), <20><>ʷ<EFBFBD><CAB7><EFBFBD><EFBFBD> %lu%09lu",
|
|||
|
|
(unsigned long)(s_total_pulses / 1000000000ULL),
|
|||
|
|
(unsigned long)(s_total_pulses % 1000000000ULL));
|
|||
|
|
} else {
|
|||
|
|
log_info("> <20><><EFBFBD><EFBFBD>: HLW8032 <20><><EFBFBD><EFBFBD> (UART5 PD2)");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*==== <20>ۼƵ<DBBC><C6B5><EFBFBD> kWh ====*/
|
|||
|
|
float hlw8032_get_energy_kwh(void)
|
|||
|
|
{
|
|||
|
|
if (!s_power_par) return 0.0f;
|
|||
|
|
return (float)((double)s_total_pulses * (double)s_power_par *
|
|||
|
|
(double)HLW_U_COEF * (double)HLW_I_COEF / 3.6e12);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*==== <20><>ѹ/<2F><><EFBFBD><EFBFBD>/<2F><><EFBFBD>ʣ<EFBFBD><CAA3>ֲ<D6B2><E1A3BA>Чֵ = <20><><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD>/<2F>Ĵ<EFBFBD><C4B4><EFBFBD> <20><> ϵ<><CFB5><EFBFBD><EFBFBD>====*/
|
|||
|
|
float hlw8032_get_voltage_v(void)
|
|||
|
|
{
|
|||
|
|
if (!s_synced) return 0.0f;
|
|||
|
|
return s_u_f;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
float hlw8032_get_current_a(void)
|
|||
|
|
{
|
|||
|
|
if (!s_synced) return 0.0f;
|
|||
|
|
float a = s_i_f - HLW_I_ZERO_A; /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƫ<EFBFBD><C6AB> */
|
|||
|
|
return a > 0.0f ? a : 0.0f; /* ǯλ<C7AF><CEBB> 0 */
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
float hlw8032_get_power_w(void)
|
|||
|
|
{
|
|||
|
|
if (!s_synced) return 0.0f;
|
|||
|
|
if (s_p_f < HLW_P_DEAD_W) return 0.0f; /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ 0 */
|
|||
|
|
return s_p_f - HLW_P_ZERO_W;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*==== <20><><EFBFBD><EFBFBD><EFBFBD>жϣ<D0B6>1s <20><><EFBFBD>յ<EFBFBD><D5B5><EFBFBD><EFBFBD><EFBFBD>Ч֡ ====*/
|
|||
|
|
uint8_t hlw8032_online(void)
|
|||
|
|
{
|
|||
|
|
return s_synced && (HAL_GetTick() - s_last_frame_tick) < 1000;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*==== <20><><EFBFBD><EFBFBD>д EEPROM<4F><4D><EFBFBD>ϵ<EFBFBD>Ԥ<EFBFBD><D4A4>/<2F>ƻ<EFBFBD><C6BB><EFBFBD>λǰ<CEBB><C7B0><EFBFBD>ã<EFBFBD>====*/
|
|||
|
|
void hlw8032_save(void)
|
|||
|
|
{
|
|||
|
|
if (s_total_pulses == s_saved_pulses) return;
|
|||
|
|
uint64_t v = s_total_pulses;
|
|||
|
|
if (eepromWriteData(HLW_EEP_ADDR, &v, sizeof(v)) == 0) {
|
|||
|
|
s_saved_pulses = s_total_pulses;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*==== <20>ۼƵ<DBBC><C6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㣨<EFBFBD><E3A3A8><EFBFBD><EFBFBD> ENCLR <20><><EFBFBD><EFBFBD><EEA3A9><EFBFBD><EFBFBD> RAM <20><> EEPROM ====*/
|
|||
|
|
void hlw8032_clear(void)
|
|||
|
|
{
|
|||
|
|
s_total_pulses = 0;
|
|||
|
|
s_saved_pulses = 0;
|
|||
|
|
uint64_t v = 0;
|
|||
|
|
eepromWriteData(HLW_EEP_ADDR, &v, sizeof(v));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*==== 1s <20><><EFBFBD>ڣ<EFBFBD>ÿ<EFBFBD>ܹ<EFBFBD>Լ 0.1 kWh дһ<D0B4><D2BB> EEPROM<4F><4D><EFBFBD><EFBFBD><EFBFBD>Ʋ<EFBFBD>дƵ<D0B4><C6B5> ====*/
|
|||
|
|
void hlw8032_tick(void)
|
|||
|
|
{
|
|||
|
|
if (!s_power_par) return;
|
|||
|
|
double per_01kwh = 3.6e11 / ((double)s_power_par * HLW_U_COEF * HLW_I_COEF);
|
|||
|
|
if (per_01kwh < 1.0) per_01kwh = 1.0;
|
|||
|
|
if (s_total_pulses - s_saved_pulses >= (uint64_t)per_01kwh) {
|
|||
|
|
hlw8032_save();
|
|||
|
|
}
|
|||
|
|
}
|