This is a follow on article to the work around tapping into the live data coming from the ECU’s on the car.
I’ve been focusing mainly on the gearbox computer as that has the more interesting data points with it.
I’ve been able to make decent progress in a short period of time and have a prototype of the system actually up and running. I’ve decoded many additional parameters now and having compared them to my other scan tools.



The display unit is based around a open hardware device called the M5Stack. It’s a small Arduino-clone with Bluetooth functionality, a LCD and button interface, battery power (among a bunch of other things) that made it suitable for this project (cost is around $40). It’s tiny, only about 3×3″ which makes it ideal for mounting somewhere on the dash.

The video below show the system in action. There are three main data pages. The first being clutch information, live data view, and counter stats. In the video you can hear the F1 pump kicking in and as a result the pressure in the system reading that its climed.
Connection to the Bluetooth dongle is fairly straightforward with the BTSerial library. Most of this code needs much cleaning up for error detection/handling/etc. but is meant for clarity on this page.
bool BTsetup()
{
SerialBT.begin("ESP32test", true);
Serial.println("Starting BT connection. Ensure dongle is pairing mode");
bool connected;
connected = SerialBT.connect(address);
if (connected) {
Serial.println("Connected Succesfully!");
} else {
while (!SerialBT.connected(10000)) {
Serial.println("Failed to connect. Make sure remote device is available and in range, then restart app.");
}
}
// disconnect() may take upto 10 secs max
if (SerialBT.disconnect()) {
Serial.println("Disconnected Succesfully!");
}
SerialBT.connect();
}
From there, several simple routines to handle the shuttling of data.
void SendBT(String sendString)
{
SerialBT.flush();
Serial.println("SEND> " + sendString);
SerialBT.println(sendString);
}
bool PerformTransactionConfig(String command, String &response, int wait = 0)
{
SendBT(command); // turn on headers
delay(wait);
response = SerialBT.readString();
Serial.print("RESP> ");
Serial.println(response);
}
bool PerformTransaction(String command, String &response, int wait = 0)
{
SendBT(command); // turn on headers
response = SerialBT.readStringUntil('\n');
Serial.print("RESP> ");
Serial.println(response);
}
Finally, various functions are used to decode the the raw response buffers into integers for further processing.
void parameterToLongLong(String &response, unsigned long int &first, unsigned long int &second, unsigned long int &third, unsigned long int &fourth)
{
// extract length
String Slength = response.substring(0,2);
int ilength = strtoul(Slength.c_str(), NULL, 16) - 128 - 2;
if (ilength < 1)
return;
String Sdata = response;
Sdata.replace(" ","");
String firstSdata = Sdata.substring(10,18);
String secondSdata = Sdata.substring(18,26);
String thirdSdata = Sdata.substring(26,34);
String fourthSdata = Sdata.substring(34,42);
first = strtoul(firstSdata.c_str(), NULL, 16);
second = strtoul(secondSdata.c_str(), NULL, 16);
third = strtoul(thirdSdata.c_str(), NULL, 16);
fourth = strtoul(fourthSdata.c_str(), NULL, 16);
return;
}
unsigned int parameterToInt(String response)
{
// extract length
String Slength = response.substring(0,2);
int ilength = strtoul(Slength.c_str(), NULL, 16) - 128 - 2;
if (ilength < 1)
return 0;
String Sdata = response.substring(15, 15+ilength*3-1);
Sdata.replace(" ","");
int idata = strtoul(Sdata.c_str(), NULL, 16);
return idata;
}
A struct is used to hold all raw values as a cache.
struct {
float pis;
float new_closed_pos;
float cur_closed_pos;
float wear;
unsigned int wear_deg;
float hydr_pres;
float leakage_engaged;
float leakage_disengaged;
float transtemp;
float watertemp;
unsigned int engine_rpm;
unsigned int gearbox_rpm;
unsigned int neutral_eng;
unsigned int first_eng;
unsigned int second_eng;
unsigned int third_eng;
unsigned int fourth_eng;
unsigned int fifth_eng;
unsigned int sixth_eng;
unsigned int rev_eng;
unsigned int pump_eng;
unsigned int pump_on;
unsigned int total_on;
} liveGearboxData;
Finally, what’s displayed on screen is the converted values of the various parameters.
PerformTransaction("STPX d:21%2d", response, val);
liveGearboxData.hydr_pres = (float)(parameterToInt(response)-120) / 10.0;

Update : June 28/2020
A little further progress today.
I was able to get the polling rates up significantly to get several updates per second.
I’m also now looking at monitoring/alerting. This first bit looks at how the F1 pump and system is performing.
This uses the pump relay state to measure two things:
1) Cycle time between pump activations. Too low of a time points to leakage/bleed off.
2) Pump on time. How long it takes the pump to raise the pressure from 40 bar to 50 bar. Again too long of a time here indicates a weak pump or heavy leakage.
3) Additionally I’ve added alerting to the clutch solenoid measure when they exceed 60cc/min.
The M3Stack has a small speaker so a alarm tone can be played. With all these we can get some early warnings of failures or issues that need addressing.

Next Steps
The polling rate of the system needs to be improved but I have some easy optimizations for this.
I also want to include more parameters, particularly from the engine ECU’s.
Are you going to sell these? I would really like to buy one. Thanks
LikeLike
Hi Nik. I wasn’t planning, but I could possibly assemble something. Can you email me?
LikeLike
How much would you charge for this as I would like to buy one.
LikeLike
Hi Cliff. Email me at tarun@italianautotech.com and we can discuss.
LikeLike
Would you be so kind to publish the complete Arduino source code?
LikeLike
Reach out and let me know what you’re up to. Sure I can help you with that.
LikeLike