<

CAN-Bus'tan Anlam Çıkarmak: Araç Verisinin Ham Hâli

2019 Şubat'ında bir lojistik müşterimiz sabah sekizde aradı: "Sisteminiz araçlarımın depolarını gece boşaltıyor." Panele baktık; adamın çekicilerinden birinde yakıt seviyesi gece 02:10'da yüzde 68'den yüzde 12'ye düşüyor, sabah 06:40'ta kendi kendine yüzde 65'e çıkıyordu. Yakıt hırsızlığı alarmı üç gecede dört kez çalmış, müşteri park sahasına gece bekçisi koymayı konuşuyordu. Kamera kayıtlarını izledik: araca gece boyunca kimse yaklaşmamıştı bile.

Hırsız yoktu. Ama veri de yalan söylemiyordu. Yalan söyleyen, bizim o veriyi okuma biçimimizdi.

Aracın İçinde Konuşan Kalabalık

CAN-Bus'ı ilk kez ciddi ciddi kurcalamaya başladığımda beni en çok şaşırtan şey şu oldu: araç içi ağda kimse kimseye "soru" sormuyor. Motor beyni, ABS, şanzıman, gösterge paneli — hepsi kendi bildiği değerleri sürekli olarak hatta bağırıyor. Saniyede yüzlerce frame, her biri en fazla 8 bayt veri taşıyor ve üzerinde alıcı adresi yok; sadece bir kimlik (ID) var. 11 bitlik standart ID'ler binek araçlarda, 29 bitlik genişletilmiş ID'ler ağır vasıtalarda karşımıza çıkıyor. Dinleyen herkes her şeyi duyuyor; işine yarayanı alıyor, gerisini çöpe atıyor.

Bizim telematik cihazımız da bu kalabalığın içinde sessiz bir dinleyici. Sorun şu ki duyduğu şeyin ne anlama geldiğini bilmek zorunda. 0x18FEFC17 ID'li bir frame'in ikinci baytının yakıt seviyesi olduğunu, değerin 0,4 ile çarpılıp yüzde cinsinden okunacağını bir yerden öğrenmesi gerekiyor. Üretici size DBC dosyası (sinyallerin haritası) verdiyse şanslısınız. Vermediyse — ki Türkiye'de çalıştığımız karma filolarda çoğunlukla vermiyordu — elinizde bir bayt yığını ve bolca sabır kalıyor.

OBD-II'nin Nazik ama Dar Kapısı

"OBD soketinden okuyun, standart zaten" diyen çok oldu. Kısmen haklılar. OBD-II gerçekten standart: 0x7DF ID'sine bir istek atıyorsunuz, ECU 0x7E8'den cevap veriyor. PID 0x0C motor devri, 0x0D araç hızı, 0x05 soğutma suyu sıcaklığı. Formüller bile belli; sıcaklık için cevaptaki bayttan 40 çıkarıyorsunuz, devir için ((A*256)+B)/4 hesaplıyorsunuz.

Ama OBD-II bir emisyon teşhis standardı, filo yönetim standardı değil. Kilometre sayacı OBD'de yok. Yakıt seviyesi (PID 0x2F) teoride var ama denediğimiz 2010-2016 model araçların kabaca yarısı bu PID'i desteklemiyordu. Debriyaj, retarder, aks yükü, çalışma saati gibi filo için kritik veriler OBD kapısından hiç geçmiyor. Ağır vasıtada işi J1939 ve onun üstüne oturan FMS standardı kurtarıyor; FMS gateway'i olan bir çekiciden kilometreyi, toplam yakıt tüketimini, pedal pozisyonunu düzgün alabiliyorsunuz. FMS'i olmayan araçta ise ham CAN'e inmek zorundasınız.

candump ile Geçen Geceler

Ham CAN'de sinyal keşfi kelimenin tam anlamıyla arkeoloji. Yöntemimiz şuydu: aracı sahaya çekiyoruz, cihazın debug modunda tüm trafiği dosyaya yazdırıyoruz (Linux tarafında candump'ın yaptığı işin gömülü hali), sonra araçta tek bir şeyi değiştirip kaydı tekrarlıyoruz. Kapıyı aç, kaydet. Kapat, kaydet. İki dökümün diff'inde değişen baytlar sizin kapı sinyaliniz. Gaza yüzde 20 bas, yüzde 40 bas; hangi bayt orantılı büyüyorsa pedal pozisyonu o.

Bu arada bayt sırası da ayrı bir tuzak. Aynı 16 bitlik sinyal bir üreticide Intel (küçük bayt önce), diğerinde Motorola (büyük bayt önce) düzeninde geliyor. Devir sinyalini yanlış sırayla okuduğumuz bir modelde motor rölantide 24.000 devirde görünüyordu; neyse ki bu kadar absürt değerler kendini hemen ele veriyor. Asıl sinsileri, iki düzende de "makul" görünen değerler. Hız sinyalini ters okuyup 90 km/s yerine 35 km/s gösterdiğimiz bir haftayı, müşteri "şoförlerim bu kadar yavaş gidemez" diye arayana kadar fark etmemiştik.

