I am trying to communicate between Codesys and my Window application. I have heard of PLCHandler which enables this, but use of this is not an option as its not free.
The Windows application creates a Windows Shared Memory area, lets say called "DataArea".
The Codesys application makes use of the SysShm system library.
In my Codesys application, I am then using the SysSharedMemoryOpen2() function to open this memory area, and then using the SysSharedMemoryRead() and SysSharedMemoryWrite() to get data in and out of the "DataArea" memory block.
I have read that if I have 2 Windows applications communicating via Windows Shared Memory, then I am supposed to use synchronisation to, for example, avoid one application reading data whilst the other is still writing data.
I have searched through the Codesys libraries/literature, and cannot find anything that would enable me to "lock" a Windows Shared Memory area whilst I am writing to it in Codesys, so that my Windows app can wait until the lock has been released before reading data from it (and vice-versa)
I should mention, that I have the setup "working" without any kind of locking mechanisms and it seems to work fine, but having read things about the need for synchronisation between windows applications, I am concerned that I may be missing something here????
Anyone have any experience of this kind of thing?
Thanks
Laythe
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
best way to communicate between CoDeSys and Windows is an OPC connection.
Shared memory works only, if PLC and Windows are running on the same machine (or at least in the same rack). To have access to the shared memory, you will need a driver running as part of the Windows side of communication. The driver probably has to be a special build for the PLC in use. OPC obviates all these problems.
Yes, OPC server maybe not free.
You will need an OPC client running inside the Windows side of communication. OPC is documented pretty well (available in the WWW), any Windows software developer should be able to build such a component. Then, the big advantage is to have a communication method, which works with any PLC, even with remote machines.
Regards,
Rolf
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I have wrote my own application that interfaces to the Windows Shared Memory areas which I have setup and populated with data in CodeSys, so this is not a problem. This is not really a 'driver'; its just a normal windows application.
The PLC is running on top of Windows XPe, so it is not a problem to run my driver program. I don't need them to be seperate. I am familiar with OPC and its advantages, however it is an overkill for my requirements, both in terms of cost and performance overhead.
I have this setup with my Windows application already working fine. There does not seem to be a problem, however my Windows application will be running for years once deployed (with the occasional restart), and I have not tested it for any great length of time. Therefore, the question was, do I need to protect memory access to the Windows Shared Areas, and if so how?
I can do this protection in my application via the normal semaphore etc protection mechanisms, but I cannot find anything in CodeSys which will avoid the CodeSys application reading data from a Windows Shared Memory area whilst I am still writing data into the memory block from my Windows application.
I guess I am looking for a Codesys library that allows me to access the Windows semaphores etc?
Thanks
Laythe
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Create a shared memory in a .NET application with the kernel32 function "CreateFileMapping". And now I want to read or write to this memory in CoDeSys.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Ok, sounds similar to what I have got setup. In my case I have seperate memory areas, either for reading or writing.
For Reading data:
  //------------------------------------------------------------------------------------------------------
  //Getahandletothesharedwindowsmemoryarea
  //------------------------------------------------------------------------------------------------------
  IF(hDriverToCodeSys=RTS_INVALID_HANDLEORmWindowsShmInitialisationError=TRUE )THEN
    hDriverToCodeSys :=SysSharedMemoryOpen2(dbName, 0, ADR(dbSizeBytes), ADR(rxResult)); Â
    IF(hDriverToCodeSys=RTS_INVALID_HANDLE)THEN
      mWindowsShmInitialisationError :=TRUE;
    ELSE
      mWindowsShmInitialisationError :=FALSE; Â
    END_IF
  END_IF
  mTmrWindowsShmInitialisationErrorTimeout(IN :=mWindowsShmInitialisationError, PT :=MB_TIMEOUT);
  mWindowsShmInitialisationErrorTimeout :=mTmrWindowsShmInitialisationErrorTimeout.Q;
 Â
  //------------------------------------------------------------------------------------------------------
  //Ifwehavegotahandletothesharedmemoryarea, thenreaddatafromit
  //------------------------------------------------------------------------------------------------------
  IF(mWindowsShmInitialisationError=FALSE)THEN Â
    rxBytesRead :=SysSharedMemoryRead(hDriverToCodeSys, 0, rxBufferPointer, dbSizeBytes, ADR(rxResult)); Â
    IF(rxBytesRead<>dbSizeBytes)THEN
      mWindowsShmReadError :=TRUE;
    ELSIF(rxBytesRead=dbSizeBytes)THEN     Â
      mWindowsShmReadError :=FALSE;
    END_IF
  END_IF
  mTmrWindowsShmReadErrorTimeout(IN :=mWindowsShmReadError, PT :=MB_TIMEOUT);
  mWindowsShmReadErrorTimeout :=mTmrWindowsShmReadErrorTimeout.Q;
  //------------------------------------------------------------------------------------------------------
  //ExtractRawbytebufferdatainDataBlockwordarray
  //Note. DonotjustdothisifrxDataOK=TRUEasthenwewillnotbeabletore-establishcomms
  //afteregarollingcounttimeout!
  //------------------------------------------------------------------------------------------------------
  FORwordIter:=0TO(dbSizeBytes/2)-1BY1DO Â
    //GetByte1value
    byteValue1 :=rxBufferPointer[wordIter*2];
    byteValue2 :=rxBufferPointer[(wordIter*2)+1];
   Â
    //Wordvalue=byteValue1|(byteValue2<<8)
    wordValue :=byteValue1;
    wordValue :=wordValueORSHL(byteValue2,8);
   Â
    //AssignDBwordvalue
    rxDBBufferPointer[wordIter] :=wordValue;   Â
  END_FOR;
 Â
