RSLogix5000 Alarm summary bit for annunciation

coalsand

Member
Join Date
Aug 2017
Location
Vancouver
Posts
5
I've got a plant with around 500 different instruction-based alarms. The plant would like for the sirens and beacons to go off when any one of the alarms are active. Is there an efficient way to do this that doesn't involve explicitly calling every *.InAlarm bit to activate annunciation? I'm thinking that there must be some sort of summary bit in the PLC that can tell me that there's at least 1 active alarm, but maybe such a thing doesn't exist.


Anyone know?
 
It doesn't really exist, no. Rockwell's solution is to have the SCADA system write the alarm status back to the PLC, which is all well and good if you always have a SCADA system. But even then, it introduces a dependency that I don't like.

I built my own alarm AOI, and I can assign a generic "GlobalAlarm" tag to it. At the start of the alarms routine, I unlatch this bit, and then every alarm AOI is scanned, and if any of them are active, it will latch the bit. Then at the end of the alarm logic, I check the status of the "GlobalAlarm" tag and annunciate accordingly.
 
ASF
Are you watching for new alarms by watching for a rising edge? If you are would you consider sharing that AOI or at least the basis to it.
I have used several approaches to searching a BOOL or DINT array and while the the FSC approach is the most promising, but it detects falling edge changes as well and that is not as useful. I need to detect when new alarms arrive - I don't care when they resolve and I can't seem to come up with a good solution to that.

And yes, I have learned my lesson on Bool arrays. They are more trouble than they are worth.
 
Is there an efficient way to do this that doesn't involve explicitly calling every *.InAlarm bit to activate annunciation?

The ".InAlarm" bit is an object of some UDT or AOI. Because those are scattered tags, there's no "easy" way to do it. But there are a few ways to do it "efficiently".

METHOD A
If this is a UDT under your control, you could add in a reference a bit, and in your logic, one-shot a latch to that bit on the .InAlarm.

Your horn logic would then detect that bit, trigger the horn, and unlatch the bit. The horn silence button would kill the horn, but another new alarm (or a true-to-false-to-true transition of the previous alarm) will re-trigger the horn.

Adding a tag to 500 AOIs is marginally easier than adding 500 rungs of logic that do the same. You also have the flexibility to have different bits for horns in different areas and so forth.


METHOD 2
Create an array of your UDT/AOI with 500 (or more, to allow for spares), and change your specific tags the refer to the unique tagname to an alias that points to a single element in your array, making sure that each instance points to a different element.

Example: If you have an AOI with tags TT_123 and TT_456 of datatype p_Analog, create a tag "All_Analogs" of datatype p_Analog[500], with TT_123 as an alias to All_Analogs[123].

Your HMI links will not be affected by this, since the comm driver will still by asking for TT_123.InAlarm, which is still a legitimate tag.

Now that all your alarm-containing tags are in a single object, a file instruction or a For-Next loop can find an instance where All_Analogs[Control.POS].InAlarm = 1, and then set a bit in a ActiveAlarm DINT[20] array
Set bit ActiveAlarm[(Control.POS AND NOT 31) / 32].[Control.POS AND 31]. Bit 123 is ActiveAlarm[3].27, which corresponds to All_Analogs[123] which is aliased by TT_123.

