Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decode charging status of the Epever #1

Closed
syssi opened this issue Mar 17, 2023 · 16 comments
Closed

Decode charging status of the Epever #1

syssi opened this issue Mar 17, 2023 · 16 comments

Comments

@syssi
Copy link
Owner

syssi commented Mar 17, 2023

@Chickenbreast0 Hier gehts weiter zum Thema "Charging status" sauber decodieren.

Hier findet sich eine Dokumentation der Modbus Register:

https://www.developpez.net/forums/attachments/p196506d1451307310/systemes/autres-systemes/automation/probleme-com-modbus-pl7-pro/controllerprotocolv2.3.pdf/

Im Register 0x3201 stecken diverse Informationen auf Bits verteilt:

D15-D14: Input volt status. 0x00 normal, 0x01 no power connected, 0x02 Higher volt input, 0x03 Input volt error.
D13: Charging MOSFET is short
D12: Charging or Anti-reverse MOSFET is short
D11: Anti-reverse MOSFET is short
D10: Input is over current
D9: The load is Over current
D8: The load is short
D7: Load MOSFET is short
D4: PV Input is short
D3-2: Charging status. 0x00 No charging, 0x01 Float, 0x02 Boost, 0x03 Equalization
D1: 0 Normal, 1 Fault
D0: 1 Running, 0 Standby
@syssi
Copy link
Owner Author

syssi commented Mar 17, 2023

Kannst du einmal testweise diese reduzierte Konfiguration flashen und mir einen Ausschnitt der Logmeldungen der ESPHome-Node zur Verfuegung stellen? Hier sollte der RAW-Modbus-Traffic enthalten sein. Ich moechte verstehen, wo ich mich verrechnet habe:

substitutions:
  updates: 5s
  name: epever-soyosource

esphome:
  name: esphome-web-b8c8d0
  friendly_name: ESP32
  platformio_options:
    build_flags:
      - -DCONFIG_ARDUINO_LOOP_STACK_SIZE=8192

esp32:
  board: esp32dev
  framework:
    type: arduino

logger:
  baud_rate: 0
  level: DEBUG

api:
  reboot_timeout: 0s
  encryption:
    key: "Ef0O/9zQQ/+3YjNmnNWbZrK12xfaSS7NHBWHCc/gHo0="

ota:

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  ap:
    ssid: "Esphome-Web-B8C8D0"
    password: "cChwJe9n3h2q"

time:
  - platform: sntp
    id: sntp_time
    timezone: "CET-1CEST-2,M3.5.0/2,M10.5.0/3"
    servers: "de.pool.ntp.org"

uart:
  - id: uart0
    tx_pin: GPIO1
    rx_pin: GPIO3
    baud_rate: 115200
    stop_bits: 1
    debug:

modbus:
  - id: modbus_epever
    uart_id: uart0
    send_wait_time: 200ms

modbus_controller:
  - id: epever
    address: 0x1
    modbus_id: modbus_epever
    command_throttle: 200ms
    setup_priority: -10
    update_interval: 5s

sensor:
  - platform: modbus_controller
    modbus_controller_id: epever
    name: "Charger status"
    address: 0x3201
    register_type: read
    value_type: U_WORD
    accuracy_decimals: 0

  - platform: modbus_controller
    modbus_controller_id: epever
    name: "Charger status mask 12"
    address: 0x3201
    bitmask: 12
    register_type: read
    value_type: U_WORD
    accuracy_decimals: 0

text_sensor:
  - platform: modbus_controller
    modbus_controller_id: epever
    name: "EPEVER Charging Status"
    address: 0x3201
    register_type: read
    bitmask: 12
    raw_encode: HEXBYTES
    lambda: |-
      uint16_t value = modbus_controller::word_from_hex_str(x, 0);
      ESP_LOGD("lambda", "Register 0x3201 bitmask 12 raw: 0x%04X", value);
      switch (value) {
        case 0: return std::string("Off");
        case 1: return std::string("Float");
        case 2: return std::string("Boost");
        case 3: return std::string("Equalization");
      }
      return str_snprintf("Unknown (0x%04X)", 17, value);

web_server:

Nach diesem Experiment kannst du deine große Konfiguration wieder flashen.

@syssi
Copy link
Owner Author

syssi commented Mar 17, 2023

Nach ein paar weiteere Werte die man decodieren koenntem, wenn man es drauf anlegt:

Battery status
Register 0x3200

