Jump to content
  • 1

USB-1808X: How to output analog signals when an external trigger is received?


Jin

Question

Posted (edited)

Hello, everyone!

I don't know how to ouput and analog signal when receiving an external trigger.

The purpose is: the DAQ device captures a TRIG_POS_EDGE form Output Trigger, at the same time, the AO channel 0 output a signal designed. I'm working for this in past few days.

I'm setting the scanOption with SO_EXTTRIGGER, unfortunately, the program is not paused at "Waiting for trigger ...".

I try to set the scanOption with SO_CONTINUOUS, the output is correct.

The code shows below,  could you help me? Thank you!!
 

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <thread>
#include "uldaq.h"
#include "utility.h"

#define MAX_DEV_COUNT  100
#define MAX_STR_LENGTH 64
#define MAX_SCAN_OPTIONS_LENGTH 256

enum SIGNAL_TYPE{SIG_SIN,SIG_COS,SIG_CHRIP};

void generateAnalogSignal(int fs, double phase, double duration, int samplingrate, Range range, SIGNAL_TYPE signaltype, double* buffer);


int main(){

    int descriptorIndex = 0;
	DaqDeviceDescriptor devDescriptors[MAX_DEV_COUNT];
	DaqDeviceInterface interfaceType = ANY_IFC;
	DaqDeviceHandle daqDeviceHandle = 0;
	unsigned int numDevs = MAX_DEV_COUNT;

    int lowChan = 0;
	int highChan = 0;
    double rate = 400000;
    int samplesPerChannel = rate*0.02;
	Range range;
	ScanOption scanOptions = (ScanOption) (SO_DEFAULTIO | SO_EXTTRIGGER);
	AOutScanFlag flags = AOUTSCAN_FF_DEFAULT;

    int hasAO = 0;
	int hasPacer = 0;
    TriggerType triggerType;
	int index = 0;

    char triggerTypeStr[MAX_STR_LENGTH];	
    char rangeStr[MAX_STR_LENGTH];
    char scanOptionsStr[MAX_SCAN_OPTIONS_LENGTH];

	// allocate a buffer for the data to be output
	const int chanCount = highChan - lowChan + 1;
	double* buffer = NULL;
	UlError err = ERR_NO_ERROR;

	int i = 0;
	int __attribute__((unused)) ret;
	char c;

    // Get descriptors for all of the available DAQ devices
	err = ulGetDaqDeviceInventory(interfaceType, devDescriptors, &numDevs);

    if (err != ERR_NO_ERROR)
		goto end;

	// verify at least one DAQ device is detected
	if (numDevs == 0)
	{
		printf("No DAQ device is detected\n");
		goto end;
	}

	printf("Found %d DAQ device(s)\n", numDevs);
	for (i = 0; i < (int) numDevs; i++)
		printf("  [%d] %s: (%s)\n", i, devDescriptors[i].productName, devDescriptors[i].uniqueId);

	if(numDevs > 1)
		descriptorIndex = selectDAQDevice(numDevs);

	// get a handle to the DAQ device associated with the first descriptor
	daqDeviceHandle = ulCreateDaqDevice(devDescriptors[descriptorIndex]);

	if (daqDeviceHandle == 0)
	{
		printf ("\nUnable to create a handle to the specified DAQ device\n");
		goto end;
	}

	// verify the specified device supports analog output
	err = getDevInfoHasAo(daqDeviceHandle, &hasAO);
	if (!hasAO)
	{
		printf("\nThis device does not support analog output\n");
		goto end;
	}

	// verify the specified DAQ device supports hardware pacing for analog output
	err = getAoInfoHasPacer(daqDeviceHandle, &hasPacer);
	if (!hasPacer)
	{
		printf("\nThe specified DAQ device does not support hardware paced analog output\n");
		goto end;
	}

    // create a connection to the device
	err = ulConnectDaqDevice(daqDeviceHandle);

	if (err != ERR_NO_ERROR)
		goto end;

    printf("\nConnecting to device %s - please wait ...\n", devDescriptors[descriptorIndex].devString);

    // get the first supported output range
	err = getAoInfoFirstSupportedRange(daqDeviceHandle, &range, rangeStr);

    // allocate a buffer for the output data
    buffer = (double*) malloc(chanCount * samplesPerChannel * sizeof(double));

    if(buffer == NULL)
    {
        printf("\nOut of memory, unable to create scan buffer\n");
        goto end;
    }


    // fill the buffer with data
    generateAnalogSignal(10000, 0, 0.02, rate, range, SIG_SIN, buffer);

    

    // get the first supported trigger type (this returns a digital trigger type)
	getAoInfoFirstTriggerType(daqDeviceHandle, &triggerType, triggerTypeStr);

    ConvertScanOptionsToString(scanOptions, scanOptionsStr);

	printf("\n%s ready\n", devDescriptors[descriptorIndex].devString);
	printf("    Function demonstrated: ulAOutscan()\n");
	printf("    Channels: %d - %d\n", lowChan, highChan);
	printf("    Range: %s\n", rangeStr);
	printf("    Samples per channel: %d\n", samplesPerChannel);
	printf("    Rate: %f\n", rate);
    printf("    Scan options: %s\n", scanOptionsStr);
    printf("    Trigger type: %s\n", triggerTypeStr);
	printf("\nHit ENTER to continue\n");

	ret = scanf("%c", &c);

	// clear the display
	ret = system("clear");

    // set the trigger
    // ulAOutSetTrigger(daqDeviceHandle, TRIG_POS_EDGE, 0, 0, 0, 0);

	// start the output
	err = ulAOutScan(daqDeviceHandle, lowChan, highChan, range, samplesPerChannel, &rate, scanOptions, flags, buffer);

    if(err == ERR_NO_ERROR)
	{
		ScanStatus status;
		TransferStatus transferStatus;

        // get the initial status of the acquisition
        ulAOutScanStatus(daqDeviceHandle, &status, &transferStatus);
        
        printf ("Hit 'Enter' to quit waiting for trigger\n\n");
		printf("Active DAQ device: %s (%s)\n\n", devDescriptors[descriptorIndex].productName, devDescriptors[descriptorIndex].uniqueId);
		printf ("Waiting for trigger ...\n");

        while(status == SS_RUNNING && err == ERR_NO_ERROR && !enter_press())
		{
			// get the current status of the background operation
			err = ulAOutScanStatus(daqDeviceHandle, &status, &transferStatus);
            index = transferStatus.currentIndex;
			
            if(err == ERR_NO_ERROR && index >= 0)
			{
				// reset the cursor to the top of the display and
				// show the termination message
				// resetCursor();
				// printf("Hit 'Enter' to terminate the process\n\n");
				// printf("Active DAQ device: %s (%s)\n\n", devDescriptors[descriptorIndex].productName, devDescriptors[descriptorIndex].uniqueId);
				printf("actual scan rate = %f\n\n", rate);

				// index = transferStatus.currentIndex;
				printf("currentScanCount =  %-10llu \n", transferStatus.currentScanCount);
				printf("currentTotalCount = %-10llu \n", transferStatus.currentTotalCount);
				printf("currentIndex =      %-10d \n\n", index);

				usleep(100000);
			}
		}
        // stop the output if it is still running
		if (status == SS_RUNNING && err == ERR_NO_ERROR)
		{
			err = ulAOutScanStop(daqDeviceHandle);
		}
    }

    // disconnect from the device
	ulDisconnectDaqDevice(daqDeviceHandle);


end:

	// release the handle to the DAQ device
	ulReleaseDaqDevice(daqDeviceHandle);

	// release the scan buffer
	if(buffer)
		free(buffer);

	if(err != ERR_NO_ERROR)
	{
		char errMsg[ERR_MSG_LEN];
		ulGetErrMsg(err, errMsg);
		printf("Error Code: %d \n", err);
		printf("Error Message: %s \n", errMsg);
	}

	return 0;


}


