Jump to content

AlexA

Members
  • Posts

    225
  • Joined

  • Last visited

  • Days Won

    2

Posts posted by AlexA

  1. 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

  2. So in the course of my tinkering, I came up with this gem:

    post-16778-0-23082900-1317177160_thumb.p

    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.

  3. 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

    • Like 1
  4. 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?

  5. 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?)

  6. 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.

  7. 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).

  8. Update:

    I understand why the states are unstable. The fact that idle can enque itself combined with the fact that the queue can receive a "Run" command while the idle state is happening and then the idle state enqueus itself means the states swap enqueuing themselves back and forth.

    As mentioned above, I think the key is to remove the idle state. The problem with this is, I can't then figure out how to handle typo errors in the state commands without the default structure having that error handling ability. That's fine for me, as I can be really rigorous, but if I want to give this to anyone else, for sure they'll make a typo at some stage. Anyone got any ideas?

    Alternatively, I could make the run action flush the queue every time, this seems kludgey to me though, and I'm not sure how expensive it is CPU wise.

    Also, I'm about to test whether removing the idle state actually does fry the FPGA, wish me luck!

    Report: It doesn't, at least on the VI I tested, yay! I realised that I actually can still have the typo error handling. When each parallel process starts up, it runs an Init state (w/e is needed), then goes into wait mode. Running the action command goes into a loop of continuous action, until a pause command is sent, then it goes to a pause state which flushes the queue, and then waits again. I'm pretty happy with that actually, can anyone see any obvious holes I'm missing or ways to break that pattern?

  9. Ok, further thoughts. I've seen Daklu say around this forum that letting a message handler enque to itself is dangerous. So I've tryed to change the architecture of the parallel process VI's (not in the latest zip file) to be a bit of a compromise. The only state that's allowed to enque to itself now is the action state. The problem is, this doesn't seem to play nice with the FPGA. Arggh, it would be nice if there was a simple bug in the code linked above which explained the state flickering.

  10. Hey Guys,

    I'm a pretty stubborn guy, so I couldn't just let the approach I was taking go without tinkering a bit more. It's now working for the funtionality I've implemented, namely, starting and closing an FPGA. Listening to a specific set of FIFOs from said FPGA, and triggering the FPGA to do something. Hopefully it doesn't break too badly. Paths are fixed again and the main vi is actually in the "Scratch Pad" sub folder, it's called "Main Scratch Pad.vi" (though of course you guys won't have the FPGA set up that I do).

    Hopefully I've addressed a lot of the concerns you raised James, though there are some nasty cludges, particularly in the handling of the messenger queues while in host (look at the run/stop trigger and similar states).

    I still need to implement the functionality of listening to the queue provided by the VI which is listening to the FPGA FIFO and dequeing to display etc. Which as you stated previously James, could be pretty nasty. Hopefully I've addressed that by making the queue itself package all the relevant data from the FPGA listener. So it should just be a matter of dequeuing and processing.

    Can you take a look at this and see what fundamental flaws there are in the design?

    As I mentioned previously, the one glaring fault that jumps out to me is the handling of the messenger queues. I can't figure out how to encapsulate the queue information (i.e. which queue to use), so that it's obvious to any state that wants to talk to a certain VI exactly which queue it should load its messages on.

    Edit: Oh and another thing: I've noticed that my sub-vis running in parallel, when sent the command to run whatever their task is (which takes place in a run state which enqueues itself until a pause command flushes the queue) will constantly flicker between "Idle" and "Action", even though the only thing entering the message queue should be "action". All the VI's reference a sub-vi called "State Manager Sub" which simply enques whatever is input to it and checks for an error, flushing the queue and enqueuing and error state (which in turn calls exit and shuts down the VI). My understanding is that the application should generate a new version of that code for each VI that calls it, but I was suspicious they might somehow be sharing a queue, so I took all the stuff out of State Manager and just put it straight on the BD, no change, I still see the flickering between states. Can anyone tell me what's up?

  11. Ahh, yep that matches with my understanding. The last week has been very much tinkering week for me. It's the first time I've ever created a folder called scratch code, and it's already exploded to some 20 something VI's... Back to tinkering!

    Oh, I just remembered, the kind of nitty gritty guts of my question is:

    Suppose I have a method that takes the reference to the FPGA and starts listening to its FIFOs and loading the result onto a queue. How does one start and stop this method while still going on to perform other methods. Is there an OOP equivalent of "Run VI"?

  12. Hey AQ,

    Thanks for the input. I think trying to dive into OOP via this problem I'm working on might be a little out of reach, given the time pressure I'm under, but your input is much appreciated.

    Just a quick question further to your first, short answer. My answer to your question, based on my current understanding of Labview, would be to pass a reference to the variable between VI's, but from the reading I've been doing around the internet, passing references to classes seems to be a big no no in the OOP world. Have I misunderstood something fundamental here?

  13. Hey James,

    Thanks very much for the input! I actually do have a working prototype of the code I'm trying to achieve which was the image I posted a few posts back.I think you're right in that I'm trying to do too much at once, perhaps I should just compress the FIFO read loops into some sub-VI's.

    On the subject of queues and passing data around, of course I see the potential for errors if the queues get out of sync. It was just the only way I could think to decouple certain sections of the code so that I could stop them if I didn't want that functionality. I guess it's needless compartmentalisation though, as whenever I want one I'm going to want the other. In any case, you've given me a lot to think about! And at worst, I've learnt a whole lot about Labview that I didn't know existed before!

  14. Hi guys,

    Sorry in advance for this post being a rambly display of gross, conceptual misunderstanding, I'm putting out feelers to try and figure out a little bit about this OOP thing. As per the thread title, how would you deal with the prospect of parallel processes that need to be called from the main VI and return information to it, without creating a new object (and subsequently, a new set of data?

    In my very superficial grasp of the subject I'm imagining something like the following (context is the project I'm currently working on):

    I'm tasked with talking to an FPGA module, getting data from it and storing some data on disk, and presenting other data to some sort of control algorithm.

    I imagine an "FPGA Communications" Class.

    Data:

    -FPGA Constants (certain parameters which are read once when the FPGA is started and used in future calculations)

    -FPGA Reference

    -FPGA Data (a constant for accepting data from the FPGA)??

    Methods:

    -Initialise FPGA Constants

    -Start FPGA

    -Stop FPGA

    -Listen to FPGA FIFOs (continuous process, possibly listens to the FIFO then writes the value to the FIFO data??)

    -Present FIFO Data (accesor class)??

    -Trigger FPGA activity (potentially continuous process)

    So I guess the key thing is how one deals with the "Listen to FPGA FIFOs" method? I've also included an accessor VI for the FPGA data. I guess one class would handle communications with 1 FPGA device. If I want to have a data processing class (I think I'm still too stuck in the idea of having tasks rather than actors), anyway, this class would access the FPGA Data presented by Communications Class and do something to it. This idea of storing real time output from an FPGA in class data and then accessing, how does this fall apart when speed becomes a requirement?

  15. So I thought I'd reopen this discussion as I searched the forum for using classes as clusters. I'm working on a state machine which does the typical thing of passing constants, inside a cluster, around on a shift register. I've read that mimicing this behaviour using classes is a good way to start getting into OOP. I've broken up all the constants into categories that I think make sense (such as FPGA initlisation constants and Messenger Queue Refs). What is the best way of passing these classes on one wire? Similar to the way the data cluster is one wire. Conceptually, it's nice to break the constants up into areas of responsibility and initialise them using methods and such, but I don't want to pass a class wire for every set of constants. I also don't want to group all my constants into one Class as it seems yucky to me. What's the best solution?

  16. Hey guys,

    I started a thread over in Application Design and Architecture:

    http://lavag.org/top...block-diagrams/

    It's spiralled into a bit of a story about my painful birthing process in discovering proper coding practises, state-machines, sub-vi's (and the dynamic launching thereof). As per this post:

    http://lavag.org/top...dpost__p__89479

    I would like to change the title of the thread to more accurately reflect what's in the thread now. I was thinking something like "Factoring Code and Instantiating Parallel Processes in Sub-VI's". Also, I posted another thread which was related to the first but a more specific question, another user recommended keeping tangential questions in one thread so others can follow the discussion and thought processes. As such, could I request a merger of the following thread:

    http://lavag.org/top...-state-machine/

    with the first one.

    Thanks in advance,

    Alex

    P.S. Sorry about coming through this forum, but I couldn't find out who to contact for problems like this, and I didn't want to abuse the "report to moderator" button.

  17. @drdjpowell

    Hey, the files are in there, in the Sub-VI's folder, but in my code they're using absolute paths, so I guess that's why they wouldn't be launching for you.

    On another tack:

    Last night as I was tossing and turning I decided to browse the LAVA OOP sub-forum and I found this two part tutorial by Michael Aivaliotis from JKI which does exactly what I was trying to do, but more elegantly. So for people following along with my case or looking at a similar problem here is the link again.

    If I have edit priviledges, I'm going to change the title of this thread to more accurately reflect what's here.

    Note: From "Examples of massive programs and your block diagrams" to "Factoring Code and Instantiating Parallel Processes in Sub-VI's"

    Edit: Ok, I don't have priviledges so I'll send a PM to the moderator.

    Edit 2: Ok, colour me stupid but I can't seem to find a list of the moderators responsible for this sub-forum, or even a list of moderators full stop, can anyone let me know who to contact?

  18. Ok,

    I've attached a zip of my project as it currently stands. I've taken the approach where I separate functionality into dynamically launched sub-VI's. I have a feeling like I'm a babe walking into a dark wood and the sun is setting quicker than I realise. It's quickly getting out of my control and it's all stemming from trying to separate things into small chunks which are supposed to operate in parallel but be started individually and arbitrarily.

    It would be great if someone could have a glance over the project, specifically "main.vi" and the subs it calls, and tell me if there's a better way of doing what I'm trying to do. Specifically the idea of running parallel processes which are meant to talk to each other from a single, management type, user events handler. The reason I was trying to get things all being triggered from a consumer type events manager is that to do otherwise (i.e. use dynamic events to trigger the parallel loops in the main host) is that in terms of foot-print it really wouldn't be any more efficient than what I was doing already.

    Regards,

    Alex

  19. Ok, now I am stumped, I've been merrily going along triggering VI's from my main VI, all working as intended. Until I got to one that I didn't write, a VI that acts as a serial server allowing the transfer of commands through the code to the camera attached to the FPGA. I've tested this VI in two ways. If I try to run it using the Run VI method it results in a time out error with the camera configuration software. If I run it as a sub-vi (the way it's run in the example code provided with the NI-1483 adaptor) inside the exact same state (which locks up the state machine). Then it works fine, but of course I can't then leave it alone and go do other things. I could of course just write a dynamic user event that transfers the start serial server command to another loop, but I'd much rather understand why Run VI doesn't work like launching it as a sub-vi in this case.

    So my question, what would be difference between the two runs (I've taken care to use the Ctrl Val.Set method to make sure all the inputs are the same in each case)?

×
×
  • Create New...

Important Information

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