I am working with several components like RC servo, encoder, force transducers etc. Right now, I have not integrated the force transducer VI to the programming yet. The program I have developed is attached with the post. Let me briefly explain what the program does.
I am using 2 DAQ devices (i.e.), myDAQ and NI USB 6218. The top counter is from the myDAQ and it is used to send the PWM signals to the RC servo. The second counter is outputting a TTL pulse to the camera and the same signal is used as the sample clock for the encoder acquisition. The pulse for camera and encoder acquisition is achieved through USB 6218. For my application, I will send a step signal, which will trigger all the acquisitions inside the loop and before sending the trigger, no acquisition should occur. To model that, I have used a boolean LED. When I was setting the boolean to "switch when released", the program would give me an error that "specified operation cannot be performed while the task is running". So, I changed it to "latch when released". This time that error did not pop up and I got the TTL signals from 6218 to the oscilloscope. However, the problem now is that the counter input does not continuously give the angular position data. It just gives a few data points and then stops.
Can someone point out what is going wrong with this and how it can be corrected?
Solved! Go to Solution.
I can see a lot of problematic issues, for example having a control labeled "Empty array" and containing non-empty default data seems very confusing. (Also note that you can wire error clusters directly to the compound node. No need to unbundle). :Boolean" is not a useful name for a control that has a defined function.
You are starting a task in the TRUE case and next time the case is TRUE again, you are trying to start a task that has already been started earlier.
I think it would be worth defining the requirements better, write clean code (no crisscrossing wires behind structures), label all controls and indicators with functional names, etc. Typically once a diagram is cleaner, things fall into place automatically.
In that case, should the start function on second and third counter be outside the loop? If I do that, the TTL pulses are generated irrespective of I press the boolean button or not. So, that is kind of my main question that how do I properly output TTL signals and start encoder acquisition after the case becomes true?
Should I upload the code again with the clean up as you have suggested if that will help better understand the code?
I've got similar advice for you as what I gave recently in another recent thread. Rather than retype, I'll just quote myself.
I finally took a look at the code. From what I see, you're trying to do everything at once. There are several problems and I simply don't have time to guide you through every detail of every one of them. You need to take 2 or 3 steps back, take a few deep breaths, and accept that this process of writing code to integrate multiple bits of hardware you're only partially familiar with IS GOING TO TAKE SOME TIME.
Break it down into smaller pieces. Integrating is hard enough *after* getting the individual pieces working, but it's often exponentially more difficult when you don't. Experiment with the camera -- frame rate, pulses in, pulses out, exposure settings, etc. Learn what it can & can't do, and how. Then experiment with the photon detector and counter task. Try your edge counting method with finite differencing. Try my "inside-out" period measurement. Try to understand how and why it works.
Like I said in the other thread, it really isn't close enough to "right" yet that I can guide you all the way to the finish line. Do come back with specific questions (but please link back to these earlier threads for context), but be prepared to put in some time learning and experimenting too.
As I understand your system, your end goal is (or should be) to coordinate and synchronize a variety of equipment and sensors. Most of the burden for doing this should be shifted over to your DAQ hardware, such as the counters. There's still a *little* bit of stuff you've gotta do right in software, but hardware's really the main answer.
And it looks like you've gotten started in that direction, but it also looks like you mixed it all together too soon, before you thoroughly understood and debugged the component parts.
So I'd say, back up a few steps and start making small bits of code that each accomplish ONE of your goals thoroughly and well. Experiment, learn, understand. Then try coordinating / syncing TWO of the things. Explore, learn some more. Then THREE things, and so on.
There is no short answer to your query, "what is going wrong and how can it be corrected?" except the old joke:
Q: Can you tell me how to get to Carnegie Hall?
A: Practice, practice, practice!
- write code to operate your RC servo with a PWM signal. Put all the task config in one subvi you can reuse later in your overall project
- write code to generate pulses for your camera. Figure out how you'll manage the images it captures.
- disconnect the camera and then write code that measures your encoder, using those same pulses as a sample clock. Get familiar.
- now reconnect the camera. Drive both camera and encoder sampling from your pulse code. Figure out how you'll make sure you know which camera image corresponds to which encoder sample.
- and so on, small steps forward at a time
Thank you for the reply. As you had mentioned, I developed the code by integrating one component at a time only. For example. I wrote the code for servo and made sure it is working, and then moved onto generate TTL pulses for camera etc. As you suggested, I will try to make subVIs so that it is less confusing. Only after integrating the encoder code with the whole code, I started seeing the problems, which I had mentioned in my message.
Eventually, the boolean in the code will be replaced by a signal from an external source. I have used boolean for now just to test if all other components are working or not.
I put a little more time into looking things over more closely now that I know you already worked on the individual parts before integrating. Honestly, the unnecessary messiness of the code is something I've learned to correlate with, "this one's gonna take more time than I'm willing to give." I'm not always right, but it's been a fairly decent early screening criterion overall.
I think the biggest error is that you've made your 3 tasks overly interdependent by putting interactions with all of them in 1 single loop.
Your RC servo PWM task doesn't have any interactions with the other tasks. It would more naturally belong in its own loop. It'd also make sense to use an event structure so you only write a new duty cycle to the task when there's a "Value Change" event on the duty cycle gui control.
Similarly, the only thing you do with the other counter output is decide when to start it. Seems like that could maybe move into the previously-mentioned event loop, using a "Value Change" event from the triggering booolean.
The AI task should have its own loop and you should plan to start the task before the loop. Because it gets its sample clock from the 2nd counter, no samples will be taken until you trigger that 2nd counter.
There are different ways to handle this. (Even one involving DAQmx Events and the same event loop, but let's not go there for now.) An easy one is to start looping over the DAQmx Read call, knowing you'll keep getting timeout errors until you trigger the 2nd counter. That's ok, you can clear and ignore that specific error because you, the programmer, know that it's *expected* given the way you've set things up.
Once you trigger the 2nd counter, it'll generate pulses, the AI task will use them for sampling, and your calls to DAQmx Read will stop timing out and start returning data.
There will be more things for you to work out, but that much should give you a pretty decent start.
Thank you for the reply. I figured out the problem that why the encoder was not giving me continuous data. As you had also suggested, I took out the DAQmx read for the encoder outside the case structure. So, the encoder was only triggered when it received the clock signal from the counter output. Now, the program is working as desired (i.e.), when I press the boolean button, only then the servo starts working and the TTL pulses are generated and the encoder starts acquiring. There is one more component (i.e.) the force transducer that will be added to the program and that has to start acquiring after receiving the trigger as well.