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