MCP_CAN data becomes 0xFF 0xFF… when most significant bit of data high

Hi there,

I've posted an identical thread over at Seeedstudio, but I'm not sure how to tag @coryjfowler in :slight_smile:

What it is, I am soo bloomin close to having working communications between two MCP2515s using the MCP_CAN library and two ESP32s. Messages fundamentally are sent and received fine, but I’ve noticed if the most significant bit of data, for example:
SEND Extended ID 0x00000356 DLC: 8 Data: 0xF5 0x00 0x00 0x00 0x00 0x00 0x00 0x00
245 0 0 0 0 0 0 0

The receiver always brings back
Extended ID: 0x00000356 DLC: 8 Data: 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF

If the most significant bit isn’t high, for example:
SEND Extended ID 0x00000356 DLC: 8 Data: 0x0F 0x15 0xD5 0xFF 0xC8 0xC8 0x00 0x00
15 21 213 255 200 200 0 0 Exiting sendCAN

The received data matches:
Extended ID: 0x00000356 DLC: 8 Data: 0x0F 0x15 0xD5 0xFF 0xC8 0xC8 0x00 0x00

Then it is received fine. I have traced the data out as far as I can go, seems to retain initial values up to sendMsg and no type conversions (all stay within INT8U, but when it comes to this level of detail, my knowledge isn’t there.

Any ideas at all?
Many thanks
Dan

Are you powering the MCP2515 using 3.3v?
If so are you using a 3.3v transceiver?

Most MCP2515 breakout boards have a 5v transceiver and therefore the whole board is usually designed to be powered by 5v. These boards require a high speed level shifter on the SPI lines when connected to a 3.3v microcontroller.

Hi there,

Thanks for taking the time to reply. Yes indeed it's a 5V 8Mhz MCP2515, driven via the 5V rail provided by the ESP itself via logic converters:

It is literally only when the first bit is high, which I would take as some part of the process trying to treat it (or the whole thing) as a negative value and flopping, resulting in the blank FF FF FF FF FF FF FF FF, but I can't find anything of significance.

At the moment in the proof of concept I am just providing/shorting GPIO13 with 3.3v on demand to ping a message on demand to save serial flooding, and I've forgone using the 'interrupt' level because regardless of holding the pin to input_pullup or leaving it float, the results of checking whether it had gone low (indicating received) was very... sporadic and bouncy and the serial monitor indicated a load of gpio_set_level errors (either pin out of range or value out of range, can't quite remember)

So instead, out of the main loop I leverage the checkReceive() instead.

    if (CAN0.checkReceive() == CAN_MSGAVAIL)
    {
        canResult = CAN0.readMsgBuf(&rxId, &ext, &len, rxBuf);
        while (canResult == CAN_OK)
        {
           ... do logic (in reality at the moment, flash the LED a load of times and post to serial)

           read next
        }
  }

Tbh it is working really good, of the 4 or 5 libraries I've plumbed into the concept, this actually gets somewhere.

I'm not adverse to posting the whole ino if that would help, it's only a small side project for taking values from a battery BMS via serial and posting them via CAN to an inverter, and will end up on github when complete anyway.

Many thanks
Dan

First observation is that those level shifters aren't normally fast enough for SPI. If you have an oscilloscope check the signal integrity.

If you are confident that the SPI signals are good then the first step is to do a loopback test to prove that each MCP2515 is working properly.

Wahhh I'm working blind :frowning:

Which kind of shifter would you recommend could I ask?

The 3.3v MOSI, SCK and CS outputs from the ESP to the MCP2515 board probably don't need to be shifted as the voltage levels will still likely be detected as zeros and ones.
However if you want to do it properly, you can upshift using something like the 74HCT125. You power this using 5v and undervolt the inputs. Adafruit uses this chip in its designs.

The MISO and INT from the MCP2515 to the ESP need to be downshifted using something like a 4050 buffer. You power this using 3.3v and overvolt the inputs.

Would not recommend the bidirectional TXS0108E due to possible oscillation issues.

lets go back a step.
Why do you need a MCP2515 at all on an ESP32?
The ESP32 comes already with built in CAN , you just need a CAN tranceiver, i.e. a SN65HVD233. But not a CAN controller like the MCP2515.

I agree, and I tried a transceiver only approach with libraries such as ACAN_ESP32 and Sandeep’s CAN library but in my experience, they were riddled with faults. Sandeeps would hang on send and ACAN’s buffers would just fill up and error.

Maybe I missed something obvious but my experience with very much questionable and cheap transceivers and poorly maintained libraries was not great, hence me going for the 2512 and a popular library.

I am however open to being educated/proven wrong if there is a library and transceiver that is recommended. It would make my life easier rather than the endless cycle of mod code, compile, flash, serial monitor, repeat!

Thanks a lot
Dan

I have used Sandeeps library

on boards with the SN65HVD230 or SN65HVD233 (don't remember exactly) and on some boards with the MCP2561. I haven't had major issues beside my own programming :wink:

I suspect that the sandeepmistry library has many open issues because it has essentially been abandoned for many years while the development of new hardware has marched onwards.

In addition chipageddon has resulted in a proliferation of fake transceivers that have caused problems that people have incorrectly blamed on library issues.

Given that there is now an official ESP32 board it would make sense for the Arduino company to get the library development going again by making an official fork, improving the error handling code, and updating the examples to include proper RTOS tasks that don't trigger the watchdog. However, I would surprised if any of this were to actually happen.

@mikb55 you hit the nail on the head with the logic shifters.
Loopback demonstrated the same results, so I started playing with linking direct to the ESP32 to investigate further.

First attempt, MOSI 3.3v direct to MCP2515, just the same.
SEND Extended ID 0x00000356 DLC: 8 Data: 0xF0 0x15 0xD5 0xFF 0xC8 0xC8 0x00 0x00
Exiting sendCAN
Extended ID: 0x00000356 DLC: 8 Data: 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF

Second attempt, MOSI 3.3v and CS 3.3v direct to MCP2515, very much a different set of data coming through. That was the breakthrough really, that evidenced change.
--- End Formatted ---
SEND Extended ID 0x00000356 DLC: 8 Data: 0xF0 0x15 0xD5 0xFF 0xC8 0xC8 0x00 0x00
Exiting sendCAN
Extended ID: 0x00000356 DLC: 8 Data: 0xE0 0x2B 0xAB 0xFF 0x91 0x90 0x00 0x00

And finally, MOSI 3.3V and CS 3.3v and CLK 3.3v direct to MCP2515
--- End Formatted ---
SEND Extended ID 0x00000356 DLC: 8 Data: 0xF0 0x15 0xD5 0xFF 0xC8 0xC8 0x00 0x00
Exiting sendCAN
Extended ID: 0x00000356 DLC: 8 Data: 0xF0 0x15 0xD5 0xFF 0xC8 0xC8 0x00 0x00

Interestingly, the /cheap/ logic shifter seems alright for the MISO from the MCP2515 but very much not too good at dealing with the clock. I suspect CS, given it just needs to be held low during transmission would be fine through the shifter, but it seems a bit redundant given that, as you suspected, the MCP2515 recognised 3.3V inputs across the board.

I'll get the 5V->3.3V buffer (74HC4050) for cleanliness and robustness as I can see them from various online shops/eBay (UK) but the 3.3V->5V is a little more hard to come by it seems.

Thanks for pointing me in the right direction. Now to test across two devices!

And yes, works across the two, COM9 is the sending ESP32, COM3 the receiving:

Thanks again.