pymodbus-dev / pymodbus

A full modbus protocol written in python
Other
2.23k stars 911 forks source link

cannot enable/disable RTS for client and slave #33

Closed ghost closed 3 years ago

ghost commented 10 years ago

when i use serial RTU and RS-485 wires, how do i set set RTS high and low.

i know i gotta to do it in the source codes, like for read_holding_register request , i need to set it high to send the request and low to receive the response from slave.

and for the slave Linux box, i need to set RTS high to send a reponse back to master and set it low right after that.

where do i do that ?

i know i can setRTS using pyserial.

bashwork commented 10 years ago

What you can do is simply::

client = ModbusSerialClient(...) client.socket.setRTS(true) ... client.socket.setRTS(false)

Furthermore, anything that you need to do on the serial socket, you can do as well (this is actually just the pyserial socket instance).

ghost commented 10 years ago

sorry for being noob.. i know how to set that, but what does it mean, like if i want to do a read_holding_register through just RS-485 twisted pair wires, i setRTS(true) to send the read request. client.read_holding_register would return the value? do i need to setRTS(false) after doing client.read_holding_register? do i need a delay between them? i'v been adding set RTS(True) and setRTS(false) in transaction manager's execute() method . so before a send, i set it true, after a send i set it false.

However, the real issue is with the server, the server should only setRTS(True) when the master sends a request right? how do i know when to set it high, is there a way to know if a request has been sent so i can do an IF statement?

please be more detailed i'm really noob at this..

thank you very much for all the help you've given me.

ghost commented 10 years ago

i'm using the synchronous client and asynchronous server examples..

cannot really understand the asynchronous client example, and from the documentation's library Asynchronous server example from asyn.py import ModbusSerialClient as Client doesn't work, there's no ModbusSerialClient in Async.py ..

bashwork commented 10 years ago

Okay, so I haven't actually implemented a rs-485 solution with pymodbus. Are you stuck using the half duplex mode? Is there any chance you can just use a full duplex (4 wire) configuration? Otherwise, everyone I have been in contact with has simply used a controller that does the control line detection for them.

I guess you can try to implement it yourself, but it may be a little flakey (I have no clue if this is going to work or not)::

monkey patch ModbusSerialClient._send

def _send(self, request):
    ''' Sends data on the underlying socket

    :param request: The encoded request to send
    :return: The number of bytes written
    '''
    if not self.socket:
        raise ConnectionException(self.__str__())
    if request:
        self.socket.setRTS(true) # may need to delay, poll, etc here
        return self.socket.write(request)
    return 0

monkey patch ModbusSerialClient._recv

def _recv(self, size):
    ''' Reads data from the underlying descriptor

    :param size: The number of bytes to read
    :return: The bytes read
    '''
    if not self.socket:
        raise ConnectionException(self.__str__())
    client.socket.setRTS(false) # you shouldn't have to delay here
    return self.socket.read(size)

There may be other serial flags that you have to set for the master to give/take control over the line, but this is a quick idea.

bashwork commented 10 years ago

However after reading the pyserial documetation, it seems you can just defer to the hardware flow control by setting rtscts=False in the ModbusSerialClient constructor.

ghost commented 10 years ago

yes but how about the server side

what can i do there, there does not seem to be a send and receive functions in the transaction manager in the transaction.py .

where would i enable rts high or low for that

thanks

On Thu, Sep 26, 2013 at 10:58 PM, Galen Collins notifications@github.comwrote:

However after reading the pyserial documetation, it seems you can just defer to the hardware flow control by setting rtscts=False in the ModbusSerialClient constructor.

— Reply to this email directly or view it on GitHubhttps://github.com/bashwork/pymodbus/issues/33#issuecomment-25224568 .

ghost commented 10 years ago

yes i'm doing half duplex.

On Thu, Sep 26, 2013 at 11:32 PM, Heming Liu hemingliu123@gmail.com wrote:

yes but how about the server side

what can i do there, there does not seem to be a send and receive functions in the transaction manager in the transaction.py .

where would i enable rts high or low for that

thanks

On Thu, Sep 26, 2013 at 10:58 PM, Galen Collins notifications@github.comwrote:

However after reading the pyserial documetation, it seems you can just defer to the hardware flow control by setting rtscts=False in the ModbusSerialClient constructor.

— Reply to this email directly or view it on GitHubhttps://github.com/bashwork/pymodbus/issues/33#issuecomment-25224568 .

karlp commented 10 years ago

Trying to do the toggling from userspace is fraught with danger. Lots of devices will reply before you have had time to drop the tx-enable line, and it will not work. The right way of doing this, is to ask the kernel to open the serial port in rs-485 mode, so it will take care of that for you. Of course, that's not always possible, but it's how you should do it.

monkey patching send is the first attempt is ... maybe ok. You can definitely set the tx-enable line there, but you want to be dropping it again as soon as the transmission is complete. Which, unfortunately, is not when socket.write() returns! (You can get lucky with some rs485 devices by putting a delay there and dropping the signal manually, but it will not work with lots of devices that reply when the message has been received without waiting)

(Also, please remember that just because you are using the RTS line repurposed as a rs485 driver enable line doesn't meant that's the right name for it :)

ghost commented 10 years ago

both of my Linux devices are the same. and i'm using Sync client on one and Async server on the other. should i be using an Async client? but the one in the documentation code doesn't work. i'm setting RTS high and low like this on the SYNC.PY in ModbusUdpServer

def _execute(self, request, addr): ''' Executes the request and returns the result

    :param request: The decoded request message
    '''
    try:
        context = self.store[request.unit_id]
        response = request.execute(context)
    except Exception, ex:
        _logger.debug("Datastore unable to fulfill request: %s" % ex)
        response = request.doException(merror.SlaveFailure)
    #self.framer.populateResult(response)
    response.transaction_id = request.transaction_id
    response.unit_id = request.unit_id
    self._send(response, addr)
    self.socket.setRTS(False)

def _send(self, message, addr): ''' Send a request (string) to the network

    :param message: The unencoded modbus response
    :param addr: The (host, port) to send the message to
    '''
    self.control.Counter.BusMessage += 1
    pdu = self.framer.buildPacket(message)
    if _logger.isEnabledFor(logging.DEBUG):
        _logger.debug('send: %s' % b2a_hex(pdu))
    self.socket.setRTS(True)
    return self.transport.write(pdu, addr)

Even using the modpoll simulation server, i could not get a result using the Synchronous client.. getting error like this from writing to the register assert(rq.function_code < 0x80) # test that we are not an error AttributeError: 'NoneType' object has no attribute 'function_code' and i get none from reading the register..

ghost commented 10 years ago

Hi Galen,

what controller do people use, does the controller have automatic rs-485 half-duplex enable/disable flow control?

thanks

Heming

On Thu, Sep 26, 2013 at 10:43 PM, Galen Collins notifications@github.comwrote:

Okay, so I haven't actually implemented a rs-485 solution with pymodbus. Are you stuck using the half duplex mode? Is there any chance you can just use a full duplex (4 wire) configuration? Otherwise, everyone I have been in contact with has simply used a controller that does the control line detection for them.

I guess you can try to implement it yourself, but it may be a little flakey (I have no clue if this is going to work or not):: monkey patch ModbusSerialClient._send to the following

def _send(self, request): ''' Sends data on the underlying socket

:param request: The encoded request to send
:return: The number of bytes written
'''
if not self.socket:
    raise ConnectionException(self.__str__())
if request:
    self.socket.setRTS(true) # may need to delay, poll, etc here
    return self.socket.write(request)
return 0

monkey patch ModbusSerialClient._recv to the following

def _recv(self, size): ''' Reads data from the underlying descriptor

:param size: The number of bytes to read
:return: The bytes read
'''
if not self.socket:
    raise ConnectionException(self.__str__())
client.socket.setRTS(false) # you shouldn't have to delay here
return self.socket.read(size)

There may be other serial flags that you have to set for the master to give/take control over the line, but this is a quick idea.

— Reply to this email directly or view it on GitHubhttps://github.com/bashwork/pymodbus/issues/33#issuecomment-25224214 .

xvart commented 10 years ago

Sorry but I have to dive in here,

Anyone running modbus on a multitasking OS such as linux or windows will never be able to meet the requirements of the serial spec, there is no debate on this, tasking is normally 10ms so meeting 3.5us timing requirement just doesn't fit and never will.

RS485 is balanced 2 wire coms like RS422 and there is no RTS,CTS or any other modem signalling system. If you want to send over RS485, get an RS485 converter and move on this is not a modbus issue. On serial modbus is a poll response protocol so RTS et al are meaningless, read the spec it was designed for embedded systems probably bit bashing IO.

It is even probable that with a modern RS232 chip with buffering meeting the 3.5us in the spec is not possible.

Sorry but anyone trying modbus over serial on a multitasking OS is at the mercy of the external equipment.

see here for converters http://www.usconverters.com/index.php?main_page=index&cPath=65

On 28/09/13 14:33, heming277 wrote:

Hi Galen,

what controller do people use, does the controller have automatic rs-485 half-duplex enable/disable flow control?

thanks

Heming

On Thu, Sep 26, 2013 at 10:43 PM, Galen Collins notifications@github.comwrote:

Okay, so I haven't actually implemented a rs-485 solution with pymodbus. Are you stuck using the half duplex mode? Is there any chance you can just use a full duplex (4 wire) configuration? Otherwise, everyone I have been in contact with has simply used a controller that does the control line detection for them.

I guess you can try to implement it yourself, but it may be a little flakey (I have no clue if this is going to work or not):: monkey patch ModbusSerialClient._send to the following

def _send(self, request): ''' Sends data on the underlying socket

:param request: The encoded request to send :return: The number of bytes written ''' if not self.socket: raise ConnectionException(self.str()) if request: self.socket.setRTS(true) # may need to delay, poll, etc here return self.socket.write(request) return 0

monkey patch ModbusSerialClient._recv to the following

def _recv(self, size): ''' Reads data from the underlying descriptor

:param size: The number of bytes to read :return: The bytes read ''' if not self.socket: raise ConnectionException(self.str()) client.socket.setRTS(false) # you shouldn't have to delay here return self.socket.read(size)

There may be other serial flags that you have to set for the master to give/take control over the line, but this is a quick idea.

— Reply to this email directly or view it on GitHubhttps://github.com/bashwork/pymodbus/issues/33#issuecomment-25224214 .

— Reply to this email directly or view it on GitHub https://github.com/bashwork/pymodbus/issues/33#issuecomment-25290454.

ghost commented 10 years ago

ok thanks for the informative reply!

this helps very much i've been struggling for a long time.

However as you said even RS-232 is not possible, what's the point of using the RS-232 TO RS-485 converter then.

say if i want to connect from my master box to my slave box, how would i do it.

i have a FTDI USB to RS485 converter like this one https://www.sparkfun.com/products/9822 and i do have a rs-232 to rs-485 converter.

On Sat, Sep 28, 2013 at 12:30 AM, xvart notifications@github.com wrote:

Sorry but I have to dive in here,

Anyone running modbus on a multitasking OS such as linux or windows will never be able to meet the requirements of the serial spec, there is no debate on this, tasking is normally 10ms so meeting 3.5us timing requirement just doesn't fit and never will.

RS485 is balanced 2 wire coms like RS422 and there is no RTS,CTS or any other modem signalling system. If you want to send over RS485, get an RS485 converter and move on this is not a modbus issue. On serial modbus is a poll response protocol so RTS et al are meaningless, read the spec it was designed for embedded systems probably bit bashing IO.

It is even probable that with a modern RS232 chip with buffering meeting the 3.5us in the spec is not possible.

Sorry but anyone trying modbus over serial on a multitasking OS is at the mercy of the external equipment.

see here for converters http://www.usconverters.com/index.php?main_page=index&cPath=65

On 28/09/13 14:33, heming277 wrote:

Hi Galen,

what controller do people use, does the controller have automatic rs-485 half-duplex enable/disable flow control?

thanks

Heming

On Thu, Sep 26, 2013 at 10:43 PM, Galen Collins notifications@github.comwrote:

Okay, so I haven't actually implemented a rs-485 solution with pymodbus. Are you stuck using the half duplex mode? Is there any chance you can just use a full duplex (4 wire) configuration? Otherwise, everyone I have been in contact with has simply used a controller that does the control line detection for them.

I guess you can try to implement it yourself, but it may be a little flakey (I have no clue if this is going to work or not):: monkey patch ModbusSerialClient._send to the following

def _send(self, request): ''' Sends data on the underlying socket

:param request: The encoded request to send :return: The number of bytes written ''' if not self.socket: raise ConnectionException(self.str()) if request: self.socket.setRTS(true) # may need to delay, poll, etc here return self.socket.write(request) return 0

monkey patch ModbusSerialClient._recv to the following

def _recv(self, size): ''' Reads data from the underlying descriptor

:param size: The number of bytes to read :return: The bytes read ''' if not self.socket: raise ConnectionException(self.str()) client.socket.setRTS(false) # you shouldn't have to delay here return self.socket.read(size)

There may be other serial flags that you have to set for the master to give/take control over the line, but this is a quick idea.

— Reply to this email directly or view it on GitHub< https://github.com/bashwork/pymodbus/issues/33#issuecomment-25224214>

.

— Reply to this email directly or view it on GitHub https://github.com/bashwork/pymodbus/issues/33#issuecomment-25290454.

— Reply to this email directly or view it on GitHubhttps://github.com/bashwork/pymodbus/issues/33#issuecomment-25293550 .

ghost commented 10 years ago

on the other hand, why does Modpoll work, their simulation master and slave runs fine over serial RS-485 ..

On Sat, Sep 28, 2013 at 12:30 AM, xvart notifications@github.com wrote:

Sorry but I have to dive in here,

Anyone running modbus on a multitasking OS such as linux or windows will never be able to meet the requirements of the serial spec, there is no debate on this, tasking is normally 10ms so meeting 3.5us timing requirement just doesn't fit and never will.

RS485 is balanced 2 wire coms like RS422 and there is no RTS,CTS or any other modem signalling system. If you want to send over RS485, get an RS485 converter and move on this is not a modbus issue. On serial modbus is a poll response protocol so RTS et al are meaningless, read the spec it was designed for embedded systems probably bit bashing IO.

It is even probable that with a modern RS232 chip with buffering meeting the 3.5us in the spec is not possible.

Sorry but anyone trying modbus over serial on a multitasking OS is at the mercy of the external equipment.

see here for converters http://www.usconverters.com/index.php?main_page=index&cPath=65

On 28/09/13 14:33, heming277 wrote:

Hi Galen,

what controller do people use, does the controller have automatic rs-485 half-duplex enable/disable flow control?

thanks

Heming

On Thu, Sep 26, 2013 at 10:43 PM, Galen Collins notifications@github.comwrote:

Okay, so I haven't actually implemented a rs-485 solution with pymodbus. Are you stuck using the half duplex mode? Is there any chance you can just use a full duplex (4 wire) configuration? Otherwise, everyone I have been in contact with has simply used a controller that does the control line detection for them.

I guess you can try to implement it yourself, but it may be a little flakey (I have no clue if this is going to work or not):: monkey patch ModbusSerialClient._send to the following

def _send(self, request): ''' Sends data on the underlying socket

:param request: The encoded request to send :return: The number of bytes written ''' if not self.socket: raise ConnectionException(self.str()) if request: self.socket.setRTS(true) # may need to delay, poll, etc here return self.socket.write(request) return 0

monkey patch ModbusSerialClient._recv to the following

def _recv(self, size): ''' Reads data from the underlying descriptor

:param size: The number of bytes to read :return: The bytes read ''' if not self.socket: raise ConnectionException(self.str()) client.socket.setRTS(false) # you shouldn't have to delay here return self.socket.read(size)

There may be other serial flags that you have to set for the master to give/take control over the line, but this is a quick idea.

— Reply to this email directly or view it on GitHub< https://github.com/bashwork/pymodbus/issues/33#issuecomment-25224214>

.

— Reply to this email directly or view it on GitHub https://github.com/bashwork/pymodbus/issues/33#issuecomment-25290454.

— Reply to this email directly or view it on GitHubhttps://github.com/bashwork/pymodbus/issues/33#issuecomment-25293550 .

xvart commented 10 years ago

RS422 and RS485 are ballanced lines, you can get over 1km on them with very good data rates and they are immune to noise. RS232 will go about 20m(60ft) before you start having issues this is why we use RS422/485 in industrial aplications.

On 28/09/13 20:40, heming277 wrote:

ok thanks for the informative reply!

this helps very much i've been struggling for a long time.

However as you said even RS-232 is not possible, what's the point of using the RS-232 TO RS-485 converter then.

say if i want to connect from my master box to my slave box, how would i do it.

i have a FTDI USB to RS485 converter like this one https://www.sparkfun.com/products/9822 and i do have a rs-232 to rs-485 converter.

On Sat, Sep 28, 2013 at 12:30 AM, xvart notifications@github.com wrote:

Sorry but I have to dive in here,

Anyone running modbus on a multitasking OS such as linux or windows will never be able to meet the requirements of the serial spec, there is no debate on this, tasking is normally 10ms so meeting 3.5us timing requirement just doesn't fit and never will.

RS485 is balanced 2 wire coms like RS422 and there is no RTS,CTS or any other modem signalling system. If you want to send over RS485, get an RS485 converter and move on this is not a modbus issue. On serial modbus is a poll response protocol so RTS et al are meaningless, read the spec it was designed for embedded systems probably bit bashing IO.

It is even probable that with a modern RS232 chip with buffering meeting the 3.5us in the spec is not possible.

Sorry but anyone trying modbus over serial on a multitasking OS is at the mercy of the external equipment.

see here for converters http://www.usconverters.com/index.php?main_page=index&cPath=65

On 28/09/13 14:33, heming277 wrote:

Hi Galen,

what controller do people use, does the controller have automatic rs-485 half-duplex enable/disable flow control?

thanks

Heming

On Thu, Sep 26, 2013 at 10:43 PM, Galen Collins notifications@github.comwrote:

