[英]SF30 Controller Bluez Programming
Bluez 问题:我有一个 Raspberry Pi ZW、一个 8bitdo SF30 蓝牙控制器和一个我的雇主批量生产的机器人。 我希望通过遥控器从 RPI 控制机器人。
我使用 bluetoothctl 将 RPi 连接到控制器,并且我可以通过 btmon(蓝牙监视器)查看来自控制器的消息。 很明显,下面的四个“80”值对应于两个操纵杆的中点。
> ACL Data RX: Handle 11 flags 0x02 dlen 15 #30 [hci0] 2.555574
Channel: 65 len 11 [PSM 0 mode Basic (0x00)] {chan 65535}
a1 03 0f 80 80 12 31 00 00 00 00 ......1....
> ACL Data RX: Handle 11 flags 0x02 dlen 15 #31 [hci0] 2.587293
Channel: 65 len 11 [PSM 0 mode Basic (0x00)] {chan 65535}
a1 03 0f 80 80 27 4b 00 00 00 00 .....'K....
> ACL Data RX: Handle 11 flags 0x02 dlen 15 #32 [hci0] 2.613543
Channel: 65 len 11 [PSM 0 mode Basic (0x00)] {chan 65535}
a1 03 0f 80 80 61 7b 00 00 00 00 .....a{....
> ACL Data RX: Handle 11 flags 0x02 dlen 15 #33 [hci0] 2.615552
Channel: 65 len 11 [PSM 0 mode Basic (0x00)] {chan 65535}
a1 03 0f 80 80 80 80 00 00 00 00 ...........
> ACL Data RX: Handle 11 flags 0x02 dlen 15 #34 [hci0] 74.653567
Channel: 65 len 11 [PSM 0 mode Basic (0x00)] {chan 65535}
a1 03 0f 80 80 80 80 00 00 00 08 ...........
我还一直在使用格式 LLHHQ 从 Python 中的两个结果 /dev/input/ 文件(/dev/input/js0 和 /dev/input/event0)中读取数据。 我认为来自 btmon(易于解释)的相同数据将在该格式的 Q 部分(下面的最后一个数字)中表示。
(470898350, 155732, 22190, 7185, 16919435)
(470898350, 160124, 22190, 7185, 16916057)
(470898380, 162488, 22220, 7185, 163502)
(470898380, 16915382, 22260, 7185, 16910652)
(470898420, 16908288, 22290, 7185, 161137)
(470898450, 16971797, 22300, 7185, 155732)
(470898460, 16966392, 22330, 7185, 154043)
(470898490, 16966054, 22340, 7185, 147287)
(470898500, 16967405, 22340, 7185, 131072)
(470898500, 16908288, 22740, 7185, 151060481)
(470899070, 151060480, 22970, 7185, 134283265)
(470899320, 134283264, 23200, 7185, 117506049)
(470899550, 117506048, 23420, 7185, 100728833)
(470899750, 100728832, 23590, 7185, 117506049)
(470899910, 117506048, 23930, 7185, 134283265)
(470900310, 134283264, 25110, 7185, 100728833)
(470901380, 117506049, 25250, 7185, 134283265)
(470901490, 100728832, 25390, 7185, 117506048)
(470901710, 134283264, 25580, 7185, 100728833)
(470901750, 117506049, 25720, 7185, 117506048)
(470901940, 134283265, 25810, 7185, 100728832)
(470902160, 100728833, 26070, 7185, 134283264)
(470902400, 100728832, 26690, 7185, 134283265)
(470903070, 134283264, 27130, 7185, 151060481)
(470903430, 151060480, 27360, 7185, 100728833)
然而,这些输出在读入二进制时似乎并不对应,例如两个操纵杆似乎改变了相同的位。
我的问题的基本问题是如何获取在基于 bluez 的代码中在 btmon 中读取的相同数据。
这是我目前使用的python代码。
f = open( "/dev/input/js0", "rb" ); # Open the file in the read-binary mode
EVENT_SIZE = struct.calcsize("LLHHQ")
while 1:
data = f.read(EVENT_SIZE)
unpacked_data = struct.unpack('llHHQ',data)
# print("Length:" + str(len(unpacked_data)))
# print(unpacked_data)
remote_data = unpacked_data[4]
print(format(remote_data, '064b'))
使用像evdev这样的库可能会有所帮助,因为它可以为您完成很多繁重的工作。
使用它的示例可能是:
from time import sleep
from pydbus import SystemBus
import evdev
# For testing
# python3 -m evdev.evtest
class Controller:
def __init__(self, adapter_int=0):
adapter_path = '/org/bluez/hci{}'.format(adapter_int)
self.dbus = SystemBus()
self.adapter = self.dbus.get('org.bluez', adapter_path)
# Use bluetoothctl to find out what the path is for your controller
self.controller = self.dbus.get('org.bluez', '/org/bluez/hci0/dev_DC_0C_2D_20_DA_E8')
print('Waiting for connection from DC:0C:2D:20:DA:E8')
# self.controller.Discoverable = True
while not self.controller.Connected:
sleep(1)
print('Connected')
sleep(6)
# https://python-evdev.readthedocs.io/en/latest/tutorial.html to get path of your controller
self.device = evdev.InputDevice('/dev/input/event2')
self.max_value = 0
self.min_value = 255
self.max_throttle = 1
self.min_throttle = -1
self.right_steering = 1
self.left_steering = -1
def map_throttle(self, value):
input_range = self.max_value - self.min_value
output_range = self.max_throttle - self.min_throttle
input_percentage = (value - self.min_value) / input_range
output_value = (output_range * input_percentage) + self.min_throttle
return round(output_value, 2)
def map_steering(self, value):
input_range = self.max_value - self.min_value
output_range = self.right_steering - self.left_steering
input_percentage = (value - self.min_value) / input_range
output_value = (output_range * input_percentage) + self.left_steering
return round(output_value, 2)
def get_events(self):
for event in self.device.read_loop():
ly = None
rx = None
btn = None
if event.type == evdev.ecodes.EV_ABS:
if event.code == 1:
# print('Left:', event.value)
ly = self.map_throttle(event.value)
if event.code == 3:
# print('Right:', event.value)
rx = self.map_steering(event.value)
if event.type == evdev.ecodes.EV_KEY:
if event.code == evdev.ecodes.BTN_SOUTH and event.value == 0:
btn = 'BTN_SOUTH'
elif event.code == evdev.ecodes.BTN_WEST and event.value == 0:
btn = 'BTN_WEST'
elif event.code == evdev.ecodes.BTN_NORTH and event.value == 0:
btn = 'BTN_NORTH'
elif event.code == evdev.ecodes.BTN_EAST and event.value == 0:
btn = 'BTN_EAST'
yield ly, rx, btn
if __name__ == '__main__':
ctrl = Controller()
for speed, steer, action in ctrl.get_events():
print('Speed: {}, Steer: {}, Button: {}'.format(speed, steer, action))
如果你想更上一层楼,那么像https://github.com/ApproxEng/approxeng.input这样的库是一个流行的库。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.