IFCT - Improved Flexcan Teensy Library

Status
Not open for further replies.
Can't tell you which it would reply on, capturing all traffic is good to start with to know for sure, then you can filter id by callback (software filtering) or use flexcan's hardware filter in library (hardware) which ensures only the data ids you want to stream in are accepted, so the FIFO/mailboxes wont "fill-up" with data you don't want.
 
IFCT and ODD II Implementation with a 2006 Sonata.

hi Tony.
I fully understand what you are saying and yes it is possible to do it that way but I'd rather not since this was just a test of the library. From what I am seeing it is working as advertised and probably faster and easier than current flexcan libraries. It certainly has a lot more flexibility :) Besides I need to finish my other project then I may come back to this one and finish it off. These days I seem to start more projects that I am finishing :)

From what I understand in the 2006 Sonata was fully CAN-bus/ODB2 capable I would be able to query the bus using 7df or something near it. I did try that ext message id but no luck. Same as before. I did find a couple things on line that might be of interest to the forum though.

1. CAN bus mappings by OEM ECU and aftermarket device , https://wiki.autosportlabs.com/CAN_Bus_database, which shows can ids like I showed to specific engine parameters, unfortunately my car isn't one of them :(

2. from Arduino stackexchange I did find something similar to what we are discussing.
I'm using an Arduino with MCP2515 and MCP2551 to read data from a CAN bus over the OBD-II port of my car, Honda Jazz 2012. From what I've read on other forums and the OBD wiki, I can transmit the PID query to the engine over CAN ID 0x7DF and should be receiving the data on 0x78E.

I'm transmitting the data in the format described on the wiki:
Number of bytes|01|PID|0|0|0|0|0

The data I'm receiving doesn't contain data from CAN ID 0x78E or any ID nearby. Also even if I'm not sending data to the CAN bus, I'm still receiving the data, so using that I tried to remove noise, but it seems all the CAN IDs are broadcasting all the time.
So, I sampled some STN1110, OBD-to-UART interpreter, and tried to tap the connection between STN and the car ECU. It appears that the STN has a CAN ID of 0x18DB33F1 and the ECU is transmitting the data queried over CAN ID 0x18DAF110. I've put some of the data here: https://goo.gl/zTTIkk.
If you notice the CAN ID its the same as what I saw in the previous post.

I have to take the car in for inspection this week so I am going to talk to the mechanic and see what he can tell me. I also posted on the Hyundai forum but no takers to my questions yet.

Thanks for your help Tony on this one. I will post anything else that I find on translating the data.

PS. My brother in law's car is in the shop for major repairs if they don't total it. If he gets it back I will test it on that one. :)
 
Yup, your right it was only a test thing to play with that got you too involved :p

But between teensies it still makes a good broadcasting communication link. I think we’ll let IFCT go through a few more stability and feature testing, and more ideas on features could be an implemented.

One of the features I would like to work on when I have time is create a protocol handling library similar or if not same to isotp. But alas, I would like to create a multi-master design where 2 or more requests would properly be handled (2 teensies for example telling a single teensy what to do). An easy idea would be to request availability, where the receiver locks the filter onto that specific requestor for receiving within a certain timeframe before restoring the accepting filter for allowing other teensies to submit to it, sort of like handshaking, an ACK would be returned if the link would be locked allowing the sender to start commanding what it wants to do to the receiver, on completion, a completion ACK would follow allowing other nodes know the receiver is available. Alot of design decision has to go into this before that library comes though, like also accepting broadcasts for multiple parallel teensy controlling.

there are currently isotp libraries floating around that use mcp2515/2551 chips, not much support went onto the flexcan side they seem like mcp only, but none of them seem to handle multi communication linking neither. On teensy, another decision idea would need to revolve around FIFO vs mailbox reception ordering.

FIFO would be good as it allows frames to come in-order without needing to introduce delays in sending payloads, however, a user may be using the FIFO portion of IFCT for other purposes, of which I prefer to use mailbox handling instead to allow flexibility. The interrupts are pretty fast, if you have a mailbox accepting a range of IDs for “teensy” mcus, and nothing else, the ordering should be well, but remember, if reception is from 2 different teensies, the mailbox would fill with one, and override with the other if no other mailboxes/fifo consumes it. It has to be well thought out before we jump into that kind of library, but it would be a nice addition to teensy.
 
Yup, your right it was only a test thing to play with that got you too involved
Yeah. That's me - I tend to see the potential and then carried away. It would have been nice if it the car was fully can-odb compliant. It would have worked right out of the box based on what I have seen of other libs and bench testing. Had some plans for it but I haven't given up on it yet. May give the k- line a try at some point.

But between teensies it still makes a good broadcasting communication link. I think we’ll let IFCT go through a few more stability and feature testing, and more ideas on features could be an implemented.
From my initial example with the sensors yeah it makes a good comm interface with only 3 wires (CANL-CANH-GND).


RE.ISO-TP --- Have assumed you have seen this lib - https://github.com/openxc/isotp-c
 
yeah been through a few of them, but they only deal with single calls, if two or more nodes chime in things can happen, this why i need a design idea thats based on actually controlling a teensy, not just data layer, like mst does :), canbus will actually be a multi-master design idea
 
One of the features I would like to work on when I have time is create a protocol handling library similar or if not same to isotp. But alas, I would like to create a multi-master design where 2 or more requests would properly be handled (2 teensies for example telling a single teensy what to do). An easy idea would be to request availability, where the receiver locks the filter onto that specific requestor for receiving within a certain timeframe before restoring the accepting filter for allowing other teensies to submit to it, sort of like handshaking, an ACK would be returned if the link would be locked allowing the sender to start commanding what it wants to do to the receiver, on completion, a completion ACK would follow allowing other nodes know the receiver is available. Alot of design decision has to go into this before that library comes though, like also accepting broadcasts for multiple parallel teensy controlling.
Aren't you really talking about a some sort of teensy mesh network using the canbus?

This guy uses time slots to create his mesh network, http://www.instructables.com/id/Simple-Arduino-Wireless-Mesh/. Supposedly it works for on a T3.1 as well. Heres another one for you to check out https://github.com/Coopdis/easyMesh

