Skip to content

Victron VEDirect EspHome component supporting HEX and TEXT protocol

License

Notifications You must be signed in to change notification settings

krahabb/esphome-victron-vedirect

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

esphome-victron-vedirect

This EspHome external component contains a complete implementation to support Victron VEDirect serial interface. It has parsers for both the HEX and the TEXT protocol data carried over the communication channel and allows to also issue commands in order to configure the Victron device.

In order to use an ESP (both legacy ESP8266 and/or any ESP32 variant) to connect to a VEDirect hardware interface it uses one of the UART buses available in the ESP platform. The code itself is optimized (or can be) to use the minimum amount of resources but, depending on the number of entities configured you might be better off using one of the more capable ESP32 versions so to have more RAM and CPU power for the task.

The details for hardware interfacing can be found online and this repo doesn't provide many clues but you have to basically adapt and connect the VEDirect RX/TX data lines to the ESP uart bus. Now this might be as simple as directly wiring those RX/TX lines to the UART pins of the ESP if the VEDirect device uses 3.3 V operation or, if the interface carries 5V signals, you might be better off using an optocoupler (H11L1 might be needed because of the data transfer rate used in the signaling) or any form of signal level adaptation.

Before using this component I strongly suggest to understand how VEDirect works by deeply checking these (and any other possibly available) docs:

The first document being the overall technical description and explaining what is achievable with the TEXT protocol while the others are a more detailed description of the HEX protocol features available among the different classes of devices.

Sadly enough, beside those few documents, Victron doesn't expose a very detailed 'implementation manual' for every device/family, especially the new ones (like the RS families of devices for instance) so, many times you'll have to infer or guess how to interface with these by looking at their most close counterparts for which documentation is available. As an example, I'm using this code and the knowledge from those docs to succesfully (at least partially) interface a Multi RS inverter which contains both MPPTs and INVERTERs features (plus many which are very specific and for which there's no official doc available). At any rate, for basic sensor readings and configuration those documents are enough since, even among different devices and classes, the configuration registers are pretty almost the same.

How to use

In order to include the component in your EspHome project use the instructions. Something in the lines:

external_components:
  source: github://krahabb/esphome-victron-vedirect

There are some sample configurations with a basic explanation of the features for different scenarios:

These samples mostly use the 'auto create' feature in order to automatically create an entity for any register data appearing on the communication channel. This might help to start over but could soon become cumbersome since HEX broadcasted registers might be a lot and the component will create HA entities for any of these.

These other samples show instead usage of static entities definition for different 'flavors'. See manual configuration for better insights.

We'll see then how to better configure the device for only the needed entities.

Manual configuration

Victron devices expose a lot of registers each one carrying either measured data (battery voltage for instance) or a configuration parameter (or some static info like device model, hw & sw revision, and so on). In general, TEXT frames only carry a subset of these (both measures and some info/configuration), while HEX frames can address and carry any register. Since there are so many registers and most of them are unknown, this component allows you to specify all of the details needed to decode/map any register data to a specific entity (this is an advanced feature and you really need to know how those registers work). This will be covered later.

For simple use cases instead you can use some 'well known' registers definitions which are already embedded in the component (this is related to the 'flavor' configuration). We'll go with some examples for really basic and widely used registers in order to understand this.

Example 1: Configure some sensors for battery voltage, battery current, pv power. Here things might be tricky since the component nomenclature tries to use the same conventional names used by Victron docs so let's start to say that (in general) battery voltage in Victron appliances is carried in register VE_REG_DC_CHANNEL1_VOLTAGE (and the same reasoning is behind the other entities). Having said that, in order to setup these sensors you have to configure it like this (for other configuration settings check the samples):

m3_vedirect:
  - id: vedirect_0
    uart_id: uart_0
    name: "Victron"
    flavor: [ALL]
    textframe:
      auto_create_entities: false
    hexframe:
      auto_create_entities: false
      ping_timeout: 2min

