1. Startseite
  2. Forum
  3. Auto
  4. Volvo
  5. S60, S80, V70 2, XC70, XC90
  6. Der CAN-Bus im Volvo

Der CAN-Bus im Volvo

Volvo V70 2 (S)

Um Kabelbäume unter anderem in Fahrzeugen zu vereinfachen entwickelte Bosch im Jahre 1983 das Controller Area Network. Seit dem Jahr 2000 findet dieses System in vielen Fahrzeugen Anwendung (bei Volvo ab V70II S80 S60 XC70 XC90).

Grundprinzip ist, dass der gesamte Datenaustausch auf zwei Leitungen stattfindet. Diese werden um Reflexionen an beiden Enden zu vermeiden jeweils mit einem 120 Ohm Widerstand terminiert. Die Signalübertragung erfolgt differenziell mit einer Spannungsdifferenz von 2V zwischen CAN-H und CAN-L. Da im KFZ die Datenleitung vielen Störfeldern ausgesetzt ist werden beide Kabel miteinander verdrillt ,damit beide Leitungen den Störungen gleichermaßen ausgesetzt sind und eine Spannungsdifferenz von 2V erhalten bleibt.

Link zur Grafik

Bei einem dominanten Zustand (logisch 0) liegen beide Leitung auf einer Spannung von 2,5 volt. Im rezessiven Zustand (logisch 1) wird die Spannung der Leitung CAN-H(igh) um 1V auf 3,5V angehoben und die Spannung auf der Leitung CAN-L(ow) um 1V auf 1,5V abgesenkt.

Link zur Grafik

Alle im Netzwerk befindlichen Geräte können auf dieser Leitung mithören und abwechselnd senden. Damit sichergestellt wird, dass immer nur ein einzelnes Gerät sendet ist das Übertragungsverfahren streng definiert. Eine Darstellung aller Mechanismen würden den Inhalt des Forums jedoch sprengen, somit ist es an dieser Stelle sinnvoll die wesentlichen Spezifikationen zu erläutern.
Ein Gerät muss immer auf eine Lücke warten, bis es anfangen darf, Daten in das Netzwerk zu senden. Gleichzeitig muss das sendende Gerät im Netzwerk mithören und vergleichen ob jeder einzelne Spannungszustand erfolgreich in das Netzwerk übertragen wird. Da bei einer 1 der Pegel als hoch und einer 0 der Pegel als tief definiert ist, kommt es dazu, dass wenn zwei Geräte gleichzeitig senden, das Gerät mit dem dominanten Bit das Netzwerk auf Null zieht und somit den rezessiven Zustand überschreibt. Weil jedes Gerät die zu sendende Meldung mit dem Zustand des Netzwerkes vergleicht, stellt das Gerät, welches zum eigentlichen Zeitpunkt eine 1 gesendet hat einen Fehler fest und stoppt die eigene Sendung. Infolgedessen haben Meldungen mit einer vorausgehenden 0 eine höhere Priorität als Meldungen mit einer vorausgehenden 1.

Zur Identifikation besteht jede gesendete Meldung aus einer ID und einem Datensatz.

Zum Beispiel die Meldung welche vom Lenkradmodul gesendet wird, um den Zustand des Blinker- und Wischerhebels wiederzugeben:

ID: 0111300A Daten: C0 00 00 27 80 8E 00 C0

Da Volvo den erweiterten J1939-CAN-Frame nutzt besteht die ID aus 4 Bytes “01 11 30 0A” welche einerseits die Priorität der Meldung festlegen und andererseits der Identifikation dienen. Jede ID in einem Netzwerk darf nur einmal vergeben sein. Die ID hat den Nutzen für andere Geräte, dass diese dadurch selektieren können, welche Informationen für sie wichtig sein können. Das Radio beispielsweise achtet auf IDs, welche vom CEM kommen und die Geschwindigkeit und Beleuchtungseinstellung enthalten, wie auch auf IDs welche vom Lenkradmodul kommen und eine Änderung der Lenkradtasten enthalten.
Ein Gerät darf auch über mehrere IDs verfügen, da es auch verschiedene Informationen versenden kann.

Die ID bei Volvo wird gefolgt von einem 8 Byte Datensatz “C0 00 00 27 80 8E 00 C0” in diesem sind die Informationen enthalten, welche das Gerät dem Netzwerk mitteilt.

In Beispiel des Lenkradmoduls codiert die 5te Stelle (Byte 4) für:

5te Stelle:
80: Nichts gedrückt
84: Blinkhebel in rechter Stellung
88: Blinkhebel in linker Stellung
C0: Resettaste am Blinkhebel wird betätigt (Boardcomputerversion)
A0: Read Taste am Blinkhebel wird betätigt

Die 6te Stelle "8E" gibt an, dass der Wischerhebel in 0 Stellung ist.

Die Gesamte Meldung wird etwa alle 15ms in das Datennetzwerk gesendet (nach Priorität häufiger oder seltener), damit jegliche Geräte über den Zustand Bescheid wissen und entsprechend reagieren können. Erhält das CCM die Meldung 84 aktiviert es das Relais für den Blinker der rechten Seite.

Link zum Datendiagramm

