Jump to content

Jeffrey Habets

  • Posts

  • Joined

  • Last visited

  • Days Won


Everything posted by Jeffrey Habets

  1. I'll try and add my :2cents: to show the concept of how I handle error logging and visualisation in my applications. I basically have the whole error/message logging encapsulated in a by-ref class. This class: handles logging of the errors/messages to disk rotates logs every N days has an active thread of which optionally the UI can be shown as a (floating) window to see the realtime log publishes log events to interested subscribers through dynamic events Each parallel loop (including dynamically spawned processes in active objects etc.) takes a reference to the logger object. To make sure all errors are catched all executions chains should end with the AddError method. In the example here, on error, the default logwindow would be shown (which shows all messages since application start). Whether or not you want that depends on the type of application and where you are in the development cycle. I usually use the catched event to determine what error occured and decide what to do with it (e.g. ignore it, show in a nice UI, quit app, etc.)
  2. QUOTE (neBulus @ Mar 21 2009, 02:37 PM) Your welcome. I actually just finished it for a presentation I have coming up and thought it would well fit in. Pictures say so much more that words imho. QUOTE (Michael Aivaliotis @ Mar 22 2009, 05:15 PM) Jeffrey, I also do this however I use dynamic events or queues to stop the process. Never abort. Where I talked about message and response notifiers, I of couse meant the dynamic events or queues. (Although it could be done using object attributes..) And if you really want to make sure that the thread is finished before you take other actions in your destroy method, let the thread send you some kind of notifier when it's finished. QUOTE (Michael Aivaliotis @ Mar 22 2009, 05:15 PM) I don't like imposing rules on things like this because even though you can have general guidelines and best practices, it really depends on the specific application at hand, the corporate style guidelines and (at the end of the day), the comfort level of the programmer. So I'm not saying you should never use abort, but it needs to be designed-in and all editors of the code must understand the caveats of this method. I coudn't agree with you more.. In the case of active objects the handling of the active process is fully encapsulated, so the users of the objects don't have to bother knowing what's going on inside. However, for developers that work on the object's internals it's important to know what's going on, so good documenting of the destroy method is a must here. When I use the abort method, it's mostly on AO's with a thread that does nothing more than just one thing (e.g. continuously gathering data and pushing it on to a queue or listening on a communication channel and passing the events on to a higher level). If I have no need to send commands to the thread and it's a safe loop to just abort it, I will.. By design..
  3. QUOTE (Aristos Queue @ Mar 21 2009, 06:13 AM) This is actually what I do in most all of my code.. All my parallel processes are implemented as active objects. The object takes care of allocating all necessary stuff before spawning the process and cleans up afterwards. Depending on the nature of the task of the process, I'll simply use an "Abort VI" to stop the process or a message with response notifier. For me, the usage for one over the other is about 50/50 I guess. In the class depicted below for example I use the latter because the process needs to write some last data records to a file, but still all refs are cleaned up in the Destroy method, not in the process. http://lavag.org/old_files/monthly_03_2009/post-906-1237631134.png' target="_blank">
  4. QUOTE (Yair @ Mar 18 2009, 07:28 PM) Yes, I did try it on the same file.. And I also was under the assumption that the binary primitives did basicaly something like reading the file and then unflattening. But reading AQ's response I realize that it isn't that simple in all cases. When I read the file as a string and offer that string to the unflatten primitive, LV already has a lot more information (namely type and size) then when it should read the information straight from the file. So in this case LV knows how much memory to alocate. Looking at the nature of a flattened class (and give the fact that my class data is not of variable size (e.g. no arrays or strings in it)), and seeing that the first 4 bytes determine the number of inheritance hierarchies my guess is that this is where LabVIEW chokes on. This number should be 1, since my class has no ancestors, but in my particular test case where I try to read a text file as binary, this number was very high so LabVIEW probably tried allocating memory for a couple of million class data clusters and this obviously results in an out of memory error.
  5. QUOTE (Aristos Queue @ Mar 17 2009, 08:38 PM) Thanks for your input.. After reading this and the LVClass Data Storage Format wiki article I see that this problem can occur. Untill I read the wiki article I was under the impression that classes saved more information about itself when flattened. QUOTE (Aristos Queue @ Mar 17 2009, 08:38 PM) The trick is to save your data files with a unique file extension and then restrict your users to only picking files with that extension. Ofcourse, I use that always as an extra check. But I'm not a fan of just plain extension-checking because it's pretty easy to change extensions and there are likely to be other file formats with the same extensions out there. I actually ran in to this finding accidently while migrating a program's storage format from readable text to binary, while needing to keep the extension the same for both.
  6. QUOTE (Yair @ Mar 17 2009, 06:58 PM) The unflatten node doesn't give the out of memory error, instead it returns an error (1527, Attempted to read flattened data of a LabVIEW class that is not currently loaded into LabVIEW.) which seems the correct behaviour I also would expect from the read binary primitive. (Since the(un)flatten thing is probably more or less what the binary read/write primitives do under the hood anyway.) I can actually read the class data written using the binary write by reading it as text and unflattening the string. So there's my workaround for now. Thank you guys for your thoughts, I'll file a bug report on this issue.
  7. QUOTE (neBulus @ Mar 17 2009, 04:19 PM) True, and for 'normal' (non class) data I would add a header containing file type and versioning information and read that first before attempting to further process the file. I'm using classes here to make life easier and let them do the versioning. I'd expect LV to be smarter when loading the data, because it has all information it needs in the class datatype. As a matter of fact, I just tried the same with a cluster wired to the Read binary primitive and there I get a more expected result when opening a file with other (than the cluster format) data: LV returned error 116, Unflatten or byte stream read operation failed due to corrupt, unexpected, or truncated data. It should throw the same error with classes.
  8. Hi, I have a case where I use the power of LV-Classes and their automatic version mutation capabilities for storing data to a flat binary format by just wiring the class wire to the "Read to binary file" primitive. Writing/reading class-data of different class version works like it should. However when for some reason the user would select a non-class file (e.g. some text file), I would simply expect the "Read from binary file" to return some error I could act upon. Instead, LV throws a "Not enough memory to complete this operation" dialog at me, then when I click Ok on the dialog, after a really long (10's of seconds) timeout I get error 4, End of file encountered out of the "Read from binary file" primitive. I'd qualify this as buggy behaviour. What are your thoughts?
  9. Case: given an XControl that has some custom property. If we write to the property, the facade will be called with the Display State Change event. The XControl determines from the property write that the XControl's data needs to be changed, so it does. (Illustrated in the example by applying the random value to Data Out.) Now when the VI using the XControl uses a property node where the first property written is a custom property (which as a side-effect induces the value change as described) and the second property is the Value which we write a value to (5 in the example), then when we read the Value-property again after that we would expect to see the value we wrote before (5). Instead we get the value that was induced during writing of the first property (Range in this case). If we change the example code (see disabled case) to first write the custom property and then write the value property using a separate property-node everything works as expected. Download File:post-906-1236990414.swf Download File:post-906-1236987840.zip
  10. For what you seem to be doing here (do the same action with just a slight difference depending on what item is selected) I think buttons are the wrong controls to use for your use-case. Typically I would use a (multi-column) listbox (if you also want to categorize, use a tree-control) and fill it with the data from your Excel sheet. Then, the only event you need to catch is the double-click in the list and read the values from the clicked row.
  11. You certainly won't be able to get the 20kHz deterministically since the devices you mention are all programmed I/O. I don't know about the capabilities of the counter/timer on those devices. (I do know that with the counters on an M-Series device it's pretty easy to generate the digital pulse signal you need.) As Yair said, I would give NI a ring, they should know.
  12. The problem will be resolved in a next LabVIEW release.. NI Offered me two possible workarounds of which I used the second one and this works for me: Set resource\Framework\Providers\lvrio\crio.llb\_nicrio_getModuleXML.vi and _nicrio_getModuleXMLForRSI.vi to non-reentrant. Since these are password-protected VI's that's not really an option for normal users. Configure the Open FPGA Reference node to use the bitfile instead of the FPGA VI.
  13. QUOTE (LV_FPGA_SE @ Jan 6 2009, 01:08 AM) Thanks for testing this. I tried your project, and it loads fine here.. No problem. So it seems my problem is probably not (only) class-related. Maybe it has also to do with the kind of FPGA-target configuration, I don't know. I've attached the stripped-down project that reproduces the problem. This is also the project send to the NI AE and now under investigation as CAR#: 139277. Note that my classes are GOOP3 (Endevo) which is basically a LV native class with some extra. The problem isn't in the GOOP3 framework for sure, since I can also reproduce it with a LV native class in this same project. The project as attached will open without a problem because the FPGA interface nodes are commented out. To reproduce the problem, open FPGA0_DAQ.lvclass:FPGA0_DAQ_Create.vi (under Hardware) and enable the stuff that is now disabled. Save the VI and project, then close and re-open the project. Download File:post-906-1231252734.zip
  14. I would like to encapsulate my FPGA access in a class, but it seems LV can't handle it. If I have one (or more) FPGA interface nodes in one of my methods, save and close the project and open it up again, LV crashes in exec.cpp line 1704. I reported the problem to NI and am waiting for their response, but in the meantime I'm curious if someone else has bumped into this problem. I'm using LV8.6.
  15. QUOTE (Val Brown @ Dec 18 2008, 06:58 AM) Not really.. You can actually edit all relevant class-code (the methods and attributes) without having the toolkit(s) installed (unless the programmer of the class locks the BD's). You can even add new methods without the toolkit (although it's of course a lot easier and faster if you have the toolkit).
  16. QUOTE (dblk22vball @ Nov 25 2008, 10:40 PM) In your Listbox Value Change you need to tell LV that your state and display data has changed (as you do when you handle the button clicks). To make it even simpler I would simply read the values of the listbox when the buttons are clicked. No reason to save the rows in your state and/or display date in this case.
  17. QUOTE (dblk22vball @ Nov 25 2008, 08:19 PM) You should use the listbox's Value instead of the Active Row property.. The latter one serves a different purpose (setting/getting row specific attributes, also see Ctrl-h when you hover over the property.) I also recommend you use the Value Change events (for both the listbox and booleans) to detect the value change. That's what it's for and I think it's the only way to know for sure you have the correct (updated) value at your disposal.
  18. I'm a bit short on time now and haven't really given any thought on your description and if it should work or not that way. But here's what I do in my code and this works like a charm.. Thread.vi is in my case a private method and thus not dynamic dispatch, but it in turn calls dynamic dispatch methods on the DAQ class which are overriden in the child classes. I think this should do the trick in your case also.
  19. QUOTE (Aristos Queue @ Oct 5 2008, 08:47 PM) It's a good thing that we have the custom probes.. And I have them on my own system, but often I'm debugging on a client's system and I'll have to do with the default probes. Imho, having the custom probes should not mean the generic probes don't have to evolve further with new versions of LV. Things like having the radix visible/setable and basic formatting should be available in the generic probes. The probe window doesn't have to be as big as in my example (I just used the conditional probe as an example), so screen real-estate isn't a problem here.
  20. I've submitted this to NI's product suggestion. Let floating point numeric probes by default display all digits of precision for that particular data type. In a recent project I've spend hours and hours looking for a bug of which it wasn't directly obvious to me that it was caused by the floating point lsb rounding errors because these are basically masked by the default setting of 6 significant digits. I think this is a good default for FP-controls, but not for probes which are used for debugging purposes. In my case it would have saved me tons of time. Now, I imagine it is not always wanted behavior to have full precision in a probe, so best thing would probably be to have a control on the probe FP to set the nr of digits of precision at runtime. I can create a custom probe for that, so my problem is solved, but it would be nice to have this available on the default probe. I imagine more people are caught by this 'problem'.
  21. Well, after a quick glance at the code, I see at least one race-conditions that could cause this.. The local variable state in the lower loop could be read before the value is actually initialized in the upper loop. Since the initial value of state will almost always be stop (except for when you first run the VI after opening it, it will have the default value then), this is probably your problem. So you will either have to initialize this state before you enter both loops, or better, use an occurence to stop the second loop. Here's an example:
  22. QUOTE (crelf @ Sep 8 2008, 04:00 AM) Yep, I now all of these 'tricks'.. But I still would like to see possible generated error codes with the function descriptions in the manual. In some cases I want to present a custom error message to the user (with explanations on what to do to resolve, etc.) instead of just presenting the sometimes (to the user) cryptic default explanations. Now I often just trial and error the different use-cases I want to catch and note the error that needs to be filtered. QUOTE (crelf @ Sep 8 2008, 04:00 AM) That looks like you really tore it out of a LabVIEW manual Yeah, I regret it already..
  23. The error are grouped in the LV help: I do agree that it would be a big help if possible generated error's would be mentioned with the VI/function help instead of a seperate place. Particularly for HW I/O functions.
  24. QUOTE (crelf @ Sep 1 2008, 05:56 PM) Amen to everything created by mister Mark Knopfler! I must say I normally just code with the radio on.. But if it's not the radio it's MK/DS or the Eagles.
  • Create New...

Important Information

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