【项目背景】
最近买了两个Xbox手柄,这个手柄支持Bluetooth(蓝牙4.0),行空板也支持蓝牙功能。本项目中,Xbox手柄通过蓝牙连接行空板,控制麦克纳姆轮车。
【行空板启动蓝牙】
蓝牙(Bluetooth)是一个短距离无线通信标准,用于在手机、计算机和其他电子设备之间通信。行空板自带 Linux 系统,在 Linux 中权威的蓝牙协议栈实现是 BlueZ。其本身自带了很多有用的工具,如bluetoothctl。
1.电脑通过USB线连接上行空板,通过浏览器地址:10.1.2.3,访问行空板,开启终端。
- root@unihiker:~#Bluetoothctl
复制代码
复制代码 扫描蓝牙设备,找到Xbox手柄蓝牙地址(40:8E:2C:22:84:31) 复制代码
【行空板Python连接Xbox】
使用os库的system执行蓝牙连接命令。 -
- import os
- import time
-
- result=0
- def shellcom(command,wait):
- global result
- # 调用os模块的system()函数来执行Shell命令
- result = os.system(command)
- #print(result)
- time.sleep(wait)
-
-
- shellcom("bluetoothctl power on",5)
- if result==0:
- print("蓝牙已开启")
-
- #shellcom("bluetoothctl scan on",10)
- #shellcom("bluetoothctl scan off",2)
- shellcom("bluetoothctl agent on",5)
- if result==0:
- print("代理已开启")
-
- shellcom("bluetoothctl pair 40:8E:2C:22:84:31",10)
- if result==0:
- print("蓝牙配对已完成")
- else:
- print("蓝牙配对可能已存在")
-
- shellcom("bluetoothctl connect 40:8E:2C:22:84:31",4)
- if result==0:
- print("Xbox连接已完成")
- else:
- print("Xbox连接失败")
复制代码 【读取Xbox手柄各按键】
使用pygame库读取Xbox手柄各按键。 -
- import pygame
- pygame.init()
- joysticks = []
- clock = pygame.time.Clock()
- keepPlaying = True
-
- pygame.joystick.init()
- # 初始化手柄
- joystick = pygame.joystick.Joystick(0)
- joystick.init()
- while keepPlaying:
- clock.tick(60)
- for event in pygame.event.get():
-
- print(event)
复制代码
 -
- import pygame
- pygame.init()
- pygame.joystick.init()
- # 初始化手柄
- joystick = pygame.joystick.Joystick(0)
- joystick.init()
-
- while True:
- for event in pygame.event.get():
- if event.type == pygame.JOYBUTTONDOWN:
- if event.button==0:#"A"键
- pass
- elif event.button==1:#"B"键
- pass
- elif event.button==4:#"X"键
- pass
- elif event.button==3:#"Y"键
- pass
- elif event.button==6:#"RB"键,右肩键:Right Shoulder Button
- pass
- elif event.button==7:#"LB"键,左肩键:Left Shoulder Button
- pass
- elif event.button==10:#"View"键
- pass
- elif event.button==11:#"Menu"键
- pass
- elif event.button==15:#“共享”按键
- pass
- elif event.button==12:#“xbox”按键
- pass
- elif event.type == pygame.JOYHATMOTION:#方向键
- if event.hat==0:
- print(str(event.value[0])+":"+str(event.value[1]))
- if event.value[0]==0:
- if event.value[1]==0:#中间位置
- print("“中间位置”方向键")
-
- elif event.value[1]==1:#向上
- print("“向上”方向键")
-
- elif event.value[1]==-1:#向下
- print("“向下”方向键")
-
- elif event.value[0]==-1:#向右
- print("“向右”方向键")
-
- elif event.value[0]==1:#向左
- print("“向左”方向键")
-
- elif event.type == pygame.JOYAXISMOTION:
- #左摇杆按键
- if event.axis==0:#左右
- if event.value<-0.1:#向左
-
- print("“向左”左摇杆按键")
- elif event.value>0.1:#向右
-
- print("“向右”左摇杆按键")
- else:
-
- print("左右stop左摇杆按键")
- elif event.axis==1:#上下
- if event.value<-0.1:#向上
-
- print("“向上”左摇杆按键")
- elif event.value>0.1:#向下
-
- print("“向下”左摇杆按键")
- else:
-
- print("上下stop左摇杆按键")
- #右摇杆按键
- if event.axis==2:#左右
- if event.value<-0.1:#向右
-
- print("“向右”右摇杆按键")
- elif event.value>0.1:#向左
-
- print("“向左”右摇杆按键")
- else:
-
- print("“停止”右摇杆按键")
- elif event.axis==3:#上下
- if event.value<-0.1:#向上
- print("“向上”右摇杆按键")
- elif event.value>0.1:#向下
- print("“向下”右摇杆按键")
- elif event.axis==5:#左射击键
- if event.value>0:
- print("左射击键")
-
- elif event.axis==4:#右射击键
- if event.value>0:
- print("右射击键")
复制代码
【控制麦克纳姆轮车】
1.电机驱动扩展板初始化 -
- from pinpong.extension.unihiker import *
- from pinpong.libs.microbit_motor import DFMotor
- from pinpong.board import Board
-
- from pinpong.board import Pin
-
- Board().begin()
-
- p_dfr0548_motor_M1 = DFMotor(1)
- p_dfr0548_motor_M2 = DFMotor(2)
- p_dfr0548_motor_M3 = DFMotor(3)
- p_dfr0548_motor_M4 = DFMotor(4)
复制代码
2.自定义麦克纳姆轮车运动函数-
- def forward(speed):#带速度参数——前进
- p_dfr0548_motor_M1.speed(speed)
- p_dfr0548_motor_M1.run(p_dfr0548_motor_M1.CCW)
- p_dfr0548_motor_M2.speed(speed)
- p_dfr0548_motor_M2.run(p_dfr0548_motor_M2.CCW)
- p_dfr0548_motor_M3.speed(speed)
- p_dfr0548_motor_M3.run(p_dfr0548_motor_M3.CW)
- p_dfr0548_motor_M4.speed(speed)
- p_dfr0548_motor_M4.run(p_dfr0548_motor_M4.CW)
- def back(speed):#带速度参数——后退
- p_dfr0548_motor_M1.speed(speed)
- p_dfr0548_motor_M1.run(p_dfr0548_motor_M1.CW)
- p_dfr0548_motor_M2.speed(speed)
- p_dfr0548_motor_M2.run(p_dfr0548_motor_M2.CW)
- p_dfr0548_motor_M3.speed(speed)
- p_dfr0548_motor_M3.run(p_dfr0548_motor_M3.CCW)
- p_dfr0548_motor_M4.speed(speed)
- p_dfr0548_motor_M4.run(p_dfr0548_motor_M4.CCW)
- def left(speed):#带速度参数——向左
- p_dfr0548_motor_M1.speed(speed)
- p_dfr0548_motor_M1.run(p_dfr0548_motor_M1.CW)
- p_dfr0548_motor_M2.speed(speed)
- p_dfr0548_motor_M2.run(p_dfr0548_motor_M2.CCW)
- p_dfr0548_motor_M3.speed(speed)
- p_dfr0548_motor_M3.run(p_dfr0548_motor_M3.CCW)
- p_dfr0548_motor_M4.speed(speed)
- p_dfr0548_motor_M4.run(p_dfr0548_motor_M4.CW)
- def right(speed):#带速度参数——向右
- p_dfr0548_motor_M1.speed(speed)
- p_dfr0548_motor_M1.run(p_dfr0548_motor_M1.CCW)
- p_dfr0548_motor_M2.speed(speed)
- p_dfr0548_motor_M2.run(p_dfr0548_motor_M2.CW)
- p_dfr0548_motor_M3.speed(speed)
- p_dfr0548_motor_M3.run(p_dfr0548_motor_M3.CW)
- p_dfr0548_motor_M4.speed(speed)
- p_dfr0548_motor_M4.run(p_dfr0548_motor_M4.CCW)
- def stop():#停止
-
- p_dfr0548_motor_M1.stop()
- p_dfr0548_motor_M2.stop()
- p_dfr0548_motor_M3.stop()
- p_dfr0548_motor_M4.stop()
- def Lrotate(speed):#带速度参数——向左原地旋转
- p_dfr0548_motor_M1.speed(speed)
- p_dfr0548_motor_M1.run(p_dfr0548_motor_M1.CCW)
- p_dfr0548_motor_M2.speed(speed)
- p_dfr0548_motor_M2.run(p_dfr0548_motor_M2.CCW)
- p_dfr0548_motor_M3.speed(speed)
- p_dfr0548_motor_M3.run(p_dfr0548_motor_M3.CCW)
- p_dfr0548_motor_M4.speed(speed)
- p_dfr0548_motor_M4.run(p_dfr0548_motor_M4.CCW)
- def Rrotate(speed):#带速度参数——向右原地旋转
- p_dfr0548_motor_M1.speed(speed)
- p_dfr0548_motor_M1.run(p_dfr0548_motor_M1.CW)
- p_dfr0548_motor_M2.speed(speed)
- p_dfr0548_motor_M2.run(p_dfr0548_motor_M2.CW)
- p_dfr0548_motor_M3.speed(speed)
- p_dfr0548_motor_M3.run(p_dfr0548_motor_M3.CW)
- p_dfr0548_motor_M4.speed(speed)
- p_dfr0548_motor_M4.run(p_dfr0548_motor_M4.CW)
复制代码

