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
    Ash

    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

  • 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(sourceSe​lect); // (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::tG​1_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_Sourc​e(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(tTI​O::tG1_Mode::kG1_Trigger_Mode_For_Edge_GateGate_Do​es_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_Synchroniza​tion(0);
        tio->G1_Counting_Mode.flush();
        //MSeries.CTR.EnableOutput
        //board->Analog_Trigger_Etc.setGPFO_1_Output_Enab​le(tMSeries::tAnalog_Trigger_Etc::kGPFO_1_Output_E​nableOutput);
        //board->Analog_Trigger_Etc.setGPFO_1_Output_Sele​ct(tMSeries::tAnalog_Trigger_Etc::kGPFO_1_Output_S​electG_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_A​rm_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(sourceSel​ect); // (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_C​ommand::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::t​G1_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::k​G1_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_Doe​s_Not_Stop);
    tio->G1_Mode.setG1_Stop_Mode(tTIO::tG1_Mode::kG1_S​top_ModeStop_On_Gate);
    tio->G1_Mode.setG1_Counting_Once(tTIO::tG1_Mode::k​G1_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::k​G1_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_Synchronizat​ion(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,
    Ami

    No 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.
    Kenneth

    Hi
    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

  • E-series counter

    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 KB

    Hi 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
    Bertrand

    Hello 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

  • Time-based interrupt m-series

    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.
    Aaron

    Hi 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 Fundamentals

    Hi 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

  • Can I use the the measured time between the first count and the last count in a fixed time window in order to increase the accuracy of a quadrature velocity measurement?

    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,
    Larry

    Hi 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

  • Missing something obvious

    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

  • Which calendar is useful for an office? So that we can maintain one appointment calendar, yet anyone in the office who has an iphone can sync the info to their iphone.

    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

  • Glitch with tooltip layout

    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