본문 바로가기

아두이노우노 R4

손가락 수를 이용한 아두이노 LED 제어

반응형

 

 

이 프로젝트는 아두이노 우노를 사용하여 컴퓨터에서 수신한 손가락 수 데이터를 기반으로 LED를 제어합니다. 파이썬 스크립트가 카메라에 보이는 손가락의 수를 감지하고 이 데이터를 아두이노로 전송하면 아두이노가 해당 수의 LED에 불을 켭니다. 

 

 

 

회로 다이어그램: 아래 다이어그램을 참조하여 회로를 설정하세요: 

 

 

 

 

설정 지침 

 

중요: 이 프로젝트에는 Arduino 및 Python 개발 환경이 모두 필요합니다. 이 튜토리얼에서는 컴퓨터에 이미 Python과 Arduino IDE가 설치되어 있다고 가정합니다. 그렇지 않은 경우 아래 제공된 설치 가이드를 따를 수 있습니다:

 

이 프로젝트에서 Arduino와 Python은 각각 중요한 역할을 합니다: 

 

  • 아두이노: 아두이노는 하드웨어 제어의 핵심 역할을 합니다. 파이썬 스크립트로부터 명령을 받아 감지된 손가락의 수에 따라 LED를 제어합니다. 아두이노는 직렬 포트를 통해 컴퓨터와 통신하며 파이썬 스크립트가 전송한 데이터에 실시간으로 응답합니다.
  • 파이썬: Python 스크립트는 이미지 처리와 제스처 인식을 담당합니다. 컴퓨터의 카메라를 사용하여 표시되는 손가락의 수를 감지합니다. 파이썬 스크립트는 OpenCV를 활용하여 이미지를 분석하고 손가락 수를 결정합니다. 그런 다음 이 데이터를 직렬 통신을 통해 아두이노로 전송하여 적절한 LED 제어를 트리거합니다. 

 

프로그램 코드의 소스는 깃허브 사이트를 참고하세요. 다운 받으세요.

 

 

아두이노 설정

 

1. 회로를 구성합니다.

2. 아두이노 IDE에서 LedController.ino 파일을 엽니다.

3. USB를 통해 아두이노 우노를 컴퓨터에 연결합니다. Python 스크립트에 필요하므로 포트 번호를 기록해 두세요.

 

 

 

4. LedController.ino 스케치를 Arduino 보드에 업로드합니다. 

 

파이썬 설정

 

중요: 파이썬 코드를 실행하기 전에 Arduino IDE에서 직렬 모니터를 닫았는지 확인하세요. 이렇게 하면 파이썬이 아두이노로 데이터를 전송하지 못하게 하는 포트 충돌을 방지할 수 있습니다.

 

1. 필요한 파이썬 라이브러리를 설치합니다:

 

pip install opencv-python mediapipe pyserial

 

혹시 설치할 때 아래와 마지막에 다음과 같은 에러가 납니다.

 

  WARNING: Failed to write executable - trying to use .deleteme logic
ERROR: Could not install packages due to an OSError: [WinError 2] 지정된 파일을 찾을 수 없습니다: 'C:\\Python311\\Scripts\\pyserial-miniterm.exe' -> 'C:\\Python311\\Scripts\\pyserial-miniterm.exe.deleteme'


[notice] A new release of pip available: 22.3 -> 24.2
[notice] To update, run: python.exe -m pip install --upgrade pip
PS D:\dev-python>

 

맨 아래를 보니 pip를 업그레이드 하는 명령을 입력하라고 합니다.

 

그래서 다음 명령을 입력하면

 

python.exe -m pip install --upgrade pip

 

다시 아래와 같은 에러 메시지가 나오는데

 

ERROR: Could not install packages due to an OSError: [WinError 5] 액세스가 거부되었습니다: 'c:\\python311\\lib\\site-packages\\pip-22.3.dist-info\\entry_points.txt'
Consider using the `--user` option or check the permissions.

 

에러가 난다면 --user 옵션을 사용해서 아래명령을 사용하세요.

 

python.exe -m pip install --user --upgrade pip

 

그 다음 다시 라이브러리 설치하시면 됩니다.

 

 pip install opencv-python mediapipe pyserial

 

 

2. 올바른 직렬 포트를 사용하도록 파이썬 스크립트를 업데이트하여 아두이노 설정 중에 식별한 포트와 일치하는지 확인하세요.

 

 

3. FingerCountSender.py 실행

 

4. 커뮤니티 가입 페이스 북 주소

 

 

아래는 LedController.ino 아두이노 스케치 코드

 