EDIT: You know in doing more reading the CAN BUS is a bus unto itself and a network of sort itself. Like you said you need a method to arbitrate commands going to a single teensy. You might get a few ideas from the links I posted but don't think you are implementing the mesh itself. Since they are all linked. You description of what has to get done is pretty much it.
 
Last edited:
if only we were dealing with a single payload a mesh would be very easy to do, but we need to rebuild ordered payloads of each containing 8 bytes max, which means the library would need to handle several packets per client for a single instruction if needed. doing a mesh within an 8 byte payload is possible with multiple nodes, but wifi/radio can have more bytes per payload than a canbus frame can
 
Hello all,

I fixed a bug which is present in all teensy flexcan libraries, including IFCT, which contain the CAN_message_t struct.
The bitfields are not default to 0, and it caused unpredictable behaviour when I was sending 4 frames each loop cycle, after debugging through the code, the flags being read if not set contained undefined values, in turn, any time a user created a message frame via CAN_message_t, and didn't set the flag fields, they would randomly fire. In this case, even though the RTR was NOT being used, and the msg.rtr bit was NEVER set, alot of random RTR frames were sent randomly because of this. I've updated the library and replaced the bitfields with bool instead, and the issue is now ressolved. All values are defaulted to 0 on creation of new message struct, repo updated
 
Greetings, I've redesigned the reading of mailboxes and FIFO and changed the way read() is used.

2 new methods have been formed, ::readMB() and ::readFIFO(). They will be used to read either mailboxes or FIFO provided their respective interrupts are not enabled.

In the case each have their features:

::readFIFO(), reads FIFO provided that it's interrupt is not enabled and supplies the message to the user. If interrupt is enabled or no message in FIFO, a return of 0 is given, otherwise 1 for success.
::readMB(), reads from mailboxes in an even form accross every call. If a message is found a return value of 1 is sent while the msg struct was updated. If no messages exists, 0 is returned.
::read(), this was redesigned to use one of the above 2 calls randomly. If FIFO was targeted, it's interrupt check and message flags are checked for success before readFIFO runs, otherwise a fallback to readMB is done. So even though it's random, the fallback method would always be readMB() unless FIFO is enabled, it's interrupt is not enabled, it's flag is set, and the randomizer in read() targets it.

These new methods have been tested overnight on a Teensy 3.5 & Teensy 3.6.
 
Good evening everyone. I created a simulation of the mcp_can library on teensy, that mimics the behaviour of how mcp_can works, but redirects config/data to flexcan controller instead. This simulation allows you to use most common methods used by everyone who use MCP2515 CAN controllers. The demo examples of mcp_can (examples from seeedstuido Can_Bus_Shield) also work on teensy, using the flexcan controller as the target for communication.

Mike had an idea to include masking and filtering capability, which today has been completed, and the repo has been updated. An example of how teensy runs an mcp_can demo on flexcan controller is typically like this, lets take the receive_check.ino, where only red area was modified: (also take note, IFCT was not #included using the demo, and the demo is running off the flexcan controller :) )

Code:
// demo: CAN-BUS Shield, receive data with check mode
// send data coming to fast, such as less than 10ms, you can use this way
// loovee, 2014-6-13


#include <SPI.h>
#include "mcp_can.h"


// the cs pin of the version after v1.1 is default to D9
// v0.9b and v1.0 is default D10
const int SPI_CS_PIN = 9;

MCP_CAN CAN(SPI_CS_PIN);                                    // Set CS pin

void setup()
{
    Serial.begin(115200);
  [COLOR="#FF0000"][B]pinMode(2, OUTPUT); digitalWrite(2, 0);[/B][/COLOR]
    while (CAN_OK != CAN.begin(CAN_500KBPS))              // init can bus : baudrate = 500k
    {
        Serial.println("CAN BUS Shield init fail");
        Serial.println(" Init CAN BUS Shield again");
        delay(100);
    }
    Serial.println("CAN BUS Shield init ok!");
}


void loop()
{
    unsigned char len = 0;
    unsigned char buf[8];

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

        unsigned long canId = CAN.getCanId();
        
        Serial.println("-----------------------------");
        Serial.print("Get data from ID: 0x");
        Serial.println(canId, HEX);

        for(int i = 0; i<len; i++)    // print the data
        {
            Serial.print(buf[i], HEX);
            Serial.print("\t");
        }
        Serial.println();
    }
}

/*********************************************************************************************************
  END FILE
*********************************************************************************************************/

The red area was needed to enable the transceiver chip on the T3.6, the rest of the sketch remains the same.

You may change the filters/masks as well as per demo:

Code:
   /*
     * set filter, we can receive id from 0x04 ~ 0x09
     */
    CAN.init_Filt(0, 0, 0x04);                          // there are 6 filter in mcp2515
    CAN.init_Filt(1, 0, 0x05);                          // there are 6 filter in mcp2515

    CAN.init_Filt(2, 0, 0x06);                          // there are 6 filter in mcp2515
    CAN.init_Filt(3, 0, 0x07);                          // there are 6 filter in mcp2515
    CAN.init_Filt(4, 0, 0x08);                          // there are 6 filter in mcp2515
CAN.init_Filt(5, 0, 0x09); // there are 6 filter in mcp2515

You may also send data the mcp_can way:

Code:
CAN.sendMsgBuf(0x00, 0, 8, stmp);

This may have benefits in code portability, however, theres lots of libraries that rely on the mcp_can library, perhaps it will allow "compatibility" for porting them over to IFCT & Teensy 3.x devices :)
 
Test of MCP_CAN simulator on Teensy using FLEXCAN

As Tony said, filters have been implemented. Since I am using a different CAN module there is no need for setting the pinmode so I did not include it. I slightly the mcp_can library demo sketch, set_mask_filter_rcv_interrupt.ino as a test for filtering:

Code:
// demo: CAN-BUS Shield, receive data and set mask and filter
//


#include <SPI.h>
#include "mcp_can.h"

// the cs pin of the version after v1.1 is default to D9
// v0.9b and v1.0 is default D10
const int SPI_CS_PIN = 9;

MCP_CAN CAN(SPI_CS_PIN);                                    // Set CS pin


unsigned char flagRecv = 0;
unsigned char len = 0;
unsigned char buf[8];
char str[20];

