Skip to main content
Summary

이제는 예제가 아니라 문제에서 시작한다

지금까지의 실습은 대부분 정해진 부품과 정해진 코드를 따라 움직였습니다. LED를 켜고, 버튼을 읽고, 센서값을 화면에 표시하고, 모터를 안전하게 제어했습니다. 마지막 단계에서는 순서가 조금 바뀝니다. 먼저 "무엇을 해결할 것인가"를 정하고, 그다음에 필요한 센서와 출력 장치와 코드를 고릅니다.

캡스톤 프로젝트는 거창한 작품을 뜻하지 않습니다. 작지만 끝까지 완성한 장치입니다. 책상 위에서만 한 번 작동하는 회로가 아니라, 전원을 껐다 켜도 다시 동작하고, 값이 조금 흔들려도 오작동하지 않으며, 다른 사람이 봐도 어떻게 만들었는지 이해할 수 있는 프로젝트를 목표로 합니다.

이번 장에서는 세 가지 후보 중 하나를 골라 기획하는 방법을 살펴보겠습니다.

프로젝트입력처리출력
주차 거리 경보기초음파 거리 센서거리에 따라 위험 단계 판단LED, 부저, OLED 또는 LCD
미니 날씨 표시기온습도 센서, 조도 센서온도·습도·밝기 값을 읽고 표시 형식 정리LCD/OLED, 시리얼 출력, Wi-Fi 전송
자동 식물 급수기토양 수분 센서, 버튼건조 기준과 수동 급수 명령 판단펌프, 릴레이 또는 MOSFET, 상태 LED

세 프로젝트 모두 구조는 같습니다. 입력은 상황을 읽고, 처리는 기준에 따라 판단하고, 출력은 사람이 보거나 장치가 움직이는 결과를 만듭니다. 차이는 어떤 문제를 선택했는지뿐입니다.

캡스톤 프로젝트와 다음 단계AI 생성 이미지

요구사항을 먼저 짧은 문장으로 쓴다

부품을 꺼내기 전에 요구사항을 써야 합니다. 요구사항은 "멋지게 만든다"가 아니라 확인 가능한 문장이어야 합니다.

예를 들어 주차 거리 경보기라면 다음처럼 정리할 수 있습니다.

  • 초음파 센서로 앞쪽 물체까지의 거리를 0.2초마다 측정한다.

  • 거리가 50cm보다 멀면 초록 LED를 켠다.

  • 20~50cm이면 노란 LED를 켜고 부저를 천천히 울린다.

  • 20cm보다 가까우면 빨간 LED를 켜고 부저를 빠르게 울린다.

  • 센서값이 비정상일 때는 부저를 끄고 화면에 NO DATA를 표시한다.

자동 식물 급수기도 같은 방식으로 쓸 수 있습니다.

  • 토양 수분값을 1초마다 읽는다.

  • 기준값보다 건조하면 펌프를 3초 동안만 켠다.

  • 한 번 급수한 뒤 30초 동안은 다시 급수하지 않는다.

  • 버튼을 누르면 수동으로 한 번 급수한다.

  • 물통이 비어 있거나 센서값이 이상하면 펌프를 켜지 않는다.

여기서 중요한 문장은 마지막 두 줄입니다. 초보 프로젝트는 "정상일 때"만 생각하기 쉽습니다. 하지만 완성도를 결정하는 것은 비정상 상황입니다. 센서가 빠졌을 때, 값이 튈 때, 전원이 약할 때, 모터가 예상보다 많은 전류를 요구할 때 장치가 안전하게 멈춰야 합니다.

조립 전에 네 가지 문서를 만든다

프로젝트가 복잡해질수록 바로 꽂고 바로 코딩하는 방식은 오히려 느립니다. 선 하나가 잘못되어도 원인을 찾기 어렵기 때문입니다. 조립 전에는 최소한 네 가지를 준비합니다.

1. 회로도

정교한 전자 설계 도면이 아니어도 됩니다. 종이에 손으로 그려도 충분합니다. 단, 전원선과 신호선은 구분해야 합니다.

