python桥接手柄和串口实现通信

一、需求分析

需要使用游戏手柄来控制平衡小车,由于游戏手柄和平衡小车不能连接,所以使用电脑作为中介实现两者通信。

需要实现以下功能

  1. 接收手柄或键盘的键值
  2. 处理接受的键值
  3. 通过串口发送指定信息给下位机
  4. 读取下位机发送的消息并显示

二、环境搭建

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("按任意键退出!")


上一篇:Python AngryBirds完整代码+讲解


下一篇:pygame中display模块方法详解