이번 기말과제에서는 아두이노 센서들을 조합하여 하나의 프로젝트를 완성하는 과제가 주어졌다.
과제를 마무리하면서 그동안 배운 내용을 복습하고 정리할 겸,
Velog에 프로젝트 내용을 기록할 예정이다.
원래는 블루투스를 중점으로 프로젝트를 진행하고 싶었지만 아이폰은 HM-10 모듈을 이용해야하는데 적당한 앱도 없고 쓰기가 너무 번거로워서 포기하기로 했다,,
수업 시간 중 서보모터와 초음파 센서를 조합해 하나의 유닛처럼 작동하는 모습을 보고,
또 가변저항 등 다양한 센서를 활용해 서보모터를 제어하는 과정이 개인적으로 매우 흥미로웠다.
그래서 이러한 요소들을 바탕으로 좀 더 완성도 있게 만들어보고 싶다는 생각이 들었고,
그 결과 이번 과제의 주제를 ‘간이 레이더'로 정하게 되었다.
여기에 추가로 서보모터가 덜덜거리는 현상이 발생하기도 하고
시리얼 값을 꾸준히 일정하게 보내줘야 하는데 전압이 부족하여 노이즈가 발생하고 값도 일정하게 못 보내 줘서 서보모터만 따로 외부전압 6V를 줬다.
별도의 센서에 외부전압을 줄 때에는 반드시 GND를 공유해줘야 한다.
코드는 이때 까지 공부했던 것들 위주 여서 이번에 프로젝트를 진행하면서 새롭게 공부한 코드 위주로 설명을 달 예정이다.
서보모터와 초음파 센서를 제어할 때는 delay()대신 millis() 함수를 사용할 예정이기 때문에,
시간 흐름을 비교하기 위한 이전 시간을 저장하는 변수가 필요하다.
또한 스위치는 토글 방식으로 작동하며,
두 개의 버튼을 이용해 수동모드와 자동모드를 선택할 수 있도록 구성할 것이다.
이 때 현재 어떤 모드가 활성화되어 있는지를 판단하기 위해,
bool 타입의 변수를 사용하여 작동 중인지 여부를 판별하도록 했다.

setup()은 늘 먹던 맛이다.
초음파 센서에서 신호를 보내는 trigPin은 OUTPUT, 신호를 수신하는 echoPin은 INPUT으로 설정하였다.
또한, 브레드보드에 스위치를 연결하여 사용할 예정이기 때문에 별도의 저항을 추가하지 않고, 아두이노 내부 풀업 기능을 활용하여 스위치 입력 핀은 INPUT_PULLUP 모드로 설정했다.

처음에는 거리측정에 delay() 함수를 사용했지만, 이 방식은 loop() 함수 전체를 멈추기 때문에 다른 센서의 시리얼 값 송신까지 함께 중단되는 문제가 발생했다.
따라서 센서마다 millis() 함수를 이용해 비동기적으로 제어하는 방식으로 변경했다.
거리 측정 주기는 약 0.03초(30ms) 간격으로 설정했으며, 직접 여러 차례 테스트해본 결과 이 정도의 주기가 반응성과 안정성면에서 가장 적절했다.
millis()를 이용한 구조는 다음과 같다:
또한, 시리얼 통신을 통해 거리 값을 전송할 때는 ,(쉼표)와 .(온점)을 구분자로 사용하였다.
이는 이후 Processing에서 시리얼 데이터를 파싱하여 시각화할 때 데이터를 정확히 분리하기 위해 필요하며, 그에 맞춰 출력 포맷을 구성하였다.
이번 프로젝트에서는 아두이노가 메인이기 때문에 Processing은 따로 다루지 않을 예정이다.

우선, 현재 버튼의 상태는 digitalRead() 이용해 읽어온다.
버튼은 INPUT_PULLUP 모드로 설정되어 있기 때문에 기본 상태는 HIGH, 버튼을 누르면 LOW가 되는 점에 유의해야 한다.
버튼이 눌렸는지를 감지하기 위해
if (lastButtonState == HIGH && currentButtonState == LOW)
와 같은 조건문을 사용하며, 이 조건이 참일 경우 전역 변수로 선언한 isRunning의 값을 반전(toggle) 시켜 모드 전환이 이루어지도록 구성했다.

이 부분은 자동 모드 동작을 위한 코드이다.
isRunning 변수가 True일 때 자동모드가 작동하도록 구성되어 있으며,
처음에는 for문을 이용해 0도 부터 180도까지 서보 모터를 회전시키려고 했다.
하지만 for문은 반복이 끝날 때까지 빠져나올 수 없기 때문에, 작동 중에 버튼을 눌러도 중간에 정지되지 않는 문제가 발생했다.
이를 해결하기 위해 for문 대신 if문을 사용하고, goingUP이라는 플래그 변수를 통해 회전 방향을 제어하도록 구성했다.

