IMCTFD - Improved Microchip CAN Teensy FlexData Library

Status
Not open for further replies.

tonton81

Well-known member
Hi all! Over the last couple of weeks I've been working on the MCP2517FD, similar in ways to IFCT. Theres still alot of things I'd like to add like local queues and sub enhancements and distributions like I have done on IFCT.

The repo will be at https://github.com/tonton81/IMCTFD/

The board I purchased from digikey: https://www.mikroe.com/mcp2517fd-click

I've updated the readme on the current progress. It uses background threading via TeensyThreads (ftrias) and SPI transactions from teensy core.

Bonus features that are not even included in the microchip API are automatic filters/masks (11, 12, and 29 bit!) and well, "12" Bit standard ID support in FD mode (which isn't AT ALL in their API), and , enabling/disabling global CRC mode SPI transfers.
Simplicity of use is always a concern, so I try to make it easy for others :)

You 'CAN' send CAN2.0 and CANFD frames using the MCP2517FD.

Tony
 
Last edited:
IMCTFD - Improved Microchip CAN-FD - Teensy FlexData Library

tonton81 has allowed me to try out the library while in development as I have tendency to break things during testing. Good way to find bugs. All I can say is that the library is pretty seamless to use and stable. Its a lot easier to use that microchip API and any other libraries that use it. You also only need to connect one interrupt pin to make it work not all three as in some cases.

tonton81 has completely revamped it to be in align with the MCP2517FD CAN-FD chip. As he said it supports CAN 2.0 messages as well. I have been testing with a T3.2 and a T3.5 and it works as advertised. Sending all different length messages etc. Pretty much tried every feature that in the library.

Stayed tuned as some examples will get posted. Right now my test sketches are a mess and would be more confusing if I post them
 
Thanks to tonton81 in helping me getting the examples working. My test setup is using a T3.2 to send different types of messages to a T3.5 for testing the receive message part of the library. It doesn't really matter to be honest - you could use any Teensy you choose.

This is the sending sketch that I use on the T3.2:
Code:
/************************************************************
 * Test sketch for sending CANFD messages using a MCP1517FD
 * Click board by Microchip with a Teensy.
 */

#include <IMCTFD.h>

CANFD_message_t msg;

// Constructor. In my case, I'm using default pins for SPI on 
// both 3.2. 9 is the interrupt pin attached
// to pin "INT" of the MCP2517FD.
IMCTFD FD = IMCTFD(SPI, 12, 11, 14, 10, 9);

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

  // 500kbps arbitration, 4Mbit data transfers  
  // returns true if successful 
  FD.setBaudRate(500000, 4);

  while(!Serial);        // Leonardo: wait for serial monitor
  delay(2000);           // time for serial to come on line
  
  // On of the features of the library is to use the int0 and int1 pins
  // of the MCP25178FD chip as GPIO pins.  To test
  // At attach the int0 pin to the Teensy pin 17
  //pinMode(17, INPUT);
  // Set the int0 pin of the MCP2517FD as high and then do a
  // digitalWrite high. Setup is just like what you would for any
  // Teensy pin.
  //FD.pinMode(0,OUTPUT);
  //FD.digitalWrite(0,HIGH);

  // the following lines set up your FIFO configurations as either RX or
  // TX.  In this case I have 4 FIFOs setup, 1 RX and 2 TX. 1 TX is for 
  // TXQ
  FD.configureFIFO(FIFO1, FIFO_RX, PLSIZE_7, DEPTH_5, PRIORITY_3, TIMESTAMP_ON);
  FD.configureFIFO(FIFO2, FIFO_TX, PLSIZE_7, DEPTH_5, PRIORITY_2, TIMESTAMP_ON);
  FD.configureFIFO(FIFO3, FIFO_TX, PLSIZE_7, DEPTH_15, PRIORITY_2, TIMESTAMP_ON);
  //FD.configureTEF(DEPTH_5, TIMESTAMP_ON);
  FD.configureTXQ(PLSIZE_7, DEPTH_6, PRIORITY_1);
  // This enables timestamping of the messages.
  FD.enableTimeStamping();

  // This line sets up a filter configuration for FIFO1.  In this
  // I am tell it to catch all message ID's coming in.
  // We will get more complex on the receiver end
  FD.setFIFOFilter(FILTER_0, FIFO1, CATCH_ALL);
  
  // This specifies that FIFO3 should queue the messages and then send.
  // This is optional.
  //FD.setQueue(FIFO3, TX_QUEUE);

  FD.begin();           // Intializes and starts up the lib
  FD.currentConfig();   // Standard print of the FIFO configurations
                        // in use
  FD.currentFilters();  // Standard print of the FIFO filter 
                        // configurations in use

  delay(5000);          // just here if you want a few seconds to read the
                        // the configurations printed

}