sensor:
  - platform: m3_vedirect
    vedirect_id: vedirect_0    
    vedirect_entities:
      - type: DC_CHANNEL1_VOLTAGE
        name: 'Battery voltage'
      - type: DC_CHANNEL1_CURRENT
        name: 'Battery current'
      - type: PANEL_POWER
        name: 'PV power'

Using the type configuration will automatically set all of the needed info in order to correctly decode the register carrying the battery voltage (DC_CHANNEL1_VOLTAGE) and setup the sensor entity with proper unit, digits and scale. Now, keep in mind the DC_CHANNEL1_VOLTAGE-DC_CHANNEL1_CURRENT-PANEL_POWER registers are defined as NUMERIC in 'component terms' and that allows them to be configured as (numeric) sensors (this is useful when inspecting the list of available pre-defined registers published later in order to know which kind of entity supports it)

Let's see another useful Example 2: configure a text_sensor for DEVICE_STATE

text_sensor:
  - platform: m3_vedirect
    vedirect_id: vedirect_0    
    vedirect_entities:
      - type: DEVICE_STATE
        name: 'Device state (enum)'

Register DEVICE_STATE (hex address 0x0201) is encoded as an ENUM and this component carries (hardcoded in english) the different labels associated with those enum values (according to Victron official nomenclature) so that the text sensor will show you these labels instead of numeric values. This is true for any register defined as ENUM so that the text sensor will always try to map the numeric value to a meaningful label. If you want to see the underlying numeric value it is possible though: just use a sensor definition instead of a text_sensor:

sensor:
  - platform: m3_vedirect
    vedirect_id: vedirect_0
    vedirect_entities:
      - type: DEVICE_STATE
        name: 'Device state (raw)'

More: you can map the same register (DEVICE_STATE) to more than one entity so that you can see it in different representations (both as a sensor and a text_sensor). The component will dispatch the incoming raw data to all of the entities representing it.

Register definitions

This table exposes the list of actually pre-defined registers to be used with the 'shortcut' configuration type. It is extracted from the source file definitions in ve_reg_register.h which is always the 'source of truth' for the component.

