FlexCAN_T4 - FlexCAN for Teensy 4

Before doing a vehicle test, I started using ISOTP Plugin with Vehicle SPY ISO15765-2 multi frame function.
With modifying a short codes, SID$09 InfoType$02 VIN Read seems to be working properly. It is very nice.
I will try to use isotp_server instead of using Vehicle Spy.


Code:
#include <FlexCAN_T4.h>
#include <isotp.h>
isotp<RX_BANKS_16, 512> tp; /* 16 slots for multi-ID support, at 512bytes buffer each payload rebuild */

FlexCAN_T4<CAN2, RX_SIZE_256, TX_SIZE_16> can2;

void myCallback(const ISOTP_data &config, const uint8_t *buf) {
  Serial.print("ID: ");
  Serial.print(config.id, HEX);
  Serial.print("\tLEN: ");
  Serial.print(config.len);
  Serial.print("\tFINAL ARRAY: ");
  for ( int i = 0; i < config.len; i++ ) {
    Serial.print(buf[i], HEX);
    Serial.print(" ");
  } Serial.println();
}

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(" BUS: "); Serial.print(msg.bus);
  Serial.print(" Buffer: ");
  for ( uint8_t i = 0; i < msg.len; i++ ) {
    Serial.print(msg.buf[i], HEX); Serial.print(" ");
  } Serial.println();
}

void setup() {
  Serial.begin(115200); delay(400);
  can2.begin();
  can2.setClock(CLK_60MHz);
  can2.setBaudRate(500000);
  can2.setMaxMB(16);
  can2.enableFIFO();
  can2.enableFIFOInterrupt();
  can2.onReceive(canSniff);
  tp.begin();
  tp.setWriteBus(&can2); /* we write to this bus */
  tp.onReceive(myCallback); /* set callback */
}

void loop() {
  static uint32_t sendTimer = millis();
  if ( millis() - sendTimer > 1000 ) {
    uint8_t buf[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5 };
    const char b[] = "01413AAAAABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    CAN_message_t msg;
    ISOTP_data config;
    config.id = 0x7E0;
    config.flags.extended = 0;
    config.blockSize = 0;
    config.separation_time = 20;
    msg.id = 0x7E0;
    msg.flags.extended = 0;
    msg.len = 8;
    msg.buf[0] = 2;
    msg.buf[1] = 9;
    msg.buf[2] = 2;
    can2.write(msg);
    tp.sendFlowControl(config);    

    sendTimer = millis();
    //ISOTP_data config;
    //config.id = 0x666;
    //config.flags.extended = 0; /* standard frame */
    //config.separation_time = 10; /* time between back-to-back frames in millisec */
    //tp.write(config, buf, sizeof(buf));
    //tp.write(config, b, sizeof(b));
    //sendTimer = millis();
  }
}

ISOTP_Plugin_test.jpg
 
isotp_server was updated, with an example, showing how to serve multiple buffers on CAN, and to send them to their own bus if needed
The ESP32 is requesting all 3 buffers using 6 CAN frames to Teensy 4, and all payloads reach the ESP32 callback :)

Code:
ID: 666	LEN: 121	FINAL ARRAY: 49 2 1 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 1 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 3 3 2 4 4 F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F 5 
ID: 555	LEN: 121	FINAL ARRAY: 7 3 2 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 1 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 3 3 2 4 4 F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F 5 
ID: 133	LEN: 16	FINAL ARRAY: 9 9 9 1 2 3 4 5 6 7 8 9 0 0 0 3
 
I m try use isotp for requesting from ECU
But looks need make some changes

I mean about 30 00 00 00 00 00 00 00 msg

Its working flow (not isotp)

1.JPG


And its form isotp

2.JPG


So, my question - possible add 30 00 00 00 00 00 00 00 msg after ECU answering?

May be possible add manually configurated for the msg
 
You mean have it send after the response? You can do that from FlexCAN_T4 callback if you see your request and send it. Then isotp callback will give you the buffer after
If your talking about the 3rd byte 0xF, thats the separation_time, if you don't want any, set it as 0.

