SF30控制器Bluez编程

问题描述

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这样的库是一个受欢迎的库。