3.Xbox按键控制麦克纳姆轮车运动-
- if event.type == pygame.JOYHATMOTION:#方向键
- if event.hat==0:
- print(str(event.value[0])+":"+str(event.value[1]))
- if event.value[0]==0:
- if event.value[1]==0:#中间位置
- print("“中间位置”方向键")
- stop()
- elif event.value[1]==1:#向上
- print("“向上”方向键")
- forward(200)
- elif event.value[1]==-1:#向下
- print("“向下”方向键")
- back(200)
- elif event.value[0]==-1:#向右
- print("“向右”方向键")
- right(200)
- elif event.value[0]==1:#向左
- print("“向左”方向键")
- left(200)
-
- elif event.type == pygame.JOYAXISMOTION:
- #左摇杆按键
- if event.axis==0:#左右
- if event.value<-0.1:#向左
- left(int(abs(event.value)*255))
- print("“向左”左摇杆按键")
- elif event.value>0.1:#向右
- right(int(event.value*255))
- print("“向右”左摇杆按键")
- else:
- stop()
- print("左右stop左摇杆按键")
- elif event.axis==1:#上下
- if event.value<-0.1:#向上
- forward(int(abs(event.value)*255))
- print("“向上”左摇杆按键")
- elif event.value>0.1:#向下
- back(int(event.value*255))
- print("“向下”左摇杆按键")
- else:
- stop()
- print("上下stop左摇杆按键")
- #右摇杆按键
- if event.axis==2:#左右
- if event.value<-0.1:#向右
- Rrotate(int(abs(event.value)*255))
- print("“向右”右摇杆按键")
- elif event.value>0.1:#向左
- Lrotate(int(event.value*255))
- print("“向左”右摇杆按键")
- else:
- stop()
- print("“停止”右摇杆按键")
复制代码

