I am new to LabVIEW and NI products and I'm trying to accomplish the following (I expected this to be simple to do!):
I have a bunch of CAN devices (let's say 12 of them) and I'd like to periodically read data from them. To do so, I write a certain frame (as specified in one of the device's datasheets) to set them all in operational mode. I only need to this once. To read data, I have to write a frame requesting the data and then read the frame I receive, and extract its payload. I set the bus speed to the maximum possible which is 1 Mbit/sec. I think each frame has around 109 bits max (based on the datasheet too), so my expectation is that 250 microsecond is more than enough for one request and receive operation.
Since I am using cRIO9022 (cRIO-9114 chassis) and a NI 9853 CAN module, I was not able to run in scan mode, which seems to be easier to do from the tutorials I saw. I had to run in FPGA mode, and so I used the section 5 in the following tutorial: http://www.ni.com/tutorial/11198/en/ combined with code from "CAN Basic (FPGA).vi" example code to come up with something. I have no problem sending and receiving the frames I want and extracting data, but I'm having trouble writing data to a file using a fixed sample rate and in real-time.
I have two files, the first runs on the FPGA target. It continuously runs, requesting data from the 12 elements, extracting data from the received frames and writing that to a FIFO once I read from all 12 devices. What I'm trying to do in my code is to only spend 250 microseconds to do a request/read operation. I don't know if I implemented correctly, and I'm not sure if the hardware is actually reading every 250 microseconds although I expect it to. I'm not sure how to debug that either.
The second program runs the FPGA target program and sets the send/receive period for it. It's supposed to record data for a set recording time and write it to a tdms file. It somewhat works but what's happening is that the data is not actually always real-time. If I set the frame send/receive period to 250us, it records for a longer time (probably another timing issue in my code). If I set it to 800 us, it seems to match real time as expected. If I set it to more, it records for a shorter amount of time. I tried recording the time elapsed and things don't seem to be timed as I expect.
I attached the code, I think it's simple and has enough comments. It has the project file and VIs. I included the CANOpen communication datasheet for the device(s) I'm reading from. I also included a sample log file. Rows 2 to 12505 are the data measurements and the remaining ones are "timestamps" (taken based on write-to-file time) for 12 measurements.
Please let me know if anything need clarification. I need help resolving my timing issues, or if you can recommend any easy way to do this. I can't be the first one trying to periodically extract and log payload from a CANBus!
Your help is appreciated!
I just had a look at your post and found it interesting since I would like to perform some measurement data logging and also log-file management for a test-system with an sbRIO-9651 (SoM)
I'm not quite done developing the general software architecture for the Hardware yet but found this interesting whitepaper
It might be helpfull even if it does not solve your problem...
Maybe this tutorial also helps.
Unfortunately I'm out of office for the next 3 weeks but hope the community can contribute something more promissing.
If I come up with a solution after my vacation I'll let you know!