Keyword-Protocol-2000 icon indicating copy to clipboard operation
Keyword-Protocol-2000 copied to clipboard

Connect with Honda

Open man-go1 opened this issue 4 years ago • 29 comments

Hi, Want to readout my bike using an Arduino. I used some code to connect to it. But I can’t do anything past the handshake. So I want to use you library. Can you help out?

man-go1 avatar May 04 '20 22:05 man-go1

Yes, as you may have read the library is not ready for Honda, yet. Which model is your bike and year? Do you have a sequence of request known to work?

aster94 avatar May 05 '20 05:05 aster94

great, I think i have the same bike as Stefan (in the other issue). its a VFR. m'n is from 2010. i looked around on internet and found a table mapping http://projects.gonzos.net/wp-content/uploads/2015/09/Honda-data-tables.pdf and it looks like all info is in table 16 for my bike. but it's not saying how and what. i think i can figure that out what is wat. but i can't get a connection. first off i'm not an expert. juist looked for stuf on the internet what i think is needed. send a low wait 70 ms Send a hi wait 120ms send a wake up: 0xFE, 0x04, 0x72, 0x8C wait 200Ms send a handshake?! 0x72, 0x05, 0x00, 0xF0, 0x99 and the ECU needs to respond with 02 04 00 FA

man-go1 avatar May 05 '20 07:05 man-go1

@man-go1 if you can double-check this sequence:

send a low
wait 70 ms
Send a high
wait 120ms
send: 0xFE, 0x04, 0x72, 0x8C
wait 200Ms
send: 0x72, 0x05, 0x00, 0xF0, 0x99

I can write a code for you, I will check with my logic analyzer and then I will send it to you But I can't do it before Saturday

aster94 avatar May 05 '20 08:05 aster94

i think so. what i did( see below) and i get a succes back.

//initialise communications byte initHonda(){ debug.println("Starting initialise Honda"); bike.end(); delay(350); //Sending LOW digitalWrite(TX_PIN, LOW); delay(70); //Sending High digitalWrite(TX_PIN, HIGH); delay(120); pinMode(TX_PIN, OUTPUT); //Start Bike serial bike.begin(10400); bike.write(MessageWakeup, sizeof(MessageWakeup)); //Send WakeUp delay(200); bike.write(MessageInitialise, sizeof(MessageInitialise)); // initialise communications bike.flush(); // wait to send all

