메뉴 전체보기

회원메뉴

PIPBOY AR Mark 6000 > 게시판

본문 바로가기

쇼핑몰 검색

NO. 3199
제목 : PIPBOY AR Mark 6000
2026-09-09 10:44

소개: PIPBOY AR Mark 6000


소개: PIPBOY AR Mark 6000


소개: PIPBOY AR Mark 6000


소개: PIPBOY AR Mark 6000


소개: PIPBOY AR Mark 6000


소개: PIPBOY AR Mark 6000


소개: PIPBOY AR Mark 6000


소개: PIPBOY AR Mark 6000


소개: PIPBOY AR Mark 6000


소개: PIPBOY AR Mark 6000


소개: PIPBOY AR Mark 6000


소개: PIPBOY AR Mark 6000


여러분, 안녕하세요. 다시 찾아 주셔서 환영합니다!

다음 제품을 소개합니다: PipBoy AR Mark 6000, 완전히 처음부터 직접 설계하고 제작한 나만의 PipBoy 버전입니다.

게이머라면 Fallout이라는 게임을 들어본 적이 있을 가능성이 높습니다. Fallout은 핵전쟁으로 문명이 초토화된 디스토피아적 미래를 배경으로 하는 포스트 아포칼립스 RPG 시리즈입니다. 게임은 폐허가 된 도시, 돌연변이 생물, 여러 세력, 구세계의 잔재로 가득한 레트로 퓨처리즘 황무지 곳곳에서 펼쳐집니다. 각 게임은 서로 다른 주인공을 따라가며 Fallout 세계관의 서로 다른 지역을 배경으로 하지만, 핵심 설정과 독특한 레트로 퓨처리즘 미학은 대체로 동일하게 유지됩니다.

Fallout 세계관에서 가장 상징적인 기술 중 하나가 PipBoy입니다. 기본적으로 플레이어의 팔에 착용하는 컴퓨터로, 종말 이후 세계의 초대형 Apple Watch 같은 물건입니다.

게임 내내 Pip-Boy는 거의 모든 일에 사용됩니다. 인벤토리를 확인하고, 캐릭터 능력치를 살펴보고, Perk를 관리하고, 지도와 퀘스트를 확인하며, 라디오 방송을 듣는 데까지 활용됩니다.

Fallout 팬으로서 저는 늘 게임 속 기술 중 일부를 직접 만들어 보고 싶었습니다. 이전에는 Fallout에서 영감을 받은 터미널을 만들었으니, 자연스럽게 다음 프로젝트로 Pip-Boy를 제작해 보고 싶었습니다.

하지만 기존 게임 속 Pip-Boy 모델 중 하나를 단순히 재현하고 싶지는 않았습니다. 대신 Pip-Boy를 한눈에 알아볼 수 있게 만드는 디자인 언어와 미학은 유지하면서, 저만의 버전을 설계하고 싶었습니다.

또한 단순히 착용 가능한 소품을 넘어선 결과물을 만들고 싶었습니다. 목표는 게임과 최대한 유사한 사용자 인터페이스를 갖추면서도, 저만의 기능과 아이디어를 더한 완전한 기능의 Pip-Boy를 만드는 것이었습니다.

이 글에서는 초기 하드웨어와 3D 디자인부터 전자 장치, 소프트웨어, 마감, 최종 조립에 이르기까지 전체 제작 과정을 다룹니다.

그럼 제작을 시작해 보겠습니다!




STEP 1. 준비물


이 프로젝트에 필요한 재료는 다음과 같습니다.

  1. Waveshare ESP32 P4 4.3인치 개발 보드
  2. 전원—3.7V 2000mAh Li-ion 셀
  3. 3D 프린트 부품
  4. 슬라이드 스위치
  5. M2 나사
  6. M3 인서트 너트
  7. M3 볼트
  8. M6 너트
  9. M6 손잡이 볼트
  10. 자동차용 퍼티
  11. 사포
  12. 스프레이 페인트
  13. 스프레이 프라이머
  14. 모든 부품 제작용 Hyper PLA 2롤
  15. 인내심과 시간




STEP 2. FALLOUT - PIPBOY


FALLOUT - PIPBOY


FALLOUT - PIPBOY


FALLOUT - PIPBOY


FALLOUT - PIPBOY


FALLOUT - PIPBOY


FALLOUT - PIPBOY


FALLOUT - PIPBOY


Pip-Boy는 Fallout 세계관에 등장하는 가상의 웨어러블 컴퓨터입니다. (손목에 차는 CyberDeck이나 더 크고 두꺼운 Apple Watch와 비슷합니다.) 플레이어 캐릭터의 팔에 착용하며, 황무지를 여행하는 동안 여러 요소를 관리할 수 있도록 돕는 올인원 개인용 컴퓨터 역할을 합니다.

게임과 Pip-Boy 모델에 따라 캐릭터 능력치, 체력과 신체 부위 상태, 인벤토리, Perk, 지도, 퀘스트, 라디오 방송국 및 기타 정보를 표시할 수 있습니다. 본질적으로 플레이어가 자신의 캐릭터와 주변 세계를 조작하기 위한 주요 인터페이스로 작동합니다.

여러 게임을 통해 Pip-Boy 2000, Pip-Boy 3000, Pip-Boy 3000 Mark II, 그리고 Fallout 76에 등장한 Pip-Boy 4.0 등 다양한 버전의 기기를 볼 수 있었습니다. 각 버전은 고유한 디자인과 기능을 갖추고 있지만, 모두 플레이어를 위한 웨어러블 컴퓨터라는 동일한 기본 목적을 수행합니다.

