EPICS Controls Argonne National Laboratory

Experimental Physics and
Industrial Control System

1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  <20122013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024  Index 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  <20122013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
<== Date ==> <== Thread ==>

Subject: RE: modbus 2.4
From: Mark Rivers <[email protected]>
To: "'Pierrick M Hanlet'" <[email protected]>, "[email protected]" <[email protected]>
Date: Fri, 28 Sep 2012 19:40:39 +0000
H Pierrick,

I think there are 2 problems:

1) You configured your read ports as follows:
drvModbusAsynConfigure("read1ADDR", "RFTunerPort",0x01,0x03,0x0000,1,0,86400000,"ProportionAir")

Where drvModbusAsynConfigure is defined as:
drvModbusAsynConfigure(portName, 
                       tcpPortName,
                       slaveAddress, 
                       modbusFunction, 
                       modbusStartAddress, 
                       modbusLength,
                       dataType,
                       pollMsec, 
                       plcType);

So you have set pollMsec to a very large value (86400000).  That won't work.  The driver only reads the inputs by polling, but you are only polling once per day!  So you are getting this error:

epics> 2012/09/28 12:09:42.604 MICE-RF-TUNE-01:READVALU devAsynInt32 process read error 

because the poller has never read the inputs.


2) The asynTrace output for the serial port proves that device is sending a reply, but you are getting this error:

2012/09/28 12:13:53.566 modbusInterpose::readIt, LRC error


If we look just at the asynTrace messages from /ttys3 (because they are repeated for RFTunerPort) the reply message is the following:

3a 30 31 31 30 30 30 33 31 30 30 30 31 42 44 0d 29

In ASCII this is:
: 0 1 1 0 0 0 3 1 0 0 0 1 B D \r )

The first character of the response should be ':', so that is correct.

In Modbus ASCII the message encodes each byte as 2 ASCII characters.  Each ASCII character encodes a 4 bit nibble (0-15), and they are combined in "big-endian" order, i.e. the most significant nibble comes first.  The encoding is 0-9='0'-'9', 10-15='A'-'F'.

The next 2 bytes are combined to be the slave address, which is 0x01, which is correct.

The rest of the message should contain the following structure, followed by CR LF.
typedef struct modbusWriteMultipleResponse_str
{
    unsigned char  fcode;
    unsigned short startReg;
    unsigned short numOutput;
} PACKED_STRUCTURE modbusWriteMultipleResponse;

The next 2 bytes are combined to be the function code, which is 0x10, so this is correct.

The next 4 bytes encode the start register, which is 0x0031, which is correct.

The next 4 bytes encode the number of values written, which is 0x0001, which is correct.

The next 2 bytes encode the LRC which is 0xBD.  I suspect this is incorrect (it's hard to calculate by hand), and I think I know why.  The message is supposed to be terminated with CR (0x0d) LF (0x0a). But that is NOT what your device is sending: it is sending CR (0x0d) then ')' (0x29).  So it sending ')' rather than LF.  The read is thus not terminating on the expected terminator, it is terminating on the expected byte count.  But because the terminator is not found and removed, the LRC calculation is using the wrong byte count, and is incorrect.

You need to figure out if this is perhaps a parity setting problem on your port/device, or if the manufacturer is sending the wrong terminator for some reason.

Mark

-----Original Message-----
From: Pierrick M Hanlet [mailto:[email protected]] 
Sent: Friday, September 28, 2012 12:17 PM
To: Mark Rivers; [email protected]
Subject: RE: modbus 2.4

Hi Mark,
Thanks for the rapid response.  I have the CLS record as a convenient way to close the
valve; VAL is a more complicated process.

