UART - working with bytes objects

General discussions and questions abound development of code with MicroPython that is not hardware specific.
Target audience: MicroPython Users.
Post Reply
mschulz
Posts: 35
Joined: Fri Apr 17, 2015 11:26 am
Location: Germany

UART - working with bytes objects

Post by mschulz » Sun Jun 21, 2015 6:45 pm

Hello,
I communicate over UART with an other Komponent to get commands.

At first I check,if there is a message

Code: Select all

uart2.any()
Then I read the messeage and print it.

Code: Select all

command =  self.__uart2.read(9)
print('INFO-YB: read:',command)
This is the result:
b'\x01\x88\x00\x00\x00\x00\x00\x00\x89'
This is coded in Hex.

Now I want to dismantle this in individuals:
01 => irrelevant
88 => 136 (command)
00 => 0 (type)
00 => irrelevant
00 => irrelevant
00 => irrelevant
00 => irrelevant
00 => value with the MSB first, here I need the decimal value to use it.
89 => Checksum(Summe of all)

I do not need the Dec value, but I must calc the Checksum and read some of the values?

Whitch is the best way to dismantle this?

Should I use this?

Code: Select all

uart.readinto(buf, 9)
Or can I dismantle the strinng with command[1,2] etc?

Which, do you think, is the easiest solution?

Thank you very much!

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: UART -

Post by dhylands » Mon Jun 22, 2015 5:27 am

You can use indicies just like with regular strings:

Code: Select all

>>> x = b'ABCDEF'
>>> x[1:3]
b'BC'
>>> x[1]
66
>>> bytes((66,))
b'B'
The difference between read and readinto is that read always allocates a new buffer. With readinto you need to allocate the buffer ahead of time but you can reuse it over and over.

You can use the following to calculate the sum:

Code: Select all

>>> x = b'\x01\x88\x00\x00\x00\x00\x00\x00\x89'
>>> sum(x[0:8])
137
>>> hex(137)
'0x89'

mschulz
Posts: 35
Joined: Fri Apr 17, 2015 11:26 am
Location: Germany

Re: UART -

Post by mschulz » Mon Jun 22, 2015 12:57 pm

Thank you for your answer.

when I want to use readinto[buf,9], how I must define the buffer?

Code: Select all

buf=bytearray(18)
To convert from hex to dec work very vel with hex() and int()

To use indices like with regular strings, what is with the '\x'?

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: UART -

Post by dhylands » Mon Jun 22, 2015 2:38 pm

With regular strings and binary strings, you can specify the individual bytes or characters using hex notation. For example, an uppercase A has a hex value of 0x41 or a decimal value of 65.

So you can create a binary string with an uppercase A in a variety of ways:

Code: Select all

>>> b'A'
b'A'
>>> b'\x41'
b'A'
>>> bytes((65,))
b'A'
>>> bytes((0x41,))
b'A'
When printing a binary string, the \x notation is used for characters which are outside the ASCII range. The \x must be followed by 2 hex digits and the 4 byte sequence \x12 used in byte strings to represent a single byte with a value of 0x12 (hexadecimal) or 18 (decimal). Although there are few other special escape sequences as well (\t = TAB = \x09)

Code: Select all

>>> x = b'\x08\x09'
>>> x[0]
8
>>> x[1]
9
>>> x
b'\x08\t'

Damien
Site Admin
Posts: 647
Joined: Mon Dec 09, 2013 5:02 pm

Re: UART -

Post by Damien » Mon Jun 22, 2015 3:17 pm

When you read data from the UART it returns a "bytes" object, which is simply an array of bytes. When printing a "bytes" object Python prints a "b" at the start to indicate that it's bytes. It uses hex notation to display bytes that don't have an associated ASCII character.

To get individual bytes it's best to use the subscript operation:

Code: Select all

data = uart.read(9)
command = data[1]
type = data[2]
value = data[7]
checksum = data[8]
These variables that you assign to will have integer values, eg command = 0x88 = 136 in your example.

A more concise way of extracting the data is to use tuple unpacking:

Code: Select all

_, data, command, _, _, _, _, value, checksum = data
To check the checksum you can use:

Code: Select all

if sum(data[0:7]) == data[8]:
    print("checksum passed")
else:
    print("checksum failed")

mschulz
Posts: 35
Joined: Fri Apr 17, 2015 11:26 am
Location: Germany

Re: UART - working with bytes objects

Post by mschulz » Tue Aug 04, 2015 10:30 am

Thank you,
I check with
newinstruction = self.__uart2.any()
if true I read
message = self.__uart2.read(9)
print(message)
modulard, commandnr, typenr, banknr, value0, value1, value2, value3, checksum = message

Sometimes ist works very well but with some messages I print only 2 parts and so I get an error.

Have sombody an good idea why I lost some parts of the message?
With my WLAN Modul (ESP8266) I have sometimes the same problem, that I lost a part of an message

Thank you

Post Reply