resState = BUSY; // Try to read a wakeup is send while (resState == BUSY) resState = getResponse(resbuf); if (resState == SUCCESS) { delay(300); resState = BUSY; // Try to read initialise response while (resState == BUSY) resState = getResponse(resbuf); if (resState == SUCCESS) {

   if (resState == SUCCESS) {
      return SUCCESS; 
   } else {
        debug.println("Failed init Honda, something is wrong retry"); // Return false if diagnostic mode request was denied or failed
        return BUSY; 
     }
}
if (resState == TIMEOUT){
    debug.println("TIMEOUT init Honda"); // Return false if diagnostic mode request was denied or failed
    return BUSY; 
}

} if (resState == TIMEOUT){ debug.println("TIMEOUT WakeUp Honda"); // Return false if diagnostic mode request was denied or failed return BUSY; } }

man-go1 avatar May 05 '20 09:05 man-go1

where does your code stuck?

aster94 avatar May 05 '20 10:05 aster94

This part is okay. But I can’t get info out of tables.

man-go1 avatar May 05 '20 17:05 man-go1

can you post what are you getting from the ECU?

aster94 avatar May 07 '20 09:05 aster94

hi, sorry for the late response but i fryde my Arduino.. and needed to fix it. i think i know how to communication works. i can get table 16 from the bike and calculate the RPM.

now i just need to implement it with your code. This is my code: ( yeah its a mess, just needed it to talk)

`*/ #define SWversion "version 0.4" // Serial Debug USB #define debug Serial //Serial to connect to the bike #define bike Serial1 #define TX_PIN 18 #define t0

//Status Flags #define SUCCESS 0 #define TIMEOUT 1 #define BUSY 2 #define BUFFEROVERFLOW 3

// default variable // Flag for ECU connection byte ECUconnected; byte resbuf[26]; byte resState; uint16_t RPM;

//initialise communications messages byte MessageWakeup[] = {0xFE, 0x04, 0x72, 0x8C}; // wakeup no responce from ECU byte MessageInitialise[] = {0x72, 0x05, 0x00, 0xF0, 0x99}; //initialise communications The ECU should respond with: 02 04 00 FA

//get info from ECU VFR Specific byte Table00[] = { 0x72, 0x07, 0x72, 0x00, 0x00, 0x06, 0x0F}; //unknown byte Table10[] = { 0x72, 0x07, 0x72, 0x10, 0x00, 0x06, 0xFF}; //unknown byte Table11[] = { 0x72, 0x07, 0x72, 0x11, 0x00, 0x06, 0xFE}; //unknown byte Table16[] = { 0x72, 0x07, 0x72, 0x16, 0x00, 0x06, 0xF9}; //vfr 1200f responce byte Table20[] = { 0x72, 0x07, 0x72, 0x20, 0x00, 0x06, 0xEF}; //unknown byte Table21[] = { 0x72, 0x07, 0x72, 0x21, 0x00, 0x06, 0xEE}; //unknown byte TableD0[] = { 0x72, 0x07, 0x72, 0xD0, 0x00, 0x06, 0x3F}; //unknown byte TableD1[] = { 0x72, 0x07, 0x72, 0xD1, 0x00, 0x06, 0x3E}; //unknown byte Table61[] = { 0x72, 0x07, 0x72, 0x61, 0x00, 0x06, 0xAE}; //unknown byte Table70[] = { 0x72, 0x07, 0x72, 0x70, 0x00, 0x06, 0x9F}; //unknown

// needed to calculate checksum
byte calculate[] = {0x72, 0x07, 0x72, 0x60, 0x00, 0x06};

void setup() { // put your setup code here, to run once: debug.begin(115200);// For debugging debug.println("Starting setup"); // needed for Bluetooth //EEBlue.begin(9600); //Default Baud for comm, it may be different for your Module.

}

void loop() {

unsigned long startedWaiting = millis();

ECUconnected = BUSY;
//Try to connect with the ECU
while (ECUconnected == BUSY){
 ECUconnected = initHonda();
 }
while (ECUconnected == SUCCESS) {

   // Request table 16
  bike.write(Table16, sizeof(Table16));
  bike.flush();
  bikeFlush();
  // Receive the response. Receiving this way will block the Arduino.
  resState = BUSY;
  delay(300);
  //checkResponse();
  while (resState == BUSY) {
    resState = getResponse(resbuf);
  }
  // Successfully received the response message which is stored in resbuf
  if (resState == SUCCESS) {
   // Check if response is positive
     if (resbuf[3] == 0x16) { // change from 0x16 to D1
        uint16_t varY = resbuf[5];
        varY = varY << 8;
        varY = varY + resbuf[4];
        RPM = varY;            
        // Do something with RPM e.g. show on LCD
        debug.println("");
        debug.print("RPM ");
        debug.println(RPM,DEC);
        debug.println("");  
        debug.println("Tabel 16");          
        debug.print("hex");
        debug.println("");
        
        for(int i = 0; i< 26; i++)
         {
           debug.print(resbuf[i],HEX);
           debug.print("-");
          }
        debug.println("");

     } 
     else {
        // No positive response, reset ECU connection
        ECUconnected = BUSY;
     }
} 
else if (resState == TIMEOUT) {
  // Timeout, reinitiate ECU
  debug.println("Timeout Getting Responce");
  RPM = 0;
 ECUconnected = BUSY;
  

}

}

}

// Simple check the response to debug terminal void checkResponse(){ while (bike.available() > 0){ byte incomingByte = bike.read(); debug.print(incomingByte, HEX); debug.print(' '); } } // cleare bike terminal void bikeFlush(){ while(bike.available()) bike.read(); }

//initialise communications byte initHonda(){ debug.println("Starting initialise Honda"); bike.end(); delay(350); //Sending LOW digitalWrite(TX_PIN, LOW); delay(70); //Sending High digitalWrite(TX_PIN, HIGH); delay(120); pinMode(TX_PIN, OUTPUT); //Start Bike serial1 bike.begin(10400); bike.write(MessageWakeup, sizeof(MessageWakeup)); //Send WakeUp delay(200); bike.write(MessageInitialise, sizeof(MessageInitialise)); // initialise communications bike.flush(); // wait to send all

resState = BUSY; // Try to read a wakeup is send while (resState == BUSY) resState = getResponse(resbuf); if (resState == SUCCESS) { delay(300); resState = BUSY; // Try to read initialise responce while (resState == BUSY) resState = getResponse(resbuf); if (resState == SUCCESS) { if (resState == SUCCESS) { return SUCCESS; } else { debug.println("Failed init Honda, somthing is wrong retry"); // Return false if diagnostic mode request was denied or failed return BUSY; } } if (resState == TIMEOUT){ debug.println("TIMEOUT init Honda"); // Return false if diagnostic mode request was denied or failed return BUSY; } } if (resState == TIMEOUT){ debug.println("TIMEOUT WakeUp Honda"); // Return false if diagnostic mode request was denied or failed return BUSY; } }

byte getResponse(byte *rbuffer) { // These bytes remain unchanged in between function calls // Used to monitor the response while not blocking the program static int index = 0; static int len = 255; static unsigned long t = 0;

// After a request is send the timer is set if (t == 0) t = millis(); // Check if function call is within timeout limit if (millis() - t < 250) { // Check if more bytes need to be received if (index < len) { // Check if bytes are available unsigned long startedWaiting = millis(); while (bike.available() > 0) { t=0; rbuffer[index] = bike.read();

    // First received byte must be correct 0xFE, 0x04, 0x72, 0x8C
    if (rbuffer[0] == 0xFE){
   // debug.print(rbuffer[0], HEX);
      // Clear bike RX buffer
      while(bike.available()) bike.read();
      memset(rbuffer, 0, sizeof(rbuffer));
      debug.println("Wakeup OK");
       
          t = 0;
          index = 0;
          len = 255; 
      return SUCCESS;
      
     }

     if ((rbuffer[0] == 0x02) && (rbuffer[1] == 0x04) && (rbuffer[2] == 0x00) && (rbuffer[3] == 0xFA)){
        // Clear bike RX buffer
        while(bike.available()) bike.read();
        debug.println("ini OK");  
          t = 0;
          index = 0;
          len = 255;
          delay(200);
          memset(rbuffer, 0, sizeof(rbuffer));
        return SUCCESS;
     }
    if (rbuffer[3] == 0x16){

          t = 0;
          //index = 0;
          index++;
          len = 12;
        return BUSY;
     }
     index++;
      return BUSY; 
      
   }
   debug.println("Timeout");
    return TIMEOUT;
    
 }
  // Read all bytes, reset timer, index and length
 else {
  t = 0;
  index = 0;
  len = 255;
  delay(55);
  //debug.println("succes");
  return SUCCESS;
 }

} else { t = 0; index = 0; len = 255; //debug.println("Timeout"); return TIMEOUT; //return BUSY; } } `

this is the Result from the serial interface:

Starting initialise Honda Wakeup OK ini OK RPM 0 Tabel 16 hex 2-C-72-16-0-0-0-19-A-0-0-47-0-0-0-0-0-0-0-0-0-0-0-0-0-0-

man-go1 avatar May 07 '20 15:05 man-go1

okkkk we have a starting point

I can write some code about it but I need some explanation:

send a low
wait 70 ms
Send a high
wait 120ms
send: 0xFE, 0x04, 0x72, 0x8C
receive: ????
wait 200Ms
send: 0x72, 0x05, 0x00, 0xF0, 0x99
receive: ????
send: 0x72, 0x07, 0x72, 0x16, 0x00, 0x06, 0xF9
receive: data

can you check if this is correct and fill the part that I don't know?

aster94 avatar May 09 '20 17:05 aster94

hi,

as i have learned. is this step an initialise: -/--------------------------------------- send a low wait 70 ms Send a high wait 120ms send: 0xFE, 0x04, 0x72, 0x8C receive: Nothing wait 200Ms send: 0x72, 0x05, 0x00, 0xF0, 0x99 receive: Nothing. -/--------------------------------------- then I can send a request to send data. in this example table 16. send: 0x72, 0x07, 0x72, 0x16, 0x00, 0x06, 0xF9 receive: data -/--------------------------------------- as long as I ask for data the link keeps alive. when I stop I need to initialise again

man-go1 avatar May 14 '20 19:05 man-go1

Okkk, in the next days I will write the code.

Actually, it is something bad that the ECU doesn't answer back. We can't know if the initialization has gone well 😔

Can you give me a few samples of the data the ECU return when you send the table 16 and an explanation of them? For example I see that the rpm are between byte 4 and 5

aster94 avatar May 14 '20 20:05 aster94

If you have some other code to look at response I’m happy to try. But I can’t get a response back.

About the other question. I’m still cracking my brain for all the response back I’m getting of ecu. And what is what? I have no manual. And theres not much to find on the internet for the VFR. It does not match other Honda’s. And binaire is not my best thing. 4 and 5 are RPM Calculating it like this will get the correct RPM.

uint16_t varY = resbuf[5]; varY = varY << 8; varY = varY + resbuf[4]; RPM = varY;
The rest I need to find. My goal is to create a mile to the galon calculation. To calculate how far I can go with the fuel in the tank. . 😓 but I’m a long way from there 😬

man-go1 avatar May 14 '20 21:05 man-go1

good news!

I wrote the code and put it on a branch: https://github.com/aster94/Keyword-Protocol-2000/tree/honda

I tested it with a logic analyzer and it looks good. You may wish to double-check it with https://sigrok.org/wiki/Downloads this is the file honda.zip

a few example: LOW for 70 and then HIGH for 120 image

send: 0xFE, 0x04, 0x72, 0x8C and wait 200ms image

send: 0x72, 0x05, 0x00, 0xF0, 0x99 image

send: 0x72, 0x07, 0x72, 0x16, 0x00, 0x06, 0xF9 (table 16) image

Also here there are a few other questions:

  1. does honda have a delay between bytes?
  2. does it have a connection time-out? (for example on suzuki is 2 seconds)
  3. I strongly need a real data to make sure everything is fine can you provide one or two of these?

send: 0x72, 0x07, 0x72, 0x16, 0x00, 0x06, 0xF9 receive: data

  1. Which arduino board are you using?
  2. which IDE?

Please before trying the above code on your motorbike answer these questions

aster94 avatar May 21 '20 17:05 aster94

Tnx, Will check tomorrow. 👍🏻

man-go1 avatar May 21 '20 18:05 man-go1

@man-go1 did you had time to check it? Any update?

aster94 avatar Jun 13 '20 23:06 aster94

Hi, I don't have enough kwonledge about this, but I found this, maybe it could be help you to finalize the code :

The ECU will not respond until it has received the correct initialisation sequence. I used this:

    Pull the K-line low for 70msec

    Return the K-line to the high state for 120msec

    Send “Wakeup” message: FE 04 FF FF. No response is expected

    Wait 200msec

    Send “Initialise” message: 72 05 00 F0 99

    The ECU should respond with: 02 04 00 FA

That’s it. You can then send requests and the ECU should respond with the data requested. The communications needs to be “kept alive”, however. That means that if the ECU hasn’t received a request within a certain time it goes back to sleep and needs to be initialised again. I think the time is around 3 sec.

Maximouss89 avatar Oct 23 '20 21:10 Maximouss89

Hi @Maximouss89 which motorbike do you have? The sequence is a little bit different (but still very similar) to the VFR 2010 of @man-go1 Do you have the hardware and knowledge to test a snippet of code?

aster94 avatar Oct 24 '20 06:10 aster94

Hello, I have a 2010 - CBR1000RR. I would connect an Arduino to DLC and know RPM and vehicule Speed. But I didn't know K-line and have few knowledge in programmation. (I'll do all tuto with arduino's kit but I'm not a master ;) ) All informations I gave you are on this website : http://forum.pgmfi.org/viewtopic.php?f=57&t=22199&start=45

