Command Center: Minecraft Controller – Piper

Command Center: Minecraft Controller

Minecraft Controller

DIY GAME CONTROLLER

30 MINUTES

In this project you will learn how to wire mini buttons on the Breadboard Puck to the Microcontroller, in order to customize the Command Center as a game controller. Once the circuit is complete, you then upload new code to the Microcontroller. The code changes the device from a USB controlled mouse to the gamepad of a computer’s keyboard. Wiring the circuit and uploading the code will take approximately 30 minutes to complete. When all steps are completed, have fun playing Raspberry Pi’s Edition of Minecraft on your Piper Computer Kit.

STEP ONE:

Collect all your materials.

  • Screwdriver
  • Piper Command Center
  • Piper Computer Kit
  • From your storage chest in the Piper Computer Kit, grab the following:
  • x4 Wires - Blue, Black, Green, and Yellow
  • x3 Mini Buttons

STEP TWO:

        

  • Remove Command Center’s Lid (Part 7 or 8).
  • Remove the black plastic cover from the 6 pins resting next to the red reset button.

STEP THREE:

  • Switch 11/32” standoffs (x2) for the Lid with ⅝” standoffs (x2) used to attach the Breadboard Puck.
  • Then, screw the Breadboard puck onto the 11/32” standoffs.

STEP FOUR:

  • Attach Mini Buttons (x3) onto the Breadboard Puck as shown below.
  • Wire the Blue, Black, Green, and Yellow wires as shown below.

STEP FIVE:

  • Insert the controller’s USB braided cable into a USB port on your desktop computer
  • Download the Arduino IDE
  • Confirm you have downloaded the Arduino IDE to your desktop computer. If not, follow these instructions.
  • Open Arduino’s IDE and launch a new sketch.

STEP SIX:

  • Copy and paste the code listed below into the Arduino IDE Sketch.
  • Once pasted, upload the code.
  • Having issues? Check your port and board connection under the tools menu.

// Arduino libraries to control the mouse and keyboard

#include <Keyboard.h>

#include <Mouse.h>

/////////////////////////////////////////////////////////////////////////

// Pin mappings to Arduino Micro according to the assembly instructions

enum ArduinoPinMap {

  // Joystick Movement

  VerticalAxisPin = A0,

  HorizontalAxisPin = A1,

  // Click & Button Pins

  LeftButtonPin = 8,

  RightButtonPin = 9,

  UpButtonPin = 6,

  DownButtonPin = 7,

  JoystickPressPin = 13,

  // Extra Buttons

  TopButtonPin = MOSI,

  MiddleButtonPin = MISO,

  BottomButtonPin = SCK,

};

/////////////////////////////////////////////////////////////////////////

enum InputAction {

  LeftButton = 0,

  RightButton,

  UpButton,

  DownButton,

 

  JoystickLeft,

  JoystickRight,

  JoystickUp,

  JoystickDown,

  JoystickPress,

 

  TopButton,

  MiddleButton,

};

#define NOT_MAPPED 0

// Eight elements to correspond to the button. Each map to a keyboard action

// Change these to map the buttons in Keyboard Mode

const int InputMap[11] = {

    'a',              // LeftButton

    'd',              // RightButton

    'w',              // UpButton

    's',              // DownButton

    NOT_MAPPED,       // JoystickLeft

    NOT_MAPPED,       // JoystickRight

    NOT_MAPPED,       // JoystickUp

    NOT_MAPPED,       // JoystickDown

    ' ',              // JoystickPress

    MOUSE_RIGHT,      // TopButton

    MOUSE_LEFT,       // MiddleButton

};

const int InputMapModified[11] = {

    'a',              // LeftButton

    'd',              // RightButton

    KEY_ESC,          // UpButton

    's',              // DownButton

    NOT_MAPPED,       // JoystickLeft

    NOT_MAPPED,       // JoystickRight

    MOUSE_MIDDLE,     // JoystickUp

    'e',              // JoystickDown

    KEY_LEFT_SHIFT,   // JoystickPress

    MOUSE_RIGHT,      // TopButton

    MOUSE_LEFT,       // MiddleButton

};

// State of the modifier buttons

int isModifierPressed = 0;

int wasModifierPressed = 0;

// State of any buttons that can be modified

int isMouseMiddlePressed = 0;

int isEkeyPressed = 0;

int isEscPressed = 0;

int isShiftPressed = 0;

int isSpacePressed = 0;

int isWkeyPressed = 0;

// This is set on the mode toggle

const int *currentModeMap = InputMap;

const int AxisMaxInput = 1023;

const int AxisMaxOutput = 16;

const uint8_t MOUSE_MOVE_DELAY = 8;

// Global variable for the last time the mouse (aka joystick) was moved

unsigned long lastMouseMovement = 0;

int MappedThreshold = 3;               // resting threshold, mapped

int MappedCenter = AxisMaxOutput / 2;  // resting position value, mapped

void getControllerMap() {

  if (isModifierPressed) {

    currentModeMap = InputMap;

  } else {

    currentModeMap = InputMapModified;

  }

}

// Reads an axis (data pin) and scales the analog input range to a range

// from 0 to <range>

int readAxis(int axis) {

  // Read the analog input

  int reading = analogRead(axis);

  // Map the reading from the analog input range to the output range:

  int mappedReading = map(reading, 0, AxisMaxInput, 0, AxisMaxOutput);

  // If the output reading is outside from the rest position threshold, use it:

  int distanceFromCenter = mappedReading - MappedCenter;

  if (abs(distanceFromCenter) < MappedThreshold) {

    distanceFromCenter = 0;

  }

  // Return the distance for this axis:

  return distanceFromCenter;

}

// Converts a button from the InputAction enum into a mouse or keyboard press

