AI IoT 엣지 디바이스 메이커 교재

아두이노의 디지털 출력과 액추에이터 제어 원리를 이해하고, 인공지능 비전 모델의 인식 결과를 실제 하드웨어 동작과 연결하는 방법을 학습합니다.

하드웨어 표준 포트 설계 표준안

실습 중 포트 충돌과 오배선을 줄이기 위해 사용하는 로보그램 교육용 표준 하드웨어 연결 규격입니다.

하드웨어 컴포넌트 아두이노 우노 지정 디지털 핀 제어 명령 사용 값
LED 모듈 디지털 11번 포트 (Digital 11) "value" "HIGH" (5V 점등) / "LOW" (0V 소등)
피에조 부저 (Buzzer) 디지털 5번 포트 (Digital 5) "tone" 주파수 값 (단위: Hz)
서보 모터 (Servo) 디지털 9번 포트 (Digital 9) "servo" "181" (시동) / "182" (보호), 각도 신호(0~180)

실습 전 꼭 확인하기

코드 복사: 노트북 웹페이지에서 코드 복사 버튼을 누른 다음, 라즈베리파이의 지니 코딩창을 클릭하고 Ctrl + V로 붙여넣습니다. 최신 Clipboard API가 동작하지 않는 환경에서도 사용할 수 있도록 호환 복사 기능을 함께 적용했습니다.
이 교재의 표준 포트: LED는 11번, 부저는 5번, 서보 모터는 9번을 사용합니다. 뒤의 모든 예제도 같은 포트 번호로 통일했습니다.
중요: 라즈베리파이마다 아두이노 장치명이 /dev/ttyUSB0가 아닐 수 있습니다. 연결이 되지 않으면 터미널에서 ls /dev/ttyUSB* /dev/ttyACM* 2>/dev/null로 실제 포트를 확인하세요.

[PART 1] LED 디지털 출력 및 타이밍 응용 제어

예제 1. LED.py

LED.py
from robomy_arduino import Arduino
from time import sleep

myArduino = Arduino("/dev/ttyUSB0")
myArduino.setPort("digital", 11, "output")
print("LED 켜는 중...")
myArduino.write("value", 11, "HIGH")
sleep(3)
print("LED 끄는 중...")
myArduino.write("value", 11, "LOW")

예제 2. LED SOS 구조신호.py

LED_SOS_구조신호.py
from robomy_arduino import Arduino
from time import sleep

myArduino = Arduino("/dev/ttyUSB0")
myArduino.setPort("digital", 11, "output")

print("🆘 LED SOS 구조 신호를 시작합니다.")

def blink(on_time, off_time):
    myArduino.write("value", 11, "HIGH")
    sleep(on_time)
    myArduino.write("value", 11, "LOW")
    sleep(off_time)

try:
    # S : 짧게 3번
    for i in range(3):
        blink(0.2, 0.2)

    sleep(0.4)

    # O : 길게 3번
    for i in range(3):
        blink(0.7, 0.2)

    sleep(0.4)

    # S : 짧게 3번
    for i in range(3):
        blink(0.2, 0.2)

    print("SOS 신호 전송 완료!")

finally:
    myArduino.write("value", 11, "LOW")

예제 3. 깜빡이등.py

깜빡이등.py
from robomy_arduino import Arduino
from time import sleep

myArduino = Arduino("/dev/ttyUSB0")
myArduino.setPort("digital", 11, "output")

print("딱 5번만 깜빡이고 자동으로 꺼지는 경고등")

# range(5)를 넣으면 0부터 4까지 딱 5번만 반복하고 끝납니다!
for i in range(5):
    print(f"{i+1}번째 깜빡!")
    myArduino.write("value", 11, "HIGH")
    sleep(0.5)
    myArduino.write("value", 11, "LOW")
    sleep(0.5)

print("정해진 횟수를 다 채워서 안전하게 종료합니다.")

예제 4. 미니 불꽃놀이.py

미니 불꽃놀이.py
from robomy_arduino import Arduino
from time import sleep
import random  # 랜덤한 느낌을 주기 위해 추가!

myArduino = Arduino("/dev/ttyUSB0")
myArduino.setPort("digital", 11, "output")

