Reverse Engineering
Reverse Engineering

BMW E87 Direksiyon Tuşlarını K-CAN Üzerinden Arduino ile Okumak

BMW E87 116i aracımda Arduino ve MCP2515 ile K-CAN hattını dinleyip direksiyon tuşlarının 0x1D6 mesajlarını Serial Monitor’de okuduğum bir deneme; kullandığım filtreleme/çözümleme kodu ve gerçek çıktılarla.

BMW E87 K-CAN Arduino kapak görseli

Bu yazıda BMW E87 2011 116i aracımda direksiyon üzerindeki multimedya tuşlarının K-CAN hattında nasıl göründüğünü anlamaya çalıştığım küçük bir denemeyi anlatıyorum. Amaç araca müdahale eden büyük bir modifikasyon değil; sadece CAN hattını dinleyip tuşlara basıldığında gelen mesajları Arduino ve MCP2515 ile okuyup Serial Monitor üzerinde görmekti.

Projeye başlarken merak ettiğim soru basitti: direksiyon tuşlarına bastığımda K-CAN üzerinde hangi mesajları görüyorum? İleride bu tuşları harici bir Bluetooth ses modülüyle kullanma fikrim vardı, ama bu aşamada oraya geçmedim. İlk hedefim sadece tuşları okuyup gelen CAN mesajlarını Serial Monitor’e yazdırmaktı.

Araç ve Deneme Ortamı

text
Araç: BMW 1 Serisi
Kasa: E87
Model: 2011 BMW 116i
Hat: K-CAN (100 kbit/s)
Çalışma alanı: Direksiyon multimedya tuşları
Amaç: Tuş basımlarını okuyup Serial Monitor'de gözlemlemek
Kullanılan Aletler
  • ArduinoCAN mesajlarını okuyup Serial’e basan taraf
  • MCP2515 + TJA1050 CAN modülüK-CAN ile Arduino arasında köprü
  • Jumper kablolargeçici test bağlantısı
  • Arduino IDE + Serial Monitorgözlem

Neden Hattı Dinledim, Tuşlara Kablo Çekmedim?

BMW E87’de birçok modül birbiriyle haberleşiyor ve direksiyon tuşları da bu hatlar üzerinden ilgili modüllere bilgi iletiyor. Benim hedefim, tuşa bastığımda bu bilginin CAN hattında nasıl temsil edildiğini görmekti. Bu yüzden doğrudan tuşlara fiziksel kablo çekmek yerine araç içindeki haberleşme hattını dinlemek daha mantıklıydı.

Bu yaklaşımın avantajı şu: tuşların orijinal çalışma mantığı korunuyor, direksiyon içine müdahale etmeye gerek kalmıyor ve CAN frame’leri üzerinden hangi tuşun nasıl göründüğü analiz edilebiliyor. Odaklandığım hat K-CAN tarafıydı.

Geçici Bağlantı ve Dinleme Mantığı

K-CAN hattını gözlemlemek için klima/IHKA soketi tarafında geçici bir test bağlantısı kullandım. Amacım hatta veri yazmak değil, sadece trafiği dinlemekti; kalıcı montaj, lehimli bağlantı veya geri döndürülemez bir değişiklik yapmadım.

Dinleme akışı
  1. K-CAN hattını IHKA soketi tarafından geçici olarak dinle.
  2. MCP2515 modülü üzerinden mesajları Arduino’ya aktar.
  3. Arduino ile gelen CAN frame’lerini oku.
  4. Serial Monitor üzerinde print et.

Önce Tüm Trafik, Sonra Tek ID

CAN hattında çok fazla mesaj olabiliyor. Bu yüzden tüm trafiği görmek mümkün olsa da asıl önemli olan, direksiyon tuşlarına basıldığında değişen mesajları ayırt etmekti. İzlediğim mantık şuydu:

İzlediğim mantık
  1. Arduino + MCP2515 ile K-CAN hattını dinle.
  2. Serial Monitor’de gelen mesajları izle.
  3. Direksiyon tuşlarına bas.
  4. Tuş basımı sırasında tekrar eden veya değişen CAN ID’lerini işaretle.
  5. Gereksiz trafiği filtreleyip ilgili ID’ye odaklan.
Problem

Direksiyon tuşlarıyla ilişkili olarak anlamlı görünen ID 0x1D6 idi. Önemli not: bu ID’nin her araç, her yıl ve her donanım için aynı olduğunu iddia etmiyorum; kendi aracım üzerinde yaptığım gözleme dayanan bir sonuç.

