Netduino home hardware projects downloads community

Jump to content


The Netduino forums have been replaced by new forums at community.wildernesslabs.co. This site has been preserved for archival purposes only and the ability to make new accounts or posts has been turned off.
Photo

Playstation 2 Controller interface


  • Please log in to reply
6 replies to this topic

#1 eqol

eqol

    New Member

  • Members
  • Pip
  • 3 posts

Posted 14 January 2011 - 04:54 PM

SUP HOMIES!

So i made this cool class with which you can instantly connect your playstation 2 controller to your netduino, assuming you have 4 GPIO-ports available. I use this at the moment to control 3 servos of which 2 i have attached to the analog sticks and 1 to the d-pad. This is still somewhat work in progress, since i have not yet implemented the polling of trigger, d-pad and button pressures.

Anyways this is a very straightforward interface which i think you'll find easy to use.

PS2Controller.cs
using System;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.Netduino;

namespace Robot3DOF
{
    class PS2Controller
    {
        // I/O wires
        private OutputPort attention;
        private OutputPort command;
        private OutputPort clock;
        private InputPort data;

        // Properties, first the analog sticks' positions
        private short leftX = 127;
        private short leftY = 127;
        private short rightX = 127;
        private short rightY = 127;

        // Triggers
        private bool leftTrigger1 = false;
        private bool leftTrigger2 = false;
        private bool rightTrigger1 = false;
        private bool rightTrigger2 = false;

        // D-Pad
        private bool left = false;
        private bool right = false;
        private bool up = false;
        private bool down = false;

        // Buttons
        private bool triangle = false;
        private bool circle = false;
        private bool square = false;
        private bool cross = false;

        // Other
        private bool select = false;
        private bool start = false;
        private bool leftStickPress = false;
        private bool rightStickPress = false;

        public bool LeftStickPress
        {
            get { return leftStickPress; }
            set { leftStickPress = value; }
        }
        public bool RightStickPress
        {
            get { return rightStickPress; }
            set { rightStickPress = value; }
        }
        public bool Select
        {
            get { return select; }
            set { select = value; }
        }
        public bool Start
        {
            get { return start; }
            set { start = value; }
        }
        public bool Triangle
        {
            get { return triangle; }
            set { triangle = value; }
        }
        public bool Circle
        {
            get { return circle; }
            set { circle = value; }
        }
        public bool Cross
        {
            get { return cross; }
            set { cross = value; }
        }
        public bool Square
        {
            get { return square; }
            set { square = value; }
        }
        public short RightX
        {
            get { return rightX; }
            set { rightX = value; }
        }
        public short LeftY
        {
            get { return leftY; }
            set { leftY = value; }
        }
        public short RightY
        {
            get { return rightY; }
            set { rightY = value; }
        }
        public short LeftX
        {
            get { return leftX; }
            set { leftX = value; }
        }
        public bool LeftTrigger1
        {
            get { return leftTrigger1; }
            set { leftTrigger1 = value; }
        }
        public bool LeftTrigger2
        {
            get { return leftTrigger2; }
            set { leftTrigger2 = value; }
        }
        public bool RightTrigger1
        {
            get { return rightTrigger1; }
            set { rightTrigger1 = value; }
        }
        public bool RightTrigger2
        {
            get { return rightTrigger2; }
            set { rightTrigger2 = value; }
        }
        public bool Left
        {
            get { return left; }
            set { left = value; }
        }
        public bool Right
        {
            get { return right; }
            set { right = value; }
        }
        public bool Down
        {
            get { return down; }
            set { down = value; }
        }
        public bool Up
        {
            get { return up; }
            set { up = value; }
        }

        public PS2Controller()
        {
            // Change these pins as necessary
            this.attention = new OutputPort(Pins.GPIO_PIN_D1, false);
            this.command = new OutputPort(Pins.GPIO_PIN_D2, false);
            this.clock = new OutputPort(Pins.GPIO_PIN_D3, false);
            this.data = new InputPort(Pins.GPIO_PIN_D4, false, Port.ResistorMode.PullUp);
        }

        // This brings the controller to "config mode"
        public bool toConfigMode()
        {
            this.command.Write(true);
            this.attention.Write(false);

            gameByte(0x01);
            gameByte(0x43);
            gameByte(0x00);
            gameByte(0x01);
            gameByte(0x00);

            this.command.Write(true);
            this.attention.Write(true);
            return true;
        }

        // This brings the controller back from config mode
        public bool fromConfigMode()
        {
            this.command.Write(true);
            this.clock.Write(true);
            this.attention.Write(false);

            gameByte(0x01);
            gameByte(0x43);
            gameByte(0x00);
            gameByte(0x00);
            gameByte(0x5A);
            gameByte(0x5A);
            gameByte(0x5A);
            gameByte(0x5A);
            gameByte(0x5A);

            this.command.Write(true);
            this.attention.Write(true);
            return true;
        }