Okay, so I haven't actually implemented a rs-485 solution with pymodbus. Are you stuck using the half duplex mode? Is there any chance you can just use a full duplex (4 wire) configuration? Otherwise, everyone I have been in contact with has simply used a controller that does the control line detection for them.

I guess you can try to implement it yourself, but it may be a little flakey (I have no clue if this is going to work or not):: monkey patch ModbusSerialClient._send to the following

def _send(self, request): ''' Sends data on the underlying socket

:param request: The encoded request to send :return: The number of bytes written ''' if not self.socket: raise ConnectionException(self.str()) if request: self.socket.setRTS(true) # may need to delay, poll, etc here return self.socket.write(request) return 0

monkey patch ModbusSerialClient._recv to the following

def _recv(self, size): ''' Reads data from the underlying descriptor

:param size: The number of bytes to read :return: The bytes read ''' if not self.socket: raise ConnectionException(self.str()) client.socket.setRTS(false) # you shouldn't have to delay here return self.socket.read(size)

There may be other serial flags that you have to set for the master to give/take control over the line, but this is a quick idea.

— Reply to this email directly or view it on GitHub< https://github.com/bashwork/pymodbus/issues/33#issuecomment-25224214>

.

— Reply to this email directly or view it on GitHub

https://github.com/bashwork/pymodbus/issues/33#issuecomment-25290454.

— Reply to this email directly or view it on GitHubhttps://github.com/bashwork/pymodbus/issues/33#issuecomment-25293550 .

— Reply to this email directly or view it on GitHub https://github.com/bashwork/pymodbus/issues/33#issuecomment-25295846.

xvart commented 10 years ago

If you need to have RTS/CTS and the other modem stuff to trigger the direction on the RS232/RS485 converter you have then this is an issue with your hardware implementation. You may want to check http://www.rs232-to-rs485.com/ for circuits and how they switch disrection, the one shown uses DTR and RTS to do some funky with the converter IC. Find out how your converter works first, then patch the send to toggle the appropriate bits and post the patch. Unfortunately nothing says they will all work the same.

I have used modpoll and simplymodbus to test applications we have and have had no issues bot serial and tcp. If your remote end decides it's going to hold to 3.5 bits your going to have issues. Our current code base interfaces to PLC gear and works ok, I'm moving to pymodbus as I'm sick of maintaining the current code written in C.

On 28/09/13 20:44, heming277 wrote:

on the other hand, why does Modpoll work, their simulation master and slave runs fine over serial RS-485 ..

On Sat, Sep 28, 2013 at 12:30 AM, xvart notifications@github.com wrote:

Sorry but I have to dive in here,

Anyone running modbus on a multitasking OS such as linux or windows will never be able to meet the requirements of the serial spec, there is no debate on this, tasking is normally 10ms so meeting 3.5us timing requirement just doesn't fit and never will.

RS485 is balanced 2 wire coms like RS422 and there is no RTS,CTS or any other modem signalling system. If you want to send over RS485, get an RS485 converter and move on this is not a modbus issue. On serial modbus is a poll response protocol so RTS et al are meaningless, read the spec it was designed for embedded systems probably bit bashing IO.

It is even probable that with a modern RS232 chip with buffering meeting the 3.5us in the spec is not possible.

Sorry but anyone trying modbus over serial on a multitasking OS is at the mercy of the external equipment.

see here for converters http://www.usconverters.com/index.php?main_page=index&cPath=65

On 28/09/13 14:33, heming277 wrote:

Hi Galen,

what controller do people use, does the controller have automatic rs-485 half-duplex enable/disable flow control?

thanks

Heming

On Thu, Sep 26, 2013 at 10:43 PM, Galen Collins notifications@github.comwrote:

Okay, so I haven't actually implemented a rs-485 solution with pymodbus. Are you stuck using the half duplex mode? Is there any chance you can just use a full duplex (4 wire) configuration? Otherwise, everyone I have been in contact with has simply used a controller that does the control line detection for them.

I guess you can try to implement it yourself, but it may be a little flakey (I have no clue if this is going to work or not):: monkey patch ModbusSerialClient._send to the following

def _send(self, request): ''' Sends data on the underlying socket

:param request: The encoded request to send :return: The number of bytes written ''' if not self.socket: raise ConnectionException(self.str()) if request: self.socket.setRTS(true) # may need to delay, poll, etc here return self.socket.write(request) return 0

monkey patch ModbusSerialClient._recv to the following

def _recv(self, size): ''' Reads data from the underlying descriptor

:param size: The number of bytes to read :return: The bytes read ''' if not self.socket: raise ConnectionException(self.str()) client.socket.setRTS(false) # you shouldn't have to delay here return self.socket.read(size)

There may be other serial flags that you have to set for the master to give/take control over the line, but this is a quick idea.

— Reply to this email directly or view it on GitHub< https://github.com/bashwork/pymodbus/issues/33#issuecomment-25224214>

.

— Reply to this email directly or view it on GitHub

https://github.com/bashwork/pymodbus/issues/33#issuecomment-25290454.

— Reply to this email directly or view it on GitHubhttps://github.com/bashwork/pymodbus/issues/33#issuecomment-25293550 .

— Reply to this email directly or view it on GitHub https://github.com/bashwork/pymodbus/issues/33#issuecomment-25295909.

ghost commented 10 years ago

Before I tried a USB to rs232 to rs485 connection, which is connecting USB to master and the A and B data wires to slave device.

Then modpoll didn't work.

If I simply connect 2 wires from rs485 port to the other rs485 port it works..

I'm confuse as to what is the right thing to do here.

Sent from my iPhone

On Sep 28, 2013, at 4:17 AM, xvart notifications@github.com wrote:

If you need to have RTS/CTS and the other modem stuff to trigger the direction on the RS232/RS485 converter you have then this is an issue with your hardware implementation. You may want to check http://www.rs232-to-rs485.com/ for circuits and how they switch disrection, the one shown uses DTR and RTS to do some funky with the converter IC. Find out how your converter works first, then patch the send to toggle the appropriate bits and post the patch. Unfortunately nothing says they will all work the same.

I have used modpoll and simplymodbus to test applications we have and have had no issues bot serial and tcp. If your remote end decides it's going to hold to 3.5 bits your going to have issues. Our current code base interfaces to PLC gear and works ok, I'm moving to pymodbus as I'm sick of maintaining the current code written in C.

On 28/09/13 20:44, heming277 wrote:

on the other hand, why does Modpoll work, their simulation master and slave runs fine over serial RS-485 ..

On Sat, Sep 28, 2013 at 12:30 AM, xvart notifications@github.com wrote:

Sorry but I have to dive in here,

Anyone running modbus on a multitasking OS such as linux or windows will never be able to meet the requirements of the serial spec, there is no debate on this, tasking is normally 10ms so meeting 3.5us timing requirement just doesn't fit and never will.

RS485 is balanced 2 wire coms like RS422 and there is no RTS,CTS or any other modem signalling system. If you want to send over RS485, get an RS485 converter and move on this is not a modbus issue. On serial modbus is a poll response protocol so RTS et al are meaningless, read the spec it was designed for embedded systems probably bit bashing IO.

It is even probable that with a modern RS232 chip with buffering meeting the 3.5us in the spec is not possible.

Sorry but anyone trying modbus over serial on a multitasking OS is at the mercy of the external equipment.

see here for converters http://www.usconverters.com/index.php?main_page=index&cPath=65

On 28/09/13 14:33, heming277 wrote:

Hi Galen,

what controller do people use, does the controller have automatic rs-485 half-duplex enable/disable flow control?

thanks

Heming

On Thu, Sep 26, 2013 at 10:43 PM, Galen Collins notifications@github.comwrote:

Okay, so I haven't actually implemented a rs-485 solution with pymodbus. Are you stuck using the half duplex mode? Is there any chance you can just use a full duplex (4 wire) configuration? Otherwise, everyone I have been in contact with has simply used a controller that does the control line detection for them.

I guess you can try to implement it yourself, but it may be a little flakey (I have no clue if this is going to work or not):: monkey patch ModbusSerialClient._send to the following

def _send(self, request): ''' Sends data on the underlying socket

:param request: The encoded request to send :return: The number of bytes written ''' if not self.socket: raise ConnectionException(self.str()) if request: self.socket.setRTS(true) # may need to delay, poll, etc here return self.socket.write(request) return 0

monkey patch ModbusSerialClient._recv to the following

def _recv(self, size): ''' Reads data from the underlying descriptor

:param size: The number of bytes to read :return: The bytes read ''' if not self.socket: raise ConnectionException(self.str()) client.socket.setRTS(false) # you shouldn't have to delay here return self.socket.read(size)

There may be other serial flags that you have to set for the master to give/take control over the line, but this is a quick idea.

— Reply to this email directly or view it on GitHub< https://github.com/bashwork/pymodbus/issues/33#issuecomment-25224214>

.

— Reply to this email directly or view it on GitHub

https://github.com/bashwork/pymodbus/issues/33#issuecomment-25290454.

— Reply to this email directly or view it on GitHubhttps://github.com/bashwork/pymodbus/issues/33#issuecomment-25293550 .

— Reply to this email directly or view it on GitHub https://github.com/bashwork/pymodbus/issues/33#issuecomment-25295909.

— Reply to this email directly or view it on GitHub.

xvart commented 10 years ago

Get a CRO and make sure the USB device has all the pins connected and these are changing state when you transmit.

If nothing changes state then the pymodbus serial driver may need to change the way it configures the serial port or your kernel driver isn't doing what you think it is.

The RS232->RS485 device uses the modem lines to define direction and can use them to power the converter, you need to work all this out first.

On 29/09/13 06:45, heming277 wrote:

Before I tried a USB to rs232 to rs485 connection, which is connecting USB to master and the A and B data wires to slave device.

Then modpoll didn't work.

If I simply connect 2 wires from rs485 port to the other rs485 port it works..

I'm confuse as to what is the right thing to do here.

Sent from my iPhone

On Sep 28, 2013, at 4:17 AM, xvart notifications@github.com wrote:

If you need to have RTS/CTS and the other modem stuff to trigger the direction on the RS232/RS485 converter you have then this is an issue with your hardware implementation. You may want to check http://www.rs232-to-rs485.com/ for circuits and how they switch disrection, the one shown uses DTR and RTS to do some funky with the converter IC. Find out how your converter works first, then patch the send to toggle the appropriate bits and post the patch. Unfortunately nothing says they will all work the same.

I have used modpoll and simplymodbus to test applications we have and have had no issues bot serial and tcp. If your remote end decides it's going to hold to 3.5 bits your going to have issues. Our current code base interfaces to PLC gear and works ok, I'm moving to pymodbus as I'm sick of maintaining the current code written in C.

On 28/09/13 20:44, heming277 wrote:

on the other hand, why does Modpoll work, their simulation master and slave runs fine over serial RS-485 ..

On Sat, Sep 28, 2013 at 12:30 AM, xvart notifications@github.com wrote:

Sorry but I have to dive in here,

Anyone running modbus on a multitasking OS such as linux or windows will never be able to meet the requirements of the serial spec, there is no debate on this, tasking is normally 10ms so meeting 3.5us timing requirement just doesn't fit and never will.

RS485 is balanced 2 wire coms like RS422 and there is no RTS,CTS or any other modem signalling system. If you want to send over RS485, get an RS485 converter and move on this is not a modbus issue. On serial modbus is a poll response protocol so RTS et al are meaningless, read the spec it was designed for embedded systems probably bit bashing IO.

It is even probable that with a modern RS232 chip with buffering meeting the 3.5us in the spec is not possible.

Sorry but anyone trying modbus over serial on a multitasking OS is at the mercy of the external equipment.

see here for converters http://www.usconverters.com/index.php?main_page=index&cPath=65

On 28/09/13 14:33, heming277 wrote:

Hi Galen,

what controller do people use, does the controller have automatic rs-485 half-duplex enable/disable flow control?

thanks

Heming

On Thu, Sep 26, 2013 at 10:43 PM, Galen Collins notifications@github.comwrote:

Okay, so I haven't actually implemented a rs-485 solution with pymodbus. Are you stuck using the half duplex mode? Is there any chance you can just use a full duplex (4 wire) configuration? Otherwise, everyone I have been in contact with has simply used a controller that does the control line detection for them.

I guess you can try to implement it yourself, but it may be a little flakey (I have no clue if this is going to work or not):: monkey patch ModbusSerialClient._send to the following

def _send(self, request): ''' Sends data on the underlying socket

:param request: The encoded request to send :return: The number of bytes written ''' if not self.socket: raise ConnectionException(self.str()) if request: self.socket.setRTS(true) # may need to delay, poll, etc here return self.socket.write(request) return 0

monkey patch ModbusSerialClient._recv to the following

def _recv(self, size): ''' Reads data from the underlying descriptor

:param size: The number of bytes to read :return: The bytes read ''' if not self.socket: raise ConnectionException(self.str()) client.socket.setRTS(false) # you shouldn't have to delay here return self.socket.read(size)

There may be other serial flags that you have to set for the master to give/take control over the line, but this is a quick idea.

— Reply to this email directly or view it on GitHub<

https://github.com/bashwork/pymodbus/issues/33#issuecomment-25224214>

.

— Reply to this email directly or view it on GitHub

https://github.com/bashwork/pymodbus/issues/33#issuecomment-25290454.

— Reply to this email directly or view it on

GitHubhttps://github.com/bashwork/pymodbus/issues/33#issuecomment-25293550

.

— Reply to this email directly or view it on GitHub

https://github.com/bashwork/pymodbus/issues/33#issuecomment-25295909.

— Reply to this email directly or view it on GitHub.

— Reply to this email directly or view it on GitHub https://github.com/bashwork/pymodbus/issues/33#issuecomment-25308124.

ghost commented 10 years ago

what is a CRO?.

so if i use pymodbus to send out data through RS-232 port and after the converter it becomes RS-485 and it goes to the slave's RS-48 port, that would have auto-flow control as suppose to using just 2 wires for RS-485?

i'm sorry but i'm really noob .. had no experience in these kind of systems.

i just want to know if there's a way to do the way Modpoll is enabling RTS in pymodbus , they do it like enable RTS when send, and disable 1MS after. that worked fine, or using auto-flow control transmitters? if i send data serially through either RS-232 or USB port, modpoll doesn't work.. the ports are already configured as they are on the Linux system .

On Sat, Sep 28, 2013 at 7:55 PM, xvart notifications@github.com wrote:

Get a CRO and make sure the USB device has all the pins connected and these are changing state when you transmit.

If nothing changes state then the pymodbus serial driver may need to change the way it configures the serial port or your kernel driver isn't doing what you think it is.

The RS232->RS485 device uses the modem lines to define direction and can use them to power the converter, you need to work all this out first.

On 29/09/13 06:45, heming277 wrote:

Before I tried a USB to rs232 to rs485 connection, which is connecting USB to master and the A and B data wires to slave device.

Then modpoll didn't work.

If I simply connect 2 wires from rs485 port to the other rs485 port it works..

I'm confuse as to what is the right thing to do here.

Sent from my iPhone

On Sep 28, 2013, at 4:17 AM, xvart notifications@github.com wrote:

If you need to have RTS/CTS and the other modem stuff to trigger the direction on the RS232/RS485 converter you have then this is an issue with your hardware implementation. You may want to check http://www.rs232-to-rs485.com/ for circuits and how they switch disrection, the one shown uses DTR and RTS to do some funky with the converter IC. Find out how your converter works first, then patch the send to toggle the appropriate bits and post the patch. Unfortunately nothing says they will all work the same.

I have used modpoll and simplymodbus to test applications we have and have had no issues bot serial and tcp. If your remote end decides it's going to hold to 3.5 bits your going to have issues. Our current code base interfaces to PLC gear and works ok, I'm moving to pymodbus as I'm sick of maintaining the current code written in C.

On 28/09/13 20:44, heming277 wrote:

on the other hand, why does Modpoll work, their simulation master and slave runs fine over serial RS-485 ..

On Sat, Sep 28, 2013 at 12:30 AM, xvart notifications@github.com wrote:

Sorry but I have to dive in here,

Anyone running modbus on a multitasking OS such as linux or windows will never be able to meet the requirements of the serial spec, there is no debate on this, tasking is normally 10ms so meeting 3.5us timing requirement just doesn't fit and never will.

RS485 is balanced 2 wire coms like RS422 and there is no RTS,CTS or any other modem signalling system. If you want to send over RS485, get an RS485 converter and move on this is not a modbus issue. On serial modbus is a poll response protocol so RTS et al are meaningless, read the spec it was designed for embedded systems probably bit bashing IO.

It is even probable that with a modern RS232 chip with buffering meeting the 3.5us in the spec is not possible.

Sorry but anyone trying modbus over serial on a multitasking OS is at the mercy of the external equipment.

see here for converters http://www.usconverters.com/index.php?main_page=index&cPath=65

On 28/09/13 14:33, heming277 wrote:

Hi Galen,

what controller do people use, does the controller have automatic rs-485 half-duplex enable/disable flow control?

thanks

Heming

On Thu, Sep 26, 2013 at 10:43 PM, Galen Collins notifications@github.comwrote:

Okay, so I haven't actually implemented a rs-485 solution with pymodbus. Are you stuck using the half duplex mode? Is there any chance you can just use a full duplex (4 wire) configuration? Otherwise, everyone I have been in contact with has simply used a controller that does the control line detection for them.

I guess you can try to implement it yourself, but it may be a little flakey (I have no clue if this is going to work or not):: monkey patch ModbusSerialClient._send to the following

def _send(self, request): ''' Sends data on the underlying socket

:param request: The encoded request to send :return: The number of bytes written ''' if not self.socket: raise ConnectionException(self.str()) if request: self.socket.setRTS(true) # may need to delay, poll, etc here return self.socket.write(request) return 0

monkey patch ModbusSerialClient._recv to the following