Im Datendiagramm ist zu erkennen, dass die gesamte Meldung (als Frame bezeichnet) aus mehr als der ID und dem Datensatz besteht. Es sind noch einige Zusätze nötig, damit eine Meldung erfolgreich übertragen werden kann, diese sind aber bei alleiniger Betrachtung der Meldungen hier nicht von Bedeutung und werden in der realen Anwendung von Controllern automatisch errechnet und durchgeführt.

Kommt es trotz aller Mechanismen dazu, dass ein Fehler auftritt, weil beispielsweise eine ID doppelt im Netzwerk auftritt, unterbricht das Gerät mit gleicher ID die Sendung sofortig und versucht zu einem weiteren Zeitpunkt seine Meldung in das Netzwerk zu senden. Kommt es weiterhin hintereinander zum selbigen Fehler, klinkt sich das Gerät für eine vergleichsweise längere Zeit (ca. 10s) aus dem Netzwerk aus und versucht den Datentransfer erneut. Dies kann jedoch gravierend sein, wenn beispielsweise für etwa 10s der Blinker nicht mehr funktioniert.

Im Volvo gibt es zwei verschiedene CAN-Netzwerke:

Link zur Grafik

Das Motor High-Speed CAN mit einer Datenrate von 250kb/s und das Comfort-Low-Speed-CAN mit einer Datenrate von 125kb/s. Beide Netzwerke laufen voneinander unabhängig, das CEM ist das einzige Gerät welches in Kontakt mit beiden Netzwerken steht und somit Daten zwischen diesen austauschen kann wie beispielsweise die Drehzahl.

Volvo hat die Codierung jeglicher Daten in jedem Baujahr geändert, was zur Folge hat, das sich Geräte aus unterschiedlichen Baujahren nicht über den CAN-Bus unterhalten können, das sie ihre Meldungen nicht mehr verstehen.

Dazu ein Beispiel für die Datenwörter, welche unter anderem für die Tasten des Lenkrades zuständig sind:

Fahrzeug aus 2001
ID: 00200066 Daten: C0 00 00 01 1F 40 40 7F

Fahrzeug aus 2002:
ID: 0261300A Daten: 80 00 00 27 80 C2 00 CF

Beide Meldungen erfüllen genau die gleiche Funktion, können aber nicht von Geräten aus anderen Baujahren interpretiert werden.

Durch diese Zusammenhänge lassen sich nicht nur Funktionen im Fahrzeug ergründen sondern auch Erweiterungen wie die eines CAN-Extenders aufbauen. Durch ein einfaches Senden einer Meldung in dieses Netzwerk lässt sich somit etwa eine Coming-Home Funktion mit zusätzlich aktivierten Nebelscheinwerfen realisieren oder es können Tastendrücke oder Fahrzeugdaten jeglicher Art erfasst werden.

Beste Antwort im Thema

Um Kabelbäume unter anderem in Fahrzeugen zu vereinfachen entwickelte Bosch im Jahre 1983 das Controller Area Network. Seit dem Jahr 2000 findet dieses System in vielen Fahrzeugen Anwendung (bei Volvo ab V70II S80 S60 XC70 XC90).

Grundprinzip ist, dass der gesamte Datenaustausch auf zwei Leitungen stattfindet. Diese werden um Reflexionen an beiden Enden zu vermeiden jeweils mit einem 120 Ohm Widerstand terminiert. Die Signalübertragung erfolgt differenziell mit einer Spannungsdifferenz von 2V zwischen CAN-H und CAN-L. Da im KFZ die Datenleitung vielen Störfeldern ausgesetzt ist werden beide Kabel miteinander verdrillt ,damit beide Leitungen den Störungen gleichermaßen ausgesetzt sind und eine Spannungsdifferenz von 2V erhalten bleibt.

Link zur Grafik

Bei einem dominanten Zustand (logisch 0) liegen beide Leitung auf einer Spannung von 2,5 volt. Im rezessiven Zustand (logisch 1) wird die Spannung der Leitung CAN-H(igh) um 1V auf 3,5V angehoben und die Spannung auf der Leitung CAN-L(ow) um 1V auf 1,5V abgesenkt.

Link zur Grafik

Alle im Netzwerk befindlichen Geräte können auf dieser Leitung mithören und abwechselnd senden. Damit sichergestellt wird, dass immer nur ein einzelnes Gerät sendet ist das Übertragungsverfahren streng definiert. Eine Darstellung aller Mechanismen würden den Inhalt des Forums jedoch sprengen, somit ist es an dieser Stelle sinnvoll die wesentlichen Spezifikationen zu erläutern.
Ein Gerät muss immer auf eine Lücke warten, bis es anfangen darf, Daten in das Netzwerk zu senden. Gleichzeitig muss das sendende Gerät im Netzwerk mithören und vergleichen ob jeder einzelne Spannungszustand erfolgreich in das Netzwerk übertragen wird. Da bei einer 1 der Pegel als hoch und einer 0 der Pegel als tief definiert ist, kommt es dazu, dass wenn zwei Geräte gleichzeitig senden, das Gerät mit dem dominanten Bit das Netzwerk auf Null zieht und somit den rezessiven Zustand überschreibt. Weil jedes Gerät die zu sendende Meldung mit dem Zustand des Netzwerkes vergleicht, stellt das Gerät, welches zum eigentlichen Zeitpunkt eine 1 gesendet hat einen Fehler fest und stoppt die eigene Sendung. Infolgedessen haben Meldungen mit einer vorausgehenden 0 eine höhere Priorität als Meldungen mit einer vorausgehenden 1.