void generateAnalogSignal(int fs, double phase, double duration, int samplingrate, Range range, SIGNAL_TYPE signaltype, double* buffer) 
{
    // [ATTENTION!] This function only suitable for single channel signal generation, and only support Channel 0.
    // If user want to generate signal for channel, please halve the analogAmplitude.

    // Amplitiude of the signal
    double min,max;
    ConvertRangeToMinMax(range,&min,&max);
    double analogAmplitude = max - min;
    double dt = 1.0/samplingrate;
    double sampleNum = samplingrate * duration;

    int index = 0;

    switch (signaltype)
    {
        case SIG_SIN:{
            for (int sample = 0; sample < sampleNum; sample++)
            {
                buffer[index++] =  (double) (sin(phase) * analogAmplitude/2);
                phase += 2 * M_PI * ((double)fs/(double)samplingrate);
                if (phase > 2 * M_PI) {
                    phase -= 2 * M_PI;
                }
            }
            break;
        }

        case SIG_COS:{
            for (int sample = 0; sample < sampleNum; sample++)
            {
                buffer[index++] =  (double) (cos(phase) * analogAmplitude/2);
                phase += 2 * M_PI * (fs/samplingrate);
                if (phase > 2 * M_PI) {
                    phase -= 2 * M_PI;
                }
            }
            break;
        }

        case SIG_CHRIP:{
            // not implemented yet
            break;
        }
    
        default:
            break;
    }

}


UlError ConfigureAnalogOutputChannels(int numberOfChannels, Range range, DaqOutChanDescriptor* descriptors, int* scanDesriptorIndex)
{
	UlError err = ERR_NO_ERROR;
	int numbeOfAnalogChans = 0;
	int i;
	int index = *scanDesriptorIndex;

		// fill a descriptor for each channel
	for (i = 0; i< numberOfChannels; i++)
	{
		descriptors[index].channel = i;
		descriptors[index].type = DAQO_ANALOG;
		descriptors[index].range = range;
		index++;

		numbeOfAnalogChans++;

		if (numbeOfAnalogChans == numberOfChannels)
			break;
	}

	*scanDesriptorIndex = index;

	return err;
}

And in "utility.h", I append a new function to get Analog Output Info.

UlError getAoInfoFirstTriggerType(DaqDeviceHandle daqDeviceHandle, TriggerType* triggerType, char* triggerTypeStr)
{
	UlError err = ERR_NO_ERROR;
	long long triggerTypes = 0;

	err = ulAOGetInfo(daqDeviceHandle, AO_INFO_TRIG_TYPES, 0, &triggerTypes);

	if (err == ERR_NO_ERROR && triggerTypes != 0)
	{
		// use the first available trigger type
		long long triggerMask = 1;
		while ((triggerTypes & triggerMask) == 0)
			triggerMask = triggerMask << 1;

		*triggerType = (TriggerType)triggerMask;

		ConvertTriggerTypeToString(*triggerType, triggerTypeStr);
	}

	return err;
}

 

Edited by Jin
Link to comment
Share on other sites

0 answers to this question

Recommended Posts

There have been no answers to this question yet

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...