from grove_rgb_lcd import setText, setRGB
import grovepi
import RPi.GPIO as GPIO
import time
import cv2
import numpy as np
# GPIO 핀 설정
# LED 부분
LED_RED = 4 # 빨간색 LED 핀
LED_GREEN = 18 # 초록색 LED 핀
# DC모터 부분(GPIO)
ENA = 22 # 모터 1 속도 제어 (PWM 핀)
ENB = 23 # 모터 2 속도 제어 (PWM 핀)
IN1 = 17 # 모터 1 방향 제어 핀 (단방향 고정)
IN3 = 24 # 모터 2 방향 제어 핀 (단방향 고정)
# 초음파 센서 부분(GROVEPI)
ULTRASONIC_PIN_1 = 4 # 초음파 센서 1 (입구 감지용)
ULTRASONIC_PIN_2 = 3 # 초음파 센서 2 (카메라 위치 감지용)
# 서보 모터 부분(GPIO)
SERVO_PIN1 = 27 # 서보 모터 1 제어 핀
SERVO_PIN2 = 2 # 서보 모터 2 제어 핀
# GPIO 초기화
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM) # GPIO 핀 번호를 BCM 모드로 설정
GPIO.setup(LED_RED, GPIO.OUT) # 빨간색 LED 출력 모드 설정
GPIO.setup(LED_GREEN, GPIO.OUT) # 초록색 LED 출력 모드 설정
GPIO.setup(SERVO_PIN1, GPIO.OUT) # 서보 모터 1 출력 모드 설정
GPIO.setup(SERVO_PIN2, GPIO.OUT) # 서보 모터 2 출력 모드 설정
GPIO.setup(ENA, GPIO.OUT) # 모터 1 속도 제어 핀 출력 모드 설정
GPIO.setup(ENB, GPIO.OUT) # 모터 2 속도 제어 핀 출력 모드 설정
GPIO.setup(IN1, GPIO.OUT) # 모터 1 방향 제어 핀 출력 모드 설정
GPIO.setup(IN3, GPIO.OUT) # 모터 2 방향 제어 핀 출력 모드 설정
GPIO.output(IN1, GPIO.LOW)
GPIO.output(IN3, GPIO.LOW)
# PWM 초기화
pwm1 = GPIO.PWM(ENA, 100) # 모터 1 속도 제어용 PWM 생성 (100Hz)
pwm2 = GPIO.PWM(ENB, 100) # 모터 2 속도 제어용 PWM 생성 (100Hz)
servo1 = GPIO.PWM(SERVO_PIN1, 50) # 서보 모터 1 PWM 생성 (50Hz)
servo2 = GPIO.PWM(SERVO_PIN2, 50) # 서보 모터 2 PWM 생성 (50Hz)
pwm1.start(0) # 모터 1 초기 속도 0%
pwm2.start(0) # 모터 2 초기 속도 0%
servo1.start(7) # 서보 모터 1 초기 위치 (0도)
servo2.start(7) # 서보 모터 2 초기 위치 (0도)
# 기준 이미지 로드
reference_images = {
'Plastic': cv2.imread('/home/pi/image1.jpg'), # 플라스틱 기준 이미지
'Paper': cv2.imread('/home/pi/image2.jpg'), # 종이 기준 이미지
'PET': cv2.imread('/home/pi/image3.jpg'), # PET 병 기준 이미지
'Glass': cv2.imread('/home/pi/image4.jpg'), # 유리 기준 이미지
}
# LCD 메시지 출력 함수
def lcd_string(message, line):
"""
Grove RGB LCD에 메시지 출력.
line: 출력할 줄 번호 (1 또는 2)
"""
if line == 1:
setText(message)
elif line == 2:
setText("\n" + message)
# 초음파 센서 거리 측정 함수
def get_distance(pin):
"""
초음파 센서를 이용해 거리를 측정.
pin: 초음파 센서 핀 번호
"""
try:
distance = grovepi.ultrasonicRead(pin) # 거리 값 읽기
return distance
except TypeError:
print("초음파 센서 오류") # 오류 발생 시 출력
return None
def operate_dc_motor(speed, state):
"""
DC 모터를 제어하는 함수 (단방향 회전).
speed: 모터 속도 (0~100)
state: 모터 작동 상태 (1: 작동, 0: 정지)
"""
if state == 1: # 모터 작동
GPIO.output(IN1, GPIO.HIGH) # 모터 1 작동
GPIO.output(IN3, GPIO.HIGH) # 모터 2 작동
pwm1.ChangeDutyCycle(speed) # 모터 1 속도 제어
pwm2.ChangeDutyCycle(speed) # 모터 2 속도 제어
else: # 모터 정지
GPIO.output(IN1, GPIO.LOW) # 모터 1 정지
GPIO.output(IN3, GPIO.LOW) # 모터 2 정지
pwm1.ChangeDutyCycle(0) # 속도 0
pwm2.ChangeDutyCycle(0) # 속도 0
# 쓰레기 분류 함수
def classify_waste(input_image):
"""
입력 이미지를 기준 이미지와 비교하여 쓰레기 종류를 분류.
input_image: 입력 이미지
"""
input_hist = cv2.calcHist([input_image], [0, 1, 2], None, [8, 8, 8], [0, 256, 0, 256, 0, 256]) # 입력 이미지 히스토그램 계산
cv2.normalize(input_hist, input_hist, 0, 1, cv2.NORM_MINMAX) # 히스토그램 정규화
best_match = None
highest_score = -1
for label, ref_image in reference_images.items(): # 기준 이미지와 비교
ref_hist = cv2.calcHist([ref_image], [0, 1, 2], None, [8, 8, 8], [0, 256, 0, 256, 0, 256])
cv2.normalize(ref_hist, ref_hist, 0, 1, cv2.NORM_MINMAX)
score = cv2.compareHist(input_hist, ref_hist, cv2.HISTCMP_CORREL)
if score > highest_score:
highest_score = score
best_match = label
return best_match # 가장 유사한 분류 반환
# 서보 모터 동작
def move_servo(result):
"""
서보 모터를 동작시켜 쓰레기를 분류.
result: 쓰레기 종류
"""
if result == 'Paper':
servo1.ChangeDutyCycle(3) # 30도
servo2.ChangeDutyCycle(12) # 120도
elif result == 'Plastic':
servo1.ChangeDutyCycle(6) # 60도
servo2.ChangeDutyCycle(9) # 90도
elif result == 'PET':
servo1.ChangeDutyCycle(9) # 90도
servo2.ChangeDutyCycle(6) # 60도
elif result == 'Glass':
servo1.ChangeDutyCycle(12) # 120도
servo2.ChangeDutyCycle(3) # 30도
time.sleep(1)
# 메인 반복문
try:
setRGB(0, 255, 0) # LCD 색상 설정
GPIO.output(LED_GREEN, GPIO.HIGH)
while True:
# 초음파 센서 1에서 물체 감지
if get_distance(ULTRASONIC_PIN_1) < 10:
lcd_string("ul 1 check", 1)
GPIO.output(LED_GREEN, GPIO.LOW)
GPIO.output(LED_RED, GPIO.HIGH)
time.sleep(2)
operate_dc_motor(speed=50, state=1)
# 초음파 센서 2에서 물체 감지
if get_distance(ULTRASONIC_PIN_2) < 10:
lcd_string("2 check", 1)
operate_dc_motor(speed=0, state=0) # 모터 정지
# 카메라로 이미지 캡처
camera = cv2.VideoCapture(0)
if not camera.isOpened():
break
ret, frame = camera.read()
camera.release()
if ret and frame is not None:
# 쓰레기 분류
result = classify_waste(frame)
# LCD에 물체 종류 출력
lcd_string(result, 1)
# 서보 모터 동작
move_servo(result)
time.sleep(3)
lcd_string("move", 1)
operate_dc_motor(speed=50, state=1)
time.sleep(3)
operate_dc_motor(speed=0, state=0)
GPIO.output(LED_RED, GPIO.LOW)
GPIO.output(LED_GREEN, GPIO.HIGH)
lcd_string("clear", 1)
time.sleep(2)
# LCD 초기화
lcd_string("", 1)
lcd_string("", 2)
else:
print("이미지를 캡처할 수 없습니다")
except KeyboardInterrupt:
print("프로그램 종료")
finally:
pwm1.stop()
pwm2.stop()
servo1.stop()
servo2.stop()
GPIO.cleanup()
setRGB(0, 0, 0)
setText("")
Raspberry Pi 연결
DC 모터 (L298N 모터 드라이버 사용):
초음파 센서 (GrovePi 사용):
서보 모터:
LED:
전원 연결:
sudo apt-get update sudo apt-get install python3-opencv
테스트
from grove_rgb_lcd import setText, setRGB # Grove RGB LCD 모듈 추가
import grovepi # GrovePi 모듈 제어 라이브러리
import RPi.GPIO as GPIO # Raspberry Pi GPIO 핀 제어 라이브러리
import time # 시간 지연을 위한 라이브러리
import random # 랜덤 분류를 위한 라이브러리
# GPIO 핀 설정
# LED 부분
LED_RED = 4 # 빨간색 LED 핀
LED_GREEN = 18 # 초록색 LED 핀
# DC모터 부분(GPIO)
ENA = 22 # 모터 1 속도 제어 (PWM 핀)
ENB = 23 # 모터 2 속도 제어 (PWM 핀)
IN1 = 17 # 모터 1 방향 제어 핀 (단방향 고정)
IN3 = 24 # 모터 2 방향 제어 핀 (단방향 고정)
# 초음파 센서 부분(GROVEPI)
ULTRASONIC_PIN_1 = 4 # 초음파 센서 1 (입구 감지용)
ULTRASONIC_PIN_2 = 3 # 초음파 센서 2 (카메라 위치 감지용)
# 서보 모터 부분(GPIO)
SERVO_PIN1 = 27 # 서보 모터 1 제어 핀
SERVO_PIN2 = 25 # 서보 모터 2 제어 핀
# GPIO 초기화
GPIO.setmode(GPIO.BCM) # GPIO 핀 번호를 BCM 모드로 설정
GPIO.setup(LED_RED, GPIO.OUT) # 빨간색 LED 출력 모드 설정
GPIO.setup(LED_GREEN, GPIO.OUT) # 초록색 LED 출력 모드 설정
GPIO.setup(SERVO_PIN1, GPIO.OUT) # 서보 모터 1 출력 모드 설정
GPIO.setup(SERVO_PIN2, GPIO.OUT) # 서보 모터 2 출력 모드 설정
# GPIO 초기화
GPIO.setup(ENA, GPIO.OUT) # 모터 1 속도 제어 핀 출력 모드 설정
GPIO.setup(ENB, GPIO.OUT) # 모터 2 속도 제어 핀 출력 모드 설정
GPIO.setup(IN1, GPIO.OUT) # 모터 1 방향 제어 핀 출력 모드 설정
GPIO.setup(IN3, GPIO.OUT) # 모터 2 방향 제어 핀 출력 모드 설정
GPIO.output(IN1, GPIO.LOW)
GPIO.output(IN3, GPIO.LOW)
# PWM 초기화
pwm1 = GPIO.PWM(ENA, 100) # 모터 1 속도 제어용 PWM 생성 (100Hz)
pwm2 = GPIO.PWM(ENB, 100) # 모터 2 속도 제어용 PWM 생성 (100Hz)
servo1 = GPIO.PWM(SERVO_PIN1, 50) # 서보 모터 1 PWM 생성 (50Hz)
servo2 = GPIO.PWM(SERVO_PIN2, 50) # 서보 모터 2 PWM 생성 (50Hz)
pwm1.start(0) # 모터 1 초기 속도 0%
pwm2.start(0) # 모터 2 초기 속도 0%
servo1.start(0) # 서보 모터 1 초기 위치
servo2.start(0) # 서보 모터 2 초기 위치
# 쓰레기 종류 리스트
categories = ['Plastic', 'Paper', 'PET', 'Glass']
# LCD 초기화 함수
def lcd_string(message, line):
"""
Grove RGB LCD에 메시지 출력.
line: 출력할 줄 번호 (1 또는 2)
"""
if line == 1:
setText(message[:LCD_WIDTH]) # 첫 줄에 텍스트 출력
elif line == 2:
setText("\n" + message[:LCD_WIDTH]) # 두 번째 줄로 출력
# 초음파 센서 거리 측정 함수
def get_distance(pin):
"""
초음파 센서를 이용해 거리를 측정.
pin: 초음파 센서 핀 번호
"""
try:
distance = grovepi.ultrasonicRead(pin) # 거리 값 읽기
return distance
except TypeError:
print("초음파 센서 오류") # 오류 발생 시 출력
return None
# 메인 반복문
try:
setRGB(0, 255, 0) # LCD 색상 설정 (초록)
GPIO.output(LED_GREEN, GPIO.HIGH)
while True:
# 초음파 센서 1에서 물체 감지
if get_distance(ULTRASONIC_PIN_1) < 10:
lcd_string("물체 감지", 1)
GPIO.output(LED_GREEN, GPIO.LOW)
GPIO.output(LED_RED, GPIO.HIGH)
time.sleep(2)
lcd_string("컨베이어 벨트 작동", 1)
# 모터 작동
operate_dc_motor(speed=50, state=1)
# 초음파 센서 2에서 물체 감지
if get_distance(ULTRASONIC_PIN_2) < 10:
lcd_string("카메라 아래", 1)
lcd_string("물체 감지", 2)
operate_dc_motor(speed=0, state=0)
result = random.choice(categories)
print(f"분류 결과: {result}")
lcd_string("Classified as:", 1)
lcd_string(result, 2)
move_servo(result)
time.sleep(3)
lcd_string("컨베이어 벨트 작동", 1)
operate_dc_motor(speed=50, state=1)
time.sleep(3)
operate_dc_motor(speed=0, state=0)
GPIO.output(LED_RED, GPIO.LOW)
GPIO.output(LED_GREEN, GPIO.HIGH)
lcd_string("물체 분류 완료", 1)
time.sleep(2)
lcd_string("", 1)
lcd_string("", 2)
time.sleep(2)
except KeyboardInterrupt:
pwm1.stop()
pwm2.stop()
servo1.stop()
servo2.stop()
GPIO.cleanup()
print("프로그램 종료")
finally:
pwm1.stop()
pwm2.stop()
servo1.stop()
servo2.stop()
GPIO.cleanup()
setRGB(0, 0, 0) # LCD 백라이트 끄기
setText("")