CAN no readings MCP2515

Good evening everyone,

I'm currently working on a project that involves connecting an MCP2515 and an Arduino UNO to talk to my Renault car's OBD2 interface.

Here's how my setup looks right now, with the MCP2515 pins on the left and the corresponding Arduino pins on the right:

INT  -> D2
SCK  -> D13
SI   -> D11
SO   -> D12
CS   -> D10 
VCC  -> 5V Arduino
GND  -> GND Arduino

I've been reading through some forums where people had trouble because they didn't use the ground (GND) of the car correctly.

This post about Fiat cars caught my eye: Reaading OBD canbus on Fiat?

Following their advice, I connected the SIGNAL GND and CHASSIS GND to the GND of the Arduino. Specifically, I connected pins 4 and 5 from the OBD connector together and linked them to the Arduino's GND.

Here's a diagram showing the pins for Renault's OBD:

This is the code I'm using:

#include <SPI.h>
#include <mcp2515.h>

struct can_frame canMsg;
MCP2515 mcp2515(10);

void setup() {
  Serial.begin(115200);
  
  mcp2515.reset();
  mcp2515.setBitrate(CAN_500KBPS,MCP_8MHZ);
  mcp2515.setNormalMode();
  
  Serial.println("------- CAN Read ----------");
  Serial.println("ID  DLC   DATA");
}

void loop() {
  if (mcp2515.readMessage(&canMsg) == MCP2515::ERROR_OK) {
    Serial.print(canMsg.can_id, HEX); // print ID
    Serial.print(" "); 
    Serial.print(canMsg.can_dlc, HEX); // print DLC
    Serial.print(" ");
    
    for (int i = 0; i<canMsg.can_dlc; i++)  {  // print the data
      Serial.print(canMsg.data[i],HEX);
      Serial.print(" ");
    }

    Serial.println();      
  }
}

I made sure to change this line mcp2515.setBitrate(CAN_500KBPS,MCP_8MHZ); to match my MCP2515's 8MHz quartz, like the library's instructions said:

You can also set oscillator frequency for module when setting bitrate: mcp2515.setBitrate(CAN_500KBPS, MCP_8MHZ);

But despite all this, nothing seems to be working.

I even tried sending CAN bus messages with the MCP2515 to check if it was the issue, but my oscilloscope readings indicate that the connection between the Arduino and MCP2515 is okay, and the MCP2515 itself is working because I can see changes on the screen of the oscilloscope.

I've tried different speeds using mcp2515.setBitrate, different libraries, various tutorials, and even tested with and without the 120 ohms jumper, but nothing has worked so far.

For the 120 ohms jumper I used the one on the board :

If anyone as a suggestion it would be very helpful :pray:

Thanks !

The OBD2 interface works as a request and response system using PIDs. See

Lots of mistooks, you are using unknown hardware to communicate with an unknown interface on an unfamiliar system. This makes it very hard. Schematics, not frizzes would make your question easier to understand. Show your termination scheme.

Renault and Fiat are different vehicles, probably different years as well. Hint there messages are not necessary the same. Messages on the OBDII connector are in several groups, starting with CARB (California Resources Board) federal required messages, dealer messages, user messages and probably several others, depends on year, make, model, etc.

I suggest you start with another UNO and make another unit and get them talking first, if you are not successful with that you will more then likely not talk to the vehicle. Cory Fowler's mcp_can library works very well and has both ".ino" files for send and receive.

Many vehicles use a gateway to communicate the OBDII connector, this allows them to control what information is leaving the car and control what comes in. Hopefully you know putting the wrong data on the vehicle bus can damage the vehicle. What is the vehicle's can bit rate?

Do you understand IFR (In Frame Response), you can check that with your scope. Hint it is the Ack (Acknowledge) bit. What about when there is a bus collision or error? This is part of what you might run into in debugging your system.

Use one of the example codes supplied in the library for the 2515.

You have to request the PID you want and the reply gives the data , which you then need to decode

Hello, is this the code I should use for the PID request ?
I tested it but nothing came from the car and when I try to decomment : //CAN0.setMode(MCP_LOOPBACK); the Serial correctly outputs data like this :

09:26:52.284 -> Message Sent Successfully! 09:26:52.284 -> Extended ID: 0x18DB33F1 DLC: 8 Data: 0x02 0x01 0x00 0x55 0x55 0x55 0x55 0x55

/* CAN OBD & UDS Simple PID Request
 *
 *  Currently requests PID 0x00 at a 1 second interval and
 *  displays all received CAN traffic to the terminal at 115200.
 *
 *  Written By: Cory J. Fowler  April 5th, 2017
 *
 *  (Disclaimer: Standard IDs are currently UNTESTED against a vehicle)
 *
 */

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

