아두이노와 파이썬으로 제스처 제어 PC 만들기 - 핸즈프리 조작
부품 및 소모품
| Arduino UNO |
1 |
| 초음파 센서 HC-SR04 |
2 |
| 점퍼 와이어 |
1 |
앱 및 온라인 서비스
- Arduino IDE
- Python IDLE
- PySerial 라이브러리
- PyAutoGUI 라이브러리
프로젝트 개요
아두이노와 파이썬을 조합해 제스처로 노트북/컴퓨터를 제어하는 방법을 배웁니다.
키보드, 마우스, 조이스틱 대신 손 제스처로 동영상 재생/일시정지, 사진 슬라이드 좌/우 이동, 웹페이지 스크롤 업/다운 등 다양한 기능 제어 가능. 데모로 VLC 미디어 플레이어 제어를 구현했습니다.
작동 원리
노트북 화면 상단에 HC-SR04 초음파 센서 2개를 배치해 손과의 거리를 측정. 아두이노가 거리 데이터를 시리얼 포트로 파이썬에 전송하면, 파이썬이 이를 읽어 해당 액션을 수행합니다.
하드웨어 구성
- Arduino
- HC-SR04 초음파 센서 2개
- 연결 와이어
소프트웨어
- Arduino IDE
- Python IDLE
- PySerial (시리얼 통신용)
- PyAutoGUI (GUI 자동화용)
5가지 제스처 명령
- 재생/일시정지: 양손을 좌/우 센서 앞 일정 거리(멀리)에 동시에 위치
- 되감기: 왼손을 왼쪽 센서 앞 일정 거리(멀리)에 위치
- 빨리감기: 오른손을 오른쪽 센서 앞 일정 거리(멀리)에 위치
- 볼륨 업: 왼손을 왼쪽 센서 앞 일정 거리에 두고 멀리 이동
- 볼륨 다운: 왼손을 왼쪽 센서 앞 일정 거리에 두고 가까이 이동
회로도
각 센서 4핀: Vcc(5V), Trig(아두이노 핀 지정), Echo(아두이노 핀 지정), GND. 좌측 센서 Trig=2, Echo=3 / 우측 센서 Trig=4, Echo=5
파이썬 환경 설정
- Python IDLE 설치: python.org에서 다운로드. 64비트 OS라도 32비트 파이썬 권장 (아두이노 라이브러리 호환성)
- PySerial 설치:
import serial로 테스트
- PyAutoGUI 설치: 명령 프롬프트에서
cd C:\Python27
python -m pip install --upgrade pip
python -m pip install pyautogui
import pyautogui로 테스트
아두이노 코드
const int trigger1 = 2, echo1 = 3;
const int trigger2 = 4, echo2 = 5;
long time_taken;
int dist, distL, distR;
void setup() {
Serial.begin(9600);
pinMode(trigger1, OUTPUT); pinMode(echo1, INPUT);
pinMode(trigger2, OUTPUT); pinMode(echo2, INPUT);
}
void calculate_distance(int trigger, int echo) {
digitalWrite(trigger, LOW); delayMicroseconds(2);
digitalWrite(trigger, HIGH); delayMicroseconds(10);
digitalWrite(trigger, LOW);
time_taken = pulseIn(echo, HIGH);
dist = time_taken * 0.034 / 2;
if (dist > 60) dist = 60;
}
void loop() {
calculate_distance(trigger1, echo1); distL = dist;
calculate_distance(trigger2, echo2); distR = dist;
// 재생/일시정지 - 양손 감지
if ((distL > 40 && distR > 40) && (distL < 60 && distR < 60)) {
Serial.println("Play/Pause"); delay(500);
}
calculate_distance(trigger1, echo1); distL = dist;
calculate_distance(trigger2, echo2); distR = dist;
// 왼쪽 제어 모드 (볼륨)
if (distL >= 13 && distL <= 17) {
delay(100);
calculate_distance(trigger1, echo1); distL = dist;
if (distL >= 13 && distL <= 17) {
Serial.println("Left Locked");
while (distL <= 40) {
calculate_distance(trigger1, echo1); distL = dist;
if (distL < 10) { Serial.println("Volume Increased"); delay(300); }
if (distL > 20) { Serial.println("Volume Decreased"); delay(300); }
}
}
}
// 오른쪽 제어 모드 (탐색)
if (distR >= 13 && distR <= 17) {
delay(100);
calculate_distance(trigger2, echo2); distR = dist;
if (distR >= 13 && distR <= 17) {
Serial.println("Right Locked");
while (distR <= 40) {
calculate_distance(trigger2, echo2); distR = dist;
if (distR < 10) { Serial.println("Rewind"); delay(300); }
if (distR > 20) { Serial.println("Forward"); delay(300); }
}
}
}
delay(200);
}
파이썬 코드
import serial
import time
import pyautogui
ArduinoSerial = serial.Serial('COM15', 9600) # 포트 번호 확인 필요
time.sleep(2)
while True:
incoming = str(ArduinoSerial.readline())
print(incoming)
if 'Play/Pause' in incoming:
pyautogui.typewrite(['space'], 0.2)
if 'Rewind' in incoming:
pyautogui.hotkey('ctrl', 'left')
if 'Forward' in incoming:
pyautogui.hotkey('ctrl', 'right')
if 'Volume Increased' in incoming:
pyautogui.hotkey('ctrl', 'down')
if 'Volume Decreased' in incoming:
pyautogui.hotkey('ctrl', 'up')
incoming = ""
주의: 파이썬 코드의 'COM15'를 실제 아두이노 포트로 변경하세요. 아두이노 IDE의 도구 → 포트 메뉴에서 확인 가능합니다.