print("✨ 미니 불꽃놀이 시작!")

try:
    while True:
        # 1단계: 불꽃이 피어오르듯 파르르 떨리며 켜지는 효과 (15번 빠르게 반짝임)
        for i in range(15):
            myArduino.write("value", 11, "HIGH")
            sleep(0.02)
            myArduino.write("value", 11, "LOW")
            sleep(0.05)
            
        # 2단계: 불꽃이 팡! 터져서 유지되는 순간
        myArduino.write("value", 11, "HIGH")
        sleep(1.5)  # 1.5초 동안 환하게 유지!
        
        # 3단계: 불꽃이 꺼지고 다음 불꽃이 터질 때까지 대기
        myArduino.write("value", 11, "LOW")
        # 1초에서 3초 사이의 랜덤한 시간 동안 암전 (진짜 불꽃놀이처럼!)
        wait_time = random.uniform(1.0, 3.0)
        sleep(wait_time)

except KeyboardInterrupt:
    print("\n불꽃놀이를 종료합니다.")
    myArduino.write("value", 11, "LOW")

추가 예제 A. 로켓 발사 카운트다운 LED.py

로켓_발사_카운트다운_LED.py
from robomy_arduino import Arduino
from time import sleep

myArduino = Arduino("/dev/ttyUSB0")
myArduino.setPort("digital", 11, "output")

print("🚀 로켓 발사 준비!")

for count in range(5, 0, -1):
    print(count)
    # 숫자가 줄어들수록 더 빠르게 반짝입니다.
    blink_time = 0.12 + count * 0.08
    myArduino.write("value", 11, "HIGH")
    sleep(blink_time)
    myArduino.write("value", 11, "LOW")
    sleep(blink_time)

print("🚀 발사!")
for i in range(12):
    myArduino.write("value", 11, "HIGH")
    sleep(0.04)
    myArduino.write("value", 11, "LOW")
    sleep(0.04)

myArduino.write("value", 11, "LOW")

추가 예제 B. 심장 박동 LED.py

심장_박동_LED.py
from robomy_arduino import Arduino
from time import sleep

myArduino = Arduino("/dev/ttyUSB0")
myArduino.setPort("digital", 11, "output")

print("❤️ 심장 박동 LED - Ctrl + C로 종료")

try:
    while True:
        # 두 번 빠르게 뛰고 잠시 쉬는 박동 패턴
        for beat in range(2):
            myArduino.write("value", 11, "HIGH")
            sleep(0.12)
            myArduino.write("value", 11, "LOW")
            sleep(0.12)
        sleep(0.7)

except KeyboardInterrupt:
    print("\n심장 박동 LED를 종료합니다.")

finally:
    myArduino.write("value", 11, "LOW")

[PART 2] 피에조 부저 음계·효과음 및 경보음 제어

예제 5. 버저음.py

버저음.py
from robomy_arduino import Arduino
from time import sleep

myArduino = Arduino("/dev/ttyUSB0")
myArduino.setPort("digital",5,"output")
print(" 도...")
myArduino.write("tone",5,"262")
sleep(1)
print(" 레...")
myArduino.write("tone",5,"294")
sleep(1)
print(" 미...")
myArduino.write("tone",5,"330")
sleep(1)
print(" 파...")
myArduino.write("tone",5,"349")
sleep(1)
print(" 솔...")
myArduino.write("tone",5,"392")
sleep(1)
print(" 라 ...")
myArduino.write("tone",5,"440")
sleep(1)
print(" 시 ...")
myArduino.write("tone",5,"494")
sleep(1)
print(" 정지 ...")
myArduino.write("tone",5,"0")

예제 6. 긴급 사이렌 효과.py

긴급 사이렌 효과.py
from robomy_arduino import Arduino
from time import sleep

myArduino = Arduino("/dev/ttyUSB0")
myArduino.setPort("digital", 5, "output")

print("🚨 사이렌 패턴을 실행합니다. (종료하려면 Ctrl + C)")

try:
    while True:
        # 고음
        myArduino.write("tone", 5, "880")
        sleep(0.3)
        
        # 저음
        myArduino.write("tone", 5, "659")
        sleep(0.3)

