ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
selec_meter_registers.h
Go to the documentation of this file.
1#pragma once
2
3#include <cstdint>
4
5namespace esphome::selec_meter {
6
7/* PHASE STATUS REGISTERS */
8static constexpr uint16_t SELEC_TOTAL_ACTIVE_ENERGY = 0x0000;
9static constexpr uint16_t SELEC_IMPORT_ACTIVE_ENERGY = 0x0002;
10static constexpr uint16_t SELEC_EXPORT_ACTIVE_ENERGY = 0x0004;
11static constexpr uint16_t SELEC_TOTAL_REACTIVE_ENERGY = 0x0006;
12static constexpr uint16_t SELEC_IMPORT_REACTIVE_ENERGY = 0x0008;
13static constexpr uint16_t SELEC_EXPORT_REACTIVE_ENERGY = 0x000A;
14static constexpr uint16_t SELEC_APPARENT_ENERGY = 0x000C;
15static constexpr uint16_t SELEC_ACTIVE_POWER = 0x000E;
16static constexpr uint16_t SELEC_REACTIVE_POWER = 0x0010;
17static constexpr uint16_t SELEC_APPARENT_POWER = 0x0012;
18static constexpr uint16_t SELEC_VOLTAGE = 0x0014;
19static constexpr uint16_t SELEC_CURRENT = 0x0016;
20static constexpr uint16_t SELEC_POWER_FACTOR = 0x0018;
21static constexpr uint16_t SELEC_FREQUENCY = 0x001A;
22static constexpr uint16_t SELEC_MAXIMUM_DEMAND_ACTIVE_POWER = 0x001C;
23static constexpr uint16_t SELEC_MAXIMUM_DEMAND_REACTIVE_POWER = 0x001E;
24static constexpr uint16_t SELEC_MAXIMUM_DEMAND_APPARENT_POWER = 0x0020;
25
26/* EM4M REGISTERS -- offsets are register indices from input register 30000 */
27static constexpr uint8_t EM4M_REGISTER_COUNT = 114; // 114 x 16-bit registers
28
29/* EM4M -- common quantities shared with the EM2M sensor keys */
30static constexpr uint16_t EM4M_VOLTAGE = 0x0006; // Average Voltage LN
31static constexpr uint16_t EM4M_CURRENT = 0x0016; // Average Current
32static constexpr uint16_t EM4M_ACTIVE_POWER = 0x002A; // Total kW
33static constexpr uint16_t EM4M_REACTIVE_POWER = 0x002C; // Total kVAr
34static constexpr uint16_t EM4M_APPARENT_POWER = 0x002E; // Total kVA
35static constexpr uint16_t EM4M_POWER_FACTOR = 0x0036; // Average PF
36static constexpr uint16_t EM4M_FREQUENCY = 0x0038;
37static constexpr uint16_t EM4M_MAXIMUM_DEMAND_ACTIVE_POWER = 0x0046;
38static constexpr uint16_t EM4M_MAXIMUM_DEMAND_REACTIVE_POWER = 0x0048;
39static constexpr uint16_t EM4M_MAXIMUM_DEMAND_APPARENT_POWER = 0x004A;
40static constexpr uint16_t EM4M_IMPORT_ACTIVE_ENERGY = 0x0058; // Total kWh - Import
41static constexpr uint16_t EM4M_EXPORT_ACTIVE_ENERGY = 0x005A; // Total kWh - Export
42static constexpr uint16_t EM4M_IMPORT_REACTIVE_ENERGY = 0x0068; // Total kVArh - Import
43static constexpr uint16_t EM4M_EXPORT_REACTIVE_ENERGY = 0x006A; // Total kVArh - Export
44static constexpr uint16_t EM4M_AVERAGE_VOLTAGE_LL = 0x000E; // Average Voltage LL
45
46// Net (import - export) energy totals, split by source. Only meaningful when the
47// meter's "Dual Source" setting is Yes; DG registers read 0 on single-source installs.
48static constexpr uint16_t EM4M_NET_ACTIVE_ENERGY_MAINS = 0x003A; // Total Net kWh (MAINS)
49static constexpr uint16_t EM4M_NET_REACTIVE_ENERGY_MAINS = 0x003C; // Total Net kVArh (MAINS)
50static constexpr uint16_t EM4M_NET_APPARENT_ENERGY_MAINS = 0x003E; // Total Net kVAh (MAINS)
51static constexpr uint16_t EM4M_NET_ACTIVE_ENERGY_DG = 0x0040; // Total Net kWh (DG)
52static constexpr uint16_t EM4M_NET_REACTIVE_ENERGY_DG = 0x0042; // Total Net kVArh (DG)
53static constexpr uint16_t EM4M_NET_APPARENT_ENERGY_DG = 0x0044; // Total Net kVAh (DG)
54
55/* EM4M -- per-phase quantities, no EM2M equivalent */
56static constexpr uint16_t EM4M_VOLTAGE_L1 = 0x0000; // Voltage V1N
57static constexpr uint16_t EM4M_VOLTAGE_L2 = 0x0002; // Voltage V2N
58static constexpr uint16_t EM4M_VOLTAGE_L3 = 0x0004; // Voltage V3N
59static constexpr uint16_t EM4M_VOLTAGE_L12 = 0x0008; // Voltage V12
60static constexpr uint16_t EM4M_VOLTAGE_L23 = 0x000A; // Voltage V23
61static constexpr uint16_t EM4M_VOLTAGE_L31 = 0x000C; // Voltage V31
62static constexpr uint16_t EM4M_CURRENT_L1 = 0x0010;
63static constexpr uint16_t EM4M_CURRENT_L2 = 0x0012;
64static constexpr uint16_t EM4M_CURRENT_L3 = 0x0014;
65static constexpr uint16_t EM4M_ACTIVE_POWER_L1 = 0x0018; // kW1
66static constexpr uint16_t EM4M_ACTIVE_POWER_L2 = 0x001A; // kW2
67static constexpr uint16_t EM4M_ACTIVE_POWER_L3 = 0x001C; // kW3
68static constexpr uint16_t EM4M_REACTIVE_POWER_L1 = 0x001E; // kVAr1
69static constexpr uint16_t EM4M_REACTIVE_POWER_L2 = 0x0020; // kVAr2
70static constexpr uint16_t EM4M_REACTIVE_POWER_L3 = 0x0022; // kVAr3
71static constexpr uint16_t EM4M_APPARENT_POWER_L1 = 0x0024; // kVA1
72static constexpr uint16_t EM4M_APPARENT_POWER_L2 = 0x0026; // kVA2
73static constexpr uint16_t EM4M_APPARENT_POWER_L3 = 0x0028; // kVA3
74static constexpr uint16_t EM4M_POWER_FACTOR_L1 = 0x0030;
75static constexpr uint16_t EM4M_POWER_FACTOR_L2 = 0x0032;
76static constexpr uint16_t EM4M_POWER_FACTOR_L3 = 0x0034;
77static constexpr uint16_t EM4M_IMPORT_ACTIVE_ENERGY_L1 = 0x004C; // kWh1 - Import
78static constexpr uint16_t EM4M_IMPORT_ACTIVE_ENERGY_L2 = 0x004E; // kWh2 - Import
79static constexpr uint16_t EM4M_IMPORT_ACTIVE_ENERGY_L3 = 0x0050; // kWh3 - Import
80static constexpr uint16_t EM4M_EXPORT_ACTIVE_ENERGY_L1 = 0x0052; // kWh1 - Export
81static constexpr uint16_t EM4M_EXPORT_ACTIVE_ENERGY_L2 = 0x0054; // kWh2 - Export
82static constexpr uint16_t EM4M_EXPORT_ACTIVE_ENERGY_L3 = 0x0056; // kWh3 - Export
83static constexpr uint16_t EM4M_IMPORT_REACTIVE_ENERGY_L1 = 0x005C; // kVArh1 - Import
84static constexpr uint16_t EM4M_IMPORT_REACTIVE_ENERGY_L2 = 0x005E; // kVArh2 - Import
85static constexpr uint16_t EM4M_IMPORT_REACTIVE_ENERGY_L3 = 0x0060; // kVArh3 - Import
86static constexpr uint16_t EM4M_EXPORT_REACTIVE_ENERGY_L1 = 0x0062; // kVArh1 - Export
87static constexpr uint16_t EM4M_EXPORT_REACTIVE_ENERGY_L2 = 0x0064; // kVArh2 - Export
88static constexpr uint16_t EM4M_EXPORT_REACTIVE_ENERGY_L3 = 0x0066; // kVArh3 - Export
89static constexpr uint16_t EM4M_APPARENT_ENERGY_L1 = 0x006C; // kVAh-1
90static constexpr uint16_t EM4M_APPARENT_ENERGY_L2 = 0x006E; // kVAh-2
91static constexpr uint16_t EM4M_APPARENT_ENERGY_L3 = 0x0070; // kVAh-3
92
93// The decoder reads L2/L3 as the L1 register plus one or two strides; the L2/L3 names above
94// document the datasheet and are checked against that stride here.
95static constexpr uint16_t EM4M_PHASE_STRIDE = 2;
96#define SELEC_EM4M_CHECK_STRIDE(name) \
97 static_assert(EM4M_##name##_L2 == EM4M_##name##_L1 + EM4M_PHASE_STRIDE && \
98 EM4M_##name##_L3 == EM4M_##name##_L1 + 2 * EM4M_PHASE_STRIDE, \
99 #name " per-phase registers must be EM4M_PHASE_STRIDE apart");
102SELEC_EM4M_CHECK_STRIDE(ACTIVE_POWER)
103SELEC_EM4M_CHECK_STRIDE(REACTIVE_POWER)
104SELEC_EM4M_CHECK_STRIDE(APPARENT_POWER)
105SELEC_EM4M_CHECK_STRIDE(POWER_FACTOR)
106SELEC_EM4M_CHECK_STRIDE(IMPORT_ACTIVE_ENERGY)
107SELEC_EM4M_CHECK_STRIDE(EXPORT_ACTIVE_ENERGY)
108SELEC_EM4M_CHECK_STRIDE(IMPORT_REACTIVE_ENERGY)
109SELEC_EM4M_CHECK_STRIDE(EXPORT_REACTIVE_ENERGY)
110SELEC_EM4M_CHECK_STRIDE(APPARENT_ENERGY)
111#undef SELEC_EM4M_CHECK_STRIDE
112
113// Far outside the main 0-113 register block; read via a separate Modbus transaction.
114static constexpr uint16_t EM4M_SERIAL_NUMBER = 0x02AC; // Serial No. (Hex), 30684
115static constexpr uint16_t EM4M_DG_SENSING = 0x02C6; // DG Sensing (1: Pass, 0: Fail), 30710
116
117} // namespace esphome::selec_meter
SELEC_EM4M_CHECK_STRIDE(CURRENT) SELEC_EM4M_CHECK_STRIDE(ACTIVE_POWER) SELEC_EM4M_CHECK_STRIDE(REACTIVE_POWER) SELEC_EM4M_CHECK_STRIDE(APPARENT_POWER) SELEC_EM4M_CHECK_STRIDE(POWER_FACTOR) SELEC_EM4M_CHECK_STRIDE(IMPORT_ACTIVE_ENERGY) SELEC_EM4M_CHECK_STRIDE(EXPORT_ACTIVE_ENERGY) SELEC_EM4M_CHECK_STRIDE(IMPORT_REACTIVE_ENERGY) SELEC_EM4M_CHECK_STRIDE(EXPORT_REACTIVE_ENERGY) SELEC_EM4M_CHECK_STRIDE(APPARENT_ENERGY) static const expr uint16_t EM4M_SERIAL_NUMBER=0x02AC