syssi / esphome-soyosource-gtn-virtual-meter

ESPHome component to simulate the current clamp to control the Soyosource GTN1200 limiter
Apache License 2.0
78 stars 21 forks source link

Multiple soyosource inverters #135

Closed ingoooooo closed 1 year ago

ingoooooo commented 1 year ago

Hello,

maybe this is a dumb question though I do not know how your esp32-multiple-uarts-example.yaml needs to be modified if three soyosource inverters should be controlled. Specifically the tx_pin, rx_pin part has to look then.

Any hints?

Thank you, Ingo

syssi commented 1 year ago

Do you want to control 3 inverters independently using separate RS485 connections?

ingoooooo commented 1 year ago

As that could be one option I would like to try the RS485 bus approach first.

syssi commented 1 year ago

Please try something like this:

substitutions:
  name: soyosource-gtn-virtual-meter
  device_description: "Monitor multiple Soyosource GTNs and control the power output on demand both via RS485"
  device0: firstfloor_soyosource_gtn_virtual_meter
  device1: groundfloor_soyosource_gtn_virtual_meter
  device2: secondfloor_soyosource_gtn_virtual_meter
  external_components_source: github://syssi/esphome-soyosource-gtn-virtual-meter@main
  tx_pin_uart_0: GPIO1
  rx_pin_uart_0: GPIO3
  tx_pin_uart_1: GPIO14
  rx_pin_uart_1: GPIO4
  tx_pin_uart_2: GPIO32
  rx_pin_uart_2: GPIO33

esphome:
  name: ${name}
  comment: ${device_description}
  project:
    name: "syssi.esphome-soyosource-gtn-virtual-meter"
    version: 2.1.0

esp32:
  board: esp-wrover-kit

external_components:
  - source: ${external_components_source}
    refresh: 0s

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

ota:

logger:
  baud_rate: 0
  level: INFO

# If you use Home Assistant please remove this `mqtt` section and uncomment the `api` component!
# The native API has many advantages over MQTT: https://esphome.io/components/api.html#advantages-over-mqtt
mqtt:
  broker: !secret mqtt_host
  username: !secret mqtt_username
  password: !secret mqtt_password
  id: mqtt_client

# api:

uart:
  - id: uart_0
    baud_rate: 4800
    tx_pin: ${tx_pin_uart_0}
    rx_pin: ${rx_pin_uart_0}
  - id: uart_1
    baud_rate: 4800
    tx_pin: ${tx_pin_uart_1}
    rx_pin: ${rx_pin_uart_1}
  - id: uart_2
    baud_rate: 4800
    tx_pin: ${tx_pin_uart_2}
    rx_pin: ${rx_pin_uart_2}

soyosource_modbus:
  - id: modbus0
    uart_id: uart_0
    # flow_control_pin: GPIO12
    # The name is used as prefix for some log messages and should
    # help to distinguish between different instances/devices
    name: firstfloor
  - id: modbus1
    uart_id: uart_1
    name: groundfloor
    # flow_control_pin: GPIO13
  - id: modbus2
    uart_id: uart_2
    name: secondfloor
    # flow_control_pin: GPIO0

soyosource_inverter:
  - id: inverter0
    soyosource_modbus_id: modbus0
  - id: inverter1
    soyosource_modbus_id: modbus1
  - id: inverter2
    soyosource_modbus_id: modbus2

soyosource_virtual_meter:
  - id: virtualmeter0
    soyosource_modbus_id: modbus0
    update_interval: 3s

    # the state of this sensor (instantaneous power in watt) is used as source
    power_id: powermeter0
    power_sensor_inactivity_timeout: 20s
    power_demand_calculation: NEGATIVE_MEASUREMENTS_REQUIRED
    min_power_demand: 0
    max_power_demand: 900
    zero_output_on_min_power_demand: true
    # A positive buffer value (10) tries to avoid exporting power to the grid (demand - 10 watts)
    # A negative buffer value (-10) exports power to the grid (demand + 10 watts)
    buffer: 10
    # The operation_status_id sensor is expected here. Passing the operation_status won't work
    # The state is used to suspend the limiter if the operation status of the inverter isn't 0x0 (normal)
    # operation_status_id: operation_status_id0

  - id: virtualmeter1
    soyosource_modbus_id: modbus1
    update_interval: 3s
    # the state of this sensor (instantaneous power in watt) is used as source
    power_id: powermeter1
    power_sensor_inactivity_timeout: 20s
    power_demand_calculation: NEGATIVE_MEASUREMENTS_REQUIRED
    min_power_demand: 0
    max_power_demand: 900
    zero_output_on_min_power_demand: true
    # A positive buffer value (10) tries to avoid exporting power to the grid (demand - 10 watts)
    # A negative buffer value (-10) exports power to the grid (demand + 10 watts)
    buffer: 10
    # The operation_status_id sensor is expected here. Passing the operation_status won't work
    # The state is used to suspend the limiter if the operation status of the inverter isn't 0x0 (normal)
    # operation_status_id: operation_status_id1

  - id: virtualmeter2
    soyosource_modbus_id: modbus2
    update_interval: 3s
    # the state of this sensor (instantaneous power in watt) is used as source
    power_id: powermeter1
    power_sensor_inactivity_timeout: 20s
    power_demand_calculation: NEGATIVE_MEASUREMENTS_REQUIRED
    min_power_demand: 0
    max_power_demand: 900
    zero_output_on_min_power_demand: true
    # A positive buffer value (10) tries to avoid exporting power to the grid (demand - 10 watts)
    # A negative buffer value (-10) exports power to the grid (demand + 10 watts)
    buffer: 10
    # The operation_status_id sensor is expected here. Passing the operation_status won't work
    # The state is used to suspend the limiter if the operation status of the inverter isn't 0x0 (normal)
    # operation_status_id: operation_status_id1

