CAN Bus using Teensy 4.1

Hi,

I'm trying to implement a CAN bus for my universities Formula Student car. I am using a Teensy 4.1 as my microcontroller to read the CAN messages and display them on an Adafruit HX8357 display.

To complete the CAN interface for the Teensy i'm using an ISO1050 isolated CAN transceiver (see link below) which connects directly to CAN_H and CAN_L of the CAN bus, and CRX3 and CTX3 of the Teensy.

The CAN data is coming from a PM100DX inverter, which already has a CAN node built into it. (See CAN protocol documentation attached below).

All I am trying to do initially is get this data displayed onto the serial monitor and then its a small step from there to get it displayed onto the screen. I am using the FlexCAN_T4 library to program the Teensy (in Arduino IDE of course) but nothing is happening.

I will point out that i'm using a PCAN USB to monitor the traffic on the bus and there is definitely data on the CAN_H and CAN_L wires which go into the transceiver.

Here is my code thus far:

#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_HX8357.h>
#include <FlexCAN_T4.h>

#define TFT_CS 10
#define TFT_DC 9
#define TFT_RST 8
#define CRX3 30
#define CTX3 31

unsigned int motor_data;

Adafruit_HX8357 tft = Adafruit_HX8357(TFT_CS, TFT_DC, TFT_RST);
FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_16> can;

///////////////////////////////////////////////////////////////////////////////////////////////////
void setup() {

  Serial.begin(115200);
  delay(3000);
  Serial.println("Code Debug");
  Serial.println("  ");

  pinMode(CRX3, INPUT);
  pinMode(CTX3, OUTPUT);

  //Initialise the screen
  tft.begin();
  tft.setRotation(1);
  firstScreen();
  motor_speed();

  //Initialise the CAN bus
  can.begin();
  can.setBaudRate(250000);
  can.enableFIFO();
}
///////////////////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////////////////////
void loop() {
  CAN_message_t msg;
  while (can.read(msg)) {
    Serial.print("ID: ");
    Serial.print(msg.id, HEX);
    Serial.print(" Data: ");
    for (int i = 0; i < msg.len; i++) {
      Serial.print(msg.buf[i], HEX);
      Serial.print(" ");
    }
    Serial.println();
  }
}
///////////////////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////////////////////
void firstScreen() {
  Serial.begin(115200);
  Serial.println("You are on the first screen");

  //Backround
  tft.fillScreen(HX8357_BLACK);

  //Outer Borders
  tft.drawFastHLine(0, 0, 480, HX8357_WHITE);    //Top Border
  tft.drawFastHLine(1, 319, 480, HX8357_WHITE);  //Bottom Border
  tft.drawFastVLine(479, 0, 319, HX8357_WHITE);  //Left Border
  tft.drawFastVLine(0, 0, 319, HX8357_WHITE);    //Right Border

  //Inner Borders
  tft.drawFastVLine(240, 0, 320, HX8357_WHITE);    //Down the middle
  tft.drawFastHLine(0, 30, 480, HX8357_WHITE);     //Top Border - Horizontal
  tft.drawFastHLine(0, 155, 240, HX8357_WHITE);    //Range Intersect
  tft.drawFastHLine(0, 295, 240, HX8357_WHITE);    //Battery Level Intersect
  tft.drawFastHLine(240, 200, 240, HX8357_WHITE);  //Speed Intersect
  tft.drawFastVLine(360, 200, 120, HX8357_WHITE);  //Torque Intersect

  //Titles
  tft.setCursor(100, 5);
  tft.setTextColor(HX8357_WHITE);
  tft.setTextSize(3);
  tft.println("BMS");

  tft.setCursor(320, 5);
  tft.setTextColor(HX8357_WHITE);
  tft.setTextSize(3);
  tft.println("MOTOR");

  ////BMS////

  //Range
  tft.setCursor(90, 80);
  tft.setTextColor(HX8357_WHITE);
  tft.setTextSize(2);
  tft.println("Range");

  tft.setCursor(70, 110);
  tft.setTextColor(HX8357_WHITE);
  tft.setTextSize(2);
  tft.println("-- miles");

  for (int p = 2000; p < 4000; p++) {
    int j, j2, i, i2;
    j = 100 * (sin(PI * p / 2000));
    i = 100 * (cos(PI * p / 2000));
    j2 = 90 * (sin(PI * p / 2000));
    i2 = 90 * (cos(PI * p / 2000));
    tft.drawLine(i2 + 120, j2 + 140, i + 120, j + 140, HX8357_GREEN);
  }

  //Battery Temperature
  tft.setCursor(83, 225);
  tft.setTextColor(HX8357_WHITE);
  tft.setTextSize(2);
  tft.println("BatTemp");

  tft.setCursor(80, 255);
  tft.setTextColor(HX8357_WHITE);
  tft.setTextSize(2);
  tft.println("-- degC");

  //Outer Gauge
  for (int p = 2000; p < 2666; p++) {
    int j, j2, i, i2;
    j = 100 * (sin(PI * p / 2000));
    i = 100 * (cos(PI * p / 2000));
    j2 = 90 * (sin(PI * p / 2000));
    i2 = 90 * (cos(PI * p / 2000));
    tft.drawLine(i2 + 120, j2 + 270, i + 120, j + 270, HX8357_GREEN);
  }

  for (int p = 2666; p < 3332; p++) {
    int j, j2, i, i2;
    j = 100 * (sin(PI * p / 2000));
    i = 100 * (cos(PI * p / 2000));
    j2 = 90 * (sin(PI * p / 2000));
    i2 = 90 * (cos(PI * p / 2000));
    tft.drawLine(i2 + 120, j2 + 270, i + 120, j + 270, HX8357_YELLOW);
  }

  for (int p = 3332; p < 4000; p++) {
    int j, j2, i, i2;
    j = 100 * (sin(PI * p / 2000));
    i = 100 * (cos(PI * p / 2000));
    j2 = 90 * (sin(PI * p / 2000));
    i2 = 90 * (cos(PI * p / 2000));
    tft.drawLine(i2 + 120, j2 + 270, i + 120, j + 270, HX8357_RED);
  }

  //Inner Gauge
  for (int p = 2000; p < 300 * 2000 / 180; p++) {
    int j, j2, i, i2;
    j = 85 * (sin(PI * p / 2000));
    i = 85 * (cos(PI * p / 2000));
    j2 = 75 * (sin(PI * p / 2000));
    i2 = 75 * (cos(PI * p / 2000));
    tft.drawLine(i2 + 120, j2 + 270, i + 120, j + 270, HX8357_WHITE);
  }

  //Battery Charge
  tft.fillRect(6, 300, 43, 15, HX8357_GREEN);
  tft.fillRect(53, 300, 43, 15, HX8357_GREEN);
  tft.fillRect(100, 300, 43, 15, HX8357_GREEN);
  tft.fillRect(147, 300, 43, 15, HX8357_GREEN);
  tft.fillRect(194, 300, 43, 15, HX8357_GREEN);

  ////Motor////

  // //Speed
  // tft.setCursor(320, 50);
  // tft.setTextColor(HX8357_WHITE);
  // tft.setTextSize(3);
  // tft.println("Speed");

  // tft.setCursor(300, 110);
  // tft.setTextColor(HX8357_WHITE);
  // tft.setTextSize(5);
  // tft.println(motor_data);

  // tft.setCursor(350, 110);
  // tft.setTextColor(HX8357_WHITE);
  // tft.setTextSize(5);
  // tft.println(" mph");

  //Torque
  tft.setCursor(265, 220);
  tft.setTextColor(HX8357_WHITE);
  tft.setTextSize(2);
  tft.println("Torque");

  tft.setCursor(260, 270);
  tft.setTextColor(HX8357_WHITE);
  tft.setTextSize(3);
  tft.println("-- Nm");
}

