- ESP32 기반 물리적 집중 타이머 저장소로, ePaper 디스플레이와 로터리 다이얼을 입력 장치로 사용해 포모도로식 작업·휴식 흐름을 구현함
- 코드는 일부 에셋과 폰트가 제거되어 바로 사용할 수는 없지만, 필요하면 자신의 용도에 맞게 수정할 수 있음
- 하드웨어는 ESP32, WaveShare 4.26인치 800x480 e-Paper HAT, KY-040 로터리 인코더, WS2812 LED, USB-C 커넥터, 3D 프린트 케이스, 저항·커패시터로 구성됨
- ePaper는 백라이트가 없어 작업 중 방해를 줄이고, 4.26인치 모델은 부분 새로고침 0.3초를 지원해 새로고침 시 검은색·흰색 깜빡임을 피할 수 있음
- 소프트웨어는 C++와 Arduino 프레임워크, PlatformIO, GxEPD2 라이브러리를 사용하며, 프리셋 선택·LED 알림·휴식 통계·긴 휴식 반복 같은 기능을 제공함
프로젝트 개요
- 이 저장소는 ESP32 기반 집중 타이머를 위한 코드와 설계 자료를 담고 있음
- 입력은 로터리 다이얼을 사용하고, 표시는 ePaper 디스플레이로 처리함
- 저장소의 코드는 일부 에셋과 폰트가 제거되어 즉시 사용 가능한 상태는 아님
- 필요하면 코드를 자신의 요구에 맞게 수정해 사용할 수 있음
- 완성품은 MakerWorld에서도 볼 수 있음
사용 부품
제작 동기와 설계 목표
- 프로젝트는 친구를 위한 집중 타이머를 만드는 목적에서 시작됨
- 제작자는 생산성 기법을 시도하는 것을 좋아하고, 매년 한 번 정도 다른 사람에게 도움이 되는 프로젝트에 약 한 달의 시간을 쓰는 습관이 있음
- BambuLab X1C 3D 프린터를 산 뒤 이를 활용하고 싶었고, 전자공학 견습을 마친 뒤 소프트웨어 엔지니어링으로 전환한 경험 때문에 물리적인 장치를 만들고 싶었음
- 설계 목표는 세 가지였음
- 물리적 장치일 것
- 재미있을 것
- 직관적으로 사용할 수 있을 것
- 기존 프로젝트인 Focus Dial by Salim Benbouziyane 같은 사례가 있었지만, 처음부터 직접 만들고 싶었음
부품 선택 이유
-
ESP32
- 오랜만에 마이크로컨트롤러로 무언가를 만드는 두 번째 시도였고, ESP32에 익숙해 다시 시작하기 편했음
- 디스플레이 지원 여부를 확인하기 위해 사전 조사를 진행함
-
ePaper 디스플레이
- 디스플레이 배선 안내는
docs/display_wiring.md에 있음
- 프로젝트의 주요 목표 중 하나는 장치가 작업 흐름을 방해하지 않는 것이었고, 이를 위해 백라이트 없는 디스플레이를 원했음
- 책상 위에 두고도 읽을 수 있을 만큼 큰 화면이 필요했음
- 여러 WaveShare ePaper 디스플레이를 주문해 사용해 본 뒤 4.26인치 모델을 선택함
- 해상도가 좋음
- 크기가 적절함
- 부분 새로고침을 지원하며, 새로고침 시간은 0.3초임
- 새로고침 중 방해되는 검은색·흰색 깜빡임이 없음
- 처음에는 흑백·빨강 디스플레이를 쓰고 싶었지만, 마음에 든 모델은 새로고침 시간이 16초였고 부분 새로고침을 지원하지 않아 제외됨
- 백라이트가 없기 때문에 책상이 충분히 밝지 않으면 밤에는 화면을 읽기 어렵고, 이를 “버그가 아니라 기능”으로 봄
-
로터리 인코더
- 입력 장치로 다이얼을 쓰는 것이 가장 자연스럽다고 판단함
- 다이얼 입력은 메뉴 설계를 더 복잡하게 만들고, 입력 디바운싱을 제대로 처리해야 함
- CLK와 DT 핀에는 신호를 완화하기 위해 0.1uF 커패시터를 추가함
-
LED
- 초기 반복 버전에는 LED 계획이 없었음
- 백라이트 없는 디스플레이는 집중 시간이 끝났을 때 너무 미묘하게 느껴질 수 있었음
- 알림 수단으로 여러 대안을 시험함
- 버저는 사용자를 놀라게 해 좋지 않은 경험이었음
- 스피커는 시도한 구성에서 잡음과 우는 소리가 많았음
- WS2812 LED는 NeoPixel 라이브러리로 애니메이션을 만들 수 있고 사용이 쉬웠음
- WS2812 LED는 더 많은 출력 핀을 많이 쓰지 않아도 되는 장점이 있었음
- 최종적으로 LED는 여러 상태를 표시하는 데 잘 동작했고, 케이스에는 LED를 더 보기 좋게 만들기 위한 작은 가림막과 확산 레이어를 추가함
케이스와 물리적 설계
- 케이스는 베이스와 뚜껑 두 부분으로 구성됨
- 디스플레이 프레임을 베이스의 일부로 한 번에 출력한 설계 때문에, 출력 중 상단 모서리가 약간 휘어지는 문제가 있었음
- 다이얼을 전면에 둔 선택은 아쉬운 지점이었음
- 출력물과 전자부품이 가벼워 다이얼 스위치를 누르면 장치 전체가 뒤로 밀릴 수 있음
- 바닥에 고무발과 타이어 밸런싱용 웨이트를 추가해 해결함
소프트웨어 구성
- 소프트웨어는 C++ 로 작성되었고 Arduino 프레임워크를 사용함
- 프로젝트 관리는 PlatformIO를 사용함
- 디스플레이는 GxEPD2 라이브러리에 크게 의존함
- 저장소의 코드는 마감 기한 안에 완성하기 위해 복사·붙여넣기와 이전 코드 미정리가 남아 있어 다소 정리되지 않은 상태임
- 일부 코드는 프로젝트 마감에 맞추기 위해 AI, 주로 Claude로 생성됨
- 친구를 위한 프로젝트였기 때문에 이스터에그와 재미 요소도 포함함
- 집중 중 화면에 무작위 사실을 표시하는 기능이 들어 있음
기기 사용 흐름
- 장치가 시작되면 설정을 바꾸거나 프리셋 선택 모드로 들어갈 수 있음
- 프리셋은 세 가지 중 하나를 선택함
- 타이머가 시작되고 시간이 끝나면 LED가 깜빡이며 화면에 메시지가 표시됨
- 사용자는 계속 작업할 수도 있고, 이후 휴식을 시작할 수 있음
- 휴식 중에는 통계를 볼 수 있음
- 기본값 기준 4회마다 더 긴 휴식 시간이 주어짐
개발과 커스터마이징
- 개발에 필요한 도구:
- PlatformIO
- 에셋 재생성을 위한 Python 3.13 이상
- 이미지, 아이콘, 폰트를 준비하려면
generate_assets.py 스크립트를 실행해야 함
- 이미지 크기 조정
- 올바른 형식으로 변환
- 프로젝트에 포함할 C++ 코드 생성
- 실행 예시는 다음과 같음
uv sync
uv run scripts/generate_assets.py
- 프리셋은
src/main.cpp에 정의되어 있음
- 기본 프리셋 예시는 Emails, Coding, Focus임
- Emails: 집중 15분, 휴식 5분, 긴 휴식 15분
- Coding: 집중 45분, 휴식 15분, 긴 휴식 30분, 반복 수 2
- Focus: 집중 25분, 휴식 5분, 긴 휴식 20분
핀 매핑
- KY-040 로터리 인코더:
- WaveShare 4.26인치 흑백 ePaper 디스플레이:
- BUSY: 4
- RST: 16
- DC: 17
- CS: 5
- CLK: 18
- DIN: 23
- WS2812 LED: