ESP32 AI 피지컬 컴퓨팅 & 로봇 프로젝트

센서로 세상을 느끼고, 모터로 움직이는 나만의 스마트 로봇을 만들어보세요. 기초부터 탄탄하게 시작하는 메이커 교육 가이드입니다.

시작하기

필수 준비물

ESP32 & 확장보드

Wi-Fi와 블루투스가 내장된 30핀 메인 두뇌와 선 연결을 쉽게 해주는 확장보드

LK 37종 센서 & 점퍼선

온도, 소리, 빛 등 다양한 환경을 감지하는 센서 세트와 암-암 케이블

구동 모터 & 모터 드라이버

360도 서보모터 또는 DC 기어드 모터, 그리고 이를 제어할 L298N 등의 드라이버

전원부 및 기구부

18650 배터리(2홀더), 전압강하 모듈, 골판지, 볼캐스터, 글루건 등

ESP32 30핀 기초

주의: ESP32의 신호핀은 3.3V에서 동작합니다. (5V 센서 연결 시 데이터핀 레벨에 주의하세요)

확장보드 사용법

ESP32 30핀 보드를 확장보드(쉴드)에 꽂으면 왼쪽 포트 라인은 S(신호), V(전원), G(그라운드) 순서이고, 오른쪽 포트 라인은 G(그라운드), V(전원), S(신호) 순서입니다. 좌우 방향이 다르므로 꽂기 전에 줄 이름을 먼저 확인하세요!

확장보드 한눈에 보기

왼쪽 S/V/G, 오른쪽 G/V/S 센서 포트

GGND V전원 S신호
왼쪽 포트 라인
번호SVG
1ENSVG
2VPSVG
3VNSVG
4D34SVG
5D35SVG
6D32SVG
7D33SVG
8D25SVG
9D26SVG
10D27SVG
11D14SVG
12D12SVG
13D13SVG
1
2
3
4
5
6
7
8
USB 5V
ESP32 DevKit 30핀 보드 장착 위치
I2C x2 D22 SCL D21 SDA VCC / GND
V열 전압 점퍼
5V 3V3
DC 6.5~16V
오른쪽 포트 라인
번호GVS
14D23GVS
15D22GVS
16TX0GVS
17RX0GVS
18D21GVS
19D19GVS
20D18GVS
21D5GVS
22D17GVS
23D16GVS
24D4GVS
25D0GVS
26D2GVS
27D15GVS
1PWR LED
2USB 5V 입력
3DC 6.5~16V 배럴잭
4I2C 포트 2세트: SCL/SDA/VCC/GND
5왼쪽 S/V/G · 오른쪽 G/V/S 센서 포트
6ESP32 30핀 장착 위치
7별도 5V/3V3 출력핀
8G/V/S V열 5V 또는 3V3 선택 점퍼

SCL / SDA란?

SCL과 SDA는 I2C 통신에 쓰이는 두 신호선입니다. SCL은 장치들이 박자를 맞추는 시계선(Clock), SDA는 실제 데이터를 주고받는 데이터선(Data)입니다. OLED, PCA9685, 일부 센서처럼 I2C 장치는 보통 같은 SCL/SDA 선을 함께 나눠 쓰고, 장치마다 주소가 달라 ESP32가 구분합니다.

ESP32 기본 I2C 연결

  • SDA → GPIO21
  • SCL → GPIO22
  • VCC → 3V3 또는 모듈 규격 전원
  • GND → GND 공통 연결

I2C 모듈 대부분은 풀업 저항이 포함되어 있지만, 긴 배선이나 여러 모듈을 연결할 때는 신호 안정성을 확인하세요.

ESP32 30핀 확장보드 핀 역할표

USB 포트를 위쪽으로 두고 보드를 정면에서 봤을 때의 일반적인 ESP32 DevKit V1 30핀 배열입니다. 제조사마다 실크 인쇄가 조금 다를 수 있으므로 실제 보드에 적힌 핀 이름을 최우선으로 확인하세요.

마이크로파이썬 개발 환경 구축

0단계: 웹 브라우저로 펌웨어 설치 (가장 쉬운 방법)

크롬(Chrome)이나 엣지(Edge) 브라우저를 사용하면 복잡한 프로그램 설치 없이 웹에서 바로 ESP32에 MicroPython 펌웨어를 올릴 수 있습니다.

  1. MicroPython 공식 사이트에서 ESP32용 .bin 펌웨어 파일을 다운로드합니다.
  2. Adafruit WebSerial ESPTool 사이트에 접속합니다.
  3. 우측 상단의 Connect를 누르고 ESP32가 연결된 포트를 선택합니다. (보드에 따라 연결 시 BOOT 버튼을 누르고 있어야 할 수 있습니다)
  4. 파일 선택 창에 다운로드한 .bin 파일을 넣고, Offset 주소를 0x1000으로 설정한 뒤 Program 버튼을 클릭하여 설치를 완료합니다.

1단계 (초보자용): Thonny IDE 코딩

  1. 파이썬 코딩을 위해 Thonny IDE를 다운로드하고 설치합니다.
  2. 우측 하단의 인터프리터 설정에서 MicroPython (ESP32)와 연결된 포트(COM)를 선택합니다.
  3. 코드를 작성하고 상단의 재생(Run) 버튼을 눌러 보드에서 바로 실행합니다.
PRO

고수용: VS Code + mpremote + Type Stub

플러그인의 잦은 연결 오류가 싫고 가벼운 툴을 원한다면, 마이크로파이썬 공식 CLI 툴인 mpremote와 자동 완성용 스텁(Stub) 파일을 함께 쓰는 방법입니다. 확장 프로그램의 동작과 관계없이 ESP32 전용 내부 함수(machine, network 등)의 자동 완성을 지원합니다.

구축 및 사용 방법
  1. PC 터미널 도구 설치:
    pip install mpremote micropython-stubber
  2. VS Code 터미널 명령어 활용:
    • $ mpremote run main.py # 보드에서 즉시 실행
    • $ mpremote cp main.py :main.py # 보드로 파일 복사
  3. micropython-stubber를 통해 빨간 줄(에러 표시)을 줄이고 자동 완성을 사용해 보세요.

배터리 전원 및 회로 설계 가이드

모터를 사용하는 피지컬 컴퓨팅의 핵심은 '전력(전압과 전류)'의 올바른 분배입니다. 안정적인 회로 구성을 위한 필수 지식을 알아봅니다.

1. 18650 2구 배터리와 DC 배럴잭

이 확장보드는 DC 6.5~16V 배럴잭 입력이 있으므로 18650 배터리 2구 홀더(2S)를 배럴잭 플러그에 연결해 전원을 넣으면 됩니다. 2구 직렬 18650은 평소 약 7.4V, 완충 시 약 8.4V라 보드 입력 범위에 맞습니다.

  • 전압(Voltage): 3.7V × 2개 = 7.4V (완충 시 8.4V)
  • 연결: 18650 2구 홀더 → DC 배럴 플러그 → 확장보드 DC 6.5~16V 잭
  • 용량(mAh): mAh는 주로 “얼마나 오래 쓰는가”를 뜻합니다. 다만 같은 종류의 18650이라면 1200mAh보다 3000mAh급이 전류 여유도 더 큰 경우가 많습니다.
  • 전류(Current): 모터가 많거나 무거운 물체를 움직이면 순간 전류가 크게 필요합니다. 전류가 부족하면 ESP32가 재부팅되거나, 서보가 떨리거나, 모터 힘이 약해집니다.
  • 정량 기준: 셀의 연속 방전율이 1C라고 가정하면 1200mAh는 약 1.2A, 3000mAh는 약 3A까지가 대략적인 기준입니다. 모터/서보가 2개 이상이면 순간적으로 2~3A가 필요할 수 있으므로 3000mAh급 또는 연속 방전 5A 이상으로 표기된 18650을 권장합니다.
  • 선택 기준: LED와 센서 중심 실습은 1200mAh도 가능하지만, 360도 서보 1개 이상 또는 DC 모터 2개 이상을 쓰는 프로젝트는 3000mAh급을 기본으로 준비합니다. 가능하면 같은 용량/같은 종류의 배터리 2개를 한 세트로 사용합니다.
  • 주의: 극성(+/-)을 반드시 확인하고, 가급적 보호회로(PCM)가 있는 배터리와 스위치 달린 홀더를 사용합니다.

2. 확장보드 5V/3.3V 점퍼