void loop() {

  // now we set up some messgae and types
  msg.flags.extended = 0;  // 1 == extended
  msg.len = 18;            // msg length
  msg.fdf = 1;             // sending as a CANFD frame, 0 for CAN2.0
  for ( uint8_t i = 0; i < 18; i++ ) 
        msg.buf[i] = i + 1;
  msg.id = 0x7df;          // msg id
  // writing the message to FIFO2
  if(!FD.write(msg, FIFO2)){  // returns true if message is successfully
                              // transmitted
    Serial.print("timeout 0x7df");
  }
  delay(50);

  // CAN2.0 message being sent
  msg.flags.extended = 0;
  msg.len = 13;
  msg.fdf = 0;
  for ( uint8_t i = 0; i < 13; i++ ) msg.buf[i] = i + 1;
  msg.id = 0x7d0;
  if(!FD.write(msg, FIFO2)){
    Serial.println("timeout on 0x7d0");
  }
  delay(50);

  // Example of an extended frame message
  msg.flags.extended = 1;
  msg.len = 13;
  msg.fdf = 1;
  for ( uint8_t i = 0; i < 13; i++ ) msg.buf[i] = i + 1;
  msg.id =  0x1F5002;
  if(!FD.write(msg, FIFO2)){
    Serial.println("timeout on 0x1F5002");
  }
  delay(50);
/*
  // This is a test if you want to send messages that you
  // you queued for sending
  uint8_t counter = 0;
  for(uint8_t t=0; t<10;t++){
  msg.flags.extended = 1;
  msg.len = 24;
  msg.fdf = 1;
  for ( uint8_t i = 0; i < 24; i++ )  msg.buf[i] = i + 1;
  msg.id = 0x8d0;
  if(!FD.write(msg, FIFO3)){
    Serial.println("timeout on 0x8d0");
  }
  FD.setQueue(FIFO3, TX_SEND);
*/
  delay(50);
  
  //TXQ test messages
  msg.flags.extended = 0;
  msg.len = 8;
  msg.fdf = 0;
  for ( uint8_t i = 0; i < 8; i++ ) msg.buf[i] = i + 1;
  msg.id = 0x9;
  if(!FD.write(msg, TXQ)){
    Serial.println("Timeout on TXQ");
  }
  delay(50);

  msg.flags.extended = 0;
  msg.len = 8;
  msg.fdf = 0;
  for ( uint8_t i = 0; i < 8; i++ ) msg.buf[i] = i + 1;
  msg.id = 0xa1;
  if(!FD.write(msg, TXQ)){
    Serial.println("Timeout on TXQ");
  }
  delay(50);
  
   msg.flags.extended = 0;
  msg.len = 8;
  msg.fdf = 0;
  for ( uint8_t i = 0; i < 8; i++ ) msg.buf[i] = i + 1;
  msg.id = 0x4;
  if(!FD.write(msg, TXQ)){
    Serial.println("Timeout on TXQ");
  }
  delay(50);

/*  //Msg for displaying TEF messages
  // remember to configue a TEF to do this.
  // uncomment the configureTEF line in the setup.   
  msg.flags.extended = 0;
  msg.len = 8;
  msg.fdf = 0;
  for ( uint8_t i = 0; i < 8; i++ ) msg.buf[i] = i + 1;
  msg.id = 0x6d0;
  if(!FD.write(msg, TEF)){
    Serial.println("timeout on 0x6d0");
  }
  delay(50);
*/  


  // Setup the print outs for polling the filters
  // An example of an interrupt driven FIFO is in the
  // Receiver Sketch.
  if (FD.read(msg, FIFO1)) {
    Serial.println("==========FIFO1 Read ===========");
    Serial.println(msg.fifo);
    Serial.print("from Filter_"); Serial.println(msg.filthit);
    Serial.print("ID: 0x"); Serial.println(msg.id, HEX);
    Serial.print("TimeStamp: "); Serial.println(msg.timestamp);
    Serial.print("Packet type: "); Serial.print(msg.fdf);
    Serial.print(",   Len: "); Serial.println(msg.len);
    Serial.print("Output: ");
    for ( uint8_t i = 0; i < msg.len; i++ ) {
      Serial.print(msg.buf[i]); Serial.print(" ");
    } Serial.println();
  }
  
  if (FD.read(msg, FIFO2)) {
    Serial.println("==========FIFO2 Read ===========");
    Serial.println(msg.fifo);
    Serial.print("from Filter_"); Serial.println(msg.filthit);
    Serial.print("ID: 0x"); Serial.println(msg.id, HEX);
    Serial.print("TimeStamp: "); Serial.println(msg.timestamp);
    Serial.print("Packet type: "); Serial.print(msg.fdf);
    Serial.print(",   Len: "); Serial.println(msg.len);
    Serial.print("Output: ");
    for ( uint8_t i = 0; i < msg.len; i++ ) {
      Serial.print(msg.buf[i]); Serial.print(" ");
    } Serial.println();
  }  

  if (FD.read(msg, FIFO3)) {
    Serial.println("==========FIFO3 Read ===========");
    Serial.println(msg.fifo);
    Serial.print("from Filter_"); Serial.println(msg.filthit);
    Serial.print("ID: 0x"); Serial.println(msg.id, HEX);
    Serial.print("TimeStamp: "); Serial.println(msg.timestamp);
    Serial.print("Packet type: "); Serial.print(msg.fdf);
    Serial.print(",   Len: "); Serial.println(msg.len);
    Serial.print("Output: ");
    for ( uint8_t i = 0; i < msg.len; i++ ) {
      Serial.print(msg.buf[i]); Serial.print(" ");
    } Serial.println();
  }

  if (FD.read(msg, FIFO4)) {
    Serial.println("==========FIFO4 Read ===========");
    Serial.println(msg.fifo);
    Serial.print("from Filter_"); Serial.println(msg.filthit);
    Serial.print("ID: 0x"); Serial.println(msg.id, HEX);
    Serial.print("TimeStamp: "); Serial.println(msg.timestamp);
    Serial.print("Packet type: "); Serial.print(msg.fdf);
    Serial.print(",   Len: "); Serial.println(msg.len);
    Serial.print("Output: ");
    for ( uint8_t i = 0; i < msg.len; i++ ) {
      Serial.print(msg.buf[i]); Serial.print(" ");
    } Serial.println();
  }

  // print for int0 read
  //Serial.println(digitalRead(17));
}

