Bike interface OBD

o5i,

The first thing you will need is the hardware to connect your 5 volt arduino to your 12 volt motorcycle communication line. I have a circuit board that uses a LM393 as a level shifter. I had a bunch of circuit boards made and I was selling an interface that goes from computer USB to the bikes computer.....I have a few boards left over. They work with 07 GSXRs and newer as far as I know. Personally, I have an 08 GSXR and it works well on it. If you want to go the computer route, let me know. Otherwise, I will help you with your Arduino project.

I have put a lot of work on getting an Atmel 1284 chip to talk to the motorcycle computer and I have had some success but, the project is not completed. I will share some of my hard work with you to get you started.

Here is the initiation part of the code that works well for me. I am providing you with a snippet to get you started. After the initiation part of the code, you are going to need read incoming data. Add you coding ideas, put in effort, and I will help more.

You will need to define your TX and RX pins based on the board you are using. In my case, my board is the Bobuino with a 1284 chip.

//variables
byte message[6] = {
  0x81,0x12,0xF1,0x81,0x05};
int mode = 0;
/////////////////DATA START///////////////
void datastart(){
  mode = 0;                 //reset mode to 0 for first step of logging
  digitalWrite (TX, HIGH);  // makes K-line high 3
  digitalWrite(ledPin,HIGH);
  delay(2000);             // wait for K-line to be clear 3
  digitalWrite (TX, LOW);  // makes K-line low  3
  delay(25);
  digitalWrite (TX, HIGH); // makes K-line high  3
  delay(25);               //last delay before first message
  Serial1.begin(10400);  // baud rate of the OBD
  //send package 0x81,0x12,0xF1,0x81,0x05
  for (int i = 0; i < 5; i++){
    Serial1.write(message[i]);
    byte inByte = Serial1.read();
    delay(1);                 //inter byte delay for to match k-line spec. changed from 15ms to 1, tune as needed
  }
}

Thanks, i try if it works... I have a code that send something but the ecu didnt reply... I tried to log the data when ecueditor is running but it looses some data...
But i want to use one like yours whit LM393 on it because it is smaller.
I think it is going forward...
You know if it is possible to connect the digital out pins directly to the pins of the ecu like "mode (map switch)" "reset" "fwe" "dealer mode" and of course the programing pins? In case of that it can be used als programing interface too...

o5i_:
You know if it is possible to connect the digital out pins directly to the pins of the ecu like "mode (map switch)" "reset" "fwe" "dealer mode" and of course the programing pins? In case of that it can be used als programing interface too...

I think that the answer is "yes" because you can connect directly to the 5 volt FTDI cable to the ECU on the "reset" "fwe" pins . I have only logged with the Arduino, and I have never made any attempts to program using the Arduino. I would exercise caution when connecting to the map switch and dealer mode by using resistors to limit current.

I have a problem, i tried the code and put an other serial on it to see waht the ecu responds but the ecu only replies the same as i have send...
I think there is something wong, maybee the pin 18/19 on mega are not the serial ones or i need to use the serial0? Last time i tried whit same result...

#define TX 18
#define RX 19
#define ledPin 10
#define console Serial
#define cbaud 14400
#define sds Serial1
#define sdsbaud 10400

//variables
byte message[] = {
  0x81,0x12,0xF1,0x81,0x05};
int mode = 0;

void setup() {
}

void loop() {
  datastart();
}


/////////////////DATA START///////////////
void datastart(){
  mode = 0;                 //reset mode to 0 for first step of logging
  digitalWrite (TX, HIGH);  // makes K-line high 3
  digitalWrite(ledPin,HIGH);
  delay(2000);             // wait for K-line to be clear 3
  digitalWrite (TX, LOW);  // makes K-line low  3
  delay(25);
  digitalWrite (TX, HIGH); // makes K-line high  3
  delay(25);               //last delay before first message
  console.begin(cbaud);    // test ---------------------------------------------------------------------------------------
  sds.begin(sdsbaud);  // baud rate of the OBD
  //send package 0x81,0x12,0xF1,0x81,0x05
  for (int i = 0; i < 5; i++){
    Serial1.write(message[i]);
    byte inByte = sds.read();
    console.println(inByte,HEX);  //test -----------------------------------------------------------------------------------
    delay(1);                 //inter byte delay for to match k-line spec. changed from 15ms to 1, tune as needed
  }
}

