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  <20132014  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  2012  <20132014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
<== Date ==> <== Thread ==>

Subject: RE: More on Modbus
From: Mark Rivers <[email protected]>
To: Zenon Szalata <[email protected]>
Cc: "[email protected]" <[email protected]>
Date: Mon, 27 May 2013 18:46:32 +0000
Hi Zen,

I have tried to reproduce the problem, and have not been able to. I have added a test program to the latest version of the synApps modbus module, which you can get at:

https://subversion.xor.aps.anl.gov/synApps/modbus/trunk

In the src/ directory there is a new driver, testModbusSyncIO.cpp.  This is a simple driver derived from asynPortDriver.  It uses the asynInt32SyncIO interface to write to a Modbus output driver and read from a Modbus input driver.  The Modbus test application (modbusApp) is now built with support for this test driver.

The modbus/iocBoot/iocTest directory now contains 2 new files, sim3.cmd and sim3.substitutions.  These launch an IOC with 4 drivers:

1) sim1 is a drvAsynIPPort driver that provides the low-level TCP communication.  I connected this to a Modbus simulator device running on my PC, but any Modbus device with a read/writeable register can be used instead.

2) A0_Out_Word is a Modbus driver that writes a single register to a TCP Modbus server.

3) A0_In_Work is a Modbus that reads a single register from a TCP Modbus server.  It should be configured to read the same register that A0_Out_Word writes to.

4) TEST_SYNCIO is the new testModbusSyncIO driver that communicates with A0_In_Word and A0_Out_Word drivers using the asynInt32SyncIO interface.

sim3.substitutions loads 4  asynRecords for debugging, one connected to each driver above.  It also loads a longout record connected to A0_Out_Word, a longin record connected to A0_In_Word, a longout record connected to TEST_SYNCIO, and a longin record connected to TEST_SYNCIO.

I created a new medm screen, modbusTestSyncIO.adl which exposes these records.

Everything seems to work OK.  I can write to the A0_Out_Word longout record, and both longin records update.  I can also write to the TEST_SYNCIO longout record (which writes using the asynInt32SyncIO interface to the A0_Out_Word driver), and again both longin records update as expected.

Please give this simple test program a try, configured to a register on your Beckhoff device.

Please also send me your test driver, databases and startup script and I'll see if I can spot a problem, or reproduce your error on a more complex configuration.

Cheers,
Mark





________________________________________
From: Zenon Szalata [[email protected]]
Sent: Thursday, May 23, 2013 11:20 PM
To: Mark Rivers
Cc: [email protected]
Subject: Re: More on Modbus

Hi Mark,
This is what I get:
epics> epicsMutexShowAll 1
ellCount(&mutexList) 1117 ellCount(&freeList) 0
epicsMutexId 0xd30420 source ../../asyn/asynDriver/asynManager.c line 1868
epicsMutexId 0xd33680 source ../drvModbusAsyn.c line 311
epicsMutexId 0x7f617c0009e0 source ../../asyn/asynDriver/asynManager.c
line 1701
epicsMutexId 0xd435a0 source
../../asyn/asynPortDriver/asynPortDriver.cpp line 2092
epicsMutexId 0xd43870 source ../../asyn/asynDriver/asynManager.c line 1868
epicsMutexId 0x7f615c0009d0 source ../../asyn/asynDriver/asynManager.c
line 1701
epics>
Thanks Mark,
Zen