void motor_speed() {
  //Speed
  tft.setCursor(320, 50);
  tft.setTextColor(HX8357_WHITE);
  tft.setTextSize(3);
  tft.println("Speed");

  tft.setCursor(300, 110);
  tft.setTextColor(HX8357_WHITE);
  tft.setTextSize(5);
  tft.println(motor_data);

  tft.setCursor(350, 110);
  tft.setTextColor(HX8357_WHITE);
  tft.setTextSize(5);
  tft.println(" mph");
}
///////////////////////////////////////////////////////////////////////////////////////////////////

Apologies for any glaringly obvious mistake, I am extremely new to the CAN protocol and have much to learn in regards to my programming skills as well. Would appreciate any help. Thanks.

Links:

https://app.box.com/s/vf9259qlaadhzxqiqrt5cco8xpsn84hk/file/27334613044

Do you get this part?

I do, yes...

Okay. You said nothing was happening so I just wanted to be sure.

Actually, do you make it through all of the items in your setup function calls? Maybe add a serial.println with a delay before the CAN read just as a test that it's looping?

Not a problem.

I believe so. The setup calls for the graphics function names "firstScreen()" which runs fine.
I put a serial.println just before the while loop and can.read() and it its running on the serial monitor okay...

I'm a little confused. At first you said nothing worked. When you say that, I'm imagining the screen didn't come on, no serial communication, etc. Can you be specific about the issue(s) you are having.

I apologise for the confusion.

The screen and graphics are working fine.

The issue is receiving the CAN data. When I have the inverter on and connected to the bus, I can see the CAN messages on the bus using PCAN-View. All i'm trying to do is read the data I already know is there and display it on my serial monitor, from there it should just be a small step to then get it displayed on my screen.

The problem is, the code I've written doesn't seem acknowledge that there's any data there to be read and hence nothing happens.
I'm missing something somewhere and I don't know know where the issue lies...

Hope this clears things up a bit better...

How about on the hardware side? Do you see any pin activity on 30 or 31 with a scope or frequency measurement on a meter?

So, I actually had to replace the ISO1050 as it was blown, but now its replaced, I can definitely see CAN data coming out of the RX TX pins of the ISO and going into the Teensy...
However it still doesn't seem to see anything....

If the interface blew, are you sure your pins didn't as well?

I haven't used that board, but can you set the CAN pins to work as standard IO? Set one to blink, and one to digital read. See if it turns on and reads properly?

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.