Zur Identifikation besteht jede gesendete Meldung aus einer ID und einem Datensatz.

Zum Beispiel die Meldung welche vom Lenkradmodul gesendet wird, um den Zustand des Blinker- und Wischerhebels wiederzugeben:

ID: 0111300A Daten: C0 00 00 27 80 8E 00 C0

Da Volvo den erweiterten J1939-CAN-Frame nutzt besteht die ID aus 4 Bytes “01 11 30 0A” welche einerseits die Priorität der Meldung festlegen und andererseits der Identifikation dienen. Jede ID in einem Netzwerk darf nur einmal vergeben sein. Die ID hat den Nutzen für andere Geräte, dass diese dadurch selektieren können, welche Informationen für sie wichtig sein können. Das Radio beispielsweise achtet auf IDs, welche vom CEM kommen und die Geschwindigkeit und Beleuchtungseinstellung enthalten, wie auch auf IDs welche vom Lenkradmodul kommen und eine Änderung der Lenkradtasten enthalten.
Ein Gerät darf auch über mehrere IDs verfügen, da es auch verschiedene Informationen versenden kann.

Die ID bei Volvo wird gefolgt von einem 8 Byte Datensatz “C0 00 00 27 80 8E 00 C0” in diesem sind die Informationen enthalten, welche das Gerät dem Netzwerk mitteilt.

In Beispiel des Lenkradmoduls codiert die 5te Stelle (Byte 4) für:

5te Stelle:
80: Nichts gedrückt
84: Blinkhebel in rechter Stellung
88: Blinkhebel in linker Stellung
C0: Resettaste am Blinkhebel wird betätigt (Boardcomputerversion)
A0: Read Taste am Blinkhebel wird betätigt

Die 6te Stelle "8E" gibt an, dass der Wischerhebel in 0 Stellung ist.

Die Gesamte Meldung wird etwa alle 15ms in das Datennetzwerk gesendet (nach Priorität häufiger oder seltener), damit jegliche Geräte über den Zustand Bescheid wissen und entsprechend reagieren können. Erhält das CCM die Meldung 84 aktiviert es das Relais für den Blinker der rechten Seite.

Link zum Datendiagramm

Im Datendiagramm ist zu erkennen, dass die gesamte Meldung (als Frame bezeichnet) aus mehr als der ID und dem Datensatz besteht. Es sind noch einige Zusätze nötig, damit eine Meldung erfolgreich übertragen werden kann, diese sind aber bei alleiniger Betrachtung der Meldungen hier nicht von Bedeutung und werden in der realen Anwendung von Controllern automatisch errechnet und durchgeführt.

Kommt es trotz aller Mechanismen dazu, dass ein Fehler auftritt, weil beispielsweise eine ID doppelt im Netzwerk auftritt, unterbricht das Gerät mit gleicher ID die Sendung sofortig und versucht zu einem weiteren Zeitpunkt seine Meldung in das Netzwerk zu senden. Kommt es weiterhin hintereinander zum selbigen Fehler, klinkt sich das Gerät für eine vergleichsweise längere Zeit (ca. 10s) aus dem Netzwerk aus und versucht den Datentransfer erneut. Dies kann jedoch gravierend sein, wenn beispielsweise für etwa 10s der Blinker nicht mehr funktioniert.

Im Volvo gibt es zwei verschiedene CAN-Netzwerke:

Link zur Grafik

Das Motor High-Speed CAN mit einer Datenrate von 250kb/s und das Comfort-Low-Speed-CAN mit einer Datenrate von 125kb/s. Beide Netzwerke laufen voneinander unabhängig, das CEM ist das einzige Gerät welches in Kontakt mit beiden Netzwerken steht und somit Daten zwischen diesen austauschen kann wie beispielsweise die Drehzahl.

Volvo hat die Codierung jeglicher Daten in jedem Baujahr geändert, was zur Folge hat, das sich Geräte aus unterschiedlichen Baujahren nicht über den CAN-Bus unterhalten können, das sie ihre Meldungen nicht mehr verstehen.

Dazu ein Beispiel für die Datenwörter, welche unter anderem für die Tasten des Lenkrades zuständig sind:

Fahrzeug aus 2001
ID: 00200066 Daten: C0 00 00 01 1F 40 40 7F

Fahrzeug aus 2002:
ID: 0261300A Daten: 80 00 00 27 80 C2 00 CF

Beide Meldungen erfüllen genau die gleiche Funktion, können aber nicht von Geräten aus anderen Baujahren interpretiert werden.

Durch diese Zusammenhänge lassen sich nicht nur Funktionen im Fahrzeug ergründen sondern auch Erweiterungen wie die eines CAN-Extenders aufbauen. Durch ein einfaches Senden einer Meldung in dieses Netzwerk lässt sich somit etwa eine Coming-Home Funktion mit zusätzlich aktivierten Nebelscheinwerfen realisieren oder es können Tastendrücke oder Fahrzeugdaten jeglicher Art erfasst werden.

277 weitere Antworten
277 Antworten

motor-talk scheint hier was gegen inks zu haben, wenn man es mit diagtools austauscht klappt es, aber es gibt viele Anbieter und der Versand scheint extrem schnell zu gehen...

Der Arduino mit dem Shield soll auch funktionieren wenn das Auto aus und abgeschlossen ist, dies erfordert also ständige Bereitschaft unter Stromverbrauch.

