-
Notifications
You must be signed in to change notification settings - Fork 140
Description
This is a basic HowTo for using a ESP32 to communicate via Bluetooth to the MG ECU. I purchased a “AUTOHIL” unit which simply plugs into the OBD2 port (under the dash on the right side). I am sure other Bluetooth units would work OK, but I have tested only one. I used a NodeMCU32s as the ESP32 processor, and programmed it using Arduino IDE.
This is meant to help those who are reasonably familiar with Arduino style programming, but have not tackled OBDII before.
The ELMDuino software works fine for the MG EV and the AUTOHIL unit, but there are a few tricks to using the non-standard PIDs.
The first thing to do is to get a list of the PIDs. They are available at:
https://github.com/peternixon/MG-EV-OBD-PID/blob/main/extendedpids/MG%20ZS%20EV.csv
Many thanks to Peter Nixon!
If you look at the above file on the browser you don’t see all the data – you need to download it and open it with a spreadsheet program.
Late edit: I just got tripped up using a spreadsheet program to open the above document - it converted a hex value 7E3 to 7000, which, of course didn't work. The spreadsheet program is OK for seeing the structure, but maybe using a text editor is a better option for seeing the data.
Let’s take the first item:
MG DC Bus Voltage. It has an entry for “Mode and PID” 0x22b041.
What this means is that the Mode (also called Service) is 22 (hex) and 34 (decimal), and the PID is b041 (hex) and 45121 (decimal). You’ll need these numbers later. If you don’t know how to convert hex to decimal, and vice versa, now’s the time to learn. There are a number of spreadsheet functions to help you (eg HEX2DEC() ).
It also has an entry for “Equation”. This tells you how to use the numbers returned from a query to the ECU to calculate the value you want. For this example it is “INT16(A:B) * 0.25”. What this means is that the query will return two hex values A and B. You need to combine them make them into a decimal number and then multiply that by 0.25 . You’ll need this info later. The ELMDuino library will do all the extraction of the numbers and the calculations for you, but you need to tell it what to do.
The spreadsheet has other useful info (max/min values, etc) and it also has values for “Header”, which, for this and many other items is “781”. Remember this.
Next, you need to find out what your Bluetooth adapter’s broadcast name is. Mine is AUTOHIL. You can find out by plugging the adapter into the car’s OBD port, turning the car on, and, using your phone, searching for Bluetooth devices.
To set up the ELMDuino you need to do these steps:
-
Install the ELMDuino library and load the Bluetooth Serial example in your Arduino IDE
-
Use the adapter’s Bluetooth name to set up the Bluetooth serial in the line:
if (!ELM_PORT.connect(“OBDII”))
Replace the “OBDII” with your adapter’s name -
After the Bluetooth connection step is completed, you need to issue a command to set the HEADER. It goes like this:
myELM327.sendCommand("AT SH 781");
where the 781 is the header value you determined earlier. -
To query the ECU, you have to use the generalised query form because the PIDs are non-standard:
processPID(const uint8_t& service,
const uint16_t& pid,
const uint8_t& num_responses,
const uint8_t& numExpectedBytes,
const float& scaleFactor,
const float& bias)
Where
• “service” is the Mode in DECIMAL form (34 in the example above)
• “pid” is the PID in DECIMAL ( 45121 in the example above)
• “num_responses” is the number of lines in the response from the ECU. In my case it was always 1.
• “numExpectedBytes” are how many values are used in the “Equation” expression. If there’s only A, then it’s 1. If there are A and B, then it’s 2, and so on.
• “scaleFactor” is the number you use to multiply. In the example above it’s 0.25. If there is no multiplier, use 1.0 . Use a “float” number – 1.0 not 1
• “bias” is how much to add or subtract after you’ve done the multiplying. If there is no bias, then use 0.0 . Again, use a float number.
So the query would look like this:
float myQuery = processPID(34, 45121, 1, 2, 0.25, 0.0);
Now, there’s a catch here. You need to be careful how you use scaleFactor and bias. For instance, the battery current equation is given as: (INT16(A:B) - 40000) * 0.25 / 10 . This equation applies the bias first, and then the scaleFactor. You can’t use the numbers like this. You have to change the equation to scaleFactor first, then bias.The equation will become INT16(A:B)*0.25 /10 - 40000 * 0.25 / 10 which simplifies to:
INT16(A:B)*0.025 - 1000 . The scale factor is 0.025 and the bias is -1000.0 .
- After issuing the “processPID()” command, you need to keep looping and re-issuing the same command until you get a success, an error, or it times out.
The command to issue to test for success is
if (myELM327.nb_rx_state == ELM_SUCCESS)
The return value of the successful processPID() command ( the float variable myQuery, above ) is the value calculated using the equation you supplied. You can then use that in the rest of your program to display the values, or whatever.
Many thanks to PowerBroker2 for providing this excellent library and for promptly answering queries.
Gonzo