def _recv(self, size): ''' Reads data from the underlying descriptor

:param size: The number of bytes to read :return: The bytes read ''' if not self.socket: raise ConnectionException(self.str()) client.socket.setRTS(false) # you shouldn't have to delay here return self.socket.read(size)

There may be other serial flags that you have to set for the master to give/take control over the line, but this is a quick idea.

— Reply to this email directly or view it on GitHub<

https://github.com/bashwork/pymodbus/issues/33#issuecomment-25224214>

.

— Reply to this email directly or view it on GitHub

https://github.com/bashwork/pymodbus/issues/33#issuecomment-25290454.

— Reply to this email directly or view it on

GitHub< https://github.com/bashwork/pymodbus/issues/33#issuecomment-25293550>

.

— Reply to this email directly or view it on GitHub

https://github.com/bashwork/pymodbus/issues/33#issuecomment-25295909.

— Reply to this email directly or view it on GitHub.

— Reply to this email directly or view it on GitHub https://github.com/bashwork/pymodbus/issues/33#issuecomment-25308124.

— Reply to this email directly or view it on GitHubhttps://github.com/bashwork/pymodbus/issues/33#issuecomment-25313332 .

xvart commented 10 years ago

Ok using the sync client test app talking to /dev/ttyUSB0 I get from stty -F /dev/ttyUSB0 -a

speed 19200 baud; rows 0; columns 0; line = 0; intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = ; eol2 = ; swtch = ; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min = 0; time = 0; -parenb -parodd cs8 hupcl -cstopb cread clocal -crtscts -ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl -ixon -ixoff -iuclc -ixany -imaxbel -iutf8 -opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0 -isig -icanon -iexten -echo -echoe -echok -echonl -noflsh -xcase -tostop -echoprt

The -crtscts says that hardware flow control is not enabled.

You can tye running the serialclient with a start up delay after it open the port then doing a "stty -F /dev/ttyUSB0 crtscts", and see if that works.

On 29/09/13 06:45, heming277 wrote:

Before I tried a USB to rs232 to rs485 connection, which is connecting USB to master and the A and B data wires to slave device.

Then modpoll didn't work.

If I simply connect 2 wires from rs485 port to the other rs485 port it works..

I'm confuse as to what is the right thing to do here.

Sent from my iPhone

On Sep 28, 2013, at 4:17 AM, xvart notifications@github.com wrote:

If you need to have RTS/CTS and the other modem stuff to trigger the direction on the RS232/RS485 converter you have then this is an issue with your hardware implementation. You may want to check http://www.rs232-to-rs485.com/ for circuits and how they switch disrection, the one shown uses DTR and RTS to do some funky with the converter IC. Find out how your converter works first, then patch the send to toggle the appropriate bits and post the patch. Unfortunately nothing says they will all work the same.

I have used modpoll and simplymodbus to test applications we have and have had no issues bot serial and tcp. If your remote end decides it's going to hold to 3.5 bits your going to have issues. Our current code base interfaces to PLC gear and works ok, I'm moving to pymodbus as I'm sick of maintaining the current code written in C.

On 28/09/13 20:44, heming277 wrote:

on the other hand, why does Modpoll work, their simulation master and slave runs fine over serial RS-485 ..

On Sat, Sep 28, 2013 at 12:30 AM, xvart notifications@github.com wrote:

Sorry but I have to dive in here,

Anyone running modbus on a multitasking OS such as linux or windows will never be able to meet the requirements of the serial spec, there is no debate on this, tasking is normally 10ms so meeting 3.5us timing requirement just doesn't fit and never will.

RS485 is balanced 2 wire coms like RS422 and there is no RTS,CTS or any other modem signalling system. If you want to send over RS485, get an RS485 converter and move on this is not a modbus issue. On serial modbus is a poll response protocol so RTS et al are meaningless, read the spec it was designed for embedded systems probably bit bashing IO.

It is even probable that with a modern RS232 chip with buffering meeting the 3.5us in the spec is not possible.

Sorry but anyone trying modbus over serial on a multitasking OS is at the mercy of the external equipment.

see here for converters http://www.usconverters.com/index.php?main_page=index&cPath=65

On 28/09/13 14:33, heming277 wrote:

Hi Galen,

what controller do people use, does the controller have automatic rs-485 half-duplex enable/disable flow control?

thanks

Heming

On Thu, Sep 26, 2013 at 10:43 PM, Galen Collins notifications@github.comwrote:

Okay, so I haven't actually implemented a rs-485 solution with pymodbus. Are you stuck using the half duplex mode? Is there any chance you can just use a full duplex (4 wire) configuration? Otherwise, everyone I have been in contact with has simply used a controller that does the control line detection for them.

I guess you can try to implement it yourself, but it may be a little flakey (I have no clue if this is going to work or not):: monkey patch ModbusSerialClient._send to the following

def _send(self, request): ''' Sends data on the underlying socket

:param request: The encoded request to send :return: The number of bytes written ''' if not self.socket: raise ConnectionException(self.str()) if request: self.socket.setRTS(true) # may need to delay, poll, etc here return self.socket.write(request) return 0

monkey patch ModbusSerialClient._recv to the following

def _recv(self, size): ''' Reads data from the underlying descriptor

:param size: The number of bytes to read :return: The bytes read ''' if not self.socket: raise ConnectionException(self.str()) client.socket.setRTS(false) # you shouldn't have to delay here return self.socket.read(size)

There may be other serial flags that you have to set for the master to give/take control over the line, but this is a quick idea.

— Reply to this email directly or view it on GitHub<

https://github.com/bashwork/pymodbus/issues/33#issuecomment-25224214>

.

— Reply to this email directly or view it on GitHub

https://github.com/bashwork/pymodbus/issues/33#issuecomment-25290454.

— Reply to this email directly or view it on

GitHubhttps://github.com/bashwork/pymodbus/issues/33#issuecomment-25293550

.

— Reply to this email directly or view it on GitHub

https://github.com/bashwork/pymodbus/issues/33#issuecomment-25295909.

— Reply to this email directly or view it on GitHub.

— Reply to this email directly or view it on GitHub https://github.com/bashwork/pymodbus/issues/33#issuecomment-25308124.

xvart commented 10 years ago

CRO - https://en.wikipedia.org/wiki/Oscilloscope

On 29/09/13 13:09, heming277 wrote:

what is a CRO?.

so if i use pymodbus to send out data through RS-232 port and after the converter it becomes RS-485 and it goes to the slave's RS-48 port, that would have auto-flow control as suppose to using just 2 wires for RS-485?

i'm sorry but i'm really noob .. had no experience in these kind of systems.

i just want to know if there's a way to do the way Modpoll is enabling RTS in pymodbus , they do it like enable RTS when send, and disable 1MS after. that worked fine, or using auto-flow control transmitters? if i send data serially through either RS-232 or USB port, modpoll doesn't work.. the ports are already configured as they are on the Linux system .

On Sat, Sep 28, 2013 at 7:55 PM, xvart notifications@github.com wrote:

Get a CRO and make sure the USB device has all the pins connected and these are changing state when you transmit.

If nothing changes state then the pymodbus serial driver may need to change the way it configures the serial port or your kernel driver isn't doing what you think it is.

The RS232->RS485 device uses the modem lines to define direction and can use them to power the converter, you need to work all this out first.

On 29/09/13 06:45, heming277 wrote:

Before I tried a USB to rs232 to rs485 connection, which is connecting USB to master and the A and B data wires to slave device.

Then modpoll didn't work.

If I simply connect 2 wires from rs485 port to the other rs485 port it works..

I'm confuse as to what is the right thing to do here.

Sent from my iPhone

On Sep 28, 2013, at 4:17 AM, xvart notifications@github.com wrote:

If you need to have RTS/CTS and the other modem stuff to trigger the direction on the RS232/RS485 converter you have then this is an issue with your hardware implementation. You may want to check http://www.rs232-to-rs485.com/ for circuits and how they switch disrection, the one shown uses DTR and RTS to do some funky with the converter IC. Find out how your converter works first, then patch the send to toggle the appropriate bits and post the patch. Unfortunately nothing says they will all work the same.

I have used modpoll and simplymodbus to test applications we have and have had no issues bot serial and tcp. If your remote end decides it's going to hold to 3.5 bits your going to have issues. Our current code base interfaces to PLC gear and works ok, I'm moving to pymodbus as I'm sick of maintaining the current code written in C.

On 28/09/13 20:44, heming277 wrote:

on the other hand, why does Modpoll work, their simulation master and slave runs fine over serial RS-485 ..

On Sat, Sep 28, 2013 at 12:30 AM, xvart notifications@github.com wrote:

Sorry but I have to dive in here,

Anyone running modbus on a multitasking OS such as linux or windows will never be able to meet the requirements of the serial spec, there is no debate on this, tasking is normally 10ms so meeting 3.5us timing requirement just doesn't fit and never will.

RS485 is balanced 2 wire coms like RS422 and there is no RTS,CTS or any other modem signalling system. If you want to send over RS485, get an RS485 converter and move on this is not a modbus issue. On serial modbus is a poll response protocol so RTS et al are meaningless, read the spec it was designed for embedded systems probably bit bashing IO.

It is even probable that with a modern RS232 chip with buffering meeting the 3.5us in the spec is not possible.

Sorry but anyone trying modbus over serial on a multitasking OS is at the mercy of the external equipment.

see here for converters http://www.usconverters.com/index.php?main_page=index&cPath=65

On 28/09/13 14:33, heming277 wrote:

Hi Galen,

what controller do people use, does the controller have automatic rs-485 half-duplex enable/disable flow control?

thanks

Heming

On Thu, Sep 26, 2013 at 10:43 PM, Galen Collins notifications@github.comwrote:

Okay, so I haven't actually implemented a rs-485 solution with pymodbus. Are you stuck using the half duplex mode? Is there any chance you can just use a full duplex (4 wire) configuration? Otherwise, everyone I have been in contact with has simply used a controller that does the control line detection for them.

I guess you can try to implement it yourself, but it may be a little flakey (I have no clue if this is going to work or not):: monkey patch ModbusSerialClient._send to the following

def _send(self, request): ''' Sends data on the underlying socket

:param request: The encoded request to send :return: The number of bytes written ''' if not self.socket: raise ConnectionException(self.str()) if request: self.socket.setRTS(true) # may need to delay, poll, etc here return self.socket.write(request) return 0

monkey patch ModbusSerialClient._recv to the following

def _recv(self, size): ''' Reads data from the underlying descriptor

:param size: The number of bytes to read :return: The bytes read ''' if not self.socket: raise ConnectionException(self.str()) client.socket.setRTS(false) # you shouldn't have to delay here return self.socket.read(size)

There may be other serial flags that you have to set for the master to give/take control over the line, but this is a quick idea.

— Reply to this email directly or view it on GitHub<

https://github.com/bashwork/pymodbus/issues/33#issuecomment-25224214>

.

— Reply to this email directly or view it on GitHub

https://github.com/bashwork/pymodbus/issues/33#issuecomment-25290454.

— Reply to this email directly or view it on

GitHub< https://github.com/bashwork/pymodbus/issues/33#issuecomment-25293550>

.

— Reply to this email directly or view it on GitHub

https://github.com/bashwork/pymodbus/issues/33#issuecomment-25295909.

— Reply to this email directly or view it on GitHub.

— Reply to this email directly or view it on GitHub

https://github.com/bashwork/pymodbus/issues/33#issuecomment-25308124.

— Reply to this email directly or view it on GitHubhttps://github.com/bashwork/pymodbus/issues/33#issuecomment-25313332 .

— Reply to this email directly or view it on GitHub https://github.com/bashwork/pymodbus/issues/33#issuecomment-25313487.

xvart commented 10 years ago

You can try this for laughs and see what happens,

In the sync client, add "client.socket.rtscts=True" to your code after you create the client.

The serial port according to this http://pyserial.sourceforge.net/pyserial_api.html, states that rtscts is normally set to false.

On 29/09/13 13:09, heming277 wrote:

what is a CRO?.

so if i use pymodbus to send out data through RS-232 port and after the converter it becomes RS-485 and it goes to the slave's RS-48 port, that would have auto-flow control as suppose to using just 2 wires for RS-485?

i'm sorry but i'm really noob .. had no experience in these kind of systems.

i just want to know if there's a way to do the way Modpoll is enabling RTS in pymodbus , they do it like enable RTS when send, and disable 1MS after. that worked fine, or using auto-flow control transmitters? if i send data serially through either RS-232 or USB port, modpoll doesn't work.. the ports are already configured as they are on the Linux system .

On Sat, Sep 28, 2013 at 7:55 PM, xvart notifications@github.com wrote:

Get a CRO and make sure the USB device has all the pins connected and these are changing state when you transmit.

If nothing changes state then the pymodbus serial driver may need to change the way it configures the serial port or your kernel driver isn't doing what you think it is.

The RS232->RS485 device uses the modem lines to define direction and can use them to power the converter, you need to work all this out first.

On 29/09/13 06:45, heming277 wrote:

Before I tried a USB to rs232 to rs485 connection, which is connecting USB to master and the A and B data wires to slave device.

Then modpoll didn't work.

If I simply connect 2 wires from rs485 port to the other rs485 port it works..

I'm confuse as to what is the right thing to do here.

Sent from my iPhone

On Sep 28, 2013, at 4:17 AM, xvart notifications@github.com wrote:

If you need to have RTS/CTS and the other modem stuff to trigger the direction on the RS232/RS485 converter you have then this is an issue with your hardware implementation. You may want to check http://www.rs232-to-rs485.com/ for circuits and how they switch disrection, the one shown uses DTR and RTS to do some funky with the converter IC. Find out how your converter works first, then patch the send to toggle the appropriate bits and post the patch. Unfortunately nothing says they will all work the same.

I have used modpoll and simplymodbus to test applications we have and have had no issues bot serial and tcp. If your remote end decides it's going to hold to 3.5 bits your going to have issues. Our current code base interfaces to PLC gear and works ok, I'm moving to pymodbus as I'm sick of maintaining the current code written in C.

On 28/09/13 20:44, heming277 wrote:

on the other hand, why does Modpoll work, their simulation master and slave runs fine over serial RS-485 ..

On Sat, Sep 28, 2013 at 12:30 AM, xvart notifications@github.com wrote:

Sorry but I have to dive in here,

Anyone running modbus on a multitasking OS such as linux or windows will never be able to meet the requirements of the serial spec, there is no debate on this, tasking is normally 10ms so meeting 3.5us timing requirement just doesn't fit and never will.

RS485 is balanced 2 wire coms like RS422 and there is no RTS,CTS or any other modem signalling system. If you want to send over RS485, get an RS485 converter and move on this is not a modbus issue. On serial modbus is a poll response protocol so RTS et al are meaningless, read the spec it was designed for embedded systems probably bit bashing IO.

It is even probable that with a modern RS232 chip with buffering meeting the 3.5us in the spec is not possible.

Sorry but anyone trying modbus over serial on a multitasking OS is at the mercy of the external equipment.

see here for converters http://www.usconverters.com/index.php?main_page=index&cPath=65

On 28/09/13 14:33, heming277 wrote:

Hi Galen,

what controller do people use, does the controller have automatic rs-485 half-duplex enable/disable flow control?

thanks

Heming

On Thu, Sep 26, 2013 at 10:43 PM, Galen Collins notifications@github.comwrote:

Okay, so I haven't actually implemented a rs-485 solution with pymodbus. Are you stuck using the half duplex mode? Is there any chance you can just use a full duplex (4 wire) configuration? Otherwise, everyone I have been in contact with has simply used a controller that does the control line detection for them.

I guess you can try to implement it yourself, but it may be a little flakey (I have no clue if this is going to work or not):: monkey patch ModbusSerialClient._send to the following

def _send(self, request): ''' Sends data on the underlying socket

:param request: The encoded request to send :return: The number of bytes written ''' if not self.socket: raise ConnectionException(self.str()) if request: self.socket.setRTS(true) # may need to delay, poll, etc here return self.socket.write(request) return 0

monkey patch ModbusSerialClient._recv to the following

def _recv(self, size): ''' Reads data from the underlying descriptor

:param size: The number of bytes to read :return: The bytes read ''' if not self.socket: raise ConnectionException(self.str()) client.socket.setRTS(false) # you shouldn't have to delay here return self.socket.read(size)

There may be other serial flags that you have to set for the master to give/take control over the line, but this is a quick idea.

— Reply to this email directly or view it on GitHub<

https://github.com/bashwork/pymodbus/issues/33#issuecomment-25224214>

.

— Reply to this email directly or view it on GitHub

https://github.com/bashwork/pymodbus/issues/33#issuecomment-25290454.

— Reply to this email directly or view it on

GitHub< https://github.com/bashwork/pymodbus/issues/33#issuecomment-25293550>

.

— Reply to this email directly or view it on GitHub

https://github.com/bashwork/pymodbus/issues/33#issuecomment-25295909.

— Reply to this email directly or view it on GitHub.

— Reply to this email directly or view it on GitHub

https://github.com/bashwork/pymodbus/issues/33#issuecomment-25308124.

— Reply to this email directly or view it on GitHubhttps://github.com/bashwork/pymodbus/issues/33#issuecomment-25313332 .

— Reply to this email directly or view it on GitHub https://github.com/bashwork/pymodbus/issues/33#issuecomment-25313487.

ghost commented 10 years ago

how do i do a startup delay?..the serial client specify the paramters and then do a client.connect(), do i put the delay between these?..

i currently do not have my test equipment with me. but even enabling the rts/cts is not automatic flow control right, i still have to manually turn it on or off after sending and receiving data?

thanks

On Sat, Sep 28, 2013 at 8:12 PM, xvart notifications@github.com wrote:

Ok using the sync client test app talking to /dev/ttyUSB0 I get from stty -F /dev/ttyUSB0 -a

speed 19200 baud; rows 0; columns 0; line = 0; intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = ; eol2 = ; swtch = ; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min = 0; time = 0; -parenb -parodd cs8 hupcl -cstopb cread clocal -crtscts -ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl -ixon -ixoff -iuclc -ixany -imaxbel -iutf8 -opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0 -isig -icanon -iexten -echo -echoe -echok -echonl -noflsh -xcase -tostop -echoprt

