FlexCAN_T4 - FlexCAN for Teensy 4

Great, thanks for confirming.
I put in a different Teensy MicroMod that I had in another carrier board and it worked - so it must have been a bad unit from the production line.
 
I have two sets right now. In on combination I do not get USB communication with one of them. If I swap the Micromod Teensy's around then everything works fine.

This is definitely a connector tolerance issue.

I have build 3 other boards with the Teensy 4.1 and work flawlessly.
Tennsy 4_1 3CAN.jpg
Good old DIP pins never failed me.
 
While the DIP package is much more reliable, the form factor of the MicroMod is a winner for me.
Its small and easily replaceable!
 
That is why I developed both packages.

Depends if you want resident Ethernet or not.

Teensy 4.1 has 100 mbs ethernet on board also the SDIO micro SD card is a tiny more stable then having to put it on a separate board.

Distance does matter when it comes to signal integrity/timing delays and so on.

As far as I know the other micromod carrier boards use SPI not SDIO which is a waste if you are using the Teensy micromod.

So I have both ready to roll but still working on the software.

I can read DBC file and acquire/calculate both 11 and 29 but messages/signal. Send/receive PIDs including ISO TP with multiple modes (1, 9, 22) and so on.

I have GUI interface via BT 2.0 and Virtuino.

Now working on J1939 networking. Got the address claim down and working on the TP messages now.

Waiting for J1939 DBC with request messages (>8 byte messages for J1939).
 
I can read DBC file and acquire/calculate both 11 and 29 but messages/signal. Send/receive PIDs including ISO TP with multiple modes (1, 9, 22) and so on.

I have GUI interface via BT 2.0 and Virtuino.

Now working on J1939 networking. Got the address claim down and working on the TP messages now.

Waiting for J1939 DBC with request messages (>8 byte messages for J1939).

Do you mind sharing some of this code?
I'm looking to do something similar but been thinking on the best approach forward.
I'm only querying mode 22, but I would like to allow the user to choose up to 8 different PID's to poll in compressed frames via a UI.
 
Shifting Payload of CAN-FD Frame

Hey guys,

After successfully splitting up CAN-FD frames into CAN Frames I am now at a point where I have to shift the payload of the CAN-FD payload. The reason is that I can't extract information about e.g. a velocity signal out of two seperate generated CAN Frames.

To achieve the shift I wanted to keep it simple and overwrite each buffer element of CANFD_message_t &msg struct with ist successor.

Code:
for (i = 1; i < msg.len; i++){
      msg.buf[i] = msg.buf[i+1];
    }

In order to avoid compile errors, I removed the "const" assignment of "CANFD_message_t &msg"
Awkwardly nothing changes in the payload and my outcoming CAN-Frames are not shifted.
Even more controversial is the fact, that trying following did its job:

Code:
msg.buf[0] = msg.buf[1];

Did I miss some special C/C++ rules regarding for loops, or do you recognize an mistake in my simple for loop?
I would be very glad if someone could help me.I am also willing to change my approach of shifting Bytes in the CAN-FD payload;)
 
Code:
for (i = 1; i < msg.len; i++){
      msg.buf[i] = msg.buf[i+1];
    }


Code:
msg.buf[0] = msg.buf[1];

If the msg data is 8 bytes long, msg.len is 8.
Valid indices for msg.buf are 0:7. Your last loop iteration is then:
Code:
msg.buf[7] = msg.buf[8];
which is out of range. Also, the first index msg.buf[0] is never assigned in your loop, unlike the line that worked.
 
Hi everyone!

Code:
In file included from /Users/iuser/Desktop/CODE/sketch/config.h:19:0,
                 from /Users/iuser/Desktop/CODE/sketch/sketch.ino:16:
/Users/iuser/Desktop/CODE/sketch/src/drivers/tja1051/FlexCAN_T4.h:560:26: fatal error: FlexCAN_T4.tpp: No such file or directory
 #include "FlexCAN_T4.tpp"
                          ^
compilation terminated.

Why the compiler does not see templates files?

Can I leave the library files where I want them or do I have to add the library to the Arduino folder?
 
I renaming .tpp files to _template.h and adjust the include statement accordingly.
I don't know yet if this solution will work fine. Because I don't understand how templates work at all.

For posterity - this problem occurs only in the Arduino IDE, in the PlatformIO this problem does not arise. This is due to the fact that in Arduino IDE template files cannot be located in the same folder with the sketch
 
it runs fine in the Arduino IDE, template (.tpp) files are supported by it, no need to rename. Even if you do rename you still need to edit the new name in the .h file to reflect that.
 
