CAN BUS - BMW E91 poblems with function/class

Hey guys,
I start playing with my car and get first results. The hardware is a Arduino Nano with a cheap MPC2515 and a 16x2 LCD.

The procedure looks like:

  • Init the CAN Module
  • send request like 0x6F1 84 12 F1 2C 10 07 6F on to the JBE (JunctionBoxElectronic) which gets passed to the ECU (DDE7.3)
  • the ECU respond with a standart 11bits CAN message like 0x612 84 F1 12 6C 10 0C 8A 99
    0C 8A stands for 47,86 °C engine temp

I have a lot of diferent readings from the ECU and each vlaue fom the ECU has his own request message.

I put some copy&paste some code together wich runs but without au function. Can somebody can help me with wrapping the request send and the recieving part in to a working function?

/* CAN BUS OBD2 - E9X
 -------PINOUT-------
 * LCD RS pin to digital pin 8
 * LCD Enable pin to digital pin 2
 * LCD D4 pin to digital pin 7
 * LCD D5 pin to digital pin 6
 * LCD D6 pin to digital pin 5
 * LCD D7 pin to digital pin 4
 * LCD R/W pin to ground
 * LCD VSS pin to ground
 * LCD VCC pin to 5V

 * CAN CS to PD 10
 * CAN SO to PD 11
 * CAN SI to PD 12
 * CAN SCK to PD 13
 * CAN INT to PD 9
 
 * Button_r to PD 3 
 * Button_u to PA 0
 
*/

#include <mcp_can.h>
#include <SPI.h>
#include <LiquidCrystal.h>

#define Button_r 3
//#define Button_u 0;
#define CAN0_INT 9                                                    // Set INT to pin 9
MCP_CAN CAN0(10);                                                     // Set CS to pin 10

LiquidCrystal lcd(8, 2, 7, 6, 5, 4);                                  // initialize the library with the numbers of the interface pins

int NB_page = 1;                                                             //Variable for page count
//int buttonPushCounter = 0;                                            // counter for the number of button presses
int buttonState = 0;                                                  // current state of the button
int lastButtonState = 0;                                              // previous state of the button
long unsigned int rxId;
unsigned char len = 0;
unsigned char rxBuf[8];
char lcdtemp[6];
byte data[8] = {0x12, 0x04, 0x2C, 0x10, 0x0A, 0xF1, 0x00, 0x00};       //Dataframe for Enginetemp request


void setup() {
 Serial.begin(115200);
 pinMode(Button_r, INPUT);
 lcd.begin(16, 2);                                                     // set up the LCD's number of columns and rows:
 if(CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_8MHZ) == CAN_OK){              // Initialize MCP2515 running at 8MHz with a baudrate of 500kb/s and the masks and filters disabled.
    lcd.print("Init OK!");
    delay(2000);
    //lcd.noDisplay();
 }else{
    lcd.print("Error Initializing MCP2515...");
    delay(2000);
    lcd.noDisplay();
    }    
//    CAN0.init_Mask(0,1,0x1FFFFFFF);                                   // Init first mask...
//    CAN0.init_Filt(0,1,0x612);
  CAN0.setMode(MCP_NORMAL);                                           // Set operation mode to normal so the MCP2515 sends acks to received data.  
  pinMode(CAN0_INT, INPUT);                                           // Configuring pin for /INT input
}


void loop() {
 buttonState = digitalRead(Button_r);  
 if (buttonState != lastButtonState) {
   if (buttonState == HIGH) {
     NB_page++;
     lcd.clear();
     lcd.setCursor(0,0);
     lcd.print(NB_page);
      if (NB_page > 2){
       NB_page = 1;    
       }
     }
   }
    delay(50);
    lastButtonState = buttonState;

 switch (NB_page){
  case 1:{
  byte sndStat = CAN0.sendMsgBuf(0x6F1, 0, 8, data);
  //Serial.print(sndStat);
  lcd.setCursor(0,0);                                                 // set the cursor to column 0, line 0
  lcd.print("Motortemp");
  if(sndStat == CAN_OK){
    if(!digitalRead(CAN0_INT)){                                             // If CAN0_INT pin is low, read receive buffer
      //Serial.print("Send - ok");
      CAN0.readMsgBuf(&rxId, &len, rxBuf);
      //Serial.print(rxId);
      if(rxId == 0x612){
        float temp = (((rxBuf[4]*256)+rxBuf[5])/**0,1)-273,14*/);              // calculate Enginetemp in °C
        temp = (temp/10)-273,14;
        dtostrf(temp,5,1,lcdtemp);
        lcd.setCursor(0,2);                                                 // set the cursor to column 0, line 0
        lcd.print(lcdtemp);
        lcd.print(" ");
        //lcd.setCursor(1,10);
        lcd.print((char)223);
        lcd.print("C");
      }
    }
   }
  }
  break;
 


 
  case 2:
  //byte sndStat = CAN0.sendMsgBuf(0x6F1, 0, 8, data);
  lcd.setCursor(0,0);                                                 // set the cursor to column 0, line 0
  lcd.print("Test - Page 2");
  // call function
  // do shit
  break;
 }
}

Thank you!

I try this

#include <LiquidCrystal.h>
#include <mcp_can.h>
#include <SPI.h>

#define Button_r 3
#define CAN0_INT 9                              // Set INT to pin 2
MCP_CAN CAN0(10);                               // Set CS to pin 10

LiquidCrystal lcd(8, 2, 7, 6, 5, 4);                                  // initialize the library with the numbers of the interface pins

char msgString[128];                        // Array to store serial string

int IDDDE = 0x612;
byte ITMOTtx[8] = {0x12, 0x04, 0x2C, 0x10, 0x0A, 0xF1, 0x00, 0x00};
int ITMOTrxID = 0x6F1;
char lcdtemp[6];

//byte INMOTtx[8];
//byte INMOTrx[8];

int NB_page = 1; 
int buttonState = 0;                                                  // current state of the button
int lastButtonState = 0; 



void setup() {
 Serial.begin(115200);
 pinMode(Button_r, INPUT);
 lcd.begin(16, 2);  
  // Initialize MCP2515 running at 8MHz with a baudrate of 500kb/s and the masks and filters disabled.
  if(CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_8MHZ) == CAN_OK){
    lcd.print("Init OK!");
    delay(2000);
    //lcd.noDisplay();
 }else{
    lcd.print("Error Initializing MCP2515...");
    delay(2000);
    lcd.noDisplay();
    }    
  CAN0.setMode(MCP_NORMAL);                     // Set operation mode to normal so the MCP2515 sends acks to received data.
  pinMode(CAN0_INT, INPUT);                            // Configuring pin for /INT input
}

void loop() {
 buttonState = digitalRead(Button_r);  
 if (buttonState != lastButtonState) {
   if (buttonState == HIGH) {
     NB_page++;
     lcd.clear();
     lcd.setCursor(0,0);
     lcd.print(NB_page);
      if (NB_page > 2){
       NB_page = 1;    
       }
     }
   }
   delay(50);
   lastButtonState = buttonState; 

 switch (NB_page){
  case 1:{
  lcd.setCursor(0,0);                                                 // set the cursor to column 0, line 0
  lcd.print("Motortemp");
  char ITMOTBuf[8]={0};
  //ITMOTBuf[8] = CANrxBuf(ITMOTrxID, IDDDE, ITMOTtx);

  ITMOTBuf[8] = *CANrxBuf(ITMOTrxID, IDDDE, ITMOTtx);
  float temp = (((ITMOTBuf[4]*256)+ITMOTBuf[5]));              // calculate Enginetemp in °C
        temp = (temp/10)-273,14;
        dtostrf(temp,5,1,lcdtemp);
        lcd.setCursor(0,2);                                                 // set the cursor to column 0, line 0
        lcd.print(lcdtemp);
        lcd.print(" ");
        lcd.setCursor(1,1);
        lcd.print((char)223);
        lcd.print("C");
  }
  break;

  case 2:{
  lcd.setCursor(0,0);                                                 // set the cursor to column 0, line 0
  lcd.print("Ladelufttemp");
//  unsigned char ITMOTBuf[8] = CANrxBuf(ITMOTrxID, IDDDE, ITMOTtx);
//  float temp = (((ITMOTBuf[4]*256)+ITMOTBuf[5]));              // calculate Enginetemp in °C
//        temp = (temp/10)-273,14;
//        dtostrf(temp,5,1,lcdtemp);
//        lcd.setCursor(0,2);                                                 // set the cursor to column 0, line 0
//        lcd.print(lcdtemp);
//        lcd.print(" ");
//        lcd.setCursor(0,0);
//        lcd.print((char)223);
//        lcd.print("C");
  }
  break;
}
}

//---------------------------------------*functions*---------------------------------------------//

char *CANrxBuf( /*int txID,*/ int IDc, byte data[8]){
  long unsigned int rxID;
  unsigned char len = 0;
  unsigned char rxBuf[8];
  //char msgString[128];                        // Array to store serial string

// send data:  ID = 0x100, Standard CAN Frame, Data length = 8 bytes, 'data' = array of data bytes to send
  byte sndStat = CAN0.sendMsgBuf(0x6F1, 0, 8, data);
  if(sndStat == CAN_OK){
    if(!digitalRead(CAN0_INT)){                         // If CAN0_INT pin is low, read receive buffer
       CAN0.readMsgBuf(&rxID, &len, rxBuf);      // Read data: len = data length, buf = data byte(s)
        if(rxID == IDc){
          for(byte i = 0; i<len; i++){
            sprintf(msgString, " 0x%.2X", rxBuf[i]);
            Serial.print(msgString);
            return msgString;
            //------OR-----------
            //if(rxID == IDc){
            //return rxBuf;
          }
        }
    }
  }
}

but it didn’t work. Can knowbody help me?

Hi,

I am also trying to query some values, mainly the DPF parameters (regenerations, ash, soot, engine temperatures,...)

Can you explain the meaning of the IDs you are using 0x6F1 and 0x612? And how to compose the query messages?

Is there any e90 CAN-BUS details available online?

Thanks!