void setup()
{
    Serial.begin(115200);
    delay(5000);
    
    while (CAN_OK != CAN.begin(CAN_500KBPS))              // init can bus : baudrate = 500k
    {
        Serial.println("CAN BUS Shield init fail");
        Serial.println(" Init CAN BUS Shield again");
        delay(100);
    }
    Serial.println("CAN BUS Shield init ok!");


    /*
     * set mask, set both the mask to 0x3ff
     */
    CAN.init_Mask(0, 0, 0x3ff);                         // there are 2 mask in mcp2515, you need to set both of them
    CAN.init_Mask(1, 0, 0x3ff);


    /*
     * set filter, we can receive id from 0x04 ~ 0x09
     */
    CAN.init_Filt(0, 0, 0x09);  
    CAN.init_Filt(1, 0, 0x08);
    CAN.init_Filt(2, 0, 0x07); 
[COLOR="#FF0000"]    CAN.init_Filt(3, 0, 0x320);    //this departs from example file just to demo
    CAN.init_Filt(4, 0, 0x320);    //how to only use 3 filters instead of all 6.
    CAN.init_Filt(5, 0, 0x320);    //you can substitute the demo version here and it will still work[/COLOR]
}    

void loop()
{
    [COLOR="#FF0000"]//no need to attachinterrupt anymore.  Just use the following construct and its all taken care of for you
[/COLOR]    if(CAN_MSGAVAIL == CAN.checkReceive())            // check if data coming
    {
        CAN.readMsgBuf(&len, buf);    // read data,  len: data length, buf: data buf

        Serial.println("\r\n------------------------------------------------------------------");
        Serial.print("Get Data From id: ");
        Serial.println(CAN.getCanId());
        for(int i = 0; i<len; i++)    // print the data
        {
            Serial.print("0x");
            Serial.print(buf[i], HEX);
            Serial.print("\t");
        }
        Serial.println();

    }
}

/***************************************************************
  END FILE
****************************************************************/

The send sketch is the same as for the mcp_can library. But here is a copy:
Code:
// demo: set_mask_filter_send
// this demo will show you how to use mask and filter

#include <mcp_can.h>
#include <SPI.h>

// the cs pin of the version after v1.1 is default to D9
// v0.9b and v1.0 is default D10
const int SPI_CS_PIN = 9;

MCP_CAN CAN(SPI_CS_PIN);                                    // Set CS pin

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

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

unsigned char stmp[8] = {0, 1, 2, 3, 4, 5, 6, 7};

void loop()
{
    for(int id=0; id<10; id++)
    {
        memset(stmp, id, sizeof(stmp));                 // set id to send data buff
        CAN.sendMsgBuf(id, 0, sizeof(stmp), stmp);
        delay(100);
    }
}

/***************************************************************************************
  END FILE
****************************************************************************************/
 
Last edited:
Good evening, here I am with another update for IFCT. Filters now have an enhancement.

for FIFO usage: When applying filters, first it's a good idea to REJECT_ALL frames from comming in. You may edit any of the 0-7 filters, not all need to be set if you don't want..
Code:
 // 1) Can0.setFIFOFilter(REJECT_ALL);
 // 2) Can0.setFIFOFilter(0, 0x1, 0x0B, STD);
 // 3) Can0.setFIFOFilterRange(3, 0x10, 0x20, STD);
 // 4) Can0.enhanceFilter(FIFO);

1) first we block all frames from entering FIFO, opposite of "catch-all".
2) here we setup a filter to capture only 2 Standard IDs, mask is automatically created and applied by the library. You will get these IDs that will pass the filter, not just 0x1 and 0xB, this is normal as they all have the same mask.
Code:
ID: 1
ID: 3
ID: 9
ID: B
3) here we setup a range based capture of Standard IDs ranging from 0x10 to 0x20. Output will be as follows:
Code:
ID: 1
ID: 2
ID: 3
ID: 4
ID: 5
ID: 6
ID: 7
ID: 8
ID: 9
ID: A
ID: B
ID: C
ID: D
ID: E
ID: F
ID: 10
ID: 11
ID: 12
ID: 13
ID: 14
ID: 15
ID: 16
ID: 17
ID: 18
ID: 19
ID: 1A
ID: 1B
ID: 1C
ID: 1D
ID: 1E
ID: 1F
ID: 20
ID: 21
ID: 22
ID: 23
ID: 24
ID: 25
ID: 26
ID: 27
ID: 28
ID: 29
ID: 2A
ID: 2B
ID: 2C
ID: 2D
ID: 2E
ID: 2F
ID: 30
ID: 31
ID: 32
ID: 33
ID: 34
ID: 35
ID: 36
ID: 37
ID: 38
ID: 39
ID: 3A
ID: 3B
ID: 3C
ID: 3D
ID: 3E
ID: 3F
The mask to achieve those IDs have alot of matching IDs as more bits are checked.

4) After your filters are done, there is a new feature enhancement called enhanceFilter. By running it, your output for both will be the following:
Code:
// range based:
ID: 10
ID: 11
ID: 12
ID: 13
ID: 14
ID: 15
ID: 16
ID: 17
ID: 18
ID: 19
ID: 1A
ID: 1B
ID: 1C
ID: 1D
ID: 1E
ID: 1F
ID: 20
// multi-ID based
ID: 1
ID: B

Mailboxes have the same enhancement, for example we setup a mailbox as follows:
Code:
  Can0.setMBFilter(REJECT_ALL);
  // here we assume you setup a mailbox as EXT or STD based, where the ID would be matched against.
  Can0.setMBFilter(MB8, 0x55, 0x66);

The output should be as follows:
Code:
ID: 44
ID: 45
ID: 46
ID: 47
ID: 54
ID: 55
ID: 56
ID: 57
ID: 64
ID: 65
ID: 66
ID: 67
ID: 74
ID: 75
ID: 76
ID: 77

in order to capture both IDs 0x55 and 0x66, the mask for them accepts more than requested. Lets apply the enhancement to mailbox 8...
Code:
  Can0.enhanceFilter(MB8);
Output:
Code:
ID: 55
ID: 66

The enhancement ensures that those unneeded frames don't enter your callback, or read/readMB/readFIFO calls. Especially since those unneeded frames won't be queued for callbacks, so your queues will not be bloated. :)