Hi tonton81!
It runs fine when library added to /Users/iuser/Documents/Arduino or with command add zip library file in Arduino IDE.
But in my case, the library is located in a folder on the desktop. Therefore, when you compile it, you get an error that the .TPP files is not found.
I solved this problem by renaming the TPP file to "_template.h". In the parent header file I made the necessary replacements and everything compiled.
But now I have doubts about correct workability of this variant.
 
workability? well if it compiles it should work because without the linkage of both files it will be impossible to compile
 
I wasn't expecting any problems. I have long-term experience with the SN65HVD230D chips and they're flawless.
Here's my setup. This is a custom PCB I made, which has dual TCAN330's. There are pins to pull SHDN/SILENT modes high or low (Teensy pins 2, 3).
The board has a jumper pad that should be cut to either control SHDN or S. I have not cut the trace, thinking I can just pull both low at the same time (maybe this is the mistake?).
I am using one of the examples sketches, just adding the pullup/down:

I am connecting to an 11B/250K CAN simulator. This is known working, tested with a different device.
I'm using CAN2 (pins 0, 1), pulling the appropriate function pin low (sleepPin1), but not getting anything at all from the Teensy. I have also tried removing the 120ohm resistor.
sleepPin2 is high to disable CAN1 (22, 23). I have a common ground with the simulator.
Any ideas are greatly appreciated.

View attachment 24320

I'm having a similar issue with a similar board with a MAX3051 transceiver. Can't figure out why it's not working, I've tested on 2xT4.1 and 2xtransceiver boards, both on CAN1 and CAN2, TX buffers just keep filling up. Receiving end is a Pican2 Duo that I've verified is working correctly with other CAN devices. Bus termination is OK, 60 Ohm on the bus. Even tried different clock settings, but just can't seem to get it working. No receive either. Have triple checked all the wiring, should be good and checked connections even on the PCB traces that everything is hooked up as it should:confused:

Code that I've been using for testing:

Code:
#include <FlexCAN_T4.h>
FlexCAN_T4<CAN2, RX_SIZE_256, TX_SIZE_256> Can0;

void setup(void) {
  Serial.begin(115200); delay(400);
  pinMode(2, OUTPUT); digitalWrite(2, LOW); // enable tranceiver
  pinMode(3, OUTPUT); digitalWrite(3, LOW); // enable tranceiver
  delay(1000);
  Can0.begin();
  //Can0.setClock(CLK_24MHz);
  Can0.setBaudRate(250000);
  Can0.setMaxMB(16); // up to 64 max for T4, not important in FIFO mode, unless you want to use additional mailboxes with FIFO
  Can0.enableFIFO();
  Can0.enableFIFOInterrupt();
  Can0.onReceive(canSniff);
  Can0.mailboxStatus();

}

void canSniff(const CAN_message_t &msg) {
  Serial.print("MB "); Serial.print(msg.mb);
  Serial.print("  OVERRUN: "); Serial.print(msg.flags.overrun);
  Serial.print("  LEN: "); Serial.print(msg.len);
  Serial.print(" EXT: "); Serial.print(msg.flags.extended);
  Serial.print(" TS: "); Serial.print(msg.timestamp);
  Serial.print(" ID: "); Serial.print(msg.id, HEX);
  Serial.print(" Buffer: ");
  for ( uint8_t i = 0; i < msg.len; i++ ) {
    Serial.print(msg.buf[i], HEX); Serial.print(" ");
  } Serial.println();
}

void loop() {
  Can0.events();

  static uint32_t timeout = millis();
  if ( millis() - timeout > 1000 ) { // send random frame every 20ms
    CAN_message_t msg; 
    msg.id = random(0x1,0x7FE);
    for ( uint8_t i = 0; i < 8; i++ ) msg.buf[i] = i + 1;
    Can0.write(msg);
    timeout = millis();
    Can0.mailboxStatus();
  }

}

Output ends up being:

Code:
FIFO Enabled --> Interrupt Enabled
	FIFO Filters in use: 8
	Remaining Mailboxes: 8
		MB8 code: TX_DATA (Transmitting)(Standard Frame)(ID: 0x76D)(Payload: 1 2 3 4 5 6 7 8)
		MB9 code: TX_DATA (Transmitting)(Standard Frame)(ID: 0x4BC)(Payload: 1 2 3 4 5 6 7 8)
		MB10 code: TX_DATA (Transmitting)(Standard Frame)(ID: 0x489)(Payload: 1 2 3 4 5 6 7 8)
		MB11 code: TX_DATA (Transmitting)(Standard Frame)(ID: 0x599)(Payload: 1 2 3 4 5 6 7 8)
		MB12 code: TX_DATA (Transmitting)(Standard Frame)(ID: 0x151)(Payload: 1 2 3 4 5 6 7 8)
		MB13 code: TX_DATA (Transmitting)(Standard Frame)(ID: 0x5F2)(Payload: 1 2 3 4 5 6 7 8)
		MB14 code: TX_DATA (Transmitting)(Standard Frame)(ID: 0x641)(Payload: 1 2 3 4 5 6 7 8)
		MB15 code: TX_DATA (Transmitting)(Standard Frame)(ID: 0xC6)(Payload: 1 2 3 4 5 6 7 8)

Everything works OK if I use the skpang Triple CAN T4.0 board instead. Any ideas on way forward? Could it be faulty transceiver, sounds dodgy as I've tested on 2 boards, i.e. 4 different ICs. Or could it be some compatibility issue?
 
if the TX mailboxes are all full, it is in bus off state, there is either a wiring issue to the transceiver or the device it's attached to, or the baudrate is mismatched, or a termination issue, which you said that part is correct. other than a bad baudrate, it ain't software provided the correct bus pins and bus are used

verify if the transceiver comms pins have not been crossed
 
It's a ready-made breakout that sits directly on T4.1 so assuming all the wiring is correct, just checked and yes, RX from Teensy going to RXD and TX to TXD for both buses, that's correct AFAIK? Tried cutting the connection between shutdown SHDN and mode-select RS pin, no difference. SHDN has a pull-down resistor, so the transceiver should stay on if the pin is disconnected.

Baudrate is the same, I tested even with 125K and 500K on both devices. Also back-to-back with 2xT4.1 setup. Running the pican2 on 250K I can plug in devices running at 250K no problem.Wiring I've tried shielded, plain wires, twisted pair etc. with no change and common GND connected between devices. Running out of options other than a bad chip?
 
yeah if skpang works its a physical connection/transceiver issue
on the triple can board schematic it shows CTX to TX amd CRX to RX so thats fine, and CANH to CANH and CANL to CANL, if those are still correct, you're left with the transceiver or termination at that point
 
Just wanted to confirm that the MAX3051 transceivers work okay with Flexcan.
Can't say yet what could be wrong with nut's setup.

IMG_5427 Large.jpg

IMG_5428 Large.jpg

Code:
#include <FlexCAN_T4.h>

FlexCAN_T4<CAN2, RX_SIZE_256, TX_SIZE_16> canbus;
CAN_message_t msg;

void setup(void) {
  pinMode(2, OUTPUT); 
  digitalWrite(2, LOW); // enable tranceiver
  pinMode(13, OUTPUT);
  digitalWrite(13, HIGH);
  delay(500);
  canbus.begin();
  canbus.setBaudRate(500000);
  canbus.setMaxMB(16); // up to 64 max for T4, not important in FIFO mode, unless you want to use additional mailboxes with FIFO
  canbus.enableFIFO();
  canbus.enableFIFOInterrupt();
  canbus.onReceive(canSniff);
  canbus.mailboxStatus();
  Serial.println("CAN Test");
}

void canSniff(const CAN_message_t &msg) {
  static uint32_t timeout = millis();
  Serial.print("MB "); Serial.print(msg.mb);
  Serial.print("  OVERRUN: "); Serial.print(msg.flags.overrun);
  Serial.print("  LEN: "); Serial.print(msg.len);
  Serial.print(" EXT: "); Serial.print(msg.flags.extended);
  Serial.print(" TS: "); Serial.print(timeout);
  Serial.print(" ID: "); Serial.print(msg.id, HEX);
  Serial.print(" Buffer: ");
  for ( uint8_t i = 0; i < msg.len; i++ ) {
    Serial.print(msg.buf[i], HEX); Serial.print(" ");
  } Serial.println();
  timeout = millis();

  digitalWrite(13, HIGH);
  digitalWrite(13, LOW);
}

void loop() {
  canbus.events();

  static uint32_t timeout = millis();
  if ( millis() - timeout > 49 ) { // send random frame every 20ms
    CAN_message_t msg;
    msg.id = random(0,0);
    for ( uint8_t i = 0; i < 8; i++ ) msg.buf[i] = i + 1;
    canbus.write(msg);
    timeout = millis();
  }

}
 