The documentation for the device only accepts 3, 8, 16 (I'm not certain about 8).  The
device also appears to impose offset of 40001 to the address.  I know that it works
because I can watch the pressure change in my setup.

I added the tracing as you suggested.  For an attempt to read, nothing happens:
epics> 2012/09/28 12:09:42.604 MICE-RF-TUNE-01:READVALU devAsynInt32 process read error 

When a write the simple close command, I get a LOT more:

epics> 2012/09/28 12:13:53.521 RFTunerPort asynManager::lockPort locking port
2012/09/28 12:13:53.521 RFTunerPort asynManager::lockPort taking mutex 0x9f25e78
2012/09/28 12:13:53.521 RFTunerPort asynManager::lockPort queueing request
2012/09/28 12:13:53.521 RFTunerPort addr -1 queueRequest priority 0 not lockHolder
2012/09/28 12:13:53.521 RFTunerPort asynManager::lockPort waiting for event
2012/09/28 12:13:53.521 asynManager::portThread port=RFTunerPort callback
2012/09/28 12:13:53.522 RFTunerPort asynManager::lockPortCallback signaling begin event
2012/09/28 12:13:53.522 RFTunerPort asynManager::lockPortCallback waiting for mutex from unlockPort
2012/09/28 12:13:53.522 RFTunerPort asynManager::lockPort got event from callback
2012/09/28 12:13:53.522 RFTunerPort flush
2012/09/28 12:13:53.522 /dev/ttyS3 flush
2012/09/28 12:13:53.522 /dev/ttyS3 write.
2012/09/28 12:13:53.522 /dev/ttyS3 write 23

3a 30 31 31 30 30 30 33 31 30 30 30 31 30 32 30 30 30 30 42 
42 0d 0a 
2012/09/28 12:13:53.522 wrote 23 to /dev/ttyS3, return asynSuccess
2012/09/28 12:13:53.522 RFTunerPort wrote

3a 30 31 31 30 30 30 33 31 30 30 30 31 30 32 30 30 30 30 42 
42 0d 0a 
2012/09/28 12:13:53.522 asynOctetSyncIO wrote:

01 10 00 31 00 01 02 00 00 
2012/09/28 12:13:53.522 /dev/ttyS3 read.
2012/09/28 12:13:53.550 /dev/ttyS3 read 2

3a 30 
2012/09/28 12:13:53.550 /dev/ttyS3 read 2, return 0
2012/09/28 12:13:53.551 RFTunerPort read

3a 30 
2012/09/28 12:13:53.551 /dev/ttyS3 read.
2012/09/28 12:13:53.552 /dev/ttyS3 read 2

31 31 
2012/09/28 12:13:53.553 /dev/ttyS3 read 2, return 0
2012/09/28 12:13:53.553 RFTunerPort read

31 31 
2012/09/28 12:13:53.553 /dev/ttyS3 read.
2012/09/28 12:13:53.553 /dev/ttyS3 read 1

30 
2012/09/28 12:13:53.554 /dev/ttyS3 read 1, return 0
2012/09/28 12:13:53.554 RFTunerPort read

30 
2012/09/28 12:13:53.554 /dev/ttyS3 read.
2012/09/28 12:13:53.555 /dev/ttyS3 read 1

30 
2012/09/28 12:13:53.555 /dev/ttyS3 read 1, return 0
2012/09/28 12:13:53.555 RFTunerPort read

30 
2012/09/28 12:13:53.555 /dev/ttyS3 read.
2012/09/28 12:13:53.556 /dev/ttyS3 read 1

30 
2012/09/28 12:13:53.556 /dev/ttyS3 read 1, return 0
2012/09/28 12:13:53.556 RFTunerPort read

30 
2012/09/28 12:13:53.556 /dev/ttyS3 read.
2012/09/28 12:13:53.557 /dev/ttyS3 read 1

33 
2012/09/28 12:13:53.557 /dev/ttyS3 read 1, return 0
2012/09/28 12:13:53.557 RFTunerPort read

33 
2012/09/28 12:13:53.557 /dev/ttyS3 read.
2012/09/28 12:13:53.558 /dev/ttyS3 read 1

31 
2012/09/28 12:13:53.558 /dev/ttyS3 read 1, return 0
2012/09/28 12:13:53.558 RFTunerPort read

31 
2012/09/28 12:13:53.558 /dev/ttyS3 read.
2012/09/28 12:13:53.559 /dev/ttyS3 read 1

30 
2012/09/28 12:13:53.559 /dev/ttyS3 read 1, return 0
2012/09/28 12:13:53.559 RFTunerPort read

30 
2012/09/28 12:13:53.559 /dev/ttyS3 read.
2012/09/28 12:13:53.560 /dev/ttyS3 read 1

30 
2012/09/28 12:13:53.560 /dev/ttyS3 read 1, return 0
2012/09/28 12:13:53.560 RFTunerPort read

30 
2012/09/28 12:13:53.560 /dev/ttyS3 read.
2012/09/28 12:13:53.561 /dev/ttyS3 read 1

30 
2012/09/28 12:13:53.561 /dev/ttyS3 read 1, return 0
2012/09/28 12:13:53.561 RFTunerPort read

30 
2012/09/28 12:13:53.561 /dev/ttyS3 read.
2012/09/28 12:13:53.562 /dev/ttyS3 read 1

31 
2012/09/28 12:13:53.562 /dev/ttyS3 read 1, return 0
2012/09/28 12:13:53.562 RFTunerPort read

31 
2012/09/28 12:13:53.562 /dev/ttyS3 read.
2012/09/28 12:13:53.563 /dev/ttyS3 read 1

42 
2012/09/28 12:13:53.563 /dev/ttyS3 read 1, return 0
2012/09/28 12:13:53.563 RFTunerPort read

42 
2012/09/28 12:13:53.563 /dev/ttyS3 read.
2012/09/28 12:13:53.564 /dev/ttyS3 read 1

44 
2012/09/28 12:13:53.564 /dev/ttyS3 read 1, return 0
2012/09/28 12:13:53.564 RFTunerPort read

44 
2012/09/28 12:13:53.564 /dev/ttyS3 read.
2012/09/28 12:13:53.565 /dev/ttyS3 read 1

0d 
2012/09/28 12:13:53.565 /dev/ttyS3 read 1, return 0
2012/09/28 12:13:53.565 RFTunerPort read

0d 
2012/09/28 12:13:53.565 /dev/ttyS3 read.
2012/09/28 12:13:53.566 /dev/ttyS3 read 1

29 
2012/09/28 12:13:53.566 /dev/ttyS3 read 1, return 0
2012/09/28 12:13:53.566 RFTunerPort read

29 
2012/09/28 12:13:53.566 modbusInterpose::readIt, LRC error
2012/09/28 12:13:53.566 RFTunerPort unlockPort
2012/09/28 12:13:53.566 RFTunerPort asynManager::unlockPort waiting for event
2012/09/28 12:13:53.566 RFTunerPort unlockPort unlock mutex 0x9f25e78 complete.
2012/09/28 12:13:53.566 drvModbusAsyn::doModbusIO port write1CLS error calling writeRead, error=, nwrite=9/9, nread=0
2012/09/28 12:13:53.566 MICE-RF-TUNE-01:WRITE000 devAsynInt32 process error 

I don't know what to look at here.  Hopefully this will give you what you need.
Thank you,
Pierrick



"Whether you think you can or think you can't, either way, you are correct"
-- Henry Ford

_________________________________________________________________________
Pierrick Hanlet
IIT/Fermilab
+1-630-697-8758 (FNAL)
+1-312-567-5745 (IIT)
+1-630-697-8758/+44-7-948-860-1978 (US/UK mobile)
________________________________________
From: Mark Rivers [[email protected]]
Sent: Friday, September 28, 2012 11:58 AM
To: Pierrick M Hanlet; [email protected]
Subject: RE: modbus 2.4

Hi Pierrick,

Some questions:

- Are sure this device talks Modbus ASCII, not Modbus RTU?

- I don't understand the difference between port wirte1VAL and write1CLS that you have created.  They are created identically, i.e. they write to the same address, so why did you create 2 ports?
drvModbusAsynConfigure("write1VAL","RFTunerPort",0x01,0x10,0x0031,1,0,0,"ProportionAir1")
drvModbusAsynConfigure("write1CLS","RFTunerPort",0x01,0x10,0x0031,1,0,0,"ProportionAir1")

- Since you are writing a single register why did you use Modbus function code 0x10 (=16=write multiple registers), rather than function code 6 (write single register)?

- What is the evidence that the write is successful?

Write operations read a response from the Modbus server.  In your case you are getting the following:
2012/09/28 10:49:49.964 modbusInterpose::readIt, LRC error
2012/09/28 10:49:49.964 drvModbusAsyn::doModbusIO port write1CLS error calling writeRead, error=, nwrite=9/9, nread=0

That implies it is getting no response.  But to be sure you should turn on asynTrace on the underlying RS-485 port:

asynSetTraceIOMask("RFTunerPort",0,4)
asynSetTraceMask("RFTunerPort",0,255)

That will show you what is being written and read by the underlying serial port, and hopefully help to pin down the problem.

Mark


-----Original Message-----
From: [email protected] [mailto:[email protected]] On Behalf Of Pierrick M Hanlet
Sent: Friday, September 28, 2012 11:41 AM
To: [email protected]
Subject: modbus 2.4

Hi,
I have an ioc (base 3.14.11) using modbus 2.4 in which I'm controlling ProportionAir
Modbus Serial OPV1 proportional air valves over RS485 serial.  In my st.cmd file,
I have:
modbusInterposeConfig("RFTunerPort",2,1000,0)
drvModbusAsynConfigure("read1ADDR", "RFTunerPort",0x01,0x03,0x0000,1,0,86400000,"ProportionAir")
drvModbusAsynConfigure("read1VALU", "RFTunerPort",0x01,0x03,0x0031,1,0,86400000,"ProportionAir")
drvModbusAsynConfigure("read2ADDR", "RFTunerPort",0x02,0x03,0x0000,1,0,86400000,"ProportionAir")
drvModbusAsynConfigure("read2VALU", "RFTunerPort",0x02,0x03,0x0031,1,0,86400000,"ProportionAir")

drvModbusAsynConfigure("write1VAL","RFTunerPort",0x01,0x10,0x0031,1,0,0,"ProportionAir1")
drvModbusAsynConfigure("write1CLS","RFTunerPort",0x01,0x10,0x0031,1,0,0,"ProportionAir1")
drvModbusAsynConfigure("write2VAL","RFTunerPort",0x02,0x10,0x0031,1,0,0,"ProportionAir2")
drvModbusAsynConfigure("write2CLS","RFTunerPort",0x02,0x10,0x0031,1,0,0,"ProportionAir2")


And, in my database, I have:
record(ai,"MICE-RF-TUNE-01:READADDR") {
        field(DESC,"Read address")
        field(SCAN,"Passive")
        field(DTYP,"asynInt32")
        field(INP,"@asyn(read1ADDR,0, 60)MODBUS_DATA")
}
record(ai,"MICE-RF-TUNE-01:READVALU") {
        field(DESC,"Read value")
        field(SCAN,"Passive")
        field(DTYP,"asynInt32")
        field(INP,"@asyn(read1VALU,0,36000)MODBUS_DATA")
}

record(ai,"MICE-RF-TUNE-02:READADDR") {
        field(DESC,"Read address")
        field(SCAN,"Passive")
        field(DTYP,"asynInt32")
        field(INP,"@asyn(read1ADDR,0, 60)MODBUS_DATA")
}
record(ai,"MICE-RF-TUNE-02:READVALU") {
        field(DESC,"Read value")
        field(SCAN,"Passive")
        field(DTYP,"asynInt32")
        field(INP,"@asyn(read1VALU,0,36000)MODBUS_DATA")
}


###############################################################################
### Write functions
###############################################################################
### Unit 1
record(ao,"MICE-RF-TUNE-01:WRITEVALU") {
        field(DESC,"Write open 0%")
        field(SCAN,"Passive")
        field(DTYP,"asynInt32")
        field(VAL, "0x0000")
        field(OUT,"@asynMask(write1VAL,0,16)MODBUS_DATA")
}
record(ao,"MICE-RF-TUNE-01:WRITE000") {
        field(DESC,"Write open 0%")
        field(SCAN,"Passive")
        field(DTYP,"asynInt32")
        field(VAL, "0x0000")
        field(OUT,"@asynMask(write1CLS,0,16)MODBUS_DATA")
}

### Unit 2
record(ao,"MICE-RF-TUNE-02:WRITEVALU") {
        field(DESC,"Write open 0%")
        field(SCAN,"Passive")
        field(DTYP,"asynInt32")
        field(VAL, "0x0000")
        field(OUT,"@asynMask(write2VAL,0,16)MODBUS_DATA")
}
record(ao,"MICE-RF-TUNE-02:WRITE000") {
        field(DESC,"Write open 0%")
        field(SCAN,"Passive")
        field(DTYP,"asynInt32")
        field(VAL, "0x0000")
        field(OUT,"@asynMask(write2CLS,0,16)MODBUS_DATA")
}


===================================================
My problem is that I can successfully write, but I cannot read from the devices.
Whether I read or write, I get messages:
After a successful write:
2012/09/28 10:49:49.964 modbusInterpose::readIt, LRC error
2012/09/28 10:49:49.964 drvModbusAsyn::doModbusIO port write1CLS error calling writeRead, error=, nwrite=9/9, nread=0
2012/09/28 10:49:49.964 MICE-RF-TUNE-01:WRITE000 devAsynInt32 process error

An attempt to read results in:
2012/09/28 11:37:55.103 MICE-RF-TUNE-01:READVALU devAsynInt32 process read error

I keep reading the modbus 2.4 Driver Support for Modbus Protocol under EPICS, but I'm clearly
missing something.  I don't understand why I get an error on a successful write, and I don't
understand why I cannot read at all.  Please help.
Thanks,
Pierrick


===================================================
"Whether you think you can or think you can't, either way, you are correct"
-- Henry Ford

_________________________________________________________________________
Pierrick Hanlet
IIT/Fermilab
+1-630-697-8758 (FNAL)
+1-312-567-5745 (IIT)
+1-630-697-8758/+44-7-948-860-1978 (US/UK mobile)


References:
modbus 2.4 Pierrick M Hanlet
RE: modbus 2.4 Mark Rivers
RE: modbus 2.4 Pierrick M Hanlet

Navigate by Date:
Prev: Re: CAC problem between RTEMS and vxWorks Wesley Moore
Next: Re: CAC problem between RTEMS and vxWorks Benjamin Franksen
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  <20122013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
Navigate by Thread:
Prev: RE: modbus 2.4 Pierrick M Hanlet
Next: Oxford CryoStream 700 support in EPICS? Pete R. Jemian
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  <20122013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
ANJ, 18 Nov 2013 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·