Talking to a usb device (serial terminal)

B

blaine

Hey everyone,
We have a usb spectrometer device that we have finally got working
in linux (we were provided linux only drivers). The device has a
Silicon Instruments cp2101 serial-to-usb chip onboard, and we loaded
the kernel module cp2101.c after taking the device apart to see what
was on the inside. Using minicom we are able to set a baud rate and
open up a terminal when pointing to the device /dev/ttyusb0 (I
think). Anyway, I want to be able to talk to our cool device using
python. I haven't been able to find many resources specifically in
this area, but there are a few package that are vaguely mentioned,
including fcntl and termios. But the web doesn't seem to have a lot
of documentation on fcntl, particularly information thats from the
past 8 years.

So my question is this - what is the easiest way to interface to this
"serial" device?

I don't imagine a straight read() and write() command to /dev/ttyusb0
is the most efficient (if it even works) especially since we would
need to set a baud rate. My experience with terminal communication is
pretty limited.

Any advice that can be offered would be awesome. Thanks!
PS: The device that we will be using python on will be an embedded ARM
system. Currently we are testing using a linux laptop and cross
compiling the kernel over to the embedded device. The device has
Python 2.4, and does have both the termios and fcntl packages
available.

Python 2.4.2 (#1, Feb 20 2008, 11:07:36)
[GCC 4.1.1] on linux2

uname -a:
Linux gumstix 2.6.21gum #1 Wed Feb 20 02:53:01 EST 2008 armv5tel
unknown

Blaine Booher
University of Cincinnati
 
B

Bjoern Schliessmann

blaine said:
So my question is this - what is the easiest way to interface to
this "serial" device?

I don't imagine a straight read() and write() command to
/dev/ttyusb0 is the most efficient (if it even works)

It doesn't only work, it's the preferred way (if you don't use
advanced wrappers like pyserial). For the basics see

http://www.easysw.com/~mike/serial/serial.html
especially since we would need to set a baud rate.

What is the relationship between read/write, the baud rate, and
efficiency? The serial port is configured using POSIX terminal
interface (termios).

Regards,


Björn
 
B

blaine

It doesn't only work, it's the preferred way (if you don't use
advanced wrappers like pyserial). For the basics see

http://www.easysw.com/~mike/serial/serial.html [...]
What is the relationship between read/write, the baud rate, and
efficiency? The serial port is configured using POSIX terminal
interface (termios).

Thank you so much for that reference link, it was very helpful. I now
understand the difference in the modules - termios and fctnl.

As far as PySerial goes - were trying to stick to built-in modules
since cross compiling to an arm processor is being a little bit of a
pain for us. Thank you for the suggestion though!

Thanks!
Blaine
 
G

Grant Edwards

As far as PySerial goes - were trying to stick to built-in
modules since cross compiling to an arm processor is being a
little bit of a pain for us.

pyserial is pure python, so I don't see how it's going to be
any more painful than something you write yourself. If you
want something that's more of a transparent object wrapper
aroudn the Posix serial interface, there's PosixSerial.py (upon
which pyserial's posix support is based):

ftp://ftp.visi.com/users/grante/python/PosixSerial.py
 
B

blaine

pyserial is pure python, so I don't see how it's going to be
any more painful than something you write yourself. If you
want something that's more of a transparent object wrapper
aroudn the Posix serial interface, there's PosixSerial.py (upon
which pyserial's posix support is based):

ftp://ftp.visi.com/users/grante/python/PosixSerial.py

Oh - good point. There wouldn't be any compilation issues with the C
api. Nevermind! :)

I do have a question though. In the termios module, I am attempting
to set the baud rate to 921600, which is what we use with
'cutecom' (because minicom does not have this as an option) and is
what the supplier recommends. When I try to set the rate using
termios.tcsetattr(), I get an Argument Error. I do not get this when
I use an existing baud rate, such as termios.B9600. Is there a way I
can get around this? We would like to use it at full speed.

Thank you,
Blaine
 
G

Grant Edwards

I do have a question though. In the termios module, I am attempting
to set the baud rate to 921600, which is what we use with
'cutecom' (because minicom does not have this as an option) and is
what the supplier recommends. When I try to set the rate using
termios.tcsetattr(), I get an Argument Error.

What values are you using for ispeed and ospeed? Those values
are special (and rather arbitrary) constant bit-patterns and
not simply integers like 9600 or 115200.
I do not get this when I use an existing baud rate, such as
termios.B9600. Is there a way I can get around this? We would
like to use it at full speed.

It looks like the fastest speed supported by python termios on
Linux is B460800 (uses a constant of 0x1004). If you look in
/usr/include/..., baud rates do go up to 921600 (which uses a
constant of 0x1007).

Try using the appropriate constant from /usr/include/... (for
the target platform, of course).
 
B

blaine

It looks like the fastest speed supported by python termios on
Linux is B460800 (uses a constant of 0x1004). If you look in
/usr/include/..., baud rates do go up to 921600 (which uses a
constant of 0x1007).

Try using the appropriate constant from /usr/include/... (for
the target platform, of course).
Thank you for your response. I can't seem to find what you're
referencing in /usr/include. I found termios.h - but it does not
define any constants (I can include it if you wish). I did find
termios.c in the Python module file, which only defines constants up
to :
[...]
{"B2400", B2400},
{"B4800", B4800},
{"B9600", B9600},
{"B19200", B19200},
{"B38400", B38400},
#ifdef B57600
{"B57600", B57600},
#endif
#ifdef B115200
{"B115200", B115200},
#endif
#ifdef B230400
{"B230400", B230400},

I could recompile python, I imagine, with additional constants but
this wouldn't be ideal - although it is a possible solution.

the only reference to a baud rate in termios.h is here:
/* Return the output baud rate stored in *TERMIOS_P. */
extern speed_t cfgetospeed (__const struct termios *__termios_p)
__THROW;

/* Return the input baud rate stored in *TERMIOS_P. */
extern speed_t cfgetispeed (__const struct termios *__termios_p)
__THROW;

/* Set the output baud rate stored in *TERMIOS_P to SPEED. */
extern int cfsetospeed (struct termios *__termios_p, speed_t __speed)
__THROW;

/* Set the input baud rate stored in *TERMIOS_P to SPEED. */
extern int cfsetispeed (struct termios *__termios_p, speed_t __speed)
__THROW;

the termios.h and const.h in the linux/ folder aren't much help. I'm
sure I'm just looking at the wrong file.

Thank you again for all your help!
Blaine
 
G

Grant Edwards

Thank you for your response. I can't seem to find what you're
referencing in /usr/include. I found termios.h - but it does not
define any constants (I can include it if you wish).

$ grep -r B921600 /usr/include
/usr/include/asm/termbits.h:#define B921600 0010007
/usr/include/bits/termios.h:#define B921600 0010007
I could recompile python, I imagine, with additional constants but
this wouldn't be ideal - although it is a possible solution.

termios.c in Python definitely needs to be updated.
the only reference to a baud rate in termios.h is here:

It's in a file that's included in termios.h. See above.
 
B

blaine

It looks like the fastest speed supported by python termios on
Linux is B460800 (uses a constant of 0x1004). If you look in
/usr/include/..., baud rates do go up to 921600 (which uses a
constant of 0x1007).

Try using the appropriate constant from /usr/include/... (for
the target platform, of course).

I want to thank you SO MUCH for all your help. Here are my issues
that I overcame (sanity check):
1. Why did we have to use 0x1007, instead of 0x10007 that our grep
command returns?
2. PySerial works beautifully. Thank you for the suggestion. What I
had to do was add this to the PySerial source root in serialpostix.py,
after the import termios:

termios.B921600 = 0x1007

because PySerial looks for the actual baud rate in termios (via
getattr()) which does not exist. PySerial actually defines the
following baud rates, but termios does not handle it:
#default values, may be overriden in subclasses that do not
support all values
BAUDRATES =
(50,75,110,134,150,200,300,600,1200,1800,2400,4800,9600,

19200,38400,57600,115200,230400,460800,500000,576000,921600,

1000000,1152000,1500000,2000000,2500000,3000000,3500000,4000000)
.... so now I can pass 921600 as a parameter to PySerial! :)

So my next question is - I would like to contribute to the python
source tree by updating termios.h to handle the higher baud rates by
default. Is this a good opportunity for me to submit a patch? I've
never done this before but have always been interested in doing so.

Thanks again!
Blaine
 
G

Grant Edwards

I want to thank you SO MUCH for all your help. Here are my issues
that I overcame (sanity check):
1. Why did we have to use 0x1007, instead of 0x10007 that our grep
command returns?

The number might be different for the host where you did the
grep that it is for the target machine (IIRC, you said it was
an ARM, right?). Did you do the grep on the include files for
the ARM target or on a host of some other architecture?

The actual numbers might also be different in different
versions of the kernel.
2. PySerial works beautifully. Thank you for the suggestion.
What I had to do was add this to the PySerial source root
in serialpostix.py, after the import termios:

termios.B921600 = 0x1007
[...]

... so now I can pass 921600 as a parameter to PySerial! :)

So my next question is - I would like to contribute to the
python source tree by updating termios.h to handle the higher
baud rates by default. Is this a good opportunity for me to
submit a patch? I've never done this before but have always
been interested in doing so.

Sure! It's been a while since I submitted a patch, and I don't
remember what the process is, but hopefully somebody reading
the thread does. It could be that the change is already in the
development branch...
 
T

Tim Roberts

blaine said:
...I haven't been able to find many resources specifically in
this area, but there are a few package that are vaguely mentioned,
including fcntl and termios. But the web doesn't seem to have a lot
of documentation on fcntl, particularly information thats from the
past 8 years.

That's because serial ports, and the means of accessing them, haven't
changed significantly in the last 8 years. Or the last 38 years, for that
matter.
 
B

blaine

Because it is NOT 0x10007... It is OCTAL 010007 -- which just
happens to map to hexadecimal 0x1007 <G>
--
Wulfraed Dennis Lee Bieber KD6MOG
(e-mail address removed) (e-mail address removed)
HTTP://wlfraed.home.netcom.com/
(Bestiaria Support Staff: (e-mail address removed))
HTTP://www.bestiaria.com/

oh wow - that makes a lot more sense. haha.

The processor we are going to use is ARM, yes, but our development at
this point (to keep it simple) is just on a simple linux laptop pc.

Thanks again for all the help :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,954
Messages
2,570,116
Members
46,704
Latest member
BernadineF

Latest Threads

Top