Nano 33BLE and Can Bus Shield - compatibility issue

Good morning,

I need to use an Arduino Nano 33 BLE with a TFT Display (Adafruit) and CAN BUS Shield (Seed Studio).
Display and CAN Bus are on SPI bus, each one with different CS.

Well, everything works using an Arduino Mega 2560 but using the same sketch and the same connections (adapted to the Nano pinout) with the Arduino 33 BLE, nothing works, CAN doesn't dispatch messages and TFT Display stay WHITE since the power on.

Trying some testing, looks like that the problem is the mcp2515_can.h because compiling the sketch without it (and without all the related code parts) the display works correctly (CAN obviously not).

Do you know if there are some issues (non compatibility for example) between mcp2515.h and arduino nano 33 ble?

Thanks a lot!

Following the sketch code:

#include <SPI.h>
#include "mcp2515_can.h"
#include "Adafruit_GFX.h"
#include "Adafruit_HX8357.h"

#define CAN_2515
#define MAX_DATA_SIZE 8
#define TFT_CS 10
#define TFT_DC 9
#define TFT_RST -1 

const int CAN_SPI_CS_PIN = 6;

uint32_t id;
uint8_t  type; // bit0: ext, bit1: rtr
uint8_t  len;
byte cdata[MAX_DATA_SIZE] = {0};
unsigned char buf[8];
uint32_t ulCanId;

uint32_t dCycleTime, dCycleTimeStart, dCycleTimeMax;

uint32_t ulMsgID;
uint8_t  bBuffStartData;
float    fReadData, fScaleData;

uint32_t startMillis;           
uint32_t currentMillis;
const uint32_t tftRefreshPeriod = 250;   //the value is in milliseconds

uint16_t wThrottleGrip, wVehicleSpeed, wReadyStop, wMotorRPM;
float fOdometerTot, fOdometerPart, fTorqueRequest;
float f48VBatterySOC;

// Display object
Adafruit_HX8357 tft = Adafruit_HX8357(TFT_CS, TFT_DC, TFT_RST);
// CAN shield object
mcp2515_can CAN(CAN_SPI_CS_PIN); 


// Color definitions
#define BLACK       0x0000      /*   0,   0,   0 */
#define NAVY        0x000F      /*   0,   0, 128 */
#define DARKGREEN   0x03E0      /*   0, 128,   0 */
#define DARKCYAN    0x03EF      /*   0, 128, 128 */
#define MAROON      0x7800      /* 128,   0,   0 */
#define PURPLE      0x780F      /* 128,   0, 128 */
#define OLIVE       0x7BE0      /* 128, 128,   0 */
#define LIGHTGREY   0xC618      /* 192, 192, 192 */
#define DARKGREY    0x7BEF      /* 128, 128, 128 */
#define BLUE        0x001F      /*   0,   0, 255 */
#define GREEN       0x07E0      /*   0, 255,   0 */
#define CYAN        0x07FF      /*   0, 255, 255 */
#define RED         0xF800      /* 255,   0,   0 */
#define MAGENTA     0xF81F      /* 255,   0, 255 */
#define YELLOW      0xFFE0      /* 255, 255,   0 */
#define WHITE       0xFFFF      /* 255, 255, 255 */
#define ORANGE      0xFD20      /* 255, 165,   0 */
#define GREENYELLOW 0xAFE5      /* 173, 255,  47 */
#define PINK        0xF81F


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

    #if MAX_DATA_SIZE > 8
    CAN.setMode(CAN_NORMAL_MODE);
    #endif

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


  tft.begin();
  tft.setRotation(3);
  drawInitialScreen();
  readCanData();
  drawData();      
  startMillis = millis();  //initial start time
  
}
  
void loop() {
  currentMillis = millis();
  dCycleTimeStart = micros(); 
  unsigned char len = 0;

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

      ulCanId = CAN.getCanId();
  readCanData ();
  
  }

//Timing to next data Write on TFT
 if (currentMillis - startMillis >= tftRefreshPeriod)
  {
   drawData();
   startMillis = currentMillis;  
  }

// CPU Cycle time calculus
  dCycleTime = micros() - dCycleTimeStart;
  if (currentMillis > 5000) {
    if (dCycleTimeMax < dCycleTime) {
     dCycleTimeMax = dCycleTime; 
   } 
  }  
}

float fReadInteger16_BE (unsigned char ucBuffer[8], uint8_t bStartByte, float fScale){
  float fValTmp = 0;
  int16_t iValTmp = 0;
  if ( (bStartByte < 1) || (bStartByte > 7) ) {
    fValTmp = 0;
    return fValTmp;
  }
  iValTmp = ucBuffer[bStartByte-1] << 8;
  iValTmp = iValTmp + ucBuffer[bStartByte];
  fValTmp = float(iValTmp)*fScale;
  return fValTmp;   
}

