Jump to content

Daklu

Members
  • Posts

    1,824
  • Joined

  • Last visited

  • Days Won

    83

Everything posted by Daklu

  1. Kudos to Chris for bringing this to my attention! Kudos to Jon for making sure I don't use it!
  2. The last couple weeks I've been chasing a performance issue with an I2C data collection component I wrote. Specifically I've been using Process Explorer to monitor (and try to reduce) the cpu load. The attached WaveformStressTest vi is a simplified model of the display component of my application that I've been using to try and figure out the issues. The questions below are some of the weird things I've seen while exploring the limits of the waveform chart. *Noob Questions Alert* Sure waveform charts have been around forever, but I actually haven't used them for anything meaningful until this project. So while this is probably a "well, duh" moment for the rest of you, for me these are a "huh?" Q1 The waveform 'Synchronous Display' property help says... In multithreaded systems, you can use the Synchronous Display property to set whether to defer updates for controls and indicators. I've always took that to mean setting that property true synchronizes the display updates with the data arrival. Now that I'm looking at it again it's ambiguous. Does setting it true synchronize display updates with the data arrival (refreshing every time new data arrives) or synchronize display updates with the regular screen refreshes (buffering the data until the OS screen refresh occurs?) Q2 Why does a strip chart's cpu load increase so much once the data actually starts scrolling? Enable the disabled case for Test Config 1, make sure all four charts are empty and set to strip chart mode, then run the vi. I get ~25% load while the data makes its way across the chart. Once the data starts scrolling the load jumps to 50%. I don't think it's due to the strip chart's circular buffer background processing, since minimizing the window drops the load to essentially 0. Is it because once the data starts scrolling the entire chart surface has to be repainted as opposed to just the section that has new data? Is repainting *that* inefficient? This is one place where I'd expect the synchronous display setting to help out, but changing it doesn't seem to have any effect on load or display. Q3 Why does a scope chart use so much less cpu time than a strip chart before the strip chart data starts scrolling? I'd expect them to be about the same, since in both cases they only have to repaint the part that has new data. Yet the strip charts use ~25% of the cpu while the scope charts use ~13% of the cpu. Q4 Try this... Start the test vi. Set each chart to strip mode then back to scope mode so they are all in scope mode but reach the end of the display at different times. Minimize the front panel for a second or two then restore it. Things look normal. Now minimize the panel for 10 seconds or so and then restore it. All the data that should be displayed has been erased and the four charts are synched. Is Labview being a good citizen and releasing that memory if we don't need it within 10 seconds? Q5 (This one has me stumped) Enabled the disabled cases for Test Config 2. In the display loop I set up a simple case stucture so each chart only displays every 20th data point. The charts should show a smooth line with a constant slope. Instead I get long delays between screen refreshes and a jagged line, indicating the chart isn't processing all the data it is receiving. Probing inside the cases with the chart controls shows they are executing correctly. For some reason the charts are not processing the data they receive. Note the processor load in this test is relatively low at ~10%. Test Config 3 is the one that most resembles where I am now in passing parsed I2C data to my display loop. Each of the four sensors sends out a data point ~every 3 ms. Once I realized I couldn't send each point to the chart as I acquired it and let the Synchronous Display property manage refresh resources, I used the case structure as a simple way to decimate the data. Oddly, in the test vi the charts appear to miss data. In my app they don't stutter or miss data, but they do use an excessive amount of cpu time even though they are only getting about 15 pts/sec. I have also seen situations where the chart control appears to buffer data points before displaying it. When that happens I can stimulate the signals on my desk and there's a 1-2 sec delay before it is displayed on the chart. So... any insights into waveform charts y'all would like to share? WaveformStressTest.vi
  3. A couple weeks ago I was getting ready to release a preview of the LapDog List Collection when I thought, I really ought to have some unit tests for this and make them available to end users. So I reinstalled JKI's VI Tester (the best free unit test framework available for LV) and started playing around with it again. VI Tester is based on xUnit so anyone who is familiar with that family of test frameworks can likely help me out. I'm struggling a bit with figuring out the best way to organize the testing I want to do. The stuff I've read online about xUnit testing implies that each class being tested should have a single TestCase class for it. True? I'm finding I need different Setup methods (requiring different test cases) to test different aspects of my code. I'm also wondering if each TestCase should give valid results if executed directly? Several of my test cases require some sort of configuring before executing them. I do this in the TestSuite code, but it means the TestCase returns "incorrect" results if I run it independently. I've included the project source and unit test code if anyone wants to take a look. Unfortunately it's dependent on an error handling library that I don't have access to right now, so you won't be able to execute the code. I'll try to fix that in the next couple days. [Edit 03 Dec 10 - Added the missing library to the project.] LapDog List Collection source.zip
  4. I've explored using user events for various things and eventually came to the same conclusion. Setting up user events is kind of a pain, so mostly I just use them to send messages to my fp event handling loop. Has there been any discussion of revisiting user events and making them easier to work with?
  5. Depends on your role in the house-building process. If I'm the carpenter I'll focus on how to use a table saw thank you very much. The architect isn't in much danger of cutting off his thumb because he was careless while sharpening his pencil. (Actually I agree with your statement--the language used to write an application is far less important than your average c++ developer would lead you to believe, and most software design principles are largely language agnostic. I just had an uncontrollable urge to poke my finger through the hole in your metaphor. ) -------------- To answer the OP, if we couldn't use LV anymore I'd probably switch over to C#.
  6. While I was poking around to post this idea on the idea exchange, I discovered something unusual. It's possible to unbundle data from a class wire using the Get Waveform Components prim and with the IPE waveform node. (Note this does NOT allow users access to private class data. It still has to be used in class methods.) Is there a practical difference between the unbundle cluster and unbundle waveform nodes? I dunno--haven't played with it that much. The circle icon on the waveform nodes is a little rough, so I suspect it's just early prototyping code that was accidentally left in place. I kind of understand how it could have happened. Class data and waveforms are both clusters, so in one sense it makes sense that either prim can unbundle them. Still, regular clusters can't be connected to the waveform prims, leading me to believe this is unexpected behavior. (Edit: Cross-posted to the dark side.)
  7. Whaddya mean? That's 100% gar-un-teed authentic. Still trying to cover for NI, huh? We're SO on to you now...
  8. Ugh... you have no idea how much grief that hideous, cross-dressing, wanna-be rock star freak caused me during high school in the 80's. Uh huh... denial is the surest way to confirm my suspicions. (I think I vaguely recall a 'Darren' or 'Derek' Snyder from NI's forums.) You'll never guess what I found... Sorry man, looks like you've caught their eye too.
  9. Thanks everyone. At least I can be fairly confident it's not something in my environment. Mike, case E didn't repro for you even after opening the Blank (Obj) icon in the icon editor? That's odd... it repros reliably for me.
  10. I posted a bug on NI's forums that caused me all sorts of headaches while trying to track down a performance issue I was seeing recently. Normally NI is pretty responsive to these kinds of threads, especially when repro code is posted too. I'm left wondering if maybe the problem isn't reproducing for them. If anyone has a few minutes to spare I'd appreciate it if you download the project from NI's site and see if the repros for you. Repro instructions are included on the block diagram. It should only take a few minutes.
  11. I thought my recent appearance on Google was humorous, but this afternoon I was reading through the "What's new in TestStand 2010" document and found this. Yeah, that user name is me. Coincidence or evidence? You tell me...
  12. By 'multiple inheritance' I assume you mean multiplel levels of inheritance? If you're going to be downtyping through multiple levels of inheritance I'd take a hard look at your class relationships. Inheritance may not be the best way to accomplish what you're trying to do. In fact, since you have to create the signal object before knowing what kind of signal it is, I'd definitely look for an aggregation relationship instead of an inheritance relationship. Perhaps you could add a SignalProperties class as a member of the Signal class that contains the 20 attributes you referred to. Then when you know your signal is a diagnostic signal, you create a new DiagnosticSignal object and insert the SignalProperties class. As Mark said, typedefs are one way to address this, though I probably wouldn't use one. (Personal preference.) Each class is responsible for implementing it's own CopyData method to transfer data between different instances. If you're concerned that future developers might change the class data and forget to update the CopyData method, drop a comment on the class .ctl reminding them to update CopyData. Do you mean "all data from an ancestor" or "all data from all ancestors?" For the former, Mark's typedef suggestion, paying attention to changes, and unit testing can all help prevent errors. For the latter case, a string of CopyData methods from each of the ancestors clearly shows your intent and should be easy to verify by examination. (But like I said above, I'd look for a better way to accomplish your goal than forced downtyping. You code will be clearer and easier to maintain in the long run.) Mark, Why do you use the PRC prim in your copy method? The data copy from the source to the destination has already taken place, so by raising an error if the cast fails all you're doing is putting restrictions on how the copy method can be used. For example, the PRC prevents the user from copying parent data from a SubSubClass object to a SubClass object, or copying parent data between sibling classes. Did you intentionally implement that restriction, or is it to help make sure users are wiring the sub vi correctly? (Discovering the new use cases prompted me to relabel the terminals on my copy method to 'Source' and 'Destination' rather than 'Parent' and 'Child.') DowncastingObjects2.zip
  13. Or you could just disable auto-populating folders and not include the .svn folder in the project. (It must just be me, but AP folders drive me nuts.)
  14. Ugh... installers. A completely new technology I'm not particularly interested in learning. Too bad I don't have an installation team I can push that task on to. I haven't used either of these enough to vouch for them, but the two I've been looking at are InstallAware and WiX.
  15. No can do. Once you create a Signal object it will forever be a Signal object. You can't downcast a parent object into a child object--it opens the door to too many problems. (Here's a post from AQ with some more details.) I can't say this is the best procedure, but it's how I've solved the problem in the past. Create a child class with the attributes you want. The parent data in the child class will all be set to the default values. Then copy the parent data from the existing parent object into the new child object's parent data. I've attached an example using 2010. DowncastingObjects.zip
  16. Wow... I go offline for a couple weeks and y'all put me on Google to bring me back. I'm touched. **sniff** Thanks. I kinda figured I was best known as "that guy who highjacks QSM threads."
  17. I haven't had any trouble with 2010 built executables. Of course, my sample size is pretty small (half a dozen or so) and none of them have been in continuous use for extended periods of time, so don't put too much weight on my experience.
  18. I use several conditional disable symbols in my project. I'd like to create a build script for each spec that sets the symbols to a value appropriate for that build. Is there a way to retrieve the symbol names and values using scripting or vi server? This is as far as I got when I realized I have no idea how to proceed...
  19. For kicks and grins I think someday I'll create a real class that uses a white question mark as an icon... .
  20. The DVR is convenient, but the same thing can be accomplished with a SEQ. If you're LVOOPing then that's enough reason to upgrade from 8.5. Later versions seem to be more stable when classes are used. (Though in general 2010 seems to take a small step backwards.) Yes, if you branch the meter class wire it will create copies of the meter object at runtime. That may or may not matter--it depends on how you've built and how you're using your class. If your meter class doesn't contain any mutable state information (stuff that will change after it has been set initially) then it's no problem. All the copies contain the same information and will talk to the same device. Are you trying to create reusable code or is this all application-specific code? If it's app code, don't bother with the abstraction layer until you need it. If you're expecting to reuse this code later, take a step back and figure out what each object should be responsible for. For example (and these comments apply only if you want PowerSensor and PowerMeter to be reusable and extendable,) I see your PowerSensor class has a PortNumber field. From what I can tell ports are a property of the meter, not the sensor. The PowerSensor class is a convenient place to put the port number considering your current needs, but it's unwanted baggage in a reuse module. What if you use a different device that doesn't have port numbers? Maybe it uses strings or references to refer to each port. Port number has no meaning to a power sensor. Don't burden your reuse classes with things they don't care about. I also see you've hardcoded the PowerMeter class into the PowerSensor class. If reusability and extendability is your goal, then yes, I'd definitely put an abstraction layer in there. What happens if your manager decides he wants to communicate with a PowerSensor directly instead of through another device. Or maybe you get a new kind of device that accepts a PowerSensor. Are you going to add a new class to the PowerSensor private data for every device that the sensor can be plugged in to? And how are you going to decide which of those classes is the one you need to call in the ReadPower method you're showing? The power sensor isn't dependent on the power meter to function; don't make the PowerSensor class dependent on the PowerMeter class to function. As long as you haven't branched the PowerMeter class wire anywhere, you'll have only one PowerMeter object. (I have to admit that using a DVR seems largely unnecessary. I don't see what using a PowerMeter reference is gaining you here.)
  21. Good question. Short answer: If you can't directly drop a PowerMeter object in the PowerSensor class, you probably already have a PowerSensor object in the PowerMeter class. LV can't allow circular dependencies like that. To solve your immediate problem drop a LVObject into the PowerSensor class and name it PowerMeter. In your getter downcast it to a PowerMeter object before returning it. Long answer: There are lots of ways to skin this cat. Since you're a little uncertain of which direction to go, I'd favor option 3. Keeping the two classes independent makes them more flexible and easier to maintain. I'm making a lot of assumptions about how the power meter and power sensor work, but I don't know anything about them. In particular, I'm assuming the power meter is a chassis that accepts plug in modules somewhat like a CRIO or CDAQ. First step is to write your PowerMeter and PowerSensor classes thinking about that device only. What can the power meter do regardless of what module is plugged into it? What can the power sensor do regardless of what device it is plugged in to? Don't write any methods in one class that references or uses methods from the other class. That removes your ability to reuse them independently in other apps. For example, at a minimum the power meter would include things like an address/handle for reading and writing to it. It might also contain an array of LVObjects for keeping track of module objects that are plugged into it as well as methods for storing and retrieving those objects. (If all modules that can be plugged into the device have a number of common functions you can create an abstract PowerMeterModule class with overridable methods, but it's not needed at the moment.) The PowerSensor class could have methods like Get PowerReading, Set Scale, etc. It shouldn't have a PortNumber field since the module doesn't know or care what port it is plugged into in the host device. BUT, it does need a host device if you want to communicate with it. So create an abstract Host class that will store the information needed to communicate with host device. It's hard to say what public overridable methods the Host class should have without knowing more about the specific host devices. The most flexible way to go about it is probably to have a SendCommand or similar method. Require child classes to override SendCommand. Use the SendCommand as a generic way to issue commands in your PowerSensor methods. To keep your code tidy, drop PowerMeter.lvclass (and PowerMeterModule.lvclass if you've created one) into PowerMeter.lvlib and drop PowerSensor.lvclass and Host.lvclass into PowerSensor.lvlib. These become part of your reuse library. Once you have two independent classes, the question is how do you get them to work together in your application? Well, do you want your application-level code to talk to the power meter or the power sensor? Either way will work. It depends on your goals. You indicated you want your app to refer to the power sensors, not the power meters, so with that in mind... In your application, create a subclass from PowerSensor:Host. I'll call it HostPowerMeter. Drop a PowerMeter object in HostPowerMeter's private data and create accessors for it. Override the SendCommand method. On the bd use the PowerMeter object's methods to communicate with the power meter. One important thing to note is that you need to set up a PowerMeter object in your application before adding it to the HostPowerMeter object. There are more details than what I've described, but this is the route I'd take. Not necessarily. The PowerSensor object doesn't need to know the details of what it's connected to. It just needs to be able to communicate with the actual power sensor device. I think it would be possible to abstract a Connection object instead of a Host object. The above design uses inheritance and the Host class to avoid direct bi-directional associations, though you could argue they are still present. (Since PowerSensor contains a HostPowerMeter object, which in turn contains a PowerMeter object.) Ahhh.... I need to release my LapDog Collections... Except then the PowerMeter class is dependent on the PowerSensor class. You have to drag the PowerSensor code around every time you want to use the PowerMeter class. (Maybe a power meter without a power sensor is meaningless, in which case that would be okay. Otherwise I try to break up dependencies in potential reuse code.) And BTW, I thought you didn't like OOP...
  22. You haven't included enough information for anyone to give you a specific suggestion. There is no single "best" way to communicate between apps; it all depends on your requirements and restrictions. Here are a couple options; there are others as well. Tightly coupled solution: To notify the C# app of events in the LV appAdd code to your .Net app exposing public methods telling the app something happened in the LV app. In your LV app use the .Net constructor node to get a reference to your .Net app. When events of interest occur in the LV app call the appropriate methods in the .Net app. [*]To notify the LV app of events in the C# app Use callbacks in your LV code. (I haven't done this so I can't comment on how to change your C# code to allow it.) This solution makes your LV source code dependent on the C# executable. In other words, you'll have to have the C# app installed on your dev computer and on any computer that executes the LV app. Loosely coupled solution: Add a TCP component to your LV app. When something interesting happens in the LV app, broadcast a message on the TCP port. At the same time, constantly listen on the TCP port for messages broadcast by other apps. When a message is received, react accordingly. Repeat steps 1-3 for the C# app. This solution removes the dependencies between the two applications. Neither app "knows" about the other one. They only know they are supposed to broadcast messages when stuff happens and do other stuff when messages are received.
  23. The round to inf prim would be a good candidate. We can call it the 'Balla' in honor of Mark's willingness to go to infinity while helping another user. For my part I gave up on that thread long ago...
  24. Daklu

    dB Qs

    It's been over 10 years since I've done anything with databases and back then we were programming in VB6. At the time one advantage MSAccess had over other solutions was that it had a pretty easy ui that allowed users to query data. Do the other solutions offered have good data viewers available?
  25. This is completely irrelevant to your question, but I like the icon for your dialog box.
×
×
  • Create New...

Important Information

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