Made quite a bit of progress this weekend and now have the first 'polled' metrics displaying nicely. These are things that are not broadcast on the CAN network as they are not needed to be consumed by other modules in the car. Examples are oil temp, gas pedal position, air fuel ratios, intake air temp and injector duration. All of these thing in my case are coming from the Nissan ECM but there is no reason you can't do the same for the BMW or any other car for that matter.
Have also tweaked some visuals on the temp graphs to display blue when 'too cold' then green for normal and red when cooked. Plenty of easy mucking about left to do here when frustrated with the harder work.
For those curious, the rough process of reverse engineering has been:
Set up some light weight Arduino code to listen on the Nissan CAN bus and setup basic filtration to NOT show messages destined to known ID's (the things broadcast under normal conditions like coolant temp). For me these are ID's 0x160, 0x180, 0x1f9, 0x182, 0x580, 0x551 and 0x6e2.
Connect the ELM32 Bluetooth adapter to the diagnostic (OBD) port which I know works with the Android software on my phone which talks Nissan Consult 3 protocol ... no easy suite of OBD2 for me unfortunately.
Go about connecting via the Android application to the dongle and ECM whilst 'sniffing' the CAN network via the Arduino.
Turns out there are commands that need to be sent before you can query the parameters successfully, annoying.
Go about logging data for a specific metric one at a time if possible via a custom 'dashboard' in the Android app. For example I setup a dash with ONLY the gas pedal position ... in the Arduino serial debug I can see the CAN messages that are being sent by the Android app as well as the reply from the ECM.
Make note of the request payload and all of the responses plus what real world value they correspond with. For example to get the gas pedal position I know the request is sent to the ECM diagnostic ID of 0x7DF and the payload is {0x03, 0x22, 0x12, 0x0D, 0x00, 0x00, 0x00, 0x00}. For this Nissan generation the ECM replies to ID 0x7E8 with the requested info. An example of the data recorded which allows a formula to be worked out is as below ... you will see the actual values are represented in the bytes that change ... for this metric its bytes 4 and 5 (starting at 0, from the left):
0.67v is represented by {0x05,0x62,0x12,0x0D,0x00,0x86,0x00,0x00}
1.05v is represented by {0x05,0x62,0x12,0x0D,0x00,0xD2,0x00,0x00}
1.50v is represented by {0x05,0x62,0x12,0x0D,0x01,0x2C,0x00,0x00}
2.23v is represented by {0x05,0x62,0x12,0x0D,0x01,0xBE,0x00,0x00}
2.81v is represented by {0x05,0x62,0x12,0x0D,0x02,0x32,0x00,0x00}
3.06v is represented by {0x05,0x62,0x12,0x0D,0x02,0x63,0x00,0x00}
3.70v is represented by {0x05,0x62,0x12,0x0D,0x02,0xE3,0x00,0x00}
4.03v is represented by {0x05,0x62,0x12,0x0D,0x03,0x26,0x00,0x00}
4.26v is represented by {0x05,0x62,0x12,0x0D,0x03,0x54,0x00,0x00}
4.42v is represented by {0x05,0x62,0x12,0x0D,0x03,0x75,0x00,0x00}
4.82v is represented by {0x05,0x62,0x12,0x0D,0x03,0xC3,0x00,0x00}
So from there you can try and work out how its representing the 'real' value in the data. This is quite the ball ache to be fair !! I used Chat GPT like any good geek to try and avoid fully understanding what I am doing and it got fairly close. In the end the learning from trying to get Chat GPT to do it allowed me to manually muck around with the data and come up with the formula.
Good job if you are still reading I won't keep you in suspense any longer, the calculation is (the cool shades guy is an 8 then a right bracket hah):
int raw_value = (buf[4] << 😎 | buf[5];
float voltage = raw_value / 200.0;
If we take our value of 4.26v buf[4] is 0x03 and buf[5] is 0x54 this would be effectively concatenating the hex values to get 0x0354 (in hex) which is 852 in decimal ... 852 / 200 = 4.26 ta daaaaaaaaa !!
Anyhooooo some pictures are below and my source code can be had at the link below also ... its starting to get pretty wild, needs a big refactor at some stage !!
https://github.com/david-morton/BMW_E46_Gauge_Cluster_Control