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  2012  2013  2014  2015  <20162017  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  2012  2013  2014  2015  <20162017  2018  2019  2020  2021  2022  2023  2024 
<== Date ==> <== Thread ==>

Subject: RE: CARS:Modbus - function 06 (write single register) issue
From: Nick Levchenko <[email protected]>
To: Mark Rivers <[email protected]>, "'Pearson, Matthew R.'" <[email protected]>
Cc: "[email protected] list" <[email protected]>
Date: Fri, 5 Aug 2016 13:24:46 +0000
Hi Mark,

Just to let you know that I have successfully configure comms using your new driver. I only used the new format with Function 6:
drvModbusAsynConfigure("$(PLCNAME)write",	$(PLCNAME), 0, 6, -1, 2, 0, 0, "S7-1500")

So far it seems to work and not causing any issues. I will continue actively using it over next few weeks and report back.

______________________

Nick Levchenko
Control Systems Engineer
Integrated Control System Division

European Spallation Source ERIC
P.O Box 176, SE-221 00 Lund, Sweden
Visiting address: Tunavägen 24, Lund

Mobile: +46 721 79 23 64
Phone: +46 46 888 33 64
E-mail: [email protected]

www.esss.se


-----Original Message-----
From: Mark Rivers [mailto:[email protected]] 
Sent: 21 July 2016 00:50
To: 'Pearson, Matthew R.'; Nick Levchenko
Cc: [email protected] list
Subject: RE: CARS:Modbus - function 06 (write single register) issue

Hi Nick and Matt,

I have added support for absolute Modbus addressing to the EPICS Modbus driver.  It is done in a much more general manner than my proposal of July 16.  

This is from the new release notes:
*****************************************
Added support for specifying absolute Modbus addresses in the asyn "addr" field. Previously each driver was limited to addressing at most 125 registers (read operations) or 123 registers (write operations), and the asyn "addr" field specified an offset relative to the modbusStartAddress passed as the fifth argument to drvAsynModbusConfigure(). Now if the modbusStartAddress=-1 then the driver will use absolute addressing, and the asyn "addr" specifes the absolute Modbus address in the range 0 to 65535. In this case the modbusLength argument to drvAsynModbusConfigure() is the maximum length required for any single Modbus transaction by that driver. This would be 1 if all Modbus reads and writes are for 16-bit registers, but it would be 4 if 64-bit floats (4 16-bit registers) are being used, and 100 (for example) if an Int32 waveform record with NELM=100 is being read or written.
*****************************************

The change is not restricted to function code 6, it works with any function code.  

The initial readback for output records will be done if the pollMsec argument to drvAsynModbusConfigure is greater than 0.

Absolute addressing is not restricted to 16-bit integer data types.  It works will all of the data types that the Modbus driver currently supports, including 32-bit integers, and 32-bit and 64-bit floats.  It supports big and little endian versions of these data types.  It also works with waveform records, where each element of the waveform is a 16-bit Modbus register. 

The only restriction is that there is no polling done for inputs when absolute addressing is used, so EPICS records cannot have SCAN=I/O Intr.  This is because the polling is done a single Modbus read operation, and is restricted by the Modbus protocol to at most 125 registers.  When using absolute addressing input records will need to be periodically scanned, and each record processing will result in a Modbus read operation.

The new version is in the "absolute_address" branch on Github, https://github.com/epics-modules/modbus/tree/absolute_address.

There are new test files in the iocBoot/iocTest directory, sim5.cmd and sim5.substitutions.  These test all of the data types.  The medm screen modbusDataTypesTest.adl can be used to display the values of the input and output records. 

Please test  with your applications and let me know of any problems.

Cheers,
Mark



-----Original Message-----
From: Pearson, Matthew R. [mailto:[email protected]] 
Sent: Monday, July 18, 2016 11:09 AM
To: Mark Rivers
Cc: Nick Levchenko; [email protected] list
Subject: Re: CARS:Modbus - function 06 (write single register) issue