개인적으로 저는 Fallout: New Vegas의 Pip-Boy 3000 외형을 늘 좋아했고, 그것이 이번 프로젝트에 가장 큰 영감을 주었습니다.




STEP 3. 하드웨어- ESP32-P4-WIFI6 4.3인치 개발 보드


하드웨어- ESP32-P4-WIFI6 4.3인치 개발 보드


하드웨어- ESP32-P4-WIFI6 4.3인치 개발 보드


하드웨어- ESP32-P4-WIFI6 4.3인치 개발 보드


주요 하드웨어, 즉 이 프로젝트의 두뇌로는 Waveshare ESP32-P4-WIFI6-Touch-LCD-4.3 개발 보드를 선택했습니다.

이 특정 보드를 선택한 데에는 몇 가지 이유가 있었습니다. 첫 번째는 내장된 4.3인치 480 × 800 정전식 터치스크린으로, Pip-Boy 인터페이스에 거의 완벽했습니다. 디스플레이와 터치 하드웨어가 이미 통합되어 있어 전체적인 설계도 훨씬 간단해졌습니다.

두 번째이자 아마 더 중요한 이유는 ESP32-P4 자체였습니다. ESP32-P4는 Espressif의 고성능 ESP32 칩 중 하나로, 최대 400 MHz로 작동하는 듀얼 코어 RISC-V 프로세서와 AI 및 DSP 명령어 확장, 부동소수점 장치, 전용 멀티미디어 하드웨어, 그리고 제가 기존에 주로 사용하던 ESP32 보드보다 훨씬 강력한 메모리 및 주변 장치 시스템을 갖추고 있습니다.

이 프로젝트에서는 그래픽 요소가 상당한 사용자 인터페이스, 애니메이션, 오디오, 터치 상호작용, 미디어 재생을 Pip-Boy가 처리하도록 하고 싶었기 때문에 이러한 추가 처리 성능이 특히 유용했습니다. 또한 이 보드에는 ESP32-C6 무선 코프로세서가 포함되어 있어 Wi-Fi 6와 Bluetooth 5 기능을 제공합니다.

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

이 보드로 작업하기 쉬웠던 또 다른 이유는 문서였습니다. Waveshare는 하드웨어 정보, 예제, 개발 리소스를 제공하는 전용 Wiki/문서 페이지를 보드별로 운영하고 있습니다. 특히 디스플레이, 터치 인터페이스 및 기타 주변 장치를 파악하는 개발 과정에서 이 자료를 상당히 많이 참고했습니다.

전반적으로 대형 터치스크린, 강력한 ESP32-P4 프로세서, 내장 주변 장치의 조합 덕분에 이 보드는 커스텀 Pip-Boy를 제작하기에 매우 적합했습니다.




STEP 4. WAVSHARE 서비스


WAVSHARE 서비스


WAVSHARE 서비스


이 프로젝트에 사용한 하드웨어를 제공해 주신 Waveshare 에 특별히 감사드립니다. 10.1인치 DSI 화면과 지원 액세서리는 테스트 및 평가를 위한 리뷰용 제품으로 제공되었습니다.

Waveshare는 로보틱스, IoT, 자동화, 교육 및 기타 다양한 분야에서 사용되는 전자 부품, 모듈, 개발 도구를 제공하는 글로벌 선도 기업입니다. 품질, 신뢰성, 지속적인 혁신에 중점을 둔 Waveshare는 전 세계 엔지니어, 디자이너, 취미 개발자 및 메이커들의 신뢰를 얻고 있습니다.

이들의 광범위한 제품군은 디스플레이와 HAT부터 확장 보드 및 임베디드 모듈에 이르기까지 다양하며, 전문 제작과 DIY 프로젝트 모두에서 Waveshare를 가장 먼저 고려할 만한 선택지로 만들어 줍니다.




STEP 5. 코드 설정


코드 설정


이번 제작에 사용한 코드는 다음과 같습니다. 길어 보이지만 로직은 간단합니다.

#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);
}

코드 외에도 4.3" RGB LCD 디스플레이를 구동하기 위해 LovyanGFX 및 LVGL 라이브러리를 사용했습니다. SD 카드에서 이미지를 불러오는 대신 Vault Boy 초상화와 Vault-Tec 로고를 raw C 배열(arnov_portrait.h 및 vault_logo.h)로 변환했습니다. 이 파일들은 플래시 메모리에 직접 저장되므로, 마이크로컨트롤러가 로딩 지연 없이 그래픽을 즉시 렌더링할 수 있습니다. 또한 I2C 핀을 사용해 GT911 정전식 터치 컨트롤러를 연결하여 화면이 입력에 반응하도록 했습니다.

장치의 전원을 켜면 setup 함수가 디스플레이 드라이버를 초기화하고 LVGL 인터페이스를 여러 층으로 구성하기 시작합니다. 화면은 클래식 Pip-Boy 섹션으로 나뉩니다. 상단 바에는 Level과 XP 같은 주요 수치가 표시되고, 중앙 초상화 패널에는 마스코트가 표시되며, 체력 패널에는 HP 및 AP 바가 표시되고, 하단에는 내비게이션 메뉴가 배치됩니다. 밝은 녹색 텍스트에는 0x00FF00, 어두운 배경에는 0x000800과 같은 특정 hex 코드를 사용해 모든 색상을 설정하여 단색 CRT 분위기를 완벽하게 재현했습니다.