except KeyboardInterrupt:
    print("\n사이렌을 종료합니다.")
    myArduino.write("tone", 5, "0")

예제 7. 슈퍼마리오 점프음.py

슈퍼마리오 점프음.py
from robomy_arduino import Arduino
from time import sleep

myArduino = Arduino("/dev/ttyUSB0")
myArduino.setPort("digital", 5, "output")

print("🎮 게임 효과음 예제를 시작합니다. (3회 반복)")

try:
    for jump in range(3):
        print(f"{jump+1}번째 점프")
        
        # 주파수를 300부터 1200까지 40씩 빠르게 올립니다.
        for freq in range(300, 1200, 40):
            myArduino.write("tone", 5, str(freq))
            sleep(0.01)  # 0.01초마다 음이 변함
            
        # 점프 후 잠시 쉬기
        myArduino.write("tone", 5, "0")
        sleep(1)

    print("효과음 재생을 마쳤습니다.")

except KeyboardInterrupt:
    myArduino.write("tone", 5, "0")

추가 예제 A. 게임 아이템 획득음.py

게임_아이템_획득음.py
from robomy_arduino import Arduino
from time import sleep

myArduino = Arduino("/dev/ttyUSB0")
myArduino.setPort("digital", 5, "output")

notes = [523, 659, 784, 1047]

print("✨ 아이템 획득!")
for freq in notes:
    myArduino.write("tone", 5, str(freq))
    sleep(0.12)

myArduino.write("tone", 5, "0")

추가 예제 B. 폭탄 타이머 효과음.py

폭탄_타이머_효과음.py
from robomy_arduino import Arduino
from time import sleep

myArduino = Arduino("/dev/ttyUSB0")
myArduino.setPort("digital", 5, "output")

print("⏱️ 5초 타이머 시작!")

for remain in range(5, 0, -1):
    print(remain)
    myArduino.write("tone", 5, "880")
    sleep(0.08)
    myArduino.write("tone", 5, "0")
    sleep(0.18 + remain * 0.10)

print("💥 시간 종료!")
myArduino.write("tone", 5, "1200")
sleep(0.35)
myArduino.write("tone", 5, "0")

[PART 2-1] LED + 부저 복합 제어

두 개의 출력 장치를 함께 제어하면 시각 신호와 청각 신호를 동시에 설계할 수 있습니다. 이 예제에서는 LED 11번 핀과 부저 5번 핀을 함께 사용합니다.

예제 8. 비상 경고등 + 경고음.py

비상_경고등_경고음.py
from robomy_arduino import Arduino
from time import sleep

myArduino = Arduino("/dev/ttyUSB0")
myArduino.setPort("digital", 11, "output")  # LED
myArduino.setPort("digital", 5, "output")   # 부저

print("🚨 비상 경고 신호를 5회 출력합니다.")

try:
    for i in range(5):
        print(f"{i + 1}번째 경고")

        myArduino.write("value", 11, "HIGH")
        myArduino.write("tone", 5, "880")
        sleep(0.3)

        myArduino.write("value", 11, "LOW")
        myArduino.write("tone", 5, "659")
        sleep(0.3)

finally:
    myArduino.write("value", 11, "LOW")
    myArduino.write("tone", 5, "0")

print("경고 신호 출력이 끝났습니다.")

예제 9. 퀴즈 정답 알림 장치.py

퀴즈_정답_알림장치.py
from robomy_arduino import Arduino
from time import sleep

myArduino = Arduino("/dev/ttyUSB0")
myArduino.setPort("digital", 11, "output")  # LED
myArduino.setPort("digital", 5, "output")   # 부저

answer = input("문제: 7 × 8 = ? : ").strip()

try:
    if answer == "56":
        print("✅ 정답입니다.")
        myArduino.write("value", 11, "HIGH")

        for freq in [523, 659, 784]:
            myArduino.write("tone", 5, str(freq))
            sleep(0.18)

        myArduino.write("tone", 5, "0")
        sleep(1)

    else:
        print("❌ 다시 확인해 보세요.")

        for i in range(3):
            myArduino.write("value", 11, "HIGH")
            myArduino.write("tone", 5, "220")
            sleep(0.2)

            myArduino.write("value", 11, "LOW")
            myArduino.write("tone", 5, "0")
            sleep(0.2)

