//************************************ // Method: setupCLK // FullName: fetch::device::NationalInstrumentsDAQ::setupCLK // Access: public // Returns: void // Qualifier: // // set up counter for sample clock // - A finite pulse sequence is generated by a pair of on-board counters. // In testing, it appears that after the device is reset, initializing // the counter task doesn't work quite right. First, I have to start the // task with the paired counter once. Then, I can set things up normally. // After initializing with the paired counter once, things work fine until // the device (or computer) is reset. My guess is this is a fault of the // board or driver software. // - below, we just cycle the counters when config gets called. This ensures // everything configures correctly the first time, even after a device // reset or cold start. //************************************ void NationalInstrumentsDAQ::setupCLK(float64 nrecords, float64 record_frequency_Hz) { TaskHandle clk = 0; int32 N = _config->ao_samples_per_waveform(); float64 hz = computeSampleFrequency(nrecords, record_frequency_Hz); const char *dev =_config->name().c_str(), *ctr =_config->ctr().c_str(), *armstart_in =_config->armstart().c_str(), *gate_out =_config->frame_trigger_out().c_str(), *trig =_config->trigger().c_str(); float64 lvl =_config->level_volts(); char term_ctr[1024]={0}, term_gate[1024]={0}, term_arm_out[1024]={0}; make_terminal_name(term_ctr ,sizeof(term_ctr) ,dev,ctr); make_terminal_name(term_gate ,sizeof(term_gate) ,dev,ctr); strcat(term_gate,"Gate"); make_terminal_name(term_arm_out,sizeof(term_arm_out),dev,gate_out); DAQERR( DAQmxClearTask(_clk.daqtask) ); // Once a DAQ task is started, it needs to be cleared before restarting DAQERR( DAQmxCreateTask("fetch_CLK",&_clk.daqtask)); clk = _clk.daqtask; DAQERR(DAQmxCreateCOPulseChanFreq (clk,term_ctr,NULL,DAQmx_Val_Hz,DAQmx_Val_Low,0.0,hz,0.5)); DAQERR(DAQmxCfgImplicitTiming (clk,DAQmx_Val_FiniteSamps,N)); DAQERR(DAQmxCfgDigEdgeStartTrig (clk,"AnalogComparisonEvent",DAQmx_Val_Rising)); DAQERR(DAQmxSetArmStartTrigType (clk,DAQmx_Val_DigEdge)); // Arm trigger has to be through clk DAQERR(DAQmxSetDigEdgeArmStartTrigSrc (clk,armstart_in)); DAQERR(DAQmxSetDigEdgeArmStartTrigEdge(clk,DAQmx_Val_Rising)); DAQERR(DAQmxSetStartTrigRetriggerable (clk,1)); DAQERR(DAQmxConnectTerms(term_gate,term_arm_out,DAQmx_Val_DoNotInvertPolarity)); }
int32 Tweezers::TriggerFrames(unsigned int nr) { //DAQmxErrRtn(DAQmxStopTask(DOtaskHandle)); DAQmxErrRtn(DAQmxCfgImplicitTiming(DOtaskHandle, DAQmx_Val_FiniteSamps, 1)); DAQmxErrRtn(DAQmxStartTask(DOtaskHandle)); DAQmxErrRtn(DAQmxWaitUntilTaskDone(DOtaskHandle,-1)); DAQmxErrRtn(DAQmxStopTask(DOtaskHandle)); }
int32 Tweezers::CurrentRun(float64* curr, float64* indata, void* lpParam) { threadinfo* t = (threadinfo*)lpParam; // config and start analog tast DAQmxErrRtn(DAQmxCfgSampClkTiming(AOtaskHandle,"",10*float64(1/(*t->delta*1E-3)),DAQmx_Val_Rising,DAQmx_Val_FiniteSamps,(*t->cycles*10*t->nofFrames))); DAQmxErrRtn(DAQmxCfgOutputBuffer(AOtaskHandle, t->nofFrames*10)); DAQmxErrRtn(DAQmxCfgDigEdgeStartTrig(AOtaskHandle, "PFI0", DAQmx_Val_Rising)); DAQmxErrRtn(DAQmxWriteAnalogF64(AOtaskHandle,t->nofFrames*10,0,10.0,DAQmx_Val_GroupByChannel,curr,&written,NULL)); DAQmxErrRtn(DAQmxStartTask(AOtaskHandle)); cerr << "\nTrying to allocate buffer for " << (*t->cycles * t->nofFrames) << " frames\n"; // config and start pulse channel with parameters set by user //DAQmxErrRtn(DAQmxCfgImplicitTiming(DOtaskHandle, DAQmx_Val_FiniteSamps,*t->cycles * t->nofFrames)); DAQmxErrRtn(DAQmxCfgImplicitTiming(DOtaskHandle, DAQmx_Val_ContSamps,1)); DAQmxErrRtn(DAQmxCfgDigEdgeStartTrig(DOtaskHandle, "PFI0", DAQmx_Val_Rising)); DAQmxErrRtn(DAQmxStartTask(DOtaskHandle)); // config analog in task DAQmxErrRtn(DAQmxCfgSampClkTiming(AItaskHandle,"Ctr0Out",100,DAQmx_Val_Rising,DAQmx_Val_FiniteSamps,*t->cycles * t->nofFrames)); DAQmxErrRtn(DAQmxStartTask(AItaskHandle)); // set trigger line to 1 - GO! DAQmxWriteDigitalLines(TRtaskHandle,1,1,10,DAQmx_Val_GroupByChannel,trigdata[1],&written,NULL); // wait until cam trigger task is done DAQmxWaitUntilTaskDone(AOtaskHandle,-1); // reset trigger line DAQmxWriteDigitalLines(TRtaskHandle,1,1,10,DAQmx_Val_GroupByChannel,trigdata[0],&written,NULL); // read protocol samples DAQmxReadAnalogF64(AItaskHandle,*t->cycles * t->nofFrames,5.0,DAQmx_Val_GroupByChannel,indata,*t->cycles * t->nofFrames*2,&read,NULL); //read indeed current ofstream strom; strom.open("newcurrent.txt", ofstream::app); for(int i=0;i<t->nofFrames;i++) strom<<i*(*t->delta*1E-3)<<"\t"<<indata[i]<<endl; strom.close(); // stop tasks, disable trigger DAQmxStopTask(AOtaskHandle); DAQmxStopTask(DOtaskHandle); DAQmxStopTask(AItaskHandle); DAQmxDisableStartTrig(AOtaskHandle); DAQmxDisableStartTrig(DOtaskHandle); }
void TriggerFrames(unsigned int nr, double extime) { char errBuff[2048]; // int32 error; TaskHandle DOtaskHandle; DAQmxCreateTask("DO",&DOtaskHandle); //cerr<<"sending trigger pulse: "<<extime*1E-3<<" secs!\n"; DAQmxCreateCOPulseChanTime(DOtaskHandle,"Dev1/Ctr0","",DAQmx_Val_Seconds,DAQmx_Val_Low,0.0,extime*1E-3,extime*1E-3); //DAQmxCfgImplicitTiming(DOtaskHandle, DAQmx_Val_ContSamps, 1); DAQmxCfgImplicitTiming(DOtaskHandle, DAQmx_Val_FiniteSamps, 1); DAQmxStartTask(DOtaskHandle); DAQmxWaitUntilTaskDone(DOtaskHandle,-1); DAQmxStopTask(DOtaskHandle); DAQmxClearTask(DOtaskHandle); DAQmxGetExtendedErrorInfo(errBuff,2048); cerr<<errBuff; }
//Function: Run //Description: Runs acquisition routine in a new thread // This function cannot access gui widgets so all variables are frozen when thread class instance is created void AcqThread::run() { int error=0; TaskHandle digTaskHandle=0; bool done; int retVal; int numZSteps; int iZCount; int x1; int x2; int y1; int y2; int numValidXSamps; int numValidYSamps; double debug; //set to not be terminated (default) terminate = false; //scaling coeff has not been calculated for this acq yet bScaleCoeffCalc = false; //overscan values have not yet been calculated into the fov scanEng->setOverscanCalculated(false); done = false; do { //if regular acq (not line scan), call generateWaveForms if(!bLinescan) { scanEng->initScan(true,false); retVal = scanEng->generateWaveForms(); retVal = acqEng->initAcq(true,false); } else //Line scan mode { retVal = scanEng->initScan(true,true); if(!NIVisionCurrContourInfo) { emit sendMessageForPopup("Error","No data points defined\n"); goto Error; } if (NIVisionCurrContourInfo->type != IMAQ_LINE) { emit sendMessageForPopup("Error","Points must be defined with line tool\n"); goto Error; } //grab endpoints from line contour x1=NIVisionCurrContourInfo->structure.line->start.x; y1=NIVisionCurrContourInfo->structure.line->start.y; x2=NIVisionCurrContourInfo->structure.line->end.x; y2=NIVisionCurrContourInfo->structure.line->end.y; //Update data class data2P->Header.setLsX1(x1); data2P->Header.setLsX2(x2); data2P->Header.setLsY1(y1); data2P->Header.setLsY2(y2); //Calc the voltages that correspond to the x1,y1,x2,y2. These will define the line scan waveforms. double x1V,y1V,x2V,y2V; CalcXYVoltsFromPxlVal(x1, y1, x1V, y1V); scanEng->setROIPt1XVolts(x1V); scanEng->setROIPt1YVolts(y1V); CalcXYVoltsFromPxlVal(x2, y2, x2V, y2V); scanEng->setROIPt2XVolts(x2V); scanEng->setROIPt2YVolts(y2V); retVal = scanEng->generateLineScanWaveForms(); retVal = acqEng->initAcq(true,true); } //_____Setup for 3D Acq if needed_____ if (acqEng->getB3DAcq()) { numZSteps = this->CalcNumZSteps(); CalcIntensityScalingCoeff(); } else numZSteps = 1; //_____DAQmx DigOut Configure Code (Sample clock for Aout and Ain)____________________________________________ DAQmxErrChk (DAQmxCreateTask("SampleClockTask",&digTaskHandle)); DAQmxErrChk (DAQmxCreateCOPulseChanFreq (digTaskHandle, "/Dev1/ctr1", "SampleClock", DAQmx_Val_Hz, DAQmx_Val_Low, 0.1, scanEng->getSamp_Rate(), 0.5)); if (bLinescan) DAQmxErrChk (DAQmxCfgImplicitTiming(digTaskHandle,DAQmx_Val_ContSamps ,scanEng->getNumSampsPerFrame_LS())) else DAQmxErrChk (DAQmxCfgImplicitTiming(digTaskHandle,DAQmx_Val_ContSamps ,scanEng->getNumSampsPerFrame())) //_____config AOut task for triggered, finite samps_____ retVal = scanEng->configDAQmxTask(true, false); //_____Write samples to daq board_____ retVal = scanEng->writeDAQmxTask(); //_____Config AIn task for triggered, finite samps_____ retVal = acqEng->configDAQmxTask(true, false); pDone = 0; for (iZCount = 0; iZCount < numZSteps; iZCount++) { //Only if there are Z steps to do if(numZSteps>1) { //update Z Pos zStep.setDesiredZPos(acqEng->getZStartPos() + (acqEng->getZStepSize() * iZCount)); //if (zStep->getDesiredZPos() != acqEng->getZPos()) if(numZSteps!=1) zStep.MoveTo(zStep.getDesiredZPos(),zStep.getCurrentStepConvFactor()); //Manual zPos Calculations //acqEng->setZPos(acqEng->getZPos()+acqEng->getZStepSize()); acqEng->setZPos(zStep.getCurrentZPos()); emit sigZPosChange(zStep.getCurrentZPos()); //Update pDone for updating gui progress bar pDone = ((double)iZCount)/((double)numZSteps); emit sendProgress(pDone); //update gui field //TwoPhotonGui::doubleSpinBox_zPos->setValue(zStepEng->getCurrentZPos()); NEED IMPLEMENTATION //update acqEng field //acqEng->setZPos(zStep->getCurrentZPos()); NOTE: this isn't working, using manual z-pos calculations } //if Aom Voltage scaling is selected, update Aom if(aomCtrl->getBIntScaling()) { debug = CalcAomIntVoltage((acqEng->getZStartPos()-acqEng->getZPos())); AomUpdate(debug); //turns AOM on } else { AomUpdate(aomCtrl->getAomOnVoltage()); //Turns on AOM (no updating for depth) } //_____Start DAQmx Read._____ retVal = acqEng->startDAQmxTask(); //_____Start DAQmx write._____ retVal = scanEng->startDAQmxTask(); //_____Start DAQmx Trig._____ DAQmxErrChk (DAQmxStartTask(digTaskHandle)) //_____Perform read. Execution will pause until all samps acquired._____ retVal = acqEng->readDAQmxTask(); /* Added for diagnostics. I want to write out the acq buffer here before I flip even rows. */ /* NEED IMPLEMENTATION //_____Update Histogram._____ retVal = ProcessDataForHistogram(appState->acqStruct); if (appState->acqStruct.bInput1) DeleteGraphPlot (appState->panelHandle, PANEL_HIST1, -1, VAL_IMMEDIATE_DRAW); PlotXY (appState->panelHandle, PANEL_HIST1, appState->binsArray, appState->histArray1, NUM_BINS, VAL_SHORT_INTEGER, VAL_UNSIGNED_INTEGER, VAL_VERTICAL_BAR, VAL_SOLID_SQUARE, VAL_SOLID, 1, VAL_BLUE); if (appState->acqStruct.bInput2) DeleteGraphPlot (appState->panelHandle, PANEL_HIST2, -1, VAL_DELAYED_DRAW); PlotXY (appState->panelHandle, PANEL_HIST2, appState->binsArray, appState->histArray2, NUM_BINS, VAL_SHORT_INTEGER, VAL_UNSIGNED_INTEGER, VAL_VERTICAL_BAR, VAL_SOLID_SQUARE, VAL_SOLID, 1, VAL_BLUE); */ //Update image display retVal = ProcessDataForDisplay(bLinescan); if(!bLinescan) { numValidXSamps = (int)acqEng->getnumValidXSamps(); numValidYSamps = (int)acqEng->getnumValidYSamps(); if (!bLifetimeFov) { //Had to move imaq.. calls out of this thread. Wasn't updating when called from this thread. // using signal to notify other thread that new image data are in the image pointers. imaqArrayToImage(*ptrToimage1, *ptrToimageData1, (int)acqEng->getnumValidXSamps(),(int)acqEng->getnumValidYSamps()); imaqDisplayImage(*ptrToimage1, displayWinNum1, 1); //emit this->sigUdateVisionWindows(displayWinNum1,numValidXSamps,numValidYSamps); } } else { numValidXSamps = (int)acqEng->getWidth(); numValidYSamps = (int)acqEng->getRepeats(); if (!bLifetimeFov) { imaqArrayToImage(*ptrToimage2, *ptrToimageData2, (int)acqEng->getWidth(),(int)acqEng->getRepeats()); imaqDisplayImage(*ptrToimage2, displayWinNum2, 1); //emit this->sigUdateVisionWindows(displayWinNum2,numValidXSamps,numValidYSamps); } } //imaqHistogram(image1,65536,0,1,NULL); //Update Data2P class instance before writing it to file updateDataPtr(); //Save the data to file if requested if (acqEng->getSaveData()) { if(!bLinescan) { Update2PDataStruct(); if (acqEng->getBInput1()) retVal = data2P->WriteTheData(1,acqEng); if (acqEng->getBInput2()) retVal = data2P->WriteTheData(2,acqEng); } else //If linescan, need to record correct lineLength/lineRate { retVal =scanEng->calcLineLengthStruct(x1,y1,x2,y2); retVal =scanEng->calcLineRate(); Update2PDataStruct(); data2P->Header.setLineRate(data2P->Header.getLinescanRate()); //ensure linerate recorded is that of linescan if (acqEng->getBInput1()) retVal = data2P->WriteTheData(1,acqEng); if (acqEng->getBInput2()) retVal = data2P->WriteTheData(2,acqEng); } } DAQmxStopTask(digTaskHandle); retVal = acqEng->stopDAQmxTask(); retVal = scanEng->stopDAQmxTask(); //retVal = scanEng->clearDAQmxTask(); //scanEng->setScanTaskHandle(0); if(terminate) goto Kill; //turn off Aom until ready to image again (set to 0 volts) AomUpdate(0.0); aomCtrl->setAomOn(false); } Kill: retVal = scanEng->stopDAQmxTask(); //Cleanup ... // retVal = AcqEngineStopDAQmxTask(acqStruct); DAQmxClearTask(scanEng->getScanTaskHandle()); scanEng->setScanTaskHandle(0); // retVal = ScanEngineStopDAQmxTask(scanStruct); DAQmxClearTask(acqEng->getAcqTaskHandle()); acqEng->setAcqTaskHandle(0); DAQmxClearTask(digTaskHandle); scanEng->releaseMemory(); acqEng->releaseMemory(); }while(bContinuous && (!terminate)); /* SetCtrlVal(appState->panelHandle,PANEL_ledRunning,0); NEED IMPLEMENTATION SetCtrlVal(appState->panelHandle,PANEL_ledAcquiring,0); SetCtrlVal(appState->panelHandle,PANEL_cbx3DAcq,0); SetCtrlVal(appState->panelHandle,PANEL_cbxSave,0); */ //Disable Aom (set to 0 volts)-------------------- AomUpdate(0.0); aomCtrl->setAomOn(false); bScaleCoeffCalc = false; pDone = 0; emit acqFinished(); quit(); return; Error: //return; if( DAQmxFailed(error) ) DAQmxGetExtendedErrorInfo(errBuff,2048); //DAQmxDisconnectTerms ("/Dev1/PFI12", "/Dev1/PFI1"); if( digTaskHandle!=0 ) { // _____DAQmx Stop Code DAQmxStopTask(digTaskHandle); DAQmxClearTask(digTaskHandle); } if( scanEng->getScanTaskHandle() != 0 ) { DAQmxStopTask(scanEng->getScanTaskHandle()); DAQmxClearTask(scanEng->getScanTaskHandle()); scanEng->setScanTaskHandle(0); //SetCtrlVal(appState->panelHandle,PANEL_ledRunning,0); NEED IMPLEMENTATION //SetCtrlVal(appState->panelHandle,PANEL_ledAcquiring,0); } if( acqEng->getAcqTaskHandle() != 0 ) { DAQmxStopTask(acqEng->getAcqTaskHandle()); DAQmxClearTask(acqEng->getAcqTaskHandle()); acqEng->setAcqTaskHandle(0); } if (scanEng->getMemIsAllocated()) scanEng->releaseMemory(); if (acqEng->getMemIsAllocated()) acqEng->releaseMemory(); // if( DAQmxFailed(error) ) // QMessageBox::about(this,"DAQmx Error",errBuff); emit sendMessageForPopup("DAQmx Error",errBuff); emit acqFinished(); return; }
void ScanThreadLinear::InitializeSyncAndScan(void) { //CLEAR TASKS DAQmxClearTask(taskClock); DAQmxClearTask(taskTrig); DAQmxClearTask(taskTrA); DAQmxClearTask(taskAnalog); Samps = globalOptions->IMAGEHEIGHT+NumPtsDw; LineRate = Samps*FrameRate; //CREATE TASKS DAQmxCreateTask("",&taskAnalog); DAQmxCreateTask("",&taskTrig); DAQmxCreateTask("",&taskTrA); DAQmxCreateTask("",&taskClock); /************************* CLOCK SOURCE *************************/ //CREATE INTERNAL CLOCK SOURCE DAQmxCreateCOPulseChanFreq(taskClock, "Dev1/ctr0", "", DAQmx_Val_Hz, DAQmx_Val_Low, __DDELAY, FrameRate, .2); /************************* DIGITAL PULSE TRAIN *************************/ //CREATE DIGITAL LINE DAQmxCreateDOChan(taskTrig,"Dev1/port0/line0","",DAQmx_Val_ChanPerLine); //SET TIMING AND STATE CLOCK SOURCE //Clock source is based off the analog sample clock DAQmxCfgSampClkTiming(taskTrig,"ao/SampleClock",FrameRate*Samps, DAQmx_Val_Rising,DAQmx_Val_ContSamps,Samps); /************************* ANALOG SAW TOOTH *************************/ //CREATE ANALOG CHANNEL DAQmxCreateAOVoltageChan(taskAnalog,"Dev1/ao0", "",-10,10.0,DAQmx_Val_Volts,NULL); DAQmxCreateAOVoltageChan(taskAnalog,"Dev1/ao1", "",-10,10.0,DAQmx_Val_Volts,NULL); //SET TIMING DAQmxCfgSampClkTiming(taskAnalog,"",FrameRate*Samps, DAQmx_Val_Rising,DAQmx_Val_ContSamps,Samps); //GET TERMINAL NAME OF THE TRIGGER SOURCE GetTerminalNameWithDevPrefix(taskTrig, "Ctr0InternalOutput",trigName); //TRIGGER THE ANALOG DATA BASED OFF INTERNAL TRIGGER (CLOCK SOURCE) DAQmxCfgDigEdgeStartTrig(taskAnalog,trigName,DAQmx_Val_Rising); if (globalOptions->bVolumeScan == false) { GenSawTooth(Samps,XScanVolts_mV,XScanOffset_mV,ScanBuff); for (int i = 0; i< Samps; i++) VolBuff[i] = ScanBuff[i]; for (int i = Samps; i < 2*Samps; i++) VolBuff[i] = YScanOffset_mV/1000; DAQmxWriteAnalogF64(taskAnalog, Samps, false ,10 ,DAQmx_Val_GroupByChannel, VolBuff,NULL,NULL); //GENERATE PULSE TRAIN TO TRIGGER CAMERA GenPulseTrain(Samps,digiBuff); DAQmxWriteDigitalLines(taskTrig,Samps,false,10.0,DAQmx_Val_GroupByChannel,digiBuff,NULL,NULL); } else { int frameCount; GenSawTooth(Samps,XScanVolts_mV,XScanOffset_mV,ScanBuff); for (frameCount = 0; frameCount < globalOptions->NumFramesPerVol; frameCount++) { for (int i = 0; i< Samps; i++) VolumeBuff[i+frameCount*Samps] = ScanBuff[i]; } GenStairCase(Samps,globalOptions->NumFramesPerVol,YScanVolts_mV, YScanOffset_mV, tempBuff); for (int i = 0; i < Samps*globalOptions->NumFramesPerVol; i++) VolumeBuff[i + Samps*globalOptions->NumFramesPerVol] = tempBuff[i]; DAQmxWriteAnalogF64(taskAnalog, Samps*globalOptions->NumFramesPerVol, false ,10 ,DAQmx_Val_GroupByChannel, VolumeBuff,NULL,NULL); //GENERATE PULSE TRAIN TO TRIGGER CAMERA for (int frameCount = 0; frameCount < globalOptions->NumFramesPerVol; frameCount++) { GenPulseTrain(Samps,digiBuff); for (int i = 0; i< Samps; i++) digiVolBuff[i+frameCount*Samps] = digiBuff[i]; } DAQmxWriteDigitalLines(taskTrig,Samps*globalOptions->NumFramesPerVol,false,10.0,DAQmx_Val_GroupByChannel,digiVolBuff,NULL,NULL); } //GENERATE PULSE TRAIN TO TRIGGER CAMERA DAQmxCreateCOPulseChanFreq(taskTrA,"Dev1/ctr1","",DAQmx_Val_Hz,DAQmx_Val_Low,0.0,LineRate,0.2); DAQmxCfgImplicitTiming(taskTrA,DAQmx_Val_FiniteSamps,globalOptions->IMAGEHEIGHT); DAQmxCfgDigEdgeStartTrig(taskTrA,"/Dev1/PFI4",DAQmx_Val_Rising); DAQmxSetStartTrigRetriggerable(taskTrA, 1); DAQmxConnectTerms ("/Dev1/Ctr1InternalOutput", "/Dev1/RTSI0", DAQmx_Val_DoNotInvertPolarity); //START TASKS //IMPORTANT - Need to arm analog task first to make sure that the digital and analog waveforms are in sync DAQmxStartTask(taskAnalog); DAQmxStartTask(taskTrA); DAQmxStartTask(taskTrig); DAQmxStartTask(taskClock); }
int32 Tweezers::Run(float64* force, float64* indata, void* lpParam) { threadinfo* t = (threadinfo*)lpParam; // init output data array float64 out_data[1]; out_data[0] = 0.0; register int i = 0,j = 0; // # of samples to be generated per cycle register int nofSamples = (int)(t->nofFrames/(*t->cycles)) * (*t->delta)*1E-3 * Srate_HTSP; //cerr<<nofSamples<<" samples\n"; // setup HTSP timing and deactivate onboard memory DAQmxErrRtn(DAQmxCfgSampClkTiming(AOtaskHandle,"OnboardClock",Srate_HTSP,DAQmx_Val_Rising,DAQmx_Val_HWTimedSinglePoint,nofSamples)); DAQmxSetRealTimeConvLateErrorsToWarnings(AOtaskHandle, TRUE); // setup start trigger DAQmxErrRtn(DAQmxCfgDigEdgeStartTrig(AOtaskHandle, "PFI0", DAQmx_Val_Rising)); // setup counter task and start trigger // maybe change trigger to digital line? need to use ContSamps, otherwise limited frame # //DAQmxErrRtn(DAQmxCreateCOPulseChanTime(DOtaskHandle,"Dev1/Ctr0","",DAQmx_Val_Seconds,DAQmx_Val_Low,0,1E-3*(*t->delta)/2,1E-3*(*t->delta/2))); DAQmxErrRtn(DAQmxCfgImplicitTiming(DOtaskHandle, DAQmx_Val_ContSamps, 1)); // setup start trigger DAQmxErrRtn(DAQmxCfgDigEdgeStartTrig(DOtaskHandle, "PFI0", DAQmx_Val_Rising)); // setup analog in task DAQmxErrRtn(DAQmxCfgSampClkTiming(AItaskHandle,"Ctr0Out",100,DAQmx_Val_Rising,DAQmx_Val_FiniteSamps,*t->cycles * t->nofFrames)); //DAQmxErrRtn(DAQmxCfgDigEdgeStartTrig(AItaskHandle, "PFI0", DAQmx_Val_Rising)); // start tasks (still waiting for edge trigger from TRtask) DAQmxErrRtn(DAQmxStartTask(DOtaskHandle)); DAQmxErrRtn(DAQmxStartTask(AOtaskHandle)); DAQmxErrRtn(DAQmxStartTask(AItaskHandle)); // precalulate number of loop runs to speed up loop int samps = (nofSamples * (*t->cycles) - 1); // write first sample outside loop, so there is enough time to send the TR start trigger out_data[0] = current(force[0],t->dist); DAQmxErrRtn(DAQmxWriteAnalogF64(AOtaskHandle,1,true,-1,DAQmx_Val_GroupByChannel,out_data,&written,NULL)); // GO! DAQmxErrRtn(DAQmxWriteDigitalLines(TRtaskHandle,1,1,10,DAQmx_Val_GroupByChannel,trigdata[1],&written,NULL)); // 1 kHz sample generation loop while(!(*t->bead_lost && // [email protected]: 05/10/2012 16:16 - dont stop recording if bead is lost in Creep-noint protocol *t->protocol != "Creep-noint" // end of change ) && i < samps) { j = (++i % nofSamples); //cerr<<j<<"\r"; out_data[0] = current(force[j],t->dist); DAQmxErrRtn(DAQmxWaitForNextSampleClock(AOtaskHandle, 1.0, &islate)); DAQmxErrRtn(DAQmxWriteAnalogF64(AOtaskHandle,1,true,-1,DAQmx_Val_GroupByChannel,out_data,&written,NULL)); if(islate) { cerr<<i++<<"\n****** late write - out of sync! *******\n"; *t->bead_lost = TRUE; t->syncerror = TRUE; } } printf("DEBUG: bead_lost(%d) protocol(%s) i(%d) samps(%d)\n", *t->bead_lost, *t->protocol, i, samps); // wait for last sample to be generated DAQmxErrRtn(DAQmxWaitForNextSampleClock(AOtaskHandle, 1.0, &islate)); // make sure enough trigger pulses are generated Sleep(*t->delta * 5); // stop tasks DAQmxErrRtn(DAQmxStopTask(DOtaskHandle)); DAQmxErrRtn(DAQmxStopTask(AOtaskHandle)); // number of frames actually taken t->FramesTaken = 1 + floor(t->nofFrames * (double)i/(double)(nofSamples * (*t->cycles))); // read protocol samples DAQmxReadAnalogF64(AItaskHandle,t->FramesTaken,5.0,DAQmx_Val_GroupByChannel,indata,t->FramesTaken*2,&read,NULL); DAQmxErrRtn(DAQmxStopTask(AItaskHandle)); // disable start triggers DAQmxErrRtn(DAQmxDisableStartTrig(DOtaskHandle)); DAQmxErrRtn(DAQmxDisableStartTrig(AOtaskHandle)); // reset trigger line DAQmxErrRtn(DAQmxWriteDigitalLines(TRtaskHandle,1,1,10,DAQmx_Val_GroupByChannel,trigdata[0],&written,NULL)); }
// from ConfigDAQmxTasks(float xVolts, float yVolts, ScanStructure scanStructure); int LifetimeAcq::configDAQmxTasks(float xVolts, float yVolts, ScanEngine* scanStruct) { int error; int retVal; char errBuff[2048]; double voltagePair[2]; //extern Trig_Channel; voltagePair[0] = (double)xVolts; voltagePair[1] = (double)yVolts; //_____DAQmx Configure Code________________________________________________________________ //_____Setup analog output task_____ DAQmxErrChk (DAQmxCreateTask("AnalogOuput",&aoTaskHandle)); DAQmxErrChk (DAQmxCreateAOVoltageChan (aoTaskHandle, scanStruct->getXChan(), "xChan", -2.0, 2.0, DAQmx_Val_Volts, NULL)); DAQmxErrChk (DAQmxCreateAOVoltageChan (aoTaskHandle, scanStruct->getYChan(), "yChan", -2.0, 2.0, DAQmx_Val_Volts, NULL)); DAQmxErrChk (DAQmxWriteAnalogF64 (aoTaskHandle, 1, 1, 10, DAQmx_Val_GroupByChannel, voltagePair, DAQmx_Val_GroupByChannel, NULL)); //_____Setup Analog input task_____ DAQmxErrChk (DAQmxCreateTask("TrigAcq",&acqTaskHandle)); /*Add analog input channel to acqtask*/ DAQmxErrChk (DAQmxCreateAIVoltageChan(acqTaskHandle, ACQ_CHANNEL, "PMT", DAQmx_Val_RSE,ACQMIN, ACQMAX, DAQmx_Val_Volts,NULL)); /*config analog input to use counter output as sample clock and continuous samps*/ DAQmxErrChk (DAQmxCfgSampClkTiming (acqTaskHandle, SAMPCLK_CHANNEL, SAMP_RATE, DAQmx_Val_Rising, DAQmx_Val_ContSamps, totSamps)); /*Make buffer size slightly larger than default*/ DAQmxErrChk (DAQmxSetBufferAttribute (acqTaskHandle, DAQmx_Buf_Input_BufSize, totSamps+1000)); //_____Setup counter task_____ DAQmxErrChk (DAQmxCreateTask ("couterOutTask", &ctrTaskHandle)); /*Add counter clock to counter task*/ DAQmxErrChk (DAQmxCreateCOPulseChanFreq (ctrTaskHandle, COUNTER_CHANNEL, "coChannel", DAQmx_Val_Hz,DAQmx_Val_Low, 0, SAMP_RATE, 0.5)); /*config clock for counter output task to generate correct numSamps*/ DAQmxErrChk (DAQmxCfgImplicitTiming (ctrTaskHandle, DAQmx_Val_FiniteSamps, numSamps)); /*Config triggering of counter task*/ DAQmxErrChk (DAQmxCfgDigEdgeStartTrig (ctrTaskHandle, TRIG_CHANNEL, DAQmx_Val_Rising)); DAQmxErrChk (DAQmxSetTrigAttribute (ctrTaskHandle, DAQmx_StartTrig_Retriggerable, TRUE)); return 1; Error: if( DAQmxFailed(error) ) DAQmxGetExtendedErrorInfo(errBuff,2048); retVal = this->stopTasks(); //if( DAQmxFailed(error) ) // MessagePopup("DAQmx Error",errBuff); return 0; }