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(")");
*/
}