ABB TACW fw ver 1.6.5 adaptions (#4626)
Charger improvements for ABB Terra AC Wallbox with firmware version 1.6.5 (and newer?) from Nov 2022.
!!! Will break compatibility with older firmware - you have to upgrade the firmware to use the charger !!!
New: Vehicle connection detection outside of an active session
New: Getting an enabled state outside of an active session now
New: Setting max current outside of an active session now
Charger implementation allows to switch modbus protocol (rtu or tcp) now
Firmware 1.6.5 still has some crazy "non-linear" behavior regarding the sent, applied and read-back max current..
This commit is contained in:
parent
9fc017e91c
commit
03cf93f9e8
3 changed files with 24 additions and 38 deletions
|
|
@ -30,7 +30,6 @@ import (
|
|||
|
||||
// ABB charger implementation
|
||||
type ABB struct {
|
||||
log *util.Logger
|
||||
conn *modbus.Connection
|
||||
curr uint32
|
||||
}
|
||||
|
|
@ -40,6 +39,7 @@ const (
|
|||
abbRegFirmware = 0x4004 // Firmware version 2 unsigned RO available
|
||||
abbRegMaxRated = 0x4006 // Max rated current 2 unsigned RO available
|
||||
abbRegErrorCode = 0x4008 // Error Code 2 unsigned RO available
|
||||
abbRegSocketLock = 0x400A // Socket Lock State 2 unsigned RO available
|
||||
abbRegStatus = 0x400C // Charging state 2 unsigned RO available
|
||||
abbRegGetCurrent = 0x400E // Current charging current limit 2 0.001 A unsigned RO
|
||||
abbRegCurrents = 0x4010 // Charging current phases 6 0.001 A unsigned RO available
|
||||
|
|
@ -48,8 +48,6 @@ const (
|
|||
abbRegSetCurrent = 0x4100 // Set charging current limit 2 0.001 A unsigned WO available
|
||||
// abbRegSession = 0x4105 // Start/Stop Charging Session 1 unsigned WO available
|
||||
// abbRegPhases = 0x4102 // Set charging phase 1 unsigned WO Not supported
|
||||
|
||||
abbMinCurrent = 0x1720 // 5920 mA
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
|
@ -59,21 +57,19 @@ func init() {
|
|||
// NewABBFromConfig creates a ABB charger from generic config
|
||||
func NewABBFromConfig(other map[string]interface{}) (api.Charger, error) {
|
||||
cc := modbus.Settings{
|
||||
ID: 1,
|
||||
Baudrate: 9600,
|
||||
Comset: "8N1",
|
||||
ID: 1,
|
||||
}
|
||||
|
||||
if err := util.DecodeOther(other, &cc); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewABB(cc.URI, cc.Device, cc.Comset, cc.Baudrate, cc.ID)
|
||||
return NewABB(cc.URI, cc.Device, cc.Comset, cc.Baudrate, modbus.ProtocolFromRTU(cc.RTU), cc.ID)
|
||||
}
|
||||
|
||||
// NewABB creates ABB charger
|
||||
func NewABB(uri, device, comset string, baudrate int, slaveID uint8) (api.Charger, error) {
|
||||
conn, err := modbus.NewConnection(uri, device, comset, baudrate, modbus.Rtu, slaveID)
|
||||
func NewABB(uri, device, comset string, baudrate int, proto modbus.Protocol, slaveID uint8) (api.Charger, error) {
|
||||
conn, err := modbus.NewConnection(uri, device, comset, baudrate, proto, slaveID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -86,9 +82,8 @@ func NewABB(uri, device, comset string, baudrate int, slaveID uint8) (api.Charge
|
|||
conn.Logger(log.TRACE)
|
||||
|
||||
wb := &ABB{
|
||||
log: log,
|
||||
conn: conn,
|
||||
curr: abbMinCurrent, // assume min current
|
||||
curr: 6000, // assume min current
|
||||
}
|
||||
|
||||
// keep-alive
|
||||
|
|
@ -110,15 +105,6 @@ func (wb *ABB) status() (byte, error) {
|
|||
return b[2] & 0x7f, nil
|
||||
}
|
||||
|
||||
func (wb *ABB) session() (bool, error) {
|
||||
s, err := wb.status()
|
||||
if err != nil || s == 0 || s == 5 { // ToDo: check if 1 is active/inactive/unknown
|
||||
return false, err
|
||||
}
|
||||
|
||||
return true, err
|
||||
}
|
||||
|
||||
// Status implements the api.Charger interface
|
||||
func (wb *ABB) Status() (api.ChargeStatus, error) {
|
||||
s, err := wb.status()
|
||||
|
|
@ -138,6 +124,13 @@ func (wb *ABB) Status() (api.ChargeStatus, error) {
|
|||
case 4: // State C2: Charging Contact closed, energy delivering
|
||||
return api.StatusC, nil
|
||||
case 5: // Other: Session stopped
|
||||
b, err := wb.conn.ReadHoldingRegisters(abbRegSocketLock, 2)
|
||||
if err != nil {
|
||||
return api.StatusNone, err
|
||||
}
|
||||
if binary.BigEndian.Uint32(b) >= 0x0101 {
|
||||
return api.StatusB, nil
|
||||
}
|
||||
return api.StatusA, nil
|
||||
default: // Other
|
||||
return api.StatusNone, fmt.Errorf("invalid status: %0x", s)
|
||||
|
|
@ -146,26 +139,16 @@ func (wb *ABB) Status() (api.ChargeStatus, error) {
|
|||
|
||||
// Enabled implements the api.Charger interface
|
||||
func (wb *ABB) Enabled() (bool, error) {
|
||||
s, err := wb.session()
|
||||
if err != nil || !s {
|
||||
return false, err
|
||||
}
|
||||
|
||||
b, err := wb.conn.ReadHoldingRegisters(abbRegGetCurrent, 2)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return binary.BigEndian.Uint32(b) >= abbMinCurrent, nil
|
||||
return binary.BigEndian.Uint32(b) != 0, nil
|
||||
}
|
||||
|
||||
// Enable implements the api.Charger interface
|
||||
func (wb *ABB) Enable(enable bool) error {
|
||||
s, err := wb.session()
|
||||
if err != nil || !s {
|
||||
return err
|
||||
}
|
||||
|
||||
var current uint32
|
||||
if enable {
|
||||
current = wb.curr
|
||||
|
|
@ -196,11 +179,6 @@ func (wb *ABB) MaxCurrentMillis(current float64) error {
|
|||
return fmt.Errorf("invalid current %.1f", current)
|
||||
}
|
||||
|
||||
s, err := wb.session()
|
||||
if err != nil || !s {
|
||||
return err
|
||||
}
|
||||
|
||||
wb.curr = uint32(current * 1e3)
|
||||
|
||||
return wb.setCurrent(wb.curr)
|
||||
|
|
@ -271,10 +249,13 @@ func (wb *ABB) Diagnose() {
|
|||
fmt.Printf("\tFirmware:\t%d.%d.%d\n", b[0], b[1], b[2])
|
||||
}
|
||||
if b, err := wb.conn.ReadHoldingRegisters(abbRegMaxRated, 2); err == nil {
|
||||
fmt.Printf("\tMax rated current:\t%.1fA\n", float32(binary.BigEndian.Uint32(b))/1e3)
|
||||
fmt.Printf("\tMax rated current:\t%dmA\n", binary.BigEndian.Uint32(b))
|
||||
}
|
||||
if b, err := wb.conn.ReadHoldingRegisters(abbRegGetCurrent, 2); err == nil {
|
||||
fmt.Printf("\tCharging current limit:\t%.1fA\n", float32(binary.BigEndian.Uint32(b))/1e3)
|
||||
fmt.Printf("\tCharging current limit:\t%dmA\n", binary.BigEndian.Uint32(b))
|
||||
}
|
||||
if b, err := wb.conn.ReadHoldingRegisters(abbRegSocketLock, 2); err == nil {
|
||||
fmt.Printf("\tSocket lock state:\t%x\n", b)
|
||||
}
|
||||
if b, err := wb.conn.ReadHoldingRegisters(abbRegStatus, 2); err == nil {
|
||||
fmt.Printf("\tStatus:\t%x\n", b)
|
||||
|
|
|
|||
|
|
@ -5,6 +5,9 @@ products:
|
|||
generic: Terra AC
|
||||
capabilities: ["mA"]
|
||||
requirements:
|
||||
description:
|
||||
de: Erfordert Firmware >= 1.6.5
|
||||
en: Requires firmware >= 1.6.5
|
||||
evcc: ["sponsorship"]
|
||||
params:
|
||||
- name: modbus
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ product:
|
|||
description: Terra AC
|
||||
capabilities: ["mA"]
|
||||
requirements: ["sponsorship"]
|
||||
description: |
|
||||
Erfordert Firmware >= 1.6.5
|
||||
render:
|
||||
- default: |
|
||||
type: template
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue