问题描述
Bluez问题: 我有一个RaspBerry Pi Z W,一个8bitdo SF30蓝牙控制器和一个我的雇主大量生产的机器人。我希望通过RPI通过遥控器控制机器人。
我有Rpi使用bluetoothctl连接到控制器,并且可以通过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,16916057)
(470898380,162488,22220,163502)
(470898380,16915382,22260,16910652)
(470898420,16908288,22290,161137)
(470898450,16971797,22300,155732)
(470898460,16966392,22330,154043)
(470898490,16966054,22340,147287)
(470898500,16967405,131072)
(470898500,22740,151060481)
(470899070,151060480,22970,134283265)
(470899320,134283264,23200,117506049)
(470899550,117506048,23420,100728833)
(470899750,100728832,23590,117506049)
(470899910,23930,134283265)
(470900310,25110,100728833)
(470901380,117506049,25250,134283265)
(470901490,25390,117506048)
(470901710,25580,100728833)
(470901750,25720,117506048)
(470901940,134283265,25810,100728832)
(470902160,100728833,26070,134283264)
(470902400,26690,134283265)
(470903070,27130,151060481)
(470903430,27360,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,action))
如果您想更高一点,那么像https://github.com/ApproxEng/approxeng.input这样的库是一个受欢迎的库。