The -crtscts says that hardware flow control is not enabled.

You can tye running the serialclient with a start up delay after it open the port then doing a "stty -F /dev/ttyUSB0 crtscts", and see if that works.

On 29/09/13 06:45, heming277 wrote:

Before I tried a USB to rs232 to rs485 connection, which is connecting USB to master and the A and B data wires to slave device.

Then modpoll didn't work.

If I simply connect 2 wires from rs485 port to the other rs485 port it works..

I'm confuse as to what is the right thing to do here.

Sent from my iPhone

On Sep 28, 2013, at 4:17 AM, xvart notifications@github.com wrote:

If you need to have RTS/CTS and the other modem stuff to trigger the direction on the RS232/RS485 converter you have then this is an issue with your hardware implementation. You may want to check http://www.rs232-to-rs485.com/ for circuits and how they switch disrection, the one shown uses DTR and RTS to do some funky with the converter IC. Find out how your converter works first, then patch the send to toggle the appropriate bits and post the patch. Unfortunately nothing says they will all work the same.

I have used modpoll and simplymodbus to test applications we have and have had no issues bot serial and tcp. If your remote end decides it's going to hold to 3.5 bits your going to have issues. Our current code base interfaces to PLC gear and works ok, I'm moving to pymodbus as I'm sick of maintaining the current code written in C.

On 28/09/13 20:44, heming277 wrote:

on the other hand, why does Modpoll work, their simulation master and slave runs fine over serial RS-485 ..

On Sat, Sep 28, 2013 at 12:30 AM, xvart notifications@github.com wrote:

Sorry but I have to dive in here,

Anyone running modbus on a multitasking OS such as linux or windows will never be able to meet the requirements of the serial spec, there is no debate on this, tasking is normally 10ms so meeting 3.5us timing requirement just doesn't fit and never will.

RS485 is balanced 2 wire coms like RS422 and there is no RTS,CTS or any other modem signalling system. If you want to send over RS485, get an RS485 converter and move on this is not a modbus issue. On serial modbus is a poll response protocol so RTS et al are meaningless, read the spec it was designed for embedded systems probably bit bashing IO.

It is even probable that with a modern RS232 chip with buffering meeting the 3.5us in the spec is not possible.

Sorry but anyone trying modbus over serial on a multitasking OS is at the mercy of the external equipment.

see here for converters http://www.usconverters.com/index.php?main_page=index&cPath=65

On 28/09/13 14:33, heming277 wrote:

Hi Galen,

what controller do people use, does the controller have automatic rs-485 half-duplex enable/disable flow control?

thanks

Heming

On Thu, Sep 26, 2013 at 10:43 PM, Galen Collins notifications@github.comwrote:

Okay, so I haven't actually implemented a rs-485 solution with pymodbus. Are you stuck using the half duplex mode? Is there any chance you can just use a full duplex (4 wire) configuration? Otherwise, everyone I have been in contact with has simply used a controller that does the control line detection for them.

I guess you can try to implement it yourself, but it may be a little flakey (I have no clue if this is going to work or not):: monkey patch ModbusSerialClient._send to the following

def _send(self, request): ''' Sends data on the underlying socket

:param request: The encoded request to send :return: The number of bytes written ''' if not self.socket: raise ConnectionException(self.str()) if request: self.socket.setRTS(true) # may need to delay, poll, etc here return self.socket.write(request) return 0

monkey patch ModbusSerialClient._recv to the following

def _recv(self, size): ''' Reads data from the underlying descriptor

:param size: The number of bytes to read :return: The bytes read ''' if not self.socket: raise ConnectionException(self.str()) client.socket.setRTS(false) # you shouldn't have to delay here return self.socket.read(size)

There may be other serial flags that you have to set for the master to give/take control over the line, but this is a quick idea.

— Reply to this email directly or view it on GitHub<

https://github.com/bashwork/pymodbus/issues/33#issuecomment-25224214>

.

— Reply to this email directly or view it on GitHub

https://github.com/bashwork/pymodbus/issues/33#issuecomment-25290454.

— Reply to this email directly or view it on

GitHub< https://github.com/bashwork/pymodbus/issues/33#issuecomment-25293550>

.

— Reply to this email directly or view it on GitHub

https://github.com/bashwork/pymodbus/issues/33#issuecomment-25295909.

— Reply to this email directly or view it on GitHub.

— Reply to this email directly or view it on GitHub https://github.com/bashwork/pymodbus/issues/33#issuecomment-25308124.

— Reply to this email directly or view it on GitHubhttps://github.com/bashwork/pymodbus/issues/33#issuecomment-25313523 .

xvart commented 10 years ago

In your client after, "client = ModbusClient(method='rtu', port='/dev/ttyUSB0', timeout=1)" insert the line, "client.socket.rtscts=True"

this enables hardware handshaking, the "crtscts" parameter shown with stty. *

*On 29/09/13 14:08, heming277 wrote:

how do i do a startup delay?..the serial client specify the paramters and then do a client.connect(), do i put the delay between these?..

i currently do not have my test equipment with me. but even enabling the rts/cts is not automatic flow control right, i still have to manually turn it on or off after sending and receiving data?

thanks

On Sat, Sep 28, 2013 at 8:12 PM, xvart notifications@github.com wrote:

Ok using the sync client test app talking to /dev/ttyUSB0 I get from stty -F /dev/ttyUSB0 -a

speed 19200 baud; rows 0; columns 0; line = 0; intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = ; eol2 = ; swtch = ; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min = 0; time = 0; -parenb -parodd cs8 hupcl -cstopb cread clocal -crtscts -ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl -ixon -ixoff -iuclc -ixany -imaxbel -iutf8 -opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0 -isig -icanon -iexten -echo -echoe -echok -echonl -noflsh -xcase -tostop -echoprt

The -crtscts says that hardware flow control is not enabled.

You can tye running the serialclient with a start up delay after it open the port then doing a "stty -F /dev/ttyUSB0 crtscts", and see if that works.

On 29/09/13 06:45, heming277 wrote:

Before I tried a USB to rs232 to rs485 connection, which is connecting USB to master and the A and B data wires to slave device.

Then modpoll didn't work.

If I simply connect 2 wires from rs485 port to the other rs485 port it works..

I'm confuse as to what is the right thing to do here.

Sent from my iPhone

On Sep 28, 2013, at 4:17 AM, xvart notifications@github.com wrote:

If you need to have RTS/CTS and the other modem stuff to trigger the direction on the RS232/RS485 converter you have then this is an issue with your hardware implementation. You may want to check http://www.rs232-to-rs485.com/ for circuits and how they switch disrection, the one shown uses DTR and RTS to do some funky with the converter IC. Find out how your converter works first, then patch the send to toggle the appropriate bits and post the patch. Unfortunately nothing says they will all work the same.

I have used modpoll and simplymodbus to test applications we have and have had no issues bot serial and tcp. If your remote end decides it's going to hold to 3.5 bits your going to have issues. Our current code base interfaces to PLC gear and works ok, I'm moving to pymodbus as I'm sick of maintaining the current code written in C.

On 28/09/13 20:44, heming277 wrote:

on the other hand, why does Modpoll work, their simulation master and slave runs fine over serial RS-485 ..

On Sat, Sep 28, 2013 at 12:30 AM, xvart notifications@github.com wrote:

Sorry but I have to dive in here,

Anyone running modbus on a multitasking OS such as linux or windows will never be able to meet the requirements of the serial spec, there is no debate on this, tasking is normally 10ms so meeting 3.5us timing requirement just doesn't fit and never will.

RS485 is balanced 2 wire coms like RS422 and there is no RTS,CTS or any other modem signalling system. If you want to send over RS485, get an RS485 converter and move on this is not a modbus issue. On serial modbus is a poll response protocol so RTS et al are meaningless, read the spec it was designed for embedded systems probably bit bashing IO.

It is even probable that with a modern RS232 chip with buffering meeting the 3.5us in the spec is not possible.

Sorry but anyone trying modbus over serial on a multitasking OS is at the mercy of the external equipment.

see here for converters http://www.usconverters.com/index.php?main_page=index&cPath=65

On 28/09/13 14:33, heming277 wrote:

Hi Galen,

what controller do people use, does the controller have automatic rs-485 half-duplex enable/disable flow control?

thanks

Heming

On Thu, Sep 26, 2013 at 10:43 PM, Galen Collins notifications@github.comwrote:

Okay, so I haven't actually implemented a rs-485 solution with pymodbus. Are you stuck using the half duplex mode? Is there any chance you can just use a full duplex (4 wire) configuration? Otherwise, everyone I have been in contact with has simply used a controller that does the control line detection for them.

I guess you can try to implement it yourself, but it may be a little flakey (I have no clue if this is going to work or not):: monkey patch ModbusSerialClient._send to the following

def _send(self, request): ''' Sends data on the underlying socket

:param request: The encoded request to send :return: The number of bytes written ''' if not self.socket: raise ConnectionException(self.str()) if request: self.socket.setRTS(true) # may need to delay, poll, etc here return self.socket.write(request) return 0

monkey patch ModbusSerialClient._recv to the following

def _recv(self, size): ''' Reads data from the underlying descriptor

:param size: The number of bytes to read :return: The bytes read ''' if not self.socket: raise ConnectionException(self.str()) client.socket.setRTS(false) # you shouldn't have to delay here return self.socket.read(size)

There may be other serial flags that you have to set for the master to give/take control over the line, but this is a quick idea.

— Reply to this email directly or view it on GitHub<

https://github.com/bashwork/pymodbus/issues/33#issuecomment-25224214>

.

— Reply to this email directly or view it on GitHub

https://github.com/bashwork/pymodbus/issues/33#issuecomment-25290454.

— Reply to this email directly or view it on

GitHub< https://github.com/bashwork/pymodbus/issues/33#issuecomment-25293550>

.

— Reply to this email directly or view it on GitHub

https://github.com/bashwork/pymodbus/issues/33#issuecomment-25295909.

— Reply to this email directly or view it on GitHub.

— Reply to this email directly or view it on GitHub

https://github.com/bashwork/pymodbus/issues/33#issuecomment-25308124.

— Reply to this email directly or view it on GitHubhttps://github.com/bashwork/pymodbus/issues/33#issuecomment-25313523 .

— Reply to this email directly or view it on GitHub https://github.com/bashwork/pymodbus/issues/33#issuecomment-25314083.

ghost commented 10 years ago

i did that the question i was trying to understand is , is it automatic? like when master sends data its rts is high, after it sends it needs to be low immediately.. also using ansynchronous server or synchrounous server from pymodbus, how do you set the rts? do you just do server.setRTS? and how do you know when to set it high or low..

thanks for the help you've given me

On Sat, Sep 28, 2013 at 10:29 PM, xvart notifications@github.com wrote:

In your client after, "client = ModbusClient(method='rtu', port='/dev/ttyUSB0', timeout=1)" insert the line, "client.socket.rtscts=True"

this enables hardware handshaking, the "crtscts" parameter shown with stty. *

*On 29/09/13 14:08, heming277 wrote:

how do i do a startup delay?..the serial client specify the paramters and then do a client.connect(), do i put the delay between these?..

i currently do not have my test equipment with me. but even enabling the rts/cts is not automatic flow control right, i still have to manually turn it on or off after sending and receiving data?

thanks

On Sat, Sep 28, 2013 at 8:12 PM, xvart notifications@github.com wrote:

Ok using the sync client test app talking to /dev/ttyUSB0 I get from stty -F /dev/ttyUSB0 -a

speed 19200 baud; rows 0; columns 0; line = 0; intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = ; eol2 = ; swtch = ; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min = 0; time = 0; -parenb -parodd cs8 hupcl -cstopb cread clocal -crtscts -ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl -ixon -ixoff -iuclc -ixany -imaxbel -iutf8 -opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0 -isig -icanon -iexten -echo -echoe -echok -echonl -noflsh -xcase -tostop -echoprt

The -crtscts says that hardware flow control is not enabled.

You can tye running the serialclient with a start up delay after it open the port then doing a "stty -F /dev/ttyUSB0 crtscts", and see if that works.

On 29/09/13 06:45, heming277 wrote:

Before I tried a USB to rs232 to rs485 connection, which is connecting USB to master and the A and B data wires to slave device.

Then modpoll didn't work.

If I simply connect 2 wires from rs485 port to the other rs485 port it works..

I'm confuse as to what is the right thing to do here.

Sent from my iPhone

On Sep 28, 2013, at 4:17 AM, xvart notifications@github.com wrote:

If you need to have RTS/CTS and the other modem stuff to trigger the direction on the RS232/RS485 converter you have then this is an issue with your hardware implementation. You may want to check http://www.rs232-to-rs485.com/ for circuits and how they switch disrection, the one shown uses DTR and RTS to do some funky with the converter IC. Find out how your converter works first, then patch the send to toggle the appropriate bits and post the patch. Unfortunately nothing says they will all work the same.

I have used modpoll and simplymodbus to test applications we have and have had no issues bot serial and tcp. If your remote end decides it's going to hold to 3.5 bits your going to have issues. Our current code base interfaces to PLC gear and works ok, I'm moving to pymodbus as I'm sick of maintaining the current code written in C.

On 28/09/13 20:44, heming277 wrote:

on the other hand, why does Modpoll work, their simulation master and slave runs fine over serial RS-485 ..

On Sat, Sep 28, 2013 at 12:30 AM, xvart notifications@github.com wrote:

Sorry but I have to dive in here,

Anyone running modbus on a multitasking OS such as linux or windows will never be able to meet the requirements of the serial spec, there is no debate on this, tasking is normally 10ms so meeting 3.5us timing requirement just doesn't fit and never will.

RS485 is balanced 2 wire coms like RS422 and there is no RTS,CTS or any other modem signalling system. If you want to send over RS485, get an RS485 converter and move on this is not a modbus issue. On serial modbus is a poll response protocol so RTS et al are meaningless, read the spec it was designed for embedded systems probably bit bashing IO.

It is even probable that with a modern RS232 chip with buffering meeting the 3.5us in the spec is not possible.

Sorry but anyone trying modbus over serial on a multitasking OS is at the mercy of the external equipment.

see here for converters http://www.usconverters.com/index.php?main_page=index&cPath=65

On 28/09/13 14:33, heming277 wrote:

Hi Galen,

what controller do people use, does the controller have automatic rs-485 half-duplex enable/disable flow control?

thanks

Heming

On Thu, Sep 26, 2013 at 10:43 PM, Galen Collins notifications@github.comwrote:

Okay, so I haven't actually implemented a rs-485 solution with pymodbus. Are you stuck using the half duplex mode? Is there any chance you can just use a full duplex (4 wire) configuration? Otherwise, everyone I have been in contact with has simply used a controller that does the control line detection for them.

I guess you can try to implement it yourself, but it may be a little flakey (I have no clue if this is going to work or not):: monkey patch ModbusSerialClient._send to the following

def _send(self, request): ''' Sends data on the underlying socket

:param request: The encoded request to send :return: The number of bytes written ''' if not self.socket: raise ConnectionException(self.str()) if request: self.socket.setRTS(true) # may need to delay, poll, etc here return self.socket.write(request) return 0

monkey patch ModbusSerialClient._recv to the following

def _recv(self, size): ''' Reads data from the underlying descriptor

:param size: The number of bytes to read :return: The bytes read ''' if not self.socket: raise ConnectionException(self.str()) client.socket.setRTS(false) # you shouldn't have to delay here return self.socket.read(size)

There may be other serial flags that you have to set for the master to give/take control over the line, but this is a quick idea.

— Reply to this email directly or view it on GitHub<

https://github.com/bashwork/pymodbus/issues/33#issuecomment-25224214

.

— Reply to this email directly or view it on GitHub

https://github.com/bashwork/pymodbus/issues/33#issuecomment-25290454.

— Reply to this email directly or view it on

GitHub< https://github.com/bashwork/pymodbus/issues/33#issuecomment-25293550>

.

— Reply to this email directly or view it on GitHub

https://github.com/bashwork/pymodbus/issues/33#issuecomment-25295909.

— Reply to this email directly or view it on GitHub.

— Reply to this email directly or view it on GitHub

https://github.com/bashwork/pymodbus/issues/33#issuecomment-25308124.

— Reply to this email directly or view it on GitHub< https://github.com/bashwork/pymodbus/issues/33#issuecomment-25313523>

.

— Reply to this email directly or view it on GitHub https://github.com/bashwork/pymodbus/issues/33#issuecomment-25314083.

— Reply to this email directly or view it on GitHubhttps://github.com/bashwork/pymodbus/issues/33#issuecomment-25314760 .

xvart commented 10 years ago

RTS/CTS/DTR/CD etc are old modem hardware signal control lines and normally controlled by the RS232 IC, normally something that looks like a 16550, on whatever your computer is. With the correct drivers you can pull the line high but it's the IC's job to do this in the real world. Setting the client.socket.rtscts=True (in this instance socket is a serial object) tells serial.py to turn on hardware handshaking in the seral IC so after that it should be automatic magic.

From what I can tell the async/sync in pymodbus has nothing to do with the serial IO, it's about how pymodbus handles incoming packets.

Did the change work???

On 29/09/13 17:41, heming277 wrote:

i did that the question i was trying to understand is , is it automatic? like when master sends data its rts is high, after it sends it needs to be low immediately.. also using ansynchronous server or synchrounous server from pymodbus, how do you set the rts? do you just do server.setRTS? and how do you know when to set it high or low..

thanks for the help you've given me

On Sat, Sep 28, 2013 at 10:29 PM, xvart notifications@github.com wrote:

In your client after, "client = ModbusClient(method='rtu', port='/dev/ttyUSB0', timeout=1)" insert the line, "client.socket.rtscts=True"

this enables hardware handshaking, the "crtscts" parameter shown with stty. *

*On 29/09/13 14:08, heming277 wrote:

how do i do a startup delay?..the serial client specify the paramters and then do a client.connect(), do i put the delay between these?..

