I have always loved retro games, and I wanted to build my own console instead of buying one. So I made PocketNES-32, a pocket-sized, battery-powered handheld that plays NES games from a microSD card.
The brain is an ordinary ESP32 development board, the same kind used in many beginner IoT projects. The case is 3D printed, the buttons are hand-wired, and the power system uses a 2S lithium battery so it can run for hours and be recharged.
What it can do- Plays NES games from a microSD card
- Colour 320x240 display
- Built-in speaker with sound
- Rechargeable 2S 7.4V 3800mAh battery
- Charging through a dedicated 2S charger/protection board
- 8-button control layout: D-pad, A, B, Start, Select
- Start + Select opens a pause menu
- Compact two-piece 3D-printed shell
The NES emulator is Anemoia-ESP32 by Shim06, an open-source project on GitHub. All credit for the emulation goes to the original author. My work was the hardware design, wiring, power system, 3D-printed case, configuration, integration and testing. Please star the original repo if you build this.
Parts usedPART PURPOSE & DESCRIPTION
--------------------------------------------------------------------------------------
ESP32 DevKit Microcontroller core; runs the emulator firmware
ST7789 SPI Display 320x240 LCD screen for video output
MicroSD Card Module SPI storage interface for loading ROM files
2S Li-ion Battery Pack 7.4V 3800mAh main power supply
2S Charger & BMS Board Battery protection and charging controller
Mini Buck Converter Steps 7.4V down to 5.0V for ESP32 Vin
Audio Amplifier & Speaker Mono audio output board and speaker for sound
Push Buttons Tactile controls (D-Pad, A, B, Start, Select)
SPDT Slide Switch Primary power toggle switch
3D-Printed Enclosure Two-part custom housing (top & bottom shell)
Assembly Hardware Wires, solder, Kapton tape, and screwsHow it works
The ESP32 is fast enough to emulate the NES CPU, graphics and sound at around 60 frames per second. To save processing power, the firmware turns off Wi-Fi and Bluetooth, and it uses both ESP32 cores. One core runs the main emulation and the other handles audio and button reading.
The pieces connect like this:
- Display: the ST7789 connects over fast SPI (up to 80 MHz) using MOSI on GPIO 23, clock on GPIO 18, chip select on GPIO 4 and data/command on GPIO 2. The reset pin is not used.
- SD card: it sits on its own separate SPI bus so game loading never conflicts with the display.
- Audio: the ESP32’s built-in DAC outputs sound through I2S to a small amplifier and speaker.
- Buttons: each button connects between a GPIO pin and ground. [add your button pins]
- Power: battery → charger/protection board → switch → buck converter (5V) → ESP32 VIN.
I designed the case in Freecad as two halves. The orange front holds the screen and buttons, and the black back holds the battery, charger board and speaker. I printed it in ABS Plastic.
I left room for the large battery, a ventilation grille over the speaker, and cut-outs for charging and the SD card.
The battery is a 2S Li-ion pack (7.4V, 3800mAh), roughly 28 Wh, which is a lot for a handheld this size. Because the ESP32 needs 5V, I used a small buck converter.
Important: before connecting anything to the ESP32, I connected only the buck converter and adjusted its trimmer with a multimeter until the output read exactly 5.0V. Skipping this can destroy the board.
The 2S charger/protection board sits between the battery and the rest of the circuit. It lets me recharge the pack and protects against over-charge, over-discharge and short circuits.
Step 3: Wiring the buttonsI made the D-pad on small pieces of perfboard, with a soldered contact for each direction. The A, B, Start and Select buttons are standard push buttons. Each one connects from its GPIO pin to ground, and the code uses the ESP32’s internal pull-up resistors, so no external resistors are needed.
The display uses the pins listed above. I set them in the display configuration header (Anemoia-ST7789.h) for the TFT_eSPI library, selecting the ST7789 driver and a 320x240 resolution.
The SD module connects to a separate SPI bus with its own pins, which I set in config.h. If the SD card fails to initialise, the firmware shows an on-screen message telling you to check the card or lower the SD frequency in config.h.
Sound comes from the ESP32’s built-in DAC. I routed it to a small amplifier board and speaker in the back half of the case.
Step 6: Software setup- Install the Arduino IDE and the ESP32 board package.
- Install the TFT_eSPI library.
- Download the Anemoia-ESP32 project from Shim06’s GitHub page.
- Copy my display configuration into the TFT_eSPI setup so it selects the ST7789 driver with the pins above.
- Set my button, SD and audio pins in
config.h. - Follow the repo’s build instructions, including the optimization flags step, which is needed for full speed.
- Upload to the ESP32.
- Copy your NES game files onto a FAT-formatted microSD card and insert it.
After testing everything on the bench, I fitted the parts into the case, secured the battery, and closed the two halv. I tested several games for frame rate, sound and button response.
- Smooth gameplay at around 60 FPS [confirm with your own tests]
- Battery life: 2-5 Hours
- Charging time: 1 Hour
- Total cost: about 1500Rs or Aprroax 15$
- Fitting the large battery into a small case
- Avoiding SPI conflicts between display and SD card
- Getting stable 5V power
- Reducing speaker noise
- Custom PCB to replace the hand wiring
- Battery level indicator on screen
- Volume control and a headphone jack
- Better speaker enclosure
- Slimmer case design
- Always use a battery protection board with 2S lithium packs.
- Set the buck converter to 5V before connecting the ESP32.
- Secure the battery and keep wires away from sharp edges.
- Use only game files you own or legally obtained.
- Firmware: Anemoia-ESP32 by Shim06 (GitHub link)
PocketNES-32 shows that a low-cost ESP32 can power a real handheld console. It taught me a lot about power systems, SPI displays, 3D design and putting several modules together in one device. If you build one, I would love to see it, and please leave questions in the comments.







Comments