So I'm easing my way back into VisiLogic land, in-between phone calls from TV trucks. The other morning I get a call from one of our techs on a startup somewhere in Texas, telling me that the customer is requesting that all the panels on the "A" side of the facility have their primary power feeds fed from the "A" side breaker panels, and that on the "B" side, "A" side breakers should go to the secondary power inputs. For this they wake me up? Just swap the feeds on the "B" side, right?
Unfortunately, when we laid out these panels, we made the decision to label the primary power feeds as "Power Feed A" and the secondary feeds as "Power Feed B". So, now that the customer is hooking up power, they think of "A" as "Side A", not "Primary", and half the panels are wired up backwards, because the panels on the "B" side need to have "Power Feed B" be primary, not secondary.
So, we offer to relabel things "Primary" and "Secondary", but the customer really likes "A" and "B" because it matches the names of the sides of the building. OK, we rewire half the panels to make "B" be primary - problem solved, right?
Not so fast. It turns out that "Using Power B" is one of the alarm texts - on half the panels, it'll have to be changed to "Using Power A". Similarly, the input designation will have to change on the signal telling us if the panel has lost its primary power feed. So, I figure I'll just have the PLC program look at the network address - if the panel's on side "B", the ladder can just swap the text of the alarm. Except that I can't - the texts are stored in String Libraries, which are in Flash memory and are not changeable by the PLC program.
OK, says my technician, just make a separate version for the "A" side and the "B" side...
And, yes, I could have done that. It would have been easier and quicker - but it wouldn't have been the right thing to do. Splitting software into multiple working versions - referred to as "Forking" a piece of software - is something to avoid if at all possible. If you have an "A" and "B" side program, which are mostly the same, then in the future you've got to be sure that any changes you make to "A" are also made to "B". You also have to be sure that if a PLC needs to be replaced or have its software reloaded, that the correct version gets put in. It means that if the customer wants to have a spare on the shelf, they now either need two spares, or they have to be concerned about keeping SD cards with the different versions on hand. Forking is one of those things that seems quick and easy, and winds up causing you massive headaches a couple years down the road.
So, I thought of a couple of ways to get around the problem - using two different alarm numbers in the controller depending on what side it was on, then swapping the numbers back before passing the alarm list off to the master PLC, or putting the alarm list into the string table twice, one starting at zero, and one at five hundred, and having the list display routine add five hundred to the alarm number if the controller was on the "B" side. It all sounded like just too much effort, and I was about to hold my nose and save off an "A" and "B" version of the software, when I realised:
String Libraries aren't just for multiple languages anymore.
Each index in a String Library table has multiple entries associated with it, and by far the most common use for these entries is to support easy switching between languages. If, for instance, instead of just placing the text "OPEN" on the screen, you use "String From Library", you can have "OPEN", "ABIERTO", and "OFFEN" stored at one index. Then with a single function block, the PLC can select whether to use the first, second, or third String Library, and the text on the screen will switch from English to Spanish or German. Carry that through the entire HMI program, and you can easily have a program where the operator can set the display's language with one keypress.
Now, here's the fun part - I wasn't using multiple languages, but I _did_ need to have a handful of String Library entries change from "A" to "B" or vice versa, depending on the network address. So, I used .csv import to load the exact same list into the first and second Library, changed the "A" and "B" on the alarms and input names in Library 2, and set up a rung of PLC code to switch to either Library 1 or Library 2 depending on network address.
Boy, did _that_ make a mess! The HMI became unresponsive, the screen flickered constantly - I knew I'd done _something_ wrong, but what? Aha! I had made MB219 be "This Is Side B", then used a normally closed MB219 to set String Library 1, and a normally open MB219 to set String Library 2. However, the PLC redraws the entire HMI page every time the String Library is selected, even if it's the same library as it
was last scan. So, I quickly added a normally open SB2 to each rung so that the Library is only selected at power-up - I thought about using transitional contacts [P] and [N] on the MB219, but felt it would be better to use the SB2 and be sure that the proper library gets selected each time the PLC gets powered up.
That worked perfectly, and I now have just one software version for both sides of the plant, plus I have an extra tool in the toolbox - using multiple String Libraries to change a PLC's configuration. You could use network address, a password protected setting in a configuration screen, or even a hardware jumper on a spare input (a method that protects against accidental mis-configurations) - just have some way to let the PLC know which way to set its String Libraries, and you may be able to avoid having multiple versions of the same PLC program kicking around, waiting to trip you up five years in the future.