Sign in to follow this  
Followers 0
Datman

RSLinx DDE Comms Problem

43 posts in this topic

Hi Guys. Ive got an application that uses VB6 to get data from a Micrologix1100 using DDE. Occasionally the system needs to write data down to the PLC, usually just 1 integer. Sometimes ( maybe once a day ) this gives a timeout or message que filled error. This is fine, i am using error traps in my vb6 code, and it will halt and try to handle the error. So if such error occurs, i close my DDE Link, and try to reconnect after 5 seconds. This is where the system completely falls over. In the code below, it will get to the linkmode = 2 , then halt with an error ( no foreign application responded to a ddeinitiate ). From here i can go nowhere, it seems that rslinx still has the ddetopic locked, and will not allow access. the only way to solve the issue is to shut down rslinx and run my application again. Is this a problem anyone has seen before? WHen looking at the Server Diagnostics in RSLinx, it says the number of conversations is 1 after an error, even though my application has close all its dde connections. how can i "kill" any dde connections in order to get this thing to reconnect without having to restart RSLinx. hope this makes sense, any help much appreciated. FrmMain.DDETest.Text = data FrmMain.DDETest.LinkTopic = "RSLinx|BOARD_GRADER" 'Define DDE application and Topic FrmMain.DDETest.LinkItem = address 'Define DDE link item FrmMain.DDETest.LinkMode = 2 'Open DDE link (manual) FrmMain.DDETest.LinkPoke 'Write data to RSLinx FrmMain.DDETest.LinkMode = 0 'Close DDE link Exit Function

Share this post


Link to post
Share on other sites
Not sure about this, but you may want to add a while loop to make sure the link is closed... EX: While FrmMain.DDETest.LinkMode <> 0 FrmMain.DDETest.LinkMode = 0 Wend

Share this post


Link to post
Share on other sites
ok thanks ill try that. its really bugging me that rslinx will not let me connect again. sometimes i also get an error back after trying to write.. "message que filled". I guess this means RSLinx is struggling and i cant put any more data across. to be fair, my test code is very hard on the DDE, im performing a DDEwrite every loop (~300ms) in order to 'destructive test' this thing. the real application only does a write once every 0.5s at most, more like 1 every second under normal conditions.

Share this post


Link to post
Share on other sites
Datman - I have used Excel VBA for DDE connection to a processor. You'll find a couple of my samples in the Ab Download section. I've never stress tested them. I always use a DDETerminate. I would wonder what is your ping time between your PC and MLGX. Use a 128 byte packet and at least 100 packets before you average. By the way each open and close pass counts as a connection and msg request added to the queue. You might be more stress friendly if you opened the dde link and left it connected until you had completed all writes then close. Just MHO. BTW - since this a test app can you post the vb6 project and forms.

Share this post


Link to post
Share on other sites
although its a test app on my bench i cant really post because the app im testing is the actual source code for the machine itself how many conversations can i have open with rslinx? Let me explain fully, i am using two different methods of doing DDE within my vb code. upon starting the application i create a topic called RSIchan. this topic is used though the code to perform reads, using the DDERequest (RSIchan, address) command. However with VB6 a write needs to be done from an object. Therefore whenever i need to write, i enter the data into a text box, and perform the following code: Public sub DDEWrite(address as string, data as integer) FrmMain.DDETest.Text = data FrmMain.DDETest.LinkTopic = "RSLinx|BOARD_GRADER" 'Define DDE application and Topic FrmMain.DDETest.LinkItem = address 'Define DDE link item FrmMain.DDETest.LinkMode = 2 'Open DDE link (manual) FrmMain.DDETest.LinkPoke 'Write data to RSLinx FrmMain.DDETest.LinkMode = 0 'Close DDE link Exit Function its just now and then that i get an error when trying to write, message que filled, or "no forgein application responded to a DDEInitiate" when trying to perform the line DDETest.linkmode = 2. Once this error occurs i am stuck. My error handler disconnects all DDE conversations, but when looking at the server diagnostics on RSLinx it appears as though there are still conversations active. So my code is stuck because linkmode = 2 just generates an error every time, unless i restart rslinx. It is interesting however that my rsichan will create a link ok and perform reads ok. Its just this write that is giving me grief

Share this post