I would like to learn how to interact with my CBR and arduino

Maximouss89 avatar Oct 25 '20 20:10 Maximouss89

If you have the code, I could try to test if code works. I have Arduino and I'm going to have MC33290 and 510Ohm resistor. If I understood correctly I have to connect like that : http://compcar.ru/forum/attachment.php?s=f0cd48d1c97ceffe7a692e527d7bf43c&attachmentid=18808&d=1453708488

Maximouss89 avatar Oct 25 '20 21:10 Maximouss89

ok, which arduino board? do you have a board with 2 or more serial port?

aster94 avatar Oct 26 '20 10:10 aster94

I have an Arduino UNO and Nano, but I could use other pins (10 an 11 for example) and SoftwareSerial Library right? If it's necessary I'll buy a arduino mega.

Maximouss89 avatar Oct 26 '20 13:10 Maximouss89

hi there, From my experience software serial is not good, often uses timers used by other libraries, go for mega.

cheers

On Mon, 26 Oct 2020 at 21:15, Maximouss89 [email protected] wrote:

I have an Arduino UNO and Nano, but I could use other pins (10 an 11 for example) and SoftwareSerial Library right? If it's necessary I'll buy a arduino mega.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/aster94/Keyword-Protocol-2000/issues/5#issuecomment-716538003, or unsubscribe https://github.com/notifications/unsubscribe-auth/AKOIO3ENDOTIOBY7Z3YH45DSMVY6LANCNFSM4MZD46HA .