주차 거리 경보기라면 다음 연결을 먼저 그립니다.

  • HC-SR04 VCC → 5V

  • HC-SR04 GND → GND

  • HC-SR04 TRIG → D9

  • HC-SR04 ECHO → D8

  • 초록 LED 양극 → D3, 음극 → 220Ω 저항 → GND

  • 노란 LED 양극 → D4, 음극 → 220Ω 저항 → GND

  • 빨간 LED 양극 → D5, 음극 → 220Ω 저항 → GND

  • 부저 → D6와 GND

  • OLED 사용 시 SDA/SCL → 보드의 I2C 핀

모터나 펌프가 들어가는 프로젝트라면 더 조심해야 합니다. 아두이노 핀은 모터 전원선이 아닙니다. 펌프는 MOSFET이나 릴레이 모듈로 제어하고, 외부 전원을 쓰며, 필요한 경우 GND를 공통으로 연결합니다. DC 모터나 펌프처럼 코일이 들어간 부품은 전원을 끌 때 역전압이 생길 수 있으므로, 드라이버 모듈의 보호 회로나 플라이백 다이오드도 함께 확인합니다.

2. 핀 배치표

핀 배치표는 나중에 코드를 읽는 사람을 위한 지도입니다.

기능부품아두이노 핀주의점
거리 측정 시작HC-SR04 TRIGD9출력 핀
반사 시간 입력HC-SR04 ECHOD8입력 핀
안전 표시초록 LEDD3저항 필요
주의 표시노란 LEDD4저항 필요
위험 표시빨간 LEDD5저항 필요
경고음부저D6큰 부저는 직접 연결 금지

핀을 표로 만들면 충돌을 빨리 발견할 수 있습니다. 예를 들어 OLED의 I2C 핀과 다른 센서의 핀이 겹치지 않는지, PWM이 필요한 출력에 PWM 가능 핀을 쓰고 있는지 확인할 수 있습니다.

3. 부품 목록

부품 목록에는 이름뿐 아니라 수량과 이유를 적습니다.

부품수량필요한 이유
Arduino Uno 계열 보드1센서 입력과 출력 제어
HC-SR04 초음파 센서1거리 측정
LED 3색각 1거리 단계 표시
220Ω 저항3LED 전류 제한
부저1소리 경고
브레드보드와 점퍼선1세트납땜 전 테스트
USB 데이터 케이블1업로드와 전원 공급

이 목록은 구매용이기도 하지만 점검표이기도 합니다. LED가 켜지지 않을 때 "저항이 필요한가?", "GND가 빠졌는가?", "부저가 능동형인지 수동형인지?"를 확인할 수 있습니다.

4. 코드 구조표

코드도 먼저 나눠 봅니다.

함수역할
readDistance()초음파 센서로 거리 측정
decideLevel()거리를 안전·주의·위험 단계로 분류
updateLeds()단계에 맞게 LED 표시
updateBuzzer()단계에 맞게 부저 패턴 출력
updateDisplay()거리와 상태를 화면에 표시

이렇게 나누면 loop()가 짧아집니다. loop()는 일을 직접 다 하는 곳이 아니라, 필요한 함수를 빠르게 호출하는 흐름표에 가까워집니다.

작동하는 최소 코드에서 시작한다

처음부터 화면, 부저, LED, 통신을 모두 넣지 않습니다. 먼저 센서 하나가 믿을 만한 값을 내는지 확인합니다.

const int trigPin = 9;
const int echoPin = 8;

void setup() {
  Serial.begin(9600);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
}

void loop() {
  long duration;
  float distance;

  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);

  duration = pulseIn(echoPin, HIGH, 30000);

  if (duration == 0) {
    distance = -1;
  } else {
    distance = duration * 0.0343 / 2.0;
  }

  Serial.print("distance: ");
  Serial.println(distance);

  delay(200);
}

이 코드는 완성본이 아닙니다. 센서가 살아 있는지 확인하는 첫 단계입니다. 시리얼 모니터에서 손을 가까이 가져가면 숫자가 줄고, 멀리하면 숫자가 커져야 합니다. -1이 계속 나오면 정해진 시간 안에 반사 신호를 받지 못했다는 뜻이므로 ECHO 연결, TRIG 연결, 전원, GND를 확인합니다. 말도 안 되는 큰 값이 자주 나오면 측정 대상이 너무 멀거나 반사면이 불안정할 수 있습니다.

센서 확인이 끝나면 delay()를 줄이고, 이전 장에서 배운 millis() 구조로 바꿉니다. 최종 프로젝트는 버튼, 화면, 부저가 함께 동작해야 하므로 한 곳에서 오래 멈추면 안 됩니다.

