Hi Guys,

Attached is a git patch file.

I tested all of the Modbus function codes via RTU serial from 600-115K baud. Tested link recovery etc.

I can't kill it and comm  errors are now very rare.

I dropped the 300 baud setting since some crazy errors showed up that did not exist at higher baud rates. I doubt that 300 baud will be missed.

Also tested Modbus TCP with all Modbus function codes. I believe it works as it did previously.

Altered the Modbus setting config page to more correctly identify functionality.

The manual page for Classic ladder should be corrected as the default Modbus TCP port is 502, not 9502 as it says in the docs.

I had no problem running Modbus TCP via either port.

Because I removed all hard coded timers, the Modbus Com thread can now put significant load on the CPU if run without either a delay after transmit or an inter transaction delay.

At 38,400 baud on a Celeron dual core 2 ghz cpu the cpu loading could be noticably affected by the Modbus thread. I think I will use a 25 ms inter transaction delay in my next application just to reduce CPU loading.

At 38,400 baud a 5 word register read seems to take 20-25 ms with a Siemens S7-200 PLC.

Dave Cole
>From 8d771ca4f3916e1ab1d92e6f6ef7c4b520fa54ea Mon Sep 17 00:00:00 2001
From: Dave Cole <d...@colecontrols.com>
Date: Tue, 25 May 2010 18:05:37 -0400
Subject: [PATCH] Altered Modbus RTU code to improve comm link reliability, 
speed of transactions

Modifications removed tuning requirement to get Modbus to run without errors.
Removed hardcoded time delays.  Dropped 300 baud setting from the option list.
Altered Modbus settings page to reflect actual functionality.
Dave Cole 5/25/2010
---
 src/hal/classicladder/config_gtk.c             |   16 ++-
 src/hal/classicladder/protocol_modbus_master.c |   71 ++++++----
 src/hal/classicladder/serial_common.h          |    2 +-
 src/hal/classicladder/serial_linux.c           |  173 +++++++++++++++++++-----
 src/hal/classicladder/socket_modbus_master.c   |  134 ++++++++++++-------
 5 files changed, 280 insertions(+), 116 deletions(-)
 mode change 100755 => 100644 src/hal/classicladder/socket_modbus_master.c

diff --git a/src/hal/classicladder/config_gtk.c 
b/src/hal/classicladder/config_gtk.c
index a7fc248..76011c2 100644
--- a/src/hal/classicladder/config_gtk.c
+++ b/src/hal/classicladder/config_gtk.c
@@ -21,6 +21,9 @@
 /* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 //Chris Morley July 08
 
+/* Modified by Dave Cole 5/24/10 to increase serial receive reliability, 
+   correct errors in EMC2 implementation version*/
+
 #include <gtk/gtk.h>
 #include <stdio.h>
 #include <string.h>
@@ -40,8 +43,6 @@
 #endif
 GtkWidget *LabelParam[ NBR_OBJECTS ],*ValueParam[ NBR_OBJECTS ];
 
-
-
 #define NBR_IO_PARAMS 6
 GtkWidget *InputParamEntry[ NBR_INPUTS_CONF ][ NBR_IO_PARAMS ];
 GtkWidget *InputDeviceParam[ NBR_INPUTS_CONF ];
@@ -56,7 +57,7 @@ GtkWidget *OutputFlagParam[ NBR_OUTPUTS_CONF ];
 // ModbusReqType must be in the same order as MODBUS_REQ_ in 
