
Der CAN-Bus selbst wird schon viel benutzt, wo ich mich für den Einsatz im Auto interessiere, obwohl dieser Bereich nicht eingeschränkt werden kann. Vor allem vor ein paar Jahren hat sich diese Gelegenheit ergeben. Ich habe mir die allgemeinen Spezifikationen angesehen - es scheint nichts besonders Kompliziertes zu geben. Ich habe mir die Programme angesehen, die im Internet zu finden sind - und ich mochte keine, jedem fehlte etwas, das mir zu dieser Zeit notwendig erschien. Ich werde mein Fahrrad neu erfinden. Ich lasse meinen CAN-Sniffer unter dem Schnitt weiter schnüffeln.
CAN-Bus
Eine detaillierte Beschreibung der technischen Details des CAN-Busses ist Teil der Dokumentation. In diesem Artikel ist es genug zu wissen, dass es:
- hat eine zweiadrige physikalische Verbindung
- es gibt verschiedene datenraten
- Zum Anschluss stehen bereits vorgefertigte Chips und sogar vorgefertigte Platinen mit Lötteilen zur Verfügung
Nachdem ich die Seiten eines berühmten Online-Shops aus dem Reich der Mitte durchgeblättert hatte, bestellte ich verschiedene Optionen für Schutzschilde und studierte die Eigenschaften von elektrischen Signalen in einem Auto. Das Versuchsauto war der LADA Kalina Cross mit dem 127. Motor und einem elektronischen Steuergerät ITELMA M74.5 CAN.
Ich verbinde mich mit dem OBD-Diagnosestecker (Stifte 6 und 14) und schaue auf das Oszilloskop, das dort ist. Nach dem Drehen des Zündschlüssels beginnen Pakete mit einer Amplitude von bis zu 2,5 V. Ich mache eine Pause auf dem Oszilloskop und schaue mir das Paket an.
Start- und Stoppbits sind erkennbar, einige Daten im Paket. Zu diesem Zeitpunkt wusste ich bereits, dass die Datenübertragungsrate 500 kbit / s betragen sollte, was für den Motor-CAN-Bus am häufigsten der Fall ist. Die Paketdauer beträgt ca. 230 μs und vor dem Paket liegt eine recht große Pause in der Datenübertragung vor. Ich skaliere die Zeit und sehe drei Pakete und pausiere zwischen ihnen.
Wenn wir die Dauer der Datenübertragung und die Pause zwischen Paketen addieren, stellt sich heraus, dass die Übertragung eines Datenstücks ungefähr 1 ms dauert.
Warum ziehe ich das alles ab? Und die Frage ist rein praktisch: Reicht die Geschwindigkeit der seriellen Schnittstelle aus, um alle Daten zu übertragen? Und basierend auf dem, was wir gesehen haben, können wir schließen, dass sich die Geschwindigkeit von 500 kbit / s innerhalb des Pakets entwickelt, was ungefähr ein Viertel der Übertragungszeit beansprucht. Die durchschnittliche Übertragungsrate wird also viermal niedriger sein. Zu diesem Zeitpunkt hatte ich noch keine Geschwindigkeitstests für die serielle Schnittstelle von Arduino und mit Blick auf die Zukunft kann ich sagen, dass selbst mit dem gebräuchlichsten Seriell-zu-USB-CH340-Konverter eine Geschwindigkeit von 2 Mbit / s stabil funktioniert.
CAN-Scanner auf Arduino
Der erste angekommene Schild für den klassischen Arduino UNO. Ja, es kostet deutlich mehr als seine kleineren Gegenstücke, aber es hat alles an Bord, was Sie brauchen, und sogar zwei Knöpfe.
Mit ihm habe ich alle Experimente begonnen. Mit dieser Abschirmung und einem zweizeiligen Flüssigkristallschirm wurde eine einfache Schaltung zusammengebaut. Ziel war es, zumindest einige Daten auf dem Bildschirm anzuzeigen. Ich habe verschiedene Bibliotheken für die Arbeit mit dem CAN-Bus auf Arduino sortiert (ich sage gleich, dass die richtige und funktionierende Bibliothek von Seeed Studio mit der Header-Datei mcp_can.h CAN-BUS Shield heißt), den Quarzresonator auf dem 16-MHz-Shield geändert (ursprünglich waren es 8 MHz) - Es gab keine Daten.
Auf dem Schild sind zwei Mikrokreise installiert: der CAN-Bus-Controller MCP2515 und der CAN-Bus-Treiber TJA1050. Nachdem ich die Dokumentation und verschiedene Foren gelesen hatte, entschied ich mich, den TJA1050 auf einen kanonischeren Treiber MCP2551 umzustellen, und die Daten erschienen. Vielleicht war der TJA1050 anfangs defekt, da es sehr schwierig war, einen Fehler beim Anschließen mit zwei Drähten zu machen. Außerdem verwendete ich OBD- und DB9-Steckverbinder für den Anschluss.
Innerhalb weniger Stunden wurde ein einfacher CAN-Scanner geschrieben, der die Nummer des erfassten Pakets, seine ID und bis zu 8 Datenbytes für dieses Paket auf dem LCD anzeigt.
Hier haben sich die Knöpfe am Schild als nützlich erwiesen, mit denen ich zwischen der Nummer des angezeigten Pakets gewechselt habe.
Über SchaltflächenIm Allgemeinen haben sich diese Tasten dann für viele Dinge als nützlich erwiesen. Mit ihnen fing ich an, die Steuerung einiger Geräte des Autos zu testen.
Der Anfang war gelegt, wir müssen zu einer interessanteren Implementierung übergehen.
KANN auf Arduino schnüffeln
Die Aufgabe war ganz einfach:
- Paket vom CAN-Bus annehmen
- Die empfangenen Daten geben wir in unsere Struktur ein
- Struktur über serielle Schnittstelle senden
Bei den ersten beiden Aufgaben habe ich keine Probleme gesehen. Die Bibliothek bot eine Unterbrechung beim Empfang des nächsten Datenpakets und praktische Funktionen zum Empfangen von Daten. Ich entschied mich jedoch, Daten über die CyberLib-Bibliothek an den Computer zu senden, wodurch ein Teil des Overheads der gesamten Arduino-Plattform entfällt und Sie den Prozessor leicht entlasten können, um die Daten zu verarbeiten. Später musste diese Bibliothek aufgegeben werden.
Damit die zu sendenden Daten auf der Computerseite korrekt verarbeitet werden, wird vor jedem nächsten Datenelement ein Präfix von vier Bytes 0xAA55AA55 in den Stream eingefügt (aus irgendeinem Grund wurden diese Bytes für die letzten zwei Bytes des DOS-Bootsektors gespeichert, nur in einer anderen Reihenfolge). Die Logik ist folgende:
- Der Computer liest den gesamten Stream von der seriellen Schnittstelle und findet die gewünschte Präfixsequenz 0xAA55AA55 darin
- Unmittelbar nach dem Präfix befinden sich 4 Bytes der Paketkennung
- Über die Datenlänge dieses Pakets wird die Länge des gesamten Pakets gesteuert
- Bis zu 8 Datenbytes
Damit war der damalige Software-Teil in Arduino abgeschlossen. Später wurde es erheblich überarbeitet, aber das allgemeine Konzept hat sich nicht geändert.
Ich habe auch einen einfachen Generator für Datenpakete zum Debuggen geschrieben, der zu Hause debuggt. Er sendet einfach Pakete mit zufälligen Daten an die serielle Schnittstelle, sodass Sie die Anwendung auf Ihrem Computer unter komfortablen Bedingungen debuggen können.
Etwa zur gleichen Zeit kamen die kleineren Komponenten des Arduino Nano- und Mini-CAN-Shields an.
Ich entwarf einen kleinen Koffer, druckte ihn aus und legte alle Komponenten hinein.
Draußen befindet sich auf der einen Seite ein OBD-Anschluss und auf der anderen Seite ein Mini-USB-Anschluss. Im Inneren befindet sich ein Schalter für einen Abschlusswiderstand.
CAN-Sniffer am PC mit wxWidgets
Ich skizzierte einen einfachen Entwurf eines Programms in C #, das die empfangenen Daten im Raster anzeigt. Und er ging, um das Auto einzuchecken. Ich bin einfach nicht mit meinem Laptop gefahren, da mir sein Akku lange Zeit das Leben gekostet hatte und als stationärer Computer verwendet wurde, aber ich habe ein Netbook mit einem sehr schwachen Prozessor mitgenommen. Was ich gesehen habe ... Ich habe nichts gesehen. Beide Kerne sind zu 100% geladen, die Anwendungsschnittstelle reagiert nicht. Aber auf meinem Computer, der immer noch viel schneller als ein Netbook ist, funktionierte die Anwendung mit dem Zufallspaketgenerator einwandfrei und zeigte Daten an. Daraus folgerte ich, dass die .NET-Plattform auf schwachen Computern für mich nicht funktionieren würde, da ich zu diesem Zeitpunkt im Feld nur mit diesem Netbook debuggen konnte.
Früher habe ich die wxWidgets-Bibliothek in mehreren Projekten verwendet und habe nur eine angenehme Erfahrung damit. Es ist leichtgewichtig, es müssen keine verschiedenen Bibliotheken und sogar plattformübergreifend mitgeführt werden, was die Hoffnung weckt, dass der Schnittstellenteil des Codes ohne wesentliche Änderungen auf andere Plattformen übertragen werden kann. Am Ende des Artikels finden Sie einen Link zum kompilierten Programm, falls Sie sich nicht darum kümmern möchten.
So installieren und kompilieren Sie wxWidgets für Visual StudioInstallation und Kompilierung1. Laden Sie Windows Installer
wxWidgets herunter und installieren Sie es beispielsweise im Ordner C: \ wxWidgets
2. Erstellen Sie eine Umgebungsvariable:
WXWIN = C: \ wxWidgets
3. Führen Sie die Visual Studio-Eingabeaufforderung aus und wechseln Sie in das Verzeichnis:
% WXWIN% \ build \ msw
4. Geben Sie zwei zu kompilierende Befehle ein:
nmake / f makefile.vc BUILD = Debuggen von RUNTIME_LIBS = statisch
nmake / f makefile.vc BUILD = RUNTIME_LIBS = static freigeben
Einrichten eines Projekts in Visual Studio1. Erstellen Sie in Visual Studio ein Win32-Projekt mit dem Parameter Leeres Projekt.
2. Geben Sie in den Projekteigenschaften für die Konfiguration Alle die Pfade im Abschnitt VC ++ - Verzeichnisse an:
Verzeichnisse einschließen:
$ (WXWIN) \ include
$ (WXWIN) \ include \ msvc
Bibliotheksverzeichnisse:
$ (WXWIN) \ lib \ vc_lib
3. Ändern Sie im Abschnitt C / C ++ - Codegenerierung Folgendes:
Laufzeitbibliothek für Debug: / MTd-Konfiguration
Laufzeitbibliothek zur Konfiguration von Release: / MT
4. Ändern Sie im Abschnitt Allgemein Folgendes:
Zeichensatz: Verwenden Sie den Unicode-Zeichensatz
5. Um einer exe-Datei ein Symbol hinzuzufügen, müssen Sie eine Ressourcendatei mit folgendem Inhalt hinzufügen:
#include "wx \ msw \ wx.rc"
wxicon icon app_icon.ico
6. Wenn Sie zusätzlich die Benutzerkontensteuerung verwenden müssen, gehen Sie im Abschnitt Linker - Manifestdatei wie folgt vor:
UAC-Ausführungsebene: Administrator erforderlich
Der erste in C ++ und wxWidgets implementierte Prototyp zeigte, dass sogar ein Netbook mit der Anzeige von Daten in einer Tabelle fertig wird, und ich begann, das zu entwickeln, was ich geplant hatte.
Architektonisch besteht das Programm aus zwei Streams: Schnittstelle und Workflow mit einer seriellen Schnittstelle. Es wurden keine unglaublich interessanten Algorithmen angewendet. Der Code ist reichlich kommentiert und sollte ziemlich einfach sein. Ein Link zur Quelle befindet sich am Ende des Artikels.
Als Erstes wurden die Datenzellen in der Tabelle entsprechend der Beschränkung zum Abrufen dieser Daten eingefärbt. Schon im ersten Prototypen, der 17 Datenzeilen mit sich ständig ändernden Werten betrachtete, wurde mir klar, dass es notwendig ist, zwischen frischen Daten und Daten zu unterscheiden, die sich nicht oder nur selten ändern. Er machte eine Färbung in zwei Schritten:
- Erstdaten werden im Hintergrund der grünen Zelle hervorgehoben
- Daten, die wiederholt und weiter ankommen, werden mit einem roten Hintergrund hervorgehoben, der allmählich in Weiß übergeht, wenn sich diese Daten nicht mehr ändern
Sofort wurde klar, welche Zellen überhaupt nicht verwendet wurden, welche die Zählersignale enthielten. Die Suche nach Variablenwerten von Interesse wird stark vereinfacht. Im Folgenden werden alle Bilder animiert. Wenn die Animation im Artikel nicht funktioniert (in einigen mobilen Browsern) - klicken Sie auf das Bild, um die Vollversion der Animation zu öffnen.