Kod: 0x1D6’yı Filtrelemek ve Tuşları Çözmek

Trafiği okunabilir hale getirmek için MCP2515’in donanım filtresiyle yalnızca 0x1D6 ID’sini geçirdim, sonra gelen frame’in ilk byte’ına göre tuşu çözdüm. Aşağıdaki tam sketch, videoda görünen filtreleme satırlarını birebir içeriyor; setup/loop ve tuş çözümleme kısmı ise gözlemlediğim çıktıyı (ilk byte boşta C0, UP E0, DOWN D0) yeniden üreten bir referans uygulama. Pinleri ve eşik değerlerini kendi bağlantına ve aracına göre uyarlaman gerekir.

cpp
#include <SPI.h>
#include <mcp_can.h>          // coryjfowler/MCP_CAN_lib

// --- pinler: kendi bağlantına göre ayarla ---
const int CAN0_CS = 10;        // MCP2515 CS pini
#define MODE_PIN  3
#define PLAY_PIN  4
#define NEXT_PIN  5
#define PREV_PIN  6
#define EQ_PIN    7

MCP_CAN CAN0(CAN0_CS);

long unsigned int rxId;
unsigned char len = 0;
unsigned char rxBuf[8];
bool pressed = false;          // şu an bir tuş basılı mı

void setup() {
  Serial.begin(115200);

  pinMode(MODE_PIN, OUTPUT);
  pinMode(PLAY_PIN, OUTPUT);
  pinMode(NEXT_PIN, OUTPUT);
  pinMode(PREV_PIN, OUTPUT);
  pinMode(EQ_PIN,   OUTPUT);
  digitalWrite(MODE_PIN, LOW);
  digitalWrite(PLAY_PIN, LOW);
  digitalWrite(NEXT_PIN, LOW);
  digitalWrite(PREV_PIN, LOW);
  digitalWrite(EQ_PIN,   LOW);

  // K-CAN 100 kbit/s; mavi MCP2515 modüllerinde kristal genelde 8 MHz
  if (CAN0.begin(MCP_STDEXT, CAN_100KBPS, MCP_8MHZ) == CAN_OK)
    Serial.println("MCP2515 init OK");
  else
    Serial.println("MCP2515 init FAIL");

  // sadece 0x1D6 (direksiyon tuşları) ID'sini geçir
  CAN0.init_Mask(0, 0, 0x07FF0000);
  CAN0.init_Filt(0, 0, 0x01D60000);
  //CAN0.init_Filt(1, 0, 0x01D60000);
  CAN0.init_Mask(1, 0, 0x07FF0000);
  CAN0.init_Filt(2, 0, 0x01D60000);

  // yalnızca dinleme: hatta ACK/veri yazmaz
  CAN0.setMode(MCP_LISTENONLY);
}

void loop() {
  if (CAN0.checkReceive() != CAN_MSGAVAIL) return;

  CAN0.readMsgBuf(&rxId, &len, rxBuf);
  if ((rxId & 0x7FF) != 0x1D6) return;

  Serial.print("ID: 1D6 Data: ");
  for (int i = 0; i < len; i++) {
    if (rxBuf[i] < 0x10) Serial.print('0');
    Serial.print(rxBuf[i], HEX);
    Serial.print(' ');
  }

  // gözlemlenen ilk byte: boşta 0xC0, UP 0xE0, DOWN 0xD0
  byte b = rxBuf[0];
  if (b == 0xE0)      { Serial.println("- UP Button Pressed down");   pressed = true; }
  else if (b == 0xD0) { Serial.println("- DOWN Button Pressed down"); pressed = true; }
  else if (b == 0xC0 && pressed) { Serial.println("- Buttons Released"); pressed = false; }
  else Serial.println();
}

Filtre mantığı şu: maske olarak 0x07FF0000 (11-bit ID’nin tamamı) kullanıp filtreye 0x01D60000 yazınca yalnızca 0x1D6 ID’li frame’ler geçiyor (değer ID’nin 16 bit sola kaydırılmış hali, 0x1D6 << 16). K-CAN 100 kbit/s olduğu için modülü o hızda başlattım ve yalnızca dinleme (listen-only) moduna aldım; böylece hatta hiçbir şey yazmıyor. Üstteki digitalWrite satırları ise ileride harici ses modülünü süreceğim çıkış pinlerini başlangıçta LOW’a çekiyor; bu aşamada o tarafı henüz kullanmadım.

