Driver Development Kit (DDK)

cancel
Showing results for 
Search instead for 
Did you mean: 

control loop - HardwareTimed Single Point Acquisition

I was reading the " What is the required order of operations for the M-series DAQ (PCI-6229)?" thread and saw a reply which is closely analogous to what I want to do:
"
- Put the device in a known state: reset AI, AO
- Configure AO for on-demand output.  In this mode when you write a value to the DACs it goes out inmediately.
- Configure AI for continuous acquisition.  Set up a interrupt source to determine when there's data avaliable.  You can use the FIFO condition interrupt or the scan clock interrupt.
- How you handle the interrupt and where you proccess the data depends on you system.  Assuming you process everything in the ISR:
    - Get the latest sample(s) from the FIFO by emptying it
    - Process the data point
    - Write the response to the DAC(s).  Output is generated inmediately
- Goes on forever...

In DAQmx terminology you would be doing a Hardware-Timed Single Point acquisition.
"
I have a PCI-6229 and BNC-2120 and am having difficulty making sense of the 13 thousand  line chipobjects/tMSeries.h file. The examples contain a lot of useful idioms but are just a bit too non-parallel to my goal and I wonder if someone has some example code more similar to the following or advice on whether I am being foolishly fastidious. I imagined setting up a continuous pulse stream on the 6229 available on one of the digital output lines. The interval between the rising edges is my time step and the pulse width is wide enough so that the on chip ADC portion of ai was initiated on the rising edge and would not be affected by the on chip DAC ao initiated on the falling edge. The interrupt would occur on the falling edge and by then the computer could read the ai buffer. Some computation would occur which fills the ao buffer, ready for transfer atthe next falling edge. I'd also like DI and DO to be synchronized to the rising and falling edges.
By the way, before I bought the 6229, I verified that with RTAI linux I could work comfortably with a time step of 0.025 ms (those interrupts came from the computer clock). In practice, I'll be working somewhere between that and 1 ms steps.
0 Kudos
Message 1 of 4
(7,959 Views)
Check out this post  Clocked M-Series DIO.  It seems you are trying to do something very similar. 


The
tMSeries class is just a description of the registers available in the device.  Each register is an object that manages a soft-copy of the register.  Each register class defines some methods to read and write to the register as a whole or to the bitfiled of the register.  Using the a tMSeries object you don't need to worry about register offsets or shifting bitfields. 

Diego






0 Kudos
Message 2 of 4
(7,921 Views)
I was partly mistaken about the examples not being parallel to my goals. Beginning with aiex2.cpp,  dividing it into several functions, and adding the http://forums.ni.com/ni/board/message?board.id=90&message.id=387 "Clocked M-Series DIO" fragment, have gotten me a fair ways along the path toward a prototype control loop. But I'm having trouble merging in the aoex4.cpp example and I guess need to experiment with that part in isolation. Since the fundamental clock for my control loop is (I'm guessing) given by the aiex2
   aiTrigger (board,
               tMSeries::tAI_Trigger_Select::kAI_START1_SelectPulse,
               tMSeries::tAI_Trigger_Select::kAI_START1_PolarityRising_Edge,
               tMSeries::tAI_Trigger_Select::kAI_START2_SelectPulse,
               tMSeries::tAI_Trigger_Select::kAI_START2_PolarityRising_Edge);
I am curious, why that pulse does not appear on my BNC block at the "AI CONV CLK" output (PFI 2)?
Nevertheless, with the Clocked M-Series DIO example I am able to see a pulse train on P0.0.
My main question is how to get the AO triggered by the aiTrigger instead of the <independent?>
   aoTrigger (board,
               tMSeries::tAO_Trigger_Select::kAO_START1_SelectPulse,
               tMSeries::tAO_Trigger_Select::kAO_START1_PolarityRising_Edge);
or do I need to externally trigger from P0.0?

0 Kudos
Message 3 of 4
(7,915 Views)
My control loop is working well using the idioms for AO on demand output from aoex2.cpp and AI continuous acquisition from aiex1.cpp. However the interrupt follows the LXRT extension to RTAI example for processor generated periodic interrupts using

        start_rt_timer(period_);
        rt_make_hard_real_time();
        nrn_fake_step(); // get as much as possible into the cache
                        // saves up to 10 us on the first step
        rt_task_make_periodic(rtrun_task_, rt_get_time() + period_, period_);
        rt_task_wait_period();
        while (t < tstop_) {
                t1 = rt_get_cpu_time_ns();
                nrn_fixed_step(); // start ai scan, compute, ai read, ao write
                nrn_rtstep_time_ = (double)(rt_get_cpu_time_ns() - t1);
                ovrn += rt_task_wait_period();
                if (stoprun) { break; }
        }
        rt_make_soft_real_time();
        stop_rt_timer();

Now I'd like to have the 6229 generate the interrupt and I wonder if anyone can give advice on how to carry out the transformation. There was some mention about using the FIFO condition interrupt or the scan clock interrupt and there are some intriguing lines in
http://forums.ni.com/ni/board/message?board.id=90&message.id=287&query.id=4559#M287
but I have to admit to being somewhat at a loss as to how this connects to the rtai api. The only thing I've found that is remotely analogous is
http://www.captain.at/programming/rtai/parportintlxrt-magma2.php
that gives an example using things like rt_request_irq_task, rt_startup_irq, rt_enable_irq, rt_irq_wait, rt_ack_irq,... Is that the avenue I should explore?

I should mention that my experiments with AO on demand and AI hardware time acquisition from aiex2.cpp also worked nicely and I expect to use that idiom after I get this interrupt driven. However I was unable to get the AO hardware timed generation from aiex4.cpp to work hardly at all. Sometimes it hung in aoArm at
    while (board->Joint_Status_2.readAO_TMRDACWRs_In_Progress_St ())
    {
        // Wait
    }
and could only get it going again by running the aoex4 example itself, More often no output I was writing appeared at the BNC connector, and when I did see output it was delayed by a dozen or so steps. Obviously I do not know how to manage the fifo. The serious conceptual error, though, was using kCDO_Update_Source_SelectAI_Convert to toggle P0.0 and then connecting that to AI CONV CLK and using kAO_START1_SelectAI_START_1 for the trigger and kAO_UPDATE_Source_SelectPFI2 for the aoUpdate. The problem is that the rising edge is every two steps so my output is half the rate I want.

Sorry for the long message and my glaring naivety. I suspect that a few minutes from someone with experience will save days of my flailing around.

Thanks!
Michael


0 Kudos
Message 4 of 4
(7,894 Views)