binary_sensor:
  - platform: soyosource_inverter
    soyosource_inverter_id: inverter0
    fan_running:
      name: "${device0} fan running"
  - platform: soyosource_inverter
    soyosource_inverter_id: inverter1
    fan_running:
      name: "${device1} fan running"
  - platform: soyosource_inverter
    soyosource_inverter_id: inverter2
    fan_running:
      name: "${device2} fan running"

number:
  - platform: soyosource_virtual_meter
    soyosource_virtual_meter_id: virtualmeter0
    buffer:
      name: "${device0} buffer"
      initial_value: 10
      restore_value: true
    manual_power_demand:
      name: "${device0} manual power demand"
    max_power_demand:
      name: "${device0} max power demand"
      initial_value: 600
      restore_value: true
    power_demand_divider:
      name: "${device0} power demand divider"
      initial_value: 1
      restore_value: true

  - platform: soyosource_virtual_meter
    soyosource_virtual_meter_id: virtualmeter1
    buffer:
      name: "${device1} buffer"
      initial_value: 10
      restore_value: true
    manual_power_demand:
      name: "${device1} manual power demand"
    max_power_demand:
      name: "${device1} max power demand"
      initial_value: 600
      restore_value: true
    power_demand_divider:
      name: "${device1} power demand divider"
      initial_value: 1
      restore_value: true

  - platform: soyosource_virtual_meter
    soyosource_virtual_meter_id: virtualmeter2
    buffer:
      name: "${device2} buffer"
      initial_value: 10
      restore_value: true
    manual_power_demand:
      name: "${device2} manual power demand"
    max_power_demand:
      name: "${device2} max power demand"
      initial_value: 600
      restore_value: true
    power_demand_divider:
      name: "${device2} power demand divider"
      initial_value: 1
      restore_value: true

sensor:
  - platform: soyosource_virtual_meter
    soyosource_virtual_meter_id: virtualmeter0
    power_demand:
      name: "${device0} power demand"
  - platform: soyosource_virtual_meter
    soyosource_virtual_meter_id: virtualmeter1
    power_demand:
      name: "${device1} power demand"
  - platform: soyosource_virtual_meter
    soyosource_virtual_meter_id: virtualmeter2
    power_demand:
      name: "${device2} power demand"

  - platform: soyosource_inverter
    soyosource_inverter_id: inverter0
    operation_status_id:
      name: "${device0} operation status id"
      id: operation_status_id0
    battery_voltage:
      name: "${device0} battery voltage"
    battery_current:
      name: "${device0} battery current"
    battery_power:
      name: "${device0} battery power"
    ac_voltage:
      name: "${device0} ac voltage"
    ac_frequency:
      name: "${device0} ac frequency"
    temperature:
      name: "${device0} temperature"
  - platform: soyosource_inverter
    soyosource_inverter_id: inverter1
    operation_status_id:
      name: "${device1} operation status id"
      id: operation_status_id1
    battery_voltage:
      name: "${device1} battery voltage"
    battery_current:
      name: "${device1} battery current"
    battery_power:
      name: "${device1} battery power"
    ac_voltage:
      name: "${device1} ac voltage"
    ac_frequency:
      name: "${device1} ac frequency"
    temperature:
      name: "${device1} temperature"
  - platform: soyosource_inverter
    soyosource_inverter_id: inverter2
    operation_status_id:
      name: "${device2} operation status id"
      id: operation_status_id2
    battery_voltage:
      name: "${device2} battery voltage"
    battery_current:
      name: "${device2} battery current"
    battery_power:
      name: "${device2} battery power"
    ac_voltage:
      name: "${device2} ac voltage"
    ac_frequency:
      name: "${device2} ac frequency"
    temperature:
      name: "${device2} temperature"

  # mqtt subscribe example
  - id: powermeter0
    internal: true
    platform: mqtt_subscribe
    name: "${device0} instantaneous power consumption"
    topic: "smartmeter/sensor/firstfloor/obis/1-0:16.7.0/255/value"
    accuracy_decimals: 2
    unit_of_measurement: W
    device_class: power
    filters:
      - throttle_average: 15s

  - id: powermeter1
    internal: true
    platform: mqtt_subscribe
    name: "${device1} instantaneous power consumption"
    topic: "smartmeter/sensor/groundfloor/obis/1-0:16.7.0/255/value"
    accuracy_decimals: 2
    unit_of_measurement: W
    device_class: power
    filters:
      - throttle_average: 15s

  - id: powermeter2
    internal: true
    platform: mqtt_subscribe
    name: "${device2} instantaneous power consumption"
    topic: "smartmeter/sensor/secondfloor/obis/1-0:16.7.0/255/value"
    accuracy_decimals: 2
    unit_of_measurement: W
    device_class: power
    filters:
      - throttle_average: 15s