UI가 구성되면 장치는 loop() 함수를 계속 실행합니다. 여기서 GT911 컨트롤러를 통해 터치 입력을 확인하여 화면과 상호작용할 수 있습니다. 동시에 millis() 타이머를 사용해 55밀리초마다 반투명한 녹색 선을 초상화 패널 아래로 이동시킵니다. 이 선이 프레임 하단에 닿으면 다시 상단으로 돌아가며, 오래된 터미널 모니터처럼 연속적인 레트로 스캔라인 애니메이션을 만듭니다.

전체 코드: https://github.com/razorArnov/FalloutPipboy

인터페이스가 실행되는 모습을 보여주는 짧은 영상을 첨부했으니, 데모로 확인해 주세요.




STEP 6. 디자인


디자인


디자인


디자인


디자인


디자인


디자인


디자인


이 프로젝트의 디자인을 위해 Fallout: New Vegas에 등장하는 PipBoy 3000에서 많은 영감을 받았습니다. 제 버전도 전반적인 디자인 언어와 레트로 퓨처리스틱한 느낌은 동일하게 유지하고 싶었지만, 원본을 단순히 그대로 복사하고 싶지는 않았습니다.

가장 큰 과제는 디자인을 제 하드웨어에 맞게 조정하는 것이었습니다. 원래 PipBoy에는 비교적 작은 디스플레이가 사용되지만, 제 프로젝트에서는 훨씬 더 큰 디스플레이를 사용합니다. 화면 주변에 원본 Pip-Boy의 비율을 그대로 유지했다면 장치 전체가 불필요하게 커졌을 것입니다. 그래서 원본에서 영감을 얻되, 제 하드웨어에 맞춰 특별히 제작한 자체 버전을 설계했습니다.

가장 눈에 띄는 변화는 중앙의 대형 디스플레이입니다. 그 아래에는 원본 Pip-Boy에서 볼 수 있는 시각적 디테일을 더하기 위해 리브 세트를 추가했습니다. 디스플레이 측면에는 다이얼 같은 그리블도 추가했습니다.

디스플레이가 터치스크린이므로 내비게이션을 위한 물리 버튼이나 로터리 컨트롤은 필요하지 않았습니다. 대신 다이얼처럼 생긴 부분에 메인 전원 스위치 역할을 하는 슬라이드 스위치를 넣었습니다.




STEP 7. 디스플레이 하우징


디스플레이 하우징


디스플레이 하우징


디스플레이 하우징


디스플레이 하우징


디스플레이 하우징은 PipBoy에 좀 더 레트로한 느낌을 주고 싶어서, 오래된 CRT 텔레비전에서 영감을 받은 곡선형 베젤을 사용해 화면 커버를 설계했습니다. 또한 디스플레이 상단 주변에 셰이드를 추가해 오래된 산업 장비의 일부처럼 느껴지도록 했습니다.

셰이드에는 PIPBOY 로고를 고정하는 작은 그리블도 포함되어 있습니다. 나중에 듀얼 컬러 프린팅 기법으로 3D 프린트하여 로고에 대비되는 마감 효과를 줄 수 있도록 별도 부품으로 설계했습니다.

왼쪽에는 Wavshare 디스플레이의 듀얼 Type-C 포트를 위한 액세스 포인트도 모델링하여, 보드 재프로그래밍이나 충전에 사용할 수 있도록 했습니다.




STEP 8. 손목 장착형 디자인


손목 장착형 디자인


손목 장착형 디자인


이 장치는 실제로 손목에 착용하는 용도이므로, 본체가 어떻게 열리고 팔에 맞춰지는지 고려해야 했습니다.

전체 본체는 기본적으로 두 부분으로 나뉩니다. 상부에는 디스플레이와 전자 부품이 들어가고, 하부는 손목을 감싸는 부분을 형성합니다. 측면에서 보면 두 부분은 하나의 원형을 두 조각으로 나눈 듯한 형태를 이룹니다.

이 두 부분을 연결하기 위해 Pip-Boy 측면의 중앙 회전축을 중심으로 힌지 메커니즘을 설계했습니다. 이를 통해 하부가 본체에서 바깥쪽으로 회전할 수 있어 장치를 손목에 착용하기가 더 쉬워집니다.

두 부분을 단단히 연결하기 위해 자동 잠금식 M6 너트 두 개를 사용하는 추가 장착 부품도 두 개 넣었습니다. 이 부품들은 힌지가 움직일 수 있게 하면서도 상부와 하부 사이를 더욱 견고하게 연결해 줍니다.




STEP 9. 외부 그리블


외부 그리블


외부 그리블


외부 그리블


Pip-Boy에 시각적인 디테일을 더하기 위해 커스텀 그리블도 몇 가지 추가했습니다.

전면 프레임에는 제가 다이얼이라고 부르는 별도 부품이 있습니다. 실제로는 장식용일 뿐이지만, 물리적인 컨트롤 다이얼처럼 보이도록 모델링했습니다.

본체의 메인 리브 아래에는 “MODEL 6000” 라벨이 들어간 또 다른 그리블을 추가했습니다. PIPBOY 로고와 마찬가지로 본체와 대비되도록 두 가지 색상으로 출력할 수 있게 별도 부품으로 설계했습니다.

본문이 길어 아래 덧글 1개로 계속됩니다.


원문: https://www.instructables.com/PIPBOY-AR-Mark-6000/

좋아요 0
게시판

본문 계속 1/1




STEP 10. 3D 프린트 부품


3D 프린트 부품


3D 프린트 부품


3D 프린트 부품


3D 프린트 부품


3D 프린트 부품