finally:
    myArduino.write("value", 11, "LOW")
    myArduino.write("tone", 5, "0")
확장 활동: 정답 문자열, LED 점멸 횟수, 부저 주파수를 바꾸어 자신만의 알림 장치를 설계해 보세요.

[PART 3] 서보 모터 각도 제어 및 동작 시나리오

예제 10. 모터제어9번포트.py

모터제어9번포트.py
from robomy_arduino import Arduino
from time import sleep

# 1. 아두이노 보드 연결
myArduino = Arduino("/dev/ttyUSB0")

# 2. 9번 핀을 모터 출력 모드로 설정
myArduino.setPort("digital", 9, "output")

# 3. 모터 제어 신호 켜기 (초기화)
print("motor 키는중...")
myArduino.write("servo", 9, "181") 
sleep(2)  # ⭐ 중요: 모터가 켜지고 준비할 시간을 2초 동안 줍니다!

# 4. 90도로 회전
print("motor 회전 ...")
myArduino.write("servo", 9, "90")  
sleep(3)  # 90도까지 완전히 회전할 수 있도록 3초 대기

# 5. 0도로 회전
print("motor 회전 ...")
myArduino.write("servo", 9, "0")   
sleep(3)  # 0도까지 완전히 돌아올 수 있도록 3초 대기

# 6. 모터 제어 신호 끄기 (안전 종료)
print("motor 정지 및 보호...")
myArduino.write("servo", 9, "182") # ⭐ 모터의 힘을 풀어 과열을 방지합니다.

예제 11. 자동차 와이퍼 모드.py

자동차 와이퍼 모드.py
from robomy_arduino import Arduino
from time import sleep

myArduino = Arduino("/dev/ttyUSB0")
myArduino.setPort("digital", 9, "output")

print("🚗 와이퍼 시스템 가동! (종료하려면 Ctrl + C)")

# 1. 모터 신호 켜고 대기
myArduino.write("servo", 9, "181")
sleep(2)

try:
    while True:
        print("오른쪽으로 쓱~")
        myArduino.write("servo", 9, "180")
        sleep(1.5)  # 끝까지 회전할 수 있도록 여유 있게 대기
        
        print("왼쪽으로 싹~")
        myArduino.write("servo", 9, "0")
        sleep(1.5)

except KeyboardInterrupt:
    print("\n와이퍼를 안전하게 정지합니다.")
    # 안전하게 0도로 복귀시킨 후 모터 전원 끄기
    myArduino.write("servo", 9, "0")
    sleep(1)
    myArduino.write("servo", 9, "182")

예제 12. 낚시꾼 모드.py

낚시꾼 모드.py
from robomy_arduino import Arduino
from time import sleep

myArduino = Arduino("/dev/ttyUSB0")
myArduino.setPort("digital", 9, "output")

print("🎣 🎣 서보 모터 낚시 시뮬레이션을 시작합니다.")

# 1. 모터 신호 켜고 준비 단계
myArduino.write("servo", 9, "181")
sleep(2)

try:
    # 0도(기본 위치)에서 대기
    myArduino.write("servo", 9, "0")
    sleep(2)
    
    # 2. 입질 단계: 물고기가 툭툭 건드림 (80도와 90도 사이를 아주 빠르게 3번 왕복)
    print("어? 입질이 옵니다...! 툭. 툭.")
    for i in range(3):
        myArduino.write("servo", 9, "80")
        sleep(0.15)
        myArduino.write("servo", 9, "90")
        sleep(0.15)
        
    sleep(1) # 잠시 정적...
    
    # 3. 챔질 단계: 물고기가 미끼를 물었을 때 확 낚아챔! (180도로 빠르게 회전)
    print("입질 감지! 낚싯대를 빠르게 들어 올립니다. 🌊")
    myArduino.write("servo", 9, "180")
    sleep(3) # 낚아챈 상태로 3초간 힘겨루기 유지
    
    # 4. 마무리: 원래 자리로 돌아와서 모터 쉬게 하기
    print("상황 종료! 물고기를 바구니에 담고 다음 낚시 준비...")
    myArduino.write("servo", 9, "0")
    sleep(2)

