Electronic – arduino – SPI read error with MCP2515

arduino unocancommunicationspi

In an attempt to interface a motor controller, battery management system and maximum power point tracking device on a CAN bus, I used the MCP2515 and TJA1050 CAN breakout board. All these devices send out CAN messages at the same bit rates.
When interfacing with the motor controller, the messages were properly interpreted by Arduino. However, with both the other devices, there is an issue with the SPI read function.
I am using the Seeed library, the documentation for which can be found here: https://github.com/Seeed-Studio/CAN_BUS_Shield/blob/master/mcp_can.cpp

The following function returns the code that suggests that there is no message. The readStatus condition fails.

byte MCP_CAN::checkReceive(void)
{
    byte res;
    res = mcp2515_readStatus()              // RXnIF in Bit 1 and 0
    return ((res & MCP_STAT_RXIF_MASK)?CAN_MSGAVAIL:CAN_NOMSG);
}

The readStatus function is as follows:

byte MCP_CAN::mcp2515_readStatus(void)
{
    byte i;
#ifdef SPI_HAS_TRANSACTION
    SPI_BEGIN();
#endif
    MCP2515_SELECT();
    spi_readwrite(MCP_READ_STATUS);
    i = spi_read();
    MCP2515_UNSELECT();
#ifdef SPI_HAS_TRANSACTION
    SPI_END();
#endif

    return i;
}

The i value returns a 0.
Each of the devices has a termination resistor, so a 100 ohm resistor was added at the CAN module end. The voltages were measured with respect to CAN ground, around 2.7 and 2.1 on CANH and CANL lines respectively.

Best Answer

Do you know if your MPPT or BMS are configured to send CAN messages periodically without first receiving some external request over CAN?

For example, I know of at least two popular solar car MPPTs that will only send CAN messages in response to corresponding CAN frame with the same ID and with the remote transmission request (RTR) bit set.

You can try to distinguish between a CAN bus where all of the other nodes are declining to send messages and a CAN bus that is non-functional by attempting to send a CAN message and checking if it is ACKed. You should be able to do this in software by checking if the message transmits successfully or in hardware by probing the non-differential CANRX pin on the TJA1050 and checking for the ACK bit using a logic analyzer.

If you don't have a logic analyzer, you can use a two channel oscilloscope to monitor CANRX and CANTX of the TJA1050. When the MCP2515 transmits a message, CANRX and CANTX will be identical if nobody ACKs your message. If someone does ACK the message, you should see a single dominant (low) bit on CANRX that is not present on CANTX.

You may also want to try swapping out your 100 ohm termination resistor for a 120 ohm termination resistor - all of the CAN devices I've used personally have used 120 ohm termination resistors. I don't expect there would be compatibility issues, but it's trivial to swap it to rule out the termination resistor as a potential source of error.