3D 프린트 부품에는 프로젝트 전체에 Hyper PLA를 사용했습니다. 부품을 여러 색상으로 출력했지만, 이는 제작에 꼭 필요한 조건은 아닙니다. 나중에 바디 필러, 프라이머, 페인트로 부품을 마감할 계획이었기 때문에 당시 사용할 수 있었던 필라멘트 색상을 그냥 사용했습니다. 따라서 필라멘트 색상은 크게 중요하지 않습니다.

모든 부품에는 필요한 곳에 트리 서포트를 사용했습니다. 모델은 Anycubic Kobra S1 Pro에서 0.2 mm 레이어 높이와 25% 인필로 출력했습니다.

최종 부품은 바디 마감 및 도색 과정을 거칠 예정이었기 때문에, 여기서는 프린터에서 바로 완벽한 표면 마감을 얻기보다는 강하고 깔끔한 출력물을 만드는 데 주로 초점을 맞췄습니다.

작은 그리블 디테일을 위해 특수 부품 세 개를 출력했습니다. 하나는 Pip-Boy 로고가 들어간 부품이고, 다른 하나는 Model 6000 라벨이 들어간 부품이며, 세 번째는 Pip-Boy의 다이얼 역할을 하는 부품입니다.

세 부품 모두에 듀얼 컬러 프린팅 기법을 사용했습니다. 각 부품의 바탕은 흰색 PLA로 출력하고, 텍스트와 디테일은 다른 색상으로 출력했습니다.

Pip-Boy 로고와 Model 6000 부품은 흰색 PLA로 출력을 시작한 뒤, 적절한 레이어에서 출력을 일시 정지했습니다. 그런 다음 필라멘트를 검은색 PLA로 교체하고 출력을 재개하여, 부품의 나머지 부분은 흰색으로 유지하면서 글자만 검은색으로 출력되도록 했습니다.

다이얼에도 같은 기법을 사용했지만, 검은색 대신 빨간색 PLA로 교체하여 다이얼 표시를 출력했습니다.

이를 통해 나중에 작은 글자와 다이얼 요소를 따로 칠할 필요 없이, 3D 프린팅 과정에서 대비되는 디테일을 직접 만들 수 있었습니다.




STEP 11. 퍼티 준비 작업


퍼티 준비 작업


퍼티 준비 작업


퍼티 준비 작업


퍼티 준비 작업


퍼티 재료로는 필러와 경화제로 구성된 3M 자동차용 2액형 퍼티를 사용합니다.

경화제 2%를 넣고 필러와 충분히 혼합하면, 출력한 본체의 틈새와 레이어 라인, 기타 결함을 메우는 데 사용할 수 있는 혼합물이 만들어집니다.

퍼티 작업은 도색 전에 거쳐야 하는 중요한 단계입니다. 3D 프린트물에 퍼티를 바른 뒤 표면을 매끄럽게 샌딩하고, 프라이머와 페인트를 적용하면 전혀 3D 프린트물처럼 보이지 않을 정도로 깔끔한 마감이 완성됩니다.




STEP 12. 표면 마감 공정 - 바디 퍼티


표면 마감 공정 - 바디 퍼티


표면 마감 공정 - 바디 퍼티


표면 마감 공정 - 바디 퍼티


표면 마감 공정 - 바디 퍼티


페인트 스크레이퍼로 혼합한 퍼티를 소량 덜어 세 부품 전체에 발랐습니다. 이 단계의 주된 목표는 결합된 부분 사이의 틈을 메우고, 눈에 보이는 레이어 라인이 있는 부분을 덮는 것이었습니다.

퍼티가 레이어 라인과 틈새에 스며들어 표면을 더 고르게 만들어 주며, 이후 프라이머와 페인트를 바르기 전에 샌딩하여 매끄럽게 다듬을 수 있습니다.




STEP 13. 샌딩 공정 재료 및 준비 작업


샌딩 공정 재료 및 준비 작업


샌딩 공정 재료 및 준비 작업


퍼티를 바른 다음 단계는 샌딩입니다. 하지만 시작하기 전에 제대로 준비해야 합니다.

여기서는 주로 두 가지 사포를 사용합니다. 거친 연마에는 100방, 중간 정도의 마감에는 150방을 사용합니다.

사포를 효과적으로 사용하기 위해 샌드페이퍼 홀더를 사용합니다. 샌딩에 매우 유용한 도구입니다. 사포를 띠 모양으로 잘라 홀더에 부착한 뒤 샌딩에 사용합니다. 사포만 사용하는 것보다 더 효과적이고 작업도 잘됩니다.

또한 미세한 먼지 입자를 발생시키는 퍼티 재료를 샌딩하므로, 적절한 필터가 장착된 마스크를 사용합니다.

이 과정은 상당히 지저분해질 수 있으므로 장갑을 착용하는 것도 권장합니다.




STEP 14. 표면 마감 공정 - 샌딩


표면 마감 공정 - 샌딩


표면 마감 공정 - 샌딩


표면 마감 공정 - 샌딩


표면 마감 공정 - 샌딩


이제 제가 프로젝트에서 가장 재미있어하는 부분인 샌딩을 시작합니다.

먼저 세 부품의 윗면을 모두 샌딩한 다음, 퍼티로 메운 부품 사이의 틈을 샌딩합니다. 필렛이 있는 부품의 가장자리도 샌딩합니다.

여기서 목표는 플라스틱 자체를 깎는 것이 아니라 추가로 바른 퍼티를 깎아내는 것입니다. 이렇게 하면 플라스틱 본체는 그대로 유지하면서 과도하게 도포된 퍼티를 제거할 수 있습니다.

이 작업을 통해 레이어 라인 사이의 눈에 보이는 틈을 없애고 표면을 고르게 만들 수 있습니다.