#define standard 0
// 7E0/8 = Engine ECM
// 7E1/9 = Transmission ECM
#if standard == 1
  #define LISTEN_ID 0x7EA
  #define REPLY_ID 0x7E0
  #define FUNCTIONAL_ID 0x7DF
#else
  #define LISTEN_ID 0x98DAF101
  #define REPLY_ID 0x98DA01F1
  #define FUNCTIONAL_ID 0x98DB33F1
#endif

// CAN TX Variables
unsigned long prevTx = 0;
unsigned int invlTx = 1000;
byte txData[] = {0x02,0x01,0x00,0x55,0x55,0x55,0x55,0x55};

// CAN RX Variables
unsigned long rxID;
byte dlc;
byte rxBuf[8];
char msgString[128];                        // Array to store serial string

// CAN Interrupt and Chip Select Pins
#define CAN0_INT 2                              /* Set INT to pin 2 (This rarely changes)   */
MCP_CAN CAN0(10);                                /* Set CS to pin 9 (Old shields use pin 10) */


void setup(){

  Serial.begin(115200);
  while(!Serial);
 
  // Initialize MCP2515 running at 8MHz with a baudrate of 500kb/s and the masks and filters disabled.
  if(CAN0.begin(MCP_STDEXT, CAN_500KBPS, MCP_8MHZ) == CAN_OK)
    Serial.println("MCP2515 Initialized Successfully!");
  else{
    Serial.println("Error Initializing MCP2515... Permanent failure!  Check your code & connections");
    while(1);
  }

//
//  // Allow all Standard IDs
//  CAN0.init_Mask(0,0x00000000);                // Init first mask...
//  CAN0.init_Filt(0,0x00000000);                // Init first filter...
//  CAN0.init_Filt(1,0x00000000);                // Init second filter...
//  // Allow all Extended IDs
//  CAN0.init_Mask(1,0x80000000);                // Init second mask...
//  CAN0.init_Filt(2,0x80000000);                // Init third filter...
//  CAN0.init_Filt(3,0x80000000);                // Init fourth filter...
//  CAN0.init_Filt(4,0x80000000);                // Init fifth filter...
//  CAN0.init_Filt(5,0x80000000);                // Init sixth filter...

#if standard == 1
  // Standard ID Filters
  CAN0.init_Mask(0,0x7F00000);                // Init first mask...
  CAN0.init_Filt(0,0x7DF0000);                // Init first filter...
  CAN0.init_Filt(1,0x7E10000);                // Init second filter...

  CAN0.init_Mask(1,0x7F00000);                // Init second mask...
  CAN0.init_Filt(2,0x7DF0000);                // Init third filter...
  CAN0.init_Filt(3,0x7E10000);                // Init fourth filter...
  CAN0.init_Filt(4,0x7DF0000);                // Init fifth filter...
  CAN0.init_Filt(5,0x7E10000);                // Init sixth filter...

#else
  // Extended ID Filters
  CAN0.init_Mask(0,0x90FF0000);                // Init first mask...
  CAN0.init_Filt(0,0x90DA0000);                // Init first filter...
  CAN0.init_Filt(1,0x90DB0000);                // Init second filter...

  CAN0.init_Mask(1,0x90FF0000);                // Init second mask...
  CAN0.init_Filt(2,0x90DA0000);                // Init third filter...
  CAN0.init_Filt(3,0x90DB0000);                // Init fourth filter...
  CAN0.init_Filt(4,0x90DA0000);                // Init fifth filter...
  CAN0.init_Filt(5,0x90DB0000);                // Init sixth filter...
#endif

  CAN0.setMode(MCP_NORMAL);                      // Set operation mode to normal so the MCP2515 sends acks to received data.

  // Having problems?  ======================================================
  // If you are not receiving any messages, uncomment the setMode line below
  // to test the wiring between the Ardunio and the protocol controller.
  // The message that this sketch sends should be instantly received.
  // ========================================================================
  CAN0.setMode(MCP_LOOPBACK);

  pinMode(CAN0_INT, INPUT);                          // Configuring pin for /INT input
 
  Serial.println("Simple CAN OBD-II PID Request");
}

