Multifunction DAQ

cancel
Showing results for 
Search instead for 
Did you mean: 

Counter Problems with NIDAQmx v8 for Linux

Hello, sorry for the long post but this is a long-running problem (a few weeks) which requires a lot of detail to give a complete picture.  I've tried posting small pieces of the problem I am having in different threads but most of the comments were on things that have already been discussed and tried in other threads and over the phone with NI, so I thought it would be best to put it all in one location.

I am working on developing a hardware-in-the-loop controls system that can handle real-time data acquistion.  To accomodate this I have a PCIe-6259 DAQ card along with a SC-2345 signal conditioning unit with accompanying modules.  Because of the real-time demands I need to use this in a Linux PC.  Initially, I was using Fedora Core 5 but have since tried other operating systems.  I was able to get NIDAQmx to run on FC5 by referring to <a href="http://forums.ni.com/ni/board/message?board.id=250&message.id=23429">this</a> thread.  More on that later.

My first test and application of the system is to control a DC motor.  I have the motor connected to an amplifier which is then connected to the DAQ board.  Currently, I am using a LS7183 encoder-to-counter interface chip that is between the encoder output of the amplifier (it is a straight pass-through of the motor's encoder outputs) and the counter of my DAQ card.  I have SCC-CTR01 counter modules but am not using them because I can only produce about 1 mA of current on the encoder outputs and I believe the module requires something around 2.2 mA to function.  Instead I am connecting the outputs of the LS7183 directly to the terminal block on the SC-2345.  The LS7183 basically takes in the phase A and phase B outputs of the encoder and then outputs pulses on two lines.  One line is UpClk which produces true pulses like an encoder when phase A leads phase B.  The other output line is DnClk which produces true pulses when phase B is leading phase A.  For both UpClk and DnClk the 'false' output is 5V and the 'true' output is 0V.  More information on this chip can be found <a href="http://www.usdigital.com/products/ls7183-ls7184/">here</a>.  I am using counter 1 on this card because through earlier testing it was determined with the help of a NI support person that our counter 0 was defective and was causing our motor to lose commutation.  So I now have UpClk connected to ctr1_src pin 42 PFI 3, DnClk connected to ctr1_aux pin 46 PFI 11, and the Z index of the encoder (coming straight out of the amplifier pass-through) connected to ctr1_gate pin 41 PFI 4.

Because I am using Linux the MAX application is unavailable to me (although I have tested this system on a Windows machine, more on that later) and I do not have LabView.  The software I am using to test this system is example code written in C that comes with the driver and that I have to compile myself (see attached and note).  I have set up the program to use the TwoPulseCounting method which is supposed to increment the count on a pulse from channel A and decrement the count on a pulse from channel B.  It is because of this functionality that I chose to use the LS7183 chip.  It is my understanding that the fact that the count is incremented or decremented on a low-to-high transition of the pulse means that it is acceptable that this chip produces a 5V signal as a logic 'false' and a 0V signal as a logic 'true', rather than the other way around.  Can anyone verify this assumption for me?  Before learning of the TwoPulseCounting method I was using X4 decoding and did not have the chip in the circuit.  That setup produces values which never changed and were either 0 or a large negative number.  This is somewhat like the problem I am about to describe.

Now on to the actual problem.  When I try to use the example angular encoder code, I am not able to get values that make sense.  When the motor spins in one direction, I get a constant, large negative number (which happens to be the same value I get with X4 decoding as previously mentioned).  When the motor spins in the other direction, I get positive numbers which change but seem to just oscillate around a number that does not make any sense.  As mentioned before, the LS7183 chip routes all the pulses to one input for spinning in one direction, and to another input when spinning in the other direction.  When the motor is spinning in the direction that creates the large negative number, all the pulses are being routed to the AUX input on pin 46 PFI 11.  When the motor is spinning in the direction that creates the oscillating, nonsensical positives numbers, all of the pulses are being routed to the SRC input on pin 42 PFI 3. 

It is my belief that the problem somehow lies in the AUX input, and here's why.  I have connected a function generator to the SRC input of counter 1 and sent pulses or square waves with it.  I then ran the example program CntDigEvents which just generates a count of the number of pulses coming in through the SRC input, and everything seemed to work correctly.  The same is true when I only connected the phase A or phase B output of the encoder (without using the LS7183 chip) to SRC and ran the program.  The problem I have only seems to appear when I am attempting angular decoding with the SRC, GATE, and AUX inputs.  I do not know of a way to test my AUX input with a simple diagnostic program similar to CntDigEvents to verify my assessment of the problem.  Does anyone know of a way to do this?

After being on the phone with NI support, I got a Windows PC and installed the same card into it and the NIDAQmx v8 Windows driver.  The setup was exactly the same as described above, the only differences being the PC used, the operating system, and the driver.  I ran MAX and created an Angular Encoder task with all the same parameters as in my sample code (ie. TwoPulseCounting) and everything worked perfectly.  This assures me that our hardware (not including counter 0) is fine.  As a result of this, NI support recommended using a distribution of Linux that was supported by NIDAQmx assuming that we would not encounter this problem on something that had already been tested.  I then got a new hard drive, installed Red Hat Enterprise Linux 3 and the NIDAQmx v8 driver on it, and connected it into the exact same setup as previously described, running the exact same software.  Upon running the example angular decoder program, I have the exact same problem.  The same negative number in one direction and the same random positive numbers in the other direction.

After going through all this, it is my assertion that the problem lies in the NIDAQmx v8 for Linux and probably when that driver has to communicate with the AUX input.  That seems to be the only common thread causing problems in all of my testing.  If anyone has any comments on their own personal experience with this driver and counters, or on something new to test, or on a solution, I would greatly appreciate it.  My colleagues here working on the project with me and I are out of ideas at this point.

-Josh

*NOTE: I have made some edits to the example program that I have attached.  The lines which are commented out made up the original code that you get when you first install the driver.  I have left them in for reference.
0 Kudos
Message 1 of 12
(4,776 Views)
Sorry about the html links.  I'll repost them

Thread on running NIDAQmx on Fedora Core 5 - http://forums.ni.com/ni/board/message?board.id=250&message.id=23429

Information on the LS7183 chip -
http://www.usdigital.com/products/ls7183-ls7184/
0 Kudos
Message 2 of 12
(4,773 Views)
have you tried running DAQmxTestPanels to test out your counter connection? It's almost the same as test panels in Windows under MAX, but in Linux.

0 Kudos
Message 3 of 12
(4,767 Views)
Yes but it seems I can't run them without having LabView installed.
0 Kudos
Message 4 of 12
(4,764 Views)
Another tip I can offer, if you want to try compiling that code in Windows, download Qt 4 from ftp://ftp.trolltech.com/qt/source/qt-win-opensource-4.2.2-mingw.exe
Qt is free for non-commercial use, and you can use the same source code in Windows and Linux. It works, I've done it myself.

This link has Windows libraries for NIDAQmx and Qt (minGW) that I compiled a while ago:

http://forums.ni.com/ni/board/message?board.id=250&message.id=17557&jump=true


0 Kudos
Message 5 of 12
(4,761 Views)
You don't need LabView, follow that how-to I wrote. I don't have LabView here either.

0 Kudos
Message 6 of 12
(4,760 Views)

Shot in the nearly dark: have your tried performing your counter read in 32-bit integer format rather than the 64-bit double precision floating point I saw in the attached c code?  And have you tried doing this as an on-demand peek at the counter register rather than as buffered hw-timed acquisition?

I would think that a simple on-demand request for a 32-bit integer would be the best way to minimize the amount of driver code that executes.  When you request floating point, the driver performs scaling.  When you do buffered acquisition, the driver manages stuff for you.  I'd think that a simple on-demand peek at the counter's instantaneous count register value would be the closest you can get to a no-op driver-wise.

I only do LabVIEW in Windows so I don't know the c syntax for the driver calls, and I've never even used, let alone installed or maintained, Linux.  But I've done a lot with encoders and would like to probe just a bit more on that stuff too.

First, I've used a 6259 in several apps to directly interface to a quad encoder using X4 decoding.  The board handles it well, and I'm surprised you needed an interface chip to create up pulses and down pulses.  I'm not 100% sure, but I think that in two-pulse encoder mode, you can choose the "active edge" for both the Up and Down pulses.  Rising edge is typically the default, but many counter measurements allow you to specify a falling edge as active if you choose.

Here's one dirtly little secret about Z-index pulses that I'm pretty certain is still true on the M-series boards.  The reset operation is NOT edge-sensitive as some of the docs suggest.  It's state-sensitive.  It is also not configurable for polarity (last I knew) -- reset happens during high state only.  When I hardwired it to high (5V) so there would never be an edge and then rotated a quad encoder, the count would go 1,2,3,0,1,2,3,0,1,2,3,0,...  Further, the reset only happens at a specific phase combination of the A,B channels which you must specify.  If the Z-index pulse is short and happens during the wrong phase -- no reset.  If the Z-index pulse is long and lasts through several cycles of the specified A,B phase -- multiple resets.

It's also possible to configure the Z-index to reset to a value other than 0.  Under LV and Windows, the default reset value  is 0, but perhaps if unspecified in your environment, the default reset value may be unpredictable?  Could this somehow explain the case where you had positive numbers which kept oscillating around some value?  As to the constant large negative number -- not to ask a dumb question, but are you sure you saw ALL the digits of precision?  The raw count value is an unsigned 32-bit integer.  When you decrement below 0, you get a bit pattern of 32 high bits.  Maybe the driver (dumbly) interprets this as -(2^31) rather than as -1?  It may then convert to floating point degrees based on -(2^-31).  You might need to look at 10-12 digits of precision on your floating point value to detect whether it's changing.  My earlier comments about reading in 32-bit integer format would be an even better check.

A lot of guesswork here, hope some turns out useful.  Personally, I think the Z-index issues are more likely a problem than the AUX input.  I could easily believe that the driver may also be part of the problem -- converting from int to floating point might do some dumb stuff like I outlined above -- in fact, I'm not so sure it doesn't do that under LabVIEW and Windows.  I've long had the habit of reading counter values as U32's and doing all my own scaling.  See if it helps to dis the driver and do unbuffered on-demand 32-bit integer reads.

-Kevin P.

ALERT! LabVIEW's subscription-only policy came to an end (finally!). Unfortunately, pricing favors the captured and committed over new adopters -- so tread carefully.
0 Kudos
Message 7 of 12
(4,749 Views)
I haven't tried reading in 32-bit format, but a question of that nature was posed by someone working on the project with me.  He was thinking it looked like maybe at some point in the process the data was being handled as 64-bit and somewhere else it was being handled as 32-bit, causing an erroneous output.  I mentioned this to the NI support rep I've been in touch with and asked to see if he could find any information on that, but I've yet to hear back from him.  The CntDigEvents reads in the pulses as u32, so I'll have to try that.

I have only run this as buffered in Linux.  I remember the on-demand option in MAX under Windows.  I tried it then and it worked as well, but of course so did everything else.  That will be something else to try.

It wasn't exactly a demand that we use the LS7183 chip, we just happened to have one and it fit nicely with that mode of decoding.  At the time we were having trouble with X4 so it was just an attempt at getting something else to work.  A side benefit of the chip is that it does a bit of filtering and reduces the 'bounciness' we get from the encoder.  It makes our position reading more stable (in Windows/MAX).

The Z-indexing functionality and resetting was confusing to me when I first looked at it.  I read the API thinking that, with the default options, the counter value would be reset everytime A, B, and Z were high at the same point in time, which would hurt our position control.  When I asked NI support about it, it was explained to me that the option only related to an initial configuration of the counter and was not something that would keep resetting the counter as the motor rotated.  After reading what you wrote, though, I think maybe that's wrong and I misunderstood.  Though having said all that I must mention that I have run that script with the Z-indexing both enabled and disabled and have not seen any change in the output.  I will look into what value the Z-index is set to reset to but it would seem as though whatever effect that had, it would apply regardless of the direction of motor rotation.

That large negative number was something on the order of -1.5 billion, so we're looking at somewhere around 13-14 digits (there are 3 or 4 decimal places, I think).  Something that bothers me about the behavior we see is that the switch from the oscillating values to the negative number is pretty much instantaneous.  It's almost as if the src and aux lines have their own counters rather than incrementing or decrementing the same value.  It doesn't look like the two are affecting each other.

Thank you both for your responses.  I'm currently working on getting the TestPanels running in Fedora and then I'll try the 32-bit and on-demand approaches and give an update on what happens.
0 Kudos
Message 8 of 12
(4,744 Views)

Briefly:

1. At least using drivers for LabVIEW on Windows, the default setting for Z-index reset is NOT enabled.  It must be enabled explicitly.

2. If Z-index reset IS enabled, then it'd happen every time Z is in high state while A,B are in their "specified" state combo.  I *think* the default combo is A-high, B-high.

3. Z-index might happen only for +dir and not for -dir in a two-pulse-encoder mode, depending on the A,B phase combo settings.  For example, if configured for A-low, B-high with your active-low pulses, then +dir would have B always high and A generating low pulses to increment count.  The Z-index might also be high with the right A,B phase.  But in the -direction, you'd have A always high and B generating low pulses to decrement count.  When Z goes high, A,B phase wouldn't be as specified so no z-index reset would happen.

4. Agreed that if Z-index reset happens at all, it should reset to the same value each time.  I don't think this can be purposely changed on-the-fly after the task starts running even if you try.

5. A sudden jump from positive oscillations to a large negative value seems inexplicable to me too.

6. Another troubleshooting thought.  Count the UP pulses with one counter and the DOWN pulses with another.  Use simple edge-counting mode and 32-bit integer reads.  Wire to the counters' source pins.  Do something like rotate +2 revs, -4 revs, +2 revs and see if you wind up back at 0.  Look for increments on the wrong counter at the wrong time.

7.  You mentioned that the chip provided helpful filtering.  Perhaps some of the odd behavior is caused by spiky noise that isn't fully filtered out?  Noise can be tricky, and it may be partly a coincidence that the Windows box was less susceptible (different physical location, different case & power supply, etc.)

-Kevin P.

ALERT! LabVIEW's subscription-only policy came to an end (finally!). Unfortunately, pricing favors the captured and committed over new adopters -- so tread carefully.
0 Kudos
Message 9 of 12
(4,738 Views)
I have gotten TestPanels running under Fedora, which is nice but I forgot that the only counter functionality it provides is edge counting and pulse-train generation.  It doesn't look like I can do any decoding.

I tried reading the data as u32 and that works.  With two pulse-counting I can get a number of pulses that is in accordance with what I'm commanding the motor to do.  The number it produces is just a raw number of pulses though, so does that mean that what was causing the problem was the driver trying to convert that number to degrees?

My Z-reset was set to 0, although with the problems it seems to be having with scaling that could cause those strange numbers I guess.  Now that I know that the resetting happens continuously throughout the running of the program I can see why the numbers hardly changed before.  The way this LS7183 chip works it's going to be outputting a high signal most of the time, and the default on the reset condition is A high B high.

Right now I can only use one counter because my other is defective.  We're going to have work out a repair or replacement with NI.

So is it correct that this whole problem is being caused by scaling?  If so, is it something wrong with my setup or is it something that is known to be wrong with the driver?  Is there a way to fix it?  Or am I just going to have to read in raw pulses and convert them to degrees or revolutions or whatever myself through coding?

Also, about the buffered vs. on-demand thing.  The only example program provided with the driver for measuring position is buffered.  I'm not sure how to set up an on-demand method as the coding aspect of this is relatively new to me.  Any suggestions on how to go about it?
0 Kudos
Message 10 of 12
(4,733 Views)