float fReadByte_BE (unsigned char ucBuffer[8], uint8_t bStartByte, float fScale){
  float fValTmp = 0;
  int16_t iValTmp = 0;
  if ( (bStartByte < 0) || (bStartByte > 7) ) {
    fValTmp = 0;
    return fValTmp;
  }
  iValTmp = ucBuffer[bStartByte];
  fValTmp = float(iValTmp)*fScale;
  return fValTmp;   
}

uint16_t wReadByte_BE (unsigned char ucBuffer[8], uint8_t bStartByte){
  uint16_t wValTmp = 0;
  if ( (bStartByte < 0) || (bStartByte > 7) ) {
    wValTmp = 0;
    return wValTmp;
  }
  wValTmp = ucBuffer[bStartByte];
  return wValTmp;   
}

float fReadInteger16_LE (unsigned char ucBuffer[8], uint8_t bStartByte, float fScale){
  float fValTmp = 0;
  int16_t iValTmp = 0;
  if ( (bStartByte < 0)||(bStartByte > 6) ) {
    fValTmp = 0;
    return fValTmp;
  }
  iValTmp = ucBuffer[bStartByte+1] << 8;
  iValTmp = iValTmp + ucBuffer[bStartByte];
  fValTmp = float(iValTmp)*fScale;
  return fValTmp;   
}

float fReadByte_LE (unsigned char ucBuffer[8], uint8_t bStartByte, float fScale){
  float fValTmp = 0;
  int16_t iValTmp = 0;
  if ( (bStartByte < 0) || (bStartByte > 7) ) {
    fValTmp = 0;
    return fValTmp;
  }
  iValTmp = ucBuffer[bStartByte];
  fValTmp = float(iValTmp)*fScale;
  return fValTmp;   
}

uint16_t wReadByte_LE (unsigned char ucBuffer[8], uint8_t bStartByte){
  uint16_t wValTmp = 0;
  if ( (bStartByte < 0) || (bStartByte > 7) ) {
    wValTmp = 0;
    return wValTmp;
  }
  wValTmp = ucBuffer[bStartByte];
  return wValTmp;   
}

/************************************* 
 * READ DATA FROM CAN BUS
 *************************************/
 
void readCanData(){

// Throttle Grip Percentage
  ulMsgID = 3;
  bBuffStartData = 5;
  fScaleData = 0.1;

  if (ulCanId == ulMsgID) {
    wThrottleGrip = uint16_t(fReadInteger16_BE(buf, bBuffStartData, fScaleData));
  }

// Torque Request
  ulMsgID = 2;
  bBuffStartData = 3;
  fScaleData = 0.1;

  if (ulCanId == ulMsgID) {
     fTorqueRequest = fReadInteger16_BE(buf, bBuffStartData, fScaleData);
  }
  
// Odometer Total
  ulMsgID = 3;
  bBuffStartData = 1;
  fScaleData = 0.1;

  if (ulCanId == ulMsgID) {
     fOdometerTot = fReadInteger16_BE(buf, bBuffStartData, fScaleData);
  }
 
// Odometer Partial
  ulMsgID = 3;
  bBuffStartData = 3;
  fScaleData = 0.01;

  if (ulCanId == ulMsgID) {
     fOdometerPart = fReadInteger16_BE(buf, bBuffStartData, fScaleData);
  }
 
// 48V Battery SOC
  ulMsgID = 196;
  bBuffStartData = 0;
  fScaleData = 0.4;

  if (ulCanId == ulMsgID) {
     f48VBatterySOC = fReadByte_BE(buf, bBuffStartData, fScaleData);
  }

// Vehicle Speed
  ulMsgID = 2;
  bBuffStartData = 1;
  fScaleData = 0.1;

  if (ulCanId == ulMsgID) {
     wVehicleSpeed = uint16_t(fReadInteger16_BE(buf, bBuffStartData, fScaleData));
  }
 
// Motor RPM
  ulMsgID = 672;
  bBuffStartData = 3;
  fScaleData = 1;

  if (ulCanId == ulMsgID) {
     wMotorRPM = uint16_t(fReadInteger16_BE(buf, bBuffStartData, fScaleData));
  }
  // protect against some too high value  
  if (wMotorRPM >= 20000) {wMotorRPM = 0;}
  
 
// Ready-Stop
  ulMsgID = 1;
  bBuffStartData = 1;
  fScaleData = 1;

  if (ulCanId == ulMsgID) {
     wReadyStop = uint16_t(fReadInteger16_BE(buf, bBuffStartData, fScaleData));
  }

}

