Glowing Game Controller

by Donut Studio in Circuits > Arduino

143 Views, 0 Favorites, 0 Comments

Glowing Game Controller

Controller_On.jpg
Controller_Effects (2).gif

I've recently got my hands on an Arduino Pro Micro and instantly got the idea to create my own controller! So far I haven't seen any commercial product that features rgb lighting (we don't want to talk about their price ;) ). So I started building myself one and you can too! It's actually not that complex! I'd even say that this is a great first solder project for a weekend! Without further ado, let's get building!

Everything you'll need can be found on my repository (just download or clone it).

Supplies

Controller_Parts.jpg

Depending on your skillset, you may not include the smd components. However, they make this thing look super awesome! Now here is everything you'll need:

  • custom pcb (order them from your preferred pcb company)
  • 1x Arduino Pro Micro
  • 2x PS4 joystick (potentiometer) with caps
  • 8x 12x12mm tactile switch with caps
  • 2x 6x6mm tactile switch bend by 90°
  • 12x 1N5817 (or other similar schottky! diode)
  • 1x 220R resistor
  • 1x 10uF or 100uF

SMD:

  • 11x WS2812b smd leds
  • 11x 100nF 0805

Soldering and the Case

PCB_Front.jpg
Controller_Solder.jpg
Controller_Case.jpg

I won't go into detail on how to solder as there are many great tutorials out there. Check out these two videos to learn about the process:

General solder tutorial: https://youtu.be/oqV2xU1fee8?feature=shared

SMD solder tutorial: https://youtu.be/fYInlAmPnGo?feature=shared

You begin with the smallest components and work your way up. The pcb has different silkscreen labels to indicate what component belongs where. First, you'll start with the smd components and then the through-hole ones. The following list shows you the order:

  • 100nF -> C2-C12
  • WS2812b -> LED1-LED11
  • 220R -> R1
  • 1N5817 -> D1-D12
  • Arduino Pro Micro -> U3
  • 10uF/100uF bend -> C1
  • 12x12mm switch -> B1-B8
  • 6x6mm switch -> B9, B10
  • PS4 joysticks -> U1, U2

Once everything is in place, you might want to clean the pcb with some isopropanol. Now you can add the caps for the joysticks and buttons. Right now there is no proper case for the joystick. I'll design one soon, but in the meantime you can just mount another unused pcb to the bottom with some 10mm spacers, M3x20mm screws and M3 nuts. There are a few mounting holes you can use.

Programming

Controller_Effects (1).gif

With the hardware complete it's time for the software! This Instructable teaches everything about the gamepad library we are using.

  1. Download the gamepad library from here: https://github.com/GAMELASTER/ArduinoGamepad
  2. Open the source code (`src/Controller/Controller.ino`) from my repo in the Arduino IDE
  3. Add the gamepad library to the Arduino IDE via: Sketch/Include Library/Add .ZIP Library...
  4. If not installed, add the 'Adafruit Neopixel' library through the 'Library Manager'
  5. Plug in the controller and upload the sketch:
  • set the corresponding port and board (in my case 'Arduino Leonardo')

With that you have everything set up. Now open up the control panel and go to `Devices and Printers` and perform a right click on your gamepad (In my case it was named `Arduino Leonardo`). Select the menu `Settings of game device` go to its `Properties` and `Test`. By pressing the buttons and rotating the joysticks, you should see these values change. However, there might be some issues with the joysticks, we'll fix that in the next step!


Note: If you have issues with reuploading the code, you can interrupt the input transmission by pressing the outer two buttons (left & right) when plugging in the controller (it will flash red).

Adjusting the Sketch

The values of the potentiometers in the joysticks (there are 4 for each axis: LeftY, LeftX, RightY, RightX) can vary. This can lead to some issues: maybe they transmit input eventhough the joystick is not moved at all. To fix that, I've defined "deadzones". Only if the joystick moves out of this zone, the controller will transmit the input.

Open up the JoystickText.ino file and upload it to the controller.

You basically have to adjust these lines according to your measurements:

const int joystickMiddleMin[4] = { 510, 510, 490, 560 }; // LeftY, LeftX, RightY, RightX
const int joystickMiddleMax[4] = { 540, 540, 520, 585 }; // LeftY, LeftX, RightY, RightX

Open up the serial port or plotter to observe the analog values of the joysticks. Now take a look at the idle values of each axis, starting at left y (then left x, right y, right x). Take note and adjust the values in the array accordingly.

Here is an example:

The readings go from 499 to 501. The deadzone should go from around 490 to 510. You can even give a little more/less space. Just try out what works best for you. The minimum value has to be entered at the `joystickMiddleMin` array (first element for left y, ...) and vice versa.

Copy the two arrays and paste them into the `Controller.ino` sketch and reupload. Now everything should be fine.

All that is left is to try out your controller with some games (some games will not detect the controller). There are a few software solutions out there that might fix this issue, for example the Xbox 360 Controller Emulator (x360ce).

Modifing

Controller.jpg
Game GIF 2.gif

If you verified the functionality, you can start adapting my desing to your needs. I've only added 12 out of the 16 buttons, so you may want to remap some of them, or create your own lighting effects. Refer to the linked instuctable when working with the library, for me it was really helpful!


Custom lighting effects can be easily achieved thanks to object-oriented-programming and the neopixel library! Just add another `YourEffect.h` file to the sketch folder. The content should look something like this:

#ifndef YOUREFFECT_h
#define YOUREFFECT_h

class YourEffect : public ControllerEffect
{
  public:
    YourEffect() : ControllerEffect(100) { } //ControllerEffect(int effect speed, unsigned long effectDuration)
    void onStart()
    {
      // initialize your effect
    }
    void onUpdate(int& i)
    {
      // do some crazy effects, `i` can be used as a counter for each update call
    }

private:
// some private variables here...
};
#endif

In the `Controller.ino` file you just have to include the file and add it to the array of effects:

#include "ControllerEffect.h"
#include "Chaser.h"
#include "Rainbow.h"
#include "RainbowFill.h"
#include "Filler.h"
#include "Randomizer.h"

#include "YourEffect.h" // the new effect file


const int effectsCount = 6; // be sure to increase the count value
ControllerEffect * effects[] = { new YourEffect(), // a new object of your class
new RainbowFill(), new Filler(), new Randomizer(), new Chaser(), new Rainbow() };

The first element of the array will be the first effect to show, then the controller will switch to another random effect after each effect duration. Set the count to 1, to just use the first effect.

Great! Now you got yourself your own controller! Modify the code to your needs and enjoy some games. Stay creative and be sure to share! Keep in mind, that I'll revisit this project to create an improved version with all 16 buttons and maybe a display to select different controller schemes.

Cheers :)


Note: You can also disable the leds when the controller is plugged in, just press the upper two buttons (not triggers).