Another fork of FlexCAN

Yes, i know i need the transceiver to properly communicate, but im seemingly not getting an ACK when i receive messages. So i was curious if the ACK was handled by the transceiver on its own, or if it were handled by the Flexcan/Teensy. If i knew what part of the system handles the ACK, then i can test that part of the system to try to isolate the problem.
 
Yes, i know i need the transceiver to properly communicate, but im seemingly not getting an ACK when i receive messages. So i was curious if the ACK was handled by the transceiver on its own, or if it were handled by the Flexcan/Teensy. If i knew what part of the system handles the ACK, then i can test that part of the system to try to isolate the problem.

It is handled by the hardware within the MCU on the Teensy. ACK works like this:

1. The sender produces a frame and leaves the ACK bit recessive.
2. The sending node actually listens to the physical line the entire time it is sending. It checks to see if the bus is tracking the bits it sent. If it tried to send a recessive bit and got a dominant bit then it knows another node is transmitting and clobbered it. It quits trying for this message and tries again later.
3. Everything else on the bus receives every message. They all use filtering to see if they really care. At the first bit of the ID that doesn't match the receiving nodes quit listening.
4. Everyone is free to listen but any nodes that make it through the whole frame have a choice to make. At the end of the frame is the recessive ACK bit. Each node must decide whether they'd like to force this bit dominant or not. No one has any requirement to set this bit. This is the only bit that can go from recessive to dominant and not cause the sending node to have a panic attack. Since the sender is also listening to the bus it knows whether anyone set the bit dominant or not. If something did then it assumes the transmission went OK and it will leave happy. If nobody set the ACK bit then it assumes that no one got it. The sender then has the choice of either giving up or giving it another try later on.

So, there are multiple reasons that things might go wrong:
1. Everything capable of listening might be in listen only mode which prevents any attempts to set dominant bits. This would then preclude such nodes from ACK bit setting.
2. Everything else might be set to a different baud rate and thus unable to sync to this node
3. Everything else might have filters set up that drop the frame before it is fully received (thus they're not paying attention when the ACK bit comes around)
4. A bus collision could occur which causes the sender to abort and *maybe* try back later

I'm not really sure what is going on for you but hopefully the above explanation helps to narrow down what could be going on.
 
Thanks for that detailed explanation Collin, much appreciated!

There in lies my predicament. I can receive to the teensy/sn65hvd230 just fine, yet it seems as the teensy isn't setting the ACK bit dominant causing the arduino to infinitely re-send the message.

I also can't successfully send a message from the teensy/sn65hvd230 to the arduino.

I can't determine whether it's a problem with code or transceiver.

There is another thread on this forum where people have reported issues with the sn65hvd230 transceivers and sending. Seems there was a bad batch or something. Mine don't seem capable of transmissing anything.

I guess I could buy a couple MCP2551's and give them a whirl as a test. But I'm using a teensy 3.6 so I'm not sure if it would hurt the teensy even if I used a seperate 5v power supply only for the MCP chip.
 
If it won't transmit at all then therein lies the trouble. Setting ACK is a form of transmission so if you can't send you can't ACK and then you'll get the message infinite times. I haven't used the HVD230 myself so I just looked it up again. As it turns out, that particular transceiver has functionality to put it into listen only mode completely separate from the listen only mode available on the MCU itself. This could be your trouble. Apparently if the Rs pin is high on this chip you will be in listen only / standby mode. You need to ensure that you are grounding the Rs pin. Then it will probably work right. If you are grounding the pin and it is still doing this then you have a bad chip and it should be replaced.
 
Yea I took interest in the Rs pin on the board. As received, it used a 10k pulldown to ground, putting the chip in "slope control mode". I've since de-soldered the pulldown, and shorted the pin across the pads directly to ground with no change in function.

I guess replacement is the route I will go. What transceiver do you use? And where do you source them? I'll need 1mbps capability for my intended use.
 
i dont think some devices wait for ACK and the sender usually spits out data realtime so buffering it and resending the same frame for example on a car rpm or vss, it wont ask the receiver if it got it, disconnecting the cluster will prove it as the same frame is not sent repeatedly. if your doing mcu to mcu can its a good idea to do the same concept without acks, specially if the data is changing at a fast rate, send it once and clear the buffer. this has the benefit as well for your slaves not needing the extra transceivers if your just controlling them with 8 data bytes. when i set mine up on mega2560 i stacked 3 canbus shields back to back and only bridges necessary pins, with 11 wires comming out in the end

power(+ and -) spi(miso,mosi,sclk,cs0,cs1,cs2) hscan(high and low) and bcan (single wire hookup)
the hscan has 2 because one is filtered for ecu requests, and one is for all other traffic except ecu, at 500kbps, however i needed a 3rd at 33.33kbps for the bodycontroller accessible via single wire behind the cluster.

once i transfered over my mega2560 to teensy i kept the same hardware and dropped then on spi2 @ 4mhz, one can on the teensy isnt enough for my project, and to keep my project portable ( new teensies in future??) :) i decided to keep attached hardware over built in hardware
 
Yea I took interest in the Rs pin on the board. As received, it used a 10k pulldown to ground, putting the chip in "slope control mode". I've since de-soldered the pulldown, and shorted the pin across the pads directly to ground with no change in function.

I guess replacement is the route I will go. What transceiver do you use? And where do you source them? I'll need 1mbps capability for my intended use.

I usually use the HVD232 which is still in the same class, it just doesn't have the listen only functionality. Usually I get my parts from DigiKey or Mouser. I kind of randomly pick one over the other at any given moment.
 
I use the HV230 and have no issues with it. I have 4 of them here, the ones that I've posted here. at 1Mbps with 0 delay between sends, none of the nodes have issue logging the sent data.
 
I use the HV230 and have no issues with it. I have 4 of them here, the ones that I've posted here. at 1Mbps with 0 delay between sends, none of the nodes have issue logging the sent data.

Yeah, I don't think that the problem is really the HVD230. Such a transceiver should work fine. It just appears that some people have gotten broken chips from some shady place or something. Those chips seem to never go out of standby mode and that's a problem.

Any of the HVD transceivers should work fine. I've also used ISO1050 transceivers. Those are isolated which then requires two separated power supplies. But, they're useful for when you want really, really good noise immunity on your CAN tranceiver.
 
Thank you for working on this interrupt based CAN messages for the Teensy. This is a nice feature. I have a couple things to share:
1. It was able to work on 666000 and 1000000 baud CAN. That was nice since I didn't have to mess with bit timing.
2. Extended IDs are not enabled by default. I had to set filters before being able to receive extended ID messages. I did it by adding a filter during setup (See attached Arduino Sketch).
3. Multiple mailboxes and filters needed to be setup to ensure reception of all traffic. I attached the modified ObjectOrientedCAN.ino sketch that implements this. Many messages will be dropped if only 1 mailbox is setup.

I ran a "stress" test and tried to get the most messages captured as possible. I used the Teensy3.6 on one end with each CAN channel using the TI TCAN332 transceiver. This was my receiving node. The transmitting node was a BeagleBoneBlack running SocketCAN with can-utils. It was a short network, but a correctly terminated CAN bus with 120 ohm resistors at each end.

I issued the following commands on the BeagleBoneBlack to generate 100% bus load with standard frames that were 1 byte long (the shortest message). At the bash command prompt I entered this:
Code:
sudo ip link set can0 down
sudo ip link set can0 type can bitrate 1000000
sudo ip link set can0 up
cangen -g 0  -i   -I 0 -D i  -L 1 can0 &

sudo ip link set can1 down
sudo ip link set can1 type can bitrate 1000000
sudo ip link set can1 up
cangen -g 0  -i   -I 1 -D i  -L 1 can1 &

On the Teensy 3.6 at 180 MHZ, I ran the attached sketch. The output was 27168 message per second on both channels. If I only ran one channel at a time, I get about 16746 messages per second on each channel. Since I was expecting a factor of 2, I hooked up an oscilloscope to verify 100% bus load and my BBB can't generate 100% busload with both channels going. I'll scrounge up another and try layer, but I suspect the Teensy can handle it.

When I switched to transmitting extended IDs:
Code:
cangen -g 0  -i -e  -I 0 -D i  -L 1 can0 &

My reception rate dropped to about 12069 messages per second with the o'scope trace showing a saturated bus.

If you enable the serial display, expect something like this:

6 ID: 0 Data: 94
4 ID: 1 Data: 87
5 ID: 0 Data: 95
5 ID: 1 Data: 88
6 ID: 0 Data: 6
4 ID: 1 Data: 89
5 ID: 0 Data: 7
5 ID: 1 Data: 8A
6 ID: 0 Data: 8
4 ID: 1 Data: 8B
5 ID: 0 Data: 9
5 ID: 1 Data: A4
6 ID: 0 Data: A
4 ID: 1 Data: A5
5 ID: 0 Data: B
5 ID: 1 Data: A6
6 ID: 0 Data: C
4 ID: 1 Data: A7
5 ID: 0 Data: D
5 ID: 1 Data: A8

However, the serial output just stops... I'm wondering if it's a Teensy thing or I've filled up the Arduino serial monitor. So I ran the serial monitor in a little Python program to see if it stalled. Interestingly, it started using mailboxes 4 and 5 then moved up to 5 and 6 and so on in a matter of a minute. It stayed on mailbox 9 and 10 for a while, then the serial monitor froze again after about 5 minutes but the LED kept on blinking. This is where I'm stuck. How do we keep this serial print functionality going on in perpetuity? Is the CAN RX rate higher than the Serial TX rate and I'm overflowing the Serial port buffer?

View attachment ObjectOrientedCANExtendedIDs.ino
 
it probably locks up if theres too much data, what seeedstuido code/or hardware? does is if the data cant be read by the time the buffers are full the software/hardware clears old data while loading new, essentially you get missing frames because the bus is heavily congested. however, ive never had it lock uo. when i had teensy3.5 can runnung without tranceiver, and a mega2560 with sparkfun canshield using seestudio code with constant frame sendings, mega was sending frames to teensy fine at 500,000 kbits, however i did notice lockups too on teensy, but, i lowered it to 100,000kbps or lower, and it didnt freeze anymore
 
2. Extended IDs are not enabled by default. I had to set filters before being able to receive extended ID messages. I did it by adding a filter during setup (See attached Arduino Sketch).
3. Multiple mailboxes and filters needed to be setup to ensure reception of all traffic. I attached the modified ObjectOrientedCAN.ino sketch that implements this. Many messages will be dropped if only 1 mailbox is setup.

Yes, the example sketches were pretty basic. I also have a special sketch for CAN capture and it does set multiple mailboxes. If you get up to really fast reception rates then I could see how a second frame might come in while you're still processing the first one. And, yes, I didn't do anything to support extended frames.

I ran a "stress" test and tried to get the most messages captured as possible. I used the Teensy3.6 on one end with each CAN channel using the TI TCAN332 transceiver. This was my receiving node. The transmitting node was a BeagleBoneBlack running SocketCAN with can-utils. It was a short network, but a correctly terminated CAN bus with 120 ohm resistors at each end.

I issued the following commands on the BeagleBoneBlack to generate 100% bus load with standard frames that were 1 byte long (the shortest message). At the bash command prompt I entered this:
Code:
sudo ip link set can0 down
sudo ip link set can0 type can bitrate 1000000
sudo ip link set can0 up
cangen -g 0  -i   -I 0 -D i  -L 1 can0 &

sudo ip link set can1 down
sudo ip link set can1 type can bitrate 1000000
sudo ip link set can1 up
cangen -g 0  -i   -I 1 -D i  -L 1 can1 &

On the Teensy 3.6 at 180 MHZ, I ran the attached sketch. The output was 27168 message per second on both channels. If I only ran one channel at a time, I get about 16746 messages per second on each channel. Since I was expecting a factor of 2, I hooked up an oscilloscope to verify 100% bus load and my BBB can't generate 100% busload with both channels going. I'll scrounge up another and try layer, but I suspect the Teensy can handle it.

When I switched to transmitting extended IDs:
Code:
cangen -g 0  -i -e  -I 0 -D i  -L 1 can0 &

My reception rate dropped to about 12069 messages per second with the o'scope trace showing a saturated bus.

If you enable the serial display, expect something like this:

6 ID: 0 Data: 94
4 ID: 1 Data: 87
5 ID: 0 Data: 95
5 ID: 1 Data: 88
6 ID: 0 Data: 6
4 ID: 1 Data: 89
5 ID: 0 Data: 7
5 ID: 1 Data: 8A
6 ID: 0 Data: 8
4 ID: 1 Data: 8B
5 ID: 0 Data: 9
5 ID: 1 Data: A4
6 ID: 0 Data: A
4 ID: 1 Data: A5
5 ID: 0 Data: B
5 ID: 1 Data: A6
6 ID: 0 Data: C
4 ID: 1 Data: A7
5 ID: 0 Data: D
5 ID: 1 Data: A8

However, the serial output just stops... I'm wondering if it's a Teensy thing or I've filled up the Arduino serial monitor. So I ran the serial monitor in a little Python program to see if it stalled. Interestingly, it started using mailboxes 4 and 5 then moved up to 5 and 6 and so on in a matter of a minute. It stayed on mailbox 9 and 10 for a while, then the serial monitor froze again after about 5 minutes but the LED kept on blinking. This is where I'm stuck. How do we keep this serial print functionality going on in perpetuity? Is the CAN RX rate higher than the Serial TX rate and I'm overflowing the Serial port buffer?

Wow, thanks for such thorough testing! I've tested with a Teensy 3.6 at 180Mhz on one end and a Kvaser leaf light with socketcan on the other side. I tried full bus load at 500k and 1M and it didn't drop frames or lock up. I was testing with much larger frames though. Usually I either lock it at 8 bytes per frame or leave it at random bytes per frame. At 1M you can saturate as low as about 8400 frames per second if you have 8 data bytes. But, I haven't tested with really short frames. I suppose that's a better stress test as it requires the code to handle more frames at a faster rate.

It sure sounds like you're moving up the mailbox list which would suggest that the CAN reception rate is slightly higher than the USB rate. That... well, it just might be possible. USB is run as a polled bus where the master side polls clients. Maybe the way the comm flow works is causing your serial data to run a little behind and get farther and farther behind as time goes on. In my special firmware for CAN capture I use my own buffer that I dump to the USB interface every 2ms so that I'm sure to be dumping as large of a payload as possible. I feel like that helps to ensure that when the polling interval hits I'm ready with large payloads and not trying to send little chunks. Maybe that helps, maybe not. So far it seems stable at the bus loads I've tried it on. Perhaps I should try really small frames and see what happens.
 
CollinK, I did some correction recently to my fork of the FlexCAN library to use proper alternative pins for T3.5. Also updated the pictures in the readme to include the alternative CAN pins. You may want to merge these changes into your fork. :)
 
CollinK, I did some correction recently to my fork of the FlexCAN library to use proper alternative pins for T3.5. Also updated the pictures in the readme to include the alternative CAN pins. You may want to merge these changes into your fork. :)

Thanks, yeah, I did see the changes as I've subscribed to both your and Teachop's repo so I get a notification every time a new commit happens. I'm going to try to get all of the various bits merged in tonight. I see some changes regarding RTR, I believe on the Teachop repo. I really, really am against the use of RTR but I suppose there are probably some antiques that still use it. Maybe I'll merge that stuff in too.
 
