LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

What is the best way to read all CAN messages in the Rx CAN Queue

Hi,

 

I am a bit new to labview but have a strong embedded programming and CAN background. I am currently using a sbRIO9626 with embedded CAN. 

 

This is in an automotive application where there are many CAN messages coming in but there may not be a CAN message in the queue every 5ms. The main way I service CAN is in a timed loop that runs every 5ms. I have a CAN read in while loop nested within the timed loop where my intention is that the while loop will execute until all the messages in the CAN recieve queue have been processed. The way I know there are no messages left is by comparing the CAN frame from the CANRead.vi to an empty CAN frame, if it is true the while loop will exit. I initially wanted to do a for loop based off the current size of the CAN recieve queue but from what I could gather from the help documents I couldn't find a way to do this. 

 

My problem is arising when I have no CAN messages to process. After a short duration of using the profiling tool my largest impactors to total time is the CANStatusToError.vi which is a NI supplied VI. It seems like when there are no messages in the queue and I call the CAN read VI it is making a huge impact to my CPU utilization. 

 

 

Is there a less impactful method to process all the CAN messages in the recieve queue I created? Has anyone else tried a different approach and seen better results?

 

Thanks!

 

 

 

0 Kudos
Message 1 of 9
(3,421 Views)

What software are you working with (NI-CAN vs. NI-XNET, version of LabVIEW, OS, etc) and have you used the LabVIEW example finder?

0 Kudos
Message 2 of 9
(3,370 Views)

Hey George,

 

Versions are the following:

Labview 2014

NI-CAN 15.0

Now from what I can gather from the CAN library on my sbRIO is RIOEmbeddedCAN version 14.0.0

I've been told that the real time OS on sbRIOs is VxWorks, I can't find the version in NI MAX however. I believe they wrote the actual software for the CAN blocks (CANRead.vi, CANWrite.vi, etc.) 

 

I did try to pull up some Labview examples, they seem to be comparing the CAN frame payload array to an empty array after they call the read which is different then the functionality I get when there is nothing to read. In the case of no frame recieved I get a frame with a payload of length 8 with all bytes equal to zero. 

 

Hope that helps..

 

 

 

 

0 Kudos
Message 3 of 9
(3,321 Views)

Hi MCorona,

 

Here is a KB that walks through what operating system your device has:

 

http://digital.ni.com/public.nsf/allkb/35F1FD98520D6E0E8625783A005AF557

 

Additionally, here is a link to the NI-CAN Hardware and Software manual:

 

http://www.ni.com/pdf/manuals/370289k.pdf

 

The manual has documentation for all of the VIs available for use in LabVIEW in addition to equivalent C code in LabWindows CVI; it should be a pretty valuable resource for the future. If you are using the Frame API, it looks like you can use the ncGetAttr.vi  to get the number of frames available in the read queue. Documentation about the ncGetAttr.vi is found on page 10-43 and information about Read Entries Pending can be found on 10-45. What examples were you looking at

0 Kudos
Message 4 of 9
(3,288 Views)

@KingPGeorge wrote:

If you are using the Frame API, it looks like you can use the ncGetAttr.vi  to get the number of frames available in the read queue. Documentation about the ncGetAttr.vi is found on page 10-43 and information about Read Entries Pending can be found on 10-45. What examples were you looking at


Well, that's pretty useless, since the poster was clear that they're using the NI Embedded CAN for RIO, which doesn't support the functions you mentioned.

 

MCorona - I haven't used the Embedded CAN for RIO recently, and I don't remember running into performance problems, but here's one possible alternate approach. Move reading from the CAN module into a separate loop, with a timeout of -1 (wait until a new CAN packet arrives, no timeout). When a packet arrives, put it into a standard LabVIEW queue or an RT-FIFO. Then your existing loop can pull out of that queue instead.

0 Kudos
Message 5 of 9
(3,276 Views)

Hi nathand,

 

Thanks for your reply it has been helpful. Doing that allows me to eliminate processing that status to error vi and I see a huge drop in CPU utilization since it is just sitting in the read the whole time and not processing the error. I also thought this might starve out other aspects of the CAN hardware and it seems to not bother it as long as it isn't within the same timed loop.

 

The only issue with this approach for me has been that whenever I hit the abort button the program never really stops running since it is too busy waiting in the CANRead.vi for a message to come in. Since one never comes in i'm forced to disconnect power from the module and reconnect each time I want to try something new. Any suggestions for a hard abort on that call? My loop stop condition will also not stop the program.

0 Kudos
Message 6 of 9
(3,238 Views)

I'm surprised that the Abort button (on the toolbar) won't stop the CANRead; usually that kills everything.

 

Try forking the CAN Interface wire, and when you want to abort the read, close the interface in a separate loop. I don't know if this will work, but it's worth a try. That's the standard technique for killing other tasks that wait forever (for example, a TCP Read with a timeout of -1).

0 Kudos
Message 7 of 9
(3,231 Views)

After a few different fork locations for the CAN interface it is terminating when I hit the abort button on the toolbar. Thanks for the help nathand.

 

It still is strange how that status to error vi is taking so long though.. It would be nice to not worry about the execution times of the CAN api blocks.

 

Now it's time to test the recieve when we do have valid messages coming in. 

0 Kudos
Message 8 of 9
(3,207 Views)

@MCorona wrote:

After a few different fork locations for the CAN interface it is terminating when I hit the abort button on the toolbar. Thanks for the help nathand.


I don't understand what you're saying here - forking the wire shouldn't matter if you're using the Abort button on the toolbar. I was trying to suggest that if you want to avoid using that Abort button, try closing the CAN interface somewhere else in your code (for example after the loop that reads from the queue terminates); if the embedded CAN VIs work like other LabVIEW functions, closing the reference will cause the CANRead to stop waiting.

0 Kudos
Message 9 of 9
(3,193 Views)