Voltie: only offer phase switching where the power board supports it (#33070)
This commit is contained in:
parent
ebe064ad97
commit
fbbe12a0ec
2 changed files with 30 additions and 12 deletions
|
|
@ -55,6 +55,11 @@ import (
|
||||||
// communication timeout, the hardware current limit, lifetime energy and the
|
// communication timeout, the hardware current limit, lifetime energy and the
|
||||||
// phase powers. Those capabilities are only offered when the charger reports
|
// phase powers. Those capabilities are only offered when the charger reports
|
||||||
// that firmware, and the block read lengths follow the firmware as well.
|
// that firmware, and the block read lengths follow the firmware as well.
|
||||||
|
//
|
||||||
|
// Phase switching additionally depends on the power board, which the firmware
|
||||||
|
// does not expose over Modbus. The same firmware also runs on older boards that
|
||||||
|
// have no L2/L3 relay and reject the write, so the capability is enabled by
|
||||||
|
// configuration rather than guessed.
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// register blocks fetched in bulk
|
// register blocks fetched in bulk
|
||||||
|
|
@ -267,6 +272,7 @@ func NewVoltieFromConfig(ctx context.Context, other map[string]any) (api.Charger
|
||||||
cc := struct {
|
cc := struct {
|
||||||
modbus.TcpSettings `mapstructure:",squash"`
|
modbus.TcpSettings `mapstructure:",squash"`
|
||||||
Cache time.Duration
|
Cache time.Duration
|
||||||
|
Phases1p3p bool
|
||||||
}{
|
}{
|
||||||
TcpSettings: modbus.TcpSettings{
|
TcpSettings: modbus.TcpSettings{
|
||||||
ID: voltieDefaultSlaveID,
|
ID: voltieDefaultSlaveID,
|
||||||
|
|
@ -280,11 +286,11 @@ func NewVoltieFromConfig(ctx context.Context, other map[string]any) (api.Charger
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return NewVoltie(ctx, cc.TcpSettings, cc.Cache)
|
return NewVoltie(ctx, cc.TcpSettings, cc.Cache, cc.Phases1p3p)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewVoltie creates a Voltie charger
|
// NewVoltie creates a Voltie charger
|
||||||
func NewVoltie(ctx context.Context, settings modbus.TcpSettings, cache time.Duration) (*Voltie, error) {
|
func NewVoltie(ctx context.Context, settings modbus.TcpSettings, cache time.Duration, phaseSwitching bool) (*Voltie, error) {
|
||||||
conn, err := settings.Connection(ctx)
|
conn, err := settings.Connection(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -329,11 +335,18 @@ func NewVoltie(ctx context.Context, settings modbus.TcpSettings, cache time.Dura
|
||||||
}
|
}
|
||||||
|
|
||||||
if wb.ext {
|
if wb.ext {
|
||||||
implement.Has(wb, implement.PhaseSwitcher(wb.phases1p3p))
|
|
||||||
implement.Has(wb, implement.PhaseGetter(wb.getPhases))
|
implement.Has(wb, implement.PhaseGetter(wb.getPhases))
|
||||||
implement.Has(wb, implement.MeterEnergy(wb.totalEnergy))
|
implement.Has(wb, implement.MeterEnergy(wb.totalEnergy))
|
||||||
implement.Has(wb, implement.PhasePowers(wb.powers))
|
implement.Has(wb, implement.PhasePowers(wb.powers))
|
||||||
implement.Has(wb, implement.CurrentLimiter(wb.getMinMaxCurrent))
|
implement.Has(wb, implement.CurrentLimiter(wb.getMinMaxCurrent))
|
||||||
|
|
||||||
|
if phaseSwitching {
|
||||||
|
implement.Has(wb, implement.PhaseSwitcher(wb.phases1p3p))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if phaseSwitching && !wb.ext {
|
||||||
|
log.WARN.Printf("phase switching requires firmware %d or later", voltieExtFirmware)
|
||||||
}
|
}
|
||||||
|
|
||||||
return wb, nil
|
return wb, nil
|
||||||
|
|
@ -533,12 +546,8 @@ func (wb *Voltie) Voltages() (float64, float64, float64, error) {
|
||||||
return wb.getPhaseValues(voltieRegVoltages, 1e3)
|
return wb.getPhaseValues(voltieRegVoltages, 1e3)
|
||||||
}
|
}
|
||||||
|
|
||||||
// phases1p3p implements the api.PhaseSwitcher interface. The register is only
|
// phases1p3p implements the api.PhaseSwitcher interface. The firmware never
|
||||||
// writable on chargers manufactured from 2026, which carry an HPOW108 power
|
// accepts the write while charging, so charging is paused for the switch.
|
||||||
// board; other hardware rejects the write with exception 0x03, as does a relay
|
|
||||||
// or EEPROM error. The hardware generation cannot be detected up front: the
|
|
||||||
// serial numbers exposed over Modbus are the MCU and power board serials, not
|
|
||||||
// the charger serial that carries the generation prefix.
|
|
||||||
func (wb *Voltie) phases1p3p(phases int) error {
|
func (wb *Voltie) phases1p3p(phases int) error {
|
||||||
if phases != 1 && phases != 3 {
|
if phases != 1 && phases != 3 {
|
||||||
return fmt.Errorf("invalid phases: %d", phases)
|
return fmt.Errorf("invalid phases: %d", phases)
|
||||||
|
|
@ -565,9 +574,7 @@ func (wb *Voltie) phases1p3p(phases int) error {
|
||||||
u = 1
|
u = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err = wb.conn.WriteSingleRegister(voltieRegSinglePhase, u); err != nil {
|
_, err = wb.conn.WriteSingleRegister(voltieRegSinglePhase, u)
|
||||||
err = fmt.Errorf("switch phases: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
wb.cache.Clear()
|
wb.cache.Clear()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,18 @@ params:
|
||||||
- name: cache
|
- name: cache
|
||||||
advanced: true
|
advanced: true
|
||||||
default: 1s
|
default: 1s
|
||||||
|
- name: phases1p3p
|
||||||
|
description:
|
||||||
|
de: Phasenumschaltung
|
||||||
|
en: Phase switching
|
||||||
|
help:
|
||||||
|
de: Nur auf Ladegeräten ab Baujahr 2026 verfügbar, deren Seriennummer mit 1026 beginnt. Auf älterer Hardware weist das Ladegerät die Umschaltung ab.
|
||||||
|
en: Only available on chargers manufactured from 2026, whose serial number starts with 1026. On older hardware the charger rejects the switch.
|
||||||
|
type: bool
|
||||||
|
default: false
|
||||||
|
advanced: true
|
||||||
render: |
|
render: |
|
||||||
type: voltie
|
type: voltie
|
||||||
{{- include "modbus" . }}
|
{{- include "modbus" . }}
|
||||||
cache: {{ .cache }}
|
cache: {{ .cache }}
|
||||||
|
phases1p3p: {{ .phases1p3p }}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue