Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 21 of 21

Thread: Teensy 3.6 - FlexCAN - Listen and respond

  1. #1

    Teensy 3.6 - FlexCAN - Listen and respond

    Hi!

    A few weeks ago I posted a question in the project guidance forum but never received any feedback. Thought it might be the wrong place so I give it a try here instead.


    My goal is rather simple. I want the Teensy to respond to a frame when its detected on the bus. But I don't know how to implement it with the help of the FlexCAN library examples. I have a Teensy 3.6 and a CAN transceiver module SN65HVD230.


    Pseudo code
    Code:
    loop() {
    Listen on CAN bus for certain frame.
    If frame == "t568101" detected..
    then 
    send on CAN bus "t5653001511" in decimal format.
    }

    Have anyone done something similar and can post an example snipped of code?


    Code:
    #include <FlexCAN.h>
    
    
    void setup() {
    delay(1000);
    Serial.println(F("Starting up..."));
    Can0.begin(500000);   
    }
    
    void loop() {
    }

    Regards
    Tobias

  2. #2
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    2,964
    Its definately possible to do, a received frame ID would update the msg.id with the CAN ID of the frame.

    But what do you mean frame id is t568101?, that is not valid, are you looking at the data field?

  3. #3
    Thank you for taking time to look at my project tonton.

    The "t568101” is a frame as I have read it on my CANbus with a canbus sniffer device. According to my research in translates into:
    t = transmit
    568 = frame hex ID
    101 = payload in hex.

  4. #4
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    2,964
    irregardless, you will have no issue identifying that frame when you see it, 568 will be populating the msg.id variable and your payload will appear in msg.buf[x];

    sorry I didn’t catch your last post I would have definately helped you out

    You can try out my IFCT library, there are simple examples included with it

  5. #5
    Thank you. Looking at your library now.

    So what I need to do is create an IF statement on the content of msg.id variable and msg.buf[x] compared to the ID and string I'm looking for?

  6. #6
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    2,964
    pretty much yeah

    but start it easy first, let it show what it sees on the serial monitor when the transmissions occur, the rest will come to you easily

  7. #7
    Thank you. I will give it a go and get back here. =)

  8. #8
    Hi again.

    I have now done some dumping on the bus with the following code, which is an altered version of the test code supplied with the library.

    Dump code:
    Code:
    #include <FlexCAN.h> // by Collin Kidder, Based on CANTest by Pawelsky (based on CANtest by teachop)
    
    
    static CAN_message_t msg;
    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)
    {
      delay(1000);
      Serial.println(F("Hello Teensy 3.6 dual CAN Test."));
      Can0.begin(500000); 
       pinMode(13, OUTPUT);    
      digitalWrite(13, HIGH);
    }  
    
    // -------------------------------------------------------------
    void loop(void)
    {
      CAN_message_t inMsg;
      while (Can0.available()) 
      {
        Can0.read(inMsg);
        Serial.print("CAN bus 0: ");
        Serial.print(inMsg.id);
        Serial.print(", ");
        hexDump(8, inMsg.buf);
      }
     // delay(1);
    }
    Code:
    18:05:39.604 -> CAN bus 0: 1384, 0100000000000000
    18:05:39.604 -> CAN bus 0: 1304, 0000000000000000
    18:05:39.604 -> CAN bus 0: 1328, 0000000000000c00
    18:05:39.604 -> CAN bus 0: 1384, 0100000000000000
    18:05:39.604 -> CAN bus 0: 1304, 0000000000000000
    18:05:39.604 -> CAN bus 0: 1328, 0000000000000c00
    18:05:39.604 -> CAN bus 0: 1384, 0100000000000000
    18:05:39.604 -> CAN bus 0: 1304, 0000000000000000
    18:05:39.604 -> CAN bus 0: 1328, 0000000000000c00
    18:05:39.604 -> CAN bus 0: 1384, 0100000000000000
    18:05:39.604 -> CAN bus 0: 1304, 0000000000000000
    18:05:39.604 -> CAN bus 0: 1328, 0000000000000c00
    18:05:39.604 -> CAN bus 0: 1384, 0100000000000000
    18:05:39.604 -> CAN bus 0: 1304, 0000000000000000
    18:05:39.604 -> CAN bus 0: 1328, 0000000000000c00
    18:05:39.650 -> CAN bus 0: 1384, 0100000000000000
    Its the "1384, 0100000000000000" I would like to give my reply to on the CANbus, buts its very confusing with the conversion between HEX, DEC and Binary....

  9. #9
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    2,964
    ok what you can do is for example ignore the hexdump() call in loop and access the data directly.

    inMsg.id is your CAN ID
    inMsg.buf[x] is your 8 data bytes, where x is the indice 0 to 7.

    to write a frame you can do this:

    CAN_message_t out;
    out.len = 8;
    out.flags.extended = 1;
    out.buf[0] = 0xFF;
    out.id = 1384; // or 0x568 in hex
    Can0.write(out);

  10. #10
    Thank you for your response.

    How do I read the date without going thru hexdump? And what is hexdump actually doing?

  11. #11
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    2,964
    hexdump is just a function that prints the data from the buffer (8 bytes)
    you dont need that...

    you read it like this:

    firstByte = inMsg.buf[0];
    secondByte = inMsg.buf[1];
    etc up to buf[7]...

  12. #12
    Ok! Let me experiment a bit and see how I go.

  13. #13
    I have experiemented a bit more and being able to detect the frame ID which is great sucess. Now I want to detect the content of the frame and respond with a CAN message as well.

    Code:
    #include <FlexCAN.h> // by Collin Kidder, Based on CANTest by Pawelsky (based on CANtest by teachop)
    
    
    static CAN_message_t msg;
    static uint8_t hex[17] = "0123456789abcdef";
    
    
    static uint8_t msg_to_be_checked[8];
    //msg_to_be_checked[0] = 1;
    
    
    void setup(void)
    {
      delay(1000);
      Serial.println(F("Hello Teensy 3.6 dual CAN Test."));
      Can0.begin(500000);
      pinMode(13, OUTPUT);
      digitalWrite(13, HIGH);
    }
    
    void loop(void)
    {
      CAN_message_t inMsg;
    
      while (Can0.available())
      {
        Can0.read(inMsg); // Read message into inMsg
    
        Serial.print("CAN bus 0: ");
    
        // PRINT TO SERIAL RAW
        Serial.print(inMsg.id);
        Serial.print("  ");
        Serial.print(inMsg.buf[0]);
        Serial.print(" ");
        Serial.print(inMsg.buf[1]);
        Serial.print(" ");
        Serial.print(inMsg.buf[2]);
        Serial.print(" ");
        Serial.print(inMsg.buf[3]);
        Serial.print(" ");
        Serial.print(inMsg.buf[4]);
        Serial.print(" ");
        Serial.print(inMsg.buf[5]);
        Serial.print(" ");
        Serial.print(inMsg.buf[6]);
        Serial.print(" ");
        Serial.print(inMsg.buf[7]);
    
        Serial.print("\t");
    
        // PRINT TO SERIAL HEX
        Serial.print(inMsg.id, HEX);
        Serial.print("  ");
        Serial.print(inMsg.buf[0], HEX);
        Serial.print(" ");
        Serial.print(inMsg.buf[1], HEX);
        Serial.print(" ");
        Serial.print(inMsg.buf[2], HEX);
        Serial.print(" ");
        Serial.print(inMsg.buf[3], HEX);
        Serial.print(" ");
        Serial.print(inMsg.buf[4], HEX);
        Serial.print(" ");
        Serial.print(inMsg.buf[5], HEX);
        Serial.print(" ");
        Serial.print(inMsg.buf[6], HEX);
        Serial.print(" ");
        Serial.print(inMsg.buf[7], HEX);
    
        Serial.print("\t");
    
        // PRINT TO SERIAL HEXDUMP
        hexDump(8, inMsg.buf);
    
        if (inMsg.id == 568) {
          Serial.print("568 FRAME DETECTED!");
          Serial.print("\n");
        }
    
        if (inMsg.id == 1384) {
          Serial.print("1384 FRAME DETECTED!");
          Serial.print("\n");
    
    
          msg.ext = 0;
          msg.id = 1385;
          msg.len = 7;
          msg.buf[0] = 3;
          msg.buf[1] = 0;
          msg.buf[2] = 0;
          msg.buf[3] = 1;
          msg.buf[4] = 5;
          msg.buf[5] = 0;
          msg.buf[6] = 0;
    
    
          msg.buf[0]++;
          Can0.write(msg);
          msg.buf[0]++;
          Can0.write(msg);
          msg.buf[0]++;
          Can0.write(msg);
          msg.buf[0]++;
          Can0.write(msg);
          msg.buf[0]++;
          Can0.write(msg);
          msg.buf[0]++;
          Can0.write(msg);
          msg.buf[0]++;
          Can0.write(msg);
        }
      }
    }
    
    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');
    }
    Serial output
    Code:
    14:35:02.740 -> CAN bus 0: 1328  0 0 0 0 0 0 12 0	530  0 0 0 0 0 0 C 0	0000000000000c00
    14:35:02.740 -> CAN bus 0: 520  0 0 0 0 11 10 0 0	208  0 0 0 0 B A 0 0	000000000b0a0000
    14:35:02.786 -> CAN bus 0: 1384  1 0 0 0 0 0 0 0	568  1 0 0 0 0 0 0 0	0100000000000000
    14:35:02.786 -> 1384 FRAME DETECTED!	
    14:35:02.786 -> CAN bus 0: 1304  0 0 0 0 0 0 0 0	518  0 0 0 0 0 0 0 0	0000000000000000
    14:35:02.786 -> CAN bus 0: 1328  0 0 0 0 0 0 12 0	530  0 0 0 0 0 0 C 0	0000000000000c00
    14:35:02.786 -> CAN bus 0: 520  0 0 0 0 11 10 0 0	208  0 0 0 0 B A 0 0	000000000b0a0000
    14:35:02.786 -> CAN bus 0: 1384  1 0 0 0 0 0 0 0	568  1 0 0 0 0 0 0 0	0100000000000000
    14:35:02.786 -> 1384 FRAME DETECTED!	
    14:35:02.786 -> CAN bus 0: 1304  0 0 0 0 0 0 0 0	518  0 0 0 0 0 0 0 0	0000000000000000
    14:35:02.786 -> CAN bus 0: 1328  0 0 0 0 0 0 12 0	530  0 0 0 0 0 0 C 0	0000000000000c00
    14:35:02.786 -> CAN bus 0: 520  0 0 0 0 11 10 0 0	208  0 0 0 0 B A 0 0	000000000b0a0000
    14:35:02.786 -> CAN bus 0: 1384  1 0 0 0 0 0 0 0	568  1 0 0 0 0 0 0 0	0100000000000000

  14. #14
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    2,964
    you see where your always incrementing indice [0] and Can0.writing it? If thats what your doing than thats pretty much all you have to do for sending

    You will NOT see what you are sending that is normal, but your other device will see it

  15. #15
    Quote Originally Posted by tonton81 View Post
    you see where your always incrementing indice [0] and Can0.writing it? If thats what your doing than thats pretty much all you have to do for sending
    I'm note sure this is correct at all to be honest... Is it enought to do:
    Code:
        Serial.print("WRITING TO CAN0");
        Serial.print("\n");
        msg.ext = 0;
       msg.id = 1385;
       // msg.id = 569;
        msg.len = 3;
        msg.buf[0] = 00;
        msg.buf[1] = 15;
        msg.buf[2] = 00;
        //  "t5693001500"
        Can0.write(msg);
        framedetected = false;
        Serial.print("WRITING DONE.");
        Serial.print("\n");
    ?


    Another thing I cant get my head around is how to format the outgoing CAN msg. Shall it be in HEX or DEC? Depending on how I read the CANbus with different tools and settings, the same CAN msg shows up in different formats.

    These are the same frames in different format.
    Code:
    00 15 00
    00 21 00
    ff 15 00
    And the frame ID can be both 569 and 1385 depending on if its HEX or DEC.

  16. #16
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    2,964
    hex or dec doesnt matter, the value is the same result. you can view the data (read variable) in hex or dec or even binary, your choice

    Serial.print( (HEX) msg.buf[0] );

    just use casting HEX, DEC, BIN

    if you wanna use HEX for setting a variable, you MUST specify 0x

    msg.id = 0x568;

  17. #17
    Thank you. Does this mean that the library accepts DEC as standard when populating the msg.id and buf?

  18. #18
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    2,964
    this is normal accross all C/C++ programming.

    putting buf[0] = 1234; is always decimal
    to specify HEX, use 0x1234
    to specify 3 in binary you put: 0b11


  19. #19
    You live, you learn. Thanks alot for your quick replys!

    Quote Originally Posted by tonton81 View Post
    this is normal accross all C/C++ programming.

    putting buf[0] = 1234; is always decimal
    to specify HEX, use 0x1234
    to specify 3 in binary you put: 0b11


  20. #20
    Alright, I'm stepping this game up a couple of notches. =)

    I've learned a lot during the last few days and its getting really fun.

    With the following program I've made, I have been able to print in both DEC, HEX and BIN to serial console. This to give greater insight to what is happening on the bus. But, first and foremost the serial print in BIN format gives me a bit of grief because it leaves out beginning zeroes, which makes it hard to read which 1 and 0 belongs where on the payload.

    Code:
    #include <FlexCAN.h> // by Collin Kidder, Based on CANTest by Pawelsky (based on CANtest by teachop)
    
    /*
      putting buf[0] = 1234; is always decimal
      to specify HEX, use 0x1234
      to specify DEC 3 in binary you put: 0b11
    */
    
    
    static CAN_message_t msg;
    static uint8_t hex[17] = "0123456789abcdef";
    boolean framedetected = false;
    int rawrmp;
    int displayrpm;
    
    void setup(void)
    {
      delay(1000);
      Serial.println(F("Hello Teensy 3.6 dual CAN Test."));
      Can0.begin(500000);
      pinMode(13, OUTPUT);
      digitalWrite(13, HIGH);
      Serial.print("\n");
    
      Serial.print("DEC");
      Serial.print("\t");
      Serial.print("HEX");
      Serial.print("\t");
      Serial.print("HEXDUMP");
      Serial.print("\t");
      Serial.print("BIN");
      Serial.print("\n");
    
    }
    
    void loop(void)
    {
      CAN_message_t inMsg;
    
      while (Can0.available())
      {
        Can0.read(inMsg); // Read message into inMsg
        if (inMsg.id == 1344) {
          // PRINT TO SERIAL RAW
          Serial.print(inMsg.id);
          Serial.print(" ");
          Serial.print(inMsg.buf[0]);
          Serial.print(" ");
          Serial.print(inMsg.buf[1]);
          Serial.print(" ");
          Serial.print(inMsg.buf[2]);
          Serial.print(" ");
          Serial.print(inMsg.buf[3]);
          Serial.print(" ");
          Serial.print(inMsg.buf[4]);
          Serial.print(" ");
          Serial.print(inMsg.buf[5]);
          Serial.print(" ");
          Serial.print(inMsg.buf[6]);
          Serial.print(" ");
          Serial.print(inMsg.buf[7]);
    
          Serial.print("\t");
    
          // PRINT TO SERIAL HEX
          Serial.print(inMsg.id, HEX);
          Serial.print(" ");
          Serial.print(inMsg.buf[0], HEX);
          Serial.print(" ");
          Serial.print(inMsg.buf[1], HEX);
          Serial.print(" ");
          Serial.print(inMsg.buf[2], HEX);
          Serial.print(" ");
          Serial.print(inMsg.buf[3], HEX);
          Serial.print(" ");
          Serial.print(inMsg.buf[4], HEX);
          Serial.print(" ");
          Serial.print(inMsg.buf[5], HEX);
          Serial.print(" ");
          Serial.print(inMsg.buf[6], HEX);
          Serial.print(" ");
          Serial.print(inMsg.buf[7], HEX);
    
          Serial.print("\t");
    
          // PRINT TO SERIAL HEXDUMP
     //     hexDump(8, inMsg.buf);
     //     Serial.print("\t");
    
          // PRINT TO SERIAL BIN
          Serial.print(inMsg.id, BIN);
          Serial.print(" ");
          Serial.print(inMsg.buf[0], BIN);
          Serial.print(" ");
          Serial.print(inMsg.buf[1], BIN);
          Serial.print(" ");
          Serial.print(inMsg.buf[2], BIN);
          Serial.print(" ");
          Serial.print(inMsg.buf[3], BIN);
          Serial.print(" ");
          Serial.print(inMsg.buf[4], BIN);
          Serial.print(" ");
          Serial.print(inMsg.buf[5], BIN);
          Serial.print(" ");
          Serial.print(inMsg.buf[6], BIN);
          Serial.print(" ");
          Serial.print(inMsg.buf[7], BIN);
    
          Serial.print("\n");
    }
    }
    }
    
    
    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');
    }
    Red = DEC, Blue = HEX, Green = BIN. You can see the bytes that is just one "0" instead of "00000000"


    Secondly, I have found that the nodes on the CANbus is packing multiple data into one byte. This is where the BIN readout comes in very handy. With this I have verified the following.



    But! How do read this out to understandable variables in an easy way? Lets say I want to populate the variables

    Code:
    int GearNumber
    boolean standPostion 
    boolean ABSLight
    boolean neutralLight
    from the CANBus frame "10101000000 00100101 101100 1 0 0 0 0 0"? From my table above, this frame means ID 1344 (DEC), 2nd gear, Side stand Up, Neutral Light Off, ABS light On.

    Somehow I will have to read out the individual BIN data and make sense out of it.

  21. #21
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    2,964
    the leading 0s are not printed is normal, you need to use printf or sprintf for that

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •