ControlLogix/RSLinx SDK/Unsolicited

T

Thread Starter

Tom Hornyak

The summary pretty much says it all. I've tried using both the DTL_C_CONNECT and DTL_DRIVER_OPEN call (with DTL_DRIVER_OPEN, I tried using both the TCP and AB_ETH driver) to open the driver.

I call DTL_UNSOL_PLC2MEMORY_REGISTER to set up the call back. The CL PLC is writng to address 20, doing a PLC2 style write. I've monitored both address 10 and 20 (with some PLC's I've had to divide the address by 2) with no luck.

I ran a network monitor program and TCP packets are being sent that seem to contain the data. However the unsolicited callback routine is never called.

Any help would be appreciated, esp. any special set required for the ControlLogix, or any sample code.
 
H

Hugh Pickard

Tom,<br>
The DTL_UNSOL_PLC2MEMORY_REGISTER call exists mainly for compatability with the older comms driver called Interchange and there's quite a bit of historical baggage associated with it (of which your address doubling is
one example). I've never tried using it with a ControlLogix because RSLinx provides other, less confusing, ways of doing unsolicited messages. The simple console program that follows shows how. The corresponding MSG in the ControlLogix should have the following settings:-<br>
<br>
Message type - Any type of PLC write (the example code accepts PLC-2 writes)<br>
Comms Method - CIP with source ID<br>
Source Link - N/A<br>
Dest Link - The virtual link ID set up in RSLinx<br>
Dest Node - same as the VLINK_STATION_NUMBER in the example below<br>
Path - a valid path that ends with the IP address of your PC running the program<br>
<br>
<br>
Hope this helps<br>
<br>
Hugh<br>
<br><pre>
// Simple RSLinx asynchronous unsolicited message demo
// This version uses DTL_UNSOL_VIRTUAL_LINK_REGISTER to
// register this program as a station on the VLINK virtual
// network within RSLinx. PLCs can then send messages to
// this station (the destination of the MSG instruction
// should be VLINK_STATION_NUMBER on the link number configured
// for VLINK in RSLinx).

#include <windows.h>
#include <stdio.h>
#include <dtl.h>

#define REGISTER_TIME 500L // Unsol register timeout
#define VLINK_STATION_NUMBER 7 // Station # on VLINK
#define VLINK_STATION_NAME "UNSOL" // Station name on VLINK


// Function prototypes

void errprint(unsigned long);
void DTL_CALLBACK UnsolCallback(DTSA_TYPE *, BYTE *, DWORD, DWORD);

// Main program

void main ()
{
DTL_RETVAL status; // function return value

// Initialize the Data Table Library for a maximum of 1 definition.

status = DTL_INIT( 1 );
if ( status != DTL_SUCCESS )
{
printf ("DTL_INIT %d\n",status);
errprint( status );
exit(0);
}

// There's no need to DTL_DRIVER_OPEN etc. when using VLINK for unsolicited
// messages - we just have to register as a station on VLINK.

status=DTL_UNSOL_VIRTUAL_LINK_REGISTER(UnsolCallback, 0, VLINK_STATION_NUMBER,
VLINK_STATION_NAME, REGISTER_TIME);
if( status != DTL_SUCCESS )
{
printf ("DTL_UNSOL_VIRTUAL_LINK_REGISTER %d\n",status);
errprint(status);
exit(0);
}

// Just loop forever - the callback routine does the rest
printf("Waiting for unsolicited message...");
do
Sleep(100); // do nothing in an efficient way
while(1);
}

// Callback routine
// baBuffer has the form CMD,STS,TNSL,TNSH,data,data...
// Refer to the Communication Protocol and Command set manual for details
// (Publication number 1770-6.5.16)

void DTL_CALLBACK UnsolCallback(DTSA_TYPE *dtsa, BYTE *baBuffer, DWORD dwLength,
DWORD dwCallback)
{
unsigned long i;
BYTE *p;

printf("\n\nGot One! CMD byte is %02x\n",baBuffer[0]);

// You should analyse the DTSA structure here to determine
// who sent the message. This simple example just processes all
// PLC-2 unprotected writes. See dtl.h for definition of DTSA and
// the types of structures it can hold.

if ((baBuffer[0]==8) && (dwLength>4)) // PLC-2 unprotected write?
{
for(i=0,p=baBuffer;i<dwLength;i++,p++) //print buffer
{
if (!(i%10))
printf("\n%03d: ",i);
printf("%02X ",*p);
}
DTL_MAKE_REPLY(baBuffer, 0); // Status = zero = OK
}
else
{
DTL_MAKE_REPLY(baBuffer,0x10); // Status = 0x10 = Illegal command
}
DTL_SEND_REPLY(dtsa,baBuffer,4); // send reply
}

// Print an RSLinx error

void errprint(unsigned long value)
{
char msgbuff[80];

DTL_ERROR_S(value,msgbuff,80);
printf("%s\n",msgbuff);
}
</pre>
 
Top