A
Arduino20h ago
Kyand

When is common ground needed?

Hi all! I'm new to all this, and my first project to learn hardware is reading my car's CAN bus! I bought a MCP2515 CAN Bus Module with a TJA1050 Receiver. I set it up correctly with my arduino, but all the data I'm reading is essentially junk (keeps repeating itself, even when it really should be different). I only connected pin 6 & 14 (OBD cable) to the MCP2515 module, so technically, TJA1050 has no common ground ( car & arduino )... Could that be messing up everything? Or not in reality?
30 Replies
Maverick
Maverick20h ago
If it's differential pair like half duplex RS485, you don't need a common ground. You do need a common ground for, ie: UART, RS232 which do not use a differential pair.
Kyand
KyandOP20h ago
Yeahh that's what I thought too... So differential we really don't care about shared ground? Like not even in any edge cases?
Maverick
Maverick20h ago
How is the MCP2515 used in your circuit? Do you have a schematic? I'm not exactly familiar with CAN bus, only RS485. The systems I work on have only two wires between devices but all grounds are bonded to earth. I'm not sure if you also need a termination resistor as you do with RS485. Have you checked the datasheets for the MCP2515 and TJA1050?
Kyand
KyandOP20h ago
Sooo I don't really have a schematic or anything like that, but it's 1:1 as this (stole from a youtube video)
No description
Maverick
Maverick20h ago
So, if the Arduino is powered by the car's electrical system in this example, then there is a common ground. How does the TJA1050 come into play? It's not pictured here.
Kyand
KyandOP20h ago
The arduino is powered from my latpop 🙂 TJA1050 is on the little board
Kyand
KyandOP20h ago
If that helps
No description
Kyand
KyandOP20h ago
I honestly heavily doubt I need a common ground, but it's the last idea I have to solve my issue... After that, no idea what I've done wrong But tldr, laptop grnd -> arduino -> MCP2515 (and TJA1050) while car has it's own ground But I really doubt it would be such a difference to... make a difference
Maverick
Maverick19h ago
Do you have the J1 jumper in place on the board? That is the termination resistor.
Kyand
KyandOP19h ago
I don't, as far as I understood I don't need it (unless I'm making my own CAN bus or something)
Maverick
Maverick19h ago
With RS485, you always need a termination resistor. CAN looks very similar. I would keep it in place.
Kyand
KyandOP19h ago
Is that to prevent "echo" ? Because I think CAN buses in cars already have 2 60ohms resistors on each side so adding in more resistance wouldn't be good, although really not sure what I'm talking about honestly
Maverick
Maverick19h ago
The last device in the network has the termination resistor. I'm used to this being a circuit with very long wires though (for impedance matching). The more I think about it, the more I am thinking you might actually need a common ground. Can't hurt to try that as well.
Kyand
KyandOP19h ago
Yeahh I'll try that tomorrow (Can't try right now). Just overthinking it because guy on youtube did not use a common ground hahaha. But I guess it's a case of "could work without it, could also not work without it".
Maverick
Maverick19h ago
Was he also using a laptop or did he power the Arduino from the car's electrical system?
Kyand
KyandOP19h ago
Laptop too! Here's the video for reference, if you are curious (its pretty neat honestly) https://www.youtube.com/watch?v=cAAzXM5vsi0 But anyways, massive thanks for helping out! I'll bring updates after I test with common ground tomorrow 🙂
Maverick
Maverick19h ago
No problem. RS485 cables are typically shielded and the shield is grounded at both ends, essentially creating a common ground on top of the fact that all grounds are bonded to earth. So despite the differential pair, there really is a common ground now that I think about it.
Kyand
KyandOP19h ago
Mmmm so another question actually. Any idea what the results would look like without a common ground (aka floating ground)? Because it's not like I'm getting gibberish or anything like that, but I am constantly getting the same frames over and over and it really doesn't make sense imo... But now I'm going crazy and thinking maybe its normal? Ughh this is getting confusing haha
Kyand
KyandOP19h ago
Here are the full logs I captured. And somewhere in there, I turned the car on... But all frames look very very similar... very supsicious I don't know
Maverick
Maverick19h ago
If it was interfering with communication, you would get gibberish, or errors due to failed CRC checks / back checksums, something like that. Getting the same thing over and over probably isn't a hardware issue.
Kyand
KyandOP19h ago
Well then Welllllllllllll You do make sense I guess I'll try another CAN bus on the car, see if that changes something? But theres just no way I'm getting these data frames on car startup... I refuse to believe it? But it wouldnt make sense to programmatically turn that into data if the hardware part wasn't correct I guess Yeah and now that I think about it... If the issue is indeed not having common ground, then my current results would simply be an offset of the "correct" results? Am I right to think of it that way? Which really wouldn't fix my issue of "It's the same data over and over"
Maverick
Maverick19h ago
You might want to post the code you're using here as well. I'm not sure what the data above represents. It looks like the RTR part are the requests sent from the MCU and the response is data packets mostly filled with 0x67.
Kyand
KyandOP19h ago
#include <mcp_can.h>
#include <SPI.h>