0xF means 15ms per next flow frame. If your bus is high on traffic, or you lack mailboxes, or your project code is plain slow, or you are polling mailboxes, thats about the only time separation_time is needed, to keep up and not loose sequential frames. Frames out of sequence (which can happen in non-FIFO mode (all mailboxes can receive in any order)), will not collect a payload. If you have 64 mailboxes set to catch all and just 1 frame is out of order, the rebuild of isotp frame is aborted. In that case separation_time is useful to use, since the CPU can sweep the mailboxes within that timeframe.

Wouldn't make sense to automate a flow control frame in a library, since that is user specific. However, i should add auto abort eventually, if an out-of-order frame is captured, to tell the host to abort sending remaining frames, which makes better sense
 
Last edited:
Well if we take this info as example:
Code:
  can0  7DF   [8]  02 09 02 00 00 00 00 00
  can0  7E8   [8]  10 14 49 02 01 33 46 41
  can0  7E0   [8]  30 00 00 00 00 00 00 00
  can0  7E8   [8]  21 44 50 34 46 4A 32 42
  can0  7E8   [8]  22 4D 31 31 33 39 31 33

You'd make a request to from loop():
Code:
  CAN_message_t msg;
  msg.id = 0x7DF;
  msg.len = 8;
  msg.buf[0] = 0x02;
  msg.buf[1] = 0x09;
  msg.buf[2] = 0x02;
  Can0.write(msg);

Then in your FlexCAN_T4 callback (not isotp):
Code:
  if ( msg.id == 0x7E8 && msg.buf[2] == 0x49 && msg.buf[3] == 0x02 ) {
    CAN_message_t flow;
    flow.id = 0x7E0;
    flow.len = 8;
    flow.buf[0] = 0x30;
    flow.buf[2] = 0xF;
    Can0.write(flow);
  }

That should automatically request flow control based on the info posted above
 
mm, what do u mean? Add this if to loop()?

I m try it, but looks no any 30 00 msg
Add Tony's example to your global rx callback (canSniff)
If the 1st byte starts with or is equal to 0x10 and the 3rd byte is equal to 0x49 (positive response) and the 4th byte is equal to 0x02 (VIN request PID) then send a flow control (0x30) to receive the rest of the response payload
Screen Shot 2021-02-08 at 19.57.04.png
I highly suggest you take a read here


@tonton81 on another note, but same topic..

I have implemented an ISOTP flow with FlexCAN a while ago but barely tested it. Results were okay but I did not try FIFO at all - I believe this may speed things up just a bit (and hopefully enough)

This is my current setup for FlexCAN
Code:
    Can0.begin();
    Can0.setClock(CLK_60MHz);
    Can0.setBaudRate(500000);
    Can0.setMBFilter(REJECT_ALL);
    Can0.setMBFilter(MB1, 0x7E8);
    Can0.setMBFilter(MB2, 0x7E8);
    Can0.enableMBInterrupt(MB1);
    Can0.enableMBInterrupt(MB2);
    Can0.onReceive(canSniff);

If I want to enable FIFO with all available Rx/Tx mailboxes and apply a filter to only allow messages from ID 0x7E8 to be received, how do you suggest I do that? Could you add the additional init functions to my code sample above?
 
you want to capture only one message on all mailboxes and FIFO or just enable FIFO and mailboxes to capture all messages but assign only mailbox filtering for ECU?

or do you want FIFO only for ordered reception without mailboxes?

FIFO is 6 messages deep (without mailboxes). You can't expand it but you can mix mailboxes and FIFO together with their own filtering

for FIFO filters it's almost same as for mailboxes:
setMBFilter becomes setFIFOFilter, except FIFO filters have an extra argument for standard or extended frames (because their filter catches both), and by default you have up to 8 filters for FIFO

Can0.setFIFOFilter(REJECT_ALL);
Can0.setFIFOFilter(0, 0x7E8, STD); // 0-7 == 8 filters, you don't have to set them all since you set them as rejected, STD means standard frames
 
Last edited:
TBH, I don't know what is the best route here..

I send one request which is a total of 3 frames.
So I send off frame#1
receive flow control
Send frame#2
Send frame#3