배럴잭으로 들어온 7.4V 배터리 전원은 확장보드에서 5V/3.3V로 변환해 G/V/S의 V열에 공급할 수 있습니다. 이 점퍼는 G/V/S 전체 V열 전압을 한 번에 바꾸므로, 서보와 센서를 동시에 쓸 때는 어떤 부품이 V열을 함께 쓰는지 먼저 정해야 합니다.

  • 서보만 사용: D13의 G/V/S에 꽂을 때 V열 점퍼를 5V로 선택합니다.
  • 센서만 사용: 3.3V 센서가 많다면 V열 점퍼를 3.3V로 두는 것이 가장 안전합니다.
  • 서보 + 센서 동시 사용: 수업 기본 구성은 점퍼를 5V로 두고 서보는 D13 G/V/S에 꽂습니다. 센서는 5V 구동이 가능한 모듈만 G/V/S에 꽂고, 3.3V 전용 센서는 G/V/S의 V핀에 꽂지 말고 별도 3.3V 출력핀을 사용합니다.
  • 신호 전압 주의: ESP32 신호핀은 3.3V 기준입니다. 5V로 동작하는 센서의 OUT/S 신호가 5V로 나오는 모듈은 레벨 변환을 사용하거나 3.3V로 구동합니다.
  • 5V 아날로그 센서: 조이스틱처럼 VCC가 5V인 아날로그 모듈은 전원은 5V로 쓰고, VRx/VRy/AO 신호는 저항 분압으로 3.3V 이하로 낮춘 뒤 ESP32 ADC에 연결합니다.
  • 용량 한계: 서보가 여러 개이거나 힘을 많이 쓰면 전류가 부족할 수 있으므로 3000mAh급 또는 연속 방전 전류가 높은 18650을 사용하고, 한 번에 구동하는 모터 수를 줄입니다.

3. 배럴잭 전원 흐름

이 수업 구성에서는 18650 2구 배터리를 DC 배럴잭에 연결하고, 확장보드 점퍼로 G/V/S의 V열 전압을 선택합니다. G/V/S의 G열은 보드 안에서 이미 GND로 연결되어 있으므로, 서보와 센서는 각 핀 줄의 G, V, S 방향만 맞춰 꽂으면 됩니다.

# 배럴잭 전원 입력

18650 2구(7.4V) -> DC 배럴잭(6.5~16V)

점퍼 5V 선택 -> G/V/S의 V열 -> 360도 서보

점퍼 3.3V 선택 -> G/V/S의 V열 -> 3.3V 센서

각종 센서 및 부품 설명

ESP32를 활용하여 서보모터, DC 모터를 포함한 다양한 센서와 부품을 제어하는 방법을 알아봅니다. (클릭하여 확인)

응용 예제

센서 입력과 모터 출력을 함께 사용해 작은 조종 시스템을 만들어 봅니다.

응용 구성: 조이스틱 아날로그 입력 + 360도 무한회전 서보 2개 PWM 제어

360도 무한회전 서보는 각도를 정하는 모터가 아니라 속도와 방향을 정하는 모터입니다. 조이스틱이 가운데에 있으면 두 서보가 멈추고, 레버를 앞으로/뒤로 밀면 회전 방향이 바뀌며, 많이 기울일수록 더 빠르게 회전합니다. X축은 좌우 회전, Y축은 전진/후진 속도로 섞어 작은 2바퀴 로봇처럼 움직입니다.

동작 원리: 조이스틱 중립값을 시작할 때 자동으로 보정합니다. 중립 근처의 작은 흔들림은 데드존으로 무시해 서보가 멈추고, 레버가 중립에서 멀어질수록 -100~100 속도값이 커집니다.

추천 핀 연결

18650 2구 홀더
DC 배럴잭(6.5~16V)
확장보드 V열 점퍼
5V 선택
왼쪽 서보 S
D13 S핀(GPIO13)
오른쪽 서보 S
D14 S핀(GPIO14)
조이스틱 VCC
5V 출력
조이스틱 GND
GND/G핀
조이스틱 VRx
D34 S핀(GPIO34)
조이스틱 VRy
D35 S핀(GPIO35)
조이스틱 SW
D32 S핀(GPIO32)
점퍼 주의: 서보 때문에 V열 점퍼는 5V로 둡니다. 조이스틱도 5V 전원을 사용하되, VRx/VRy는 5V까지 올라갈 수 있으므로 저항 분압이나 레벨 변환을 거쳐 ESP32 ADC에 3.3V 이하로 입력해야 합니다.
main.py
from machine import ADC, Pin, PWM
import time