        // This sets the controller's operating mode to "analog"
        public bool toAnalogMode()
        {
            this.command.Write(true);
            this.clock.Write(true);
            this.attention.Write(false);

            gameByte(0x01);
            gameByte(0x44);
            gameByte(0x00);

            gameByte(0x01);
            gameByte(0x03);
            gameByte(0x00);

            gameByte(0x00);
            gameByte(0x00);
            gameByte(0x00);

            this.command.Write(true);
            this.attention.Write(true);
            return true;
        }

        // This polls the controller with 3 bytes header and 6 bytes data payload.
        // This could be optimized for different operating modes, for example in the digital mode only 2 bytes of data 
        // are needed. This function takes around 31ms to complete.
        public bool pollController()
        {
            byte[] data = new byte[6];

            this.command.Write(true);
            this.clock.Write(true);
            this.attention.Write(false);

            gameByte(0x01);                                   // bite 0. header.
            gameByte(0x42);                                   // bite 1. header. (should possibly put test on this byte to detect unplugging of controller.)
            gameByte(0x00);                                   // bite 2. header.

            gameByte(0x00, ref data[0]);                         // Buttons1
            gameByte(0x00, ref data[1]);                         // Buttons2
            gameByte(0x00, ref data[2]);                         // Right joy X
            gameByte(0x00, ref data[3]);                         // Right joy Y
            gameByte(0x00, ref data[4]);                         // Left joy X
            gameByte(0x00, ref data[5]);                         // left joy Y

            #region Set properties

            // My goodness, i do this for all ya n000000000000bs
            if ((data[0] & (1 << 0)) == 0) // Select
                this.Select = true;
            else
                this.Select = false;

            if ((data[0] & (1 << 1)) == 0) // L3 (joy push)
                this.LeftStickPress = true;
            else
                this.LeftStickPress = false;

            if ((data[0] & (1 << 2)) == 0) // R3
                this.RightStickPress = true;
            else
                this.RightStickPress = false;

            if ((data[0] & (1 << 3)) == 0) // Start
                this.Start = true;
            else
                this.Start = false;

            if ((data[0] & (1 << 4)) == 0) // Up
                this.Up = true;
            else
                this.Up = false;

            if ((data[0] & (1 << 5)) == 0) // Right
                this.Right = true;
            else
                this.Right = false;

            if ((data[0] & (1 << 6)) == 0) // Down
                this.Down = true;
            else
                this.Down = false;

            if ((data[0] & (1 << 7)) == 0) // Left
                this.Left = true;
            else
                this.Left = false;

            if ((data[1] & (1 << 0)) == 0) // L2
                this.LeftTrigger2 = true;
            else
                this.LeftTrigger2 = false;

            if ((data[1] & (1 << 1)) == 0) // R2
                this.RightTrigger2 = true;
            else
                this.RightTrigger2 = false;

            if ((data[1] & (1 << 2)) == 0) // L1
                this.LeftTrigger1 = true;
            else
                this.LeftTrigger1 = false;

            if ((data[1] & (1 << 3)) == 0) // R1
                this.RightTrigger1 = true;
            else
                this.RightTrigger1 = false;

            if ((data[1] & (1 << 4)) == 0) // Triangle
                this.Triangle = true;
            else
                this.Triangle = false;

            if ((data[1] & (1 << 5)) == 0) // Circle
                this.Circle = true;
            else
                this.Circle = false;

            if ((data[1] & (1 << 6)) == 0) // Cross
                this.Cross = true;
            else
                this.Cross = false;

            if ((data[1] & (1 << 7)) == 0) // Square
                this.Square = true;
            else
                this.Square = false;

            #endregion

            this.command.Write(true);
            this.attention.Write(true);

            this.LeftX = data[4];
            this.RightX = data[2];

            return true;
        }

        // Send a byte, receive a byte
        void gameByte(byte command, ref byte dataByte)
        {
            byte i;

            for (i = 0; i < 8; i++)
            {
                if ((command & (1 << i)) == (1 << i))               // Adjust command wire according to the command
                    this.command.Write(true);
                else
                    this.command.Write(false);

                this.clock.Write(false);                            // CLK to low

                if (this.data.Read() == true)                       // Hacked delay
                    dataByte |= (byte)(1 << i);

                this.clock.Write(true);                             // CLK to high
            }
            this.command.Write(true);
        }
        