4.控制车上灯(1)控制车底彩灯,共四个LED彩灯,使用NeoPixel库驱动。-
- if bs==1 and time.time()-time1>0.2:
- time1=time.time()
- np1.rotate(1)
- elif bs==2 and time.time()-time2>0.5:
- time2=time.time()
- np1.rotate(1)
- for event in pygame.event.get():
- if event.type == pygame.JOYBUTTONDOWN:
- if event.button==0:#"A"键
- print("“A”键")
- color=0xFF0000
- elif event.button==1:#"B"键
- print("“B”键")
- color=0x00FF00
- elif event.button==4:#"Y"键
- print("“Y”键")
- color=0x0000FF
- elif event.button==3:#"X"键
- print("“X”键")
- color=0xFF00FF
- elif event.button==6:#"RB"键,右肩键:Right Shoulder Button
- print("“RB”键")
- pin14.write_digital(1)
- pin15.write_digital(1)
- elif event.button==7:#"LB"键,左肩键:Left Shoulder Button
- print("“LB”键")
- pin14.write_digital(0)
- pin15.write_digital(0)
- elif event.button==10:#"View"键
- print("“View”键")
- bs=1
- np1.rainbow(0,3,1,360)
- elif event.button==11:#"Menu"键
- print("“Menu”键")
- bs=2
- np1.rainbow(0,3,1,360)
- elif event.button==15:#“共享”按键
- print("“共享”键")
- bs=0
- np1.clear()
- elif event.button==12:#“xbox”按键
- print("“xbox”键")
复制代码 (2)控制车前灯,两个LED灯分别接在引脚14、15。 -
- if event.axis==5:#左射击键
- if event.value>0:
- print("左射击键")
- np1.range_color(0,3,color)
- elif event.axis==4:#右射击键
- if event.value>0:
- print("右射击键")
- np1.clear()
复制代码
【完整程序】 -
- import pygame
- import time
- pygame.init()
- pygame.joystick.init()
- # 初始化手柄
- joystick = pygame.joystick.Joystick(0)
- joystick.init()
-
- from pinpong.extension.unihiker import *
- from pinpong.libs.microbit_motor import DFMotor
- from pinpong.board import Board
-
- from pinpong.board import NeoPixel
-
- from pinpong.board import Pin
-
-
- Board().begin()
- pin1 = Pin(Pin.P8)
- np1 = NeoPixel(pin1,4)
-
- p_dfr0548_motor_M1 = DFMotor(1)
- p_dfr0548_motor_M2 = DFMotor(2)
- p_dfr0548_motor_M3 = DFMotor(3)
- p_dfr0548_motor_M4 = DFMotor(4)
-
- pin14 = Pin(Pin.P14,Pin.OUT)
- pin15 = Pin(Pin.P15,Pin.OUT)
- color=0x000000
- bs=0
- time1=0
- time2=0
- def forward(speed):#带速度参数——前进
- p_dfr0548_motor_M1.speed(speed)
- p_dfr0548_motor_M1.run(p_dfr0548_motor_M1.CCW)
- p_dfr0548_motor_M2.speed(speed)
- p_dfr0548_motor_M2.run(p_dfr0548_motor_M2.CCW)
- p_dfr0548_motor_M3.speed(speed)
- p_dfr0548_motor_M3.run(p_dfr0548_motor_M3.CW)
- p_dfr0548_motor_M4.speed(speed)
- p_dfr0548_motor_M4.run(p_dfr0548_motor_M4.CW)
- def back(speed):#带速度参数——后退
- p_dfr0548_motor_M1.speed(speed)
- p_dfr0548_motor_M1.run(p_dfr0548_motor_M1.CW)
- p_dfr0548_motor_M2.speed(speed)
- p_dfr0548_motor_M2.run(p_dfr0548_motor_M2.CW)
- p_dfr0548_motor_M3.speed(speed)
- p_dfr0548_motor_M3.run(p_dfr0548_motor_M3.CCW)
- p_dfr0548_motor_M4.speed(speed)
- p_dfr0548_motor_M4.run(p_dfr0548_motor_M4.CCW)
- def left(speed):#带速度参数——向左
- p_dfr0548_motor_M1.speed(speed)
- p_dfr0548_motor_M1.run(p_dfr0548_motor_M1.CW)
- p_dfr0548_motor_M2.speed(speed)
- p_dfr0548_motor_M2.run(p_dfr0548_motor_M2.CCW)
- p_dfr0548_motor_M3.speed(speed)
- p_dfr0548_motor_M3.run(p_dfr0548_motor_M3.CCW)
- p_dfr0548_motor_M4.speed(speed)
- p_dfr0548_motor_M4.run(p_dfr0548_motor_M4.CW)
- def right(speed):#带速度参数——向右
- p_dfr0548_motor_M1.speed(speed)
- p_dfr0548_motor_M1.run(p_dfr0548_motor_M1.CCW)
- p_dfr0548_motor_M2.speed(speed)
- p_dfr0548_motor_M2.run(p_dfr0548_motor_M2.CW)
- p_dfr0548_motor_M3.speed(speed)
- p_dfr0548_motor_M3.run(p_dfr0548_motor_M3.CW)
- p_dfr0548_motor_M4.speed(speed)
- p_dfr0548_motor_M4.run(p_dfr0548_motor_M4.CCW)
- def stop():#停止
-
- p_dfr0548_motor_M1.stop()
- p_dfr0548_motor_M2.stop()
- p_dfr0548_motor_M3.stop()
- p_dfr0548_motor_M4.stop()
- def Lrotate(speed):#带速度参数——向左原地旋转
- p_dfr0548_motor_M1.speed(speed)
- p_dfr0548_motor_M1.run(p_dfr0548_motor_M1.CCW)
- p_dfr0548_motor_M2.speed(speed)
- p_dfr0548_motor_M2.run(p_dfr0548_motor_M2.CCW)
- p_dfr0548_motor_M3.speed(speed)
- p_dfr0548_motor_M3.run(p_dfr0548_motor_M3.CCW)
- p_dfr0548_motor_M4.speed(speed)
- p_dfr0548_motor_M4.run(p_dfr0548_motor_M4.CCW)
- def Rrotate(speed):#带速度参数——向右原地旋转
- p_dfr0548_motor_M1.speed(speed)
- p_dfr0548_motor_M1.run(p_dfr0548_motor_M1.CW)
- p_dfr0548_motor_M2.speed(speed)
- p_dfr0548_motor_M2.run(p_dfr0548_motor_M2.CW)
- p_dfr0548_motor_M3.speed(speed)
- p_dfr0548_motor_M3.run(p_dfr0548_motor_M3.CW)
- p_dfr0548_motor_M4.speed(speed)
- p_dfr0548_motor_M4.run(p_dfr0548_motor_M4.CW)
- while True:
- if bs==1 and time.time()-time1>0.2:
- time1=time.time()
- np1.rotate(1)
- elif bs==2 and time.time()-time2>0.5:
- time2=time.time()
- np1.rotate(1)
- for event in pygame.event.get():
- if event.type == pygame.JOYBUTTONDOWN:
- if event.button==0:#"A"键
- print("“A”键")
- color=0xFF0000
- elif event.button==1:#"B"键
- print("“B”键")
- color=0x00FF00
- elif event.button==4:#"Y"键
- print("“Y”键")
- color=0x0000FF
- elif event.button==3:#"X"键
- print("“X”键")
- color=0xFF00FF
- elif event.button==6:#"RB"键,右肩键:Right Shoulder Button
- print("“RB”键")
- pin14.write_digital(1)
- pin15.write_digital(1)
- elif event.button==7:#"LB"键,左肩键:Left Shoulder Button
- print("“LB”键")
- pin14.write_digital(0)
- pin15.write_digital(0)
- elif event.button==10:#"View"键
- print("“View”键")
- bs=1
- np1.rainbow(0,3,1,360)
- elif event.button==11:#"Menu"键
- print("“Menu”键")
- bs=2
- np1.rainbow(0,3,1,360)
- elif event.button==15:#“共享”按键
- print("“共享”键")
- bs=0
- np1.clear()
- elif event.button==12:#“xbox”按键
- print("“xbox”键")
- elif event.type == pygame.JOYHATMOTION:#方向键
- if event.hat==0:
- print(str(event.value[0])+":"+str(event.value[1]))
- if event.value[0]==0:
- if event.value[1]==0:#中间位置
- print("“中间位置”方向键")
- stop()
- elif event.value[1]==1:#向上
- print("“向上”方向键")
- forward(200)
- elif event.value[1]==-1:#向下
- print("“向下”方向键")
- back(200)
- elif event.value[0]==-1:#向右
- print("“向右”方向键")
- right(200)
- elif event.value[0]==1:#向左
- print("“向左”方向键")
- left(200)
-
- elif event.type == pygame.JOYAXISMOTION:
- #左摇杆按键
- if event.axis==0:#左右
- if event.value<-0.1:#向左
- left(int(abs(event.value)*255))
- print("“向左”左摇杆按键")
- elif event.value>0.1:#向右
- right(int(event.value*255))
- print("“向右”左摇杆按键")
- else:
- stop()
- print("左右stop左摇杆按键")
- elif event.axis==1:#上下
- if event.value<-0.1:#向上
- forward(int(abs(event.value)*255))
- print("“向上”左摇杆按键")
- elif event.value>0.1:#向下
- back(int(event.value*255))
- print("“向下”左摇杆按键")
- else:
- stop()
- print("上下stop左摇杆按键")
- #右摇杆按键
- if event.axis==2:#左右
- if event.value<-0.1:#向右
- Rrotate(int(abs(event.value)*255))
- print("“向右”右摇杆按键")
- elif event.value>0.1:#向左
- Lrotate(int(event.value*255))
- print("“向左”右摇杆按键")
- else:
- stop()
- print("“停止”右摇杆按键")
- elif event.axis==3:#上下
- if event.value<-0.1:#向上
- print("“向上”右摇杆按键")
- elif event.value>0.1:#向下
- print("“向下”右摇杆按键")
- elif event.axis==5:#左射击键
- if event.value>0:
- print("左射击键")
- np1.range_color(0,3,color)
- elif event.axis==4:#右射击键
- if event.value>0:
- print("右射击键")
- np1.clear()
复制代码 【演示视频】
|
万分感谢