i currently do not have my test equipment with me. but even enabling the rts/cts is not automatic flow control right, i still have to manually turn it on or off after sending and receiving data?

thanks

On Sat, Sep 28, 2013 at 8:12 PM, xvart notifications@github.com wrote:

Ok using the sync client test app talking to /dev/ttyUSB0 I get from stty -F /dev/ttyUSB0 -a

speed 19200 baud; rows 0; columns 0; line = 0; intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol =

; eol2 = ; swtch = ; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min = 0; time = 0; -parenb -parodd cs8 hupcl -cstopb cread clocal -crtscts -ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl -ixon -ixoff -iuclc -ixany -imaxbel -iutf8 -opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0 -isig -icanon -iexten -echo -echoe -echok -echonl -noflsh -xcase -tostop -echoprt The -crtscts says that hardware flow control is not enabled. You can tye running the serialclient with a start up delay after it open the port then doing a "stty -F /dev/ttyUSB0 crtscts", and see if that works. On 29/09/13 06:45, heming277 wrote: > Before I tried a USB to rs232 to rs485 connection, which is > connecting > USB to master and the A and B data wires to slave device. > > Then modpoll didn't work. > > If I simply connect 2 wires from rs485 port to the other rs485 > port it > works.. > > I'm confuse as to what is the right thing to do here. > > Sent from my iPhone > > On Sep 28, 2013, at 4:17 AM, xvart notifications@github.com > wrote: > > > If you need to have RTS/CTS and the other modem stuff to > > trigger > > the > > direction on the RS232/RS485 converter you have then this is an > > issue > > with your hardware implementation. You may want to check > > http://www.rs232-to-rs485.com/ for circuits and how they switch > > disrection, the one shown uses DTR and RTS to do some funky > > with > > the > > converter IC. Find out how your converter works first, then > > patch the > > send to toggle the appropriate bits and post the patch. > > Unfortunately > > nothing says they will all work the same. > > > > I have used modpoll and simplymodbus to test applications we > > have and > > have had no issues bot serial and tcp. If your remote end > > decides it's > > going to hold to 3.5 bits your going to have issues. Our > > current > > code > > base interfaces to PLC gear and works ok, I'm moving to > > pymodbus > > as I'm > > sick of maintaining the current code written in C. > > > > On 28/09/13 20:44, heming277 wrote: > > > > > on the other hand, why does Modpoll work, their simulation > > > master and > > > slave > > > runs fine over serial RS-485 .. > > > > > > On Sat, Sep 28, 2013 at 12:30 AM, xvart > > > notifications@github.com > > > wrote: > > > > > > > Sorry but I have to dive in here, > > > > > > > > Anyone running modbus on a multitasking OS such as linux or > > > > windows > > > > will > > > > never be able to meet the requirements of the serial spec, > > > > there > > > > is no > > > > debate on this, tasking is normally 10ms so meeting 3.5us > > > > timing > > > > requirement just doesn't fit and never will. > > > > > > > > RS485 is balanced 2 wire coms like RS422 and there is no > > > > RTS,CTS > > > > or any > > > > other modem signalling system. If you want to send over > > > > RS485, > > > > get an > > > > RS485 converter and move on this is not a modbus issue. On > > > > serial > > > > modbus > > > > is a poll response protocol so RTS et al are > > > > meaningless, read > > > > the spec > > > > it was designed for embedded systems probably bit > > > > bashing IO. > > > > > > > > It is even probable that with a modern RS232 chip with > > > > buffering > > > > meeting > > > > the 3.5us in the spec is not possible. > > > > > > > > Sorry but anyone trying modbus over serial on a > > > > multitasking OS > > > > is at > > > > the mercy of the external equipment. > > > > > > > > see here for converters > > > > > > > > http://www.usconverters.com/index.php?main_page=index&cPath=65 > > > > > > > > On 28/09/13 14:33, heming277 wrote: > > > > > > > > > Hi Galen, > > > > > > > > > > what controller do people use, does the controller have > > > > > automatic > > > > > rs-485 > > > > > half-duplex enable/disable flow control? > > > > > > > > > > thanks > > > > > > > > > > Heming > > > > > > > > > > On Thu, Sep 26, 2013 at 10:43 PM, Galen Collins > > > > > notifications@github.comwrote: > > > > > > > > > > > Okay, so I haven't actually implemented a rs-485 > > > > > > solution with > > > > > > pymodbus. > > > > > > Are you stuck using the half duplex mode? Is there any > > > > > > chance you > > > > > > can just > > > > > > use a full duplex (4 wire) configuration? Otherwise, > > > > > > everyone I > > > > > > have > > > > > > been > > > > > > in contact with has simply used a controller that > > > > > > does the > > > > > > control line > > > > > > detection for them. > > > > > > > > > > > > I guess you can try to implement it yourself, but it > > > > > > may > > > > > > be a > > > > > > little > > > > > > flakey (I have no clue if this is going to work or > > > > > > not):: > > > > > > monkey patch ModbusSerialClient._send to the following > > > > > > > > > > > > def _send(self, request): > > > > > > ''' Sends data on the underlying socket > > > > > > > > > > > > :param request: The encoded request to send > > > > > > :return: The number of bytes written > > > > > > ''' > > > > > > if not self.socket: > > > > > > raise ConnectionException(self.**str**()) > > > > > > if request: > > > > > > self.socket.setRTS(true) # may need to delay, poll, etc > > > > > > here > > > > > > return self.socket.write(request) > > > > > > return 0 > > > > > > > > > > > > monkey patch ModbusSerialClient._recv to the following > > > > > > > > > > > > def _recv(self, size): > > > > > > ''' Reads data from the underlying descriptor > > > > > > > > > > > > :param size: The number of bytes to read > > > > > > :return: The bytes read > > > > > > ''' > > > > > > if not self.socket: > > > > > > raise ConnectionException(self.**str**()) > > > > > > client.socket.setRTS(false) # you shouldn't have to > > > > > > delay here > > > > > > return self.socket.read(size) > > > > > > > > > > > > There may be other serial flags that you have to set > > > > > > for > > > > > > the > > > > > > master to > > > > > > give/take control over the line, but this is a quick > > > > > > idea. > > > > > > > > > > > > — > > > > > > Reply to this email directly or view it on > > > > > > GitHub< > > https://github.com/bashwork/pymodbus/issues/33#issuecomment-25224214 > > > > > > > . > > > > > > > > > > — > > > > > Reply to this email directly or view it on GitHub

https://github.com/bashwork/pymodbus/issues/33#issuecomment-25290454.

— Reply to this email directly or view it on

GitHub<

https://github.com/bashwork/pymodbus/issues/33#issuecomment-25293550>

.

— Reply to this email directly or view it on GitHub

https://github.com/bashwork/pymodbus/issues/33#issuecomment-25295909.

— Reply to this email directly or view it on GitHub.

— Reply to this email directly or view it on GitHub

https://github.com/bashwork/pymodbus/issues/33#issuecomment-25308124.

— Reply to this email directly or view it on GitHub< https://github.com/bashwork/pymodbus/issues/33#issuecomment-25313523>

.

— Reply to this email directly or view it on GitHub

https://github.com/bashwork/pymodbus/issues/33#issuecomment-25314083.

— Reply to this email directly or view it on GitHubhttps://github.com/bashwork/pymodbus/issues/33#issuecomment-25314760 .

— Reply to this email directly or view it on GitHub https://github.com/bashwork/pymodbus/issues/33#issuecomment-25315954.

ghost commented 10 years ago

well using the

client.socket.rtscts =True returned an error with nonetype object doesn't not have rtscts so i did client.socket = serial.Serial(port='/dev/ttyUSB0', rtscts=True) and then i ran synclient.py

then i run stty -F /dev/usb0 -crstcts doesn't return anything , the code compiles and that's it.. so i don't know if it worked or not?

like i just want to know if there's a way to turn on auto flow control on both the master and slave side, like synchronous client and asynchronous server. and do i need an asynchronous client as well?

thanks

On Sun, Sep 29, 2013 at 1:52 AM, xvart notifications@github.com wrote:

RTS/CTS/DTR/CD etc are old modem hardware signal control lines and normally controlled by the RS232 IC, normally something that looks like a 16550, on whatever your computer is. With the correct drivers you can pull the line high but it's the IC's job to do this in the real world. Setting the client.socket.rtscts=True (in this instance socket is a serial object) tells serial.py to turn on hardware handshaking in the seral IC so after that it should be automatic magic.

From what I can tell the async/sync in pymodbus has nothing to do with the serial IO, it's about how pymodbus handles incoming packets.

Did the change work???

On 29/09/13 17:41, heming277 wrote:

i did that the question i was trying to understand is , is it automatic? like when master sends data its rts is high, after it sends it needs to be low immediately.. also using ansynchronous server or synchrounous server from pymodbus, how do you set the rts? do you just do server.setRTS? and how do you know when to set it high or low..

thanks for the help you've given me

On Sat, Sep 28, 2013 at 10:29 PM, xvart notifications@github.com wrote:

In your client after, "client = ModbusClient(method='rtu', port='/dev/ttyUSB0', timeout=1)" insert the line, "client.socket.rtscts=True"

this enables hardware handshaking, the "crtscts" parameter shown with stty. *

*On 29/09/13 14:08, heming277 wrote:

how do i do a startup delay?..the serial client specify the paramters and then do a client.connect(), do i put the delay between these?..

i currently do not have my test equipment with me. but even enabling the rts/cts is not automatic flow control right, i still have to manually turn it on or off after sending and receiving data?

thanks

On Sat, Sep 28, 2013 at 8:12 PM, xvart notifications@github.com wrote:

Ok using the sync client test app talking to /dev/ttyUSB0 I get from stty -F /dev/ttyUSB0 -a

speed 19200 baud; rows 0; columns 0; line = 0; intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol =

; eol2 = ; swtch = ; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min = 0; time = 0; -parenb -parodd cs8 hupcl -cstopb cread clocal -crtscts -ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl -ixon -ixoff -iuclc -ixany -imaxbel -iutf8 -opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0 -isig -icanon -iexten -echo -echoe -echok -echonl -noflsh -xcase -tostop -echoprt The -crtscts says that hardware flow control is not enabled. You can tye running the serialclient with a start up delay after it open the port then doing a "stty -F /dev/ttyUSB0 crtscts", and see if that works. On 29/09/13 06:45, heming277 wrote: > Before I tried a USB to rs232 to rs485 connection, which is > connecting > USB to master and the A and B data wires to slave device. > > Then modpoll didn't work. > > If I simply connect 2 wires from rs485 port to the other rs485 > port it > works.. > > I'm confuse as to what is the right thing to do here. > > Sent from my iPhone > > On Sep 28, 2013, at 4:17 AM, xvart notifications@github.com > wrote: > > > If you need to have RTS/CTS and the other modem stuff to > > trigger > > the > > direction on the RS232/RS485 converter you have then this is an > > issue > > with your hardware implementation. You may want to check > > http://www.rs232-to-rs485.com/ for circuits and how they > > switch > > disrection, the one shown uses DTR and RTS to do some funky > > with > > the > > converter IC. Find out how your converter works first, then > > patch the > > send to toggle the appropriate bits and post the patch. > > Unfortunately > > nothing says they will all work the same. > > > > I have used modpoll and simplymodbus to test applications we > > have and > > have had no issues bot serial and tcp. If your remote end > > decides it's > > going to hold to 3.5 bits your going to have issues. Our > > current > > code > > base interfaces to PLC gear and works ok, I'm moving to > > pymodbus > > as I'm > > sick of maintaining the current code written in C. > > > > On 28/09/13 20:44, heming277 wrote: > > > > > on the other hand, why does Modpoll work, their simulation > > > master and > > > slave > > > runs fine over serial RS-485 .. > > > > > > On Sat, Sep 28, 2013 at 12:30 AM, xvart > > > notifications@github.com > > > wrote: > > > > > > > Sorry but I have to dive in here, > > > > > > > > Anyone running modbus on a multitasking OS such as linux or > > > > windows > > > > will > > > > never be able to meet the requirements of the serial spec, > > > > there > > > > is no > > > > debate on this, tasking is normally 10ms so meeting 3.5us > > > > timing > > > > requirement just doesn't fit and never will. > > > > > > > > RS485 is balanced 2 wire coms like RS422 and there is no > > > > RTS,CTS > > > > or any > > > > other modem signalling system. If you want to send over > > > > RS485, > > > > get an > > > > RS485 converter and move on this is not a modbus issue. On > > > > serial > > > > modbus > > > > is a poll response protocol so RTS et al are > > > > meaningless, read > > > > the spec > > > > it was designed for embedded systems probably bit > > > > bashing IO. > > > > > > > > It is even probable that with a modern RS232 chip with > > > > buffering > > > > meeting > > > > the 3.5us in the spec is not possible. > > > > > > > > Sorry but anyone trying modbus over serial on a > > > > multitasking OS > > > > is at > > > > the mercy of the external equipment. > > > > > > > > see here for converters > > > > > > > > http://www.usconverters.com/index.php?main_page=index&cPath=65 > > > > > > > > On 28/09/13 14:33, heming277 wrote: > > > > > > > > > Hi Galen, > > > > > > > > > > what controller do people use, does the controller have > > > > > automatic > > > > > rs-485 > > > > > half-duplex enable/disable flow control? > > > > > > > > > > thanks > > > > > > > > > > Heming > > > > > > > > > > On Thu, Sep 26, 2013 at 10:43 PM, Galen Collins > > > > > notifications@github.comwrote: > > > > > > > > > > > Okay, so I haven't actually implemented a rs-485 > > > > > > solution with > > > > > > pymodbus. > > > > > > Are you stuck using the half duplex mode? Is there any > > > > > > chance you > > > > > > can just > > > > > > use a full duplex (4 wire) configuration? Otherwise, > > > > > > everyone I > > > > > > have > > > > > > been > > > > > > in contact with has simply used a controller that > > > > > > does the > > > > > > control line > > > > > > detection for them. > > > > > > > > > > > > I guess you can try to implement it yourself, but it > > > > > > may > > > > > > be a > > > > > > little > > > > > > flakey (I have no clue if this is going to work or > > > > > > not):: > > > > > > monkey patch ModbusSerialClient._send to the following > > > > > > > > > > > > def _send(self, request): > > > > > > ''' Sends data on the underlying socket > > > > > > > > > > > > :param request: The encoded request to send > > > > > > :return: The number of bytes written > > > > > > ''' > > > > > > if not self.socket: > > > > > > raise ConnectionException(self.**str**()) > > > > > > if request: > > > > > > self.socket.setRTS(true) # may need to delay, poll, etc > > > > > > here > > > > > > return self.socket.write(request) > > > > > > return 0 > > > > > > > > > > > > monkey patch ModbusSerialClient._recv to the following > > > > > > > > > > > > def _recv(self, size): > > > > > > ''' Reads data from the underlying descriptor > > > > > > > > > > > > :param size: The number of bytes to read > > > > > > :return: The bytes read > > > > > > ''' > > > > > > if not self.socket: > > > > > > raise ConnectionException(self.**str**()) > > > > > > client.socket.setRTS(false) # you shouldn't have to > > > > > > delay here > > > > > > return self.socket.read(size) > > > > > > > > > > > > There may be other serial flags that you have to set > > > > > > for > > > > > > the > > > > > > master to > > > > > > give/take control over the line, but this is a quick > > > > > > idea. > > > > > > > > > > > > — > > > > > > Reply to this email directly or view it on > > > > > > GitHub< > > https://github.com/bashwork/pymodbus/issues/33#issuecomment-25224214 > > > > > > > . > > > > > > > > > > — > > > > > Reply to this email directly or view it on GitHub

https://github.com/bashwork/pymodbus/issues/33#issuecomment-25290454.

— Reply to this email directly or view it on

GitHub<

https://github.com/bashwork/pymodbus/issues/33#issuecomment-25293550>

.

— Reply to this email directly or view it on GitHub

https://github.com/bashwork/pymodbus/issues/33#issuecomment-25295909.

— Reply to this email directly or view it on GitHub.

— Reply to this email directly or view it on GitHub

https://github.com/bashwork/pymodbus/issues/33#issuecomment-25308124.

— Reply to this email directly or view it on GitHub< https://github.com/bashwork/pymodbus/issues/33#issuecomment-25313523>

.

— Reply to this email directly or view it on GitHub

https://github.com/bashwork/pymodbus/issues/33#issuecomment-25314083.

— Reply to this email directly or view it on GitHub< https://github.com/bashwork/pymodbus/issues/33#issuecomment-25314760>

.

— Reply to this email directly or view it on GitHub https://github.com/bashwork/pymodbus/issues/33#issuecomment-25315954.

— Reply to this email directly or view it on GitHubhttps://github.com/bashwork/pymodbus/issues/33#issuecomment-25316775 .

bashwork commented 10 years ago

Right now you will have to do the second assignment you did (client.socket = serial.Socket) as I don't currently pass all the configuration flags to the Serial constructor. I will make a fix for this.

When you set rtscts = True, pyserial is effectively going to set the ioctl that enables that in the serial driver. So if this is supported by your device driver/device (it should be), then you should be good to go.

As for the master side, you should be able to set that as well in just the same manner. If you want to play with various settings on a single box (say to emulate various serial servers), use http://www.modbusdriver.com/diagslave.html or start a synchronous/asynchronous pymodbus server with the options you care to test with. If you need to set up null modem support (if you don't have a cable), here are some options that you can use to set up a software loopback: https://github.com/bashwork/pymodbus/tree/master/examples/tools/nullmodem

The synchronous and asynchronous servers/clients are for two different purposes:

  1. async uses the twisted framework to run a high performance event based service. This basically tries to remove all blocking operations from your code (io) and have the kernel do them for you, and let you know when they are finished. You can think of it like:

while (running): io_events = get_io_events() # kernel code distribute(io_events) # your non-blocking code

  1. sync uses python threads to simply do everything in one go. The problem with this is that python is really bad at threading as the whole interpreter has to stop to switch threads.