You may change filters for mailbox or FIFO at any time, dynamically. The enhancement will be unset when applying a filter to mailboxes, and FIFO filter enhancement will be unset when setting a FIFO filter. After you set your filters, you re-enable the enhancement with the enhanceFilter function calling either MBx (mailboxes) or FIFO accordingly.

Tony
 
Last edited:
Hello all, today I decided to solder on another ribbon line to a T3.2 CAN node for testing. I applied the T3.5 sketch copy to the T3.2. The T3.6 is receiving the correct IDs from both in the enhanced filter mode and working very well!
This test demonstrates linking all 3 Teensies 3.2, 3.5 and 3.6 :)

https://www.youtube.com/watch?v=bPxSO2DJZXg

EDIT, here are the T3.2 & T3.5 & T3.6 consoles at work, where T3.6 is participating in flooding the bus with the 3.2 & 3.5, while using enhanced filters to capture the same IDs matched by both T3.2 and T3.5

https://www.youtube.com/watch?v=nI0fMp_3dM8
 
Last edited:
Hi all, I've added new features to IFCT.

Code:
    uint32_t getBaudRate() { return currentBitrate; }
    void autoBaud();
    bool connected();

getBaudRate shows the current bitrate your connected at.
connected returns bool if your sync on the network without errors.

Can0.autoBaud is used to automatically detect the bitrate of the bus your connecting to. On startup the library will attempt to connect using autoBaud. This won't work for 1 node setups. If you plan on having a small network of nodes at least 2 must be active for autoBaud to work. Otherwise just use Can0.setBaudRate(bitrate) in setup(), or call autoBaud to detect a network's bitrate when you know it'll be active. Plugging teensy into the vehicle and powering it up will automatically know the bitrate before setup() is even entered, you can use getBaudRate to see what speed your connected at.
 
Hi tonton81. Just gave your latest changes a whirl and they are working great. A couple of things for reference if any gives this a try:
1. If you have 1 sender and 2 receivers (two with events and filters set) one can use autobaud and the other the fixed baud rate. Having to retest with both on autobaud :)
2. Duplicated you setup in the video and works great :) Even ran it at 33.333khz just for the fun of it.
 
Update:

1) events() now returns a value of how many items are left in queue (after processing 1, if any)
This gives possibility to clear queues immediately if necessary:

Code:
while(Can0.events());

2) write() has an optional overload for retry count should any mailboxes not be available for writing.
3) library has intervalTimer and teensyThreads support for running events() as a background process from the loop.
Code:
    void intervalTimer(bool enable = 1, uint32_t time = 150, uint8_t priority = 128);
    void teensyThread(bool enable = 1);
This gives you ability to:
Not run events() --> direct callback firing without queueing
run events() in loop() --> dequeue and process interrupt queued messages from normal loop()
run events() using intervalTimer, which allows dequeueing and processing of available queues should your loop() be occupied with slow code
run events() using teensythreads, allows dequeueing and processing available queues while task switching between threads.

4) added patch for entering freeze mode, where on single nodes can sometimes cause a hard crash lockup of the MCU, this is because the flexcan controller needs to enter freeze mode when:

Datasheet:
NOTE:
FRZACK will be asserted within 178 CAN bits from the freeze mode request by the CPU, and
negated within 2 CAN bits after the freeze mode request removal (see Section "Protocol Timing").

This would fail randomly with single nodes and the flexcan controller leads to a deadlock state unless you connect more nodes to get the traffic going. I solved this issue by saving the current pin state, clearing it (disabling), put the controller into freezemode, modify as necessary, and then put the pin states back as they were before they were disabled. With the pins disabled, entering freeze mode was immediate.
 
Major update. The filtering system was optimised, and new features introduced.

1) The multiple mailbox function pointers now use indices instead of separate lines, cleaner.

Example,
Before:
Code:
_MB_ptr IFCT::_MB0handler = nullptr;
_MB_ptr IFCT::_MB1handler = nullptr;
_MB_ptr IFCT::_MB2handler = nullptr;
_MB_ptr IFCT::_MB3handler = nullptr;
_MB_ptr IFCT::_MB4handler = nullptr;
_MB_ptr IFCT::_MB5handler = nullptr;
_MB_ptr IFCT::_MB6handler = nullptr;
_MB_ptr IFCT::_MB7handler = nullptr;
_MB_ptr IFCT::_MB8handler = nullptr;
_MB_ptr IFCT::_MB9handler = nullptr;
_MB_ptr IFCT::_MB10handler = nullptr;
_MB_ptr IFCT::_MB11handler = nullptr;
_MB_ptr IFCT::_MB12handler = nullptr;
_MB_ptr IFCT::_MB13handler = nullptr;
_MB_ptr IFCT::_MB14handler = nullptr;
_MB_ptr IFCT::_MB15handler = nullptr;
_MB_ptr IFCT::_MBAllhandler = nullptr;

After:
Code:
_MB_ptr IFCT::_MBhandlers[16] = { nullptr };
_MB_ptr IFCT::_MBAllhandler = nullptr;

2) Mailbox setup and filter settings now return bool, 1 == success, 0 == fail
3) I added a new function call, Can0.currentMasks(), which displays on serial monitor the status of your mailbox filters:
Code:
FIFO enabled. Filters 0 to 7 used for FIFO.

Masks:
[ 0 ]:	Flexcan Mask: 0x3FFF3FFF ( FIFO Filter )
		^--  [Table B]
			 * Filter was not set

[ 1 ]:	Flexcan Mask: 0xFFFFFFFF ( FIFO Filter )
		^--  [Table B]
			 * User Mask 1: (Extended Mask) 0x3FFF
			 * User Mask 2: (Extended Mask) 0x3FFF

[ 2 ]:	Flexcan Mask: 0xFEF7FEFF ( FIFO Filter )
		^--  [Table B]
			 * User Mask 1: (Standard Mask) 0x7DE
			 * User Mask 2: (Standard Mask) 0x7DF

[ 3 ]:	Flexcan Mask: 0x3FFF3FFF ( FIFO Filter )
		^--  [Table B]
			 * Filter was not set