I don't see single shot mode being possible with the library as-is? There are some circumstances where it'd be nice if the CAN hardware didn't try to saturate the bus upon failure to send a frame. In an ECU, for instance, it might be a good idea to use either single shot or 3 shot (if the hardware supports that) so that it tries only for a limited time and then stops.

I looked at the processor data sheet and... do my eyes deceive me? Is there really no way to set single shot mode with this hardware?! Tell me they aren't that crazy?!
 
honestly, single shot mode in "flexcan" hardware, this is it's behaviour. i spent alot of time on that debugging and really the only way to stop it is by manually aborting, which, you'd have to handle all on your own (or alternatively reconfigure the mailbox woth setMB), however you will still need to tepp your code to stop sending if that is your goal. this loops you round circles. another alternate way is to just deassert the transceiver and force aborts, stop sending, but then you'd not get traffic activity to get out of bus off without reasserting the transceiver. But yes, bus off on flexcan hardware puts all transmissions in retry attempt, not once only.

EDIT: alternatively we can switch to listen only mode until the bus off state recovers? I did add error reporting recently, perhaps that may be of assistance?
 
Last edited:
Some more FlexCAN_T4 questions:
1. I noticed that 128 filters are available for the FIFO, is that for both the Teensy 3.x and 4.x?
2. What is the FIFO depth (i.e. how many messages can fill the FIFO without me checking before some are dropped)?

Thanks!
 
not all 128 are implemented, anything above the 32 limit in fifo uses global filter for remaining X and only certain bits are checked, all those filters rely on a single mask, so i didn't bother implementing past that threshold since we have mask and filter independant of each other for first 32 elements. yes it's for all flexcan controllers. FIFO is 6 messages deep, fixed, cannot be changed.
 
honestly, single shot mode in "flexcan" hardware, this is it's behaviour. i spent alot of time on that debugging and really the only way to stop it is by manually aborting, which, you'd have to handle all on your own (or alternatively reconfigure the mailbox woth setMB), however you will still need to tepp your code to stop sending if that is your goal. this loops you round circles. another alternate way is to just deassert the transceiver and force aborts, stop sending, but then you'd not get traffic activity to get out of bus off without reasserting the transceiver. But yes, bus off on flexcan hardware puts all transmissions in retry attempt, not once only.

EDIT: alternatively we can switch to listen only mode until the bus off state recovers? I did add error reporting recently, perhaps that may be of assistance?

Well, here's what is going on (and it seems strange to me). I have two devices set up for CAN-FD testing. One is a Teensy MicroMod running though an MCP2562FD transceiver. This is connected to an ESP32 driving an MCP2517FD that runs through an MCP2562FD. So, both the transceivers are the same. I try sending normal CAN then CAN-FD from each side to the other. Both sides can send CAN traffic to each other and it works fine. The ESP32 can send traffic to the TeensyMM perfectly fine. However, when the TeensyMM tries to send CAN-FD traffic the ESP32 side will fault like crazy giving me all sorts of bit errors, constantly resetting to try to fix the errors then the constant barrage of traffic faults it again, over and over. For some reason the MCP2517FD chip just hates the traffic coming from the TeensyMM when it is a CAN-FD frame. I find this peculiar because the traffic works bidirectionally for CAN traffic and one direction for CAN-FD but not the other. I've looked at it with a logic analyzer and it looks like CAN-FD traffic either direction. I believe the CAN fault happens right after the CRC and it almost makes me think that the two sides might be disagreeing on whether a given frame needs CRC15, 17, or 21. That is supposed to be set in stone but the fault happens around the end of CRC so... maybe? I thought it might be nice if the Teensy didn't spam the bus so that I could test with single instances of the message. But, in practice it would not ordinarily be necessary to limit retries as a message should only very seldom fault and need a re-send.

The problem is, while I have a logic analyzer it doesn't interpret CAN-FD frames and I have no other FD capable tools so now I don't know which one is being silly. It sure sounds like you've tested the Teensy code against other CAN-FD devices, right? In that case it would seem to be a fault on my ESP32 side that makes it reject the frames from the Teensy improperly. But, the question is why? I've been working on creating a C++ plugin for Saleae Logic to make it interpret CAN-FD traffic. Of course, then I'd have three devices where I wrote the code and then I'm not really a lot further along as this whole thing could be (and likely is) all my fault and adding another thing I wrote may not help me point fingers any better. All I know is that the ESP32 rejects CAN-FD traffic from the Teensy. But, I have no proof that either of them would have trouble talking to different hardware. I have a very new car but it still doesn't use CAN-FD.

So, I wonder who has used FlexCAN_T4 in FD mode with external hardware and what their experience has been.
 
Back
Top