# 360도 무한회전 서보 2개
left_servo = PWM(Pin(13), freq=50)   # D13 S핀
right_servo = PWM(Pin(14), freq=50)  # D14 S핀

# 조이스틱: VCC는 5V, VRx/VRy는 저항 분압 후 ESP32 ADC로 입력
joy_x = ADC(Pin(34))  # VRx
joy_y = ADC(Pin(35))  # VRy
joy_sw = Pin(32, Pin.IN, Pin.PULL_UP)

for adc in (joy_x, joy_y):
    adc.atten(ADC.ATTN_11DB)
    adc.width(ADC.WIDTH_12BIT)

# 서보마다 정지값이 조금 다릅니다. 중립에서 움직이면 75~78 사이에서 조정하세요.
LEFT_STOP = 77
RIGHT_STOP = 77

MIN_DUTY = 40
MAX_DUTY = 115

# 조이스틱 중립 근처 흔들림을 무시하는 범위입니다.
RAW_DEAD_ZONE = 180
CENTER_SAMPLES = 30

def clamp(value, low=-100, high=100):
    return max(low, min(high, value))

def read_center(adc, samples=CENTER_SAMPLES):
    total = 0
    for _ in range(samples):
        total += adc.read()
        time.sleep_ms(10)
    return total // samples

def axis_to_speed(raw, center):
    """
    조이스틱 ADC 값을 -100~100 속도값으로 변환합니다.
    중립이면 0, 한쪽으로 밀면 양수, 반대쪽으로 밀면 음수가 됩니다.
    """
    delta = raw - center

    if abs(delta) < RAW_DEAD_ZONE:
        return 0

    if delta > 0:
        span = max(1, 4095 - center)
    else:
        span = max(1, center)

    speed = int(delta / span * 100)
    return clamp(speed)

def set_servo(servo, speed, stop_duty):
    """
    speed: -100(역방향 최대) ~ 0(정지) ~ 100(정방향 최대)
    """
    speed = clamp(speed)

    if speed == 0:
        duty = stop_duty
    elif speed > 0:
        duty = int(stop_duty + (MAX_DUTY - stop_duty) * speed / 100)
    else:
        duty = int(stop_duty - (stop_duty - MIN_DUTY) * abs(speed) / 100)

    servo.duty(duty)

def stop_all():
    set_servo(left_servo, 0, LEFT_STOP)
    set_servo(right_servo, 0, RIGHT_STOP)

print("조이스틱을 가운데에 놓고 기다리세요.")
center_x = read_center(joy_x)
center_y = read_center(joy_y)
print("중립값:", "x =", center_x, "y =", center_y)

stop_all()
time.sleep(1)

try:
    while True:
        turn = axis_to_speed(joy_x.read(), center_x)
        drive = -axis_to_speed(joy_y.read(), center_y)  # 방향이 반대면 -를 제거하세요.

        # 버튼을 누르면 즉시 정지
        if joy_sw.value() == 0:
            stop_all()
            time.sleep(0.1)
            continue

        # 중립이면 drive=0, turn=0이 되어 두 서보가 멈춥니다.
        # 레버를 많이 기울일수록 speed 절댓값이 커져 더 빠르게 회전합니다.
        left_speed = clamp(drive + turn)
        right_speed = clamp(drive - turn)

        # 오른쪽 서보가 왼쪽과 마주 보는 방향으로 붙어 있으면 부호를 반대로 줍니다.
        set_servo(left_servo, left_speed, LEFT_STOP)
        set_servo(right_servo, -right_speed, RIGHT_STOP)

        print("turn:", turn, "drive:", drive, "left:", left_speed, "right:", right_speed)
        time.sleep(0.05)

except KeyboardInterrupt:
    pass

finally:
    stop_all()
    left_servo.deinit()
    right_servo.deinit()

과학 실험 응용 아이디어

현재 센서 목록만으로 만들 수 있는 간단한 측정 장치 예시입니다. 값은 CSV로 저장하거나 시리얼 플로터로 관찰하면 탐구 보고서 자료로 바로 쓸 수 있습니다.

물체 운동 속도 측정기

포토 인터럽터 2개를 일정 거리로 놓고 물체가 첫 번째와 두 번째 빛길을 가리는 시간을 재서 평균 속도를 계산합니다.

