Spurious transmission when reading from serial port under linux (ttyUSB..) - linux

I have a USB to RS485 converter connected to my linux box:
ID 067b:2303 Prolific Technology, Inc. PL2303 Serial Port
and it is currently st up using
stty -F /dev/ttyUSB0 raw 57600
So when I write some characters to the device (using echo or the similar on the console) I can monitor the TX LED flash and I can clearly identify the characters on an oscilloscope.
However, when I try to read characters from it something weird happens:
I connected a simple teletyper to the RS485 output.
When I type a couple of characters on it I can watch the oscilloscope and I notice the flashing of the RX LED in the converter.
Then I start reading from the device, e.g. using cat /dev/ttyUSB0.
Now whenever I type a character on the teletyper both the RX and TX LEDs flash, and as expected, I can see garbled signals on the oscilloscope as RS485 is only half-duplex. So basically the teletyper is using the lines at the same time as the linux box seems to send something, causing a clash.
When I kill the cat process this stops and everything is fine again.
I have never witnessed this before. What am I missing?

As you were.
It's the line discipline: The linux box has had its echo enabled, so it actually echoed back every incoming character.
The solution is to disable this:
stty -F /dev/ttyUSB0 -echo

Related

Reading data from the serial port of a STM32 using the Linux terminal

I'm trying to read and send data with a STM32F429ZI using a RS232-USB cable.
For the hardware, I'm using a RS232 DB9 to TTL MAX3232 converter connected to the UART2 ports PA2 and PA3 of the STM32. I don't know if this is relevant, but I'm using a couple of 10 cm long cables to connect the TX-RX of the RS232 module to the STM32.
Then, I'm trying to use the Linux terminal on Kubuntu to send and read data from the uC. These are the steps I'm following to configure the connection:
Using ls -lah /dev/ I look where the RS232-USB is connected. In my case, I can see that it connects to /dev/ttyUSB0.
Then I give my user permissions to read and write the USB port using sudo chmod o+rw /dev/ttyUSB0.
After that, I configure the baud rate of the connection with the stty command. In my case, I'm configuring the STM32 to work at 9600 bauds per second, so stty -F /dev/ttyUSB0 9600. Using stty -F /dev/ttyUSB0 -a, I can see that the speed is actually 9600 bauds per second.
So far so good. I can send data from my computer to the STM32 with no problems. To test this, I'm doing the following:
I have a 2x16 LCD display connected to the STM32, where I print the data I send from my computer.
To send data from the terminal, I'm just doing echo -n 'a' > /dev/ttyUSB. This seems to work just fine, as I can print the data in the LCD display correctly.
I have even tested a program to count the characters on a file and the time the operations takes, in order to corroborate the 9600 baud rate. To do this, I created a file with 9600 characters and I used cat test.txt | tr '\n' '#' > /dev/ttyUSB0 to send the file to the STM32. This is working mostly fine, I usually get the correct answer but other times I don't. Nonetheless, the times it doesn't work are quite low, so I'm assuming it is due to noise.
So, having tested I can actually send data from my computer to the STM32, I tried to do the opposite: to send data from the STM32 to my computer. But this doesn't seem to work, as I can't really read anything in my computer.
I have read in several forums that to read data from the serial on the Linux console, one just has to use the cat command on the device. So, I tried that in several ways but I just couldn't read anything:
cat /dev/ttyUSB0 shows nothing and I have to quit with Ctrl+C.
cat -v /dev/ttyUSB0 shows nothing and I have to quit with Ctrl+C.
cat < /dev/ttyUSB0 shows nothing and I have to quit with Ctrl+C.
cat /dev/ttyUSB0 & just shows a number and it finishes.
So, I don't know if I'm just using the cat command wrong or if it is a hardware problem or why I can send data from my computer but not read.
Here is the part of the program (in C) I'm using in the STM32 to read and send data:
while(1)
{
if (USART_GetFlagStatus(USART2, USART_FLAG_RXNE) != RESET)
{
Data = USART_ReceiveData(USART2);
while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET)
USART_SendData(USART2, Data);
}
}
If someones needs it, I can upload the configuration of the USART ports, but I don't know if it will be relevant considering I can read data just fine.
Any help is appreciated.
Thanks in advance.
Edit: here's the current project - https://github.com/AugustoRiedinger/06TP_E02 ; and the project to read data https://github.com/AugustoRiedinger/06TP_E01
Your loop says "as long as it is not possible to send a byte, repeatedly try to send it anyway, as soon as it is possible to send a byte, discard it without sending"
Change:
while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET)
USART_SendData(USART2, Data);
To:
while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
USART_SendData(USART2, Data);

Sending files over Half-duplex interface

