Jump to content

AlexA

Members
  • Posts

    225
  • Joined

  • Last visited

  • Days Won

    2

Everything posted by AlexA

  1. Hi JMak, As dj mentioned above, learn to love the queue! I didn't really like the JKI template as it locked the UI and for me I didn't really intuitively grasp how to work with it to asynchronously launch plugins. There are many different variations of the producer-consumer, or master-slave architecture. At it's most basic, it's just two while loops communicating via queue. Good luck, I think you're taking the first big step into Labview programming.
  2. Hmm, had a little play and it appears the compiler is too smart for its own good. If you put the VIs in a constant wired case structure (opposing side), they will NOT be included.
  3. Yeah, I've already dropped a suggestion regarding having to deploy an RT project as a startup. Will drop another one regarding Dynamic VIs. The solution I've come up with in the mean time is to call each Dynamic VI once in a normal fashion (sub-vi directly placed on block diagram) and shut it down immediately as part of the host code start-up, this forces the VI to be deployed as a dependency which can subsequently be launched dynamically.
  4. Hmmmmmm, I've had a tiny break through with my problem. Thanks to you guys above but your answers didn't really help my problem. Mads, I think the answer might have been somewhere in your post but my brain did flips trying to follow your example. So, the problem was, when a Labview Real-Time VI is run in Development mode (i.e. just by pressing the arrow), any sub-VI's which are called dynamically (via a "Start Asynchronous Call") will NOT be deployed in the correct sense. The only way I could find to get Asynchronously Called VI's to launch in development mode was to manually deploy them. As in, go to the project window, right click them all and select deploy. This opens up their windows, and as long as the windows aren't closed, they will be recognised using the App.Dir property plus their name and subsequently launched correctly via the main VIs dynamic launch process. I'm really not sure why this is, but I think it's a bug in Labview not recognising the potential dependencies of Asynchronously Called VIs during deployment. Now, to see if there is a programmatic way to deploy these VIs so I can just hit Run in my windows host code.
  5. Hey Swenp, thanks for the advice, in my explorations I created a build that had the sub-vis included under the "always included" box, it didn't seem to help. if I include them in a build via the "always included" box, how should I path to them? Simply via the App.Dir plus name method? In which case, what was I missing previously?
  6. Hey guys, thanks heaps for your help! You've really seeded my mind with some new avenues to think along. For anyone interested, this is the poll N queues message handler I came up with. As I noted in my previous post and in the block diagram, this is not a very good method unless you don't care at all what order the sub VI's start in. Thanks again for the help, will update when I've solidified a method.
  7. AlexA

    MessageHandler

    From the album: Code Pics

  8. Hey guys, I've stumbled across a problem when trying to use the "Application path" constant along with the name of a sub-VI to obtain a reference for dynamic launching (using the asynchronous call and forget VI). Putting the Sub-VI in the application folder, or alternatively a special "Sub-VI" folder, then using "Application Path" constant plus the name of the Sub-VI to obtain a reference works fine on a windows PC. When deployed to real-time you get "Error 7", sub-VI not found. So I'm wondering, where exactly does a dynamically launched sub-VI go when it's deployed to real-time, and how do I build a path to it programmatically for the purposes of dynamic launching? Thanks in advance, Alex
  9. The thing is, if a single status queue is used for the master to action on statuses from the subVIs, that queue must be the same queue that is driving that master's state machine (else you have the problem of the master loop reading two queues anyway, one for statuses and one for commands). That feels wrong to me, I'm not sure why, but I feel like the purity of communication should be 2 way only, for sub modules to tie into a masters command queue to get their own statuses across feels dirty. I've actually come up with a message handler that "locks" like a queue with no time out wired, but manages to poll N different high-priority queues and one low priority queue (the masters command queue). I'll link a png of it when I get back to work tomorrow, but basically it polls N high-priority queues and if there is nothing in them polls a low priority queue, if there's nothing in that queue either, then the it reloops until a message is found on at least one queue. Considering the use case where the user asks to launch 3-4 modules in sequence, there is a danger (handled by setting sufficiently long time outs on the queue polls in the message handler) that somehow the module launcher control(master) queue will progress right through its requested launch sequence before any of the Sub VI's actually manage to fire up and return their statuses. As long as at least one Sub VI gets its statuses and handshaking requests into one of the N high-priority queue it's likely that all of them will. I can't really think of a more elegant way to handle sequences like that. So to be clear on how I have been passing sequences of commands that require a confirmation. The UI code will take an event and turn it into the correct sequence of Sub VI launches which are sent to a Sub VI handling loop, at the end of this sequence it loads the specific command "Done" which is a handshaking command, what that does is that when the Sub VI handling loop dequeues "Done", it loads its own "Done" command back onto a return queue which goes to the UI loop, which is waiting at a dequeue. Do you have any recommendations for handshaking logic if you use only a single status report queue? I couldn't figure out how to make the Sub VI handler wait for a hand shake from the subs after each one it tried to launch if there was already a sequence of launch requests in the master queue (hope I'm being clear). The best I came up with when working with a single return queue for all Subs as well as commands from the higher level stuff, was to allow requests from Sub-VI's to be enqueued at the opposite end, so as each Sub VI fired up it loaded its own requests on to the top of the queue. The problem with this, is that there's still a forseeable chain of events where a Sub-VI's start up routine takes so long that before it can load its request onto the queue, the queue finishes its sequence and returns command to the top level code. In fact, I seemed to see this case frequently with a certain launch sequence. I really don't like the idea of incorporating "Wait x seconds" in a launch sequence as it feels crude and superfluous if I can just come up with the right hand-shaking logic. So, once again, to crystallise my ponderings, when working in an environment which has been specifically coded to be asynchronous, what is the best way to ensure that a strict sequence of events is followed? Edit: The more I think about it, the more dirty my new code feels to me, some of the launched sub-modules need to pass data between each-other, there's a strong potential for a consumer to request a queue before a producer has published it, requiring re-request code. Ugggh, if I could just think how to ensure that each Sub-VI gets all the way through its launch sequence before the next one is launched (WITHOUT using crude "wait x seconds" code) I'd be set. Edit 2 (2 minutes after edit 1): I supposed I could format the commands such that they can be parsed for specific information (like the command string could read "Status:Request Data" from a Sub VI and "VI Control:Launch X" from a master level command. That way perhaps commands could be dequeued in some sort of order then requeued if they don't match whats...required...at the time? Hmmm, have to ponder the possibilities a bit more. I wish I wasn't under PhD time pressure, I'm enjoying Labview more than muscle bath design at the moment!
  10. Hi guys, I've had to re-do some code I've been working on as it needed to be deployed to a real-time system. I'm taking this opportunity to make some architectural changes because some of the inter-process signalling felt really dirty. Here's a brief outline of what I'm doing. Host machine VI controls Real-Time VI via network stream. Real-Time VI take messages sent by network stream and performs some "program control" type logic (telling other mediator loops to launch sub-VIs, launch an FPGA based VI, etc. etc). I'm currently wrestling with the practical implementation of an abstraction I want to use (because it feels right). That is, I want each dynamic sub-VI to be launched with it's own pair of messaging queues, one to receive commands from it's master, the other to send status reports back to the master. The problem I'm having is I can't think of a really elegant way for the Sub-VI launcher to monitor "n" status queues. To give some more context, the Sub-VI launcher loop has it's own pair of messaging queues which connect it to the Real-Time VI's master loop, that is, the loop that handles commands from the host machine via the network. Previously the sub-VI launcher loop has presented it's own command queue (that is, the command queue used by the Real-Time master loop to tell it to launch VI's) to listen for and handle status up-dates from the Sub-VI's. This has run me into trouble when trying to elegantly handle shut-down orders as suddenly the sub-VI launcher loop receives a stack of status updates from a raft of different Sub-VI's and must shut them down in the correct order and then report to the master loop so further action can be taken. I feel as if somehow abstracting communication between the Sub-VI launcher and it's progeny to an individual messenger pair per child will allow me to perform sequences of shut-down events elegantly. So, to synthesise, how can a master-loop elegantly monitor all its dynamically launched children and still respond to commands from its master? Thanks for any insight you guys give, Alex Edit: A final note, I would prefer to stay away from an OOP solution for now. I've tried in the past to look into it but I just don't have the time to study it at the minute. So if you could confine answers to standard LV "state-machine" type architecture (a while loop enclosing a case structure), that would be much appreciated.
  11. So the situation I'm faced with is as follows. I have a PXI crate with an FPGA card in it that has multiple DIO connectors. Each one of these connectors is wired out to a laser interferometer card's hardware interface. One connector corresponds to one channel on the laser interferometer. We have code that takes the input to each DIO, formats them, then presents each channels information on a "To-Host DMA". The PXI crate is connected to a Real Time box. We (my work mate and myself) want to be able to work from two different Windows machines, connect to the real time box and subsequently each read a different to host DMA for the information from different channels. Is there a graceful way to share FPGA resources like this between multiple projects? If not, what would be the best way to get this information (each individual channel) out of the FPGA, into the RT box and subsequently access it from the different machines? Regards and thanks for your help in advance, Alex
  12. Hey Ravi, Thank you very much! I didn't know queues behaved like that (error input true to the queue returns a blank element). That's really weird, why not just have it return nothing, i.e. no dequeue and pass the error cluster? Once again, thanks for your help! Kind regards, Alex
  13. Alright, Attached you'll find a zip of the current project I'm writing. I've got an insane error where an "error" message (a simple string + variant cluster) is loaded into a control queue. When previewed before dequeued, it shows up fine, when dequeued proper it's blank and causes a meltdown. Steps to reproduce: 1) Fire up "Main Separate Sub VI" 2) Run the Code 3) Look for "Start Calibration VI" on the front panel, bottom left hand side, under a comment that says "Debugging commands only" and hit the button. 4) Watch the sparks fly... 5) Use the abort button to kill the code Note: I think I've set up the VI path right for the calibration VI, if not, change it to an absolute path which points to wherever it ended up. So the error you should see, is that a pop up appears saying "The case does not exist in the Sub VI Control Loop please check your spelling" which is my default typo handling case. What's happening is that the calibration VI is looking for a data queue it can latch onto, as it can't find any, it registers an error with the host code, passing the error code along with it's name back to the host. The error code is then loaded onto the common error handling line of the "Sub VI Status Handling" loop and caught by the error handling case at the end of each iteration of that while loop. This is when things get funky. As mentioned above, the enqueue operation doesn't time out, the "Error+Variant" data message is loaded onto the queue, when the queue is previewed shortly before it's supposed to be dequeued, it shows the element contained within (the "Error + Variant" thing). Once dequeued the message is blank, causing the loop to go into it's default typo handling behaviour. So my question is obvious I guess. Why in the blue blazes is the "Error" string blank upon dequeue?! P.S. As a quick side note, I use the exact same method of catching errors within the Calibration Sub VI in it's own control queue. It works clearly as this is how the error is caught and passed back to the host code in the first place. Queue Error Example.zip
  14. Thanks Jcarmody for clarifying and putting up that code. Time zones meant I was asleep! Anyway, the reason I wanted two means of stopping, was that the program can receive shut down messages from another section of the code and also from the user when they're looking at the front panel. Either way should shut down the code with a single button press.
  15. I achieved what I was trying to do by having no timeout and writing the stop condition of the stop loop to a property node (value(signalling)) linked to the control bool. Still don't know why having a time out causes the control to become unresponsive.
  16. So in the course of my tinkering, I came up with this gem: The time out case of the event structure contains nothing. So, here's what happens. If there is a timeout wired, the stop button (passed via local variable from the upper loop) causes the program to stop, but the "data calibrated", which is basically junk but should also stop the program, doesn't. (Even if you add something like a set true to a local variable corresponding to the upper loop stop. Basically, with a timeout value wired in, the "Data Calibrated" event is never handled (wire a simple indicator to the button to observe). If no timeout is wired, data calibrated works but the stop button obviously doesn't. Why does this happen? I've read through everything I could find in the labview help searching for something to do with this behaviour, but couldn't parse any useful information out of it.
  17. Of course... I am thumping my head on the table right now. Sorry for wasting everyones time.
  18. This is kind of obvious I guess, but a for loop which is not iterated, will not pass a reference through. This means if you're controlling your loop using auto-indexing (as I was), and for the use case where there is no data in the input array, any operations which had pass through references will return an error in the next operation to require that reference. In my case, an enqueue operation. I guess this is by design, though I don't see why it should be. I know I can handle this but manually checking the size of the input array and using case structure. Or just split the queue reference and not pass it through (order of operation is already ensured by error terminals in any case). Just curious as to the logic of this, given we have the ability to control For Loops by auto-indexing. Regards, Alex
  19. Ok, that leads me to another question. Given that my mediator/host is responsible for managing the order of shut down, and hence preserving the integrity of the queue, should I be dropping those remove queue operations on the block diagram as a matter of principle? Or should I just leave it, I guess that's a "best coding practise?" type question.
  20. Hey James, I know, I know, look for simplicity. I try, I really do, but I'm also obssessed with this project as a way to learn new tricks. Even though they may not be all that useful. I figure once I've got more of an understanding of what can be done, I can learn what should be done. Anyway, my solution without getting into any OOP, was to take the message a consumer sends acknowledging a data queue reference, and do some logic in the host to add that VI to a list of consumers. Then, in shutting down. Consumers are shut down before producers, finally the main host cleans itself up. A quick question though, when the VI that creates a queue is shut down, obviously it destroys that queue reference as all other VI's subsequently return an error. Is this the same as calling the "Release reference" queue command in terms of memory behaviour? In other words, if the queue reference is lost this way, is the memory still freed up?
  21. Hey AQ, I had a look over AF, but I just don't think I'm ready (no free time atm) to battle with the OOP concepts. I'm pretty sure I can achieve what I'm trying to achieve with a regular labview architecture and proper hand-shaking or queue exchanges. Cheers, Alex
  22. Hahahaha. Thanks AQ. There is a huge smile on my face atm, just purely because I feel like, while I'm stumbling along by myself, I'm following in the footsteps of people that have been before me. Hard to explain the feeling, but it's nice to be tinkering and know that there are people out there who can look at what you're doing and say, "that's ok... but it won't work and here's why". You nailed in that post exactly what I've just been dealing with, specifically, I try to shut down everything at program end, but I have no control over the order of Sub VI shutdowns, hence I have been scratching my head over how to gracefully deal with the loss of queue references. In my hacked together approach, I guess I could set some sort of "Producer or Consumer" property and then deal with it like that... Thanks as well for the succinct overview of how to attack the problem with AF. I'll have a look over it and see if I can get my head around it. I'm definitely in the "huh?" phase of trying to think in terms of OOP. Your post is why this forum rocks . Edit: Is there an AF version available for 2010? Edit 2: Ahh well, guess this is the kick up the ass I need to finally install 2011 (incidentally, could you have a word to whoever about some sort of bulk "search and install" function which can look at every toolkit I have currently installedr and install the most recent version of it?)
  23. I've come up with a way to do it without OOP that seems pretty cool to me. Any parallel sub-VI is either a producer or a consumer of data. If it's a producer, when it starts it creates a data queue named after itself (with the word "data" concatenated). Then sends the queue ref back to the mediator as a variant packaged with a command to the host to process "publish data queue", which builds an array of data queue references. When a consumer fires up, it sends a request to the host for a data queue reference. The host then pulls all its current listed data queue references and passes them one by one to the consumer. The consumer knows what type of data it wants so the "Variant to Data" converter acts like the gate keeper, generating an error for each reference that doesn't match until it finds one that does, then it flushes the remaining queue references and goes to wait with it's shiny new queue ref. I intend to implement a score keeping type counter which iterates with each attempt to grab a queue reference, then I have an index of which queue was good which I can return to the host so it can remove that queue from it's list of available data queues (If I want exclusivity). The passing every data queue ref is a little crude, but I can't think of a good way to know exactly which queue ref to pass without ruining the generality of my mediator processing case. Edit: Sorry for the side-track, it's only tangentially related to what's going on here.
  24. This topic seems to be the most similar to what I'm scratching my head over at the moment. I can't figure out how to create a scenario where a dynamically launched sub-vi creates a data pipeline queue (for offloading processing of high-speed data to another asynchronous parallel process), then registers the queue to the mediator which passes it to a sub-vi that calls for it. Unless I do it by name... This is the only way I can think of to pass the information about what pipeline the receiving VI should listen to without the mediator having to care about what form the data pipeline takes. Is there something in OOP that addresses this issue? (I'm currently tinkering away in my 4 hour compile times with different ideas. Yet to strike upon a good one).
  25. Thanks Kurt, I had a bit of a brain fart and didn't assume that you could just cluster the object wires!
×
×
  • Create New...

Important Information

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