Go Down

Topic: OBD II Bike Connector - Pass via bluetooth (Read 84213 times) previous topic - next topic


Jul 14, 2016, 10:18 pm Last Edit: Jul 15, 2016, 07:31 am by Scissor
Today I estimated the conversion formula for the pressure readings (IAP & MAP) by comparing to the Z750 manual.

In the manual there is a graph of Pressure vs. Voltage for the IAP. From the linear plot I was able to determine the slope dP/dV to be 191.0±0.4 mmHg/V using the least squares method of excel.

The 2 bytes are a 16 bit integer such that the value is given by x=256*a+b [0-65536]. I assumed again that normalizing the value and multiplying by 5 V results in the sensor voltage.

V = (5/(256*256)) * x

Then the pressure is simply given by P = (dP/dV)*V.

This results in:

P_mmHg = 191*(5/(256*256))*x

Or, in more common units:

P_Pa = P_mmHg * 133 = (133*5*191)/(256*256)*x

The last equation can be approximated by using 100 * 256/192=133:

P_Pa = (100*256/192)*(5*191)/(256*256)*x  ~= (100*5/256)*x

And by simply dividing by a factor 1000 to get the pressure in kPa:

P_kPa = P_Pa/1000 =  (1/(2*256))*x

Now, this last equation can be simplified by losing some resolution by ignoring b.

P_kPa = a/2 + b/(2*256) ~= a/2


I´m back and me and my bike are still intact :D

There have been several issues during the rides:
TPS went up to 92,7% and afterwards down to zero. That must be related to a rounding issue, which results on a value greater then 255. It overruns and begun at 0.
My temporary fix was to set the value to 0xFF manually, if value is greater then 880 but the response is below 10.
Not the gentleman-way, but it worked.

The speed formula was made by people with speed limits. It covers 120kmh only  :smiley-yell:
Like TPS, you have to multiply with 255 instead of 100.

In matter of that, it would be consequential that RPM has to be multiplied by 255 instead of 100, also. But 100 worked good from 1000-11.500 RPM  :smiley-roll:

There must be a specific value, which reboots the arduino. Sometimes after 2, sometimes after 15 minutes.
It should not be related to the communication, global variables or something like that. My emulator is working for hours with the Ardu. I think it must be related to a formula which probably divides by null or something :(

MAP is calculated without voltage. My calculation has always been like that :D
Code: [Select]
      case 0x05: //Airpressure: From 2 byte to 1 byte:   
      if(ecuResponse[2] >= 2)
        ecuResponse[2] = ecuResponse[2] / 2; //Double precision
      //Ignore accuracy
      ecuResponse[3] = 0x00;     


Jul 15, 2016, 12:52 pm Last Edit: Jul 15, 2016, 03:32 pm by Scissor
Very good to hear your results. Good to know that the speed is calculated the same way, strange though that RPM deviates from that. The longer I work on this, the more confused I get. I just wanted to double check the formula for the IAP/MAP value :) Now this simply proves that you were right all along haha! It also proves that the IAP/MAP values follow the specifications written in the Z750 manual e.g. the sensor pressure is linearly proportional to the voltage.

What is your code to calculate the TPS?


Jul 16, 2016, 09:49 am Last Edit: Jul 16, 2016, 10:25 am by Scissor
I'm having some issues to reconnect with the ECU after communication is lost. When I adjust the delays on the go with a potentiometer, of course at some point the request is send too fast after the last responds which ends up in a timeout (> No response within 1500 ms). Now, when I send a fastinit command directly, I don't get any response back no matter how many times I try.

The sequence looks like this:

45 ms delay
Request (This is not received by the ECU)
Response timeout

Fast init sequence
Response timeout

Fast init sequence
Response timeout

Fast init sequence
Response timeout

I assumed a simple >300 ms delay would be sufficient as described by the KWP2000 protocol. However, it just won't initiate. So I tried to increase the delay before sending the fastinit sequence to 5000 ms, and it worked!
I took at look at your code, and I see you have a 2000 ms delay before reconnecting. I remember to have read this somewhere in the KWP2000 protocol, but I can't remember in what document. Do you know what the rules are for reconnecting after a timeout?

Edit: I guess it simply means that I have to wait up to 5000 ms to receive the response. There is no way to ignore the response and restart the ECU earlier. I'm going to test this right now.

Edit: Turns out you have to wait for 5000 ms before reinitializing. That's a shame.


What is your code to calculate the TPS?
Today I changed my approach to fix wrong values, by using a different function, to avoid rounding issues:
Code: [Select]
        //ecuResponse[2] = (value-minimum) *100 / (ThrottlePosMax - minimum) * 255/100;
        ecuResponse[2] = map(value, minimum, ThrottlePosMax, 0, 255);

Seems to work :)

