라즈베리파이에서 yolov5와 mg996r 서보모터를 연동하고 싶습니다 모터 드라이버는 pca9685를 사용하고 로버플로우를 통해서 플라스틱,캔,페트,종이 4가지를 이미지 학습을 진행했고 분류하는거까지 확인했고 서보모터코드도 따로 실행시켜서 동작하는거 확인했습니다 그런데 서보모터 동작하는 코드와 객체인식 코드를 합치니 객체 인식은 되는데 서보모터가 동작하질 않습니다
터미널 창에는
Setting servo 0 to angle 40 (duty cycle: 4177)
Setting servo 1 to angle 100 (duty cycle: 6844)
Setting servo 2 to angle 100 (duty cycle: 6844)
Current classes: {'Can'}
Current classes: {'Can'}
Current classes: {'Can'}
Detected: Can
Exit program
이러고 서보모터는 동작을 안하고 프로그램이 종료됩니다
밑에는 전체 코드입니다
import torch
import cv2
from PIL import Image
import time
import board
import busio
from adafruit_pca9685 import PCA9685
import threading
모델 로드
model = torch.hub.load('ultralytics/yolov5', 'custom', path='/home/JDH/pr/yolov5/best.pt') # custom 모델 경로 지정
카메라 설정
cap = cv2.VideoCapture(0) # 라즈베리파이 카메라 일반적으로 0번 디바이스 사용
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640) # 프레임 너비 설정
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480) # 프레임 높이 설정
PCA9685 PWM 컨트롤러 초기화
i2c = busio.I2C(board.SCL, board.SDA)
pca9685 = PCA9685(i2c)
pca9685.frequency = 60
서보모터 초기 설정 (서보1번 40도, 서보2,3번 100도)
def initialize_servos():
print("Initializing servos")
set_servo_angle(0, 40)
set_servo_angle(1, 100)
set_servo_angle(2, 100)
서보모터 제어 함수
def set_servo_angle(channel, angle):
pulse = (650 - 150) * angle / 180 + 150 # 각도에 따른 펄스 계산
duty_cycle = int(pulse * 0xFFFF / 4096) # 듀티 사이클 계산
print(f"Setting servo {channel} to angle {angle} (duty cycle: {duty_cycle})")
pca9685.channels[channel].duty_cycle = duty_cycle # 해당 채널에 듀티 사이클 설정
전역 변수
detected_class = None
consecutive_detections = {}
running = True
초기화
initialize_servos()
def read_frames():
global detected_class, running
detection_counts = {}
while running:
ret, frame = cap.read()
if not ret:
print("Failed to capture frame")
break
# OpenCV 이미지를 PIL 이미지로 변환
img = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
results = model(img)
# 결과 분석
current_classes = set()
for detection in results.pred[0]:
_, _, _, _, _, cls = detection
class_name = results.names[int(cls)]
current_classes.add(class_name)
# 디버깅을 위한 출력
print(f"Current classes: {current_classes}")
# 연속 감지 카운트
for class_name in current_classes:
if class_name in detection_counts:
detection_counts[class_name] += 1
else:
detection_counts[class_name] = 1
# 3회 연속 감지 확인
if detection_counts[class_name] >= 3:
detected_class = class_name
running = False
break
# 감지되지 않은 클래스는 카운트 초기화
for class_name in detection_counts:
if class_name not in current_classes:
detection_counts[class_name] = 0
# 매 프레임마다 키 입력 확인
if cv2.waitKey(1) & 0xFF == ord('q'): # q를 누르면 종료
running = False
break
def control_servos():
global detected_class, running
while running:
time.sleep(0.1)
if detected_class:
print(f"Detected: {detected_class}") # 감지된 객체 출력
if detected_class == 'pet':
set_servo_angle(0, 0)
time.sleep(2)
set_servo_angle(0, 40)
time.sleep(2)
set_servo_angle(1, 25)
time.sleep(2)
set_servo_angle(1, 100)
elif detected_class == 'plastic':
set_servo_angle(0, 80)
time.sleep(2)
set_servo_angle(0, 40)
time.sleep(2)
set_servo_angle(1, 175)
time.sleep(2)
set_servo_angle(1, 100)
elif detected_class == 'paper':
set_servo_angle(0, 0)
time.sleep(2)
set_servo_angle(0, 40)
time.sleep(2)
set_servo_angle(2, 25)
time.sleep(2)
set_servo_angle(2, 100)
elif detected_class == 'can':
set_servo_angle(0, 80)
time.sleep(2)
set_servo_angle(0, 40)
time.sleep(2)
set_servo_angle(2, 175)
time.sleep(2)
set_servo_angle(2, 100)
프레임 읽기와 처리 스레드 시작
read_thread = threading.Thread(target=read_frames)
servo_thread = threading.Thread(target=control_servos)
read_thread.start()
servo_thread.start()
read_thread.join()
servo_thread.join()
cap.release()
pca9685.deinit() # PCA9685 리소스 정리
print("Exit program")