-- With Best Regards Bartek Chrzanowski

mobile UK: (+44) 0 757 099 8842 <%28%2B44%29%2007570998842>

e-mail: [email protected] [email protected] linked-in: Bartek-Chrzanowski http://www.linkedin.com/pub/bartek-chrzanowski/33/121/987 ( https://uk.linkedin.com/pub/bartek-chrzanowski/33/121/987 ) -KJM-

BartasCh avatar Oct 26 '20 13:10 BartasCh

Yes, you can use a software serial but an hardware one would be better. I don't want you to spend this extra money for now, we can just try the software serial on the arduino Uno/nano and see if it will work

In reply to @BartasCh I do agree that the soft serial is not good but we can run a test

P.S: sorry I closed the issue for mistake

aster94 avatar Oct 26 '20 13:10 aster94

Which board has 2 or more serial port ? I found : Arduino MEGA, et ZERO, right? Arduino Zero use 3.3V, doesn't matter? I don't buy yet, but I'm looking for in case it would be necessary. (sorry for my English, I'm not very good ;/ )

Maximouss89 avatar Oct 26 '20 15:10 Maximouss89

Yes, and also the arduino-compatible board like the stm32f103 as the bluepill 3.3V is ok

aster94 avatar Oct 26 '20 15:10 aster94

