Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > Is it possible to use python to get True Full Duplex on a Serial port?

Reply
Thread Tools

Is it possible to use python to get True Full Duplex on a Serial port?

 
 
Hendrik van Rooyen
Guest
Posts: n/a
 
      08-14-2009
In the past, on this group, I have made statements that said that on Linux,
the serial port handling somehow does not allow transmitting and receiving at
the same time, and nobody contradicted me.

I am running into the self same issue again.

What I normally do is to open the port like this:

port = open("/dev/ttyS0","r+b",0)

and then I unblock it with:

def unblock(f):
"""Given file 'f', sets its unblock flag to true."""

fcntl.fcntl(f.fileno(), fcntl.F_SETFL, os.O_NONBLOCK)

Then I can write a loop that uses a try-except to see if there are characters
available, and that examines a queue to see if there is something to
transmit, to give the appearance of full duplex functionality.

What I would really like is to have two threads - one that does blocking input
waiting for a character, and one that examines an output queue and transmits
the stuff it finds.

When I try to do this, it does not seem to work - as far as I can see, it is
as if the underlying implementation is somehow single threaded - if it is
waiting for a received character, it waits until something comes in before it
will transmit anything. So if you are talking to a device that does not
respond, the whole thing freezes up waiting for a character that never comes,
and nothing is transmitted either, despite the call to
port.write(somestring). The write blocks, and everything stops, waiting for
the receipt to finish.

Is there a way to get full duplex, so that the transmit and receive are
independent of each other?

Or are we stuck with a disk-like model that forces a sequence on reads and
writes?

- Hendrik

 
Reply With Quote
 
 
 
 
Diez B. Roggisch
Guest
Posts: n/a
 
      08-14-2009
Hendrik van Rooyen schrieb:
> In the past, on this group, I have made statements that said that on Linux,
> the serial port handling somehow does not allow transmitting and receiving at
> the same time, and nobody contradicted me.
>
> I am running into the self same issue again.
>
> What I normally do is to open the port like this:
>
> port = open("/dev/ttyS0","r+b",0)


How about using pyserial? With that, I never had any problems accessing
the the serial ports, and AFAIK no duplex-problems as well. And I
seriously doubt that these are a python-related problem - python only
has a very thin, direct layer above the posix-calls, and doesn't do
anything that would explain your observed behavior. The GIL is not the
issue here either - it won't interfer with blocking IO.

Diez
 
Reply With Quote
 
 
 
 
greg
Guest
Posts: n/a
 
      08-14-2009
Hendrik van Rooyen wrote:

> port = open("/dev/ttyS0","r+b",0)
>
> What I would really like is to have two threads - one that does blocking input
> waiting for a character, and one that examines an output queue and transmits
> the stuff it finds.


You can't read and write with the same stdio file object
at the same time. Odd things tend to happen if you try.

You need to open *two* file objects, one for reading
and one for writing:

fr = open("/dev/ttyS0","rb",0)
fw = open("/dev/ttyS0","wb",0)

and give fr to the reading thread and fw to the
writing thread.

You could also try avoiding file objects altogether
and use the raw system calls in the os module. Since
you're not using any buffering, there's little reason
to use the stdio layer. If you do that, you should be
able to use the same file descriptor for reading and
writing without any trouble.

--
Greg
 
Reply With Quote
 
Hendrik van Rooyen
Guest
Posts: n/a
 
      08-14-2009
On Friday 14 August 2009 12:54:32 Diez B. Roggisch wrote:

>
> How about using pyserial? With that, I never had any problems accessing
> the the serial ports, and AFAIK no duplex-problems as well. And I
> seriously doubt that these are a python-related problem - python only
> has a very thin, direct layer above the posix-calls, and doesn't do
> anything that would explain your observed behavior. The GIL is not the
> issue here either - it won't interfer with blocking IO.


I will have a look at pyserial - have never used it before.

I agree that it is probably not a Python issue, and that the GIL is
irelevant - I was hoping that someone had already travelled the road and
could give me a signpost.

In the meantime I have had another idea which I have also not tried yet,
namely to do independent opens for reading and writing, to give me two file
instances instead of one, and to try with that. I have no idea if it would
make any difference, or even work at all.

My normal stuff works, but I do not like it as it is essentially busy looping
with short sleeps in between. In the eBox, it uses most of the processor just
to move a few bytes of I/O in and out between the serial port and the TCP/IP,
and struggles to do that better than five times a second, while the message
time on the 115200 baud port is only about 2 milliseconds.

- Hendrik
 
Reply With Quote
 
Hendrik van Rooyen
Guest
Posts: n/a
 
      08-14-2009
On Friday 14 August 2009 14:13:46 greg wrote:

> You can't read and write with the same stdio file object
> at the same time. Odd things tend to happen if you try.
>
> You need to open *two* file objects, one for reading
> and one for writing:
>
> fr = open("/dev/ttyS0","rb",0)
> fw = open("/dev/ttyS0","wb",0)
>
> and give fr to the reading thread and fw to the
> writing thread.


Does this actually work without somehow falling foul of the fact that
the /dev/ttyS0 is only one thing? - I know that there is no physical reason
for not being able to go in and out at the same time - in my embedded stuff I
do that routinely - but that is all assembler running on bare metal so it is
under my own control.