Hi Mark,

I would find that change useful too, as I had a similar issue writing support for the Eurotherm NanoDAC. This has a modbus address range spanning a wide number range, and so I ended up having a dozen or so calls to drvAsynModbusConfigure in order to cover all the required parameters. 

Regarding reading strings, I am currently using a workaround that involves a waveform of Ints and forward linking to a subArray of chars. In my case, I believe it is 1 char per register, stored in the high order byte.

Cheers,
Matt


> On Jul 16, 2016, at 3:55 PM, Mark Rivers <[email protected]> wrote:
> 
> Hi Nick,
> 
> I apologize for my delay in answering your original message on this topic.  I understand the issue you are describing.  The reason for the restriction to a block of 123 words for each asyn modbus port driver is that even output records are allowed to do one initial read operation during device support  init_record.  This is so that the initial value of the output record can match the actual hardware value.  This is commonly called a "bumpless reboot", i.e. one can reboot the IOC and the output records match the hardware without modifying the hardware.  It is more efficient to do that initial read as a single block read of up to 123 registers than to read one register at a time.  That is the motivation for the current design.
> 
> That being said, I can understand that there are times that the 123 word restriction is a pain, so I am willing to figure out a solution.  Your proposed syntax of specifying an offset of 0 and a length of 0 to mean "use asyn addr field as absolute 16-bit address" sounds reasonable.  It would only be allowed for Modbus function code 6.  The question then arises about how to handle the initial read of the register during device support init_record.  This currently works as follows:
> 
> - If the pollMsec argument to drvAsynModbusConfigure is greater than 0 then the driver reads the entire block of registers once when the driver is created.
> 
> - When device support init_record calls the asynInt32->read() function the driver returns the value for that register from the block that was read in the previous step, and returns asynSuccess (assuming the initial read was successful).
> 
> This mechanism won't work for the proposed new driver behavior, because the driver would need to read the entire 16-bit address space, reading at most 123 registers at a time.  Many of those read operations are likely to fail, because the device will not implement the entire 16-bit address space.
> 
> An alternative does exist.  As described above, currently the asynInt32->read() function for MODBUS_DATA returns the register value from the last poll, including the initial poll.  It does not actually cause any I/O operation to occur.  The driver could be changed so that it does an actual Modbus read of that single register at the asyn addr under the following conditions:
>  Function code == 6 AND
>  Offset == 0 AND 
>  Length == 0 AND
>  pollMsec > 0 
> 
> By requiring pollMsec > 0 you can disable the initial read if desired.  You could even create 2 drvAsynModbus drivers that handle the entire 16-bit address space, one with pollMsec=0 (disallow the initial read) and one with pollMsec>0 (allow the initial read).  Then you can select the behavior you want on a per-record basis by choosing one driver or the other.
> 
> Reading the registers one at a time will not be as efficient as block reads, and so iocInit will take a little longer, but that should be fine.  It will be backwards compatible, because offset=0 and length=0 is not currently allowed.
> 
> Does this sound reasonable? If so I will begin to work on it.
> 
> On a somewhat related note, I have received a request to support reading strings from Modbus devices using the asynOctet interface.  Apparently some vendors store strings in a series of registers, 2 characters per register.  Of course there is no standard as to whether the first character will be in the high or low byte of the register, so I plan to implement both options.
> 
> Mark
> _______________________________________
> From: [email protected] [[email protected]] on behalf of Nick Levchenko [[email protected]]
> Sent: Saturday, July 16, 2016 1:53 PM
> To: [email protected]
> Subject: CARS:Modbus - function 06 (write single register) issue
> 
> Hi everyone,
> 
> 
> I have started to use Modbus (Asyn) driver (CARS:Modbus, Mark Rivers) and so far it looks great. I've gone through instructions under http://cars9.uchicago.edu/software/epics/modbusDoc.html and successfully got comms going.
> 
> Now that I'm starting to work further and actually create records I realised that I have a bit of a problem.
> 
> What I'm planning to use the driver for is only WRITING values from EPICS to PLC (Siemens S7-1500 in case you're interested).
> The values are only written when IOC changes them (for example user pushes the button on GUI), i.e. asynchronously. Therefore I want to use Modbus function 6 (write single register).
> As per instructions I added the following to my command file to create modbus port:
> drvModbusAsynConfigure("modbuswrite",        $(PLCNAME), 0, 6, 0, 123, 0, 0, "S7-1500")
> where 6 is the modbus function, 0 is memory offset, and 123 is the number of words.
> 
> And this is when I realised I have an issue. In this set up I have to specify offset and length. These parameters make perfect sense for Modbus function 3 (where the driver will poll all these registers), but (as far as I know Modbus protocol) for Modbus function 6 they are actually not required at all. The modbus message looks like:
> 06 0001 0003 XXXX(CRC)
> 06 - function
> 0001 - modbus address to write to
> 0003 - value to write
> 
> Basically Modbus allows writing to ANY offset on the fly. So what I'm trying to understand is why does the driver force me to specify offset and length for FC03?
> 
> The reason it is a problem for me is that I will have a lot more than 123 words to write, therefore currently it looks like I will have to repeat drvModbusAsynConfigure quite a few times, have multiple Modbus port names and then write my records accordingly (recalculating offsets for every next port). This is going to be very painful.
> 
> I was trying to be sneaky and use:
> drvModbusAsynConfigure("modbuswrite",        port1, 0, 6, 0, 0, 0, 0, "S7-1500")
> hoping the driver has allowed for that, the response was
> drvModbusAsyn::drvModbusConfigure, port modbuswrite memory length<=0
> 
> I also tried
> drvModbusAsynConfigure("modbuswrite",        port1, 0, 6, 0, 124, 0, 0, "S7-1500")
> the response was
> drvModbusAsyn::drvModbusConfigure, port modbuswrite memory length=124 too large, max=123
> 
> So, clearly, there are some checks in driver code there.
> 
> So, what I'm trying to understand is why does the driver require offset and length for FC06? Is it really necessary, etc.?
> I was almost thinking that something like:
> drvModbusAsynConfigure("modbuswrite",        port1, 0, 6, 0, 0, 0, 0, "S7-1500")
> can just create the connection and then driver would form Modbus message based on the offset from the record.
> 
> I sincerely hope I haven't made this too confusing and it makes sense. I'd love to get community's thoughts on this.
> 
> Thank you in advance!
> 
> 
> Regards,
> 
> Nick Levchenko
> Control Systems Engineer
> Integrated Control System Division
> 
> European Spallation Source ERIC
> P.O Box 176, SE-221 00 Lund, Sweden
> Visiting address: Tunavägen 24, Lund
> 
> Mobile: +46 721 79 23 64
> Phone: +46 46 888 33 64
> E-mail: [email protected]
> 
> www.esss.se
> 
> 



References:
CARS:Modbus - function 06 (write single register) issue Nick Levchenko
RE: CARS:Modbus - function 06 (write single register) issue Mark Rivers
Re: CARS:Modbus - function 06 (write single register) issue Pearson, Matthew R.
RE: CARS:Modbus - function 06 (write single register) issue Mark Rivers

Navigate by Date:
Prev: Re: Ralph Lange
Next: CA connection problems between VxWorks and Windows Benjamin Franksen
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  <20162017  2018  2019  2020  2021  2022  2023  2024 
Navigate by Thread:
Prev: RE: CARS:Modbus - function 06 (write single register) issue Nick Levchenko
Next: RE: CARS:Modbus - function 06 (write single register) issue Nick Levchenko
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  <20162017  2018  2019  2020  2021  2022  2023  2024 
ANJ, 19 Aug 2016 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·