Teensy 3.1 and CAN Bus

We've got similar setNAME(pin) functions for hardware serial, I2C, SPI, and they're planned for audio. I'd really like to see FlexCAN use consistent functions.

Also on my todo list is looking into the possibility of a unified CAN base class API. Currently we have similar functionality but different APIs for Teensy, Arduino Due, MCP2551, and ChipKit. My hope is we can make all of the API compatible, so people can share Arduino sketches between them, and also to allow libraries for higher level protocols built on to of CAN to work without being coded to specific hardware.

I agree that we should aim towards consistent APIs, but that would require bigger refactoring of the library so I'll leave it for teachop. In the meantime I've added simplified selection of the alternate pins in the constructor and will push that change to github later today.
 
Been looking at the timestamp feature for flexcan, its pretty much a one liner addition but bit unsure what the units would be for the timestamp, as in is it display in microseconds or requires a conversion to microseconds?

I see a pull/addition made by Xboxpro1 that had also implemented this already.

msg.timestamp = (FLEXCAN0_MBn_CS(rxb) & FLEXCAN_MB_CS_TIMESTAMP_MASK);

Its a 16bit value that just keeps rolling over.. but Im a bit lost in what the actual recorded time will indicate. The manual indicates the following:

This register represents a 16-bit free running counter that can be read and written by the
CPU. The timer starts from 0x0 after Reset, counts linearly to 0xFFFF, and wraps around.

The timer is clocked by the FlexCAN bit-clock, which defines the baud rate on the CAN
bus. During a message transmission/reception, it increments by one for each bit that is
received or transmitted. When there is no message on the bus, it counts using the
previously programmed baud rate. The timer is not incremented during Disable, Stop,
and Freeze modes.

So for an example, if the CANbaud was set to 500kb/s, and a timestamp of 0x100 is received, then would the actual converted time be this: 256/500000/s = 0.000512sec = 0.512ms = 512us
It makes sense.. just wanted to check if thats right?

Alternative is to setup a teensy to fire off at a set interval and see what the timestamp shows?
 
Looks like the above is correct.

Requesting a simply 7E0 01 20 message to the ECU at intervals of 10ms results in the following:

Time: 8876 Msg: 7E8 1,60,0,0,0,0,0,0,
Time: 18836 Msg: 7E8 1,60,0,0,0,0,0,0,
Time: 28900 Msg: 7E8 1,60,0,0,0,0,0,0,
Time: 38708 Msg: 7E8 1,60,0,0,0,0,0,0,
Time: 48936 Msg: 7E8 1,60,0,0,0,0,0,0,
Time: 58780 Msg: 7E8 1,60,0,0,0,0,0,0,
Time: 68830 Msg: 7E8 1,60,0,0,0,0,0,0,
Time: 78706 Msg: 7E8 1,60,0,0,0,0,0,0,
Time: 88934 Msg: 7E8 1,60,0,0,0,0,0,0,
Time: 98776 Msg: 7E8 1,60,0,0,0,0,0,0,
Time: 108914 Msg: 7E8 1,60,0,0,0,0,0,0,
Time: 118788 Msg: 7E8 1,60,0,0,0,0,0,0,
Time: 128948 Msg: 7E8 1,60,0,0,0,0,0,0,
Time: 7710 Msg: 7E8 1,60,0,0,0,0,0,0,

Can see there is a 10millisecond delay between the frames.. 28900-18836 = ~10000micro = 10milliseconds.

The the timestamp ticks over every 131070 microseconds at 500,000kbps so its pretty quick.

The conversion I am doing to put the CAN timestamp into microseconds is:
(Timestamp *1000*1000)/ 500000
or put simply:
(Timestamp * 10)/ 5

Hopefully that helps some others out there. Makes precise logging a breeze!
 
Problem with sending

I try to send CAN Bus data with the FlexCan library and this code:

Code:
#include <FlexCAN.h>

static CAN_message_t msg;

// -------------------------------------------------------------
void setup(void)
{
  delay(1000);
  Can0.begin(500000);

  msg.ext = 0;
  msg.id = 0x100;
  msg.len = 8;
  msg.buf[0] = 10;
  msg.buf[1] = 20;
  msg.buf[2] = 0;
  msg.buf[3] = 100;
  msg.buf[4] = 128;
  msg.buf[5] = 64;
  msg.buf[6] = 32;
  msg.buf[7] = 16;
}


// -------------------------------------------------------------
void loop(void)
{
  msg.buf[0]++;
  Serial.print(Can0.write(msg));
  delay(20);
}

In the serial I get only this:
Code:
11111111111111111000000000000000...

From than on, I get only "Zeros" and there is no CAN Data anymore been sent.

