Forum: Mikrocontroller und Digitale Elektronik Can Bus Daten auslesen


von CanBusShield (Gast)


Lesenswert?

Hallo zusammen,

möchte gerne mit Hilfe eines Arduino Mega 2560 und einem
Seedstudio Can Bus Shield die Motordrehzahl von einem Golf 7 über den 
serial Monitor anzeigen lassen. Ein passender OBD Stecker ist auch 
vorhanden.

Mit welcher passenden library kann ich diesen Wert auslesen?
Und wo und wie setze ich die ID ein?
Habe mir über eine Software den dazugehörigen Identifier aus dem 
Motorsteuergerät gezogen der angesrochen werden soll.

z.B Engine RPM $F40C

Wie kann ich das jetzt alles in einem Programm unterbringen das der HEX 
Wert ausgelesen wird und mir über den serial Monitor angezeigt wird.

Die vorhandenen Beispielprogramme haben mir bisher leider nicht 
geholfen, weil immer wieder irgendwelche Fehler auftreten beim 
programmieren.

Vielen Dank im Voraus und hoffe auf zahlreiche antworten die mir 
weiterhelfen

von Prof (Gast)


Lesenswert?

Eine Library wird's wohl nicht geben. Nimm einen STN1110 und überlaß dem 
das Protokoll. Dann kannst Du alle OBD II Werte einfach per UART 
abfragen.
Oder kauf ein Buch und schreibe Deine eigene Library. 
http://www.buch.de/shop/home/mehrvonartikel/obd/florian_schaeffer/ISBN3-645-65156-X/ID33048317.html?fftrk=2%3Anull%3A10%3A10%3A1&jumpId=28632473

von npn (Gast)


Lesenswert?

CanBusShield schrieb:
> irgendwelche Fehler auftreten

Das hilft uns weiter beim Beantworten deiner Frage. ;-)

von Thomas (Gast)


Lesenswert?

Eine Library gibts hier: https://code.google.com/p/mechanic/
Einen Artikel aus der c't hacks gibts hier: 
https://www.heise.de/artikel-archiv/ch/2013/02/054_Fahrzeugdiagnose-mit-Arduino

Und ein Beispiel gibts hier:
1
#define          myversion                        "V 0.0.10"
2
3
#define          LCDCOLS                          16
4
#define          LCDROWS                          2
5
#define          lcdinitsequence                      LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
6
7
/* TC, 05.02.2014:
8
  Hardware: 
9
  1x Arduino Uno
10
  1x CAN-BUS Shield von Seedstudio
11
  1x LCD-Display von Sainsmart mit Buttons die am Analog PIN A0 liegen
12
  1x Opel Astra H
13
  
14
  Der Opel Astra H unterstuetzt folgende PIDs:
15
  0x00  PIDs supported [01 - 20]
16
  0x01  Monitor status since DTCs cleared
17
  0x04  Calculated engine load value
18
  0x05  Engine coolant temperature
19
  0x0B  Intake manifold absolute pressure
20
  0x0C  Engine RPM
21
  0x0D  Vehicle speed
22
  0x0F  Intake air temperature
23
  0x10  MAF air flow rate
24
  0x1C  OBD standards this vehicle conforms to
25
  0x20  PIDs supported [21 - 40]
26
  0x21  Distance traveled with malfunction indicator lamp (MIL) on
27
  0x23  Fuel Rail Pressure (diesel, or gasoline direct inject)
28
  0x2C  Commanded EGR
29
  0x33  Barometric pressure
30
  0x40  PIDs supported [41 - 60]
31
  0x41  Monitor status this drive cycle
32
  0x42  Control module voltage
33
  0x49  Accelerator pedal position D
34
  0x4A  Accelerator pedal position E
35
*/
36
37
#include <Mechanic.h>
38
#include <SoftwareSerial.h>
39
#include <LiquidCrystal.h>
40
41
// LCD Instanziierung
42
lcdinitsequence
43
44
ObdInterface obd;
45
ObdMessage msg;
46
47
void setup() 
48
{
49
  // Serielle Schnittstelle fuer Debug-Output aktivieren
50
  Serial.begin(115200);
51
  while (!Serial);
52
  
53
  Serial.println("System started.");
54
  
55
  // LCD-Display initialisieren
56
  delay(2000);                                // Noetig da sonst init des Displays nicht klappt (Spannunsproblem?)
57
  lcd.begin(LCDCOLS, LCDROWS);                        // LCD mit LCDCOLS Spalten, LCDROWS Zeilen
58
  lcd.setBacklightPin(3, POSITIVE);
59
  lcd.setCursor(LCDCOLS - strlen(myversion), 0);
60
  lcd.print(myversion);  
61
  lcd.setCursor(0, 1);
62
  lcd.print("init...");
63
  delay(1000);
64
65
  obd.setSlow(false);
66
  obd.setExtended(false);
67
  obd.setDebug(true);
68
  obd.begin();                                // Gibt es einen HARDWARE-Fehler bleiben wir hier haengen
69
  lcd.clear();
70
}
71
72
void loop() 
73
{
74
  char buffer[16];
75
  
76
  // Links oben, Temperatur angesaugte Luft
77
  obd.getPidAsString(0x0F, -40.0f, 215.0f, "%d", buffer);
78
  lcd.setCursor(0, 0);
79
  lcd.print("      ");
80
  lcd.write(0xDF);                               // Grad-Zeichen
81
  lcd.print("C");
82
  lcd.setCursor(0, 0);
83
  lcd.print(buffer);
84
  
85
  // Rechts oben: Temperatur Kuehlfluessigkeit
86
  obd.getPidAsString(0x05, -40.0f, 215.0f, "%d", buffer);
87
  lcd.setCursor(8, 0);
88
  lcd.print("      ");
89
  lcd.write(0xDF);                               // Grad-Zeichen
90
  lcd.print("C");
91
  lcd.setCursor(8, 0);
92
  lcd.print(buffer);
93
  
94
  // Links unten: Umdrehungsgeschwindigkeit Motor
95
  obd.getPidAsString(0x0C, 0.0f, 16383.75f, "%d", buffer);
96
  lcd.setCursor(0, 1);
97
  lcd.print("     rpm");
98
  lcd.setCursor(0, 1);
99
  lcd.print(buffer);
100
  
101
  // Rechts unten: Aktuelle Geschwindigkeit in km/h
102
  obd.getPidAsString(0x0D, 0.0f, 255.0f, "%d", buffer);
103
  lcd.setCursor(8, 1);
104
  lcd.print("    km/h");
105
  lcd.setCursor(8, 1);
106
  lcd.print(buffer);
107
108
  delay(250);
109
}