maybee the pin 18/19 on mega are not the serial ones

check for pinMapping

Dont know whats wrong here... I think it should work? Why the ecu responds whit the same string?
I have tried to send whit the arduino and recieve whit the ftdi but it shows nothing usefull... Maybee there is something wrong whit the arduino? Its a mega 2560..

void datastart()
{
  mode = 0;
  digitalWrite (TX, HIGH);  // <<<<<<<<<<<<<
  digitalWrite(ledPin, HIGH);
  delay(2000);
  digitalWrite (TX, LOW);
  delay(25);
  digitalWrite (TX, HIGH);
  delay(25);
  console.begin(cbaud);    // <<<<<<<<<< 
  sds.begin(sdsbaud);   //  <<<<<< 

  for (int i = 0; i < 5; i++)
  {
    Serial1.write(message[i]);  // <<< byte array ?
    while (sds.Available() == 0); // blocking wait for byte to arrive
    byte inByte = sds.read();
    console.println(inByte, HEX); 
  }
  console.println();
}

Some questions
is TX the transmitpin of Serial1, console or from sds or something else ?
why are those two baudrates initialized in the middle of this function ?

I have added auto tuning for the byte reception, assuming SDS implements an Available() function.
and assuming there will arrive 5 bytes.

Dont know if this helps,

you could try to write some minimal sketches that just test single functions hjust to verify.

  • 3 sketches for the 3 serial ports
  • etc
    diagnostics step by step

Hi, i have read some things, according whit somebody who knows how it works the arduino maybee have problems to get the right timing. The protocol has a tolerance of +-1ms.... Is there a way to test?
The replys probably are echos, the data is transmitted throug one wire...

The replys probably are echos, the data is transmitted throug one wire...

You are correct, you will get echo. My answer for this was to read the bytes available until they equal the amount sent. In the first part of the code, I sent this:

byte message[6] = {0x81,0x12,0xF1,0x81,0x05};

To get around the echo problem, I read 5 bytes, if the fifth by equals 0x05, then the next byte is coming from the ECU.

The protocol has a tolerance of +-1ms.... Is there a way to test?

I started with "extra" time between bytes sent and I gradually reduced the delay between bytes and I watched for loss of communication. I used a potentiometer in my sketch to make my timing adjustable on the fly.

o5i_

I also thought you should know that you do not want to use Software Serial for communicating with the ECU. In my case, I found that it was far easier to use Hardware Serial.

Also, in my case, I used Serial1 for communication with ECU and Serial0 to repeat the data to my computer during testing.
I would recommend doing the same with your Mega if it is possible.

Hi, i had sucess, i got some AE 8F replys, but they were somewhere between the echos..
i only need to add
pinMode(TX, OUTPUT);
:smiley:
But it is not working everytime i try..

Post the code you are using and maybe we can find some improvements.

Another tip, I made the baud rate from my Arduino to my computer 115,200 which is the fastest setting the Serial Monitor allows. The reason I did this was to insure that I was not taking up too much time sending data to the computer.

Hi

I did this;

#define TX 18
#define console Serial
#define cbaud 115200
#define sds Serial1
#define sdsbaud 10400

//variables
byte message[6] = {
  0x81,0x12,0xF1,0x81,0x05};

void setup() {
  console.begin(cbaud);
  pinMode(TX, OUTPUT);
}

void loop() {
  datastart();
}

