K-line/KWP2000 Communication with Piaggio Zip – Only Echo, No ECU Response

Hi everyone,

I’m trying to read my Piaggio Zip 4T Euro 5 ECU using an ESP32-C3 + MC33660 (K-line transceiver), but I’m only getting my own command echoes and no real ECU response. Hoping for some expert advice!

My Setup:

  • MC33660 connected to ESP32-C3 (RX: GPIO20, TX: GPIO21, CEN: 3.3V).
  • K-line wired to K Line + 1kΩ pull-up to 12V.
  • Scooter ignition ON.

What I’ve Tried:

  1. Baud rates tested: 10400, 9600, 4800.
  2. ECU addresses tried: 0xF1, 0x33, 0x7E.
  3. Wakeup sequences:
  • Standard KWP2000 (0x81 0x13 [ADDR] 0x81).
  • Alternative (0xC0 0x33 [ADDR] 0x81).
  1. Disabled echo (0x85).
  2. Hardware checks:
  • K-line shows ~12V at idle (with pull-up).
  • No TX/RX shorts.

Result:

Only my own commands echoed back, e.g.:

Sent: 68 6A F1 01 01 0C FF  
Received: 68 6A F1 01 01 0C FF  (no real ECU data)

No error codes, no RPM, no actual response.

Questions:

  1. Does the Piaggio Zip Euro 5 even support K-line diagnostics?
  2. Is 0xF1 the correct ECU address, or is there a different protocol?
  3. Am I missing a step in initialization?
  4. Has anyone successfully reverse-engineered Piaggio’s Euro 5 ECUs?

I've hit a wall after days of testing. Any insights would be hugely appreciated! I tried using ChatGPT but didn’t get very far with the responses I got.

Code:

#include <HardwareSerial.h>

#define KLINE_RX_PIN 20   // GPIO20 = RX
#define KLINE_TX_PIN 21   // GPIO21 = TX
#define CEN_PIN 4         // GPIO4 - MC33660 enable
HardwareSerial KLine(1);  // UART1

// K-line parameters
const uint32_t baudrates[] = {10400, 9600, 4800}; 
const uint8_t ecuAddresses[] = {0xF1, 0x33, 0x7E};

void setup() {
  Serial.begin(115200);
  pinMode(CEN_PIN, OUTPUT);
  digitalWrite(CEN_PIN, HIGH);
  delay(500);
  testKLineConnection();
}

void testKLineConnection() {
  for (auto baud : baudrates) {
    KLine.begin(baud, SERIAL_8N1, KLINE_RX_PIN, KLINE_TX_PIN);
    Serial.print("\nTesting baudrate: ");
    Serial.println(baud);

    for (auto addr : ecuAddresses) {
      Serial.print("\nAttempting ECU address 0x");
      Serial.println(addr, HEX);

      digitalWrite(CEN_PIN, LOW);
      delay(100);
      digitalWrite(CEN_PIN, HIGH);
      delay(200);

      uint8_t wakeup[] = {0x81, 0x13, addr, 0x81};
      KLine.write(wakeup, sizeof(wakeup));
      delay(300);

      KLine.write(0x85);
      delay(50);

      uint8_t request[] = {0x68, 0x6A, addr, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD9};
      KLine.write(request, sizeof(request));
      KLine.flush();

      delay(500);
      if (KLine.available()) {
        Serial.print("ECU response: ");
        while (KLine.available()) {
          Serial.print(KLine.read(), HEX);
          Serial.print(" ");
        }
        Serial.println("Communication found!");
        return;
      } else {
        Serial.println("No Communication!");
      }
    }
  }
  Serial.println("No Communication!");
}

void loop() {
}

Thanks in advance!

You are assuming we understand every acronym. Post links to datasheets for any non Arduino hardware, take a picture with labelled hand drawn wiring connections.
Example
In the sentence 1. Does the Piaggio Zip Euro 5 even support K-line diagnostics?
I suspect most helpers only understand Does the five even support diagnostics?
Maybe there is a helper here who understands all the assumptions, but I will be surprised.