Kulağa basit geliyor ama bir binek araçta saniyede 700-800 frame akarken, 60 saniyelik iki kaydın farkını almak size yüzlerce "değişen" bayt gösteriyor. Sayaçlar var, checksum baytları var, sürekli titreyen sensörler var. Biz zamanla şöyle bir eleme geliştirdik: önce her ID için baytların varyansını çıkar, deney sırasında varyansı sıçrayanları aday listesine al, sonra adayları fiziksel olayla korelasyona sok. Bir aracın yakıt sinyalini bu yöntemle bulmak ortalama yarım günümüzü alıyordu. (En hızlı rekorumuz 40 dakika, en kötüsü üç gündü — o araçta sinyal multiplexed çıktı, birazdan geleceğim.)

Bir de ölçekleme tuzağı var. Sinyali buldunuz diyelim; ham değer 0-255 arası. Bu yüzde mi, litre mi, litrenin dörtte biri mi? Depoyu fişe kadar doldurup değeri okuyor, yarıya indirip tekrar okuyorduk. Bir modelde deponun "dolu" değerinin 255 değil 247 olduğunu, üstünün hiç kullanılmadığını görmüştük. Kalibrasyonu tabloya gömdük; o araç ailesi için yüzde hesabını 247 üzerinden yaptık. Bu tür tablo bilgisi hiçbir dokümanda yok, sadece yaşayarak öğreniliyor.

Gece 02:10'da Depoyu Boşaltan Frame

Gelelim baştaki hırsıza. O çekicide yakıt sinyalini aylar önce ters mühendislikle bulmuş, belirli bir ID'nin belirli baytına bağlamıştık. Gece kayıtlarını cihazın ham log'undan çektiğimizde tuhaflık ortaya çıktı: 02:10'da aynı ID'den gelen frame'lerin ilk baytı değişiyordu. Meğer o frame multiplexed'miş — ilk bayt bir "sayfa numarası", kalan yedi baytın anlamı bu sayfaya göre değişiyor. Gündüz hep sayfa 0'ı görüyorduk; yakıt oradaydı. Gece 02:10'da devreye giren bağımsız yakıtlı ısıtıcı (şoför soğuk sabahlar için programlamış) aynı ID'de sayfa 2 yayınlamaya başlıyor, bizim kod sayfa ayrımı yapmadığı için ısıtıcının kendi küçük deposunun değerini ana depo sanıyordu. Isıtıcı 06:40'ta susunca "yakıt" da yerine geliyordu.

Düzeltme iki satırdı: mux baytını kontrol et, sayfa 0 değilse frame'i atla. Asıl kazanım ise süreçti — o günden sonra her sinyal tanımına "mux var mı?" sorusunu zorunlu alan olarak ekledik ve alarm motoruna şu kuralı koyduk: yakıt seviyesi 10 dakikadan kısa sürede yüzde 30'dan fazla düşüp sonra kendiliğinden yükseliyorsa bu hırsızlık değil, veri hatasıdır; alarmı bastırıp mühendislik kuyruğuna düşür. Yanlış alarm oranımız o çeyrekte yüzde 4,1'den yüzde 0,6'ya indi.

Sinyal tanımlarını da kod içinden söküp veritabanına taşıdık. Marka, model, yıl ve şasi aralığına göre eşleşen bir "sinyal sözlüğü" tablomuz var artık; ID, başlangıç biti, uzunluk, çarpan, ofset, bayt sırası ve varsa mux sayfası tek satırda duruyor. Yeni bir araç tipi geldiğinde firmware güncellemesi değil, tabloya satır eklemek yetiyor. 2019 sonunda bu sözlükte 60'tan fazla araç ailesi ve 400'ü aşkın sinyal tanımı birikmişti; muhtemelen şirketin en değerli ama bilançoda görünmeyen varlığı buydu.

Bu işin bana öğrettiği en kalıcı ders şu: telematikte veri kalitesi cihazda değil, yorum katmanında kazanılıyor ya da kaybediliyor. Aynı cihaz, aynı araç, aynı bus; fark sadece bir baytı okuyup okumamak. Müşteriye giden her sayının altında böyle onlarca küçük karar var ve bunların hiçbiri broşürlerde yazmıyor. Filonuzdan gelen verinin tuhaf davrandığını düşünüyorsanız — gece buharlaşan yakıt, geri giden kilometre sayacı, eksi 40 dereceye düşen motor — bize yazın; muhtemelen benzerini görmüşüzdür.

Bir sonraki yazıda işin başka bir çilesini anlatacağım: GPS'in kendisi de yalan söylüyor ve onu terbiye etmenin adı Kalman filtresi.

📅 Yayınlanma:  ·  Yakup Zengin