Cleaning up UART data

CircuitPython on hardware including Adafruit's boards, and CircuitPython libraries using Blinka on host computers.

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
sebastienperth
 
Posts: 113
Joined: Fri Jan 15, 2021 4:21 pm

Cleaning up UART data

Post by sebastienperth »

Hello,
I have a RFID reader, hooked up to a Feather M0 express. I want to send that data as keyboard input.
The reader sends ASCII formatted data. When I print to serial, I get
b'\r\n-5500C147AA\r\n>'
I've tried using:

Code: Select all

import board
import busio
import digitalio

uart = busio.UART(board.D1, board.D0, baudrate=9600)

while True:
    data = uart.read() 
    if data is not None:
        data_string = ''.join([chr(b) for b in data])
        print(data_string, end="")
While that gets me:
-5500C147AA
If I try to send that using layout.write(data_string) I get this error message:
ValueError: No keycode available for character '\r' (13/0x0d).
I've tried using 'replace' as well without success.
I just want to keep the tag as read, without escape codes or whitespace.

User avatar
mikeysklar
 
Posts: 13824
Joined: Mon Aug 01, 2016 8:10 pm

Re: Cleaning up UART data

Post by mikeysklar »

Lots of ways to filter out escape codes. Here is one example:

Code: Select all

>>> s="\x01\x02\x10\x13\x20\x21hello world"
>>> print(s)
 !hello world
>>> s
'\x01\x02\x10\x13 !hello world'
>>> escapes = ''.join([chr(char) for char in range(1, 32)])
>>> translator = str.maketrans('', '', escapes)
>>> t = s.translate(translator)
>>> t
' !hello world'
Another would be to make a simple function test:

Code: Select all

def is_ascii(s):
    try:
        s.decode('ascii')
        return True
    except UnicodeDecodeError:
        return False

User avatar
neradoc
 
Posts: 542
Joined: Wed Apr 27, 2016 2:38 pm

Re: Cleaning up UART data

Post by neradoc »

Hi, you can remove the \r and \n at the start and end with strip().
You convert bytes to str with decode(). (CP only supports UTF8).

Code: Select all

    data = uart.read()
    if data:
    	data_string = data.decode().strip()
    	layout.write(data_string)

User avatar
sebastienperth
 
Posts: 113
Joined: Fri Jan 15, 2021 4:21 pm

Re: Cleaning up UART data

Post by sebastienperth »

I've tried a few ways of doing this, and just now using your suggestion I get this:
Traceback (most recent call last):
File "code.py", line 20, in <module>
File "adafruit_hid/keyboard_layout_base.py", line 121, in write
ValueError: No keycode available for character '\r' (13/0x0d).
I just can't seem to shake that \r

User avatar
neradoc
 
Posts: 542
Joined: Wed Apr 27, 2016 2:38 pm

Re: Cleaning up UART data

Post by neradoc »

Ah yeah that would be because the \r\n is inside the data you receive because it sends multiple lines. You would want to split on that or use readline() to read a single line at a time.

You can print the data that causes the error before trying to type it to see:

Code: Select all

if data:
    print(data)
Read one line at a time, assuming that the device only sends lines.

Code: Select all

if uart.in_waiting > 0: # only try to read if there's data
    data = uart.readline().strip() # read a line and strip whitespaces
    if data: # received something
        print(data) # debug print
        data_string = data.decode() # get the string version
        layout.write(data_string)

User avatar
neradoc
 
Posts: 542
Joined: Wed Apr 27, 2016 2:38 pm

Re: Cleaning up UART data

Post by neradoc »

Note that if it's possible that the RFID reader sends incomplete lines with \r in the middle, you would want to discard that data since it's likely incorrect:

Code: Select all

try:
    layout.write(data_string)
except ValueError:
    print(f"Error with <{data_string}> {data}")
    # maybe make a sound if possible or light up a red LED to say error ?

Locked
Please be positive and constructive with your questions and comments.

Return to “Adafruit CircuitPython”