11-07-2008 04:42 PM
I am learning to use NIDAQmx in my process control project and am puzzled with my problem. I'm using LabWindows CVI 8.5 and PCI-6229. Here is the code segment that causes problem
----------------
// DAQ DIGITAL OUTPUT Reserve line 0-23
char chanP1Leds[] = "dev1/port0/line0:2"; // RGY
char chanP1TestClr[] = "dev1/port0/line12";
char chanP1AirCtl[] = "dev1/port0/line16";
// DAQ DIGITAL INPUT Reserve line 23-31
char chanP1TestIn[] = "dev1/port0/line30:31"; // 30: test, 31:retest
// DAQ Analog
char chanP1RegMon[] = "dev1/ai0"; // Pressure Regulator monitor
char chanP1FlowMon[] = "dev1/ai1"; // Flow Regulator monitor
char chanP1TransMon[]= "dev1/ai2"; // Pressure transducer monitor
char chanP1PressureCmd[] = "dev1/ao0"; // Pressure Regulator command
char chanP1FlowCmd[] = "dev1/ao1"; // Flow Regulator command
.
.
void GlobalInit(void)
{
int n;
int32 SamplesWritten;
int error=0;
char errBuff[2048]={'\0'};
uInt8 TestData = 1;
uInt32 P1LedsData,P1AirCtlData,P1ClrData;
// Data Inititialization
P1SerNo = 0;
P1PressCmdData = 0.0;
P1FlowCmdData = 0.0;
P1FlowMonData = 0.0;
P1PressMonData = 0.0;
P1TransMonData = 0.0;
P1LedsData = 0x7;
P1ClrData = 1; // low -> Clear
P1AirCtlData = 1; // low -> On
/*********************************************/
// DAQmx Configure Code Digital
/*********************************************/
SetWaitCursor(1);
/////////////////// Digital Outputs //////////////////
// LEDs channel
DAQmxErrChk (DAQmxCreateTask("",&P1TaskDOLeds));
DAQmxErrChk (DAQmxCreateDOChan(P1TaskDOLeds,chanP1Leds,"P1Leds",DAQmx_Val_ChanForAllLines));
DAQmxErrChk(DAQmxSetChanAttribute(P1TaskDOLeds, "P1Leds", DAQmx_DO_InvertLines, 0));
// Test channel
DAQmxErrChk (DAQmxCreateTask("",&P1TaskDOClr));
DAQmxErrChk (DAQmxCreateDOChan(P1TaskDOClr,chanP1TestClr,"P1Clear",DAQmx_Val_ChanForAllLines));
DAQmxErrChk(DAQmxSetChanAttribute(P1TaskDOClr, "P1Clear", DAQmx_DO_InvertLines, 0));
// Solenoid Air Input Control
DAQmxErrChk (DAQmxCreateTask("",&P1TaskDOAirCtl));
DAQmxErrChk (DAQmxCreateDOChan(P1TaskDOAirCtl,chanP1AirCtl,"P1AirCtl",DAQmx_Val_ChanForAllLines));
DAQmxErrChk(DAQmxSetChanAttribute(P1TaskDOAirCtl, "P1AirCtl", DAQmx_DO_InvertLines, 0));
/////////////////// Digital Inputs //////////////////
DAQmxErrChk (DAQmxCreateTask("",&P1TaskDI));
DAQmxErrChk (DAQmxCreateDIChan(P1TaskDI,chanP1TestIn,"P1Test",DAQmx_Val_ChanForAllLines));
DAQmxErrChk(DAQmxSetChanAttribute(P1TaskDI, "P1Test", DAQmx_DI_InvertLines, 0));
// Activate tasks
DAQmxErrChk (DAQmxStartTask(P1TaskDOLeds)); //start the output task
DAQmxErrChk (DAQmxStartTask(P1TaskDOClr)); //start the output task
DAQmxErrChk (DAQmxStartTask(P1TaskDOAirCtl)); //start the output task
DAQmxErrChk (DAQmxStartTask(P1TaskDI)); //start the input task
/*********************************************/
// DAQmx Write Code
/*********************************************/
DAQmxErrChk (DAQmxWriteDigitalU32(P1TaskDOLeds,1,1,10.0,DAQmx_Val_GroupByChannel,&P1LedsData,NULL,NULL));
DAQmxErrChk (DAQmxWriteDigitalU32(P1TaskDOClr,1,1,10.0,DAQmx_Val_GroupByChannel,&P1ClrData,NULL,NULL));
DAQmxErrChk (DAQmxWriteDigitalU32(P1TaskDOAirCtl,1,1,10.0,DAQmx_Val_GroupByChannel,&P1AirCtlData,NULL,NULL));
//DAQmxErrChk (DAQmxWriteDigitalScalarU32(P1TaskDOAirCtl,1,10.0,P1AirCtlData,NULL));
//DAQmxErrChk (DAQmxWriteDigitalLines(P1TaskDOAirCtl,1,1,10.0,DAQmx_Val_GroupByChannel,&TestData,NULL,NULL));
-----------------
My problem:
the 1st DAQmxWriteDigitalU32 writes correct data.
the 2nd & the 3rd DAQmxWriteDigitalU32 wrote zero to the channels and it doesn't matter where I move those 2 lines, they always write zero to the channels. The commented DAQmxWriteDigitalScalarU32 also writes zero to the channel but the DAQmxWriteDigitalLines writes correct data to the channel. The MAX test panel also writes correct data to the port. I really don't understand why this happening so I need your experts' help to point out what I'm missing here.
Thanks a lot.
Lanny
Solved! Go to Solution.
11-09-2008 12:54 AM - edited 11-09-2008 12:54 AM
Hi Lanny,
When you say DAQmxWriteDigitalU32 writes 0, do you mean all outputs or did just some of them became zero?
I am not sure but can you try changing the channel create option from "DAQmx_Val_ChanForAllLines" to "DAQmx_Val_ChanPerLine"?
11-09-2008 01:01 PM
Hi Eren,
Thanks for trying to help me. After the first write to line 0:2, all other lines are always written with zero regardless what the data is. I did try to change that Val_ChanForAllLines to Val_ChanPerLine and the results are still the same. I do not have any error neither in compiling nor running the code.
My hardware is as followed:
I use port 0 (32 bit ports) of a PCI-6229 (we just bought LabWindows & the 6229 last month for this project) to assign the 1st 3 lines to LEDs sinked 20 mA each. The 2nd line goes to a 74LS74 clear input (low clear). The 3rd line goes to a relay to sink 10 mA (low activate) so it can't be the hardware because the 1st 3 lines sink the most current (assume I miscalculate the current which could happened).
The puzzle is why DAQmxWriteDigitalLines and MAX are working fine
and but not those line of code? I couldn't find any help from MAX or DAQAssistant because they can only generate configuration codes but not
code to read or write to port. After I ran my code, I used MAX and MAX did verify those lines are indeed written with zero.
11-10-2008 12:26 AM
Hi,
I have always found DAQmx little bit cumbersome to use. I feel like I might be doing something wrong each time I code in DAQmx and I cannot feel positive that the code will work at the first time.
However, in my opinion, Traditional DAQ library is more intuitive to use. It is clear which function is doing what.
So if your application does not require complex operation like triggers, special timing, etc you may have a look at that.
Btw, did you try creating a single task for all your outputs and use write scalar function to set all outputs in a single call. It is necessary to use WriteDigital32 type functions if you are writing only a single value (a scalar). Those are mostly aimed for buffered write operations.
If you see it works, I advise you to write yourself some simple functions to turn each line on/off. So you do not have to "build" the value to write to the channel each time you need to make a change.
Hope this helps.
11-10-2008 11:45 AM
Eren,
I can't change to a single task for all of my outputs and inputs because
1) The intended application has 4 major parallel operations (Pt to P4) therefore, many tasks. Right now I just get the code for P1 and it's just a simple scheme for me to learn DAQmx.
2) I can't sidestep the problem as descibed above because it will limit me to certain code and I will never learn why it happened.
The reason I used this forum for my problem because it will help others who try to use DAQmx the first time to see how the code is written for many tasks and DAQmx is very hard to people who try to learn to use it the first time. The NI samples is so simple and and the DAQmx self help is confusing like an after thought handout provided for a neglected child as LabWindows.I learn more about DAQmx by searching this forum and helps by people like you than by reading NI's sample codes.If NI application Engineer doesn't want to answer this issue here and hopes that it will go away, then I will take it to them. One way or another, I will post the result here.
11-10-2008 01:30 PM - edited 11-10-2008 01:33 PM
Hi Lanny,
I understand your concerns very well and I -unfortunately- agree with you about the situation of DAQmx documentation and CVI
.
I did not generally had time to keep a problem unsolved for a long time in my projects, so I'm easily tempted to workarounds whenever I face a problem, even if the problem is not directly my lack of "intelligence".
On the task issue;
I do not think you need to create 4 tasks just for what your project sounds like in real world.
In my opinion single task will do as long as you program it accordingly. But it is your choice after all.
I inspected your code a few separate times and still could not find the problem.
You may also try the Multifunction DAQ forum. It is probably full of DAQmx related posts.
I keep looking for an answer too. Good luck.
note:
I'd like to correct myself for the previous post. The correct sentence would be "It is NOT necessary to use WriteDigital32 type functions ..."
11-11-2008 12:47 PM
Hello Lanny,
I think that I've found a probable cause to this behavior. The DAXmxWriteDigitalU32 is a port format that writes values for only the lines specified in the task assuming a 32 bit word. Basically if you write the value 1 to your task with line 12 in it then the value 00000000 00000000 0000000 00000001 will be written and the 12th line will be a zero. In order to write a 1 to this line you would need to write a value of 2^12 = 4096. Similarly for lines 16 and 17 I would use the value 196608 (= 2^16 + 2^17).
For more details on the expected behavior of this function and for future reference, this information is available in the NI-DAQmx C Reference Help. This help file is located at Start> All Programs> National Instruments> NI-DAQ> NI-DAQmx C Reference Help. Once you open the help file navigate to NI-DAQmx C Functions> Write Functions> DAQmxWriteDigitalScalarU32. In this documentation it states that the value to be written is "uInt32 A 32-bit integer sample to write to the task." If you click on the link for "32-bit integer it takes you to another article called "Digital Data (Integer Format)" that explains the behavior you're seeing in detail.
I hope this helps, and have a great day!
Cheers,
11-11-2008 02:10 PM
Well, that was why I asked in my first reply whether they are all zero or just some of them.
I thought writing a value of 1 to latch clear task would at least set one of the led outputs.
But now I see that's not possible because clear task cannot access led output channels.
Still in this case I expect the led outputs to work since they are on the lowest 3 bits and Lanny is writing 0x7.
11-11-2008 03:12 PM
That's it. Thank you Brooks.
I did read the help file on DAQmxWriteDigitalXX and the data format in the NI-DAQmx Reference and did not get it until now with your explanation. I guess the WriteDigitalLines throws me in a loop of thinking DAQmx is masking and shifting data to write correct value to a port for other types of writing (and reading). A sample with lines and tasks scattered around the port like my case would save a NI-DAQmx newbie like me few agony days. Well, we got the sample here now.
11-12-2008 01:59 PM - edited 11-12-2008 02:00 PM
Hello Eren,
Just for clarification purposes, the reason that what you described is not the case is because this function essentially uses place holders for each line in the port. If you write a value to the port using this function, only lines that are included in the task will update and their value will be set as if all 32 lines were included. If you write 1 to the port, this would only update line 0, and only if line 0 was in the task. Incase you or other forum users don't have the NI-DAQ help file handy, here's a screen shot of the article that provides a detailed explanation of this behavior.

Cheers,