Dann wollte ich noch prüfen, ob die serielle Schnittstelle mit dem Datenstrom zurechtkommt. Zu diesem Zweck habe ich auf der Arduino-Seite Zähler für die Anzahl der empfangenen Pakete und einen Byte-Zähler im Paket hinzugefügt. Diese Zähler werden in einem Paket mit der Kennung 0x000 an den Computer gesendet. Nach Erhalt dieser Daten zeigt das Programm diese nicht in einer Tabelle an, sondern in separaten Informationsfeldern oben. Die Ergebnisse waren sogar recht angenehm. Im Durchschnitt werden bis zu 750 Pakete / s mit einer Geschwindigkeit von bis zu 9,5 kBit / s empfangen, und dies ist in der Region mit bis zu 80 kBit / s der Fall, was für eine serielle Schnittstelle durchaus möglich ist. Trotzdem ist der Datenaustausch standardmäßig auf 500 kbit / s konfiguriert.
Das Hinzufügen der Fähigkeit, Daten in das Protokoll zu schreiben, erschien, nachdem ich den ELM327-Diagnoseadapter parallel zur OBD-Schnittstelle angeschlossen und mit dem Telefon verbunden hatte, und versuchte, verschiedene Daten zu lesen. Die Daten liefen so schnell, dass es unmöglich war, sie zu sehen. Nachdem Sie dies alles in einem Tagebuch festgehalten haben, können Sie sich ruhig hinsetzen und die übertragenen Daten sehen. Dazu können sogar ASCII-Textdaten in das Protokoll geschrieben werden. Sie können auch den Dateityp und das Begrenzungszeichen auswählen und den Paketfilter konfigurieren, indem Sie auf die angegebene Paketkennung in der Tabelle klicken und auf die Schaltfläche "ID zum Filter hinzufügen" klicken (standardmäßig werden alle Daten geschrieben), wenn alle Daten redundant geschrieben werden.
Zu diesem Zeitpunkt stellte sich heraus, dass alle Telefonanwendungen, die über das ELM327-Paket und das Telefon alle Arten von „Diagnosen“ durchführen, nicht direkt mit dem CAN-Bus des Fahrzeugs kommunizieren. Sie nutzen lediglich die OBD-Diagnosefunktionalität über den CAN-Bus, indem sie auf die CAN-ID 0x7E0 zugreifen. In der Regel ist dies die Adresse des Motorcontrollers (ECU), die Antwort kommt in einem Paket mit der Kennung 0x7E8. Alle anderen Datenpakete sind jedoch herstellerspezifisch und werden von keinem Hersteller einfach geöffnet (obwohl es ein Beispiel gibt:
Ford hat ein SDK für seine Autos veröffentlicht ).
Als ich weiter untersuchte, was in diesen Paketen übertragen wird, kam mir eine andere Idee: Wenn ich auf eine Zelle in der Tabelle rechts im Programmfenster klicke, zeige ich den Binär- und Dezimalwert dieses Bytes an und nehme das nächste Byte und füge es zum Wort hinzu. Als nächstes multiplizieren Sie dieses Wort mit einem bestimmten Koeffizienten und erhalten ein Dezimalergebnis. Es klingt nicht sehr klar, aber in Verbindung mit dem, was es getan hat: Die Motordrehzahl wird in CAN-ID 0x180-Paketen in den ersten beiden Bytes angegeben. Diese zwei Bytes ergeben ein bestimmtes Wort, das proportional zu den Umdrehungen ist. Wenn die Bedeutung dieses Wortes durch 8 geteilt wird, erhält man den aktuellen Impuls. Daher wird ein Faktor von 0,125 als Kehrwert von 8 angegeben. Anschließend wird dieses Wort in einem Diagramm mit dynamischer Anpassung der Amplitude dargestellt. Im Prinzip kann der Multiplikator in umgekehrter Reihenfolge durchsucht werden: Ich habe Zellen gefunden, die der Motordrehzahl sehr ähnlich sind, oder etwas anderes gemäß dem Zeitplan, wonach der Multiplikator angepasst wird, um reale Werte zu erhalten.