        // Send byte only
        void gameByte(byte command)
        {
            byte i;
            byte data = 0x00;

            for (i = 0; i < 8; i++)
            {
                if ((command & (1 << i)) == (1 << i))               // Adjust command wire according to the command
                    this.command.Write(true);
                else
                    this.command.Write(false);

                this.clock.Write(false);                            // CLK to low

                if (this.data.Read() == true)                       // Hacked delay
                    data |= (byte)(1 << i);

                this.clock.Write(true);                             // CLK to high
            }
            this.command.Write(true);
        }
    }
}

A small application example

using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.Netduino;

namespace Robot3DOF
{
    public class Program
    {
        public static void Main()
        {
            Servo servo2 = new Servo(Pins.GPIO_PIN_D6); // Setting up some servos to control
            Servo servo3 = new Servo(Pins.GPIO_PIN_D5);

            PS2Controller controller = new PS2Controller();

            servo2.Degree = 0;
            servo3.Degree = 0;
            float coeff = (180f / 255f); // Needed, since the analog stick gives an 8-bit value

            while (true)
            {
                controller.pollController();

                servo2.Degree = (int)(coeff * (float)controller.LeftX);
                servo3.Degree = (int)(coeff * (float)controller.RightX);
            }
        }
    }
}

So in a nutshell

  • Connect wires
  • Instantiate controller in code
  • Poll controller state
  • Assign properties to cool stuff

Note that the controller operates at 3.3V and should be connected accordingly.

Any ideas to make this interface better will yield an aggressive and sensuel brohug from yours truly.

#2 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 14 January 2011 - 04:57 PM

Very cool. Do you have a wiring diagram (Fritzing perhaps)? We don't have a PS2 in the lab, but we might have to get a controller :) Do you think the PS3 controllers are similar? Chris

#3 eqol

eqol

    New Member

  • Members
  • Pip
  • 3 posts

Posted 14 January 2011 - 05:02 PM

Very cool. Do you have a wiring diagram (Fritzing perhaps)? We don't have a PS2 in the lab, but we might have to get a controller :)

Do you think the PS3 controllers are similar?

Chris


Not sure if they are backwards compatible. If you can use a ps3 controller with ps2, then there should be no problems. Might not even need any modifications. I will also include in this post a few useful links. You don't really need schematics or anything, since this requires absolutely no external components whatsoever. All you need is some wire, a controller and a netduino.

Check this to see what connects where, also the messaging protocol
http://store.curious....com/guides/PS2

Check this for instructions how to do this 'oldskool'
http://sites.google....ntrolleronanavr

#4 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 14 January 2011 - 05:14 PM

Perfect. Thanks, eqol. And welcome to the Netduino community! Chris

#5 CwbhX

CwbhX

    Advanced Member

  • Members
  • PipPipPip
  • 85 posts
  • LocationNYC

Posted 14 January 2011 - 06:20 PM

Not sure about the PS3 controller, it runs off Bluetooth or USB Connections. Could this be used in an application similar to Johny Chung Lee's posting: http://procrastineer...roller-for.html for the controlling part, or is it only at the receiving state? -Cwbh
-Cwbh

#6 eqol

eqol

    New Member

  • Members
  • Pip
  • 3 posts

Posted 14 January 2011 - 06:45 PM

Not sure about the PS3 controller, it runs off Bluetooth or USB Connections. Could this be used in an application similar to Johny Chung Lee's posting: http://procrastineer...roller-for.html for the controlling part, or is it only at the receiving state?

-Cwbh


With this code you can't really emulate a controller to an actual playstation console, I would imagine that to be an entire project on its own. Doable, maybe, but quite challenging as the communication between the controller and the console is full-duplex at a high bitrate.

It would be interesting though to hook up the netduino to a ps2 and see if it can be controlled that way.

#7 Bendage

Bendage

    Advanced Member

  • Members
  • PipPipPip
  • 153 posts
  • LocationIrvine, CA

Posted 06 March 2012 - 06:00 PM

Hello, I'm just curious if anyone has gotten this code to work. Seems to me that the controller works over SPI and this code does not take advantage of the built in SPI interface in the Netduino framework. Looks like he's bit banging but not sure how this code is keeping the 500 khz clock speed the communication requires. I've looked at tons of specs on the controller and a bit of Arduino code. I do not confess to be a hardware guy or a C guy and I can't find any breadboard schematics on layout so not sure if the reason this does not work for me is based on the fact I'm missing a pullup/down resistor somewhere. The wireless PS2 controller is 10 bucks new and much easier to interface with than the PS3 bluetooth controller. This would be a huge addition to my toybox if I can get this to work. (My wife calls this stuff adult Legos) Any suggestions?




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

home    hardware    projects    downloads    community    where to buy    contact Copyright © 2016 Wilderness Labs Inc.  |  Legal   |   CC BY-SA
This webpage is licensed under a Creative Commons Attribution-ShareAlike License.