D3-D0: 0x00 Normal, 0x01 Overvoltage, 0x02 Undervoltage, 0x03 Low voltage disconnect, 0x04 Fault
D7-D4: 0x00 Normal, 0x01 Over Temperature, 0x02 Low Temperature
D8: 0x00 Normal, 0x01 Battery inner resistance abnormal
D15: 0x00 Normal, 0x01 Wrong identification for rated voltage
Discharging equipment status
Register 0x3202

D15-D14: 0x00H Normal, 0x01 Input voltage low, 0x02 Input voltage high, 03H No access
D13-D12: Output power: 0x00 Light load, 0x01 Moderate, 0x02 Rated, 0x03 Overload
D11: Short circuit
D10: Unable to discharge
D9: Unable to stop discharging
D8: Output voltage abnormal
D7: Input overpressure
D6: High voltage side short circuit
D5: Boost overpressure
D4: Output overpressure
D1: 0x00 Normal, 0x01 Fault
D0: 0x00 Standby, 0x01 Running

@Chickenbreast0
Copy link

Kannst du einmal testweise diese reduzierte Konfiguration flashen und mir einen Ausschnitt der Logmeldungen der ESPHome-Node zur Verfuegung stellen? Hier sollte der RAW-Modbus-Traffic enthalten sein. Ich moechte verstehen, wo ich mich verrechnet habe:

substitutions:
  updates: 5s
  name: epever-soyosource

esphome:
  name: esphome-web-b8c8d0
  friendly_name: ESP32
  platformio_options:
    build_flags:
      - -DCONFIG_ARDUINO_LOOP_STACK_SIZE=8192

esp32:
  board: esp32dev
  framework:
    type: arduino

logger:
  baud_rate: 0
  level: DEBUG

api:
  reboot_timeout: 0s
  encryption:
    key: "Ef0O/9zQQ/+3YjNmnNWbZrK12xfaSS7NHBWHCc/gHo0="

ota:

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  ap:
    ssid: "Esphome-Web-B8C8D0"
    password: "cChwJe9n3h2q"

time:
  - platform: sntp
    id: sntp_time
    timezone: "CET-1CEST-2,M3.5.0/2,M10.5.0/3"
    servers: "de.pool.ntp.org"

uart:
  - id: uart0
    tx_pin: GPIO1
    rx_pin: GPIO3
    baud_rate: 115200
    stop_bits: 1
    debug:

modbus:
  - id: modbus_epever
    uart_id: uart0
    send_wait_time: 200ms

modbus_controller:
  - id: epever
    address: 0x1
    modbus_id: modbus_epever
    command_throttle: 200ms
    setup_priority: -10
    update_interval: 5s

sensor:
  - platform: modbus_controller
    modbus_controller_id: epever
    name: "Charger status"
    address: 0x3201
    register_type: read
    value_type: U_WORD
    accuracy_decimals: 0

  - platform: modbus_controller
    modbus_controller_id: epever
    name: "Charger status mask 12"
    address: 0x3201
    bitmask: 12
    register_type: read
    value_type: U_WORD
    accuracy_decimals: 0

text_sensor:
  - platform: modbus_controller
    modbus_controller_id: epever
    name: "EPEVER Charging Status"
    address: 0x3201
    register_type: read
    bitmask: 12
    raw_encode: HEXBYTES
    lambda: |-
      uint16_t value = modbus_controller::word_from_hex_str(x, 0);
      ESP_LOGD("lambda", "Register 0x3201 bitmask 12 raw: 0x%04X", value);
      switch (value) {
        case 0: return std::string("Off");
        case 1: return std::string("Float");
        case 2: return std::string("Boost");
        case 3: return std::string("Equalization");
      }
      return str_snprintf("Unknown (0x%04X)", 17, value);

web_server:

Nach diesem Experiment kannst du deine große Konfiguration wieder flashen.

Here we go - ich bleibe auf standby. Gerne kannste mir einen anderen Code zusenden.
logs_esphome-web-b8c8d0_run.zip

@syssi
Copy link
Owner Author

syssi commented Mar 17, 2023

Super! Das hilft bereits. Ich melde mich im Laufe des Nachmittags wieder!

@syssi
Copy link
Owner Author

syssi commented Mar 18, 2023