type class r/w hex address flavor
BLE_MODE BITMASK READ_WRITE 0x0090 ANY
PRODUCT_ID VOID CONSTANT 0x0100 ANY
APP_VER VOID CONSTANT 0x0102 ANY
SERIAL_NUMBER STRING CONSTANT 0x010A ANY
MODEL_NAME STRING CONSTANT 0x010B ANY
CAPABILITIES BITMASK CONSTANT 0x0140 ANY
CAPABILITIES_BLE BITMASK CONSTANT 0x0150 ANY
DEVICE_MODE ENUM READ_WRITE 0x0200 ANY
DEVICE_STATE ENUM READ_ONLY 0x0201 ANY
DEVICE_OFF_REASON BITMASK READ_ONLY 0x0205 ANY
DEVICE_OFF_REASON_2 BITMASK READ_ONLY 0x0207 ANY
INVERTER_DEVICE_STATE ENUM READ_ONLY 0x0209 INV
CHARGER_DEVICE_STATE ENUM READ_ONLY 0x020A CHG
AC_OUT_VOLTAGE_SETPOINT NUMERIC READ_WRITE 0x0230 INV
MPPT_TRACKERS NUMERIC CONSTANT 0x0244 MPPT_RS
UNKNOWN_0305 NUMERIC READ_ONLY 0x0305 MULTI_RS
UNKNOWN_0310 NUMERIC READ_ONLY 0x0310 MULTI_RS
UNKNOWN_0311 NUMERIC READ_ONLY 0x0311 MULTI_RS
WARNING_REASON BITMASK READ_ONLY 0x031C ANY
ALARM_REASON BITMASK READ_ONLY 0x031E ANY
ALARM_LOW_VOLTAGE_SET NUMERIC READ_WRITE 0x0320 INV
ALARM_LOW_VOLTAGE_CLEAR NUMERIC READ_WRITE 0x0321 INV
RELAY_CONTROL BOOLEAN READ_WRITE 0x034E ANY
RELAY_MODE ENUM READ_WRITE 0x034F ANY
UNKNOWN_0FFC NUMERIC READ_ONLY 0x0FFC MULTI_RS
TTG NUMERIC READ_ONLY 0x0FFE BMV
SOC NUMERIC READ_ONLY 0x0FFF BMV
SOLAR_ACTIVITY BOOLEAN READ_ONLY 0x2030 MPPT
TIME_OF_DAY NUMERIC READ_ONLY 0x2031 MPPT
AC_OUT_VOLTAGE NUMERIC READ_ONLY 0x2200 INV
AC_OUT_CURRENT NUMERIC READ_ONLY 0x2201 INV
AC_OUT_APPARENT_POWER NUMERIC READ_ONLY 0x2205 INV
SHUTDOWN_LOW_VOLTAGE_SET NUMERIC READ_WRITE 0x2210 INV
VOLTAGE_RANGE_MIN NUMERIC CONSTANT 0x2211 INV
VOLTAGE_RANGE_MAX NUMERIC CONSTANT 0x2212 INV
U_AC_OUT_VOLTAGE NUMERIC READ_ONLY 0x2213 MULTI_RS
U_AC_OUT_CURRENT NUMERIC READ_ONLY 0x2214 MULTI_RS
U_AC_OUT_APPARENT_POWER NUMERIC READ_ONLY 0x2215 MULTI_RS
UNKNOWN_2216 NUMERIC READ_ONLY 0x2216 MULTI_RS
UNKNOWN_2250 NUMERIC READ_ONLY 0x2250 MULTI_RS
UNKNOWN_2251 NUMERIC READ_ONLY 0x2251 MULTI_RS
U_AC_OUT_CURRENT_MA NUMERIC READ_ONLY 0xD3A1 MULTI_RS
UNKNOWN_D5C8 NUMERIC READ_ONLY 0xD5C8 MULTI_RS
UNKNOWN_D5CA NUMERIC READ_ONLY 0xD5CA MULTI_RS
UNKNOWN_D5CB NUMERIC READ_ONLY 0xD5CB MULTI_RS
MPPT_TRACKER_MODE_1 ENUM READ_ONLY 0xECC3 MPPT_RS
PANEL_VOLTAGE_1 NUMERIC READ_ONLY 0xECCB MPPT_RS
PANEL_POWER_1 NUMERIC READ_ONLY 0xECCC MPPT_RS
PANEL_CURRENT_1 NUMERIC READ_ONLY 0xECCD MPPT_RS
MPPT_TRACKER_MODE_2 ENUM READ_ONLY 0xECD3 MPPT_RS
PANEL_VOLTAGE_2 NUMERIC READ_ONLY 0xECDB MPPT_RS
PANEL_POWER_2 NUMERIC READ_ONLY 0xECDC MPPT_RS
PANEL_CURRENT_2 NUMERIC READ_ONLY 0xECDD MPPT_RS
MPPT_TRACKER_MODE_3 ENUM READ_ONLY 0xECE3 MPPT_RS
PANEL_VOLTAGE_3 NUMERIC READ_ONLY 0xECEB MPPT_RS
PANEL_POWER_3 NUMERIC READ_ONLY 0xECEC MPPT_RS
PANEL_CURRENT_3 NUMERIC READ_ONLY 0xECED MPPT_RS
MPPT_TRACKER_MODE_4 ENUM READ_ONLY 0xECF3 MPPT_RS
PANEL_VOLTAGE_4 NUMERIC READ_ONLY 0xECFB MPPT_RS
PANEL_POWER_4 NUMERIC READ_ONLY 0xECFC MPPT_RS
PANEL_CURRENT_4 NUMERIC READ_ONLY 0xECFD MPPT_RS
BATTERY_RIPPLE_VOLTAGE NUMERIC READ_ONLY 0xED8B MPPT_RS
DC_CHANNEL1_VOLTAGE NUMERIC READ_ONLY 0xED8D ANY
DC_CHANNEL1_POWER NUMERIC READ_ONLY 0xED8E BMV
DC_CHANNEL1_CURRENT NUMERIC READ_ONLY 0xED8F ANY
LOAD_OUTPUT_STATE BOOLEAN READ_ONLY 0xEDA8 MPPT
LOAD_CURRENT NUMERIC READ_ONLY 0xEDAD MPPT
MPPT_TRACKER_MODE ENUM READ_ONLY 0xEDB3 MPPT
PANEL_MAXIMUM_VOLTAGE NUMERIC CONSTANT 0xEDB8 MPPT
PANEL_VOLTAGE NUMERIC READ_ONLY 0xEDBB MPPT
PANEL_POWER NUMERIC READ_ONLY 0xEDBC MPPT
PANEL_CURRENT NUMERIC READ_ONLY 0xEDBD MPPT
PANEL_MAXIMUM_CURRENT NUMERIC CONSTANT 0xEDBF MPPT_RS
MAXIMUM_POWER_YESTERDAY NUMERIC READ_ONLY 0xEDD0 MPPT
YIELD_YESTERDAY NUMERIC READ_ONLY 0xEDD1 MPPT
MAXIMUM_POWER_TODAY NUMERIC READ_ONLY 0xEDD2 MPPT
YIELD_TODAY NUMERIC READ_ONLY 0xEDD3 MPPT
CHARGER_VOLTAGE NUMERIC READ_ONLY 0xEDD5 CHG
CHARGER_CURRENT NUMERIC READ_ONLY 0xEDD7 CHG
CHR_ERROR_CODE ENUM READ_ONLY 0xEDDA CHG
CHR_INTERNAL_TEMPERATURE NUMERIC READ_ONLY 0xEDDB CHG
USER_YIELD NUMERIC READ_ONLY 0xEDDC MPPT
SYSTEM_YIELD NUMERIC READ_ONLY 0xEDDD MPPT
BAT_TEMPERATURE NUMERIC READ_ONLY 0xEDEC ANY
DC_MONITOR_MODE NUMERIC READ_ONLY 0xEEB8 BMV71
ALARM_BUZZER BOOLEAN READ_WRITE 0xEEFC BMV

