New: the AI firewall watches the whole platform and explains each incident in plain words. See how it works

USB-RS232 scale indicator on Pi: permission error, ttyUSB0/ttyUSB1 keeps changing, readline hangs

USB-RS232 scale indicator on Pi: permission error, ttyUSB0/ttyUSB1 keeps changing, readline hangs

Solved 6 5

Translated from Türkçe by AI ·

Hi. We have a weighing indicator in the warehouse (RS232 output, continuously transmitting weight). I connected it to a Raspberry Pi 4 with a USB-RS232 converter; my goal is to read the weight with Python and send it to Hermetry via MQTT. On the Pi I’m running Raspberry Pi OS Lite, Python 3.11, pyserial 3.5.
On the first attempt I got this error:

serial.serialutil.SerialException: [Errno 13] could not open port /dev/ttyUSB0:
[Errno 13] Permission denied: '/dev/ttyUSB0'

The code is simple:

ser = serial.Serial('/dev/ttyUSB0', 9600)
while True:
    line = ser.readline()
    print(line)

What should I do? Also, I’d eventually like this to run on its own as a service, so I’d appreciate suggestions with that in mind.

♥ 0

Translated from Türkçe by AI ·

Does it happen when you run it with sudo? It happened to me too.

♥ 0

Translated from Türkçe by AI ·

That’s fine, but don’t run the service as root. Add the user to the dialout group: sudo usermod -aG dialout $USER, then log out and log back in.

Sahadan selamlar.
♥ 0

Translated from Türkçe by AI ·

The permission problem is gone after adding the user to dialout, thanks. But I have two new issues: after rebooting the Pi, sometimes the scale indicator becomes ttyUSB1 (there is also a USB-RS485 on the same Pi), and readline sometimes waits forever, with nothing being printed. The indicator data does flow in a terminal program, though.

♥ 0

Translated from Türkçe by AI ·

I experienced both, in a weighing scale project.Port name: the ttyUSB number is assigned based on enumeration order, so don’t trust it. Check with ls -l /dev/serial/by-id/, there is a permanent name containing the converter’s serial number, use that. If you have two of the same chip and no serial numbers, you can name them by USB port with a udev rule, but most of the time by-id is enough.readline: by default it waits for
. Most indicators end lines with , so it never returns. Also, if you don’t set a timeout, it waits forever when the cable is unplugged. What I use:

PORT = '/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A10K3XYZ-if00-port0'
ser = serial.Serial(PORT, 9600, bytesize=8, parity='N', stopbits=1, timeout=2)
buf = b''
while True:
    chunk = ser.read(64)
    if not chunk:
        continue          # no data for 2 s, log here
    buf += chunk
    while b'' in buf:
        line, buf = buf.split(b'', 1)
        w = parse_weight(line)   # e.g. b'ST,GS,+0012.45kg'
        if w is not None:
            client.publish('v1/telemetry', json.dumps({'weight_kg': w}), qos=1)

If the indicator prints several times a second, don’t send every line. Send once per second, or only the ST (stable) lines. Write a systemd unit for the service, put your own user in the User= line, and use Restart=always.

Ağ geçidi yine bağlanıyor…
Accepted solution♥ 5

Translated from Türkçe by AI ·

The line ending really is , I checked with hexdump. The port problem is also solved with by-id. Now I just send stable readings once a second, and it has been running without issues for 2 days with systemd. Thanks.

♥ 0

Translated from Türkçe by AI ·

Cheap CH340-based converters have no serial number, and both show up the same under by-id. In that case, use /dev/serial/by-path/; it stays tied to the USB port.

♥ 1
Viewing 7 posts – 1 through 7 (of 7 total)
  • You must be logged in to reply to this topic.

Join the conversation

Sign in to ask and answer, like helpful posts and mark the reply that solved your problem. Every contribution earns points and levels.

Share