/////////////////DATA START///////////////
void datastart(){
  digitalWrite (TX, HIGH);  // makes K-line high 3
  delay(2000);             // wait for K-line to be clear 3
  digitalWrite (TX, LOW);  // makes K-line low  3
  delay(25);
  digitalWrite (TX, HIGH); // makes K-line high  3
  delay(25);               //last delay before first message
  sds.begin(sdsbaud);  // baud rate of the OBD
  //send package 0x81,0x12,0xF1,0x81,0x05
  for (int i = 0; i < 5; i++){
    sds.write(message[i]);
    byte inByte = sds.read();
    console.print(inByte,HEX);
    delay(1);
  }
  console.println();
  while (!sds.available());
  while (sds.available()) {
    console.println(sds.read(),HEX);
  }
}

And recieved this:

FFFFFFFFFF
FF8112F181
5
80F1123C1
EA
8F
C0
81
12
F1
81
5
FF8112F181
5
FF8112F181
5

This one works good:

#define TX 18
#define console Serial
#define cbaud 57600
#define sds Serial1
#define sdsbaud 10400

//variables
byte message[6] = {
  0x81,0x12,0xF1,0x81,0x05};
int length = 5;
int counter;
int mode;

void setup() {
  console.begin(cbaud);
  pinMode(TX, OUTPUT);
}

void loop() {
  fastinit();
  sendrequest();
  recievedata();
}

void fastinit(){
  if (!mode) {
    digitalWrite (TX, HIGH);  // makes K-line high 3
    delay(2000);             // wait for K-line to be clear 3
    digitalWrite (TX, LOW);  // makes K-line low  3
    delay(25);
    digitalWrite (TX, HIGH); // makes K-line high  3
    delay(25);               //last delay before first message
    sds.begin(sdsbaud);  // baud rate of the OBD
    mode++;
  }
}
void sendrequest() {
  if (counter < length) {
    sds.write(message[counter]);
    // delay(1);
    counter++;
  }
}
void recievedata() {
  if (sds.available()){
    console.print(sds.read(),HEX);
  }
}

Reply:

8112F181580F1123C1EA8FC0

Hope there are no problems if the code became longer...

Litle update

#define TX 18
#define console Serial
#define cbaud 57600
#define sds Serial1
#define sdsbaud 10400

//variables
int dotdelay = 1000;
int timeout = 10000;
int timeold;



int messagelength = 5;
byte message[5] = {
  0x81,0x12,0xF1,0x81,0x05
};
int responselength = 8;
byte message_response[8] = {
  0x80,
  0xF1,
  0x12,
  0x03,
  0xC1,
  0xEA,
  0x8F,
  0xC0
};


int mode;


void setup() {
  console.begin(cbaud);
  pinMode(TX, OUTPUT);
}

void loop() {
  fastinit();
  sendrequest();
  recievedata();
}

void fastinit(){
  if (!mode) {
    console.println("starting comunication (fastinit)");
    digitalWrite (TX, HIGH);  // makes K-line high 3
    console.println("Set K-Line High");
    delay(3000);             // wait for K-line to be clear 3
    digitalWrite (TX, LOW);  // makes K-line low  3
    console.println("Set K-Line Low");
    delay(25);
    digitalWrite (TX, HIGH); // makes K-line high  3
    console.println("Set K-Line High");
    delay(25);               //last delay before first message
    sds.begin(sdsbaud);  // baud rate of the OBD
    console.println("starting serial comunication");
    mode++;
  }
}

void sendrequest() {
  console.println("send request");
  for (int i = 0; ((i < messagelength) & (mode == 1)); i++) {
    sds.write(message[i]);
    console.print("sending data: ");
    console.println(message[i], HEX);
  } 
  console.println("request sent");
}

void recievedata() {
  int i = 0;
  int req = 0;
  int data = 0;
  int dataok = 0;
  console.println("waiting for data");
  while (!dataok) {
    int time = millis();
    if ((timeold + timeout) < time) {
      timeold = time;
      console.println("TIMEOUT");
      mode = 0;
      sds.end();
      return;     
    }
    if (sds.available()) {
      byte inByte = sds.read();
      console.print("recieving data: ");
      console.println(inByte,HEX);
      if (inByte == message[i]) {
        i++;
        console.println("OK");
        if (messagelength == i) {
          console.println("request ok");
          req++;
          i = 0;
        }
      }
      if ((req) & (inByte == message_response[i])) {
        i++;
        console.println("OK");
      }
      if (responselength == i) {
        data++;
        i = 0;
        dataok++;
        console.println("Communication OK");
      }
    }
  }
}