[ 4 ]:	Flexcan Mask: 0x3FFF3FFF ( FIFO Filter )
		^--  [Table B]
			 * Filter was not set

[ 5 ]:	Flexcan Mask: 0x3FFF3FFF ( FIFO Filter )
		^--  [Table B]
			 * Filter was not set

[ 6 ]:	Flexcan Mask: 0x3FFF3FFF ( FIFO Filter )
		^--  [Table B]
			 * Filter was not set

[ 7 ]:	Flexcan Mask: 0x3FFF3FFF ( FIFO Filter )
		^--  [Table B]
			 * Filter was not set

[ 8 ]:	Flexcan Mask: 0x1F300000 ( Mailbox Filter )
		^-- (Standard Mask) * User Mask: 0x7CC

[ 9 ]:	Flexcan Mask: 0x00020002 ( Mailbox Filter )
		^-- (Extended Mask) * User Mask: 0x20002

[ 10 ]:	Flexcan Mask: 0x0003FFE0 ( Mailbox Filter )
		^-- (Extended Mask) * User Mask: 0x3FFE0

[ 11 ]:	Flexcan Mask: 0xFFFFFFFF ( Mailbox Filter )
		^-- * Filter was not set

[ 12 ]:	Flexcan Mask: 0xFFFFFFFF ( Mailbox Filter )
		^-- * Filter was not set

[ 13 ]:	Transmit Mailbox

[ 14 ]:	Transmit Mailbox

[ 15 ]:	Transmit Mailbox

4) Added mailbox distribution. This is a VERY useful feature when using duplicate or cross-filtering. If 2 callback filters receive same ID, the distribution code will send it to both mailboxes. The process is done by matching an incomming ID against the mailbox/FIFO local mask filtering via code, if the ID & MASK of that MB/FIFO filter match the ID of the received ID, it will be copied there as well. To enable this feature, just call Can0.distribute();.

Example:
You setup 2 filter ranges
Can0.setMBFilterRange(MB9, 0x10, 0x20);
Can0.setMBFilterRange(MB10, 0x18, 0x25);

When your callbacks fire, IDs 0x10-> 0x20 will enter MB9 callback and IDs 0x18->0x25 enter MB10 callback.
Normally, it's first come first serve, and the ID will goto only one mailbox, and you need to handle it as you wish.
If you expect the 2nd mailbox to receive the IDs between 0x18->0x20, may the odds be for ever in your favour :)
The distribution code will assure that the 2nd callback gets the message as well, as long as the incomming ID matches against the mask list.
Enhancement is supported for distributions as well.

5) Added Table B and C support for enhanced filtering.

Table A allows either standard or extended ids with all bits checked, with IFCT you get 2,3,4 and 5 ID support, as well as ranged based IDs.

TableB uses all bits for masking 11bit IDs, extended ID's are only masked the 14 most significant bits. This table has dual ID support, a bonus of quad ID support via IFCT, and dual range based IDs.


TableC uses only 11 most significant bits of any ID, be it extended or standard. If enhancement is enabled for Table C, only the 4 set IDs per filter will be received, essentially
giving you up to 32 ID receptions using 8 filters if RFFN is 0;

Tony
 
Last edited:
SLcand for Teensy

Hi Tony.
Been working on new project using a sketch made for the SeedStudio Can Shield that uses MCP CAN :) It is based on the Linux SLcand which reads any SLcan data from the bus and then dumps it so it can be used with other applications, https://github.com/latonita/arduino-canbus-monitor and (http://www.can232.com/docs/can232_v3.pdf)

Since the IFCT MCP_CAN should be a drop in I used that instead and was able to compile it no without issues. Unfortunately no message traffic came across. So as a check I broke out my Uno and hooked up the CanShield to it going to a T3.5. Loaded it up with correct MCP_CAN library (embedded in the sketch) and it worked without a problem. Can't seem to figure out why it doesn't work with your MCP_CAN. I am attaching the sketch with their MCP_CAN for reference.



Any suggestions, :)
Mike
 

Attachments

  • arduino-canbus-monitor.zip
    18.9 KB · Views: 70
ok ill check it later when i get home :) its prolly a cross-app filtering issue or something minor :)

not all functions in mscan were used for demos, so ill see if theres anything maybe set there
sometimes libraries check return flags and maybe its not set, ill figure it out
 
Basically it just streams message traffic - not even returns just a stream. Essentially the Teensy becomes a CAN-USB bridge for things like CANapp or the UAVcan Gui tool.
 
You suppose to get something like this?

Code:
t01B88AA52EF557F8FED5

t01A8DBF74B4F53B4E848

T18DD1BCA80001020304050607

T18DD1BCB80001020304050607

t01C82BBB075F35A20D6D

T18DD1BCC80001020304050607

T18DD1BCD80001020304050607

t01D82E0E07E92CA798D0

t01E8B69A199E8C78DD32

T18DD1BCE80001020304050607

t0208ED64C67F09EBE2A6

t01F87FF82CAE1F8F03CE

T18DD1BCF80001020304050607

T18DD1BD080001020304050607

t0218368072E6C96EADC6

T18DD1BD180001020304050607

t0238C1AE7B6E3D63B048

t022883B247E70E87F1A7

T18DD1BD280001020304050607

T18DD1BD380001020304050607

t024899C349BD21CDD397

T18DD1BD480001020304050607

T18DD1BD580001020304050607

t025878A3CAE18C47A78E

t0268DED9D56C5A27CFF1

T18DD1BD680001020304050607

t0288028A05409E4AB117

t027832532FEBC8C9C960

T18DD1BD780001020304050607

T18DD1BD880001020304050607

t0298E96F6A89658D80A1

T18DD1BD980001020304050607

T18DD1BDA80001020304050607

t02A893C40422BAB75F98

t02B8FEE519358917D8D5

T18DD1BDB80001020304050607

t02D83E97225A0D00819D

t02C876824E1807BA76D9

T18DD1BDC80001020304050607

T18DD1BDD80001020304050607

t02E81E306F9F799112D9

T18DD1BDE80001020304050607

T18DD1BDF80001020304050607

t02F8FC275DCE38B77517

t0308F76B2DCE470882D9

T18DD1BE080001020304050607

t0328BC18CE7908D2FAE5

t031838BC08F5A4B8F8A5

