제12부 실전 프로젝트
12.2 종합 프로젝트 ② 카메라 비전 프로젝트
카메라로 무언가를 "본" 다음, 그 결과로 현실 세계의 무언가를 "움직인다" — MPU의 추론과 MCU의 실시간 GPIO 제어를 한 파이프라인으로 잇는 프로젝트다.
이 장에서는 카메라로 프레임을 받아 객체 탐지 추론을 수행하고, 탐지 결과에 따라 MCU가 서보나 LED 같은 액추에이터를 제어하는 엔드투엔드 예제를 만든다. 카메라 선택(MIPI CSI vs USB 웹캠)과 추론 경로(App Lab Brick vs 직접 실행) 각각에 트레이드오프가 있으므로, 강요 없이 두 방식을 모두 제시한다.
⚠️ 정직성 표기: 이 장은 9.2(One-Click AI/Brick 경유)·9.3(TFLite·ONNX Runtime 직접 호출)·9.4(GPU 직접 접근 커뮤니티 시도)에서 이미 조사·확인한 내용을 그대로 이어받는다. 그 조사에서 드러난 가장 중요한 사실은 — UNO Q에서 Qualcomm의 QNN(NPU/AI 엔진) 가속 경로는 이 책 집필 시점 기준 사실상 동작하지 않는 것으로 보고돼 있다는 점이다(9.2.2, 9.3.4, 9.4). 이 장은 이 사실을 숨기지 않고, "GPU 가속을 켜면 빨라진다"는 식의 낙관적 서술 대신 9.3·9.4이 확인한 그대로를 반영한다. 카메라 배선·전체 파이프라인 결합은 저자가 실물 보드에서 끝까지 실행 검증하지 못했다 — "검증 필요" 라벨을 따라간다.
12.2.1 이 프로젝트가 전제하는 장
- 2.1 두 프로세서 아키텍처 — Adreno 702 GPU·Hexagon DSP가 어느 쪽에 있는지
- 2.2 핀아웃과 GPIO·PWM·아날로그 — 서보·LED 배선, PWM 타이머 공유 주의
- 2.3 고속 인터페이스 — MIPI CSI, JMEDIA1과 캐리어 보드 경유 구조
- 3.4 Bridge — 탐지 결과를 MCU로 넘기는 경로
- 4.3 GPIO·센서 예제 모음 — 액추에이터 제어 기초, PWM 핀 공유 이슈
- 9.1 GPU·DSP 하드웨어 이해 — Adreno 702, Hexagon DSP
- 9.2 One-Click AI로 모델 배포하기 —
ObjectDetection브릭의 실제 코드 - 9.3 TensorFlow Lite·ONNX Runtime GPU 가속 추론 — CPU 기준선과 GPU 가속의 실제 한계
- 9.4 App Lab 없이 GPU 직접 추론하기 — QNN 경로 실패 보고
- 10.1 라즈베리파이 호환 HAT·카메라 활용 — MIPI CSI 카메라를 캐리어 보드 경유로 연결하는 실제 경로(10.1.5·10.1.6)
- 10.3 Qwiic 생태계와 커뮤니티 확장보드 — 카메라 캐리어 보드 커뮤니티 대안 조사(10.3.6)
- 11.1 인클로저 설계 원칙 — 캐리어 보드 스택·방열
- 11.3 마운트·거치대·카메라 마운트 만들기 (3D 프린팅, 집필 순서상 이 장 뒤에 올 수 있다)
12.2.2 무엇을 만드나 — 엔드투엔드 파이프라인
예시 시나리오: 카메라가 사람을 인식하면 팬·틸트 서보로 카메라를 그쪽으로 향하게 하고, LED로 상태를 표시한다.
12.2.3 카메라 선택과 연결 — MIPI CSI vs USB 웹캠
| 기준 | ① MIPI CSI 카메라 (2.3) | ② USB 웹캠 |
|---|---|---|
| 지연·프레임률 | 낮음 — 듀얼 ISP(Spectra 340L)를 거쳐 하드웨어 가속 | 상대적으로 높음 — USB 대역폭·드라이버 오버헤드 |
| 연결 난이도 | 캐리어 보드가 반드시 필요(아래 설명) | USB-A/C에 연결하면 대부분 즉시 동작 |
| 소프트웨어 스택 | libcamera 기반 | v4l2/OpenCV VideoCapture로 표준화돼 있어 자료가 많음 |
| 기계적 통합 | 캐리어 보드+FFC 케이블 부피를 마운트에 반영해야 함(11.1) | 웹캠 본체 크기·무게를 마운트에 반영해야 함 |
| App Lab 공식 예제 기준 | (미확인) | 9.2.5의 정지 이미지 예제는 카메라 종류를 특정하지 않지만, App Lab 자체가 "이미지 모델이면 USB 카메라가 필요"라고 안내한다(9.2.3) |
중요한 정정: 2.3.1에서 이미 바로잡았듯, UNO Q 본체에는 라즈베리파이 카메라를 바로 연결할 수 있는 커넥터가 없다. MIPI CSI 신호는 보드 하단의 JMEDIA1(60핀, GPIO 아님, 1.8V)에 나오며, 여기에 캐리어 보드(공식 UNO Media Carrier, 또는 Camemake Vision Adaptor 같은 커뮤니티 대안)를 장착해야 비로소 라즈베리파이 5 호환 22핀 FPC 커넥터가 나타난다. 즉 실제 경로는:
견해: 처음 시도하거나 결과를 빨리 보고 싶다면 USB 웹캠으로 시작해 파이프라인 전체(추론→Bridge→액추에이터)를 먼저 검증한 뒤, 지연이 문제가 되는 단계에서 캐리어 보드를 구매해 MIPI CSI로 옮겨가는 순서를 권한다 — 캐리어 보드는 별도 예산·조달이 필요한 부품이라는 점을 1.1~1.3(구매 계획)에도 반영해 둔다.
USB 웹캠 프레임 캡처(OpenCV):
import cv2
cap = cv2.VideoCapture(0) # /dev/video0
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
ret, frame = cap.read()
MIPI CSI 프레임 캡처(libcamera, 검증 필요 — 캐리어 보드·드라이버 조합에 따라 절차가 달라질 수 있음):
sudo apt update
sudo apt install libcamera-tools gstreamer1.0-libcamera
libcamera-hello --list-cameras # 카메라 인식 확인
Python에서는 picamera2(libcamera 기반)나 GStreamer 파이프라인을 OpenCV로 받는 방식을 쓴다 — 정확한 패키지명·바인딩은 2.3·10.1에서 실물 보드 기준으로 재검증한다. 특정 카메라 센서(IMX219 등)의 공식 지원 여부는 릴리스마다 바뀔 수 있다는 점도 2.3.2가 이미 지적했다.
12.2.4 추론 경로 선택 — App Lab Brick vs 직접 실행
| 기준 | ① ObjectDetection 브릭 (9.2) | ② 직접 실행 — TFLite/ONNX Runtime (9.3) |
|---|---|---|
| 진입 장벽 | 낮음 — bricks: [arduino:object_detection] 선언 + 몇 줄 | 높음 — 런타임·전처리·후처리 직접 구성 |
| 기본 제공 모델 | YOLOX-Nano 기반 COCO 80종, Lightweight-Face-Detection 등(9.2.2) | 직접 준비한 .tflite/.onnx 중 임의의 파일 |
| 커스텀 모델 학습 | Edge Impulse Studio 연동(9.2.3) | 어떤 프레임워크로 학습했든 변환만 하면 자유 |
| 가속 여부 | App Lab이 내부적으로 처리 — 불투명(9.2.6) | provider를 직접 지정·확인 가능(session.get_providers()) |
| GPU/NPU 가속 실제 상태 | 확인 불가(블랙박스) | CPU가 신뢰할 수 있는 기준선. GPU delegate는 리눅스 비공식 빌드 필요, QNN은 포럼 보고상 초기화 실패(9.3, 9.4) |
| App Lab 의존성 | 있음 | 없음 — SSH 터미널에서 바로 실행 가능 |
① ObjectDetection 브릭 경로 — Arduino 공식 예제 저장소(arduino/app-bricks-examples)의 정지 이미지 객체 탐지 예제를 그대로 옮기면(9.2.5):
from arduino.app_utils import App, Logger
from arduino.app_bricks.object_detection import ObjectDetection
from PIL import Image
import time
CONFIDENCE_THRESHOLD = 0.5
logger = Logger("VisionProject")
object_detection = ObjectDetection() # 모델 미지정 시 UNO Q 기본 모델(YOLOX-Nano 등) 자동 사용
def loop():
frame = capture_frame_as_pil_image() # 12.2.3의 USB/CSI 캡처 코드로 구현
results = object_detection.detect(frame, confidence=CONFIDENCE_THRESHOLD)
if results:
detections = results.get("detection", [])
logger.info(f"Detected {len(detections)} objects")
on_detections(detections) # 12.2.5로 이어짐
time.sleep(0.1)
App.run(user_loop=loop)
app.yaml에는 9.2.5와 같은 방식으로 브릭을 선언한다.
name: Camera Vision Project
icon: 📷
description: Detect objects from a live camera feed and drive pan/tilt servos toward the target.
bricks:
- arduino:object_detection
커스텀 .eim 모델을 쓰려면 Edge Impulse Studio에서 학습한 뒤 App Lab의 AI Models 탭에서 설치하고 Brick 설정에서 선택한다(9.2.3의 전체 절차 참고). 이 경로가 정지 이미지가 아니라 실시간 비디오 프레임에도 그대로 쓰이는지, 그 경우 지연·FPS가 어느 정도인지는 9.5(카메라 비전 예제와 추론 성능 측정)에서 실측한다.
② 직접 실행 경로 — 9.3가 이미 세운 신뢰할 수 있는 기준선은 CPU다. 예를 들어 YOLO 계열 경량 모델을 ONNX로 준비했다면:
import onnxruntime as ort
import numpy as np
import cv2
session = ort.InferenceSession("model.onnx", providers=["CPUExecutionProvider"])
input_name = session.get_inputs()[0].name
def preprocess(frame):
img = cv2.resize(frame, (640, 640))
img = img[:, :, ::-1].transpose(2, 0, 1).astype(np.float32) / 255.0
return np.expand_dims(img, axis=0)
def infer(frame):
outputs = session.run(None, {input_name: preprocess(frame)})
return outputs # 후처리(NMS 등)로 박스·클래스·신뢰도 추출
GPU/NPU 가속을 시도하고 싶다면 반드시 9.3·9.4을 먼저 읽는다. 요약하면:
- TFLite GPU delegate: 공식 문서는 Android·iOS만 다룬다. aarch64 Debian 리눅스에서 쓰려면 TensorFlow를 GPU delegate·OpenCL 지원을 켜서 소스에서 직접 빌드해야 하는 고급·자기 책임 경로다(9.3.2.2).
- ONNX Runtime QNN:
onnxruntime-qnn패키지는 존재하지만, Arduino 포럼에 실제로 보고된 시도(9.4.2)는QNN_BACKEND_ERROR_CANNOT_INITIALIZE오류로 끝났고, 별도 스레드(9.4.3)는libQnnTFLiteDelegate.so같은 QNN 유저랜드 라이브러리 자체가 공식 이미지에 없다고 보고했다. 9.2.2의 공식 모델 매니페스트도hw_acceleration_backend: qnn태그가 붙은 모델을 전부 UNO Q가 아니라 VENTUNO Q 전용으로 등록해 두었다 — 세 근거가 같은 방향을 가리킨다(다만 9.4.4가 강조하듯 이는 정황 증거이지 확정은 아니다). - Mesa Turnip/Rusticl(오픈소스 Vulkan/OpenCL): 드라이버 자체는 동작하는 것으로 보고돼 있으나(9.4.5), 신경망 추론에 실제로 활용한 성공 사례는 이 책 조사로 확인하지 못했다.
따라서 이 프로젝트의 기본값은 CPU 실행이다. GPU/QNN을 시도한다면 9.3.5의 벤치마크 절차(워밍업 제외, 50회 이상 반복, 평균/중앙값/p95 기록)로 CPU 대비 실제 이득을 스스로 측정하고, 실패하면 조용히 CPU로 폴백하도록 providers 리스트에 항상 CPUExecutionProvider를 포함한다.
견해: 처음 만들어보는 프로젝트이거나 표준 탐지(사람·손 등)로 충분하다면 ①이 훨씬 빠르고, 가속 여부를 App Lab에 맡길 수 있다는 점도 부담을 줄인다(그 대가로 내부를 확인할 수 없다는 점은 감수해야 한다). 커스텀 클래스나 지연시간을 직접 통제해야 하면 ②로 가되, "GPU면 당연히 빠르다"는 가정 없이 9.3의 CPU 기준선부터 확보한다.
12.2.5 탐지 결과를 MCU로 — Bridge로 액추에이터 제어
Python(MPU)이 탐지 루프에서 대상의 화면상 위치(중심 좌표)를 계산해 Bridge로 MCU에 팬·틸트 각도를 전달한다.
def on_detections(detections):
if not detections:
return
box = detections[0] # 가장 신뢰도 높은 탐지 하나만 추적한다고 가정 — 실제 필드명은 브릭 응답 스키마 확인 필요
cx, cy = box_center(box)
frame_w, frame_h = 640, 640
pan_angle = int(90 + (cx - frame_w / 2) / (frame_w / 2) * 45)
tilt_angle = int(90 + (cy - frame_h / 2) / (frame_h / 2) * 45)
Bridge.call("set_servo_angles", pan_angle, tilt_angle)
sketch/sketch.ino:
#include <Arduino_RouterBridge.h>
#include <Servo.h> // 검증 필요 — Zephyr 기반 Arduino Core로의 이식 여부
Servo panServo, tiltServo;
const int PAN_PIN = 9; // ~D9, TIM4_CH3(2.2)
const int TILT_PIN = 10; // ~D10, TIM4_CH4(2.2) — PAN_PIN과 같은 타이머(TIM4)를 쓴다, 아래 주의 참고
const int LED_PIN = 4; // D4 — PWM 비지정 핀, 다른 타이머와 충돌 없음(2.2)
bool set_servo_angles(int pan, int tilt) {
panServo.write(constrain(pan, 0, 180));
tiltServo.write(constrain(tilt, 0, 180));
digitalWrite(LED_PIN, HIGH); // 탐지 시 LED 점등으로 상태 표시
return true;
}
void setup() {
Bridge.begin();
Monitor.begin(115200);
panServo.attach(PAN_PIN);
tiltServo.attach(TILT_PIN);
pinMode(LED_PIN, OUTPUT);
Bridge.provide_safe("set_servo_angles", set_servo_angles);
}
void loop() {
// 실시간 제어는 MCU 루프에 맡기고, 고수준 목표(각도)만 MPU에서 내려받는 구조
}
set_servo_angles처럼 하드웨어(서보·GPIO)를 직접 제어하는 콜백은 Bridge.provide_safe()로 등록해 메인 루프가 idle일 때 안전하게 실행되도록 한다(3.4.4). 그 콜백 안에서 Bridge.call()·Monitor.print()·Serial.print()를 부르면 데드락에 빠지므로(3.4.4) 위 코드는 순수 digitalWrite/Servo.write만 쓴다.
⚠️ PWM 타이머 공유 주의: ~D9(TIM4_CH3)와 ~D10(TIM4_CH4)은 같은 STM32 타이머(TIM4)의 서로 다른 채널이다. 4.3.3이 보고한 "한 PWM 핀 활성화가 같은 타이머를 쓰는 다른 핀의 GPIO 동작을 막는" 알려진 이슈는 구체적으로는 D3/D6/D8 조합과 D11/D5/D12/D13 조합에서 보고됐고, D9·D10처럼 애초에 둘 다 정식 PWM 채널로 동시에 쓰는 조합이 같은 문제를 겪는지는 이 책이 확인하지 못했다 — 하나의 타이머가 여러 채널에서 동시에 PWM을 내는 것은 정상적인 하드웨어 동작이므로 원리적으로는 문제없어야 하지만, 실물에서 두 서보를 동시에 움직여 검증하고 이상 동작이 보이면 ArduinoCore-zephyr 0.55.2 이상(4.3.3이 이 문제의 수정 버전으로 보고)으로 갱신했는지부터 확인한다.
12.2.6 성능 측정과 튜닝
- FPS 측정: 캡처~추론~Bridge 호출까지 한 사이클의 시간을
time.perf_counter()로 감싸 측정한다. 9.3.5의 벤치마크 절차(워밍업 제외, 반복, p95 기록)를 그대로 카메라 파이프라인에 적용한다. - Bridge 호출 빈도 제한: 추론이 매 프레임 나오더라도
Bridge.call()을 프레임마다 부르면 MCU-MPU 링크에 불필요한 부하가 걸릴 수 있다 — 값이 일정 이상 바뀌었을 때만 호출하거나 최소 호출 간격을 두는 스로틀링을 권장한다(8.3의 Bridge 지연 실측과 연결). - 입력 해상도 절충: 추론 입력을 낮추면(예: 640×640 → 320×320) FPS는 오르지만 작은 물체 탐지율이 떨어진다 — 9.5에서 더 체계적으로 다룬다.
- 열 상태 기록: 장시간 연속 추론은 SoC 온도를 상승시켜 스로틀링을 유발할 수 있다 —
cat /sys/class/thermal/thermal_zone*/temp로 함께 로깅한다(9.3.5, 11.1.4).
12.2.7 3D 프린팅으로 물리적 설치
카메라(또는 팬·틸트 서보 조립체)를 실제로 고정하려면 11.1의 인클로저 설계 원칙과 11.3의 마운트 설계를 그대로 적용한다.
- MIPI CSI 경로를 쓴다면: 캐리어 보드가 UNO Q 아래에 스택되는 구조라는 점(2.3.1, 12.2.3)을 마운트 설계에 반영해야 한다 — 11.1.2가 이미 언급했듯 "UNO Q 단독 사용 vs 카메라 캐리어 스택"은 인클로저 설계의 분기점이다. 바닥판을 완전히 막지 말고 캐리어 높이만큼 스탠드오프를 추가로 확보한다(11.1.3).
- USB 웹캠 경로를 쓴다면: 웹캠 본체 크기·케이블 인출 방향만 고려하면 되므로 마운트 설계가 훨씬 단순하다.
- 서보를 쓰는 팬·틸트 구조: 서보 혼(horn) 규격에 맞는 체결 구멍을 정확히 설계해야 유격 없이 고정된다.
- 소재: 장시간 추론으로 보드 발열이 있는 인클로저라면 11.1.4의 권고(PETG/ABS/ASA, PLA는 여름철 유리전이온도 근접 주의)를 그대로 따른다.
12.2.8 엣지케이스와 트러블슈팅
- 조도 변화: 실내조명·역광에서 탐지율이 크게 변동한다 — 데이터셋에 다양한 조도 샘플을 포함시키거나(재학습), 카메라 노출 설정을 자동에서 고정으로 바꿔 일관성을 높이는 방법을 검토한다.
- 서보 떨림: 탐지 좌표가 프레임마다 미세하게 변동하면 서보가 계속 미세 진동한다 — 이동평균이나 데드존(각도 변화가 일정 임계값 미만이면 무시)을 Python 쪽에서 적용한다.
- "가속이 되고 있다"는 착각:
providers리스트에 QNN·GPU를 먼저 두고 CPU를 폴백으로 둔 경우, 조용히 CPU로 떨어져도 로그를 확인하지 않으면 가속 중이라고 착각하기 쉽다 —session.get_providers()로 실제 사용 provider를 항상 확인한다(9.3.6). - Bridge 타임아웃: 추론이 느려 콜백 처리가 지연되면
Bridge.call()이 타임아웃될 수 있다 — 부하가 큰 추론은 별도 스레드/프로세스에서 실행하고 Bridge 호출은 소량의 결과 전달에만 쓴다. - 캐리어 보드 조달 지연: MIPI CSI 경로를 택했는데 공식 UNO Media Carrier 재고가 없거나 커뮤니티 대안 보드의 리드타임이 길 수 있다 — 프로젝트 일정에 여유를 두거나 12.2.3의 견해대로 USB 웹캠으로 먼저 진행한다.
12.2.9 확장 아이디어
- 탐지 클래스별로 다른 반응(사람=추적, 특정 물체=경보) 매핑
- 12.1의 대시보드와 결합해 탐지 이력을 시계열로 기록·검색
- 12.3의 이동 로봇에 카메라를 탑재해 "보고 따라가는" 로봇으로 확장(장의 결합은 목차 4 의존관계 참고)
12.2.10 BOM — 자재명세서
이 절은 12.2.1~12.2.9에서 실제로 등장한 부품·모듈만을 대상으로 정리한 자재명세서(BOM)다. 카메라 경로(MIPI CSI vs USB 웹캠, 12.2.3)에 따라 필요한 항목이 갈리므로 구분해 정리한다. 가격은 변동이 크고 지역·환율·판매 채널에 따라 달라지므로, 이 책이 다른 장(1.1, 1.3)에서 시점을 명시해 확인한 가격만 그대로 인용하고 그 외는 확인 필요로 표기한다 — 구매 전 공식 스토어·판매 페이지에서 재확인한다.
12.2.10.1 이미 보유하고 있다고 전제하는 것
12.2.1이 전제하는 장(2.1·2.2 등)에서 다룬, 보드 자체와 최소 동작에 필요한 항목이다.
| 품목 | 참고 장 | 비고 |
|---|---|---|
| UNO Q 보드(2GB 또는 4GB) | 1.1 | 추론을 CPU로 실행하는 것이 이 장의 기본값(12.2.4)이므로 특정 모델을 강제하지 않는다 — 다만 메모리 여유는 4GB 쪽이 낫다는 것이 필자의 견해 |
| USB-C 케이블, 5V/3A 이상 전원(또는 45W PD 어댑터) | 1.3.2 | 최소 동작 필수품 |
| PC 또는 SBC 모드용 모니터·키보드·마우스 | 1.3.4 | App Lab·모델 배포 설정용(9.2) |
12.2.10.2 카메라 — 경로에 따라 갈리는 항목 (12.2.3)
| 품목 | 수량 | 참고 사양/모델 | 참고 장 | 가격대 |
|---|---|---|---|---|
| ① USB 웹캠(UVC 호환) | 1개 | v4l2/OpenCV VideoCapture로 인식되는 표준 UVC 웹캠 — 이 책이 특정 모델을 검증·추천하지는 않음 | 12.2.3 | 확인 필요 — 브랜드·해상도·프레임률에 따라 편차가 큼 |
| ① 전원 공급 USB 허브 | 1개 | USB 웹캠 사용 시 필수 — UNO Q는 USB-C 포트 하나가 전원·데이터를 겸하므로 전원이 없는 허브로는 웹캠에 별도 전력을 대지 못할 수 있다 | 9.5.4 | Arduino USB-C Hub(8-in-1) 공식 $16.34(1.3.5, 확인 시점 2026-08-24) — 서드파티 전원 허브로 대체 가능(확인 필요) |
| ② MIPI CSI 카메라 모듈 | 1개 | 라즈베리파이 호환 22핀 FPC 커넥터, 예: IMX219 계열 — 이 책이 UNO Q에서 특정 센서를 검증하지는 않음 | 12.2.3, 2.3 | 확인 필요 |
| ② 캐리어 보드 | 1개 | JMEDIA1(60핀, 1.8V)을 22핀 FPC 카메라 커넥터로 변환 — MIPI CSI 경로에서는 필수, 공식 Arduino UNO Media Carrier 또는 커뮤니티 대안(Camemake Vision Adaptor, RevLmt/camboard-uno-q 등, 10.3.6) | 12.2.3, 2.3.1, 10.3.6 | 공식 UNO Media Carrier $19.25(1.3.5, 확인 시점 2026-08-24 — 당시 "Coming Soon" 상태였으므로 현재 재고·가격 재확인 필요). 커뮤니티 대안은 별도 확인 필요 |
| ② FFC/FPC 카메라 케이블 | 1개(카메라에 동봉되지 않은 경우) | 22핀, 카메라·캐리어 보드 간 길이에 맞춰 선택 | 12.2.3 | 확인 필요 |
견해(12.2.3과 동일): 처음 시도한다면 ①(USB 웹캠)로 시작해 파이프라인을 검증한 뒤, 지연이 문제가 될 때 ②(MIPI CSI + 캐리어 보드)로 옮기는 편이 조달 리스크(캐리어 보드 리드타임, 12.2.8)를 줄인다.
12.2.10.3 액추에이터·배선 (12.2.5)
| 품목 | 수량 | 참고 사양/모델 | 참고 장 | 가격대 |
|---|---|---|---|---|
| 표준 서보모터(팬·틸트용) | 2개 | 코드는 Servo 라이브러리로 0~180도 각도만 제어(12.2.5) — 이 책이 특정 제품(예: SG90급 소형 서보)을 지정·검증하지는 않음 | 12.2.5 | 확인 필요 |
| LED(상태 표시) | 1개 | D4 핀에 연결, 코드 예시는 저항값을 지정하지 않으므로 실제 배선 시 적정 전류제한 저항을 별도로 계산·추가해야 한다 | 12.2.5 | 소액, 확인 필요 |
| 저항(LED용) | 1개 | LED 순방향 전압·전류에 맞춰 선정 — 코드에 명시되지 않은 실배선 필수 부품 | 12.2.5 | 소액, 확인 필요 |
| 점퍼선/브레드보드 또는 직결 배선 | 필요 수만큼 | 서보·LED를 UNO Q 헤더 핀에 연결 | 12.2.5, 2.2 | 소액, 확인 필요 |
12.2.10.4 3D 프린팅 설치 (12.2.7)
| 품목 | 수량 | 참고 사양/모델 | 참고 장 | 가격대 |
|---|---|---|---|---|
| 3D 프린터 필라멘트 | 필요량 | 11.1.4의 방열 원칙을 그대로 따르면 PETG(유리전이 약 80℃) 또는 ABS/ASA 권장 — PLA(유리전이 55~60℃대)는 보드를 함께 덮는 인클로저라면 여름철 변형 위험이 있으니 주의. 다만 이 프로젝트의 팬·틸트 브래킷처럼 보드 발열원과 직접 맞닿지 않는 구조물이라면 PLA로도 무방할 수 있다는 것이 필자의 견해(확정 아님) | 12.2.7, 11.1.4 | 필라멘트 종류·브랜드에 따라 편차가 큼, 확인 필요 |
| 체결용 나사(서보 혼 고정 등) | 필요 수만큼 | 서보 혼(horn) 규격·마운트 설계에 맞춘 소형 나사 — 서보 제품에 기본 동봉되는 경우가 많음(동봉 여부 확인 필요) | 12.2.7 | 소액, 확인 필요 |
| M3 스탠드오프(보드 마운트) | 필요 수만큼 | 11.1의 인클로저 설계 원칙 적용 시 | 12.2.7, 11.1 | 소액, 확인 필요 |
정직성 노트: 이 절의 가격 항목 대다수가 "확인 필요"인 것은, 카메라·서보·필라멘트가 이 책이 1.1·1.3에서 시점을 명시해 직접 조회한 Arduino 공식 액세서리 목록에 들어있지 않기 때문이다 — 공식 UNO Media Carrier처럼 1.3.5가 확인한 항목만 그 가격을 그대로 인용했고, 나머지는 시중 범용 부품(서보·웹캠·필라멘트)이라 브랜드·사양에 따른 가격 편차를 이 책이 단정할 근거가 없다.