unsigned long lastMeasureTime = 0;
const unsigned long measureInterval = 200;
float distance = -1;

void loop() {
  unsigned long now = millis();

  if (now - lastMeasureTime >= measureInterval) {
    lastMeasureTime = now;
    distance = readDistance();
  }

  int level = decideLevel(distance);
  updateLeds(level);
  updateBuzzer(level, now);
}

여기서 핵심은 "측정 주기"와 "출력 갱신"을 분리하는 것입니다. 센서는 0.2초마다 읽고, 부저 패턴은 더 자주 확인할 수 있습니다. 이렇게 해야 장치가 멈춘 것처럼 보이지 않습니다. 이때 readDistance() 안에서도 pulseIn()에 timeout을 두어야 센서 응답이 없을 때 프로그램이 오래 멈추지 않습니다.

작동 이후의 완성도는 작은 정리에서 나온다

브레드보드에서 한 번 성공했다고 프로젝트가 끝난 것은 아닙니다. 실제 사용에 가까워질수록 다음 작업이 중요합니다.

센서 보정은 기준값을 현실에 맞추는 과정입니다. 토양 수분 센서는 마른 흙과 젖은 흙에서 직접 값을 읽어 기준을 정해야 합니다. 조도 센서는 방, 창가, 손전등 아래에서 값을 비교해야 합니다. 거리 센서는 가까운 거리와 먼 거리에서 실제 자와 비교해 오차를 확인합니다.

전원 안정화도 중요합니다. USB로는 잘 되던 장치가 배터리에서는 리셋될 수 있습니다. 특히 펌프, 서보모터, DC 모터는 순간적으로 큰 전류를 요구합니다. 이때 아두이노가 꺼졌다 켜지거나 센서값이 튀면 코드보다 전원을 먼저 의심해야 합니다.

케이스 배치는 센서 성능에 영향을 줍니다. 초음파 센서는 앞이 막히면 안 되고, 온습도 센서는 보드의 열에 너무 가까우면 실제보다 높은 온도를 읽을 수 있습니다. 토양 수분 센서 선은 물과 닿는 환경을 고려해 흔들리지 않게 고정해야 합니다.

선 정리는 보기 좋은 문제가 아니라 오류를 줄이는 문제입니다. 전원선, GND선, 신호선을 색으로 구분하고, 빠지기 쉬운 점퍼선은 묶어 둡니다. 프로젝트를 옮길 때만 고장 난다면 대부분 선, 커넥터, 전원 접촉 문제입니다.

문제 해결은 하드웨어와 소프트웨어를 나눠서 본다

프로젝트가 안 될 때는 한 번에 모든 것을 바꾸지 않습니다. 증상을 하나씩 좁혀야 합니다.

업로드 오류

먼저 USB 케이블이 데이터 케이블인지 확인합니다. 보드와 포트 선택이 맞는지 확인하고, 시리얼 모니터가 포트를 잡고 있다면 닫은 뒤 다시 업로드합니다. 호환 보드라면 드라이버 문제도 확인합니다. 업로드가 안 되는 상태에서는 회로와 코드를 의심하기보다 컴퓨터와 보드의 연결부터 점검합니다.

센서 무응답

센서값이 계속 0, nan, 또는 고정된 숫자로 나오면 배선을 봅니다. VCC와 GND가 바뀌지 않았는지, 데이터 핀이 코드와 같은지, I2C 장치라면 주소가 맞는지 확인합니다. 그다음 최소 예제 코드로 센서만 테스트합니다. 전체 프로젝트 코드에서만 안 된다면 핀 충돌이나 실행 주기 문제가 원인일 수 있습니다.

값 튐

값이 가끔 크게 튄다면 센서 불량이라고 단정하지 않습니다. 평균값, 이동 평균, 히스테리시스를 적용해 볼 수 있습니다. 히스테리시스는 켜지는 기준과 꺼지는 기준을 조금 다르게 두는 방법입니다. 예를 들어 식물 급수기는 수분값이 400 아래로 내려가면 펌프를 켜고, 480 이상이 되어야 다시 건조 상태를 해제하도록 만들 수 있습니다. 기준 하나만 쓰면 값이 경계 근처에서 흔들릴 때 펌프가 켜졌다 꺼졌다 반복됩니다.