#   # import smartmeter reading from homeassistant f.e.
#   # requires the "api" component see above
#    - platform: homeassistant
#     id: powermeter0
#     name: "${device0} smartmeter instantaneous power"
#     entity_id: sensor.firstfloor_smartmeter_instantaneous_power
#
#   - platform: homeassistant
#     id: powermeter1
#     name: "${device1} smartmeter instantaneous power"
#     entity_id: sensor.groundfloor_smartmeter_instantaneous_power

switch:
  - platform: soyosource_virtual_meter
    soyosource_virtual_meter_id: virtualmeter0
    manual_mode:
      name: "${device0} manual mode"
  - platform: soyosource_virtual_meter
    soyosource_virtual_meter_id: virtualmeter1
    manual_mode:
      name: "${device1} manual mode"
  - platform: soyosource_virtual_meter
    soyosource_virtual_meter_id: virtualmeter2
    manual_mode:
      name: "${device2} manual mode"

text_sensor:
  - platform: soyosource_inverter
    soyosource_inverter_id: inverter0
    operation_status:
      name: "${device0} operation status"
  - platform: soyosource_inverter
    soyosource_inverter_id: inverter1
    operation_status:
      name: "${device1} operation status"
  - platform: soyosource_inverter
    soyosource_inverter_id: inverter2
    operation_status:
      name: "${device2} operation status"

  - platform: soyosource_virtual_meter
    soyosource_virtual_meter_id: virtualmeter0
    operation_mode:
      name: "${device0} limiter operation mode"
  - platform: soyosource_virtual_meter
    soyosource_virtual_meter_id: virtualmeter1
    operation_mode:
      name: "${device1} limiter operation mode"
  - platform: soyosource_virtual_meter
    soyosource_virtual_meter_id: virtualmeter2
    operation_mode:
      name: "${device2} limiter operation mode"
ingoooooo commented 1 year ago

Thank you very much. But I am still curious where these numbers come from: tx_pin_uart_0: GPIO1 rx_pin_uart_0: GPIO3 tx_pin_uart_1: GPIO14 rx_pin_uart_1: GPIO4 tx_pin_uart_2: GPIO32 rx_pin_uart_2: GPIO33

Can you give a little explanation if you do not mind?

syssi commented 1 year ago

A ESP32 supports three hardware UARTs. Because of the GPIO Matrix / Pin mux the hardware UARTs can be assigned to any GPIO. In other words: You can choose any GPIO.

ingoooooo commented 1 year ago

Does that mean that other pins need to be soldered compared to those shown on your photo? https://github.com/syssi/esphome-soyosource-gtn-virtual-meter/blob/main/images/circuit.jpg

I am planning to upgrade from one inverter to three.

syssi commented 1 year ago

There are two options:

  1. Use the schematics above and attach all inverters to the same RS485. Set the divider at the configuration to the number of the attached inverters. As soon as there is an power demand all inverter will provide the power partially.
  2. Attach three RS485 converter modules to three different sets of GPIOs and drive the inverters individually.

What's you goal?

ingoooooo commented 1 year ago

Hello Sebastian,

okay, now I got it. I was confused as I thought there has to be a combination of divider AND GPIOs. Your last message made it clear. Thanks a lot.

I think the easiest way is option one. Obviously I won't have so much control over each inverter are there other disadvantages when using the divider?

syssi commented 1 year ago

I recommend the simple approach (divider) too to avoid complexity. In case of different smartmeters (households) the second approach fits better.

ingoooooo commented 1 year ago

Thank you very much for your help and your great project!