except KeyboardInterrupt:
    print("\n낚시대를 접습니다.")
    myArduino.write("servo", 9, "0")
    sleep(1)
    myArduino.write("servo", 9, "182")

추가 예제 A. 레이더 스캐너 모터.py

레이더_스캐너_모터.py
from robomy_arduino import Arduino
from time import sleep

myArduino = Arduino("/dev/ttyUSB0")
myArduino.setPort("digital", 9, "output")

myArduino.write("servo", 9, "181")
sleep(1)

print("📡 레이더 스캔 시작!")

try:
    for scan in range(3):
        print(f"{scan + 1}회 스캔")
        for angle in range(20, 161, 20):
            myArduino.write("servo", 9, str(angle))
            sleep(0.18)
        for angle in range(160, 19, -20):
            myArduino.write("servo", 9, str(angle))
            sleep(0.18)

finally:
    myArduino.write("servo", 9, "90")
    sleep(0.5)
    myArduino.write("servo", 9, "182")
    print("레이더 스캔 종료")

추가 예제 B. 주차장 차단기.py

주차장_차단기.py
from robomy_arduino import Arduino
from time import sleep

myArduino = Arduino("/dev/ttyUSB0")
myArduino.setPort("digital", 9, "output")

myArduino.write("servo", 9, "181")
sleep(1)
myArduino.write("servo", 9, "0")
sleep(1)

print("🚗 차량 접근! 차단기를 엽니다.")
myArduino.write("servo", 9, "90")
sleep(3)

print("🚧 차량 통과 완료! 차단기를 닫습니다.")
myArduino.write("servo", 9, "0")
sleep(1)

myArduino.write("servo", 9, "182")

[PART 4] 인공지능 컴퓨터 비전 사물 인식 엔진 연동

후반부 예제 보강: LED·부저·모터 포트를 11·5·9번으로 통일했고, 실시간 인식 예제는 같은 사물이 화면에 계속 보일 때 매 프레임 하드웨어가 반복 동작하지 않도록 상태값을 추가했습니다.

예제 13. 사물인식.py

사물인식.py
import robomy_cv as rcv
rcv.create_object_h5('obj_data',90,6)

예제 14. 사물인식1(보정).py

사물인식1(보정).py
import robomy_cv as rcv
import cv2

# [주의] rcv.create_object_h5('obj_data', 90, 3) 명령어는 이미 사진 수집과 
# AI 모델 학습을 끝마쳤으므로 다시 실행하여 데이터가 덮어써지지 않도록 주석(##) 처리합니다.
## rcv.create_object_h5('obj_data', 90, 3)

# 1. 프로그램에서 사용할 변수들을 초기화합니다.
keyVal = None  # 키보드 입력 값을 저장할 변수
camera = None  # 카메라 장치 객체를 담을 변수

# 2. 라즈베리파이에 연결된 0번(기본) 카메라의 전원을 켜고 영상 스트리밍을 준비합니다.
camera = rcv.get_camera(0)

print("🔍 [실시간 사물 인식 가동] 카메라 화면이 열립니다.")
print("👉 가방, 스마트폰, 키보드, 볼펜 등을 카메라에 보여주세요.")
print("👉 종료하려면 카메라 영상 창을 선택한 상태에서 키보드 'ESC' 키를 누르세요.")

# 3. 사용자가 ESC 키(아스크코드 27번)를 누르기 전까지 영상 처리를 무한 반복합니다.
while not keyVal == 27:
    
    # [단계 A] 카메라 렌즈로부터 현재 순간의 정지 영상 화면(Frame)을 1장 캡처해 가져옵니다.
    frame = rcv.get_frame(camera)
    
    # [단계 B] 캡처한 화면(frame)을 우리가 미리 학습시켜 둔 인공지능 모델('obj_data')에 입력하여 
    # 사물이 어디에 있고 이름이 무엇인지 판단(Prediction)합니다. 
    # 인식 결과 사물 이름 문자열(예: 'keyboard', 'mouse')이 pred 변수에 담깁니다.
    frame, pred = rcv.find_object_from_frame(frame, 'obj_data')
    
    # [단계 C] 인공지능이 분석한 결과 상자와 이름표가 합성된 화면을 컴퓨터 모니터 창('로보그램 실시간 인식')에 출력합니다.
    cv2.imshow('로보그램 실시간 인식', frame)
    
    # [단계 D] 키보드 입력이 들어오는지 0.01초(10ms) 동안 대기하며 입력값을 keyVal 변수에 업데이트합니다.
    keyVal = cv2.waitKey(10)

