MrPLC Member
  • Content count

  • Joined

  • Last visited

Community Reputation

2 Neutral

About gazroo

  • Rank

Profile Information

  • Country United Kingdom
  1. Hi, Based on other information I've garnered on the web, my A-B driver currently initiates a session with an SLC or MicroLogix as follows: Step 1 - Register Session Step 2 - Forward Open (over CIP CM, encapsulated inside a SendRRData) Step 3 - Can now send read/write tag requests as needed (over CIP PCCC, encapsulated inside a SendUnitData) Please don't hesitate to correct me if I'm wrong, but this appears to be the typical way of doing things (although I've observed how RS/Linx works at a lower level than this to achieve high throughput when data monitoring). At the moment, step 3 executes synchronously. In other words, max one request goes out and my driver can't do anything else whilst it waits for the response. This obviously limits the efficient use of networking bandwidth. I know I can make up payloads which request multiple reads at a time but, regardless, the approach I want to take is to do some request/response matching using a unique transaction id field. In this way, it seems to me I can transmit multiple async requests and not be worried about the order in which the responses arrive. Reading the documentation, it seems that the "Sender Context" is almost purpose-made for this type of matching. The "SendRRData" command certainly responds with the "Sender Context" that I send in the original request. That's great. However the "SendUnitData" command doesn't do this; it always returns a Sender Context of zero. And yet PCCC tag read/write requests are typically sent using "SendUnitData" - so the Sender Context field is useless in that context ? Can PCCC tag reads/writes be carried out with "SendRRData" and, if so, are there are any payload examples of how it's done ? Thanks  
  2. Mark, Many thanks for the reply. I temporarily re-inserted a ping every 8 seconds to send "List Identity". This turned out NOT to stop the session from going inactive after 60 seconds and I think Wireshark explained why: the protocol column shows 'ENIP' rather than 'CIP' for that packet, whereas presumably the PLC needs to see a CIP-level incoming request before it will reset its 60-second timeout. I took out the List Identity and in its place sent a read tag request every 8 seconds for N7:0. This does now prevent the session from going inactive (probably no surprise there !!). So, question: are there any CIP-level commands that would be suitable alternatives to a tag read as a CIP watchdog mechanism ? In this respect, one customer asked if we could add some configuration to our driver to allow them to choose which tag to read as a watchdog (in case N7:0 doesn't exist on any given PLC). This seems overkill, and it could well be that it actually doesn't matter if N7:0 doesn't exist (as long as the tag read request just gets through to the PLC, since I don't need/want to read the response). I'll test this approach next -- however, if there's a neater alternative to a tag read you can suggest, could you let me know ? Appreciate your help.
  3. Mark, Apologies - I've only just got back on to this so I wasn't ignoring you ! And sorry that I might have jumped the gun when I talked about needing to send the NoOp as a means to prevent the TCP RST from taking place. See below. I've stopped tweaking, and stripped the code back in the way you said, i.e. all that I do now is to register a session then Forward Open. That's it - I've taken out the NoOp device ping, and taken out any triggers that would cause the code to try to read or write any proxy tags configured in my driver. I just wait, watch Wireshark, and watch a browser session onto the PLC so I can monitor the Encapsulated Session Table. The first thing to report is that the TCP RST is no longer happening after 16 seconds. In fact it isn't happening at all now. It definitely used to -- I have absolutely no explanation why it has stopped. I've double-checked Wireshark and it is definitely no longer there. Next thing that happens is that, after 60 seconds, the PLC session table shows the session transitioning from ACTIVE with 1 x CIP Cnx to ACTIVE with 0 x CIP Cnx. This is now starting to make sense, because the PLC was configured for a 60 second Ethernet connection timeout via the relevant setup tab in RS Logix. Thirdly, I can see that the PLC is now sending me a [TCP Keep-Alive] every 45 seconds like clockwork. It never used to do this. I'm sending back [TCP Keep-Alive ACK] but not deliberately from my own code -- something much lower down my comms stack must be doing that on my behalf (not that it really matters). So that answers your request for test results. One final observation. After I completed the above tests, I put the repeated NoOp request back into my code -- TEMPORARILY. Wireshark shows it gets sent every 8 seconds to the PLC, as before. However, NOW, it's having absolutely no effect! In other words, the connection goes inactive after 60 seconds, with or without the repeated NoOp. Concluding question Presumably, you would argue that the above now seems more like what you would expect to happen ? So I think my only remaining question is this: what is the CORRECT method for ensuring the session doesn't go inactive after that configured interval (60 seconds for my PLC here) ? Since the TCP-level NoOp appears not to have an effect any more, should it be a connected or unconnected request ? Should I assume I can read a well-known tag such as N7:0 (which sounds prone to error) or is there a better approach ? Thanks Gary
  4. Mark, See whether you go with this idea, but I think there's a more obvious answer. I've just realised that the List Identity is being sent as a UDP datagram. As such, there's no way it is ever going to act as a keep-alive for the TCP session ! It doesn't explain why the ML1400 is only waiting 17 seconds before it issues the RST, but I can worry about that later. Do you agree ? Gary  
  5. Hi all, I have my own driver to communicate with a MicroLogix 1400. Please refer to the attached screenshot from Wireshark. is my driver's host, and is the ML1400. The startup sequence to establish a connection & session with the PLC is correct I believe: - In the grey highlight, client requests a connection to .192 via SYN and this is ack'd - A session is registered, and forward open is successful - There's a lot of stuff in green simply because I've also got an HTTP browser session open to the PLC to monitor its session table - In between, spaced 8 seconds apart, are my two attempts to keep the connection alive by sending a List Identity request (as a ping, if you like). These are highlighted in pale blue. - However, 16.5 seconds from the start of the grey highlight, and 16.4 seconds after sequence=115 ack=99, the controller sends back a [RST, ACK] and a callback from my socket code tells me that the session has been dropped. The connection timeout for the PLC is configured as either 30 or 60 seconds, so I don't see how that's relevant here when the reset is happening only 17 seconds after it was established ? However, presumably the PLC doesn't see the application-level "List Identity" request as a valid means of keeping the connection alive. What is the correct mechanism to use that the PLC will accept as a keep-alive ?
  6. Hi, As part of developing an EtherNet/IP driver for the CLX family, I have the task of recognising tags that would ordinarily be represented as strings. With SLC/ML, that wasn't too difficult since strings were a pre-defined type found in files with a file type of 0x8d. With CLX, I understand that the situation is quite different, since a string now becomes just another structured tag like so many others. So, for instance, in my controller, and with the help of information gleaned from the LogixTagRead program, I can see that a request sent for one particular tag (which I happen to know is a string) returns me the following information: Tag type: A0 02, followed by, Structure handle: CE 0F, followed by, Length (DINT): 1A 00 00 00, followed by, Data (Series of SINT): 41 42 43 and so on through to 58 59 5A Now in one sense I am fairly clear how to interpret most of the above data -- but in another sense, I don't believe (unless I'm missing something) that it can ever tell me that this tag should be INTERPRETED as a string. What do I mean by that ? Well, the tag type of A0 02 simply says that this tag is a structure (because the top bit is set). Even if we were to unset the top bit, the value becomes 20 02 and I'm not sure if that has significance in itself. I'm not sure if the structure handle (aka template id) of CE 0F tells me anything other than the fact that this is a symbol type of CE 8F. I know that this field can be looked up and will tell me that this structure comprises a C4 (DINT) followed by data comprising a series of C2 (SINTs) where the number of SINTs is given by the value of the DINT preceding. And, of course, this makes sense in that the DINT value of 1A 00 00 00 is decimal 26, followed by 41 42 43 ... 58 59 5A which is a 26-character string ABCDEFGHIJKLMNOPQRSTUVWXYZ. This is all correct. So whilst this LOOKS like a string, how can my code be sure that it is actually to be INTERPRETED as a string ? At the end of the day, it is only a DINT followed by a series of SINT; this doesn't of itself mean it is a string. Is there anything in the tag type or structure handle which actually identifies this as a string-type tag ? Thanks.  
  7. I did some web research and coincidentally found the answer to my own question. There IS a list of numbers for the file types I mentioned, but the information was tucked away in a scientific paper and apparently is not available in standard Allen-Bradley documentation (typically, the DF1 Protocol Reference Manual). For anyone else who needs it: Long: 0x91 Message: 0x92 PID: 0x93 PLS: 0x94 RI: 0x95 RIX: 0x96
  8. Hi all, I'm enhancing an Ethernet IP driver but only just learning the ropes in terms of Allen-Bradley PLCs. I'm presently focussing on that part of the driver which specifically supports SLC/500 & MicroLogix 1400, for which I have one controller of each type for testing purposes. I can already cater for a range of standard file types: integer, float, binary, input, output, string, counter, timer, control, status, and this is working well. However, by working with RSLogix500, I can see that there are other data file types which can be hosted in these controller types (dependent on model) and, indeed for test purposes, I have actually created instances of them as follows: ASCII (at A21, 20 elements) for both SLC & ML1400 Long (at L22, 10 elements) for ML1400 Message (at MG23, 8 elements) for ML1400 PID (at PD24, 4 elements) for ML1400 Programmable Limit Switch (at PLS25, 3 elements) for ML1400 Routing Info (at RI26, 3 elements) for ML1400 Extended Routing Info (at RIX27, 3 elements) for ML1400 Now, the driver obviously uses standard DF1 PCCC data types (see below) to read/write individual elements/sub-elements of the file types that I can already support -- and I can see that there's a file type listed below for ASCII. •80 to 83 hex: reserved •84 hex: status •85 hex: bit •86 hex: timer •87 hex: counter •88 hex: control •89 hex: integer •8A hex: floating point •8B hex: output logical by slot •8C hex: input logical by slot •8D hex: string •8E hex: ASCII •8F hex: BCD However, my question is this: since there are no hex file types corresponding to non-elementary data types such as L, MG, PID, PLS, RI and RIX, what file type do I specify in my DF1 PCCC packets to read/write the elements/sub-elements of these six data types ? Thanks in advance.
  9. Hi there, As a software engineer, but a newbie to the Allen-Bradley world, sorry if this question doesn't make sense. I'm enhancing an existing driver by trying to add the ability to read/write structured and array data types - rather than just the elementary data types it supports right now. This following question is only in the context of SLC/500 & MicroLogix 1400. And I'm currently working on a Counter as a test case, but any solution obviously needs to take into account other structured (and array) data types. One of the requirements is that the user should be able to select a specific atomic item within a parent structure/array that they want to read/write. So, using the Counter as an example, they might want to define a field which holds just the value of the accumulator. I know that I can achieve this with a CIP command. I specify file type 87 for counter, file number as 5 (my test example happens to be the standard C5 data file of counters), and element is 0 (for the first counter in C5). Bit number is irrelevant so remains as zero. I ask CIP to return me 2 bytes of data (to hold just the accumulator word). Finally, I tell CIP that I want sub-element 2 (because the accumulator is Word 2 of the whole structure). Sure enough, the CIP response gives me exactly the 2-byte accumulator value I was expecting, nothing more, nothing less. Success. My question is this: I knew I had to specify the sub-element as 2; this happens to work for a Counter because of the way it is structured as 3 words. However, it implies that the value I specify for sub-element is ALWAYS measured in units of 16-bit words. Is this a universal truth (i.e. works for other structured types too ?), or does the size of a sub-element depend on other factors, such as the file type ?   Thank you in anticipation.
  10. All, Just wanted to say thanks for your replies so far. I'm understanding how these different controllers either do or don't support UDT. I'm also understand how everything (whether UDT, structures or arrays) eventually maps down to atomic data types. And I've tried out the free AdvancedHMI software with at least some success (e.g. I can amend a string and capture the command packet needed to achieve that with Wireshark, then compare that packet with my driver's existing functions). So that's all good progress. It leads me onto another question …. I notice that if I use RSLinx Data Monitor to look at what each of my different controllers has in terms of data files, I get different results, e.g. SLC 5/05: S2, B3, T4, C5, R6, N7, F8, ST9, F10, N11, B12, N20 MicroLogix 1400: O0, I1, S2, B3, T4, C5, R6, N7, F8, ST9, B10 1756-L55/A: No data tags found   Now I'm assuming these results are simply reflecting the actual data files that have been set up by whoever commissioned the controllers in the first place. I can also see that various non-atomic data types are mentioned, e.g. string, counter, timer and so on, which appear in one type of controller but not another. My question is simply: given the 4 types of controller model listed at the top of my original post (and completely leaving aside the question of UDT), how do I determine the full catalogue of "standard" non-atomic types that each controller specifically supports (and which my driver would also therefore need to cater for) ? Is there a set of docs I need to read ? Or is the answer simpler than that ?   Thanks
  11. @b_carlton Thanks for the reply. What you say now makes some sort of sense to me, because it appears from the existing driver code that we can only read data of types integer (89), float (8a), boolean (85), output (82) and input (83). One of the mistakes I guess I made was when I looked at the RSLinx Data Monitor for one of the controllers: I saw a list of data files which included not just integral and float types, but also strings, timers and counters, and made the (wrong) assumption that they were all atomic data types as far as the controller was concerned. Once I've worked out the correct format of command packet required to read non-atomic data files, you're implying I should be able to read one or more of the timers or counters already available in the above controller. So, one follow-on question if I may: I am guessing that, since 'string' is not an atomic data type, it must be an array type (wouldn't make sense for it to be a structured data type) ? And presumably if there was a 'table' of strings I wanted to read, that would be a 2-dim array ? It's just that I'm sure I've seen in one of the protocol documents that it is possible to read both structures and arrays of 1, 2 or 3 dimensions (and even where each element of that array needn't be just an atomic type but could be a structure, e.g. a 2-dimensional array of counters).
  12. Hi, I'll apologise for asking noob questions before I start - please don't shoot, but searching for existing answers on this is very difficult for me as I'm not confident in what search terms to use to get some appropriate results! And I'm afraid there are several aspects to my question too. I'm a software developer tasked with extending an existing EtherNet/IP driver. The driver already has the ability to identify atomic data in a range of AB controller models (by specifying a file type, file number, element and sub-element). The driver can then issue the appropriate commands (at the different link layers) to read the values of that atomic data, and write new values back. I have some test hardware:  (1) Control Logix 1756-ENBT (2) SLC 500 1747-L551 (3) MicroLogix 1400 1766-L32BWA (4) CompactLogix 5370 1769-L30ER I need to access these units remotely over a VPN. I've been able to change the subnet & gateway of (2) and (3) so that I can now see them over my VPN but have yet to work out how to do this for (I) and (4). None of the controllers are set for BOOTP but, to be honest, I'm less concerned about an answer for this than I am about other stuff that follows in a while! I also have a valid licensed dongle which allows me to load RSLinx, RsLogix 500 and Studio 5000 software - for some reason, the RSLogix 500 hasn't activated and I only have a day's grace period left but, here again, I hope to find a resolution to that outside of this forum. So, to the nitty-gritty.... I'm a confident, mature developer but I have absolutely no experience with PLCs and their terminology - and I admit I haven't been on any training courses. It will take me long enough to figure out protocol/command formats without the added burden of understanding the PLC programming processes, different pieces of Rockwell applications software and their associated plethora of documentation. In short, my task is to extend our driver to read and write non-atomic data types, i.e. structures and arrays. As a general concept, naturally, I know what a structure and an array are, but not specifically in terms of my test hardware's existing data files. I'm assuming that my easiest approach is to create a couple of simple structures and arrays in the existing test hardware using the Rockwell apps, at which I point I then have an odds-on chance of working out the command packets to put in my driver to read them. I believe that, to read non-atomic data structures and arrays like these, I need to use tags to address the data - if I've understood that correctly. Later on, I could then look at how I put together command packets to write to those structures and arrays, but I want to walk before I run. At present, I have fumbled my way through setting up a driver in RSLinx to access test hardware items (2) and (3). I can even run up a data monitor for both controllers, and can see various atomic data such as integers, booleans, etc. However, I'm guessing RSLinx doesn't let me set up structures and arrays. I assume that is done through either RSLogix500 or Studio 5000 -- but I have absolutely no idea how to do it or what I'm looking for. And the other aspect that's confusing me is that these two pieces of software are limited in the controller models for which I can start a new project. If someone could just give me some idiotproof pointers to step me through this, it would be fantastic. Thanks in anticipation.