LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

How to use ANSI C/ C++ to control a USB-6216 BNC device

Solved!
Go to solution
Solution
Accepted by topic author Fuh

Thank you all so much for your time and kindness to help me out! Greatly appreciated!!!

 

I found a horrible mistake in my code. The closing curly bracket for the switch statements was in a wrong spot. How stupid can I be? I moved this closing curly bracket to an appropriate place (i.e., immediately after the printf("Unrecognizable sequence number") statement. And the error message disappeared. Hooray!!!

 

However, as you have foreseen and indicated in your comments, the AO and AI tasks will stop immediately after they are started. So, I did the following modifications to the program. And it WORKED!!!!

  1. I changed the AO task sample mode to finite samples, so that the status of the DAQmxIsTaskDone() function returns true when N samples have been written to the AO buffer successfully.
  2. I added DAQmxWaitUntilDone() and DAQmxIsTaskDone() functions in Step 11, to check if the AO task is done.
  3. I included Steps 3-12 inside the For loop

 

I am very happy for what I have learned so far. I love NI Discussion Forum. I do. Call this a flattery if you want. But I do appreciate your kindness and time to help me out.

 

I guess now the only major thing left is that Step 13 is somewhat meaningless, because the user can no longer interrupt the program once the For loop has started. It appears to me that this requires some knowledge of multithreading, which I currently do not possess. I will spend some time to study on this subject, and will get back to this forum at a later time.

 

For your review and advising, I am posting my revised program below for comments. Please feel free to let me know if there is anything that can be done to further improve this program.

 

Thank you SO MUCH!!!

 

#include <stdio.h>
#include <NIDAQmx.h>			// DAQmx 9.3
#include <math.h>			// sin()

#define DAQmxErrChk(functionCall) if( DAQmxFailed(error=(functionCall)) ) goto Error; else

#define PI 3.141592653589793238

// function prototypes
int32 CVICALLBACK EveryNCallback(TaskHandle taskHandleAI, int32 everyNsamplesEventType, uInt32 nSamples, void *callbackData);
void StopTaskAOAI();
	
// initialize parameters at a global scope, so they are accessible inside any subroutine functions.
const unsigned int N = 10000;				// number of data points (This number refers to the number of data points per sweep, which include the stimulus duration and silent interval data points)
const unsigned int BUFFER_SIZE = N; 			// buffer size in data points, [default 1000]. 

// declare nSweeps parameters
const unsigned int N_SWEEPS_TARGET = 10;		// number of sweeps to be obtained (i.e., the targeted number of sweeps to be obtained after the user has initiated the AI task)
unsigned int nSweepsRecorded = 0;			// number of sweeps that have been obtained via AI task

// declare and initialize an error code and error buffer. This will be used for both the AO and AI tasks. 
int32 error = 0;					// error code
char errBuff[2048] = {'\0'};				// error message

// create and initialize AO and AI task handles
TaskHandle  taskHandleAO = 0;
TaskHandle  taskHandleAI = 0;

int main(void)
{
	// prepare two sine waves that will be delivered via an AO channel, in a pre-defined arbitrary sequence
	double frequency1 = 100;				// frequency in Hz, for stimulus 1
	double frequency2 = 50;					// frequency in Hz, for stimulus 2
	double amplitude = 1.0;					// baseline-to-peak amplitude of a sine wave (roughly in volts). Should be between +- 10 volts.
	double samplingRateWav = 20000.0;			// sampling rate of the sine wave
	float64 stimulus1[N];					// stimulus 1 (e.g., a 100 Hz tone)
	float64 stimulus2[N];					// stimulus 2 (e.g., a 50 Hz tone)
	for (int i = 0; i < N; i++)				// generate two sine waves (i.e., stimulus 1 and stimulus 2)
	{
		stimulus1[i] = amplitude * sin(2.0 * PI * frequency1 * (double)(i) / samplingRateWav);	
		stimulus2[i] = amplitude * sin(2.0 * PI * frequency2 * (double)(i) / samplingRateWav);	
	}
	
	// a variable indicating whether the AO task is done
	bool32 isTaskDoneAO = false;

	// arbitrarily define a presentation sequence 
	int sequence[N_SWEEPS_TARGET] = {1, 1, 2, 1, 1, 1, 2, 1, 1, 1};		// 1 for stimulus 1, and 2 for stimulus 2

	/* ---- Step 1 User presses Enter to start AO and AI tasks ----*/
	printf("Press Enter to start AO and AI tasks");
	getchar(); 

	/* ---- Step 2 Loop through AO and AI tasks for N_SWEEPS_TARGET times ---- */
	for (unsigned int sweep = 0; sweep < N_SWEEPS_TARGET; sweep++)
	{
		/* --- Step 3 Create AO and AI tasks --- */
		DAQmxErrChk(DAQmxCreateTask("taskAO", &taskHandleAO));	
		DAQmxErrChk(DAQmxCreateTask("taskAI", &taskHandleAI));

		/* --- Step 4 Create and configure an Analog Output Voltage channel and an Analog Input Voltage channel --- */
		DAQmxErrChk(DAQmxCreateAOVoltageChan(taskHandleAO, "Dev1/ao0", "", -10.0, 10.0, DAQmx_Val_Volts, NULL));	
		DAQmxErrChk(DAQmxCreateAIVoltageChan(taskHandleAI, "Dev1/ai0", "", DAQmx_Val_Cfg_Default, -10.0, 10.0, DAQmx_Val_Volts, NULL));

		/* --- Step 5 Define sampling rate and related parameters for the AO task and the AI task ---*/
		DAQmxErrChk(DAQmxCfgSampClkTiming(taskHandleAO, "", 20000.0, DAQmx_Val_Rising, DAQmx_Val_FiniteSamps, N)); 	
		DAQmxErrChk(DAQmxCfgSampClkTiming(taskHandleAI, "", 20000.0, DAQmx_Val_Rising, DAQmx_Val_FiniteSamps, BUFFER_SIZE));	

		/* --- Step 6 setup a Digital Edge, Start Trigger --- */
		DAQmxErrChk(DAQmxCfgDigEdgeStartTrig(taskHandleAO, "/Dev1/ai/StartTrigger", DAQmx_Val_Rising));

		/* --- Step 7 setup parameters for AI buffer ---*/
		DAQmxErrChk(DAQmxRegisterEveryNSamplesEvent(taskHandleAI, DAQmx_Val_Acquired_Into_Buffer, BUFFER_SIZE, 0, EveryNCallback, NULL));

		/* ---- Step 8 write signal via AO ---- */
		switch (sequence[nSweepsRecorded])
		{
			case 1:
				DAQmxErrChk(DAQmxWriteAnalogF64(taskHandleAO, N, 0, 10.0, DAQmx_Val_GroupByChannel, stimulus1, NULL, NULL));
				break;
			case 2:
				DAQmxErrChk(DAQmxWriteAnalogF64(taskHandleAO, N, 0, 10.0, DAQmx_Val_GroupByChannel, stimulus2, NULL, NULL));
				break;
			default:
				printf("Unrecognizable sequence number");
		}	

		/* ---- Step 9 start AO and AI tasks --- */
		DAQmxErrChk(DAQmxStartTask(taskHandleAO));
		DAQmxErrChk(DAQmxStartTask(taskHandleAI));

		/* --- Step 10 read data via AI ----*/
		// This step is executed through EveryNCallback() function --- 

		/* ---- Step 11 waite until AO task is done ----*/
		DAQmxErrChk(DAQmxWaitUntilTaskDone(taskHandleAO, 10));
		DAQmxErrChk(DAQmxIsTaskDone(taskHandleAO, &isTaskDoneAO));

		/* ---- Step 12 stop and clear AO and AI tasks ---- */
		if (isTaskDoneAO)	
			StopTaskAOAI();
		else
			printf("AO task got timed out.\n");
	}

	/*--- Step 13 User presses Enter to exit the program --- */
	printf("Press Enter to stop AO and AI tasks\n");
	getchar(); 
	
Error:
	if( DAQmxFailed(error) )
		DAQmxGetExtendedErrorInfo(errBuff, 2048);
	if( taskHandleAI!=0 ) 
	{
		StopTaskAOAI();
	}
	if( DAQmxFailed(error) )
		printf("DAQmx Error: %s\n", errBuff);
	printf("End of program, press Enter to quit\n");
	getchar(); 
	return 0;
}

// A function to execute when every N samples have been obtained via AI
int32 CVICALLBACK EveryNCallback(TaskHandle taskHandleAI, int32 everyNsamplesEventType, uInt32 nSamples, void *callbackData)
{
	static int  totalRead = 0;
	int32       read = 0;
	float64     data[BUFFER_SIZE];		// N

	/*********************************************/
	// DAQmx Read Code
	/*********************************************/
	DAQmxErrChk(DAQmxReadAnalogF64(taskHandleAI, BUFFER_SIZE, 10.0, DAQmx_Val_GroupByScanNumber, data, BUFFER_SIZE, &read, NULL));  // N, N
	if( read > 0 ) 
	{
		totalRead += read;				// increment totalRead
		nSweepsRecorded++;				// increment nSweepsRecorded
		printf("Sweep %d: Acquired %d samples, total %d samples.\n", nSweepsRecorded, read, totalRead);

		if (nSweepsRecorded == N_SWEEPS_TARGET)		// If N_SWEEPS_TARGET has been obtained, stop AO and AI tasks.
		{
			StopTaskAOAI();							
			printf("%d sweeps have been obtained. Press Enter to exit.\n", N_SWEEPS_TARGET);
		}
	}

Error:
	if( DAQmxFailed(error) ) 
	{
		DAQmxGetExtendedErrorInfo(errBuff, 2048);
		StopTaskAOAI();							
		printf("DAQmx Error: %s\n", errBuff);  		/* NOTE: If an error occurs here, the user will see the error message and will respond accordingly*/
	}
	return 0;						
}

// A function to stop and clear AO and AI tasks
void StopTaskAOAI()
{
	/* --- stop AI and AO tasks --- */
	DAQmxStopTask(taskHandleAO);
	DAQmxStopTask(taskHandleAI);

	/* --- clear AI and AO tasks --- */
	DAQmxClearTask(taskHandleAO);
	DAQmxClearTask(taskHandleAI);

	/* --- reset AI and AO task handles --- */
	taskHandleAO = 0;
	taskHandleAI = 0;
}

 

0 Kudos
Message 21 of 21
(1,672 Views)