모터 오작동

모터가 돌 때 보드가 리셋되면 전원 부족 가능성이 큽니다. 외부 전원의 전류 용량, GND 공통 연결, 드라이버 방향, 플라이백 다이오드 또는 모듈 보호 회로를 확인합니다. 코드에서는 모터를 계속 켜 두지 않도록 최대 동작 시간을 둡니다. 자동 급수기라면 "건조하면 계속 펌프 켜기"가 아니라 "최대 3초 켜고, 일정 시간 쉬기"가 안전합니다.

공개 튜토리얼은 출발점이지 완성본이 아니다

Arduino Project Hub 같은 사이트에는 다양한 형식의 커뮤니티 프로젝트가 모여 있고, 공개 튜토리얼 사이트에서는 회로도와 코드와 제작 과정을 함께 제공하는 예제를 찾을 수 있습니다12. 이런 자료는 좋은 출발점입니다. 하지만 그대로 복사해 제출하면 자신의 프로젝트가 되기 어렵습니다.

참고할 때는 다음 세 가지를 바꿔 봅니다.

  1. 입력 추가: 버튼, 조도 센서, 토양 수분 센서처럼 상황을 더 잘 읽는 입력을 하나 더한다.

  2. 출력 개선: 단순 LED 대신 OLED 표시, 부저 패턴, 상태 메시지를 추가한다.

  3. 안전 조건 추가: 센서 오류, 통신 끊김, 모터 최대 동작 시간, 수동 정지 버튼을 넣는다.

예를 들어 흔한 자동 식물 급수기 튜토리얼을 참고했다면, 자신만의 기능으로 "마지막 급수 시간 표시", "수동 급수 버튼", "물 부족 경고 LED", "30초 재급수 방지"를 추가할 수 있습니다. 이 변화가 포트폴리오의 핵심입니다.

프로젝트 기록은 다음 순서로 정리하면 좋습니다.

  • 해결하려는 문제

  • 최종 기능 목록

  • 부품 목록과 선택 이유

  • 회로도와 핀 배치표

  • 코드 구조와 핵심 함수 설명

  • 테스트 과정과 실패 기록

  • 완성 사진 또는 동작 영상

  • 참고한 자료와 직접 바꾼 점

실패 기록을 빼지 마세요. 포트폴리오에서 중요한 것은 한 번에 성공했다는 이야기가 아닙니다. 문제가 생겼을 때 어떤 기준으로 원인을 좁혔는지가 더 중요합니다.

다음 단계: 더 크게 만들기보다 더 믿을 만하게 만들기

이 책을 끝낸 뒤 바로 복잡한 로봇이나 클라우드 서비스를 만들 수도 있습니다. 하지만 실력을 빠르게 키우는 방법은 하나의 작은 프로젝트를 더 믿을 만하게 다듬는 것입니다.

주차 거리 경보기라면 케이스를 만들고, 전원을 배터리로 바꾸고, 부저 소리를 상황에 맞게 조절해 보세요. 미니 날씨 표시기라면 하루 동안 값을 기록하고, 화면 갱신 주기를 조절하고, Wi-Fi로 데이터를 보내 보세요. 자동 식물 급수기라면 실제 화분에서 며칠 동안 테스트하며 기준값과 펌프 시간을 조정해 보세요.

아두이노 학습의 마지막 목표는 모든 함수를 외우는 것이 아닙니다. 문제를 입력·처리·출력으로 나누고, 필요한 부품을 고르고, 작은 코드로 검증한 뒤, 오류를 하나씩 줄여 가는 태도를 갖추는 것입니다. 이제 예제를 따라 하는 단계는 지났습니다. 작은 문제 하나를 정하고, 직접 설계하고, 실패 기록까지 남긴다면 그것이 첫 번째 완성 프로젝트입니다.

참고

1Arduino Project Hub

2CircuitDigest Arduino Projects

책 목록

아두이노 학습: 기초 회로부터 IoT 캡스톤까지

전체 목차 보기

이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.

틸노트는 사용자가 AI를 활용해 노트를 쉽게 작성하거나 편집할 수 있는 서비스입니다.

AI 스퀘어 단톡방에 함께해요

AI 활용과 틸노트 사용 팁을 나누는 오픈채팅방입니다. 입장 비밀번호는 tilnote입니다.

참여하기