Der Arduino besitzt zur Spannungsregelung einen NCP1117ST50T3G welcher nicht der fortschrittlichste ist. Je höher die Eingangsspannung, desto größer ist auch die Verlustleistung welche in Wärme umgesetzt wird. Dazu leuchten noch dauerhaft zwei LEDs, eine auf dem Shield und eine auf dem Arduino welche jeweils etwa 3mA benötigen.

Gemessen benötigt der Ardunio somit etwa 68mA im Betrieb.
Bei verschlossenen Fahrzeug kommt nach etwa 30 Sekunden Ruhe in den Bus und der Arduino wird nicht mehr benötigt um Meldungen auszuwerten.
Auch der mcp2515 muss nicht mehr in vollem Betrieb arbeiten.

Somit bietet es sich sehr an diese Geräte in den Standby zu schicken. Eine gute Grundlage dazu bietet der mcp2515 mit dem Ausgang CAN_INT, dieser ist Aktiv (+5V) wenn keine Nachrichten im Speicher sind und wird auf Masse gezogen wenn der Speicher eine Nachricht enthält. Bereits durch das Shield ist dieser Ausgang mit dem Interrupt Pin 2 des Arduinos verbunden.
Wenn der Arduino in den Standby-Modus versetzt wird eignet sich dieser Pegel-Wandel am Pin 2 um den Arduino wieder zu wecken.

Eine Möglichkeit wäre es um Strom zu Sparen, die Meldungen zu zählen welche eintreffen, falls das Auto den Bus schlafen legt, wird zuerst der Speicher des mcp2515 gelöscht, damit der INT-Pin auf eine Spannung von 5V gesetzt wird. Dann sendet der Arduino einen Befehl um den mcp2515 in den Standby zu versetzen und wird anschließend selbst in den Standby versetzt. Wenn wieder eine Meldung im Bus auftauch setzt der mcp2515 den Interrupt Pin auf Masse und weckt den Arduino, dieser versetzt weiterhin den mcp2515 wieder in Normalbetrieb. Dadurch geht zwar die erste Meldung verloren, dies ist jedoch meist belanglos, da die Zentralverrieglung oder die Fernbedienung erfahrungsgemäß nie in der ersten Meldung auftauchen.

Im Standby benötigt der Arduino dann nur noch etwa 34mA welche auf den ungünstigen Spannungsregler und die beiden LEDs wie den mcp2551 zurückzuführen sind.

Dies sollte für eine Autobatterie jedoch kein Problem darstellen.

34mA eine Stunde lang: 0,034 Ah
34 mA 100 Stunden lang 3,4 Ah
34 mA 1000 Stunden lang 34 Ah
1000 Stunden entsprechen 41 Tage

Nach dieser Zeit wäre eine 72Ah Autobatterie dann in der Theorie zur Hälfte entladen.
In der Praxis ist also die Selbstentladung größer als der Stromverbrauch des Arduinos samt Shield.

Aber das ganze lässt sich wenn gewünscht noch stark weiter reduzieren, etwa durch Nutzung eines sparsamen Spannungsreglers (beispielsweise des MAX667), durch das Verzichten von LEDs und durch den zusätzlichen Standbymodus des mcp2551.

Dies alles ist nicht erforderlich, da der Stromverbrauch noch weit unter der Selbstentladung liegt, es soll lediglich das Mögliche darstellt werden. Alternativ lässt sich eventuell noch einiges einsparen, wenn der Arduino über den USB-Port etwa von einem 7805 versorgt wird.

Bilder zum Vergleich wurden am 12V Ausgang eines ATX Netzteils gemacht.

Code zum Standby folgt...

Zitat:

Original geschrieben von DR_V70


Ich möchte hier noch einmal darstellen, dass für dieses Projekt keineswegs VADIS benötigt wird, denn die Diagnosemeldungen sollten eigentlich in jedem Fahrzeug funktionieren.....

Da magst du Recht haben,aber gibt es denn eine Tabelle mit Diagnosecodes? Problem ohne ein Diagnosegerät ist es ja den Code herauszufinden....

Ein Tabelle ist mir keineswegs bekannt, es ist halt nur die Frage ob sich dies gesamt betrachtet lohnt. Halte die Diagnosecodes für die Blinker und die Scheinwerfer am wichtigsten, der Rest ist halt fraglich ob es wirklich benötigt wird. Der Lichtschalter etwa ist mit dem Lin-Bus an das CEM angebunden, hier wird keine CAN-Message gesendet. Aber mit einer Diagnosemeldung ist es trotzdem möglich das Licht einzuschalten. Die Zentralverrieglung und die Fensterheber kommunizieren untereinander über den CAN-Bus, hier müssen nur die Meldungen identifiziert werden und können dann eigenständig gesendet werden. Selbiges gilt für das Standlicht und viele weitere Dinge.

Zu Beginn sieht das mit den gesammelten Diagnosemeldungen schlecht aus, da es wirklich nicht viele gibt welche sich mit diesem Bereich beschäftigen. Aber es können ja nur mehr werden.

Spontan habe ich da jetzt nur:
Kofferraumentrieglung
Relais-Abfrage Licht
Standlicht
Innenraumbeleuchtung
Laderraumbeleuchtung
CCM-Lichtsensor Abfrage
Innenraumtemperatur Abfrage
Fensterheber Fahrer Beifahrer
Schloss Beifahrer
Schiebedach

Telefon muss selbst vorhanden sein um dieses zu loggen, für 2002 sollte das Beispiel von Olaf funktionieren. Ansonsten ist es nicht anders möglich an die Meldungen zu gelangen welche das Display im DIM aktivieren. (Text kann aber natürlich auch ohne Telefon dargestellt werden)

Also wenn nicht unbedingt viele gebraucht werden kann ich nochmal schauen...
Personen mit Diagnosegerät welche mitloggen sind aber immer willkommen...

Ähnliche Themen

Hoffe das klappt jetzt auf Anhieb mit dem Code, die Grundlage zum Standby-Modus stammt von Olaf, welcher sich durch das Datenblatt des mcp2515 geschlagen hat. Danke!

Wenn in 3000 Cyclen lang keine Meldung empfangen wird, schaltet das Programm in den Standby, neu ist die ausführliche setup() Konfiguration sowie die unten angehängten Funktionen welche den Controller in den Standby befördern und wieder wecken, zusätzlich gibt es vorm Standby noch eine Übsicht zum genutzten Arbeitsspeicher im Serial Monitor...

Code:
#include <Canbus.h>
#include <defaults.h>
#include <global.h>
#include <mcp2515.h>
#include <mcp2515_defs.h>
#include <avr/sleep.h>
int cc = 0; // Cycle counter
#define MODE_NORMAL 0
#define MODE_SLEEP 1