/*
  This code controls a series of LEDs on an Arduino Uno based on finger count data 
  received from a Python script. The script detects the number of fingers shown 
  to a camera and sends this data to the Arduino via serial communication. The Arduino 
  then lights up the corresponding number of LEDs.

  The LEDs are connected to digital pins 2 through 6, with the number of lit LEDs 
  corresponding to the finger count detected by the Python script.

  Board: Arduino Uno R3 (or R4)
  Components: LEDs, Resistors

  Wulu from SunFounder 2024.08
*/

// Define the LED pins
const int ledPins[] = {2, 3, 4, 5, 6}; // Pins where the LEDs are connected
const int numLeds = 5; // Number of LEDs

void setup() {
  // Initialize the LED pins as outputs
  for (int i = 0; i < numLeds; i++) {
    pinMode(ledPins[i], OUTPUT);
    digitalWrite(ledPins[i], LOW); // Ensure all LEDs are off initially
  }
  
  // Start serial communication
  Serial.begin(115200);
  Serial.setTimeout(1);
}

void loop() {
  // Check if data is available on the serial port
  if (Serial.available() > 0) {

    // Read the incoming data
    int value = Serial.readString().toInt();
    
    // Ensure the value is within the range 0-5
    if (value >= 0 && value <= numLeds) {
      // Turn off all LEDs first
      for (int i = 0; i < numLeds; i++) {
        digitalWrite(ledPins[i], LOW);
      }

      // Turn on the appropriate number of LEDs
      for (int i = 0; i < value; i++) {
        digitalWrite(ledPins[i], HIGH);
      }

    }
  }
}

 

 

 

아래는 파이선 코드 FingerCountSender.py

 

 

"""
This script captures video from a camera, detects the number of fingers shown using 
the MediaPipe Hands module, and sends the finger count to an Arduino via serial communication.

The script uses OpenCV to process the video feed and MediaPipe to perform hand and finger 
detection. The number of fingers detected is displayed on the video frame and sent to 
the Arduino in real-time.

Components:
- Camera: Captures the video feed.
- Arduino: Receives the finger count via serial communication and controls LEDs accordingly.

Serial Communication:
- Port: 'COM5' (Modify as needed)
- Baud Rate: 115200

Wulu from SunFounder 2024.08
"""

import cv2
import mediapipe as mp
import serial
import time
import math

# Set up serial communication with the Arduino
ser = serial.Serial('COM8', 115200, timeout=1)

# Initialize MediaPipe Hands module
mp_hands = mp.solutions.hands
hands = mp_hands.Hands(min_detection_confidence=0.7)
mp_drawing = mp.solutions.drawing_utils

# Initialize camera
cap = cv2.VideoCapture(0)

def calculate_angle(p1, p2, p3):
    """ Calculate angle between three points. """
    v1 = (p1.x - p2.x, p1.y - p2.y)
    v2 = (p3.x - p2.x, p3.y - p2.y)
    dot_product = v1[0] * v2[0] + v1[1] * v2[1]
    magnitude_v1 = math.sqrt(v1[0]**2 + v1[1]**2)
    magnitude_v2 = math.sqrt(v2[0]**2 + v2[1]**2)
    cos_angle = dot_product / (magnitude_v1 * magnitude_v2)
    angle = math.degrees(math.acos(min(1.0, max(-1.0, cos_angle))))
    return angle

while cap.isOpened():
    ret, frame = cap.read()
    if not ret:
        break
    
    # Convert the frame to RGB
    rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    
    # Process the frame with MediaPipe Hands
    result = hands.process(rgb_frame)
    
    if result.multi_hand_landmarks:
        for hand_landmarks in result.multi_hand_landmarks:
            # Draw hand landmarks on the frame
            mp_drawing.draw_landmarks(frame, hand_landmarks, mp_hands.HAND_CONNECTIONS)
            
            # Count fingers based on landmark positions
            finger_tips_ids = [8, 12, 16, 20]
            count_fingers = sum([hand_landmarks.landmark[tip_id].y < hand_landmarks.landmark[tip_id - 3].y for tip_id in finger_tips_ids])
            
            # Calculate thumb angle and adjust finger count if the thumb is extended
            thumb_angle = calculate_angle(
                hand_landmarks.landmark[2],  # thumb base
                hand_landmarks.landmark[3],  # thumb middle
                hand_landmarks.landmark[4]   # thumb tip
            )
            if thumb_angle > 160:  # Adjust the angle threshold as needed
                count_fingers += 1
            
            # Display the number of fingers on the frame
            cv2.putText(frame, str(count_fingers), (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 1.5, (0, 255, 0), 3)
            print("finger:", count_fingers)

            # Send finger count to Arduino via serial communication
            ser.write(bytes(str(count_fingers), 'utf-8')) 
    else:
        ser.write(bytes('0', 'utf-8')) 

    # Show the frame
    cv2.imshow('Finger Count', frame)
    
    # Exit the loop when 'q' is pressed
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

 

 

 

반응형

더욱 좋은 정보를 제공하겠습니다.~ ^^