Next post will have the sketch I use on the T3.5
 
Receiving sketch (T3.5 for me):
Code:
/************************************************************
 * Test sketch for receing CANFD messages using a MCP1517FD
 * Click board by Microchip with a Teensy using
 * the sending sketch.
 */
#include "IMCTFD.h"

 CANFD_message_t msg;

// Constructor. In my case, I'm using default pins for SPI on 
// both 3.6. 39 is the interrupt pin attached
// to pin "INT" of the MCP2517FD.
//IMCTFD(port, _miso,  _mosi, _sck, _cs, _int, uint32_t _mhz)
IMCTFD FD = IMCTFD(SPI, 12, 11, 14, 10, 39);

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

  // 500kbps arbitration, 4Mbit data transfers  
  // returns true if successful 
  FD.setBaudRate(500000, 4);
  
  // the following lines set up your FIFO configurations as either RX or
  // TX.  In this case I have 4 FIFOs setup, 1 TX and 3 RX. Also configuring 
  // for TXQ reception
  FD.configureFIFO(FIFO1, FIFO_RX, PLSIZE_7, DEPTH_5, PRIORITY_3, TIMESTAMP_ON);
  FD.configureFIFO(FIFO2, FIFO_TX, PLSIZE_7, DEPTH_5, PRIORITY_3, TIMESTAMP_ON);
  FD.configureFIFO(FIFO3, FIFO_RX, PLSIZE_7, DEPTH_5, PRIORITY_3, TIMESTAMP_ON);
  FD.configureFIFO(FIFO4, FIFO_RX, PLSIZE_7, DEPTH_5, PRIORITY_1, TIMESTAMP_ON);
  //FD.configureTEF(DEPTH_3, TIMESTAMP_ON);
  FD.configureTXQ(PLSIZE_7, DEPTH_3, PRIORITY_1);

  FD.enableTimeStamping();

  //call back test for FIFO3 Interrupt
  //FD.onReceive(myCB);
  FD.enableFIFOInterrupt(FIFO3);
  FD.onReceive(FIFO3, myCB);

  // sets filter configurations for different msg ids
  FD.setFIFOFilter(FILTER_0, FIFO1, 0x7df);
  FD.setFIFOFilter(FILTER_1, FIFO3, 0x8d0);
  FD.setFIFOFilter(FILTER_2, FIFO1, 0x1F5002);
  FD.setFIFOFilterRange(FILTER_3, FIFO4, 0x02, 0xa4);   //TXQ filter

  FD.begin();
  
  FD.currentConfig();
  FD.currentFilters();
  delay(5000);
}