void loop(){

  if(!digitalRead(CAN0_INT)){                         // If CAN0_INT pin is low, read receive buffer
 
    CAN0.readMsgBuf(&rxID, &dlc, rxBuf);             // Get CAN data
  
    // Display received CAN data as we receive it.
    if((rxID & 0x80000000) == 0x80000000)     // Determine if ID is standard (11 bits) or extended (29 bits)
      sprintf(msgString, "Extended ID: 0x%.8lX  DLC: %1d  Data:", (rxID & 0x1FFFFFFF), dlc);
    else
      sprintf(msgString, "Standard ID: 0x%.3lX       DLC: %1d  Data:", rxID, dlc);
 
    Serial.print(msgString);
 
    if((rxID & 0x40000000) == 0x40000000){    // Determine if message is a remote request frame.
      sprintf(msgString, " REMOTE REQUEST FRAME");
      Serial.print(msgString);
    } else {
      for(byte i = 0; i<dlc; i++){
        sprintf(msgString, " 0x%.2X", rxBuf[i]);
        Serial.print(msgString);
      }
    }
      
    Serial.println();
  }
 
  /* Every 1000ms (One Second) send a request for PID 00           *
   * This PID responds back with 4 data bytes indicating the PIDs  *
   * between 0x01 and 0x20 that are supported by the vehicle.      */
  if((millis() - prevTx) >= invlTx){
    prevTx = millis();
    if(CAN0.sendMsgBuf(FUNCTIONAL_ID, 8, txData) == CAN_OK){
      Serial.println("Message Sent Successfully!");
    } else {
      Serial.println("Error Sending Message...");
    }
  }
}

Hey there,

Here's my current setup:

I've got a Renault Megane III CC 2010, and unfortunately, I couldn't find any documentation specific to this car. All I could locate was the OBD2 interface pinout.

From what I've gathered, there are two CAN bus speeds to consider: the high-speed CAN bus, which was introduced in 2016 and can go up to 1 Mbit/s, but it requires a 16 MHz receiver to achieve that speed. Since I'm using an MCP2515 running at 8 MHz, it can only reach up to 500 kbits/s.

However, since my car is from 2010, the ISO 11898-2 standard for the High-Speed CAN wasn't established back then; only the ISO 11898-3 from 2006, which is the low-speed interface operating at 125 kbits/s, was in place. So, it seems my issue might be due to using the wrong speed in the code ?

UPDATE : I just tried to change on the new code using PID request if(CAN0.begin(MCP_STDEXT, CAN_125KBPS, MCP_8MHZ) == CAN_OK) to match the 125kbits/s limits of 2006 but nothing.
What is very strange is that when i upload the code (not connected to the obd) i have a "MCP2515 Initialized successfully" but this could only happen when the CAN bus is initialized too :

  // Initialize MCP2515 running at 8MHz with a baudrate of 500kb/s and the masks and filters disabled.
  if(CAN0.begin(MCP_STDEXT, CAN_125KBPS, MCP_8MHZ) == CAN_OK)
    Serial.println("MCP2515 Initialized Successfully!");
  else{
    Serial.println("Error Initializing MCP2515... Permanent failure!  Check your code & connections");
    while(1);
  }

When you send are you choosing an ID to go in the send statement from the list ?

(You send a code with a header and a request string and you get a result back
.)

Have you got the ignition on ?

That does not say some form of that may not have be used. I have seen protocols etc on cars for testing that were not released to the public in any form. Generally only on one or two models.

You found it, great!

I simply opened the example file and adjusted the value to match with the quartz speed of my MCP, and set the baud rate for communication with the car (according to my theory with the ISO....).

Upon running the test, I enabled the line //CAN0.setMode to debug and I received the expected outcome that the code's comment said.

I tested with both the ignition on and then only the infotainment system active (without the engine running, just by pressing the start button).

As for the ID I didn't choose anything, I just left it like the original code. But the code tries to communicate with PID 0x00 :

 *  Currently requests PID 0x00 at a 1 second interval and
 *  displays all received CAN traffic to the terminal at 115200.

Apologies if I'm unclear, but I don't believe I found it, or perhaps I'm mistaken? As you mentioned, there's a possibility that even older models may have the high-speed protocol.

The tutorial I followed recommended using the 500kbits/s speed because it's standard in most cars. The most recent version of the car used in the tutorial, from 2008, utilized this speed.

You should use a known PID , or you won’t get a return

How can I found PID, is there any method ? There's no documentation anywhere about the car's CAN bus that I can find. What's confusing is how people can just upload code, plug in the OBD interface, and read the CAN bus so easily.

I found out about the ELM327, can it be a good solution ?
The module is compatible with my Megane III : PyRen / pyren · GitLab
And I have found a few librairies on it.
But before buying anything I would like to have your opinion on this solution

If you google can bus , you will find the standard PID’s common to all cars , defined by the standard - such as battery voltage

Read me

Thanks for the link, is this the correct way to request with PID ?

