ESP32与Xbox手柄的UART通信测试,基于Arduino框架和pyserial+pygame

本文详细描述了如何通过Python与ESP32搭建Xbox手柄与无人机的串口通信链路,包括PC作为中继的测试,以及手柄与ESP32直接通信的实现过程。重点在于手柄数据的处理和ESP32的接收与响应。

1. 说明

这个项目的目标是实现使用手柄来控制ESP32。最近正在进行无人机项目,但是由于没有适合的遥控器来控制四轴,画板子也有些占用时间,所以比较有效的方法就是基于手头有的Xbox手柄来进行一个DIY,在手柄与ESP32之间建立串口通信。此处使用PC作为中继,可能速度有些慢,但是基于目前需求,速度已经足够了。下图说明了无人机项目的通信方式,红框部分为本次涉及部分。

在这里插入图片描述

2. 环境

这里我使用主要Ubuntu 18作为开发环境,Win10下也能正常运行。python版本为3.9,所需库为pygamepyserial

3. 手柄与PC之间的通信测试

手柄与PC之间通过Pygame建立通信,以下提供了两个测试程序,第一个测试程序是一个简单的终端输出,如果手柄工作正常,就会看到六轴的输出。

import pygame
import time

pygame.init()
pygame.joystick.init()
done=False

while (done != True):
    for event in pygame.event.get():  # User did something
        if event.type == pygame.QUIT:  # If user clicked close
            done = True  # Flag that we are done so we exit this loop
    joystick_count = pygame.joystick.get_count()
    for i in range(joystick_count):
        joystick = pygame.joystick.Joystick(i)
        joystick.init()
        axes = joystick.get_numaxes()
        print('================')
        time.sleep(0.1)
        for i in range(axes):
            axis = joystick.get_axis(i)
            print(axis) 

以下测试程序提供了一个简单的GUI来对每个按键进行测试

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# vi:ts=4 sw=4 et
#
# This tool runs fine on both Python 2 and Python 3.
#
# https://github.com/denilsonsa/pygame-joystick-test

from __future__ import division
from __future__ import print_function

import sys
import pygame
from pygame.locals import *


class joystick_handler(object):
    def __init__(self, id):
        self.id = id
        self.joy = pygame.joystick.Joystick(id)
        self.name = self.joy.get_name()
        self.joy.init()
        self.numaxes    = self.joy.get_numaxes()
        self.numballs   = self.joy.get_numballs()
        self.numbuttons = self.joy.get_numbuttons()
        self.numhats    = self.joy.get_numhats()

        self.axis = []
        for i in range(self.numaxes):
            self.axis.append(self.joy.get_axis(i))

        self.ball = []
        for i in range(self.numballs):
            self.ball.append(self.joy.get_ball(i))

        self.button = []
        for i in range(self.numbuttons):
            self.button.append(self.joy.get_button(i))

        self.hat = []
        for i in range(self.numhats):
            self.hat.append(self.joy.get_hat(i))


class input_test(object):
    class program:
        "Program metadata"
        name    = "Pygame Joystick Test"
        version = "0.2"
        author  = "Denilson Figueiredo de Sá Maia"
        nameversion = name + " " + version

    class default:
        "Program constants"
        fontnames = [
            # Bold, Italic, Font name
            (0, 0, "Bitstream Vera Sans Mono"),
            (0, 0, "DejaVu Sans Mono"),
            (0, 0, "Inconsolata"),
            (0, 0, "LucidaTypewriter"),
            (0, 0, "Lucida Typewriter"),
            (0, 0, "Terminus"),
            (0, 0, "Luxi Mono"),
            (1, 0, "Monospace"),
            (1, 0, "Courier New"),
            (1, 0, "Courier"),
        ]
        # TODO: Add a command-line parameter to change the size.
        # TODO: Maybe make this program flexible, let the window height define
        #       the actual font/circle size.
        fontsize     = 20
        circleheight = 10
        resolution   = (640, 480)

    def load_the_fucking_font(self):
        # The only reason for this function is that pygame can find a font
        # but gets an IOError when trying to load it... So I must manually
        # workaround that.

        # self.font = pygame.font.SysFont(self.default.fontnames, self.default.fontsize)
        for bold, italic, f in self.default.fontnames:
            try:
                filename = pygame.font.match_font(f, bold, italic)
                if filename:
                    self.font = pygame.font.Font(filename, self.default.fontsize)
                    # print("Successfully loaded font: %s (%s)" % (f, filename))
                    break
            except IOError as e:
                # print("Could not load font: %s (%s)" % (f, filename))
                pass
        else:
            self.font = pygame.font.Font(None, self.default.fontsize)
            # print("Loaded the default fallback font: %s" % pygame.font.get_default_font())

    def pre_render_circle_image(self):
        size = self.default.circleheight
        self
DIY使用ESP32的手持游戏手柄并通过BLE进行通信 硬件部件: esp32× 1个 ws2812b× 6 游戏杆× 2 角度按钮× 2 按钮× 8 18560电池电池座× 2 三向拨动开关× 1个 TP4056带保护的电池充电电路× 1个 MT3608升压转换器× 1个 软件应用程序在线服务: Arduino IDE 手动工具制造机: 烙铁(通用) 这是一个使用ESP32微控制器制作的DIY手持游戏手柄。您可能之前已经看过这样的游戏控制器。但大多数使用Arduino。或更具体地说,是Arduino pro micro或Leonardo开发板。因为这些板支持HID或通过USB的人机接口设备。但是esp32没有这种功能。那么我们该怎么做呢?嗯,esp32确实具有BLE或低功耗蓝牙,我们可以使用它通过蓝牙进行无线通信。 因此,我们有ESP32模块作为中央控制器,然后有USB C型端口一个3.3v稳压器,可将5v转换为3.3v。然后我们有了编程电路,使用具有自动编程模式的ch340c usb到串行转换器使用双工晶体管的自动复位电路。我们还具有电池充电电路,以及过充电过放电保护功能。然后使用升压转换器ic将其升压至5v。接下来,我们有操纵杆,D-Pad按钮,触发按钮,Neopixel LEDi2c端口。最后是3向开关,可在USB电源电池电源之间切换。 游戏手柄有 2个模拟游戏杆 2个触发按钮 2个D-Pads 6个可寻址RGB LED 一个i2c端口 它可以使用2个18650锂离子电池运行,可以使用USB C型端口对其进行更改。它也可以用来对微控制器进行编程。该设计的灵感来自新的ps5控制器,以使其外观更好。GPIO4使用分压器连接到电池。这样我们就可以测量电池电压了。NeoPixel LED将指示控制器是否连接到设备或电池电压是否低。 该代码基于lemmingDev的BLE Gamepad库。在代码中,我为不同的输入定义了所有GPIO引脚。然后在设置中有一些初始的led动画。板子一旦连接到设备,所有的LED就会变成绿色。并且它将按先前定义的时间间隔检查电池电压。然后我们获得按钮状态,并相应地设置游戏手柄按钮。然后,我们采用模拟输入,并将其映射到合适的值。最后根据我们收到的值设置轴。上载代码后,在智能手机或PC上打开蓝牙菜单,您会看到一个新设备弹出。单击该按钮将其连接,就可以开始游戏了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Stan Fu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值