반사, 인지, 그리고 사고

발행: (2026년 1월 7일 오후 04:55 GMT+9)
6 min read
원문: Dev.to

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: 반사적 움직임 제어와 인지적 인식을 결합하여 드로이드가 시각적 신호에 실시간으로 반응하도록 합니다.
Back to Blog

관련 글

더 보기 »

기술은 구원자가 아니라 촉진자다

왜 사고의 명확성이 사용하는 도구보다 더 중요한가? Technology는 종종 마법 스위치처럼 취급된다—켜기만 하면 모든 것이 개선된다. 새로운 software, ...

에이전틱 코딩에 입문하기

Copilot Agent와의 경험 나는 주로 GitHub Copilot을 사용해 인라인 편집과 PR 리뷰를 수행했으며, 대부분의 사고는 내 머리로 했습니다. 최근 나는 t...