云天 发表于 2024-2-19 19:54:08

Xbox 行空板麦克纳姆轮车

本帖最后由 云天 于 2024-2-19 20:02 编辑


【项目背景】
最近买了两个Xbox手柄,这个手柄支持Bluetooth(蓝牙4.0),行空板也支持蓝牙功能。本项目中,Xbox手柄通过蓝牙连接行空板,控制麦克纳姆轮车。





【行空板启动蓝牙】
蓝牙(Bluetooth)是一个短距离无线通信标准,用于在手机、计算机和其他电子设备之间通信。行空板自带 Linux 系统,在 Linux 中权威的蓝牙协议栈实现是 BlueZ。其本身自带了很多有用的工具,如bluetoothctl。
1.电脑通过USB线连接上行空板,通过浏览器地址:10.1.2.3,访问行空板,开启终端。
root@unihiker:~#Bluetoothctl#power on扫描蓝牙设备,找到Xbox手柄蓝牙地址(40:8E:2C:22:84:31)
#scan on


【行空板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)+":"+str(event.value))
               if event.value==0:
                     if event.value==0:#中间位置
                         print("“中间位置”方向键")
                        
                     elif event.value==1:#向上
                         print("“向上”方向键")
                        
                     elif event.value==-1:#向下
                         print("“向下”方向键")
                        
               elif event.value==-1:#向右
                  print("“向右”方向键")
                  
               elif event.value==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)+":"+str(event.value))
               if event.value==0:
                     if event.value==0:#中间位置
                         print("“中间位置”方向键")
                         stop()
                     elif event.value==1:#向上
                         print("“向上”方向键")
                         forward(200)
                     elif event.value==-1:#向下
                         print("“向下”方向键")
                         back(200)
               elif event.value==-1:#向右
                  print("“向右”方向键")
                  right(200)
               elif event.value==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)+":"+str(event.value))
               if event.value==0:
                     if event.value==0:#中间位置
                         print("“中间位置”方向键")
                         stop()
                     elif event.value==1:#向上
                         print("“向上”方向键")
                         forward(200)
                     elif event.value==-1:#向下
                         print("“向下”方向键")
                         back(200)
               elif event.value==-1:#向右
                  print("“向右”方向键")
                  right(200)
               elif event.value==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()
【演示视频】
https://www.bilibili.com/video/BV1UZ42117hC/?share_source=copy_web&vd_source=98855d5b99ff76982639c5ca6ff6f528



页: [1]
查看完整版本: Xbox 行空板麦克纳姆轮车