Driver Development Kit (DDK)

cancel
Showing results for 
Search instead for 
Did you mean: 

How to config parameters of NI DDK aiex2.cpp to accomplish continuous mode

Hi,
I am doing PXI-6220 driver in RTX and met some problems.
In my application, the pfi 0 (P1.0) receives a 1 kHz external signal source. Every time PXI-6220 receives a pulse (rising edge), it will trigger an AI scan from channel 0 to channel 3. I think it is the so called "hardware timed acquisition". So I made some changes to aiex2.cpp. Listed:
//aiPersonalize (board, tMSeries::tAI_Output_Control::kAI_CONVERT_Output_SelectActive_Low);
aiPersonalize (board, tMSeries::tAI_Output_Control::kAI_CONVERT_Output_SelectActive_High); // special for PXI-6220
//adcReset(board); //not 625x serials
The example works very well. However, I found it is a post trigger mode. When it runs, I must wait for very long time and get all the results after the program exits. But I want a continuous mode and I hope the scan will continue infinitely with the external signal. The problem is I am not sure about some parameter settings. So can not accomplish the real continuous mode. I am puzzled by these questions:
1.     aiTrigger (board,
               //tMSeries::tAI_Trigger_Select::kAI_START1_SelectPulse,               // change
               tMSeries::tAI_Trigger_Select::kAI_START1_SelectPFI0                   // change
               tMSeries::tAI_Trigger_Select::kAI_START1_PolarityRising_Edge,
               tMSeries::tAI_Trigger_Select::kAI_START2_SelectPulse,
               tMSeries::tAI_Trigger_Select::kAI_START2_PolarityRising_Edge);
Since every time the pfi 0 receives the external pulse, the AI controller will do a scan from channel 0 to 3. So I guess this signal should be the start trigger. I changed the first parameter to kAI_START1_SelectPFI0. Am I right?     
2.    aiNumberOfSamples (board,  
                       numberOfSamples, // posttrigger samples
                       0,               // pretrigger samples
                       continuous);     // continuous?
From the discussion on this DDK forum, I add tBoolean continuous = kTrue;
And ignored posttrigger and pretrigger parameters (set them all to 0). Can these two parameters be ignored in continuous mode?
3.    aiSampleStart (board,
                   samplePeriodDivisor,
                   3,
                   //tMSeries::tAI_START_STOP_Select::kAI_START_SelectSI_TC,    // change
                   tMSeries::tAI_START_STOP_Select::kAI_START_SelectPFI0,         // change
                   tMSeries::tAI_START_STOP_Select::kAI_START_PolarityRising_Edge);
   
    aiConvert (board,
               //280,     // convert period divisor   // change
               80,     // convert period divisor      // change, make it most fastest
               3,       // convert delay divisor
               //kFalse); // external sample clock?              // change  
               kTrue); // external sample clock?                 // change, it should be true
   
I did not change the periodDivisor and delayDivisor. Are they different in continuous mode?
I changed both source of aiSampleStart() and aiTrigger() to kAI_START_SelectPFI0. But I am not sure of it. I just need to do an AI scan once the board receives a rising edge and continue on infinitely. Could anybody make some recommendations?
4. I guess since it is in continuous mode, maybe the read progress need to be included into a while loop, like:          
 
    // ---- Read FIFO ----
   
    i32 value;
    f32 scaled;
   
    u32 n = 0; 
    //while (n < numberOfChannels*numberOfSamples)                 // change
    while (!0)                                                                       // change
    {
        if(!board->AI_Status_1.readAI_FIFO_Empty_St())
        {
            value = board->AI_FIFO_Data.readRegister ();
            aiPolynomialScaler (&value, &scaled, &scale);
            printf ("%e,\n", scaled);
            //n++;
        }
    }
   
Since the external signal is 1k Hz, I expected that this segment of code will print out the AI scan result every 1ms. Is this right?
 
This is my first time to write NI driver. So not very familiar with it 😞  Could anybody help me a little? or make some suggestions?
Thank you in advance!
Rick
Masterpiece Technology Co. LTD
  
   
   
   
 
0 Kudos
Message 1 of 9
(9,827 Views)
Could anybody help me on this issue?
0 Kudos
Message 2 of 9
(9,806 Views)
Hi Rick-
 
Let me address your questions one-by-one:
 
1. Since every time the pfi 0 receives the external pulse, the AI controller will do a scan from channel 0 to 3. So I guess this signal should be the start trigger. I changed the first parameter to kAI_START1_SelectPFI0. Am I right?     
 
No.  AI_START1 is used as the start trigger for the entire acquisition (where an "acquisition" is comprised of several scans of your channel list).  The signal that actually initiates a scan from the channels in your channel list is AI_START.  You should actually set AI_START to PFI0 using aiSampleStart() in order to use PFI0 as the external sample clock to begin each scan of your channel list.
 
2.  From the discussion on this DDK forum, I add tBoolean continuous = kTrue; And ignored posttrigger and pretrigger parameters (set them all to 0). Can these two parameters be ignored in continuous mode?
 
Yes.  Setting the acquisition to continuous mode (via aiNumberOfSamples() ) tells the STCII to ignore internal signals that would normally signal a complete acqusition. 
 
3.  I did not change the periodDivisor and delayDivisor. Are they different in continuous mode?  I changed both source of aiSampleStart() and aiTrigger() to kAI_START_SelectPFI0. But I am not sure of it. I just need to do an AI scan once the board receives a rising edge and continue on infinitely. Could anybody make some recommendations?
 
There is no difference for periodDivisor and delayDivisor in continuous mode.  The period divisor dictates the behavior of the AI convert clock (the signal that actually scans through your channel list once an AI_START has occurred) and should not be changed.  The delay divisor allows you to introduce some delay (defined in number of ticks of the AI sample clock timebase) between the AI_START1 signal and the first AI_START signal.  3 is the minimum value allowed and should work for most applications.
 
4.  I guess since it is in continuous mode, maybe the read progress need to be included into a while loop, like: [SNIP]
 
True, it could work that way.  Instead, I would suggest using one of the DMA-enabled examples.  For example, aiex4.cpp.  That example seems particularly useful because it uses an external start trigger (AI_START1) and sample clock (AI_START).  It shows how to perform DMA for a finite operation.  In order to extend that example for continuous operation, you would only need to remove the comparison
 
(bytesRead < totalNumberOfBytes)

since totalNumberOfBytes has no meaning in continuous mode.

 

Hopefully this helps-

Tom W
National Instruments
0 Kudos
Message 3 of 9
(9,793 Views)
Hi Tom,
 
I am out of office these days and have not replied this thread in time.
 
Your answer is really an excellent one! That satisfied all of my questions! The only one I am not sure is about the aiex4.cpp. Is it a valid example for M-serials cards? I have downloaded all the samples for M-serials. But this one is not included...
 
Could you please attach it on this thread or send to me? My email is zhangjing@msptc.com.
 
Thanks a lot! 
 
Rick
MSP
0 Kudos
Message 4 of 9
(9,749 Views)

Hi Rick-

Sorry about that- I haven't updated the MHDDK page in a while and since the last update there has been a new example added.  I have attached aiex4.cpp here.  You will also need the DMA library, available from the MHDDK download page, to run this example.

Thanks-

Tom W
National Instruments
0 Kudos
Message 5 of 9
(9,745 Views)

Hi Tom,

 

Thank you for the code file you sent to me. I have met a new question about aiGetScalingCoefficients() function. The comment for aiGetScalingCoefficients() is :

//
// aiGetScalingCoefficients --
//
// modeIdx
//    0 -> default
//
// intervalIdx
//    0 -> +/- 10V
//    1 -> +/- 5V
//    2 -> +/- 2V
//    3 -> +/- 1V
//    4 -> +/- 500mV
//    5 -> +/- 200mV
//    6 -> +/- 100mV
//
// channel
//    ignored - all channels use the same ADC
//

I do not understand why the "channel" parameter is ignored. If all the channels have the same AI range, it is OK to ignore this parameter. However, if different channels apply different analog input gain value, how can I distinguish the channels without the "channel" parameter?

 

I am afraid I have some misunderstanding on this function. Could you please make an explanation for me?

 

Thank you in advance 🙂

 

Regards,

 

Rick

MSP

0 Kudos
Message 6 of 9
(9,276 Views)

Hi Rick-

The aiGetScalingCoefficients() function does not require a channel parameter because there is only one set of scaling coefficients for each range (because there is only one ADC on the device).  In order to scale channels of varying ranges, you would need to call aiGetScalingCoefficients() multiple times and use different intervalIdx values.  In this way, you can retrieve scaling coefficients for the various ranges on the device as needed.  Any channel configured for +-10V operation would need to be scaled relative to intervalIdx = 0, any channel at +-5V would need to be scaled relative to intervalIdx = 1, etc.

Tom W
National Instruments
0 Kudos
Message 7 of 9
(9,266 Views)

Hi Tom,

 

Sorry to interrupt you again 🙂

 

In your last reply on this thread, you said "In order to scale channels of varying ranges, you would need to call aiGetScalingCoefficients() multiple times and use different intervalIdx values." But I'm not clear about how to call aiGetScalingCoefficients() multiple times.

 

If I put aiGetScalingCoefficients()s after aiClearFifo (board) and before aiArm (board, kFalse) (similar to the code sample 1), there will be always ONE range for all the channels, whatever the range value is. The result of the AI scan is also incorrect. I'm afraid this is not the "multiple times".             


I wonder whether I can put aiGetScalingCoefficients() before aiPolynomialScaler (&value, &scaled, &scale) (which means set the range before read the value). This can satisfy the "multiple" demand. But when I run the program, the Windows unfortunately crashed...

 

So, could you please explain a little clear about how to call aiGetScalingCoefficients() multiple times? Where is the correct position to place this function at?

 

Thank you for your support during my project!

 

Rick
MSP

0 Kudos
Message 8 of 9
(9,203 Views)

Hi Rick-

 

aiGetScalingCoefficients() only retrieves scaling coefficients from the device EEPROM for a single AI range.  So, in order to call it twice you would need two instances of tScalingCoefficients and would call aiGetScalingCoefficients() twice, passing different range offset values and tScalingCoefficients references each time.

 

To actually apply the two different sets of scaling coefficients you would need to modify aiPolynomialScaler().  Right now, it operates on the raw data sequentially and applies the same scaling coefficients to all data.  You would need to modify it to apply different scaling coefficients based on which channel index you were into your raw data.  The raw data is interleaved per channel, which means that each sequential point in the rawData array would correspond to a different channel's data.

Message Edited by Tom W [DE] on 08-20-2008 04:45 PM
Tom W
National Instruments
0 Kudos
Message 9 of 9
(9,161 Views)