PIPBOY AR Mark 6000

by Arnov Sharma in Circuits > Computers

3336 Views, 30 Favorites, 0 Comments

PIPBOY AR Mark 6000

thumb1.JPG
PIP-BOY IS FINALLY READY! ☢️
70.gif
72.gif
76.gif
77.gif
78.gif
79.gif
IMG_2070.JPG
IMG_2075.JPG
IMG_2076.JPG
IMG_2077.JPG

Greetings everyone, and welcome back!

Meet the PipBoy AR Mark 6000, my own version of the PipBoy designed and built completely from scratch.

If you’re a gamer, chances are you’ve heard of Fallout. Fallout is a post-apocalyptic RPG series set in a dystopian future where civilization has been devastated by nuclear war. The games take place across a retro-futuristic wasteland filled with ruined cities, mutated creatures, factions, and remnants of the old world. While each game follows a different protagonist and takes place in a different part of the Fallout universe, the core setting and its unique retro-futuristic aesthetic remain largely the same.

One of the most iconic pieces of technology in the Fallout universe is the PipBoy. It’s essentially a wearable computer strapped to the player's arm, kind of like an extremely oversized, post-apocalyptic Apple Watch.

Throughout the games, the Pip-Boy is used for almost everything: keeping track of inventory, checking character stats, managing perks, viewing maps and quests, and even listening to radio stations.

As a Fallout fan, I’ve always wanted to build some of the technology from the games. I previously made a Fallout-inspired terminal, so naturally, the next project I wanted to take on was a Pip-Boy.

However, I didn’t want to simply recreate one of the existing Pip-Boy models from the games. Instead, I wanted to design my own version while still following the design language and aesthetic that makes the Pip-Boy instantly recognizable.

I also wanted this to be more than just a wearable prop. The goal was to make a fully functional Pip-Boy, with a user interface that stays as close to the games as possible while adding some of my own features and ideas.

This article covers the complete build process, from the initial hardware and 3D design to the electronics, software, finishing, and final assembly.

So, let’s get started with the build!

Supplies

These were the materials required for this project.

  1. Waveshare ESP32 P4 4.3-inch Dev Board
  2. Power Source—3.7V 2000mAh Li-ion cell
  3. 3D Printed Parts
  4. Slide Switch
  5. M2 screws
  6. M3 Threaded Inserts
  7. M3 Bolts
  8. M6 Nut
  9. M6 Thumb bolt
  10. Automotive filler
  11. Sandpapers
  12. Spray paint
  13. Spray primer
  14. Hyper PLA x 2 Rolls for all parts
  15. Patience and Time

FALLOUT - PIPBOY

Sapling-front-screen-on-v2-1-1024x887.jpg
original.jpg
why-does-everyone-think-this-is-courier-six-v0-oyeh4lf26drf1.jpeg
how-would-courier-six-lone-wanderer-and-sole-survivor-fair-v0-qcfokifyxkkc1.jpg
images (11).jpg
images (10).jpg
Fallout_S1_UT_220831_WHIJOJ_01690RC_3000.jpg