Nun, die binäre Darstellung ermöglicht es Ihnen, nach verschiedenen Bit-Indikatoren zu suchen. Beispielsweise reduziert sich die Suche nach Fahrtrichtungsanzeigern darauf, diese einzuschalten und zu beobachten, welche Zelle sich zu ändern beginnt. Im folgenden Beispiel ist dies CAN ID 0x481 Byte 2. Danach zeigt ein Klick auf die Zelle ihren Binärwert im entsprechenden Feld an, in dem die beiden umschaltenden unteren bereits sichtbar sind Bits (links, rechts und wenn zusammen - ein Alarm).

Und schließlich musste ich einige Steuerdaten auf den CAN-Bus senden und die Reaktion auf diese Befehle sehen. Dem Arduino-Programm wurde ein Code hinzugefügt, der Daten vom Computer empfängt und auf den CAN-Bus überträgt. Zu diesem Zeitpunkt musste CyberLib abgebrochen werden, da es keine Unterstützung für die Unterbrechung des Datenempfangs im Puffer der seriellen Schnittstelle gab. Im Programm auf dem Computer habe ich mehrere Textfelder hinzugefügt, in die Sie verschiedene Parameter und eine Tabelle eingeben können, um die Reaktion des Stellantriebs anzuzeigen. Das folgende Beispiel zeigt die Steuerbefehle zum Aktivieren / Deaktivieren der ersten Drehzahl des Kühlgebläses (0x0A) und zum Aktivieren / Deaktivieren der Kupplung der Klimaanlage (0x0B).

Zusammenfassung
Eine vollständige Entschlüsselung der Herstellerdaten, insbesondere der offiziellen, ist praktisch nirgendwo zu finden. Im besten Fall handelt es sich um fremde Forschungsarbeiten im Rahmen der Implementierung einiger Zusatzfunktionen. Mit dem CAN-Sniffer können Sie diese Daten leichter finden. Ich konnte ungefähr 40 verschiedene Parameter des Autos finden und aus Versuchsgründen habe ich auf der Grundlage der erhaltenen Daten meine eigene Steuerung des Kühlgebläses vorgenommen.
Ich hoffe, dass all dies nicht nur für mich von Nutzen ist.