Link to post
Share on other sites
I think the following sub should work in VB6 for your stress test. Let me know? Public Sub TestDDEComms Dim RSIChan Dim RSITopic Dim DataFile Dim DataElement Dim DDETarget Dim Target RSITopic = "BOARD_GRADER" RSIChan = DDEInitiate("RSLinx", RSITopic) DataFile = ????? ' Change ???? to the Data File you are writing to DataElement = ????? ' Change ???? to the DataElement youa re writing to Target = ????? ' Change ????? to the actual write data. DDETarget = DataFile & "[" & DataElement & "]" DDEPoke RSIChan, DDETarget, Target DDETerminate (RSIChan) End Sub

Share this post


Link to post
Share on other sites
tried the above. DDEPoke does not work with vb6, although i understand it works with VBA in excel. VB6 needs an actual object to do DDE pokes, hence why i have to use a text box. I made a slight change to my code, and I've been running for 4 hours without error as yet. a good sign. Note that the after the while loop was added i was still getting errors. adding the line as shown seems to have fixed the problem. it doesnt make much sense to me... FrmMain.DDETest.Text = data FrmMain.DDETest.LinkMode = 0 '[ADDED THIS LINE] 'double check no channel is open FrmMain.DDETest.LinkTopic = "RSLinx|BOARD_GRADER" 'Define DDE application and Topic FrmMain.DDETest.LinkItem = address 'Define DDE link item FrmMain.DDETest.LinkMode = 2 'Open DDE link (manual) FrmMain.DDETest.LinkPoke 'Write data to RSLinx While FrmMain.DDETest.LinkMode <> 0 FrmMain.DDETest.LinkMode = 0 Wend Exit Function

Share this post


