Page 1 of 1

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

Posted: Sun Jun 08, 2025 8:21 pm
by N0edL22131
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`).
4. Disabled echo (`0x85`).
5. Hardware checks:
K-line shows ~12V at idle (with pull-up).
No TX/RX shorts.

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

Code: Select all

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:

Code: Select all

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