/* CAN OBD & UDS Simple PID Request
 *
 *  Currently requests PID 0x00 at a 1 second interval and
 *  displays all received CAN traffic to the terminal at 115200.
 *
 *  Written By: Cory J. Fowler  April 5th, 2017
 *
 *  (Disclaimer: Standard IDs are currently UNTESTED against a vehicle)
 *
 */

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

#define standard 0
// 7E0/8 = Engine ECM
// 7E1/9 = Transmission ECM
#if standard == 1
  #define LISTEN_ID 0x7EA
  #define REPLY_ID 0x7E0
  #define FUNCTIONAL_ID 0x7DF
#else
  #define LISTEN_ID 0x98DAF101
  #define REPLY_ID 0x98DA01F1
  #define FUNCTIONAL_ID 0x98DB33F1
#endif

// CAN TX Variables
unsigned long prevTx = 0;
unsigned int invlTx = 1000;
byte txData[] = {0x02, 0x01, 0x0C, 0x55, 0x55, 0x55, 0x55, 0x55};

// CAN RX Variables
unsigned long rxID;
byte dlc;
byte rxBuf[8];
char msgString[128];                        // Array to store serial string

// CAN Interrupt and Chip Select Pins
#define CAN0_INT 2                              /* Set INT to pin 2 (This rarely changes)   */
MCP_CAN CAN0(10);                                /* Set CS to pin 9 (Old shields use pin 10) */


void setup(){

  Serial.begin(115200);
  while(!Serial);
 
  // Initialize MCP2515 running at 16MHz with a baudrate of 500kb/s and the masks and filters disabled.
  if(CAN0.begin(MCP_STDEXT, CAN_500KBPS, MCP_8MHZ) == CAN_OK)
    Serial.println("MCP2515 Initialized Successfully!");
  else{
    Serial.println("Error Initializing MCP2515... Permanent failure!  Check your code & connections");
    while(1);
  }

//
//  // Allow all Standard IDs
//  CAN0.init_Mask(0,0x00000000);                // Init first mask...
//  CAN0.init_Filt(0,0x00000000);                // Init first filter...
//  CAN0.init_Filt(1,0x00000000);                // Init second filter...
//  // Allow all Extended IDs
//  CAN0.init_Mask(1,0x80000000);                // Init second mask...
//  CAN0.init_Filt(2,0x80000000);                // Init third filter...
//  CAN0.init_Filt(3,0x80000000);                // Init fourth filter...
//  CAN0.init_Filt(4,0x80000000);                // Init fifth filter...
//  CAN0.init_Filt(5,0x80000000);                // Init sixth filter...

#if standard == 1
  // Standard ID Filters
  CAN0.init_Mask(0,0x7F00000);                // Init first mask...
  CAN0.init_Filt(0,0x7DF0000);                // Init first filter...
  CAN0.init_Filt(1,0x7E10000);                // Init second filter...

  CAN0.init_Mask(1,0x7F00000);                // Init second mask...
  CAN0.init_Filt(2,0x7DF0000);                // Init third filter...
  CAN0.init_Filt(3,0x7E10000);                // Init fourth filter...
  CAN0.init_Filt(4,0x7DF0000);                // Init fifth filter...
  CAN0.init_Filt(5,0x7E10000);                // Init sixth filter...

#else
  // Extended ID Filters
  CAN0.init_Mask(0,0x90FF0000);                // Init first mask...
  CAN0.init_Filt(0,0x90DA0000);                // Init first filter...
  CAN0.init_Filt(1,0x90DB0000);                // Init second filter...

  CAN0.init_Mask(1,0x90FF0000);                // Init second mask...
  CAN0.init_Filt(2,0x90DA0000);                // Init third filter...
  CAN0.init_Filt(3,0x90DB0000);                // Init fourth filter...
  CAN0.init_Filt(4,0x90DA0000);                // Init fifth filter...
  CAN0.init_Filt(5,0x90DB0000);                // Init sixth filter...
#endif

  CAN0.setMode(MCP_NORMAL);                      // Set operation mode to normal so the MCP2515 sends acks to received data.

  // Having problems?  ======================================================
  // If you are not receiving any messages, uncomment the setMode line below
  // to test the wiring between the Ardunio and the protocol controller.
  // The message that this sketch sends should be instantly received.
  // ========================================================================
  //CAN0.setMode(MCP_LOOPBACK);

  pinMode(CAN0_INT, INPUT);                          // Configuring pin for /INT input
 
  Serial.println("Simple CAN OBD-II PID Request");
}

