From c281c69b5e02cf19d6d0cd845442c1a3b22ede46 Mon Sep 17 00:00:00 2001 From: Tatyana Date: Wed, 15 Mar 2023 15:45:46 +0100 Subject: [PATCH] (blueprint) update SRNE ML-2440 --- .../srne_ml-2440/firmware.lua | 434 +++++++++--------- .../srne_ml-2440/manifest.yml | 113 ++++- 2 files changed, 320 insertions(+), 227 deletions(-) diff --git a/solar_charge_controllers/srne_ml-2440/firmware.lua b/solar_charge_controllers/srne_ml-2440/firmware.lua index d8b0aafd..4ff52805 100755 --- a/solar_charge_controllers/srne_ml-2440/firmware.lua +++ b/solar_charge_controllers/srne_ml-2440/firmware.lua @@ -3,11 +3,14 @@ ADDRESS = 1 function main() local result = rs232.init(9600, 8, "N", 1) if result ~= 0 then - enapter.log("RS-232 failed: "..result.." "..rs232.err_to_str(result), "error", true) + enapter.log("RS232 failed: "..result.." "..rs232.err_to_str(result), "error", true) end scheduler.add(30000, send_properties) - scheduler.add(1000, metrics) + scheduler.add(1000, send_telemetry) + + enapter.register_command_handler("read_controller_parameters", read_controller_parameters) + enapter.register_command_handler("write_controller_parameters", write_controller_parameters) end function send_properties() @@ -27,20 +30,20 @@ function send_properties() enapter.send_properties(properties) end -function metrics() +function send_telemetry() local telemetry = {} local alerts = {} local status = "ok" - local data, result = modbus.read_holdings(ADDRESS, 11, 1, 1000) - if data then - telemetry["rated_disc_current"] = data[1] >> 8 - telemetry["device_type"] = data[1] & 0xFF - else - enapter.log("Register 11 reading failed: "..modbus.err_to_str(result), "error") - alerts = {"communication_failed"} - status = "read_error" - end + -- local data, result = modbus.read_holdings(ADDRESS, 11, 1, 1000) + -- if data then + -- telemetry["rated_disc_current"] = data[1] >> 8 + -- telemetry["device_type"] = data[1] & 0xFF + -- else + -- enapter.log("Register 11 reading failed: "..modbus.err_to_str(result), "error") + -- alerts = {"communication_failed"} + -- status = "read_error" + -- end -- Controller dynamic information local data, result = modbus.read_holdings(ADDRESS, 256, 1, 1000) @@ -56,7 +59,7 @@ function metrics() if data then telemetry["battery_voltage"] = data[1] / 10.0 else - enapter.log("Register 256 reading failed: "..modbus.err_to_str(result), "error") + enapter.log("Register 257 reading failed: "..modbus.err_to_str(result), "error") alerts = {"communication_failed"} status = "read_error" end @@ -70,15 +73,15 @@ function metrics() status = "read_error" end - local data, result = modbus.read_holdings(ADDRESS, 259, 1, 1000) - if data then - telemetry["controller_temp"] = tosignedint(data[1] >> 8) - telemetry["battery_temp"] = tosignedint(data[1] >> 0xFF) - else - enapter.log("Register 259 reading failed: "..modbus.err_to_str(result), "error") - alerts = {"communication_failed"} - status = "read_error" - end + -- local data, result = modbus.read_holdings(ADDRESS, 259, 1, 1000) + -- if data then + -- telemetry["controller_temp"] = tosignedint(data[1] >> 8) + -- telemetry["battery_temp"] = tosignedint(data[1] >> 0xFF) + -- else + -- enapter.log("Register 259 reading failed: "..modbus.err_to_str(result), "error") + -- alerts = {"communication_failed"} + -- status = "read_error" + -- end local data, result = modbus.read_holdings(ADDRESS, 260, 1, 1000) if data then @@ -136,180 +139,170 @@ function metrics() end -- Battery information - local data, result = modbus.read_holdings(ADDRESS, 267, 1, 1000) - if data then - telemetry["today_min_battery_volt"] = data[1] / 10.0 - else - enapter.log("Register 267 reading failed: "..modbus.err_to_str(result), "error") - alerts = {"communication_failed"} - status = "read_error" - end - - local data, result = modbus.read_holdings(ADDRESS, 268, 1, 1000) - if data then - telemetry["today_max_battery_volt"] = data[1] / 10.0 - else - enapter.log("Register 268 reading failed: "..modbus.err_to_str(result), "error") - alerts = {"communication_failed"} - status = "read_error" - end - - local data, result = modbus.read_holdings(ADDRESS, 269, 1, 1000) - if data then - telemetry["today_max_charging_curr"] = data[1] / 100.0 - else - enapter.log("Register 269 reading failed: "..modbus.err_to_str(result), "error") - alerts = {"communication_failed"} - status = "read_error" - end - - local data, result = modbus.read_holdings(ADDRESS, 270, 1, 1000) - if data then - telemetry["today_max_discharging_curr"] = data[1] / 100.0 - else - enapter.log("Register 270 reading failed: "..modbus.err_to_str(result), "error") - alerts = {"communication_failed"} - status = "read_error" - end - - local data, result = modbus.read_holdings(ADDRESS, 0x10F, 1, 1000) - if data then - telemetry["today_max_charging_power"] = data[1] - else - enapter.log("Register 0x10F reading failed: "..modbus.err_to_str(result), "error") - alerts = {"communication_failed"} - status = "read_error" - end - - local data, result = modbus.read_holdings(ADDRESS, 0x110, 1, 1000) - if data then - telemetry["today_max_discharging_power"] = data[1] - else - enapter.log("Register 0x110 reading failed: "..modbus.err_to_str(result), "error") - alerts = {"communication_failed"} - status = "read_error" - end - - local data, result = modbus.read_holdings(ADDRESS, 0x111, 1, 1000) - if data then - telemetry["today_charging_amp_hrs"] = data[1] - else - enapter.log("Register 0x111 reading failed: "..modbus.err_to_str(result), "error") - alerts = {"communication_failed"} - status = "read_error" - end - - local data, result = modbus.read_holdings(ADDRESS, 0x112, 1, 1000) - if data then - telemetry["today_discharging_amp_hrs"] = data[1] - else - enapter.log("Register 0x112 reading failed: "..modbus.err_to_str(result), "error") - alerts = {"communication_failed"} - status = "read_error" - end - - local data, result = modbus.read_holdings(ADDRESS, 0x113, 1, 1000) - if data then - telemetry["today_power_generation"] = data[1] - else - enapter.log("Register 0x113 reading failed: "..modbus.err_to_str(result), "error") - alerts = {"communication_failed"} - status = "read_error" - end - - local data, result = modbus.read_holdings(ADDRESS, 0x114, 1, 1000) - if data then - telemetry["today_power_consumption"] = data[1] - else - enapter.log("Register 0x114 reading failed: "..modbus.err_to_str(result), "error") - alerts = {"communication_failed"} - status = "read_error" - end - - -- Historical data information - local data, result = modbus.read_holdings(ADDRESS, 0x115, 1, 1000) - if data then - telemetry["operating_days"] = data[1] - else - enapter.log("Register 0x115 reading failed: "..modbus.err_to_str(result), "error") - alerts = {"communication_failed"} - status = "read_error" - end - - local data, result = modbus.read_holdings(ADDRESS, 0x116, 1, 1000) - if data then - telemetry["battery_over_discharges"] = data[1] - else - enapter.log("Register 0x116 reading failed: "..modbus.err_to_str(result), "error") - alerts = {"communication_failed"} - status = "read_error" - end - - local data, result = modbus.read_holdings(ADDRESS, 0x117, 1, 1000) - if data then - telemetry["battery_full_charges"] = data[1] - else - enapter.log("Register 0x117 reading failed: "..modbus.err_to_str(result), "error") - alerts = {"communication_failed"} - status = "read_error" - end - - local data, result = modbus.read_holdings(ADDRESS, 0x118, 2, 1000) - if data then - telemetry["charging_amp_hrs"] = toint(data) - else - enapter.log("Register 0x118 reading failed: "..modbus.err_to_str(result), "error") - alerts = {"communication_failed"} - status = "read_error" - end - - local data, result = modbus.read_holdings(ADDRESS, 0x11A, 2, 1000) - if data then - telemetry["discharging_amp_hrs"] = toint(data) - else - enapter.log("Register 0x11A reading failed: "..modbus.err_to_str(result), "error") - alerts = {"communication_failed"} - status = "read_error" - end - - local data, result = modbus.read_holdings(ADDRESS, 0x11C, 2, 1000) - if data then - telemetry["cumulative_power_gen"] = toint(data) - else - enapter.log("Register 0x11C reading failed: "..modbus.err_to_str(result), "error") - alerts = {"communication_failed"} - status = "read_error" - end - - local data, result = modbus.read_holdings(ADDRESS, 0x11E, 2, 1000) - if data then - telemetry["cumulative_power_consum"] = toint(data) - else - enapter.log("Register 0x11E reading failed: "..modbus.err_to_str(result), "error") - alerts = {"communication_failed"} - status = "read_error" - end - - local data, result = modbus.read_holdings(ADDRESS, 0x120, 1, 1000) - if data then - telemetry["load_status"] = is_on(data[1] >> 15) - telemetry["load_brightness"] = (data[1] >> 8) & 0x7F - telemetry["charging_state"] = data[1] >> 0xFF - else - enapter.log("Register 0x120 reading failed: "..modbus.err_to_str(result), "error") - alerts = {"communication_failed"} - status = "read_error" - end - - --- TEST --- - local data, result = modbus.read_holdings(ADDRESS, 0xE01D, 1, 1000) - if data then - telemetry["load_working_mode"] = data[1] - else - enapter.log("Register 0xE01D reading failed: "..modbus.err_to_str(result), "error") - alerts = {"communication_failed"} - status = "read_error" - end + -- local data, result = modbus.read_holdings(ADDRESS, 267, 1, 1000) + -- if data then + -- telemetry["today_min_battery_volt"] = data[1] / 10.0 + -- else + -- enapter.log("Register 267 reading failed: "..modbus.err_to_str(result), "error") + -- alerts = {"communication_failed"} + -- status = "read_error" + -- end + + -- local data, result = modbus.read_holdings(ADDRESS, 268, 1, 1000) + -- if data then + -- telemetry["today_max_battery_volt"] = data[1] / 10.0 + -- else + -- enapter.log("Register 268 reading failed: "..modbus.err_to_str(result), "error") + -- alerts = {"communication_failed"} + -- status = "read_error" + -- end + + -- local data, result = modbus.read_holdings(ADDRESS, 269, 1, 1000) + -- if data then + -- telemetry["today_max_charging_curr"] = data[1] / 100.0 + -- else + -- enapter.log("Register 269 reading failed: "..modbus.err_to_str(result), "error") + -- alerts = {"communication_failed"} + -- status = "read_error" + -- end + + -- local data, result = modbus.read_holdings(ADDRESS, 270, 1, 1000) + -- if data then + -- telemetry["today_max_discharging_curr"] = data[1] / 100.0 + -- else + -- enapter.log("Register 270 reading failed: "..modbus.err_to_str(result), "error") + -- alerts = {"communication_failed"} + -- status = "read_error" + -- end + + -- local data, result = modbus.read_holdings(ADDRESS, 0x10F, 1, 1000) + -- if data then + -- telemetry["today_max_charging_power"] = data[1] + -- else + -- enapter.log("Register 0x10F reading failed: "..modbus.err_to_str(result), "error") + -- alerts = {"communication_failed"} + -- status = "read_error" + -- end + + -- local data, result = modbus.read_holdings(ADDRESS, 0x110, 1, 1000) + -- if data then + -- telemetry["today_max_discharging_power"] = data[1] + -- else + -- enapter.log("Register 0x110 reading failed: "..modbus.err_to_str(result), "error") + -- alerts = {"communication_failed"} + -- status = "read_error" + -- end + + -- local data, result = modbus.read_holdings(ADDRESS, 0x111, 1, 1000) + -- if data then + -- telemetry["today_charging_amp_hrs"] = data[1] + -- else + -- enapter.log("Register 0x111 reading failed: "..modbus.err_to_str(result), "error") + -- alerts = {"communication_failed"} + -- status = "read_error" + -- end + + -- local data, result = modbus.read_holdings(ADDRESS, 0x112, 1, 1000) + -- if data then + -- telemetry["today_discharging_amp_hrs"] = data[1] + -- else + -- enapter.log("Register 0x112 reading failed: "..modbus.err_to_str(result), "error") + -- alerts = {"communication_failed"} + -- status = "read_error" + -- end + + -- local data, result = modbus.read_holdings(ADDRESS, 0x113, 1, 1000) + -- if data then + -- telemetry["today_power_generation"] = data[1] + -- else + -- enapter.log("Register 0x113 reading failed: "..modbus.err_to_str(result), "error") + -- alerts = {"communication_failed"} + -- status = "read_error" + -- end + + -- local data, result = modbus.read_holdings(ADDRESS, 0x114, 1, 1000) + -- if data then + -- telemetry["today_power_consumption"] = data[1] + -- else + -- enapter.log("Register 0x114 reading failed: "..modbus.err_to_str(result), "error") + -- alerts = {"communication_failed"} + -- status = "read_error" + -- end + + -- -- Historical data information + -- local data, result = modbus.read_holdings(ADDRESS, 0x115, 1, 1000) + -- if data then + -- telemetry["operating_days"] = data[1] + -- else + -- enapter.log("Register 0x115 reading failed: "..modbus.err_to_str(result), "error") + -- alerts = {"communication_failed"} + -- status = "read_error" + -- end + + -- local data, result = modbus.read_holdings(ADDRESS, 0x116, 1, 1000) + -- if data then + -- telemetry["battery_over_discharges"] = data[1] + -- else + -- enapter.log("Register 0x116 reading failed: "..modbus.err_to_str(result), "error") + -- alerts = {"communication_failed"} + -- status = "read_error" + -- end + + -- local data, result = modbus.read_holdings(ADDRESS, 0x117, 1, 1000) + -- if data then + -- telemetry["battery_full_charges"] = data[1] + -- else + -- enapter.log("Register 0x117 reading failed: "..modbus.err_to_str(result), "error") + -- alerts = {"communication_failed"} + -- status = "read_error" + -- end + + -- local data, result = modbus.read_holdings(ADDRESS, 0x118, 2, 1000) + -- if data then + -- telemetry["charging_amp_hrs"] = toint(data) + -- else + -- enapter.log("Register 0x118 reading failed: "..modbus.err_to_str(result), "error") + -- alerts = {"communication_failed"} + -- status = "read_error" + -- end + + -- local data, result = modbus.read_holdings(ADDRESS, 0x11A, 2, 1000) + -- if data then + -- telemetry["discharging_amp_hrs"] = toint(data) + -- else + -- enapter.log("Register 0x11A reading failed: "..modbus.err_to_str(result), "error") + -- alerts = {"communication_failed"} + -- status = "read_error" + -- end + + -- local data, result = modbus.read_holdings(ADDRESS, 0x11C, 2, 1000) + -- if data then + -- telemetry["cumulative_power_gen"] = toint(data) + -- else + -- enapter.log("Register 0x11C reading failed: "..modbus.err_to_str(result), "error") + -- alerts = {"communication_failed"} + -- status = "read_error" + -- end + + -- local data, result = modbus.read_holdings(ADDRESS, 0x11E, 2, 1000) + -- if data then + -- telemetry["cumulative_power_consum"] = toint(data) + -- else + -- enapter.log("Register 0x11E reading failed: "..modbus.err_to_str(result), "error") + -- alerts = {"communication_failed"} + -- status = "read_error" + -- end + + -- local data, result = modbus.read_holdings(ADDRESS, 0x120, 1, 1000) + -- if data then + -- telemetry["load_status"] = is_on(data[1] >> 15) + -- telemetry["load_brightness"] = (data[1] >> 8) & 0x7F + -- telemetry["charging_state"] = data[1] >> 0xFF + -- else + -- enapter.log("Register 0x120 reading failed: "..modbus.err_to_str(result), "error") + -- alerts = {"communication_failed"} + -- status = "read_error" + -- end -- Controller fault information local data, result = modbus.read_holdings(ADDRESS, 0x121, 2, 1000) @@ -334,8 +327,6 @@ function metrics() table.insert(alerts, "high_ambient_temp") elseif (data[1] << 10) >> 15 == 1 then table.insert(alerts, "high_controller_temp") - elseif (data[1] << 10) >> 15 == 1 then - table.insert(alerts, "high_controller_temp") elseif (data[1] << 11) >> 15 == 1 then table.insert(alerts, "load_overpower") elseif (data[1] << 12) >> 15 == 1 then @@ -359,28 +350,28 @@ function metrics() enapter.send_telemetry(telemetry) end -function is_on(value) - if value == 1 then - return true - else - return false - end -end - -function toint(register) - local raw_str = string.pack("BBBB", register[1]>>8, register[1]&0xff, register[2]>>8, register[2]&0xff) - return string.unpack(">I4", raw_str) -end - -function tosignedint(value) - local byte7 = value >> 7 - local result = value & 0x7F - if byte7 == 1 then - return result * (-1) - else - return result - end -end +-- function is_on(value) +-- if value == 1 then +-- return true +-- else +-- return false +-- end +-- end + +-- function toint(register) +-- local raw_str = string.pack("BBBB", register[1]>>8, register[1]&0xff, register[2]>>8, register[2]&0xff) +-- return string.unpack(">I4", raw_str) +-- end + +-- function tosignedint(value) +-- local byte7 = value >> 7 +-- local result = value & 0x7F +-- if byte7 == 1 then +-- return result * (-1) +-- else +-- return result +-- end +-- end function read_controller_parameters(ctx) local parameters = {} @@ -425,9 +416,6 @@ function write_controller_parameters(ctx, args) end end -enapter.register_command_handler("read_controller_parameters", read_controller_parameters) -enapter.register_command_handler("write_controller_parameters", write_controller_parameters) - main() --[[function from_float_to_int32(number) diff --git a/solar_charge_controllers/srne_ml-2440/manifest.yml b/solar_charge_controllers/srne_ml-2440/manifest.yml index 88761c7a..ed8d6eee 100755 --- a/solar_charge_controllers/srne_ml-2440/manifest.yml +++ b/solar_charge_controllers/srne_ml-2440/manifest.yml @@ -24,6 +24,14 @@ properties: model: type: string display_name: Model + max_voltage: + display_name: Maximum Voltage Supported by System + type: float + unit: V + power_l1: + display_name: Maximum Current Supported by System + type: float + unit: A telemetry: status: @@ -32,19 +40,116 @@ telemetry: enum: - ok - read_error - max_voltage: - display_name: Maximum Voltage Supported by System + battery_soc: + display_name: Battery SOC + type: float + unit: '%' + battery_voltage: + display_name: Battery Voltage type: float unit: V - power_l1: - display_name: Maximum Current Supported by System + charging_current: + display_name: Charging Current type: float unit: A + load_dc_voltage: + display_name: Load DC Voltage + type: float + unit: V + load_dc_current: + display_name: Load DC Current + type: float + unit: A + load_dc_power: + display_name: Load DC Power + type: float + unit: W + solar_panel_voltage: + display_name: Solar Panel Voltage + type: float + unit: V + solar_panel_current: + display_name: Solar Panel Current + type: float + unit: V + charging_power: + display_name: Charging Power + type: float + unit: W + # controller_temp: + # display_name: Controller temperature + # type: float + # unit: '°C' + # battery_temp: + # display_name: Battery temperature + # type: float + # unit: '°C' alerts: communication_failed: display_name: Communication Failed severity: error + charge_mos_short_circuit: + display_name: Charge MOS short circuit + severity: error + anti_reverse_mos_short: + display_name: Anti-reverse MOS short circuit + severity: error + solar_panel_reverse_connect: + display_name: Solar panel reversely connected + severity: error + solar_panel_over_voltage: + display_name: Solar panel working point over-voltage + severity: error + solar_panel_ctr_current: + display_name: Solar panel counter-current + severity: error + pv_input_over_voltage: + display_name: PV input side over-voltage + severity: error + pv_input_short_circuit: + display_name: PV input side short circuit + severity: error + pv_input_overpower: + display_name: PV input side over-power + severity: error + high_ambient_temp: + display_name: High ambient temperature + severity: error + high_controller_temp: + display_name: High controller temperature + severity: error + load_overpower: + display_name: Load over-power + severity: error + load_short_circuit: + display_name: Load short circuit + severity: error + battery_under_voltage: + display_name: Battery under-voltage + severity: warning + battery_over_voltage: + display_name: Battery over-voltage + severity: error + battery_over_discharge: + display_name: Battery over-discharge + severity: error .cloud: category: renewable_energy_sources + mobile_main_chart: battery_soc + mobile_telemetry: + - battery_soc + - battery_voltage + - charging_current + - load_dc_power + - solar_panel_voltage + mobile_charts: + - battery_soc + - battery_voltage + - charging_current + - load_dc_voltage + - load_dc_current + - load_dc_power + - solar_panel_voltage + - charging_power