Jump to content

Mads

Members
  • Posts

    437
  • Joined

  • Last visited

  • Days Won

    27

Everything posted by Mads

  1. I did not include the scope in the test. To use the variant attribute to get the sort and search we need a string key, not a cluster. This should be easy enough to fix though, either we could add the scope number to the name, or by flattening the cluster. I have not tested that yet though. Now all you need is a script that updates all the polymorph VIs :-) There is no hit on the constant name lookup as a check for that precedes the search in the list of refnums.
  2. As before in 1.1 when the linear search was used to find the register refnum. The linear search is just a bit slower in absolute terms, but with 10000 registers this slowness has extra impact due to the combination of having a large list to search, and having to do it so many times... In the test I changed the register name on every call so it is a worst case scenario. The very first run takes a bit longer than the quoted times because of the array build though (that part could perhaps be sped up as well by expanding the list in chuncks instead of on every call, but that's a minor issue).
  3. Yes, the way polymorph VIs work in LabVIEW I can definitely understand why you do not want to update the VIRegister library again. In most cases the current implementation will be just fine. Thanks again for the work. I did run a quick test to see what kind of performance I could get if needed though. To simplify the change I skipped the scope part and just used the register name as the reference. Updating 10 000 booleans with the same node used to take 1,5 seconds, now it runs in 39 ms.
  4. Thanks for the update . One first comment: Calling the same node with varying register names works now, but it is very slow. If you use a variant to store and look up the index of requested queue (instead of using the standard search function) the use of the cache will be much quicker.
  5. You do not need to open the block diagram, just run the Lock.State method on the VI. You can run the Get method first if you want and if it is locked you can run the set method with unlock as the new state and provide the password you have... If the password is wrong you will get an error, if it is correct you can lock it again if you want and go to the next VI.
  6. Describing architectures can be quite a task. I'm sure the designers behind the CVT e.g. could mention some intended use cases for you, but OK. Let me first give you an overview, and perhaps I can describe something more concrete later if necessary: I typically make different types of monitoring systems that consists of a server that runs 24/7 on an oil rig somewhere and interfaces with the local control system - and remote clients that connect to that server to monitor the situation or do analysis and reports. The server (on a PC or PAC) is configured to poll data from a number of sensors through different types of communication interfaces, it does a number of calculations on the data (new calculations can be added during run-time), logs the trends and system alarms/events - and offers remote configuration, current values, and historic trends to a client counterpart - or via web pages through a web service. A bit like a SCADA/DCS, but more specialised. Most of the applications came in their first version in the late 90's. Back then a main part of the server was its modbus interface to the main control system. All inputs and outputs of the system would have a place in the modbus registers that were read or written to by one or multiple control systems. The existence of such a central and globally addressable memory space made it easy to use it to share data not just with external units, but internally as well. However this would mean that everyone needed to know the modbus address of the data they needed - or be able to use a middle-man that would know that address if given a name e.g...Using modbus registers for something like this is not exactly ideal as there are data type restrictions, scaling is involved etc. but these are obstacles we could live with. I've since then moved away from using the modbus register this way as I do not want to couple things like that, but the idea of having a centrally accessible register of data lives on... If a new calculation or device is coming online it typically needs access to data which may come from any part of the system. If all parts of the system had an interface on its own which allowed others to poll data from it when needed (and ideally this would be a generic interface so that it would be supported by all others), then that might be a way to go, but they do not (some could be redesigned, but it is not very practical to impose such a requirement on all components) - and even so the consumer should not need to know anything about who produced the measurement, just the tag (and data type) of the measurement. The only thing that can really be made sure is that the current data will be available in memory in a "database", and historic values will be available from disk in a log-file/database. So let's say e.g. that the customers asks us to use data from sensor x, two values coming in via OPC, a value from the modbus link to system Y...and produce a calculated value from those variables that is accessible by all other parts of the system. We do this by providing a middle-man which can take in a list of tags and outputs the data we need, and the calculator writes back the results to the same middle-man by providing a tag and the value. This way the calculator (or other consumer/producer) only needs to be configured with a set of tags and a formula. If only current values are required (most of the time this is the case), the middle-man is an equivalent to the Current-Value-Table, which is what I'm proposing that NI develops to be as efficient as it can be because implementing it with the tools we have available now results in a number of performance issues (as discussed here related to the VIRegister and on the CVT site). I've also described this as a type of global that you can create when needed and access by name, but that description might confuse some.
  7. I think Steen sums it all up pretty nicely. My own two cents: If you cannot lookup globals programmatically by their name (basically a simple internal database) then the only value added by such a library seems to be that you can add some flow control to the global (error terminals e.g.) and can hard-code things part textually by typing the name instead of using your mouse. The latter two are both nice features which should be part of the standard globals in LV, but they do not address the need for scalability.
  8. I see it was only added as a feature request so I guess that's why it has not been included: http://forums.openg.org/index.php?showtopic=1117 Version 4 does not include the manual solution with a format specifier input on the read section or ini cluster either. However that would not be a good solution because then you would need to open the file and check what decimal sign is used in it prior to running the read * cluster function.
  9. When I saw this release and the statement that all reported bugs had been fixed (including one described as a fix for custom decimal signs) I thought that the bug that prevents it from correctly interpreting floating point arrays in configuration files created on another machine with a different decimal sign had been solved as well, but that problem is still there, right? I had hoped to be able to ditch my custom version of Read Key (Variant) that automatically detects what the decimal sign is in the file and adjusts the format specifier accordingly
  10. One thing I noticed is that you cannot use one write node to write to multiple registers without risking that the previous registers are lost. As long as no read is opened on the given register the write is the only place the queue ref is open, therefore the queue is destroyed when the write node runs a release when it switches to another register. The release node does not have the force flag set, but the queue is still destroyed because no other reference to the queue exists (necessarily). If this is the case then I think it would be more useful if you the destruction had to be done explicitly. The test scenario that made me see this behaviour (which I did not expect, but perhaps it is intentional?) was that I planned to do a double write to 10 000 registers and then a double read of the same registers, and time the 4 operations. The reads turned out not to return an error, but they would return all but one register with default values (i.e. a DBL would return with the value 0 instead of the value I had previously written to it). Now I only ran through this quickly so I may have overlooked something and gotten it all wrong...However perhaps you can correct me before I come to that conclusion myself :-)
  11. This looks like a smart take on of what NI has posted as a "Current-Value-Table Reference Library". They have used functional globals to store the data instead of queues which makes it easy to access the list of available registers, debug etc. One of the weakest points of their implementation is the slow search it uses to look up the "Register Name" (they could use a binary search instead or use the search capability of variant attributes to dramatically improve this, but your approach gets that part for free from the queue functions). Perhaps the two efforts could be joined? PS. The polymorphic VIs do not have the "Allow Polymorhpic VI to Adapt to Data Type"-flag set so they did not work as I expected in my LV2010.
  12. No, I'm not thinking about the System Replication software. In our case the PAC will be typically be a few thousand meters subsea so it is definitely risky. The startup executable needs to be a bootstrapper which will unload and load the main code dynamically. That way we can ensure that we get another chance if the new software fails...
  13. Your window manager could monitor key events, and regularly check the FP.Open status of all VIs in memory. The default state of the window manager would be to poll the positions of the open front panels (and only those), keep a log of their correct position and move the windows back if the position has changed but has now settled* (and they are still open). (Ideally there would be a window move event for this that you could set an event structure to respond to, but there is not...). If the user hits F2 the state is changed to an ignore mode until F2 is pressed again - in which case the monitoring state will automatically correct the positions back to their original values again... On start and every 1-5 seconds from then on the window manager will run through the list of VIs in memory and update the list of VIs it should monitor. I did a quick test now with 750 VIs in memory and checking their FP.OPen property only took about 40 ms on my machine so it should be doable (the CPU load was not bad either). It is not required that you know which window is currently active. * You could reset the position immediately when a change was detected but that would probably look extra messy so I would rather wait another cycle to ensure that the window has settled, before resetting it...
  14. I need to make the same thing for PACs and the PAC only runs one application so it will have to replace itself (because no network interface will be available - the new app will be transfered on a serial link). I thought I had seen a framework for this somewhere on ni.com earlier, but I cannot find it now. On the PAC it should be rather simple though. All this functionality has to do is to pick up the new file(s) once it shows up (or it is asked to), move them to their proper location (replacing the old executable etc.) - and then do a soft restart of the device (it does get a bit more complicated if such a restart is not permissible though; then the main app will have to be a dynamic launcher that graciously jumps from the old to the new code without interruption). The part that transfers the file is a separate issue.
  15. Kudos just added to that idea. Thanks Ton.
  16. How are you supposed to add an xcontrol to your user.lib / LabVIEW IDE? If you just copy the xctl file and its support files into user.lib the user.lib palette will get populated with the support VIs, but not the control? Should it not be possible to add an xcontrol to your library of controls just as easily as adding a standard control? In my mind the xctl file should contain everything and should show up as a control on your palette when dropped into the lib folder, but is there any such functionality today? PS. There are many x-controls that could have been part of OpenG e.g. (like the IP address string control, the intellisense string control (I think I picked that one up here once, but it is gone now)...but perhaps its due to a lack of support that they have not become that commonplace in toolkits etc.?
  17. As others already say here your app needs admin access. I normally add the file association from the installer instead as it will always have the necessary access anyway.
  18. Because if we did not then surely nothing would happen? The two options you mention are nicely formulated. In the long run I hope NI will implement the first one, but the second one would be fine too. As part of the first option you mentioned a third one, that's my straw of hope here: Perhaps there is an option where another type of method is developed, one that would have limitations in other respects, but which would solve this particular problem preliminarily (until a more fundamental rewrite has become inevitable, one that also allows for an optimal solution to this issue).
  19. As LabVIEW programmers we are all fairly used to find ways to get around limitations in the development environment and G as a language, however at times those limitations and bugs are just so fundamental that it gets depressing. The graph axis bug that was introduced in LabVIEW 2009 was one such case: if you wanted to use graphs and upgrade to LV2009 you had to rewrite all your code so the scale markers would show up correcly, or wait for months to get the first revised version of LabVIEW (because even fundamental errors like that are not patched instantly....). The good thing about that example though was the fact that you could actually make a fix yourself. Well, now I'm depressed again, and this time the problem is much worse. There are ways to come around this one too, but man - it should not be necessary. I'm a bit surprised it has not been commented before, because it is not really anything new - but once you run into its consequences it is extremely frustrating... The problem: The run method (and related methods like set control value e.g.) runs in the user interface thread - and that thread is blocked if e.g. the user opens a contextual menu somewhere in your application . The consequences: In short, LabVIEW is unable to reliably start an asynchronous background process on demand. - You can try to dynamically scale your software by instatiating a VI and run it with the run method (with Wait until done set to false), but if you need it to always happen within a reasonable time your application cannot have a user interface. It can not, because if it does then the run method might be stuck indefinetly if the user happens to e.g. open a contextual menu... So when does this actually become a problem? Well, in my case its most painful impact is that all client-server interfaces I have in my applications are unreliable because they, in order to allow an undefined number of simultaneous clients, create session handlers dynamically. A client might do a transaction that takes a lot of time, and with multiple simultaneous clients even quick transactions would add up so handling the client transactions in sequence is not possible. Hence the use of dynamically created parallell running session handlers. This works fine, but if the local user of the server should happen to open a contextual menu my server(s) effectively become unavailable to any new connections. One minute my servers are there...the next they are practically off-line to all new clients because the local user happened to open a menu...and if we're really unlucky he might leave the PC in that condition and never return! An unacceptable situation, plain and simple. So how do we get around this? Well, either we stop making software that both has to scale to outside requests, and have a user interface...or we predefine a maximum number of parallell processes and instatiate them in an idle condition at startup. Neither one of these make me proud or happy. PS. When I first noticed this I posted two ideas to the idea exchange (here and here). They do not have any illustrations that catch people's attention, and as it turns out neither of them are very precise, so perhaps a new one should be formulated and illustrated - but it's kind of depressing too that so few people realise their impact.
  20. I understand. The optimal solution if you need the functionality that you descibe is probably to split the splash into an optional GUI (the visible splash screen) - and a loader. The latter is the top-level VI of the app, and it will hide itself and do the necessary prechecks etc. in the background. The loader will only launch the visible splash screen if this is enabled. The "GUI" of the splash screen then also becomes a VI you can use as an About Box e.g. :-) Mads
  21. A small tip about splash screens: Having the splash screen launch the main program is not always ideal as it prevents you from disabling the splash screen if needed (we have to do this for customers who run our apps on terminal servers e.g. - to save bandwidth (or at least many prefer it that way). A more flexible solution is to launch the splash screen from the main instead - but hide the main until the splash screen has closed. To do this optimally LabVIEW should offer us the possibility to set the run-time state of VI windows to "Hidden"...but that's not available so the next best thing is to set it to minimized...and then hide it immediately by running the necessary method (hardly noticable...unlike if you had shown the window in normal size and then hidden it). This way the main program can check if it is supposed to show a splash screen or not - and if it is - it will hide itself and then launch the splash VI....if it is not - it will just normalize or maximize itself and continue. Mads
  22. Yes, but it is not the most elegant way to do it as it may produce a flickering window on the screen - and it will force everything to stop at the instant it is run. A tidier way to do it is to make sure all internal processes are terminated properly and then close every window the application has opened. When the last window is closed the application (and its use of the RTE) will stop. Mads
  23. Do anyone know where the 2010 mobile module has gone? I saw some talk about discontinuing it...but has that happened, or is it just not ready yet?
  24. If you set the installer to run the batch files they will run with the same access level as the installer, at least that's what my experience is so far. We use batch files to install our app as a service. If run on their own they have to be run by the Administrator...but that is no issue when they are run by the installer.
  25. If you are working on Windows (and probably on other OSes as well) you should store the files in a system folder - and use the Get System Directory VI to get the path to it in both applications. Storing files together with applications that are installed in the Program Folder is not permitted on Vista and Windows 7 (no write access, this was true for earlier OSes as well, but back then everyone had the bad habit of being an admin...). The choice of system folder is not straighforward though...you could use the user's document folder or application data (hidden) - but then the location will vary with the user...or you can use the common ProgramData folder...but then only the server will get write access, the clients will only have read access unless you use a tool to edit the access rights. The latter would not be a problem if the server was in fact serving the data to your clients via a data link (TCP/IP e.g.)...and that would be more flexible than to require access for the clients to the local files, but I assume that's out of the scope. Here is a related discussion about where to store files on Windows. MTO
×
×
  • Create New...

Important Information

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