Then I receive response frame#1
send flow control
Receive response frame#2
Receive response frame#3

After this whole sequence I move on to another request consisting of 2 frames and in response get another 3 frames. Then back to the flow above. It does this in an infinite loop, allowing me to request 14 PIDs in mode 22 as fast as possible.

With FIFO I understand that this will ensure that the frames are sent and received in the intended order, is that correct?
I also remember you had once mentioned that using a filter will increase speed of the CAN controller processing time rather than receiving everything and doing an if(msg.id==xx) to catch the right frames.

So what do you suggest I try?
 
yes there is no software load when the hardware filters out messages. with 6 message deep FIFO your messages will be ordered. Even without filters, you should be fine without loosing messages if you have fifo/mb interrupt enabled and events() commented out (removed) from the loop().

but yeah your ECU frames will be guarenteed ordered with FIFO. Mailboxes nope. you either have to set 1 mailbox as reception for ECU filtered or set flow control to allow ECU to send each sequence with a few millisec gap. If you want to go more complex with interrupts enabled, you can assign all frames to FIFO and set ECU to receive in one mailbox, that way you will get ECU messages and other data from the car as well. or ECU for FIFO and everything else in mailboxes.

plus you don't need a global callback, each mailbox and fifo can have it's own callback as well
 
yes there is no software load when the hardware filters out messages. with 6 message deep FIFO your messages will be ordered. Even without filters, you should be fine without loosing messages if you have fifo/mb interrupt enabled and events() commented out (removed) from the loop().

Does this setup seem right then?
Code:
  Can0.begin();
  Can0.setClock(CLK_60MHz);
  Can0.setBaudRate(500000);
  Can0.setMaxMB(16);
  Can0.enableFIFO();
  Can0.enableFIFOInterrupt();
  Can0.setFIFOFilter(REJECT_ALL);
  Can0.setFIFOFilter(0, 0x7E8, STD);
  Can0.onReceive(FIFO, canSniff);
And remove Can0.events(); from the mail loop
 
Have an easy one Tony!
If I was to add another FIFO filter, lets say setFIFOFilter(1, 0x714, STD) - could it trigger a different callback? How would I set that up?
 
unfortunately fifo has only one callback, but yeah 1 would be another filter spot. if you consume 2 more mailboxes fifo can have 16 filters. more complexity for you though :) however, your still limited to a 6 deep fifo queue, no matter how many mailboxes FIFO consumes for it's filters. There is also a limitation of 32 filters for fifo, RM says 128 but the >32 rely on one global mask while the first 32 have individual masks. who uses 32 filters anyways? ha
 
Sorry me to ask silly questions.
Do I get it right, that if I need received can messages to be in correct order, then I have to use the FIFO mode? I plan to make kind a CAN logger, so that the messages order is very important. The messages could be dumped to SD card using SDfat lib. SDfat is described to be blocking interrupts for small periods of time, so i would like not to use interrupts with FlexCANT4, but just polling events one by one. Is it an acceptable approach, FIFO FlexCANT4 + events (without interrupts) + SDfat?
Thank you!
 
yes FIFO for ordered frames, however, if polling you most likely will loose frames if your loop() code is slow. events() has nothing to do with polling whether you use it or not, since your not using enableFIFOInterrupt()
 
Thanks. Seems, like FlexCanT4 FIFO + interrupts are what i need and write onto SD right inside interrupt routine.
 
yes although im not sure SD latency will play a role but it,s best to build a buffer block before writing to SD

example, have the CAN frames goto a buffer and after it's filled have the loop() write to SD
 
Hoping for some insight on something I am, so far, entirely unable to figure out.

The Goal

I need a simple CAN bus sniffer to display all traffic on the bus - specifically on Ford truck. This should be simple, but I appear to be missing something fundamental. I have single request/response functionality working (for standard PIDs, anyway), but I cannot for the life of me get a sniffer working. I know getting everything will be a lot of data, but I've got a lot of experience doing analysis on very large data sets. The purpose of the sniffer is to help me locate specific Extended PIDs and associated ECU IDs for use in the real project which is an electronic gauge cluster for my motorhome. Once I find areas of interest I'll use filters to reduce the firehose to something more manageable.