The decision to use one over the other is basically asking the following questions:

  1. Do I need high performance (say monitoring a data center for devices). If so, use the async client.
  2. Do I need to quickly script a modbus solution. If so, use the sync client.
  3. Do I need to run on a platform where twisted isn't available. If so, use the sync client/server.
  4. Do I need to run a modbus server. Ideally use the async server.
ghost commented 10 years ago

is there a way i can check that RTS is enabled or not?

using the STTY method it just takes me to a new command line doesn't show anything in terminal.

does that mean it succeeded?

thanks

On Mon, Sep 30, 2013 at 1:04 PM, Galen Collins notifications@github.comwrote:

Right now you will have to do the second assignment you did (client.socket = serial.Socket) as I don't currently pass all the configuration flags to the Serial constructor. I will make a fix for this.

When you set rtscts = True, pyserial is effectively going to set the ioctl that enables that in the serial driver. So if this is supported by your device driver/device (it should be), then you should be good to go.

As for the master side, you should be able to set that as well in just the same manner. If you want to play with various settings on a single box (say to emulate various serial servers), use http://www.modbusdriver.com/diagslave.html or start a synchronous/asynchronous pymodbus server with the options you care to test with. If you need to set up null modem support (if you don't have a cable), here are some options that you can use to set up a software loopback: https://github.com/bashwork/pymodbus/tree/master/examples/tools/nullmodem

The synchronous and asynchronous servers/clients are for two different purposes:

  1. async uses the twisted framework to run a high performance event based service. This basically tries to remove all blocking operations from your code (io) and have the kernel do them for you, and let you know when they are finished. You can think of it like:

while (running): io_events = get_io_events() # kernel code distribute(io_events) # your non-blocking code

  1. sync uses python threads to simply do everything in one go. The problem with this is that python is really bad at threading as the whole interpreter has to stop to switch threads.

The decision to use one over the other is basically asking the following questions:

  1. Do I need high performance (say monitoring a data center for devices). If so, use the async client.
  2. Do I need to quickly script a modbus solution. If so, use the sync client.
  3. Do I need to run on a platform where twisted isn't available. If so, use the sync client/server.
  4. Do I need to run a modbus server. Ideally use the async server.

— Reply to this email directly or view it on GitHubhttps://github.com/bashwork/pymodbus/issues/33#issuecomment-25399872 .

bashwork commented 10 years ago

stty --all -F /dev/usb0

Should show you the current settings for the device.

ghost commented 10 years ago

yes it does show me the baudrate.. stty --all -F /dev/ttyS2 speed 9600 baud; rows 0; columns 0; line = 0; intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = ; eol2 = ; swtch = ; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min = 0; time = 0; -parenb -parodd cs8 -hupcl -cstopb cread clocal crtscts -cdtrdsr -ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl -ixon -ixoff -iuclc -ixany -imaxbel -iutf8 -opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0 -isig -icanon -iexten -echo -echoe -echok -echonl -noflsh -xcase -tostop -echoprt

i see this, where does this show me the status of RTS

On Tue, Oct 1, 2013 at 9:51 AM, Galen Collins notifications@github.comwrote:

stty --all -F /dev/usb0

Should show you the current settings for the device.

— Reply to this email directly or view it on GitHubhttps://github.com/bashwork/pymodbus/issues/33#issuecomment-25467800 .

bashwork commented 10 years ago

... -parenb -parodd cs8 -hupcl -cstopb cread clocal crtscts -cdtrdsr ...

A prefix of - indicates a negation, it is enabled in this case.

ghost commented 10 years ago

so here is my sync client code

!/usr/bin/python2.4

'''

Pymodbus Synchronous Client Examples

The following is an example of how to use the synchronous modbus client implementation from pymodbus.

It should be noted that the client can also be used with the guard construct that is available in python 2.5 and up::

with ModbusClient('127.0.0.1') as client:
        result = client.read_coils(1,10)
                print result
                '''

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

import the various server implementations

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

from pymodbus.client.sync import ModbusTcpClient as ModbusClient

from pymodbus.client.sync import ModbusUdpClient as ModbusClient

from pymodbus.client.sync import ModbusSerialClient as ModbusClient import serial,time

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

configure the client logging

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

import logging logging.basicConfig() log = logging.getLogger() log.setLevel(logging.DEBUG)

client = ModbusClient('localhost', port=502)

client = ModbusClient(method='ascii', port='/dev/pts/2', timeout=1)

client = ModbusClient(method='rtu', retry_on_empty=True, retries=10, port='/dev\ /ttyS2', timeout=1, bytesize=8, baudrate=9600, stopbits=1, parity='E') client.socket = serial.Serial(rtscts=True, port='/dev/ttyS2') client.connect()

rq = client.write_register(1, 10, unit = 0X01) rr = client.read_holding_registers(1, 5, unit = 0X01) assert(rq.function_code < 0x80) # test that we are not an error assert(rr.registers[0] == 10) # test the expected value

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

close the client

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

client.close()

And then my sync server code is

!/usr/bin/python2.4

'''

Pymodbus Asynchronous Server Example

The asynchronous server is a high performance implementation using the twisted library as its backend. This allows it to scale to many thousands of nodes which can be helpful for testing monitoring software. '''

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

import the various server implementations

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

from pymodbus.server.async import StartTcpServer from pymodbus.server.async import StartUdpServer from pymodbus.server.sync import StartSerialServer from pymodbus.server.sync import ModbusSerialServer as ModbusServer from pymodbus.device import ModbusDeviceIdentification from pymodbus.datastore import ModbusSequentialDataBlock from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext from pymodbus.transaction import ModbusRtuFramer, ModbusAsciiFramer import serial,time

import logging logging.basicConfig() log = logging.getLogger() log.setLevel(logging.DEBUG)

slaves = { 0X01: ModbusSlaveContext( di = ModbusSequentialDataBlock(1, [17,18,19,20,21,22])), 0X02: ModbusSlaveContext( dd = ModbusSequentialDataBlock(1, [17]*100)), }

context = ModbusServerContext(slaves=slaves, single=False)

server = ModbusServer(context,identity=identity, port='/dev/ttyS2', timeout=1, \ bytesize=8, baudrate=9600, stopbits=1, parity='E')

server.socket = serial.Serial(port='/dev/ttyS2', rtscts=True)

StartTcpServer(context, identity=identity, address=("localhost", 5020))

StartUdpServer(context, identity=identity, address=("localhost", 502))

StartSerialServer(context, identity=identity, port='/dev/ttyS2', timeout=1, byt\ esize=8, baudrate=9600, stopbits=1, parity='E')

StartSerialServer(context, identity=identity, port='/dev/pts/3',

framer=Modbus\ AsciiFramer)

However with the added client = serial.Serial(rtscts=True)

it gives me an error like this python synclient.py DEBUG:pymodbus.transaction:Running transaction 1 Traceback (most recent call last): File "synclient.py", line 84, in ? rq = client.write_register(1, 10, unit = 0X01) File "/usr/lib/python2.4/site-packages/pymodbus-1.2.0-py2.4.egg/pymodbus/client/common.py", line 87, in write_register return self.execute(request) File "/usr/lib/python2.4/site-packages/pymodbus-1.2.0-py2.4.egg/pymodbus/client/sync.py", line 83, in execute return self.transaction.execute(request) File "/usr/lib/python2.4/site-packages/pymodbus-1.2.0-py2.4.egg/pymodbus/transaction.py", line 65, in execute result = self.client._recv(1024) File "/usr/lib/python2.4/site-packages/pymodbus-1.2.0-py2.4.egg/pymodbus/client/sync.py", line 359, in recv return self.socket.read(size) File "/usr/lib/python2.4/site-packages/pyserial-2.6-py2.4.egg/serial/serialposix.py", line 446, in read ready,,_ = select.select([self.fd],[],[], self._timeout) KeyboardInterrupt

it seems to get hanged on serialposix line 446..

what is causing this?

if however i remove the line client= serial.Serial..

i get none type attribute error..

thanks

On Tue, Oct 1, 2013 at 9:51 AM, Galen Collins notifications@github.comwrote:

stty --all -F /dev/usb0

Should show you the current settings for the device.

— Reply to this email directly or view it on GitHubhttps://github.com/bashwork/pymodbus/issues/33#issuecomment-25467800 .

ghost commented 10 years ago

so i think i know what problem i have. i check on the server side, using stty --all -F /dev/ttyS2, the rtscts is not enabled by the code i did here

server = ModbusServer(context,identity=identity, port='/dev/ttyS2', timeout=1, bytesize=8, baudrate=9600, stopbits=1, parity='E')

server.socket = serial.Serial(port='/dev/ttyS2', rtscts=True)

Also after the code StartSerialServer(context, identity=identity, port='/dev/ttyS2', timeout=1, byt\ esize=8, baudrate=9600, stopbits=1, parity='E')

i must exit the server to check RTS status..

not sure what's wrong here. how do i basically set RTS when using Sync or Async Server?

thank you very much

On Tue, Oct 1, 2013 at 1:39 PM, Heming Liu hemingliu123@gmail.com wrote:

so here is my sync client code

!/usr/bin/python2.4

'''

Pymodbus Synchronous Client Examples

The following is an example of how to use the synchronous modbus client implementation from pymodbus.

It should be noted that the client can also be used with the guard construct that is available in python 2.5 and up::

with ModbusClient('127.0.0.1') as client:
        result = client.read_coils(1,10)
                print result
                '''

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

import the various server implementations

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

from pymodbus.client.sync import ModbusTcpClient as ModbusClient

from pymodbus.client.sync import ModbusUdpClient as ModbusClient

from pymodbus.client.sync import ModbusSerialClient as ModbusClient import serial,time

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

configure the client logging

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

import logging logging.basicConfig() log = logging.getLogger() log.setLevel(logging.DEBUG)

client = ModbusClient('localhost', port=502)

client = ModbusClient(method='ascii', port='/dev/pts/2', timeout=1)

client = ModbusClient(method='rtu', retry_on_empty=True, retries=10, port='/dev\ /ttyS2', timeout=1, bytesize=8, baudrate=9600, stopbits=1, parity='E') client.socket = serial.Serial(rtscts=True, port='/dev/ttyS2') client.connect()

rq = client.write_register(1, 10, unit = 0X01) rr = client.read_holding_registers(1, 5, unit = 0X01) assert(rq.function_code < 0x80) # test that we are not an error assert(rr.registers[0] == 10) # test the expected value

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

close the client

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

client.close()

And then my sync server code is

!/usr/bin/python2.4

'''

Pymodbus Asynchronous Server Example

The asynchronous server is a high performance implementation using the twisted library as its backend. This allows it to scale to many thousands of nodes which can be helpful for testing monitoring software. '''

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

import the various server implementations

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

from pymodbus.server.async import StartTcpServer from pymodbus.server.async import StartUdpServer from pymodbus.server.sync import StartSerialServer from pymodbus.server.sync import ModbusSerialServer as ModbusServer from pymodbus.device import ModbusDeviceIdentification from pymodbus.datastore import ModbusSequentialDataBlock from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext from pymodbus.transaction import ModbusRtuFramer, ModbusAsciiFramer import serial,time

import logging logging.basicConfig() log = logging.getLogger() log.setLevel(logging.DEBUG)

slaves = { 0X01: ModbusSlaveContext( di = ModbusSequentialDataBlock(1, [17,18,19,20,21,22])), 0X02: ModbusSlaveContext( dd = ModbusSequentialDataBlock(1, [17]*100)), }

context = ModbusServerContext(slaves=slaves, single=False)

server = ModbusServer(context,identity=identity, port='/dev/ttyS2', timeout=1, \ bytesize=8, baudrate=9600, stopbits=1, parity='E')

server.socket = serial.Serial(port='/dev/ttyS2', rtscts=True)

StartTcpServer(context, identity=identity, address=("localhost", 5020))

StartUdpServer(context, identity=identity, address=("localhost", 502))

StartSerialServer(context, identity=identity, port='/dev/ttyS2', timeout=1, byt\ esize=8, baudrate=9600, stopbits=1, parity='E')

StartSerialServer(context, identity=identity, port='/dev/pts/3',

framer=Modbus\ AsciiFramer)

However with the added client = serial.Serial(rtscts=True)

it gives me an error like this python synclient.py DEBUG:pymodbus.transaction:Running transaction 1 Traceback (most recent call last): File "synclient.py", line 84, in ? rq = client.write_register(1, 10, unit = 0X01) File "/usr/lib/python2.4/site-packages/pymodbus-1.2.0-py2.4.egg/pymodbus/client/common.py", line 87, in write_register return self.execute(request) File "/usr/lib/python2.4/site-packages/pymodbus-1.2.0-py2.4.egg/pymodbus/client/sync.py", line 83, in execute return self.transaction.execute(request) File "/usr/lib/python2.4/site-packages/pymodbus-1.2.0-py2.4.egg/pymodbus/transaction.py", line 65, in execute result = self.client._recv(1024) File "/usr/lib/python2.4/site-packages/pymodbus-1.2.0-py2.4.egg/pymodbus/client/sync.py", line 359, in recv return self.socket.read(size) File "/usr/lib/python2.4/site-packages/pyserial-2.6-py2.4.egg/serial/serialposix.py", line 446, in read ready,,_ = select.select([self.fd],[],[], self._timeout) KeyboardInterrupt

it seems to get hanged on serialposix line 446..

what is causing this?

if however i remove the line client= serial.Serial..

i get none type attribute error..

thanks

On Tue, Oct 1, 2013 at 9:51 AM, Galen Collins notifications@github.comwrote:

stty --all -F /dev/usb0

Should show you the current settings for the device.

— Reply to this email directly or view it on GitHubhttps://github.com/bashwork/pymodbus/issues/33#issuecomment-25467800 .

bashwork commented 10 years ago

Here is what I would recommend that you do, write a simple serial program for your server and client that simply ping pong with each other (something like this):

import serial, sys

def server(socket):
    while (true):        
        ping = socket.read(4)
        print "ponging a ping"
        if ping == "pong":
            socket.write("pong")

def client(socket):
     while True:
         count = socket.write("ping")
         if count < 4:
             print "failed to ping"
             continue
         pong = socket.read(4)
         if pong == "pong": print "ping was ponged"

if __name__ == "__main__":
    socket = serial.Serial(...)
    if sys.argv[1] == "server":
        server(socket)
    else: client(socket)

Then play with your serial connection settings until you can get this to work. Don't worry about modbus for now. When you get this working, simply replace the serial socket settings you used in the modbus code and you should be good to go.

xvart commented 10 years ago

The "crtscts" stands for rts cts lines, this says it is being used, when showing as "-crtscts" it is disabled.

The printout says hardware flow control is on.

On 02/10/13 05:55, heming277 wrote:

yes it does show me the baudrate.. stty --all -F /dev/ttyS2 speed 9600 baud; rows 0; columns 0; line = 0; intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = ; eol2 = ; swtch = ; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min = 0; time = 0; -parenb -parodd cs8 -hupcl -cstopb cread clocal crtscts -cdtrdsr -ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl -ixon -ixoff -iuclc -ixany -imaxbel -iutf8 -opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0 -isig -icanon -iexten -echo -echoe -echok -echonl -noflsh -xcase -tostop -echoprt

i see this, where does this show me the status of RTS

On Tue, Oct 1, 2013 at 9:51 AM, Galen Collins notifications@github.comwrote:

stty --all -F /dev/usb0

Should show you the current settings for the device.

— Reply to this email directly or view it on GitHubhttps://github.com/bashwork/pymodbus/issues/33#issuecomment-25467800 .

— Reply to this email directly or view it on GitHub https://github.com/bashwork/pymodbus/issues/33#issuecomment-25482794.

ghost commented 10 years ago

ok so i think i found the reason

using client.socket = serial.Serial(rtscts=True) doesn't send anything or recive anything for some reason

i have to set RTS using client.socket.setRTS(True) and False

in the ping pong example, i used socket.setRTS(True) and socket.setRTS(False) and it worked

the problem is. with Modbus it doesn't work

the modifications i made to Sync.py under ModbusSerialClient source code is this

def _send(self, request): ''' Sends data on the underlying socket

    :param request: The encoded request to send
    :return: The number of bytes written
    '''
    #self.socket = serial.Serial(port='/dev/ttyS2', timeout=1,

