mirror of
https://github.com/esphome/esphome.git
synced 2024-12-11 14:49:20 +01:00
Add Sonoff POW-CT support along with frequency sensor
Add configuration entry to set sonoff model: sonoff_model (Optional, int): Manually specify the Sonoff model, can be one of DUALR3, POWCT. Defaults to DUALR3. This solve the following issue: https://community.home-assistant.io/t/sonoff-powct-pow-ring-power-not-accurate/789686 Add frequency sensor: frequency (Optional): Use the frequency value calculated by the meter. All options from Sensor.
This commit is contained in:
parent
cf835d1580
commit
436fb0b214
@ -12,32 +12,48 @@ static const char *const TAG = "cse7761";
|
|||||||
*
|
*
|
||||||
* Based on Tasmota source code
|
* Based on Tasmota source code
|
||||||
* See https://github.com/arendst/Tasmota/discussions/10793
|
* See https://github.com/arendst/Tasmota/discussions/10793
|
||||||
* https://github.com/arendst/Tasmota/blob/development/tasmota/xnrg_19_cse7761.ino
|
* https://github.com/arendst/Tasmota/blob/development/tasmota/tasmota_xnrg_energy/xnrg_19_cse7761.ino
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
|
|
||||||
static const int CSE7761_UREF = 42563; // RmsUc
|
static const int CSE7761_UREF = 42563; // RmsUc
|
||||||
static const int CSE7761_IREF = 52241; // RmsIAC
|
static const int CSE7761_IREF = 52241; // RmsIAC
|
||||||
static const int CSE7761_PREF = 44513; // PowerPAC
|
static const int CSE7761_PREF = 44513; // PowerPAC
|
||||||
|
static const int CSE7761_FREF = 3579545; // System clock (3.579545MHz) as used in frequency calculation
|
||||||
|
|
||||||
static const uint8_t CSE7761_REG_SYSCON = 0x00; // (2) System Control Register (0x0A04)
|
static const uint8_t CSE7761_REG_SYSCON = 0x00; // (2) System Control Register (0x0A04)
|
||||||
static const uint8_t CSE7761_REG_EMUCON = 0x01; // (2) Metering control register (0x0000)
|
static const uint8_t CSE7761_REG_EMUCON = 0x01; // (2) Metering control register (0x0000)
|
||||||
static const uint8_t CSE7761_REG_EMUCON2 = 0x13; // (2) Metering control register 2 (0x0001)
|
static const uint8_t CSE7761_REG_EMUCON2 = 0x13; // (2) Metering control register 2 (0x0001)
|
||||||
static const uint8_t CSE7761_REG_PULSE1SEL = 0x1D; // (2) Pin function output select register (0x3210)
|
static const uint8_t CSE7761_REG_PULSE1SEL = 0x1D; // (2) Pin function output select register (0x3210)
|
||||||
|
|
||||||
static const uint8_t CSE7761_REG_RMSIA = 0x24; // (3) The effective value of channel A current (0x000000)
|
static const uint8_t CSE7761_REG_UFREQ = 0x23; // (2) Voltage Frequency (0x0000)
|
||||||
static const uint8_t CSE7761_REG_RMSIB = 0x25; // (3) The effective value of channel B current (0x000000)
|
static const uint8_t CSE7761_REG_RMSIA = 0x24; // (3) The effective value of channel A current (0x000000)
|
||||||
static const uint8_t CSE7761_REG_RMSU = 0x26; // (3) Voltage RMS (0x000000)
|
static const uint8_t CSE7761_REG_RMSIB = 0x25; // (3) The effective value of channel B current (0x000000)
|
||||||
static const uint8_t CSE7761_REG_POWERPA = 0x2C; // (4) Channel A active power, update rate 27.2Hz (0x00000000)
|
static const uint8_t CSE7761_REG_RMSU = 0x26; // (3) Voltage RMS (0x000000)
|
||||||
static const uint8_t CSE7761_REG_POWERPB = 0x2D; // (4) Channel B active power, update rate 27.2Hz (0x00000000)
|
static const uint8_t CSE7761_REG_POWERPA = 0x2C; // (4) Channel A active power, update rate 27.2Hz (0x00000000)
|
||||||
static const uint8_t CSE7761_REG_SYSSTATUS = 0x43; // (1) System status register
|
static const uint8_t CSE7761_REG_POWERPB = 0x2D; // (4) Channel B active power, update rate 27.2Hz (0x00000000)
|
||||||
|
static const uint8_t CSE7761_REG_SYSSTATUS = 0x43; // (1) System status register
|
||||||
|
|
||||||
static const uint8_t CSE7761_REG_COEFFCHKSUM = 0x6F; // (2) Coefficient checksum
|
// static const uint8_t CSE7761_REG_COEFFOFFSET = 0x6E; // (2) Coefficient checksum offset (0xFFFF)
|
||||||
static const uint8_t CSE7761_REG_RMSIAC = 0x70; // (2) Channel A effective current conversion coefficient
|
static const uint8_t CSE7761_REG_COEFFCHKSUM = 0x6F; // (2) Coefficient checksum
|
||||||
|
static const uint8_t CSE7761_REG_RMSIAC = 0x70; // (2) Channel A effective current conversion coefficient
|
||||||
|
// static const uint8_t CSE7761_REG_RMSIBC = 0x71; // (2) Channel B effective current conversion coefficient
|
||||||
|
// static const uint8_t CSE7761_REG_RMSUC = 0x72; // (2) Effective voltage conversion coefficient
|
||||||
|
// static const uint8_t CSE7761_REG_POWERPAC = 0x73; // (2) Channel A active power conversion coefficient
|
||||||
|
// static const uint8_t CSE7761_REG_POWERPBC = 0x74; // (2) Channel B active power conversion coefficient
|
||||||
|
// static const uint8_t CSE7761_REG_POWERSC = 0x75; // (2) Apparent power conversion coefficient
|
||||||
|
// static const uint8_t CSE7761_REG_ENERGYAC = 0x76; // (2) Channel A energy conversion coefficient
|
||||||
|
// static const uint8_t CSE7761_REG_ENERGYBC = 0x77; // (2) Channel B energy conversion coefficient
|
||||||
|
|
||||||
static const uint8_t CSE7761_SPECIAL_COMMAND = 0xEA; // Start special command
|
static const uint8_t CSE7761_SPECIAL_COMMAND = 0xEA; // Start special command
|
||||||
static const uint8_t CSE7761_CMD_RESET = 0x96; // Reset command, after receiving the command, the chip resets
|
static const uint8_t CSE7761_CMD_RESET = 0x96; // Reset command, after receiving the command, the chip resets
|
||||||
static const uint8_t CSE7761_CMD_CLOSE_WRITE = 0xDC; // Close write operation
|
// static const uint8_t CSE7761_CMD_CHAN_A_SELECT = 0x5A; // Current channel A setting command, which specifies the current used to calculate apparent power,
|
||||||
static const uint8_t CSE7761_CMD_ENABLE_WRITE = 0xE5; // Enable write operation
|
// // Power factor, phase angle, instantaneous active power, instantaneous apparent power and
|
||||||
|
// // The channel indicated by the signal of power overload is channel A
|
||||||
|
// static const uint8_t CSE7761_CMD_CHAN_B_SELECT = 0xA5; // Current channel B setting command, which specifies the current used to calculate apparent power,
|
||||||
|
// // Power factor, phase angle, instantaneous active power, instantaneous apparent power and
|
||||||
|
// // The channel indicated by the signal of power overload is channel B
|
||||||
|
static const uint8_t CSE7761_CMD_CLOSE_WRITE = 0xDC; // Close write operation
|
||||||
|
static const uint8_t CSE7761_CMD_ENABLE_WRITE = 0xE5; // Enable write operation
|
||||||
|
|
||||||
enum CSE7761 { RMS_IAC, RMS_IBC, RMS_UC, POWER_PAC, POWER_PBC, POWER_SC, ENERGY_AC, ENERGY_BC };
|
enum CSE7761 { RMS_IAC, RMS_IBC, RMS_UC, POWER_PAC, POWER_PBC, POWER_SC, ENERGY_AC, ENERGY_BC };
|
||||||
|
|
||||||
@ -150,13 +166,17 @@ uint32_t CSE7761Component::read_(uint8_t reg, uint8_t size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t CSE7761Component::coefficient_by_unit_(uint32_t unit) {
|
uint32_t CSE7761Component::coefficient_by_unit_(uint32_t unit) {
|
||||||
|
uint32_t coeff = 1;
|
||||||
|
if (this->data_.model == CSE7761_MODEL_POWCT) {
|
||||||
|
coeff = 5;
|
||||||
|
}
|
||||||
switch (unit) {
|
switch (unit) {
|
||||||
case RMS_UC:
|
case RMS_UC:
|
||||||
return 0x400000 * 100 / this->data_.coefficient[RMS_UC];
|
return 0x400000 * 100 / this->data_.coefficient[RMS_UC];
|
||||||
case RMS_IAC:
|
case RMS_IAC:
|
||||||
return (0x800000 * 100 / this->data_.coefficient[RMS_IAC]) * 10; // Stay within 32 bits
|
return (0x800000 * 100 / (this->data_.coefficient[RMS_IAC] * coeff )) * 10; // Stay within 32 bits
|
||||||
case POWER_PAC:
|
case POWER_PAC:
|
||||||
return 0x80000000 / this->data_.coefficient[POWER_PAC];
|
return 0x80000000 / (this->data_.coefficient[POWER_PAC] * coeff );
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -180,10 +200,178 @@ bool CSE7761Component::chip_init_() {
|
|||||||
|
|
||||||
uint8_t sys_status = this->read_(CSE7761_REG_SYSSTATUS, 1);
|
uint8_t sys_status = this->read_(CSE7761_REG_SYSSTATUS, 1);
|
||||||
if (sys_status & 0x10) { // Write enable to protected registers (WREN)
|
if (sys_status & 0x10) { // Write enable to protected registers (WREN)
|
||||||
this->write_(CSE7761_REG_SYSCON | 0x80, 0xFF04);
|
|
||||||
this->write_(CSE7761_REG_EMUCON | 0x80, 0x1183);
|
/*
|
||||||
this->write_(CSE7761_REG_EMUCON2 | 0x80, 0x0FC1);
|
System Control Register (SYSCON) Addr:0x00 Default value: 0x0A04
|
||||||
this->write_(CSE7761_REG_PULSE1SEL | 0x80, 0x3290);
|
Bit name Function description
|
||||||
|
15-11 NC -, the default is 1
|
||||||
|
10 ADC2ON
|
||||||
|
=1, means ADC current channel B is on (Sonoff Dual R3)
|
||||||
|
=0, means ADC current channel B is closed (Pow CT)
|
||||||
|
9 NC -, the default is 1.
|
||||||
|
8-6 PGAIB[2:0] Current channel B analog gain selection highest bit
|
||||||
|
=1XX, PGA of current channel B=16 (Sonoff Dual R3)
|
||||||
|
=011, PGA of current channel B=8
|
||||||
|
=010, PGA of current channel B=4
|
||||||
|
=001, PGA of current channel B=2
|
||||||
|
=000, PGA of current channel B=1 (Pow CT)
|
||||||
|
5-3 PGAU[2:0] Highest bit of voltage channel analog gain selection
|
||||||
|
=1XX, PGA of voltage U=16
|
||||||
|
=011, PGA of voltage U=8
|
||||||
|
=010, PGA of voltage U=4
|
||||||
|
=001, PGA of voltage U=2
|
||||||
|
=000, PGA of voltage U=1 (Sonoff Dual R3 / Pow CT)
|
||||||
|
2-0 PGAIA[2:0] Current channel A analog gain selection highest bit
|
||||||
|
=1XX, PGA of current channel A=16 (Sonoff Dual R3)
|
||||||
|
=011, PGA of current channel A=8
|
||||||
|
=010, PGA of current channel A=4
|
||||||
|
=001, PGA of current channel A=2
|
||||||
|
=000, PGA of current channel A=1 (Pow CT)
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (this->data_.model == CSE7761_MODEL_POWCT) {
|
||||||
|
this->write_(CSE7761_REG_SYSCON | 0x80, 0xFE00); //POW CT + enable channel B
|
||||||
|
} else {
|
||||||
|
this->write_(CSE7761_REG_SYSCON | 0x80, 0xFF04); // Sonoff Dual R3
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Energy Measure Control Register (EMUCON) Addr:0x01 Default value: 0x0000
|
||||||
|
Bit name Function description
|
||||||
|
15-14 Tsensor_Step[1:0] Measurement steps of temperature sensor:
|
||||||
|
=2'b00 The first step of temperature sensor measurement, the Offset of OP1 and OP2 is +/+. (Sonoff Dual R3 / Pow CT)
|
||||||
|
=2'b01 The second step of temperature sensor measurement, the Offset of OP1 and OP2 is +/-.
|
||||||
|
=2'b10 The third step of temperature sensor measurement, the Offset of OP1 and OP2 is -/+.
|
||||||
|
=2'b11 The fourth step of temperature sensor measurement, the Offset of OP1 and OP2 is -/-.
|
||||||
|
After measuring these four results and averaging, the AD value of the current measured temperature can be obtained.
|
||||||
|
13 tensor_en Temperature measurement module control
|
||||||
|
=0 when the temperature measurement module is closed; (Sonoff Dual R3 / Pow CT)
|
||||||
|
=1 when the temperature measurement module is turned on;
|
||||||
|
12 comp_off Comparator module close signal:
|
||||||
|
=0 when the comparator module is in working state
|
||||||
|
=1 when the comparator module is off (Sonoff Dual R3 / Pow CT)
|
||||||
|
11-10 Pmode[1:0] Selection of active energy calculation method:
|
||||||
|
Pmode =00, both positive and negative active energy participate in the accumulation,
|
||||||
|
the accumulation method is algebraic sum mode, the reverse REVQ symbol indicates to active power; (Sonoff Dual R3 / Pow CT)
|
||||||
|
Pmode = 01, only accumulate positive active energy;
|
||||||
|
Pmode = 10, both positive and negative active energy participate in the accumulation,
|
||||||
|
and the accumulation method is absolute value method. No reverse active power indication;
|
||||||
|
Pmode =11, reserved, the mode is the same as Pmode =00
|
||||||
|
9 NC -
|
||||||
|
8 ZXD1 The initial value of ZX output is 0, and different waveforms are output according to the configuration of ZXD1 and ZXD0:
|
||||||
|
=0, it means that the ZX output changes only at the selected zero-crossing point (Sonoff Dual R3 / Pow CT)
|
||||||
|
=1, indicating that the ZX output changes at both the positive and negative zero crossings
|
||||||
|
7 ZXD0
|
||||||
|
=0, indicates that the positive zero-crossing point is selected as the zero-crossing detection signal (Sonoff Dual R3 / Pow CT)
|
||||||
|
=1, indicating that the negative zero-crossing point is selected as the zero-crossing detection signal
|
||||||
|
6 HPFIBOFF
|
||||||
|
=0, enable current channel B digital high-pass filter (Sonoff Dual R3)
|
||||||
|
=1, turn off the digital high-pass filter of current channel B (Pow CT)
|
||||||
|
5 HPFIAOFF
|
||||||
|
=0, enable current channel A digital high-pass filter (Sonoff Dual R3 / Pow CT)
|
||||||
|
=1, turn off the digital high-pass filter of current channel A
|
||||||
|
4 HPFUOFF
|
||||||
|
=0, enable U channel digital high pass filter (Sonoff Dual R3 / Pow CT)
|
||||||
|
=1, turn off the U channel digital high-pass filter
|
||||||
|
3-2 NC -
|
||||||
|
1 PBRUN
|
||||||
|
=1, enable PFB pulse output and active energy register accumulation; (Sonoff Dual R3 / Pow CT)
|
||||||
|
=0 (default), turn off PFB pulse output and active energy register accumulation.
|
||||||
|
0 PARUN
|
||||||
|
=1, enable PFA pulse output and active energy register accumulation; (Sonoff Dual R3 / Pow CT)
|
||||||
|
=0 (default), turn off PFA pulse output and active energy register accumulation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
this->write_(CSE7761_REG_EMUCON | 0x80, 0x1183); //Same as Sonoff Dual R3 (enable channel B) + zero crossing on both negative and positive signal
|
||||||
|
|
||||||
|
/*
|
||||||
|
Energy Measure Control Register (EMUCON2) Addr: 0x13 Default value: 0x0001
|
||||||
|
Bit name Function description
|
||||||
|
15-13 NC -
|
||||||
|
12 SDOCmos
|
||||||
|
=1, SDO pin CMOS open-drain output
|
||||||
|
=0, SDO pin CMOS output (Sonoff Dual R3 / Pow CT)
|
||||||
|
11 EPB_CB Energy_PB clear signal control, the default is 0, and it needs to be configured to 1 in UART mode.
|
||||||
|
Clear after reading is not supported in UART mode
|
||||||
|
=1, Energy_PB will not be cleared after reading; (Sonoff Dual R3 / Pow CT)
|
||||||
|
=0, Energy_PB is cleared after reading;
|
||||||
|
10 EPA_CB Energy_PA clear signal control, the default is 0, it needs to be configured to 1 in UART mode,
|
||||||
|
Clear after reading is not supported in UART mode
|
||||||
|
=1, Energy_PA will not be cleared after reading; (Sonoff Dual R3 / Pow CT)
|
||||||
|
=0, Energy_PA is cleared after reading;
|
||||||
|
9-8 DUPSEL[1:0] Average register update frequency control
|
||||||
|
=00, Update frequency 3.4Hz
|
||||||
|
=01, Update frequency 6.8Hz
|
||||||
|
=10, Update frequency 13.65Hz
|
||||||
|
=11, Update frequency 27.3Hz (Sonoff Dual R3 / Pow CT)
|
||||||
|
7 CHS_IB Current channel B measurement selection signal
|
||||||
|
=1, measure the current of channel B (Sonoff Dual R3 / Pow CT)
|
||||||
|
=0, measure the internal temperature of the chip
|
||||||
|
6 PfactorEN Power factor function enable
|
||||||
|
=1, turn on the power factor output function (Sonoff Dual R3 / Pow CT)
|
||||||
|
=0, turn off the power factor output function
|
||||||
|
5 WaveEN Waveform data, instantaneous data output enable signal
|
||||||
|
=1, turn on the waveform data output function (if frequency enable)
|
||||||
|
=0, turn off the waveform data output function (Sonoff Dual R3 / Pow CT)
|
||||||
|
4 SAGEN Voltage drop detection enable signal, WaveEN=1 must be configured first
|
||||||
|
=1, turn on the voltage drop detection function
|
||||||
|
=0, turn off the voltage drop detection function (Sonoff Dual R3 / Pow CT)
|
||||||
|
3 OverEN Overvoltage, overcurrent, and overload detection enable signal, WaveEN=1 must be configured first
|
||||||
|
=1, turn on the overvoltage, overcurrent, and overload detection functions
|
||||||
|
=0, turn off the overvoltage, overcurrent, and overload detection functions (Sonoff Dual R3 / Pow CT)
|
||||||
|
2 ZxEN Zero-crossing detection, phase angle, voltage frequency measurement enable signal
|
||||||
|
=1, turn on the zero-crossing detection, phase angle, and voltage frequency measurement functions (if frequency enable)
|
||||||
|
=0, disable zero-crossing detection, phase angle, voltage frequency measurement functions (Sonoff Dual R3 / Pow CT)
|
||||||
|
1 PeakEN Peak detect enable signal
|
||||||
|
=1, turn on the peak detection function
|
||||||
|
=0, turn off the peak detection function (Sonoff Dual R3 / Pow CT)
|
||||||
|
0 NC Default is 1
|
||||||
|
*/
|
||||||
|
|
||||||
|
this->write_(CSE7761_REG_EMUCON2 | 0x80, 0x0FE5); // Sonoff Dual R3 / Pow CT + frequency measure enable
|
||||||
|
// !!!!!!!! CLEAN MEEEEEE UPPPPPP !!!!!!!!!!!!!!
|
||||||
|
// if (this->frequency_sensor_ != nullptr) {
|
||||||
|
// this->write_(CSE7761_REG_EMUCON2 | 0x80, 0x0FE5); // Sonoff Dual R3 / Pow CT + frequency measure enable
|
||||||
|
// } else {
|
||||||
|
// this->write_(CSE7761_REG_EMUCON2 | 0x80, 0x0FC1); // Sonoff Dual R3 / Pow CT
|
||||||
|
// }
|
||||||
|
// !!!!!!!! CLEAN MEEEEEE UPPPPPP !!!!!!!!!!!!!!
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Pin function output selection register (PULSE1SEL) Addr: 0x1D Default value: 0x3210
|
||||||
|
Bit name Function description
|
||||||
|
15-13 NC -
|
||||||
|
12 SDOCmos
|
||||||
|
=1, SDO pin CMOS open-drain output
|
||||||
|
|
||||||
|
15-12 NC NC, the default value is 4'b0011
|
||||||
|
11-8 NC NC, the default value is 4'b0010
|
||||||
|
7-4 P2Sel Pulse2 Pin output function selection, see the table below
|
||||||
|
3-0 P1Sel Pulse1 Pin output function selection, see the table below
|
||||||
|
|
||||||
|
Table Pulsex function output selection list
|
||||||
|
Pxsel Select description
|
||||||
|
0000 Output of energy metering calibration pulse PFA
|
||||||
|
0001 The output of the energy metering calibration pulse PFB
|
||||||
|
0010 Comparator indication signal comp_sign
|
||||||
|
0011 Interrupt signal IRQ output (the default is high level, if it is an interrupt, set to 0)
|
||||||
|
0100 Signal indication of power overload: only PA or PB can be selected
|
||||||
|
0101 Channel A negative power indicator signal
|
||||||
|
0110 Channel B negative power indicator signal
|
||||||
|
0111 Instantaneous value update interrupt output
|
||||||
|
1000 Average update interrupt output
|
||||||
|
1001 Voltage channel zero-crossing signal output (Tasmota add zero-cross detection)
|
||||||
|
1010 Current channel A zero-crossing signal output
|
||||||
|
1011 Current channel B zero crossing signal output
|
||||||
|
1100 Voltage channel overvoltage indication signal output
|
||||||
|
1101 Voltage channel undervoltage indication signal output
|
||||||
|
1110 Current channel A overcurrent signal indication output
|
||||||
|
1111 Current channel B overcurrent signal indication output
|
||||||
|
*/
|
||||||
|
|
||||||
|
// this->write_(CSE7761_REG_PULSE1SEL | 0x80, 0x3290); // Enable zero crosing signal output on function pin
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGD(TAG, "Write failed at chip_init");
|
ESP_LOGD(TAG, "Write failed at chip_init");
|
||||||
return false;
|
return false;
|
||||||
@ -200,6 +388,9 @@ void CSE7761Component::get_data_() {
|
|||||||
uint32_t value = this->read_(CSE7761_REG_RMSU, 3);
|
uint32_t value = this->read_(CSE7761_REG_RMSU, 3);
|
||||||
this->data_.voltage_rms = (value >= 0x800000) ? 0 : value;
|
this->data_.voltage_rms = (value >= 0x800000) ? 0 : value;
|
||||||
|
|
||||||
|
value = this->read_(CSE7761_REG_UFREQ, 2);
|
||||||
|
this->data_.frequency = (value >= 0x8000) ? 0 : value;
|
||||||
|
|
||||||
value = this->read_(CSE7761_REG_RMSIA, 3);
|
value = this->read_(CSE7761_REG_RMSIA, 3);
|
||||||
this->data_.current_rms[0] = ((value >= 0x800000) || (value < 1600)) ? 0 : value; // No load threshold of 10mA
|
this->data_.current_rms[0] = ((value >= 0x800000) || (value < 1600)) ? 0 : value; // No load threshold of 10mA
|
||||||
value = this->read_(CSE7761_REG_POWERPA, 4);
|
value = this->read_(CSE7761_REG_POWERPA, 4);
|
||||||
@ -217,6 +408,10 @@ void CSE7761Component::get_data_() {
|
|||||||
this->voltage_sensor_->publish_state(voltage);
|
this->voltage_sensor_->publish_state(voltage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float freq = (this->data_.frequency) ? ((float) CSE7761_FREF / 8 / this->data_.frequency) : 0; // Hz
|
||||||
|
if (this->frequency_sensor_ != nullptr) {
|
||||||
|
this->frequency_sensor_->publish_state(freq);
|
||||||
|
}
|
||||||
for (uint8_t channel = 0; channel < 2; channel++) {
|
for (uint8_t channel = 0; channel < 2; channel++) {
|
||||||
// Active power = PowerPA * PowerPAC * 1000 / 0x80000000
|
// Active power = PowerPA * PowerPAC * 1000 / 0x80000000
|
||||||
float active_power = (float) this->data_.active_power[channel] / this->coefficient_by_unit_(POWER_PAC); // W
|
float active_power = (float) this->data_.active_power[channel] / this->coefficient_by_unit_(POWER_PAC); // W
|
||||||
|
@ -7,15 +7,23 @@
|
|||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace cse7761 {
|
namespace cse7761 {
|
||||||
|
|
||||||
|
enum SonoffModel : uint8_t
|
||||||
|
{
|
||||||
|
CSE7761_MODEL_DUALR3 = 0,
|
||||||
|
CSE7761_MODEL_POWCT
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
struct CSE7761DataStruct {
|
struct CSE7761DataStruct {
|
||||||
uint32_t frequency = 0;
|
|
||||||
uint32_t voltage_rms = 0;
|
uint32_t voltage_rms = 0;
|
||||||
|
uint32_t frequency = 0;
|
||||||
uint32_t current_rms[2] = {0};
|
uint32_t current_rms[2] = {0};
|
||||||
uint32_t energy[2] = {0};
|
uint32_t energy[2] = {0};
|
||||||
uint32_t active_power[2] = {0};
|
uint32_t active_power[2] = {0};
|
||||||
uint16_t coefficient[8] = {0};
|
uint16_t coefficient[8] = {0};
|
||||||
uint8_t energy_update = 0;
|
uint8_t energy_update = 0;
|
||||||
bool ready = false;
|
bool ready = false;
|
||||||
|
SonoffModel model = CSE7761_MODEL_DUALR3;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// This class implements support for the CSE7761 UART power sensor.
|
/// This class implements support for the CSE7761 UART power sensor.
|
||||||
@ -26,6 +34,8 @@ class CSE7761Component : public PollingComponent, public uart::UARTDevice {
|
|||||||
void set_current_1_sensor(sensor::Sensor *current_sensor_1) { current_sensor_1_ = current_sensor_1; }
|
void set_current_1_sensor(sensor::Sensor *current_sensor_1) { current_sensor_1_ = current_sensor_1; }
|
||||||
void set_active_power_2_sensor(sensor::Sensor *power_sensor_2) { power_sensor_2_ = power_sensor_2; }
|
void set_active_power_2_sensor(sensor::Sensor *power_sensor_2) { power_sensor_2_ = power_sensor_2; }
|
||||||
void set_current_2_sensor(sensor::Sensor *current_sensor_2) { current_sensor_2_ = current_sensor_2; }
|
void set_current_2_sensor(sensor::Sensor *current_sensor_2) { current_sensor_2_ = current_sensor_2; }
|
||||||
|
void set_frequency_sensor(sensor::Sensor *frequency_sensor) { frequency_sensor_ = frequency_sensor; }
|
||||||
|
void set_model(SonoffModel model) { data_.model = model; }
|
||||||
void setup() override;
|
void setup() override;
|
||||||
void dump_config() override;
|
void dump_config() override;
|
||||||
float get_setup_priority() const override;
|
float get_setup_priority() const override;
|
||||||
@ -38,6 +48,7 @@ class CSE7761Component : public PollingComponent, public uart::UARTDevice {
|
|||||||
sensor::Sensor *current_sensor_1_{nullptr};
|
sensor::Sensor *current_sensor_1_{nullptr};
|
||||||
sensor::Sensor *power_sensor_2_{nullptr};
|
sensor::Sensor *power_sensor_2_{nullptr};
|
||||||
sensor::Sensor *current_sensor_2_{nullptr};
|
sensor::Sensor *current_sensor_2_{nullptr};
|
||||||
|
sensor::Sensor *frequency_sensor_{nullptr};
|
||||||
CSE7761DataStruct data_;
|
CSE7761DataStruct data_;
|
||||||
|
|
||||||
void write_(uint8_t reg, uint16_t data);
|
void write_(uint8_t reg, uint16_t data);
|
||||||
|
@ -4,13 +4,16 @@ from esphome.components import sensor, uart
|
|||||||
from esphome.const import (
|
from esphome.const import (
|
||||||
CONF_ID,
|
CONF_ID,
|
||||||
CONF_VOLTAGE,
|
CONF_VOLTAGE,
|
||||||
|
CONF_FREQUENCY,
|
||||||
DEVICE_CLASS_CURRENT,
|
DEVICE_CLASS_CURRENT,
|
||||||
DEVICE_CLASS_POWER,
|
DEVICE_CLASS_POWER,
|
||||||
DEVICE_CLASS_VOLTAGE,
|
DEVICE_CLASS_VOLTAGE,
|
||||||
|
ICON_CURRENT_AC,
|
||||||
STATE_CLASS_MEASUREMENT,
|
STATE_CLASS_MEASUREMENT,
|
||||||
UNIT_VOLT,
|
UNIT_VOLT,
|
||||||
UNIT_AMPERE,
|
UNIT_AMPERE,
|
||||||
UNIT_WATT,
|
UNIT_WATT,
|
||||||
|
UNIT_HERTZ,
|
||||||
)
|
)
|
||||||
|
|
||||||
CODEOWNERS = ["@berfenger"]
|
CODEOWNERS = ["@berfenger"]
|
||||||
@ -25,6 +28,13 @@ CONF_CURRENT_1 = "current_1"
|
|||||||
CONF_CURRENT_2 = "current_2"
|
CONF_CURRENT_2 = "current_2"
|
||||||
CONF_ACTIVE_POWER_1 = "active_power_1"
|
CONF_ACTIVE_POWER_1 = "active_power_1"
|
||||||
CONF_ACTIVE_POWER_2 = "active_power_2"
|
CONF_ACTIVE_POWER_2 = "active_power_2"
|
||||||
|
CONF_SONOFF_MODEL = "sonoff_model"
|
||||||
|
|
||||||
|
SonoffModel = cse7761_ns.enum("SonoffModel")
|
||||||
|
SONOFF_MODEL = {
|
||||||
|
"DUALR3": SonoffModel.CSE7761_MODEL_DUALR3,
|
||||||
|
"POWCT": SonoffModel.CSE7761_MODEL_POWCT,
|
||||||
|
}
|
||||||
|
|
||||||
CONFIG_SCHEMA = (
|
CONFIG_SCHEMA = (
|
||||||
cv.Schema(
|
cv.Schema(
|
||||||
@ -60,6 +70,13 @@ CONFIG_SCHEMA = (
|
|||||||
device_class=DEVICE_CLASS_POWER,
|
device_class=DEVICE_CLASS_POWER,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
),
|
),
|
||||||
|
cv.Optional(CONF_FREQUENCY): sensor.sensor_schema(
|
||||||
|
unit_of_measurement=UNIT_HERTZ,
|
||||||
|
icon=ICON_CURRENT_AC,
|
||||||
|
accuracy_decimals=1,
|
||||||
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_SONOFF_MODEL, default="dualR3"): cv.enum(SONOFF_MODEL, upper=True),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.extend(cv.polling_component_schema("60s"))
|
.extend(cv.polling_component_schema("60s"))
|
||||||
@ -82,9 +99,12 @@ async def to_code(config):
|
|||||||
CONF_CURRENT_2,
|
CONF_CURRENT_2,
|
||||||
CONF_ACTIVE_POWER_1,
|
CONF_ACTIVE_POWER_1,
|
||||||
CONF_ACTIVE_POWER_2,
|
CONF_ACTIVE_POWER_2,
|
||||||
|
CONF_FREQUENCY,
|
||||||
]:
|
]:
|
||||||
if key not in config:
|
if key not in config:
|
||||||
continue
|
continue
|
||||||
conf = config[key]
|
conf = config[key]
|
||||||
sens = await sensor.new_sensor(conf)
|
sens = await sensor.new_sensor(conf)
|
||||||
cg.add(getattr(var, f"set_{key}_sensor")(sens))
|
cg.add(getattr(var, f"set_{key}_sensor")(sens))
|
||||||
|
|
||||||
|
cg.add(var.set_model(config[CONF_SONOFF_MODEL]))
|
Loading…
Reference in New Issue
Block a user