The Hardware

I'm using a Teensy 4.0 on a Tall Dog breakout board. The BoB is populated with a Microchip MCP2558FD transceiver and associated caps and termination resistors. The hardware has been pretty well tested and seems to be working fine. As mentioned, request/response to standard PIDs is working just fine.

The Current Situation

Using the code below, derived from examples posted here and elsewhere, I am able to request data for Standard PIDs and I get the expected responses. It works quite well for that.
I am not able to get data for extended PIDs (Service 22). I'm hoping the sniffer will help me find the data I need to make this part work.
Code:
#ifndef OBD2Reader_h
#define OBD2Reader_h

//	standard libraries

//	project specific libraries
	#include "Globals.h"
	#include "Utilities.h"

class OBD2reader
{//BEGIN class OBD2reader
	private:
		CAN_message_t 	rx_msg;
		CAN_message_t 	tx_msg;

		void dump_buffers(int status, CAN_message_t	tx_msg, CAN_message_t	rx_msg)
			{//BEGIN dump_buffers()
				char outbuf[128];

				Serial.println();
				Serial.println("*************************************************************************************************************");
				sprintf(outbuf, "status = %i \n", status);
				Serial.println(outbuf);

				Serial.println("Request                   	Response");

				sprintf(outbuf, "     Module   : %04X      ", 	(unsigned int)tx_msg.id);			Serial.print(outbuf);
				sprintf(outbuf, "     %04X                 ", 	(unsigned int)rx_msg.id);			Serial.println(outbuf);

				sprintf(outbuf, "     Data Len : %02d      ", 	tx_msg.buf[0]);						Serial.print(outbuf);
				sprintf(outbuf, "       %02d                 ", 	rx_msg.buf[0]);					Serial.println(outbuf);

				sprintf(outbuf, "     Service  : %02X      ", 	tx_msg.buf[1]);						Serial.print(outbuf);
				sprintf(outbuf, "       %02X                 ", 	rx_msg.buf[1]);					Serial.println(outbuf);

				sprintf(outbuf, "     PID      : %02X %02X ",	tx_msg.buf[2], tx_msg.buf[3]);		Serial.print(outbuf);
				sprintf(outbuf, "         %02X %02X            ",	rx_msg.buf[2], rx_msg.buf[3]);	Serial.println(outbuf);

				sprintf(outbuf, "     Data     : %02X, %02X",	tx_msg.buf[4], tx_msg.buf[5]);		Serial.print(outbuf);
				sprintf(outbuf, "         %02X, %02X           ",	rx_msg.buf[4], rx_msg.buf[5]);	Serial.println(outbuf);
			}//END   dump_buffers()

	public:
		CAN_message_t init_tx_buffer
			(	bool			extended_code,
				uint16_t		tx_module,
				uint8_t			service,
				uint8_t			pid_byte_1,
				uint8_t			pid_byte_2
			)
			{//BEGIN init_tx_buffer()
				CAN_message_t	msg;

				msg.id				= tx_module;
				msg.flags.extended	= 0; 
				msg.flags.remote	= 0;
				msg.len				= 8; 

				if (!extended_code)
					{//BEGIN standard PID
						msg.buf[0] = 0x02;
						msg.buf[1] = service;
						msg.buf[2] = pid_byte_1;
						msg.buf[3] = 0x00;
					}//END   standard PID
				else
					{//BEGIN extended PID
						msg.buf[0] = 0x03;
						msg.buf[1] = service;
						msg.buf[2] = pid_byte_1;
						msg.buf[3] = pid_byte_2;	
					}//END   extended PID
					
				msg.buf[4]	= 0;  
				msg.buf[5]	= 0;
				msg.buf[6]	= 0;  
				msg.buf[7]	= 0;

				return msg;
			}//END   init_tx_buffer()