baudrate=192\ 00, stopbits=serial.STOPBITS_ONE, parity=serial.PARITY_EVEN, bytesize=serial.EI\ GHTBITS) (Not sure if i need this line or not, seems to be no help, it also resets baudrate and everything to be what's declared here) if not self.socket: raise ConnectionException(self.str())

    if request:
       self.socket.setRTS(True)
       return self.socket.write(request)
       time.sleep(0.0025)
       self.socket.setRTS(False)
    return 0

def _recv(self, size): ''' Reads data from the underlying descriptor

    :param size: The number of bytes to read
    :return: The bytes read
    '''
    if not self.socket:
        raise ConnectionException(self.__str__())
    self.socket.setRTS(False)
    return self.socket.read(size)

and the modification i made to the server's Sync.py the SingleRequestHandler codes are below

def send(self, message): ''' Send a request (string) to the network

    :param message: The unencoded modbus response
    '''
    self.socket = serial.Serial(port='/dev/ttyS2', baudrate=19200,

timeout=\ 1, parity=serial.PARITY_EVEN, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIG\ HTBITS) if message.should_respond:

self.server.control.Counter.BusMessage += 1

        pdu = self.framer.buildPacket(message)
        if _logger.isEnabledFor(logging.DEBUG):
            _logger.debug('send: %s' % b2a_hex(pdu))
        self.socket.setRTS(True)
        return self.request.send(pdu)
        time.sleep(0.0025)
        self.socket.setRTS(False)

and i made modification to Asyn Server's UDP server's execute method, not sure if UDP server is used for serial

def _execute(self, request, addr): ''' Executes the request and returns the result

    :param request: The decoded request message
    '''
    self.socket = serial.Serial(port='/dev/ttyS2', baudrate=19200,

timeout=\ 1, parity=serial.PARITY_EVEN, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIG\ HTBITS) try: context = self.store[request.unit_id] response = request.execute(context) except Exception, ex: _logger.debug("Datastore unable to fulfill request: %s" % ex) response = request.doException(merror.SlaveFailure)

self.framer.populateResult(response)

    response.transaction_id = request.transaction_id
    response.unit_id = request.unit_id
    self.socket.setRTS(True)
    self._send(response, addr)
    time.sleep(0.0025)
    self.socket.setRTS(False)

Could anyone help me out? i think i'm getting close

thank you guys very much

On Mon, Sep 30, 2013 at 1:04 PM, Galen Collins notifications@github.comwrote:

Right now you will have to do the second assignment you did (client.socket = serial.Socket) as I don't currently pass all the configuration flags to the Serial constructor. I will make a fix for this.

When you set rtscts = True, pyserial is effectively going to set the ioctl that enables that in the serial driver. So if this is supported by your device driver/device (it should be), then you should be good to go.

As for the master side, you should be able to set that as well in just the same manner. If you want to play with various settings on a single box (say to emulate various serial servers), use http://www.modbusdriver.com/diagslave.html or start a synchronous/asynchronous pymodbus server with the options you care to test with. If you need to set up null modem support (if you don't have a cable), here are some options that you can use to set up a software loopback: https://github.com/bashwork/pymodbus/tree/master/examples/tools/nullmodem

The synchronous and asynchronous servers/clients are for two different purposes:

  1. async uses the twisted framework to run a high performance event based service. This basically tries to remove all blocking operations from your code (io) and have the kernel do them for you, and let you know when they are finished. You can think of it like:

while (running): io_events = get_io_events() # kernel code distribute(io_events) # your non-blocking code

  1. sync uses python threads to simply do everything in one go. The problem with this is that python is really bad at threading as the whole interpreter has to stop to switch threads.

The decision to use one over the other is basically asking the following questions:

  1. Do I need high performance (say monitoring a data center for devices). If so, use the async client.
  2. Do I need to quickly script a modbus solution. If so, use the sync client.
  3. Do I need to run on a platform where twisted isn't available. If so, use the sync client/server.
  4. Do I need to run a modbus server. Ideally use the async server.

— Reply to this email directly or view it on GitHubhttps://github.com/bashwork/pymodbus/issues/33#issuecomment-25399872 .

ghost commented 10 years ago

the error it gives me right now is that it is still getting None same errors as before..

On Wed, Oct 2, 2013 at 5:55 PM, Heming Liu hemingliu123@gmail.com wrote:

ok so i think i found the reason

using client.socket = serial.Serial(rtscts=True) doesn't send anything or recive anything for some reason

i have to set RTS using client.socket.setRTS(True) and False

in the ping pong example, i used socket.setRTS(True) and socket.setRTS(False) and it worked

the problem is. with Modbus it doesn't work

the modifications i made to Sync.py under ModbusSerialClient source code is this

def _send(self, request): ''' Sends data on the underlying socket

    :param request: The encoded request to send
    :return: The number of bytes written
    '''
    #self.socket = serial.Serial(port='/dev/ttyS2', timeout=1,

baudrate=192\ 00, stopbits=serial.STOPBITS_ONE, parity=serial.PARITY_EVEN, bytesize=serial.EI\ GHTBITS) (Not sure if i need this line or not, seems to be no help, it also resets baudrate and everything to be what's declared here)

    if not self.socket:
        raise ConnectionException(self.__str__())

    if request:
       self.socket.setRTS(True)
       return self.socket.write(request)
       time.sleep(0.0025)
       self.socket.setRTS(False)
    return 0

def _recv(self, size): ''' Reads data from the underlying descriptor

    :param size: The number of bytes to read
    :return: The bytes read
    '''
    if not self.socket:
        raise ConnectionException(self.__str__())
    self.socket.setRTS(False)
    return self.socket.read(size)

and the modification i made to the server's Sync.py the SingleRequestHandler codes are below

def send(self, message): ''' Send a request (string) to the network

    :param message: The unencoded modbus response
    '''
    self.socket = serial.Serial(port='/dev/ttyS2', baudrate=19200,

timeout=\ 1, parity=serial.PARITY_EVEN, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIG\ HTBITS) if message.should_respond:

self.server.control.Counter.BusMessage += 1

        pdu = self.framer.buildPacket(message)
        if _logger.isEnabledFor(logging.DEBUG):
            _logger.debug('send: %s' % b2a_hex(pdu))
        self.socket.setRTS(True)
        return self.request.send(pdu)
        time.sleep(0.0025)
        self.socket.setRTS(False)

and i made modification to Asyn Server's UDP server's execute method, not sure if UDP server is used for serial

def _execute(self, request, addr): ''' Executes the request and returns the result

    :param request: The decoded request message
    '''
    self.socket = serial.Serial(port='/dev/ttyS2', baudrate=19200,

timeout=\ 1, parity=serial.PARITY_EVEN, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIG\ HTBITS) try: context = self.store[request.unit_id] response = request.execute(context) except Exception, ex: _logger.debug("Datastore unable to fulfill request: %s" % ex) response = request.doException(merror.SlaveFailure)

self.framer.populateResult(response)

    response.transaction_id = request.transaction_id
    response.unit_id = request.unit_id
    self.socket.setRTS(True)
    self._send(response, addr)
    time.sleep(0.0025)
    self.socket.setRTS(False)

Could anyone help me out? i think i'm getting close

thank you guys very much

On Mon, Sep 30, 2013 at 1:04 PM, Galen Collins notifications@github.comwrote:

Right now you will have to do the second assignment you did (client.socket = serial.Socket) as I don't currently pass all the configuration flags to the Serial constructor. I will make a fix for this.

When you set rtscts = True, pyserial is effectively going to set the ioctl that enables that in the serial driver. So if this is supported by your device driver/device (it should be), then you should be good to go.

As for the master side, you should be able to set that as well in just the same manner. If you want to play with various settings on a single box (say to emulate various serial servers), use http://www.modbusdriver.com/diagslave.html or start a synchronous/asynchronous pymodbus server with the options you care to test with. If you need to set up null modem support (if you don't have a cable), here are some options that you can use to set up a software loopback: https://github.com/bashwork/pymodbus/tree/master/examples/tools/nullmodem

The synchronous and asynchronous servers/clients are for two different purposes:

  1. async uses the twisted framework to run a high performance event based service. This basically tries to remove all blocking operations from your code (io) and have the kernel do them for you, and let you know when they are finished. You can think of it like:

while (running): io_events = get_io_events() # kernel code distribute(io_events) # your non-blocking code

  1. sync uses python threads to simply do everything in one go. The problem with this is that python is really bad at threading as the whole interpreter has to stop to switch threads.

The decision to use one over the other is basically asking the following questions:

  1. Do I need high performance (say monitoring a data center for devices). If so, use the async client.
  2. Do I need to quickly script a modbus solution. If so, use the sync client.
  3. Do I need to run on a platform where twisted isn't available. If so, use the sync client/server.
  4. Do I need to run a modbus server. Ideally use the async server.

— Reply to this email directly or view it on GitHubhttps://github.com/bashwork/pymodbus/issues/33#issuecomment-25399872 .

ghost commented 10 years ago

here's my master code from ping pong code. import serial, sys, time

def server(socket): while True: ping = socket.read(4) print "ponging a ping" if ping == "ping": socket.write("pong")

def client(socket): while True: socket.setRTS(True) count = socket.write("ping") if count < 4: print "failed to ping" continue time.sleep(0.0025) socket.setRTS(False) pong = socket.read(4) if pong == "pong": print "ping was ponged" if name == "main": socket = serial.Serial(port='/dev/ttyS2', baudrate=19200, timeout=1, parit\ y=serial.PARITY_EVEN, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS) if sys.argv[1] == "server": server(socket) else: client(socket)

and my slave code from ping pong

import serial, sys, time

def server(socket): while (True): socket.setRTS(False) ping = socket.read(4) print ping print "ponging a ping" if ping == "ping": socket.setRTS(True) socket.write("pong") time.sleep(0.0025)

def client(socket): while (True): count = socket.write("ping") if count < 4: print "failed to ping" continue pong = socket.read(4) if pong == "pong": print "ping was ponged" if name == "main": socket = serial.Serial(port='/dev/ttyS2', baudrate=19200, timeout=1, stopbi\ ts=serial.STOPBITS_ONE, parity=serial.PARITY_EVEN, bytesize=serial.EIGHTBITS) if sys.argv[1] == "server": server(socket) else: client(socket)

the only problem i have now is when using modbus, it doesn't work..

On Wed, Oct 2, 2013 at 5:55 PM, Heming Liu hemingliu123@gmail.com wrote:

ok so i think i found the reason

using client.socket = serial.Serial(rtscts=True) doesn't send anything or recive anything for some reason

i have to set RTS using client.socket.setRTS(True) and False

in the ping pong example, i used socket.setRTS(True) and socket.setRTS(False) and it worked

the problem is. with Modbus it doesn't work

the modifications i made to Sync.py under ModbusSerialClient source code is this

def _send(self, request): ''' Sends data on the underlying socket

    :param request: The encoded request to send
    :return: The number of bytes written
    '''
    #self.socket = serial.Serial(port='/dev/ttyS2', timeout=1,

baudrate=192\ 00, stopbits=serial.STOPBITS_ONE, parity=serial.PARITY_EVEN, bytesize=serial.EI\ GHTBITS) (Not sure if i need this line or not, seems to be no help, it also resets baudrate and everything to be what's declared here)

    if not self.socket:
        raise ConnectionException(self.__str__())

    if request:
       self.socket.setRTS(True)
       return self.socket.write(request)
       time.sleep(0.0025)
       self.socket.setRTS(False)
    return 0

def _recv(self, size): ''' Reads data from the underlying descriptor

    :param size: The number of bytes to read
    :return: The bytes read
    '''
    if not self.socket:
        raise ConnectionException(self.__str__())
    self.socket.setRTS(False)
    return self.socket.read(size)

and the modification i made to the server's Sync.py the SingleRequestHandler codes are below

def send(self, message): ''' Send a request (string) to the network

    :param message: The unencoded modbus response
    '''
    self.socket = serial.Serial(port='/dev/ttyS2', baudrate=19200,

timeout=\ 1, parity=serial.PARITY_EVEN, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIG\ HTBITS) if message.should_respond:

self.server.control.Counter.BusMessage += 1

        pdu = self.framer.buildPacket(message)
        if _logger.isEnabledFor(logging.DEBUG):
            _logger.debug('send: %s' % b2a_hex(pdu))
        self.socket.setRTS(True)
        return self.request.send(pdu)
        time.sleep(0.0025)
        self.socket.setRTS(False)

and i made modification to Asyn Server's UDP server's execute method, not sure if UDP server is used for serial

def _execute(self, request, addr): ''' Executes the request and returns the result

    :param request: The decoded request message
    '''
    self.socket = serial.Serial(port='/dev/ttyS2', baudrate=19200,

timeout=\ 1, parity=serial.PARITY_EVEN, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIG\ HTBITS) try: context = self.store[request.unit_id] response = request.execute(context) except Exception, ex: _logger.debug("Datastore unable to fulfill request: %s" % ex) response = request.doException(merror.SlaveFailure)

self.framer.populateResult(response)

    response.transaction_id = request.transaction_id
    response.unit_id = request.unit_id
    self.socket.setRTS(True)
    self._send(response, addr)
    time.sleep(0.0025)
    self.socket.setRTS(False)

Could anyone help me out? i think i'm getting close

thank you guys very much

On Mon, Sep 30, 2013 at 1:04 PM, Galen Collins notifications@github.comwrote:

Right now you will have to do the second assignment you did (client.socket = serial.Socket) as I don't currently pass all the configuration flags to the Serial constructor. I will make a fix for this.

When you set rtscts = True, pyserial is effectively going to set the ioctl that enables that in the serial driver. So if this is supported by your device driver/device (it should be), then you should be good to go.

As for the master side, you should be able to set that as well in just the same manner. If you want to play with various settings on a single box (say to emulate various serial servers), use http://www.modbusdriver.com/diagslave.html or start a synchronous/asynchronous pymodbus server with the options you care to test with. If you need to set up null modem support (if you don't have a cable), here are some options that you can use to set up a software loopback: https://github.com/bashwork/pymodbus/tree/master/examples/tools/nullmodem

The synchronous and asynchronous servers/clients are for two different purposes:

  1. async uses the twisted framework to run a high performance event based service. This basically tries to remove all blocking operations from your code (io) and have the kernel do them for you, and let you know when they are finished. You can think of it like:

while (running): io_events = get_io_events() # kernel code distribute(io_events) # your non-blocking code

  1. sync uses python threads to simply do everything in one go. The problem with this is that python is really bad at threading as the whole interpreter has to stop to switch threads.

The decision to use one over the other is basically asking the following questions:

  1. Do I need high performance (say monitoring a data center for devices). If so, use the async client.
  2. Do I need to quickly script a modbus solution. If so, use the sync client.
  3. Do I need to run on a platform where twisted isn't available. If so, use the sync client/server.
  4. Do I need to run a modbus server. Ideally use the async server.

— Reply to this email directly or view it on GitHubhttps://github.com/bashwork/pymodbus/issues/33#issuecomment-25399872 .

ghost commented 10 years ago

anyone knows what i'm doing wrong? .. thanks

On Thu, Oct 3, 2013 at 11:34 AM, Heming Liu hemingliu123@gmail.com wrote:

here's my master code from ping pong code. import serial, sys, time

def server(socket): while True:

    ping = socket.read(4)
    print "ponging a ping"
    if ping == "ping":

        socket.write("pong")

def client(socket): while True: socket.setRTS(True)

    count = socket.write("ping")
    if count < 4:
        print "failed to ping"
        continue
    time.sleep(0.0025)
    socket.setRTS(False)

    pong = socket.read(4)
    if pong == "pong": print "ping was ponged"

if name == "main": socket = serial.Serial(port='/dev/ttyS2', baudrate=19200, timeout=1, parit\ y=serial.PARITY_EVEN, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS)

if sys.argv[1] == "server":
    server(socket)
else: client(socket)

and my slave code from ping pong

import serial, sys, time

def server(socket): while (True): socket.setRTS(False) ping = socket.read(4) print ping print "ponging a ping" if ping == "ping": socket.setRTS(True) socket.write("pong") time.sleep(0.0025)

def client(socket): while (True):

    count = socket.write("ping")
    if count < 4:
        print "failed to ping"
        continue
    pong = socket.read(4)
    if pong == "pong": print "ping was ponged"

if name == "main": socket = serial.Serial(port='/dev/ttyS2', baudrate=19200, timeout=1, stopbi\ ts=serial.STOPBITS_ONE, parity=serial.PARITY_EVEN, bytesize=serial.EIGHTBITS)

if sys.argv[1] == "server":
    server(socket)
else: client(socket)

the only problem i have now is when using modbus, it doesn't work..

On Wed, Oct 2, 2013 at 5:55 PM, Heming Liu hemingliu123@gmail.com wrote:

ok so i think i found the reason

using client.socket = serial.Serial(rtscts=True) doesn't send anything or recive anything for some reason

i have to set RTS using client.socket.setRTS(True) and False

in the ping pong example, i used socket.setRTS(True) and socket.setRTS(False) and it worked

the problem is. with Modbus it doesn't work

the modifications i made to Sync.py under ModbusSerialClient source code is this

def _send(self, request): ''' Sends data on the underlying socket

    :param request: The encoded request to send
    :return: The number of bytes written
    '''
     #self.socket = serial.Serial(port='/dev/ttyS2', timeout=1,

baudrate=192\ 00, stopbits=serial.STOPBITS_ONE, parity=serial.PARITY_EVEN, bytesize=serial.EI\ GHTBITS) (Not sure if i need this line or not, seems to be no help, it also resets baudrate and everything to be what's declared here)

    if not self.socket:
        raise ConnectionException(self.__str__())

    if request:
       self.socket.setRTS(True)
       return self.socket.write(request)
       time.sleep(0.0025)
       self.socket.setRTS(False)
    return 0

def _recv(self, size): ''' Reads data from the underlying descriptor

    :param size: The number of bytes to read
    :return: The bytes read
    '''
    if not self.socket:
        raise ConnectionException(self.__str__())
    self.socket.setRTS(False)
    return self.socket.read(size)

and the modification i made to the server's Sync.py the SingleRequestHandler codes are below

def send(self, message): ''' Send a request (string) to the network

    :param message: The unencoded modbus response
    '''
    self.socket = serial.Serial(port='/dev/ttyS2', baudrate=19200,

timeout=\ 1, parity=serial.PARITY_EVEN, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIG\ HTBITS) if message.should_respond:

self.server.control.Counter.BusMessage += 1

        pdu = self.framer.buildPacket(message)
        if _logger.isEnabledFor(logging.DEBUG):
            _logger.debug('send: %s' % b2a_hex(pdu))
        self.socket.setRTS(True)
        return self.request.send(pdu)
        time.sleep(0.0025)
        self.socket.setRTS(False)

and i made modification to Asyn Server's UDP server's execute method, not sure if UDP server is used for serial

def _execute(self, request, addr): ''' Executes the request and returns the result

    :param request: The decoded request message
    '''
    self.socket = serial.Serial(port='/dev/ttyS2', baudrate=19200,

timeout=\ 1, parity=serial.PARITY_EVEN, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIG\ HTBITS) try: context = self.store[request.unit_id] response = request.execute(context) except Exception, ex: _logger.debug("Datastore unable to fulfill request: %s" % ex) response = request.doException(merror.SlaveFailure)

self.framer.populateResult(response)

    response.transaction_id = request.transaction_id
    response.unit_id = request.unit_id
    self.socket.setRTS(True)
    self._send(response, addr)
    time.sleep(0.0025)
    self.socket.setRTS(False)

Could anyone help me out? i think i'm getting close

thank you guys very much

On Mon, Sep 30, 2013 at 1:04 PM, Galen Collins notifications@github.comwrote:

Right now you will have to do the second assignment you did (client.socket = serial.Socket) as I don't currently pass all the configuration flags to the Serial constructor. I will make a fix for this.

When you set rtscts = True, pyserial is effectively going to set the ioctl that enables that in the serial driver. So if this is supported by your device driver/device (it should be), then you should be good to go.

As for the master side, you should be able to set that as well in just the same manner. If you want to play with various settings on a single box (say to emulate various serial servers), use http://www.modbusdriver.com/diagslave.html or start a synchronous/asynchronous pymodbus server with the options you care to test with. If you need to set up null modem support (if you don't have a cable), here are some options that you can use to set up a software loopback: https://github.com/bashwork/pymodbus/tree/master/examples/tools/nullmodem

The synchronous and asynchronous servers/clients are for two different purposes:

  1. async uses the twisted framework to run a high performance event based service. This basically tries to remove all blocking operations from your code (io) and have the kernel do them for you, and let you know when they are finished. You can think of it like:

while (running): io_events = get_io_events() # kernel code distribute(io_events) # your non-blocking code

  1. sync uses python threads to simply do everything in one go. The problem with this is that python is really bad at threading as the whole interpreter has to stop to switch threads.

The decision to use one over the other is basically asking the following questions:

  1. Do I need high performance (say monitoring a data center for devices). If so, use the async client.
  2. Do I need to quickly script a modbus solution. If so, use the sync client.
  3. Do I need to run on a platform where twisted isn't available. If so, use the sync client/server.
  4. Do I need to run a modbus server. Ideally use the async server.

— Reply to this email directly or view it on GitHubhttps://github.com/bashwork/pymodbus/issues/33#issuecomment-25399872 .

ghost commented 10 years ago

please help! any suggestion is helpful!

thanks

On Mon, Oct 7, 2013 at 12:47 AM, Heming Liu hemingliu123@gmail.com wrote:

anyone knows what i'm doing wrong? .. thanks

On Thu, Oct 3, 2013 at 11:34 AM, Heming Liu hemingliu123@gmail.comwrote:

here's my master code from ping pong code. import serial, sys, time

def server(socket): while True:

    ping = socket.read(4)
    print "ponging a ping"
    if ping == "ping":

        socket.write("pong")

def client(socket): while True: socket.setRTS(True)

    count = socket.write("ping")
    if count < 4:
        print "failed to ping"
        continue
    time.sleep(0.0025)
    socket.setRTS(False)

    pong = socket.read(4)
    if pong == "pong": print "ping was ponged"

if name == "main": socket = serial.Serial(port='/dev/ttyS2', baudrate=19200, timeout=1, parit\ y=serial.PARITY_EVEN, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS)

if sys.argv[1] == "server":
    server(socket)
else: client(socket)

and my slave code from ping pong

import serial, sys, time

def server(socket): while (True): socket.setRTS(False) ping = socket.read(4) print ping print "ponging a ping" if ping == "ping": socket.setRTS(True) socket.write("pong") time.sleep(0.0025)

def client(socket): while (True):

    count = socket.write("ping")
    if count < 4:
        print "failed to ping"
        continue
    pong = socket.read(4)
    if pong == "pong": print "ping was ponged"

if name == "main": socket = serial.Serial(port='/dev/ttyS2', baudrate=19200, timeout=1, stopbi\ ts=serial.STOPBITS_ONE, parity=serial.PARITY_EVEN, bytesize=serial.EIGHTBITS)

if sys.argv[1] == "server":
    server(socket)
else: client(socket)

the only problem i have now is when using modbus, it doesn't work..

On Wed, Oct 2, 2013 at 5:55 PM, Heming Liu hemingliu123@gmail.comwrote:

ok so i think i found the reason

using client.socket = serial.Serial(rtscts=True) doesn't send anything or recive anything for some reason

i have to set RTS using client.socket.setRTS(True) and False

in the ping pong example, i used socket.setRTS(True) and socket.setRTS(False) and it worked

the problem is. with Modbus it doesn't work

the modifications i made to Sync.py under ModbusSerialClient source code is this

def _send(self, request): ''' Sends data on the underlying socket

    :param request: The encoded request to send
    :return: The number of bytes written
    '''
     #self.socket = serial.Serial(port='/dev/ttyS2', timeout=1,

baudrate=192\ 00, stopbits=serial.STOPBITS_ONE, parity=serial.PARITY_EVEN, bytesize=serial.EI\ GHTBITS) (Not sure if i need this line or not, seems to be no help, it also resets baudrate and everything to be what's declared here)

    if not self.socket:
        raise ConnectionException(self.__str__())

    if request:
       self.socket.setRTS(True)
       return self.socket.write(request)
       time.sleep(0.0025)
       self.socket.setRTS(False)
    return 0

def _recv(self, size): ''' Reads data from the underlying descriptor

    :param size: The number of bytes to read
    :return: The bytes read
    '''
    if not self.socket:
        raise ConnectionException(self.__str__())
    self.socket.setRTS(False)
    return self.socket.read(size)

and the modification i made to the server's Sync.py the SingleRequestHandler codes are below

def send(self, message): ''' Send a request (string) to the network

    :param message: The unencoded modbus response
    '''
    self.socket = serial.Serial(port='/dev/ttyS2', baudrate=19200,

timeout=\ 1, parity=serial.PARITY_EVEN, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIG\ HTBITS) if message.should_respond:

self.server.control.Counter.BusMessage += 1

        pdu = self.framer.buildPacket(message)
        if _logger.isEnabledFor(logging.DEBUG):
            _logger.debug('send: %s' % b2a_hex(pdu))
        self.socket.setRTS(True)
        return self.request.send(pdu)
        time.sleep(0.0025)
        self.socket.setRTS(False)

and i made modification to Asyn Server's UDP server's execute method, not sure if UDP server is used for serial

def _execute(self, request, addr): ''' Executes the request and returns the result

    :param request: The decoded request message
    '''
    self.socket = serial.Serial(port='/dev/ttyS2', baudrate=19200,

timeout=\ 1, parity=serial.PARITY_EVEN, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIG\ HTBITS) try: context = self.store[request.unit_id] response = request.execute(context) except Exception, ex: _logger.debug("Datastore unable to fulfill request: %s" % ex) response = request.doException(merror.SlaveFailure)

self.framer.populateResult(response)

    response.transaction_id = request.transaction_id
    response.unit_id = request.unit_id
    self.socket.setRTS(True)
    self._send(response, addr)
    time.sleep(0.0025)
    self.socket.setRTS(False)

Could anyone help me out? i think i'm getting close

thank you guys very much

On Mon, Sep 30, 2013 at 1:04 PM, Galen Collins <notifications@github.com

wrote:

Right now you will have to do the second assignment you did (client.socket = serial.Socket) as I don't currently pass all the configuration flags to the Serial constructor. I will make a fix for this.

When you set rtscts = True, pyserial is effectively going to set the ioctl that enables that in the serial driver. So if this is supported by your device driver/device (it should be), then you should be good to go.

As for the master side, you should be able to set that as well in just the same manner. If you want to play with various settings on a single box (say to emulate various serial servers), use http://www.modbusdriver.com/diagslave.html or start a synchronous/asynchronous pymodbus server with the options you care to test with. If you need to set up null modem support (if you don't have a cable), here are some options that you can use to set up a software loopback: https://github.com/bashwork/pymodbus/tree/master/examples/tools/nullmodem

The synchronous and asynchronous servers/clients are for two different purposes:

  1. async uses the twisted framework to run a high performance event based service. This basically tries to remove all blocking operations from your code (io) and have the kernel do them for you, and let you know when they are finished. You can think of it like:

while (running): io_events = get_io_events() # kernel code distribute(io_events) # your non-blocking code

  1. sync uses python threads to simply do everything in one go. The problem with this is that python is really bad at threading as the whole interpreter has to stop to switch threads.

The decision to use one over the other is basically asking the following questions:

  1. Do I need high performance (say monitoring a data center for devices). If so, use the async client.
  2. Do I need to quickly script a modbus solution. If so, use the sync client.
  3. Do I need to run on a platform where twisted isn't available. If so, use the sync client/server.
  4. Do I need to run a modbus server. Ideally use the async server.

— Reply to this email directly or view it on GitHubhttps://github.com/bashwork/pymodbus/issues/33#issuecomment-25399872 .

bashwork commented 10 years ago

So you shouldn't have had to modify the code I provided to get that example to work. If so, you are going to have to modify the pymodbus code everywhere and resort to bit-banging to get a functioning client/server. I don't have too much more that I can offer aside from working with the pyserial module more to figure out how to get it working without pymodbus. When that works consistently, you should just be able to create the socket just as you would from an example and it will work with pymodbus. It should be noted that the library doesn't do anything directly with the hardware layer directly (i.e. it doesn't manually do anything special based on TCP, UDP, Serial, etc), it just sends data to an opened socket. So once the socket is working correctly, the library will work correctly.

