[SOLVED] Using library Can-mcp25x causes "Failed to power on modem" on Tracker One

Hello Folks!

I’m extremely excited about the new MIT Licensed CAN library for the MCP25625 can interface devices. Thank you Particle for making this library! Its going to be a game changer for sure!

I have hit a slight bump in the road when it comes to implementation. I was migrating an early example of CAN_Receive.cpp from the MCP_CAN_RK repository, which was working nominally with the mcp-can library, but when I run it with the can-mcp25x library, I get an error where the MCP initialization fails and the mode does not connect.

Here is my example file. (modified to work with J1939 and read vehicle speed at 500k)

// CAN Receive Example - For Tracker One
// Remember to "Particle: Configure Project for Device" ->
// and selected 1.5.4-rc.1 and Tracker platform. 

// Example Updated: Adam Baumgartner, 9-18-2020

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

SYSTEM_THREAD(ENABLED);
SYSTEM_MODE(AUTOMATIC);

SerialLogHandler logHandler;

long unsigned int rxId;
const long unsigned int J1939speed = 0x18FEF100;
long unsigned int rxId_test;
unsigned char len = 0;
unsigned char rxBuf[8]; 
char msgString[128];    
char outputString[128];
unsigned int canSpeed = 65535;
int actualSpeed = 0;

MCP_CAN canInterface(CAN_CS, SPI1);                          

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

  // Wait 10 seconds for USB debug serial to be connected (plus 1 more)
  waitFor(Serial.isConnected, 10000);
  delay(1000);
  pinMode(CAN_PWR, OUTPUT);
  digitalWrite(CAN_PWR, HIGH);

  pinMode(CAN_STBY, OUTPUT);
  digitalWrite(CAN_STBY, LOW);
  pinMode(CAN_INT, INPUT);

  // Hardware reset the CAN controller. Not really necessary, but doesn't hurt.
  pinMode(CAN_RST, OUTPUT);
  digitalWrite(CAN_RST, LOW);
  delay(100);
  digitalWrite(CAN_RST, HIGH);

  // Initialize MCP2515 running at 16MHz with a baudrate of 500kb/s and the masks and filters disabled.
  if(canInterface.begin(MCP_EID0, CAN_500KBPS, MCP_20MHZ) == CAN_OK){
    Serial.println("MCP2515 Initialized Successfully!");
  }else{
    Serial.println("Error Initializing MCP2515...");
  }
  canInterface.setMode(MODE_NORMAL);  
  pinMode(CAN_INT, INPUT); 
}

void loop(){
  if(!digitalRead(CAN_INT)) 
  {
    canInterface.readMsgBufID(&rxId, &len, rxBuf); 
    if((rxId & 0x1FFFFFFF) == J1939speed){ 
      canSpeed = (rxBuf[2] << 8) | rxBuf[1]; 
      actualSpeed = canSpeed >> 8; 
      sprintf(outputString, " Speed kph: %d", actualSpeed);
      Serial.print(outputString);
      Serial.println();
    }
  }
}

And here is I get over serial monitor if when I run it.

For the migration instructions I followed the details at the bottom of AN017 Tracker CAN page.

I was looking to have the CAN initialization occur successfully and also fix having the modem fail to power on.

When I revert to using the MCP_CAN_RK library, and the slight typo changes, everything goes back to normal. I think the modem being shutdown and CAN chip not initializing are connected somehow.

I found the bug but for some reason I don’t have write permission to that repository. Until it’s fixed, in lib/can_mcp25x/src/mcp_can_dfs.h.

At the top of this file is this:

// if print debug information
#define CAN_DEBUG_MODE 0

Right after that, add this:

#if (PLATFORM_ID == PLATFORM_TRACKER) && !defined(MCP2515_NORMAL_WRITES)
#define MCP2515_NORMAL_WRITES 1
#endif
1 Like

It would also be good when the repository owner would enable issue reporting.

Hello RK, Thank you for the suggestion.

I added the extra code, but I am still getting an error when trying to Initialize the MCP2515 modem
and I’m also getting the error that the cellular modem fails to power on.

I didn’t see the change I expected. I’m surprised the CAN library affects the modem status. I suppose what’s happening here is the library crashes, which prevents things down the chain from starting up?

// CAN Receive Example - For Tracker One
// Remember to "Particle: Configure Project for Device" ->
// and selected 1.5.4-rc.1 and Tracker platform. 

// Example Updated: Adam Baumgartner, 9-18-2020

#define CAN_DEBUG_MODE 0

#if (PLATFORM_ID == PLATFORM_TRACKER) && !defined(MCP2515_NORMAL_WRITES)
#define MCP2515_NORMAL_WRITES 1
#endif

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


SYSTEM_THREAD(ENABLED);
SYSTEM_MODE(AUTOMATIC);

SerialLogHandler logHandler;

long unsigned int rxId;
const long unsigned int J1939speed = 0x18FEF100;
long unsigned int rxId_test;
unsigned char len = 0;
unsigned char rxBuf[8]; 
char msgString[128];    
char outputString[128];
unsigned int canSpeed = 65535;
int actualSpeed = 0;