On 05/23/13 19:19, Mark Rivers wrote:
> Hi Zen,
>
> The modbus driver definitely does not lock the port and never unlock it.
>
> However, it is possible that there is a deadlock, which can occur when there is more than one mutex, and they are not taken/released in the correct order.
>
> The modification I was proposing previously was not to fix a deadlock, but rather to lock the port for even longer in the polling thread.
>
> In order to figure out if this is a deadlock, please type the following iocsh command when your simple test driver is blocking:
>
> epicsMutexShowAll 1
>
> That will list all mutexes that are currently held, and what line of code those mutexes were created in.
>
> Thanks,
> Mark
>
> ________________________________________
> From: Zenon Szalata [[email protected]]
> Sent: Monday, May 20, 2013 10:19 PM
> To: Mark Rivers
> Cc: [email protected]
> Subject: Re: More on Modbus
>
> Hi Mark,
> I have written a simple test device driver derived directly from
> asynPortDriver. The call to pasynInt32SyncIO->read(pasynUser,&val,tmo)
> is blocking forever. So, it seems that the modbus driver locks the port
> and never unlocks it. You did mentioned the issue with locks in an
> earlier email on this topic. Could you make the modification to the
> modbus support module?
> Thank you much,
> Zen
>
> On 05/18/13 16:38, Mark Rivers wrote:
>> Hi Zen,
>>
>> Actually I don't think I need to expose any data structures in the Modbus driver. Your motor driver should be able to communicate with the Modbus driver using only the following information:
>>
>> - The name of the Modbus port
>> - The asyn "address" field, which is the offset of the register relative to the first register address for that port
>> - The asyn interface (e.g. asynInt32, etc.)
>> - The asyn drvInfo field, which you may not need if the default MODBUS_DATA is sufficient
>>
>> With the above information your motor driver will probably do something like the following:
>>
>> pasynInt32SyncIO->connect(port, addr, &pasynUser, drvInfo); // In your driver's constructor
>>
>> pasynInt32SyncIO->write(pasynUser, value, timeout); // In your driver's I/O routines
>> pasynInt32SyncIO->read(pasynUser, &value, timeout);
>>
>> With the above scheme you will need a number of pasynUser structures (one for each port/addr pair). You could also use the pasynInt32SyncIO->writeOnce and readOnce methods, which are less efficient but don't require storing multiple pasynUser structures.
>>
>> Mark
>>
>> ________________________________________
>> From: Zenon Szalata [[email protected]]
>> Sent: Saturday, May 18, 2013 1:55 PM
>> To: Mark Rivers
>> Cc: [email protected]
>> Subject: Re: More on Modbus
>>
>> Hi Mark,
>> This is just a short follow up on my last email.
>> After looking at my Pico driver implementation and digging a bit more
>> into drvModbusAsyn.c file, it seems to me that you might need to expose
>> the data structures that are created for each port and then I should be
>> able to call pasynOctetSyncIO routines as needed. Is that approximately
>> what you had in mind?
>> Thanks for helping me with this,
>> Zen
>>
>> P.S. At this point I have a reasonably well working implementation, all
>> in a collection of records in a database, about 1000 of them. The only
>> problem is that one has to pay attention to reads and writes to the
>> hidden registers as these sometimes go wrong.
>> With that said, some people here are getting somewhat excited, because
>> Beckhoff offers a very inexpensive hardware solution compared to XPS.
>> And the XPS controllers are not problem free.
>>
>>
>> On 05/18/13 08:45, Mark Rivers wrote:
>>> Hi Zen,
>>>
>>> Hi Zen,
>>>
>>> I think I see a solution that should allow you to stop the poller thread when you want to access the same Modbus addresses in another thread. The solution is to have the poller thread take the asyn port driver lock (pasynManager->lockPort()) for its operation loop. Your other thread can then also lock the port, which will block the poller thread while you do a sequence of write and read operations. This will work fine if your motor code is written as a C/C++ driver. But if it is just a collection of records in a database I'm not sure how to do it.
>>>
>>> Since the problematic Beckhoff devices are motor controllers, you could write a real driver in C++ using the asynMotorController and asynMotorAxis base classes, which are themselves derived from asynPortDriver. There are quite a few examples of relatively simple drivers using that model in the synApps motor module now. Such drivers are normally used with the synApps motor record, but this is NOT required. Since the driver uses standard asyn interfaces it is possible to just use standard records to move the motor, control the velocity, read the status, etc. You lose the "state machine" aspect of the motor record (backlash correction, retries, etc.). But for a simple controller the standard records may be fine. In your C++ driver you will then call lockPort() for the underlying Modbus driver when needed.
>>>
>>> I can make the appropriate minor change to the Modbus driver for you to test if this seems like a reasonable approach to you.
>>>
>>> Mark
>>>
>>> ________________________________________
>>> From: Zenon Szalata [[email protected]]
>>> Sent: Friday, May 17, 2013 4:39 PM
>>> To: Mark Rivers; [email protected]
>>> Subject: More on Modbus
>>>
>>> Hi Mark,
>>> Some of what I wrote in my previous email is no longer relevant. I have
>>> since played with controlling the polling timeout to reduce the
>>> interference between the reads done in the polling thread and the
>>> write-reads that I am attempting from my rather complicated set of EPICS
>>> records. I have reached a conclusion, hopefully correct, that what I
>>> really need is a Modbus device driver that would give me a full control
>>> when and in which order register read and write operations are performed.
>>> Is this possible with the existing Modbus support module?
>>> I am thinking that it would be very nice to have a C++ base class like
>>> asynPortDriver, or perhaps a subclass of asynPortDriver, which would
>>> implement all the details of Modbus protocol and basic IO.
>>> Have you thought of writing something like that?
>>> Do you think such a class would be useful?
>>> Beckhoff are the only modbus devices that I have written software for
>>> and the stepper motor controllers are the only devices for which I find
>>> your Modbus support module too limited. For that reason I am a bit
>>> hesitant to start a new project, that is to write the C++ class. Could
>>> you offer your insight on this?
>>> Thanks in advance,
>>> Zen



Replies:
RE: More on Modbus Mark Rivers
References:
More on Modbus Zenon Szalata
RE: More on Modbus Mark Rivers
Re: More on Modbus Zenon Szalata
RE: More on Modbus Mark Rivers
Re: More on Modbus Zenon Szalata
RE: More on Modbus Mark Rivers
Re: More on Modbus Zenon Szalata

Navigate by Date:
Prev: Re: streamdevice Sebastian Matkovich
Next: Motor record .RDBD field Emma Shepherd
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  <20132014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
Navigate by Thread:
Prev: Re: More on Modbus Zenon Szalata
Next: RE: More on Modbus Mark Rivers
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  <20132014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
ANJ, 20 Apr 2015 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·