I don´t really remember where I got the 2 seconds from. Think the EcuHacking-Forum was it.
Raised it today, but after 20 minutes I still got a break down :(
Maybe the Error was never called and it is really a divide by zero or something.

If the init comes earlier then the 5 Seconds, but then static every second, does it still get ignored?

What´s the matter, that you need the reinitialization?


Today I changed my approach to fix wrong values, by using a different function, to avoid rounding issues:
Code: [Select]
       //ecuResponse[2] = (value-minimum) *100 / (ThrottlePosMax - minimum) * 255/100;
        ecuResponse[2] = map(value, minimum, ThrottlePosMax, 0, 255);

Seems to work :)

I don´t really remember where I got the 2 seconds from. Think the EcuHacking-Forum was it.
Raised it today, but after 20 minutes I still got a break down :(
Maybe the Error was never called and it is really a divide by zero or something.

If the init comes earlier then the 5 Seconds, but then static every second, does it still get ignored?

What´s the matter, that you need the reinitialization?
Good that you have hopefully solved that problem! I finally did some first test rides, and found the datalogger works great. I can log approximately 8-10 localIds per second, at a very stable rate. However the Arduino seems to restart sometimes. It takes roughly 10 seconds to restart logging as I found from the motorcycle operating time (works as a RTC :) )

I guess there are two possible reasons for a reboot: SRAM overflow or a power supply issue.
I have excluded the first possibility by logging the free memory, which was constant i.e. no memory leaks. The latter possibility seems more likely to me, especially since my (Ebay) Arduino Nano does not have the standard voltage regulator. After a ride the datalogger also feels quite hot, so this indicates there is quite some heat dissipation. The voltage regulator is an AMS1117 with an absolute maximum input voltage of 15V, which is on the edge I think. Do you know if the 12 V line from the diagnostic plug is stable at 12V, or is it directly coupled to the battery such that during charging the voltage can be like 14V? I hope to have solved this problem by using an extra decoupling capacitor. If this problem can't be solved I either have to buy a genuine Arduino Nano, or use an additional voltage regulator.

About the reinitialization, the strange thing is that the K-line must be silent for > 5000 ms. I investigated this by changing the response-request delay (0-55 ms), and the response timeout (0-5000 ms) on the go. Only when the response timeout > 5000 ms (including the 350 ms I have included in the fast init sequence) the ECU responds again. Setting it to a lower value like 1000 ms, and trying 5 or 6 times does not work. It could be related to a flaw in my code, but at this point I assume my code works as it should.


That´s a great speed! You have removed every delay, except the 55ms between the messages, right?
Got still the delay between every byte. Removed it also and test that tomorrow!

I was expecting that! The Arduino crashes and my Action Camera goes on asking for values. EcuConnected is false, so it will try to init constantly.
I have no clue how to differ between a clean startup sequence or a crash to execute the 5 Sec delay :(

But the best solution would be not to crash :D
Checked temperature and it was okay! BT module is warm, but far away from hot!
Also the soldering is made to resist cobblestones or earthquakes ;)

You should add a Ceramic-Capacitor 10 nF 50 V/DC. The voltage will be up to ~14,5 on idle. Probably more during the ride.
As you can see in the manual, even the internal voltage differs.

Our beloved discussion about A*100+B or A*255+B:
I´ve never reached more then 11.100 RPM. The limiter comes up at about 12.500 RPM (which I maxed out on the home straight, several times).
Did the camera missed the point or do we still have a wrong formula?

Last but not least: The first thing which stops on my recordings, was the temperature.
Maybe it is just the result of a failure, maybe the cause.
The formula is not very typesafe...
Code: [Select]
    case 0x07:
      //(A-48)/1.6 = Celsius (KDS)
      //+40 to avoid negative values (OBD)
      if(ecuResponse[2] == 0x00)
        ecuResponse[2] = 40; //0C°
        ecuResponse[2] = (ecuResponse[2] -48) / 1.6 + 40;

I´m sure it will explode below zero! But water has been between 40-80° (Celsius) and Air between 19-40° (temperature in the Airbox which heats up, not the outside temp).
Do you also store temp on your SD card?


It is really fast! I didn't expect this rate, since I do use the 5 ms and 55 ms delay, just to make sure no timeout occurs.

I added a 1 uF capacitor besides a 100 nF, and managed to capture 21 minutes of logging (I attached the CSV file). I already used the 100 nF capacitor, and could not log the data for more than about 5 minutes before crashing the Arduino. I'm going to try to use the 10 nF capacitor, and see if it can improves stability. This time the arduino did not feel that hot as before, although that's a bit of a placebo effect I guess.

So far I used the 100*a+b formula to calculate the RPM, but never checked carefully. You can use the attached file to compare with your results. I think the formula is at least very close, you could have missed the rev limiter, as it obviously is only a very short period of time. My logger logs the RPM roughly every second, therefore you have to be very lucky to capture the exact right moment.

You can see in the attached log that I capture 10 localIds: TPS, IAP, ECT, IAT, MAP, RPM, Battery voltage, gear, speed and total operating time.


