Another fork of FlexCAN

I am trying to listen for a single address, take bytes [4] and [5], and output that value on teensy's DAC. My problem is that no matter what I try, the filter doesn't take, and I am receiving addresses that should be filtered out.
Look at the mask. It determines which filter bits are active - by default none. (Consider it wildcard matching.)
 
If I do a Can0.begin(1000000, filter) with filter.id = 0x70 to set a mask of 0x70, this still allows addresses of 0x110 through. If I'm understanding the documentation correctly, it will do an AND operation with the received message and then pass to a mailbox for further filtering.

In this case, 0x70 AND 0x110 is 0x10. But I have each mailbox with a filter of also 0x70, yet frameHandler() is still receiving data with messages that do not have 0x70 address
 
The mask is not the filter. The mask can partially (or completely) disable the filter (which the default config does). There is a separate 'setMask()' function.

Read the manual, go to the FlexCan section and search for mask.
 
Thanks, I'll definitely take a look at that.

Even if I didn't have a mask set, shouldn't the filters on the individual mailboxes take care of it on their own? Or are you saying that a mask is mandatory for the filters to work properly?
 
Success! Did some reading and also went back and took a closer look at Darcy's example from earlier in the thread.

Part of what was tripping me up is that setMask() expects a 29-bit number. The documentation says 11 or 29 bit, so that wasn't very clear. I don't think I would have figured this one out without Darcy's example.

Can0.begin() also doesn't seem to work for setting a default mask. I tried passing 0x7FF as well as 0x7FF<<18, but neither seemed to work. Maybe the mask is only applied when using read() instead of frameHandler? Either way, it seems like setMask() must be set for every mailbox of interest if you want to use the callback interface.

Here's the working code to filter all mailboxes for a single address:

Code:
#include <FlexCAN.h>

uint16_t raw;

class ExampleClass : public CANListener 
{
public:
   bool frameHandler(CAN_message_t &frame, int mailbox, uint8_t controller); //overrides the parent version so we can actually do something
};

bool ExampleClass::frameHandler(CAN_message_t &frame, int mailbox, uint8_t controller)
{
  raw = 0;
  raw |= frame.buf[5] << 8;       //received bytes are in Intel LSB order
  raw |= frame.buf[4];
  
  analogWrite(A14,raw);
  
  return true;
}

ExampleClass exampleClass;

// -------------------------------------------------------------
void setup(void)
{
  delay(1000);
  
  //turn LED on
  pinMode(13, OUTPUT);
  digitalWrite(13, HIGH);

  //change analogWriteResolution to 16-bit to avoid pre-bitshifting to 12-bit
  analogWriteResolution(16);

  CAN_filter_t filter;
  filter.id = 0x70;
  filter.flags.extended = 0;
  filter.flags.remote = 0;

  Can0.begin(1000000);
  Can0.attachObj(&exampleClass);

  for (uint8_t filterNum=0; filterNum<14; filterNum++)
  {
    Can0.setMask(0x7FF<<18,filterNum);          //require exact match on filter.id, bitshift is necessary for 11-bit id's
    Can0.setFilter(filter,filterNum);
  }

  for (uint8_t filterNum=0; filterNum<14; filterNum++)
  {
    exampleClass.attachMBHandler(filterNum);
  }
}


// -------------------------------------------------------------
void loop(void)
{
}

Also, tni, thank you for your help! For some reason, even though you said it plainly, the concept of the mask acting on the filter just wasn't registering. I think it didn't make any intuitive sense for me and it took a little while to actually sink in.
 
Last edited:
Aw Snap

I am stuck;
first basic question, Has anyone had this system work with the GMLAN? Specifically the high speed 500kb one.