The 'flavor' property is used to conditionally include the corresponding definition(s) in the code. This works as an optimization for code size so that it is possible to decide which of the registers must be defined. It is controlled by the configuration key in the main platform configuration:

m3_vedirect:
  - id: vedirect_0
    uart_id: uart_0
    name: "Victron"
    flavor: [ALL] # include all flavors i.e. all of the register definitions

If you want to use a particular register definition you have to ensure the corresponding flavor is set.

The 'class' and 'r/w' properties are very important and state which kind of data the register is carrying and if it's read only or writable. Different 'classes' and 'r/w' can be supported by different EspHome entity types according to the following table:

class r/w primary entity
BITMASK READ_ONLY binary_sensor(1)
BITMASK READ_WRITE switch(1)
BOOLEAN READ_ONLY binary_sensor
BOOLEAN READ_WRITE switch
ENUM READ_ONLY text_sensor
ENUM READ_WRITE select
NUMERIC READ_ONLY sensor
NUMERIC READ_WRITE number
STRING READ_ONLY text_sensor

(1) in order to use a binary_sensor or switch for BITMASK registers you'd also have to set the configuration property mask which, as the name implies, is used to extract/mask the intended bit from the register value (representing a bitmask for the matter).

binary_sensor:
  - platform: m3_vedirect
    vedirect_id: vedirect_0
    vedirect_entities:
      - type: DEVICE_OFF_REASON_2
        name: 'No input power'
        mask: 1 # Bit 0 of DEVICE_OFF_REASON bitmask

Beside these 'primary entity' mappings you can always use a sensor entity to represent the raw value as a numeric value even if the register is not marked as NUMERIC (though some sign conversion issues might happen since the conversion would be done as an unsigned type whenever the class is not NUMERIC). Moreover, the text_sensor entity too can represent any class data type, generally falling back to report the hex register value 'as is' (if no better conversion is provided by the register definition).

More help and wiki will come.

Good interfacing!

Notes

This is a 'replica' of the same component as developed on https://github.com/krahabb/esphome. This repository is just an extraction in order to raise its public status.

About

Victron VEDirect EspHome component supporting HEX and TEXT protocol

Topics

Resources

License

Stars

Watchers

Forks