STEP 15. 표면 마감 공정 - 프라이머


표면 마감 공정 - 프라이머


표면 마감 공정 - 프라이머


표면 마감 공정 - 프라이머


표면 마감 공정 - 프라이머


표면 마감 공정 - 프라이머


표면 마감 공정 - 프라이머


표면 마감 공정 - 프라이머


이제 프라이밍 과정입니다. 이 작업은 꽤 오래 걸렸습니다.

도색에서 프라이머는 필수적인 베이스 코트입니다. 페인트가 표면에 더 잘 부착되도록 하고 내구성을 높이며, 추가 보수가 필요한 남은 결함을 드러내기 때문입니다.

여기서는 스프레이 프라이머를 사용했는데, 스프레이 페인트와 비슷하게 작동하지만 베이스 레이어용으로 특별히 설계된 제품입니다.

먼저 본체 전체에 얇고 고르게 도포하여 표면을 조금씩 덮었습니다. 첫 번째 코트를 바른 후 프라이머가 몇 시간 동안 마르도록 두고, 두 번째 코트를 바른 뒤 다시 건조시켰습니다.

마지막으로 세 번째 코트를 적용하여 균일하고 도색에 적합한 표면을 완성했습니다.




STEP 16. 표면 마감 공정 - 페인트(베이스 코트)


표면 마감 공정 - 페인트(베이스 코트)


표면 마감 공정 - 페인트(베이스 코트)


표면 마감 공정 - 페인트(베이스 코트)


표면 마감 공정 - 페인트(베이스 코트)


표면 마감 공정 - 페인트(베이스 코트)


원했던 표면 마감은 메탈릭 실버 느낌이었지만, 실버 스프레이 페인트만으로는 원하는 마감을 얻을 수 없었습니다. 대신 먼저 검은색 베이스 코트를 적용했습니다.

부품에 얇은 코트를 여러 번 분사하고, 다음 코트를 적용하기 전에 각 레이어가 마르도록 했습니다. 이 과정을 반복하여 전체 표면에 검은색 페인트를 약 5~6회 도포했습니다.

검은색 베이스는 다음 단계에서 중요합니다. 도색된 표면 위에 실버 더스트를 적용할 것이기 때문입니다. 이렇게 하면 단순히 은색으로 칠한 플라스틱처럼 보이는 것이 아니라, 실제 금속의 외관과 질감에 가까운 더욱 설득력 있는 메탈릭 마감을 만들 수 있습니다.




STEP 17. 표면 마감 공정 - 페인트(최종 코트)


표면 마감 공정 - 페인트(최종 코트)


표면 마감 공정 - 페인트(최종 코트)


표면 마감 공정 - 페인트(최종 코트)


표면 마감 공정 - 페인트(최종 코트)


표면 마감 공정 - 페인트(최종 코트)


표면 마감 공정 - 페인트(최종 코트)


표면 마감 공정 - 페인트(최종 코트)


표면 마감 공정 - 페인트(최종 코트)


표면 마감 공정 - 페인트(최종 코트)


이제 Pip-Boy에 금속 느낌을 부여하는 단계입니다.

이를 위해 아크릴 실버 더스트 페인트를 사용합니다. 일반 실버 페인트와 달리 붓으로 바를 수 있는 미세한 금속 분말입니다. 3D 프린트 부품의 전체 표면에 실버 더스트를 붓으로 가볍게 발랐습니다.

아래의 검은색 페인트가 미세한 입자가 달라붙을 표면을 제공하고, 남은 더스트는 털어낼 수 있습니다. 그러면 메탈릭 실버 층이 남아 부품이 실제 금속처럼 보이고 느껴지게 됩니다.

작은 greeble 디테일을 포함한 모든 부품에 같은 과정을 반복하여 전체가 동일한 메탈릭 마감을 갖도록 했습니다.

결과가 마음에 든 후에는 취급 중 실버 더스트가 벗겨지지 않도록 해야 했습니다. 이를 위해 아크릴 컨포멀 코팅 스프레이를 사용하여 모든 부품에 두 번 도포했습니다. 이렇게 하면 전체적인 마감을 유지하면서 금속 분말을 제자리에 고정할 수 있습니다.

그 결과 부품이 3D 프린트 플라스틱처럼 보이는 느낌은 훨씬 줄어들고, 오래된 Fallout 시대 하드웨어처럼 보이는 설득력 있는 주철 같은 마감이 완성되었습니다.




STEP 18. greeble 부품 조립


greeble 부품 조립


greeble 부품 조립


greeble 부품 조립


이제 Pip-Boy에 greeble 부품을 장착할 차례입니다.

먼저 다이얼부터 시작합니다. 전면 커버의 지정된 장착 부위에 순간접착제를 소량 바르고 다이얼을 제자리에 배치한 뒤, 접착제가 굳을 때까지 몇 초간 눌러 고정했습니다.

Pip-Boy 로고에도 같은 과정을 따랐습니다. 전면 커버의 장착 위치에 순간접착제를 소량 바른 다음 로고를 배치하고 제자리에 고정했습니다.

마지막으로 메인 본체의 Model 6000 라벨 장착 부위에 순간접착제를 발랐습니다. 라벨을 제 위치에 놓고 접착제가 굳을 때까지 단단히 눌러 주었습니다.

세 개의 greeble 부품을 모두 장착하자 Pip-Boy의 외관이 완성된 소품에 훨씬 가까워지기 시작했습니다.




STEP 19. 웨더링 공정


웨더링 공정


웨더링 공정


웨더링 공정


웨더링 공정


웨더링 공정


웨더링 공정


웨더링 공정