I'm trying to send files over a half-duplex interface (RS-485) between a box PC running debian (4.19) and a SBC with an im6xDL.
Thanks to this community I can successfully transfer simple data between the units using picocom or by echoing/reading.
The box PC supports half-duplex RS-485 natively and has automatic RTS functions so that you can read/send data without any issue. The SBC on the other hand needs to be toggled to change into RX or TX mode.
This turned out to be a problem when I tried to send files from the box PC to the SBC.
On the box PC:
picocom /dev/ttyUSB0 -b 9600 -fn
C-a,C-S
***file: /home/user/test.txt
Transfer incomplete
*** exit status: 128
On the SBC
picocom /dev/ttymxc2 -b 9600 -fn -et
C-a,C-r
Terminal ready
�000000
As you can see something is terribly wrong, it is like it cannot interpret the bits when a file is being transferred.
My questions:
Is it possible to send files from the command line in half-duplex systems? (The SBC needs to be in RX mode the entire time).
Is there another way to achieve this that is more intuitive?
As always, thanks for the help and support :)
/W
See here:
Pymodbus - Read input register of Energy meter over rs485 on uart of raspberry pi3
The solution I presented there using pylibmodbus should work for any hardware with UART and one or two GPIO lines accessible from user space in Linux.
If, on the other hand, what you want to do is use something like picocom or minicom then you can take a look at the hardware-only solution using a 555 timer.
Of course, if prototyping circuits is not for you, you can always buy a USB to RS485 with half-duplex support. You have many available but those based on the MAX13487 IC seem to work very well.
EDIT: The solution using the 555 timer is not in the post I linked above but here together with some more background material on half-duplex RS485 links: RS485: Inappropriate ioctl for device

cat /dev/ttyUSB - Why does this work, also why doesn't it work

I have an devive blasting some data continiously into an FTDI that's connected to my PC over USB. I want to log the data into a CSV using a simple bash script.
When I cat /dev/ttyUSB0 I'm getting some characters that I want (1023) and also some malformed random character.
How does the phy reciving the data know the baud rate?
Where are the malformed packets coming from?
Running: Debian GNU/Linux 8 (jessie) 64-bit
Screencap of output
You can set the baud rate using stty. For example to set the baudrate to 9600 do:
stty -F /dev/ttyUSB0 9600
This could because ground has not been connected between the devices. Loose connections. Noise if you use long serial wires. There could be many reasons.

U-Boot - Embedded Linux - Terminal Connection

I have an embedded linux board with a max3222e RS232 converter. The pins are availlable on soldering pins. I think I've figured out the ground pin, the TX pin and the RX pin. When I connect my pc with a terminal program, I can see the boot logs of the embedde linux system. Also I can stop u-boot with pressing any key. But when I try to use some boot arguments then the characters of the pressed key are not the same like on the pc. For example:
Enter->y
a -> 0
s -> F
Can anybody tell me what's wrong. The serial settings are 115200 Baut 8N1 and no Flowcontrol.
Thanks a lot
Karl-Heinz
What terminal you use ? I use minicom. I have set
`NO PROGRAMING FLOW CONTROL,'
`YES DEVICE FLOW CONTROL`.
And u-boot char is send good.
You try other terminal for example putty for windows ?

How to open serial port in linux without changing any pin?

Posix requires changing RTS pin on port opening. I want a way to avoid it.
I have no idea why you'd want to do this, but this can be done pretty easily by modifying the linux kernel driver for your serial console so it doesn't toggle RTS. For example, for the 8250-series driver in drivers/tty/serial/8250/ you could change every write to the MCR register (UART_MCR) to ensure that bit 1 (mask is UART_MCR_RTS) is never set.
Since it's abstracted away in userspace, you're out of luck if you want to do this without modifying the kernel driver.
Having the same problem, I'd give it a try by patching the ftdi_sio kernel driver. You just need to uncomment a small piece of code in ftdi_dtr_rts() like this:
static void ftdi_dtr_rts(struct usb_serial_port *port, int on) {
...
/* drop RTS and DTR */
if (on)
set_mctrl(port, TIOCM_DTR /*| TIOCM_RTS*/); // <<-- HERE
else
clear_mctrl(port, TIOCM_DTR /*| TIOCM_RTS*/); // <<-- and HERE
}
and the RTS handshake line is not longer changed upon open() call.
Note, that the uart than might not longer working with RTS/CTS hardware handshake, as long as your modified kernel driver is loaded. But you can still control the state of the RTS handshake line manually by calling e.g.:
int opins = TIOCM_RTS;
ioctl(tty_fd, TIOCMBIC, &opins);
I'd tested this with the Ctrl+A+G command of picocom 2.3a, running Kubuntu 16.04 64 bit and Ftdi FT2232H based usb uart adapter.
You might find more details on this topic here.
A change in the DTR pin can be (eventually) avoided using the command line
stty -F /dev/ttyUSB0 -hupcl
This has the effect of making DTR turn on; and subsequently when the port is opened and closed, DTR is not affected.
Source: https://raspberrypi.stackexchange.com/questions/9695/disable-dtr-on-ttyusb0/27706#27706
And there is code there to do the same thing from python via termios, this can be done before opening the port via pyserial:
import termios
path = '/dev/ttyACM0'
# Disable reset after hangup
with open(path) as f:
attrs = termios.tcgetattr(f)
attrs[2] = attrs[2] & ~termios.HUPCL
termios.tcsetattr(f, termios.TCSAFLUSH, attrs)
The OP was running this on a Raspberry Pi, but I just tried it on Linux Mint on x86_64, it worked. I don't know how RTS is affected.
The reason I find this useful, is for communication with an Arduino Nano - which has a USB-> serial chip on board - and normally the Arduino gets reset every time you open the serial port from linux (rising edge of DTR causes reset). For some applications, this is not a problem, but it's clearly useful to avoid this for other applications, and it's not so easy to remove that tiny capacitor from the Arduino which connects DTR to reset.
You will still get a single reset when the stty command is executed (after plugging in the USB cable). But at least you can then keep opening and closing the serial port after that without further resets.
calling fopen("/dev/ACM0", "r") doesn't require you do do anything:) You may not receive the data you expect though.

Resources