Wrong newline character over serial port (CR instead of LF)
Andrew Mclaughlin
I'm trying to talk to a device using a usb-to-serial converter on linux. Drivers are working, the device exists at /dev/ttyUSB0.
There is a strange problem (checked with a null-modem cable to another computer): Whatever program I use to connect to the device (putty, minicom, screen), they all send a CR (\r) on enter. I (and my device) expect a LF (\n) on enter.
When I use the console to send a command - it sends a LF:
# echo Hello World > /dev/ttyUSB0Results in "Hello World\n". I also wrote the classic c hello world program (printf("Hello, world!\n");) and redirected the output to /dev/ttyUSB0 - also gives me a "Hello world\n" on the other end of the line.
But all other terminal programs send a \r on enter.
What's going on here?
34 Answers
If using picocom, it's a matter of mapping the serial output from CR to CR+LF.
Example:
picocom /dev/ttyS0 --baud 19200 --omap crcrlf --echoActually able to send commands to the device now!
2Please ensure you have set the ttyUSBx port in raw mode. Otherwise there can be some character replacements e.g. \r with \n and vice versa on receiver side.
TLDR: you can't; Screen will override any options set via stty when it starts. It doesn't support the ocrnl/onlcr/icrnl/inlcr options required to configure carriage return vs. newline. It opens the terminal device in exclusive mode, so you can't use stty to change these options after screen starts. This is true for Screen version 4.08.00 (GNU), 05-Feb-20.
Long form:
I've run into this same issue, and have searched through several related questions and answers across the stack exchange universe. I'm forced to conclude that You can't get screen to send Line Feed (LF; \n) instead of Carriage Return (CR; \r), at least not without changing something in the source and recompiling.
This question asks how to send LF instead of CR from screen. It doesn't have an answer yet. This answer is wrong (stty -F /dev/YOURSERIALDEVICE YOURBAUDRATE raw won't change how screen configures the tty). This answer suggests using picocom, but doesn't answer the question of how to get screen to send the correct newline character. It does, however, work:
picocom /dev/YOURSERIALDEVICE --baud YOURBAUDRATE --omap crcrlf --echo
# (press Control+a Control+x to exit)There are hints for how one might address this for screen in the stty man page. Screen forwards the comma-delimited list of options after the tty file to stty, so some of these options might help:
> man stty
# (output abridged..)
Input settings: [-]icrnl translate carriage return to newline [-]inlcr translate newline to carriage return
Output settings: [-]ocrnl translate carriage return to newline [-]onlcr translate newline to carriage return-newline [-]onlret newline performs a carriage returnHowever, setting both input and output to replace \r with \n, ensuring that \n isn't replaced by \r, and ensuring that onlret is not set ... doesn't make a difference,
screen /dev/YOURSERIALDEVICE YOURBAUDRATE,ocrnl,-onlcr,icrnl,-inlcr,-onlretbehaves the same as before. I'm not sure why screen doesn't seem to apply the options. This answer to a vaguely similar question suggests using stty to change the options.
> stty -F /dev/YOURSERIALDEVICE YOURBAUDRATE ocrnl -onlcr icrnl -inlcr -onlret
> screen /dev/YOURSERIALDEVICEThis does nothing, because screen resets any configuration performed by stty when it starts. This answer claims that one can run stty after screen starts, but when I do this I get the error Device or resource busy.
This answer also addresses the issue with CR/LF in screen. It refers to the Window Types section of screen's online documentation.
"an exclusive open is attempted on the node to mark the connection line as busy" -- so we shouldn't be able to change the tty options after starting screen.
Only
baud_rate,cs8/cs7(number of bits per byte),ixon/off, andistripare documented options. This probably means that ocrnl etc. aren't recognized/supported by screen.
In summary: The question of how to get screen to send LF (\n) instead of CR (\r) has been asked several times on various stack-exchange sites. None of the provided answers work, and a thorough reading of the documentation suggests that it's not possible at this time.
You should use:
echo -e "Hello World\n" > /dev/ttyUSBxwhere x={0,1,...n}
The -e is used to send (i.e. interpretation of) special characters
Check help on Ubuntu 18.04 terminal:
~$ help echo
echo: echo [-neE] [arg ...] Write arguments to the standard output. Display the ARGs, separated by a single space character and followed by a newline, on the standard output. Options: -n do not append a newline -e enable interpretation of the following backslash escapes -E explicitly suppress interpretation of backslash escapes
(...) 1