반사, 인지, 그리고 사고
Source: Dev.to
Overview
이전 게시물에서는 기본—LED를 깜빡이게 하고 배선을 이해하는—을 다뤘습니다. 이번 글에서는 드로이드가 실제로 작동하기 위해 필요로 하는 사항을 확장하여 Reflex Layer(Arduino 프로토타이핑)와 Cognition Layer(컴퓨터 비전 및 로컬 AI)에 초점을 맞춥니다.
Reflex Layer: Arduino 프로토타이핑
시각적 오도미터
나는 부호가 있는 char의 4비트를 나타내기 위해 네 개의 LED를 사용해 시각적 오도미터를 만들었다. 카운터를 120(1바이트 부호 있는 정수의 127 한계에 가깝게)부터 시작했기 때문에 오도미터가 오버플로우되는 순간을 직접 볼 수 있었다:
- 128이 되면 LED가 ‑128로 전환되고, Serial Monitor에 음수 거리값이 표시되었습니다.
- 교훈: 센서 값에 적절한 데이터 타입을 선택하지 않으면, 제한에 도달했을 때 로봇이 뒤로 움직이는 것으로 인식합니다.
포토레지스터로 걸음 시뮬레이션
아직 움직이는 섀시가 없었기 때문에 포토레지스터를 이용해 “걸음”을 시뮬레이션했다. 휴대폰 불빛을 한 번 깜빡일 때마다 Arduino가 이를 한 걸음으로 인식했다. 추가 LED가 감지된 빛에 따라 색을 바꾸어 즉각적인 시각 피드백을 제공했다.
피타고라스 정리를 이용한 거리 계산
피타고라스 정리
[ a^2 + b^2 = h^2 ]
를 사용해 시작점으로부터의 직선 거리를 계산했다. Serial Plotter는 계단식 (X)와 (Y) 좌표를 표시하면서, 계산된 빗변은 부드러운 곡선으로 그려졌다.
#include
// ... logic to detect light pulse ...
if (sensorValue < 400 && !triggered) {
xPos += 5;
yPos += 3;
// h = sqrt(x^2 + y^2)
hypotenuse = sqrt(pow(xPos, 2) + pow(yPos, 2));
triggered = true;
}
모터와 서보의 난관
오도미터가 정상 작동한 뒤, 이동 거리에 따라 모터를 회전시키는 하드웨어를 추가하려고 시도했다. Arduino 모터 쉴드는 쉽게 설치했지만, Geek 서보를 연결하는 과정은 혼란스러웠다:
- LED는 켤 수 있었지만 서보는 회전하지 않았습니다.
- 서보는 본질적으로 외부 전원이 필요한 모터입니다.
- LEGO 호환 서보는 올바른 전압 및 그라운드 연결이 이루어져야 움직입니다.
이러한 도전 과제들은 다음 뇌 레이어를 탐구하도록 만들었습니다.
Source: …
인지 레이어: Raspberry Pi 5 + Vision AI
“고성능” 뇌 설정하기
CanaKit 키트에서 Raspberry Pi 5를 조립했습니다(빠른 설정, 패키지 업데이트). 하드웨어가 준비되자 바로 엣지 AI로 넘어갔습니다.
카메라와 로컬 비전 언어 모델
- ELP 2.0 Megapixel USB 카메라를 연결했습니다.
- Ollama를 설치하고 로컬 Vision Language Model
openbmb/minicpm-v4.5를 가져왔습니다. - OpenCV를 사용해 프레임을 캡처하고 모델에 전달하는 파이썬 스크립트를 작성했습니다.
샘플 출력
DROID SAYS:
Observing: A human with glasses and purple attire occupies the center of an indoor space;
ceiling fan whirs above while wall decor and doorframes frame background elements—a truly multifaceted environment!
단일 프레임을 처리하는 데 약 3분이 걸렸습니다—느리지만, 드로이드는 실제로 주변을 “생각”하고 있습니다.
카메라와 AI 사이의 브리지
import cv2
import ollama
import os
import time
def capture_and_analyze():
# Initialize USB Camera
cam = cv2.VideoCapture(0)
if not cam.isOpened():
print("Error: Could not access /dev/video0. Check USB connection.")
return
print("--- Droid Vision Active ---")
# Warm-up: Skip a few frames so the auto-exposure adjusts
for _ in range(5):
cam.read()
time.sleep(0.1)
ret, frame = cam.read()
if ret:
img_path = 'droid_snapshot.jpg'
cv2.imwrite(img_path, frame)
print("Image captured! Sending to MiniCPM-V-4.5...")
try:
# Querying the local Ollama model
response = ollama.chat(
model='openbmb/minicpm-v:4.5',
messages=[{
'role': 'user',
'content': 'Act as a helpful LEGO droid. Describe what you see in one short, robotic sentence.',
'images': [img_path]
}]
)
print("\nDROID SAYS:", response['message']['content'])
except Exception as e:
print(f"Ollama Error: {e}")
# Clean up the photo after analysis
if os.path.exists(img_path):
os.remove(img_path)
else:
print("Error: Could not grab a frame.")
cam.release()
if __name__ == "__main__":
capture_and_analyze()
다음 단계
- Motor Integration: 서보 모터의 전원 공급 배선을 해결하고 실제 움직임을 테스트합니다.
- Speeding Up Vision: 더 작고 빠른 모델(예: OpenCV 얼굴 인식, 양자화된 VLM)로 실험하여 3분짜리 추론 시간을 줄입니다.
- Layer Fusion: 반사적 움직임 제어와 인지적 인식을 결합하여 드로이드가 시각적 신호에 실시간으로 반응하도록 합니다.