What's in a name? Chose tag names wisely


#1

Let’s ponder variables, also called tags, and how to choose a good name.

Whether you’re starting a new PAC Control strategy or updating an old one, carefully consider how to name your strategy variables, because good names can make your strategy easier to troubleshoot and maintain.

For example, use the first letter or two of the name as a [B]prefix [/B]to indicate the variable type.

  •      Name an integer table [B]nt[/B]ProductTypeTable
    
  •      Name an up timer[B] ut[/B]ElapsedTimeInSeconds 
    
  •      Name an analog point[B] ai[/B]DuckProductionRate_[B]in_Ducks_per_Second[/B]
    

[B]Use all caps to name[/B] a variable used as [B]a constant[/B]: MAX_TIME_TO_WAIT_IN_SECONDS.

[B]Put the units in[/B]to the variable name, which can be stored in the I/O Unit’s memory and is visible during PAC Control debugging, while this configuration-only “Scaled” text [circled below] is not:


[FYI - if this image doesn’t appear, log into My.Opto22 to see all OptoForum images]

Use all 50 characters of your variable names wisely. The PAC Control User’s Guide (form 1700) covers naming conventions in more detail. Look in the index under “naming” for more helpful hints, such as a list of Hungarian notation prefixes.

Note: these are just conventions, not rules (except for the 50-character limit). Pick what works for you and your team and stay consistent.

What times of naming conventions to you use?

Write on…
Mary


#2

There are lots of different ways to do the same thing when programing.
Mary has got the ball rolling on an important topic, I really want to give it a bit more of a push…

When I program, I don’t use Hungarian notion… for me, I really could not see the point.
In fact, in my mind, its more of a hindrance than a help; so here’s my take on tag names…

PAC Control does a great job in telling you what type each variable is, both in the strategy tree and when selecting variables when programming.
Take a look at the following grab from one of my typical strategy’s;
(Note, you have to log into the forums to see any of the images)


You see a few thing here, but lets drop down to the green and light blue arrows.
Here you can see how PAC Control tells you what sort of variable each tag is.
You can see if its a float, and you can see if its an int32 (or even an int64).
When you program, you get the chance to select from all your floats, ints and different types as shown in this screen shot;


As you can see, you can very easily select just what ever variable you want.

But my point really does not stop here.
Do you really even need to know what type of variable or tag you are working with?
PAC Control does a great job of flipping between floats and ints for example, that often you don’t even have to worry about it, if you know your tag names, you just program your process and leave PAC Control to take care of the details.
Take a look back up at the first screen shot, the large red and blue sections, you can see that they are grouped by name.
PAC Control will always sort your names alphanumerically, so use this fact to your advantage.

Think for a moment. Do you want say, all your alarms grouped together? If that’s the case, then prefix all your tags, whether they be floats or ints with ‘alarm_’.
In my case here, I wanted all the variables for each fluid cooler to be grouped together… So, I named all my tags ‘fc2_’ and ‘fc3_’. This way, when I am looking the strategy tree, I don’t have to look through the whole tree to find what I need. They are all in the one spot.
Same when I am programming in the chart, I don’t even have to use the drop down box to select my variable type, I just grab the number of the cooler I am working on and use the tag I want.

If you use Hungarian notation, you will have all your ‘fv’ and ‘dt’ in one spot in the tree, and they will be double redundant with whats shown in the strategy tree.

I think my summery is this; if you are new to programming, try a few different small charts and see what works with your brain.
If you are an experienced programmer, this entire entry is probably null and void because you already know what works for you and it may not even be what Mary said or what I have shared.
There is no right and wrong, just bug free code. (Well, that’s the hope!)

Sound off in this tread, what naming conventions have you found works best for you?

And as always;

Code On!


Variable Rounding Issue
#3

[B]“Not Hungary? Me neither”[/B]

Mary. You may be striking me off your christams card list, but I’m with Ben on this one. I get fed up of scrolling up and down through the strategy tree looking for some lost variable name. Working from an object and parameter point of view, its easier to locate and understand [B]HEATER01_CTL_PV[/B] and [B]HEATER1_CTL_LSP[/B] than [B]Process_Variable_Heater_Controller_01_In_Degrees_C[/B] and [B]Local_Setpoint_Heater_Controller_01_in_Degrees_C[/B] !!!

I also live in the hope that one day PACControl will support objects and parameters.

Coming from an age where 1K was all you had to write your entire complete application in, I have never been a fan of trying to write my lifestory in a variable name. Not sure if its still valid nowadays with PAC Project, but I also get the feeling that passing huge tag names up and down the line between the controller and PACDisplay / PAC OPC Server is wasting time and processing power. Also in times of economic recession, it pays more sense in keeping variable names tight just in case you have to type them into OptoScript.

Maybe a good time to repeat my long standing request for Analog Input and Output points, PAC Control Debug environment to include information about engineering zero, max and units displayed in the variable window along with the live value being scanned. Thats how to clear up any doubts, and also avoids that you have to return to configuration mode just to see the units or a maximum scaled value that corresponds to a calibrated 20mA input. Much better way then trying to include the scaling information in a variable name!

