DualShock 3-like M5StampS3 Controller
by SayaNIGHT in Circuits > Microcontrollers
1018 Views, 17 Favorites, 0 Comments
DualShock 3-like M5StampS3 Controller
In this project, I replaced the board of a DualShock 3-like controller with my own M5StampS3 board. I've been looking for the best controller to control my toy robots. While my previous work is a viable option, some projects require additional buttons and joysticks. I think the DualShock 3 (DS3) for PlayStation 3 (PS3) has enough interfaces. The touchpad on the DualShock 4 for PS4 or DualSense for PS5 is unnecessary for my use at the moment.
Fortunately, controllers with the same interface as the DS3 are available at a low cost. However I wanted one that can choose between multiple communication methods such as Bluetooth, Wi-Fi, ESP-NOW, and serial communication. This is why I decided to start this project.
M5StampS3 used in this project is a compact microcontroller (MCU) module featuring the Espressif ESP32-S3 chip, which provides many GPIOs. It also complies with FCC, CE, and Japanese radio standards (important for hobbyists like me!).
The features of the controller in this project are as follows:
- Ability to choose the communication method such as Bluetooth, Wi-Fi, ESP-NOW and serial communication
- No need for case modifications such as cutting the case
- Charging, software upload, and serial communication are possible via USB mini-B
- Power can be turned off
- The vibration motors can rotate in both directions (I was curious about how it feels.)
- Capable of mounting a 9-DoF IMU sensor (optional)
- All pins of M5StampS3 are utilized! (Just wanted to mention thatš)
Here, I'll share not only how to replace the board but also how it was developed, because the PCB data might be specific to the controller I purchased. For example PCB outline, connector position for the FPC, or other component placements might not be compatible with other controllers. I hope this Instructables is useful for your own controller or M5StampS3 projectsš
Supplies
Parts
- DS3 like controller
- MCU: M5StampS3 (M5Stack)
- Power control module: M5Stamp Timer Power (M5Stack)
- 9-DoF IMU: MPU9250 module (retired product) (optional)
- Refer to the BOM file on GitHub for the other electrical parts.
Tools
- Screwdrivers
- Soldering iron
- Solder-wick (for reusing parts)
- Heat gun
- Soldering flux
- tweezers
Software
- KiCad 7.0
- Visual Studio Code with PlatformIO IDE (Arduino)
Service
Controller Teardown
To understand the schematic of the controller, I tried to teardown it.
MCU:
I wasn't able to identify the MCU chip's manufacturer, but it has sufficient GPIOs to individually detect the state of all buttons and joysticks, as well as control two vibration motors and four LEDs. Additionally, there are no dedicated power control ICs; the LiPo battery and the 5V line from the USB mini-B are directly connected to the MCU chip pins.
Motor Driver:
A typical switching circuit is used for controlling the two vibration motors, allowing for single-direction control only.
FPC for Switches:
The FPC is used for wiring switches. A conductive material part (rubber?) on the back of each button shorts out the lines on the FPC when pressed. The circuit is divided into three sections, each with a single common line.
IMU Sensor:
I initially thought the controller had a 6-DoF sensor (accelerometer X, Y, Z and gyroscope X, Y, Z), but I couldn't find any such device.
Wireless Compliance:
I did not find any wireless compliance marks on the controller.
Designing the Schematic Diagram
Attached picture shows the schematic diagram I designed.
The DS3-like controller has 17 push buttons, four variable resistors for two joysticks, four LEDs and two motors. If each device were connected individually to the MCU GPIOs, at least 27 GPIOs would be required. Additionally, I wanted to rotate motors in two directions and add IMU sensor. While the M5StampS3 has a total of 23 GPIOs, this is still insufficient. To address this, I used a button matrix for the button switches and an I/O expander for the LEDs.
Button Switches:
Only the Select, Start, and PS (P3) buttons are individually connected to the M5StampS3. The remaining buttons are configured in a button matrix. The pins labeled COL1-COL3 are configured as output pins and activate each COL lines. The pins labeled ROW1-ROW5 are configured as input pins and read the state of ROW lines. The diodes (D2-D15) are necessary for proper detection and to prevent MCU from breaking when more than two buttons are pressed at the same time.
J1 connector is used to connect the original controller's FPC.
Controlling the LEDs:
To control the four LEDs, an I/O expander (U4: TCA9534A) is employed, which is controlled via I2C. It is also used to control the motor driver's nsleep pin.
It was selected from the components available from JLCPCB's stock.
Motor Driver:
The U3: DRV8833 motor driver includes two H-bridge circuits, enabling it to drive two DC motors in both directions. The R3 and R4 resistors are current sense resistors, set to limit motor current to 833mA . However, the vibration motor draws only approximately 100mA when 5V is applied. For added safety, the current limit can be adjusted to a lower value. Refer to the datasheet to calculate the current.
It was also selected from JLCPCB's available stock.
Power Management:
A M5Stamp Timer Power has many features that are useful for power management. In this project, it is utilized for the DC-DC converter, LiPo battery charger and wake-up/power-off control.
When PS (P3) button is long-pressed, the HOLD pin is set to low output, turning off the controller. Pressing the PS (P3) button again pulls the WAKE pin to GND, waking the controller. The WAKE pin is pulled up to a voltage higher than 3.3V inside the module, so the diode (D1) is used to prevents current flow from the WAKE pin to GPIO40.
USB Data Lines:
To access the USB of M5StampS3 from outside the case, I considered three options. The first was to position the M5StampS3's USB-C port facing the outside of the case. The second option was to extend the USB cable from the M5StampS3 outside the case. However, these options were not feasible due to space constraints, as either the M5StampS3 or the cable interfered with the case. Consequently, I choose to use the (secret?) pads on the back of the M5StampS3 (see the attached photo). Although I'm not sure if these pads are intended for user access, they work effectively. By connecting these D+ and D- pads to the USB mini-B pins, it enabled software uploads and serial communication via the USB mini-B port.
9-DoF IMU (Optional):
Although there are no current plans to use it, an IMU module can be mounted as an option and connects via I2C. I apologize for using a retired product, but the controller functions properly even without the IMU.
Notes on using all pins of M5StampS3:
Some pins are intended for specific purposes. Therefore, I would recommend referring to both the M5StampS3 schematic and the ESP32-S3 datasheet when considering about pin assignment. Here are some key points to note for this project:
ć»GPIO0 and GPIO3: These pins are pulled up to 3.3V on the M5StampS3 module and cannot be used as output or pull-down inputs. Internal pull-up resistors are not required for these pins
ć»GPIO43: This pin has a 510Ī© resistor inserted for TX use. In this project, it was not used for TX, but it was configured as an input pin with an internal pull-up resistor of 45kĪ©. The voltage drop across the 510Ī© resistor is approximately 37mV, which is small enough to detect high and low input voltage levels correctly.
Designing the PCB Layout
I used KiCad 7.0 for designing the PCB, which is a two-layer board as shown in the attached final layout picture. To make sure there is no interference with the case, I printed the board shape using a 3D printer and placed the main components on it for checking, as shown in the attached photos. For component placement, I printed the layout onto paper.
Ordering the PCB
I ordered the PCB and assembly service from JLCPCB. The assembly service was requested only for the components listed in the BOM file. To order the PCB, you need to upload a zip file containing the Gerber and Drill files. For the assembly service, you need to upload the BOM file and the Centroid file. Instructions for generating these files from your EDA tool can be found on the JLCPCB's websites (PCB file preparation, PCBA file preparation). All fabrication files in this project are available on GitHub:
https://github.com/sayatooon/DS3LikeM5StampS3Controller/tree/main/pcb
The attached pictures show detail setups for ordering the PCB and assembly. Note that the PCB thickness is 1mm.
Soldering Parts on the PCB
If you have solder paste and hot plate (or an oven for reflow soldering), this step might be easier. However, since I didnāt have these tools, I used solder wire, a soldering iron, a heat gun and soldering flux. Hereās how I approached it, though other methods might also work well.
- Prepare Reused Parts: Before soldering, remove some components from the original board for reuse. The reused parts are shown in the attached picture. A heat gun can make this process easier.
- Soldering the M5StampS3:
- Apply soldering flux to both the pads on the M5StampS3 and the pads for it on the PCB.
- Using a soldering iron, apply solder only to the USB data pads and two additional pads for positioning, as shown in the attached picture.
- Place the M5StampS3 on the PCB and heat it with a heat gun until the solder melts. You can check if the solder has melted by looking the USB data pads. Align the M5StampS3 before the solder hardens using tweezers.
- After it is fixed, use a soldering iron to solder all the M5StampS3 pads.
- Soldering Other Components:
- Solder the Stamp Timer Power and the reset switch with a soldering iron.
- Solder the FPC connector with a soldering iron.
- Solder the USB mini-B and the battery connector with a soldering iron.
- (Optional) Solder IMU module with a soldering iron.
- Solder the joysticks and the motor wires with a soldering iron. Motor wires can be soldered during the 5th process in the Step 6: Assembly section.
- Attach the LiPo Battery: Use double-sided tape to attach the LiPo battery to the PCB and connect the battery connector.
Assembling the Controller
Basically, reassemble the case in the reverse order of how you opened it.
- Insert the FPC to the FPC connector.
- Set the plastic plate behind the FPC.
- Install the two rubbers for the R1, R2, L1 and L2 buttons.
- Place buttons and button rubbers into the front case.
- Install the electrical parts to the front case. Make sure the rubbers for the L1 and R1 buttons are correctly positioned under the L1 button.
- Attach the R2 and L2 buttons to the back cover with the springs.
- Close the back cover onto the front case. Before completely closing, use tweezers to hook the springs for R2 and L2 onto the plastic plate behind the FPC.
- Finally, fastened the cover with the five screws.
Uploading the Code
You can upload your own code to the controller. As an example, I'll share my code on GitHub. The code was written using PlatformIO.
The communication method used in the code is ESP-NOW. Please make sure to update the variable 'deviceMacAddress[]' in 'main.cpp' to the MAC address of the device you wish to communicate with.
The libraries used are as follows:
Test and Use!
Test and use your controller as you like!
As an example, Iāll explain the controller test demonstrated in the video attached in the introduction. The configuration for the test is shown in the attached picture. In this setup, the M5StampS3 in the controller communicates with another M5StampS3 via ESP-NOW. The second M5StampS3 connects to a laptop via USB cable, and they communicate using serial communication. The GUI for this setup was created Python Matplotlib.
I'm not sure that it will works on your environment, but I will share the codes on GitHub. I used PlatformIO for the M5StampS3 and Python 3.12.1 for the GUI on the laptop.
Please make sure to update the variable 'controllerMacAddress[]' in 'main.cpp' to the MAC address of your controller's M5StampS3.
- The code for the M5StampS3 communicating with the controller is available here.
- The used library: PacketSerial by Christopher Baker
- The GUI code is available here.