|
25 | 25 | * Regs 92-97: Generator registers — SPE has no generator input, all zero |
26 | 26 | - offgrid_protocol flag prevents reading VPP registers (30000+) which return garbage on this firmware |
27 | 27 |
|
| 28 | +Grid-Tie Export Controls (confirmed via nicauswu field data, Issue #322): |
| 29 | +- Holding regs 115-124 control grid-tied export behaviour (not present on SPF) |
| 30 | +- Cross-referenced against Off-Grid Protocol V0.26 (docs/developer/protocol-offgrid.md) |
| 31 | +
|
28 | 32 | DTC Identification: |
29 | 33 | - This device returned DTC 64541 (unknown, not in standard mapping) in the Issue #212 scan |
30 | 34 | - Auto-detection falls back to legacy range analysis for this device |
|
56 | 60 | for _addr in (92, 93, 94, 95, 96, 97): |
57 | 61 | _spe_input_regs.pop(_addr, None) |
58 | 62 |
|
| 63 | +# ── Add grid export energy registers (SPE grid-tied, not present in SPF) ───── |
| 64 | +# Reg 44 = DTC (Device Type Code) per Off-Grid Protocol V0.26 — NOT overridden here. |
| 65 | +# Reg 45 = Export to Grid Today — single 16-bit register (scale 0.1 kWh) per V0.26. |
| 66 | +# Nicauswu's implementation also reads this as a standalone register. Max 6553.5 kWh |
| 67 | +# is sufficient for daily totals. |
| 68 | +# Regs 46/47 = Export to Grid Total — 32-bit pair, combined scale 0.1 kWh per V0.26. |
| 69 | +_spe_input_regs.update({ |
| 70 | + 45: { |
| 71 | + 'name': 'energy_to_grid_today', 'scale': 0.1, 'unit': 'kWh', |
| 72 | + 'desc': 'Grid export energy today (single 16-bit register). Protocol V0.26 reg 45.', |
| 73 | + }, |
| 74 | + 46: { |
| 75 | + 'name': 'energy_to_grid_total_high', 'scale': 1, 'unit': '', 'pair': 47, |
| 76 | + 'desc': 'Grid export energy total (HIGH word). Protocol V0.26 reg 46.', |
| 77 | + }, |
| 78 | + 47: { |
| 79 | + 'name': 'energy_to_grid_total_low', 'scale': 1, 'unit': '', 'pair': 46, |
| 80 | + 'combined_scale': 0.1, 'combined_unit': 'kWh', |
| 81 | + 'desc': 'Grid export energy total (LOW word). Protocol V0.26 reg 47.', |
| 82 | + }, |
| 83 | +}) |
| 84 | + |
59 | 85 | # ── Remap energy registers: SPF names are semantically wrong for SPE ────────── |
60 | 86 |
|
61 | 87 | # Regs 64/65: SPF labels these "AC discharge energy today" (battery-to-load via inverter). |
|
123 | 149 | 'description': 'Single-phase hybrid inverter with battery storage (8-12kW)', |
124 | 150 | 'notes': ( |
125 | 151 | 'Uses SPF-compatible 0-97 register range with key remapping. ' |
| 152 | + 'Reg 45 = grid export energy today (single 16-bit, 0.1 kWh). ' |
| 153 | + 'Regs 46/47 = grid export energy total (32-bit pair). ' |
126 | 154 | 'Regs 64/65 = grid import energy (not AC discharge), ' |
127 | 155 | 'Regs 85-88 = load energy today/total (not operational discharge). ' |
128 | 156 | 'Regs 36/37 (ac_input_power) excluded — produces 429GW overflow. ' |
129 | | - 'No generator input. PV register validation pending daytime scan.' |
| 157 | + 'No generator input. ' |
| 158 | + 'Grid-tie controls at holding regs 115-124 (confirmed via Issue #322, Protocol V0.26).' |
130 | 159 | ), |
131 | 160 | # NOTE: offgrid_protocol refers to the REGISTER LAYOUT (SPF-style 0-97), |
132 | 161 | # not the inverter's grid capability. The SPE supports grid-tied operation |
|
139 | 168 | # entity values seen in Issue #212 scan (charge_current, battery_type, |
140 | 169 | # ac_input_mode, output_config, charge_config all reading correctly). |
141 | 170 | **SPF_3000_6000_ES_PLUS['holding_registers'], |
| 171 | + |
| 172 | + # ── SPE grid-tie export controls ────────────────────────────────────── |
| 173 | + # All confirmed via nicauswu field data (Issue #322). |
| 174 | + # Cross-referenced against Off-Grid Protocol V0.26 holding register table. |
| 175 | + # Ranges and names from V0.26 unless noted. |
| 176 | + |
| 177 | + # 115: uwFeedEn — grid feed enable |
| 178 | + 115: {'name': 'spe_grid_export_enable', 'scale': 1, 'unit': '', 'access': 'RW', |
| 179 | + 'desc': 'Grid export enable (uwFeedEn): 0=Disabled, 1=Enabled', |
| 180 | + 'values': {0: 'Disabled', 1: 'Enabled'}}, |
| 181 | + |
| 182 | + # 116: uwLoadFirst — output priority: charge first / load first / feed first |
| 183 | + 116: {'name': 'spe_output_priority', 'scale': 1, 'unit': '', 'access': 'RW', |
| 184 | + 'desc': 'Output priority (uwLoadFirst): 0=Charge first, 1=Load first, 2=Feed first', |
| 185 | + 'values': {0: 'Charge First', 1: 'Load First', 2: 'Feed First'}}, |
| 186 | + |
| 187 | + # 117: uwFeedRange — grid compliance region |
| 188 | + 117: {'name': 'spe_feed_range', 'scale': 1, 'unit': '', 'access': 'RW', |
| 189 | + 'desc': 'Grid compliance region (uwFeedRange): 0=Asia, 1=Europe, 2=S.America, 3=S.Africa', |
| 190 | + 'values': {0: 'Asia', 1: 'Europe', 2: 'South America', 3: 'South Africa'}}, |
| 191 | + |
| 192 | + # 118: uwBatFeedEn — battery-to-grid export enable |
| 193 | + 118: {'name': 'spe_battery_export_enable', 'scale': 1, 'unit': '', 'access': 'RW', |
| 194 | + 'desc': 'Battery-to-grid export enable (uwBatFeedEn): 0=Disabled, 1=Enabled', |
| 195 | + 'values': {0: 'Disabled', 1: 'Enabled'}}, |
| 196 | + |
| 197 | + # 119: uwFeedPow — feed power limit (0-120 raw = 0-12.0 kW) |
| 198 | + 119: {'name': 'spe_export_limit_power', 'scale': 0.1, 'unit': 'kW', 'access': 'RW', |
| 199 | + 'valid_range': (0, 120), |
| 200 | + 'desc': 'Grid export power limit (uwFeedPow): 0-12 kW (raw 0-120, scale 0.1)'}, |
| 201 | + |
| 202 | + # 120: uwBatFeedCurr — max battery current for grid export (0-400 A per V0.26) |
| 203 | + # NOTE: nicauswu had this as 0-100; protocol V0.26 states 0-400. |
| 204 | + # Pending validation from nicauswu register scan. |
| 205 | + 120: {'name': 'spe_battery_export_max_current', 'scale': 1, 'unit': 'A', 'access': 'RW', |
| 206 | + 'valid_range': (0, 400), |
| 207 | + 'desc': 'Max battery current for grid export (uwBatFeedCurr): 0-400 A (Protocol V0.26)'}, |
| 208 | + |
| 209 | + # 121: uwBatFeedVLoss — battery voltage at which export stops (420-540, units: 0.1V = 42-54V) |
| 210 | + 121: {'name': 'spe_bat_feed_vloss', 'scale': 0.1, 'unit': 'V', 'access': 'RW', |
| 211 | + 'valid_range': (420, 540), |
| 212 | + 'desc': 'Battery voltage loss point to stop export (uwBatFeedVLoss): 42-54V (raw 420-540)'}, |
| 213 | + |
| 214 | + # 122: uwBatFeedVBack — battery voltage at which export resumes (440-560, units: 0.1V = 44-56V) |
| 215 | + 122: {'name': 'spe_bat_feed_vback', 'scale': 0.1, 'unit': 'V', 'access': 'RW', |
| 216 | + 'valid_range': (440, 560), |
| 217 | + 'desc': 'Battery voltage back point to resume export (uwBatFeedVBack): 44-56V (raw 440-560)'}, |
| 218 | + |
| 219 | + # 123: uwBatFeedSocLoss — minimum SOC to allow export (5-90 %) |
| 220 | + # NOTE: SPH reg 123 = export_limit_power (%). WRITABLE_REGISTERS carries |
| 221 | + # not_profiles=['SPE_8000_12000_ES'] on that entry to prevent cross-contamination. |
| 222 | + # Protocol V0.26 valid range is 5-90 (not 0-100 as nicauswu had). |
| 223 | + 123: {'name': 'spe_export_min_soc', 'scale': 1, 'unit': '%', 'access': 'RW', |
| 224 | + 'valid_range': (5, 90), |
| 225 | + 'desc': 'Min battery SOC to allow export (uwBatFeedSocLoss): 5-90% (Protocol V0.26)'}, |
| 226 | + |
| 227 | + # 124: uwBatFeedSocBack — SOC hysteresis to re-enable export (15-100 %) |
| 228 | + 124: {'name': 'spe_export_back_soc', 'scale': 1, 'unit': '%', 'access': 'RW', |
| 229 | + 'valid_range': (15, 100), |
| 230 | + 'desc': 'SOC back point to resume export (uwBatFeedSocBack): 15-100% (Protocol V0.26)'}, |
142 | 231 | }, |
143 | 232 | } |
144 | 233 |
|
|
0 commit comments