Here is the log file of approximately 20 minutes of riding in regular traffic.

Btw, to double check if the RPM formula is OK, you can try to log only the RPM. If you manage to log at like 8 Hz the probability is a lot higher that you can capture the rev limiter.


Possibilities for a reset:
  • Divide by zero - should not cause a reboot as I read
  • Stack overflow - full RAM
  • Access Array with a indices greater then the size
  • Bad Pointer Access
  • Voltage drops
  • Reset by Serial (Like Arduino IDE does during an upload)

The serial buffer can be overloaded as well and cause problems.

When emulating, the Arduino is connected via USB, not Pin 0 & 1 and powered by it, also.
The Emulator values  differ a bit from what the ECU does. Only some fake random values within the known ranges.
Anything else is the same!
In that scenario the Arduino works like charm for more then 2 hours! Stopped it by myself afterwards. That´s why I´m sure it is related to the data itself. Or as you mentioned, to the power supply.

I got the Autobahn here. Think I will reach the 12,5k RPM for testing purposes somehow :D

The init sequence has to timeout or receive an error value as response. Before it will return "false" I attached a 5 Sec delay. I hope it will make the deal to go on working after an error occurred.


I also observe the same phenomenon. Using your emulator (which is extremely useful for debugging btw, thanks alot!) never leads to restarts. Restarts only occur when logging a real ride, and not at a regular interval. I think the most likely causes for the restarts are noisy power supply or index out of bounds. I tend to suspect the former cause most, as I could reduce the number of restarts by decoupling the noise. Since my arduino uses a voltage regulator with a relatively low maximum input voltage, this is easily exceeded when noise is on the line.

Today I bought a cheap Kawasaki Diagnostic tool from ebay, I believe it is an old version of the Healtech OBD tool. It will arrive in 2-4 weeks! I'll prepare a sniffer to find all the possible requests. :)


There are more and more people complaining about that behaviour...

I´ve never read about 3rd party gear indicators, which have breakdowns. They are also connected to the diagnostic plug and have been the basis of our work (some guy sniffed such a device to find out the init sequence and the communication protocol).

From my perspective it can only be:
  • Voltage drops (rather the capacitor then the bike itself)
  • Data noise (Bike, L9637D, timing, elektro-magnetic distortion, ect.)

What happens, if the data is not as expected? If any value is missing or wrong, it could break the whole communication. Length is greater then X, Checksum is missing, last byte got lost somewhere.
The switch-case is a nice solution to identify the header, PID, value and checksum. But if the byte count will be shifted, caused by missing data: Good night :D

I´ll include a WatchDog and see what happens. If it won´t store anything, its related to the power connection. If it will store something, we can identify where it happens.


I think you are right, it's either a hardware or software problem. We can also test it by running the arduino from a battery to identify the problem.

My code simply continues receiving bytes untill it recognizes the 3 or 4 byte header. Then the number of bytes to read is determined from the response. If not all bytes are received the receiver times out. It does not check the checksum though.
Whenever the response has some weird format it will just be discarded, not filling up te buffer. It could go wrong when the length byte got messed up somehow, such that possibly the buffer overflows. I cannot think of any other possible software issues.

A battery of a motorcycle is typically very hard on electronics due to the inductive character. If spikes occur the voltage regulator might shut down to protect itself.

It is a good idea to use the watchdog to see if its related to software. I'm curious what the results are going to be.


Watchdog is included and seems to work. Tested it by starting the Sniffer, which takes much longer then 4 seconds. But the Arduino just blinks at the end and does not restart. Even the reset button doesn´t help. Only remove vin.
The error code is written, which is important!
Additionally to that, I´m storing a number if no WatchDog error appears, but the Init fails. Or a timeout appears.
It is so hot right now, that I don´t want to ride  :o
Maybe at the weekend...

Beside of that, I changed the engine load to the current gear:
Code: [Select]
ecuResponse[2] = map(ecuResponse[2], 0, 6, 0, 15);
So I can reuse it on my video overlay. The value has to be rounded, then it works great!

Cannot wait to test that!



You guys are doing some great work!  I'm trying to do something similar on a KWP 2000 Protocol (K-line) vehicle.  I want to access the transmission temperature, which is located in the transmission module.  That's my problem, how to communicate with the TCM (transmission control module).   I know the TCM address is 20 and the PID is 30, the wake-up command is 81 20 F1 81 15 and the header is 82 20 F1 21.   

I've connected an Arduino Mega Rx/TX outputs to an ELM327 to communicate on the K-line.  Communication works well when talking to the ECM (engine).  The ELM has different modes.  Mode 01 talks to the engine.  I need mode 21 to talk to the TCM (note the last byte in the header = 21).  I've had no luck getting that communication started.

My understanding is that you are not using the ELM327, but directly communicating on the K-line via an Arduino processor & L9637 bus driver?  Which Arduino are you using?  Did you post a sketch?   

Thanks for any info.

Go Up