Seeed Studio Can Bus Shield & UNO R3

Hello, i am using v2 with uno r3.

Here is my code:

#include "Config.h"

#include "Components/Can.h"

#include "mcp2515_can.h"

mcp2515_can CAN(9);

namespace ii::blackbox::components {

unsigned char len = 0;
unsigned char buf[8];
char str[20];

void Can::SetUp() {
	while (CAN.begin(CAN_500KBPS) != 0) {
#ifdef SERIAL_DEBUG
		SERIAL_PORT_MONITOR.println("CAN init fail, retry...");
#endif
		delay(100);
	}

	CAN.setMode(MODE_NORMAL);

#ifdef SERIAL_DEBUG
	SERIAL_PORT_MONITOR.println("CAN init OK.");
#endif

	unsigned char stmp[8] = {0x02, 0x90, 0x02, 0, 0, 0, 0, 0};

	for (size_t i = 0; i < 10; i++) {
		auto send = CAN.sendMsgBuf(0x7DF, 0, 8, stmp);
		if (send == CAN_OK) {
			SERIAL_PORT_MONITOR.println("CAN send OK.");
		}
		else {
			SERIAL_PORT_MONITOR.println("CAN send fail.");
		}
	}
}

void Can::Loop() {
	while (CAN_MSGAVAIL == CAN.checkReceive()) {
		// read data,  len: data length, buf: data buf
		CAN.readMsgBuf(&len, buf);

		for (int i = 0; i < len; i++) {
			SERIAL_PORT_MONITOR.print(buf[i]);
			SERIAL_PORT_MONITOR.print(",");

			m_logger.Log(g_logFileName, buf[i]);
		}
		SERIAL_PORT_MONITOR.println();
		SERIAL_PORT_MONITOR.println("----");
		m_logger.Log(g_logFileName, "\n");
	}
}

} // namespace ii::blackbox::components

Loop back mode works as expected, but normal mode outputs:
CAN send fail.
CAN send fail.
CAN send fail.
CAN send fail.
CAN send fail.
CAN send fail.
CAN send fail.
CAN send fail.
CAN send fail.

Also i cutted P1 at all and desoldered the R3. I am testing with car ( w204 ) and PCAN-USB FD. Both of them not works. Am connecting PCAN FD cable or car by DB9.

Welcome! It appears you did not read the CAN specifications. From what I can determine it is working the way it should. The CAN protocol requires an in-message acknowledge, if it does not receive it will try a bunch of times and fail. It appears you used Cory Fowler's library, in there there is also a receive module. You need that on the bus along with the appropriate termination resistors. Be sure the bus is at least 1 meter in length. If you look at the message on your scope it will look just fine but at the acknowledge point the transmitter is sending a recessive bit, the receivers place a dominate bit on the buss during that time slot.

Hi gilshultz,
Thank you for your reply. Im kinda confused about the termination resistors. Im kinda newbie about the hardware stuff, sorry for that. When i read some about them on the Seeed studio forum, i saw people talking about the desoldering R3 ( resistors ). Before that ( when i purchased shield, without touch to hw ), i couldnt get CAN message from car or pcan fd usb. After removing R3 ( also cutting p1 ), still couldnt get CAN message :slight_smile:

Here is the shield's schmatics :

I have tested my setup with 2 OBD DB9 cables, both of them not works. ( Its 1m 10 cm )

Here is the my fight with this shield :slight_smile:

Resoldered the R3:


As you can see, i cutted P1 at all ( I was really angry to shield after countless try)

Also i tried Elecfreak's shield. But still same issue:

From the schematic it appears P1 (should be a cuttable jumper) is the termination and R3 is the termination resistor, that should be about 120 ohms. The design leaves the termination resistor in the circuit so you are all set with that. P1 is in series with R3 so cutting and removing is redundant. Not all cars are the same or at the same baud.

"CAN_500KBPS" You need to set the baud to match what your car is. I do not know what the baud is but it might be available if you look online. You can work with this. This project will take some time, it is not a simple task connecting to the OBDII and expecting wanted results. Also be aware putting messages on the vehicle CAN bus can do nothing to causing a catastrophic failure of the vehicle.

2 Likes

I am sure my w204 works with 500k baud. Actually i got enought experience with can bus, but not with self builded hardware. At the beginning, i am thinking only use OBDII protocol since they arent any harmfull requests :slight_smile:

But the only issue on this side, im really confused because how can my both shield could be defective. I am just plugging them to my UNO R3 ( i tried with my UNO as well ).

If we say some settings are incorrect on my code, it should be work on PCAN since im can to set baud or other settings on the PCAN cable.

Here is the schemantics of other shield ( elecfreaks ). I didnt modify anything on it.

If i am correct there is a 60 ohm terminator.

You are close, the bus is 60 Ohm but it is comprised of 2 120 Ohm resistors one on each end. You can try without any as OBDII has some termination and see if you get anything.

I would start with two UNO's talking to each other. If you cannot get that to work the OBD II will not work either. When you do that be sure to use termination on each end. I used the MPC2515 module and they worked first try. I have used CAN years ago and knew about termination etc. When you start be sure there is nothing else connected to the UNO especially anything using SPI. Hopefully this will get you going, let us know how you do. Without an annotated schematic of your circuit as you have wired it makes it mainly just guessing on my end.

image

You might try swapping CAN H & L.

My circuit consists of plugging the shield into my arduino uno r3. No other customization. There is nothing else that uses SPI either.

I am not getting any data from OBDII or I can't write either. Now I will try to communicate to each other with 2 shields. Please to clear;

To communicate between 2 shields;
Should both shields be 60 ohms?

To talk to OBDII, do I need to have no resistors on my shield?

Almost. Nothing on the SPI is good. With two shields and more the bus impedance is 60 Ohms. A bus is normally terminated at each end and not in the middle. The end point resistors should be 120 Ohm, one on each end. This was to minimize the signal reflections. 2 120 Ohm resistors on the bus ends gives you an actual value of 60 ohms that is what it should be.

If you have modules in the middle they do NOT get resistors. With OBDII try it both ways as I do not know how the bus is structured. At one point it was going to be a bus to the connector from a gateway, nothing else on the bus so you would need the resistor. To my knowledge there were three modes. User, Dealer, OEM, each comes with more privileges and retains the previous privileges. Things have changed in the past 20 or so years and I am no longer involved.

Tomorrow or tuesday ( i am waiting for shipping ) , im going to try. It seems i destoryed my two shield. Ill let you know on this thread.

What happened when you tried the two Arduinos only on your bus?

Couldnt receive from or write on the bus between two Arduinos. I think, i little bit destroyed my shields, because i used knife to clear missplaced soldered parts.

1 Like

That would do it. Sorry it happened, you were so close!


My secondary seeed studio shield on the way. Ill be keep updated this thread.

Hopefully they work. I will watch for your post.

OK, i got my new shield now. To be clear, for the first attempt ill try it without cutting 60 ohm terminator. Then if it not works, ill try it with cutting terminator. ( Without implement 120 ohm ).

Have fun! If it is not wired properly I will pass on further help. Note post #8, Putting to low of a resistance can fry the drivers. The total on the bus is 60 Ohms, the termination resistor is 120 Ohms and there is only one at each end of the bus. Your unit should never have less then 120 Ohms total termination.

Now i am going to car without cutting 60 ohm terminator with this sketch:

/*************************************************************************************************
    OBD-II_PIDs TEST CODE
    LOOVEE @ JUN24, 2017

    Query
    send id: 0x7df
      dta: 0x02, 0x01, PID_CODE, 0, 0, 0, 0, 0

    Response
    From id: 0x7E9 or 0x7EA or 0x7EB
      dta: len, 0x41, PID_CODE, byte0, byte1(option), byte2(option), byte3(option), byte4(option)

    https://en.wikipedia.org/wiki/OBD-II_PIDs

    Input a PID, then you will get reponse from vehicle, the input should be end with '\n'
***************************************************************************************************/
#include <SPI.h>

#define CAN_2515
// #define CAN_2518FD

// Set SPI CS Pin according to your hardware

#if defined(SEEED_WIO_TERMINAL) && defined(CAN_2518FD)
// For Wio Terminal w/ MCP2518FD RPi Hat:
// Channel 0 SPI_CS Pin: BCM 8
// Channel 1 SPI_CS Pin: BCM 7
// Interupt Pin: BCM25
const int SPI_CS_PIN  = BCM8;
const int CAN_INT_PIN = BCM25;
#else