		//
		//	Function	read_canbus
		//		poll a pid, returning whatever comes back; no error checking except timeout
		//
		int	read_canbus
				(	CAN_message_t	tx_msg,
					CAN_message_t	&rx_msg
				)
			{//BEGIN read_canbus()
				Can0.write(tx_msg);

				elapsedMillis waiting;
				while (waiting < 1000)
					{//BEGIN look for response messages for up to a second
						if (Can0.read(rx_msg))
							{//BEGIN process the inbound message
								return 1;
							}//END   process the inbound message
					}//END   look for response messages for up to a second
				
				return 555;
			}//END   read_canbus()

		//
		//	Function	poll_canbus()
		//
		int	 poll_canbus
				(	CAN_message_t	tx_msg,
					uint16_t		rx_module,
					CAN_message_t	&rx_msg
				)
			{//BEGIN poll_canbus()
				int status = 555;		// process timed out with no messages received

				Can0.write(tx_msg);

				elapsedMillis waiting;
				while (waiting < 1000)
					{//BEGIN look for response messages for up to a second
						if (Can0.read(rx_msg))
							{//BEGIN process the inbound message
								if (rx_msg.id == rx_module)
									{//BEGIN modules are correct, process the PID
										if (((tx_msg.buf[2] = 0x02) && (rx_msg.buf[2] = tx_msg.buf[2])) ||
											((tx_msg.buf[2] = 0x03) && (rx_msg.buf[2] = tx_msg.buf[2]) && (rx_msg.buf[3] = tx_msg.buf[3])))
												return 1;
										else	status = 777;	// PID mismatch
									}//END   modules are correct, process the PID
								else	status = 888;	// module mismatch
							}//END   process the inbound message
					}//END   look for response messages for up to a second
				
				return status;
			}//END   poll_canbus()

		//
		//	function_init()
		//
		void init()
			{//BEGIN init()
				Can0.begin();
				Can0.setBaudRate(500000);
			}//END   init()

		//
		//	function read()
		//
		int read
			(	int				gid,	// gauge ID
				uint8_t			&A,		// 1st byte returned data value
				uint8_t			&B		// 2nd byte returned data value
			)
			{//BEGIN read()
				CAN_message_t	tx_msg = init_tx_buffer(pid_table[gid].data_bytes == 3, pid_table[gid].send_to, pid_table[gid].service, pid_table[gid].pid1, pid_table[gid].pid2);
				CAN_message_t	rx_msg;

				int				status;
				status = poll_canbus(tx_msg, pid_table[gid].receive_from, rx_msg);
//				dump_buffers(status, tx_msg, rx_msg);

				if (status)
					{//BEGIN process the response
						if (tx_msg.buf[0] == 2)	{	A = rx_msg.buf[3];  B = rx_msg.buf[4];	}			// 1 byte PID
						else					{	A = rx_msg.buf[4];  B = rx_msg.buf[5];	}			// 2 byte PID
					}//END   process the respose

				return status;
			}//END   read()
};//END  class OBD2_reader
#endif

The Ask