Im Allgemeinen würde ich sagen dass mit der Library und dem Shield das 
ganze einfach zu bewerkstelligen ist. Notfalls hilft ein Logikanalysator 
jedem Fehler auf die Schliche zu kommen...

Mfg,

Thomas

von CanBusShield (Gast)


Lesenswert?

ok vielen dank schonmal für eure beiträge.

werde mich dann nochmal ran setzen und es ausprobieren..

von Thomas (Gast)


Lesenswert?

Viel Erfolg.

Achte auch drauf dass die Steckerbelegung passt (in dem ct hacks Artikel 
ist sie nochmal abgebildet), denn je nachdem welches Kabel man gekauft 
hat kann das durchaus anders belegt sein.

Thomas

von CanBusShield (Gast)


Lesenswert?

@Prof

wäre dieses Produkt geeignet oder felht mir da noch was dann?
Muss ja zugeben bin echt ein richtiger Anfänger in diesem Gebiet :-)

https://www.sparkfun.com/products/9555

von Thomas (Gast)


Lesenswert?

Dieser Mikroprozessor samt Hühnerfutter:
http://www.watterott.com/de/Arduino-Leonardo
(achtung: Hier müssen die Buchsenleisten noch angelötet werden, das ist 
bei anderen Arduino Boards nicht der Fall, die hat Watterott aber gerade 
nicht - alternativ nimmst du sowas hier: 
http://www.amazon.de/SainSmart-Kompatibel-Entwicklungsbrett-ATmega328P-enthaltend/dp/B00760RLFO/ref=sr_1_2?ie=UTF8&qid=1421756758&sr=8-2&keywords=arduino+uno 
oder 
http://www.amazon.de/SainSmart-Leonardo-ATMEGA32U4-Entwicklungsbrett-Duemilanove/dp/B00GAUW7L4/ref=sr_1_2?ie=UTF8&qid=1421756768&sr=8-2&keywords=arduino+leonardo)

Dieses Shield für obigen µC:
http://www.watterott.com/de/Arduino-CANdiy-Shield

Dieser Stecker:
http://www.watterott.com/de/OBD2-Stecker-mit-PCB

Und ein Netzwerkkabel dass du auf einer Seite seines RJ45-Stecker 
beraubst und statt dessen den OBD2-Stecker anlötest.
Hierbei natürlich aufs richtige verlöten achten.

Das SparkFun Teil scheint auch nicht falsch zu sein, nur recht teuer und 
die Stecker müssen auch noch angelötet werden. ODBC2-Stecker, Kabel 
sowie einen USB<->Seriel Converter würdest du da noch brauchen.

Im allgemeinen ist CAN-Bus etwas was viele Mikroprozessoren mittlerweile 
sprechen. Problem ist nur immer dass du zu einem (recht günstigen) 
Mikroprozessor immer noch das physische Interface zum CAN-Bus brauchst 
(Stecker, Kabel...) sowie auf der anderen Seite eine Stromversorgung und 
Programmiermöglichkeit.

Die Arduino Variante finde ich deshalb recht angenehm weil sie eine 
angenehm unkomplizierte Entwicklungsumgebung sowie viele vorgefertigte 
Programmierbeispiele bietet.

Thomas

von CanBusShlied (Gast)


Lesenswert?

Danke dir Thomas,

hoffe das mich das weiterbringt.
habe ja noch einen Arduino MEGA 2560 zu Hause liegen.
mit dem sollte es ja auch funktionieren oder?

Habe ja auch ein beispiel Programm mal ausprobiert:

// demo: CAN-BUS Shield, receive data
#include "mcp_can.h"
#include <SPI.h>
#include <LiquidCrystal.h>
#include <stdio.h>
#define INT8U unsigned char

INT8U Flag_Recv = 0;
INT8U len = 0;
INT8U buf[8];
INT32U canId = 0x000;
char str[20];
LiquidCrystal lcd(9, 8, 7, 6, 5, 4);

void setup()
{
lcd.begin(20, 4);
CAN.begin(CAN_500KBPS); // init can bus : baudrate = 500K
Serial.println("CAN Init ok");
attachInterrupt(0, MCP2515_ISR, FALLING); // start interrupt
Serial.begin(115200);
}

void MCP2515_ISR()
{
Flag_Recv = 1;
}

void loop()
{
if(Flag_Recv) // check if data was recieved
{
Flag_Recv = 0; // clear flag
CAN.readMsgBuf(&len, buf); // read data, len: data length, buf: data buf
canId = CAN.getCanId();
//Print data to the serial console
//and the LCD display
Serial.println("CAN_BUS GET DATA!");
Serial.print("CAN ID: ");
Serial.println(canId);
lcd.setCursor(0, 0);
lcd.print("CAN ID: ");
lcd.print(canId);
lcd.setCursor(0, 2);
Serial.print("data len = ");Serial.println(len);
//This loops through each byte of data and prints it
for(int i = 0; i<len; i++) // print the data
{
Serial.print(buf[i]);Serial.print("\t");
lcd.print(buf[i]);
lcd.print(" ");
}
Serial.println();
delay(50);
}
}

Nur hier zeigt er mir nur im serial MOnitor an " CAN INIT OK "

wie bekomme ich hier meinen Identifier für die Drehzahl untergebracht 
oder geht das nicht einfach so? Engine RPM $F40C

Sorry für die vielen Fragen :(

Mfg

von Thomas (Gast)


Lesenswert?

Ich gehe mal davon aus dass du ein Seed-Studio CAN_BUS_Shield verwendest 
und das deine Verkabelung korrekt ist.

In dem Fall wirfst du das hier mal raus:
1
attachInterrupt(0, MCP2515_ISR, FALLING); // start interrupt
(am Anfang solltest du erstmal pollen, das ist einfacher, deshalb 
brauchst du keine ISR)

Nun kannst du statt:
1
if(Flag_Recv)
mal das hier versuchen:
1
if (CAN::checkReceive() == 1)

Das hier:
1
CAN.readMsgBuf(&len, buf); // read data, len: data length, buf: data buf
2
canId = CAN.getCanId();
sieht eigentlich so aus als könnte es dann funktionieren.

Es ist auch gut möglich dass dein Programmcode nicht falsch ist, aber 
die Verkabelung nicht stimmt, ich denke fast dass ist das Problem.
Bist du dir sicher dass du hier alles richtig verkabelt hast?

Fotos, fotos, fotos !

Thomas

von CanBusShlied (Gast)


Lesenswert?

ja, verwende das Seed Can bus Shield und abe es auf den ARduino Mega 
gesteckt. Passt ja auch nur einmal drauf irgendwie.

werde aufjedenfall mal Fotos machen wenn ich zu Hause bin und sie dir 
hier zukommen lassen.
vllt siehst du ja auf anhieb ob etwas falsch verkabelt ist.

aber wohin mit meinem Identifier?? "Engine RPM $F40C"

Danke dir schonmal für deine schnelle Antowrt..

MFG

von Thomas (Gast)


Lesenswert?

Du scheinst hier etwas CAN und OBD durcheinander zu bringen.
CAN ist der Bus, OBD ist ein Protokoll was über den CAN-Bus übertragen 
wird.

Auf dem CAN Bus kannst du theoretisch viel mehr hören und machen als nur 
ODB.

Seis drum, das OBD Protokoll gibt im sog. MODE 1 die folgenden Daten 
aus: http://en.wikipedia.org/wiki/OBD-II_PIDs#Mode_01
Deine Modordrehzahl ist also ein standardtisierter Wert mit der PID 
0x0C.

Du musst also auf den BUS eine Nachricht schicken. Empfängeradresse ist 
0x7df (Broadcast), length ist 2, mode 1 und pid 0x0C.

Daraufhin sollte das freundliche Steuergerät deiner Wahl (also welches 
sich zuständig fühlt) dir antworten.
Diese Antwort kannst du dann auswerten.
Also erst freundlich fragen, dann eine Antwort bekommen.
Ich lege dir mal den ct Hacks Artikel (nochmal) ans Herz, da ist das 
ganz gut erklärt. Zitieren daraus trau ich mich nicht.
Bei meinem Programmcode habe ich folgende Library verwendet: 
https://code.google.com/p/mechanic/
(diese Library nutzt auch den Chip MCP2515, genauso wie die Library von 
Seed)

Diese unterstütze den folgenden Aufruf:
1
obd.getPidAsString(0x0C, 0.0f, 16383.75f, "%d", buffer);

Heißt also: CAN Library ist das eine, OBD-Library das anderes.
Auch im Readme von dem Seed Dingens steht irgendwas von
1
With an OBD-II converter cable added on and the OBD-II library imported, you are ready to build an onboard diagnostic device or data logger.

Thomaas

von CanBusShield (Gast)


Angehängte Dateien:

Lesenswert?

ok Vielen dank für die Infos.

habe mal ein paar Bilder gemacht von meinem Controller und dem Shield,
hoffe man kann alles gut einsehen.

mfg

von Thomas (Gast)


Lesenswert?

Na das Shield ist schonmal richtig. Sonst hätte wohl auch der init nicht 
geklappt.
Jetzt probier vielleicht mal meinen oben geposteten Beispielcode und die 
mechanics-Library aus.

Viel Glück!

Thomas

von CanBusShield (Gast)


Lesenswert?

ok super..

dann werde ich mich mal ransetzen und ein bisschen ausprobieren.

herzlichen dank für deine antworten Thomas..

werde über meinen fortschritt berichten...

mfg

von Pete (Gast)


Lesenswert?

Thomas schrieb:
> Dieser Stecker:

Etwas mehr Auswahl an Varianten findest Du noch hier: 
http://www.obd2.tools

von CanBusShield (Gast)


Lesenswert?

Hallo Thomas,

habe jetzt die mechanic library mal reingeladen und dein Beispiel 
Programm verwendet, nur nicht mit dem LCD Display sondern über den 
Serial Monitor, sollte ja nichts ändern.

im Fehlerfeld unten taucht nun folgender Fehler auf:

>  C:\Program Files (x86)\Arduino\libraries\can\mcp2515.c: In function 
'mcp2515_init':
>  C:\Program Files (x86)\Arduino\libraries\can\mcp2515.c:201: error: 'for' loop 
initial declaration used outside C99 mode

kannst du mir da weiterhelfen?

mfg

von Thomas (Gast)


Lesenswert?

Ists denn die aktuellste Version der Arduino Software?

Hier gibts ne genaue Erklärung dazu: 
http://forum.arduino.cc/index.php?topic=47598.0

von CanBusShield (Gast)


Lesenswert?

Lag an der mechanic 0.5. Diese war nicht kompatibel mit dem Arduino Mega

Mit der mechanic 0.6 läuft es einwandfrei. Kann mir auch ohne Probleme 
jetzt eine Drehzahl über die OBD Pids anzeigen lassen.

Mal schauen wir es jetzt mit den Werten vom Can Bus aussieht. Habe mir 
noch einen Multoprotokoll Adapter bestellt, weil ich noch  Werte 
brauche, die nur auf dem Antriebs Can zu finden sind.

Möchte ja nur hören und nichts auf den Can senden.

von Thomas (Gast)


Lesenswert?

Cool. Freut mich dass es nun geht!

Thomas

von CanBusShield (Gast)


Lesenswert?

deine Tipps waren ja auch sehr hilfreich.

Vielen Dank dafür

Mit Daten vom Can Bus kennst du dich aber nicht aus oder? (Über die OBD 
Buchse)

von Thomas (Gast)


Lesenswert?

Mehr als das oben zitierte Beispielprogramm und den Wikipedia Link kann 
ich leider nicht bieten.

Damit kriegt man halt Motordrehzahl, Öltemperatur und sowas... das 
reichte mir damals.

Finde experimentieren mit dem Auto immer etwas unbequem...

Thomas

von Marina (Gast)


Lesenswert?

Hallo,

habe viel ausprobiert wie auch mechanic 0.6

Mein Problem ist das ich bei den Beipielen keine Daten zurückbekomme

Ich habe Fahrzeuge hier stehen die mit 29bit kommunizieren.

Sende ich zb. 0x7DF kommt keine Antwort.

Bei 29bit muss ich aber 18DB33F1 senden.

Aber sämtliche Beispiele sind immer nur für 11bit.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.