void drawInitialScreen() {

  tft.fillScreen(BLACK);

// title
  tft.setCursor(10, 10);
  tft.setTextColor(RED);  
  tft.setTextSize(4);
  tft.println("DASHBOARD");
  tft.drawLine(10, 50, 460, 50, CYAN);

// Descriptions Grid
  tft.setTextSize(2);
  tft.setTextColor(WHITE);  

// Throttle Grip
  tft.drawRoundRect(10, 60, 460, 30, 5, CYAN);
  tft.setCursor(20, 68);
  tft.println("Throttle Grip [%]: ");

// Torque Request
  tft.drawRoundRect(10, 90, 460, 30, 5, CYAN);
  tft.setCursor(20, 98);
  tft.println("Torque Request [Nm]: ");

// Vehicle Speed
  tft.drawRoundRect(10, 120, 460, 30, 5, CYAN);
  tft.setCursor(20, 128);
  tft.println("Vehicle Speed [km/h]: ");

// Motor RPM
  tft.drawRoundRect(10, 150, 460, 30, 5, CYAN);
  tft.setCursor(20, 158);
  tft.println("Motor RPM [rpm]: ");

// Odometer Total
  tft.drawRoundRect(10, 180, 460, 30, 5, CYAN);
  tft.setCursor(20, 188);
  tft.println("Odometer Total [km]: ");

// Odometer Partial
  tft.drawRoundRect(10, 210, 460, 30, 5, CYAN);
  tft.setCursor(20, 218);
  tft.println("Odometer Partial [km]: ");

// Odometer Partial
  tft.drawRoundRect(10, 240, 460, 30, 5, CYAN);
  tft.setCursor(20, 248);
  tft.println("48V Battery SOC [%]: ");

// Ready-Stop 
  tft.drawRoundRect(10, 270, 460, 30, 5, CYAN);
  tft.setCursor(20, 278);
  tft.println("Ready-Stop: ");



/* Arduino Cycle Time
  tft.drawRoundRect(10, 290, 460, 30, 5, RED);
  tft.setCursor(20, 298);
  tft.println("CPU Cycle (max) [usec]: ");
*/
}

void drawData() {

// Data Values on TFT
  tft.setTextColor(YELLOW);  

// Throttle Grip
  tft.fillRect(300, 62, 100, 26, BLACK);
  tft.setCursor(305, 68);
  tft.println(wThrottleGrip);

// Torque Request
  tft.fillRect(300, 92, 100, 26, BLACK);
  tft.setCursor(305, 98);
  tft.println(fTorqueRequest, 1);

// Vehicle Speed
  tft.fillRect(300, 122, 100, 26, BLACK);
  tft.setCursor(305, 128);
  tft.println(wVehicleSpeed);

// Motor RPM
  tft.fillRect(300, 152, 100, 26, BLACK);
  tft.setCursor(305, 158);
  tft.println(wMotorRPM);

// Odometer Total
  tft.fillRect(300, 182, 100, 26, BLACK);
  tft.setCursor(305, 188);
  tft.println(fOdometerTot, 1);

// Odometer Partial
  tft.fillRect(300, 212, 100, 26, BLACK);
  tft.setCursor(305, 218);
  tft.println(fOdometerPart, 2);

// 48V Battery SOC
  tft.fillRect(300, 242, 100, 26, BLACK);
  tft.setCursor(305, 248);
  tft.println(f48VBatterySOC, 1);

// Ready-Stop
  tft.fillRect(300, 272, 100, 26, BLACK);
  tft.setCursor(305, 278);
//  tft.println(wReadyStop);  
  if (wReadyStop == 1) {
    tft.setTextColor(GREEN);  
    tft.println("READY");
  }else {
    tft.setTextColor(RED);  
    tft.println("STOP");
  }


/* Arduino cycle time
  tft.fillRect(300, 292, 150, 26, BLACK);
  tft.setCursor(305, 298);
  tft.setTextColor(LIGHTGREY);  
  tft.print(dCycleTime);
  tft.print(" (");
  tft.print(dCycleTimeMax);
  tft.println(")");
*/ 

}


It may be helpful if you tell us where you got the library that contains this file. If you installed it via the Arduino IDE Library Manager, then tell us the exact and full name of the library as shown in Library Manager.


I will recommend this library, which was written by one of Arduino's own firmware developers, and explicitly states Nano 33 BLE compatibility:

You can install it via Library Manager ("107-Arduino-MCP2515 by Alexander Entinger") and it comes with a couple of example sketches to demonstrate its usage.

Good morning,
thanks to reply.

The library that I'm using is that one made from the vendor.
https://github.com/Seeed-Studio/Seeed_Arduino_CAN
the version is the 2.3.1.

I'll download the counciled library in order to try it.

Yesterday I tried other tests and it looks like as the NANO 33-BLE SPI management has a bug.
Leaving all the code into the sketch and disconnecting the SCK from can shield, the tft works (after few reboot).
Connecting the SCK the tft continue to work for few seconds and then return blank as if there is some conflict.

Thanks!

I have used that library successfully with the Arduino MKR CAN Shield on an Arduino MKR Zero board, but I don't have any experience using it with the Nano 33 BLE.

There is some information about that library here:

Thanks a lot in0!