but how can i clear the array "message" and write "80 12 F1 02 21 08 AE" in it after "dataok"?
How can i print the numbers of databytes of an array?
I want to diff the request from the response... but i dont know how it can be the best way...
Of course there are needed some formula to calculate checksum, sended and recieved string ecc...

I read your code and it is a little difficult because you need to put more comments so that I can understand the purpose of each line of your code. Remember, that this project may take you awhile to reach perfection. You may need comments and notes in the code to remind yourself about the functions in the code.
Here are the steps that need to happen. In my case, I used a variable called mode to step through my code.

  1. fastinit(); Using pinmode, and HIGH and LOW
  2. send message = 0x81,0x12,0xF1,0x81,0x05
  3. wait for response 80 F1 12 03 C1 EA 8F C0
  4. send data request 0x80,0x12,0xF1,0x02,0x21,0x08,0xAE
  5. read incoming data "I believe you will receive 56 bytes back
  6. store results
  7. repeat steps 4 through 6 over and over as long as you are getting response from the ECU.

I am not sure how to properly stop communication but, I do know that there is a message that can be sent to do it.

1 Like

How can i calculate the checksum?
for example:
80 12 F1 02 21 08
has 08 as checksum, but how to calculate it from the other values?

for checksum there are many formulas/techniques. It is not a trivial or / xor / addition.

What you can do is assume the checksum is right and ignore it (for now). First prio is to get the data.

I did not make any effort on using the checksum. In my case, I expected 56 bytes returned from the ECU. If I did not get 56 bytes in a reasonable time, I assumed that I lost communication. The ECU will only reply after a request. Therefore, I send a request, wait on 56 bytes, and then make another request.

Hi
i did some work... It reads data and print value on console.. But i have problems to get the timout timer working because millis is switching to negative values.... Speed is up to 140ms, thats better than expected :smiley:
Next i need to test writing on sd... I hope it doesnt slows to much...
Somone have maybee the definitions for the sensor values?

#define TX 18
#define console Serial
#define cbaud 57600
#define sds Serial1
#define sdsbaud 10400

////////////////////////////////////////////////////// some static options ////////////////////////////////////////////////////// 

int const debug = 0;
int const timeout = 2000;
int const cyclespeed = 50;
byte const source = 0xF1;
byte const target = 0x12;
byte const header = 0x80;

////////////////////////////////////////////////////// possible protocol values ////////////////////////////////////////////////////// 

byte const startinit[5] = {
  0x81,
  target,
  source,
  0x81,
  0x05,
};

byte const keepalive[1] = {
  0x01,
};

byte monitorsensordata[7] = {
  header,
  target,
  source,
  0x02,
  0x21,
  0x08,
  0xAE,  
};

////////////////////////////////////////////////////// variables ////////////////////////////////////////////////////// 

int datalength = 0;
int mode = 0;
int timeold;
int time;


void setup() {
  console.begin(cbaud);
  pinMode(TX, OUTPUT);
}

void loop() {
  fastinit();
  senddata();
  recievedata();
}

// KWP2000 Fast Init
void fastinit(){
  if (!mode) {
    console.println("Starting comunication (fastinit)");
    digitalWrite (TX, HIGH);                                       
    if (debug) console.println("Set K-Line High");
    delay(6000);                                                              
    digitalWrite (TX, LOW);                                                    
    if (debug) console.println("Set K-Line Low");
    delay(25);
    digitalWrite (TX, HIGH);                                                      
    if (debug) console.println("Set K-Line High");
    delay(25);                                                                
    sds.begin(sdsbaud);                                                      
    if (debug) console.println("starting serial comunication");
    mode++;
  }
}

