M-series counter interrupts/dma
I'm trying to get the counters on an m-series board (6281) to generate interrupts, so I can do buffered event counting. As a test, when I turn on terminal count interrupts, then make the counter count down to zero, no interrupt is generated. It is disarming when it hits the TC (I have it configured to stop counting and disarm on TC) but no interrupt. I have the TC interrupt enabled in the interrupt A enable register (i'm using counter 0), and I am able to generate TC interrupts using an e-series board. I've noticed the m-series has some additional bits in the Gi_DMA_Config register and I've played with them but to no effect.
Is there any extra magic to make counter interrupts work on m-series boards? Is there any example code of buffered counting using m-series boards (there's none in the m-series ddk, although there is for the 660x boards in the 660x ddk)? Ultimately, I'd like to get buffered counting working with DMA, but for now I'd just like to get it to generate an interrupt.
Hi fmhess-
I created an example recently for DMA-based buffered period measurement. It's attached as gpctex6.cpp and should be a good starting point (along with gpctex1.cpp from the M Series MHDDK) to get buffered edge counting with DMA working. This should give considerably better performance than interrupt-based transfers; will DMA-based transfers (using the MHDDK's DMA library) work for your app?
Thanks-
Tom W
National Instruments
Attachments:
gpctex6.cpp 12 KB
Similar Messages
-
M Series Counter TC interruption and Gi_Status_1 register
Hello everyone
Q1: About the G0_Status1 register
Everytime I get TC interruption from a board, checking the G0_Status_1 register.
And I could find bit 12 is always TRUE and it is even when TC doesn't hit to 0.
The 660x RLP Manual says the bit 15 is G0 Interrupt and bit 3 is TC interrupt and
I'm sure it working correct. But I don't know why the bit 12 is always TRUE.
Could anyone tell me what the bit 12 is?
Q2: About TC interruption
Also, I could make the TC interrupt count down direction and when it hits to 0.
If there is some configuration the direction inverted, I would like to know how to
do it. I mean it is something like that the Counter0 counts up and when it hits to
specified value, TC interrupt occurs.
Thanks in advance
AshHi fmhess-
I created an example recently for DMA-based buffered period measurement. It's attached as gpctex6.cpp and should be a good starting point (along with gpctex1.cpp from the M Series MHDDK) to get buffered edge counting with DMA working. This should give considerably better performance than interrupt-based transfers; will DMA-based transfers (using the MHDDK's DMA library) work for your app?
Thanks-
Tom W
National Instruments
Attachments:
gpctex6.cpp 12 KB -
M-Series Buffered Event Counting with DMA -- gating problem
Hi --
I am implementing DMA-based buffered event counting on a PCIe-6259 board. I use G0_Out as the gate for G1, which counts events on a PFI pin. So by setting the speed of G0, I get an event count (either cumulative or non-cumulative) on a periodic basis, which is directly DMA'd to my buffer, and synchronized with other i/o operations.
This is working well right now, except for one problem, which is that the I only get data if there is at least one source edge between gates. i.e. if there are no edges, nothing gets pumped to the dma buffer.
I am guessing that a stale data error is somehow choking off the DMA transfer from the counter. Is that possible?
Is there some magic that I need to do to avoid this, because for this application, especially if I am counting cumulatively, I don't care about a missing edge, but I do care if the dma transfers get out of phase with the rest of my timing.
Thanks in advance for any help!
--spg
Here is a snippet of the code that sets up the event counting on G1, partly based on gpctex6.cpp:
const int sDMASelect[] = {1,2,4,8,3,5};
// source: pfi, or -1 for 20Khz clock
void eventTimerSetup(tMSeries *board, tTIO *tio, int dmaChannel, bool cumulative, int source)
int sourceSelect = (source==-1) ? 0 : (source+1);
//MSeries.CTR.Source
tio->G1_Input_Select.setG1_Source_Select(sourceSelect); // (pfi+1) or 20Khz=0
tio->G1_Input_Select.setG1_Source_Polarity(0); //rising=0
tio->G1_Input_Select.setG1_OR_Gate(0);
tio->G1_Input_Select.flush();
//MSeries.CTR.Gate
tio->G1_Input_Select.setG1_Gate_Select(20); //the G_OUT signal from other clock=20
tio->G1_Input_Select.setG1_Output_Polarity(0); //active high=0
tio->G1_Input_Select.flush();
//MSeries.CTR.IncrementRegisters
tio->G1_AutoIncrement.writeRegister(0);
//MSeries.CTR.InitialCountRegisters
tio->G1_Mode.writeG1_Load_Source_Select(tTIO::tG1_Mode::kG1_Load_Source_SelectLoad_A);
tio->G1_Load_A.writeRegister(0);
tio->G1_Command.writeG1_Load(1);
tio->G1_Load_B.writeRegister(0);
tio->G1_Load_A.writeRegister(0);
tio->G1_Command.setG1_Bank_Switch_Enable(tTIO::tG1_Command::kG1_Bank_Switch_EnableBank_X);
tio->G1_Command.setG1_Bank_Switch_Mode(tTIO::tG1_Command::kG1_Bank_Switch_ModeGate);
tio->G1_Command.flush();
//MSeries.CTR.ApplicationRegisters
tio->G1_Input_Select.setG1_Gate_Select_Load_Source(0);
tio->G1_Mode.setG1_Reload_Source_Switching(tTIO::tG1_Mode::kG1_Reload_Source_SwitchingAlternate);
tio->G1_Mode.setG1_Loading_On_Gate(cumulative ? tTIO::tG1_Mode::kG1_Loading_On_GateNo_Reload : tTIO::tG1_Mode::kG1_Loading_On_GateReload_On_Stop_Gate);
tio->G1_Mode.setG1_Loading_On_TC(tTIO::tG1_Mode::kG1_Loading_On_TCRollover_On_TC);
tio->G1_Mode.setG1_Gating_Mode (tTIO::tG1_Mode::kG1_Gating_ModeEdge_Gating_Active_High);
tio->G1_Mode.setG1_Gate_On_Both_Edges (tTIO::tG1_Mode::kG1_Gate_On_Both_EdgesBoth_Edges_Disabled);
tio->G1_Mode.setG1_Trigger_Mode_For_Edge_Gate(tTIO::tG1_Mode::kG1_Trigger_Mode_For_Edge_GateGate_Does_Not_Stop);
tio->G1_Mode.setG1_Stop_Mode(tTIO::tG1_Mode::kG1_Stop_ModeStop_On_Gate);
tio->G1_Mode.setG1_Counting_Once(tTIO::tG1_Mode::kG1_Counting_OnceNo_HW_Disarm);
tio->G1_Second_Gate.setG1_Second_Gate_Gating_Mode(0);
tio->G1_Input_Select.flush();
tio->G1_Mode.flush();
tio->G1_Second_Gate.flush();
//MSeries.CTR.UpDown.Registers
tio->G1_Command.writeG1_Up_Down(tTIO::tG1_Command::kG1_Up_DownSoftware_Up); //kG1_Up_DownSoftware_Down
//MSeries.CTR.OutputRegisters
tio->G1_Mode.writeG1_Output_Mode(tTIO::tG1_Mode::kG1_Output_ModePulse);
tio->G1_Input_Select.writeG1_Output_Polarity(0);
//MSeries.CTR.BufferEnable
board->G1_DMA_Config.writeG1_DMA_Reset(1);
board->G1_DMA_Config.setG1_DMA_Write(0);
board->G1_DMA_Config.setG1_DMA_Int_Enable(0);
board->G1_DMA_Config.setG1_DMA_Enable(1);
board->G1_DMA_Config.flush();
tio->G1_Counting_Mode.setG1_Encoder_Counting_Mode(0);
tio->G1_Counting_Mode.setG1_Alternate_Synchronization(0);
tio->G1_Counting_Mode.flush();
//MSeries.CTR.EnableOutput
//board->Analog_Trigger_Etc.setGPFO_1_Output_Enable(tMSeries::tAnalog_Trigger_Etc::kGPFO_1_Output_EnableOutput);
//board->Analog_Trigger_Etc.setGPFO_1_Output_Select(tMSeries::tAnalog_Trigger_Etc::kGPFO_1_Output_SelectG_OUT);
//board->Analog_Trigger_Etc.flush();
//MSeries.CTR.StartTriggerRegisters
tio->G1_MSeries_Counting_Mode.writeG1_MSeries_HW_Arm_Enable(0);
board->G0_G1_Select.writeG1_DMA_Select(sDMASelect[dmaChannel]);
tio->G1_Command.writeG1_Arm(1); // arm it
Scott Gillespie
http://www.appliedbrain.com
scott gillespie
applied brain, inc.
Solved!
Go to Solution.Okay, I have it working now. In addition to your suggested changes, I had to remove the following line:
tio->G1_MSeries_Counting_Mode.writeG1_MSeries_HW_Arm_Enable(0);
It appears that writing something to MSeries_Counting_Mode causes that register to supersede the Counting_Mode register. Is that right?
So code that now works for me is listed below.
thanks Tom!
-spg
void eventCounterSetup(tMSeries *board, tTIO *tio, int dmaChannel, bool cumulative, int source) // pfi, or -1 for 20Khz clock
int sourceSelect = (source==-1) ? 0 : (source+1);
//MSeries.CTR.Source
tio->G1_Input_Select.setG1_Source_Select(sourceSelect); // (pfi+1) or 20Khz=0
tio->G1_Input_Select.setG1_Source_Polarity(0); //rising=0
tio->G1_Input_Select.setG1_OR_Gate(0);
tio->G1_Input_Select.flush();
//MSeries.CTR.Gate
tio->G1_Input_Select.setG1_Gate_Select(20); //the G_OUT signal from other clock=20
tio->G1_Input_Select.setG1_Output_Polarity(0); //active high=0
tio->G1_Input_Select.flush();
//MSeries.CTR.IncrementRegisters
tio->G1_AutoIncrement.writeRegister(0);
//MSeries.CTR.InitialCountRegisters
tio->G1_Mode.writeG1_Load_Source_Select(tTIO::tG1_Mode::kG1_Load_Source_SelectLoad_A);
tio->G1_Load_A.writeRegister(0);
tio->G1_Command.writeG1_Load(1);
tio->G1_Load_B.writeRegister(0);
tio->G1_Load_A.writeRegister(0);
tio->G1_Command.setG1_Bank_Switch_Enable(tTIO::tG1_Command::kG1_Bank_Switch_EnableBank_X);
tio->G1_Command.setG1_Bank_Switch_Mode(tTIO::tG1_Command::kG1_Bank_Switch_ModeGate);
tio->G1_Command.flush();
//MSeries.CTR.ApplicationRegisters
tio->G1_Input_Select.setG1_Gate_Select_Load_Source(0);
tio->G1_Mode.setG1_Reload_Source_Switching(tTIO::tG1_Mode::kG1_Reload_Source_SwitchingAlternate);
tio->G1_Mode.setG1_Loading_On_Gate(cumulative ? tTIO::tG1_Mode::kG1_Loading_On_GateNo_Reload : tTIO::tG1_Mode::kG1_Loading_On_GateReload_On_Stop_Gate);
tio->G1_Mode.setG1_Loading_On_TC(tTIO::tG1_Mode::kG1_Loading_On_TCRollover_On_TC);
tio->G1_Mode.setG1_Gating_Mode (tTIO::tG1_Mode::kG1_Gating_ModeEdge_Gating_Active_High);
tio->G1_Mode.setG1_Gate_On_Both_Edges (tTIO::tG1_Mode::kG1_Gate_On_Both_EdgesBoth_Edges_Disabled);
tio->G1_Mode.setG1_Trigger_Mode_For_Edge_Gate(tTIO::tG1_Mode::kG1_Trigger_Mode_For_Edge_GateGate_Does_Not_Stop);
tio->G1_Mode.setG1_Stop_Mode(tTIO::tG1_Mode::kG1_Stop_ModeStop_On_Gate);
tio->G1_Mode.setG1_Counting_Once(tTIO::tG1_Mode::kG1_Counting_OnceNo_HW_Disarm);
tio->G1_Second_Gate.setG1_Second_Gate_Gating_Mode(0);
tio->G1_Input_Select.flush();
tio->G1_Mode.flush();
tio->G1_Second_Gate.flush();
//MSeries.CTR.UpDown.Registers
tio->G1_Command.writeG1_Up_Down(tTIO::tG1_Command::kG1_Up_DownSoftware_Up); //kG1_Up_DownSoftware_Down
//MSeries.CTR.OutputRegisters
tio->G1_Mode.writeG1_Output_Mode(tTIO::tG1_Mode::kG1_Output_ModePulse);
tio->G1_Input_Select.writeG1_Output_Polarity(0);
//MSeries.CTR.BufferEnable
board->G1_DMA_Config.writeG1_DMA_Reset(1);
board->G1_DMA_Config.setG1_DMA_Write(0);
board->G1_DMA_Config.setG1_DMA_Int_Enable(0);
board->G1_DMA_Config.setG1_DMA_Enable(1);
board->G1_DMA_Config.flush();
// from Tom:
// The "magic" you need is referred to as synchronous counting mode (or Duplicate Count Prevention in NI-DAQmx).
// Try setting G1_Encoder_Counting_Mode to 6 (synchronous source mode) and G1_Alternate_Synchronization to 1 (enabled).
tio->G1_Counting_Mode.setG1_Encoder_Counting_Mode(6); // 0
tio->G1_Counting_Mode.setG1_Alternate_Synchronization(1); // 0
tio->G1_Counting_Mode.flush();
board->G0_G1_Select.writeG1_DMA_Select(sDMASelect[dmaChannel]);
tio->G1_Command.writeG1_Arm(1); // arm it
scott gillespie
applied brain, inc. -
How to count interrupts of a specific driver / HW
I am using Perfmon to get #interrupts/sec.
I can also drill down to single core resolution (e.g. core0, 1, 2, 3 in a 4 core CPU)
This is good, but i would like to get interrupts/sec for a specific source (e.g. network interface card) or all interrupts handled by a specific driver.
Couldn't find this capability in Perfmon.
does anyone have an idea?
Thanks,
AmiNo version of Reader offers word counting or word auditing.
-
PCI-6229 M-Series (count 3 encoders)
Hello,
I only have one DAQ board (PCI-6229 M-Series) and as I know, the board have two counters:
Ctr0 which uses PFI8 and PFI10 - now using that to count outputs from my first encoder
Ctr1 which uses PFI3 and PFI11 - for my second encoder
But I have 3 encoders, can I use other PFI pins on the DAQ board to count the outputs coming from my third encoder? Is it possible with just one DAQ board? Did I miss any example code which tell me how to do this?
Thanks alot.
KennethHi
Try the link below
http://sine.ni.com/apps/we/niepd_web_display.display_epd4?p_guid=F0F64AEE06C0010CE0340003BA7CCD71&p_...
for using a counter as the DIO clock for M Series boards.
Requirements= LabVIEW 7.1
NI DAQ MX 7.3
I hope this example helps!
Kind Regards,
Kurt
Attachments:
Using_a_Counter_as_the_DIO_clock_for_M_Series.vi 84 KB -
Hi, evry!
The task is to measure time interval (around 10 ms) between rising edges of two different digital lines.
How can this be done using 6052E card?
Thanks in advance!
Solved!
Go to Solution.
Attachments:
Interval.png 7 KBHi JungleBoy,
Please take a look at this example from the Example Finder: Meas Two Edge Separation. You can use the Gate and Source of a single counter to measure the time between a rising (or falling) edge of a signal with respect to the falling (or rising) edge of another one. This example can be found in Help » Find Examples » Hardware Input and Output » DAQmx » Counter measurements » Two-Signal Edge-Separation.
Regards,
Daniel REDS
RF Systems Engineer
Help us grow.
If a post solves your question, mark it as The Solution.
If a post helps, give Kudos to it. -
X Series DDK: Configure Interrupt on DMA Channel's total transfer count
Hello,
In the DAQ-STC3 X Series DDK Reference Manual, Chapter 1: Theroy of Operation, Section Interrupts, Subsection Special Considerations: Maximizing Throughput in Low-Latency Situations (p41), it is said:
"for X Series devices, the CHInCh can interrupt on the DMA channel’s total transfer count, which occurs once the data has been completely transferred to the host memory. The order of programming for this situation (and output operations) is as follows:
1. Program the DMA channel’s Total_Transfer_Count_Compare_Register (CHTTCCR) with the number of Bytes in a single input/output sample.
2. Set the DMA channel’s Notify on Total Count flag in the CHCR.
3. Set the DMA channel’s Arm Total Count Interrupt flag in the CHOR.
4. Start data transfer (through the DMA controller and the subsystem’s Stream Circuit).
5. Receive total transfer count interrupt.
6. Increase the CHTTCCR by the number of Bytes in a single input/output sample.
7. Re-arm the total transfer count interrupt in the CHOR.
Using the X Series DDK, I don't manage to perform such a configuration.
Can you please provide me code sample to do so ?
Thanks in advance for your support.
Sincerely
BertrandHello Steve,
Weeks ago, we developed a Linux application that configure NI acquisition board (serie X) to send an interrupt when FIFO count reach a given number. At this stage we manage to prove that our board configuration was good and that the problem was due to INtime. TenAsys (INtime developers) fix this issue few weeks ago.
We just come back from holidays, apply the modifications created by TenAsys and manage to get interrupt inside INtime.
We still have two problems.
Reading DMA
===========
From the interrupt handler, when we access to the DMA to get samples stored in the FIFO, we manage to get the samples inside the first interrupt handler. With the following interrupts, when accessing DMA with the tCHInChDMAChannel structure, it said that there is no available bytes. But when we read the Channel_Total_Transfer_Count_Status_Register from the DMA channel, we see that we have the desired numbers of samples.
In the interrupt handler, during the interrupt aknowledgement, instead of only reading the Volatile_Interrupt_Status_Register to ackowledge the interrupt, if I increase the Channel_Total_Transfer_Count_Compare_Register_LSW by a given number (X) then I got X samples to read in the following interrupt. Problem with this solution is that the delay between two interrupts is not constant.
It seems that we mis-configured the DMA channel. But don't manage to find the error.
Two interrupts generated
====================
Moreover, we always get 2 FIFO_Count interrupts. Even configuring conversion, sampling and interrupt frequencies at very low value (conversion 1KHz, sampling 1Hz, interrupt generation: 1Hz). The delay between the two interrupts is about few nano seconds.
Source code
============
I attach to this post the source code we use to play/test this configuration. There is a Visual Studio workspace that we used to play with INtime and a CMake configuration file that we used to manage our Linux tests. You can find all the informations you need to build the binary in the README file.
Thanks in advance for your help with these issues.
Sincerely
Bertrand Cachet
Attachments:
IOMonitoring.zip 355 KB -
I can't find anything directly related to what I'm hoping to do, so I'm back to ask more questions.
I'm running a hardware timed analog input acquisition (80 kHz currently) using dma transfers, on-demand analog output, and on-demand DIO on an M-series PCI-622x. I'm exploring the possibility of using a counter to send an interrupt every 200 ms using an internal signal as the counter source. I found this forum post, which looks like it is a least a good source of information about the counter registers. I haven't found much else on internal routing, setting up a continuous digital output task to feed back to the counter (if I have to go with a round about way to do this), etc, but as you can see I'm really stabbing in the dark.
I'm hoping I can set the counter up in a trivial setup that counts like crazy to a specified number, triggers an interrupt, resets the counter, and automatically begins counting again repeating the process. Any enlightenment people can provide to the possibility of this or even round about ways of accomplishing a similar task would be greatly appreciated.
AaronHi Aaron-
I'm a bit unclear on exactly what you're trying to accomplish. Is the "interrupt" you're trying to generate just a pulse to be generated out to the I/O connector for interface to some external hardware, or are you looking for a way to route an internal event signal back to the host CPU as a software interrupt (to be handled by some ISR associated with your app).
If it's the former, you should be able to achieve what you want by setting up the M Series counter for pulse train generation. We don't have an example of this for the M Series DDK, but the 660x DDK examples do show how to set this up (specifically, ni660x/Examples/gpct_ex3.cpp would be a good reference).
Hopefully this helps-
Message Edited by Tom W [DE] on 10-11-2007 09:56 AM
Tom W
National Instruments -
X Series is here – New Counter Features!
Hey All,
The new X Series Multifunction DAQ devices have been announced – check them out here.
I’m posting here because I think X Series has several new counter features that many on this forum have been looking for. The user manual
will have all of these details and more with timing diagrams but I
thought I’d summarize a few of the sexier features and open it up for
comments/feedback.
First off – what stayed the same between
M Series/TIO counters and X series counters? The pinouts between M and
X series are the same so the PFI lines and default counter pinouts are
the same. The DAQmx programming is the same (you’ll need DAQmx 9.0, it
should be up this afternoon) and all the functionality that was
supported by M Series is supported by X Series, though a few behaviors
may have changed. Counters are still 32 bit.
Now on to
the fun stuff – the big one that I tend to overlook: X Series has 4
counters per board! They all have the same features and Freq Out is
still there too (with an additional 20MHz timebase).
Timebases:
X Series devices have 100MHz, 20MHz and 100kHz timebases. Note the
difference between 80MHz on M series and 100MHz on X series. DAQmx will
take care of the difference for you, unless you were programming in
terms of ticks and hardcoded in numbers based off of a 80MHz clock.
Counter
FIFOs: X Series has a 127 sample FIFO per counter. When combined with
PCIe/PXIe, our benchmarked buffered counter rates went from ~350k on M series
(with a 2 sample FIFO) with a single counter to 10MHz on all four
counters (160MB/s streaming rate). The FIFO also allows us to implement…
Buffered Counter Output: Probably my favorite new feature. You can
now use a multi point write on counters and write out a buffer of pulse
values. There are two timing modes for this: implicit and sample
clocked. With implicit timing, every idle/active pair you write is
generated as a pulse. You can vary the idle/active time for every pulse
in your pulse train. Check out the "Gen Dig Pulse
Train-Buff-Implicit-Cont.vi" shipping example. With sample clock
timing, the idle/active time are updated every time a sample clock is
received. Check out the "Gen Dig Pulse Train-Buff-Ext Clk-Cont.vi"
shipping example. These modes give you much more control over your
waveform – now everything about it can be hardware timed. Also, I’ve
benchmarked the output rates at 10MHz on all four counters at the same
time.
Finite pulse train with one counter: Each X Series
counter has an Embedded counter paired with it. The embedded counter
isn’t directly programmable, but it does allow you to do counter
operations on one counter that used to take two. A finite pulse train
used to take two counters – one to generate the pulse train and one to
gate it. Now a counter generates the pulse train, and its embedded
counter counts the TCs and disables the counter when it reaches the
number of pulses to generate.
More sample clocked
measurement modes: Edge counting and encoder measurements always
supported sample clocks, all other counter measurements were implicitly
(timed by the measurement waveform) timed. With the addition of the
sample clock terminal to the counters now all counter measurements
(except for semi-period) support sample clock timing. You can now get
the pulse width of the pulse just before the sample clock rather than
getting all the pulse widths and figuring out where they happened in
time. Why not semi period? We added a new “pulse” measurement instead
that returns a sample that contains the high and low time (or high and
low ticks, or frequency and duty cycle) so for each sample clock edge
you get a full pulse spec. Semi period still supports the same
measurements it used to, just not sample clocked. Speaking of sample
clocked…
Sample clocked frequency/period measurement
with averaging: X Series still supports the three frequency modes: Low
frequency 1 counter, 2 counter High Frequency and 2 counter Large
Range. In addition it supports sample clocked averaging. This is
essentially a method that is high accuracy method based on the sample
clock rate. With the same measurement time it has the same accuracy as
the Large range mode but it doesn’t take two counters. Note, counters
do not have their own internal sample clock so you have to provide them
with an external signal.
Hope this helps,
Andrew S
National Instruments
Multifunction DAQ Product Support Engineer
Getting Started with NI-DAQmx
Measurement FundamentalsHi guys,
I drew up a schematic of one of the applications I need to get running in our lab. To recap:
1) We have several piezo controllers for nanopositioning of samples under a microscope, some of them driven by a digital circuit that handles coordinate programming and trigger line programming (for syncing detectors to the piezo motion), other controllers are analog and need to be driven by voltages.
2) We would like to emulate the behavior of the digital controller using the analog HW (we have much more analog controllers than digital ones).
3) The basic implementation is like this (see also slide one in the attached pdf file) and runs perfectly:
a. A global pulsetrain ticks with a certain frequency
b. At each tick a voltage is written on an AO line and this tick is also sent to an RTSI line to sync multiple detectors
4) To fully emulate the digital controller we also need to implement 4 trigger lines that exist on the digital controller. These trigger lines allow for fully programmable pulsetrain output that is in sync with the movement of the piezo. Slide two in the attached pdf illustrates what is needed. These trigger lines allow for much more intricate syncing of our detectors (only measure during certain parts of the motion instead of all the time).
After a lot of thinking and experimenting with the existing M series boards back here I came to the conclusion that the desired behavior is not possible with an M series board since they only allow for the output of “simple” pulsetrains with a given frequency.
Looking at this webpage (http://zone.ni.com/devzone/cda/tut/p/id/9384#toc3) however, I think that the X series board would offer exactly what we need since it allows for buffered counter output that enables definition of very complex pulstrain “shapes”.
Looking at the schemes I provided, could someone confirm that the X-series covers our needs? If this is the case, we would be interested in purchasing these kinds of boards.
Cheers,
Kris Janssen
Attachments:
Raman Imaging Timing Implementation.pdf 76 KB -
I am measuring velocity using a linear encoder. Resolution is 40microns, sample frequency is 1MHz and the real velocity is oscillatory in nature with an amplitude of 200 to 400 mm/s with a freq of about 1Hz. We use a 5ms fixed time window to measure velocity. The quanization error for this is 8mm/s. Can I get rid of the quatization error by somehow measuring the exact time from the first pulse to the last pulse in the measurement window?
There is probably a way to do it, but it it may be easier to use an X-series board for the job. They support a new counter capability for count reset on a digital edge without needing to be configured in encoder position mode. I am not sure exactly how that feature's been implemented however, so maybe it won't make things easier after all.
The plan based on the hoped-for behavior:
1. Configure an X-series counter for pulse generation based on "ticks" of your clock channel.
2. Set both initial delay and low time to the critical # of ticks.
3. Configure for count reset on a digital edge (if possible in pulse generation mode)
4. Configure the count reset value to be the critical # (or possibly 1 less, if possible in pulse generation mode)
5. If you want the output to remain high indefinitely, configure the counter task to use its own output as a
pause trigger, and pause while high.
The way pulse generation works is to preload a # of "low time" ticks into the count register. Then every source edge will decrement the count. When the count reaches terminal count (0), the counter's output is toggled (or can be configured to pulse). The register is then loaded with the # of "high time" ticks and the process continues.
You would be perpetually interrupting the count-down process as long as you got your triggers in time. The count would keep getting reset to the # of low counts, keep decrementing toward 0 without reaching it, and so on. If ever you did reach 0, the output state would toggle high, then the high state would prevent subsequent clock signals from decrementing the count.
You can conceivably do a similar thing with a 6601, but I'm pretty sure you'd need 2 counters working together to get it working.
-Kevin P -
AXI DMA velocity and DCache doubts
This is a 2 question in one thread.
I'm basing my model on the matrix multiplication example,
First set of questions:
After some optimizations I have now a MM2S velocity of 1009 Mbytes/s and a S2MM velocity of 383 Mbytes/s.
1.1- Why is S2MM so slow when comparing to MM2S?
1.2- Are these the maximum velocities that you think I can get? Currently I'm not using interrupts and just waiting for each transfer to end before continuing. If I use interrupts will it be faster?
Second set of questions:
Following some advices I am going to divide my 512x512 matrices in 32x32 ones and treat each of them separately, since the Zedboard resources are not that big.
I already tested my design and the first 32x32 matrix is properly normalized. Input and output values are correct. However if I try and do a for cycle for all the matrices, the results are not correct and I think this is related to the cache flush and invalidate.
Here's my code:
#define DIM 32
//Start my IP block and enable auto-restart (doubts about this..)
XMm2s_Start(&BRAM_func);
XMm2s_EnableAutoRestart(&BRAM_func);
for(i=0;i<LIMIT;i++){
mm2s_bufferPtr=(u32 *)(SLOPE_ADDR+i*DIM*DIM*4);
result_Ptr =(u32 *)(FINAL_ADDR+i*DIM*DIM*4);
Xil_DCacheFlushRange((u32)mm2s_bufferPtr,DIM*DIM*4);
Xil_DCacheFlushRange((u32)result_Ptr,DIM*DIM*4);
Status = XAxiDma_SimpleTransfer(&axi_dma, (u32)mm2s_bufferPtr, DIM*DIM*4, XAXIDMA_DMA_TO_DEVICE);
if (Status != XST_SUCCESS)
xil_printf("ERROR! Failed to kick off MM2S transfer!\n\r");
return XST_FAILURE;
while (XAxiDma_Busy(&axi_dma,XAXIDMA_DMA_TO_DEVICE));
// Kick off DMA S2MM transfer
Status = XAxiDma_SimpleTransfer(&axi_dma, (u32)result_Ptr, DIM*DIM*4, XAXIDMA_DEVICE_TO_DMA);
if (Status != XST_SUCCESS)
xil_printf("ERROR! DMA transfer from Vivado HLS block failed!\n\r");
return XST_FAILURE;
while (XAxiDma_Busy(&axi_dma,XAXIDMA_DEVICE_TO_DMA));
print_matrix(result_Ptr,DIM,DIM);
Xil_DCacheFlushRange((u32)result_Ptr,DIM*DIM*4);
I already read this carefully about DCacheFlush and DCacheInvalidate but I still clearly have not understood very well.
Note: In the linker script I changed the heap and stack sizes to 10Kbytes instead of 1Kbyte.
Ty very much in advance for the help.Hello jmales,
Right now my main IP (designed with Vivado HLS) is receiving a 32x32 matrix of floats. So, everytime I call my IP block within SDK I transfer 4096 bytes with the MM2S and then 4096 back with the S2MM transfer. So is 4096 my bandwidth ?
Oh okay, I see what you mean. The remaining question to answer first is:
- How often do you need to transfer a new 32x32 matrix? Or probably more useful question is how often do you need to transfer the 512x512 matrices? In other words, how fast are you acquiring new 512x512 matrices. What is your sample rate. This will tell you how much bandwidth you need.
If you only take in a new matrix every 10 seconds, then we only need to move data at a rate of 512 * 512 * 4 (bytes) / 10 = ~105KB/s in which case we don't really care about DMA efficiency because data is coming in so slowly. All we need to do is clock the DMA in the MHz range and you'll easily be able to keep up. The DMA will be sitting idle while we wait for new matrix for a while anyway, so any overhead associated with setting up the next transfer will be completely eclipsed and inconsequential. However, if you're taking in a new matrix every 10 milliseconds, we need to move data at 512*512*4/10e-3 = ~105MB/s which becomes a more difficult problem to solve and DMA efficiency may become a larger factor.
Another thing to think about is latency. Do you care about the absolute time (in milliseoncs) from when you acquire your matrix until it arrives at it's final destination? This will affect the rate that you clock your accelerator hardware (including DMAs, interconnects, etc). Take our 10 second matrix acquisition rate example. Even though the data rate is slow, if we need to pass data from DDR to accelerator, perform the matrix multiplication, then send data back to DDR all under 10 milliseconds, then you'll need to run your DMA operations faster. For minimal latency, every clock cycle counts so DMA configuration overhead might not be acceptable.
I was looking into this and actually posted a new thread regarding that meanwhile. So if I set the frequency of the MM2S and S2MM ports to 200MHz and the frequency of my custom IP block to 100Mhz, a FIFO ow 2 FIFOS will make sure everything runs smoothly?
Reading the other thread, I want to be clear about which problem this will solve. Doing this will ensure that your 100MHz clock domain will receive a continuous stream of data (i.e. no bubble cycles where the accelerator is not taking in new data). This is because the FIFO will have data in it which the accelerator can be processing while the DMA is being configured for the next transfer.
From a raw bandwidth (MB/s) perspective, this won't be as high as just running everything at 200MHz and allowing for those handful of buble cycles where the DMA is being reconfigured.
Maybe running some number will help to show the distinction:
1) FIFO case where you run processing at 150MHz with no buble cycles (in the processing clock domain) due to DMA downtime. 150MHz * 4 bytes per clock * 100% efficiency = 600MB/s
2) No FIFO, everything runs at 200MHz, DMA transfer length is 32*32 = 1024 cycles (or 4096 bytes), and say it takes 20 cycles to reconfigure the DMA for each transfer. The efficiency is 1024/(1024+20) = ~98%. So total bandwidth is 200MHz * 4 bytes per clock * 98% = 784MB/s
2) Again, no FIFO and everything runs at 200MHz with 20 cycles to reconfigure the DMA, but this time lets say we transfer the data one row at a time so our transfer length is 32 cycles (or 128 bytes). Now our efficiency is only 32/(32+20) = ~61.5%. So total bandwidth is 200MHz * 4 bytes per clock * 61.5% = 492MB/s
So if we figure out the number of matrices you need to process per second and the input-to-output latency requirements, then we can start deciding on architectural stuff about how best to move the data around. -
How to disable (turn off) a counter output
I have a similar question up on the the board but I thought I would ask it in another way to make it simple and straightforward.
Can an E-series counter output be disabled (and enabled) quickly through some software command? When I say " disabled" I mean switched off to a TTL low state. I have tried both the "disable" counter control command and gating the counter with a TTL signal. Both methods leave the output pin in whatever state the output happens to be in at the time of the command or gating. I need a disable function where "disabled" automatically sets an OFF or LOW on the output. I am using this to generate a pulse train where the pulse train switches off at certain times, and I cannot have the output remain high at these times.
I am using traditional DAQ but if there is a method in DAQmx that works I'd be willing to try it...Have you tried using the following vi with a reset command (search in help, it works with the E series counters)
Counter Control
This VI controls groups of counters. Control operations include starting, stopping, and setting the state of active acquisitions. This VI works with DAQ-STC and NI-TIO-based devices.
Control code 1 (reset) reinitializes the counter back to the default settings.
~~~~~~~~~~~~~~~~~~~~~~~~~~
"It’s the questions that drive us.”
~~~~~~~~~~~~~~~~~~~~~~~~~~ -
Register information on X series driver for encoder
Hi All:
I am working on the X series driver development by using MHDDK. After comparing M series and X series I found that theere is a Gi_Save_Trace bit in register Gi_Command_Register in M series. When it is set, the register goes into the latched mode after the next clock edge to assure valid data was latched. However, I can't find equivalent register bit in all X series counter registers.
Can anyone tell me what is the equivalent register bit for same function that Gi_Save_Trace does?
Thanks,
LarryHi PedroMunoz,
Actually, I wanted to post it at DDK forum. I don't know why it is shown here. I may need to do it again.
Thanks,
Larry -
Can I use the 'Export Signal Property Node' on a quadrature encoder?
Hi,
So I don't know which counter board I'd be using yet for this (it's used in conjunction with a PCI-6280--the PCI-6280's counter inputs are all taken and so I need another board), but assuming this is possible at all in DAQmx I wouldn't mind knowing whether, say, the PCI-6601 (or any other timer board for that matter) could do this. I'm programming this in LabVIEW 2010 by the way.
I want to have a counter which counts the number of pulses on one channel (I'll call this the 'clock' channel) between when another channel goes from low to high (which I'll call the trigger). It's basically a pulse width measurement, but I only care if there are more than n clock pulses between triggers. I need to have a hardware-timed digital signal which goes from low to high if there are ever more than n pulses between trigger changing state from low to high.
What I am planning to do is this:
Wire 'trigger' to the z-input of the quadrature encoder, and set the z-input value to some arbitrary large value such that, at the quadrature encoder counter task's settings, the counter reaches terminal count in n pulses.
Configure the quadrature encoder counter using DAQmx Export Signal Property Node (tutorial I was looking at is here: http://zone.ni.com/devzone/cda/tut/p/id/5387 ) to toggle a digital channel ('counter event output') from low to high if the counter reaches terminal count (ie, if the encoder reads n pulses).
If the encoder ever reads n pulses on 'clock' between two rising pulses on 'trigger', it sets counter event output high.
Is this possible? Reading through the manual of M series PCI-62xx devices, the index pulse loads the counter with a particular value so it seems like you could conceivably set the counter to the terminal count if you wanted. My only real problem is whether DAQmx Export Signal Property Node works on all counter tasks or just on edge counting tasks.
Thanks in advance for your help. If this isn't possible, I can reply with more details on the problem this is supposed to solve so that you can help me figure out an alternate method.
Solved!
Go to Solution.There is probably a way to do it, but it it may be easier to use an X-series board for the job. They support a new counter capability for count reset on a digital edge without needing to be configured in encoder position mode. I am not sure exactly how that feature's been implemented however, so maybe it won't make things easier after all.
The plan based on the hoped-for behavior:
1. Configure an X-series counter for pulse generation based on "ticks" of your clock channel.
2. Set both initial delay and low time to the critical # of ticks.
3. Configure for count reset on a digital edge (if possible in pulse generation mode)
4. Configure the count reset value to be the critical # (or possibly 1 less, if possible in pulse generation mode)
5. If you want the output to remain high indefinitely, configure the counter task to use its own output as a
pause trigger, and pause while high.
The way pulse generation works is to preload a # of "low time" ticks into the count register. Then every source edge will decrement the count. When the count reaches terminal count (0), the counter's output is toggled (or can be configured to pulse). The register is then loaded with the # of "high time" ticks and the process continues.
You would be perpetually interrupting the count-down process as long as you got your triggers in time. The count would keep getting reset to the # of low counts, keep decrementing toward 0 without reaching it, and so on. If ever you did reach 0, the output state would toggle high, then the high state would prevent subsequent clock signals from decrementing the count.
You can conceivably do a similar thing with a 6601, but I'm pretty sure you'd need 2 counters working together to get it working.
-Kevin P -
I am using nigpib version 6 with RedHat Linux 6.2. I am having problems talking to my instruments. Two devices a Keithley Multimeter 2001 and an IO TECH dac488hr refuse to communicate. Their remote lights go on but I get an EBUS error when doing ibwrt to either. Two other devices an SRS850 lockin amplifier, and an ESI model 73 precision transformer respond to commands well enough but I get an EAB0 error returned. I recognize the problems have to do with timeout. I have changed ibtmo to various settings but continue to get errors. I have tried to be careful setting the EOS and EOI attributes for each device but clearly I am missing something. Any suggestions?
In the past I used the LLP gpib driver and don't recall gett
ing these kinds of problems. I was going to port over my old code to talk with the instruments but I see that there is some rather sigificant differences in the way you do business. For one under LLP Clausi set up a /dev/gpib0/master device through which commands were passed. In addition he had a /etc/gpib.conf file and loaded his module via insmod in rc.d. You, on the other hand, set up /dev/gpib, /dev/gpib0, /dev/gpib1/, /dev/gpib2, /dev/gpib3, /dev/gpibdebug and /dev/dev0 /dev/dev1 etc (where dev# is a device configured with ibconf). What are the relationships between your strategies? What must I do to port my old software to my newer linux OS and use your drivers rather than those from LLP?
I could really use some insights. Any comments (sans flaming ;-) would be welcome.I tried this but with no success. I called the help line and spoke with Ben P. and Armando V. they walked me through the ibic and ibconf tools, again, with no success.
I spoke with the vendors of the instruments which are giving the EBUS error. They walked me through the setups (especially wrt to EOS and EOI). They were confused as to why the instruments failed to respond.
With my last call to NI (SR#345883) the engineers suggested that I respond to this email and ask for further support. They requested/suggested I supply the following 3 pieces of information:
1) revision of boards and part nos.
2 ATGPIB-TNT boards vintage 1993
assy 181830-01 REV. D
1 ATGPIB-TNT PNP vintage 1995
assy 182885E-01
The implication was that NI might be able to provide an upgrade to the firmware if that was at fault.
2) Capture of errors in ibic
basically following your webpage for ibic works upto communicating with devices. Sample output follows:
: ibfind gpib0
id = 0
gpib0: ibpad 0
[0100] ( cmpl )
previous value: 0
gpib0: ibfind keithley
id = 1002
keithley: ibwrt "*IDN?\xA"
[8100] ( err cmpl )
<>
error: EBUS
count: 0
keithley: ibrd 100
[8100] ( err cmpl )
error: EBUS
count: 0
<>
keithley: ibfind ratio
id = 1003
ratio: ibwrt "Ratio 0.1234567\xA"
[c100] ( err timo cmpl )
error: EAB0
count: 16
<
the ratio, as verified by the display >>
ratio: ibrd 100
[e100] (err timo end cmpl )
error: EAB0
count: 17
52 61 74 69 6f 20 30 2e Ratio 0.
31 32 33 34 35 36 37 30 12345670
0a .
using the SRS850 Lockin Amplifier has an added advantage. It will show the input and output queues on the screen. When I command this instrument I can watch as it receives its instructions. The commands are going through correctly (NOTE: this device also gives an EAB0 error).
I have tried different cables, different machines, different DMA settings, different interrupts, different instruments, different ibtmo values, different cards, single devices on short cables, but keep getting errors.
I have used the ibic webpage (setting ibsre 1, etc) and these work fine but the devices still complain.
3) Give the version of Linux I am using...
We are running Redhat 6.2, kernel version 2.2. We have older versions of the Linux OS which are running the LLP gpib driver for the SAME devices and it works fine. I would rather not go back to older versions if possible, besides since NI has done the Linux gpib driver, it appears that LLP has dropped support. In particular, I cannot get their drivers to compile in Redhat 6.2 and get no response from my emails. I would be willing to move to newer versions of Linux if that would solve the problem.
I have confirmed the following:
The ibtsta program says the driver is installed correctly (run without the gpib cable attached.)
Interrupts, dma, iports are unique and without contention.
The gpib card responds to commands (eg using ibic.)
Some devices respond in a fashion, others fail. But all seem to receive signals from the computer.
The instruments and cables attached to the system are sound.
The gpib card, cables, and devices respond correctly from a dual boot machine running WinNT and Linux (i.e. no movement of cables, devices, or cards). On the WinNT side the recently downloaded NI drivers work and I can communicate (with the Keithley 2001) flawlessly.
I am must now ask whether the driver is at fault. I understand the drivers are beta, but these appear to be the only workable drivers out there. ANY HELP WOULD BE APPRECIATED!
>>
Maybe you are looking for
-
I work at an office that has an office calendar for all of our client appointments. My boss is getting an iphone, he is terrible at using technology. Which calendar could we use that would allow him (or anyone in the office with an iphone) to sync
-
Hi, I'm having a problem with iTunes. My problem is the tooltips for certain buttons are popping up in the wrong places, keeping me from clicking there. The first four tooltips that are in the wrong spot are: "Create a playlist" "Turn shuffle on or o
-
What does the following code mean???
what does the following code mean ?? fpm.raiseReviewAndSaveEvent(IFPM.EVENT_REVIEW, IFPM.EVENT_SAVE, vcFormEditButtons); thanks in advance. can you please tell me best site to learn WD4J coding. site having lot of WD4J code examples
-
Equivalent for Word's Format Painter?
I've bought iWork 09 to use on my MBA as a substitute for Word. One of the feature I used most in Word is the format painter, where you copy complete formatting from one area to another with one click. Is there any equivalent to this in Pages?
-
Strange capacity reading...Need help!
Hey! my sister has a pink, 2g, 4GB ipod Nano. Things have worked smoothly for a whole year now...but yesterday she tried uploading a CD onto her ipod. She has 3GB of memory used. 1 GB free. So...she inserts the CD and adds it to her playlist. When sh