void loop(){

  // Sends a message back to the other sketch as a test
  msg.len = 24;
  msg.fdf = 1;
  for ( uint8_t i = 0; i < 24; i++ ) msg.buf[i] = i + 1;
  msg.id = 0x7d9;
  FD.write(msg, FIFO2); 
  delay(50);

  if (FD.read(msg, TEF)) {
    Serial.println("==========TEF TEF  TEF  TEF ===========");
    Serial.print("from Filter_"); Serial.println(msg.filthit);
    Serial.print("ID: 0x"); Serial.println(msg.id, HEX);
    Serial.print("TimeStamp: "); Serial.println(msg.timestamp);
    Serial.print("Len: "); Serial.println(msg.len);
    Serial.print("Sequence: "); Serial.println(msg.sequence);
    Serial.print("ESI: "); Serial.println(msg.flags.esi);
    Serial.println();
  } 

  if (FD.read(msg, FIFO1)) {
    Serial.println("==========FIFO1 Read ===========");
    Serial.println(msg.fifo);
    Serial.print("from Filter_"); Serial.println(msg.filthit);
    Serial.print("ID: 0x"); Serial.println(msg.id, HEX);
    Serial.print("TimeStamp: "); Serial.println(msg.timestamp);
    Serial.print("Packet type: "); Serial.print(msg.fdf);
    Serial.print(",   Len: "); Serial.println(msg.len);    Serial.print("Output: ");
    for ( uint8_t i = 0; i < msg.len; i++ ) {
      Serial.print(msg.buf[i]); Serial.print(" ");
    } Serial.println();
  }

  if (FD.read(msg, FIFO4)) {
    Serial.println("==========FIFO4 Read ===========");
    Serial.println(msg.fifo);
    Serial.print("from Filter_"); Serial.println(msg.filthit);
    Serial.print("ID: 0x"); Serial.println(msg.id, HEX);
    Serial.print("TimeStamp: "); Serial.println(msg.timestamp);
    Serial.print("Len: "); Serial.println(msg.len);
    Serial.print("Output: ");
    for ( uint8_t i = 0; i < msg.len; i++ ) {
      Serial.print(msg.buf[i]); Serial.print(" ");
    } Serial.println();
  }
}

//FIFO3 interrupt call back function
void myCB(const CANFD_message_t &msg){
    Serial.println("==========FIFO3 MyCB ===========");
    Serial.println(msg.fifo);
    Serial.print("ID: 0x"); Serial.println(msg.id, HEX);
    Serial.print("TimeStamp: "); Serial.println(msg.timestamp);
    Serial.print("Len: "); Serial.println(msg.len);
    Serial.print("Output: ");
    for ( uint8_t i = 0; i < msg.len; i++ ) {
      Serial.print(msg.buf[i]); Serial.print(" ");
    } Serial.println();
}
 
Hi all, just a few more tests need to be done. On points 14, 15, and 16 of the readme on github, i added (like IFCT) filter enhancements and message distributions.
I've also implemented (like IFCT) a background task and outputs so 3rd party libraries could interface with the library to use it's thread time and msg outputs without any references needed to be known by IMCTFD.
This is how CANquitto was able to be just loaded in the sketch and run off IFCT without any configurations between them, just only including it's H file was all was needed (plug&play) .. :)

Tony
 
Good evening everyone. I worked on getting a simple example posted on the repo, and..... the library has been posted! Hope you all like it :)

Thanks to Mike for finding bugs and running tests in his spare time :)

The release does not include the API dependancies, suffice it to say they contain too much bloat and static globals, only the registers have been imported to IMCTFD. Enhancements, distributions, automatic filter/masking, that was talked about is implemented, including the background process hook for external library interfacing.

Tony
 
In addition to the Click (ref post #1) that I have been testing with exclusively I just tried hooking up SK Pangs Microchip MCP2517FD CAN FD Breakout Board. Also tested with SK Pang's CANFD with the Teensy3.2 board.

Tonton81's new library works like a charm with this board as well as expected since they both use the MCP2517FD chip.
 
Last edited:
New update: IMCTFD now supports Teensy LC !

Note, TeensyLC does not support TeensyThreads, so when using TeensyLC, the library will transparently switch to use IntervalTimer instead
 
Last edited:
Status
Not open for further replies.
Back
Top