Jump to content

ned

Members
  • Posts

    571
  • Joined

  • Last visited

  • Days Won

    14

Everything posted by ned

  1. I saw this issue when I first upgraded to LabVIEW 8.2, but at the same time our network drives were regularly having problems so I assumed it was related to that, even though LabVIEW 7.1 never complained. Since then our IT staff has apparently fixed something related to the network drives and I no longer see the error, but I have no idea what changed. Sorry I can't be of much help other than to tell you that you're not the only one who's seen the problem. If I get an opportunity I'll ask our IT staff what they did.
  2. At the risk of repeating myself... just create another notifier, like you did for the inputs, but this time put the "Send Notification" inside of MotCan.vi, and the "Get Notifier Status" inside the while loop of the Plate Motor VI. Wire the actual speed as the notification to be sent and you'll be all set.
  3. Perhaps I'm misunderstanding your problem, but you can use notifiers for your outputs, too.
  4. I don't think I've seen this mentioned yet. One improvement I like is that it's now possible to get help by right-clicking on a function within a pinned palette - no need to drop the function on the block diagram first.
  5. I usually create notifier controls or indicators by right-clicking on the "Notifier" terminal of any notifier function and choosing "Create -> Control". I then copy and paste the control wherever it's needed.
  6. The reentrant VI solution is the right way to go, and you just need to separate the logic from the user interface. Create a custom control of a cluster containing the speed, power and direction controls and place one instance of it for each motor you want to control. Then, use a notifier to pass values from the user interface into the timed loop while the loops are running. Note the use of "Get Notifier Status" and not "Wait On Notification" in the subVI. As often happens with LabVIEW, a diagram is much clearer than an explanation, so take a look at the illustration below.
  7. The attached ZIP file contains two folders, each containing one project. Open both projects, then open "copy typedef bug.vi" from project 1, and "blank fp.vi" from project 2. Try to copy the enumeration from the front panel of "copy typedef bug.vi" to the front panel of "blank fp.vi" (copy/paste or drag) and notice that it fails silently, because there's a conflicting type definition already in memory in the application instance for project 2. I accept that the copy should fail, I just don't think it should do so without explaining the error. If you're trying to copy a number of front panel elements at once, one of which happens to be a type definition, and the conflicting type definition in the target VI is buried several layers deep in subVIs, it's very puzzling to see the copy fail. Download File:post-3989-1165587744.zip
  8. The way you're doing it is just fine. Surround your for loop with enabling and disabling the front panel property "Defer Panel Updates" as shown below. All the controls will be disabled simultaneously when you disable "Defer Panel Updates" at the end of the loop.
  9. Maybe you could try an alternate interface. Instead of showing the user an array of steps, have a listbox showing the steps that have been created, and one single cluster control. The user could set up the cluster, and then insert that set of parameters into the list of steps. See the attached mock front panel. When the user selects an existing step from the list, update the cluster control (using a local variable). You'd need to maintain a list of the steps that have been created by putting an array of clusters into a shift register. As for for activating only the appropriate controls, see the attached block diagram image. Note that on the front panel I've moved each set of parameters into its own sub-cluster. When the user selects a type of test, it automatically enables the appropriate sub-cluster of parameters, and disables the rest. I hope I've provided enough detail for you to implement this, if you like this approach.
  10. In your VI, the loop time is irrelevant; the reason that your LabVIEW results don't match your Simulink results is because the dt input to H(s) is too large. You are supplying the dt input to H(s) so you'll always get the same results regardless of how fast the loop runs. If your loop time matches your dt, then your code executes in "real time" - at the same rate as an equivalent physical system. However, you probably want to simulate faster than that (as Simulink does), so if you were to make your loop time 1ms, but leave your dt input at 10ms, you'd get your results 10 times as fast as real life. A better approach, though, might be to put your processing into a for loop inside your while loop, as shown in this diagram:
  11. This doesn't solve the problem, but if you do need to force your constants to update, open the strict type definition, change the representation to some other data type (ie, U16 to I32), apply changes, and then change it back. This was mentioned in an Info-LabVIEW post a year or so ago.
  12. Right, except that what I'm trying to do here is directly replace an existing queue (carrying a variant) with a TCP/IP connection. If I flatten the variant to a string, then when I read from the TCP/IP connection I can put the data directly into a variant and place it on the queue as though it had come from the queue locally, and the network VI doesn't need to know anything about the type of data in it (thus making the VI easily reusable). If I use Variant to Flattened String, then the receiving network VI needs to be able interpret the data, even though I'm just going to turn it right back into a variant and enqueue it. Also, I'm using variant attributes, which are conveniently transferred when flattening a variant to a string, but aren't available using Variant to Flattened String.
  13. I have an application that handles communication between a control loop and the user interface by passing messages over a pair of queues that contain variants. In order to allow these two loops to run on separate machines, I've added a VI to each loop that dequeues an element, flattens it to a string, sends it over a TCP/IP connection, and does the reverse on the receiving end. This all works great, and since I'm flattening the variants directly to a string I can use it for any data whatsoever that comes over the network. However, sometimes I'm sending clusters back and forth, and the cluster element names are included in the flattened string, which adds unnecessary network traffic. Is there any easy way to "anonymize" my clusters, either before they're queued or before sending them over the network?
  14. NI provides example code for sending a file over a modem from a FieldPoint unit, and the same code should run without major modifications on a PC. If simply having remote access to a data file is sufficient for you this might work.
  15. You might want to see this post about obtaining queues. It's not that there's a bug in obtaining multiple copies of the same queue by name, it's by design - every time you obtain a queue by name you need a corresponding release queue. You should not do obtain queue in a loop unless you also have a release queue in that loop. Personally I generally pass queue references directly to subVIs in most cases to avoid this problem; the main VI is responsible for both creating the queue and destroying it when it finishes. This approach also allows the main loop to signal termination to any subVIs that may be waiting on the queue, because any queue operation will generate an error once the queue has been destroyed. There are times when having each subVI obtain its own copy of the queue is useful - for example if you want to run and debug just the subVI and it needs a valid queue refnum.
  16. NI has already done it and has an example to share, even for those who don't have the PID toolkit: C:\Program Files\National Instruments\LabVIEW 7.1\examples\daq\solution\control.llb\simple PID.vi (also available in LabVIEW 8.0) Or you can find this in the Example Finder under Hardware Input and Output -> Traditional DAQ -> Solutions -> PID and Alarm Controllers -> Simple PID Demo It's not as elegant as the one in the PID toolkit but does the same thing.
  17. If you know the destination email address in advance, you could look up the SMTP server for that address and connect directly to it, which would avoid needing authentication. You can use the "nslookup" tool on Unix or from a Windows command prompt to do this, as shown below. The server with the lowest MX preference has first priority. If your users can enter the email address then this becomes more work, but perhaps you could get the domain from the email address, feed the query to nslookup using "Shell Exec," parse the output and determine the server to which to connect. C:\>nslookup -q=mx yahoo.com Server: nfcntad01 Address: 172.20.0.215 Non-authoritative answer: yahoo.com MX preference = 1, mail exchanger = mx2.mail.yahoo.com yahoo.com MX preference = 1, mail exchanger = mx3.mail.yahoo.com yahoo.com MX preference = 5, mail exchanger = mx4.mail.yahoo.com yahoo.com MX preference = 1, mail exchanger = mx1.mail.yahoo.com
  18. This is exactly the expected behavior. The Dialog Box vi does not terminate until the user clicks the button, and that's important - there are times when you might want to wait for the user to acknowledge the message before continuing (that's why there's an output from the Dialog Box vi). A structure (case statement, while loop, etc) can't complete until every VI inside of it has terminated, so your VI waits in the case structure until you click OK. Second, the code is not ignoring the effect of the property node until after you click the button - in fact, you may see that the motor button does change positions on the front panel while the message box is still visible - but that's not enough to turn off your motor. Somewhere in your code you must be reading the value of that button and writing that value to a relay, and your motor isn't turning off because the message box is preventing that read from occurring. One easy solution is to write directly to the relay inside your case statement (but also update the property node so you don't turn the motor back on again after the user acknowledges the message). Another is to put your message box in a separate loop, and use a notifier to tell that loop to show the message box. If you post your code, I'm sure someone will be able to suggest a good solution for you.
  19. I'm not sure I've completely understood what you're trying to do here, but here's my suggestion: Don't use a state machine. Instead, create an array of clusters and store that in a shift register in the while loop. Inside the while loop, remove the first element of the array, which should be a cluster containing the name of the remote FTP server, the directory, and list of file names. Run your code for that loop. If it succeeds, continue to the next element of the array; if it fails, add that cluster back into the array and try again. See the attached image. Also note that I disconnected the error shift register inside the while loop. Be careful with storing errors in a shift register; the way you had written it previously, if one case caused an error, that error would continue through the rest of the cases, probably causing them not to do anything.
  20. You could also modify "TCP Listen.vi" to allow you to pass FALSE to the "Resolve Remote Address" terminal of "TCP Wait On Listener.vi".
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.