ghost commented 10 years ago

yes i did modify the code for it to work. if you look at the code i sent u before. if i just to client.socket = serial.Serial( rtscts=True....) this doesn't work whereas if i do socket.setRTS(True) it works.. doesn't make any sense.

On Wed, Oct 9, 2013 at 3:05 PM, Galen Collins notifications@github.comwrote:

So you shouldn't have had to modify the code I provided to get that example to work. If so, you are going to have to modify the pymodbus code everywhere and resort to bit-banging to get a functioning client/server. I don't have too much more that I can offer aside from working with the pyserial module more to figure out how to get it working without pymodbus. When that works consistently, you should just be able to create the socket just as you would from an example and it will work with pymodbus. It should be noted that the library doesn't do anything directly with the hardware layer directly (i.e. it doesn't manually do anything special based on TCP, UDP, Serial, etc), it just sends data to an opened socket. So once the socket is working correctly, the library will work correctly.

— Reply to this email directly or view it on GitHubhttps://github.com/bashwork/pymodbus/issues/33#issuecomment-26013128 .

ghost commented 10 years ago

is there any advancement regarding this issue?

thanks

heming

On Wed, Oct 9, 2013 at 3:05 PM, Galen Collins notifications@github.comwrote:

So you shouldn't have had to modify the code I provided to get that example to work. If so, you are going to have to modify the pymodbus code everywhere and resort to bit-banging to get a functioning client/server. I don't have too much more that I can offer aside from working with the pyserial module more to figure out how to get it working without pymodbus. When that works consistently, you should just be able to create the socket just as you would from an example and it will work with pymodbus. It should be noted that the library doesn't do anything directly with the hardware layer directly (i.e. it doesn't manually do anything special based on TCP, UDP, Serial, etc), it just sends data to an opened socket. So once the socket is working correctly, the library will work correctly.

— Reply to this email directly or view it on GitHubhttps://github.com/bashwork/pymodbus/issues/33#issuecomment-26013128 .

ghost commented 10 years ago

i still have no luck..

it works fine with Modpoll, just doesn't work with pymodbus.

On Tue, Oct 15, 2013 at 11:07 AM, Heming Liu hemingliu123@gmail.com wrote:

is there any advancement regarding this issue?

thanks

heming

On Wed, Oct 9, 2013 at 3:05 PM, Galen Collins notifications@github.comwrote:

So you shouldn't have had to modify the code I provided to get that example to work. If so, you are going to have to modify the pymodbus code everywhere and resort to bit-banging to get a functioning client/server. I don't have too much more that I can offer aside from working with the pyserial module more to figure out how to get it working without pymodbus. When that works consistently, you should just be able to create the socket just as you would from an example and it will work with pymodbus. It should be noted that the library doesn't do anything directly with the hardware layer directly (i.e. it doesn't manually do anything special based on TCP, UDP, Serial, etc), it just sends data to an opened socket. So once the socket is working correctly, the library will work correctly.

— Reply to this email directly or view it on GitHubhttps://github.com/bashwork/pymodbus/issues/33#issuecomment-26013128 .

bashwork commented 10 years ago

What is the modpoll command that works correctly?

ghost commented 10 years ago

for the modpoll master it was just

./modpoll -a 1 -b 19200 -4 1 /dev/ttyS2

and for diagslave it was just

./diagslave -b 19200 -a 1 -4 1 /dev/ttyS2

the outputs are

-- Polling slave... (Ctrl-C to stop)

-- Polling slave... (Ctrl-C to stop)

-- Polling slave... (Ctrl-C to stop)

-- Polling slave... (Ctrl-C to stop)

all other parameters just default to the RTU method,

might it be that my Pymodbus scripts are wrong? i've attached them in the previous replies

thank you very much for any help

On Fri, Oct 25, 2013 at 11:06 PM, Galen Collins notifications@github.comwrote:

What is the modpoll command that works correctly?

— Reply to this email directly or view it on GitHubhttps://github.com/bashwork/pymodbus/issues/33#issuecomment-27140334 .

bashwork commented 10 years ago

Okay so since your device does not offer any RTS capabilities, you are going to have to bit bang the line and hope for the best (that is what the -4 parameter does for modpoll). Earlier when you did serial.Serial( rtscts=True....), that was trying to enable automatic RTS handling by your driver (which it apparently doesn't support) while, socket.setRTS(True) is actually just forcing the line high. What you are going to have to do is have a simple wrapper around the serial client that will controll the RTS line for you. Something like::

class RtsModbusSerialClient(ModbusSerialClient):

    def _send(self, request):
        ''' Sends data on the underlying socket

        :param request: The encoded request to send
        :return: The number of bytes written
        '''
        if not self.socket:
            raise ConnectionException(self.__str__())
        if request:
            self.socket.setRTS(True)
            result = self.socket.write(request)
            self.socket.setRTS(False)
            return result
        return 0

    def _recv(self, size):
        ''' Reads data from the underlying descriptor

        :param size: The number of bytes to read
        :return: The bytes read
        '''
        if not self.socket:
            raise ConnectionException(self.__str__())
        self.socket.setRTS(False)
        result = self.socket.read(size)
        self.socket.setRTS(True)
        return result

There may be some timing issues that you have to deal with for this to work correctly (the lines might need to be held for longer than the read/write; say 25ms). But generally this is what you are going to have to play around with until it works. I don't have a device to test against so I cannot really help you besides offering advice, however, if I ever get a tested solution, I will gladly add it to the contrib package so future users will not have to go through as much grief as you. Thanks for keeping at it!

ghost commented 10 years ago

Hi Galen,

i did do what u suggested in the client's source code, under modbus serial client, but i could not find send and recv from the server side source code!

could u suggest what i should do for the server's side?

or do i just put this code directly into my client and server's codes. like synclient.py and syncserver.py thanks

On Mon, Oct 28, 2013 at 1:44 PM, Galen Collins notifications@github.comwrote:

Okay so since your device does not offer any RTS capabilities, you are going to have to bit bang the line and hope for the best (that is what the -4 parameter does for modpoll). Earlier when you did serial.Serial( rtscts=True....), that was trying to enable automatic RTS handling by your driver (which it apparently doesn't support) while, socket.setRTS(True) is actually just forcing the line high. What you are going to have to do is have a simple wrapper around the serial client that will controll the RTS line for you. Something like::

class RtsModbusSerialClient(ModbusSerialClient):

def _send(self, request): ''' Sends data on the underlying socket

:param request: The encoded request to send
:return: The number of bytes written
'''
if not self.socket:
    raise ConnectionException(self.__str__())
if request:
    self.socket.setRTS(True)
    result = self.socket.write(request)
    self.socket.setRTS(False)
    return result
return 0

def _recv(self, size): ''' Reads data from the underlying descriptor

:param size: The number of bytes to read
:return: The bytes read
'''
if not self.socket:
    raise ConnectionException(self.__str__())
self.socket.setRTS(False)
result = self.socket.read(size)
self.socket.setRTS(True)
return result

There may be some timing issues that you have to deal with for this to work correctly (the lines might need to be held for longer than the read/write; say 25ms). But generally this is what you are going to have to play around with until it works. I don't have a device to test against so I cannot really help you besides offering advice, however, if I ever get a tested solution, I will gladly add it to the contrib package so future users will not have to go through as much grief as you. Thanks for keeping at it!

— Reply to this email directly or view it on GitHubhttps://github.com/bashwork/pymodbus/issues/33#issuecomment-27254472 .

bashwork commented 10 years ago

Right, so in server/sync.py, there is the ModbusSerialServer. What you will have to do is something like::


class RtsModbusSerialServer(object):

    def _build_handler(self):
        ''' A helper method to create and monkeypatch
            a serial handler.

        :returns: A patched handler
        '''

        def rts_send(message):
             self.socket.setRTS(True)
             result = self.socket.write(message)
             self.socket.setRTS(False)
             return result

        def rts_recv(count):
              self.socket.setRTS(False)
              result = self.socket.read(count)
              self.socket.setRTS(True)
              return result

        request = self.socket
        request.send = rts_send
        request.recv = rts_recv
        handler = ModbusSingleRequestHandler(request,
            (self.device, self.device), self)
        return handler
ghost commented 10 years ago

so if i understand correctly i should add this class into the sync.py in both master and slave sync.py?

thanks

Heming

On Tue, Oct 29, 2013 at 4:11 PM, Galen Collins notifications@github.comwrote:

Right, so in server/sync.py, there is the ModbusSerialServer. What you will have to do is something like::

class RtsModbusSerialServer(object):

def _build_handler(self):
    ''' A helper method to create and monkeypatch            a serial handler.
    :returns: A patched handler        '''

    def rts_send(message):
         self.socket.setRTS(True)
         result = self.socket.write(message)
         self.socket.setRTS(False)
         return result

    def rts_recv(count):
          self.socket.setRTS(False)
          result = self.socket.read(count)
          self.socket.setRTS(True)
          return result

    request = self.socket
    request.send = rts_send
    request.recv = rts_recv
    handler = ModbusSingleRequestHandler(request,
        (self.device, self.device), self)
    return handler

— Reply to this email directly or view it on GitHubhttps://github.com/bashwork/pymodbus/issues/33#issuecomment-27352576 .