void buttonPress(InputAction button, bool isPress) {

  getControllerMap();

 

  int action = currentModeMap[button];

  if ((action == MOUSE_RIGHT) || (action == MOUSE_LEFT) || (action == MOUSE_MIDDLE)) {

    if (isPress) {

      Mouse.press(action);

      if (action == MOUSE_MIDDLE) {

        isMouseMiddlePressed = 1;

      }

    } else {

      Mouse.release(action);

    }

  } else {

    if (isPress) {

      Keyboard.press(action);

      // If any of the modified keys have been pressed, save them so they can be

      // released if the modifier button is let go

      switch (action) {

        case 'e':

          isEkeyPressed = 1;

          break;

        case KEY_LEFT_SHIFT:

          isShiftPressed = 1;

          break;

        case ' ':

          isSpacePressed = 1;

          break;

        case KEY_ESC:

          isEscPressed = 1;

          break;

        case 'w':

          isWkeyPressed = 1;

          break;

      }

    } else {

      Keyboard.release(action);

    }

  }

}

void handleJoystick() {

  int horizontalInput = readAxis(HorizontalAxisPin);

  int verticalInput = readAxis(VerticalAxisPin);

 

  if (isModifierPressed) {

    // Take the horizontal and vertical input and move the mouse

    Mouse.move(horizontalInput, verticalInput, 0);

  } else {

    Mouse.move(0, 0, horizontalInput / 2);

    buttonPress(JoystickUp, verticalInput < -MappedThreshold);

    buttonPress(JoystickDown, verticalInput > MappedThreshold);

  }

}

void handleButtons() {

  // Get the state of the modifier Button (BottomButtonPin)

  // and store the previous state of the modifier button (to see if it changed)

  pinMode(MiddleButtonPin, OUTPUT);

  digitalWrite(MiddleButtonPin, LOW);

  delayMicroseconds(25);

  wasModifierPressed = isModifierPressed;

  isModifierPressed = digitalRead(BottomButtonPin);

  pinMode(MiddleButtonPin, INPUT_PULLUP);

  // Get the states of the rest of the buttons

  buttonPress(RightButton, digitalRead(RightButtonPin) == LOW);

  buttonPress(LeftButton, digitalRead(LeftButtonPin) == LOW);

  buttonPress(UpButton, digitalRead(UpButtonPin) == LOW);

  buttonPress(DownButton, digitalRead(DownButtonPin) == LOW);

  buttonPress(JoystickPress, digitalRead(JoystickPressPin) == LOW);

  buttonPress(TopButton, digitalRead(TopButtonPin) == LOW);

  buttonPress(MiddleButton, digitalRead(MiddleButtonPin) == LOW);

  // If the modifier button changed, then release any buttons that have been modified

  // to prevent them from getting "stuck"

  if (isModifierPressed != wasModifierPressed) {

    if (isMouseMiddlePressed) {

        Mouse.release(MOUSE_MIDDLE);

    }

    if (isEkeyPressed) {

        Keyboard.release('e');

    }

    if (isShiftPressed) {

        Keyboard.release(KEY_LEFT_SHIFT);

    }

    if (isSpacePressed) {

        Keyboard.release(' ');

    }

    if (isEscPressed) {

        Keyboard.release(KEY_ESC);

    }

    if (isWkeyPressed) {

        Keyboard.release('w');

    }

  }

}

// Called from the loop to handle input from the pins. We break up the

// handling into joystick and buttons

void processInput() {

  unsigned long currentTime = millis();

  int delayTime = MOUSE_MOVE_DELAY;

  // The scroll wheel moves really fast, so increase the mouse movement delay

  // if the modifier button is pressed

  if (!isModifierPressed) {

    delayTime = delayTime * 12;

  }

  if (currentTime - lastMouseMovement >= delayTime) {

    // Space out joystick actions. This is especially for the joystick

    // button, which sends multiple events for one press

    handleJoystick();

    lastMouseMovement = currentTime;

  }

  handleButtons();

}

// Arduino setup, called in the beginning on the startup

void setup() {

  // Setup input for all the pins

  pinMode(HorizontalAxisPin, INPUT);

  pinMode(VerticalAxisPin, INPUT);

  pinMode(LeftButtonPin, INPUT_PULLUP);

  pinMode(RightButtonPin, INPUT_PULLUP);

  pinMode(UpButtonPin, INPUT_PULLUP);

  pinMode(DownButtonPin, INPUT_PULLUP);

  pinMode(JoystickPressPin, INPUT_PULLUP);

  pinMode(TopButtonPin, INPUT_PULLUP);

  pinMode(MiddleButtonPin, INPUT_PULLUP);

  pinMode(BottomButtonPin, INPUT_PULLUP);

  Mouse.begin();

  Keyboard.begin();

}

// Main Arduino Program Loop

void loop() {

  // Loop forever, checking the pins for input

  processInput();

}

STEP SEVEN:

Ready your control.

  • Check your key mapping. If your controller’s joystick or buttons are not working properly,

check your code or wiring.

KEY MAPPING: 

MINECRAFT PI EDITION

KEY MAPPING:

PIPER COMMAND CENTER MINECRAFT CONTROLLER

STEP EIGHT:

What does each button do?

  • Press the joystick down to make your player jump.  
  • The Mod Button changes how some of the buttons work
  • Hold down the Mod button, press down the joystick, and your player will crouch instead.
  • Additional uses for the Mod button are:
  • Access inventory
  • Select a block in the bottom bar
  • Exit to the menu

STEP NINE:

Check your work.

  • When everything is working correctly, screw a Lid back onto the Piper Command Center and PLAY!
  • Do not like how a button functions? Want to hack or customize? Modify the buttons’ function in the code. Have fun and explore!