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

Thread: TeensyCAN

  1. #1
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,319

    TeensyCAN

    Here it is! CAN2.0/CANFD Implementation early stages. Redesign of CANquitto. This library has the ability not only to work on CAN2.0 and CANFD, but the payload transfers are automatically adjusted to the dlc size of your mailbox and sent out dissambled, and at the other endpoint, they are re-assembled based on the DLC implementation.

    Library supports sending payloads of theoretically 4,063,170 bytes. Considering the RAM on MCU, I doubt you'd reach this
    New feature not introduced in CANquitto ---> broadcasting payloads! All nodes can receive the same identical payload, sort of like UDP, no responses are needed.
    Payloads sent specifically to nodes, will return an ACK 0x06 if the reception and CRC are validated from other endpoint.

    Uses the background functions built into FlexCAN_T4 to receive frame data.
    Examples were posted with the library. To be effective, at least one or more extended mailboxes need to be interrupt enabled in FlexCAN_T4.

    https://github.com/tonton81/TeensyCAN

    On a side note only FD was tested, with mailbox sizes of 8 to 64 bytes in the slave demo, the master demo was set to 64 bytes to demonstrate it can accept all different DLC lengths of the slave transmissions

    Node.sendMsg() sends a broadcast payload to all nodes
    node100.sendMsg() sends a payload specifically to node #100
    Last edited by tonton81; 11-03-2019 at 06:38 AM.

  2. #2
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,319
    Upped to github is a new update to TeensyCAN. USB Serial & UART accesses can be called specifically to a node or globally on the network of nodes!

    Node.Serial.println("Hello World!"); // prints to Serial monitor of all nodes on the network, using a single set of data frames. All nodes will assemble the message and process as needed.
    node100.Serial.println("Hello World!"); // prints specifically on this node, other nodes ignore the call

    The supported functions are write(), write(buf,len), print(), println(), read(), readBytes(), peek(), available().
    Yes! This new update has a 2 way send and receive payloads in a single call, and the commands are not ran from an interrupt!
    Whats more? 2 or more nodes may print to the same port without collision if arrays are used. The accesses are sequential and responded to immediately.

    Note, do not try to print() stuff to other serial ports if you didn't run Serialx.begin() on that node, it will hard lock the mcu.

    Later on when I add GPIO support, it might be a good solution for people who want to keep gpio pins sync'd accross microcontrollers. Example is (not implemented yet):

    Node.pinMode(13, OUTPUT); /* tell all nodes to set their pin 13 as output */
    Node.digitalWrite(13,HIGH); /* tell all nodes to turn their leds on */
    node100.digitalWrite(13,LOW); /* while all other nodes have pin13 HIGH, node100 only is switched LOW */

    On a side note, global commands have no responses. Example:
    Node.Serial.println("Hello World!"); /* dont expect valid return value */
    node100.Serial.println("Hello World!"); /* returns 13 */

  3. #3
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    5,099
    Nice work Tony.

  4. #4
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,319
    New update for TeensyCAN.

    Node Discovery! The library is able to keep a list of active nodes, their DLC capabilites (receive DLC size max), and their timeout on the network (millis()).
    The timeout depicts how long before the node can resend a keep-alive signal on the bus, and the limit is kept on the sender's active list while it's checked against the local timestamp.
    DLC sizing, the node on the active list has his max DLC capability stored. This prevents 64 byte nodes from writing 64 byte data to 32byte DLC nodes. The sender node now sends at the receivers's size, in this case, 32 bytes. If, however, the receiver accepts a bigger DLC than the sender, the sender sends at his capability instead. So a 32byte node would send a 32byte buffer to a 64byte node. This is all automatic and no user intervention is needed. As far as global sends go, they go out based on the smallest DLC node. Basically, if you have 5 nodes on the network, they will be on the active list.
    Let's say:

    node1 is 32bytes,
    node2 is 16bytes,
    node3 is 64bytes,
    node4 is 16bytes,
    node5 is 8bytes.

    Global sends would go out as 8 bytes traffic. However, if node5 were to drop off the list (offline), global sends would now be sent as 16 byte traffic.

    sendMsg has been upgraded to use the unified assembler/disassembler as the commands. It's features have been retained.
    Last edited by tonton81; 11-10-2019 at 08:39 PM.

  5. #5
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,319
    TeensyCAN has now gone multi-bus mode! Nodes can be talked to on any or all of the 3 CAN busses on Teensy. Responses to nodes will happen to their appropriate busses. Globals now send to all 3 busses unless one is chosen specifically using ::setBus.

    If setBus is set, only one bus is broadcasted to. If unset, all busses will be talked to for global messages. (discoveries or node replies).

    Using 64byte frames, 1024bytes transfers now at 2ms. This requries the FlexCAN_T4::events() update to return the sequential queues left in the buffer needed to send out, before a next TeensyCAN message went out. Previously, this test took 17ms to ensure no payload collisions, to transfer the same 1024 payload accross 64byte message frames.

    Multibus mode retains FD controller TX sizes of external nodes:

    If the sender is 64byte frames supported, and the FD node supports 32 max, The sender will send at 32 frame size. In the global scheme, all CAN2 busses, the sender would send out as 8 byte frames, while, maintaining the size of the FD bus node (32bytes), sending at it's supported size on the FD bus.

  6. #6
    Junior Member ITman496's Avatar
    Join Date
    May 2020
    Location
    NJ, USA
    Posts
    10
    Hello! This library seems absolutely perfect for my project, when I get home from work I'm going to get a few teensys and try it out!

    I have a few questions that after looking around a bit I didn't see answered in the demos.

    Can I send floats directly or do I have to break them up first? This would be useful for sending GPS data (lat,lon) as well as lots of sensor data in general for me.

    (If you're curious, the project is an ultralight aircraft!)

    I have about 8 nodes that are gonna be sending all kinds of things to each other, so your large payload system and node private messaging system is going to be a godsend for me since I was struggling to figure out how I was going to implement all of this.

    Thank you again! I'm a bit of a noob at the higher level programming, I'm more of a mechanical person who knows enough coding to glue my projects together.

  7. #7
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,319
    The CAN data is bytes only, you will need to handle the data in the array, splitting up the floats to bytes and back at other end. You could always use the PacketID of the data to identify which frames are identified uniquely as floats or other data, to process different types of arrays, you could also do some trickery I think to pass an array of floats as an array of bytes by using some cast magic, and adjusting the size of the array as necessary, but I am no expert on that

  8. #8
    Junior Member ITman496's Avatar
    Join Date
    May 2020
    Location
    NJ, USA
    Posts
    10
    Sounds good! Thank you!

    I'm so excited to have found this library. It simplifies so many things I thought I was going to have to do manually by myself!

  9. #9
    Junior Member ITman496's Avatar
    Join Date
    May 2020
    Location
    NJ, USA
    Posts
    10
    Hello! I am having some trouble getting this working. I realized just now, though, that it is because CAN FD only works on port 3, and I am trying to use port 1. I know I can solder wires to the bottom, but I intend to put this in a socket on custom boards, so I don't want to have to use those non-pin-headered pins on the bottom.

    I realize FD is faster, but I do not think I need the speed. How can I switch the example to work on port 1? I'm not sure which parts I need to remove to make it non FD.

    Apologies again for the probably very noobie questions!

    To elaborate, I have 2 teensy 4's hooked via CAN1 to two of these adapters:
    https://www.amazon.com/gp/product/B0...?ie=UTF8&psc=1

    And I don't seem to be getting anything.. I changed some stuff I think would work based on the github page for flexCAN to change to CAN1, but in the serial monitor on the slave all I get is a repeating '0' and that's it.

    I'm really not sure what to do to get this working, without FD, I have not tried with FD however as I can't really easily use it in this setup. So far my CAN bus experience is with the MCP2515 boards and mcpCAN library, that did work.
    Last edited by ITman496; Today at 12:24 AM.

  10. #10
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,319
    you need to use FlexCAN_T4 constructor, not FlexCAN_T4FD, and use CAN1 instead of CAN3

    Also, it's good to run one of the FlexCAN_T4 demos to confirm your connections are good before working on TeensyCAN as it relies on the driver to be communicating properly

  11. #11
    Junior Member ITman496's Avatar
    Join Date
    May 2020
    Location
    NJ, USA
    Posts
    10
    I wanted to ask about that, actually. In mcpCAN demos there was a simple set of sketches to be able to transmit and receive on two different arduinos. I think I found the equivalent for FlexCAN_T4, this one:

    https://github.com/tonton81/FlexCAN_...interrupts.ino

    So in theory I should be able to hook two teensies together and run this sketch on both and I should start seeing things on the serial console if everything is working?

  12. #12
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,319
    yes' correct. well they receive, you need to put something to transmit so the other teensy can see it.

    CAN_message_t msg;
    msg.id = 0x123;
    Can0.write(msg);

  13. #13
    Junior Member ITman496's Avatar
    Join Date
    May 2020
    Location
    NJ, USA
    Posts
    10
    Heh. I feel dumb. I got FlexCAN_T4 working! Now to move on to TeensyCAN.

    For anyone else suffering this fate, take note, it was dumb.

    I probed the canbus lines with my oscilloscope and was wondering why the readings were so minute and low.. Didn't make any sense. Then I measured the resistance of the bus.. dead short. What?

    So on the waveshare module, there is 2 pins sticking up. On the MCP2515 these were for a jumper to include or not include the built in 120 ohm resistor. So you could jumper the two end nodes to terminate the bus.

    On the waveshare shield, these two pins are actually just CANL and CANH, you can use them instead of the screw terminals. I just shorted both sides of by bus and was wondering why it wasn't working. Doh!

    Now it works fine. Don't do that.

    Anyway, onwards to the actual library this thread is about!

  14. #14
    Junior Member ITman496's Avatar
    Join Date
    May 2020
    Location
    NJ, USA
    Posts
    10
    I have data! Woohoo!

    I guess now my only real question is.. is there any more fleshed out examples for this library? I can see that these two lines decide.. if the packet is being sent to ID 5, globally or ID7, locally..? (using Node.sendMsg instead of node100.sendMsg)

    Code:
    Serial.println(    Node.sendMsg(data, 40, 5)); /* Global always returns 1, no response. */
    Serial.println(node100.sendMsg(data, 40, 7)); /* ACK: 0x06, TIMEOUT = 0xFF */
    What I don't understand is what the difference is between sending data with node100.sendMsg vs Node.sendMsg. The FD_Master sketch receives both exactly the same, except I guess I can see the broadcast is 1 on Node.SendMsg, and broadcast is 0 on node100.sendMsg.

    My main questions right now are: How do I target certain nodes to send data to? I get broadcast is to send it to everyone, but how do I decide to send data only to nodes.. lets say from node 2, to nodes 3 and 4, on an 8 node system? What would have to be done on both ends? On node100.sendMsg, I don't see anything relating to what node to send it to, just these three fields. node100.sendMsg(data(obvious),40(data length?),7(can packet ID)

    I am super sorry for all these questions, I can usually figure all of this out on my own but there are not too many examples to follow, so this is all I have been able to do on my own thus far. Thank you so much for all the fast responses!

  15. #15
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,319
    basically, Node sends to all nodes, its global, whereas your specific node100, only receives the data.

    if you do Node.Serial.println("hello world");, all nodes will print that to Serial port.
    if you do that to node100, it will print only to node100's Serial port.

    the array transfers work the same way.

  16. #16
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,319
    check the constructor for node100, that points to the node you want. on the other nodes, you add the nodes you want to control as well. this is a 2way library where they are all multi-master.

    the nodes are automatically sending an active frame on a network that includes their payload size so they can dynamically talk to CAN and CANFD irregardless of data size, global messages would be checking the active list for the smallest DLC, which in CAN2.0 mode is 8 in your network, so they will automatically adjust based on that, which is why FD is faster, because TeensyCAN could easily see a 64 byte data node and send a frame to it 64bytes at a time provided the sender can send at that size, else it sends at it's max

    PacketID is an identifyer of the array being received, so you know what to do with it. lets say packetid 5 is sensor data and packetid 8 is gps data, you can handle the arrays that way

  17. #17
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,319
    TeensyCAN node36 = TeensyCAN(36);
    if you have nodes 2 3 8,

    on node 2, put:
    TeensyCAN node3 = TeensyCAN(3);
    TeensyCAN node8 = TeensyCAN(8);

    on node 3, put:
    TeensyCAN node2= TeensyCAN(2);
    TeensyCAN node8 = TeensyCAN(8);

    etc that will allow each node to master each other

  18. #18
    Junior Member ITman496's Avatar
    Join Date
    May 2020
    Location
    NJ, USA
    Posts
    10
    Okay! How do I set the ID of each node, though? On your slave example as I downloaded from github, this is the start of it:

    Code:
    TeensyCAN node100 = TeensyCAN(100);
    
    void setup() {
      Serial.begin(115200); delay(400);
      pinMode(6, OUTPUT); digitalWrite(6, LOW); /* enable transceiver */
      FD.begin(); /* enable the FlexCAN controller before assigning it */
    
      node100.setBus(_CAN3);
      node100.setID(20);
    From my understanding of what you are saying.. the first line of the code I posted, that's where I put all the OTHER nodes like you just said, with 2 and 8 for example, and the... node100.setID(20); is setting this node's ID?

    Why is it node100.setID instead of Node.setID? Do I always use the first constructor as the node itself? In the master it's just Node.setID. Which is the right way to do it?

    Thanks so much for the answers!

  19. #19
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,319
    it's a singleton, either can be used to set the ID of local node

  20. #20
    Junior Member ITman496's Avatar
    Join Date
    May 2020
    Location
    NJ, USA
    Posts
    10
    Oh okay. Man, I'm learning so many new things!

    Thank you! I'll go scrounge up a third node to try and start really getting this test going.

    When you were saying about how FD was faster then 2.0.. you mentioned packet size.

    I thought CAN2.0 was able to handle the 64byte packets too? Or is that FD only and I misunderstood?

    If all of my nodes are teensy4's running can2.0, will I get the 64 byte packets? Or will it shrink to 8?

  21. #21
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,319
    it will automatically adjust to the size on the network.
    lowest DLC to support global nodes, DLC of other node if capable of sending to it's size, otherwise it will use lower size automatically. CANFD is "up to" 64 bytes, CAN2.0 is 8 bytes max.
    Note: on CANFD, using 8 byte message boxes gives you up to 64 mailboxes, while using 64 byte sizes gives you around 14. CANFD is also up to 8x faster in the data field, arbitration remains same speed as CAN2.0. 1Mbps nominal max, 8Mbps data max

  22. #22
    Junior Member ITman496's Avatar
    Join Date
    May 2020
    Location
    NJ, USA
    Posts
    10
    Ok, understood!

    My can transceivers only support up to 1MBPS anyway. What I will likely do is get all 8 nodes set up and see if they can really send all the data to each other or if it will be a speed issue..

    Last question for now. Is it possible to target multiple nodes with the same message at the same time so I don't have to transmit twice? For example: Engine data unit data is relevant to the main flight computer as well as the backup display/datalogger. Right now, it seems like I have to send one transmission for each node. Broadcast would work but then it kind of defeats the point of this private messaging system in the first place, yeah?

  23. #23
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,319
    yes thats why Node.sendMsg is there, all nodes will get it

  24. #24
    Junior Member ITman496's Avatar
    Join Date
    May 2020
    Location
    NJ, USA
    Posts
    10
    Excellent. Thank you!

    Is there any other functions this library provides other then sending large packets and the whole node private/broadcast messaging system with acks and whatnot? (and I saw earlier you said I can do remote serial writes, that's pretty cool!)

    Also, I'm trying to understand by reading through other stuff, what does Can0.Events(); and Node.events(); do? How often do they have to run? I see them in just the main loop, how long can I leave them for before bad things start to happen, if my code goes off in another direction for a while before coming back to main loop?

Posting Permissions

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