forum.arduino.cc
Open in
urlscan Pro
2602:fd3f:1:ff02::4b
Public Scan
URL:
https://forum.arduino.cc/t/controlling-bmw-e90-instrument-cluster/670728/5
Submission: On April 27 via api from DE — Scanned from DE
Submission: On April 27 via api from DE — Scanned from DE
Form analysis
1 forms found in the DOMPOST /login
<form id="hidden-login-form" method="post" action="/login" style="display: none;">
<input name="username" type="text" id="signin_username">
<input name="password" type="password" id="signin_password">
<input name="redirect" type="hidden">
<input type="submit" id="signin-button" value="Anmelden">
</form>
Text Content
Arduino Forum CONTROLLING BMW E90 INSTRUMENT CLUSTER Using Arduino Project Guidance Terraviper-5 18. August 2020 um 19:11 1 Hello! I want to put a BMW E90 instrument cluster into a car that only has digital display. So I bought one off ebay thinking it would be a fairly straightforward job. To my mistake, most of people who did this years ago have posted links that are dead now and they themselves are not available any longer. 1319×400 197 KB I found the following resources * a blog with start CAN message * a wiring diagram * a forum thread where someone applied power to it (and another) * a list of sniffed CAN messages Several YT videos I bought a Seeed Can Bus Shield V2.0 and connected it to my Arduino Uno: and connected CAN-HI pin to supposed CAN-HI pin on the cluster and CAN-LO pin to CAN-LO of the cluster. I also connected 12V adapter to the cluster (+ to +, - to -) 490×700 128 KB the cluster does power on by wiggling the needles a bit and if I press the button on it, display turns on for about 15 seconds 723×400 62.7 KB but when I try to use the suggested turn-on CAN message, nothing happens. I tried both 500KBPS and 100KBPS, but still nothing. This is the code I used: #include <mcp_can.h> #include <SPI.h> /*SAMD core*/ #ifdef ARDUINO_SAMD_VARIANT_COMPLIANCE #define SERIAL SerialUSB #else #define SERIAL Serial #endif const int SPI_CS_PIN = 9; MCP_CAN CAN(SPI_CS_PIN); // Set CS pin void setup() { SERIAL.begin(115200); while (CAN_OK != CAN.begin(CAN_100KBPS)) { SERIAL.println("CAN BUS Shield init fail"); SERIAL.println(" Init CAN BUS Shield again"); delay(100); } SERIAL.println("CAN BUS Shield init ok!"); } byte data[8] = {0, 0, 0, 0, 0, 0, 0, 0}; void loop() { data[0] = 0x45; //0x45; /Key Status data[1] = 0x42; // 0x40; //Transponder Detected data[2] = 0x69; // 0x21; //Terminal Status data[3] = 0x8F; // Steering lock? data[4] = 0xE2; //Counter and Checksum CAN.sendMsgBuf(0x130, 0, 5, data); delay(100); // send data per 100ms } It is a direct combination of Seeed's example and start code from that blog, where I put in the wake-up message from that guy's blog, listed above. I checked the output of CAN shield with an oscilloscope and can confirm that it does look like something is being sent. Also, Arduino Uno sends me this message via serial Enter setting mode success set rate success!! Enter Normal Mode Success!! CAN BUS Shield init ok! I also tried the read example to see if the cluster sends any messages but I got nothing back. Im a bit puzzled. Does anybody have any suggestion please? Thank you! 1 „Gefällt mir“ BMW E90 CAN bus Instrument Cluster Terraviper-5 12. Dezember 2020 um 17:26 2 In the time elapsed I have made some progress. Initially I didnt connect the ground wire to arduino, thats why it didnt work. Here is correct pinout: 1 o o 10 2 o o 11 3 o o 12 4 o o 13 5 o o 14 6 C_H o o 15 7 C_L o o 16 8 o o 17 9 VCC o o GND 18 (Dont forget to connect GND to Arduino!) I managed to turn the cluster on, turn on the backlights and move the rpm needle. But I still cant do it consistently and everything in the same program. I read that cluster is picky about how messages and which messages come and at what intervals. I try reordering the message sends a bit, putting in delays and sometimes I manage to move the rpm needle, sometimes the lights turn on, but cant make it consistently useful. There is information that wake signal should be sent every 100ms but I cannot make it work even if I send it every 100ms. It even happened that I put into program message for turning rpm needle, then I reupload without this message and the rpm needle moves. Maybe there is something about how Seeed CAN Shield sends messages (buffers etc). I tested turning blinkers on by sending the command once in setup, but the cluster was acting as if it was spammed by that same command and showed CAN bus errors. Im starting to suspect there is something up with my CAN bus shield If anybody could shed any light onto this I would be very grateful! Here is the code: #include <SPI.h> #include "mcp2515_can.h" #define lo8(x) (uint8_t)((x)&0xff) #define hi8(x) (uint8_t)(((x) >> 8) & 0xff) const int SPI_CS_PIN = 9; const int CAN_INT_PIN = 2; mcp2515_can CAN(SPI_CS_PIN); // Set CS pin void sendIgnitionKeyOn() { uint16_t canId = 0x130; uint8_t len = 5; uint8_t buf[8] = {0, 0, 0, 0, 0, 0, 0, 0}; buf[0] = 0x45; // Key Status / T15 ON message buf[1] = 0x40; // Transponder Detected buf[2] = 0x21; // Terminal Status buf[3] = 0x8F; // Steering lock? buf[4] = 0xFE; // Counter and Checksum CAN.sendMsgBuf(canId, 0, len, buf); } void sendRPM(uint16_t rpm) { uint16_t tempRpm = rpm * 4; const uint16_t canId = 0x0AA; const uint8_t len = 8; uint8_t buf[8] = {0xFE, 0xFE, 0xFF, 0x00, 0x00, 0x00, 0xFE, 0x99}; buf[4] = lo8(tempRpm); buf[5] = hi8(tempRpm); CAN.sendMsgBuf(canId, 0, len, buf); } void sendLightsOn() { const uint16_t canId = 0x21A; const uint8_t len = 3; uint8_t buf[8] = {0b00000101, 0b00010000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; CAN.sendMsgBuf(canId, 0, len, buf); } void leftBlinkerOn() { const uint16_t canId = 0x1F6; const uint8_t len = 2; uint8_t buf[8] = {0x91, 0xF2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; CAN.sendMsgBuf(canId, 0, len, buf); } void rightBlinkerOn() { const uint16_t canId = 0x1F6; const uint8_t len = 2; uint8_t buf[8] = {0xA1, 0xF2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; CAN.sendMsgBuf(canId, 0, len, buf); } void sendFuelLevel(uint16_t litres) { uint16_t canId = 0x349; const uint8_t len = 5; uint8_t buf[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint16_t sensor1 = litres * 160; buf[0] = lo8(sensor1); buf[1] = hi8(sensor1); uint16_t sensor2 = sensor1; buf[2] = lo8(sensor2); buf[3] = hi8(sensor2); CAN.sendMsgBuf(canId, 0, len, buf); } void setup() { while (CAN_OK != CAN.begin(CAN_100KBPS)) { delay(100); } sendIgnitionKeyOn(); sendFuelLevel(24); sendLightsOn(); sendRPM(800); } List of can commands: CarPC Install xadonxander 12. Dezember 2020 um 21:37 3 You should be sending the can bus messages in a loop not in the setup. They are required to constantly receive the messages. I believe ignition on should be received about every 100ms and turn signals should be about 800ms. Terraviper-5 12. Dezember 2020 um 22:28 4 > xadonxander: > You should be sending the can bus messages in a loop not in the setup. They > are required to constantly receive the messages. I believe ignition on should > be received about every 100ms and turn signals should be about 800ms. Hello sir! I've tried putting messages into loop but it doesn't seem to work for me. Maybe the 0x130 ignition signal should have its counter increased, as it says here: CAN BUS Codes Byte 4 xx = 1.4 Second counter I tried doing this (incrementing those bits every 1400ms) but the cluster then keeps resetting For blinkers I did put it in loop: #include <SPI.h> #include "mcp2515_can.h" #define lo8(x) (uint8_t)((x)&0xff) #define hi8(x) (uint8_t)(((x) >> 8) & 0xff) const int SPI_CS_PIN = 9; const int CAN_INT_PIN = 2; mcp2515_can CAN(SPI_CS_PIN); // Set CS pin void sendIgnitionKeyOn() { uint16_t canId = 0x130; uint8_t len = 5; uint8_t buf[8] = {0, 0, 0, 0, 0, 0, 0, 0}; buf[0] = 0x45; // Key Status / T15 ON message buf[1] = 0x40; // Transponder Detected buf[2] = 0x21; // Terminal Status buf[3] = 0x8F; // Steering lock? buf[4] = 0xFE; // Counter and Checksum CAN.sendMsgBuf(canId, 0, len, buf); } void sendRPM(uint16_t rpm) { uint16_t tempRpm = rpm * 4; const uint16_t canId = 0x0AA; const uint8_t len = 8; uint8_t buf[8] = {0xFE, 0xFE, 0xFF, 0x00, 0x00, 0x00, 0xFE, 0x99}; buf[4] = lo8(tempRpm); buf[5] = hi8(tempRpm); CAN.sendMsgBuf(canId, 0, len, buf); } void sendLightsOn() { const uint16_t canId = 0x21A; const uint8_t len = 3; uint8_t buf[8] = {0b00000101, 0b00010000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; CAN.sendMsgBuf(canId, 0, len, buf); } void leftBlinkerOnInitial() { const uint16_t canId = 0x1F6; const uint8_t len = 2; uint8_t buf[8] = {0x91, 0xF2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; CAN.sendMsgBuf(canId, 0, len, buf); } void rightBlinkerOnInitial() { const uint16_t canId = 0x1F6; const uint8_t len = 2; uint8_t buf[8] = {0xA1, 0xF2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; CAN.sendMsgBuf(canId, 0, len, buf); } void keepLeftBlinkerOn() { const uint16_t canId = 0x1F6; const uint8_t len = 2; uint8_t buf[8] = {0x91, 0xF1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; CAN.sendMsgBuf(canId, 0, len, buf); } void keepRightBlinkerOn() { const uint16_t canId = 0x1F6; const uint8_t len = 2; uint8_t buf[8] = {0xA1, 0xF1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; CAN.sendMsgBuf(canId, 0, len, buf); } void sendFuelLevel(uint16_t litres) { uint16_t canId = 0x349; const uint8_t len = 5; uint8_t buf[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint16_t sensor1 = litres * 160; buf[0] = lo8(sensor1); buf[1] = hi8(sensor1); uint16_t sensor2 = sensor1; buf[2] = lo8(sensor2); buf[3] = hi8(sensor2); CAN.sendMsgBuf(canId, 0, len, buf); } uint32_t timestamp100ms = 0; uint32_t timestamp800ms = 0; bool firstBlinkerTurnOn = true; void setup() { while (CAN_OK != CAN.begin(CAN_100KBPS)) { delay(100); } } void loop() { if (millis() - timestamp100ms > 99) { sendIgnitionKeyOn(); timestamp100ms = millis(); } if (millis() - timestamp800ms > 799) { // Turn blinker on after 30 seconds to avoid kombi // missing the initial message when its turning on if (millis() > 30000) { if (firstBlinkerTurnOn == true) { leftBlinkerOnInitial(); firstBlinkerTurnOn = false; } keepLeftBlinkerOn(); } timestamp800ms = millis(); } } and the kombi does turn on after a few seconds, warning lights flash, but then turn off after about 2 seconds. The screen stays on but nothing else happens (if I understood correctly on how to use them: CAN BUS Codes) 1F6 2 91 F1 145 241 Left turn signal on (sent following initial 242) 1F6 2 91 F2 145 242 Left turn signal on (sent first, followed by 241) Im really at a loss I was so happy when they turned on but then I hit a brick wall Terraviper-5 13. Dezember 2020 um 20:51 5 Okay I have found this Arduino forum thread CAN line doesn't update: MCP2515, mcp_can.h - Networking, Protocols, and Devices - Arduino Forum and basically it sounds exactly whats happening to me. I didn't try with the scope, but symptoms sound similar. So I tried this guy's solution and switched to this lib he is talking about. I googled that SPI bandwidth of mcp2515 is 1Mbps, so I adjusted accordingly. And now I'm at the same spot as this guy: E90 Can bus project (E60, E65, E87....) - Page 2 The kombi is going through reset sequence all the time like its missing something How it looks like: http://shrani.si/f/4/GQ/1TTxeB2f/1/vid20201213212805.gif Code #include <CAN.h> #define lo8(x) (uint8_t)((x)&0xff) #define hi8(x) (uint8_t)(((x) >> 8) & 0xff) const uint8_t CS_PIN = 9; const uint8_t IRQ_PIN = 2; void sendIgnitionKeyOn() { CAN.beginPacket(0x130); CAN.write(0x45); CAN.write(0x40); CAN.write(0x21); CAN.write(0x8F); CAN.write(0xFE); CAN.endPacket(); } void sendRPM(uint16_t rpm) { uint16_t tempRpm = rpm * 4; CAN.beginPacket(0x0AA); CAN.write(0xFE); CAN.write(0xFE); CAN.write(0xFF); CAN.write(0x00); CAN.write(lo8(tempRpm)); CAN.write(hi8(tempRpm)); CAN.write(0xFE); CAN.write(0x99); CAN.endPacket(); } void sendIgnitionStatus() { CAN.beginPacket(0x26E); CAN.write(0x40); CAN.write(0x40); CAN.write(0x7F); CAN.write(0x50); CAN.write(0xFF); CAN.write(0xFF); CAN.write(0xFF); CAN.write(0xFF); CAN.endPacket(); } void sendFuelLevel(uint16_t litres) { uint16_t sensor = litres * 160; CAN.beginPacket(0x349); CAN.write(lo8(sensor)); CAN.write(hi8(sensor)); CAN.write(lo8(sensor)); CAN.write(hi8(sensor)); CAN.write(0x00); CAN.endPacket(); } void sendAirbagSeatbeltCounter() { static uint8_t count = 0x00; CAN.beginPacket(0x0D7); CAN.write(count); CAN.write(0xFF); CAN.endPacket(); count++; } void sendABSBrakeCounter2() { CAN.beginPacket(0x19E); CAN.write(0x00); CAN.write(0xE0); CAN.write(0xB3); CAN.write(0xFC); CAN.write(0xF0); CAN.write(0x43); CAN.write(0x00); CAN.write(0x65); CAN.endPacket(); } void sendABSBrakeCounter1() { static uint8_t count = 0xF0; CAN.beginPacket(0x0C0); CAN.write(count); CAN.write(0xFF); CAN.endPacket(); count++; if (count == 0x00) { count = 0xF0; } } void seatbeltLight(bool state) { uint8_t thirdBit; if (state == false) { CAN.beginPacket(0x581); thirdBit = 0x28; } else { CAN.beginPacket(0x394); thirdBit = 0x029; } CAN.write(0x40); CAN.write(0x4D); CAN.write(0x00); CAN.write(thirdBit); CAN.write(0xFF); CAN.write(0xFF); CAN.write(0xFF); CAN.write(0xFF); CAN.endPacket(); } void sendSpeed(uint16_t speed) { static uint32_t lastTimeSent = 0; static uint16_t lastReading = 0; static uint16_t count = 0xF000; uint16_t speedValToSend = ((millis() - lastTimeSent) / 50) * speed / 2; speedValToSend += lastReading; lastReading = speedValToSend; lastTimeSent = millis(); CAN.beginPacket(0x1A6); CAN.write(lo8(speedValToSend)); CAN.write(hi8(speedValToSend)); CAN.write(lo8(speedValToSend)); CAN.write(hi8(speedValToSend)); CAN.write(lo8(speedValToSend)); CAN.write(hi8(speedValToSend)); CAN.write(lo8(count)); CAN.write(hi8(count)); CAN.endPacket(); } void sendLightsOff() { CAN.beginPacket(0x21A); CAN.write(0b00000000); CAN.write(0b00000000); CAN.write(0x00); CAN.endPacket(); } uint32_t timestamp100ms = 0; uint32_t timestamp200ms = 0; void setup() { Serial.begin(115200); while (!Serial) { }; CAN.setPins(CS_PIN, IRQ_PIN); CAN.setSPIFrequency(1E6); while (!CAN.begin(100E3)) { Serial.println("CAN BUS Shield init fail"); Serial.println(" Init CAN BUS Shield again"); delay(100); } Serial.println("CAN BUS Shield init ok!"); timestamp100ms = millis(); timestamp200ms = millis(); } void loop() { if (millis() - timestamp100ms > 99) { sendIgnitionKeyOn(); sendRPM(800); sendSpeed(0); timestamp100ms = millis(); } if (millis() - timestamp200ms > 199) { sendFuelLevel(24); sendIgnitionStatus(); sendAirbagSeatbeltCounter(); sendABSBrakeCounter2(); sendABSBrakeCounter1(); seatbeltLight(false); sendLightsOff(); timestamp200ms = millis(); } } Terraviper-5 15. Dezember 2020 um 22:50 6 Found out what problem was under this video It was the termination resistor (trace marked P1) on Seeed CAN bus shield that was disrupting communication. When I cut the trace everything worked More info about E90 cluster control: gitHub link system Geschlossen, 5. Mai 2021 um 19:18 7 * Startseite * Kategorien * FAQ/Richtlinien * Nutzungsbedingungen * Datenschutzerklärung Angetrieben von Discourse, beste Erfahrung mit aktiviertem JavaScript Zum Hauptinhalt springen * Arduino.cc * Professional * Education * Store IoT Cloud Web Editor Manager for Linux Anmelden CONTROLLING BMW E90 INSTRUMENT CLUSTER Using ArduinoProject Guidance Anmelden * * Custom dashboards, smartphone remote control, data sharing between boards, remote uploads. Get them (for free) using your forum account! CONTROLLING BMW E90 INSTRUMENT CLUSTER Using ArduinoProject Guidance Du hast 0 Beiträge ausgewählt. alle auswählen Auswahlvorgang abbrechen Aug. 2020 5/7 Dez. 2020 Mai 2021 Terraviper-5 1 Aug. '20post #1 Hello! I want to put a BMW E90 instrument cluster into a car that only has digital display. So I bought one off ebay thinking it would be a fairly straightforward job. To my mistake, most of people who did this years ago have posted links that are dead now and they themselves are not available any longer. 1319×400 197 KB I found the following resources * a blog 191 with start CAN message * a wiring diagram 303 * a forum thread 98 where someone applied power to it (and another 37) * a list of 296 sniffed CAN messages Several YT videos E90 cluster being driven by Can bus from an Arduino BMW E90 KOMBI bench setup. No error lights. No needle skip. E90 Test Bench LS3 BMW E90 instrument cluster powered on the bench /zalaczenie zegarow I bought a Seeed Can Bus Shield V2.0 and connected it to my Arduino Uno: and connected CAN-HI pin to supposed CAN-HI pin on the cluster and CAN-LO pin to CAN-LO of the cluster. I also connected 12V adapter to the cluster (+ to +, - to -) 490×700 128 KB the cluster does power on by wiggling the needles a bit and if I press the button on it, display turns on for about 15 seconds 723×400 62.7 KB but when I try to use the suggested turn-on CAN message, nothing happens. I tried both 500KBPS and 100KBPS, but still nothing. This is the code I used: #include <mcp_can.h> #include <SPI.h> /*SAMD core*/ #ifdef ARDUINO_SAMD_VARIANT_COMPLIANCE #define SERIAL SerialUSB #else #define SERIAL Serial #endif const int SPI_CS_PIN = 9; MCP_CAN CAN(SPI_CS_PIN); // Set CS pin void setup() { SERIAL.begin(115200); while (CAN_OK != CAN.begin(CAN_100KBPS)) { SERIAL.println("CAN BUS Shield init fail"); SERIAL.println(" Init CAN BUS Shield again"); delay(100); } SERIAL.println("CAN BUS Shield init ok!"); } byte data[8] = {0, 0, 0, 0, 0, 0, 0, 0}; void loop() { data[0] = 0x45; //0x45; /Key Status data[1] = 0x42; // 0x40; //Transponder Detected data[2] = 0x69; // 0x21; //Terminal Status data[3] = 0x8F; // Steering lock? data[4] = 0xE2; //Counter and Checksum CAN.sendMsgBuf(0x130, 0, 5, data); delay(100); // send data per 100ms } It is a direct combination of Seeed's example and start code from that blog, where I put in the wake-up message from that guy's blog, listed above. I checked the output of CAN shield with an oscilloscope and can confirm that it does look like something is being sent. Also, Arduino Uno sends me this message via serial Enter setting mode success set rate success!! Enter Normal Mode Success!! CAN BUS Shield init ok! I also tried the read example to see if the cluster sends any messages but I got nothing back. Im a bit puzzled. Does anybody have any suggestion please? Thank you! 1 * BMW E90 CAN bus Instrument Cluster12 * ERSTELLT Aug. '20 * LETZTE ANTW. Mai '21 * 6 ANTWORTEN * 10,3 T. AUFRUFE * 2 BENUTZER * 1 „GEFÄLLT MIR“ * 17 LINKS * 5 4 Monate später Terraviper-5 Dez. '20post #2 In the time elapsed I have made some progress. Initially I didnt connect the ground wire to arduino, thats why it didnt work. Here is correct pinout: 1 o o 10 2 o o 11 3 o o 12 4 o o 13 5 o o 14 6 C_H o o 15 7 C_L o o 16 8 o o 17 9 VCC o o GND 18 (Dont forget to connect GND to Arduino!) I managed to turn the cluster on, turn on the backlights and move the rpm needle. But I still cant do it consistently and everything in the same program. I read that cluster is picky about how messages and which messages come and at what intervals. I try reordering the message sends a bit, putting in delays and sometimes I manage to move the rpm needle, sometimes the lights turn on, but cant make it consistently useful. There is information that wake signal should be sent every 100ms but I cannot make it work even if I send it every 100ms. It even happened that I put into program message for turning rpm needle, then I reupload without this message and the rpm needle moves. Maybe there is something about how Seeed CAN Shield sends messages (buffers etc). I tested turning blinkers on by sending the command once in setup, but the cluster was acting as if it was spammed by that same command and showed CAN bus errors. Im starting to suspect there is something up with my CAN bus shield If anybody could shed any light onto this I would be very grateful! Here is the code: #include <SPI.h> #include "mcp2515_can.h" #define lo8(x) (uint8_t)((x)&0xff) #define hi8(x) (uint8_t)(((x) >> 8) & 0xff) const int SPI_CS_PIN = 9; const int CAN_INT_PIN = 2; mcp2515_can CAN(SPI_CS_PIN); // Set CS pin void sendIgnitionKeyOn() { uint16_t canId = 0x130; uint8_t len = 5; uint8_t buf[8] = {0, 0, 0, 0, 0, 0, 0, 0}; buf[0] = 0x45; // Key Status / T15 ON message buf[1] = 0x40; // Transponder Detected buf[2] = 0x21; // Terminal Status buf[3] = 0x8F; // Steering lock? buf[4] = 0xFE; // Counter and Checksum CAN.sendMsgBuf(canId, 0, len, buf); } void sendRPM(uint16_t rpm) { uint16_t tempRpm = rpm * 4; const uint16_t canId = 0x0AA; const uint8_t len = 8; uint8_t buf[8] = {0xFE, 0xFE, 0xFF, 0x00, 0x00, 0x00, 0xFE, 0x99}; buf[4] = lo8(tempRpm); buf[5] = hi8(tempRpm); CAN.sendMsgBuf(canId, 0, len, buf); } void sendLightsOn() { const uint16_t canId = 0x21A; const uint8_t len = 3; uint8_t buf[8] = {0b00000101, 0b00010000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; CAN.sendMsgBuf(canId, 0, len, buf); } void leftBlinkerOn() { const uint16_t canId = 0x1F6; const uint8_t len = 2; uint8_t buf[8] = {0x91, 0xF2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; CAN.sendMsgBuf(canId, 0, len, buf); } void rightBlinkerOn() { const uint16_t canId = 0x1F6; const uint8_t len = 2; uint8_t buf[8] = {0xA1, 0xF2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; CAN.sendMsgBuf(canId, 0, len, buf); } void sendFuelLevel(uint16_t litres) { uint16_t canId = 0x349; const uint8_t len = 5; uint8_t buf[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint16_t sensor1 = litres * 160; buf[0] = lo8(sensor1); buf[1] = hi8(sensor1); uint16_t sensor2 = sensor1; buf[2] = lo8(sensor2); buf[3] = hi8(sensor2); CAN.sendMsgBuf(canId, 0, len, buf); } void setup() { while (CAN_OK != CAN.begin(CAN_100KBPS)) { delay(100); } sendIgnitionKeyOn(); sendFuelLevel(24); sendLightsOn(); sendRPM(800); } List of can commands: CarPC Install 79 xadonxander Dez. '20post #3 You should be sending the can bus messages in a loop not in the setup. They are required to constantly receive the messages. I believe ignition on should be received about every 100ms and turn signals should be about 800ms. Terraviper-5 Dez. '20post #4 > xadonxander: > You should be sending the can bus messages in a loop not in the setup. They > are required to constantly receive the messages. I believe ignition on should > be received about every 100ms and turn signals should be about 800ms. Hello sir! I've tried putting messages into loop but it doesn't seem to work for me. Maybe the 0x130 ignition signal should have its counter increased, as it says here: CAN BUS Codes 67 Byte 4 xx = 1.4 Second counter I tried doing this (incrementing those bits every 1400ms) but the cluster then keeps resetting For blinkers I did put it in loop: #include <SPI.h> #include "mcp2515_can.h" #define lo8(x) (uint8_t)((x)&0xff) #define hi8(x) (uint8_t)(((x) >> 8) & 0xff) const int SPI_CS_PIN = 9; const int CAN_INT_PIN = 2; mcp2515_can CAN(SPI_CS_PIN); // Set CS pin void sendIgnitionKeyOn() { uint16_t canId = 0x130; uint8_t len = 5; uint8_t buf[8] = {0, 0, 0, 0, 0, 0, 0, 0}; buf[0] = 0x45; // Key Status / T15 ON message buf[1] = 0x40; // Transponder Detected buf[2] = 0x21; // Terminal Status buf[3] = 0x8F; // Steering lock? buf[4] = 0xFE; // Counter and Checksum CAN.sendMsgBuf(canId, 0, len, buf); } void sendRPM(uint16_t rpm) { uint16_t tempRpm = rpm * 4; const uint16_t canId = 0x0AA; const uint8_t len = 8; uint8_t buf[8] = {0xFE, 0xFE, 0xFF, 0x00, 0x00, 0x00, 0xFE, 0x99}; buf[4] = lo8(tempRpm); buf[5] = hi8(tempRpm); CAN.sendMsgBuf(canId, 0, len, buf); } void sendLightsOn() { const uint16_t canId = 0x21A; const uint8_t len = 3; uint8_t buf[8] = {0b00000101, 0b00010000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; CAN.sendMsgBuf(canId, 0, len, buf); } void leftBlinkerOnInitial() { const uint16_t canId = 0x1F6; const uint8_t len = 2; uint8_t buf[8] = {0x91, 0xF2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; CAN.sendMsgBuf(canId, 0, len, buf); } void rightBlinkerOnInitial() { const uint16_t canId = 0x1F6; const uint8_t len = 2; uint8_t buf[8] = {0xA1, 0xF2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; CAN.sendMsgBuf(canId, 0, len, buf); } void keepLeftBlinkerOn() { const uint16_t canId = 0x1F6; const uint8_t len = 2; uint8_t buf[8] = {0x91, 0xF1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; CAN.sendMsgBuf(canId, 0, len, buf); } void keepRightBlinkerOn() { const uint16_t canId = 0x1F6; const uint8_t len = 2; uint8_t buf[8] = {0xA1, 0xF1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; CAN.sendMsgBuf(canId, 0, len, buf); } void sendFuelLevel(uint16_t litres) { uint16_t canId = 0x349; const uint8_t len = 5; uint8_t buf[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint16_t sensor1 = litres * 160; buf[0] = lo8(sensor1); buf[1] = hi8(sensor1); uint16_t sensor2 = sensor1; buf[2] = lo8(sensor2); buf[3] = hi8(sensor2); CAN.sendMsgBuf(canId, 0, len, buf); } uint32_t timestamp100ms = 0; uint32_t timestamp800ms = 0; bool firstBlinkerTurnOn = true; void setup() { while (CAN_OK != CAN.begin(CAN_100KBPS)) { delay(100); } } void loop() { if (millis() - timestamp100ms > 99) { sendIgnitionKeyOn(); timestamp100ms = millis(); } if (millis() - timestamp800ms > 799) { // Turn blinker on after 30 seconds to avoid kombi // missing the initial message when its turning on if (millis() > 30000) { if (firstBlinkerTurnOn == true) { leftBlinkerOnInitial(); firstBlinkerTurnOn = false; } keepLeftBlinkerOn(); } timestamp800ms = millis(); } } and the kombi does turn on after a few seconds, warning lights flash, but then turn off after about 2 seconds. The screen stays on but nothing else happens (if I understood correctly on how to use them: CAN BUS Codes 37) 1F6 2 91 F1 145 241 Left turn signal on (sent following initial 242) 1F6 2 91 F2 145 242 Left turn signal on (sent first, followed by 241) Im really at a loss I was so happy when they turned on but then I hit a brick wall Terraviper-5 Dez. '20post #5 Okay I have found this Arduino forum thread CAN line doesn't update: MCP2515, mcp_can.h - Networking, Protocols, and Devices - Arduino Forum 68 and basically it sounds exactly whats happening to me. I didn't try with the scope, but symptoms sound similar. So I tried this guy's solution and switched to this lib he is talking about. I googled that SPI bandwidth of mcp2515 is 1Mbps, so I adjusted accordingly. And now I'm at the same spot as this guy: E90 Can bus project (E60, E65, E87....) - Page 2 105 The kombi is going through reset sequence all the time like its missing something How it looks like: http://shrani.si/f/4/GQ/1TTxeB2f/1/vid20201213212805.gif 144 Code #include <CAN.h> #define lo8(x) (uint8_t)((x)&0xff) #define hi8(x) (uint8_t)(((x) >> 8) & 0xff) const uint8_t CS_PIN = 9; const uint8_t IRQ_PIN = 2; void sendIgnitionKeyOn() { CAN.beginPacket(0x130); CAN.write(0x45); CAN.write(0x40); CAN.write(0x21); CAN.write(0x8F); CAN.write(0xFE); CAN.endPacket(); } void sendRPM(uint16_t rpm) { uint16_t tempRpm = rpm * 4; CAN.beginPacket(0x0AA); CAN.write(0xFE); CAN.write(0xFE); CAN.write(0xFF); CAN.write(0x00); CAN.write(lo8(tempRpm)); CAN.write(hi8(tempRpm)); CAN.write(0xFE); CAN.write(0x99); CAN.endPacket(); } void sendIgnitionStatus() { CAN.beginPacket(0x26E); CAN.write(0x40); CAN.write(0x40); CAN.write(0x7F); CAN.write(0x50); CAN.write(0xFF); CAN.write(0xFF); CAN.write(0xFF); CAN.write(0xFF); CAN.endPacket(); } void sendFuelLevel(uint16_t litres) { uint16_t sensor = litres * 160; CAN.beginPacket(0x349); CAN.write(lo8(sensor)); CAN.write(hi8(sensor)); CAN.write(lo8(sensor)); CAN.write(hi8(sensor)); CAN.write(0x00); CAN.endPacket(); } void sendAirbagSeatbeltCounter() { static uint8_t count = 0x00; CAN.beginPacket(0x0D7); CAN.write(count); CAN.write(0xFF); CAN.endPacket(); count++; } void sendABSBrakeCounter2() { CAN.beginPacket(0x19E); CAN.write(0x00); CAN.write(0xE0); CAN.write(0xB3); CAN.write(0xFC); CAN.write(0xF0); CAN.write(0x43); CAN.write(0x00); CAN.write(0x65); CAN.endPacket(); } void sendABSBrakeCounter1() { static uint8_t count = 0xF0; CAN.beginPacket(0x0C0); CAN.write(count); CAN.write(0xFF); CAN.endPacket(); count++; if (count == 0x00) { count = 0xF0; } } void seatbeltLight(bool state) { uint8_t thirdBit; if (state == false) { CAN.beginPacket(0x581); thirdBit = 0x28; } else { CAN.beginPacket(0x394); thirdBit = 0x029; } CAN.write(0x40); CAN.write(0x4D); CAN.write(0x00); CAN.write(thirdBit); CAN.write(0xFF); CAN.write(0xFF); CAN.write(0xFF); CAN.write(0xFF); CAN.endPacket(); } void sendSpeed(uint16_t speed) { static uint32_t lastTimeSent = 0; static uint16_t lastReading = 0; static uint16_t count = 0xF000; uint16_t speedValToSend = ((millis() - lastTimeSent) / 50) * speed / 2; speedValToSend += lastReading; lastReading = speedValToSend; lastTimeSent = millis(); CAN.beginPacket(0x1A6); CAN.write(lo8(speedValToSend)); CAN.write(hi8(speedValToSend)); CAN.write(lo8(speedValToSend)); CAN.write(hi8(speedValToSend)); CAN.write(lo8(speedValToSend)); CAN.write(hi8(speedValToSend)); CAN.write(lo8(count)); CAN.write(hi8(count)); CAN.endPacket(); } void sendLightsOff() { CAN.beginPacket(0x21A); CAN.write(0b00000000); CAN.write(0b00000000); CAN.write(0x00); CAN.endPacket(); } uint32_t timestamp100ms = 0; uint32_t timestamp200ms = 0; void setup() { Serial.begin(115200); while (!Serial) { }; CAN.setPins(CS_PIN, IRQ_PIN); CAN.setSPIFrequency(1E6); while (!CAN.begin(100E3)) { Serial.println("CAN BUS Shield init fail"); Serial.println(" Init CAN BUS Shield again"); delay(100); } Serial.println("CAN BUS Shield init ok!"); timestamp100ms = millis(); timestamp200ms = millis(); } void loop() { if (millis() - timestamp100ms > 99) { sendIgnitionKeyOn(); sendRPM(800); sendSpeed(0); timestamp100ms = millis(); } if (millis() - timestamp200ms > 199) { sendFuelLevel(24); sendIgnitionStatus(); sendAirbagSeatbeltCounter(); sendABSBrakeCounter2(); sendABSBrakeCounter1(); seatbeltLight(false); sendLightsOff(); timestamp200ms = millis(); } } Terraviper-5 Dez. '20post #6 Found out what problem was under this 149video It was the termination resistor (trace marked P1) on Seeed CAN bus shield that was disrupting communication. When I cut the trace everything worked More info about E90 cluster control: gitHub link 393 5 Monate später Geschlossen, am 5. Mai '21 Antworten VORGESCHLAGENE THEMEN Thema Antworten Aufrufe Aktivität WiFi controller Project Guidance 15 117 2. Jan. Difference between atmega16u2-uno-wifi-r3 and Arduino UNO wifi rev2 Project Guidance 3 159 Dez. '22 Controlling a motor using a 12V line , and using arduino to vary resistance Project Guidance 7 110 Dez. '22 Uploading code through a 1/4" Male Audio Jack via Serial Project Guidance 12 184 Nov. '22 Passing time from main to class by pointer as reference Project Guidance 3 118 8. Feb. WILLST DU MEHR LESEN? DURCHSTÖBERE ANDERE THEMEN IN PROJECT GUIDANCE ODER SIEH DIR DIE AKTUELLEN THEMEN AN. Teilen Back to top * Help Center * Contact Us * Trademark & Copyright * Brand Guidelines * Distributors * Careers FOLLOW US * * * * * * © 2020 Arduino * Careers * Terms of Service * Privacy Policy * Security * Cookie Settings Invalid date Invalid date We use cookies 🍪 Our websites use cookies (also from third parties) for functional and analytical purposes, and to show you personalised advertisement. You can adjust this in Cookie Settings or learn more by reading our cookie policy. Learn more and customize ONLY REQUIREDACCEPT ALL