수동 모드는 조이스틱을 이용해 서보 모터를 제어하도록 구성했다. X축보다는 Y축 조작이 직관적이었기 때문에 Y축 값을 읽어오고, 서보 모터는 0~180도 사이의 값만을 갖기 때문에 map() 함수를 사용해 범위를 변환해주었다.
targetAngle = map(yVal, 0, 1023, 0, 180);
targetAngle = constrain(targetAngle, 0, 180);
또한, 예상치 못한 범위 초과를 방지하기 위해 constrain() 함수를 사용해
targetAngle 값을 0~180 범위 내로 제한하였다.
특히 중요한 점은, 자동 모드에서 수동 모드로 전환할 때 조이스틱이 중앙에 고정되어 있어 값이 0에 가까워진다는 것이다.
이 상태에서 바로 서보 모터가 0도로 돌아가면 갑작스러운 동작이 발생할 수 있기 때문에,
이를 방지하기 위해 다음과 같은 로직을 추가했다:
서보 모터가 부드럽게 수동 제어로 전환된다.
if (abs(targetAngle - angle) > 3)
이 조건문은 서보 모터의 불필요한 미세 움직임을 방지하기 위한 로직이다.
처음에는 map()으로 변환된 조이스틱 값을 그대로 서보 모터에 전달했는데,
이 경우 조이스틱을 아주 조금만 움직여도 값이 계속 바뀌어 서보 모터가 떨리듯 반복적으로 움직이는 현상이 발생했다.
이를 해결하기 위해 abs(targetAngle - angle) > 3 조건을 추가했다.
이 조건 덕분에 미세한 변화는 무시되고,
눈에 띌 정도로 조이스틱이 움직였을 때만 서보 모터가 반응하게 되어 보다 안정적이고 부드러운 동작이 가능해진다.

프로세싱은 수업시간에 배운 IDE는 아니라서 따로 추가적으로 보여줬다.
빨간 점이 감지된 물체이다 (시연 영상에서는 내가 손을 직접 댔다.)
이번 프로젝트는 단순한 결과물을 넘어서, 개인적으로 많은 배움과 깨달음이 있었던 시간이었다.
처음부터 아두이노를 배우며 주제를 선정하고,
비록 블로그에는 작성하지 않았지만 HTML과 CSS를 활용해 발표 자료 까지 직접 제작했다.
처음 아이디어를 구상할 때만 해도 크게 어려움이 없을 거라 생각했지만,
막상 실습에 들어가니 예상과는 달리 곳곳에서 막히는 지점이 많았다.
대표적으로 , delay() 함수의 한계부터 부딪혔고,
그동안 배워두기만 했던 millis() 함수가 왜 필요한지를 몸소 느끼게 되었다.
프로젝트를 통해 타이밍 제어의 본질과 millis() 의 중요성을 처음으로 제대로 이해하게 된 것 같다.
또한 외부 전압을 사용하는 경험도 인상 깊었다.
그동안 수업에서는 대부분 USB를 통한 5V 전원만으로도 충분했기 때문에,
정격 전압이나 전류에 대해 깊이 고민할 일이 없었다.
하지만 이번 프로젝트에서는 여러 센서를 조합하면서
서보 모터의 출력 부족 문제가 발생했고, 이를 해결하기 위해
외부 전압(6V)을 별도로 연결해야 했다.
이 과정에서 단순히 전원을 "많이 주면 좋다"는 생각이 아니라,
정격에 맞는 안정적인 전원 공급이 얼마나 중요한지를 알게 되었다.
프론트엔드 측면에서도 배운 점이 많았다.
평소에는 교수님의 과제를 따라 치거나 동일하게 구현하는 방식이 대부분이었기 때문에,
수업을 열심히 듣는 나로서는 기본기를 따라가는 데에는 큰 어려움이 없었다.
하지만 이번에는 내가 만든 유닛을 직접 소개하는 웹 페이지를 구성해야 했고,
그 순간부터 막히기 시작했다.
레이아웃을 어떻게 짤지, <a> 태그를 이용할지,
각 <section> 을 나눠 스크롤 기반 페이지로 구성할지, 컬러 테마는 어떤 톤으로 할지 등,
단순해 보이는 화면 하나를 만드는 데에도 고려할 요소가 엄청 많다.
이 과정에서 평소 좋아하던 기업 웹사이트나 제품 페이지들을 참고하며 방향을 잡아갔다.
최종적으로는 카카오, 토스 등에서 사용하는 한 제품을 소개하기 이점이 많은 스크롤 방식 레이아웃을 선택했고, 시연 영상을 소개하는 구간은 인스타그램 게시물처럼 영상 + 텍스트 구성으로 배치해보았다.
작은 시도였지만, 나름대로 구조적인 웹 페이지를 처음부터 완성시킨 경험이었다.
이번 프로젝트는 1학년 1학기 기말 프로젝트로서
엄청나게 창의적이거나, 남들이 봤을 때 "와~" 할만한 대단한 결과는 아니었을지도 모른다.
하지만 기본에 충실하고, 내가 할 수 있는 선에서 최선을 다하려고 노력했다.
그리고 결과적으로는 내 스스로 높은 만족도를 느낄 수 있는 프로젝트가 되었다.
이제 시작이기도 하고 다음 프로젝트, 다다음 프로젝트에서는 더 높은 완성도와 깊이 있는 내용을 Velog에 기록하며, 나만의 기술 성장 기록을 남기고 싶다.