T18DD1BE180001020304050607

T18DD1BE280001020304050607

t0338286471F63C287EC9

T18DD1BE380001020304050607

T18DD1BE480001020304050607

t0348307C531776C35A2F

t0358E86ABC8FEDBB4AC3

T18DD1BE580001020304050607

t0378145CA20A5034E83B

t03687BE16A3335394504

T18DD1BE680001020304050607

T18DD1BE780001020304050607

i can also assume a small t means 11bit ID and big T means extended ID?

I did only 2 changes:

CPP: comment out this line like this:
Code:
//if (lw232CAN.checkError(&err) == CAN_OK)

and the H File, we force the CAN controller status to an ON state, obviously flexcan is running :)
Code:
INT8U lw232CanChannelMode = LW232_STATUS_CAN_OPEN_NORMAL;

It was LW232_STATUS_CAN_CLOSED before...

Don't forget to assert your transceiver if needed and do a Can0.setBaudRate(), because that library doesn't seem to be actually setting the baudrate, adding IFCT's setBaudRate works.

here's the CAN232 library mods:

Code:
[ATTACH]14432._xfImport[/ATTACH]
 
Last edited:
Thanks for the fix Tony. Caught one but missed the other :) It works like a charm. Now have to get it working with UAVcan but at least its something to test with.


Mike
 
Update for IFCT, new filter status acceptance list for standard and extended mailboxes (mailboxes only currently will display, FIFO not done yet).

This shows a list of all IDs that will come in using the ID and MASK set within each mailbox.

Code:
void IFCT::acceptedIDs(const IFCTMBNUM &mb_num, bool list)

If your list exceeds 50 entries, it finalizes the output with 3 dots. To get the full list, add the overload to the function.

Here is an example of it's usage:

We setup 3 mailboxes (I have FIFO enabled, so I'll assign mailboxes 8,9 and 10 accordingly:
Code:
  // we setup 1 standard, 2 extended mailboxes
  Can0.setMB(MB8, RX); // standard ID
  Can0.setMB(MB9, RX, EXT); // extended ID
  Can0.setMB(MB10, RX, EXT); // extended ID

  // we set their filters
  Can0.setMBFilter(REJECT_ALL); // clear current accept-all filtering
  Can0.setMBFilter(MB8, 0x55, 0x66); // we want MB8 to get IDs 0x55 and 0x66 (they will be assigned using the mailbox extended/standard bit)
  Can0.setMBFilter(MB9, 0x18DCFFE7, 0x18DCFFE2); // We want MB9 to accept 0x18DCFFE7 and 0x18DCFFE2 (extended ID)
  Can0.setMBFilterRange(MB10, 0x18DCFECC, 0x18DCFFEA); // We want a range of IDs to come here, 0x18DCFECC being minimum, and 0x18DCFFEA being max.

  // for checking the detailed acceptance list of those 3 mailboxes:
  Can0.acceptedIDs(MB8);
  Can0.acceptedIDs(MB9);
  Can0.acceptedIDs(MB10);

The output:
Code:
MB8 accepted IDs: 	0x44	0x45	0x46	0x47	0x54	0x55
			0x56	0x57	0x64	0x65	0x66	0x67
			0x74	0x75	0x76	0x77	

Enhancement Disabled
		* Enhanced Multi-ID mode filtering:  0x55 0x66 


MB9 accepted IDs: 	0x18DCFFE2	0x18DCFFE3	0x18DCFFE6	0x18DCFFE7	

Enhancement Disabled
		* Enhanced Multi-ID mode filtering:  0x18DCFFE2 0x18DCFFE7 


MB10 accepted IDs: 	0x18DCFE00	0x18DCFE01	0x18DCFE02	0x18DCFE03	0x18DCFE04	0x18DCFE05
			0x18DCFE06	0x18DCFE07	0x18DCFE08	0x18DCFE09	0x18DCFE0A	0x18DCFE0B
			0x18DCFE0C	0x18DCFE0D	0x18DCFE0E	0x18DCFE0F	0x18DCFE10	0x18DCFE11
			0x18DCFE12	0x18DCFE13	0x18DCFE14	0x18DCFE15	0x18DCFE16	0x18DCFE17
			0x18DCFE18	0x18DCFE19	0x18DCFE1A	0x18DCFE1B	0x18DCFE1C	0x18DCFE1D
			0x18DCFE1E	0x18DCFE1F	0x18DCFE20	0x18DCFE21	0x18DCFE22	0x18DCFE23
			0x18DCFE24	0x18DCFE25	0x18DCFE26	0x18DCFE27	0x18DCFE28	0x18DCFE29
			0x18DCFE2A	0x18DCFE2B	0x18DCFE2C	0x18DCFE2D	0x18DCFE2E	0x18DCFE2F
			0x18DCFE30	0x18DCFE31	0x18DCFE32	...

Enhancement Disabled
		* Enhanced ID-range mode filtering:  0x18DCFECC <--> 0x18DCFFEA

As you can see, the range covers more IDs as thats what the user wants. What you didn't expect is, the results are immediate and don't take forever (for extended ids), because I only scan the masking region of the ID and not the entire 0x1FFFFFFF area. This allows fastest scan times. I applied same trick to standard IDs as well.

To allow a full list of printing, add the overload (1) to the call:
Code:
  Can0.acceptedIDs(MB8,1);
  Can0.acceptedIDs(MB9,1);
  Can0.acceptedIDs(MB10,1);

Output:

Code:
MB8 accepted IDs: 	0x44	0x45	0x46	0x47	0x54	0x55
			0x56	0x57	0x64	0x65	0x66	0x67
			0x74	0x75	0x76	0x77	

Enhancement Disabled
		* Enhanced Multi-ID mode filtering:  0x55 0x66 


MB9 accepted IDs: 	0x18DCFFE2	0x18DCFFE3	0x18DCFFE6	0x18DCFFE7	

Enhancement Disabled
		* Enhanced Multi-ID mode filtering:  0x18DCFFE2 0x18DCFFE7 


MB10 accepted IDs: 	0x18DCFE00	0x18DCFE01	0x18DCFE02	0x18DCFE03	0x18DCFE04	0x18DCFE05
			0x18DCFE06	0x18DCFE07	0x18DCFE08	0x18DCFE09	0x18DCFE0A	0x18DCFE0B
			0x18DCFE0C	0x18DCFE0D	0x18DCFE0E	0x18DCFE0F	0x18DCFE10	0x18DCFE11
			0x18DCFE12	0x18DCFE13	0x18DCFE14	0x18DCFE15	0x18DCFE16	0x18DCFE17
			0x18DCFE18	0x18DCFE19	0x18DCFE1A	0x18DCFE1B	0x18DCFE1C	0x18DCFE1D
			0x18DCFE1E	0x18DCFE1F	0x18DCFE20	0x18DCFE21	0x18DCFE22	0x18DCFE23
			0x18DCFE24	0x18DCFE25	0x18DCFE26	0x18DCFE27	0x18DCFE28	0x18DCFE29
			0x18DCFE2A	0x18DCFE2B	0x18DCFE2C	0x18DCFE2D	0x18DCFE2E	0x18DCFE2F
			0x18DCFE30	0x18DCFE31	0x18DCFE32	0x18DCFE33	0x18DCFE34	0x18DCFE35
			0x18DCFE36	0x18DCFE37	0x18DCFE38	0x18DCFE39	0x18DCFE3A	0x18DCFE3B
			0x18DCFE3C	0x18DCFE3D	0x18DCFE3E	0x18DCFE3F	0x18DCFE40	0x18DCFE41
			0x18DCFE42	0x18DCFE43	0x18DCFE44	0x18DCFE45	0x18DCFE46	0x18DCFE47
			0x18DCFE48	0x18DCFE49	0x18DCFE4A	0x18DCFE4B	0x18DCFE4C	0x18DCFE4D
			0x18DCFE4E	0x18DCFE4F	0x18DCFE50	0x18DCFE51	0x18DCFE52	0x18DCFE53
			0x18DCFE54	0x18DCFE55	0x18DCFE56	0x18DCFE57	0x18DCFE58	0x18DCFE59
			0x18DCFE5A	0x18DCFE5B	0x18DCFE5C	0x18DCFE5D	0x18DCFE5E	0x18DCFE5F
			0x18DCFE60	0x18DCFE61	0x18DCFE62	0x18DCFE63	0x18DCFE64	0x18DCFE65
			0x18DCFE66	0x18DCFE67	0x18DCFE68	0x18DCFE69	0x18DCFE6A	0x18DCFE6B
			0x18DCFE6C	0x18DCFE6D	0x18DCFE6E	0x18DCFE6F	0x18DCFE70	0x18DCFE71
			0x18DCFE72	0x18DCFE73	0x18DCFE74	0x18DCFE75	0x18DCFE76	0x18DCFE77
			0x18DCFE78	0x18DCFE79	0x18DCFE7A	0x18DCFE7B	0x18DCFE7C	0x18DCFE7D
			0x18DCFE7E	0x18DCFE7F	0x18DCFE80	0x18DCFE81	0x18DCFE82	0x18DCFE83
			0x18DCFE84	0x18DCFE85	0x18DCFE86	0x18DCFE87	0x18DCFE88	0x18DCFE89
			0x18DCFE8A	0x18DCFE8B	0x18DCFE8C	0x18DCFE8D	0x18DCFE8E	0x18DCFE8F
			0x18DCFE90	0x18DCFE91	0x18DCFE92	0x18DCFE93	0x18DCFE94	0x18DCFE95
			0x18DCFE96	0x18DCFE97	0x18DCFE98	0x18DCFE99	0x18DCFE9A	0x18DCFE9B
			0x18DCFE9C	0x18DCFE9D	0x18DCFE9E	0x18DCFE9F	0x18DCFEA0	0x18DCFEA1
			0x18DCFEA2	0x18DCFEA3	0x18DCFEA4	0x18DCFEA5	0x18DCFEA6	0x18DCFEA7
			0x18DCFEA8	0x18DCFEA9	0x18DCFEAA	0x18DCFEAB	0x18DCFEAC	0x18DCFEAD
			0x18DCFEAE	0x18DCFEAF	0x18DCFEB0	0x18DCFEB1	0x18DCFEB2	0x18DCFEB3
			0x18DCFEB4	0x18DCFEB5	0x18DCFEB6	0x18DCFEB7	0x18DCFEB8	0x18DCFEB9
			0x18DCFEBA	0x18DCFEBB	0x18DCFEBC	0x18DCFEBD	0x18DCFEBE	0x18DCFEBF
			0x18DCFEC0	0x18DCFEC1	0x18DCFEC2	0x18DCFEC3	0x18DCFEC4	0x18DCFEC5
			0x18DCFEC6	0x18DCFEC7	0x18DCFEC8	0x18DCFEC9	0x18DCFECA	0x18DCFECB
			0x18DCFECC	0x18DCFECD	0x18DCFECE	0x18DCFECF	0x18DCFED0	0x18DCFED1
			0x18DCFED2	0x18DCFED3	0x18DCFED4	0x18DCFED5	0x18DCFED6	0x18DCFED7
			0x18DCFED8	0x18DCFED9	0x18DCFEDA	0x18DCFEDB	0x18DCFEDC	0x18DCFEDD
			0x18DCFEDE	0x18DCFEDF	0x18DCFEE0	0x18DCFEE1	0x18DCFEE2	0x18DCFEE3
			0x18DCFEE4	0x18DCFEE5	0x18DCFEE6	0x18DCFEE7	0x18DCFEE8	0x18DCFEE9
			0x18DCFEEA	0x18DCFEEB	0x18DCFEEC	0x18DCFEED	0x18DCFEEE	0x18DCFEEF
			0x18DCFEF0	0x18DCFEF1	0x18DCFEF2	0x18DCFEF3	0x18DCFEF4	0x18DCFEF5
			0x18DCFEF6	0x18DCFEF7	0x18DCFEF8	0x18DCFEF9	0x18DCFEFA	0x18DCFEFB
			0x18DCFEFC	0x18DCFEFD	0x18DCFEFE	0x18DCFEFF	0x18DCFF00	0x18DCFF01
			0x18DCFF02	0x18DCFF03	0x18DCFF04	0x18DCFF05	0x18DCFF06	0x18DCFF07
			0x18DCFF08	0x18DCFF09	0x18DCFF0A	0x18DCFF0B	0x18DCFF0C	0x18DCFF0D
			0x18DCFF0E	0x18DCFF0F	0x18DCFF10	0x18DCFF11	0x18DCFF12	0x18DCFF13
			0x18DCFF14	0x18DCFF15	0x18DCFF16	0x18DCFF17	0x18DCFF18	0x18DCFF19
			0x18DCFF1A	0x18DCFF1B	0x18DCFF1C	0x18DCFF1D	0x18DCFF1E	0x18DCFF1F
			0x18DCFF20	0x18DCFF21	0x18DCFF22	0x18DCFF23	0x18DCFF24	0x18DCFF25
			0x18DCFF26	0x18DCFF27	0x18DCFF28	0x18DCFF29	0x18DCFF2A	0x18DCFF2B
			0x18DCFF2C	0x18DCFF2D	0x18DCFF2E	0x18DCFF2F	0x18DCFF30	0x18DCFF31
			0x18DCFF32	0x18DCFF33	0x18DCFF34	0x18DCFF35	0x18DCFF36	0x18DCFF37
			0x18DCFF38	0x18DCFF39	0x18DCFF3A	0x18DCFF3B	0x18DCFF3C	0x18DCFF3D
			0x18DCFF3E	0x18DCFF3F	0x18DCFF40	0x18DCFF41	0x18DCFF42	0x18DCFF43
			0x18DCFF44	0x18DCFF45	0x18DCFF46	0x18DCFF47	0x18DCFF48	0x18DCFF49
			0x18DCFF4A	0x18DCFF4B	0x18DCFF4C	0x18DCFF4D	0x18DCFF4E	0x18DCFF4F
			0x18DCFF50	0x18DCFF51	0x18DCFF52	0x18DCFF53	0x18DCFF54	0x18DCFF55
			0x18DCFF56	0x18DCFF57	0x18DCFF58	0x18DCFF59	0x18DCFF5A	0x18DCFF5B
			0x18DCFF5C	0x18DCFF5D	0x18DCFF5E	0x18DCFF5F	0x18DCFF60	0x18DCFF61
			0x18DCFF62	0x18DCFF63	0x18DCFF64	0x18DCFF65	0x18DCFF66	0x18DCFF67
			0x18DCFF68	0x18DCFF69	0x18DCFF6A	0x18DCFF6B	0x18DCFF6C	0x18DCFF6D
			0x18DCFF6E	0x18DCFF6F	0x18DCFF70	0x18DCFF71	0x18DCFF72	0x18DCFF73
			0x18DCFF74	0x18DCFF75	0x18DCFF76	0x18DCFF77	0x18DCFF78	0x18DCFF79
			0x18DCFF7A	0x18DCFF7B	0x18DCFF7C	0x18DCFF7D	0x18DCFF7E	0x18DCFF7F
			0x18DCFF80	0x18DCFF81	0x18DCFF82	0x18DCFF83	0x18DCFF84	0x18DCFF85
			0x18DCFF86	0x18DCFF87	0x18DCFF88	0x18DCFF89	0x18DCFF8A	0x18DCFF8B
			0x18DCFF8C	0x18DCFF8D	0x18DCFF8E	0x18DCFF8F	0x18DCFF90	0x18DCFF91
			0x18DCFF92	0x18DCFF93	0x18DCFF94	0x18DCFF95	0x18DCFF96	0x18DCFF97
			0x18DCFF98	0x18DCFF99	0x18DCFF9A	0x18DCFF9B	0x18DCFF9C	0x18DCFF9D
			0x18DCFF9E	0x18DCFF9F	0x18DCFFA0	0x18DCFFA1	0x18DCFFA2	0x18DCFFA3
			0x18DCFFA4	0x18DCFFA5	0x18DCFFA6	0x18DCFFA7	0x18DCFFA8	0x18DCFFA9
			0x18DCFFAA	0x18DCFFAB	0x18DCFFAC	0x18DCFFAD	0x18DCFFAE	0x18DCFFAF
			0x18DCFFB0	0x18DCFFB1	0x18DCFFB2	0x18DCFFB3	0x18DCFFB4	0x18DCFFB5
			0x18DCFFB6	0x18DCFFB7	0x18DCFFB8	0x18DCFFB9	0x18DCFFBA	0x18DCFFBB
			0x18DCFFBC	0x18DCFFBD	0x18DCFFBE	0x18DCFFBF	0x18DCFFC0	0x18DCFFC1
			0x18DCFFC2	0x18DCFFC3	0x18DCFFC4	0x18DCFFC5	0x18DCFFC6	0x18DCFFC7
			0x18DCFFC8	0x18DCFFC9	0x18DCFFCA	0x18DCFFCB	0x18DCFFCC	0x18DCFFCD
			0x18DCFFCE	0x18DCFFCF	0x18DCFFD0	0x18DCFFD1	0x18DCFFD2	0x18DCFFD3
			0x18DCFFD4	0x18DCFFD5	0x18DCFFD6	0x18DCFFD7	0x18DCFFD8	0x18DCFFD9
			0x18DCFFDA	0x18DCFFDB	0x18DCFFDC	0x18DCFFDD	0x18DCFFDE	0x18DCFFDF
			0x18DCFFE0	0x18DCFFE1	0x18DCFFE2	0x18DCFFE3	0x18DCFFE4	0x18DCFFE5
			0x18DCFFE6	0x18DCFFE7	0x18DCFFE8	0x18DCFFE9	0x18DCFFEA	0x18DCFFEB
			0x18DCFFEC	0x18DCFFED	0x18DCFFEE	0x18DCFFEF	0x18DCFFF0	0x18DCFFF1
			0x18DCFFF2	0x18DCFFF3	0x18DCFFF4	0x18DCFFF5	0x18DCFFF6	0x18DCFFF7
			0x18DCFFF8	0x18DCFFF9	0x18DCFFFA	0x18DCFFFB	0x18DCFFFC	0x18DCFFFD
			0x18DCFFFE	0x18DCFFFF	

Enhancement Disabled
		* Enhanced ID-range mode filtering:  0x18DCFECC <--> 0x18DCFFEA

Tony
 
Status
Not open for further replies.
Back
Top