I see some changes regarding RTR, I believe on the Teachop repo. I really, really am against the use of RTR but I suppose there are probably some antiques that still use it. Maybe I'll merge that stuff in too.
That's only a pull request from H4nky84 that wasn't merged (neither on the teachop's repo nor on my fork).
 
OK, I think I'm up to date with all of the changes now. I've snagged all the new pictures, updated the code to support the alternate pins on the 3.5 Teensy, added the RTR code just for the heck of it (I don't see how it can hurt), and added the posted extended frames reception example. Testing seem to indicate that it still works just like it did on the Teensy 3.6 I have so it's updated now.
 
The issue i am getting, is the Teensy 3.6, will read the same message infinitely every time CANbus0.read(rxmsg) is run.

This same thing happened to TurboStreetCar. The most likely explanation is that you have only two devices on the CAN bus, one sending, one receiving. The issue is that the receiving side is not setting the acknowledge bit. If it does not acknowledge the message then the sending side will attempt to re-send forever. Well, it depends on the sender but some resend forever. I believe we've got the FlexCAN library set to tx_once mode where it won't try even twice; just once and done. If your receiving side is not setting the ACK bit then there are two possibilities: 1. you are in listen only mode (if you're using the flexcan library then you need to call a special function to go into this mode so it wouldn't happen by accident) or 2. your transceiver is in listen only mode. Some CAN transceivers can themselves be set to listen only and then you can try to set ACK all you want but it won't do it. It turns out that some transceivers seem to be broken and work fine for reception but will not send no matter what. In that case you need to replace your transceiver. There isn't any other fix on the reception side as the infinite sending is completely a function of the transmitting side.
 
I just a few days I'm going to publish 1.35-beta2, which is (probably) the last chance to get any changes into the 1.35 release.

Sadly, I *still* haven't had time to do anything with CAN protocol. I'm really depending on your feedback for what to include with 1.35. Please let me know?
 
Has anyone tried any functions for bitshifting?
I'm not familiar with how to translate say byte 4, bit 2 and then something with it.
There was some discussion about it in the other CAN thread, but not much that could be used in practice.
 
I just a few days I'm going to publish 1.35-beta2, which is (probably) the last chance to get any changes into the 1.35 release.

Sadly, I *still* haven't had time to do anything with CAN protocol. I'm really depending on your feedback for what to include with 1.35. Please let me know?

Well, it could be a complex question. My repo at https://github.com/collin80/FlexCAN_Library is up to date with all the latest changes and the API hasn't changed since last you knew so it should be good to go. I believe you said you were going to use it in the previous release so if you did then it would be an easy choice to grab the current version in the repo and use that. If you didn't and you want to maintain continuity with the other API then Pawelsky's version would be a good choice: https://github.com/pawelsky/FlexCAN_Library He, after all, is responsible for most of the recent changes that helped to better support the Teensy 3.5 and he created several nice illustrations of where the alternate CAN pins are. All of those changes are merged into my copy too.
 
Has anyone tried any functions for bitshifting?
I'm not familiar with how to translate say byte 4, bit 2 and then something with it.
There was some discussion about it in the other CAN thread, but not much that could be used in practice.

What sort of functions are you looking for specifically? Would it be helpful to have a function that takes a byte and bit and returns that bit? Or, a byte and a bit range and returns the value (shifted to be based at 0)? Or, maybe even treating the 8 bytes within a CAN frame as a 64 bit value? What is bit 43? What is bit 10? What value is formed by bits 13-16? Problems become apparent if you want to get a value from within the CAN data which is longer than 8 bits. Then endian issues come in and it gets messy. I can write all those functions (and, in fact pretty much have in SavvyCAN) but I'd need to know what kind of stuff would be helpful to you and others.
 
Back
Top