first of all: Big Thank you for this years Christmas present. I was really happy to see ODB live data being integrated into the ABRP app.
If this isn't already on the board, I would like to request the ODB live data support for the BMW i3(s). I did a bit of research and it seems like there was a lot of effort put into reverse engineering the ODB PIDs for the i3:
and there are also Apps for Android and iOS which I both tested and they worked nicely providing data into ABRP.
I am happy to help with testing.
The PID's for the BMW i3 are also applicable for the Mini Cooper SE Electric
If you can provide us the OBD commands that are sent and how to interpret the responses we will happily add it. Our format is similiar to the torque pro csv format, so it would be easiest for us to get them in that format.
Hi Samuel. I do not know the Torque pro data format but I do know the BT commands and PID and the interpretation of them. These are for both the BMW i3 AND the (BMW) Mini Cooper SE electric.
This is the procedure and data response for both the BMW i3 and the Mini Cooper SE Electric
First send out commands to the BT dongle to prepare the dongle to send and receive the correct data
sendATCommand("ATD"); // set to all defaults
sendATCommand("ATE0"); // Echo off
sendATCommand("ATH1"); // Headers On
sendATCommand("ATAL"); // Allow long messages (> 7 bytes)
sendATCommand("ATPBE101"); // Set protocol B options and baud rate
sendATCommand("ATSPB"); // set protocol to B
sendATCommand("ATBI"); // bypass the initialisation sequence
sendATCommand("ATSH6F1"); // set header 6F1
sendATCommand("ATAT0"); // adaptive timing off
sendATCommand("ATSTFF"); // set timeout to FF x4 msec = 1024 msec = 1 sec
sendATCommand("ATCRA607"); // set can receive address to 607 (= SME module, battery management module, SME = Storage Management electronics)
sendATCommand("ATCEA07"); // use can extended address 07
sendATCommand("ATFCSH6F1"); // flow control set the header to 6F1
sendATCommand("ATFCSD07300800");// flow control set data to 07 30 08 00
sendATCommand("ATFCSM1"); //Can silent mode on
After the initialization (needs to be only once) send out request for extended PID's and interpret the response. All responses are in HEX, conversion to decimal is provided in the explanation
sendATCommand("22DDBC"); // SOC
Example Response is : 607F1100962DDBC01A6607F12103E50091FFFF
1) Relevant data 1 = 01A6 (from position 15, length 4 bytes) = State Of Charge * 10 => 0x01A6 HEX = 422 dec = 42.2% SOC = indicated SOC to driver
2) Relevant data 2 = 03E5 (from position 26, length 4 bytes) = SOC HV Max * 10 => 0x03E5 HEX = 997 dec = 99.7% SOCHVmax = Top buffer limit of real SOC
3) Relevant data 3 = 0091 (from position 30, length 4 bytes) = SOC HV min * 10 => 0x0091 HEX = 145 dec = 14.5% SOCHVmin = bottom buffer limit of real SOC
sendATCommand("22DD68"); // Battery Voltage
Example Response is : 607F10562DD688AF8
1) relevant data = 8AF8 (from position 13, length 4 bytes) = Battery Voltage * 100 => 0x8AF8 HEX = 35576 dec = 355,76 Volt = battery Voltage
sendATCommand("22DD69"); // Battery Current
Example Response is : 607F1100762DD690000607F121011AFFFFFFFF
Relevant data = 011A (from position 26, length 4 bytes) = Battery Current * 100 => 0x011A HEX = 282 dec = 2,82 Amps
SPECIAL CASE FOR NEGATIVE VALUES. The highest bit the the negative sign. Any Value above 32768 is negative current : example below
Example Response is : 607F1100762DD69FFFF607F121FFAFFFFFFFFF
Relevant data = FFAF (from position 26, length 4 bytes) = Battery Current * 100 => 0xFFAF HEX = 65455 => 65455 - 65535 = -80 => -0,80 Amps
Battery Power is to be calculated from Battery Voltage * battery Current
sendATCommand("22DDBF"); // Cell voltages (min, max, avg)
Example response is : 607F1100762DDBF0E73607F1210E81FFFFFFFF
1) Relevant data 1 = 0E73 (from position 15, length 4 bytes) = Lowest Cell Voltage => 0x0E73 HEX = 3699 dec = 3,699 Volt
2) Relevant data 2 = 0E81 (from position 26, length 4 bytes) = highest Cell Voltage => 0x0E81 HEX = 3717 dec = 3,717 Volt
Calculated value : cell balance is 3,717 Volt - 3,699 Volt = 0,018 Volt = 18 milliVolt
sendATCommand("22DDC0"); // Battery temperatures (min, max, avg)
Example response is : 607F1100962DDC009C4607F1210C1C0AF4FFFF
1) relevant data 1 = 09C4 (from position 15, length 4 bytes) = Battery lowest temperature in Celsius => 0x09C4 HEX = 2500 dec = 25,00 degrees Celcius
2) relevant data 2 = 0C1C (from position 26, length 4 bytes) = Battery highest temperature in Celsius => 0x0C1C HEX = 3100 dec = 31,00 degrees Celcius
3) relevant data 3 = 0AF4 (from position 30, length 4 bytes) = Battery middle or average temperature in Celsius => 0x0AF4 HEX = 2804 dec = 28,04 degrees Celcius
sendATCommand("22DDC4"); // RAW SOC
Example response is : 607F10662DDC413F601
1) relevant data 1 = 13F6 (from position 13, length 4 bytes) = Real SOC * 100 => 0x13F6 HEX = 5110 dec = 51,1% real State Of Charge
sendATCommand("22DFA0"); // Amp hours and average cell voltage
Example response is : 607F1102962DFA025D2607F121274B26B09082607F122910E90C309C4607F1230C1C0AF4FFFF607F124FFFF285513FE607F125155F14BCA1CC607F126A1EAA1DB2855
1) relevant data 1 = 25D2 (from position 15, length 4 bytes) = Battery amp hours * 100 => 0x25D2 HEX = 9682 dec = 96,82 AmpHours
2) relevant data 2 = 910E (from position 45, length 4 bytes) = Average Battery Cell voltage * 10000 Volt => 0x910E HEX = 37134 dec = 3,7134 Volt
sendATCommand("226335"); // SOH State Of Health
Example response is : 607F110076263350000607F1210064FFFFFFFF
1) relevant data = 0064 (from position 26, length 4 bytes) = State of Health (SOH) in percent => 0x0064 HEX = 100 dec = 100% SOH
If you need more info please let me know!
thanks for the information. That should help in getting the i3 into ABRP. If you want it to be done faster and help us out a bit, please open a PR here:
You can check the other files for reference how to do it. Once that file is available we can immediately test it. If you don't have the time we will do it later when we have time.
Thanks for the github link!
I don't really know how to perform a pull request on github but first i must understand how to construct the JSON. That i partly understand.
I've taken the MGZSEV json as a base because it resembles the Mini (BMW) protocol the best.
The initialisation is clear for me, as well as the first data commands to select the correct module
But the equation still has me a little confused. I think i understand that A is the first received byte, B the second and so on.
the following is received by the dongle. at least in my ESP32 project :
607 is the module number. 22DDBC is the command issued to get this response.
am i correct in stating the following :
607 F1 10 09 62 DD BC 01 A6 607 F1 21 03 E5 00 91 FF FF
? A B C D E F G H ? ? ? ? ? ? ? ? ?
(A = F1, B=10, C=09, D=62, E=DD, F=BC, G=01, H=A6, etc)
If Yes then the information for SOC is in the 01A6 pair (G&H), so probably the equation should be :
soc = (G*256+H)*0.1
or calculated with the example soc = (0x01 * 256 + 0xA6) * 0.1 = (256 + 166) * 0.1 = 422 * 0.1 = 42.2% soc
Am i on the right track?