CAN DATA Discrepancy Between UNO & MEGA

In point form : The title says a lot.

Same CAN hardware (MCP2515), same code,
same car (OBD2 data over CAN, via DLC connector)
same library <CAN_BUS_Shield-master>

Only difference is the MEGA and UNO.

But why are the scanned values different?

Scanned data below.

Thank you for any tips!

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

unsigned char len = 0, buf[16];
unsigned char tmp[8] = {0x02, 0x01, 0x0C, 0, 0, 0, 0, 0}; 
  
MCP_CAN CAN(9);    // Set CS pin 

void setup(){
  Serial.begin(1000000);  // COMM between LCD and ARDU MEGA Slave
  SPI.begin;
  CAN.begin(CAN_1000KBPS);
 
}

void loop(){

  CAN.sendMsgBuf(0x7DF, 0, 8, tmp); 
  CAN.readMsgBuf(&len, buf);
  
    Serial.print(buf[0], DEC);   Serial.print(','); //0
    Serial.print(buf[1], DEC);   Serial.print(',');
    Serial.print(buf[2], DEC);   Serial.print(',');
    Serial.print(buf[3], DEC);   Serial.print(',');
    Serial.print(buf[4], DEC);   Serial.print(',');
    Serial.print(buf[5], DEC);   Serial.print(',');
    Serial.print(buf[6], DEC);   Serial.print(',');
    Serial.println(buf[7], DEC);   //7      
 }

 //DATA UNO, DECIMAL (checks out)
[0]------------------------[7]
4 65  12  14  80  170 170 170
4 65  12  14  83  170 170 170
4 65  12  14  93  170 170 170
4 65  12  14  87  170 170 170
4 65  12  14  87  170 170 170


//DATA MEGA, DECIMAL (not relatable) 
[0]------------------------[7]
92  113 40  135 135 128 135 135
92  113 40  135 135 128 135 135
92  113 40  135 135 128 135 135
92  113 40  135 135 128 135 135

I cannot answer as I do not know what the data source is. Also why do you initialize the CAN before the SPI? Slow things down and I expect they might work better.

What is this?

Thank you for responding.

Data source is vehicle DLC connector (0BD2 over CAN).

I can try adding a delay to slow down the bus.

The serial connection is between MEGA, or UNO to my laptop (USB).

I suspect the real culprit is CPU overload—Serial.print() is surprisingly expensive in time. To pinpoint exactly how long your routines take, try this low-overhead timing method:

Scope-based timing

    Pick an unused digital pin and hook it up to your oscilloscope.

    In code, set that pin HIGH at the very start of the function you want to time, and LOW when it finishes.

    The oscilloscope will display a pulse whose width is the exact execution time, without the extra overhead of millis() or similar.

Alleviate CAN bus congestion

    Add a second CAN node running at the same bit rate, but deliberately insert small delays (gaps) between messages.

    If performance improves, you know bus saturation or arbitration delays are part of the problem.

Validate your physical bus layout

    Sketch a simple diagram showing the OBD port at one end, all your devices, and the location of each 120 Ω termination resistor.

    Confirm your wiring and terminations match the CAN specification—misplaced or missing terminators can introduce errors and retransmissions that eat CPU time.

By combining precise scope-based timing with controlled message spacing and a clean bus schematic, you’ll be able to identify whether it’s really processor load, bus congestion, or wiring/termination issues causing your troubles.

That's good info. I'll do some troubleshooting, and post results.

On another note, I was told the Serial.print was efficient many years ago, despite me questioning the many entries of code to allow all data to print.

I thought using an array/counter might be faster, but was advised the "line by Line" method was quickest.

What is your approach to printing several data to Serial?

TIA!

There should not be any difference between an UNO and a MEGA in terms of how long it takes to execute a Serial print.

How long it takes for Serial.print() to return is dependent on the baud rate and the amount being printed. There is a 64-byte buffer, as long as the buffer will hold whatever is being printed, print() just places the characters in the buffer and returns. If the buffer is full, print() waits for space to become available, and returns as soon as the last character is placed in the buffer.

Serial.write is an option for sending raw data. I'll try to incorporate that, and maybe try to combine Serial.print instances to reduce the number of calls.

Back to the CAN Data issue now. I'll try with/without 120 ohm resistor; adding delays, and cleaning up the physical wiring.

Just for kicks, I tried GilShultz recommendation.

For the code in the OP, I edited the Serial.print(',') entries
to Serial.write(',').

There's no 'detectable" change in time with the short amount of code listed. About 5 microseconds to complete the loop() using the UNO.

For those that want to know the difference between 30 "IF" statements vs "IF ELSE", I uploaded some junk code and measured the time. There's a
savings of half a microsecond when the processor checks 30 lines of "IF" vs "ELSE IF".

Now you know. I'll be heading to the car shortly to test the MEGA with
some code and wiring changes. Thanks for making me MORE of a Geek! :slight_smile:

Do not forget about the SPI communication on the Arduino UNO, they can block the code execution, especially if the transfer takes longer than expected or if there are issues with the connection. This can lead to the program hanging until the transfer is complete.

Since you have the scope you can check this as well. There is a buffer in the CAN controller chip, That gives you a little timing room.

I tried the following without any success:

  • slower CAN rate

  • slower CAN and Serial rate

  • with and without termination (62 ohms measured across CAN+ and CAN-

  • cleaned up wiring

Next step , try different library and CAN shield. Finally another MEGA.

Still stumped as to why it doesn't work as-is...

Did you use the same wiring (actual wires) for the UNO and the Mega? If you are using dupont style jumper wires, the wire can break inside the insulation or at the connector itself.