Go Down

Topic: Bike interface OBD (Read 41013 times) previous topic - next topic

cyclegadget


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.
Good links: Eagle tutorial= http://www.youtube.com/playlist?list=PLDE1858BD83D19C70
General Arduion tutorials = http://tronixstuff.wordpress.com
http://www.gammon.com.au/forum/bbshowpost.php?bbtopic_id=123

o5i_

Hi

I did this;
Code: [Select]
#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:
Code: [Select]
FFFFFFFFFF
FF8112F181
5
80F1123C1
EA
8F
C0
81
12
F1
81
5
FF8112F181
5
FF8112F181
5


o5i_

#32
May 16, 2014, 09:18 pm Last Edit: May 16, 2014, 09:20 pm by o5i_ Reason: 1
This one works good:
Code: [Select]
#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:
Code: [Select]
8112F181580F1123C1EA8FC0
Hope there are no problems if the code became longer...

o5i_

Litle update
Code: [Select]

#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...

cyclegadget


  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.
Good links: Eagle tutorial= http://www.youtube.com/playlist?list=PLDE1858BD83D19C70
General Arduion tutorials = http://tronixstuff.wordpress.com
http://www.gammon.com.au/forum/bbshowpost.php?bbtopic_id=123

o5i_

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?

robtillaart

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.
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

cyclegadget


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.
Good links: Eagle tutorial= http://www.youtube.com/playlist?list=PLDE1858BD83D19C70
General Arduion tutorials = http://tronixstuff.wordpress.com
http://www.gammon.com.au/forum/bbshowpost.php?bbtopic_id=123

o5i_

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 :D
Next i need to test writing on sd... I hope it doesnt slows to much...
Somone have maybee the definitions for the sensor values?
Code: [Select]

#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++;
    }
  }
}

cyclegadget


I will try to get you some received data information tomorrow when I have more time.

Glad you are making progress!
Good links: Eagle tutorial= http://www.youtube.com/playlist?list=PLDE1858BD83D19C70
General Arduion tutorials = http://tronixstuff.wordpress.com
http://www.gammon.com.au/forum/bbshowpost.php?bbtopic_id=123

o5i_

#40
May 27, 2014, 09:11 pm Last Edit: May 27, 2014, 09:16 pm by o5i_ Reason: 1
Hi, im working again on the program, i increased speed to 145 ms....
but i have trouble whit some array...
I want to do..
String array1[] = {
"RPM",
"SPEED",
"TEMP",
....
}
int array2[] = {
recievedata[10]*calculationneeded,
recievedata[11]*calculationneeded,
recievedata[15]*calculationneeded,
...
}
for (int x = 0;x < sizeof(array1);x++) {
Serial.print(array1
  • ),
    Serial.print(array2
  • ),
    }
    But if i print sizeof(array1) it gives me 18 if the arraysize is declared as 9, if i use byte it gives 9, but the value needs to bee different.......
    I cant print the values in array1... dont know why...

    The other problem is that i want to change the values of an array to values from an other value.... But i need to do
    for(int x = 0; x < sizeof(array2);x++) {
    array1
  • =array2

  • }

o5i_

Code: [Select]
   //////////////////////////////////////////////////////////// constant Values  ////////////////////////////////////////////////////////////
byte const source = 0xF1;
byte const target = 0x12;
byte const header = 0x80;
  //////////////////////////////////////////////////////////// mode 1  (init) ////////////////////////////////////////////////////////////
byte const startinit[5] = {
  0x81,
  target,
  source,
  0x81,
  0x05,
};
  //////////////////////////////////////////////////////////// mode 2  (get Values) ////////////////////////////////////////////////////////////
byte const monitorsensordata[7] = {
  header,
  target,
  source,
  0x02,
  0x21,
  0x08,
  0xAE, 
};
  //////////////////////////////////////////////////////////// not used for now  ////////////////////////////////////////////////////////////
byte const keepalive[1] = {
  0x01,
};