// Send request to the ecu (message)
void senddata() {
  if (mode) {
    if (mode == 1) {
      for (int x = 0; x <= 4; x++) {                            // messagelength=number of parameters stored in array
        sds.write(startinit[x]);
        datalength = 4;
        if (debug) {
          console.print("sending data: ");
          console.println(startinit[x], HEX);
        }
      }
    }
    if (mode == 2) {
      for (int x = 0; x <= 6; x++) {                            // messagelength=number of parameters stored in array
        sds.write(monitorsensordata[x]);
        datalength = 6;
        if (debug) {
          console.print("sending data: ");
          console.println(monitorsensordata[x], HEX);
        }
      }
    }
  } 
}

/*

 if (mode == 1) {
 for (int x = 0; x <= 4; x++) {                            // messagelength=number of parameters stored in array
 sds.write(startinit[x]);
 if (debug) {
 console.print("sending data: ");
 console.println(startinit[x], HEX);
 }
 datalength = 4;
 } 
 }
 if (mode == 2) {
 for (int x = 0; x <= 6; x++) {                            // messagelength=number of parameters stored in array
 sds.write(monitorsensordata[x]);
 if (debug) {
 console.print("sending data: ");
 console.println(monitorsensordata[x], HEX);
 }
 datalength = 6;
 } 
 }
 }
 */
void recievedata() {
  int data = 0;
  int i = 0;
  int incomingdata[] = {
  };
  /*  time = millis();
   console.print("Monitoring speed: ");
   console.print(time-timeold);
   console.println("ms"); */
  if (debug) {
    console.println("waiting for data");
  }
  timeold = millis();
  while (!data) {                          // loop, it needs to be closed later if checksum and everything else is ok
    /*    if (timeout) {
     if ((timeold + timeout) <= time) {        // if time is higher than the time stored last timeout + the needet time it starts from begining
     console.println("Timeout");
     mode = 0;
     sds.end();
     return;     
     }
     } */
    if (sds.available()) {                   // reading data
      byte inByte = sds.read();
      incomingdata[i] = inByte;
      if (debug) {
        console.println(incomingdata[i],HEX);
      }
      byte numparam;
      byte checksum;
      /*      // Check if data was recieved sucessfull
       if (i == messagelength) {
       for (int  x = 0; (incomingdata[x] == message[x]); x++) {
       if (messagelength == x) {
       console.println("Data sent to ECU");
       }
       }
       }
       */
      if (i == datalength + 4) {
        numparam = incomingdata[i];
        if (debug) {
          console.print("Number of Parameters: ");
          console.println(numparam,HEX);
        }
      }
      if (mode == 2) {
        if (i == 20) {
          console.print("Throtle Position: ");
          console.println(incomingdata[i]*125/255);
        }
        if (i == 21) {
          console.print("Intake Air Pressure: ");
          console.println((incomingdata[i]-153)*133/4/255);
        }
        if (i == 22) {
          console.print("Engine Coolant Temp: ");
          console.println(incomingdata[i]*160/255 - 30);
        }
        if (i == 23) {
          console.print("Intake Air Temp: ");
          console.println(incomingdata[i]*160/255 - 30);
        }
        if (i == 28) {
          console.print("Intake Air Pressure2: ");
          console.println((incomingdata[i]-153)*133/4/255);
        }
        if (i == 47) {
          console.print("Second Throtle Valve: ");
          console.println(incomingdata[i]*100/255);
        }
      }
      if (i == datalength+5+numparam) {
        /* for (int x = datalength+1;x<i;x++) {
         checksum += incomingdata[x];
         console.print(checksum,HEX);
         }*/
        if (debug) {
          console.print("Checksum: ");
          console.println(incomingdata[i],HEX);
        }
        mode = 2;
        data++;
        delay (cyclespeed);
        /* if (checksum == incomingdata[i]) {
         data++;
         mode = 2;
         delay (cyclespeed);
         }  */
      }
      i++;
    }
  }
}