For writing data:
  //------------------------------------------------------------------------------------------------------
  //Getahandletothesharedwindowsmemoryarea
  //------------------------------------------------------------------------------------------------------
  IF(hCodeSysToDriver=RTS_INVALID_HANDLEORmWindowsShmInitialisationError=TRUE)THEN
    hCodeSysToDriver :=SysSharedMemoryOpen2(dbName, 0, ADR(dbSizeBytes), ADR(txResult));
    IF(hCodeSysToDriver=RTS_INVALID_HANDLE)THEN
      mWindowsShmInitialisationError :=TRUE;
    ELSE
      mWindowsShmInitialisationError :=FALSE; Â
    END_IF
  END_IF
  mTmrWindowsShmInitialisationErrorTimeout(IN :=mWindowsShmInitialisationError, PT :=MB_TIMEOUT);
  mWindowsShmInitialisationErrorTimeout :=mTmrWindowsShmInitialisationErrorTimeout.Q;
 Â
  //------------------------------------------------------------------------------------------------------
  //Ifwehavegotahandletothesharedmemoryarea, thenwritedatatoit
  //------------------------------------------------------------------------------------------------------
  IF(mWindowsShmInitialisationError=FALSE)THEN Â
   Â
    //CopyBlockwordarrayintoTxByteBuffer
    FORwordIter:=0TO(dbSizeBytes/2)-1BY1DO Â
     Â
      //GetthevalueofthecurrentwordintheDB
      wordValue :=txDBBufferPointer^;
     Â
      //Extractwordvaluefromtwoconsecutivebytesinthetxbuffer
      byteValue1 :=WORD_TO_BYTE(wordValueAND255);
      byteValue2 :=WORD_TO_BYTE(SHR(wordValue,8)AND255);
     Â
      //Copythebytesintothetxbytebuffer
      txBuffer[(wordIter*2)] :=byteValue1;
      txBuffer[(wordIter*2)+1] :=byteValue2;
   Â
      //Nextword Â
      txDBBufferPointer :=txDBBufferPointer+2;
    END_FOR;   Â
 Â
    //Writethedata
    txBytesWrote :=SysSharedMemoryWrite(hCodeSysToDriver, 0, txBufferPointer, dbSizeBytes, ADR(txResult)); Â
    IF(txBytesWrote<>dbSizeBytes)THEN
      mWindowsShmWriteError :=TRUE;
    ELSIF(txBytesWrote=dbSizeBytes)THEN     Â
      mWindowsShmWriteError :=FALSE;
    END_IF
  END_IF Â
  mTmrWindowsShmWriteErrorTimeout(IN :=mWindowsShmWriteError, PT :=MB_TIMEOUT);
  mWindowsShmWriteErrorTimeout :=mTmrWindowsShmWriteErrorTimeout.Q; Â