Link to post
Share on other sites
First off, you need to realize that DDE is not very stable to begin with. It's not your fault or RS-Linx. It's just typical behavior of Windows. It is mostly related to COM/DCOM, so this is also not unusual for OPC either (switching to OPC is not a way out), although it happens much less often with OPC. The fact that OPC is more stable is one of the reasons that DDE was not recommended even 10 years ago when Microsoft still "supported" it. What you see is exactly what happens...everything looks good then suddenly nothing will talk anymore and you got to start over. It could be hours, days, or weeks. It's not you either. I've had this exact same behavior from Wonderware InSQL even though supposedly Wonderware actually wrote DDE and their DDE drivers are very unconventional compared to everyone else and just about as stable as OPC. This brings up the only other possibility. Make sure you've got good cables and solid communications. If you don't, the frequency of this problem goes way up. I've been told that the problem is related to overflowing internal buffers in Windows in COM/DCOM. In OPC this usually happens only after several days of lack of communication with the PLC but the failure mode is identical. With DDE it happens much quicker. I haven't pinned it down but I suspect even a single garbled packet can do it with DDE. Other than the lack of support forthcoming from Microsoft, this is one of the many reasons that OPC UA is being developed. If it happens, the solution is usually to close ALL connections to RS-Linx, then reopen them. This works under OPC but I'm not 100% sure if it works with DDE (I had to do the kill/restart RS-Linx approach myself back when I had to deal with Wonderware InSQL). You have 2 connections open so you must close both of them. At that point, RS-Linx should drop communication with the PLC. Then it will restart after that. Even having an RSWho session open does it, so remember to not have any RSWho or similar windows open in RS-Linx, or it won't drop communication with the PLC and restart. That's assuming that this works at all with DDE. I haven't used DDE for years so I'm assuming that DDE problems are identical to the OPC one at this point. Under OPC, you've got a few more failed packets to play with before it croaks. So, you can set up a second connection and just monitor the virtual tag called "@ispresent". It doesn't show up in the browse listing so you have to manually type it in (this is true of all the "@" tags). Whenever you see this bit go to 0, stop & close out your other sessions and wait for it to go back to a 1. This doesn't solve the buffers issue (you've still got to occasionally stop/restart everything) but it stretches out the time between total resets to enough years (instead of weeks, hours, or days) that it shouldn't ever be a problem. As to overloading the connections, each RS-Linx session takes 4 "connections" in Logix terminology. The number of connections depends on your particular PLC and you can look in the manual for that to find out when you've saturated the number of connections (not conversations). A connection is effectively the buffers and other data that the PLC has to store and maintain. If you are dealing with a PLC-5 or a SLC, then there is another way out. You can write your own drivers and bypass RS-Linx (DDE or OPC) altogether. Once you go this route, you eliminate the evil COM/DCOM layer that is the problem. Ron Gage has a web site (google for it) with source code in C++ (easily rewritten in any other language) plus pointers to the DF-1 manual from Rockwell if you are doing Ethernet. Simply talk the protocol directly with the PLC. The serial port version is almost identical. You can do similar things even with *Logix processors except that you are pretty much stuck with downloading someone else's code for talking Ethernet/IP. I suggest searching around for Unix libraries since these tend to be very standard and open source code. I know that at least a couple of them exist in C, which I believe you can use under VB (full VB, so you'll have to roll an OCX if you want to use it from VBA). Unfortunately although Ethernet/IP is an "open" protocol, you have to ante up about $5000 in license fees to join the organization and gain access to the specifications and source codes. CLX does talk some form of DF-1 via the serial port. If that's your plan of attack, then there's a problem. Allen Bradley has chosen NOT to publish the new op codes for CLX processors, so you can't theoretically use DF-1. I believe you could set up the mapping back to PLC-5 registers (there's a way to do this in Logix 5000) but you probably want direct (tag-based) communication. You can still do it but you're going to need a protocol analyzer so that you can pick the packets apart and figure out what the new codes are. I've never had a CLX processor until last month so I haven't had the time or opportunity (or need) to do this myself either.

Share this post


Link to post
Share on other sites
ahh that makes a lot of sense. not a lot of help to the application but a lot of sense. I was always against using DDE, but because it was effectively free its what management wanted... OPC was what i was hoping to use, interesting that the same issues occur though. Anyway ive done all i can do, hopefully the application runs a lot better as it is not doing as much work as my destructive testing was. thanks heaps for the info and help

Share this post


Link to post
Share on other sites
out of interest you dont know of any free OPC client tools for vb6 do you?

Share this post


Link to post
Share on other sites
IF you were doing DDE with Rslinx then you have a non-lite edition of Linx and should have the RSIAutoOPC.dll or it's successor on the Installation disc. Check the RA Website for more information, but it is basically free to use when you buy RSLinx.

Share this post


Link to post
Share on other sites
awesome tried that and ive got it working well! one question though... i want to create an item like this: OPCItemIDs(1) = "[bOARD_GRADER]N7:0,L10,C10" i can then perform a syncread and read the 10 valeus into an array fine. however vb just crashes when i try and write to this item. it only like writing to singular items. is there a way to write to something like the above?

Share this post


Link to post
Share on other sites
I am not an OPC guru, but I think for write you add items to the group and then write the group.

Share this post


Link to post
Share on other sites
hmm well i can make it loop and write to a block of different items at once no problem. but making it write to one item which references a block of data doesnt work. i guess i have to create each individual integer as an individual item. thats gonna be over 500 items for me!!

Share this post


Link to post
Share on other sites
It has been a while but this is the basic, NumberOfItems starts at 1 not 0. If a good portion of items is at the bit level, I would combine them into integers and read and or write the integer, and break it back down or assemble the integers within the VB app. WriteDataGroup.SyncWrite(NumberOfItems, SyncItemServerHandles, Values, Errors)

Share this post


Link to post
Share on other sites
For what it's worth, I've been dealing with various weird RSLynx problems by upgrading RSLynx to Ver 2.54. I had lost several tags, lost the ability to connect via PCMK, lost a couple of paths in Topuc Configuration, completely lost EDS files for PLC5/40's, and several other weird problems. I've upgraded all the workstations to 2.54. The previous tech had loaded different versions ranging from 2.31 to 2.50. Now all my communication problems seem to be resolved.

Share this post


Link to post
Share on other sites
You are attempting to use the array trick. OPC does not have a defined standard for arrays. Instead, you are relying on a trick where most OPC vendors support something that works very similar to arrays. The object comes across as a binary object and the OPC client allows you to assign it to an array and it gets interpreted like an array, but it's not really an array at all (from the OPC point of view). So reading the data works just fine because everyone agrees on what is going on except the OPC Foundation. Writing is another matter. To write, you have to push the whole thing back out as a binary object. It might be possible to do so but most of the time, I can't get it to work. The only safe way to do so is to write individual objects. Fortunately OPC lets you do mass updates of several objects at once (a whole group) so this doesn't have to be as slow as it sounds.

Share this post


Link to post
Share on other sites
Ive managed to get this all working. Block writes, reads, anything under the sun. but i have a problem someone might be able to point me in the right direction... I get no error feedback from the RSlinx server when no PLC is connected. ie i can create my group, connect to the opc server and everything fine, and when i perform writes and reads, i get no indication of an error. ie for the call: ConnectedGroup.AsyncRead index, SyncItemServerHandles, SyncItemServerErrors, 0, 0 SyncItemServerErrors(1) is 0, indicating everything is ok. I need to implement some error trapping so i know if the PLC is recieving the data or not??

Share this post


Link to post
Share on other sites
I wouldn't recommend binary either, although the simple way around that with out the problems, is to do integers, with the 1100 that is 16 bits, for one read or one write, within the VB break the integer down into the bits to read or assemble the bits and then write. When you declare each Item within the Group and you want to write or read multiples "WriteDataGroup.SyncWrite(NumberOfItems, SyncItemServerHandles, Values, Errors)" The Number of Items is just as it sounds, the starting point is the SyncItemServerHandles. This way there is No OPC manipluation. I can find the VB.Net code to break down integers into a binary if you need, just let me know.

Share this post


Link to post
Share on other sites
Hehehe. Yep, it's the old broken RS-Linx OPC implementation. The best part is that if you keep trying to get it to work, eventually it will even overflow Windows buffers and simply seize up until you close/reopen your connection to the OPC server. It even makes sure to keep sending you old stale data with no "data bad" bits indicating a problem. Rockwell does a whole lot of hand waving about how it's not a bug but a feature on this point but just like with Windows "features", I fail to grok how this can be the case. The secret is to check the "@IsPresent" item. A quick search through the Rockwell website will give you information on a whole bunch of status indicators that are built into the OPC server but will never BROWSE (so you can't find them the obvious way). Also, make sure that you recheck this bit a couple times before you declare it hopeless because if even one packet gets garbled, it will pretend that the PLC is totally out to lunch until it gets a successful retry. I was forced into going with OPC with ControlLogix with Cimplicity HMI. To get around the broken implementation of RS-Linx OPC, I had to create two "devices". One monitors @IsPresent tags. The other one is the "real" device, one per PLC. Then through some secret arcane commands (and the instructions from GE Fanuc of course are not quite correct), I have to monitor the @IsPresent tags and purposely enable/disable the real "devices". If I don't do this, eventually when OPC locks up (Windows buffer overflow), I have to totally shut down either RS-Linx or Cimplicity to restore communication to the PLC even if it's running! Edited by paulengr

Share this post


Link to post
Share on other sites
Take a look at your RSLinx Error Log. We've found that if this reaches 1000 entries we start to have DDE/OPC troubles. Routinely clearing the log circumnavigates this issue.

Share this post


Link to post
Share on other sites
ok not quite sure i understand, do i add the "@IsPresent" as an OPC item just as for all my other items i am using. then read this every so often to see what the value is? This would work for me, I could check it once every loop in my code to make sure PLC is happy... correct me if im wrong?

Share this post


Link to post
Share on other sites
Yes and no. Yes, read it periodically. It will indicate at THAT MOMENT whether there is a comm problem with your PLC. HOWEVER, that's not the full story. Also, you can't necessarily rely on the first poll because the @IsPresent bit has a nasty habit of being flat out wrong. If a packet gets deleted, RS-Linx will signal an error in spite of the fact that it's just a matter of waiting for the TCP/IP retry to occur for instance.

Share this post


Link to post
Share on other sites
The @IsPresent bit will not work on a SLC type CPU (have tried on a SLC 5/03 and always returns 0), or at least I have never been able to get it to work. This may also be true on the Micrologix 1100 your using.. It does however work "OK" on PLC-5 and Logix 5000 CPU's as previously stated. Is there an equivilent Status word to use for 500 series CPU's??

Share this post


Link to post
Share on other sites
Once we get our office network back online today ill let you know how it goes (f*cking windows!!) i can always check the bit four or five times, and once it comes back as an error a few times in a row thats when i decide to flag a comms error on my system... something like that anyway, pretty primitive but what can ya do...

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0