Jump to content

Mark Smith

  • Posts

  • Joined

  • Last visited

  • Days Won


Everything posted by Mark Smith

  1. Error -50103 occurred at an unidentified location Possible reason(s): NI Platform Services: The specified resource is reserved. The operation could not be completed as specified. This means you're likely trying to do the same class of task at the same time on the same device - for instance, if the task is analog in and you've already got an analog in task running on the device, you can't start another (if the device has a single ADC - some have multiple ADCs and you can do this - you'll have to read the device manual). You can, in general, do things like an analog in and analog out on the same device at the same time since they use different physical components of the device. Mark
  2. Now might be a good time to download an eval copy of the Execution Trace Toolkit - it's not without its own issues, but it really might be helpful in this instance to see where the memory is actually getting allocated at run time. Mark
  3. I don't have a particular microphone to recommend, but if you can attach the microphone to the UUT (with a simple clip or strap or such) then a simple contact mic would work well. You won't have to worry about ambient noise and the vibration, in particular, will be easier to detect if most of the energy from the signal couples directly into the transducer. Also, you can save yourself a lot of headaches by getting a simple commercial mic preamp to condition the mic signal and convert it to audio line level before you send it to the DAQ. I would think you get everything you need for <$150 - maybe a lot less. Mark
  4. Just use the "Shoot Yourself" Assistant - until you get an "insane object" error
  5. I'm with you - that's been my entry point and I don't see it anymore either Mark
  6. You are correct - the second loop can't start until the first finishes because there's a direct dataflow dependency between an output of the first loop and an input of the second - so, you need to rethink the program flow. Since all of the data saving is handled by the consumer, the file initialization is probably best handled there as well. And since the consumer loop determines whether or not there's data to save, it could create the file when the log data button is operated and then use an uninitialized shift register to handle the file ref between calls. This is a functional global variable (FGV) in LabVIEW terms. See the GasManifold2.vi in the attachment Mark Gas Manifold.zip
  7. User events can be a good solution to the single producer - multiple consumer pattern. The producer fires the user event with the data that you're now putting on the queue and every consumer that has registered for that event and is listening for it will get the same data. You can have anywhere from 1 to n listeners (I don't really know what the upper bound is but it is bound to be large enough). The caveat is that if you have a queue, you're guaranteed a lossless data transfer - if the queue listener is busy, the producer can just add data to the queue or block until space is available and the consumer will always have access to the data until the queue is destroyed. If a producer fires an event and no one is listening, the data just goes to the bit bucket, as far as I know. So, if you use events and you want data integrity make sure your consumer is faster than your producer. You could also use the event time stamps to tell if you missed a data message. Other wise, I think two queues as suggested would work. Also, I can't access the code from this machine but I also think your approach as I understand it is valid as well, where you dispatch the queue data after you dequeue it to the correct case for that loop iteration since you don't really need asynchronous processing. Mark
  8. By my comment that this predates SCPI, from a brief glance at the manual it looked to me that the text commands didn't necessarily follow the SCPI standard (which may well have not existed when this instrument was built) but I could be wrong - actually, I'm probably wrong since I only spent 45 seconds or so looking . I agree that's exactly how you would send a reset command (which happens to be SCPI) with HP Basic. Mark
  9. I think this explanation makes a lot of sense - the array (or string) handle must exist before the data can exist (the heap gets allocated) and that's what we see as the allocation dot. I do think the LabVIEW tool to show allocations is a little misleading in that the buffer allocation dot that shows LabVIEW just grabbed a 32 bit handle for a possible array looks just like the allocation dot that says LabVIEW is going to make a copy of 200Mb of data from an existing array. No wonder it all seems a little confusing Thanks, Mark
  10. By fail at runtime I mean the dequeue will fail (set the error out true) if run without first creating a queue. That's just meant to show that the dequeue will compile without any knowledge of whether or not a queue has been created so I was trying a mental exercise to see how a dequeue would know that a data buffer can be reused if it knows nothing about the queue size or even if the queue exists. That's all. I doubt the buffer ever gets created if the queue ref is bad, however. And I do agree that it was accepted practice in the DBDVR (days before DVR) to use a single element queue as a way to pass data by ref and avoid making copies as you and Ben have pointed out. I'm just trying to make sense of this buffer allocation on dequeue thing at this point - I really am feeling confused. Also, your argument about creating buffers for queue element refs makes a lot of sense except that the Show Buffer Allocations tool specifically shows an array buffer being allocated in my snippets above - if I do the same thing and replace the the array with a string (and the array size with a string length) the Show Buffer Allocations tool now shows the buffer allocation on the dequeue as a string. So the tool thinks a buffer is getting allocated of whatever type of data the queue holds. I know this doesn't help explain anything, but I appreciate the discussion! Mark
  11. I still see a buffer allocation here. I don't doubt that you get exactly the performance you report, but I can't create a dequeue operation that doesn't show a buffer allocation . So in order for LabVIEW to "see" a data buffer in a queue is no longer required, LabVIEW has to decide at runtime that the buffer is available? For instance, the first code snippet is perfectly valid at compile time but because no queue exists it fails at runtime. So this means the Show Buffer Allocations can't accurately show the runtime allocations for a queue ? I'm confused!
  12. Here's what I'm seeing that makes me think you just can't avoid a buffer allocation on a dequeue - I don't know exactly how you could modify this to eliminate the allocation. But maybe I misunderstood the original question. Mark
  13. Looks like this instrument predates SCPI and is no longer supported by Agilent (and all the documentation referencesHP-IB - not exactly a modern instrument) - here's a link to the manual http://www.home.agilent.com/upload/cmc_upload/All/04142-90010.pdf Look at the command sequences in the HP Basic examples and try to figure out how they might work in LabVIEW - good luck, this looks painful. Mark P.S - is this just coincidence or a duplicate post? http://forums.ni.com/t5/Signal-Generators/driver-hp-4142b/td-p/115360 Mark
  14. I don't think this is correct - the only wire I see branched is the queue ref, so this ensures you get a copy of the queue ref, not the queue element. I'm not privy to the internals of the queue implementation, but I think I do recall that I have read it is a protected implementation of shared memory. And I don't think the queues could execute at exactly the same time since a mutex or some such mechanism protects them so a queue read or write is always an atomic operation - that's the only way one could guarantee the FIFO behavior. Also, I built a simple example following the posted diagram - I get a buffer allocation on the dequeue if it wires to anything at all, even an array size function (which I'm pretty sure doesn't require a copy of the data to operate). And this is without even including the enqueue in the producer loop. So the buffer allocation seems to be part of the implementation of the queue and a DVR around the queue wouldn't help. I agree that the DVR would most likely be the most efficient way to go since as I understand it it could be thought of as a "safe" pointer. So you could write data to the DVR location in the producer and read it in the consumer and since the DVR is "safe" in the sense that you don't have to manage access and all operations are still atomic (I think) what you lose is the ability to use non-polling process in the consumer. Now, you'll have to poll the DVR and have some mechanism to determine if the data is fresh. Maybe just include an updated flag in a data structure that includes your array. Then you could operate on the array with an in-place structure and avoid making unnecessary copies. Mark
  15. playing at the Santa Fe Wine Festival this weekend

  16. We need more info before we might be able to help 1) are you using IP in dot notation or hostname as address? 2) are you specifiying the local port or letting the OS select the next available? 3) what is your timeout setting? 4) have you used a network packet sniffer (Wireshark) to look at the actual TCP/IP traffic? Mark
  17. What's taking you so long!? Seriously, this looks like it could be a really useful toolkit for those of us that learned OOP using C# and have wondered how to apply some of those lessons learned to LabVIEW. Thanks for the contribution to the open source community! Mark
  18. Here's the way I understand the buffers - and I don't guarantee this is correct! The DAQmx driver for AO allocates memory on the host computer's memory - this is the "buffer". If you are in non-regeneration mode, this buffer does act as a FIFO. A typical sequence is 1) LabVIEW program creates a waveform/analog signal and writes that data to the host computer's buffer when the DAQmx Write VI is called. 2) In non-regeneration mode, this data is consumed - the calling program is responsible for making sure there's data in the host computer's buffer as long as the DAQmx write command is requesting it. If the data buffer ever gets empty before the write is complete, DAQmx errors. 3) In regenerative mode, the task will not consume the data in the buffer and instead just re-read from the buffer for the duration of the requested waveform. The default data transfer mechanism from the host buffer to the on-board memory is DMA. This can be changed to interrupt driven, but there's hardly ever any reason to do so. The DAQmx drive takes care of all the transfer from the host memory to the onboard memory. Mark Mark
  19. I can help answer part of your question - for the analog output buffer, there's a property you can set thru the DAQmx Channel - here's the blurb from the LabVIEW help file. I think the default is Less than Full. Mark Analog Output:General Properties:Advanced:Data Transfer and Memory:Data Transfer Request Condition Property<h1>Analog Output:General Properties:Advanced:Data Transfer and Memory:Data Transfer Request Condition Property Short Name: AO.DataXferReqCond Property of DAQmx Channel Specifies under what condition to transfer data from the buffer to the onboard memory of the device. Onboard Memory Empty (10235) Transfer data to the device only when there is no data in the onboard memory of the device. Onboard Memory Half Full or Less (10239) Transfer data to the device any time the onboard memory is less than half full. Onboard Memory Less than Full (10242) Transfer data to the device any time the onboard memory of the device is not full.</h1>
  20. Thanks for all the suggestions - this at gives me a place to start. It looks like 6 PCI slots is no problem if I go the single board computer/expansion chassis route ( up to 14 seem readily available). But no dice if wanted a motherboard with 6 PCI slots - most only have up to two PCI slots with the rest being PCIe. Thanks, Mark
  21. Anybody have any opinions on suppliers of industrial rack mount (19") computers? I'm upgrading some testers and each uses up to six PCI slots. The current computers are old and need to be replaced but the PCI DAQ cards and instruments still meet our needs so I intend to keep using them. I haven't tried to buy rack mount computers in a long time so I have no idea who might be supplying quality product. And while price is considered, I'd take reliability and support over price any day. BTW, I intend to run Windows 7 and exe's built in LV2009. Thanks, Mark
  22. By Application Close icon, I assume you mean closing the top level VI with the red X in the top right corner of the active window. If so, don't use the Application Close event - instead, use the <this vi=""> Panel Close? event and set the Discard? property to True (the property shows up on the event case after you select this event). What this does is catch the panel close event and filters the actual panel close command. So the panel will not close but you can use the event to fire whatever's in the event case that handles it (could be the same code as your exit button calls) and then use a property node to close your panel after all your clean-up code executes. The only complication to this approach is that the Panel Close? and Value Change? events can't have the same event handling case so you might want to have your cleanup code in a SubVI to make it easy to call from two places. Or another approach (some might consider it a hack but I think it's OK in this particular situation) is to just have the Panel Close? case fire the Exit button's value signaling property to force the Exit case to execute. Mark<br><br>Edit: OK, Francois types faster than I do <br></this>
  23. One thing that works is to create the source VI as a re-entrant VI (instead of VIT) and launch it with the 0x8 flag set in the Open VI Reference function. Then, each copy gets spawned as a unique instance. You can track the instances by unique ref num or use the CloneName property for the spawned VI. I use the clone name to create named queues that I then use to collect/send data from all of the spawned instances running in their own threads. This is similar to what you're doing except LabVIEW names the clones instead of you and this does work in the run time. Mark
  24. Thanks for the first-hand info - that gives me confidence that all will be OK! I suspected as much, but I don't have any experience with 64 bit OS's. Mark
  25. I've looked thru the LabVIEW faqs and dev zone stuff on 32 vs 64 bit LabVIEW but I can't seem to find an answer to this specific question. That is, if I install LV 32 bit on Win7 64 bit and build an exe (from LV 32 bit), does it build an application that I can install on other 32 bit Win OS's (XP SP2 is the one I have in mind)? I'm in the process of finally upgrading (I get a new machine and I get to install LV2009 finally) and I'm trying to make a decision about whether my primary Win7 OS should be 64 or 32 bit. I have to be able to build code I can deploy to WinXP SP2 32 bit machines. Thanks, Mark
  • Create New...

Important Information

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