Files
chargeflow/components/meter_ade7758/src/ade7758.c
2025-06-08 16:55:50 +01:00

1127 lines
41 KiB
C
Executable File
Raw Blame History

#include <stdio.h>
#include <stdlib.h>
#include "driver/spi_master.h"
#include "sdkconfig.h"
#include "esp_log.h"
#include "ade7758.h"
spi_bus_config_t _spi_bus_cfg;
// spi_device_interface_config_t _spi_interface_cfg;
spi_device_handle_t _handle;
spi_host_device_t _spi_peripheral;
spi_transaction_t _spi_transaction;
esp_err_t transferByte(const uint8_t reg_addr, const uint8_t data, const uint8_t command)
{
_spi_transaction.flags = SPI_TRANS_USE_RXDATA | SPI_TRANS_USE_TXDATA;
_spi_transaction.length = 8;
//_spi_transaction.rxlength = 8;
_spi_transaction.cmd = command;
_spi_transaction.addr = reg_addr;
_spi_transaction.tx_data[0] = data;
return spi_device_transmit(_handle, &_spi_transaction);
}
esp_err_t transferMultiplesBytes(const uint8_t reg_addr, uint8_t *tx_buf, uint8_t *rx_buf, size_t data_length, const uint8_t command)
{
spi_transaction_t spi_transaction_multibyte; // spi_transaction_t to use the tx and rx buffers
if (data_length < 1)
{
data_length = 1;
}
spi_transaction_multibyte.flags = 0; // SPI_TRANS_USE_RXDATA | SPI_TRANS_USE_TXDATA;
spi_transaction_multibyte.length = (8 * data_length);
spi_transaction_multibyte.rxlength = 0;
spi_transaction_multibyte.cmd = command;
spi_transaction_multibyte.addr = reg_addr;
spi_transaction_multibyte.tx_buffer = tx_buf;
spi_transaction_multibyte.rx_buffer = rx_buf;
return spi_device_transmit(_handle, &spi_transaction_multibyte);
}
esp_err_t Init(const spi_host_device_t spi_peripheral, const int pin_miso, const int pin_mosi, const int pin_sclk)
{
esp_err_t status = ESP_OK;
_spi_peripheral = spi_peripheral;
_spi_transaction.tx_buffer = NULL;
_spi_transaction.rx_buffer = NULL;
_spi_bus_cfg.mosi_io_num = pin_mosi;
_spi_bus_cfg.miso_io_num = pin_miso;
_spi_bus_cfg.sclk_io_num = pin_sclk;
_spi_bus_cfg.quadwp_io_num = -1;
_spi_bus_cfg.quadhd_io_num = -1;
status |= spi_bus_initialize(spi_peripheral, &_spi_bus_cfg, SPI_DMA_CH_AUTO);
return status;
}
esp_err_t RegisterDevice(const uint8_t mode, const int ss, const int addr_length, const int command_length, const int bus_speed)
{
esp_err_t status = ESP_OK;
spi_device_interface_config_t _spi_interface_cfg = {
.command_bits = command_length,
.address_bits = addr_length,
.mode = mode,
.clock_speed_hz = bus_speed,
.spics_io_num = ss,
.queue_size = 5,
};
status |= spi_bus_add_device(_spi_peripheral, &_spi_interface_cfg, &_handle);
return status;
}
uint8_t ReadRegister(const uint8_t reg_addr, const uint8_t command)
{
transferByte(reg_addr, 0, command);
return _spi_transaction.rx_data[0];
}
esp_err_t WriteRegister(const uint8_t reg_addr, const uint8_t reg_data, const uint8_t command)
{
esp_err_t status = ESP_OK;
status |= transferByte(reg_addr, reg_data, command);
return status;
}
esp_err_t WriteRegisterMultipleBytes(const uint8_t reg_addr, uint8_t *reg_data_buffer, const uint8_t byte_count, const uint8_t command)
{
return transferMultiplesBytes(reg_addr, reg_data_buffer, NULL, byte_count, command);
}
esp_err_t ReadRegisterMultipleBytes(const uint8_t reg_addr, uint8_t *reg_data_buffer, const uint8_t byte_count, const uint8_t command)
{
return transferMultiplesBytes(reg_addr, NULL, reg_data_buffer, byte_count, command);
}
spi_device_handle_t GetHandle(void)
{
return _handle;
}
static uint8_t MODE = 2;
static uint8_t ADDR_BITS = 7;
static uint8_t CMD_BITS = 1;
static uint8_t SPI_WRITE = 1;
static uint8_t SPI_READ = 0;
static int BUSSPEED = 1000000;
// static const char TAG[] = "ade7758";
esp_err_t write8(uint8_t reg, uint8_t value)
{
return WriteRegister(reg, value, SPI_WRITE);
}
esp_err_t write16(uint8_t reg, uint32_t value)
{
uint8_t buff[2];
buff[0] = (value >> 8) & 0xFF;
buff[1] = (value >> 0) & 0xFF;
return WriteRegisterMultipleBytes(reg, buff, 3, SPI_WRITE);
}
esp_err_t write24(uint8_t reg, uint32_t value)
{
uint8_t buff[2];
buff[0] = (value >> 16) & 0xFF;
buff[1] = (value >> 8) & 0xFF;
buff[2] = (value >> 0) & 0xFF;
return WriteRegisterMultipleBytes(reg, buff, 4, SPI_WRITE);
}
uint8_t read8(const uint8_t reg)
{
uint8_t buff[1];
ReadRegisterMultipleBytes(reg, buff, 2, SPI_READ);
return buff[0];
}
uint32_t read16(const uint8_t reg)
{
uint8_t buff[2];
ReadRegisterMultipleBytes(reg, buff, 3, SPI_READ);
return buff[0] << 8 | buff[1];
}
uint32_t read24(const uint8_t reg)
{
uint8_t buff[3];
ReadRegisterMultipleBytes(reg, buff, 4, SPI_READ);
return buff[0] << 16 | buff[1] << 8 | buff[2];
}
esp_err_t readBlockData(const uint8_t reg, uint8_t *buf, const int length)
{
return ReadRegisterMultipleBytes(reg, buf, length, SPI_READ);
}
esp_err_t InitSpi(const int ss)
{
return RegisterDevice(MODE, ss, ADDR_BITS, CMD_BITS, BUSSPEED);
}
/*****************************
*
* public functions
*
*****************************/
/**
* In general:
* @params: void
* @return: register content (measure) of the proper type depending on register width
*/
unsigned char getVersion()
{
return read8(VERSION);
}
/** === setOpMode / getOpMode ===
OPERATIONAL MODE REGISTER (0x13)
The general configuration of the ADE7758 is defined by writing to the OPMODE register.
Table 18 summarizes the functionality of each bit in the OPMODE register.
Bit Location Bit Mnemonic Default Value Description
0 DISHPF 0 The HPFs in all current channel inputs are disabled when this bit is set.
1 DISLPF 0 The LPFs after the watt and VAR multipliers are disabled when this bit is set.
2 DISCF 1 The frequency outputs APCF and VARCF are disabled when this bit is set.
3 to 5 DISMOD 0 By setting these bits, ADE7758<35>s ADCs can be turned off. In normal operation, these bits should be left at Logic 0.
DISMOD[2:0] Description
0 0 0 Normal operation.
1 0 0 Redirect the voltage inputs to the signal paths for the current channels and the current inputs to the signal paths for the voltage channels.
0 0 1 Switch off only the current channel ADCs.
1 0 1 Switch off current channel ADCs and redirect the current input signals to the voltage channel signal paths.
0 1 0 Switch off only the voltage channel ADCs.
1 1 0 Switch off voltage channel ADCs and redirect the voltage input signals to the current channel signal paths.
0 1 1 Put the ADE7758 in sleep mode.
1 1 1 Put the ADE7758 in power-down mode (reduces AIDD to 1 mA typ).
6 SWRST 0 Software Chip Reset. A data transfer to the ADE7758 should not take place for at least 18 <20>s after a software reset.
7 RESERVED 0 This should be left at 0.
*/
void setOpMode(uint8_t m)
{
write8(OPMODE, m);
}
uint8_t getOpMode()
{
return read8(OPMODE);
}
/** === setMMode / getMMode ===
MEASUREMENT MODE REGISTER (0x14)
The configuration of the PERIOD and peak measurements made by the ADE7758 is defined by writing to the MMODE register.
Table 19 summarizes the functionality of each bit in the MMODE register.
Bit Location Bit Mnemonic Default Value Description
0 to 1 FREQSEL 0 These bits are used to select the source of the measurement of the voltage line frequency.
FREQSEL1 FREQSEL0 Source
0 0 Phase A
0 1 Phase B
1 0 Phase C
1 1 Reserved
2 to 4 PEAKSEL 7 These bits select the phases used for the voltage and current peak registers.
Setting Bit 2 switches the IPEAK and VPEAK registers to hold the absolute values
of the largest current and voltage waveform (over a fixed number of half-line cycles)
from Phase A. The number of half-line cycles is determined by the content of the
LINECYC register. At the end of the LINECYC number of half-line cycles, the content
of the registers is replaced with the new peak values. Similarly, setting Bit 3 turns
on the peak detection for Phase B, and Bit 4 for Phase C. Note that if more than one
bit is set, the VPEAK and IPEAK registers can hold values from two different phases, that is,
the voltage and current peak are independently processed (see the Peak Current Detection section).
5 to 7 PKIRQSEL 7 These bits select the phases used for the peak interrupt detection.
Setting Bit 5 switches on the monitoring of the absolute current and voltage waveform to Phase A.
Similarly, setting Bit 6 turns on the waveform detection for Phase B, and Bit 7 for Phase C.
Note that more than one bit can be set for detection on multiple phases.
If the absolute values of the voltage or current waveform samples in the selected phases exceeds
the preset level specified in the VPINTLVL or IPINTLVL registers the corresponding bit(s) in the
STATUS registers are set (see the Peak Current Detection section).
*/
void setMMode(uint8_t m)
{
write8(MMODE, m);
}
uint8_t getMMode(void)
{
return read8(MMODE);
}
/** === setWavMode / getWavMode ===
WAVEFORM MODE REGISTER (0x15)
The waveform sampling mode of the ADE7758 is defined by writing to the WAVMODE register.
Table 20 summarizes the functionality of each bit in the WAVMODE register.
Bit Location Bit Mnemonic Default Value Description
0 to 1 PHSEL 0 These bits are used to select the phase of the waveform sample.
PHSEL[1:0] Source
0 0 Phase A
0 1 Phase B
1 0 Phase C
1 1 Reserved
2 to 4 WAVSEL 0 These bits are used to select the type of waveform.
WAVSEL[2:0] Source
0 0 0 Current
0 0 1 Voltage
0 1 0 Active Power Multiplier Output
0 1 1 Reactive Power Multiplier Output
1 0 0 VA Multiplier Output
-Others- Reserved
5 to 6 DTRT 0 These bits are used to select the data rate.
DTRT[1:0] Update Rate
0 0 26.04 kSPS (CLKIN/3/128)
0 1 13.02 kSPS (CLKIN/3/256)
1 0 6.51 kSPS (CLKIN/3/512)
1 1 3.25 kSPS (CLKIN/3/1024)
7 VACF 0 Setting this bit to Logic 1 switches the VARCF output pin to an output
frequency that is proportional to the total apparent power (VA).
In the default state, Logic 0, the VARCF pin outputs a frequency proportional
to the total reactive power (VAR).
*/
void setWavMode(uint8_t m)
{
write8(WAVMODE, m);
}
uint8_t getWavMode()
{
return read8(WAVMODE);
}
/** === setCompMode / getCompMode ===
COMPUTATIONAL MODE REGISTER (0x16)
The computational method of the ADE7758 is defined by writing to the COMPMODE register.
Bit Location Bit Mnemonic Default Value Description
0 to 1 CONSEL 0 These bits are used to select the input to the energy accumulation registers.
CONSEL[1:0] = 11 is reserved. IA, IB, and IC are IA, IB, and IC phase shifted by <20>90<39>, respectively.
Registers CONSEL[1, 0] = 00 CONSEL[1, 0] = 01 CONSEL[1, 0] = 10
AWATTHR VA <20> IA VA <20> (IA <20> IB) VA <20> (IA<49>IB)
BWATTHR VB <20> IB 0 0
CWATTHR VC <20> IC VC <20> (IC <20> IB) VC <20> IC
AVARHR VA <20> IA VA <20> (IA <20> IB) VA <20> (IA<49>IB)
BVARHR VB <20> IB 0 0
CVARHR VC <20> IC VC <20> (IC <20> IB) VC <20> IC
AVAHR VARMS <20> IARMS VARMS <20> IARMS VARMS <20> ARMS
BVAHR VBRMS <20> IBRMS (VARMS + VCRMS)/2 <20> IBRMS VARMS <20> IBRMS
CVAHR VCRMS <20> ICRMS VCRMS <20> ICRMS VCRMS <20> ICRMS
2 to 4 TERMSEL 7 These bits are used to select the phases to be included in the APCF and VARCF pulse outputs.
Setting Bit 2 selects Phase A (the inputs to AWATTHR and AVARHR registers) to be included.
Bit 3 and Bit 4 are for Phase B and Phase C, respectively.
Setting all three bits enables the sum of all three phases to be included in the frequency outputs
(see the Active Power Frequency Output and the Reactive Power Frequency Output sections).
5 ABS 0 Setting this bit places the APCF output pin in absolute only mode.
Namely, the APCF output frequency is proportional to the sum of the absolute values of the watt-hour
accumulation registers (AWATTHR, BWATTHR, and CWATTHR).
Note that this bit only affects the APCF pin and has no effect on the content of the corresponding
registers.
6 SAVAR 0 Setting this bit places the VARCF output pin in the signed adjusted mode.
Namely, the VARCF output frequency is proportional to the sign-adjusted sum of the VAR-hour accumulation
registers (AVARHR, BVARHR, and CVARHR).
The sign of the VAR is determined from the sign of the watt calculation from the corresponding phase,
that is, the sign of the VAR is flipped if the sign of the watt is negative, and if the watt is positive,
there is no change to the sign of the VAR.
Note that this bit only affects the VARCF pin and has no effect on the content of the corresponding
registers.
7 NOLOAD 0 Setting this bit activates the no-load threshold in the ADE7758.
*/
void setCompMode(uint8_t m)
{
write8(COMPMODE, m);
}
uint8_t getCompMode(void)
{
return read8(COMPMODE);
}
/** === setLcycMode / getLcycMode ===
LINE CYCLE ACCUMULATION MODE REGISTER (0x17)
The functionalities involved the line-cycle accumulation mode in the ADE7758 are defined by writing to the LCYCMODE register.
Bit Location Bit Mnemonic Default Value Description
0 LWATT 0 Setting this bit places the watt-hour accumulation registers
(AWATTHR, BWATTHR, and CWATTHR registers) into line-cycle accumulation mode.
1 LVAR 0 Setting this bit places the VAR-hour accumulation registers (AVARHR, BVARHR, and CVARHR registers)
into line-cycle accumulation mode.
2 LVA 0 Setting this bit places the VA-hour accumulation registers (AVAHR, BVAHR, and CVAHR registers)
into line-cycle accumulation mode.
3 to 5 ZXSEL 7 These bits select the phases used for counting the number of zero crossings in the line-cycle
accumulation mode. Bit 3, Bit 4, and Bit 5 select Phase A, Phase B, and Phase C, respectively.
More than one phase can be selected for the zero-crossing detection,
and the accumulation time is shortened accordingly.
6 RSTREAD 1 Setting this bit enables the read-with-reset for all the WATTHR, VARHR, and VAHR registers for all three
phases, that is, a read to those registers resets the registers to 0 after the content of the registers
have been read. This bit should be set to Logic 0 when the LWATT, LVAR, or LVA bits are set to Logic 1.
7 FREQSEL 0 Setting this bit causes the FREQ (0x10) register to display the period, instead of the frequency of the
line input.
*/
void setLcycMode(uint8_t m)
{
write8(LCYCMODE, m);
}
uint8_t getLcycMode(void)
{
return read8(LCYCMODE);
}
/** === gainSetup ===
GAIN REGISTER (0x23)
The PGA configuration of the ADE7758 is defined by writing to the GAIN register.
Table 18 summarizes the functionality of each bit in the GAIN register.
Bit Location Bit Mnemonic Default Value Description
0 to 1 PGA1 0 Current GAIN
PGA1[1:0] Description
0 0 x1
0 1 x2
1 0 x4
1 1 RESERVED
2 ---- RESERVED Reserved.
3 to 4 SCALE 0 Current input full-scale select
SCALE[1:0] Description
0 0 0.5v
0 1 0.25v
1 0 0.125v
1 1 Reserved
5 to 6 PGA2 0 Voltage GAIN
PGA2[1:0] Description
0 0 x1
0 1 x2
1 0 x4
1 1 RESERVED
7 INTEGRATOR 0 This bit enables the integrator on the current chanel when set.
*/
void gainSetup(uint8_t integrator, uint8_t scale, uint8_t PGA2, uint8_t PGA1)
{
char pgas = (integrator << 7) | (PGA2 << 5) | (scale << 3) | (PGA1);
write8(GAIN, pgas); // write GAIN register, format is |3 bits PGA2 gain|2 bits full scale|3 bits PGA1 gain
}
void setupDivs(uint8_t Watt_div, uint8_t VAR_div, uint8_t VA_div)
{
write8(WDIV, Watt_div);
write8(VARDIV, VAR_div);
write8(VADIV, VA_div);
}
/** === getMaskInterrupts / setMaskInterrupts
MASK REGISTER (0x18)
When an interrupt event occurs in the ADE7758, the IRQ logic output goes active low if the mask bit for this event is Logic 1 in the MASK register.
The IRQ logic output is reset to its default collector open state when the RSTATUS register is read.
describes the function of each bit in the interrupt mask register.
Bit Location Interrupt Flag Default Value Description
0 AEHF 0 Enables an interrupt when there is a change in Bit 14 of any one of the three WATTHR registers,
that is, the WATTHR register is half full.
1 REHF 0 Enables an interrupt when there is a change in Bit 14 of any one of the three VARHR registers,
that is, the VARHR register is half full.
2 VAEHF 0 Enables an interrupt when there is a 0 to 1 transition in the MSB of any one of the three VAHR
registers, that is, the VAHR register is half full.
3 SAGA 0 Enables an interrupt when there is a SAG on the line voltage of the Phase A.
4 SAGB 0 Enables an interrupt when there is a SAG on the line voltage of the Phase B.
5 SAGC 0 Enables an interrupt when there is a SAG on the line voltage of the Phase C.
6 ZXTOA 0 Enables an interrupt when there is a zero-crossing timeout detection on Phase A.
7 ZXTOB 0 Enables an interrupt when there is a zero-crossing timeout detection on Phase B.
8 ZXTOC 0 Enables an interrupt when there is a zero-crossing timeout detection on Phase C.
9 ZXA 0 Enables an interrupt when there is a zero crossing in the voltage channel of Phase A
(see the Zero-Crossing Detection section).
10 ZXB 0 Enables an interrupt when there is a zero crossing in the voltage channel of Phase B
(see the Zero-Crossing Detection section).
11 ZXC 0 Enables an interrupt when there is a zero crossing in the voltage channel of Phase C
(see the Zero-Crossing Detection section).
12 LENERGY 0 Enables an interrupt when the energy accumulations over LINECYC are finished.
13 RESERVED 0 Reserved.
14 PKV 0 Enables an interrupt when the voltage input selected in the MMODE register is above
the value in the VPINTLVL register.
15 PKI 0 Enables an interrupt when the current input selected in the MMODE register is above the
value in the IPINTLVL register.
16 WFSM 0 Enables an interrupt when data is present in the WAVEMODE register.
17 REVPAP 0 Enables an interrupt when there is a sign change in the watt calculation among any one of
the phases specified by the TERMSEL bits in the COMPMODE register.
18 REVPRP 0 Enables an interrupt when there is a sign change in the VAR calculation among any one of
the phases specified by the TERMSEL bits in the COMPMODE register.
19 SEQERR 0 Enables an interrupt when the zero crossing from Phase A is followed not by the zero crossing
of Phase C but with that of Phase B.
*/
uint32_t getMaskInterrupts(void)
{
return read24(MASK);
}
void setMaskInterrupts(uint32_t m)
{
write24(MASK, m);
}
/** getStatus / resetStatus
INTERRUPT STATUS REGISTER (0x19)/RESET INTERRUPT STATUS REGISTER (0x1A)
The interrupt status register is used to determine the source of an interrupt event.
When an interrupt event occurs in the ADE7758, the corresponding flag in the interrupt status register is set.
The IRQ pin goes active low if the corresponding bit in the interrupt mask register is set.
When the MCU services the interrupt, it must first carry out a read from the interrupt status register to determine the source of the interrupt.
All the interrupts in the interrupt status register stay at their logic high state after an event occurs.
The state of the interrupt bit in the interrupt status register is reset to its default value once the reset interrupt status register is read.
Bit Location Interrupt Flag Default Value Event Description
0 AEHF 0 Indicates that an interrupt was caused by a change in Bit 14 among any one of the three
WATTHR registers, that is, the WATTHR register is half full.
1 REHF 0 Indicates that an interrupt was caused by a change in Bit 14 among any one of the three
VARHR registers, that is, the VARHR register is half full.
2 VAEHF 0 Indicates that an interrupt was caused by a 0 to 1 transition in Bit 15 among any one of the three
VAHR registers, that is, the VAHR register is half full.
3 SAGA 0 Indicates that an interrupt was caused by a SAG on the line voltage of the Phase A.
4 SAGB 0 Indicates that an interrupt was caused by a SAG on the line voltage of the Phase B.
5 SAGC 0 Indicates that an interrupt was caused by a SAG on the line voltage of the Phase C.
6 ZXTOA 0 Indicates that an interrupt was caused by a missing zero crossing on the line voltage of the Phase A.
7 ZXTOB 0 Indicates that an interrupt was caused by a missing zero crossing on the line voltage of the Phase B.
8 ZXTOC 0 Indicates that an interrupt was caused by a missing zero crossing on the line voltage of the Phase C.
9 ZXA 0 Indicates a detection of a rising edge zero crossing in the voltage channel of Phase A.
10 ZXB 0 Indicates a detection of a rising edge zero crossing in the voltage channel of Phase B.
11 ZXC 0 Indicates a detection of a rising edge zero crossing in the voltage channel of Phase C.
12 LENERGY 0 In line energy accumulation, indicates the end of an integration over an integer number of
half- line cycles (LINECYC). See the Calibration section.
13 RESET 1 Indicates that the 5 V power supply is below 4 V. Enables a software reset of the ADE7758
and sets the registers back to their default values. This bit in the STATUS or RSTATUS register
is logic high for only one clock cycle after a reset event.
14 PKV 0 Indicates that an interrupt was caused when the selected voltage input is above the value in the
VPINTLVL register.
15 PKI 0 Indicates that an interrupt was caused when the selected current input is above the value
in the IPINTLVL register.
16 WFSM 0 Indicates that new data is present in the waveform register.
17 REVPAP 0 Indicates that an interrupt was caused by a sign change in the watt calculation among any
one of the phases specified by the TERMSEL bits in the COMPMODE register.
18 REVPRP 0 Indicates that an interrupt was caused by a sign change in the VAR calculation among any
one of the phases specified by the TERMSEL bits in the COMPMODE register.
19 SEQERR 0 Indicates that an interrupt was caused by a zero crossing from Phase A
followed not by the zero crossing of Phase C but by that of Phase B.
*/
uint32_t getStatus(void)
{
return read24(STATUS);
}
uint32_t resetStatus(void)
{
return read24(RSTATUS);
}
/** === getAIRMS ===
* Phase A Current RMS Value
* To minimize noise, synchronize the reading of the rms register with the zero crossing
* of the voltage input and take the average of a number of readings.
* @param none
* @return long with the data (24 bits unsigned).
*/
int32_t getAIRMS(void)
{
long lastupdate = 0;
resetStatus(); // Clear all interrupts
while (!(getStatus() & ZXA)) // wait Zero-Crossing
{ // wait for the selected interrupt to occur
lastupdate++;
if (lastupdate > 20)
{
return 0; // breack;
}
vTaskDelay(pdMS_TO_TICKS(20));
}
return read24(AIRMS);
}
/** === getBIRMS ===
* Phase B Current RMS Value
* To minimize noise, synchronize the reading of the rms register with the zero crossing
* of the voltage input and take the average of a number of readings.
* @param none
* @return long with the data (24 bits unsigned).
*/
int32_t getBIRMS(void)
{
long lastupdate = 0;
resetStatus(); // Clear all interrupts
while (!(getStatus() & ZXB)) // wait Zero-Crossing
{ // wait for the selected interrupt to occur
lastupdate++;
if (lastupdate > 20)
{
return 0; // breack;
}
vTaskDelay(pdMS_TO_TICKS(20));
}
return read24(BIRMS);
}
/** === getCIRMS ===
* Phase C Current RMS Value
* To minimize noise, synchronize the reading of the rms register with the zero crossing
* of the voltage input and take the average of a number of readings.
* @param none
* @return long with the data (24 bits unsigned).
*/
int32_t getCIRMS(void)
{
long lastupdate = 0;
resetStatus(); // Clear all interrupts
while (!(getStatus() & ZXC)) // wait Zero-Crossing
{ // wait for the selected interrupt to occur
lastupdate++;
if (lastupdate > 20)
{
return 0; // breack;
}
vTaskDelay(pdMS_TO_TICKS(20));
}
return read24(CIRMS);
}
/** === getAVRMS ===
* Phase A RMS Value (Voltage Channel).
* To minimize noise, synchronize the reading of the rms register with the zero crossing
* of the voltage input and take the average of a number of readings.
* @param none
* @return long with the data (24 bits unsigned).
*/
int32_t getAVRMS(void)
{
long lastupdate = 0;
resetStatus(); // Clear all interrupts
while (!(getStatus() & ZXA)) // wait Zero-Crossing
{ // wait for the selected interrupt to occur
lastupdate++;
if (lastupdate > 20)
{
return 0; // breack;
}
vTaskDelay(pdMS_TO_TICKS(20));
}
return read24(AVRMS);
}
/** === getBVRMS ===
* Phase B RMS Value (Voltage Channel).
* To minimize noise, synchronize the reading of the rms register with the zero crossing
* of the voltage input and take the average of a number of readings.
* @param none
* @return long with the data (24 bits unsigned).
*/
int32_t getBVRMS(void)
{
long lastupdate = 0;
resetStatus(); // Clear all interrupts
while (!(getStatus() & ZXB)) // wait Zero-Crossing
{ // wait for the selected interrupt to occur
lastupdate++;
if (lastupdate > 20)
{
return 0; // breack;
}
vTaskDelay(pdMS_TO_TICKS(20));
}
return read24(BVRMS);
}
/** === getCVRMS ===
* Phase C RMS Value (Voltage Channel).
* To minimize noise, synchronize the reading of the rms register with the zero crossing
* of the voltage input and take the average of a number of readings.
* @param none
* @return long with the data (24 bits unsigned).
*/
int32_t getCVRMS(void)
{
long lastupdate = 0;
resetStatus(); // Clear all interrupts
while (!(getStatus() & ZXC)) // wait Zero-Crossing
{ // wait for the selected interrupt to occur
lastupdate++;
if (lastupdate > 20)
{
return 0; // break;
}
vTaskDelay(pdMS_TO_TICKS(20));
}
return read24(CVRMS);
}
/** === vrms ===
* Returns the mean of last 20 readings of RMS voltage. Also supress first reading to avoid
* corrupted data.
* To minimize noise, synchronize the reading of the rms register with the zero crossing
* of the voltage input and take the average of a number of readings.
* @param none
* @return long with RMS voltage value
*/
uint32_t avrms(void)
{
uint8_t i = 0;
uint32_t v = 0;
if (getAVRMS())
{ // Ignore first reading to avoid garbage
for (i = 0; i < 10; ++i)
{
v += getAVRMS();
}
return v / 10;
}
else
{
return 0;
}
}
uint32_t bvrms()
{
uint8_t i = 0;
uint32_t v = 0;
if (getBVRMS())
{ // Ignore first reading to avoid garbage
for (i = 0; i < 10; ++i)
{
v += getBVRMS();
}
return v / 10;
}
else
{
return 0;
}
}
uint32_t cvrms()
{
uint8_t i = 0;
uint32_t v = 0;
if (getCVRMS())
{ // Ignore first reading to avoid garbage
for (i = 0; i < 10; ++i)
{
v += getCVRMS();
}
return v / 10;
}
else
{
return 0;
}
}
/** === irms ===
* Returns the mean of last 20 readings of RMS current. Also supress first reading to avoid
* corrupted data.
* To minimize noise, synchronize the reading of the rms register with the zero crossing
* of the voltage input and take the average of a number of readings.
* @param none
* @return long with RMS current value in hundreds of [mA], ie. 6709=67[mA]
*/
uint32_t airms()
{
char n = 0;
long i = 0;
if (getAIRMS())
{ // Ignore first reading to avoid garbage
for (n = 0; n < 10; ++n)
{
i += getAIRMS();
}
return i / 10;
}
else
{
return 0;
}
}
uint32_t birms()
{
char n = 0;
long i = 0;
if (getBIRMS())
{ // Ignore first reading to avoid garbage
for (n = 0; n < 10; ++n)
{
i += getBIRMS();
}
return i / 10;
}
else
{
return 0;
}
}
int32_t cirms()
{
char n = 0;
int32_t i = 0;
if (getCIRMS())
{ // Ignore first reading to avoid garbage
for (n = 0; n < 10; ++n)
{
i += getCIRMS();
}
return i / 10;
}
else
{
return 0;
}
}
/** === getFreq ===
* Period of the Phase selected in MMode.
* @param none
* @return int with the data (12 bits unsigned).
*/
int32_t getFreq(void)
{
return read16(FREQ);
}
/** setLineCyc: sets the number of cycles required for the accumulations.
**/
void setLineCyc(uint32_t d)
{
write16(LINECYC, d);
}
/** === setCurrentOffset / getCurrentOffset ===
* @param none
* @return int with the data (12 bits 2-complement signed).
*/
int32_t getACurrentOffset()
{
int32_t data;
data = ((int32_t)(read16(AIRMSOS) << 20) >> 20);
return data;
}
int32_t getBCurrentOffset()
{
int32_t data;
data = ((int32_t)(read16(BIRMSOS) << 20) >> 20);
return data;
}
int32_t getCCurrentOffset()
{
int32_t data;
data = ((int32_t)(read16(CIRMSOS) << 20) >> 20);
return data;
}
void setACurrentOffset(int32_t o)
{
write16(AIRMSOS, o);
}
void setBCurrentOffset(int32_t o)
{
write16(BIRMSOS, o);
}
void setCCurrentOffset(int32_t o)
{
write16(CIRMSOS, o);
}
void setAWattOffset(int32_t o)
{
write16(AWATTOS, o);
}
void setBWattOffset(int32_t o)
{
write16(BWATTOS, o);
}
void setCWattOffset(int32_t o)
{
write16(CWATTOS, o);
}
void setAVAROffset(int32_t o)
{
write16(AVAROS, o);
}
void setBVAROffset(int32_t o)
{
write16(BVAROS, o);
}
void setCVAROffset(int32_t o)
{
write16(CVAROS, o);
}
/** === setVoltageOffset / getVoltageOffset ===
* @param none
* @return int with the data (12 bits 2-complement signed).
*/
int32_t getAVoltageOffset()
{
int32_t data;
data = ((int32_t)(read16(AVRMSOS) << 20) >> 20);
return data;
}
int32_t getBVoltageOffset()
{
int32_t data;
data = ((int32_t)(read16(BVRMSOS) << 20) >> 20);
return data;
}
int32_t getCVoltageOffset()
{
int32_t data;
data = ((int32_t)(read16(CVRMSOS) << 20) >> 20);
return data;
}
void setAVoltageOffset(int32_t o)
{
write16(AVRMSOS, o);
}
void setBVoltageOffset(int32_t o)
{
write16(BVRMSOS, o);
}
void setCVoltageOffset(int32_t o)
{
write16(CVRMSOS, o);
}
/** === setZeroCrossingTimeout / getZeroCrossingTimeout ===
* Zero-Crossing Timeout. If no zero crossings are detected
* on Channel 2 within a time period specified by this 12-bit register,
* the interrupt request line (IRQ) is activated
* @param none
* @return int with the data (12 bits unsigned).
*/
void setZeroCrossingTimeout(int32_t d)
{
write16(ZXTOUT, d);
}
int32_t getZeroCrossingTimeout()
{
return read16(ZXTOUT);
}
/** === setPotLine(Phase) ===
Set the conditions for Line accumulation in the selected phase.
Then wait for the interruption and return the phase number when it occurs.
If it does not happen for more than 1.5 seconds, it returns a 0.
**/
uint8_t setPotLine(uint8_t Phase, uint32_t Cycles)
{
long lastupdate = 0;
char m = 0;
switch (Phase)
{
case PHASE_A:
m = (LWATT | LVAR | LVA | ZXSEL_A);
break;
case PHASE_B:
m = (LWATT | LVAR | LVA | ZXSEL_B);
break;
case PHASE_C:
m = (LWATT | LVAR | LVA | ZXSEL_C);
break;
}
setLcycMode(0);
setLcycMode(m);
resetStatus();
setLineCyc(Cycles);
lastupdate = 0;
while (!(getStatus() & LENERGY)) // wait to terminar de acumular
{ // wait for the selected interrupt to occur
lastupdate++;
if (lastupdate > 20)
{
return 0; // breack;
}
vTaskDelay(pdMS_TO_TICKS(20));
}
return Phase;
}
/** === getWatt(phase) / getVar(phase) / getVa(phase) ===
Devuelve los valores de la potencia requerida de la fase seleccionada.
Utilizar antes setPotLine(phase) para generar los valores.
**/
int32_t getWatt(uint8_t Phase)
{
int32_t temp = 0;
switch (Phase)
{
case PHASE_A:
temp = read16(AWATTHR);
break;
case PHASE_B:
temp = read16(BWATTHR);
break;
case PHASE_C:
temp = read16(CWATTHR);
break;
}
return temp;
}
int32_t getVar(uint8_t Phase)
{
int32_t temp = 0;
switch (Phase)
{
case PHASE_A:
temp = read16(AVARHR);
break;
case PHASE_B:
temp = read16(BVARHR);
break;
case PHASE_C:
temp = read16(CVARHR);
break;
}
return temp;
}
int32_t getVa(uint8_t Phase)
{
int32_t temp = 0;
switch (Phase)
{
case PHASE_A:
temp = read16(AVAHR);
break;
case PHASE_B:
temp = read16(BVAHR);
break;
case PHASE_C:
temp = read16(CVAHR);
break;
}
return temp;
}
void setAPCFDEN(int32_t d)
{
write16(APCFDEN, d);
}
int32_t getAPCFDEN(void)
{
int32_t data;
data = ((int32_t)(read16(APCFDEN) << 20) >> 20);
return data;
}
void setAPCFNUM(int32_t d)
{
write16(APCFNUM, d);
}
int32_t getAPCFNUM(void)
{
int32_t data;
data = ((int32_t)(read16(APCFNUM) << 20) >> 20);
return data;
}
void setVARCFNUM(int32_t d)
{
write16(VARCFNUM, d);
}
int32_t getVARCFNUM(void)
{
int32_t data;
data = ((int32_t)(read16(VARCFNUM) << 20) >> 20);
return data;
}
void setVARCFDEN(int32_t d)
{
write16(VARCFDEN, d);
}
int32_t getVARCFDEN(void)
{
int32_t data;
data = ((int32_t)(read16(VARCFDEN) << 20) >> 20);
return data;
}
void setAWG(int32_t d)
{
write16(AWG, d);
}
int32_t getAWG()
{
return ((read16(AWG)) << 4) >> 4;
}
void setBWG(int32_t d)
{
write16(BWG, d);
}
void setCWG(int32_t d)
{
write16(CWG, d);
}
void setAVARG(int32_t d)
{
write16(AVARG, d);
}
int32_t getAVARG()
{
return ((read16(AVARG)) << 4) >> 4;
}
void setBVARG(int32_t d)
{
write16(BVARG, d);
}
int32_t getBVARG()
{
return ((read16(BVARG)) << 4) >> 4;
}
void setCVARG(int32_t d)
{
write16(CVARG, d);
}
int32_t getCVARG()
{
return ((read16(CVARG)) << 4) >> 4;
}
void setAVAG(int32_t d)
{
write16(AVAG, d);
}
void setBVAG(int32_t d)
{
write16(BVAG, d);
}
void setCVAG(int32_t d)
{
write16(CVAG, d);
}