I've got two questions. :confused:
  1. I am unable to come up with code that will simply lurk on the bus and dump any packet that comes along. I've tried several sketches I've found online, all without success. Right now, I'm playing with one of the examples from the FlexCAN_T4 GitHub. My slightly modified version looks like the following.

    My version of "CANsniff" (dump_msg) is never triggered. I've run it with lots of Serial.println() statements so I know it's looping properly, and sending the outbound pings, but no joy getting anything back.

    Code:
    #include "ILI9341_t3n.h"
    	const int		LCD_RST 				= 8;			// reset on pin 8
    	const int 		LCD_DC 					= 9;			// data on pin 9
    	const int 		LCD_CS  				= 10;			// chip select on pin 10
    	const int		LCD_SD_CS				= 1;			// SD card reader chip select pin 1
    
    	ILI9341_t3n lcd = ILI9341_t3n(LCD_CS, LCD_DC, LCD_RST);
    
    #include <FlexCAN_T4.h>
    FlexCAN_T4<CAN3, RX_SIZE_256, TX_SIZE_16> Can0;
    
    void dump_msg (const CAN_message_t &msg)
    	{//BEGIN dump_msg()
    		char		outbuf[128];
    
    		sprintf(outbuf, "%8X | %4X |  %4X |   %1d |   %1d |   %1d |   %1d |   %02X |   %02X |   %02X |     %02X |    %02X |    %02X |    %02X |    %02X |    %02X |   %02X |  %02X |   %1d",
    			(unsigned int)msg.id,	msg.timestamp,		msg.idhit,			msg.flags.extended,		msg.flags.remote,
    			msg.flags.overrun,		msg.flags.reserved,	msg.len,			msg.buf[0],				msg.buf[1],
    			msg.buf[2],				msg.buf[3],			msg.buf[4],			msg.buf[5],				msg.buf[6],
    			msg.buf[7],				msg.mb,				msg.bus,			msg.seq);
    		Serial.println(outbuf);
    		lcd.println(outbuf);
    	}//END   dump_msg()
    
    void setup(void)
    	{//BEGIN setup()
    		Serial.begin(115200);
    		delay(400);
    		Serial.println("setup() starting");
    
    		lcd.begin();
    		lcd.setRotation(3);
    		lcd.fillScreen(0x0000);
    		lcd.setFont();
    		lcd.setCursor(30, 10);
    		lcd.println("CANbus dump");
    
    
    		Can0.begin();
    		Can0.setBaudRate(500000);
    		Can0.setMaxMB(16);
    		Can0.enableFIFO();
    		Can0.enableFIFOInterrupt();
    		Can0.onReceive(dump_msg);
    		Can0.mailboxStatus();
    		Can0.events();
    
    		Serial.println("setup() complete");
    	}//END   setup
    
    CAN_message_t	msg;
    
    void loop()
    	{//BEGIN loop()
    		msg.id = random(0x1,0x7FE);
    		for ( uint8_t i = 0; i < 8; i++ ) msg.buf[i] = 90 + i;
    		Can0.write(msg);
    		delay(200);
    	}//END   loop()
  2. As a secondary question, I'd love to hear from anyone who has successfully read Extended PIDs from a Ford. I've got several PIDs that I'm sure are correct, but when requesting them I get back junk. I suspect that I need specific ECU ID's that I don't have, or perhaps need to be using extended addressing. I'm looking into both now, but progress is slow.

I imagine the problem is something simple I've missed. Your help in relieving my ignorance (well, at least some of it) is appreciated.

Regards,

Randy
 
take events() out. because you ran that in setup(), the interrupts genererate the message queue but you never rerun events() in loop to dequeue. if you want direct interrupt firing instead of queues, remove events() entirely
 
Thanks, but no joy. Using the following code with the call to Can0.Events() removed I still get nothing. Note that I changed the outbound message to be a correctly formed request for a legitimate PID. Even so the callback isn't triggered.

Code:
#include "ILI9341_t3n.h"
	const int		LCD_RST 				= 8;			 //	reset on pin 8
	const int 		LCD_DC 					= 9;			 //	data on pin 9
	const int 		LCD_CS  				= 10;			 //	chip select on pin 10
	const int		LCD_SD_CS				= 1;			 //	SD card reader chip select pin 1

	ILI9341_t3n lcd = ILI9341_t3n(LCD_CS, LCD_DC, LCD_RST);

#include <FlexCAN_T4.h>
FlexCAN_T4<CAN3, RX_SIZE_256, TX_SIZE_16> Can0;
CAN_message_t	msg;


void dump_msg (const CAN_message_t &msg)
	{//BEGIN dump_msg()
		char		outbuf[128];

		sprintf(outbuf, "%8X | %4X |  %4X |   %1d |   %1d |   %1d |   %1d |   %02X |   %02X |   %02X |     %02X |    %02X |    %02X |    %02X |    %02X |    %02X |   %02X |  %02X |   %1d",
			(unsigned int)msg.id,	msg.timestamp,		msg.idhit,			msg.flags.extended,		msg.flags.remote,
			msg.flags.overrun,		msg.flags.reserved,	msg.len,			msg.buf[0],				msg.buf[1],
			msg.buf[2],				msg.buf[3],			msg.buf[4],			msg.buf[5],				msg.buf[6],
			msg.buf[7],				msg.mb,				msg.bus,			msg.seq);
		Serial.println(outbuf);
		lcd.println(outbuf);
	}//END   dump_msg()

