1

My laptop runs a Python program that reads a joystick to send a speed command to an Arduino that in turn controls the motor on a toy car. To do that the program converts an integer with values between 0 and 255 to a single unsigned byte that it sends over a serial connection to the Arduino.

This code works to do that:

           if event.axis == axis:
                speed = int((event.value + 1.0) / 2.0 * 255.0)
                speedCommand = bytearray(b'\x00')
                speedCommand[0] = speed
                speedCommand = bytes(speedCommand)
                ser.write(speedCommand)
                print(speed, speedCommand)

While that code works, it's not very elegant. I would like to find a one-line instruction that does the same thing as the three lines that start with "speedCommand". I tried this, for example:

            speedCommand = chr(speed).encode()

But it only works for 0 to 127. Any number above 127 encodes to two bytes[, as the character is seen as a signed byte with values above 127 being negative].

EDITED TO ADD: My assumption that "the character is seen as a signed byte with values above 127 being negative" may not be correct.

Daanii
  • 259
  • 2
  • 3
  • 12
  • " as the character is seen as a signed byte with values above 127 being negative." I don't think that's what's going on, in any case, I've provided an answer – juanpa.arrivillaga Apr 10 '21 at 22:27
  • FYI `speed = chr(speed).encode('latin1')` would fix your encoding problem. The encoding defaults to `utf8` otherwise – Mark Tolonen Apr 10 '21 at 22:31
  • Mark Tolonen, that `chr(speed).encode('latin1')` solution does indeed work in my program. Good to know. – Daanii Apr 10 '21 at 23:04

2 Answers2

2

You just need:

speed_command = bytes([speed])

The bytes constructor accepts an iterable of int objects, so just put it in a list when you pass it to the constructor.

juanpa.arrivillaga
  • 88,713
  • 10
  • 131
  • 172
2

You can use the pack method from the struct built-in module. It takes as first argument a format, and as next arguments a value (or multiple values) to pack into this format. For an unsigned char, the required format is B. The module supports many other formats, which might be useful for sending other data to your Arduino. See the struct module documentation for more information, including a list of format characters.

>>> import struct
>>> speed = 255
>>> struct.pack('B', speed)
b'\xff'
luuk
  • 1,630
  • 4
  • 12
  • That `struct` module is a good one to know about in sending data to the Arduino. I can use it in a couple of other places in my program. Thanks. – Daanii Apr 10 '21 at 23:00