print("\n🛑 사물 인식 프로그램을 안전하게 종료합니다.")
cv2.destroyAllWindows()

예제 15. 오픈CV 버그 우회! 터미널 출력 + 아두이노 LED 연동.py

오픈CV_버그_우회_연동.py
import robomy_cv as rcv
from robomy_arduino import Arduino
import cv2

myArduino = Arduino("/dev/ttyUSB0")
myArduino.setPort("digital", 11, "output")

keyVal = None
camera = rcv.get_camera(0)

print("🔥 사물이 인식되면 이름을 출력하고 LED가 켜집니다. ESC로 종료합니다.")

try:
    while keyVal != 27:
        frame = rcv.get_frame(camera)
        frame, pred = rcv.find_object_from_frame(frame, 'obj_data')

        if pred and len(pred) > 0:
            detected_item = str(pred).strip().lower()
            myArduino.write("value", 11, "HIGH")

            if 'keyboard' in detected_item:
                print("🎯 키보드 감지")
            elif 'mouse' in detected_item:
                print("🎯 마우스 감지")
            elif 'smartphone' in detected_item:
                print("🎯 스마트폰 감지")
            elif 'bag' in detected_item:
                print("🎯 가방 감지")
            elif 'ball point pen' in detected_item:
                print("🎯 볼펜 감지")
            elif 'slippers' in detected_item:
                print("🎯 슬리퍼 감지")
            else:
                print(f"🎯 {detected_item} 감지")
        else:
            myArduino.write("value", 11, "LOW")

        cv2.imshow('로보그램 실시간 인식', frame)
        keyVal = cv2.waitKey(10)

finally:
    print("\n프로그램을 종료합니다.")
    myArduino.write("value", 11, "LOW")
    cv2.destroyAllWindows()

예제 16. 사물별 하드웨어 매칭 및 사용자 선택 제어 코드.py

사물별_하드웨어_매칭_시스템.py
import robomy_cv as rcv
from robomy_arduino import Arduino
import cv2
import time

myArduino = Arduino("/dev/ttyUSB0")
myArduino.setPort("digital", 11, "output")  # LED
myArduino.setPort("digital", 5, "output")  # 부저
myArduino.setPort("digital", 9, "output")  # 서보 모터

myArduino.write("servo", 9, "181")
time.sleep(0.5)
myArduino.write("servo", 9, "0")
time.sleep(0.5)

def normalize_choice(value, default):
    value = value.strip().lower()
    if value in ("led", "buzzer", "motor"):
        return value
    if value:
        print(f"⚠️ '{value}'는 사용할 수 없어 기본값 {default}를 사용합니다.")
    return default

def control_hardware(target):
    myArduino.write("value", 11, "LOW")
    myArduino.write("tone", 5, "0")

    if target == "led":
        myArduino.write("value", 11, "HIGH")
        print("💡 LED가 켜졌습니다!")
    elif target == "buzzer":
        myArduino.write("tone", 5, "523")
        print("🔊 부저가 울립니다!")
    elif target == "motor":
        myArduino.write("servo", 9, "90")
        print("🚪 서보 모터가 90도로 회전합니다.")
        time.sleep(1.5)
        myArduino.write("servo", 9, "0")

print("🤖 사물별 동작을 led / buzzer / motor 중에서 선택하세요.")

set_bag   = normalize_choice(input("🎒 가방 [기본 led]: "), "led")
set_phone = normalize_choice(input("📱 스마트폰 [기본 buzzer]: "), "buzzer")
set_key   = normalize_choice(input("⌨️ 키보드 [기본 motor]: "), "motor")
set_mon   = normalize_choice(input("🖥️ 모니터 [기본 led]: "), "led")
set_ms    = normalize_choice(input("🖱️ 마우스 [기본 buzzer]: "), "buzzer")
set_sl    = normalize_choice(input("🩴 슬리퍼 [기본 led]: "), "led")
set_pen   = normalize_choice(input("✏️ 볼펜 [기본 motor]: "), "motor")

