09-29-2021 04:38 PM
to RTSLVU
learn about object-oriented approach 😉
it is possible to follow not only in C++ but in simple C as well.
i am sure that it will be possible to create few objects and get simple top program.
by the way, i use 2 24" monitors in one place and 38" monitor in another. does it matter? no!
09-29-2021 04:41 PM
@Vasilich2004 wrote:
to RTSLVU
learn about object-oriented approach 😉
it is possible to follow not only in C++ but in simple C as well.
i am sure that it will be possible to create few objects and get simple top program.
by the way, i use 2 24" monitors in one place and 38" monitor in another. does it matter? no!
You do realize that RTSLVU was posting an example of bad code, not a sample of his code. He is quite familiar with OOP.
09-29-2021 04:44 PM - edited 09-29-2021 04:50 PM
@Vasilich2004 wrote:
to RTSLVU
learn about object-oriented approach 😉
it is possible to follow not only in C++ but in simple C as well.
i am sure that it will be possible to create few objects and get simple top program.
by the way, i use 2 24" monitors in one place and 38" monitor in another. does it matter? no!
So did you, after posting your code that is some of the worst LabVIEW I have seen in a while, just tell me I need to learn programming?
09-29-2021 04:49 PM
Mark Yedinak
"So now you are saying that clusters and shift registers are bad. What part of the language is acceptable to you?"
09-29-2021 04:52 PM
Your analysis of RTSLVU's post is flawed. His architecture is objectively better than yours. The important part here isn't the fact that he uses a stacked frame of cases, it's the fact that his architecture chooses what the next case is to execute on the fly. Note that every case can jump straight to the Error case, and the Timer case can go to more than one option (Close file and Measure). Your code can only follow the one path.
This is a simplified example, but in practice many of the states he showed would be implemented as a subVI rather than as an enum case, and each subVI would be in a line until it got to a branch point. At that point, the state machine would decide which state to go to. Otherwise, you're just using a Case structure like a Stacked Sequence structure. That can be useful, but it's not exactly what a State machine is about. A State machine chooses its next state and can change functionality on the fly.
I would guess he has more state change logic in the other states. Otherwise, all of that data could get wrapped up in a (easily testable, debuggable) subVI and called when needed. Again: it's the navigation of states that is the benefit to the architecture. Taking up less screen space is a bonus 🙂
And to answer your original question...
deinitialize functions should always ignore upstream errors, and generally should not produce errors on disconnect. Why should I care if my VISA Close function returned an error? AFAIK it only returns errors when the reference is invalid... in which case, it's likely already closed. If it disconnected during a write, the write function should return the error, and the Close shouldn't overwrite it.
If you read the Help for VISA Close and Close Reference, you will see they both have the following line in their "error in" description:
This node runs normally even if an error occurred before this node runs.
In other words, your Deinit functions should just work even if there are upstream errors.
This is a bad way to code:
You do not need the enclosing Case structure. In fact, you generally don't want an enclosing Error/No Error case structure (see NI's Darren's presentation on "An End to Brainless LabVIEW Programming").
Here's how you write a Deinit subVI:
Note that Deinit Stuff happens regardless of upstream errors, then VISA Close does its thing. If Deinit Stuff generates its own errors, it adds them to the Error wire, but upstream errors take priority.
Agilent drivers likely implement their Close functions correctly (I just checked 4 different ones and they are all programmed correctly). Any manufacturer-provided functions that are wired the first way are simply wrong, but I bet most are wired up correctly.
Thus, if your Close functions are programmed correctly, they will work fine regardless of upstream errors.
09-29-2021 04:56 PM
To RRSLVU
As I see at this moment,
- you didn't understand my question at the beginning and after I showed problem in your code and pointed that this is my question
- you brought simple state machine example which I used sometime
it is up to you learn or not to learn 😀
but! ... if you try to answer a question you need to understand the question or, as minimum, realize that you didn't understand 😉
in another case, your posts are not helpful at all!
09-29-2021 05:00 PM - edited 09-29-2021 05:22 PM
@Vasilich2004 wrote:
To RRSLVU
As I see at this moment,
- you didn't understand my question at the beginning and after I showed problem in your code and pointed that this is my question
As I see it you don't know what you are taking about.
Because even your "Why Clusters are bad" example shows a lack of basic LabVIEW programming knowledge.
09-30-2021 01:09 AM
@RTSLVU wrote:
Actually I have one more thing to add:
If you think a State Machine is hard to understand or troubleshoot. Just wait until you are handed some code that looks like this and told to fix it.
I literally had to spread this stupid block diagram out over THREE 27 inch monitors to see it all and screen capture it.
THIS is the direction you are heading and THIS is why we are trying to tell you now that you are doing it wrong.
If you think this is BAD, you haven't seen real LV spaghetti abominations yet. Also you don't need to be able to display all of a monstrously big block diagram (or front panel for that matter) to capture it, just Ctrl-A, Ctrl-C and Ctril-V in any window that accepts image data. All of it is captured anyway, no matter how much of it is on screen.
09-30-2021 01:30 AM
Could it be that we still haven't understood your question? You have been given great advice and have dismissed them.
Regarding the architectures that you dismiss, I suggest another approach: read some books (or watch Youtube or whatever) not related to LabVIEW but software architecture in general, then apply that on your code.
Another approach is to challenge yourself and implement your code in another way, e.g. an actor based approach. I would suggest to look into channel wires and look at the LabVIEW examples and make a few simple actors for your project. For simple to medium applications, I have come to love channel wires used in actors, where before I used other techniques.
So, back to your original question. I read it a couple of times more. When you are doing your initialisation, if one of the initalise stages returns an error, other stuff after that will not get initialised. This will lead to the application not working correctly. Is that your question how to solve that? The solution to that is to think through what needs to get initialised and if there really is a required order. It is easy just to put everything on the error line one after the other, but that in itself can be incorrect since some crucial references/resources will not be created if there is a previous error and will unintentionally depend on if an arbitrary previous thing was initialised or not. Most of the stuff could probably be initialised in parallell. So my advice is to review what needs to not be initialised even if there is an error.
Another way to look at it: If there is an error in the init stage, do you really want to do anything else then just shut down? If you just want to shut down, then why run any other code? But I am just guessing here and maybe I still don't understand your question.
09-30-2021 01:45 AM
@thols wrote:
So, back to your original question. I read it a couple of times more. When you are doing your initialisation, if one of the initalise stages returns an error, other stuff after that will not get initialised. This will lead to the application not working correctly. Is that your question how to solve that? The solution to that is to think through what needs to get initialised and if there really is a required order. It is easy just to put everything on the error line one after the other, but that in itself can be incorrect since some crucial references/resources will not be created if there is a previous error and will unintentionally depend on if an arbitrary previous thing was initialised or not. Most of the stuff could probably be initialised in parallell. So my advice is to review what needs to not be initialised even if there is an error.
Another way to look at it: If there is an error in the init stage, do you really want to do anything else then just shut down? If you just want to shut down, then why run any other code? But I am just guessing here and maybe I still don't understand your question.
Well, I'm speculating here, but the perceived problem is that if you have an error upstream it will effectively prevent doing everything after it, including in some cases, deinitializing what you (managed to) initialize.
I've had this happen is several cases where I didn't pay enough attention and didn't process potential errors upstream ("nothing wrong can go here, right? right!") which then propagated themselves and prevented my queues from working properly (couldn't dequeue any commands) and all went to sh!#. Basically, unprocessed errors can prevent you from doing anything about them if the program doesn't foresee doing anything about the errors to prevent them from preventing you to do something about them in the first place.