If all the elements in ActiveAlarms <> 0, you have an alarm. You can do bit twiddling using the XOR command to create a similar array which indicates only a NEW alarm (one that wasn't on last scan) to trigger your horn.



METHOD III

Write 500 rungs of contact-to-coil logic to do the above, using either a one-shot OTL to a single bit, or an OTE to an alarm array. Which is what you're trying to avoid.

But any method is still going to involve making 500 edits to existing logic, either adding something to an AOI; making 500 tags aliases to another tag, or making 500 contact-to-coil rungs. (which, you could code in Excel and then just paste in, so this might actually be the fasted method).


--------
Wouldn't it be nice if our customers would tell us requirements like these up front, BEFORE we started coding and not when we were almost done?
 
Last edited:
ASF
Are you watching for new alarms by watching for a rising edge? If you are would you consider sharing that AOI or at least the basis to it.

I can't share the AOI itself, but the crux of it is this:
Code:
|    Alarm_Condition_True           InAlarm      InAlarmUnack    GlobalUnackAlarm
|-----------| |---------------+-------|\|------+-----(L)------+-------(L)-------|
|                             |
|                             |                    InAlarm        GlobalAlarm
|                             +----------------+-----(L)------+-------(L)-------|
The "InAlarm" and "InAlarmUnack" bits are the ones related to this alarm specifically, that remain on until the alarm is cleared/reset/acknowledged/whatever. The "Global" tags are the ones that get externally unlatched each scan before the alarm AOI's are scanned, and then at the end of the alarm scanning process, you can tell whether you have any alarms in your list that are active and/or unacknowledged.

Of course it's not quite that simple because...
- I'm using the EnableInFalse routine to determine whether the alarm is active or not, not an "Alarm_Condition_True" bit within the code
- I have options for alarm delay presets and things like that
- I have options for whether the alarms are automatically cleared or require a manual reset
- I have options for enabling/disabling alarms
...and so on. But you get the idea.

And yes, I have learned my lesson on Bool arrays. They are more trouble than they are worth.
I too learned this lesson. Bool arrays are the devil.
 
Last edited:
OK, That's not gonna dig me out of this bithole I find myself in.
I need to scan for (and count) *new* TRUE bits completely ignoring the ones that transition to false. This triggers an audible alarm as many times as there are new alarms. ( I can't wait to hear this thing on a big failure test but its what was asked for)
I can't use a simple count in case 2 bits swap states. FSC just looks for the first change in either direction.
In this case the alarm delays and such are done elsewhere so I'm just handling the end result and making noise.
 
I need to scan for (and count) *new* TRUE bits completely ignoring the ones that transition to false.

Did you see my methods above?

What you need to do is how we used to do things back in the PLC-5/SLC days, when all we had were bits and words:

We'd have a block of bits in words (say the whole B13 file), that showed the active alarms.

We'd then have a block that had all the alarms that were active last scan (B14).

Then we'd have a block that are new this scan (B15).

Logic is
Alarm condition = OTE(B13.bit)
B15 = XOR (B13, B14).
B14 = COP (B13)

Counting alarms is adding up the values of the B13 words.
Triggering horns is looking for a non-zero word in B15.

----

In the ControLogix world, those structures aren't as readily available, but they can be built.

If your add to your AOI:
- an input parameter "AlarmNo" (type: Dint; range 0 to 500)
- an In/Out parameter "AlarmArray" (type: DInt[20]),

Inside the AOI add the logic

XIC( InAlarm ) OTE( AlarmArray [(AlarmNo AND NOT 31) / 32].[AlarmNo AND 31] )


AlarmArray is now the B13 from the above.
You can then build two more arrays AlarmsLastScan and AlarmsNew (type: Dint[20]).
Use an FAL to do the XOR of AlarmArray with AlarmLastScan into AlarmsNew.
Then a COP of AlarmArray into AlarmLastScan.

With an FSC of AlarmLastScan of <> 0 , a .FD bit without a .DN means that there's at least one alarm this scan that wasn't on last. Sound the horn.
 
Last edited:
Aardwizz

Using FSC is what I have done before and it works to find that there is something new, but this spec wants one sound per new alarm. So if 50 bits transition, sound the alarm 50 times. I can't recall at this moment if I can continue the FSC from the first FD bit to the next FD bit... Hmmm.... If I could that would work...

I truly think they will regret this choice but I'm not paid to think, I'm paid to make it happen. Plus counting new alarm bits might come in handy for something someday so it's a good exercise.
 
I can't recall at this moment if I can continue the FSC from the first FD bit to the next FD bit... Hmmm.... If I could that would work...

I believe you can, though I've never had a need to do so.

EDIT: You'd want to clear the .IN bit on .FD but not .DN I think, not sure if anything else needed. And even if using ALL mode it can only find one match each scan cycle of course.
 
Last edited:
If we start with a boolean one-shot/edge detector:
Code:
    In        Mem    ONS
----] [--+----]/[----( )--+--
         |                |
         |           Mem  |
         +-----------( )--+
And convert it to bit-wise form in an integer, we get this:

Code:
AND CURRENT_ALARM_BITS LAST_SCAN_INVERTED_ALARM_BITS NEW_ALARM_BITS_THIS_SCAN
NOT CURRENT_ALARM_BITS LAST_SCAN_INVERTED_ALARM_BITS
?


[UPDATE: HAH!]


Why can't I do that in upper case?

xxx.png
 
Last edited:
Program an "Alarm Handler" as follows:


1) Create an Array of BOOLss or DINTS or INTs with the tagname "Alarm_Trigger". Process / Machine conditions set the individual bits in the "Alarm_Trigger" array.


2) Use the FAL (File Arithmetic Logical) instructions with an "Alarm" array. Data Type & array size are the same as the "Alarm_Trigger" array. Logic in the FAL instruction seals the "Alarm" array bit.


Expression: (Alarm_Trigger[FAL_NAME.POS] OR(Alarm[FAL_NAME.POS] AND(NOT Alarm_Ack[FAL_NAME.POS]))) AND(NOT Alarm_Disabled[FAL_NAME.POS])


Dest: Alarm[FAL_NAME.POS]


Note: The "Alarm_Disabled" array is optional, the same Data Type & Size as the "Alarm" array. Setting a bit in the "Alarm_Disabled" array disabled the corresponding Alarm in the "Alarm" array.



3) Use the FSC (File Search & Compare) instruction to search the "Alarm" array for any alarm. If FSC output (FSC_NAME.FD) is True the turn on the Alarm Light.


Expression: Alarm[FSC_NAME.POS]<>0


4) Create a third array "Alarm_Ack" (Alarm Acknowledged) use the FAL instruction with AND logic on the "Alarm" & "Alarm_Ack" arrays with output to the "Alarm_Ack" array.