MCP_CAN canInterface(CAN_CS, SPI1);                          

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

  // Wait 10 seconds for USB debug serial to be connected (plus 1 more)
  waitFor(Serial.isConnected, 10000);
  delay(1000);
  pinMode(CAN_PWR, OUTPUT);
  digitalWrite(CAN_PWR, HIGH);

  pinMode(CAN_STBY, OUTPUT);
  digitalWrite(CAN_STBY, LOW);
  pinMode(CAN_INT, INPUT);

  // Hardware reset the CAN controller. Not really necessary, but doesn't hurt.
  pinMode(CAN_RST, OUTPUT);
  digitalWrite(CAN_RST, LOW);
  delay(100);
  digitalWrite(CAN_RST, HIGH);

  // Initialize MCP2515 running at 16MHz with a baudrate of 500kb/s and the masks and filters disabled.
  if(canInterface.begin(MCP_SIDL, CAN_500KBPS, MCP_20MHZ) == CAN_OK){
    Serial.println("MCP2515 Initialized Successfully!");
  }else{
    Serial.println("Error Initializing MCP2515...");
  }
  canInterface.setMode(MODE_NORMAL);  
  pinMode(CAN_INT, INPUT); 
}

void loop(){
  if(!digitalRead(CAN_INT)) 
  {
    canInterface.readMsgBufID(&rxId, &len, rxBuf); 
    if((rxId & 0x1FFFFFFF) == J1939speed){ 
      canSpeed = (rxBuf[2] << 8) | rxBuf[1]; 
      actualSpeed = canSpeed >> 8; 
      sprintf(outputString, " Speed kph: %d", actualSpeed);
      Serial.print(outputString);
      Serial.println();
    }
  }
}

Also remove can_mcp-25x from your project.properties if it exists there as well. Try adding a compile error where you added the code to make sure your change is getting picked up.

The problem is that digitalWriteFast does not work on the SPI CS multiplexer used on the Tracker SoM to control several SPI devices including the CAN controller. If you call it, very bad things happen. The reason it affects the modem is that calling it on CAN_CS actually causes BGRST, the reset pin on the modem, connected to the nRF52, to toggle, which is why the modem won’t boot because it keeps getting reset.

1 Like

Hi @rickkas7,

All the other lines of the #define can cause a compile error if I have a “;” placed at the end.
But the part the new code does not seem to be able to be able to show a compile error.

I was not expecting that to happen, Do you think this line (10) is not being run?

// Example Updated: Adam Baumgartner, 9-18-2020

#define CAN_DEBUG_MODE 0 

#if (PLATFORM_ID == PLATFORM_TRACKER) && !defined(MCP2515_NORMAL_WRITES)
#define MCP2515_NORMAL_WRITES 1 ;[].why doesnt this cause a compile error??
#endif

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

Also here are the current project properties.

name=tracker-edge
version=5.0.0
license=Apache License, Version 2.0
sentence=Particle Tracker reference application
url=https://www.particle.io/particle-tracking-system/
repository=https://github.com/particle-iot/tracker-edge.git
architectures=particle-tracker
dependencies.MCP_CAN_RK=1.5.1

Oddly that won’t cause a compile error because it defines MCP2515_NORMAL_WRITES to be the funny string but it’s only checked with #ifdef not #if so it will still compile. Maybe try adding another line after the #define with an error instead.

Ah! Ok gotcha,

I added another error after the #define and it did show a compile errror.

#define CAN_DEBUG_MODE 0 

#if (PLATFORM_ID == PLATFORM_TRACKER) && !defined(MCP2515_NORMAL_WRITES)
#define MCP2515_NORMAL_WRITES 1 
error;
#endif

So, indeed, the extra #define and #if statements are being picked up by the compiler.
But yeah it seems like there is still an error because I’m still getting an error with No connection the the CAN chip and the cellular modem not connecting.

This is not mission critical for me today, but I would like to use it for a project as soon as possible.

Thank you for your help so far RK!

One last possibility: Remove the MCP_CAN_RK from project.properties and also from the lib directory, if it’s still there. Also do a Clean Application (local). Since some functions are named the same, it may be picking up the wrong one. Other than that, I’ll have to take a look on Monday.

Hi @rickkas7,

No change after removing the MCP_CAN_RK from project.properties

Thanks for taking a look at it this weekend! I’ll follow up early next week.

Thank you for your help!

Hi Folks,

I have been watching the Can-mcp25x and haven’t seen an update.
I’ll be using the Tracker One with a customer in November;
Is there any thing I can help with to have this library working nominally?

The fix will be incorporated in the tracker edge firmware, not in the can-mcp25x library. The new version of tracker-edge should be released in the next few weeks.

But I just realized why the patch did not work correctly for you. It needs to go into

lib/can-mcp25x/src/mcp_can_dfs.h

not into your main.cpp file, otherwise it won’t take effect. The patch should work until the new version of tracker-edge is released.

1 Like

Ah That’s explains why I was not seeing any effect.
I was using this patch for a specific side example that does not have the full setup of the tracker one layout.

Solution: is to do the following step:

In lib/src/mcp_can_dfs.h , add the additional lines 54 to 59.

54- // if print debug information
55- #define CAN_DEBUG_MODE 0
56- 
57- #if (PLATFORM_ID == PLATFORM_TRACKER) && !defined(MCP2515_NORMAL_WRITES)**
58- #define MCP2515_NORMAL_WRITES 1**
59- #endif**

Note: this only works if you are using the full Tracker One layout of software. If you are trying to do a side example where the MCP_CAN library is in the same folder as everything else, use the standard MCP_CAN library.