Contact and Coil | Nearly In Control

Mapping Your Inputs

This is part of an RSLogix 5000 Tutorial.

Understanding Asynchronous I/O

It’s important that you understand the difference between synchronous and asynchronous I/O in PLCs. If you come from the SLC 500 or PLC/5 world, you’ll be used to synchronous I/O, and that made your life a bit easier. In the PLC/3 world, I/O was asynchronous, and in a move that surprised many programmers, the ControlLogix/CompactLogix platform uses asynchronous I/O as well.

In a SLC 500, the PLC “scanned” the inputs by reading the state of the hardware and storing them in memory. Then it solved the logic. Then it “scanned” the outputs by copying the output coils to the actual hardware outputs. The important thing to realize is that the state of an input could never change during the logic solve. That meant you could write things like this:

Asynchronous I/O Example

…and you could be certain that Output 1 and Output 2 would never be on at the same time. However, with asynchronous I/O, our assumptions are wrong. Both Output 1 and Output 2 could be on during the same scan, or off during the same scan if Input 1 changes state between the time that it solves the first rung and it solves the second rung. Rare, but possible, and it leads to bugs that are intermittent and very hard to find, especially in logic that deals with critical timing, like data collection or communication logic.

In the days of the PLC/3, I understand programmers used to make sure they didn’t use any input more than once. They would copy the state of the input to an internal coil if they had to use it in more than one rung. With RSLogix 5000, I suggest solving it by creating a MapInputs routine that “scans” your inputs into temporary coils at the beginning of your program. Then you can forget about synchronous/asynchronous and go about your business.

Contact and Coil

Faced with the problem above, what I see a lot of programmers do is define a UDT for each input card, and then use a copy instruction to move the hardware input state into the UDT tag. There are two problems with this: first, UDTs can’t be edited without downloading the processor, so if you change an input you have to stop the machine, and second, if you’re using the UDT tag in your program, you can’t force those bits directly. You have to find the input bit that corresponds to the UDT tag bit, and force that. How would you go about finding that input? You can easily right click and do a cross reference, but that only brings you to the copy instruction. You still have to figure out that you’re looking at the 5th bit in the UDT, and then you know it corresponds to output 4 in the I/O card. Quite painful when you’re trying to fix a machine.

The solution is to use a separate rung for each input: a contact for the “real” input and a coil for the “internal” input that you use in your program. If you right click on the internal input in your program and pull up a cross reference, you can always find the OTE instruction, and easily find the real input bit to force.

Does it seem like a lot of work to do this? It really isn’t, especially if you master the art of copy-paste-search-replace, and the first time you have to find the input you’re looking for, you’ll save yourself at least that much time.

Back to the Tutorial

When we finished the last section of the tutorial, we had created a MapInputs program, but it still looked like this:

RSLogix 5000 - MapInputs - MainRoutine

Following the naming convention from the last section of the tutorial, rename MainRoutine to Aa_Main (by right clicking, selecting properties, and editing the name, then clicking OK). It’s already configured as the Main routine of the MapInputs program, so we don’t have to do that.

Right click on the MapInputs program and choose New Routine… from the menu:

RSLogix 5000 Tutorial - MapInputs - New Routine

That will open the New Routine dialog box. We want this routine to hold the logic for mapping the local input card that we added in section 3 of the tutorial. We named the I/O card “LI01″ (for Local Input card 1). Name this routine the same, for consistency:

RSLogix 5000 Tutorial - MapInputs - New Routine: LI01

Click OK to finish creating it. You’ll now see LI01 in the controller organizer:

RSLogix 5000 Tutorial - MapInputs - New Routine LI01 Added

Follow the instructions from the last tutorial section to edit the Aa_Main routine in MapInputs and add a JSR instruction to call the LI01 routine:

RSLogix 5000 Tutorial - MapInputs - JSR to LI01

Now open the LI01 routine:

RSLogix 5000 Tutorial - Empty Routine

Add a contact and a coil to this empty rung. Locate the toolbar above the ladder editor, and click the contact button, and then the coil button (highlighted):

RSLogix 5000 Tutorial - Toolbar Buttons - Contact and Coil

That should change the rung so it looks like the following:

RSLogix 5000 Tutorial - MapInputs - Rung with Contact and Coil

When you created the LI01 input card in the I/O configuration, RSLogix 5000 automatically created some tags in the Controller Tags section for access to the inputs of this card. The tags begin with the word “Local”. The first input of the card is “Local:1:I.Data.0″. That means local rack, slot 1, input data, bit 0. Select the question mark above the contact in the new rung, and enter this full tag name. You should see it above the contact now:

RSLogix 5000 Tutorial - Local:1:I.Data.0

That’s the input side. Now we need an internal coil to store the value of the input during the scan. Rather than creating individual boolean tags for each coil, I suggest creating a single DINT tag called LI01 and using LI01.0 (bit 0) for the first input, LI01.1 for the second input, etc. I would go as far as using these tag names as the input wire names in your electrical drawings.

Select the question mark above the coil, and type LI01.0 and press enter:

RSLogix 5000 Tutorial - Coil LI01.0

Notice that the rung still has errors. This is because we haven’t defined the LI01 tag yet. If you hover over the tag, it will say “Undefined Tag”. To define the new tag, right click on LI01.0 above the coil and select New “LI01″ from the context menu:

RSLogix 5000 - New LI01 Tag

That will open the New Tag dialog and autopopulate the Name field with LI01. However since we defining a tag based on a Coil instruction, it defaults to a Boolean data type. Change the data type (highlighted) to DINT (a DINT is a double-integer, meaning it has 32 bits – it is the default word size in the processor):

RSLogix 5000 Tutorial - Map Inputs - New Tag LI01

Click OK, and the rung won’t show an error anymore. However, even though LI01.0 is a perfect name for a tag because it’s concise and consistent, we also need to add a description so we know what it is. Right click on LI01.0 above the coil again, and this time select Edit Main Operand Description from the context menu:

RSLogix 5000 Tutorial - Edit Main Operand Description

That will open a small window above the ladder editor where you can enter a description. Go ahead an enter “INLET Cold Water Valve On”:

RSLogix 5000 Tutorial - INLET Cold Water Valve On

Click down in the ladder area when you’re done, and the description editing window will close. That will leave you with your first complete rung in the LI01 routine:

RSLogix 5000 Tutorial - MapInputs - One Rune

Add 15 more rungs to this routine in the same way, except increment the last number in Local:1:I.Data.XX from 0 to 15, and the last number in LI01.XX from 0 to 15. You can add the descriptions for the coils that you see here:

RSLogix 5000 Tutorial - MapInputs - Rungs 0 to 7
RSLogix 5000 Tutorial - MapInputs - Rungs 8 to 15

That’s all the inputs we’re going to have for this tutorial. If you had more input cards in your application, you’d add more routines in the MapInputs routine and more DINT tags for holding the state of the inputs during the logic scan.

Next time I’ll describe how to map your outputs, which is actually a bit different.


6 comments

  • Chris Van · June 9, 2010 at 11:41 am

    First of all, thanks for taking the time to write this tutorial, I’ve been looking for some sort of instruction to get me started programming in ladder logic on RSLogix 5000 and this has been a big help, especially your explaination as to why you write things the way you do.

    I’ve worked through every step of the tutorial today and in doing so I noticed that you only create the LI01 tag in the MapInputs program – for this tag to be used in the other programs (I first noticed this when writing the Fa_Critical routine in the Faults program) I copied the entry for LI01 in the tag explorer and pasted it into the Program Tags section for each of other programs. Later on I found that I had to do the same with the FC tag created in Fa_Critical in order to reference it in Bc_CycleStart of the WashingMachine Program.

    I am not quite sure if this was the right thing to do, but it seems to work okay for the time being – whether the contents of tag are passed between the different programs is something I haven’t tested so far.

    Once again, thanks for writing the tutorial, I hope you findthe time to finish it soon.

  • Author comment by Scott Whitlock · June 9, 2010 at 12:10 pm

    Hi Chris,

    When I create the LI01 tag, take care to notice the “Scope” box on that dialog. I have it set to RSLogix5000_Tutorial, which should make it a controller tag. By default, the first time you create a tag, it will create it as program scope, so you have to change this to controller scope. Once you do that, I think all subsequent tags will default to controller scope.

    You can separate your tags out into controller and program scope. LI01 should definitely be controller, since it represents I/O which affects everything. I hope that helps.

    - Scott

  • Chris Van · June 10, 2010 at 4:06 am

    At least the fix is simple! All I needed to do to correct my mistake was copy paste the LI01 and FC tags into the controller tags database, then delete the entries I previously created for them in the relevant programs tag databases, acknowledging that this will cause the tag references in each routine to now refer to the newly created controller tags. If only variable management was this simple and explicit in all programming languages!

  • Fernando Vivanco · July 12, 2010 at 5:34 pm

    Thanks for this tutorial, I am integrator and I have experience in Micrologix, SLC500 and PLC5 but, it is the first time that I have to work with platform Controllogix. This toutoria has been useful for me.

    Thanks a lot.

  • ivirban · February 11, 2011 at 2:35 pm

    Thanks for tips!
    I’ve never seen your method before (seen lots of programs so far), I admit I also used CPS instruction.
    Question related:
    If you have a UDT and want a “alias” to a IO point from a member (which you can’t now) which option will you describe as best use:
    1- directly in IO map routine XIC+OTE to UDT member, or
    2- XIC+OTE from mapped Input to UDT member? IF this one, in same routine? Right under mapped input assigment?

  • Author comment by Scott Whitlock · February 11, 2011 at 5:43 pm

    @ivirban – If you feel you need to organize your I/O into UDT, then I suggest replacing the LIxxx DINT’s with your UDTs, and just use XIC+OTE to go right to the UDT. However, I caution against using UDT’s at all for this because you can’t edit a UDT without downloading the CPU. That’s the reason I used a stand-alone DINT for each input card. It provides more flexibility when you’re online.

Leave a Reply

Theme Design by devolux.nh2.me