protocol_modbus_master.h
 static char * ModbusReqType[] = {"Read_discrete_INPUTS  fnctn- 2", 
"Write_COIL(S)           fnctn-5/15", "Read_Input_REGS     fnctn- 4", 
"Write_hold_REG(S)    fnctn-6/16", "Read_COILS              fnctn- 
1","Read_HOLD_REG      fnctn- 3","Slave_echo              fnctn- 8",NULL };
 #define NBR_MODBUS_PARAMS 6
-static char * SerialSpeed[] = { "300", "600", "1200", "2400", "4800", "9600", 
"19200", "38400", "57600", "115200", NULL };
+static char * SerialSpeed[] = { /*"300",*/ "600", "1200", "2400", "4800", 
"9600", "19200", "38400", "57600", "115200", NULL }; // Dave Cole
 #define NBR_SERIAL_SPEED 9
 static char * PortName[] = {"IP 
port","/dev/ttyS0","/dev/ttyS1","/dev/ttyS2","/dev/ttyS3","/dev/ttyUSB0","/dev/ttyUSB1",NULL
 };
 #define NBR_PORT_NAME 6
@@ -633,18 +634,19 @@ GtkWidget * CreateModbusComParametersPage( void )
                                 
                                break;
                         case 2:
-                               sprintf( BuffLabel, "After transmit pause - 
milliseconds" );
+                               sprintf( BuffLabel, "Dwell between Xmt and 
Rcv-millisecs" );
                                sprintf( BuffValue, "%d", 
ModbusTimeAfterTransmit );
                                break;
                        
                        case 3:
-                               sprintf( BuffLabel, "After receive pause - 
milliseconds" );
+                               sprintf( BuffLabel, "Dwell between 
Transactions-millisecs" );
                                sprintf( BuffValue, "%d", ModbusTimeInterFrame 
);
                                break;
                        case 4:
-                               sprintf( BuffLabel, "Request Timeout length - 
milliseconds" );
+                               sprintf( BuffLabel, "Request Timeout 
length-millisecs" );
                                sprintf( BuffValue, "%d", ModbusTimeOutReceipt 
);
                                break;
+
                        case 5:
                                sprintf( BuffLabel, "Use RTS to send" );
                                sprintf( BuffValue, "%d", 
ModbusSerialUseRtsToSend );
@@ -987,7 +989,7 @@ void OpenConfigWindowGtk( void )
        if ( !GTK_WIDGET_VISIBLE( ConfigWindow ) )
        { 
                gtk_widget_show (ConfigWindow);
-               MessageInStatusBar("Openned Configuration window. Press again 
to update changes and close");
+               MessageInStatusBar("Opened Configuration window. Press again to 
update changes and close");
 #ifdef GTK2
                gtk_window_present( GTK_WINDOW(ConfigWindow) );
 #endif
diff --git a/src/hal/classicladder/protocol_modbus_master.c 
b/src/hal/classicladder/protocol_modbus_master.c
index b56d4af..185f0c7 100755
--- a/src/hal/classicladder/protocol_modbus_master.c
+++ b/src/hal/classicladder/protocol_modbus_master.c
@@ -25,6 +25,9 @@
 /* License along with this library; if not, write to the Free Software */
 /* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
+/* Modified by Dave Cole 5/24/10 to increase serial receive reliability, 
+   correct errors in EMC2 implementation version*/
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -380,35 +383,47 @@ int GetModbusResponseLenghtToReceive( void )
        if ( CurrentReq!=-1 )
        {
                int NbrEles = ModbusMasterReq[ CurrentReq ].NbrModbusElements;
-               LgtResp++;//for function code
+               //  LgtResp++;//for function code  where does LgtResp come 
from????  
                switch( CurrentFuncCode )
                {
                                case MODBUS_FC_READ_INPUTS:
                                 case MODBUS_FC_READ_COILS:
                                 // 1 byte for count of data bytes returned 
                                 // 1 byte for 8 coils if number of coils is 
not evenly divisable by 8 add another byte
-                                       NbrRealBytes = (NbrEles+7)/8;
-                                       LgtResp++;
-                                       LgtResp = LgtResp + NbrRealBytes;
+                                   NbrRealBytes = (NbrEles+7)/8;
+                                       LgtResp = 2 + NbrRealBytes;
                                         break;
-                               case MODBUS_FC_READ_INPUT_REGS:
-                               case MODBUS_FC_READ_HOLD_REGS:
+
+                               case MODBUS_FC_READ_INPUT_REGS: //4  was the 
same as function 3 but errored so took out two bytes
+                                // 2 bytes per register for data returned and 
1 byte for number of registers (max 125)
+                                       LgtResp = (NbrEles*2)+2 ;
+                                       break;
+
+
+                               case MODBUS_FC_READ_HOLD_REGS: //3
                                 // 2 bytes per register for data returned and 
1 byte for number of registers (max 125)
-                                       LgtResp = LgtResp + (NbrEles*2)+1;
+                                       LgtResp = (NbrEles*2)+1 +1 ;
+                                       break;
+
+                               case MODBUS_FC_FORCE_COIL:       //5 force 
single coil
+                                   LgtResp =  5;
+                                       break;
+
+                               case MODBUS_FC_FORCE_COILS:  //14
+                                   LgtResp =  2;
                                        break;
-                               case MODBUS_FC_FORCE_COIL:                      
                
-                               case MODBUS_FC_FORCE_COILS:
-                               case MODBUS_FC_WRITE_REG:
+
+                               case MODBUS_FC_WRITE_REG:  //6
                                 // 2 bytes for address 2 for data
-                                       LgtResp = LgtResp + LgtResp +4; 
+                                       LgtResp = 5;
                                        break;
-                               case MODBUS_FC_WRITE_REGS:
+                               case MODBUS_FC_WRITE_REGS:  //16
                                 // 2 bytes for address start and 2 bytes for 
number of registers 
-                                       LgtResp = LgtResp + LgtResp +4; 
+                                       LgtResp = 2 + 2 +1; 
                                        break;
                                case MODBUS_FC_DIAGNOSTICS://modbus function 8
                                 // 2 bytes for sub code 2 for data
-                                       LgtResp = LgtResp + LgtResp +4; 
+                                       LgtResp = 2 + 2; 
                                        break;
                                 default:
                                         printf("INFO CLASSICLADDER-   MODBUS 
function code not reconized");
@@ -514,7 +529,7 @@ int ModbusMasterAsk( unsigned char * SlaveAddressIP, 
unsigned char * Question )
                if ( LgtAskFrame>0 )
                {
                        if ( ModbusSerialPortNameUsed[ 0 ]!='\0' )
-                       {
+                       {    // modbus RTU
                                unsigned short CalcCRC;
                                LgtAskFrame = LgtAskFrame+OffsetHeader;
                                
@@ -526,7 +541,7 @@ int ModbusMasterAsk( unsigned char * SlaveAddressIP, 
unsigned char * Question )
                                Question[ LgtAskFrame++ ] = (unsigned 
char)CalcCRC;
                        }
                        else
-                       {
+                       {   // modbus tcp
                                // add IP specific header
                                InvoqIdentifHeaderIP++;
                                if ( InvoqIdentifHeaderIP>65535 )
@@ -582,11 +597,11 @@ char TreatModbusMasterResponse( unsigned char * Response, 
int LgtResponse )
        if ( CurrentReq!=-1 )
        {
                char FrameOk = FALSE;
-               // start of the usefull frame depend if serial or IP
+               // start of the useful frame depend if serial or IP
                int OffsetHeader = LGT_MODBUS_IP_HEADER;
                if ( LgtResponse > 0 )
                {
-                       // Modbus/RTU on serial used ?
+                       // Modbus/RTU on serial used
                        if ( ModbusSerialPortNameUsed[ 0 ]!='\0' )
                        {
                                unsigned short CalcCRC = CRC16( &Response[ 0 ], 
LgtResponse-2 ) ;
@@ -605,7 +620,7 @@ char TreatModbusMasterResponse( unsigned char * Response, 
int LgtResponse )
                                }
                        }
                        else
-                       {
+                       {   //modbus tcp
                                // verify if transaction identifier correspond
                                int TransId = (Response[ 0 ]<<8) | Response[ 1 
];
                                if ( TransId==InvoqIdentifHeaderIP )
@@ -614,7 +629,7 @@ char TreatModbusMasterResponse( unsigned char * Response, 
int LgtResponse )
                } 
        
                if ( FrameOk )
-               {
+               {  // FrameOk, now check contents of frame
                        // if valid frame => advance to next request
                        if ( TreatPureModbusResponse( &Response[ OffsetHeader 
], LgtResponse-OffsetHeader)>=0 )
                        {
@@ -623,28 +638,32 @@ char TreatModbusMasterResponse( unsigned char * Response, 
int LgtResponse )
                                RepOk = TRUE;
                        }
                        else
-                       {
+                       {   // bad response from slave 
                                printf("ERROR CLASSICLADDER-   MODBUS-INCORRECT 
RESPONSE RECEIVED FROM SLAVE!!!\n");
                                ErrorCnt++;
                        }
                }
                else
-               {
+               {   // Frame not ok - CRC failed 
                        printf("ERROR CLASSICLADDER-   MODBUS-LOW LEVEL ERROR 
IN RESPONSE!!!\n");
                         //set error coil 0 on 'MODBUS ERROR'
                         
                        ErrorCnt++;
                }
-               if ( ErrorCnt>=3 )
+
+               if ( ErrorCnt>=3 )  // Make 3 attempts with a request, if it 
fails 3 times, move on to the next request in table
                {
                        ErrorCnt = 0;
-                       FindNextReqFromTable( );
+                       FindNextReqFromTable( );  
                }
 
                
        }
-        //set error coil (%E0) as apprioprate  
-        if (RepOk==TRUE) {    WriteVar( VAR_ERROR_BIT, 0, FALSE);   }else{    
WriteVar( VAR_ERROR_BIT, 0, TRUE);   }
+        //set error coil (%E0) as apprioprate  if Modbus errors Can be 
monitored via RLL to take safe action on Modbus error
+        if (RepOk==TRUE) 
+               {   WriteVar( VAR_ERROR_BIT, 0, FALSE);   }else{    WriteVar( 
VAR_ERROR_BIT, 0, TRUE);   
+                       SerialFlush( );  // Flush input buffer when a faulty 
frame or bad CRC is received to get messages back into sync
+               }
        return RepOk;
 }
 
diff --git a/src/hal/classicladder/serial_common.h 
b/src/hal/classicladder/serial_common.h
index 56c7ac8..122c647 100755
--- a/src/hal/classicladder/serial_common.h
+++ b/src/hal/classicladder/serial_common.h
@@ -3,6 +3,6 @@ char SerialOpen( char * SerialPortName, int Speed );
 void SerialClose( );
 void SerialSend( char *Buff, int BuffLength );
 void SerialSetResponseSize( int Size, int TimeOutResp );
-int SerialReceive( char * Buff, int MaxBuffLength );
+int SerialReceive( char * Buff, int Framelength, int TimeOutResp  );
 void SerialFlush( void );
 
diff --git a/src/hal/classicladder/serial_linux.c 
b/src/hal/classicladder/serial_linux.c
index 62a036f..23b75ca 100755
--- a/src/hal/classicladder/serial_linux.c
+++ b/src/hal/classicladder/serial_linux.c
@@ -21,6 +21,9 @@
 /* License along with this library; if not, write to the Free Software */
 /* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
+/* Modified by Dave Cole 5/24/10 to increase serial receive reliability, 
+   correct errors in EMC2 implementation version*/
+
 #include <termios.h>
 #include <stdio.h>
 #include <string.h>
@@ -29,6 +32,7 @@
 #include <sys/signal.h>
 #include <sys/types.h> 
 #include <sys/ioctl.h>
+#include <errno.h>       //  Added 
 
 #include "serial_common.h"
 extern int ModbusSerialUseRtsToSend;
@@ -37,8 +41,8 @@ extern int ModbusSerialDataBits;   // Number of data bits (7, 
6, 7, 8)
 extern int ModbusSerialStopBits;   // Number of stop bits (1 or 2)
 extern int ModbusSerialParity;      // Parity (00 = NONE, 01 = Odd, 02 = Even, 
03 = Mark, 04 = Space)
 
-int SerialSpeed[ ] = { 300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 
115200, 0 };
-int SerialCorres[ ] = { B300, B600, B1200, B2400, B4800, B9600, B19200, 
B38400, B57600, B115200, 0 };
+int SerialSpeed[ ] = { /*300,*/ 600, 1200, 2400, 4800, 9600, 19200, 38400, 
57600, 115200, 0 };  // remove 300 baud
+int SerialCorres[ ] = { /*B300,*/ B600, B1200, B2400, B4800, B9600, B19200, 
B38400, B57600, B115200, 0 };
 
 char PortIsOpened = 0;
 int fd;
@@ -47,6 +51,8 @@ long STOPBITS;
 long PARITYON;
 long PARITY;
 
+
+
 struct termios oldtio;
 struct termios newtio;
 
@@ -178,7 +184,9 @@ void SerialSend( char *Buff, int BuffLength )
                }
                if ( ModbusDebugLevel>=2 )
                        printf("Serial writing...\n");
+
                write(fd,Buff,BuffLength);
+
                if ( ModbusDebugLevel>=2 )
                        printf("Writing done!\n");
                if ( ModbusSerialUseRtsToSend )
@@ -193,46 +201,147 @@ void SerialSend( char *Buff, int BuffLength )
 void SerialSetResponseSize( int Size, int TimeOutResp )
 {
        if ( PortIsOpened )
-       {
-               newtio.c_cc[VMIN] = Size; //Nbr chars we should receive;
-               newtio.c_cc[VTIME] = TimeOutResp/100; // TimeOut in 0.1s
-//             tcflush(fd, TCIFLUSH);
+       {         // "fd" (file device) control for serial port per termios 
docs 
+           newtio.c_cc[VMIN] = Size; //Nbr chars we should receive  (This 
doesn't seem to work, read returns immediately, regardless)
+               newtio.c_cc[VTIME] = TimeOutResp/100; // TimeOut in 0.1s (Read 
returns immediately and doesn't block as it should? )
                if ( ModbusDebugLevel>=2 )
                        printf("Serial config...\n");
-               tcsetattr(fd,TCSANOW,&newtio);
+               tcsetattr(fd,TCSANOW,&newtio);// TCSANOW - means make changes 
immediately
        }
 }
 
-int SerialReceive( char * Buff, int MaxBuffLength )//, int TimeOutResp )
+
+
+int SerialReceive( char * Buff, int framelength , int TimeOutResp )
 {
-       int NbrCarsReceived = 0;
+
+       int select_ret;  //added 
+       int read_ret;
+       char *p_response;
+       int size_to_read;
+       int num_rec;
+       if ( ModbusDebugLevel>=2 )
+               printf("Start of SerialReceive() \n");
+
        if ( PortIsOpened )
        {
 
-// the select is used it no char at all is received (else read() block...)
-int recep_descrip;
-fd_set myset;
-struct timeval tv;
-FD_ZERO( &myset);
-// add descrip to survey and set time-out wanted !
-FD_SET( fd, &myset );
-tv.tv_sec = 0; //seconds
-tv.tv_usec = newtio.c_cc[VTIME]*100 *1000; //micro-seconds
-if ( ModbusDebugLevel>=3 )
-       printf("select() for serial reading...\n");
-recep_descrip = select( 16, &myset, NULL, NULL, &tv );
-if ( recep_descrip>0 )
-{
-               if ( ModbusDebugLevel>=2 )
-                       printf("Serial reading...\n");
-                       NbrCarsReceived = read(fd,Buff,MaxBuffLength);
-               if ( ModbusDebugLevel>=2 )
-                       printf("%d chars found\n", NbrCarsReceived);
-}
+               fd_set myset;  // does a struct type function to create myset ??
+               struct timeval tv; // make a timer struct called tv
+
+               if ( ModbusDebugLevel>=3 )
+                       printf("First select() \n"); // checks on the status of 
the file "fd"
+
+               //  Wait for data routine               
+               FD_ZERO( &myset);  // clears a set
+               FD_SET( fd, &myset ); // adds a file descriptor to myset called 
fd
+               tv.tv_sec = 0; //seconds
+               tv.tv_usec = TimeOutResp *1000; //micro-seconds                 
        
+               while ((select_ret = select(fd+1, &myset, NULL, NULL, &tv)) == 
-1) 
+               {       
+                       if (errno == EINTR) 
+                               {                                       
+
+                               if ( ModbusDebugLevel>=2 )
+                                       printf("A non blocked signal was caught 
in wait 1\n");          
+                                                                       
+                               FD_ZERO(&myset);                        
//Necessary after an error                              
+                               FD_SET(fd, &myset);     
+
+                               if ( ModbusDebugLevel>=2 )      
+                                       printf("errno == EINTR in wait 1\n");   
                
+                               }       
+               }                                                               
                
+                       if (select_ret == 0)
+                               {
+                               if ( ModbusDebugLevel>=2 )
+                                       printf("Comm timeout on select - in 
wait 1\n"); 
+                               return  0;
+                               }                                               
+               // end of wait for data routine   
+
+               num_rec = 0;
+               size_to_read = framelength;
+               p_response = Buff;
+
+         while (select_ret)    // select_ret is >1 or true if select() has 
found chars are in buffer
+               {
+                       if ( ModbusDebugLevel>=2 )
+                         printf("size to read = %i\n",size_to_read);
+
+                         read_ret = read(fd, p_response, size_to_read);
+
+                       if (read_ret == -1) 
+                               {     // read failed 
+                                       if ( ModbusDebugLevel>=2 )
+                                                printf("Read Port failure\n"); 
+                                 return 0;
+                               } 
+                       else 
+                               {    // read was good
+                                 
+                                 num_rec += read_ret;  //Sums bytes received
+
+                               if ( ModbusDebugLevel>=2 )
+                                       printf("total chars read = %i, chars 
read this time = %i\n", num_rec, read_ret);
+
+                                       p_response = &(p_response[read_ret]);  
// Moves the pointer to receive other datas
+                                       size_to_read = framelength - num_rec; 
+
+                               }
+
+                       if (size_to_read > 0) 
+                               {
+
+                                       if ( ModbusDebugLevel>=2 )      
+                                               printf("More data to get during 
this read function\n");
+                       
+                                       //  Wait for data routine again if not 
all of it was received during the first read             
+                                       FD_ZERO( &myset);  // clears a set
+                                       FD_SET( fd, &myset ); // adds a file 
descriptor to myset called fd
+                                       tv.tv_sec = 0; //seconds
+                                       tv.tv_usec = TimeOutResp *1000; 
//micro-seconds         
+
+                                       while ((select_ret = select(fd+1, 
&myset, NULL, NULL, &tv)) == -1) 
+                                       {       
+                                               if (errno == EINTR) 
+                                               {                               
        
+
+                                                       if ( 
ModbusDebugLevel>=2 )
+                                                               printf("A non 
blocked signal was caught in wait 2 \n");         
+
+                                               // Necessary after an error     
                                
+                                               FD_ZERO(&myset);                
                                        
+                                               FD_SET(fd, &myset);     
+
+                                                       if ( 
ModbusDebugLevel>=2 )
+                                                               printf("errno 
== EINTR in wait 2\n");   
+                                               } 
+                                       }                                       
                                        
+       
+                                       if (select_ret == 0)
+                                               {
+                                               if ( ModbusDebugLevel>=2 )
+                                               printf("Comm timeout on select 
in wait 2\n");   
+                                               return  0;
+                                               }       
+                                       // end of wait for data routine
+
+                               } 
+                               else 
+                               {
+                                 /* All chars are received */
+                                 select_ret = 0;
+                               }
+               }
+
+                 /* OK */
+                 return framelength;
        }
-       return NbrCarsReceived;
 }
 
+
+
 void SerialFlush( void )
 {
        if ( PortIsOpened )
@@ -240,8 +349,8 @@ void SerialFlush( void )
                if ( ModbusDebugLevel>=2 )
                        printf("Serial flush all!\n");
                tcflush( fd, TCIOFLUSH );
-               usleep( 250*1000 );
-               tcflush( fd, TCIOFLUSH );
+       //      usleep( 250*1000 );         // doing the flush twice with a 
time delay in between
+       //      tcflush( fd, TCIOFLUSH );
        }
 }
 
diff --git a/src/hal/classicladder/socket_modbus_master.c 
b/src/hal/classicladder/socket_modbus_master.c
old mode 100755
new mode 100644
index 44bed8a..ed05dd2
--- a/src/hal/classicladder/socket_modbus_master.c
+++ b/src/hal/classicladder/socket_modbus_master.c
@@ -24,6 +24,9 @@
 /* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 // Chris Morley July 08 (EMC)
 
+/* Modified by Dave Cole 5/24/10 to increase serial receive reliability, 
+   correct errors in EMC2 implementation version*/
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -308,80 +311,111 @@ void SocketModbusMasterLoop( void )
        char AdrIP[ 30 ];
        int SizeQuestionToAsk;
        static char QuestionFrame[ 800 ];
-       int ResponseSize;
+       int ResponseSize=0;
        static char ResponseFrame[ 800 ];
         int SendResultStatus = 0;
 
-#ifdef __XENO__
-       pthread_set_name_np(pthread_self(), __FUNCTION__);
-#endif
+
+       if ( ModbusSerialPortNameUsed[ 0 ]!='\0' )   // if using Modbus RTU 
flush the receive buffer before doing he first transmit
+               SerialFlush( );
+       
 
        while( ClientSocketRunning )
        {
-// TODO: added for XENO... not found why required for now...
-// (task suspended otherwise with the watchdog, seen with dmesg!)
-// removing this next line for EMC- we don't use XENO
 
-//             DoPauseMilliSecs( 10 );
+               if (InfosGene->LadderState==STATE_RUN)
 
-               if (InfosGene->LadderState!=STATE_RUN)
-               {
-                       DoPauseMilliSecs( ModbusTimeInterFrame );
-               }
-               else
                {
                        SizeQuestionToAsk = ModbusMasterAsk( (unsigned 
char*)AdrIP, (unsigned char*)QuestionFrame );
                        if ( SizeQuestionToAsk>0 )
                        {
-                               if ( ModbusSerialPortNameUsed[ 0 ]=='\0' )
-                               {
-                                       SendResultStatus = 
SendSocketModbusMaster( AdrIP, 502, QuestionFrame, SizeQuestionToAsk );
-                               }
-                               else
-                               {
-                                       // before sending queston, set size of 
frame that will be to receive after! 
-                                       SerialSetResponseSize( 
1/*adr*/+GetModbusResponseLenghtToReceive()+2/*crc*/, ModbusTimeOutReceipt );
-                                       SerialSend( QuestionFrame, 
SizeQuestionToAsk );
+
+                               
+                               if ( ModbusSerialPortNameUsed[ 0 ]=='\0' )   
+                               {   // using Modbus TCP over Ethernet
+                                       if ( ModbusDebugLevel>=2 )
+                                               printf("Using TCP Modbus\n");
+                                       SendResultStatus = 
SendSocketModbusMaster( AdrIP, 502, QuestionFrame, SizeQuestionToAsk );         
             
+                                       if ( SendResultStatus==0 )
+                                       {
+                                               if ( ModbusTimeAfterTransmit>0 
)   // usefull for USB-RS485 dongle with TCP ??
+                                               {       
+                                                       if( ModbusDebugLevel>=3 
)
+                                                               printf("INFO 
CLASSICLADDER- after transmit delay now...%i 
milliseconds\n",ModbusTimeAfterTransmit);
+                                               DoPauseMilliSecs( 
ModbusTimeAfterTransmit );
+                                               }       
+                                       ResponseSize = 
WaitRespSocketModbusMaster( ResponseFrame, 800, ModbusTimeOutReceipt );
+                                       NbrFrames++;
+                                               if ( ResponseSize==0 )
+                                                       printf("ERROR 
CLASSICLADDER-  MODBUS NO RESPONSE (Errs=%d/%d) !?\n", ++CptErrors, NbrFrames);
+                                       }
+                                       if ( !TreatModbusMasterResponse( 
(unsigned char *)ResponseFrame, ResponseSize ) )
+                                       {
+                                               ++CptErrors;
+                                       }
+
+
+                               DoPauseMilliSecs( ModbusTimeInterFrame );
+
+
+
+
+
+
                                }
-                                if ( SendResultStatus==0 )
+                               else   // using Modbus serial RTU
                                {
-                                   if ( ModbusTimeAfterTransmit>0 )
-                                   {
-                                       // usefull for USB-RS485 dongle...
-                                       if( ModbusDebugLevel>=3 )
-                                               printf("INFO CLASSICLADDER- 
after transmit delay now...%i milliseconds\n",ModbusTimeAfterTransmit);
-                                       DoPauseMilliSecs( 
ModbusTimeAfterTransmit );
-                                   }
+                               if ( ModbusDebugLevel>=2 )                      
        
+                                       printf("Using Modbus RTU\n");
                                
-                                   if ( ModbusSerialPortNameUsed[ 0 ]=='\0' )
-                                       ResponseSize = 
WaitRespSocketModbusMaster( ResponseFrame, 800, ModbusTimeOutReceipt );
-                                   else
-                                       ResponseSize = SerialReceive( 
ResponseFrame, 800 );
-                                   NbrFrames++;
+                               // SerialFlush( );   // to flush characters in 
receive buffer before doing a send added 
+
+                               // before sending queston, set size of frame 
that will be received
+                               SerialSetResponseSize( 
1/*adr*/+GetModbusResponseLenghtToReceive()+2/*crc*/, ModbusTimeOutReceipt );
+                               SerialSend( QuestionFrame, SizeQuestionToAsk );
+
+                                       if ( ModbusTimeAfterTransmit>0 ) 
+                                               {
+                                                       if( ModbusDebugLevel>=3 
)
+                                                       printf("INFO 
CLASSICLADDER- after transmit delay now...%i 
milliseconds\n",ModbusTimeAfterTransmit);
+
+                                               DoPauseMilliSecs( 
ModbusTimeAfterTransmit ); // useful for USB to serial converter
+                                               }
+                                                                               
                        
+                                       ResponseSize = SerialReceive( 
ResponseFrame, 1/*adr*/+GetModbusResponseLenghtToReceive()+2/*crc*/, 
ModbusTimeOutReceipt );  
+                                       NbrFrames++;
+
                                    if ( ResponseSize==0 )
                                        printf("ERROR CLASSICLADDER-  MODBUS NO 
RESPONSE (Errs=%d/%d) !?\n", ++CptErrors, NbrFrames);
+
                                    if ( !TreatModbusMasterResponse( (unsigned 
char *)ResponseFrame, ResponseSize ) )
-                                   {
-                                       // trouble? => flush all (perhaps we 
can receive now responses for old asks
-                                       // and are shifted between ask/resp...)
-                                       if ( ModbusSerialPortNameUsed[ 0 
]!='\0' )
-                                               SerialFlush( );
-                                   }
-                                }
+
+
+                                       if( ModbusDebugLevel>=3 )
+                                       {
+                                       printf("INFO CLASSICLADDER- interframe 
delay now...%i milliseconds\n",ModbusTimeInterFrame);
+                                       printf("\n");  
+                                       }
+
                                DoPauseMilliSecs( ModbusTimeInterFrame );
+                               
+                                   
+                               }
                        }
-                       else
+                       else  // no question to ask - pause for 300 ms
                        {
-//                             sleep( 1 );
-                               DoPauseMilliSecs( 1000 );
+                               DoPauseMilliSecs( 50 );
                        }
                }
+               else  // not running - wait for a while and then do it again
+               {
+                       DoPauseMilliSecs( 300 );
+               }
        
-       }
-#ifndef __WIN32__
-       pthread_exit(NULL);
-#endif
+       }  // end of while
+}  // end of function
+                               
+
 
-}
 
 
-- 
1.6.3.3

------------------------------------------------------------------------------

_______________________________________________
Emc-developers mailing list
Emc-developers@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/emc-developers

Reply via email to