一、需求分析
需要使用游戏手柄来控制平衡小车,由于游戏手柄和平衡小车不能连接,所以使用电脑作为中介实现两者通信。
需要实现以下功能
- 接收手柄或键盘的键值
- 处理接受的键值
- 通过串口发送指定信息给下位机
- 读取下位机发送的消息并显示
二、环境搭建
Python扩展程序包的二进制文件下载网址为:
https://www.lfd.uci.edu/~gohlke/pythonlibs/
pygame
是一个可以读取手柄和键盘模块,我的python环境为3.7版本所以我下载的的是pygame‑2.0.1‑cp37‑cp37m‑win_amd64.whl
。
pyserial
是一个串口通信模块,我下载的为pyserial‑3.5‑py3‑none‑any.whl
。
下载完成后以管理员的身份打开命令提示符使用 pip 指令安装:
# 跳转到文件下载的目录
C:\WINDOWS\system32> cd C:\Users\Administrator\Downloads
# 使用 pip 安装 文件
C:\Users\Administrator\Downloads> pip install pygame‑2.0.1‑cp37‑cp37m‑win_amd64.whl
pyserial
的啊安装也是一样的。
注意:如果是使用pycharm
编写的程序,会提示找不到模块,因为pycharm
运行环境的扩展库只扫描当前项目下的,因此我是使用VScode 编写。
三、程序实现
定义通信规则:为了方便起见每次只发送一个字符,直行发送 ‘q’,加速发送 ‘s’,减速发送 ‘e’,左转发送 ‘l’,右转发送 ‘r’。
第一次调试可以打开print(message)
查看系统获取的信息
import pygame
import time
import serial
import serial.tools.list_ports
# 串口通信端口号
portx = ''
# 串口通信 波特率
Baud = 115200
# 程序状态
state = True
# 消息
message = dict()
# 串口对象
ser = serial.Serial()
# 检查并选择端口
def set_port():
global portx
print("正在检查可用端口。。")
port_list = list(serial.tools.list_ports.comports())
if len(port_list) == 0:
print("无可用串口!")
return 0
else:
print('序号\t名称')
for i in range(0, len(port_list)):
print(i + 1, '\t', port_list[i])
n = 1
if len(port_list) != 1:
n = int(input('输入端口序号:'))
portx = str(port_list[n - 1].device)
print('已选择端口:', portx)
return 1
def open_port():
global portx
try:
ser.baudrate = Baud
ser.port = portx
ser.open() # 打开串口
except Exception as e:
ser.close() # 关闭端口
print('端口打开失败,尝试更换端口:', e)
return 0
return 1
def send_joystick():
print('连接成功!')
global state
pygame.init()
pygame.joystick.init()
while state:
time.sleep(0.2)
message.clear()
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if event.type == pygame.JOYBUTTONDOWN:
message['JOYBUTTONDOWN'] = event.button
if event.type == pygame.JOYBUTTONUP:
message['JOYBUTTONUP'] = event.button
joystick_count = pygame.joystick.get_count()
for nums in range(joystick_count):
joystick = pygame.joystick.Joystick(nums)
joystick.init()
axes = joystick.get_numaxes()
for i in range(axes):
axis = joystick.get_axis(i)
message['axes' + str(i)] = int(axis * 10)
# print(message) #打印获取的信息
if message == {}: # 未连接
state = False
print('没有找到手柄')
break
if message.get('JOYBUTTONDOWN') == 0: # 直行
ser.write(b'z')
print('直行')
if message.get('JOYBUTTONDOWN') == 1: # 停车
ser.write(b'q')
print('停车')
if message.get('axes5') >= 0: # 加速
ser.write(b's')
print('加速')
if message.get('axes2') >= 0: # 减速
ser.write(b'e')
print('减速')
if message.get('axes0') <= -5: # 左转
ser.write(b'l')
print('左转')
if message.get('axes0') >= 5: # 右转
ser.write(b'r')
print('右转')
if message.get('JOYBUTTONDOWN') == 7: # 退出
state = False
print('退出')
if ser.in_waiting:
print(ser.read(ser.in_waiting).decode("gbk"), end='')
if set_port() == 1:
if open_port() == 1:
send_joystick()
ser.close() # 关闭端口
input("按任意键退出!")