이제 전체 프로젝트에서 제가 가장 좋아하는 작업 중 하나인 웨더링을 시작하겠습니다.

웨더링 작업의 목표는 3D 프린팅 부품이 Fallout 황무지에 지난 200년 동안 방치되어 있었던 것처럼 보이게 만드는 것입니다. 완성된 PipBoy가 녹, 긁힌 자국, 약간의 파티나까지 갖춘 낡고 닳은 금속 외관을 갖기를 원했습니다.

먼저 줄과 사포를 사용해 표면의 페인트 일부를 불규칙하게 제거했습니다. 또한 줄을 사용해 여러 부분에 긁힌 자국, 선, 패인 곳, 더 깊은 절삭 자국을 만들었습니다. 이러한 불완전함은 표면이 완벽하게 제조된 것이 아니라 손상되고 자연스럽게 닳은 것처럼 보이게 합니다.

표면 준비가 끝난 후 녹과 파티나 작업을 진행했습니다. 갈색과 이끼색 아크릴 물감을 사용해 브러시로 본체에 칠했습니다. 그런 다음 스펀지를 사용해 표면 전체에 물감을 펴 바르고 섞었습니다.

물감은 사포질한 부분과 긁힌 자국, 깊게 파인 곳에 자연스럽게 스며들어, 쌓인 녹과 먼지를 연상시키는 어두운 얼룩을 만듭니다. 또한 여러 부분에 이끼색 물감을 더해 오래된 금속 표면에 이끼와 유기물이 자라난 듯한 느낌을 주었습니다.

이 과정을 PipBoy의 주요 세 부분인 전면 프레임, 본체, 하부 핸들 전체에 반복 적용했으며, 각 부위의 웨더링 정도를 달리해 마감이 더욱 자연스럽게 보이도록 했습니다.

전체적인 파티나가 마음에 들자 아크릴 컨포멀 코팅 스프레이를 두 겹 정도 도포해 모든 부분을 밀봉했습니다. 이렇게 하면 웨더링을 보호하고 페인트가 표면에 영구적으로 부착되도록 할 수 있습니다.

완성된 결과물은 Fallout 황무지에서 실제로 200년을 견뎌낸 것처럼 보이는 녹슬고 곰팡이가 핀, 강하게 웨더링된 PipBoy입니다.




STEP 20. 본체 나사 인서트


본체 나사 인서트


본체 나사 인서트


힌지 메커니즘을 조립하기 위해 본체 양쪽에 M3 나사 인서트를 두 개씩 추가했습니다.

온도를 약 150°C로 설정한 인두를 사용해 인서트를 설치했습니다. 먼저 핀셋으로 나사 인서트를 장착 구멍에 맞췄습니다.

그런 다음 가열된 인두 팁으로 인서트를 눌렀습니다. 열과 압력이 함께 작용해 주변 PLA를 부드럽게 만들고, 인서트가 플라스틱 안으로 들어가 부품에 단단히 매립되도록 합니다.

반대쪽에도 같은 과정을 반복해 힌지 어셈블리를 위한 견고한 나사 장착 지점을 만들었습니다.




STEP 21. 전원 스위치 어셈블리


전원 스위치 어셈블리


전원 스위치 어셈블리


전원 스위치 어셈블리


전원 스위치 어셈블리


전원 스위치로는 일반 슬라이드 스위치를 사용하고, 인두로 두 개의 전선을 NC 및 NO 단자에 연결합니다.

다음으로 스위치를 노브 부품 안에 넣고 압입해 고정합니다.

그런 다음 노브 부품을 본체 측면의 제 위치에 놓고 M2 나사 하나로 고정합니다.




STEP 22. 전원 공급원 어셈블리


전원 공급원 어셈블리


전원 공급원 어셈블리


전원 공급원 어셈블리


전원 공급원 어셈블리


전원 공급원 어셈블리


전원 공급원으로는 Pip-Boy의 주 배터리로 사용할 3.7V 2200mAh 18650 Li-ion 셀을 사용합니다.

전원 스위치를 추가하기 위해 배터리의 양극선을 절단하고, 슬라이드 스위치에서 나온 두 전선을 배터리와 JST 커넥터 사이에 납땜했습니다. 이렇게 하면 스위치가 양극 연결부에 직렬로 들어가 전체 장치를 켜고 끌 수 있습니다.

납땜한 연결부를 제대로 절연하고 우발적인 단락을 방지하기 위해 열수축 튜브로 덮었습니다.

다음으로 본체 내부에 배터리를 장착했습니다. 지정된 배터리 장착 부위에 소량의 글루건 접착제를 바르고 18650 셀을 제 위치에 놓았습니다.

남는 전선이 조금 있어서 노브와 배터리 수납부 근처의 여유 공간에 깔끔하게 정리해 넣었습니다.

배터리를 고정하고 배선을 정리했으므로 전원 공급원 어셈블리가 완성되었습니다.




STEP 23. ESP32 P4 개발 보드 및 본체 조립


ESP32 P4 개발 보드 및 본체 조립


ESP32 P4 개발 보드 및 본체 조립


ESP32 P4 개발 보드 및 본체 조립


ESP32 P4 개발 보드 및 본체 조립


다음으로 Li-ion 배터리의 수 JST 커넥터를 Waveshare ESP32-P4 보드의 암 JST 커넥터에 연결합니다.

전원 연결이 완료되면 보드를 Pip-Boy 상부 내부에 배치하고 PCB 장착 스탠드오프를 인클로저의 장착 구멍에 맞춥니다.

모든 부분이 올바르게 정렬되면 후면에서 M2.5 볼트 네 개를 사용해 보드를 고정합니다.