void loop(){

  if(!digitalRead(CAN0_INT)){                         // If CAN0_INT pin is low, read receive buffer
 
    CAN0.readMsgBuf(&rxID, &dlc, rxBuf);             // Get CAN data
  
    // Display received CAN data as we receive it.
    if((rxID & 0x80000000) == 0x80000000)     // Determine if ID is standard (11 bits) or extended (29 bits)
      sprintf(msgString, "Extended ID: 0x%.8lX  DLC: %1d  Data:", (rxID & 0x1FFFFFFF), dlc);
    else
      sprintf(msgString, "Standard ID: 0x%.3lX       DLC: %1d  Data:", rxID, dlc);
 
    Serial.print(msgString);
 
    if((rxID & 0x40000000) == 0x40000000){    // Determine if message is a remote request frame.
      sprintf(msgString, " REMOTE REQUEST FRAME");
      Serial.print(msgString);
    } else {
      for(byte i = 0; i<dlc; i++){
        sprintf(msgString, " 0x%.2X", rxBuf[i]);
        Serial.print(msgString);
      }
    }
      
    Serial.println();
  }
 
  /* Every 1000ms (One Second) send a request for PID 00           *
   * This PID responds back with 4 data bytes indicating the PIDs  *
   * between 0x01 and 0x20 that are supported by the vehicle.      */
  if((millis() - prevTx) >= invlTx){
    prevTx = millis();
    if(CAN0.sendMsgBuf(FUNCTIONAL_ID, 8, txData) == CAN_OK){
      Serial.println("Message Sent Successfully!");
    } else {
      Serial.println("Error Sending Message...");
    }
  }
}

I modify this line : byte txData[] = {0x02, 0x01, 0x0C, 0x55, 0x55, 0x55, 0x55, 0x55}; to request the data from PID : 0C which is the Engine speed. After trying I have :
image
So there is something wrong with what I do
Thanks

I used an ELM327 with a wifi interface and an app on my iphone and this is the result from it (it's in french but i will translate)

0-0C-00 Engine Speed
0-0D-00 Car speed
.....

I tried to change byte txData[] = {0x02, 0x01, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00}; butttt still nothing

This is the ELM I'm using, and I've confirmed that the signal ground and chassis ground are connected together, as in my setup. Between the high and low pins on the ELM, there is 0 ohms, whereas in my setup, there is 120 ohms thanks to the jumper. So, I removed it, but nothing changed

This is the data the ELM327 can utilize, maybe it could help :

SAE J1850 PWM (41.6 kbaud)
SAE J1850 VPW (10.4 kbaud)
ISO9141-2 (5 baud init, 10.4 kbaud)
ISO14230-4 KWP (5 baud init, 10.4 kbaud)
ISO14230-4 KWP (fast init, 10.4 kbaud)
ISO15765-4 CAN (11 bit ID, 500 kbaud)
ISO15765-4 CAN (29 bit ID, 500 kbaud)
ISO15765-4 CAN (11 bit ID, 250 kbaud)
ISO15765-4 CAN (29 bit ID, 250 kbaud)
ISO15765-4 CAN (29/11bit ID, arbitrary baudrate)

I am in process of doing quite a lot of canbus and obd work. I found these two articles. One shows the formatting of a PID to send from Arduino and the other is from instructables.
https://forum.arduino.cc/t/mcp_can-library-talking-to-vag-car/666554

https://www.instructables.com/Yes-We-CAN-BUS-With-Arduino-in-30-Seconds/

What is the exact model of vehicle you are working with maybe I can help

Hello everyone,

I’m working on a project where I simulate a vehicle in MATLAB. The simulation data is sent in real-time to an Arduino microcontroller, which is connected to an MCP2515 CAN interface. The goal is to send this data to an OBD-II module via the CAN bus and then read it in a mobile application compatible with OBD-II.

Here’s what I have set up so far:

  • The 120-ohm termination resistors are properly installed.
  • The CAN bus is configured at 500 kbps.
  • I am sending CAN frames from the Arduino (e.g., ID 0x7DF with data like 01 00 00 00 00 00 00 00).
  • The ground is shared between the Arduino, MCP2515, and the external 12V power supply for the OBD-II module.

Despite this, I am not receiving any response from the OBD-II module. I’ve also tested with several mobile apps, but no data seems to be transmitted.

I’d like to know:

  1. Is my wiring complete, or should additional pins, like the OBD-II chassis ground, be connected?
  2. Are there specific steps to test or enable communication with an OBD-II module using an MCP2515 and the J2234 protocol?
  3. Has anyone successfully set up a similar configuration and could share advice or a compatible example code?

Thank you in advance for your help and suggestions!