Auslesen von OBD Daten
Jetzt, da wir den CAN Controller eingerichtet haben möchten wir unser Programm auch testen. Gut geeignet ist dazu die On Board Diagnose (OBD) von einem Fahrzeug weil dazu die notwendigen CAN Frames und die Decodierungsbeschreibung der empfangenen Antwort öffentlich zugänglich ist (zumindest der Teil, der gesetzlich vorgeschrieben ist). Auch haben wir über die Diagnosesteckdose im Fahrerfußraum einen einfachen Zugang zu einem CAN.
OBD Anfrage über den CAN senden
Die CAN Botschaften in Zusammenhang mit OBD werden in einem Anfrage - Antwort Verfahren ausgetauscht. Auf dem OBD CAN ist zunächst keine CAN Kommunikation. Erst wenn wir eine Anfrage stellen bekommen wir kurz darauf die entsprechende Antwort.
Eine OBD Anfrage wird immer mit der SID 0x7DF gesendet und ist immer 8 Datenbyte lang (DLC = 8). Die 8 Byte Payload sind folgendermaßen aufgeteilt:
D6 legt den OBD Service fest. In unserem Fall ist dies der Service '1' (Anzeige aktueller Werte). Andere Services wären zum Beispiel 'Fehlerspeicher auslesen', 'Fehlerspeicher löschen', usw. (Suchbegriff: OBD2 Services).
In D5 wird dann ausgewählt was man angezeigt bekommen möchte. 0x0C ist die Motordrehzahl (Suchbegriff: OBD2 PID). D4 bis D0 werden nicht benötigt. Hier werden Füllwerte geschrieben.
In D7 muss noch angegeben werden wie viele OBD relevante Byte in dem Payload enthalten sind. Bei uns sind das zwei. Das Service Byte in D6 und das PID Byte mit der Motordrehzahl in D5.
OBD Antwort über den CAN empfangen
Abhängig vom Steuergerät wird die Antwort mit einer CAN SID zwischen 0x7D8 und 0x7DF gesendet. Auch hier werden wie immer bei OBD 8 Byte gesendet. Wie viele davon tatsächlich relevant sind sieht man am ersten Byte D7. Im Beispiel sind es 4 (D6-D3).
0x41 in D6 bedeutet das dies die Antwort auf den Service 0x01 ist. Zur Abgrenzung zu einer Anfrage wird die Antwort immer um 40 erhöht. 0x0C bedeutet die Antwort zum PID 0x0C, also die Motordrehzahl. In D5 und D4 sind dann die Werte für die Drehzahl. Wie diese codiert werden kann man den Tabellen der PID entnehmen.
Programmcode zum Auslesen der Motordrehzahl
/* Ansteuerung des CAN Moduls über die Arduino SPI Schnittstelle
* Arduino Mega: MISO(=SO) = 50 | MOSI(=SI) = 51 | SCK = 52 |
* Arduino Uno: MISO(=SO) = 12 | MOSI(=SI) = 11 | SCK = 13 |
* VCC = 5V | GND = GND */
#include "Klasse_MCP2515.h" // Einbinden der Datei mit der erstellten Klasse 'MCP2515'
MCP2515 CAN(5); // Instanz 'CAN' der Klasse 'MCP2515' erstellen (CS Pin)
void setup() {
Serial.begin(115200);
CAN.resetController();
CAN.setBaudrate(500);
CAN.setSID(0, 0x7DF);
CAN.setPayload(0, 0x02, 0x01, 0x0C, 0x55, 0x55, 0x55, 0x55, 0x55);
CAN.setDLC(0, 8);
CAN.sendTXbuffer(0);
}
void loop() {
// Abfragen ob eine neue CAN Botschaft im Empfangsspeicher ist
if(CAN.loadRXbuffer(0) == true) {
Serial.print("SID: ");
Serial.println(CAN.getID(0), HEX);
Payload PL = CAN.getPayload(0);
Serial.print(PL.anzahlBytes); // 0= Remote Frame (1-8 = Anzahl empfangene Datenbytes)
Serial.print(" Byte: ");
Serial.print(PL.D0, HEX); Serial.print(" ");
Serial.print(PL.D1, HEX); Serial.print(" ");
Serial.print(PL.D2, HEX); Serial.print(" ");
Serial.print(PL.D3, HEX); Serial.print(" ");
Serial.print(PL.D4, HEX); Serial.print(" ");
Serial.print(PL.D5, HEX); Serial.print(" ");
Serial.print(PL.D6, HEX); Serial.print(" ");
Serial.print(PL.D7, HEX); Serial.println(" ");
// Decodieren der Motordrehzahl nach PID Tabelle
Serial.print("Motordrehzahl: ");
unsigned int rpm = (PL.D3 << 8 | PL.D4) * 0.25;
Serial.print(rpm);
Serial.println(" 1/ min");
}
}