STEP 24. 프레임 및 본체 조립


프레임 및 본체 조립


프레임 및 본체 조립


프레임 및 본체 조립


다음으로 디스플레이 위에 전면 프레임을 배치하고 상부의 장착 지점에 맞춥니다.

제대로 정렬되면 위쪽에서 프레임을 부드럽게 눌러 디스플레이 및 인클로저와 같은 높이로 밀착되도록 합니다.

마지막으로 M2 나사 여덟 개를 사용해 프레임을 상부에 고정하고, 디스플레이 주변에서 프레임이 단단히 고정되었는지 확인합니다.




STEP 25. 폼 패딩


폼 패딩


폼 패딩


폼 패딩


폼 패딩


이 장치는 착용형이므로 장시간 착용해도 편안하도록 Pip-Boy 내부에 패딩을 추가하고 싶었습니다.

패딩에는 가지고 있던 여분의 흡음 폼을 사용했습니다. 패딩을 너무 많이 넣으면 손목 주변이 더 조여지기 때문에, 폼의 두께를 줄이도록 다듬었습니다.

폼을 준비한 후 상부와 하부 안쪽에 글루건 접착제를 바르고 패딩을 조심스럽게 제 위치에 배치했습니다.




STEP 26. 너트 조립


너트 조립


이제 조립 과정에서 또 하나의 중요한 단계입니다. 상부 본체에 M6 너트를 고정할 수 있도록 육각형 슬롯을 설계했습니다.

이 너트는 나중에 손으로 조이는 볼트와 함께 사용해 Pip-Boy 하부를 상부에 고정합니다. 육각형 형태 덕분에 볼트를 조이거나 풀 때 너트가 회전하지 않습니다.

상부 본체의 슬롯에 총 두 개의 M6 너트를 넣어 손목 조임 메커니즘을 위한 나사 장착 지점을 만들었습니다.




STEP 27. 최종 조립


최종 조립


최종 조립


최종 조립


최종 조립


최종 조립


최종 조립


최종 조립


최종 조립에서는 먼저 Pip-Boy의 상부와 하부를 결합합니다. 하부의 장착 구멍을 상부의 힌지 지점에 맞춘 다음 M3 볼트 두 개로 두 부분을 고정했습니다.

다음으로 하부에 장착 플레이트 두 개를 설치했습니다. 각 플레이트를 해당 장착 위치에 맞춘 후 M2 나사 두 개씩으로 고정해 총 네 개의 나사를 사용했습니다.

그런 다음 이 장착 플레이트를 두 개의 손 조임 볼트와 함께 사용해 상부와 하부를 서로 고정합니다. 볼트를 풀면 Pip-Boy를 열어 손목에 착용할 수 있고, 다시 조이면 장치가 제자리에 단단히 고정됩니다.

힌지, 장착 플레이트, 손 조임 장치를 설치하면 조립 과정이 마침내 완료됩니다.




STEP 28. 결과


결과


결과


결과


결과


결과


결과


결과


결과


결과


결과


결과


결과


결과


결과


그리고 이 재미있는 제작의 결과물은 바로 완전히 작동하는 Pip-Boy입니다!

그럼 실제로 어떻게 작동할까요?

먼저 측면에 있는 슬라이드 스위치부터 살펴보겠습니다. 스위치를 전환하면 장치의 전원이 켜지고, Fallout의 “Please Wait” 시작 애니메이션과 함께 배경에서 Fallout: New Vegas 메뉴 음악이 재생됩니다.

약 4초 후 장치는 기본 Status 메뉴로 부팅됩니다. 머리, 팔, 기타 신체 부위의 다양한 사지 상태 표시를 포함해 게임의 캐릭터 상태 인터페이스와 매우 비슷한 레이아웃으로 구성했습니다. 여기서 가장 큰 변화는 Vault Boy 대신 제 이미지를 넣었다는 점입니다.

Status 메뉴에는 작은 숨겨진 기능도 있습니다. 제 이미지를 탭하면 New Vegas 테마, Fallout 3 테마, 파란색 New Vegas 테마의 세 가지 테마를 차례로 전환할 수 있습니다.

인터페이스를 더욱 실감 나게 만들기 위해 클래식 Pip-Boy 상호작용 사운드도 추가했습니다. 어떤 메뉴에서든 무언가를 터치하거나 선택하면, 장치에서 기존 게임의 Pip-Boy에 사용된 것과 같은 삐 소리가 재생됩니다.

작은 세부 요소에 불과하지만, 터치스크린과 상호작용하는 느낌이 실제 Pip-Boy를 사용하는 것에 훨씬 가까워집니다.

디스플레이가 터치스크린이므로 간단히 스와이프해서 다음 메뉴로 이동할 수 있습니다.

두 번째 화면은 Perks 메뉴로, 역시 기존 Pip-Boy 인터페이스에서 영감을 받았습니다. 여기서는 Strength, Charisma, Luck을 비롯한 다양한 캐릭터 능력치를 높이거나 낮출 수 있도록 했습니다.

다음은 Internet Watch입니다. 이 기능은 기존 Pip-Boy와는 조금 다릅니다. 인터넷의 NTP 데이터를 사용해 현재 시간을 가져오고, Fallout에서 영감을 받은 인터페이스로 시간, 날짜, 요일을 표시합니다.

