08-24-2011 10:40 PM
Hi, Please help me .
I'm Using NI PCI6259 and VC + + 2008.
• to solve problems
-> Multiple analog output channels using different frequencies,
Each different and each channel frequency can be adjusted would like to export the output to an analog waveform.
(Ex: AO0 = 503Hz, AO1 = 15Hz / AO0 = 497Hz, AO1 = 15Hz)
• Issues and Questions
-> PCI-6259 in the 'DAQmxCreateAOFuncGenChan' do you disable the function, correct?
If so, 'DAQmxCreateAOVoltageChan' to be controlled through the output waveform,
Sampling Rate is common to the two channels.
Channel're going to be controlled by manipulating the buffer data is not only that correct?
For example,
Using 75KHz external Sample clock
AO0 => 500Hz, AO1 => 15Hz output to be generated
F (analog) = F (update) / (samples / cycle) by the formula in
The number of 150 samples per channel AO0, AO1 5000 the number of samples per set
If the total number of buffers is set to 15000, 500Hz and 15Hz can be generated in the output.
In order to control the frequency of data samples per channel is set to 148 and 5000, the
The total number of sample data set, how do I do?
148 * 5000 => 74000 buffer, this correct?
Attach a sample source.
Please comment if any.
//////////////////////////// sample code///////////////////////////////
/ / The following code is an external clock source (PFI13) receives the analog output 15Hz, 500Hz, 15Hz to generate output code.
/ / 15Hz, 501Hz, 15Hz or 15Hz, 499Hz, 15Hz output for information on how to export?
int32 error=0;
char errBuff[2048]={'\0'};
int i=0;
int32 written;
int nSamples = 15000;
int dSamplesPerSecond = 5000;//sample per ch0
int dSamplesPerSecond2 = 150;//sample per ch1
int dSamplesPerSecon3 = 5000;//sample per ch2
//generating waveform data
//Ch1
double *data1 = new double[];
data1 = m_Cls_FunGen.FunctionGenerator(1, dSamplesPerSecond, 5); //waveform, numCycles, numSamplesPerCycle, amplitude
//Ch2
double *data2 = new double[];
data2 = m_Cls_FunGen.FunctionGenerator(3, 100, dSamplesPerSecond2, 5); //waveform, numCycles, numSamplesPerCycle, amplitude
//Ch3
double *data3 = new double[];
data3 = m_Cls_FunGen.FunctionGenerator(3, 3, dSamplesPerSecon3, 5); //waveform, numCycles, numSamplesPerCycle, amplitude
double *data = new double[nSamples * 3];
for(int i = 0; i < nSamples; ++i)
data[i] = data1[i];
for(int i = nSamples; i < nSamples*2; ++i)
data[i] = data2[i - nSamples];
for(int i = nSamples*2; i < nSamples*3; ++i)
data[i] = data3[i - nSamples*2];
/*********************************************/
// DAQmx Create Code
/*********************************************/
DAQmxErrChk (DAQmxCreateTask("", &AOAlltaskHandle));
DAQmxErrChk (DAQmxCreateAOVoltageChan(AOAlltaskHandle, "Dev1/ao1:3", "", (float)(-10), (float)(10), DAQmx_Val_Volts, NULL));
/*********************************************/
// DAQmx Configure Code
/*********************************************/
DAQmxErrChk (DAQmxCfgSampClkTiming(AOAlltaskHandle, "/Dev1/PFI13", 1000.0, DAQmx_Val_Rising, DAQmx_Val_ContSamps, nSamples));
//Set Trig
DAQmxErrChk (DAQmxCfgDigEdgeStartTrig(AOAlltaskHandle, "/Dev1/PFI13", DAQmx_Val_Rising));
/*********************************************/
// DAQmx Write Code - numSampsPerChan, autoStart, timeout, dataLayout, writeArray
/*********************************************/
DAQmxErrChk (DAQmxWriteAnalogF64(AOAlltaskHandle, nSamples, 0, 10.0 ,DAQmx_Val_GroupByChannel,data, &written,NULL));
/*********************************************/
// DAQmx Start Code
/*********************************************/
DAQmxErrChk (DAQmxStartTask(AOAlltaskHandle));
08-25-2011 11:44 PM
안녕하십니까 한국NI 기술지원부입니다,
우선 고객님께서 하고자 하시는 것이
3채널에 각각 다른 아날로그 파형을 출력하면서
실행중에 주파수를 가변하고자 하시는 것이지요.
이는 고객님이 말씀하신 것처럼
타이밍 소스가되는 PFI라인에 인가되는 신호를 가변하여 변경하시는 방법과,
소프트웨어적인 함수를 써서 변경하는 방법이 있습니다.
(후자의 경우에는 값이 반영될때까지 딜레이가 좀 있게되지요)
DAQmxCreateAOFuncGenChan함수는 핵심함수로 생략이 어렵습니다.
실제 출력되는 아날로그 파형은 말씀하신 것처럼
F(analog) = F(update) / (samples / cycle) 공식에 따라 출력되며,
/Dev1/PFI13에 인가되는 주파수[F(update)]에 따라 달라집니다.
(=아날로그가 아니라 사각파[TTL]이 입력되어야 합니다)
그 다음 관건이 되는 값은 DAQmxCfgSampClkTiming 끝에 있는 nSamples 인데
이것은 버퍼의 크기를 말하는 것으로,
각 채널의 셈플수 x 채널수 x 여유공간(10배정도)의 값으로 적당히 지정해주시면 됩니다.
DAQmxWriteAnalogF64의 nSamples 값은 위의 버퍼값과는 달라야 합니다.
이것은 1 채널당 셈플수와 똑같아야 하며,
출력되는 데이터가 담긴 1차원 배열 data에는 3채널분의 데이터를 순차적으로 담아주시면 됩니다.
감사합니다.
08-26-2011 01:22 AM
안녕하세요. 저는 미래컴퍼니 염기원입니다.
위사항에 대해 전화 및 메일로 문의를 드렸었는데,
ANSI C 기반의 프로그램은 잘 알지 못하는다는 답변이 왔더라구요...
(솔직히 모르신다는 답변에 실망을 했습니다...ㅠ, C언어 기반은 대응이 안됩니까?)
아래 사항에 대해 다시한번 문의 드립니다.
1. DAQmxCreateAOFuncGenChan 함수는 PCI-6259에서 사용가능합니까?
제가 사용해 보았는데 'status code: -200432 '에러가 발생합니다.
2. PFI 라인을 통한 외부클락을 사용할 경우, DAQmxCfgSampClkTiming 함수는 주파수에 더이상 영향을 주지 않습니다.
(맞는지요? sample수의 갯수를 0이나 10000으로 바꾸어도 아날로그 출력이 변하지 않음.)
그렇다면 채널별 주파수를 다르게 하려면 DAQmxWriteAnalogF64함수의 버퍼데이터 조작밖에 없는 것이 맞습니까?
위 사항이 맞다면, PFI라인으로 인가되는 외부클락소스가 750KHz일때, 15Hz와 500Hz의 출력을 만들고 싶으면
500 = 750K/1500개,15 = 750K/50000개에 의해 각각 1500개와 50000개의 samples / cycle이 필요합니다.
여기서 DAQmxWriteAnalogF64 함수에서 1차원 데이터 배열에 각 채널별 데이터 갯수가 같아야 하지요?
(예를 들어 1채널당 갯수가 10000이면, 3채널이면 1차원 데이터 배열의 갯수는 30000으로 해야하지요?)
그렇다면 데이터 배열의 갯수를 맞추기 위해서
샘플데이터를 1500개*100cycle 과 50000개*3cycle 해서 150000데이터를 쓰면 됩니다.
문제는 주파수를 조절하기 위해서 채널별로 샘플데이터 갯수를 변경 할 때입니다.
예를 들어, 499.334...Hz = 750K/1502개,15Hz = 750K/50000에서 499.334..Hz와 15Hz를 내보내고 싶을때,
1502개와 50000개의 데이터를 같은 크기의 배열에 저장해야하는데,
1502과 50000을 맞추려면 => 최소 37550000의 데이터 배열이 필요합니다.
이는 너무 크지요? PC에서도 메모리 용량을 초과할 수있습니다.
말하다보니 너무 복잡해 졌네요...
요점은 750K PFI 외부 클락 소스를 이용해서
499.334Hz와 15Hz의 신호를 내보내려면 어떻게 해야합니까?
F(analog) = F(update) / (samples / cycle)에 의해서
각각 1502개와 50000개의 (samples / cycle)이 필요한데,
이것을 DAQmxWriteAnalogF64 함수의 1차원 데이터 배열에 어떻게 써야하는겁니까??
조금한 답변이라도 힌트 좀 부탁드립니다..........
08-26-2011 02:18 AM - edited 08-26-2011 02:27 AM
1. PCI-6259 보드를 사용하시는군요,
DAQmxCreateAOFuncGenChan는 사용할 수 없고, DAQmxCreateAOFuncGenChan함수를 사용하셔야 합니다.
2. PFI 라인을 통한 외부클럭을 사용할 경우,
외부클럭의 빠르기 자체가 타이밍이므로 DAQmxCfgSampClkTiming 의 rate는 주파수에 영향을 주지 않는 것이 맞습니다.
(예상되는 입력 클럭 주파수의 근사치를 넣으시면 내부적으로 활용한다고 합니다.)
그 이후 부분은 고객님의 견해가 맞습니다.
이 문제는 하드웨어 스펙도 하나의 관건이지만
타이밍 클릭이 750K로 너무 높게 정해져있다는 것이 원초적인 문제입니다.
어떠한 아날로그 파형을 출력하시는지 언급해주지 않으셨지만, 사인파로 가정하고
15Hz = 750K/50000개 라는 예에서 살펴보면
15Hz 사인파를 그리는데 무려 50000개의 점을 소모하게되지요.
(보통 사인파 그리는데 100개의 점만 해도 충분합니다. 엄청 고급스러운 신호지요^^)
대안으로는,
1) 보드 내장 클럭을 타이밍 소스로 사용하시거나,
2) 반드시 외부클럭을 이용하셔야 하는 상황이라면
6259에 내장된 카운터 부분을 추가로 이용하여 외부 클럭을 1/100로 줄여서 라우팅하는 방법이 있을 것같습니다.
2)번 방법을 간단히 소개드리면,
DAQmxStartTask를 이용해서 task2 핸들을 하나더 만드시고
DAQmxCreateCOPulseChanTicks에서 high tick 1, low tick 99로 하시면
입력 클럭이 100클럭당 1클럭이 나오게 되는데요 (예: Dev1/ctr0 카운터를 이용하신다면 PFI 12)
이것을 DAQmxCfgSampClkTiming 함수의 타이밍소스로 지정해 주시는 것이랍니다.
08-26-2011 02:31 AM
위 게시물에서 1번 아래와 같이 수정합니다.
DAQmxCreateAOFuncGenChan는 사용할 수 없고, DAQmxCreateAOVoltageChan함수를 사용하셔야 합니다.
08-26-2011 02:35 AM
답변 감사드립니다.
외부 클락을 DAQmxCreateCOPulseChanTicks을 이용해 다운 시키는 방법은 알고 있습니다.
750K를 75K로 다운시킬 경우 500Hz조절의 분해능이 떨어지는게 문제 입니다.
75K/150 = 500Hz, 75K/149= 503.35Hz....로 약 3.5Hz단위 밖에 조절이 안됩니다.
외부 클락 소스가 75KHz일 경우 랩뷰에서는 1Hz단위의 조정이 가능합니까?
최소 주파수 조정 단위가 어떻게 됩니까??
저도 포럼 자료들을 많이 찾아봤는데, 결국 아날로그 출력이 독립적이지 못한게 문제 인것 같습니다.
채널별 task 생성도 안되고....
채널별 출력 데이터 버퍼의 갯수를 다르게 설정하는 것도 안되고.....
랩뷰에서는 내부적으로 어떻게 처리했는지 궁금합니다.
샘플데이터갯수와 주파수만 설정하면 해당 주파수 파형이 나온다니.....
답변부탁드립니다.
감사합니다.
08-26-2011 03:05 AM
LabVIEW와 VC++에서 DAQ프로그래밍을 할 때
사용되는 드라이버도 같고 함수의 이름과 첨자가 1:1로 매치되므로 성능은 동일하답니다.
(버퍼크기를 수동으로 지정해주어야 하는 점과 1차원 함수만 입력받는다는 점만 다릅니다)
데이터 갯수와 주파수만으로 파형을 만들어냈다는 것은
출력 함수전에 LabVIEW에서 제공하는 별도의 파형 만드는 함수를 활용했을 것인데요,
아마 보간법 등을 적용해 맞춘 것으로, 고객님이 필요로하시는 분해능을 만족하지 못할 것으로 보입니다.