From Friday, April 19th (11:00 PM CDT) through Saturday, April 20th (2:00 PM CDT), 2024, ni.com will undergo system upgrades that may result in temporary service interruption.

We appreciate your patience as we improve our online experience.

BreakPoint

cancel
Showing results for 
Search instead for 
Did you mean: 

LV OOP small tutorials and introductions in a "workshop style"


@Blokk wrote:

If we keep OOP method VIs non-reentrant, there is always a danger that parallel executed same VIs, like a read method for two or more IDENTICAL hardware interfaces will block each other partially time by time, no?


Correct.  But your methods should be fast enough it does not matter much.

 


Blokk wrote:

Ihave no idea how it works in case of inheritance, like if there are two SIMILAR hardware interfaces, and we use two differently inherited classes. I guess in this case the two inherited slightly different Read methods cannot block each other even if they are non-reentrant?


Methods from different classes will not block each other.

 

As I said before, the Shared Clone Reentrant is probably the way to go.


GCentral
There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
Message 11 of 31
(4,647 Views)

Hmm, actually it makes sense. Even if the two read method VIs would block each other, it does not make a big difference. Like there is RS232 communication with two identical units: if the two read actions will not happen strictly parallel, but in serial, who cares. Instead of 10 msec, it will take twice, which will not make any impact on a 1000 msec loop ...

 

But, as i imagine, if i need to communicate with tens of units with the same read method, each action taking for example ~100 msec, then i must go for shared clones...

0 Kudos
Message 12 of 31
(4,643 Views)

Beware! My first class ever 🙂

Because the MKS PR4000 official driver is really *bleeep*, I thought I replace my existing lvlib using a wrapped up action engine with a class approach. So here I only use the class to wrap two data values: the VISA resource name, and the node number (-1 for RS232 and non-negative value for RS485).

Any comment is welcome, I did not finish the driver, I will need to add some more methods (like set flow rate, read actual setpoint, zero MFC, etc.). Besides, this is just a playground to play with Classes, of course a real driver to share with the community should have some more things and a bit different settings (like Tree VI, etc...).

 

There were lots of options when I needed to create the private and public VIs. I selected the "VI for data member access" options for the Read/Write private methods. For the public ones, I used the "VI from static dispatch template". However I have no idea if this is the "orthodox" way to setup such class 🙂

 

I attached a zip (LV2017), and some screenshots here:

 

classproject.png

mks_class.png

MKS_PR4000.lvlib_MKS_PR4000.lvclass_Initialize_BD.png

MKS_PR4000.lvlib_MKS_PR4000.lvclass_Read_flow_rate_BD.png

Message 13 of 31
(4,614 Views)

Since your data member access functions are set to private, there is no need for them at all.  Just use the Bundle By Name and Unbundle By Name in your methods.

 

As another trick, you can set the access scope by the project folder.  Right-click on the Private folder and choose to make the scope private.  Any VI you put in there will then be set to private access.

 

And those waits are not actually needed.  The VISA Read will determine how long you actually need to wait.


GCentral
There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
Message 14 of 31
(4,610 Views)

@crossrulz wrote:

Since your data member access functions are set to private, there is no need for them at all.  Just use the Bundle By Name and Unbundle By Name in your methods.

 

As another trick, you can set the access scope by the project folder.  Right-click on the Private folder and choose to make the scope private.  Any VI you put in there will then be set to private access.

 

And those waits are not actually needed.  The VISA Read will determine how long you actually need to wait.


Thanks! For some strange reason I kind of "extrapolated" the schema what I used in the wrapped up action engine approach. Of course, I forgot that a class is like a cluster, but even better: only the member VIs can act on the wire, no one outside. So I just delete those private VIs, and use bundle/unbundle in the methods 🙂 Simple and easy!

 

ps: yes, those wait functions were in the official driver because the programmer there used the (in this case wrong, because we have the <CR> termination characters for request/response actions!) "Bytes at port" method. I delete the Waits too.

 

 

 

 

Message 15 of 31
(4,603 Views)

Question: if I need to access two identical PR4000 units, now I can easily do it, since the two class wires hold the two different VISA resource and Node data. However, i can imagine certain cases when I might mix up which Class wire goes where in the code. Is there a technique in OOP to change the name and graphical wire appearance? So using the same Class, but visualize in the block diagram that actually I "spawned" two separate class wires using the "Initialize.vi"...?

Thanks! 🙂

 

MAIN_BD.png

 

0 Kudos
Message 16 of 31
(4,600 Views)

@Blokk wrote:

However, i can imagine certain cases when I might mix up which Class wire goes where in the code. Is there a technique in OOP to change the name and graphical wire appearance? So using the same Class, but visualize in the block diagram that actually I "spawned" two separate class wires using the "Initialize.vi"...?


The wire is still determined by the type.  In the case of OOP, the wire appearance is determined by the class, not the object (instance of the class).  Depending on how your code is architected, you could use a cluster to hold the two objects and then use Bundle By Name and Unbundle By Name.  I have also used an AE to hold the classes and then use a string lookup go get a DVR of the class (Variant Attributes makes this simple).  Otherwise, wire labels.


GCentral
There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
Message 17 of 31
(4,597 Views)

Thanks for the good hints! Or, if I just wanna keep the things in one place and easily expandable to N+1, I could just use arrays (but of course I need to be careful to keep track of the array element orders!):

 

class_array.png

0 Kudos
Message 18 of 31
(4,595 Views)

When looking for a good place to start... look the same place you would for Re-use. Use the VI hierarchy screen to figure out what is at the bottom of the screen, with no or limited dependencies. Collect the related VIs and put them in a library if not already in one.

 

Re: Cluster

If I have read Stephen correctly no clusters jus the calss data is what you are after. If you are tempted to put a cluster in your class, data OR on the icon connector of a member of the class, stop and create a class to use as you would use the cluster.

 

Then bite the bullet, and use accessors to get/set all of the private data in the class.

 

It may seem like a pain at first (because it is) but in the long run, using accessors will let you go for the gusto with Over-Ride functions.

 

Another ear mark for a "LVOOP" candidate is like the description for jazz that I once heard...

 

"Variations on a theme"

 

If things are mostly the same but have some differences... think LVOOP.

 

Just my two cents,

 

Ben 

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
Message 19 of 31
(4,585 Views)

@Ben wrote:

 

Re: Cluster

If I have read Stephen correctly no clusters jus the calss data is what you are after. If you are tempted to put a cluster in your class, data OR on the icon connector of a member of the class, stop and create a class to use as you would use the cluster.

 

Then bite the bullet, and use accessors to get/set all of the private data in the class.


Ben, I am not sure if I understood correct. Do you mean, I could create a second Class, which would hold the data? If so, how should I set up the relationship between the two classes? I am not sure if i follow you...

0 Kudos
Message 20 of 31
(4,577 Views)