mapping = {
    "bag": set_bag,
    "smartphone": set_phone,
    "keyboard": set_key,
    "monitor": set_mon,
    "mouse": set_ms,
    "slippers": set_sl,
    "ball point pen": set_pen,
}

keyVal = None
camera = rcv.get_camera(0)
last_item = None

print("\n🚀 AI 사물-하드웨어 매칭 시스템을 시작합니다. ESC로 종료합니다.")

try:
    while keyVal != 27:
        frame = rcv.get_frame(camera)
        frame, pred = rcv.find_object_from_frame(frame, 'obj_data')

        detected_item = str(pred).strip().lower() if pred else ""

        matched_name = None
        for object_name in mapping:
            if object_name in detected_item:
                matched_name = object_name
                break

        # 같은 사물이 계속 보이는 동안에는 매 프레임 다시 작동하지 않습니다.
        if matched_name and matched_name != last_item:
            print(f"🎯 감지된 사물: {matched_name}")
            control_hardware(mapping[matched_name])
            last_item = matched_name
        elif not matched_name:
            myArduino.write("value", 11, "LOW")
            myArduino.write("tone", 5, "0")
            last_item = None

        cv2.imshow('AI IoT 사물 인식', frame)
        keyVal = cv2.waitKey(10)

finally:
    print("\n🛑 시스템을 종료하고 하드웨어를 초기화합니다.")
    myArduino.write("value", 11, "LOW")
    myArduino.write("tone", 5, "0")
    myArduino.write("servo", 9, "0")
    time.sleep(0.5)
    myArduino.write("servo", 9, "182")
    cv2.destroyAllWindows()

[PART 5] OpenCV 얼굴 인식 및 종합 연동

수업 팁: 얼굴 데이터는 본인 또는 촬영에 동의한 사람의 사진만 사용하고, 수업이 끝난 뒤 faces 폴더를 삭제하는 방식으로 운영하는 것이 좋습니다.

예제 17. 얼굴인식.py

얼굴인식.py
import robomy_cv as rcv
from time import sleep
from cv2 import waitKey  # 오타 수정 (waitkey -> waitKey)

# ===================================================
# [1단계] 카메라 설정 및 데이터(얼굴 사진 50장) 수집
# ===================================================
camera = None
camera = rcv.get_camera(0)  # 0번(기본) 카메라 활성화

print("📸 얼굴 등록을 시작합니다. 카메라를 정면으로 바라봐 주세요!")
sleep(2)  # 카메라 준비 시간 잠시 대기

# 0부터 49까지 총 50장의 얼굴 사진을 'faces' 폴더에 저장합니다.
for i in range(0, 50):
    rcv.save_face(camera, 'faces', i)
    print(f"사진 촬영 중... ({i+1}/50)")
    sleep(0.05)  # 너무 빨리 찍히지 않게 미세한 간격 추가

# ===================================================
# [2단계] 수집된 사진으로 AI 얼굴 모델 학습(공부)
# ===================================================
print("\n🤖 인공지능이 얼굴 특징을 학습하는 중입니다. 잠시만 기다려주세요...")
faceModel = None
faceModel = rcv.train_face('faces')
print("✅ 학습 완료! 실시간 보안 모드를 시작합니다.")

# ===================================================
# [3단계] 실시간 얼굴 인식 매칭 (ESC 누르면 종료)
# ===================================================
keyVal = None
print("\n🔒 [보안 실행 중] 등록된 사용자 확인 중... (종료하려면 ESC 키를 누르세요)")

while not keyVal == 27:
    # 실시간으로 카메라에서 얼굴 영역만 추출하여 가져옵니다.
    camera_face = rcv.face_extractor(camera)
    
    # 추출한 얼굴과 미리 학습된 AI 모델(faceModel)의 특징점 데이터를 대조 분석합니다.
    if rcv.compare_face(camera_face, faceModel):
        print("🟢 Recognized : 등록된 사용자(등록 사용자)가 확인되었습니다. 문을 엽니다.")
    else:
        print("🔴 Unknown : 등록되지 않은 얼굴입니다. 접근을 제한합니다.")
        
    keyVal = waitKey(1)