I had a Teensy 3.2 connected to one of those Chinese SN65HVD230 boards. (http://www.ebay.com/itm/252436745316?_trksid=p2057872.m2749.l2649&ssPageName=STRK%3AMEBIDX%3AIT) It is in turn connected to the the GMLAN +/- of a 2009 Silverado

I can see data being presented to pin 4 of the Teensy with my scope. Shows a 3v signal with pulses dropping to about 1.5v ref to ground.

using this program from the examples I can see the greeting line and then a period every second but no data.
Code:
/*
 * Object Oriented CAN example for Teensy 3.6 with Dual CAN buses 
 * By Collin Kidder. Based upon the work of Pawelsky and Teachop
 * 
 * Both buses are set to 500k to show things with a faster bus.
 * The reception of frames in this example is done via callbacks
 * to an object rather than polling. Frames are delivered as they come in.
 */

#include <FlexCAN.h>

class ExampleClass : public CANListener 
{
public:
   void printFrame(CAN_message_t &frame, int mailbox);
   bool frameHandler(CAN_message_t &frame, int mailbox, uint8_t controller); //overrides the parent version so we can actually do something
};

void ExampleClass::printFrame(CAN_message_t &frame, int mailbox)
{
   Serial.print("ID: ");
   Serial.print(frame.id, HEX);
   Serial.print(" Data: ");
   for (int c = 0; c < frame.len; c++) 
   {
      Serial.print(frame.buf[c], HEX);
      Serial.write(' ');
   }
   Serial.write('\r');
   Serial.write('\n');
}

bool ExampleClass::frameHandler(CAN_message_t &frame, int mailbox, uint8_t controller)
{
    printFrame(frame, mailbox);

    return true;
}

ExampleClass exampleClass;

// -------------------------------------------------------------
void setup(void)
{
  delay(1000);
  Serial.println(F("Hello Teensy Single CAN Receiving Example With Objects."));

  Can0.begin(500000);  

  //if using enable pins on a transceiver they need to be set on
  pinMode(2, OUTPUT);
  digitalWrite(2, HIGH);

  Can0.attachObj(&exampleClass);
  exampleClass.attachGeneralHandler();
}


// -------------------------------------------------------------
void loop(void)
{
  delay(1000);
  Serial.write('.');
}

this was the simplest sample I could fine here and I just get the greeting.
Code:
// -------------------------------------------------------------
// CANtest for Teensy 3.1
// by teachop
//
// This test is talking to a single other echo-node on the bus.
// 6 frames are transmitted and rx frames are counted.
// Tx and rx are done in a way to force some driver buffering.
// Serial is used to print the ongoing status.
//

//#define USE_V1_LIB
#ifndef USE_V1_LIB
#include <FlexCAN.h>
//FlexCAN CANbus(125000);
#else
#include <FlexCANv1.h>
FlexCANv1 Can0(125000);
#endif

static CAN_message_t msg,rxmsg;
static uint8_t hex[17] = "0123456789abcdef";

// -------------------------------------------------------------
static void hexDump(uint8_t dumpLen, uint8_t *bytePtr)
{
  uint8_t working;
  while( dumpLen-- ) {
    working = *bytePtr++;
    Serial.write( hex[ working>>4 ] );
    Serial.write( hex[ working&15 ] );
  }
  Serial.write('\r');
  Serial.write('\n');
}


// -------------------------------------------------------------
void setup(void)
{
#ifdef USE_V1_LIB
  Can0.begin();
#else
  Can0.begin(500000);
#endif
  delay(1000);
  Serial.println(F("Hello Teensy 3.1 CAN Test."));
}


// -------------------------------------------------------------
void loop(void)
{
  while ( Can0.read(rxmsg) )
  {
    Serial.print("Packet: ");
    Serial.print(rxmsg.id, HEX);
    Serial.print('-');
   
    hexDump( rxmsg.len, (uint8_t *)rxmsg.buf );
  }
}

My end goal is to translate the data from the 2009 engine to older Class 2 data for my 1999 Jimmy and plant that engine in it, keeping the more advanced control system on the 2009. Any help would be appreciated.

Keshka
 
If you are using flexCAN by ColinK, then it will need more work as this is not a J1939 standard.

https://en.wikipedia.org/wiki/ISO_15765-2

This is possible with the current library. It would take some work on your part in your overridden gotFrame() method as the first frame (frame.buf[0]) contains the information related to total payload size and flow control. The 0 frame would be handled, and essentially inspected to determine the number of frames to be considered as a single message. I have my Teensy set to a 64 byte buffer.
Code:
#define SIZE_RX_BUFFER  64 //RX incoming ring buffer size

This would allow up to 64 bytes to be buffered to be decoded.
 
Last edited:
first basic question, Has anyone had this system work with the GMLAN? Specifically the high speed 500kb one.
Have you actually set the baud rate correctly? There is 500'000 and 125'000 in the code you posted.

Have you connected TX? If you read back a few posts, Teensy will discard messages that are not acknowledged (by someone on the bus). If you don't want Teensy writing to the bus, you need to set up listen-only mode.
 
Have you actually set the baud rate correctly? There is 500'000 and 125'000 in the code you posted.

Have you connected TX? If you read back a few posts, Teensy will discard messages that are not acknowledged (by someone on the bus). If you don't want Teensy writing to the bus, you need to set up listen-only mode.

Yes, I double checked that.....it's just a typo when I copied the script from the original source.
 
I will have to admit, C++ gives me fits. I am an old school C programmer and am comfortable with it but some of the things done in C++ I can't translate well. That in mind, I did not quite understand everything in your remarks Detroit. The define statement is easy enough but I don't know what else "more work" implies. If you could post a sample of your code that would help me considerably.

At present, I don't know enough about capturing/decoding data from the CAN bus nor the GMLAN. Colin, pawelsky and teachop all have put a great deal of time into the libraries and when things work as supposed to, then cut/paste/go/thank you. In my case, "sorry, no banana" and the three have not gone into detail of how the code works making attempts at debugging quite challenging, especially when you toss in the fact that this old buzzard's difficulties with C++.

I am going to try translating the libs today and see how far I get but I sure could use some help. I can provide detailed feedback and test results, schematics and hookup information. I have a 100 mhz digital storage scope, spectrum analyser and the entire control system from the 2009 Silverado, the full wiring harness, all of the computers, all of the components, right down to the fuel pump on my shop floor all hooked up and running as my test bed.

I was very pleased to find this thread and hope all have not moved on. I thing everyone's work here is very valuable and will become more so as time goes by after all GM has only produced about 100 million vehicles in the last ten years, all using the new GMLAN so any assistance the members of this group can offer will be greatly appreciated.

Keshka
 
It's not unlikely that you have a hardware issue. Several people had issues with bad transceivers. Some suggestions: Check the polarity of the transceiver. Try talking between 2 Teensies with Can, there are examples.

Try to capture whatever appears on the RX pin and check the baud rate and if it's a valid Can message. The CanBUS Wikipedia page has enough details on the basic message format. There is a logic analyzer project for Teensy:
https://github.com/LAtimes2/TeensyLogicAnalyzer
 
I agree, I would first try using one of the basic examples with Arduino IDE and Teensy to confirm that the hardware is reading (anything) correctly. If not on your setup, test a different car's CAN lines to see if you get anything.
Also check the SN65 number on the chip to see if it really is a 230, not 231 or 232. Also make sure that pin 8 (iirc) on the chip, aka Rs, is connected to ground = high speed mode. It should not be left floating, nor high.

Somewhere in this thread you can find the chip marking number of the known bad chips.
 
Ok, finally had a chance to test further. I am thinking the sn65hvd230 pair of boards I have are bad. I have 2 boards of a different layout from another supplier I will try later. The results I am seeing seem to indicate the sn65hvd230 can not drive the Teensy. Using my scope I can see clean pulses coming from the R pin (4) when the GM computer is active (key on) if the sn65hvd230 is only driving the scope. As soon as I connect the R pin to a pin on the Teensy, the signal degrades to the point it can't be read by the Teensy. Here is my test code (R pin(4) connected to Teensy 3):
Code:
int countH = 0;
int countL = 0;


void setup() {
  pinMode(3, INPUT);
  pinMode(4, INPUT);

  pinMode(13, OUTPUT);
  Serial.begin(115200);
  Serial.println("ready");
  delay(10000);
  Serial.println("GO");
}

void loop() {

int foo;

foo = digitalRead(3);
if (foo){
  countH++;}
else{
  countL++;} 

digitalWrite(13,foo);
if(countH == 500)
{Serial.println("countH");
delay(2000);}
if(countL == 500)
{Serial.println("countL");
delay(2000);}

}

When run output with pins connected:
ready
GO
countH

when run output with pin 3 disconnected:
ready
GO
countL


scope output(s) same scope settings:
Pin 3 disconnected:
4820605873640963617-account_id=2.jpg
Pin 3 connected:
5790697288191293771-account_id=2.jpg

this is my board:
-font-b-SN65HVD230-b-font-CAN-Board-Network-Transceiver-Evaluation-Development-font-b-Module-b.jpg


Teensy, sn65hvd230 and scope all share a common ground with the GM computer
Teensy powered via USB of laptop
sn65hvd230 powered from the 3.3v pin on the Teensy
 
Ok, tried the other manufactures board and so far success! The TeensyLogicAnalyzer can now see the signal. Next, FlexCAN

here is a photo of the other board:
s-l300.jpg
 
Great ZOT! I have FlexCAN working. So far just the simple test posted by TurboStreetCar but that is a start. And thanks to tni for pointing me to that logic analyzer program....I will use that more in the future.

updates to follow

PS, do you know of a lib similar to FlexCAN for the older class 2 serial data used in the 90's and early 2000's?
 
CollinK,

I am having difficulty running FlexCAN CANtest.ino with Arduino IDE 1.82 and Teensyduino,
using two SN65HVD230D transceiver adapter boards from https://www.tindie.com/products/Fusion/single-can-bus-adapter-for-teensy-35-36/

The while (Can0.available())is never satisfied. Exactly what conditions are necessary for Can0.available to be TRUE?

Also for troubleshooting, I removed the transceivers and connected CAN0TX to CAN1TX and CAN0RX to CAN1RX. The Serial Monitor was intermittent. It seems to me that the circuit was affected by stray capacitance. I added a 10 pF ceramic capacitor across CAN1TX and CAN1RX and the Serial Monitor output became rock solid. However, this did not work when the transceivers were re-connected.

Any insights, comments, or suggestions?

Thanks,
Dave K
 
CollinK,

I am having difficulty running FlexCAN CANtest.ino with Arduino IDE 1.82 and Teensyduino,
using two SN65HVD230D transceiver adapter boards from https://www.tindie.com/products/Fusion/single-can-bus-adapter-for-teensy-35-36/

The while (Can0.available())is never satisfied. Exactly what conditions are necessary for Can0.available to be TRUE?

Also for troubleshooting, I removed the transceivers and connected CAN0TX to CAN1TX and CAN0RX to CAN1RX. The Serial Monitor was intermittent. It seems to me that the circuit was affected by stray capacitance. I added a 10 pF ceramic capacitor across CAN1TX and CAN1RX and the Serial Monitor output became rock solid. However, this did not work when the transceivers were re-connected.

Any insights, comments, or suggestions?

Thanks,
Dave K

Can0.available will only be satisfied if you actually receive some messages. If you get no messages it'll never be true (well, it returns the number of waiting frames so 0 which is false if no frames, otherwise it returns a positive number).

You really should leave the transceivers in there. CAN isn't meant to work without the transceivers. Technically it's possible but just don't do it.

So, suggestions:
1. Did you terminate the bus? People quite often miss this part. You need your bus to have 60 ohms of resistance from high to low. This is supposed to be done with 120 ohm resistors on both ends (terminating resistors). In robust designs this will actually take the form of two 60 ohm resistors with a 47nF cap in between them connected to local board ground. But, 120 ohms will work. And, you can usually get away with only one 120 ohm resistor or one 100 or one 60 if your bus is short. But, you need something there between 50 ohms and 120 ohms or it is not going to work.

2. Are your boards perhaps bad? Above in the thread people had bad boards and it messed them up. This can be tough to test when you are first starting out and you don't have a lot of other hardware to test against.

3. Do you have filtering messed up? I believe that FlexCAN defaults to allow everything through if you don't ask it otherwise but double check that you haven't set any filters that could be blocking things.
 
Hey! Board designer here.
Are you sure you have the Rs pin pulled low?

You need to add something along the lines of
Code:
pinMode(28, OUTPUT);
digitalWrite(28, LOW);
in your code, ideally in setup, before any CAN functions. This is not included in the FlexCAN lib by default.
This pin can be used for a low-power mode when pulled high.

If a logic high (> 0.75 VCC) is applied to RS (pin 8) in Figure 30 and Figure 32, the circuit of the SN65HVD230 enters a low-current, listen only standby mode, during which the driver is switched off and the receiver remains active. In this listen only state, the transceiver is completely passive to the bus. It makes no difference if a slope control resistor is in place as shown in Figure 32. The μP can reverse this low-power standby mode when the rising edge of a dominant state (bus differential voltage > 900 mV typical) occurs on the bus. The μP, sensing bus activity, reactivates the driver circuit by placing a logic low (< 1.2 V) on RS (pin 8).

2016-12-22T20:39:51.748Z-teensy-can-single-pinout.jpg.855x570_q85_pad_rcrop.jpg
 
Hi everyone,

I've tried my best to read into this, but am so far failing to find an answer to one of my questions, let me try and explain.

I am a car enthusiast, and have just purchased an ECU which is able to send a CAN Stream (http://www.dtafast.co.uk/download_files/Manuals/S Series CAN Stream Generic.pdf).

I have yet to fit the ECU, and as such am trying to get a head start on development before I can actually see data flowing in.

My hardware is a Teensy 3.2, with a SN65HVD230 transceiver.

According to the spec (above) the stream uses 29bit (extended) Identifiers.

My project will only read messages on the BUS, and I wondered if I needed to set an Extended ID filter to do so, or if it will do so automatically?

Here is the code I am hoping to use to test the stream before continuing on my development path

Code:
#include <FlexCAN.h>

int led = 13;
static CAN_message_t rxmsg;

void setup(void)
{
  
  Serial.begin(9600);
  while (!Serial) ; // wait for Arduino Serial Monitor
  Serial.println("Teensy 3.1 CANlisten Example"); 
  
  //boolean result = CANbus.begin(); -- Currently .begin object doesn't return state of bus
  //Serial.print("CAN begin successful: ");
  //Serial.println(result ? "YES" : "NO");
  
  // Init CAN
  Can0.begin(1000000);
  
  //Light on to indicate on-bus state
  pinMode(led, OUTPUT);
  digitalWrite(led, 1);
  
}

void loop(void){
  
//Poll Rx FIFO
while (Can0.read(rxmsg) ) {
//when message available

//light off to indicate FIFO is not being polled
digitalWrite(led, 0);

//construct string  
String text = "ID: 0x";
text = String(text + String(rxmsg.id, HEX));
text = String(text + " DLC: ");
text = String(text + String(rxmsg.len, HEX));

//check if DLC is >0 append string as required
if (rxmsg.len >= 1)
{
  text = String(text + " DATA: ");
}
  
//construct string for available bytes (trunctate to DLC to avoid reading garbage)
for( int idx=0; idx<rxmsg.len; ++idx ) 
{
   text = String(text + String(rxmsg.buf[idx],HEX));
   text = String(text + " ");
}
  
//print result
Serial.println(text);

//LED back on to indicate watching Rx FIFO  
digitalWrite(led, 1); 
} 

}

Any advice would be gratefully received.

Thanks
 
I was saying to myself "What the world needs is yet another fork of the FlexCAN library" so, I did that.

https://github.com/collin80/FlexCAN_Library

This is a fork of a fork (I forked Pawelsky's version and Pawelsky forked Teachop's version).

Hi,

Pawelsky wrote:

###Driver API FlexCAN(baud, id, txAlt, rxAlt) Create the FlexCAN object. The table below describes each parameter together with allowed values. Defaults are marked bold. When a non-allowed value is used default will be taken instead.

but you wrote:

###Driver API All available CAN buses have pre-created objects similarly to how the serial devices are created (Serial, Serial2, etc). In the case of these CAN buses they are called Can0 (Teensy 3.1/3.2/3.5/3.6) and Can1 (Teensy 3.6 only).

begin(baud, defaultMask, txAlt, RxAlt) Enable the chosen CAN bus.

So how can I use alternat(iv)e TX/RX on my Teensy 3.6? Can you share sample code?

regards,
 
Sorry Guys first post and possibly a over simple question, But I am having my first go on a Teensy with flex can. (coming from a uno with a canshield). But how do I set the pins using flexcan on a Teensy 3.2. I cant seen to get any data from my can bus, And I am guessing its mostly likely my pin setup! Thanks
 
Hello everyone, i did some search on the forum here, but didn't what i'm looking for, so to not make a new thread, will ask here.

I'm using Teensy 3.2 and FlexCAN for some projects and i'm loving it, for reading and receiving it works great, the question is how could i read and receive messages on one Teensy at the same time? maybe some one has example code or something?
 
Back
Top