I know its wrong and without actively promoting anaquism, I also use BLOCK_CAPITALS for all my variable names. Gasp, shock horror. Dirty. Yep, I admit it. It comes from working too long with “old school” systems where this was obligatory, but does help you to work out what is a variable and what is an instruction. Maybe not so much of a problem in original C with its 40 keywords, but when seeing a b&w printout, its sometimes difficult to work out the difference between variables, system variables and 500 instructions. Just look at the following OptoScript for example. Who are your variables in this scribble?

nStatus = SendCommunicationHandleCommand( chFTP, “dir” );

Mary. I can see where you are coming from a programming stance, but including descriptions of enginering scales in the tag name is the software equivalent of a pipe bomb and probably has its roots in paganism, heathenism or both!! :smiley: On any commissioning startup you can guarantee that at least some (if not most) of the instrumentation calibration spec data they originally gave you is now wrong and needs urgently modifying on the run. That flow rate they gave you in m3/min really should have been Kg/sec (Normalised). So now on top of having to change all the input ranges, scale data, totalizers etc in PACControl, you now have to change the stupid tag names, and then correct PACDisplay and pray that you didn’t use the variable name anywhere in OptoScript. All this while some plant manager is breathing down your neck asking “Why didn’t you finish programming before startup?”:mad:

George


#4

Hi George,

Good to see you on the forums again, seems like it’s been a while! I’m with you on including the scaling, min/max automatically. I don’t think that’ll happen in PAC Control, but I will protest loudly if I see that being left out of what’s in the next generation of I/O and software.

Re: “pray you didn’t use the variable name anywhere in OptoScript.” I’ve been changing variable names like crazy and they get changed in OptoScript Opto-magically too. Sounds like you need to upgrade. I see that 8.2 doesn’t do that. What version of PAC Control are you using?

Also, after reading Ben’s post I started thinking harder about naming conventions and came up with this one for myself on a little sample project: I prefaced those variables I planned to use in PAC Display with an HMI_ (the rest of the variable was all lower-case, I’m not a fan of yelling, e.g.: HMI_answer_in_progress). That way when I went to hook up my PAC Display project to my strategy, it was easy to pick out those variables I intended for that purpose.

So, I respectfully disagree on the pipe bomb (hmpf!) reference and say: changing tag/variable names is not so hard–get 9.X. And here’s a little challenge: perhaps you can think of a clever way to include those units elsewhere in your strategy, something easier to change, like a table of strings just for that purpose?

Keep thinkin’ and writin’…
-OptoMary


#5

Good topic!

I have adopted the approach of using the equipment function as the first part of the variable name, engineering units second (if required), and then add the hungarian notation at the end.

I do this because it is more important to sort items by their function in the equipment - which is how I am usually searching for things - than it is to sort by variable type.

Putting the hungarian notation at the end still tells me the variable type, but doesn’t dictate the sorting.

Kurt


#6

I leave variable types and units out of my names. Opto does a good enough job providing type information, and I’ll enter the units into my variable descriptions and comments.

My main focus when naming a variable, besides clearly describing the variables function, is to make that large variable list easy to sort through. I try to keep all the variables in a group together with a single common word like alarm_, which was mentioned before.

I also use HMI_…when a variable is going to be used with the Pac Display.

For peristent variables, I use P_ to group all the persistent variables together.


#7

Thanks for the input, OptoTechies. Lots of good ideas and points. One other thing I noticed recently: while I [I]can[/I] see my tag’s units while looking at the strategy, I might not have that handy when using a mobile device. I pondered this while trying out our new iPAC app (in which case having the units in the name might be handy). Perhaps some combination: an [B]i[/B]Prefix for sorting, a unique name, then a post-fix with units.

I’m just glad it’s easy to change a name (even easier with modern versions of PAC Control), so if I change my mind, want to try something new, or think of something better, I can have the near-instant gratification of making that quick change. Yay for the single tag database!

-OptoMary


#8

I am with Ben the anti-hungarian. I was taught hungarian naming convention in college. Fortunately, I was (and still am) a rebel, and it never grew roots with me. I would like to add to this conversation that I have some strategies that have multiple charts running concurrently. So I assign each of my concurrent charts a number and prefix my temporary variables with the number like i5_Loop or n2_Temp. I use temp variables with the same number prefix in the same chart. This assures that I will not have a For Loop based on “iLoop” in one chart interfering with a For Loop in another chart using the same “iLoop” variable. Let me add one other feature that I like that may not be directly related to variable naming; The Initialization file. I use this file extensively in my modbus projects. I have a list of sometimes hundreds of constants(variables) used as indexes of modbus registers e.g. NDX_Tank1_Pressure (Caps on the prefix since it is a constant). These variables change their modbus register locations from time to time and are different for other installations. The Init file allows me to use the macros to assign the index values to the constants in the file. I just have to change the assignments in the file and not the code. What a great feature!