The library says:
write(message) Send a frame of up to 8 bytes using the given identifier. write() will return 0 if no buffer was available for sending (see "Caller blocking" below)...

When the CAN_message_t field timeout is given, the read() and write() calls will wait if needed until the frame transfer can take place. The maximum wait for transfer is specified by timeout in milliseconds. If the call times out, it will return 0 as in the non-blocking case.

But how come? Any hints?

Cheers
 
Last edited:
Well, I do. And sometimes it transmits the data without any problems and sometimes it just stops. Do I need to clear the mailboxes or anything?

I changed the library a bit:
if (buffer > -1)
{
//Serial.println("Writing a frame directly.");
writeTxRegisters(msg, buffer);
return 2; // changed from 1 to 2
}

I send 3 messages in a "thread":
bool canSender1::loop () {
Serial.print("can1: ");
CAN_message_t msg;msg.ext = 0;msg.len = 8;
msg.id = 0x001;msg.buf[0] = 0;msg.buf[1] = 0;msg.buf[2] = 0;msg.buf[3] = 0;msg.buf[4] = 0;msg.buf[5] = 0;msg.buf[6] = 0;msg.buf[7] = 0;Serial.print(Can0.write(msg));
msg.id = 0x002;msg.buf[0] = 0;msg.buf[1] = 1;msg.buf[2] = 0;msg.buf[3] = 0;msg.buf[4] = 0;msg.buf[5] = 0;msg.buf[6] = 0;msg.buf[7] = 0;Serial.print(Can0.write(msg));
msg.id = 0x002;msg.buf[0] = 0;msg.buf[1] = 0;msg.buf[2] = 0;msg.buf[3] = 0;msg.buf[4] = 0;msg.buf[5] = 0;msg.buf[6] = 0;msg.buf[7] = 0;Serial.print(Can0.write(msg));
heartbeatCAN++;
if(heartbeatCAN>100){Serial.print("done");return false;}
this->sleep_milli(20);
Serial.println("");
return true;
}

I get:
can1: 221
...
can1: 221
can1: 221
can1: 221
can1: 221
can1: 221
can1: 221
can1: 221
can1: 221
// initiate sequence again...
can1: 221
can1: 111
can1: 111
can1: 111
can1: 111
can1: 110
can1: 000
can1: 000
can1: 000
can1: 000
can1: 000
can1: 000
...
can1: 000
 
Last edited:
It's a custom board and works fine with sending frames. I use two of them. One for sending and one for receive.

Screen Shot 2017-02-28 at 20.45.17.png Screen Shot 2017-02-28 at 20.48.41.png
 
There is a JUmper at "CAN TERM", which is currently set. The "C-GRID" is the plug to the Can Bus from the other device. So actually the resistor connects H and L.

I just measured between H and L and it is exactly 120 Ohm.
 
Last edited:
Got it.

Please check the batch number of the transceivers. I've purchased ones a couple of times that were always faulty (42M if I remember correctly).
 
Checked my old emails and it was 42M that was faulty in my case.

Do you use slope control on purpose (10k resistor on RS)? Did you try switching to High Speed mode instead (RS directly to ground)?
 
Do you use the same Teensy for receive and transmit or you use two different devices?

Try using some proven device as a receiver to make sure the messages are properly acknowledged on the CAN bus.
 
I have two devices (with Teensy 3.2) and both receive frames correctly from a proven sender (ECU).

Connecting both devices (With Teensy 3.2) to each other I get the described problem.
 
At U9 CANH is attached to CANL signal and CANL to CANH signal. I don't think thats how CAN works. CANH always attaches to CANH and L to L.

You can swap them and try. They are made to handle messed up wiring.

That is just a lable issue. Not a probleme here, sir. Switch H and L, that's it.


I figured out it's an issue when I'm sending AND receiving at the same time with the same RX/TX on the teensy. Could that be an issue? Is that supported?
 
Noticed some odd behaviour for the CANbus with 29bit frames.

Filter was not setting correctly and mask actually needed the EXT flag set as 0 before any 29bit frames would pass through.
Its a bit odd.. not sure whats going on there.

Once 29bit frames actually start passing through, setting a filter of say 0x10063320 will then seem to allow frames with an ID range of: 0x10YYZZ20. Where YY and ZZ seem to be anything... odd behaviour.

11bit seems completely unaffected.. setting mask and filters for 11bit has no problem. Only 29bit.
 
Last edited:
Is it possible to stop/restart the CAN listener somehow?

this snippet for the listener does not work:

Code:
//start:
Can0.attachObj(&exampleClass);
exampleClass.attachGeneralHandler();

//end:
exampleClass.detachGeneralHandler();

//start again: 
exampleClass.attachGeneralHandler();
 
Back
Top