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

Full BMS support for PI17 #219

Open
riogrande75 opened this issue Apr 29, 2022 · 28 comments
Open

Full BMS support for PI17 #219

riogrande75 opened this issue Apr 29, 2022 · 28 comments

Comments

@riogrande75
Copy link

riogrande75 commented Apr 29, 2022

With later firmware versions (>2017) of the infini-/mpp-solar 10+15kw inverters, full bms support was implemented.
Only supported BMS I'm aware of is pylontech via RS485 bus. You need a extra modbus-card (with modified fw on it) so the inverter can communicate with the bms. See http://www.mppsolar.com/manual/ACCESSORIES%20(FOR%20MONITORING)/BMS%20RS485%20Card/RS485-Card-Box-for%20BMS-manual-20181106.pdf
While pylontech's rs485 bms commandos are well know, the internal communication between the (bms-)modbus card and the inverter is secret.
To disclose the secret I disassamled the slave firmware of the 10k and noticed 2 PI17 commands that might be involved:
BMS
BMSV

The BMSV command just reads out the fw-version (date) from the plugged bms-card - so quite uninterresting.

BMSV: (BMSCARD:0000-00-00
BMSVersionTimeYear
BMSVersionTimeYear
BMSVersionTimeDay

The BMS commando seems to be more usefult to let any BMS communicate with the inverter.
This is what I explored so far:

^D0520000,000,0,0000,00,0,0000,0000,0000,0,0,0000,0000
^D0520aaa,bbb,c,dddd,ee,f,gggg,hhhh,iiii,j,k,llll,mmmm

; aaa
; bbb
; c
; dddd
; ee
 
; j
; k 
; llll: BMS max charge curr (amps)
; mmmm: BMS max discharge curr (amps)


; ; P B M S a bbb c d e fff ggg hhh iiii jjjj<CRC><cr>
; 0 1 2 3 4 567 9 B D F01 345 789 BCDE 0123 45 6
; 0 1 2
; a : disconnect
; bbb : BMS SOC%
; c : BMS force AC charge
; d : Bat stop discharge flag
; e : Bat stop charge flag
; fff : BMS bat CV volt
; ggg : BMS Bat float volt
; hhh : BMS bat cutoff volt
; iiii: BMS max charge curr (amps)
; jjjj: BMS max discharge curr (amps)

Anyone here interrested in getting together this 2 scripts (mpp-solar + jkbms)?

@jblance
Copy link
Owner

jblance commented May 3, 2022

Seems like you could achieve something with a specific output module, i.e

  • command to query BMS
  • gets needed results
  • outputs formated result to Inverter

this type of output hasnt been implemented yet, but shouldnt be a problem (with a lot of testing)
I'm (slowly) working on a more flexible process (powermon command in latest versions) that will allow for better configuration of inputs and outputs - seems like the above would work better with that, but the current mppsolar/jkbms commands should be able to made to work with a bunch of extra options

@riogrande75
Copy link
Author

Ok, thx.
I'll investigate commands further.
Some help with logfiles from other users would be very helpful.
Can any of the MPI10k users pls. send me the inverter's reply for the command ^P004BMS?

@riogrande75
Copy link
Author

riogrande75 commented Aug 17, 2022

After a long research I've finally found out, how PI17/PI18 inverters (10k, 15k) get the BMS values.

Conclusion: You simply need to send a ^D054BMS... string periodically to the inverter.
Format looks like this:
BMSprot
I created a script to read bms data from a mqtt server and create the ^D054BMS string that can be sent to the inverter: readmqttbms.php
Sending this to the inverter let's the display show the "LI-bAt" and battery values read from BMS.
10kDisplayLiBat
The inverter get's informed about BMS stoped charging/discharging and can react correctly:
LiBatWarn

@jblance Maybe you can implement this in your work - reading data from jk-bms (I do that currently with a extra ESP32 from https://forum.drbacke.de/viewtopic.php?t=982) and send it to mpp solar inverter.

@jblance jblance added this to the BMS to inverter support milestone Jan 8, 2023
@gianfrdp
Copy link
Contributor

gianfrdp commented May 4, 2023

After a long research I've finally found out, how PI17/PI18 inverters (10k, 15k) get the BMS values.

Conclusion: You simply need to send a ^D054BMS... string periodically to the inverter.

Hello,
how php script sends string to inverter?
And which battery type needs to be selected on inverter to let this protocol work?

@jblance jblance removed this from the 0.19 release - bms to inverter milestone Jun 23, 2023
@rene-dev
Copy link
Contributor

I have MPI 10k, and successfully used this command to set charge and discharge limits, and alarms.
converting them from pylontech battery connected via can.
Will share my code when its finished.
^P004BMS reply is:
b'^D0520422,042,0,0000,01,0,0535,0525,0500,0,0,0500,0010\x15\xd3\r'

@danieltroger
Copy link

danieltroger commented Apr 1, 2024

Hi, slightly off-topic because I don't need/have any BMS.
But I have an MPPSolar MPI 15KW inverter and wondered how you guys were able to communicate with it using this project? I'd like to, for example, receive the current charging amperage, but the "default" mpp-solar commands don't seem to work.

Edit: I managed to communicate using protocol 17!

ubuntu@ubuntu:~$ sudo  mpp-solar -P PI17  -p /dev/hidraw0  -c INGS
Command: INGS - 
--------------------------------------------------------------------------------
Parameter                    Value          	Unit
input_current_r              112            	0.1A
input_current_s              116            	0.1A
input_current_t              114            	0.1A
output_current_r             4              	0.1A
output_current_s             92             	0.1A
output_current_t             7              	0.1A
pbusvolt                     4142           	0.1V
nbusvolt                     4142           	0.1V
pbusavgv                     4135           	0.1V
nbusavgv                     4137           	0.1V
nlintcur                     0              	0.1A
unknown_value_in_response_11 0007           	    
unknown_value_in_response_12 0090           	    
------------------------------------
ubuntu@ubuntu:~$ sudo  mpp-solar -P PI17  -p /dev/hidraw0  -c PS
Command: PS - Device Power Status
--------------------------------------------------------------------------------
Parameter                      Value          	Unit
solar_input_power_1            2529           	W   
solar_input_power_2            3669           	W   
ac_input_active_power_r        1959           	W   
ac_input_active_power_s        -1927          	W   
ac_input_active_power_t        -1835          	W   
ac_input_total_active_power    -5721          	W   
ac_output_active_power_r       14             	W   
ac_output_active_power_s       78             	W   
ac_output_active_power_t       179            	W   
ac_output_total_active_power   252            	W   
ac_output_apparent_power_r     119            	VA  
ac_output_apparent_power_s     94             	VA  
ac_output_apparent_power_t     236            	VA  
ac_output_total_apparent_power 450            	VA  
ac_output_power_percentage     3              	%   
ac_output_connect_status       Connected      	    
solar_input_1_work_status      Working        	    
solar_input_2_work_status      Working        	    
battery_power_direction        Charging       	    
dc/ac_power_direction          DC to AC       	    
line_power_direction           Output         	    
--------------------------------------------------------------------------------

@PaulEPop
Copy link

PaulEPop commented Jun 3, 2024

It would be wonderfull, that we could communicate like a BMS to MPP-inverters!
Many BMS have a problem with inverters from MPP (12k / 15k)

@riogrande75
Copy link
Author

riogrande75 commented Jun 3, 2024

In fact BMS comms to MPP/FSP/Voltrinic hybrid inverters (10/15k) is quite easy. I run it with my php scripts since more than 2 years witout any issue. All you need is the information from my post above.
Issue #485 would be solved with this too, as inverter changes internal charging voltage/current settings according to bms information.

As far as I understand this project, it's "simply" pulling data from inverters and bms' for using this data in 3rd pty visualization. For bms comms to work, data from bms need to be processed and sent to the inverter.

@jblance Is bms->inverter comms on the 2do list, or will it never be implemented anyway. Off course, pulled data from bms (e.g. jk) would have to be temporarily stored on the machine and then be sent to the inverter while quering production data.
Off course I'd assist in implementing, even my python abilities are quite low.

@PaulEPop
Copy link

PaulEPop commented Jun 3, 2024

Hi riogrande75, I have noticed, you are the one from Dr. Backe. :)
You have wrote 'Die Daten vom BMS kommen via ESP32bei mir am Mosquitto an'
The link doesn't work, So I can't see the basics for the ESP32 / ESP8266. It's possible to share this information to us?
Do you read the information from the BMS internal rs485 port or CAN/rs485?

@riogrande75
Copy link
Author

The link doesn't work anymore.
I used a ESP32 that reads data from JK via BLE and pushes these values on a mqtt server via WiFi.
Everything is described here jkbms-auslesen-ueber-ble-bluetooth-oder-rs485-adapter-mittels-eps-iobroker.
But there are similar other projects that will do the job.

@jblance
Copy link
Owner

jblance commented Jun 4, 2024

As far as I understand this project, it's "simply" pulling data from inverters and bms' for using this data in 3rd pty visualization. For bms comms to work, data from bms need to be processed and sent to the inverter.

This is pretty close - it simply runs a command (any inverter or other device command) and outputs it (to a variety of outputs including mqtt)

@jblance Is bms->inverter comms on the 2do list, or will it never be implemented anyway. Off course, pulled data from bms (e.g. jk) would have to be temporarily stored on the machine and then be sent to the inverter while quering production data. Off course I'd assist in implementing, even my python abilities are quite low.

It is, probably in the powermon codebase though (as mppsolar is creaking at the seams a bit)
I havent figured out what the inverter logic is for BMS integration
is it:
1- just needs a 'command' that contains BMS data
2- needs to send a command (to the BMS) and then get a correctly formated response
3- something else
???

How does you php logic work?

@riogrande75
Copy link
Author

riogrande75 commented Jun 4, 2024

There is no start command, etc. for BMS comms to start working.
You simply send the ^D054BMS... command in cycles to the inverter. I do it every 5 seconds inbetween my queries for production data (^P003GS,...).
After a few seconds the inverter starts displaying "Li-Bat" in it's display and updates battery charging&discharging settings with the values presented by the BMS.

I created this php script that pulls data from jk bms and prepares the BMS string in a shared mem obj as well as pushing values to mqtt for my hassio battery monitoring.
My script that reads all needed values from the inverter opens this shmop and sends the contents to the inverter (line 370ff).

There is in fact no communication in direction downwards from the inverter to bms. Obviously not needed.

@PaulEPop
Copy link

PaulEPop commented Jun 4, 2024

Hi, i will use my words: Einfach Endgeil hier....
I have to modify your php script (I will try), because I'm using the direct connection via rs232 and I need just the BMS funktionality.

@riogrande75
Copy link
Author

Hi, i will use my words: Einfach Endgeil hier.... I have to modify your php script (I will try), because I'm using the direct connection via rs232 and I need just the BMS funktionality.

Well, I guess that shouldn't be a big deal with the code I posted. Big difference to the query command 's is to prepare the BMS string's CRC (crc16-xmodem).

@PaulEPop
Copy link

PaulEPop commented Jun 6, 2024

Do you get a response to the following command?

$serial->sendMessage($bmscmd.chr(hexdec($bmscrc1)).chr(hexdec($bmscrc2)).chr(0x0d));

In my case the log looks like this: (BMS1 without CRC, BMS2 with CRC)
2024-06-06 23:13:12: BMS_1: ^D054BMS0554,098,0,0000,00,0,0552,0552,1500,1,1,0504,150
2024-06-06 23:13:12: BMS_2: ^D054BMS0554,098,0,0000,00,0,0552,0552,1500,1,1,0504,1506#
string(0) ""

I'm sending just 'BMS_2'
Serial connection is running well,I will receive correct responses to ID requests.
I have a MPP-SOLAR MPI12K (PI17 Protokoll)

@riogrande75
Copy link
Author

Your string is too long, it's more than 54 (^D054) characters long.
Fault see pic.
grafik
Off course I don't see the CRC you send in your post.

@PaulEPop
Copy link

PaulEPop commented Jun 7, 2024

I have changed your code in readmqttbms.php from:
shmop_write($sh_bms1, ",00", 23); to
shmop_write($sh_bms1, ",0", 23);

Result
^D054BMS0539,077,1,0039,0#,0,0552,0552,1500,1,1,0504,150

@PaulEPop
Copy link

PaulEPop commented Jun 7, 2024

I have now the following datapackage
$bmscmd = ^D054BMS0531,094,0,0019,0,0,0560,0560,1500,1,1,0504,2000 (from shmop_read...)

this package is going thrue your script

       if($bms){
                $bmscmd = shmop_read($sh_bms, 0, 56);
                $bmscrc = paddings(genCRC($bmscmd),4);
                $bmscrc1 = substr($bmscrc,-4,2);
                $bmscrc2 = substr($bmscrc,-2);
				if($debug) logging("BMS_1: ".$bmscmd); 
				if($debug) logging("BMS_2: ".$bmscmd.chr(hexdec($bmscrc1)).chr(hexdec($bmscrc2)).chr(0x0d));
                $serial->sendMessage($bmscmd.chr(hexdec($bmscrc1)).chr(hexdec($bmscrc2)).chr(0x0d));

output in console:
2024-06-07 21:42:00: BMS_1: ^D054BMS0531,093,0,0020,0,0,0560,0560,1500,1,1,0504,2000
2024-06-07 21:42:00: BMS_2: ^D054BMS0531,093,0,0020,0,0,0560,0560,1500,1,1,0504,2000Rt

But inverter don't switch to LI-Mode

@riogrande75
Copy link
Author

What FW version is on your inverter?
Can you post the string in 'hex to see if crc is ok?

@PaulEPop
Copy link

PaulEPop commented Jun 8, 2024

2024-06-08 22:58:51: BMS_1: ^D054BMS0531,090,0,0015,0,0,0560,0560,1500,1,1,0504,2000
2024-06-08 22:58:51: BMS_2: ^D054BMS0531,090,0,0015,0,0,0560,0560,1500,1,1,0504,2000▒▒
2024-06-08 22:58:51: CRC+0x0d: eed9d

for the BMS_1 string I have used Python to 'verhexen' .
BMS_1: 5e44303534424d53303533312c3039302c302c303031352c302c302c303536302c303536302c313530302c312c312c303530342c32303030

DSP-Version: 211222123000
MCU-Version: 211222123000

@riogrande75
Copy link
Author

FW version is ok.
Looking at your output, it seems that "verhexen" of BMS_1 did not include CRC.

When I do it with your BMS string and my code the hex string looks like this.
5E44303534424D53303533312C3039302C302C303031352C302C302C303536302C303536302C313530302C312C312C303530342C32303030EED90D
Make sure that the character at the end is 0x0d and not simply "d"

@PaulEPop
Copy link

The hex value is converted into a chr and transferred.
I use exactly your code for this.
$serial->sendMessage($bmscmd.chr(hexdec($bmscrc1)).chr(hexdec($bmscrc2)).chr(0x0d));
Further up I use the following code, to which I get the corresponding answer.

$serial->sendMessage("^P003PI".chr(0x0d)); //QPI Protocol ID abfragen 6byte
$antw = $serial->readPort();

My guess is that the MPI12k does not recognize the ^D054... command, I don't get a response to the ^P004BMS request either.

@riogrande75
Copy link
Author

Ahhh, a MPI 12k WP....
Ok, that could be the case, as the inverter has a built in BMS card/port and does not need to be able to receive BMS commands via serial port.

If you have a firmware update for your inverter, I can disassamble it and check if the command is really missing or it has been modified.

@rene-dev
Copy link
Contributor

you can also look at my script which sends the bms command: https://github.com/rene-dev/solar/blob/master/mqtt.py#L102

@PaulEPop
Copy link

PaulEPop commented Jun 11, 2024

I have testet a snipset of your pythoncode with serial.
I have got b'^0\x1b\xe3\r' as answer for the ^D054 command
For the test I used fixed values:

cmd = f"^D054BMS{'0556'},{98},{1},{'0050'},{0},{0},{'0562'},{'0562'},{'0200'},{1},{1},{'0500'},{'0250'}".encode()
crc = crc16(cmd)
cmd = cmd + (crc >> 8).to_bytes(1, "big") + (crc&0xff).to_bytes(1, "big") + b'\r'

I have to add "big", without I have got an error message from Python

cmd = cmd + (crc >> 8).to_bytes(1) + (crc&0xff).to_bytes(1) + b'\r'
TypeError: to_bytes() missing required argument 'byteorder' (pos 2)

With ^P003ID --> b'^D0251496162206100759000000@\x90\r'
Serial com is running well. D054 is unknown for MPI12k.
@riogrande75 : I have asked MPP-Solar for an Firmwareupdate.

Thank you very much for your kind help.

@riogrande75
Copy link
Author

Did you activate BMS and set battery mode to LiFe in solarpower?
Did you try sending the bms command cyclic for some minutes? Even my inverters need some time to recognize bms command and show it in display.

If you have a RS485 BMS port on your MPI 12k WP, why do you frickle arround with bms command instead of using a esp32 for directly connecting jk with the inv? You could also use a simple serial2eth converter and send reply's via bms port as a last resort.

@PaulEPop
Copy link

I have tried everything, the commands was sendind more than 12h.
You mean mppsolar-lib-protocol-to-jk-bms-rs485?
The BMS isn't a JK, it' a Seplos. So I cant use this project direct and I'm not a softwareengineer just a verry little hobby coder with limited skills. :)

@riogrande75
Copy link
Author

We're OT for a long time 🫣

Pls. leave this git issue and read how to connect a seplos directly to your inverter. SEPLOS "speaks" pylontech protocol, it can be connected with a simple cable, and the correct setup, off course.

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

No branches or pull requests

6 participants