void setup()
{
Serial.begin(115200);
pinMode(2, INPUT); //Interrupt PIN 2 wird aktiviert
//Initialise MCP2515 CAN controller at the specified speed
if(Canbus.init(CANSPEED_125))
Serial.println("CAN Init ok"😉;
else
Serial.println("Can't init CAN"😉;
delay(1000);
mcp2515_bit_modify(CANCTRL, (1<<OSM), 0); // disable one-shot mode
mcp2515_bit_modify(CANINTE, (1<<WAKIE) , 1<<WAKIE); // enable CAN traffic wake up interrupt
mcp2515_bit_modify(CANCTRL, (1<<REQOP2)|(1<<REQOP1)|(1<<REQOP0), 0); // mode<<REQOP0 // switch to normal mode
delay(1);
digitalWrite(2,LOW);
delay(1);
uint8_t count=0;
while ( (MCP2515_get_op_mode()!=MODE_NORMAL) && (count<100) )
{
count++;
delay(1);
}
if (count>=100)
{
Serial.println("MCP2515 wakeup failed!"😉;
}
}
void loop()
{
tCAN message;
if (mcp2515_get_message(&message)) {
cc = 0; //Wenn eine Meldung vorhanden ist, wird der Zähler auf 0 gesetzt




//Hauptschleife mit Programmcode




}else{ //Wenn keine Meldung vorhanden
cc++; //Wird der Zähler um einen Schritt hochgezählt
if (cc == 3000){ //Wenn der Zähler bei 3000 ist
sleepNow(); //Sleep function is called
}
}

}
void mcp2515_wakeup()
{
// generate the WAKIF interrupt in case it wasn't MCP2515 that woke us up (in that case the MCP2515 is still sleeping..)
mcp2515_bit_modify(CANINTF, (1<<WAKIF), 1<<WAKIF);
delay(1);
mcp2515_bit_modify(CANINTF,1<<WAKIF,0); // clear wakeup interupt bit, so our interrupt handler is not anymore called by MCP2515
MCP2515_set_op_mode(MODE_NORMAL); // back to normal mode (MCP2515 wakes up from the sleep in listen-only mode)
delay(1);
uint8_t count=0;
while ( (MCP2515_get_op_mode()!=MODE_NORMAL) && (count<100) )
{
count++;
delay(1);
}
if (count>=100)
{
Serial.println("MCP2515 wakeup failed!"😉;
}
}
uint8_t cantx(long id, int c0, int c1, int c2, int c3, int c4, int c5, int c6, int c7)/////////////////////////////////////////////////////////////////////////Senden
{
//Serial.println(message->id,HEX);
mcp2515_bit_modify(CANCTRL, (1<<REQOP2)|(1<<REQOP1)|(1<<REQOP0), 0); //Bit modify
uint8_t status = mcp2515_read_status(SPI_READ_STATUS);
uint8_t address;
uint8_t t;
uint8_t TXBnSIDH=0;
uint8_t TXBnSIDL=0;
uint8_t TXBnEID8=0;
uint8_t TXBnEID0=0;
if (bit_is_clear(status, 2)) {
address = 0x00;
}
else if (bit_is_clear(status, 4)) {
address = 0x02;
}
else if (bit_is_clear(status, 6)) {
address = 0x04;
}
else {
return 0;
}
RESET(MCP2515_CS);
spi_putc(SPI_WRITE_TX | address);
TXBnSIDH = (id) >> 21; // 8 MSB of Identifier A
TXBnSIDL = (id) >> 18;
TXBnSIDL = (TXBnSIDL << 5) | 0x08 ; // 3 LSB of Identifier A. Enable Extended identifier (bit 3)
if (GETBIT((id),17)==1) SETBIT(TXBnSIDL,1); // bit 17 of Identifier B
if (GETBIT((id),16)==1) SETBIT(TXBnSIDL,0); // bit 16 of Identifier B
TXBnEID8 = (id)>>8; // bits 8-15 of Identifier B
TXBnEID0 = (id); // bits 0-7 of Identifier B
spi_putc(TXBnSIDH);
spi_putc(TXBnSIDL);
spi_putc(TXBnEID8);
spi_putc(TXBnEID0);
uint8_t length = 8 & 0x0f;
if (0) { //if (message->header.rtr) {
spi_putc((1<<RTR) | length);
}
else {
spi_putc(length);
spi_putc(c0);
spi_putc(c1);
spi_putc(c2);
spi_putc(c3);
spi_putc(c4);
spi_putc(c5);
spi_putc(c6);
spi_putc(c7);
}
SET(MCP2515_CS);
RESET(MCP2515_CS);
address = (address == 0) ? 1 : address;
spi_putc(SPI_RTS | address);
SET(MCP2515_CS);
return address;
}////////////////Ende Senden
uint8_t MCP2515_get_op_mode()
{
uint8_t canstat = mcp2515_read_register(CANSTAT);
return (canstat>>OPMOD0) & 0x7;
}
void sleepNow() // here we put the arduino to sleep
{
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here
sleep_enable(); // enables the sleep bit in the mcucr register
attachInterrupt(0,wakeUpNow, LOW); // use interrupt 0 (pin 2) and run function wakeUpNow when pin 2 gets LOW
mcp2515_bit_modify(CANINTF,1<<WAKIF,0); //WAKIF zurücksetzten im mcp2515
MCP2515_set_op_mode(MODE_SLEEP);
Serial.println("\n[memCheck]"😉;
Serial.println(freeRam());
Serial.println("Going to sleep now"😉;
delay(500);
sleep_mode(); // here the device is actually put to sleep!!
// THE PROGRAM CONTINUES FROM HERE AFTER WAKING UP
sleep_disable(); // first thing after waking from sleep:
detachInterrupt(0); // disables interrupt 0 on pin 2
Serial.println("Woke up"😉;
mcp2515_wakeup();
cc = 0; //Zähler wird auf 0 gesetzt
}
int freeRam () {
extern int __heap_start, *__brkval;
int v;
return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}
// NOTE! Cannot wake up MCP2515 from sleep with this! Must use WAKIF interrupt!
bool MCP2515_set_op_mode(uint8_t mode)
{
mcp2515_bit_modify(CANCTRL, (1<<REQOP2)|(1<<REQOP1)|(1<<REQOP0), mode<<REQOP0);
delay(1);
return (MCP2515_get_op_mode()==mode);
}
void wakeUpNow() {
}

hr werden.

Spontan habe ich da jetzt nur:
Kofferraumentrieglung
Relais-Abfrage Licht
Standlicht
Innenraumbeleuchtung
Laderraumbeleuchtung
CCM-Lichtsensor Abfrage
Innenraumtemperatur Abfrage
Fensterheber Fahrer Beifahrer
Schloss Beifahrer
Schiebedach

Also für. Eine Komfortöffnung wären ja erstmal Schiebedach und Fensterheber Fahrer Beifahre ausreichend....wenn du die parat hast wäre das ja super...

Also ohne Schlüssel gelingt es den Motor direkt anzusteuern, dazu muss mindestens einmal eine Alive-Message vorher oder nachher gesendet werden, ansonsten stoppt das Fenster bei der Hälfte, da es zu einem Timeout kommt.

Fenster Fahrerseite:

runter:
ID: 000FFFFE Datensatz: 8F 43 B0 11 01 C1 02 00
40ms Pause
ID: 000FFFFE Datensatz: 49 02 00 00 00 00 00 00

rauf:
ID: 000FFFFE Datensatz: 8F 43 B0 11 01 C1 01 00
40ms Pause
ID: 000FFFFE Datensatz: 49 01 00 00 00 00 00 00

Aktivierung wird entfernt durch:
ID: 000FFFFE Datensatz: CC 43 B0 11 00 00 00 00

Fenster Beifahreseite

runter:
ID: 000FFFFE Datensatz: 8F 45 B0 11 01 C1 02 00
40ms Pause
ID: 000FFFFE Datensatz: 49 02 00 00 00 00 00 00

rauf:
ID: 000FFFFE Datensatz: 8F 45 B0 11 01 C1 01 00
40ms Pause
ID: 000FFFFE Datensatz: 49 01 00 00 00 00 00 00

Aktivierung wird entfernt durch:
ID: 000FFFFE Datensatz: CC 45 B0 00 00 00 00 00

Wenn weiter alle 4 Sekunden eine Alive-Message gesendet wird und die Aktivierung nicht entfernt wurde, versucht der Motor nach gewissen Zeitabständen das Fenster erneut in bewegung zu setzten. (Als ob man den Fensterheber nach oben betätigt obwohl schon das Fenster geschlossen ist).

Schiebedach:

Auf:
ID: 000FFFFE Datensatz: CF 47 B0 10 01 01 02 00

Zu:
ID: 000FFFFE Datensatz: CF 47 B0 10 01 01 01 00

Die Position des Fensters

auf der Fahrerseite beim 2001er Modell ist zu finden in der
ID: 00E030A2 5te Stelle bei 89 zu

Beifahrerseite:
ID: 00F01022 6te Stelle bei 90 zu

Die Position des Schiebedaches ist zu finden in
ID: 00A1102A grob unterteilt 3te Stelle 00 zu 01 wenig geöffnet 02 weiter geöffnet

Im 2002er Modell kann es für die Beifahrerseite 00F01022 und für die Fahrerseite 01C030A2 sein.

Kofferraum entriegeln:
ID: 000FFFFE Datensatz: 8F 46 B1 1A 21 01 00 02
Pause 15ms
ID: 000FFFFE Datensatz: 4C 00 00 02 E0 00 00 00

Standlicht
ID: 000FFFFE Datensatz: 8F 40 B1 1A 21 01 00 20
15ms Pause
ID: 000FFFFE Datensatz: 4E 00 00 00 20 00 00 00

Deaktivierung:
ID: 000FFFFE Datensatz: CD 40 B1 1A 21 00 00 00

Abblendlicht
ID: 000FFFFE Datensatz: 8F 40 B1 1A 21 01 00 08
15ms Pause
ID: 000FFFFE Datensatz: 4E 00 00 00 08 00 00 00

Deaktivierung:
ID: 000FFFFE Datensatz: CD 40 B1 1A 21 00 00 00

Innenraumbeleuchtung
ID: 000FFFFE Datensatz: 8F 47 B0 35 01 19 00 51
15ms Pause
ID: 000FFFFE Datensatz: 4A 00 00 00 00 00 00 00

Deaktivierung:
ID: 000FFFFE Datensatz: CC 47 B0 35 00 00 00 00

Laderaumbeleuchtung
ID: 000FFFFE Datensatz: 8F 47 B0 35 01 00 10 00
15ms Pause
ID: 000FFFFE Datensatz: 4A 00 20 00 00 00 00 00

Deaktivierung:
ID: 000FFFFE Datensatz: CC 47 B0 35 00 00 00 00

Anfrage Innenraumtemperatur
ID: 000FFFFE Datensatz: CC 29 A5 12 01 00 00 00

Antwort:
ID: 00801001 Datensatz: CC 29 E5 0F 5D 00 00 00

5te Stelle in Dezimal 0,5*x-40

Bsp. 5D in Dezimal 93
0,5*93-40 = 6,5 °C

Hi vielen vielen Dank für die Diagnosecodes....jetzt habe ich neben dem Komfortblinker auch die Komfortöffnunf programmiert...was allerdings nicht ohne Schlüssel im Schloss klappt sind ist das Schiebe dach...Kann es sein, dass du die Repeat-message vergessen hast ? Oder Gibt es die einfach nicht ?

Zitat:

Original geschrieben von DR_V70


Durch das Senden der Meldungen des Telefons lässt sich sogar das Tachodisplay zum Einstellen zusätzlicher Funktionen nutzen, der Hebel mit dem Drehring und dem Reset-Schalter wurde nachgerüstet, der Wagen selbst verfügt über keinen Boardcomputer:

Video

Kann man nur Messages auf dem Display anzeigen, wenn man ein Telefonmodul hat?

Ja das geht ohne Telefon, auf Olafs Blog im letzten Beitrag auf der zweiten Seite ganz unten ist ein Beispiel für das Telefon im 2002er Modell zu finden. Die Meldungen benötigen einen Abstand von etwa 30ms zueinander, ansonsten werden die Dinge nicht richtig dargestellt.

Mit dem Schiebedach ist mir heute auch aufgefallen, habe zumindest einen Ansatz gefunden. Dazu habe ich zügig den Traffic beim Einstecken des Schlüssel und beim Drehen auf Position 1 aufgenommen und schrittweise abgespielt. Bei einer Meldung kam es zum Klicken eines Relais im REM danach waren aber die Fensterheber samt Schalter freigeschaltet. Ein mehrfaches Senden erlaubte dann auch das Öffnen und Schließen des Schiebedaches. Habe mal in einem schwedischen Forum um Rat gefragt, vielleicht hat da jemand eine Idee.

Die gefundene Meldung ist:
ID 00513FFC Datensatz: 0D 00 1C 00 70 40 58 00

Die 5te Stelle scheint für den Zustand verantwortlich zu sein.

gekürzt können die Fenster mit der Meldung
ID 00513FFC Datensatz: 0D 00 00 00 00 40 00 00
wieder aktiviert werden.

ID 00513FFC Datensatz: 0D 00 00 00 00 41 00 00
entfernt diese Aktivierung wieder.

Fürs Schiebedach ist zusätzlich die 70 an 4ter Stelle nötig
ID 00513FFC Datensatz: 0D 00 00 00 70 41 00 00

Dabei fängt dann auch das Relais an zu klicken, die Meldung muss ca. 5mal gesendet werden damit das Schiebedach funktioniert. Halte dies bis jetzt nicht für zufriedenstellend um das Dach zu öffen.

Geht der Comfortblinker? Wie ist die Lösung? Habe dies zweifach mit millis() gelöst, ein Zählen der Meldungen scheint keinen Sinn zu machen, da bei einem delay() einige Meldungen entschwinden.

Komfortblinker funktioniert mit einem normalen Delay :
//Blinker links
if (message.id == 0x261300A && message.data[4] == 136) {
cantx(0xFFFFE, 0xCE, 0x48, 0xB0, 0x05, 0x01, 0x03, 0x02, 0x00);
delay(1700);
cantx(0xFFFFE, 0xCE, 0x48, 0xB0, 0x05, 0x00, 0x00, 0x00, 0x00);
}

Schien mir die einfachste Lösung.....

Rein theoretisch kannst du den Befehl für das Schiebedach doch in eine Schleife einbinden :

for (i = 0; i < 5000; i++){ // Abbruchoperation muss dann abgestimmt sein

cantx(0x0513FFC, 0x0D, 0x00, 0x00, 0x00, 0x70, 0x41, 0x00, 0x00); // Strom an

cantx(0xFFFFE, 0xCF, 0x47, 0xB0, 0x10, 0x01, 0x01, 0x02, 0x00); // Schiebedach auf

}

Wäre das eine Möglichkeit ?

Ein delay() funktioniert in diesem Falle zwar, blockiert aber die CPU für ganze 1700ms. Es können in dieser Zeit keine Meldungen mehr empfangen oder andere Dinge ausgewertet werden. Nötig wird dies wenn etwa das Display genutzt werden soll, wenn gleichzeitig der Blinker betätigt ist, oder das Skript noch andere Daten verarbeiten soll.

Eine Möglichkeit einen Timer zu realisieren bietet die Funktion millis().
Diese zählt die Zeit in ms die der Arduino an ist. Nach 4,294,967,295ms (49 Tage) kommt es zum Überlauf und die Zeit wird wieder von 0 an gezählt.

Soll beispielsweise etwa alle 3900ms eine Alive-Message gesendet werden könnte dies wie folgt realisiert werden:

Code:
unsigned long alive_timer; //Diese Variable wird global oben im Skript angelegt.
if((millis()-alive_timer)>3900){ //Alle 3900ms wird die Meldung gesendet
cantx(0xFFFFE, 0xD8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
alive_timer = millis(); //Der Aktuelle Zeit wird der Variablen übergeben
}

So prüft der Prozessor in jedem Schleifendurchlauf ob die Funktion erneut ausgeführt werden muss.
Als globale Variable muss eine unsigned long verwendet werden, da diese den maximalen Wert des Timers bis zum Überlauf abspeichern kann.

Idealerweise benötigt der Arduino für einen Vergleich, eine Addition und eine Subtraktion nur einen CPU-Cycle, dies sollte bei 16Millionen je Sekunde also kein Problem darstellen. Ein Delay von 1000ms hingegen verschenkt 16Mio Arbeitscyclen da der Prozessor nichts tun kann.

Auf zwei Timern welche mit millis() realisiert sind funktioniert auch eine mögliche Version des Comfort-Blinkers.

Code:
//Variablen welche global angelegt werden müssen
boolean cb_aktiv; //Speichert Zustand ob der C-Blinker aktiv ist.
boolean b_umgeschaltet; //Speichert Zustand ob der Blinkhebel umgeschaltet ist
boolean b_rechts; //Speichert Zustand wie zuletzt der Hebel gesetzt war
unsigned long b_an; //Speichert die Zeit die der Blinker normal betätigt war
unsigned long b_aktiv; // Speichert die Zeit die der C-Blinker an ist

Code:
//BEGINN BLINKFUNKTION//////
if (message.id == 0x111300A){ //Prüfen auf ID des Blinkers
if (b_umgeschaltet == true){ //Zählen der Zeit in welcher der Hebel gesetzt ist
if (message.data[4] == 132 || message.data[4] == 136){ //Prüfen der Richtung 132 R 136 L
b_an = millis(); //Zeit die Blinker an War wird an b_an übergeben
if (message.data[4] == 132){ //Speichert Zustand L oder R
b_rechts = true;
}else{
b_rechts = false;
}
b_umgeschaltet = false;
}
}
if (message.data[4] == 128){ //Wenn Blinkhebel wieder neutral 128
b_umgeschaltet = true;
if(millis()-b_an <= 700 && cb_aktiv == false){ //Überprüfung ob Blinker lang genug an war

if (b_rechts == true) {
cantx(0xFFFFE, 0xCE, 0x48, 0xB0, 0x05, 0x01, 0x03, 0x01, 0x00); //Aktiviere Blinker rechts
}else{
cantx(0xFFFFE, 0xCE, 0x48, 0xB0, 0x05, 0x01, 0x03, 0x02, 0x00); //Aktiviere Blinker links
}
cb_aktiv = true;
b_aktiv = millis();
}
}
}
if (cb_aktiv == true){
if (millis()-b_aktiv >= 1700){ //Wenn der Blinker länger als 1700ms an war folgt Deaktivierung
cantx(0xFFFFE, 0xCE, 0x48, 0xB0, 0x05, 0x00, 0x00, 0x00, 0x00); //Entferne Aktivierung der Blinker
Serial.println("Aktivierung entfernt"😉;
cb_aktiv = false;
}
}

Dies ist eine mögliche Version des Comfortblinkers, dieser löst nur aus wenn der Nutzer den Hebel unterhalb von 1000ms betätigt hat. Das Skript ist sicher programmiertechnisch nicht ideal, erfüllt die Funktion des Blinkers aber einwandfrei. Es muss lediglich darauf geachtet werden, das kein anderer Programmteil mehr als 1700ms Zeit in Anspruch nimmt, da ansonsten der Blinker zu spät wieder deaktiviert wird.

Und wie bekommt man heraus, welche Adresse das Dim hat? Die von Olaf funktioniert bei mir nicht🙁

Deine Antwort
Ähnliche Themen