0

I'm attempting to interact with a peripheral from a Debian 10.4 laptop. They are connected using a Chipi-X RS-232<->USB cable, and I'm working on the code for the communication on the laptop (it's in CPython using pyserial), but I have little to no control over the implementation of the peripheral itself.

I'm having some trouble with a small fraction of the bytes transmitted being dropped, but that's possibly a subject for another question.

As part of trying to sort that out, I noticed that the serial connection has several special characters enabled, and I don't want that:

$ stty -a < /dev/ttyUSB0 
below cmd output started 2020 Tue Jul 28 03:55:48 PM PDT
speed 38400 baud; rows 0; columns 0; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R;
werase = ^W; lnext = ^V; discard = ^O; min = 1; time = 0;
-parenb -parodd -cmspar 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 echoctl echoke -flusho -extproc

Is there a pyserial way to disable all those special characters (EG intr, quit, erase, etcetera), and tuning anything else required to make the connection fully 8 bit clean?

Right now, I'm opening the serial device using:

serial_file = serial.Serial(                                                                                             
        port=self.serial_port_filename,                                                                                  
        baudrate=self.baudrate,                                                                                          
        bytesize=serial.EIGHTBITS,                                                                                       
        parity=serial.PARITY_NONE,                                                                                       
        stopbits=serial.STOPBITS_ONE,                                                                                    
        timeout=3,                                                                                                       
)

Thanks!


Update: "stty -F /dev/ttyUSB0 raw" doesn't appear to be working:

$ stty -F /dev/ttyUSB0 raw
below cmd output started 2020 Wed Jul 29 11:52:35 AM PDT
above cmd output done    2020 Wed Jul 29 11:52:35 AM PDT
root@zareason-strata7440:~/src/orange-med/NKV-Gateway x86_64-pc-linux-gnu 6942

$ stty -F /dev/ttyUSB0 -a
below cmd output started 2020 Wed Jul 29 11:52:37 AM PDT
speed 38400 baud; rows 0; columns 0; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R;
werase = ^W; lnext = ^V; discard = ^O; min = 1; time = 0;
-parenb -parodd -cmspar 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 echoctl echoke -flusho -extproc

Neither does holding the file open and sleeping.

Neither does the apparent CPython equivalent:

tty.setraw(serial_file.fd, when=termios.TCSANOW)

Am I doing something wrong?


Another update: I think I have it doing 8 bit clean communication, but I'm still seeing spuriously dropped (or spuriously inserted) sequences of bytes. This could conceivably be due to the total lack of flow control.

Here's the code I'm using to get an 8 bit clean serial line. If someone sees a lingering problem in there, please do let me know!

"""Put a terminal in raw mode and/or make a terminal 8 bit clean."""

import termios

# Indexes for termios list.
IFLAG = 0
OFLAG = 1
CFLAG = 2
LFLAG = 3
ISPEED = 4
OSPEED = 5
CC = 6


def make_8_bit_clean(file_descriptor, when=termios.TCSANOW):
    """
    Make file_descriptor able to send and receive all 256 eight bit characters without strangeness.

    Based on:
    https://stackoverflow.com/questions/12437593/how-to-read-a-binary-data-over-serial-terminal-in-c-program/12457195#12457195
    Specifically the "Code that works on my ARM SoC is" answer.
    """
    mode = termios.tcgetattr(file_descriptor)

    cfmakeraw(mode)

    mode[CC][termios.VMIN] = 1
    mode[CC][termios.VTIME] = 0

    mode[CFLAG] &= ~termios.CSTOPB
    mode[CFLAG] &= ~termios.CRTSCTS
    mode[CFLAG] |= termios.CLOCAL
    mode[CFLAG] |= termios.CREAD

    termios.tcsetattr(file_descriptor, when, mode)


def cfmakeraw(mode):
    """
    Set flags to 'raw' mode.

    Based on https://linux.die.net/man/3/cfmakeraw
    """
    mode[IFLAG] &= ~termios.IGNBRK
    mode[IFLAG] &= ~termios.BRKINT
    mode[IFLAG] &= ~termios.IGNBRK
    mode[IFLAG] &= ~termios.BRKINT
    mode[IFLAG] &= ~termios.PARMRK
    mode[IFLAG] &= ~termios.ISTRIP
    mode[IFLAG] &= ~termios.INLCR
    mode[IFLAG] &= ~termios.IGNCR
    mode[IFLAG] &= ~termios.ICRNL
    mode[IFLAG] &= ~termios.IXON

    mode[OFLAG] &= ~termios.OPOST

    mode[LFLAG] &= ~termios.ECHO
    mode[LFLAG] &= ~termios.ECHONL
    mode[LFLAG] &= ~termios.ICANON
    mode[LFLAG] &= ~termios.ISIG
    mode[LFLAG] &= ~termios.IEXTEN

    mode[CFLAG] &= ~termios.CSIZE
    mode[CFLAG] &= ~termios.PARENB
    mode[CFLAG] |= termios.CS8

Thanks.

dstromberg
  • 6,954
  • 1
  • 26
  • 27
  • The peripheral device you are using is a serial terminal, and its interface is called termios. The (proper) shell command `stty -F /dev/ttyUSB0 raw` will nullify the definition of those various control characters. Read the **man** page on termios for the details. – sawdust Jul 29 '20 at 00:28
  • @sawdust stty -F /dev/ttyUSB0 raw is good to know about. I'm still kinda hoping for a pyserial way of doing it - or other CPython way. Thanks! – dstromberg Jul 29 '20 at 03:53
  • *""stty -F /dev/ttyUSB0 raw" doesn't appear to be working"* -- Use of *"nullify"* was a poor word choice. I did not mean that the assignments would be changed to NUL, but rather that the actions associated for those characters would be inhibited/disabled. Did you read the man page on stty for the details? – sawdust Jul 29 '20 at 20:34

0 Answers0