These are just snippets, but should hopefully be helpful.
Cheers
Laythe
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hello,
I am trying to communicate between Codesys and my Window application. I have heard of PLCHandler which enables this, but use of this is not an option as its not free.
The Windows application creates a Windows Shared Memory area, lets say called "DataArea".
The Codesys application makes use of the SysShm system library.
In my Codesys application, I am then using the SysSharedMemoryOpen2() function to open this memory area, and then using the SysSharedMemoryRead() and SysSharedMemoryWrite() to get data in and out of the "DataArea" memory block.
I have read that if I have 2 Windows applications communicating via Windows Shared Memory, then I am supposed to use synchronisation to, for example, avoid one application reading data whilst the other is still writing data.
I have searched through the Codesys libraries/literature, and cannot find anything that would enable me to "lock" a Windows Shared Memory area whilst I am writing to it in Codesys, so that my Windows app can wait until the lock has been released before reading data from it (and vice-versa)
I should mention, that I have the setup "working" without any kind of locking mechanisms and it seems to work fine, but having read things about the need for synchronisation between windows applications, I am concerned that I may be missing something here????
Anyone have any experience of this kind of thing?
Thanks
Laythe
Hello,
best way to communicate between CoDeSys and Windows is an OPC connection.
Shared memory works only, if PLC and Windows are running on the same machine (or at least in the same rack). To have access to the shared memory, you will need a driver running as part of the Windows side of communication. The driver probably has to be a special build for the PLC in use. OPC obviates all these problems.
Yes, OPC server maybe not free.
You will need an OPC client running inside the Windows side of communication. OPC is documented pretty well (available in the WWW), any Windows software developer should be able to build such a component. Then, the big advantage is to have a communication method, which works with any PLC, even with remote machines.
Regards,
Rolf
Hi,
Thanks for the reply.
I have wrote my own application that interfaces to the Windows Shared Memory areas which I have setup and populated with data in CodeSys, so this is not a problem. This is not really a 'driver'; its just a normal windows application.
The PLC is running on top of Windows XPe, so it is not a problem to run my driver program. I don't need them to be seperate. I am familiar with OPC and its advantages, however it is an overkill for my requirements, both in terms of cost and performance overhead.
I have this setup with my Windows application already working fine. There does not seem to be a problem, however my Windows application will be running for years once deployed (with the occasional restart), and I have not tested it for any great length of time. Therefore, the question was, do I need to protect memory access to the Windows Shared Areas, and if so how?
I can do this protection in my application via the normal semaphore etc protection mechanisms, but I cannot find anything in CodeSys which will avoid the CodeSys application reading data from a Windows Shared Memory area whilst I am still writing data into the memory block from my Windows application.
I guess I am looking for a Codesys library that allows me to access the Windows semaphores etc?
Thanks
Laythe
Hi,
do you have a runnable application?
Can you be a bit more specific?
Cheers
Laythe
I want to try the following scenario.
Create a shared memory in a .NET application with the kernel32 function "CreateFileMapping". And now I want to read or write to this memory in CoDeSys.
Ok, sounds similar to what I have got setup. In my case I have seperate memory areas, either for reading or writing.
For Reading data:
For writing data:
These are just snippets, but should hopefully be helpful.
Cheers
Laythe