ESP32+PS2 无线手柄转接板+microPython

ESP32+PS2 无线手柄转接板+microPython_第1张图片

from machine import Pin
import time

di  = Pin(26,Pin.IN,Pin.PULL_UP)   # dat/di   ESP32接26脚 或  接ESP8266的D5脚=14
do  = Pin(27,Pin.OUT)              # cmd/do   ESP32接27脚 或  接ESP8266的D6脚=12
cs  = Pin(14,Pin.OUT)              # cs       ESP32接14脚 或  接ESP8266的D7脚=13
clk = Pin(12,Pin.OUT)              # clk      ESP32接12脚 或  接ESP8266的D8脚=15

def DO_H():
  do.value(1)
def DO_L():
  do.value(0)
def CS_H ():
  cs.value(1)
def CS_L():
  cs.value(0)
def CLK_H ():
  clk.value(1)
def CLK_L():
  clk.value(0)
#These are our button constants
PSB_SELECT     = 1
PSB_L3         = 2
PSB_R3         = 3
PSB_START      = 4
PSB_PAD_UP     = 5
PSB_PAD_RIGHT  = 6
PSB_PAD_DOWN   = 7
PSB_PAD_LEFT   = 8
PSB_L2         = 9
PSB_R2         = 10
PSB_L1         = 11
PSB_R1         = 12
PSB_GREEN      = 13
PSB_RED        = 14
PSB_BLUE       = 15
PSB_PINK       = 16
PSB_TRIANGLE   = 13
PSB_CIRCLE     = 14
PSB_CROSS      = 15
PSB_SQUARE     = 16
PSS_RX = 5
PSS_RY = 6
PSS_LX = 7
PSS_LY = 8
mask=[
    PSB_SELECT,
    PSB_L3,
    PSB_R3 ,
    PSB_START,
    PSB_PAD_UP,
    PSB_PAD_RIGHT,
    PSB_PAD_DOWN,
    PSB_PAD_LEFT,
    PSB_L2,
    PSB_R2,
    PSB_L1,
    PSB_R1 ,
    PSB_GREEN,
    PSB_RED,
    PSB_BLUE,
    PSB_PINK ]
comd=[0x01,0x42]
data=[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00]

def ps2_init():
  CLK_H()
  DO_H()
  time.sleep_ms(100)

def ps2_cmd(cmd):
  global data
  data[1]=0
  for ref in (1,2,4,8,16,32,64,128):
    if ( ref & cmd):
      DO_H()
    else:
      DO_L()
    CLK_H ()
    time.sleep_us(50)
    CLK_L()
    time.sleep_us(50)
    CLK_H ()
    if(di.value()==1):
      data[1]=ref|data[1]

def ps2_red():
  global data
  global comd
  CS_L()
  ps2_cmd(comd[0])
  ps2_cmd(comd[1])
  CS_H()
  if(data[1]==57):
    return 0 #red light
  else:
    return 1 #not red

def ps2_read():
  global data
  global comd
  byte=0
  ref=0x01
  CS_L()
  ps2_cmd(comd[0])
  ps2_cmd(comd[1])
  for byte in (2,3,4,5,6,7,8):
    for ref in (1,2,4,8,16,32,64,128):
     CLK_H ()
     CLK_L()
     time.sleep_us(50)
     CLK_H ()
     if(di.value()==1):
      data[byte]= ref|data[byte]
    time.sleep_us(50)
  CS_H ()

def ps2_clear():#ok
  global data
  for i in range(0,9,1):
    data[i]=0

def ps2_andata(button):
  global data
  return data[button]

def ps2_key():
  global data
  global mask
  ps2_clear()
  ps2_read()
  handkey=(data[4]<<8)|data[3]
  for index in (0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15):
    if (( handkey&(1<<(mask[index]-1)))==0):
      return index+2
  return 0
  

print("等待按键中......")
while True:
  if ps2_key():
    print(ps2_key())
  time.sleep(0.1) 

另一个版本的PS2代码,支持多按键同时检测,比较好用:

感谢作者,原代码地址如下:https://github.com/shallwe/micropython_ps2
以下为我修改后的代码,方便了调用。 可以保存为ps2.py,以备调用

import time
from machine import Pin