Expression: Alarm[FAL_NAME.POS] AND ALARM_Ack[FAL_NAME.POS]


Dest: Alarm_Ack[FAL_NAME.POS]


5) Use the FSC instruction to search the "Alarm" & "Alarm_Ack" array with Exclusive OR logic. If the "Alarm" & "Alarm_Ack" arrays are different then Set FSC output (FSC_NAME.FD) & turn On the Alarm Horn.


Expression: Alarm[FSC_NAME.POS] XOR Alarm_Ack[FSC_NAME.POS]<>0



6) When the Alarm Acknowledge command is issued from an HMI or Pushbutton input then Copy the "Alarm" array to the "Alarm_Ack" array. The will cause the output of the FSC instruction to be Reset & Turn Off the Alarm Horn.


Note:place the "Alarm" array to "Alarm_Ack" array Copy instruction 1 rung before the "Alarm" array & "Alarm_Ack" array FAL instruction.


a) If the "Alarm Handler" is place in separate Program File the "Alarm Handler" logic is 6 rungs which includes the 1 rung of logic for the Alarm Acknowledge command.
b) If using Data Type INT or DINT then the FAL & FSC lengths are the Elements / Word / Double Word array size.

c) If using Data Type BOOL then the FAL & FSC lengths are the Boolean array size / number of Booleans.


The "Alarm" & "Alarm_Ack" arrays can also be used to drive an Alarm display on an HMI (Panelview, RSView32, Wonderware, etc):


1) If there is Alarm condition present that has NOT been Acknowledged then display Yellow Text with Red background in an Alarm Banner or page



2) If there is an Alarm condition present that has been Acknowledged then display Red Text with a White background.
 
So if 50 bits transition, sound the alarm 50 times.

That sounds like a miscommunication. Usually what is done is, if alarm 47 fires, the horn blares, they hit the silence button. Then when alarm 123 hits, even if 47 is still active, the alarm fires again. If while 123 is on, 47 drops off and then retriggers, the horn goes on yet again.

What is sound like you think they want is, when new alarm 123 hits while 47 is active, beep the horn twice. If alarm 63 joins the fray, beep the horn 3 times.

If so, the logic I have will handled that: you have new alarm detection to start the horn, and you can use bit-counting logic to count the number of set bits in an array. See this old post:
http://www.plctalk.net/qanda/showthread.php?s=&threadid=1959



==== EDIT ====
I did make a small error in my logic for the setting the One-scan bit. The XOR detects the difference between Active and Last, so when Active drops out, the XOR would give a signal in seeing the Last set when Active is not. Thus, we need to also AND the XOR result with the Active array:

B15 = AND ( B13 , XOR (B13, B14))

As Dr.BitBoy pointed out, that's the equivalent of

B13 B13 B14 B15
---| |---+---| |---|/|---+---( )
| |
| B13 B14 |
+---|/|---| |---+

B13 B14
---| |-----------------------( )

Which reduces to

B13 B14 B15
---| |---+----|/|-----( )
|
| B14
+------------( )




So the logic
B15 = B13 AND NOT B14
B14 = B13
is simpler. Serves me right for relying solely on memory.
 
Last edited:
The Alarm Handler I posted functions as follows:


1) Alarm #1 condition occurs: The Alarm Light Flashes & the Alarm Horn is activated.
2) Operator Acknowledges the Alarms9s)but Alarm #1 condition has not cleared then the Alarm Light continues to flash & the Alarm Horn is silenced.
3) Alarm #2 condition occurs: The Alarm Light is still flashing & the Alarn Horn is activated.
4) Alarm #1 condition clears: The Alarm Light continues flashing (Alarm condition #2) & the Alarm Horn is still activated.
5) Operator Acknowledges the Alarm9s) but Alarm #2 condition has not cleared then the Alarm Light continues to flash & the Alarm Horn is silenced.
6) Alarm #2 condition clears: The Alarm Light stops flashing.


and / or


a) Alarm #1 condition occurs: The Alarm Light Flashes & the Alarm Horn is activated.
b) Alarm #1 condition clears BEFORE being Acknowledged: The Alarm Light continues flashing & the Alarm Horn stays activated.
c) Operator Acknowledges Alarm #1 condition: the Alarm Light stops flashing & the Alarm Horn is silenced.
 

Similar Topics

Hello All, Just wanted to gather peoples' thoughts regarding fault and alarm management within a program. I've seen programs where AOIs are...
Replies
3
Views
2,045
I'm creating a relatively simple application using a single PLC communicating to a PC application via OPC (specifically, Kepware) One thing I'm...
Replies
1
Views
1,432
Hi! So my problem is a little funky, I had Studio 5000 v 24 and 30 installed, but forgot to install RSLogix (which I cannot go without). Is there...
Replies
2
Views
149
So I had an odd request from a customer for the above. I have written the logic and tested it all in one PLC with only using 7 outputs and 7...
Replies
15
Views
446
Hello everyone, I have an RSLogix5000 project which is running live in the factory but I need to make some changes to the logic. I want to test...
Replies
0
Views
1,131
Back
Top Bottom