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!