I have run into an issue with my .vi where I believe either multiple physical channels or my limited understanding of timed loops.
I have only been using LabVIEW since about November, and most of what I have learned is blunt force knowledge, so hopefully you can see what's going on in my code. Basically, I am reading in from two encoders to measure the movement of a device. At the same time, I want the .vi to be able to "watch" the encoder, figure out when the device has moved a specific distance (say 1mm) and then read in a sample from a continuous string of voltages (I've simplified the code for this question) so that we have a measurement for that point.
Previously, I had the encoders both reading in through the DAQ Assistant, and the distance measurement and angle measurement seen in the code were both working. I changed to using the DAQ subVIs because I thought I needed to so that I could pull off another instance of the physical channel for encoder 1 (seen as a local variable in the file). I then added the timed loop to try to tinker with it to use as the timing for the measurement. I'm sure you can figure out how I've got that set up.
I'm not sure that this approach will work, but it was my best bet. I am getting an error that I have looked up and seems to deal with the fact that the M series DAQ cards can't do timing, but I'm not entirely sure what this means. Can someone please give me a more detailed explanation on what is going on? Remember, I haven't been doing this long, but I want to know how this really works.
Solved! Go to Solution.
I got the counters themselves to work again, so that if I disable the timed loop it works just as it did before (I didn't realize that they had reset and were both trying to read the same counter).
I have made another new VI just for the timed loop to see if I could get it to work as a standalone. It works in the sense that there are no errors or warnings, but doesn't seem to be waiting on the encoder like I want it to. Again, I want it to wait until the encoder reaches a certain count and then read in a voltage. I'm not sure if I'm understanding the timed loop correctly but this seems to be exactly what the DAQmx Create Timing Source (Digital Edge Counter) VI is used for. I am also using the same settings in the standalone as in the combined VI, but am still getting the error when they are combined. That is why I think there is a problem with the channel being used over.
An associated question: what exactly is the source input for that VI used for? I read the detailed help and still don't quite get it. Is the VI actually waiting for the counter to tell it to look for edges on the source? I have it set to the onboard clock because that is the only thing that seems logical at this point.
Thanks for the help. I'm getting pretty frustrated because up until now I've been able to fix any problems pretty easily. This is probably a little over my head, though, and if it doesn't work like this I'm not sure where to go next.
I guess I'm not sure why you're using a timed loop for this.
If I understand you correctly, you want to allow the encoder (i.e. the counter) to reach a certain number, then read in an analog voltage. Why not just monitor the counter until you reach your number and then use a case structure to either read your voltage (counter is at the correct count) or not (counter is not at the correct count)?
Sort of like this:
Also, have you looked at any of the counter examples that ship with LabVIEW? (Help...Find Examples...Hardware Input and Output...DAQmx...Counter Measurements...Position) There are some examples that show how to read a position from a quadrature encoder that you might find interesting.
As to your problems with your original code, my best guess as to why you are unable to make your counter tasks work with your timed loop task is because you have both counters configured as inputs (so you can count edges), but then you are trying to use one of them as an output (i.e. a source for your loop timing) at the same time. I'm quite sure that's not possible. A counter has to be either an input or an output...it can't be both.
I hope this helps.
I think this is exactly what I was looking for. The way the process was explained to me, I was automatically thinking about timing the reading-in. Doing it your way should allow me to put all the pieces together fairly quickly (since I already have both encoders working). The problems all arose when I tried to do too many things with the counters.
As for the examples, that's where I've turned to first. I think I've got the position measurements the way I need them already.
Thanks again, this was tons of help!
For general coding style, a few comments:
You have lots and lots of unnecessary local variables. Why?
For instance, your control "Encoder 2 resolution" is sitting outside the loop, wired to nothing...and you have local variables all over the place to read its value (including one of its local variables sitting right next to it!!). Delete every single one of those locals and wire the value in directly from the control. It's perfectly all right to branch a wire. When branching wires, do keep it tidy, however, for the sake of readability.
Do the same for your other controls. Not a single one of your locals is necessary, so get rid of them.
I counted six -- six! -- separate local variables of your "Wheel circumference" control inside the same loop. Huh? What's wrong with just branching the wire? And since that value is calculated up front, before your loops start, why do you need those locals anyway? Do you really WANT six copies of that value in memory?
Also, you have two indicators named "Relative position (cm)" and two indicators named "Relative position (in)". That's mighty confusing. They should have different names, so as to make your code easier to read.
This may seem nitpicky, but style is very, very important in a graphical programming language. (You may very well have to come back to this code a couple of years from now, and you don't want to be sitting there swearing because it's unreadable.) Abuse of local variables often leads to race conditions, which are a pain to debug, so please get out of the habit of using them. Sometimes they're necessary, which is why they exist, but in this code, they most definitely are not. Whenever possible, always wire directly from the control.
Some of this I new was going to be a problem. The local variables I started doing because I had trouble keeping track of what wire was carrying what data. I learned how to put dataflow programs together using a program that was MUCH more complicated than I was ready for and just had to dissect it little by little. With the more complicated program the wires can span several screen widths and I was trying to clean it up when I was checking my math so that I didn't get lost. I will work on getting that cleaned up, but to be honest I was just waiting on someone to tell me I had to .
As far as the front panel configuration, a lot of the confusion is because I tried to simplify the code to post on here. The working version I have is labeled a lot more effectively, but I'm still struggling to group things so that they are related but the decorations aren't overdone. This program is going to grow aggressively in the next few months so I need to come up with a more efficient way of adding on to it both in the front panel and the block diagram.