From Friday, April 19th (11:00 PM CDT) through Saturday, April 20th (2:00 PM CDT), 2024, ni.com will undergo system upgrades that may result in temporary service interruption.

We appreciate your patience as we improve our online experience.

PXI

cancel
Showing results for 
Search instead for 
Did you mean: 

Requesting feedback and advice on modifications to the FIDL examples

Hello,

 

With the help of this forum, I've been learning about FlexRIOs, low-level FPGA programming, the higher-level FlexRIO Instrument Development Library, and general techniques for high-speed synchronization and acquisition.

 

I believe I'm now on the right track, and would like to ask for feedback/advice from someone who's experienced with FlexRIO (or general PXI FPGA) programming on what I've done. I modified Acq Engine on 5734 PXIe-7962R.lvproj:FPGA Top Generic PXIe.vi to let all 15 cards trigger a synchronized acquisition. I replaced the trigger detection mechanism, but left everything else untouched:

FIDL Mod - Many Trigger Cards.png

 

Brief background

Equipment list

  • Controller: PXIe-8135 (Windows 7)
  • Chassis: PXIe-1085
  • Input cards: PXIe-7962R FlexRIO base with NI-5734 digitizer (Total of 15 cards = 60 channels)

 

Requirements

  • The system continuously monitors 60 channels for events. (An "event" is when any one channel exceeds a user-defined threshold. Events are up to 30 minutes apart)
  • When an event is detected, data is acquired simultaneously from all 60 channels (200 μs pre-event, 300 μs post-event)
  • Data is sampled at 10 MHz

 

Explanation for code modifications

Idea

  • When a card detects an event, it fires the "Detection" trigger to the Master.
  • When the Master receives a "Detection" trigger, it fires the "Acquisition" trigger to all cards.
  • When a card receives the "Acquisition" trigger, it transfers data to the host.

 

Implementation

  • The FlexRIO cards are spread across 3 different PXI busses, so I use 3 "Detection" trigger lines.
  • I hijacked Acquisition Engine - FPGA.lvlib:acqEngineTriggerPoly.vi by feed my custom trigger into acq.Trigger Immediate.

 

Questions

  1. Is this a good way to do things? It works overall and the channels are all synchronized, but the additional trigger layer seemed to introduce a delay of ~17 ns (2 samples at 120 MHz, but I think it's negligible at 10 MHz)
  2. How can I decimate the data to 10 MHz? As a simple first step, I thought I'd put a case structure around everything in the timed loop, and run this case every 12 iterations. However, FIDL Synchronization v1.lvclass:Create.vi only goes down to 17 MHz.

 

Thanks in advance!

Certified LabVIEW Developer
0 Kudos
Message 1 of 4
(4,568 Views)

Seems fine. I've always just used a single trigger connected to the master, but what you've done to allow any of the slaves to notify the master that it needs to distribute a synchronized trigger to all the slaves should work fine.  Not sure what delay you are referring to though. It probably doesn't matter as long as all of the modules see the synchronized trigger at the same time since you can always just increase the number of pre-trigger samples you collect.  

 

Regarding decimation, I suppose you could just dump 11 of every 12 samples to decimate the data down to 10MS/s, but like Rob mentioned, you may get some nasty aliasing. I would look into using the decimation filter he mentioned.

0 Kudos
Message 2 of 4
(4,543 Views)

@David-A wrote:

Seems fine. I've always just used a single trigger connected to the master, but what you've done to allow any of the slaves to notify the master that it needs to distribute a synchronized trigger to all the slaves should work fine.  Not sure what delay you are referring to though. It probably doesn't matter as long as all of the modules see the synchronized trigger at the same time since you can always just increase the number of pre-trigger samples you collect.  

 


Thanks for confirming, David.

 

About the delay: With the default example, if I specify 50 pre-trigger samples, then on the host graph I see the y-threshold crossed at t=50. With my modifications, I see the y-threshold crossed at t=48.

 

But you're right. Since the shift is constant across all cards, all I need to do is read 2 extra pre-trigger samples to compensate -- not a problem.

 


@David-A wrote:

Regarding decimation, I suppose you could just dump 11 of every 12 samples to decimate the data down to 10MS/s, but like Rob mentioned, you may get some nasty aliasing. I would look into using the decimation filter he mentioned.


I understand the importance of a decimation filter.

 

To clarify my question: After filtering my signals, how do I get the FIDL multi-record system to pass downsampled data to the host?

 

I tried modifying Acquisition Engine - Facade.lvlib: Packer.vi to Enable every 12th sample:

FIDL Mod - Decimating Packer.png

 

Explanation

  • If AcqInProgress is FALSE, Counter is always 0.
  • If AcqInProgress is TRUE, Counter decrements from 11 to 0 cyclically.
  • Enable is TRUE if (AcqInProgress == TRUE and Counter == 0)

 

However, the data received by the host is corrupted. Below is from a 100 kHz sine wave input, sampled at 10 MHz. I asked for 100 pre-trigger and 200 post-trigger samples, which should give me 3 cycles. It looks like the wrong sections from the buffer are being read from:

Corrupted Graph.png

 

What did I do wrong?

Certified LabVIEW Developer
0 Kudos
Message 3 of 4
(4,533 Views)

The record state machine that is immediately upstream of the packer VI is responisble for counting the number of samples that you've acquired since the trigger was detected and notifying the VI's downstream of itself when the requested number of post trigger samples have been acquired. The record state machine assumes that a valid sample is acquired every tick. 

 

To use the method you've chosen to decimate the data, you would need to crack open acqEngineRecordStateMachine.vi and get it to count up in unison with the packer vi. 

 

recordstatemachine.PNG

 

0 Kudos
Message 4 of 4
(4,524 Views)