MCP_CAN CAN0(10); // CS pin 10

void setup() {
Serial.begin(115200);

if (CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_8MHZ) != CAN_OK) {
Serial.println("Error Initializing MCP2515...");
while (1);
} else {
Serial.println("MCP2515 Initialized Successfully!");
}

CAN0.setMode(MCP_LISTENONLY);
Serial.println("Sniffer ready...");
}

void loop() {
if (CAN0.checkReceive() == CAN_MSGAVAIL) {
unsigned long rawId;
byte dlc;
byte data[8];

if (CAN0.readMsgBuf(&rawId, &dlc, data) != CAN_OK) return;
if (dlc > 8) return;

bool isExt = rawId & 0x80000000UL;
bool isRTR = rawId & 0x40000000UL;
unsigned long cleanId = rawId & 0x1FFFFFFFUL;

Serial.print(isExt ? 'E' : 'S');
Serial.print(",0x");
Serial.print(cleanId, HEX);
Serial.print(',');
Serial.print(dlc);
Serial.print(',');
Serial.print(isRTR ? "RTR" : "DATA");

if (!isRTR && dlc > 0) {
Serial.print(',');
for (byte i = 0; i < dlc; i++) {
if (i) Serial.print(' ');
if (data[i] < 16) Serial.print('0');
Serial.print(data[i], HEX);
}
}

Serial.println();
}
}
#include <mcp_can.h>
#include <SPI.h>

MCP_CAN CAN0(10); // CS pin 10

void setup() {
Serial.begin(115200);

if (CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_8MHZ) != CAN_OK) {
Serial.println("Error Initializing MCP2515...");
while (1);
} else {
Serial.println("MCP2515 Initialized Successfully!");
}

CAN0.setMode(MCP_LISTENONLY);
Serial.println("Sniffer ready...");
}

void loop() {
if (CAN0.checkReceive() == CAN_MSGAVAIL) {
unsigned long rawId;
byte dlc;
byte data[8];

if (CAN0.readMsgBuf(&rawId, &dlc, data) != CAN_OK) return;
if (dlc > 8) return;

bool isExt = rawId & 0x80000000UL;
bool isRTR = rawId & 0x40000000UL;
unsigned long cleanId = rawId & 0x1FFFFFFFUL;

Serial.print(isExt ? 'E' : 'S');
Serial.print(",0x");
Serial.print(cleanId, HEX);
Serial.print(',');
Serial.print(dlc);
Serial.print(',');
Serial.print(isRTR ? "RTR" : "DATA");

if (!isRTR && dlc > 0) {
Serial.print(',');
for (byte i = 0; i < dlc; i++) {
if (i) Serial.print(' ');
if (data[i] < 16) Serial.print('0');
Serial.print(data[i], HEX);
}
}

Serial.println();
}
}
There ya go 😄
Maverick
Maverick19h ago
Where does this come from?
2025-10-24 11:43:48.106 MARKER plugging into obd (battery booster on already)
2025-10-24 11:44:18.474 MARKER plugged into obd, inserting key in
2025-10-24 11:44:46.315 MARKER key in, turning key to ignition (not starting car)
2025-10-24 11:43:48.106 MARKER plugging into obd (battery booster on already)
2025-10-24 11:44:18.474 MARKER plugged into obd, inserting key in
2025-10-24 11:44:46.315 MARKER key in, turning key to ignition (not starting car)
Kyand
KyandOP19h ago
Ohh this is my py script that logs serial monitor Also added a feature where I can add markers manually to specify what im doing within logs
Maverick
Maverick18h ago
I guess you might need some means of decoding this data received.
Kyand
KyandOP18h ago
Soo the way I was originally going to do it, was to simply correlate actions to frames (press button -> find frame). Can easily build a py app that helps with this, the only issue is... With only 4 unique frames I can't correlate much 🙁 And I dont think theres public documentation about this, as most protocols are developed by the car manufacturer and as you probably can guess, its proprietary 🙁
Kyand
KyandOP18h ago
For reference, this is how data should look like
No description
Maverick
Maverick18h ago
It looks like your data is similar, just formatted differently due to the difference in code. Do you observe any change in the data when pressing a button or taking some action you would expect to cause a change in the data?
Kyand
KyandOP18h ago
Nope 🙁 Theres only 4 unique frames, which should be impossible If you ctrl+f for "marked" you can see the few actions I did, but nothing changes data wise

Did you find this page helpful?