사용 센서
포토 인터럽터 2개, 부저 또는 2색 LED
측정값
통과 시간, 평균 속도, 반복 실험 편차

진자 주기 측정기

진자가 중앙을 지날 때 포토 인터럽터가 신호를 만들도록 설치하고, 연속 통과 시간 차이로 주기를 구합니다.

사용 센서
포토 인터럽터, 조이스틱 또는 버튼, OLED/I2C 표시 장치 선택
연계 개념
주기, 진폭, 감쇠, 중력가속도 추정

용액 탁도·색 변화 관찰기

LED 또는 레이저를 용액 뒤에서 비추고 조도 센서로 통과한 빛을 읽어 탁도 변화나 색 변화 속도를 비교합니다.

사용 센서
조도 센서, 레이저 모듈 또는 RGB LED, 아날로그 입력
연계 분야
화학 반응 속도, 침전 반응, 간이 흡광도 비교

발열·흡열 반응 기록기

반응 전후 온도 변화를 일정 간격으로 기록해 냉각 곡선이나 반응열 차이를 비교합니다.

사용 센서
아날로그 온도 센서 또는 DS18B20, DHT11 보조 기록
측정값
최고 온도, 온도 상승 속도, 냉각 시간

광합성 환경 비교 장치

빛의 세기와 온습도를 함께 기록하고, LED 색이나 조도 조건을 바꿔 식물 실험 환경을 비교합니다.

사용 센서
조도 센서, DHT11, RGB LED, 릴레이 모듈
연계 분야
생물학, 생태 환경, 데이터 기반 식물 관찰

효모 발효 활동 모니터

발효 용기 주변 온습도를 기록하고, 투명 튜브를 지나는 기포를 포토 인터럽터로 세어 발효 속도를 비교합니다.

사용 센서
DHT11, 포토 인터럽터 또는 IR 장애물 감지 센서
측정값
분당 기포 수, 온도 변화, 조건별 발효 속도

반응 시간 측정기

LED가 켜진 순간부터 터치 센서나 버튼을 누르기까지의 시간을 재서 시각 자극 반응 시간을 비교합니다.

사용 센서
터치 센서, 택트 스위치, RGB LED, 능동 부저
연계 분야
생명과학, 신경계 반응, 통계적 평균과 분산

증발·건조 조건 비교 장치

온습도와 조도를 기록하면서 팬이나 조명 조건을 바꿔 물의 증발 또는 표본 건조 속도 차이를 비교합니다.

사용 센서
DHT11, 조도 센서, 릴레이 모듈, 팬
연계 분야
화학, 지구과학, 생물 표본 관리

최종 융합 프로젝트

지금까지 배운 센서와 모터를 결합하여 현실의 문제를 해결하는 AI 피지컬 컴퓨팅 시스템을 구축합니다.

Track 1: AI 과학실험

데이터 수집 및 자동화 환경 제어 시스템. 예: '스마트 온실' 또는 '미니 기상 관측소'

핵심 센서 및 부품

DHT11(온습도), 조도 센서, 아날로그 토양수분 센서, 릴레이 모듈, 워터 펌프, 쿨링팬

알고리즘(동작 원리)

1. 센서가 온도와 흙의 수분량을 주기적으로 측정.
2. 수분량이 기준치 이하로 떨어지면 ESP32가 릴레이를 통해 워터 펌프를 작동시켜 물을 공급.
3. 온도가 높으면 팬을 돌려 온도를 낮추고, 수집된 데이터를 웹이나 스마트폰으로 전송.

Track 2: AI 자율주행 로봇

환경을 인지하고 스스로 주행 경로를 결정하는 모빌리티. 예: '장애물 회피 라인트레이서'

핵심 센서 및 부품

DC 기어드 모터 2개, 모터 드라이버(L298N), 트래킹(적외선) 센서 2개, 초음파 거리 센서

알고리즘(동작 원리)

1. 트래킹 센서가 바닥의 검은색 라인을 감지하여 모터의 좌/우 PWM 속도를 조절해 선을 따라감.
2. 전방 초음파 센서로 물체와의 거리를 계속 측정.
3. 거리가 15cm 이내로 가까워지면 즉시 후진 후 우회전하여 장애물을 회피한 뒤 라인 복귀.