class PS2Controller:
    # These are our button constants
    SELECT = 1
    L3 = 2
    R3 = 3
    START = 4
    UP = 5
    RIGHT = 6
    DOWN = 7
    LEFT = 8
    L2 = 9
    R2 = 10
    L1 = 11
    R1 = 12
    TRIANGLE = 13
    CIRCLE = 14
    CROSS = 15
    SQUARE = 16
    KEYS = dict([
                  (SELECT, "SELECT"),        (L3, "L3"),        (R3, "R3"),        (START, "START"),
                  (UP, "UP"),        (RIGHT, "RIGHT"),        (DOWN, "DOWN"),        (LEFT, "LEFT"),
                  (L2, "L2"),        (R2, "R2"),        (L1, "L1"),        (R1, "R1"),
                  (TRIANGLE, "TRIANGLE"),        (CIRCLE, "CIRCLE"),        (CROSS, "CROSS"),        (SQUARE, "SQUARE")  ])

    CTRL_CLK = 10
    CTRL_BYTE_DELAY = 16

    CMD_SHORT_POLL   = [0x01, 0x42, 0x00, 0x00, 0x00]
    CMD_ENTER_CONFIG = [0x01, 0x43, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00]
    CMD_SET_MODE     = [0X01, 0x44, 0x00,
                        0x01,  # 00 normal; 01 red or analog
                        0x03,  # 03 lock; ee no lock
                        0x00, 0x00, 0x00, 0x00]
    CMD_SET_BYTES_LARGE = [0x01, 0x4F, 0x00, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00]
    CMD_EXIT_CONFIG     = [0x01, 0x43, 0x00, 0x00, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A]
    CMD_ENABLE_RUMBLE   = [0x01, 0x4D, 0x00, 0x00, 0x01]
    CMD_TYPE_READ       = [0x01, 0x45, 0x00, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A]
    CMD_READ_DATA       = [0X01, 0X42, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00]

    MAX_READ_DELAY = 1500

    VALID_MODES = [0X41, 0X73]

    def __init__(self, di_pin_no=26, do_pin_no=27, cs_pin_no=14, clk_pin_no=12):  # DI=DAT、DO=CMD 可以在此处将针脚调整为你自己对应的针脚
        self.di_pin_no = di_pin_no
        self.do_pin_no = do_pin_no
        self.cs_pin_no = cs_pin_no
        self.clk_pin_no = clk_pin_no
        self.di  = Pin(self.di_pin_no, Pin.IN)  # DI = DAT
        self.do  = Pin(self.do_pin_no, Pin.OUT) # DO = CMD
        self.cs  = Pin(self.cs_pin_no, Pin.OUT)
        self.clk = Pin(self.clk_pin_no, Pin.OUT)
        self.buff_out = [0x01, 0x42]
        self.buff_in = [0] * 9
        self.pressed_keys = []
        self.read_delay = 1
        self.last_read_ms = 0
        self.lx = 0
        self.ly = 0
        self.rx = 0
        self.ry = 0

    @property
    def red_mode(self):  # analog mode
        return self.buff_in[1] & 0xf0 == 0x70

    def do_h(self):
        self.do.value(1)

    def do_l(self):
        self.do.value(0)

    def cs_h(self):
        self.cs.value(1)

    def cs_l(self):
        self.cs.value(0)

    def clk_h(self):
        self.clk.value(1)

    def clk_l(self):
        self.clk.value(0)


    # noinspection PyUnresolvedReferences
    def delay_byte(self):
        time.sleep_us(self.read_delay)

    # noinspection PyUnresolvedReferences
    def delay_clk(self):
        time.sleep_us(self.CTRL_CLK)

    # noinspection PyUnresolvedReferences
    def delay_read(self):
        time.sleep_us(self.CTRL_BYTE_DELAY)
        # time.sleep_ms(self.read_delay)

    def cmd(self, cmd):
        ret = 0
        for i in range(8):
            if cmd & 1 << i:
                self.do_h()
            else:
                self.do_l()
            self.clk_l()
            self.delay_clk()
            if self.di.value():
                ret |= 1 << i
            self.clk_h()
        self.do_h()
        self.delay_byte()
        return ret

    """
    :param 
    pure True means not delay
    """

    def cmd_group(self, cmds):
        self.cs_l()
        self.delay_byte()
        for cmd in cmds:
            self.cmd(cmd)
        self.cs_h()
        self.delay_read()

    def init(self):
        self.di  = Pin(self.di_pin_no, Pin.IN)
        self.do  = Pin(self.do_pin_no, Pin.OUT)
        self.cs  = Pin(self.cs_pin_no, Pin.OUT)
        self.clk = Pin(self.clk_pin_no, Pin.OUT)
        self.do_h()
        self.clk_h()

        self.read_once()
        self.read_once()
        #
        if self.buff_in[1] not in [0x41, 0x73]:
            print("control type not ok, expect 41 73 79, bug get ", "{:02x}".format(self.buff_in[1]))
            return 1

        self.read_delay = 1

        for i in range(10):
            # self.cmd_group(self.CMD_SHORT_POLL)
            # self.cmd_group(self.CMD_SHORT_POLL)
            # self.cmd_group(self.CMD_SHORT_POLL)
            self.cmd_group(self.CMD_ENTER_CONFIG)
            self.delay_byte()

            self.do_h()
            self.clk_h()
            self.cs_l()

            self.delay_byte()
            #
            temp = [0] * len(self.CMD_TYPE_READ)
            for j in range(9):
                for cmd in self.CMD_TYPE_READ:
                    temp[j] = self.cmd(cmd)
            self.cs_h()

            self.cmd_group(self.CMD_SET_MODE)
            # self.cmd_group(self.CMD_ENABLE_RUMBLE)
            self.cmd_group(self.CMD_EXIT_CONFIG)
            self.read_once()
            if self.buff_in[1] in self.VALID_MODES:
                print("read_delay configed,", self.read_delay)
                break
            else:
                self.read_delay += 1
                print("read_delay++,", self.read_delay)

    def reconfig(self):
        print("reconfig")
        self.cmd_group(self.CMD_ENTER_CONFIG)
        self.cmd_group(self.CMD_SET_MODE)
        self.cmd_group(self.CMD_EXIT_CONFIG)

    def p(self, debug=True):
        if debug:
            for d in self.buff_in:
                print("{:08b}".format(d))

        key_raw = (self.buff_in[4] << 8) | self.buff_in[3]
        for i in range(1, 17):
            if not key_raw & 1 << i - 1:
                self.pressed_keys.append(i)

        if self.red_mode:
            self.rx = self.buff_in[5] - 128
            self.ry = self.buff_in[6] - 128
            self.lx = self.buff_in[7] - 128
            self.ly = self.buff_in[8] - 128
        if self.pressed_keys:
            out = "keys:" + ','.join(self.KEYS[k] for k in self.pressed_keys) + "; "
        else:
            out = ""
        # for key in self.pressed_keys:
        #     print(key, self.KEYS[key])
        if self.red_mode and (out or any(x != 0 for x in [self.rx, self.ry, self.lx, self.ly])):
            out += "pos: (lx,ly):{},{};  (rx,ry): {},{}".format(self.lx, self.ly, self.rx, self.ry)

        if out:
            print(out)

    def read_once(self, debug=False):
        now = time.ticks_ms()
        delay = now - self.last_read_ms
        if delay > self.MAX_READ_DELAY:
            print(now, self.last_read_ms, delay)
            self.reconfig()
        elif delay < self.read_delay:
            # noinspection PyUnresolvedReferences
            time.sleep_ms(self.read_delay - delay)

        self.buff_in = [0] * 9
        self.pressed_keys.clear()

        for j in range(5):
            # for i in range(1):
            self.do_h()
            self.clk_h()
            self.cs_l()
            self.delay_byte()

            for i, c in enumerate(self.CMD_READ_DATA):
                self.buff_in[i] = self.cmd(c)

            self.cs_h()

            if self.buff_in[1] in self.VALID_MODES:
                break
            else:
                print("mode: {:08b}, retry_J: {}".format(self.buff_in[1], j))
                self.reconfig()
                self.delay_read()
        if self.buff_in[1] not in self.VALID_MODES and self.read_delay < 10:
            self.read_delay += 1

        self.last_read_ms = time.ticks_ms()
        #self.p(debug)

        #以下为自己添加 ,原P()内的代码
        key_raw = (self.buff_in[4] << 8) | self.buff_in[3]
        for i in range(1, 17):
            if not key_raw & 1 << i - 1:
                self.pressed_keys.append(i)

        if self.red_mode:
            self.rx = self.buff_in[5] - 128
            self.ry = self.buff_in[6] - 128
            self.lx = self.buff_in[7] - 128
            self.ly = self.buff_in[8] - 128
        if self.pressed_keys:      #注意下面这几行的:和,千万不要修改,后面要他们做标记分割使用!
            out = "keys:" + ','.join(self.KEYS[k] for k in self.pressed_keys) + ": "
        else:
            out = "keys:无:"
        # for key in self.pressed_keys:
        #     print(key, self.KEYS[key])
        if self.red_mode and (out or any(x != 0 for x in [self.rx, self.ry, self.lx, self.ly])):
            out += "pos(lx,ly):{},{}:  pos(rx,ry):{},{}:".format(self.lx, self.ly, self.rx, self.ry)
        if out:
            print(out)
            
        #return self.buff_in
        return out

'''
# 调用方法,将以下几行代码新建一个文件如:ps2_test.py
from ps2 import PS2Controller
import time
ps2ctl = PS2Controller(di_pin_no=26, do_pin_no=27, cs_pin_no=14, clk_pin_no=12)
ps2ctl.init()
while True:
    key_car= ps2ctl.read_once()   # 收到的字符格式为 keys:UP,RIGHT: pos(lx,ly):0,-1: pos(rx,ry): 0,-1:
    #print("检测到按键:",key_car)    
    key_list= key_car.split(':')  # 用:来将字符串进行分割,写入数组key_list中  key_list[1]输入的按键、key_list[3]左摇杆坐标、key_list[5]右摇杆坐标
    if key_list[1]=="UP": 
      print(key_car," 前进")
      
    if key_list[1]=="UP,LEFT": 
      print(key_car," 左上方")
    time.sleep(0.2)
''' 



原文链接:https://www.jianshu.com/p/30723e5624ae

你可能感兴趣的:(单片机,1024程序员节)