#9

Thanks for chiming in, dmolley! And thanks, especially, for mentioning a couple good topics I haven’t seen mentioned much (if at all) so far in the forums:

[B]The Init File[/B]
We had a student in class just last week who also had a strategy using the init file option. That’s not something we normally cover in class, yet we see the “Download Options…” button every time we go to configure a Control Engine in PAC Control.

For those of you who’d like to read more, this download option is described in form 1700 on our website (the User’s Guide is also in PAC Control under Help->Manuals->User’s Guide). If you search for “download options” you’ll land in the relevant section.

Also, there’s a sample “Init.txt” which shows the somewhat-cryptic (FORTH) syntax used in the file, which gets installed like the sample strategies, someplace like this (by default, in 9.1):

C:\Users\Public\Documents\Opto 22\PAC Project 9.1\Control Pro Examples\InitVariables\Init.txt

or here (by default) for 9.0 and older:

C:\Program Files (x86)\Opto22\PAC Project 9.0\Control Pro Examples\InitVariables\Init.txt

[B]Multi-Threading[/B]
Thanks for the tip of using a naming convention to indicate the chart a loop index goes to. Good idea! Since all variables are global (unless you’re using subroutines), being careful with which chart uses which temp variable is important.

Have you used the not-so-new-anymore (added in R8.1a, circa 2007) commands [B]FlagLock[/B] and [B]FlagUnlock[/B]? These may not be practical for the loop variables you mention (where it’s easy to just have extra loop index variables for each chart), but in the case where you have, for example, a table of data (or an I/O Unit) accessed by more than one chart, this concept of a “synchronization object” might be helpful.

Anyone out there using the [B]FlagLock[/B]/[B]FlagUnlock [/B]commands?

Thanks,
-OptoMary


#10

Yes Mary, I use the FlagLock and FlagUnlock commands extensively in my multi-threaded programs as well. I didnt even think to mention it because it is a rather common concept in any multi-thread system. Many other programming platforms use semiphores, mutex, and other complicated forms of thread-locking, but the very simple FlagLock and FlagUnlock commands work very efficiently with an OPTO strategy. You must take care to chart and keep track of every variable that is used across threads so you can apply the thread locking when updating those variables. That is why I also name those variables by including an ‘mt’ in the name e.g. ‘ntmt_SensorArray’. This would be an integer table that is used in multi-thread mode. Now when I need to work with that variable, I will be reminded that I may need thread locking code to protect it.

Here is another really great feature; [B]POINTERS! [/B]Pointers can be really tricky to keep track of and you have to resist the urge to bury your code in pointers because for some reason pointers beget more pointers. But if you use them sparingly and carefully they can be very useful. I would love to know how many others use pointers in their code.

Here is a quick example of one way I used pointers to simplify my code: I have some subroutines which access many global variables, tables, strings, etc. All global variables required in a subroutine must be passed as a parameter and that parameter list is quite long for these subroutines. So I created a pointer table. During initialization I fill (reference) the table of pointers with pointers to these global variables, tables, etc. and pass the one pointer table into the subroutine. The subroutine will then dereference the pointers back to the global variables, tables, etc. to be used by the subroutine.

The PAC Control User guide has some excellent examples of using pointers to reduce chart complexity (not to mention screen space).

You can point to charts, which is awesome; I have an strategy that processes about 50 different serial commands all numbered 0 - 49. I had a huge screen of conditional blocks to execute a different chart for each command that was received. I created a 50 element pointer table, referenced a pointer to each chart and put that chartpointer into the appropriate element of the pointer table. So when command 4 is detected, it calls the chart pointed to in pointertable[4]. Several of the commands are not implemented leaving gaps in the table, I just filled those pointertable elements with a pointer to a common error chart. This simplified the code and display quite a bit.


#11

Yes! Pointers are another good topic; I’ve created a new thread for that one where I explain my favorite use of pointers (one I think everyone with an I/O Unit in their strategy should be using): click here.

I like how your brought the MultiThreaded topic back around to the original topic: using mt_ naming convention sounds like a good idea too.

-OptoMary


#12

Yes! Pointers are another good topic; I’ve created a new thread for that one where I explain my favorite use of pointers (one I think everyone with an I/O Unit in their strategy should be using): click here.

I like how your brought the MultiThreaded topic back around to the original topic: using mt_ naming convention sounds like a good idea too.

-OptoMary


#13

Yes! Pointers are another good topic; I’ve created a new thread for that one where I explain my favorite use of pointers (one I think everyone with an I/O Unit in their strategy should be using): click here.

I like how your brought the MultiThreaded topic back around to the original topic: using mt_ naming convention sounds like a good idea too.

-OptoMary


#14

Yes! Pointers are another good topic; I’ve created a new thread for that one where I explain my favorite use of pointers (one I think everyone with an I/O Unit in their strategy should be using): click here.

I like how your brought the MultiThreaded topic back around to the original topic: using mt_ naming convention sounds like a good idea too.

-OptoMary