// For Arduino MCP2515 Hat:
// the cs pin of the version after v1.1 is default to D9
// v0.9b and v1.0 is default D10
const int SPI_CS_PIN = 9;
const int CAN_INT_PIN = 2;
#endif


#ifdef CAN_2518FD
#include "mcp2518fd_can.h"
mcp2518fd CAN(SPI_CS_PIN); // Set CS pin
#endif

#ifdef CAN_2515
#include "mcp2515_can.h"
mcp2515_can CAN(SPI_CS_PIN); // Set CS pin
#endif

#define PID_ENGIN_PRM       0x0C
#define PID_VEHICLE_SPEED   0x0D
#define PID_COOLANT_TEMP    0x05

#define CAN_ID_PID          0x7DF

unsigned char PID_INPUT;
unsigned char getPid    = 0;

void set_mask_filt() {
    /*
        set mask, set both the mask to 0x3ff
    */
    CAN.init_Mask(0, 0, 0x7FC);
    CAN.init_Mask(1, 0, 0x7FC);

    /*
        set filter, we can receive id from 0x04 ~ 0x09
    */
    CAN.init_Filt(0, 0, 0x7E8);
    CAN.init_Filt(1, 0, 0x7E8);

    CAN.init_Filt(2, 0, 0x7E8);
    CAN.init_Filt(3, 0, 0x7E8);
    CAN.init_Filt(4, 0, 0x7E8);
    CAN.init_Filt(5, 0, 0x7E8);
}

void sendPid(unsigned char __pid) {
    unsigned char tmp[8] = {0x02, 0x01, __pid, 0, 0, 0, 0, 0};
    SERIAL_PORT_MONITOR.print("SEND PID: 0x");
    SERIAL_PORT_MONITOR.println(__pid, HEX);
    CAN.sendMsgBuf(CAN_ID_PID, 0, 8, tmp);
}

void setup() {
    SERIAL_PORT_MONITOR.begin(115200);
    while(!Serial){};

    while (CAN_OK != CAN.begin(CAN_500KBPS)) {             // init can bus : baudrate = 500k
        SERIAL_PORT_MONITOR.println("CAN init fail, retry...");
        delay(100);
    }
    SERIAL_PORT_MONITOR.println("CAN init ok!");
    set_mask_filt();
}


void loop() {
    taskCanRecv();
    taskDbg();

    if (getPid) {       // GET A PID
        getPid = 0;
        sendPid(PID_INPUT);
        PID_INPUT = 0;
    }
}

void taskCanRecv() {
    unsigned char len = 0;
    unsigned char buf[8];

    if (CAN_MSGAVAIL == CAN.checkReceive()) {                // check if get data
        CAN.readMsgBuf(&len, buf);    // read data,  len: data length, buf: data buf

        SERIAL_PORT_MONITOR.println("\r\n------------------------------------------------------------------");
        SERIAL_PORT_MONITOR.print("Get Data From id: 0x");
        SERIAL_PORT_MONITOR.println(CAN.getCanId(), HEX);
        for (int i = 0; i < len; i++) { // print the data
            SERIAL_PORT_MONITOR.print("0x");
            SERIAL_PORT_MONITOR.print(buf[i], HEX);
            SERIAL_PORT_MONITOR.print("\t");
        }
        SERIAL_PORT_MONITOR.println();
    }
}

void taskDbg() {
    while (SERIAL_PORT_MONITOR.available()) {
        char c = SERIAL_PORT_MONITOR.read();

        if (c >= '0' && c <= '9') {
            PID_INPUT *= 0x10;
            PID_INPUT += c - '0';

        } else if (c >= 'A' && c <= 'F') {
            PID_INPUT *= 0x10;
            PID_INPUT += 10 + c - 'A';
        } else if (c >= 'a' && c <= 'f') {
            PID_INPUT *= 0x10;
            PID_INPUT += 10 + c - 'a';
        } else if (c == '\n') { // END
            getPid = 1;
        }
    }
}
// END FILE

I will edit here after the test.

Edit:
Ok, first attempt is failed. Even i cant send message as well.

CAN.sendMsgBuf(CAN_ID_PID, 0, 8, tmp);

is not returns CAN_OK

I tried with cutting P1, and still same result. sendMsgBuf is not returns CAN_OK.
and TX RX leds always red, PWR always Green.

Idk whats wrong with my setup.

I guess it is about my soldered esp 13 shield. I am trying to use can shield on esp13 shield.