>
> You could also try avoiding file objects altogether
> and use the raw system calls in the os module. Since
> you're not using any buffering, there's little reason
> to use the stdio layer. If you do that, you should be
> able to use the same file descriptor for reading and
> writing without any trouble.


Thanks for this - I now have my weekend cut out for me...

- Hendrik

 
Reply With Quote
 
exarkun@twistedmatrix.com
Guest
Posts: n/a
 
      08-14-2009
On 01:38 pm, http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:
>On Friday 14 August 2009 12:54:32 Diez B. Roggisch wrote:
>>
>>How about using pyserial? With that, I never had any problems
>>accessing
>>the the serial ports, and AFAIK no duplex-problems as well. And I
>>seriously doubt that these are a python-related problem - python only
>>has a very thin, direct layer above the posix-calls, and doesn't do
>>anything that would explain your observed behavior. The GIL is not the
>>issue here either - it won't interfer with blocking IO.

>
>I will have a look at pyserial - have never used it before.
>
>I agree that it is probably not a Python issue, and that the GIL is
>irelevant - I was hoping that someone had already travelled the road
>and
>could give me a signpost.
>
>In the meantime I have had another idea which I have also not tried
>yet,
>namely to do independent opens for reading and writing, to give me two
>file
>instances instead of one, and to try with that. I have no idea if it
>would
>make any difference, or even work at all.
>
>My normal stuff works, but I do not like it as it is essentially busy
>looping
>with short sleeps in between. In the eBox, it uses most of the
>processor just
>to move a few bytes of I/O in and out between the serial port and the
>TCP/IP,
>and struggles to do that better than five times a second, while the
>message
>time on the 115200 baud port is only about 2 milliseconds.


One strategy you might employ to get rid of the busy looping is to use
Twisted and its serial port support. This also addresses the full-
duplex issue you've raised.

Jean-Paul
 
Reply With Quote
 
Diez B. Roggisch
Guest
Posts: n/a
 
      08-14-2009
Hendrik van Rooyen schrieb:
> On Friday 14 August 2009 14:13:46 greg wrote:
>
>> You can't read and write with the same stdio file object
>> at the same time. Odd things tend to happen if you try.
>>
>> You need to open *two* file objects, one for reading
>> and one for writing:
>>
>> fr = open("/dev/ttyS0","rb",0)
>> fw = open("/dev/ttyS0","wb",0)
>>
>> and give fr to the reading thread and fw to the
>> writing thread.

>
> Does this actually work without somehow falling foul of the fact that
> the /dev/ttyS0 is only one thing? - I know that there is no physical reason
> for not being able to go in and out at the same time - in my embedded stuff I
> do that routinely - but that is all assembler running on bare metal so it is
> under my own control.
>
>> You could also try avoiding file objects altogether
>> and use the raw system calls in the os module. Since
>> you're not using any buffering, there's little reason
>> to use the stdio layer. If you do that, you should be
>> able to use the same file descriptor for reading and
>> writing without any trouble.

>
> Thanks for this - I now have my weekend cut out for me...


You should *really* just use pyserial. No hassle, instant satisfaction.

Diez
 
Reply With Quote
 
exarkun@twistedmatrix.com
Guest
Posts: n/a
 
      08-14-2009
On 02:19 pm, invalid@invalid wrote:
>On 2009-08-14, (E-Mail Removed) <(E-Mail Removed)>
>wrote:
>>One strategy you might employ to get rid of the busy looping
>>is to use Twisted and its serial port support. This also
>>addresses the full- duplex issue you've raised.

>
>There are no such full-dulex issues.


There was a perceived issues. Obviously it's possible to do full-duplex
with Linux's serial port support (and all the other major platforms too,
as far as I know), as long as you know how. Twisted makes the how a
lot simpler.

Jean-Paul
 
Reply With Quote
 
Terry Reedy
Guest
Posts: n/a
 
      08-15-2009
greg wrote:

> You can't read and write with the same stdio file object
> at the same time. Odd things tend to happen if you try.


I believe the C standard specifies that the behavior of mixed reads and
writes is undefined without intervening seek and/or flush, even if the
seek is ignored (as it is on some Unix systems). With two threads, the
timing is undetermined.

 
Reply With Quote
 
Hendrik van Rooyen
Guest
Posts: n/a
 
      08-15-2009
On Friday 14 August 2009 15:58:37 (E-Mail Removed) wrote:

> One strategy you might employ to get rid of the busy looping is to use
> Twisted and its serial port support. This also addresses the full-
> duplex issue you've raised.


I know - vaguely - about twisted and I have been dancing around the fire, not
really ready to put the time in to understand it properly. Looks like the
time has come though - my weekend is really going to hell.

I am now going to make a loopback connector and start playing.

Thanks to everybody for the feedback.

- Hendrik
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
[False,True] and [True,True] --> [True, True]????? bdb112 Python 45 04-29-2009 02:35 AM
Cisco VXR 7200 - Unable to get full duplex link Matt Cisco 8 11-15-2005 09:13 AM
ECP Half-duplex or Full-Duplex? DigitalSierra A+ Certification 0 10-18-2004 04:39 AM



Advertisments