The Pip-Boy is a fictional wearable computer from the Fallout universe (It's like a CyberDeck on the wrist or an Apple Watch but bigger and bulkier) worn on the player character’s arm. It acts as an all-in-one personal computer, helping the player manage different aspects of their journey through the wasteland.

Depending on the game and Pip-Boy model, it can display character statistics, health and limb conditions, inventory, perks, maps, quests, radio stations, and other information. It essentially works as the player's main interface for interacting with their character and the world around them.

Across the different games, we’ve seen several versions of the device, including the Pip-Boy 2000, Pip-Boy 3000, Pip-Boy 3000 Mark II, and the Pip-Boy 4.0 seen in Fallout 76. While each version has its own design and features, they all serve the same basic purpose, which is to act as a wearable computer for the player.

Personally, I’ve always liked the look of the Fallout: New Vegas Pip-Boy 3000, and it became the biggest inspiration for this project.

HARDWARE- ESP32-P4-WIFI6 4.3inch DEV BOARD

41.gif
42.gif
esp32-p4-wifi6-touch-lcd-4.3-5.jpg

For the main hardware, or the Brain of this project, I chose the Waveshare ESP32-P4-WIFI6-Touch-LCD-4.3 development board.

There were a couple of reasons why I went with this particular board. The first was the built-in 4.3-inch 480 × 800 capacitive touchscreen, which was almost perfect for the Pip-Boy interface. Having the display and touch hardware already integrated also made the overall design much simpler.

The second, and probably more important reason, was the ESP32-P4 itself. It’s one of Espressif’s high-performance ESP32 chips, featuring a dual-core RISC-V processor running at up to 400 MHz, along with AI and DSP instruction extensions, a floating-point unit, dedicated multimedia hardware, and a much more capable memory and peripheral system than the ESP32 boards I’ve traditionally worked with.

For this project, that extra processing power was particularly useful because I wanted the Pip-Boy to handle a fairly graphical user interface, animations, audio, touch interaction, and media playback. The board also includes an ESP32-C6 wireless co-processor, giving the setup Wi-Fi 6 and Bluetooth 5 capabilities.

https://docs.waveshare.com/ESP32-P4-WIFI6-Touch-LCD-4.3

Another thing that made working with this board easier was the documentation. Waveshare has a dedicated Wiki/documentation page for the board, with hardware information, examples, and development resources. I relied on this quite a bit during development, especially while figuring out the display, touch interface, and other peripherals.

Overall, the combination of a large touchscreen, powerful ESP32-P4 processor, and built-in peripherals made this board a really good fit for building my custom Pip-Boy.

WAVSHARE SERVICE

Screenshot 2026-09-04 204600.png
Screenshot 2026-09-04 205123.png

Special thanks to Waveshare for providing the hardware used in this project. The 10.1-inch DSI screen and supporting accessories were supplied as review units for testing and evaluation.

Waveshare is a leading global provider of electronic components, modules, and development tools used across robotics, IoT, automation, education, and many other fields. With a strong focus on quality, reliability, and continuous innovation, Waveshare has earned the trust of engineers, designers, hobbyists, and makers worldwide.

Their extensive product lineup, from displays and HATs to expansion boards and embedded modules, makes them a go-to choice for both professional builds and DIY projects.

CODE SETUP

I Built a Fully Functional Pip-Boy From Scratch ☢️ | Fallout DIY

Here's the code we used in this build, and while it looks long, the logic is straightforward.

#include <lvgl.h>
#include <LovyanGFX.hpp>
#include <lgfx/v1/platforms/esp32s3/Panel_RGB.hpp>
#include <lgfx/v1/platforms/esp32s3/Bus_RGB.hpp>
#include <Wire.h>
#include <TAMC_GT911.h>
#include "arnov_portrait.h"
#include "vault_logo.h"

// ===== TOUCH =====
#define TOUCH_SDA 19
#define TOUCH_SCL 20
TAMC_GT911 touch(TOUCH_SDA, TOUCH_SCL, -1, -1, 800, 480);

// ===== DISPLAY =====
class LGFX : public lgfx::LGFX_Device {
public:
lgfx::Bus_RGB _bus;
lgfx::Panel_RGB _panel;
LGFX(void) {
auto cfg = _bus.config();
cfg.panel = &_panel;
cfg.pin_d0 = GPIO_NUM_15; cfg.pin_d1 = GPIO_NUM_7;
cfg.pin_d2 = GPIO_NUM_6; cfg.pin_d3 = GPIO_NUM_5;
cfg.pin_d4 = GPIO_NUM_4; cfg.pin_d5 = GPIO_NUM_9;
cfg.pin_d6 = GPIO_NUM_46; cfg.pin_d7 = GPIO_NUM_3;
cfg.pin_d8 = GPIO_NUM_8; cfg.pin_d9 = GPIO_NUM_16;
cfg.pin_d10 = GPIO_NUM_1; cfg.pin_d11 = GPIO_NUM_14;
cfg.pin_d12 = GPIO_NUM_21; cfg.pin_d13 = GPIO_NUM_47;
cfg.pin_d14 = GPIO_NUM_48; cfg.pin_d15 = GPIO_NUM_45;
cfg.pin_henable = GPIO_NUM_41;
cfg.pin_vsync = GPIO_NUM_40;
cfg.pin_hsync = GPIO_NUM_39;
cfg.pin_pclk = GPIO_NUM_0;
cfg.freq_write = 15000000;
cfg.hsync_polarity = 0; cfg.hsync_front_porch = 40;
cfg.hsync_pulse_width = 48; cfg.hsync_back_porch = 40;
cfg.vsync_polarity = 0; cfg.vsync_front_porch = 1;
cfg.vsync_pulse_width = 31; cfg.vsync_back_porch = 13;
cfg.pclk_active_neg = 1;
_bus.config(cfg);
auto pcfg = _panel.config();
pcfg.memory_width = 800; pcfg.memory_height = 480;
pcfg.panel_width = 800; pcfg.panel_height = 480;
_panel.config(pcfg);
_panel.setBus(&_bus);
setPanel(&_panel);
}
};
LGFX lcd;

// ===== LVGL =====
static lv_disp_draw_buf_t draw_buf;
static lv_color_t buf1[800 * 20];
static lv_disp_drv_t disp_drv;

void my_disp_flush(lv_disp_drv_t *disp,
const lv_area_t *area,
lv_color_t *color_p) {
uint32_t w = area->x2 - area->x1 + 1;
uint32_t h = area->y2 - area->y1 + 1;
lcd.pushImageDMA(area->x1, area->y1, w, h,
(lgfx::rgb565_t*)&color_p->full);
lv_disp_flush_ready(disp);
}

// ===== SCANLINE =====
lv_obj_t *scan_line = NULL;
int32_t scan_y = 1;
uint32_t t_scan = 0;
#define SCAN_TOP 52
#define SCAN_BOT (480 - 52 - 38)

// ===== SETUP =====
void setup() {
Serial.begin(115200);

pinMode(2, OUTPUT);
digitalWrite(2, HIGH);

lcd.begin();
lcd.fillScreen(TFT_BLACK);

lv_init();
lv_disp_draw_buf_init(&draw_buf, buf1, NULL,
sizeof(buf1) / sizeof(buf1[0]));
lv_disp_drv_init(&disp_drv);
disp_drv.hor_res = 800;
disp_drv.ver_res = 480;
disp_drv.flush_cb = my_disp_flush;
disp_drv.draw_buf = &draw_buf;
lv_disp_drv_register(&disp_drv);

Wire.begin(TOUCH_SDA, TOUCH_SCL);
touch.begin();

// ---- root screen ----
lv_obj_t *scr = lv_scr_act();
lv_obj_set_style_bg_color(scr, lv_color_hex(0x000800), 0);
lv_obj_set_style_bg_opa(scr, LV_OPA_COVER, 0);

// ============ TOP BAR ============
lv_obj_t *top = lv_obj_create(scr);
lv_obj_set_pos(top, 0, 0);
lv_obj_set_size(top, 800, 52);
lv_obj_set_style_bg_color(top, lv_color_hex(0x000000), 0);
lv_obj_set_style_bg_opa(top, LV_OPA_COVER, 0);
lv_obj_set_style_border_color(top, lv_color_hex(0x008000), 0);
lv_obj_set_style_border_width(top, 1, 0);
lv_obj_set_style_radius(top, 0, 0);
lv_obj_set_style_pad_all(top, 0, 0);
lv_obj_set_scrollbar_mode(top, LV_SCROLLBAR_MODE_OFF);

lv_obj_t *sb = lv_obj_create(top);
lv_obj_set_pos(sb, 4, 4);
lv_obj_set_size(sb, 90, 44);
lv_obj_set_style_bg_color(sb, lv_color_hex(0x000000), 0);
lv_obj_set_style_bg_opa(sb, LV_OPA_COVER, 0);
lv_obj_set_style_border_color(sb, lv_color_hex(0x008000), 0);
lv_obj_set_style_border_width(sb, 1, 0);
lv_obj_set_style_radius(sb, 0, 0);
lv_obj_set_style_pad_all(sb, 0, 0);
lv_obj_set_scrollbar_mode(sb, LV_SCROLLBAR_MODE_OFF);
lv_obj_t *sl = lv_label_create(sb);
lv_label_set_text(sl, "STATS");
lv_obj_set_style_text_color(sl, lv_color_hex(0x00FF00), 0);
lv_obj_set_style_text_font(sl, &lv_font_montserrat_28, 0);
lv_obj_align(sl, LV_ALIGN_CENTER, 0, 0);

char buf[24];
lv_obj_t *ll = lv_label_create(top);
lv_label_set_text(ll, "LVL");
lv_obj_set_pos(ll, 102, 16);
lv_obj_set_style_text_color(ll, lv_color_hex(0x005000), 0);
lv_obj_set_style_text_font(ll, &lv_font_montserrat_14, 0);

snprintf(buf, sizeof(buf), " %d", 20);
lv_obj_t *lv2 = lv_label_create(top);
lv_label_set_text(lv2, buf);
lv_obj_set_pos(lv2, 128, 10);
lv_obj_set_style_text_color(lv2, lv_color_hex(0x00FF00), 0);
lv_obj_set_style_text_font(lv2, &lv_font_montserrat_24, 0);

lv_obj_t *hl = lv_label_create(top);
lv_label_set_text(hl, "HP");
lv_obj_set_pos(hl, 222, 16);
lv_obj_set_style_text_color(hl, lv_color_hex(0x005000), 0);
lv_obj_set_style_text_font(hl, &lv_font_montserrat_14, 0);

lv_obj_t *hv = lv_label_create(top);
lv_label_set_text(hv, " 320/410");
lv_obj_set_pos(hv, 240, 16);
lv_obj_set_style_text_color(hv, lv_color_hex(0x00FF00), 0);
lv_obj_set_style_text_font(hv, &lv_font_montserrat_16, 0);

lv_obj_t *al = lv_label_create(top);
lv_label_set_text(al, "AP");
lv_obj_set_pos(al, 392, 16);
lv_obj_set_style_text_color(al, lv_color_hex(0x005000), 0);
lv_obj_set_style_text_font(al, &lv_font_montserrat_14, 0);

lv_obj_t *av = lv_label_create(top);
lv_label_set_text(av, " 134/104");
lv_obj_set_pos(av, 410, 16);
lv_obj_set_style_text_color(av, lv_color_hex(0x00FF00), 0);
lv_obj_set_style_text_font(av, &lv_font_montserrat_16, 0);

lv_obj_t *xl = lv_label_create(top);
lv_label_set_text(xl, "XP");
lv_obj_set_pos(xl, 562, 16);
lv_obj_set_style_text_color(xl, lv_color_hex(0x005000), 0);
lv_obj_set_style_text_font(xl, &lv_font_montserrat_14, 0);

lv_obj_t *xv = lv_label_create(top);
lv_label_set_text(xv, " MAX");
lv_obj_set_pos(xv, 582, 16);
lv_obj_set_style_text_color(xv, lv_color_hex(0x00FF00), 0);
lv_obj_set_style_text_font(xv, &lv_font_montserrat_16, 0);

// ============ PORTRAIT PANEL ============
lv_obj_t *port = lv_obj_create(scr);
lv_obj_set_pos(port, 0, 52);
lv_obj_set_size(port, 392, 376);
lv_obj_set_style_bg_color(port, lv_color_hex(0x000800), 0);
lv_obj_set_style_bg_opa(port, LV_OPA_COVER, 0);
lv_obj_set_style_border_width(port, 0, 0);
lv_obj_set_style_radius(port, 0, 0);
lv_obj_set_style_pad_all(port, 0, 0);
lv_obj_set_scrollbar_mode(port, LV_SCROLLBAR_MODE_OFF);

static lv_img_dsc_t idsc;
idsc.header.cf = LV_IMG_CF_TRUE_COLOR;
idsc.header.always_zero = 0;
idsc.header.reserved = 0;
idsc.header.w = PORTRAIT_W;
idsc.header.h = PORTRAIT_H;
idsc.data_size = PORTRAIT_W * PORTRAIT_H * 2;
idsc.data = (const uint8_t*)arnov_portrait;
lv_obj_t *img = lv_img_create(port);
lv_img_set_src(img, &idsc);
lv_obj_set_pos(img, (392 - PORTRAIT_W)/2, (376 - PORTRAIT_H)/2 - 18);

lv_obj_t *ns = lv_obj_create(port);
lv_obj_set_pos(ns, 0, 338);
lv_obj_set_size(ns, 392, 38);
lv_obj_set_style_bg_color(ns, lv_color_hex(0x000800), 0);
lv_obj_set_style_bg_opa(ns, LV_OPA_COVER, 0);
lv_obj_set_style_border_color(ns, lv_color_hex(0x008000), 0);
lv_obj_set_style_border_width(ns, 1, 0);
lv_obj_set_style_border_side(ns, LV_BORDER_SIDE_TOP, 0);
lv_obj_set_style_radius(ns, 0, 0);
lv_obj_set_style_pad_all(ns, 0, 0);
lv_obj_set_scrollbar_mode(ns, LV_SCROLLBAR_MODE_OFF);
lv_obj_t *nl = lv_label_create(ns);
lv_label_set_text(nl, "Arnov - Level 20");
lv_obj_set_style_text_color(nl, lv_color_hex(0x00FF00), 0);
lv_obj_set_style_text_font(nl, &lv_font_montserrat_24, 0);
lv_obj_align(nl, LV_ALIGN_CENTER, 0, 0);

scan_line = lv_obj_create(port);
lv_obj_set_pos(scan_line, 0, 1);
lv_obj_set_size(scan_line, 392, 2);
lv_obj_set_style_bg_color(scan_line, lv_color_hex(0x003000), 0);
lv_obj_set_style_bg_opa(scan_line, LV_OPA_60, 0);
lv_obj_set_style_border_width(scan_line, 0, 0);
lv_obj_set_style_radius(scan_line, 0, 0);
lv_obj_set_scrollbar_mode(scan_line, LV_SCROLLBAR_MODE_OFF);

lv_obj_t *vd = lv_obj_create(scr);
lv_obj_set_pos(vd, 393, 52);
lv_obj_set_size(vd, 2, 376);
lv_obj_set_style_bg_color(vd, lv_color_hex(0x008000), 0);
lv_obj_set_style_bg_opa(vd, LV_OPA_COVER, 0);
lv_obj_set_style_border_width(vd, 0, 0);
lv_obj_set_style_radius(vd, 0, 0);
lv_obj_set_scrollbar_mode(vd, LV_SCROLLBAR_MODE_OFF);

// ============ HEALTH PANEL ============
lv_obj_t *hp = lv_obj_create(scr);
lv_obj_set_pos(hp, 396, 52);
lv_obj_set_size(hp, 404, 376);
lv_obj_set_style_bg_color(hp, lv_color_hex(0x000800), 0);
lv_obj_set_style_bg_opa(hp, LV_OPA_COVER, 0);
lv_obj_set_style_border_color(hp, lv_color_hex(0x008000), 0);
lv_obj_set_style_border_width(hp, 1, 0);
lv_obj_set_style_radius(hp, 0, 0);
lv_obj_set_style_pad_all(hp, 0, 0);
lv_obj_set_scrollbar_mode(hp, LV_SCROLLBAR_MODE_OFF);

lv_obj_t *hpl = lv_label_create(hp);
lv_label_set_text(hpl, "HP");
lv_obj_set_pos(hpl, 16, 20);
lv_obj_set_style_text_color(hpl, lv_color_hex(0x00FF00), 0);
lv_obj_set_style_text_font(hpl, &lv_font_montserrat_24, 0);
lv_obj_t *hpv = lv_label_create(hp);
lv_label_set_text(hpv, "320/410");
lv_obj_set_pos(hpv, 300, 22);
lv_obj_set_style_text_color(hpv, lv_color_hex(0x005000), 0);
lv_obj_set_style_text_font(hpv, &lv_font_montserrat_20, 0);
lv_obj_t *hpbg = lv_obj_create(hp);
lv_obj_set_pos(hpbg, 16, 50);
lv_obj_set_size(hpbg, 372, 22);
lv_obj_set_style_bg_color(hpbg, lv_color_hex(0x001200), 0);
lv_obj_set_style_bg_opa(hpbg, LV_OPA_COVER, 0);
lv_obj_set_style_border_color(hpbg, lv_color_hex(0x00A000), 0);
lv_obj_set_style_border_width(hpbg, 2, 0);
lv_obj_set_style_radius(hpbg, 0, 0);
lv_obj_set_style_pad_all(hpbg, 0, 0);
lv_obj_set_scrollbar_mode(hpbg, LV_SCROLLBAR_MODE_OFF);
lv_obj_t *hpf = lv_obj_create(hpbg);
lv_obj_set_pos(hpf, 2, 2);
lv_obj_set_size(hpf, 284, 18);
lv_obj_set_style_bg_color(hpf, lv_color_hex(0x00A000), 0);
lv_obj_set_style_bg_opa(hpf, LV_OPA_COVER, 0);
lv_obj_set_style_border_width(hpf, 0, 0);
lv_obj_set_style_radius(hpf, 0, 0);
lv_obj_set_scrollbar_mode(hpf, LV_SCROLLBAR_MODE_OFF);

lv_obj_t *apl = lv_label_create(hp);
lv_label_set_text(apl, "AP");
lv_obj_set_pos(apl, 16, 85);
lv_obj_set_style_text_color(apl, lv_color_hex(0x00FF00), 0);
lv_obj_set_style_text_font(apl, &lv_font_montserrat_24, 0);
lv_obj_t *apv = lv_label_create(hp);
lv_label_set_text(apv, "134/104");
lv_obj_set_pos(apv, 300, 87);
lv_obj_set_style_text_color(apv, lv_color_hex(0x005000), 0);
lv_obj_set_style_text_font(apv, &lv_font_montserrat_20, 0);
lv_obj_t *apbg = lv_obj_create(hp);
lv_obj_set_pos(apbg, 16, 115);
lv_obj_set_size(apbg, 372, 22);
lv_obj_set_style_bg_color(apbg, lv_color_hex(0x001200), 0);
lv_obj_set_style_bg_opa(apbg, LV_OPA_COVER, 0);
lv_obj_set_style_border_color(apbg, lv_color_hex(0x00A000), 0);
lv_obj_set_style_border_width(apbg, 2, 0);
lv_obj_set_style_radius(apbg, 0, 0);
lv_obj_set_style_pad_all(apbg, 0, 0);
lv_obj_set_scrollbar_mode(apbg, LV_SCROLLBAR_MODE_OFF);
lv_obj_t *apf = lv_obj_create(apbg);
lv_obj_set_pos(apf, 2, 2);
lv_obj_set_size(apf, 368, 18);
lv_obj_set_style_bg_color(apf, lv_color_hex(0x005800), 0);
lv_obj_set_style_bg_opa(apf, LV_OPA_COVER, 0);
lv_obj_set_style_border_width(apf, 0, 0);
lv_obj_set_style_radius(apf, 0, 0);
lv_obj_set_scrollbar_mode(apf, LV_SCROLLBAR_MODE_OFF);

lv_obj_t *rdl = lv_label_create(hp);
lv_label_set_text(rdl, "RAD");
lv_obj_set_pos(rdl, 16, 150);
lv_obj_set_style_text_color(rdl, lv_color_hex(0x00FF00), 0);
lv_obj_set_style_text_font(rdl, &lv_font_montserrat_24, 0);
lv_obj_t *rdv = lv_label_create(hp);
lv_label_set_text(rdv, "12");
lv_obj_set_pos(rdv, 350, 152);
lv_obj_set_style_text_color(rdv, lv_color_hex(0x005000), 0);
lv_obj_set_style_text_font(rdv, &lv_font_montserrat_20, 0);
lv_obj_t *rdbg = lv_obj_create(hp);
lv_obj_set_pos(rdbg, 16, 180);
lv_obj_set_size(rdbg, 372, 22);
lv_obj_set_style_bg_color(rdbg, lv_color_hex(0x001200), 0);
lv_obj_set_style_bg_opa(rdbg, LV_OPA_COVER, 0);
lv_obj_set_style_border_color(rdbg, lv_color_hex(0x00A000), 0);
lv_obj_set_style_border_width(rdbg, 2, 0);
lv_obj_set_style_radius(rdbg, 0, 0);
lv_obj_set_style_pad_all(rdbg, 0, 0);
lv_obj_set_scrollbar_mode(rdbg, LV_SCROLLBAR_MODE_OFF);
lv_obj_t *rdf = lv_obj_create(rdbg);
lv_obj_set_pos(rdf, 2, 2);
lv_obj_set_size(rdf, 4, 18);
lv_obj_set_style_bg_color(rdf, lv_color_hex(0x005800), 0);
lv_obj_set_style_bg_opa(rdf, LV_OPA_COVER, 0);
lv_obj_set_style_border_width(rdf, 0, 0);
lv_obj_set_style_radius(rdf, 0, 0);
lv_obj_set_scrollbar_mode(rdf, LV_SCROLLBAR_MODE_OFF);

static lv_img_dsc_t vdsc;
vdsc.header.cf = LV_IMG_CF_TRUE_COLOR;
vdsc.header.always_zero = 0;
vdsc.header.reserved = 0;
vdsc.header.w = VAULT_W;
vdsc.header.h = VAULT_H;
vdsc.data_size = VAULT_W * VAULT_H * 2;
vdsc.data = (const uint8_t*)vault_logo;
lv_obj_t *logo = lv_img_create(hp);
lv_img_set_src(logo, &vdsc);
lv_obj_set_pos(logo, (404 - VAULT_W)/2, 220);

// ============ BOTTOM NAV ============
lv_obj_t *nav = lv_obj_create(scr);
lv_obj_set_pos(nav, 0, 428);
lv_obj_set_size(nav, 800, 52);
lv_obj_set_style_bg_color(nav, lv_color_hex(0x000000), 0);
lv_obj_set_style_bg_opa(nav, LV_OPA_COVER, 0);
lv_obj_set_style_border_color(nav, lv_color_hex(0x008000), 0);
lv_obj_set_style_border_width(nav, 1, 0);
lv_obj_set_style_radius(nav, 0, 0);
lv_obj_set_style_pad_all(nav, 0, 0);
lv_obj_set_scrollbar_mode(nav, LV_SCROLLBAR_MODE_OFF);

const char *tabs[] = {"Status","S.P.E.C.I.A.L.","Skills","Perks","General"};
int tx = 12;
for(int i = 0; i < 5; i++) {
int tw = strlen(tabs[i]) * 12 + 16;

if(i == 0) {
lv_obj_t *tb = lv_obj_create(nav);
lv_obj_set_pos(tb, tx-2, 4);
lv_obj_set_size(tb, tw, 44);
lv_obj_set_style_bg_color(tb, lv_color_hex(0x001800), 0);
lv_obj_set_style_bg_opa(tb, LV_OPA_COVER, 0);
lv_obj_set_style_border_color(tb, lv_color_hex(0x008000), 0);
lv_obj_set_style_border_width(tb, 1, 0);
lv_obj_set_style_radius(tb, 0, 0);
lv_obj_set_style_pad_all(tb, 0, 0);
lv_obj_set_scrollbar_mode(tb, LV_SCROLLBAR_MODE_OFF);
}

lv_obj_t *tl = lv_label_create(nav);
lv_label_set_text(tl, tabs[i]);
lv_obj_set_pos(tl, tx+4, 16);
lv_obj_set_style_text_color(tl,
i == 0 ? lv_color_hex(0x00FF00) : lv_color_hex(0x005000), 0);
lv_obj_set_style_text_font(tl, &lv_font_montserrat_16, 0);

if(i < 4) {
lv_obj_t *dash = lv_label_create(nav);
lv_label_set_text(dash, "-");
lv_obj_set_pos(dash, tx + tw + 5, 16);
lv_obj_set_style_text_color(dash, lv_color_hex(0x003000), 0);
lv_obj_set_style_text_font(dash, &lv_font_montserrat_16, 0);
}
tx += tw + 20;
}
}

// ===== LOOP =====
void loop() {
lv_timer_handler();

uint32_t now = millis();
if(now - t_scan >= 55 && scan_line != NULL) {
t_scan = now;
scan_y++;
if(scan_y >= 338) scan_y = 1;
lv_obj_set_pos(scan_line, 0, scan_y);
lv_obj_invalidate(scan_line);
}

touch.read();
if(touch.isTouched) {
int x = 800 - touch.points[0].x;
int y = 480 - touch.points[0].y;
x = constrain(x, 0, 799);
y = constrain(y, 0, 479);
}

delay(5);
}

Aside from the code, we used the LovyanGFX and LVGL libraries to drive the 4.3" RGB LCD display. Instead of loading images from an SD card, we converted the Vault Boy portrait and the Vault-Tec logo into raw C-arrays (arnov_portrait.h and vault_logo.h). These files are stored directly in flash memory, which allows the microcontroller to render the graphics instantly without any loading lag. We also wired up a GT911 capacitive touch controller using the I2C pins so the screen responds to input.

When we power on the device, the setup function initializes the display drivers and begins building the LVGL interface layer by layer. The screen is divided into classic Pip-Boy sections: a top bar for vital stats like Level and XP, a central portrait panel for the mascot, a health panel with HP and AP bars, and a bottom navigation menu. We set all the colors using specific hex codes—like 0x00FF00 for the bright green text and 0x000800 for the dark backgrounds—to perfectly match the monochrome CRT vibe.

Once the UI is built, the device runs the loop() function continuously. Here, it checks for touch inputs via the GT911 controller so we can interact with the screen. At the same time, we use a millis() timer to drop a semi-transparent green line down the portrait panel every 55 milliseconds. When this line hits the bottom of the frame, it resets to the top, creating a continuous retro scanline animation just like an old terminal monitor.

Full code: https://github.com/razorArnov/FalloutPipboy

We have attached a short video showing the interface running; please check it out for a demo.

DESIGN

I Built a Fully Functional Pip-Boy From Scratch ☢️ | Fallout DIY
untitled.832.png
untitled.833.png
untitled.834.png
untitled.835.png
untitled.836.png
untitled.837.png

For the design of this project, I took a lot of inspiration from the PipBoy 3000 featured in Fallout: New Vegas. I wanted my version to have the same overall design language and retro-futuristic look, but I didn’t want to simply copy the original.

The biggest challenge was adapting the design to my hardware. The original PipBoy has a relatively small display, but I’m using a much larger display in my project. If I simply maintained the proportions of the original Pip-Boy around my screen, the entire device would have become unnecessarily huge. So instead, I designed my own version that takes inspiration from the original while being built specifically around my hardware.

The most noticeable change is the large display in the center. Below it, I added a set of ribs to give the device some of the visual details found on the original Pip-Boy. I also added a dial-like greeble on the side of the display.

Since the display is touchscreen, I didn’t need physical buttons or a rotary control for navigation. Instead, the dial-like part houses a slide switch that acts as the main power switch.

DISPLAY HOUSING

Screenshot 2026-09-02 224402.png
Screenshot 2026-09-02 224459.png
Screenshot 2026-09-02 224553.png
Screenshot 2026-09-02 224619.png

For the display housing, I wanted to give the PipBoy a slightly more retro appearance, so I designed the screen cover with curved bezels inspired by old CRT televisions. I also added a screen shade around the top of the display to make it feel more like a piece of old industrial equipment.

The shade also includes a small greeble that holds the PIPBOY logo. I designed this as a separate part so it could later be 3D printed using a dual-color printing technique, giving the logo a contrasting finish.

On the left side, I also modeled an access point for the dual Type-C ports of the Wavshare display so we can use it for reprogramming or charging the board.

WRIST MOUNTED DESIGN

Screenshot 2026-09-02 224226.png
Screenshot 2026-09-02 224250.png

Since this device is meant to actually be worn on the wrist, I had to think about how the body would open and fit around the arm.

The overall body is essentially divided into two sections. The upper section contains the display and electronics, while the lower section forms the wrist-cover portion. When viewed from the side, the two sections follow a circular shape that has been split into two parts.

To connect these two sections, I designed a hinge mechanism around a central pivot point on the side of the Pip-Boy. This allows the lower section to pivot away from the main body, making it easier to put the device on the wrist.

To keep both sections securely connected, I added two additional mounting parts that use two self-locking M6 nuts. These provide a stronger mechanical connection between the upper and lower sections while still allowing the hinge to move.

EXTERIOR GREEBLE

Screenshot 2026-09-02 223537.png
Screenshot 2026-09-02 223608.png
Screenshot 2026-09-02 223633.png

I also added a few custom greebles to give the Pip-Boy more visual detail.

On the front frame, there is a separate part that I call the dial. I modelled this to resemble a physical control dial, even though it is purely decorative.

Below the ribs on the main body, I added another greeble featuring the “MODEL 6000” label. Like the PIPBOY logo, this was designed as a separate part so it could be printed in two colours and stand out from the rest of the body.

3D PRINTED PARTS

Making a functional PIPBOY from Fallout!
01.gif
02.gif
03.gif
04.gif

For the 3D-printed parts, I used Hyper PLA for the entire project. I printed the parts in different colors, but this is not a requirement for the build. I simply used whatever filament colors I had available at the time, since I planned to finish the parts with body filler, primer, and paint later. Because of that, the color of the filament doesn’t really matter.

For all the parts, I used tree supports where required. The models were printed with a 0.2 mm layer height and 25% infill on my Anycubic Kobra S1 Pro.

Since the final parts would go through a body finishing and painting process, the focus here was mainly on getting strong, clean prints rather than achieving a perfect surface finish straight off the printer.

For the smaller greeble details, I printed three special parts: one featuring the Pip-Boy logo, another with the Model 6000 label, and a third part that serves as the dial on the Pip-Boy.

For all three parts, I used a dual-color printing technique. The base of each part was printed using white PLA, while the text and details were printed in a different color.

For the Pip-Boy logo and Model 6000 part, I started the print using white PLA and paused the print at the appropriate layer. I then swapped the filament to black PLA and resumed the print, allowing the letters to be printed in black while keeping the rest of the part white.

I used the same technique for the dial, but instead of black, I switched to red PLA for the dial markings.

This allowed me to create the contrasting details directly during the 3D printing process, without having to paint the small lettering and dial elements afterwards.

FILLER PREP WORK

I Built a Fully Functional Pip-Boy From Scratch ☢️ | Fallout DIY
15.gif
16.gif
17.gif

For filler material, we are using a 3M automotive two-part filler, which consists of a filler and a hardener.

By adding 2% hardener and mixing it thoroughly with the filler, we get a compound that can be used to fill gaps, layer lines, and other imperfections on our printed body.

The filler process is an important step before painting. Applying filler to 3D prints, then sanding the surface smooth, followed by primer and paint, results in a finish so clean that it no longer looks 3D printed at all.

SURFACE FINISH PROCESS- BODY FILLER

06.gif
07.gif
IMG_1456.JPG
IMG_1459.JPG

Using a paint scraper, I took a small amount of the mixed filler compound and applied it across all three parts. The main goal at this stage was to fill the gaps between the joined sections and then cover any areas where visible layer lines were present.

The filler settles into the layer lines and gaps, creating a more even surface that can later be sanded smooth before applying primer and paint.

SANDING PROCESS MATERIALS & PREP WORK

26.gif
29.gif

The next process after applying filler is sanding. But before starting, we need to prepare properly.

Here, we are primarily using two grits of sandpaper: 100 grit for coarse grinding and 150 grit for a medium finish.

To use sandpaper effectively, we use a sandpaper holder, which is a really useful tool for sanding. I cut the sandpaper into strips, attach them to the holder, and use it for sanding. It’s more effective and works better than using sandpaper alone.

Also, since we are sanding filler material that produces fine dust particles, we use a mask with proper filters.

Gloves are also recommended, as this process can get quite messy.

SURFACE FINISH PROCESS- SANDING

08.gif
09.gif
10.gif
IMG_1479.JPG

Now comes the most fun part of the project for me: sanding.

I begin by sanding the top surfaces of all three parts, followed by sanding down the gaps between parts that were filled with filler. The edges of the parts with fillets are also sanded.

The goal here is not to sand down the plastic itself, but the added filler. This way, we remove excess filler while keeping the plastic body intact.

Doing this removes the visible gaps between layer lines and evens out the surface.

SURFACE FINISH PROCESS- PRIMER

11.gif
12.gif
13.gif
14.gif
15.gif
16.gif
IMG_1526.JPG

Now comes the priming process, and this one was quite lengthy.

For painting, primer is a mandatory base coat because it helps the paint adhere better to the surface, improves durability, and highlights any remaining imperfections that need fixing.

Here, I used a spray primer, which works just like spray paint but is specifically designed as a base layer.

I started by applying light, even coats across the entire body, gradually covering the full surface. After the first coat, I let the primer dry for a couple of hours, then applied a second coat and allowed it to dry again.

Finally, I applied a third coat for a consistent and well-prepared surface.

SURFACE FINISH PROCESS- PAINT (BASE COAT)

17.gif
18.gif
19.gif
20.gif
IMG_1553.JPG

The surface finish I wanted was a metallic silver look, but achieving that with silver spray paint alone wouldn’t give me the finish I was after. Instead, I started by applying a black base coat.

I sprayed the parts with several light coats, allowing each layer to dry before applying the next. I repeated this process until I had around five to six coats of black paint covering the entire surface.

The black base is important for the next step, where I’ll be applying silver dust over the painted surface. This will create a more convincing metallic finish with the appearance and texture of real metal rather than simply looking like silver-painted plastic.

SURFACE FINISH PROCESS- PAINT (FINAL COAT)

I Built a Fully Functional Pip-Boy From Scratch ☢️ | Fallout DIY
Making My Pip-Boy Look Like Real Metal
21.gif
22.gif
23.gif
24.gif
25.gif
26.gif
27.gif

Now comes the part that gives the Pip-Boy its metallic appearance.

For this, I’m using an acrylic silver dust paint. Unlike regular silver paint, this is a fine metallic powder that can be applied using a brush. I simply brushed the silver dust over the entire surface of the 3D-printed parts.

The black paint underneath provides a surface for the fine particles to adhere to, while any excess dust can be brushed off. This leaves behind a layer of metallic silver that gives the parts the appearance and feel of real metal.

I repeated the same process across all of the parts, including the smaller greeble details, making sure everything had the same metallic finish.

Once I was happy with the result, I needed to make sure the silver dust wouldn’t rub off during handling. For that, I used an acrylic conformal coating spray and applied two coats over all the parts. This seals the metallic powder in place while maintaining the overall finish.

The result is a convincing cast-iron-like finish that makes the parts look far less like 3D-printed plastic and much more like a piece of old Fallout-era hardware.

GREEBLE PARTS ASSEMBLY

28.gif
29.gif
30.gif

Now it’s time to install the greeble parts onto the Pip-Boy.

We’ll start with the dial. I applied a small amount of super glue to the designated mounting area on the front cover, positioned the dial in place, and held it for a few seconds until the glue secured it.

I followed the same process for the Pip-Boy logo. A small amount of super glue was applied to its mounting location on the front cover, and the logo was then positioned and secured in place.

Finally, on the main body, I applied super glue to the mounting area for the Model 6000 label. I placed the label into position and held it firmly until the glue set.

With all three greeble parts installed, the exterior of the Pip-Boy starts to look much closer to a finished prop.

WEATHERING PROCESS

I Built a Fully Functional Pip-Boy From Scratch ☢️ | Fallout DIY
31.gif
32.gif
33.gif
34.gif
35.gif
36.gif

Now comes one of my favorite parts of the entire project: weathering.

The goal of the weathering process is to make the 3D-printed parts look like they’ve been sitting in the Fallout wasteland for the last 200 years. I wanted the finished PipBoy to have an old, worn-out metal appearance, complete with rust, scratches, and a bit of patina.

I started by using a file and sandpaper to randomly remove some of the paint from the surface. I also used the file to create scratches, lines, cavities, and deeper cuts in different areas. These imperfections help make the surface look damaged and naturally worn rather than perfectly manufactured.

Once the surface was prepared, I moved on to the rust and patina. I used brown and moss-green acrylic paints, applying the paint to the body with a brush. I then used a sponge to spread and blend the paint across the surface.

The paint naturally settles into the sanded areas, scratches, and deeper cuts, creating darker patches that resemble accumulated rust and dirt. I also added moss-green paint in various areas to give the surface the appearance of moss and organic growth developing on the old metal.

I repeated this process across all three main parts of the PipBoy: the front frame, main body, and lower handle, while varying the amount of weathering on each part to make the finish look more natural.

Once I was happy with the overall patina, I sealed everything with a couple of coats of acrylic conformal coating spray. This protects the weathering and keeps the paint permanently attached to the surface.

The end result is a rusty, mouldy, and heavily weathered PipBoy that looks like it has genuinely spent 200 years surviving in the Fallout wasteland.

BASE BODY THREADED INSERTS

37.gif
38.gif

To assemble the hinge mechanism, I added two M3 threaded inserts on each side of the main body.

I installed them using a soldering iron, with the temperature set to around 150°C. Using tweezers, I first aligned the threaded insert with its mounting hole.

I then used the heated soldering iron tip to press down on the insert. The combination of heat and pressure softens the surrounding PLA, allowing the insert to sink into the plastic and become firmly embedded in the part.

I repeated the same process on the other side, giving us secure threaded mounting points for the hinge assembly.

POWER SWITCH ASSEMBLY

39.gif
40.gif
44.gif
45.gif

For the power switch, I'm using a regular slide switch, connecting two wires to its NC and NO terminals with a soldering iron.

Next, we place it inside the knob part, and it is press-fitted in place.

The Knob part is then placed in its position on the side of the main body and secured in place using a single M2 screw.

POWER SOURCE ASSEMBLY

43.gif
46.gif
47.gif
48.gif
49.gif

For the power source, I’m using a 3.7V 2200mAh 18650 Li-ion cell as the main battery for the Pip-Boy.

To add the power switch, I cut the positive wire from the battery and soldered the two wires from the slide switch between the battery and the JST connector. This essentially puts the switch in series with the positive connection, allowing us to turn the entire device on and off.

To properly insulate the soldered connections and prevent any accidental shorts, I covered them with heat-shrink tubing.

Next, I moved on to mounting the battery inside the main body. I applied a small amount of hot glue to the designated battery mounting area and positioned the 18650 cell in place.

There was a little excess wire left over, so I neatly tucked it into the available space near the knob and battery compartment.

With the battery secured and the wiring tucked away, the power source assembly is complete.

ESP32 P4 DEV BOARD & BODY ASSEMBLY

50.gif
51.gif
52.gif
53.gif

Next, we connect the male JST connector from the Li-ion battery to the female JST connector on the Waveshare ESP32-P4 board.

With the power connection made, I positioned the board inside the upper section of the Pip-Boy and aligned its PCB mounting standoffs with the mounting holes in the enclosure.

Once everything was properly aligned, I secured the board in place using four M2.5 bolts from the rear side.

FRAME & BODY ASSEMBLY

54.gif
55.gif
56.gif

Next, we position the front frame over the display and align it with its mounting points on the upper section.

Once it is properly aligned, I gently press the frame into place from the top to make sure it sits flush with the display and enclosure.

Finally, I secure the frame to the upper section using eight M2 screws, making sure the frame is firmly held in place around the display.

FOAM PADDING

57.gif
58.gif
59.gif
60.gif

Since this is a wearable device, I wanted to add some padding inside the Pip-Boy so it stays comfortable even when worn for longer periods.

For the padding, I used some leftover acoustic foam I had available. I trimmed the foam down to reduce its thickness, since adding too much padding would make the fit tighter around the wrist.

Once the foam was prepared, I applied hot glue to the inside of both the upper and lower sections and carefully placed the padding in position.

NUT ASSEMBLY

61.gif

Here’s another crucial step in the assembly. I designed hexagonal slots into the upper body to hold the M6 nuts in place.

These nuts will later be used with the hand-tightening bolts to secure the lower section of the Pip-Boy to the upper section. The hexagonal shape prevents the nuts from rotating when we tighten or loosen the bolts.

I placed a total of two M6 nuts into the slots on the upper body, creating the threaded mounting points for the wrist-tightening mechanism.

FINAL ASSEMBLY

62.gif
63.gif
64.gif
65.gif
66.gif
67.gif
68.gif

For the final assembly, we first bring together the upper and lower sections of the Pip-Boy. I aligned the mounting holes on the lower section with the hinge points on the upper section, then secured both sections using two M3 bolts.

Next, I installed the two mounting plates onto the lower section. After aligning them with their respective mounting positions, I secured each plate using two M2 screws, giving us four screws in total.

These mounting plates are then used with the two hand-tightening bolts to hold the upper and lower sections together. By loosening the bolts, we can open the Pip-Boy and put it on the wrist, and tightening them secures the device in place.

With the hinge, mounting plates, and hand-tightening mechanism installed, the assembly process is finally complete.

RESULT

THIS IS HOW MY PIP-BOY ACTUALLY WORKS!
69.gif
70.gif
71.gif
72.gif
73.gif
74.gif
75.gif
82.gif
83.gif
84.gif
85.gif
86.gif
87.gif

And here’s the result of this fun build: a fully functional Pip-Boy!

So, how does it actually work?

We start with the slide switch on the side. Once the switch is toggled, the device powers on and we’re greeted with a Fallout “Please Wait” startup animation, along with the Fallout: New Vegas menu music playing in the background.

After about four seconds, the device boots into the main Status menu. I kept the layout very close to the character status interface from the game, including the different limb condition indicators for the head, arms, and other body parts. The biggest change here is that I replaced Vault Boy with my own image.

There’s also a small hidden feature in the Status menu. By tapping my image, we can cycle through three different themes: the New Vegas theme, Fallout 3 theme, and a blue New Vegas theme.

To make the interface feel even more authentic, I also added the classic Pip-Boy interaction sound. Whenever we touch or select something in any of the menus, the device plays the same beep-style sound used by the Pip-Boy in the original games.

It’s a small detail, but it makes interacting with the touchscreen feel much more like using an actual Pip-Boy.

Since the display is a touchscreen, we can simply swipe to move to the next menu.

The second screen is the Perks menu, again inspired by the original Pip-Boy interface. Here, I added the ability to increase or decrease different character attributes, including Strength, Charisma, Luck, and other stats.

Next is the Internet Watch. This one is a little different from the original Pip-Boy. It uses NTP data from the internet to get the current time and displays the time, date, and day using a Fallout-inspired interface.

Then we have the Radio menu, although technically, it’s not a radio. It’s a music player. The songs are stored on an SD card, and from here we can play, pause, skip between tracks, and control the volume. I also added a waveform animation that moves along with the music while a song is playing, which makes the whole thing feel much more like an actual Pip-Boy interface.

Finally, we have the Map.

This one is probably my favourite because instead of using an actual Fallout map, I took a map of my hometown and redesigned it using the visual style and layout of the Mojave map from Fallout: New Vegas.

So, from character stats and perks to an internet-connected clock, music player, and a custom Fallout-style map, this Pip-Boy ended up being much more than just a wearable prop. It’s a fully functional device built from scratch, with the interface designed specifically to make it feel like something straight out of the Fallout universe.

WEARING THE PIPBOY

73.gif
74.gif
82.gif

Here’s how the PipBoy is worn.

First, we remove the two hand-tightening nuts, which allows the lower section to open up on its hinge. We can then place our hand inside the device and close it back around the wrist.

Finally, we reinstall and tighten both nuts by hand to secure the two sections together.

And that’s it; the PipBoy is securely mounted on the wrist and ready to use.

OVERVIEW

82.gif
76.gif
77.gif
78.gif
79.gif
75.gif

This was honestly one of the most fun projects I’ve worked on. Since I’m a Fallout fan, getting to take something from the game and turn it into a real, working device made the entire process much more enjoyable.

What I particularly liked about this project was that it wasn’t just about making the Pip-Boy look right. I got to work on 3D modelling, printing, finishing, electronics, UI design, and coding, while constantly trying to make the device feel like something that could actually exist in the Fallout universe.

There were definitely a few challenging parts along the way, especially getting the software and UI to work the way I wanted, but seeing everything come together and actually being able to wear the Pip-Boy and interact with it made all the work worth it.

I also really enjoyed having the freedom to create my own version instead of simply copying an existing Pip-Boy. From the custom enclosure and weathering to the UI, map, and little interaction sounds, I could add my own ideas while still keeping the Fallout aesthetic.

And honestly, this probably won’t be the last version. There are already a bunch of features I’d love to experiment with in the future.

Even though the Pip-Boy AR Mark 6000 is complete, I don’t think I’m done with it yet. There are already a few ideas I’d like to experiment with in a future version.

The first one is a camera. Adding a camera would open up a lot of possibilities; I could use it to take photos directly through the Pip-Boy or even build a proper Fallout-style camera interface around it.

Then there’s Pip-Boy calling. Since the ESP32-C6 gives the device wireless connectivity, it would be interesting to turn the Pip-Boy into an actual communication device and experiment with making calls directly from the wrist.

Another idea I want to experiment with is the ESP32 Marauder. This could turn the Pip-Boy into a portable Wi-Fi and Bluetooth testing device, essentially giving it another completely different mode of operation.

And of course, there are plenty of Pip-Boy features from the games that I’d love to recreate: more menus, interactions, and little details that could make the device feel even more like the real thing.

So while the Pip-Boy AR Mark 6000 is finished for now, I see this more as a starting point than the final version. There’s still a lot of room to experiment, add new features, and make this thing even more capable.

Check out my other Fallout projects.

https://www.instructables.com/VAULT-TEC-AIR-TERMINAL

https://www.instructables.com/PIP-WATCH

https://www.instructables.com/PiP-WATCH-Project/

This is it for now, and I'll be back with a new project real soon. peace!