print("\n👋 얼굴 인식 보안 시스템이 안전하게 종료되었습니다.")

예제 18. 얼굴인식응용.py

얼굴인식응용.py
import robomy_cv as rcv
from robomy_arduino import Arduino
from time import sleep
from cv2 import waitKey
import cv2

# ===================================================
# [준비 단계] 아두이노 하드웨어 및 카메라 초기 설정
# ===================================================
# 1. 아두이노 및 카메라 연결
myArduino = Arduino("/dev/ttyUSB0")
camera = rcv.get_camera(0)

# 2. 하드웨어 핀 모드 설정
myArduino.setPort("digital", 11, "output") # LED (11번)
myArduino.setPort("digital", 5, "output")  # 버저 (5번)
myArduino.setPort("digital", 9, "output")  # 서보 모터 (9번)

# 3. 서보 모터(도어락) 초기화 (전원 켜고 문 잠금 상태로 시작)
myArduino.write("servo", 9, "181")
sleep(1)
myArduino.write("servo", 9, "0")          # 0도: 문이 잠긴 상태
sleep(1)

# ===================================================
# [1단계] 얼굴 등록 및 AI 모델 학습
# ===================================================
print("📸 [얼굴 등록] 카메라를 정면으로 바라봐 주세요!")
sleep(1)

for i in range(0, 50):
    rcv.save_face(camera, 'faces', i)
    sleep(0.05)

print("\n🤖 인공지능이 얼굴을 학습하고 있습니다...")
faceModel = rcv.train_face('faces')
print("✅ 시스템 준비 완료! 실시간 감시를 시작합니다.")

# ===================================================
# [2단계] 실시간 보안 도어락 제어 (무한 반복)
# ===================================================
keyVal = None
door_open = False  # 문이 현재 열려있는지 체크하는 변수

try:
    while not keyVal == 27:  # ESC 누르면 종료
        camera_face = rcv.face_extractor(camera)
        
        # 👤 [경우 1] 얼굴 인식 성공 (등록 사용자 등장!)
        if rcv.compare_face(camera_face, faceModel):
            print('🟢 Recognized : 등록 사용자 확인! 문을 엽니다.')
            
            myArduino.write("value", 11, "HIGH") # 1) LED 불 켜기
            myArduino.write("servo", 9, "90")    # 2) 도어락 열기 (90도 회전)
            myArduino.write("tone", 5, "0")      # 혹시 울리던 경고음이 있다면 끄기
            
            sleep(5)  # ⏰ 문이 열린 채로 5초 동안 대기합니다 (사람이 들어가는 시간)
            
            print('🔒 다시 문을 잠급니다.')
            myArduino.write("value", 11, "LOW")  # 3) LED 불 끄기
            myArduino.write("servo", 9, "0")     # 4) 도어락 다시 잠금 (0도 복귀)
            sleep(1)

        # 👤 [경우 2] 얼굴 인식 실패 또는 모르는 사람 (경고 상황!)
        else:
            print('🔴 Unknown! : 등록되지 않은 얼굴입니다. 경고음을 출력합니다.')
            
            # 경찰차 사이렌처럼 고음과 저음을 빠르게 반복해서 강력한 경고음을 냅니다.
            myArduino.write("tone", 5, "988")  # 높은 시 음
            sleep(0.15)
            myArduino.write("tone", 5, "784")  # 높은 솔 음
            sleep(0.15)
            
        keyVal = waitKey(1)

except KeyboardInterrupt:
    print("\n시스템을 안전하게 종료합니다.")

finally:
    # 종료할 때 모든 하드웨어를 안전하게 정지시킵니다.
    myArduino.write("value", 11, "LOW") # LED 끄기
    myArduino.write("tone", 5, "0")     # 버저 끄기
    myArduino.write("servo", 9, "0")    # 모터 원위치
    sleep(1)
    myArduino.write("servo", 9, "182")  # 모터 보호 모드
    cv2.destroyAllWindows()