Yes, and also the arduino-compatible board like the stm32f103 as the bluepill 3.3V is ok

I'll have a STM32F103 board tomorrow it's good :angel: I didn't know this board, there are faster than arduino for TFT screen etc... It will be usefull thank you !

Maximouss89 avatar Oct 26 '20 16:10 Maximouss89

yes these are my favourite boards! the ratio between price and power is awesome, I usually use them

aster94 avatar Oct 26 '20 18:10 aster94

Hi, I tried to write a piece of code, could you tell me if you see any mistakes pls ?

byte wakeup[]={0xFE, 0x04, 0xFF, 0xFF}; byte initialise[]={0x72, 0x05, 0x00, 0xF0, 0x99}; byte answer[]={0x02,0x04,0x00,0xFA}; byte message[24]; //byte checksum=0xF0; int RX1 = PA10; int TX1 = PA9; bool connection=false; bool goodrep=false;

void setup() { // put your setup code here, to run once: pinMode(TX1,OUTPUT); pinMode(RX1,INPUT); Serial1.begin(10400); while(connection==false){ digitalWrite(TX1,HIGH); delay(10); digitalWrite(TX1,LOW); delay(70); digitalWrite(TX1,HIGH); delay(120); digitalWrite(TX1,LOW); Serial1.write(wakeup,sizeof(wakeup)); delay(200); Serial1.write(initialise,sizeof(initialise)); int i=0; while(Serial1.available()>0){ message[i]=Serial1.read(); Serial.print(message[i]); i=i+1; } int j=0; while(j<i-1){ if(answer[j]==message[j]){ j++; goodrep=true; }else{ goodrep=false; break; } } if (goodrep==true){ connection=true; } } }

void loop() { // put your main code here, to run repeatedly: int i=0; Serial.println(" "); while(Serial1.available()>0){ message[i]=Serial1.read(); Serial.print(message[i]); // if (message[i]<>checksum){ // i=i+1; // }else{ // break; // } } }

Maximouss89 avatar Nov 05 '20 21:11 Maximouss89

if you want you can use the library sorry but I can't check your code

aster94 avatar Nov 06 '20 08:11 aster94