LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Advice on making my project more efficient

Somehow I wrote "myRIO" in my last post, no idea where that came from. Meant CompatRIO of course (cannot edit it anymore).

 


@mrtea wrote:

The latest snippet of code I attached most recently is a smaller section of the host code where I am trying to generate an analogue signal to  then send to analogue output module (NI 9263). [..] The problem is that when trying to plot one cycle of a 100Hz signal (this being an arbitrary frequency with an easy to see time period) at the 40Mhz clock (setting the analogue frequency control to 100 and the Sampling frequency control to 40,000,000) , I was getting a time period of ~1.7seconds which is obviously incorrect.

 

Is there any specific reason you are doing this on the FPGA? It's possible, but you have to re-invent the wheel doing it. Had you considered using a DAQmx task for this? You can simply set it to 100Hz and send data to it - done: 

 

If you have a reason to do it through the FPGA, there are two steps that can help you:

  • Use a derived clock to go down from 40 MHz to some kHz (haven't checked what divider is possible with your hardware). See Creating FPGA-Derived Clocks (FPGA Module).
  • Look at the example LabVIEW»Help»Find Examples»Toolkits and Modules»FPGA»CompactRIO»Fundamentals»Clocks and Timing»Loop Timer»Loop Time.lvproj for a proper loop timing method.
  • Have a look at the FPGA code of LabVIEW»Help»Find Examples»Toolkits and Modules»myRIO»Customized FPGA Signal Generator.lvproj (code for your cRIO's FPGA will be similar/the same). This VI has a timed loop, generating a waveform and sending it to the Real-Time host via FIFO. You should be able to turn the second part around: Read the next sample from the host, then output it.

 

- Analogue Output Module (NI 9263) clock 100kS/second/channel

So just these in combination will limit my sample rate to 100kHz? where Hz is samples per second just to be 100%  


Yes, that's correct. 100kS/second is what the digital-analog-converters (DAC) of the 9263 are made for. There is one DAC per channel, so you can output 100kS/second/channel.

 

 

Is this all a matter of trying to match the sampling frequency of the wave I am creating to the sampling rate of the Rio then... Is there a way to accurately find what the actual sample rate is so I might be able to match it, or am I very misguided here?

 


No, that is absolutely possible. Just the way round: You define the output's sample rate in your code, and then you also know what sample rate your waveform needs.

 


Ingo – LabVIEW 2013, 2014, 2015, 2016, 2017, 2018, NXG 2.0, 2.1, 3.0
CLADMSD
0 Kudos
Message 11 of 28
(1,160 Views)

I had not noticed this before respectively it was not in your code except in the first posted example: How do you transfer the data from the host to the FPGA?

The current method of Writing to a FPGA Frontpanel Control does not make much sense, as this way the output rate is fully controlled via the VI running on the host. Your FPGA code is nothing more than a re-invention of "scan-mode" in this case. HAd you seen the FIFO that I mentioned before? That's a way to go. See this table: Understanding Communication Options Between the Windows HMI, RT Processor, and FPGA - Summary of Com....

 

Note, all of this does apply only if you don't use a DAQmx task instead.


Ingo – LabVIEW 2013, 2014, 2015, 2016, 2017, 2018, NXG 2.0, 2.1, 3.0
CLADMSD
0 Kudos
Message 12 of 28
(1,158 Views)

Sorry for the delay, I've been pretty caught up in other work lately.

What I have done for the moment is implement a tick count to find the rate at which the current demand loop is able to iterate at.

This is then read on the host side,  and a constant loop time set which reflects the sampling rate I want.

See picture (FPGA side). It works for the time being and can achieve 250kHz comfortably (although I can hit 333kHz as a maximum, but haven't tested it thoroughly enough as of yet.

0 Kudos
Message 13 of 28
(1,143 Views)

I am also currently exploring how to use FIFOs to transfer data between host and fpga.

Are there any tutorials or examples I can refer to about this?

 

I've been able to find this loose example for the time being but am still unsure how his example completely works.

https://forums.ni.com/t5/Example-Programs/Use-DMA-FIFOs-to-send-data-to-and-from-an-FPGA-target/ta-p...

 

0 Kudos
Message 14 of 28
(1,141 Views)

Ok, do FIFOs and using front panel controls to send data work basically the same way?

In the sense that when you use a FIFO, you need to:

  • set up an Invoke node on the Host side
  • write the array (on the HOST side) to this invoke node that you've set up which relates to a 'Host to Target' FIFO I had set up in my project
  • then 'call' the data that is in this 'FIFO' using a 'FIFO Node' on the FPGA side of the code which writes to the module pin that I want

Instead of having to send this data one element at a time to a control on the FPGA from the Host side which creates a 'weird' dependency between the Host write and FPGA read loops?

Using a FIFO gets rid of this dependency because you are creating a middle man of sorts to hold the data till the other loop is ready?

 

Have I understood it sort of correctly?

And then if this is correct,

  • I can create an array of a set size in my HOST dependant on the sampling rate and analogue frequency I want for my generated signal.
  • Send this to the FIFO middle man
  • Then read this FIFO on the FPGA side making sure to set the speed of my loop to the sampling rate I used to generate my signal on the Host side?

I have noticed when I set up my FIFO on my FPGA Target that there is a box asking for the 'requested number of elements' which is set to 1029. If I have a sample rate of 200kHz for example, I will have 200k elements in an array for just one cycle. This could then be even more samples as I will be concatenating multiple waves together. Is there a way to set this requested number of elements to the exact number of elements I generate and plan to send to the FPGA from my Host?Capture.PNG

Increasing this number (1029) I get the following messages:

  • (1 of 2) If you experience timeouts during DMA transfers from the FPGA to a host, use the FIFO. Configure method of the Invoke Method function and increase the Depth parameter rather than increasing the Requested Number of Elements. Increasing the Depth parameter increases the size of the host-side buffer, which is more likely to resolve the timeout and does not increase FPGA device utilization.
  • (2 of 2) The number of elements has been coerced to a valid value for a DMA FIFO.

 

Where then my questions then becomes :

  • is setting the depth what I am after?
  • what is this coerced value? will this be an issue when setting the depth?

Thanks for any help. I know this might have been a bit more of a rambling post.

0 Kudos
Message 15 of 28
(1,133 Views)

pp

0 Kudos
Message 16 of 28
(1,136 Views)

Hello mrtea,

Yes, your understanding of FIFO is correct! Sending elements one by one (without FIFO), you have this cramped dependency. Think of two persons, passing items from person A to person B. Person A needs to hold the item in his hand and then wait until person B picks it up. This "handshake" is only as fast as the slowest person, per each item!

With a FIFO, there is a bucket between them. Person A can throw items into it whenever he wants, and Person B can pick them out anytime. No dependency between A and B anymore, except:

  • If A is faster than B for a longer period, the bucket will spill ("buffer overflow").
  • If A is too slow, B will empty the bucket and then have to wait. This is only problematic, if B needs items "now", like in your case of live-output ("buffer underun").

So why is a FIFO good? The reason is the different structure and capabilities of your host PC vs. your FPGA: Your host PC is not deterministic, meaning sometimes there will be delays in your code (simply said: your operating system will pause your application every now and then to do other things). Because of this, your PC is not able to send out elements one by one at a stable rate. However, your PC is good at moving big chunks of data at the same time.

Your FPGA on the other hand is deterministic: It executes at a steady rate and is good at picking the elements one by one.

So a typical FIFO system looks like this: Person A drops a stack of many elements into the bucket every two seconds or so, and you FPFA picks them our one by one at a high rate. The overall rate of them shall be the same. So to say 1000 every second for the PC, and 1 every ms for the FPGA.

 

I have noticed when I set up my FIFO on my FPGA Target that there is a box asking for the 'requested number of elements' which is set to 1029. If I have a sample rate of 200kHz for example, I will have 200k elements in an array for just one cycle. This could then be even more samples as I will be concatenating multiple waves together. Is there a way to set this requested number of elements to the exact number of elements I generate and plan to send to the FPGA from my Host?


Depends. So far I thought your application would be running continuously, therefore you needed to transfer data to the FPGA all the time. Did I misinterpret this? Is it more like you define the complete waveform once, transfer it to the FPGA, and then "play" it only once? The first case would be a bit like "streaming a movie", the latter like "recording a cassette tape on a recorder, then pressing play once on the FPGA".

The FIFO concept works in both times, the only difference is that in the "streaming" case, you need to push new data to the FPGA fast enough - that's where the bucket empty (buffer underrun) thought in my first paragraph came from. Generally, you should set your FIFO to a number of elements that your PC's jitter (small delays in loops due to external factors) doesn't affect your FPGA anymore. Two seconds or more (400k elements in your case) should do.

 

There is also another method to transfer bigger chunks of data, called Host Memory Buffer (HMB), to use e.g. when there is not enough memory for a FIFO. In case size (or latency) is an issue, see the diagram in chapter 6 or Host Memory Buffer Overview.

 

Also, you might have to reconsider the structure of your application. If I understand you correctly, you have one part of your program running on your PC ("HMI"), and one on the FPGA. However, your cRIO has the Real-Time host OS ("RT") in the middle, which you might benefit from. Why? Because the HMI (and the Ethernet connection to the cRIO) is no deterministic at all, the RT is almost deterministic, and the FPGA is deterministic. For all possible data transfer options, see table 2 (chapter 4) in: Understanding Communication Options Between the Windows HMI, RT Processor, and FPGA

 

More good links:

 

 

Increasing this number (1029) I get the following messages:

  • (1 of 2) If you experience timeouts during DMA transfers from the FPGA to a host, use the FIFO. Configure method of the Invoke Method function and increase the Depth parameter rather than increasing the Requested Number of Elements. Increasing the Depth parameter increases the size of the host-side buffer, which is more likely to resolve the timeout and does not increase FPGA device utilization.
  • (2 of 2) The number of elements has been coerced to a valid value for a DMA FIFO.

 

Where then my questions then becomes :

  • is setting the depth what I am after?
  • what is this coerced value? will this be an issue when setting the depth?

The explanation here is that setting up the DMA FIFO between the PC and the FPGA, you indeed have two buffers (see How DMA Transfers Work (FPGA Module)). One is on the FPGA, which is the "Requested Number of Elements" big. On the PC, you have a bigger one, which is called Depth. If you don't specify a value here using FIFO.Configure (Invoke Method), LabVIEW uses 10k or 2x Number of Elements, whatever is greater. Due to possible jitter on the host PC, this might not be big enough, then increasing it gives the PC more time to fill it again, if it was almost empty.

About the coerced value: An FPGA chip is organized in blocks. A block will have only one type of "code" inside. If a block has FIFO in it, it makes sense to fill the block completely with FIFO, and leaving parts unused. This is why your configuration window often coerces the value to a slightly bigger one.


Ingo – LabVIEW 2013, 2014, 2015, 2016, 2017, 2018, NXG 2.0, 2.1, 3.0
CLADMSD
0 Kudos
Message 17 of 28
(1,113 Views)

I forgot one useful link: Best Practices for DMA Applications (FPGA Module)

 

mrtea, your application has sophisticated needs. Your requirements contain a deterministic code on an embedded system, with data transfer between domains. When programming this for the first time, there are of course a lot of question. Don't worry^^ I am wondering if you/your company/your university has access e.g. to the NI online courses. Is there any chance? I am asking because the "LabVIEW FPGA" course would be a benefit for you. Or "Embedded Control and Monitoring Using LabVIEW".

 

Also, for my understanding:

  • Is your goal to prepare a waveform and then "play" it once on the target?
  • Or do you want to continuously output a waveform?
  • If so, will it be a repeating pattern, or generated in real-time depending on some input?

Ingo – LabVIEW 2013, 2014, 2015, 2016, 2017, 2018, NXG 2.0, 2.1, 3.0
CLADMSD
Message 18 of 28
(1,111 Views)

Hi thanks for the response,

No, I dont have access to those online courses unfortunately. 

The goal is to prepare a waveform and then send it once to the target as you said. But then to have the possibility to prepare another possibly completely different waveform to then send it to the target. 

0 Kudos
Message 19 of 28
(1,105 Views)

 

I've been looking at possibly setting the depth of the FIFO before I send the array from my Host. And then handling (somehow, not sure yet ^^') the possible extra elements that there might be because of the effect of the coerced value in the FPGA side of the program.

I'll get through those links you sent me and give an update. 

Cheers again

0 Kudos
Message 20 of 28
(1,102 Views)