[09:07:19][D][uart_debug:114]: <<< 01:04:02:00:0B:F8:F7
[09:07:24][D][uart_debug:114]: >>> 01:04:32:01:00:01:6E:B2
[09:07:24][D][modbus_controller.sensor:025]: Sensor new state: 11.00
[09:07:24][D][sensor:127]: 'Charger status': Sending state 11.00000  with 0 decimals of accuracy
[09:07:24][D][modbus_controller.sensor:025]: Sensor new state: 2.00
[09:07:24][D][sensor:127]: 'Charger status mask 12': Sending state 2.00000  with 0 decimals of accuracy
[09:07:24][D][lambda:091]: Register 0x3201 bitmask 12 raw: 0x000B
[09:07:24][D][text_sensor:067]: 'EPEVER Charging Status': Sending state 'Unknown (0x000B)'

Erkenntnis: Die Bitmask auf dem Text-Sensor wird aktuell nicht berücksichtigt (0x0B). Beim Sensor (0x02) schon. Ich vermute, weil ich zum rohen Wert greife. Ich weiss, was zu tun ist.

@syssi
Copy link
Owner Author

syssi commented Mar 18, 2023

Nächster Versuch. Ich wäre wieder über einen Logbuchauszug dankbar:

substitutions:
  updates: 5s
  name: epever-soyosource

esphome:
  name: esphome-web-b8c8d0
  friendly_name: ESP32
  platformio_options:
    build_flags:
      - -DCONFIG_ARDUINO_LOOP_STACK_SIZE=8192

esp32:
  board: esp32dev
  framework:
    type: arduino

logger:
  baud_rate: 0
  level: DEBUG

api:
  reboot_timeout: 0s
  encryption:
    key: "Ef0O/9zQQ/+3YjNmnNWbZrK12xfaSS7NHBWHCc/gHo0="

ota:

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  ap:
    ssid: "Esphome-Web-B8C8D0"
    password: "cChwJe9n3h2q"

time:
  - platform: sntp
    id: sntp_time
    timezone: "CET-1CEST-2,M3.5.0/2,M10.5.0/3"
    servers: "de.pool.ntp.org"

uart:
  - id: uart0
    tx_pin: GPIO1
    rx_pin: GPIO3
    baud_rate: 115200
    stop_bits: 1
    debug:

modbus:
  - id: modbus_epever
    uart_id: uart0
    send_wait_time: 200ms

modbus_controller:
  - id: epever
    address: 0x1
    modbus_id: modbus_epever
    command_throttle: 200ms
    setup_priority: -10
    update_interval: 5s

sensor:
  - platform: modbus_controller
    modbus_controller_id: epever
    name: "Charger status"
    address: 0x3201
    register_type: read
    value_type: U_WORD
    accuracy_decimals: 0

  - platform: modbus_controller
    modbus_controller_id: epever
    name: "Charger status mask 12"
    address: 0x3201
    bitmask: 12
    register_type: read
    value_type: U_WORD
    accuracy_decimals: 0

text_sensor:
  - platform: modbus_controller
    modbus_controller_id: epever
    name: "EPEVER Charging Status"
    address: 0x3201
    register_type: read
    bitmask: 12
    lambda: |-
      uint16_t value = modbus_controller::word_from_hex_str(x, 0);
      ESP_LOGD("lambda", "Register 0x3201 bitmask 12 raw: 0x%04X", value);
      switch (value) {
        case 0: return std::string("Off");
        case 1: return std::string("Float");
        case 2: return std::string("Boost");
        case 3: return std::string("Equalization");
      }
      return str_snprintf("Unknown (0x%04X)", 17, value);

web_server:

@Chickenbreast0
Copy link

Das mache ich gerne schnellstmöglich, aber ich werde heute erstmal dieses falsche Regelverhalten vom Soyo prüfen müssen. Das treibt mich in den Wahnsinn 😉

@syssi
Copy link
Owner Author

syssi commented Mar 18, 2023

Ich habe hier eine getestete Version gepusht:

https://github.com/syssi/esphome-config-examples/blob/main/esp32-epever-4210an.yaml#L426-L514

Mich wundert lediglich, dass der allg. Betriebsstatus auf "Fault" steht. Entweder ist hier die Dokumentation des Protokolls falsch oder etwas lag zu diesem Zeitpunkt im Argen. Ggf. kannst du es noch einmal mit der orig. Software vergleichen.

@syssi syssi closed this as completed Mar 18, 2023
@Chickenbreast0
Copy link

Chickenbreast0 commented Mar 19, 2023

Ich habe hier eine getestete Version gepusht:

https://github.com/syssi/esphome-config-examples/blob/main/esp32-epever-4210an.yaml#L426-L514

Mich wundert lediglich, dass der allg. Betriebsstatus auf "Fault" steht. Entweder ist hier die Dokumentation des Protokolls falsch oder etwas lag zu diesem Zeitpunkt im Argen. Ggf. kannst du es noch einmal mit der orig. Software vergleichen.

Anbei der Log sowie der Screenshot.
Der Soyo hängt gerade nicht mit am ESP. Fault wird ebenfalls bei mir angezeigt, obwohl alles funktioniert und er aktuell läd.
Ebenfalls der "Status" steht auf Standby. Ich könnte den EPEVER auch noch in die Software hängen und via USB nachsehen.

image
logs_esphome-web-b8c8d0_logs.zip

Update:
Ein abklemmen des Laders ("imaginäres" Solarpanel) im Office, bringt folgende Werte zum Vorschein.
image

Das lässt sich jedoch kurz ändern ;)

@syssi
Copy link
Owner Author

syssi commented Mar 19, 2023

Ich waere ueber einen Vergleich mit der EPEVER-Software via USB dankbar. Vermutlich passt die Protokollbeschreibung nicht ganz zu deinem Charger. Sobald wir die Raw-Werte aus dem ESPHome-Log kennen und zu gehoerigen Zustaende aus der EPEVER-Software, koennen wir die Labels in der YAML überarbeiten.

@Chickenbreast0
Copy link

Chickenbreast0 commented Mar 20, 2023

Guten Morgen,

anbei zwei EPEVER Screenshots. Diese da sind im Lademodus

EPEVER_Charge

und im Standby Modus.
EPEVER_standby

Die entsprechenden Logs zu den Status sind im *.zip file zu finden: EPEVER_Status.zip

Meine aktuelle ESP HA-config ist wie folgt: esphome-web-b8c8d0.zip

@syssi
Copy link
Owner Author

syssi commented Mar 20, 2023

Ich habe an ein paar Werten gedreht. Kannst du deine YAML entsprechend anpassen?

https://github.com/syssi/esphome-config-examples/pull/2/files

Danach waere interessant, ob die EPEVER-Software und ESPHome Implementierung im Einklang sind. Es ist moeglich, dass wir die Werte aus voellig falschen Registern holen.

@Chickenbreast0
Copy link

Mit der Anpassung ist es ein jain.

Die Lademodi stimmen.
Die anderen beiden Status müssen invertiert sein, ergo Device Status: 0 = Standby und 1 = Normal, respektive Solar Status: 0 = Cut Out und 1 = Input.
Ich habs mit der EPEVER SW abgeglichen und es stimmt. Mein MPPT ist genau genommen ein: XTRA4210N-XDS2. Eventuell gabs hier marginale Änderungen, die sich hier etwas auswirken.


  - platform: modbus_controller
    modbus_controller_id: epever
    name: "Device Status"
    address: 0x3201
    register_type: read
    # Doesn't get applied at ESPHome 2023.3.0
    # bitmask: 1
    raw_encode: HEXBYTES
    lambda: |-
      uint16_t value = modbus_controller::word_from_hex_str(x, 0);
      value = modbus_controller::mask_and_shift_by_rightbit(value, 1);
      switch (value) {
        case 0: return std::string("Standby");
        case 1: return std::string("Normal");
      }
      return str_snprintf("Unknown (0x%04X)", 17, value);
   

  - platform: modbus_controller
    modbus_controller_id: epever
    name: "Solar Status"
    address: 0x3201
    register_type: read
    # Doesn't get applied at ESPHome 2023.3.0
    # bitmask: 2
    raw_encode: HEXBYTES
    lambda: |-
      uint16_t value = modbus_controller::word_from_hex_str(x, 0);
      value = modbus_controller::mask_and_shift_by_rightbit(value, 2);
      switch (value) {
        case 0: return std::string("Cut out");
        case 1: return std::string("Input");
      }
      return str_snprintf("Unknown (0x%04X)", 17, value);
      
   

@syssi
Copy link
Owner Author

syssi commented Mar 20, 2023

Alles klar! Ich habe die Werte gedreht. Dann erklaeren wir hiermit die Optimierung als abgeschlossen. :-)

@Chickenbreast0
Copy link

Alles klar! Ich habe die Werte gedreht. Dann erklaeren wir hiermit die Optimierung als abgeschlossen. :-)

Correct - case closed. Vielen Dank für deine Hilfe. 😉

@syssi
Copy link
Owner Author

syssi commented Mar 20, 2023

Immer gern!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants