LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Continuously sampling an analog input while running an event structure

Hi,

 

I'm fairly new to LabView, so hopefully I'm just missing something basic here.

 

I'm trying to control a Maxon EPOS2 motor controller with LabView.

 

The system has a motor and a position sensor whose ouput is an analog 0-5V signal.

 

What I'd like to do is have a button on the front panel. When the button is clicked the first time (setting it to "true"), the program commands the motor at some positive constant velocity until the position sensor rises to a particular voltage. Once the voltage is hit, the motor stops. When the button is clicked again (setting it to "false"), the program commands the motor at some negative constant velocity until the position reading drops to a particular voltage. Once the position sensor drops below that voltage, the motor stops.

 

 I've gotten all the individual parts of this to work on their own - I can command the motor, and I can read the position sensor. But doing both of these simultaneously and implementing the logic is giving me trouble. My VI so far is attached.

 

The general problem (I think) is that the Position Reading isn't getting through to the event structure, probably something related to data dependency between multiple structures. However, I've noticed that if I take out the while loop around the encoder reading portion of the code, the program doesn't read the analog input except for when I click the mouse (and then it's just an instantaneous update, not a live readout).

 

How can I organize these structures to get the motor behavior described while maintaining a live readout of the position sensor?

 

 

Thanks!

 

Download All
0 Kudos
Message 1 of 6
(3,692 Views)

You need a two-loop solution, because the Event structure only operates once when you give it an event (which you found out). A two-loop solution, when you put it together right, allows one loop to start another (Okay, Move.), then the second loop can continue until it finishes, with all the features you had in that "individual part" VI (STOP HERE!).  I'd use a Producer-Consumer architecture, which is designed specifically for when the Producer loop is over quickly and the Consumer loop can take as long as it wants to finish. There was just recently a long discussion of it in this forum (it's a fairly common topic), and there is an NI whitepaper introducing the concept here. (Searching NI for "producer-consumer" also leads to at least 669 hits, one of which was that link).

 

Cameron

 

To err is human, but to really foul it up requires a computer.
The optimist believes we are in the best of all possible worlds - the pessimist fears this is true.
Profanity is the one language all programmers know best.
An expert is someone who has made all the possible mistakes.

To learn something about LabVIEW at no extra cost, work the online LabVIEW tutorial(s):

LabVIEW Unit 1 - Getting Started</ a>
Learn to Use LabVIEW with MyDAQ</ a>
0 Kudos
Message 2 of 6
(3,667 Views)

In addition to what has been said already, you need to backtrack much more, because your code is faulty in many more ways.

 

Dataflow:

  • the outer loop cannot go to the next iteration until everything in it has completed. Since the upper small while loop never completes, the outer loop is stuck.
  • The position limit terminals only get read once, so the lower inner while loop will either run forever or stop immediately, depending on the values.
  • The position reading from the upper while loop will only exit the loop once the loop has finished. Since it never finishes, the event structure cannot execute because it depends on it.
  • The "mouse up" event will not work as expected, because the terminal gets read right at program start, and once the event fires, you'll get a stale boolean value. Terminals typically belong inside their respective events so they only get read once the event fires. You should also use value change events instead of mouse events. This way you can also read the new value from the event terminal if needed.
  • Your case structure has a lot of shared code. Only place the code that differs innto the case structure.
  • There is no need for the sequence structures. Just wire the error wire across the inner small while loop and all execution order is fully determined by dataflow.
  • You should NOT place while loops inside events unless they are guaranteed to complete quickly.
  • ...
0 Kudos
Message 3 of 6
(3,657 Views)

Thanks Cameron and altenbach! With your advice I was able to get something that functioned the way I'd like. I'm not convinced it's necessarily done the "proper" way though. I attached the latest code for reference and in case either of you have any further advice - I'm new, so I'd love to learn how to do it the right way.

 

One question I do have is about the queueing. As I understand it, the first while loop is piling position readings into a queue that is first-in-first-out. Then when the second loop executes the event structure, the dequeue function starts pulling data off the queue. But that seems like it would be pulling off old data - the data that was added to the queue during the time the first loop was executing but the second loop was not. Or does a dequeue function only pull data that was collected after it was called? Or is the queue only an element or two big by default, so that it will fill up right away and not grab a new value until the second loop starts dequeueing?

 

Thanks so much for the help, I was really happy to see the motor act the way I wanted it to!

0 Kudos
Message 4 of 6
(3,638 Views)

Found some issues with my last piece of code, possibly related to my question on queueing. Worked fine in some earlier code where I kept the dequeue inside the case structure, but when I moved it out it looks like it kept trying to read old values (that were outside the acceptable range) so it was exiting the loop immediately. I added in the queue flush to empty out old values so it can read in the most recent data.

Download All
0 Kudos
Message 5 of 6
(3,626 Views)

In both VI's you are continually loading up the queue.  Nothing gets dequeued until the TV Control boolean's value changes.

 

In this VI, when the event finally executes, you get the first element in the queue, the oldest.

 

Previously, you were flushing the queue which emptied it out.  Then it waits at the dequeue waiting on the next element which is going to be very fresh.

 

Is there a reason you are using the queue?  If you are discarding all of the old elements in the queue, what's the point of queueing things up?  You might as well use a notifier which gives you the latest element.

0 Kudos
Message 6 of 6
(3,620 Views)