Serial Monitor’de Ne Gördüm?

Testin en keyifli kısmı buydu: direksiyon tuşlarına bastığımda Serial Monitor’de mesajların anlık akması. Gözlemlediğim çıktı şöyleydi:

text
ID: 1D6 Data: C0 0C
ID: 1D6 Data: C0 0C - Vol + Button Pressed
ID: 1D6 Data: E0 0C - UP Button Pressed down
- Buttons Released
ID: 1D6 Data: D0 0C - DOWN Button Pressed down
- Buttons Released

Burada ilk data byte’ı tuşa göre değişiyor: boşta C0, UP tuşunda E0, DOWN tuşunda D0 görünüyor. Sketch tarafında bu değerleri yorumlayıp "UP Button Pressed down", "DOWN Button Pressed down" ve bırakınca "Buttons Released" gibi okunabilir olaylara çevirdim. Proje benim için gerçek anlamda burada "çalıştı"; çünkü artık tuşlara bastığımda araç içinde görünmeyen bir haberleşmeyi kendi ekranımda görebiliyordum.

Bu Aşamada Ne Başardım?

Sonuçlar
  1. BMW E87 üzerinde K-CAN hattını okuyabildim.
  2. Arduino + MCP2515 ile direksiyon tuşlarına ait mesajları gözlemledim.
  3. 0x1D6 ID’sine odaklanıp Serial Monitor’de anlamlı tuş olayları aldım.
  4. Bluetooth kontrol gibi bir aksiyon katmanına geçmeden önce okuma katmanını doğruladım.

Bu benim için önemliydi, çünkü bir sonraki aşamaya geçmeden önce "tuşları gerçekten okuyabiliyor muyum?" sorusunu cevaplamış oldum.

Neden Bluetooth Kontrolü Sonraki Aşama?

Projenin başındaki fikirlerden biri tuşlarla harici bir Bluetooth ses modülünü kontrol etmekti. Ama önce okuma tarafının sağlam çalıştığını görmek istedim. Bence elektronik ve otomotiv projelerinde sağlıklı sıra şu: önce sinyali oku, sonra anlamlandır, sonra filtrele, en son başka bir sistemi kontrol et. Ben bu çalışmada ilk iki-üç aşamaya odaklandım.

Öğrendiklerim

Bu küçük çalışma bana birkaç şeyi hatırlattı. Araç elektroniğinde acele etmemek gerekiyor; CAN gibi hatlarda önce dinlemek, anlamak ve not almak en güvenli yaklaşım. Gelen her mesaj anlamlı görünmeyebilir, önemli olan doğru koşulda doğru değişimi yakalamak. MCP2515 gibi basit ve ulaşılabilir bir modülle araç içi haberleşme hakkında çok şey öğrenmek mümkün. Ve benim için bu bir kalıcı modifikasyon değil, bir okuma ve öğrenme denemesiydi.

Sonraki Adım

Sıradaki adımlar: tuşlara karşılık gelen byte değerlerini daha net haritalamak, ses aç/kıs ve ileri/geri tuşlarını ayrı ayrı etiketlemek, Arduino tarafında temiz bir event sistemi kurmak ve harici bir modülü kontrol etmeden önce uzun süreli stabilite testi yapmak. Bluetooth kontrolü ancak bu doğrulamalardan sonra ayrı bir proje adımı olarak gelir.

Sonuç

Bu proje, BMW E87 üzerinde K-CAN hattını Arduino ve MCP2515 ile okumaya yönelik küçük ama benim için çok öğretici bir denemeydi. En önemli sonuç, direksiyon tuşlarına bastığımda araç içindeki haberleşmenin Serial Monitor üzerinde görünür hale gelmesiydi.

Direksiyon tuşları K-CAN üzerinden okunabiliyor ve bu mesajlar Arduino tarafında işlenebilir hale getirilebiliyor.

Bu aşama, daha ileri otomotiv elektroniği ve donanım tarafı reverse engineering projeleri için temel bir öğrenme adımı oldu. Bu tür denemeleri paylaşmamın sebebi, asıl değerin sadece sonuçta değil; problemi nasıl parçalara böldüğümde, nasıl test ettiğimde ve ne öğrendiğimde olması.