그다음은 Radio 메뉴입니다. 다만 엄밀히 말하면 라디오는 아니고 음악 플레이어입니다. 노래는 SD 카드에 저장되며, 여기서 재생, 일시 정지, 트랙 건너뛰기, 볼륨 조절을 할 수 있습니다. 노래가 재생되는 동안 음악에 맞춰 움직이는 파형 애니메이션도 추가했기 때문에, 전체적으로 실제 Pip-Boy 인터페이스를 사용하는 듯한 느낌이 훨씬 강해집니다.

마지막으로 Map이 있습니다.

이 메뉴를 아마 가장 좋아하는데, 실제 Fallout 지도를 사용하는 대신 제 고향의 지도를 가져와 Fallout: New Vegas의 Mojave 지도와 같은 시각적 스타일과 레이아웃으로 새롭게 디자인했기 때문입니다.

이처럼 캐릭터 능력치와 특성부터 인터넷에 연결된 시계, 음악 플레이어, 커스텀 Fallout 스타일 지도까지, 이 Pip-Boy는 단순한 웨어러블 소품을 훨씬 넘어선 결과물이 되었습니다. Fallout 세계관에서 바로 튀어나온 듯한 느낌을 주도록 인터페이스를 특별히 설계한, 처음부터 직접 만든 완전히 작동하는 장치입니다.




STEP 29. PIPBOY 착용하기


PIPBOY 착용하기


PIPBOY 착용하기


PIPBOY 착용하기


PipBoy를 착용하는 방법은 다음과 같습니다.

먼저 두 개의 손 조임 너트를 제거하면 힌지를 기준으로 하부를 열 수 있습니다. 그런 다음 장치 안에 손을 넣고 손목을 감싸도록 다시 닫습니다.

마지막으로 두 너트를 다시 끼우고 손으로 조여 두 부분을 서로 단단히 고정합니다.

이제 끝입니다. PipBoy가 손목에 단단히 장착되어 사용할 준비가 되었습니다.




STEP 30. 개요


개요


개요


개요


개요


개요


개요


솔직히 말해, 지금까지 작업한 프로젝트 중 가장 재미있는 프로젝트 중 하나였습니다. 저는 Fallout 팬이기 때문에, 게임 속 무언가를 실제로 작동하는 장치로 만들어 볼 수 있어 전체 과정이 더욱 즐거웠습니다.

이 프로젝트에서 특히 좋았던 점은 Pip-Boy의 외형을 똑같이 만드는 데 그치지 않았다는 것입니다. 3D 모델링, 출력, 마감, 전자공학, UI 디자인, 코딩을 모두 경험하면서, 이 장치가 실제로 Fallout 세계관에 존재할 법한 물건처럼 느껴지도록 끊임없이 고민할 수 있었습니다.

물론 과정 중에는 몇 가지 어려운 부분도 있었습니다. 특히 소프트웨어와 UI를 원하는 방식으로 작동시키는 일이 쉽지 않았습니다. 하지만 모든 요소가 하나로 완성되고, 실제로 Pip-Boy를 착용해 조작할 수 있게 되자 그동안의 모든 노력이 보람 있게 느껴졌습니다.

기존 Pip-Boy를 단순히 복사하는 대신 제 버전을 자유롭게 만들 수 있었던 점도 정말 즐거웠습니다. 커스텀 외장과 웨더링부터 UI, 지도, 작은 상호작용 사운드까지, Fallout의 분위기를 유지하면서 제 아이디어를 더할 수 있었습니다.

그리고 솔직히 말하면, 이것이 마지막 버전은 아닐 것 같습니다. 앞으로 실험해 보고 싶은 기능이 이미 많이 있습니다.

Pip-Boy AR Mark 6000은 완성되었지만, 아직 끝났다고 생각하지는 않습니다. 앞으로의 버전에서 실험해 보고 싶은 아이디어가 이미 몇 가지 있습니다.

첫 번째는 카메라입니다. 카메라를 추가하면 다양한 가능성이 열립니다. Pip-Boy를 통해 직접 사진을 찍거나, 그 위에 제대로 된 Fallout 스타일 카메라 인터페이스를 구축할 수도 있습니다.

그다음은 Pip-Boy 통화 기능입니다. ESP32-C6가 장치에 무선 연결 기능을 제공하므로, Pip-Boy를 실제 통신 장치로 바꾸고 손목에서 직접 통화하는 기능을 실험해 보는 것도 흥미로울 것 같습니다.

실험해 보고 싶은 또 다른 아이디어는 ESP32 Marauder입니다. 이를 통해 Pip-Boy를 휴대용 Wi-Fi 및 Bluetooth 테스트 장치로 바꿀 수 있으며, 완전히 다른 작동 모드를 추가할 수 있습니다.

물론 게임 속 Pip-Boy 기능 중에도 재현해 보고 싶은 것이 많습니다. 더 많은 메뉴와 상호작용, 그리고 장치를 실제 제품처럼 느끼게 해 줄 작은 세부 요소들을 추가하고 싶습니다.

따라서 Pip-Boy AR Mark 6000은 일단 완성되었지만, 저는 이것을 최종 버전이라기보다 시작점으로 보고 있습니다. 아직 실험하고 새로운 기능을 추가해 이 장치를 더욱 뛰어난 제품으로 발전시킬 여지가 많습니다.

제가 만든 다른 Fallout 프로젝트도 확인해 보세요.

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

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

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

일단은 여기까지이며, 곧 새로운 프로젝트로 돌아오겠습니다. 평화!

회사명 공방유니언 주소 각 공방 주소 참조
사업자 등록번호 0000 대표 공방유니언 전화 019-60105846 팩스 0000 이메일 gongbangunion@gmail.com
통신판매업신고번호 0000 개인정보관리책임자 공방유니언
Copyright © 2017 공방유니언. All Rights Reserved.