void setup(void)
	{//BEGIN setup()
		Serial.begin(115200);
		delay(400);
		Serial.println("setup() starting");

		lcd.begin();
		lcd.setRotation(3);
		lcd.fillScreen(0x0000);
		lcd.setFont();
		lcd.setCursor(30, 10);
		lcd.println("CANbus dump");

		Can0.begin();
		Can0.setBaudRate(500000);
		Can0.setMaxMB(16);
		Can0.enableFIFO();
		Can0.enableFIFOInterrupt();
		Can0.onReceive(dump_msg);
		Can0.mailboxStatus();

		Serial.println("setup() complete");
	}//END   setup

void loop()
	{//BEGIN loop()
		msg.id = 0x07DF;			// standard broadcast address
		msg.buf[0] = 0x02;			// 2 data bytes sent
		msg.buf[1] = 0x01;			// standard service 01 request
		msg.buf[2] = 0x05;			// engine coolant temp

		Can0.write(msg);
		delay(200);
	}//END   loop()



When I eliminate the callback and simply do a write followed by a read I get back 1 correct response, but nothing else.

Code:
#include "ILI9341_t3n.h"
	const int		LCD_RST 				= 8;			 //	reset on pin 8
	const int 		LCD_DC 					= 9;			 //	data on pin 9
	const int 		LCD_CS  				= 10;			 //	chip select on pin 10
	const int		LCD_SD_CS				= 1;			 //	SD card reader chip select pin 1

	ILI9341_t3n lcd = ILI9341_t3n(LCD_CS, LCD_DC, LCD_RST);

#include <FlexCAN_T4.h>
FlexCAN_T4<CAN3, RX_SIZE_256, TX_SIZE_16> Can0;
CAN_message_t	msg;
CAN_message_t	rx_msg;


void dump_msg (const CAN_message_t &msg)
	{//BEGIN dump_msg()
		char		outbuf[128];

		sprintf(outbuf, "%8X | %4X |  %4X |   %1d |   %1d |   %1d |   %1d |   %02X |   %02X |   %02X |     %02X |    %02X |    %02X |    %02X |    %02X |    %02X |   %02X |  %02X |   %1d",
			(unsigned int)msg.id,	msg.timestamp,		msg.idhit,			msg.flags.extended,		msg.flags.remote,
			msg.flags.overrun,		msg.flags.reserved,	msg.len,			msg.buf[0],				msg.buf[1],
			msg.buf[2],				msg.buf[3],			msg.buf[4],			msg.buf[5],				msg.buf[6],
			msg.buf[7],				msg.mb,				msg.bus,			msg.seq);
		Serial.println(outbuf);
		lcd.println(outbuf);
	}//END   dump_msg()

void setup(void)
	{//BEGIN setup()
		Serial.begin(115200);
		delay(400);
		Serial.println("setup() starting");

		lcd.begin();
		lcd.setRotation(3);
		lcd.fillScreen(0x0000);
		lcd.setFont();
		lcd.setCursor(30, 10);
		lcd.println("CANbus dump");

		Can0.begin();
		Can0.setBaudRate(500000);

		Serial.println("setup() complete");
	}//END   setup

void loop()
	{//BEGIN loop()
		msg.id 		= 0x07DF;		// standard broadcast address
		msg.buf[0]	= 0x02;			// 2 data bytes sent
		msg.buf[1]	= 0x01;			// standard service 01 request
		msg.buf[2]	= 0x05;			// engine coolant temp

		Can0.write(msg);			// send the request

		elapsedMillis waiting;
		while (waiting < 1000)
			{//BEGIN wait up to a second for a response
				while (Can0.read(rx_msg)) dump_msg(rx_msg);		// dump all responses
			}//END   wait up to a second for a response

		delay(200);
	}//END   loop()

It seems like

  1. I've done something wrong setting up FIFO and the callback, but the setup code is copied from the GitHub example
  2. bus packets are being blocked (filtered) unless they are in response to a specific request


Regards,

Randy
 
are you using the github latest copy? i dont think the one built in teensyduino has interrupt transmits or eventless loop capability

if you are not on the latest commits, you definately need events() in the loop()
 
Back
Top