image.png

1. 시리얼 통신으로 피코 제어

image.png

image.png

from machine import Pin, PWM
from time import sleep
import sys

# 내장 LED 설정
led = Pin("LED", Pin.OUT)

# 서보모터 설정
servo1 = PWM(Pin(15))
servo2 = PWM(Pin(17))
servo1.freq(50)
servo2.freq(50)

# 초기 각도
angle1 = 90
angle2 = 90

# 듀티 범위
MIN_DUTY = 1638
MAX_DUTY = 8100
STEP = 15
running = True

def angle_to_duty(angle):
    return int(MIN_DUTY + (angle / 180) * (MAX_DUTY - MIN_DUTY))

def update_servos():
    servo1.duty_u16(angle_to_duty(angle1))
    servo2.duty_u16(angle_to_duty(angle2))

update_servos()

print("시리얼 명령 대기 중...")

try:
    while True:
        command = sys.stdin.readline().strip()

        if command == '1':
            led.value(1)
            print("LED 켜짐")

        elif command == '2':
            led.value(0)
            print("LED 꺼짐")

        elif command == '3':
            print("LED 깜빡이기 시작")
            for _ in range(5):
                led.toggle()
                sleep(0.3)
            led.value(0)
            print("LED 깜빡이기 완료")

        elif command == '4':
            if running:
                angle1 = (angle1 + STEP) % 180
                update_servos()
                print(f"서보모터 1 각도: {angle1}도")

        elif command == '5':
            if running:
                angle2 = (angle2 + STEP) % 180
                update_servos()
                print(f"서보모터 2 각도: {angle2}도")

        elif command == '6':
            if running:
                angle1 = (angle1 + STEP) % 180
                angle2 = (angle2 + STEP) % 180
                update_servos()
                print(f"서보모터 1: {angle1}도, 서보모터 2: {angle2}도")

        elif command == '7':
            # 서보모터 완전 정지
            servo1.deinit()
            servo2.deinit()
            running = False
            print("서보모터 완전 정지됨")

        elif command == "8":
            angle1 = 90
            angle2 = 90
            servo1 = PWM(Pin(16))
            servo2 = PWM(Pin(17))
            servo1.freq(50)
            servo2.freq(50)
            update_servos()
            print("서보모터 초기화 (90도)")

        else:
            print("알 수 없는 명령입니다. 1~8 중 입력하세요.")

except KeyboardInterrupt:
    servo1.deinit()
    servo2.deinit()
    print("프로그램 종료")

image.png

2. 미디어파이프로 피코 제어

import cv2
import mediapipe as mp

# Mediapipe 손 추적 설정
mp_hands = mp.solutions.hands
mp_drawing = mp.solutions.drawing_utils
hands = mp_hands.Hands(
    max_num_hands=1,
    min_detection_confidence=0.7,
    min_tracking_confidence=0.7
)

# 버튼 클래스 정의
class Button:
    def __init__(self, x, y, w, h, label):
        self.x, self.y, self.w, self.h = x, y, w, h
        self.label = label
        self.clicked = False

    def draw(self, img):
        color = (0, 255, 0) if self.clicked else (200, 200, 200)
        cv2.rectangle(img, (self.x, self.y), (self.x+self.w, self.y+self.h), color, -1)
        cv2.putText(img, self.label, (self.x+30, self.y+50), cv2.FONT_HERSHEY_SIMPLEX, 1.5, (0, 0, 0), 3)

    def check_click(self, px, py):
        if self.x < px < self.x + self.w and self.y < py < self.y + self.h:
            self.clicked = True
        else:
            self.clicked = False

# 버튼 배열 생성
buttons = []
for i in range(9):
    x = 100 + (i % 3) * 150
    y = 100 + (i // 3) * 150
    buttons.append(Button(x, y, 120, 100, str(i + 1)))

# 웹캠 열기
cap = cv2.VideoCapture(0)
if not cap.isOpened():
    print("❌ 웹캠을 열 수 없습니다.")
    exit()

while True:
    ret, frame = cap.read()
    if not ret:
        print("❌ 프레임을 읽을 수 없습니다.")
        break

    frame = cv2.flip(frame, 1)  # 좌우 반전
    h, w, _ = frame.shape

    # Mediapipe용 RGB 변환
    img_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    results = hands.process(img_rgb)

    index_x, index_y = None, None

    # 손 검출되었을 때
    if results.multi_hand_landmarks:
        for hand_landmarks in results.multi_hand_landmarks:
            # 랜드마크 그리기
            mp_drawing.draw_landmarks(frame, hand_landmarks, mp_hands.HAND_CONNECTIONS)

            # 검지 손가락 끝 좌표 (랜드마크 8번)
            index_tip = hand_landmarks.landmark[8]
            index_x = int(index_tip.x * w)
            index_y = int(index_tip.y * h)

            # 손끝 시각화
            cv2.circle(frame, (index_x, index_y), 10, (255, 0, 255), -1)

            # 버튼 클릭 체크
            for button in buttons:
                button.check_click(index_x, index_y)

    # 버튼 그리기
    for button in buttons:
        button.draw(frame)

    # 화면 출력
    cv2.imshow("Hand Button Interface", frame)

    # 종료 조건
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# 종료 처리
cap.release()
cv2.destroyAllWindows()
hands.close()

<aside> 📌

[과제명][학교][이름] 바꿔주세요, 과제태그를 선생님 설명 듣고 넣어주세요.

</aside>