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

feat(Deye/Sunsynk): add Modbus over RS-485 option #269

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .luacheckrc
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ stds.vucm = {
modbustcp = {
fields = { 'new', 'err_to_str' },
},
modbusrtu = {
fields = { 'new', 'err_to_str' },
},
http = {
fields = { 'get', 'post', 'post_form', 'client', 'request' },
},
Expand Down
16 changes: 16 additions & 0 deletions solar_inverters/deye_sun-10k-sg04lp3-eu_modbus/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Deye SUN-10k-SG04LP3-EU (Modbus over RS-485)

This [Enapter Device Blueprint](https://go.enapter.com/marketplace-readme) integrates **Deye Inverter SUN-10k-SG04LP3-EU** - three-phase hybrid inverter connected to Enapter Gateway via serial port. [Enapter Virtual UCM](https://go.enapter.com/handbook-vucm) handles RS-485 connection.

## Connect to Enapter

- Sign up to Enapter Cloud using [Web](https://cloud.enapter.com/) or mobile app ([iOS](https://apps.apple.com/app/id1388329910), [Android](https://play.google.com/store/apps/details?id=com.enapter&hl=en)).
- Use [Enapter Gateway](https://go.enapter.com/handbook-gateway-setup) to run Virtual UCM.
- Create [Enapter Virtual UCM](https://go.enapter.com/handbook-vucm).
- [Upload](https://go.enapter.com/developers-upload-blueprint) this blueprint to Enapter Virtual UCM.
- Use the `Set Up Modbus Connection` command in the Enapter mobile or Web app to set up the following communication parameters:
- Your Deye inverter's Modbus address

## References

- [Deye Inverter product page](https://www.deyeinverter.com/product/hybrid-inverter-1/sun5-6-8-10-12ksg04lp3.html)
112 changes: 112 additions & 0 deletions solar_inverters/deye_sun-10k-sg04lp3-eu_modbus/firmware.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
local config = require('enapter.ucm.config')

-- Configuration variables must be also defined
-- in `write_configuration` command arguments in manifest.yml
ADDRESS = 'address'

function main()
scheduler.add(1000, send_telemetry)
scheduler.add(30000, send_properties)
config.init({
[ADDRESS] = { type = 'number', required = true, default = 1 },
})
end

function send_properties()
enapter.send_properties({
vendor = 'Deye',
model = 'SUN-10k-SG04LP3-EU'
})
end

function send_telemetry()
local modbus = modbusrtu.new("/dev/ttyUSB0", {
baud_rate=9600, data_bits=8, stop_bits=1, parity="N", read_timeout=1000
})

local addr, err = config.read(ADDRESS)
if err ~= nil then
enapter.send_telemetry({
status = 'warning',
alerts = {'config_read_error'}
})
return
end

local telemetry = {}

local data, err = modbus:read_holdings(addr, 514, 13, 1000)
if err ~= 0 then
enapter.log('514-526: ' .. modbusrtu.err_to_str(err), 'error')
else
telemetry.total_battery_charge = data[1] * 0.1
telemetry.total_battery_discharge = data[515 - 514 + 1] * 0.1
telemetry.day_gridbuy_power = data[520 - 514 + 1] * 0.1
telemetry.day_gridsell_power = data[521 - 514 + 1] * 0.1
telemetry.day_load_power = data[526 - 514 + 1] * 0.1
end

local data, err = modbus:read_holdings(addr, 587, 5, 1000)
if err ~= 0 then
enapter.log('587-591: ' .. modbusrtu.err_to_str(err), 'error')
else
telemetry.battery_voltage = data[1] * 0.01
telemetry.battery_output_power = data[590 - 587 + 1]
telemetry.battery_output_current = data[591 - 587 + 1]
end

local data, err = modbus:read_holdings(addr, 604, 6, 1000)
if err ~= 0 then
enapter.log('604-609: ' .. modbusrtu.err_to_str(err), 'error')
else
telemetry.inner_grid_power_a = data[1]
telemetry.inner_grid_power_b = data[605 - 604 + 1]
telemetry.inner_grid_power_c = data[606 - 604 + 1]
telemetry.total_active_power_side_to_side = data[607 - 604 + 1]
telemetry.grid_frequency = data[609 - 604 + 1]
end

local data, err = modbus:read_holdings(addr, 616, 10, 1000)
if err ~= 0 then
enapter.log('616-619: ' .. modbusrtu.err_to_str(err), 'error')
else
telemetry.out_of_grid_power_a = data[1]
telemetry.out_of_grid_power_b = data[617 - 616 + 1]
telemetry.out_of_grid_power_c = data[618 - 616 + 1]
telemetry.total_out_of_grid_power = data[619 - 616 + 1]
end

local data, err = modbus:read_holdings(addr, 622, 4, 1000)
if err ~= 0 then
enapter.log('622-625: ' .. modbusrtu.err_to_str(err), 'error')
else
telemetry.grid_power_a = data[1]
telemetry.grid_power_b = data[2]
telemetry.grid_power_c = data[3]
telemetry.total_grid_power = data[4]
end

local data, err = modbus:read_holdings(addr, 633, 4, 1000)
if err ~= 0 then
enapter.log('633-636: ' .. modbusrtu.err_to_str(err), 'error')
else
telemetry.inverter_output_power_a = data[1]
telemetry.inverter_output_power_b = data[2]
telemetry.inverter_output_power_c = data[3]
telemetry.total_inverter_output_power = data[4]
end

local data, err = modbus:read_holdings(addr, 650, 4, 1000)
if err ~= 0 then
enapter.log('650-653: ' .. modbusrtu.err_to_str(err), 'error')
else
telemetry.load_power_a = data[1]
telemetry.load_power_b = data[2]
telemetry.load_power_c = data[3]
telemetry.total_load_power = data[4]
end

enapter.send_telemetry(telemetry)
end

main()
184 changes: 184 additions & 0 deletions solar_inverters/deye_sun-10k-sg04lp3-eu_modbus/manifest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
blueprint_spec: device/1.0

display_name: Deye / Sunsynk Inverter (via Modbus RTU)
description: Three phase hybrid inverter with low battery voltage 48V.
icon: enapter-solar-inverter
license: MIT
author: enapter
contributors:
- anataty
support:
url: https://go.enapter.com/enapter-blueprint-support
email: support@enapter.com
verification_level: verified

communication_module:
product: ENP-VIRTUAL
lua:
file: firmware.lua
dependencies:
- enapter-ucm
allow_dev_dependencies: true

properties:
serial_number:
type: string
display_name: Serial number

telemetry:
status:
type: string
display_name: State
enum:
- ok
- warning
total_battery_charge:
display_name: Total Battery Charge
type: float
unit: kwatth
total_battery_discharge:
display_name: Total Battery Discharge
type: float
unit: kwatth
day_gridbuy_power:
display_name: Day Grid Buy Power
type: float
unit: kwatth
day_gridsell_power:
display_name: Day Grid Sell Power
type: float
unit: kwatth
day_load_power:
display_name: Day Load Power
type: float
unit: kwatth
battery_voltage:
display_name: Battery Voltage
type: float
unit: volt
battery_output_power:
display_name: Battery Output Power
type: float
unit: watt
battery_output_current:
display_name: Battery Output Current
type: float
unit: amp
inner_grid_power_a:
display_name: Inner Grid Power Phase A
type: float
unit: watt
inner_grid_power_b:
display_name: Inner Grid Power Phase B
type: float
unit: watt
inner_grid_power_c:
display_name: Inner Grid Power Phase C
type: float
unit: watt
total_active_power_side_to_side:
display_name: Total Active Power from side to side of the grid
type: float
unit: watt
grid_frequency:
display_name: Grid Frequency
type: float
unit: hertz
out_of_grid_power_a:
display_name: Out-of-Grid Power Phase A
type: float
unit: watt
out_of_grid_power_b:
display_name: Out-of-Grid Power Phase B
type: float
unit: watt
out_of_grid_power_c:
display_name: Out-of-Grid Power Phase C
type: float
unit: watt
total_out_of_grid_power:
display_name: Total Out-of-Grid Power
type: float
unit: watt
grid_power_a:
display_name: Grid Power Phase A
type: float
unit: watt
grid_power_b:
display_name: Grid Power Phase B
type: float
unit: watt
grid_power_c:
display_name: Grid Power Phase C
type: float
unit: watt
total_grid_power:
display_name: Total Grid Power
type: float
unit: watt
inverter_output_power_a:
display_name: Inverter Output Power Phase A
type: float
unit: watt
inverter_output_power_b:
display_name: Inverter Output Power Phase B
type: float
unit: watt
inverter_output_power_c:
display_name: Inverter Output Power Phase C
type: float
unit: watt
total_inverter_output_power:
display_name: Total Inverter Output Power
type: float
unit: watt
load_power_a:
display_name: Load Power Phase A
type: float
unit: watt
load_power_b:
display_name: Load Power Phase B
type: float
unit: watt
load_power_c:
display_name: Load Power Phase C
type: float
unit: watt
total_load_power:
display_name: Total Load Power
type: float
unit: watt

alerts:
config_read_error:
display_name: Configuration read error
severity: warning

command_groups:
connection:
display_name: Connection

commands:
write_configuration:
display_name: Set Up Modbus Connection
group: connection
populate_values_command: read_configuration
ui:
icon: file-document-edit-outline
arguments:
address:
display_name: Modbus address
type: integer
required: true
read_configuration:
display_name: Read Connection Parameters
group: connection
ui:
icon: file-check-outline

.cloud:
category: renewable_energy_sources
mobile_main_chart: day_grid_sell_power
mobile_charts:
- total_load_power
- battery_voltage
Loading