Code: [Select]
  //////////////////////////////////////////////////////////// create string /////////////////////////////////////////////
  data = 0;
  sendbits = 0;
  recievebits = 0;
  if (mode) {
    if (mode == 1) {
      for (int x = 0; x < sizeof(startinit); x++) {
        tx_data[x] = startinit[x];
        sendbits++;
      }   
    }
    if (mode == 2) { 
      for (int x = 0; x < sizeof(monitorsensordata); x++) {
        tx_data[x] = monitorsensordata[x];
        sendbits++;
      }
    }
  //////////////////////////////////////////////////////////// check read write delay //////////////////////////////////////////
    time = millis();
    if (time < read_write_delay + read_write_time) {
      if (debug) console.print("Im 2 fast, waiting....");
    }
    while (time < read_write_delay + read_write_time) {
      time = millis();
      if (debug) console.println(".");
    }
  //////////////////////////////////////////////////////////// send string /////////////////////////////////////////////
    for (int x = 0;x < sendbits;x++) {
      sds.write(tx_data[x]);
      delay (send_delay);
      if (debug) {
        console.print("Data tx: ");
        console.println(tx_data[x], HEX);
      }
    }


Code: [Select]
//////////////////////////////////////////////////////////// decoding protocol values  ////////////////////////////////////////////////////////////

  //////////////////////////////////////////////////////////// mode 2  (read Values)  ////////////////////////////////////////////////////////////
int const engine_value[9] = {
  ((rx_data[15] / 50.5) * 9.2) - 14.7,
  (rx_data[17]*256 + rx_data[18]) / 2.56,
  125*(rx_data[19]-55)/(256-55),
  rx_data[20]*4*0.136,
  1.1 * (rx_data[21] - 15),
  1.1 * (rx_data[22] - 15),
  rx_data[23] - rx_data[20]*4*0.136,
  rx_data[24]/12.7,
  rx_data[26],
};
String const engine_value_desc[] = {
  "boost ",
  "rpm ",
  "tps ",
  "ip ",
  "ect ",
  "iat ",
  "iap ",
  "bat ",
  "gear ",
};


Code: [Select]
  ////////////////////////////////////////////////// print values //////////////////////////////////////////////
  if (mode == 2) {
   for (int x = 0;x < sizeof(engine_value);x++) {
   console.print(engine_value_desc[x]);
   console.print(engine_value[x]);
   console.println();
   }
   }
  /////////////////////////////////////////////////// write on sd //////////////////////////////////////////////

cyclegadget


I am not sure how to fix your code without making lengthy changes but, I can give you an idea.

In my code I had two sets of variables. The first set, was constant and they defined what byte contained the information I wanted such as: RPM, Engine Temperature, Throttle Position, etc.

The second set of variables, contained the results of the bytes. For instance, I used lower case letters to tell the difference between the two sets. Below would be an example.

rpm = byte result RPM
temperature = byte result  Engine Temperature
throttle = byte result Throttle Position

I want to help you with your array problems but, they are not my strength. You may have to practice using arrays in a separate code for testing, and ask for help in the programming problems section.


Good links: Eagle tutorial= http://www.youtube.com/playlist?list=PLDE1858BD83D19C70
General Arduion tutorials = http://tronixstuff.wordpress.com
http://www.gammon.com.au/forum/bbshowpost.php?bbtopic_id=123

o5i_

Hi, i did some soldering :D
But i have problem to read the serial data transmitted from wideband...
Code: [Select]

void setup() {
  Serial.begin(57600);   
  Serial1.begin(9600);
}
void loop() {
  if (Serial1.available()) {
    Serial.println(Serial1.read());
  }
}

Gives:
Code: [Select]

123
229
235
0
103
217
123
229
235
0
103
217
123
229
235
0
103
217
123
229
235
0
103
217
123
229
235
0
103
217
123
229
235
0

But if i try to connect the wideband directly to pc:
Code: [Select]

14.8
14.8
14.8
14.8
14.8
14.8
14.8
14.8
14.8
14.8
14.8
14.8
14.8
14.8
14.8
14.8
14.8

whats wrong?

robtillaart

you must interpret the 5 bytes that come in,
the 5 bytes are constant, the 14.8 is too => so the 5 bytes represent the value.
Do you have some manual/datasheet with a formula?

floats in the arduino are 4 bytes so it is definitely not a 1-1 conversion....

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Go Up