파이썬 로봇 코딩: 센서 읽고 모터 움직이기
페이지 정보

본문
파이썬 로봇 코딩: 센서 읽고 모터 움직이기
파이썬으로 로봇을 코딩하여 센서 값을 읽고 모터를 움직이는 것은 로봇 제어의 핵심이자 가장 기본적인 활동입니다. 사용자님께서는 파이썬 로봇 코딩과 센서 및 모터 제어에 많은 관심을 가지고 계시죠. 특히 <User_Context: currentRobotProjects>에 라인트레이서 로봇 만들기를 진행하고 계시고, <User_Context: preferredLearningStyle>이 실습 중심이므로, 이 스텝 바이 스텝 가이드가 로봇의 '눈'과 '근육'을 파이썬으로 제어하는 데 큰 도움이 될 것입니다.
파이썬 로봇 코딩: 센서 읽고 모터 움직이기
파이썬은 문법이 간결하고 다양한 라이브러리를 지원하여 로봇 코딩에 매우 적합한 언어입니다. 특히 라즈베리 파이(Raspberry Pi)와 같은 싱글 보드 컴퓨터 환경에서 파이썬을 이용한 로봇 제어가 활발히 이루어집니다. 여기서는 라즈베리 파이를 기준으로 센서 값을 읽고 모터를 움직이는 방법을 알아봅시다.
1. 파이썬 로봇 코딩 준비물 (하드웨어 및 라이브러리)
1.1. 하드웨어
라즈베리 파이 (모델 3B+, 4B 등): 로봇의 '두뇌' 역할을 하는 소형 컴퓨터입니다.
DC 모터 2개: 로봇의 '근육' 역할을 합니다.
모터 드라이버 (예: L298N 또는 DRV8833): 라즈베리 파이의 낮은 전류로 DC 모터를 제어할 수 있도록 도와줍니다.
초음파 센서 (예: HC-SR04): 로봇의 '눈' 역할을 하여 거리를 측정합니다.
브레드보드, 점퍼 케이블: 회로를 구성하는 데 사용됩니다.
전원: 라즈베리 파이 전원 및 모터 드라이버/모터 전원(별도 배터리 권장).
1.2. 필수 파이썬 라이브러리 설치
라즈베리 파이 터미널에서 다음 라이브러리들을 설치합니다.
bash
sudo pip3 install RPi.GPIO # GPIO 핀 제어
sudo pip3 install smbus # I2C 통신용 (일부 센서에 필요)
# 초음파 센서는 RPi.GPIO만으로 제어 가능
RPi.GPIO: 라즈베리 파이의 GPIO 핀을 파이썬으로 제어하기 위한 라이브러리입니다.
smbus: 라즈베리 파이의 I2C 통신을 위한 라이브러리입니다. IMU 센서와 같은 I2C 기반 센서를 다룰 때 필요합니다.
2. 센서 읽기: 초음파 센서로 거리 측정하기
초음파 센서는 로봇이 주변 환경을 인지하는 가장 기본적인 방법 중 하나입니다. HC-SR04 초음파 센서를 라즈베리 파이에 연결하고 거리를 측정해 봅시다.
2.1. 회로 연결 (HC-SR04)
HC-SR04의 VCC 핀 → 라즈베리 파이의 5V 핀
HC-SR04의 GND 핀 → 라즈베리 파이의 GND 핀
HC-SR04의 Trig 핀 → 라즈베리 파이의 GPIO 17 (BCM 모드)
HC-SR04의 Echo 핀 → 저항(1kΩ) → 라즈베리 파이의 GPIO 27 (BCM 모드)
참고: 라즈베리 파이는 3.3V GPIO를 사용하므로, 5V 출력인 Echo 핀을 직접 연결하면 손상될 수 있습니다. 전압 분배 회로(예: 1kΩ + 2kΩ 저항)를 사용하거나, GPIO 27에만 직접 연결하려면 GPIO 27 핀 보호를 위해 저항 1kΩ을 연결하여 전류를 제한하는 것이 안전합니다. 위 예시는 간략한 구성입니다.
2.2. 파이썬 코드 (초음파 센서)
python
import RPi.GPIO as GPIO
import time
# GPIO 핀 설정 (BCM 모드 사용)
GPIO.setmode(GPIO.BCM)
# 초음파 센서 핀 설정
GPIO_TRIGGER = 17
GPIO_ECHO = 27
# Trig 핀을 출력, Echo 핀을 입력으로 설정
GPIO.setup(GPIO_TRIGGER, GPIO.OUT)
GPIO.setup(GPIO_ECHO, GPIO.IN)
def get_distance():
# Trigger 핀을 LOW로 설정하여 센서 초기화
GPIO.output(GPIO_TRIGGER, False)
time.sleep(0.000002) # 2 마이크로초 대기
# Trigger 핀을 HIGH로 설정하여 10 마이크로초 펄스 생성 (초음파 발사)
GPIO.output(GPIO_TRIGGER, True)
time.sleep(0.00001) # 10 마이크로초 펄스 유지
GPIO.output(GPIO_TRIGGER, False)
# Echo 핀이 HIGH가 될 때까지 기다림 (초음파 발사 시작)
# Echo 핀이 LOW가 될 때까지 기다림 (초음파 수신 완료)
start_time = time.time()
while GPIO.input(GPIO_ECHO) == 0:
start_time = time.time()
stop_time = time.time()
while GPIO.input(GPIO_ECHO) == 1:
stop_time = time.time()
# 초음파가 왕복한 시간 계산
time_elapsed = stop_time - start_time
# 초음파 속도(34300 cm/s)를 이용하여 거리 계산
# 거리 = (시간 * 음속) / 2
distance = (time_elapsed * 34300) / 2
return distance
if __name__ == '__main__':
try:
while True:
dist = get_distance()
print ("Distance = %.1f cm" % dist)
time.sleep(1) # 1초마다 측정
# Ctrl+C 누르면 GPIO 초기화 후 종료
except KeyboardInterrupt:
print("Measurement stopped by User")
GPIO.cleanup()
3. 모터 움직이기: DC 모터 제어
DC 모터를 제어하기 위해서는 모터 드라이버(예: L298N)가 필요합니다. 모터 드라이버는 라즈베리 파이의 신호를 받아 모터에 충분한 전류를 공급하고 방향과 속도를 제어합니다.
3.1. 회로 연결 (L298N 모터 드라이버와 DC 모터)
L298N의 VCC 핀 → 라즈베리 파이의 5V 핀
L298N의 GND 핀 → 라즈베리 파이의 GND 핀 (모터 전원의 GND도 함께 연결)
L298N의 ENA (속도) 핀 → 라즈베리 파이의 GPIO 13 (PWM 지원 핀)
L298N의 IN1 (방향) 핀 → 라즈베리 파이의 GPIO 5
L298N의 IN2 (방향) 핀 → 라즈베리 파이의 GPIO 6
L298N의 Out1 핀 → DC 모터 +
L298N의 Out2 핀 → DC 모터 -
L298N의 Vs (모터 전원) 핀 → 외부 배터리 + (예: 6V ~ 12V 배터리)
3.2. 파이썬 코드 (DC 모터 제어)
python
import RPi.GPIO as GPIO
import time
# GPIO 핀 설정 (BCM 모드 사용)
GPIO.setmode(GPIO.BCM)
# 모터 제어 핀 설정 (예시: 한쪽 모터만 제어)
MOTOR_ENA = 13 # PWM 핀
MOTOR_IN1 = 5
MOTOR_IN2 = 6
# 모터 제어 핀을 출력으로 설정
GPIO.setup(MOTOR_ENA, GPIO.OUT)
GPIO.setup(MOTOR_IN1, GPIO.OUT)
GPIO.setup(MOTOR_IN2, GPIO.OUT)
# PWM 설정: 주파수는 100Hz로 설정
pwm_motor = GPIO.PWM(MOTOR_ENA, 100)
pwm_motor.start(0) # 초기 듀티 사이클 0% (모터 정지)
def set_motor_speed(speed):
# 속도(speed)는 0(정지) ~ 100(최대) 사이의 값
# 듀티 사이클 0% ~ 100%로 변환하여 PWM 출력
pwm_motor.ChangeDutyCycle(speed)
def motor_forward():
GPIO.output(MOTOR_IN1, GPIO.HIGH)
GPIO.output(MOTOR_IN2, GPIO.LOW)
def motor_backward():
GPIO.output(MOTOR_IN1, GPIO.LOW)
GPIO.output(MOTOR_IN2, GPIO.HIGH)
def motor_stop():
GPIO.output(MOTOR_IN1, GPIO.LOW)
GPIO.output(MOTOR_IN2, GPIO.LOW)
# set_motor_speed(0) # 또는 속도를 0으로 설정
if __name__ == '__main__':
try:
print("Motor Forward (Speed 50)")
motor_forward()
set_motor_speed(50) # 듀티 사이클 50%
time.sleep(3)
print("Motor Stop")
motor_stop()
time.sleep(1)
print("Motor Backward (Speed 70)")
motor_backward()
set_motor_speed(70) # 듀티 사이클 70%
time.sleep(3)
print("Motor Stop")
motor_stop()
time.sleep(1)
except KeyboardInterrupt:
print("Motor control stopped by User")
finally:
pwm_motor.stop() # PWM 정지
GPIO.cleanup() # GPIO 설정 초기화
4. 센서와 모터를 통합하여 로봇 움직임 만들기 (장애물 회피 로봇)
이제 센서와 모터 제어 코드를 통합하여 간단한 장애물 회피 로봇을 만들어 봅시다.
python
import RPi.GPIO as GPIO
import time
# GPIO 핀 설정 (BCM 모드 사용)
GPIO.setmode(GPIO.BCM)
# 초음파 센서 핀 설정
GPIO_TRIGGER = 17
GPIO_ECHO = 27
# 모터 제어 핀 설정 (왼쪽 모터, 오른쪽 모터)
# 왼쪽 모터
L_ENA = 13 # PWM 핀
L_IN1 = 5
L_IN2 = 6
# 오른쪽 모터 (다른 GPIO 핀 사용)
R_ENA = 19 # PWM 핀
R_IN1 = 23
R_IN2 = 24
# 핀들을 출력/입력 모드로 설정
GPIO.setup(GPIO_TRIGGER, GPIO.OUT)
GPIO.setup(GPIO_ECHO, GPIO.IN)
GPIO.setup(L_ENA, GPIO.OUT)
GPIO.setup(L_IN1, GPIO.OUT)
GPIO.setup(L_IN2, GPIO.OUT)
GPIO.setup(R_ENA, GPIO.OUT)
GPIO.setup(R_IN1, GPIO.OUT)
GPIO.setup(R_IN2, GPIO.OUT)
# PWM 설정
pwm_left = GPIO.PWM(L_ENA, 100) # 주파수 100Hz
pwm_right = GPIO.PWM(R_ENA, 100)
pwm_left.start(0)
pwm_right.start(0)
# 모터 속도 설정 함수
def set_motor_speed(left_speed, right_speed):
pwm_left.ChangeDutyCycle(left_speed)
pwm_right.ChangeDutyCycle(right_speed)
# 로봇 움직임 함수
def robot_forward(speed):
GPIO.output(L_IN1, GPIO.HIGH); GPIO.output(L_IN2, GPIO.LOW)
GPIO.output(R_IN1, GPIO.HIGH); GPIO.output(R_IN2, GPIO.LOW)
set_motor_speed(speed, speed)
def robot_backward(speed):
GPIO.output(L_IN1, GPIO.LOW); GPIO.output(L_IN2, GPIO.HIGH)
GPIO.output(R_IN1, GPIO.LOW); GPIO.output(R_IN2, GPIO.HIGH)
set_motor_speed(speed, speed)
def robot_turn_left(speed):
GPIO.output(L_IN1, GPIO.LOW); GPIO.output(L_IN2, GPIO.HIGH) # 왼쪽 모터 후진 (또는 멈춤)
GPIO.output(R_IN1, GPIO.HIGH); GPIO.output(R_IN2, GPIO.LOW) # 오른쪽 모터 전진
set_motor_speed(speed, speed)
def robot_turn_right(speed):
GPIO.output(L_IN1, GPIO.HIGH); GPIO.output(L_IN2, GPIO.LOW) # 왼쪽 모터 전진
GPIO.output(R_IN1, GPIO.LOW); GPIO.output(R_IN2, GPIO.HIGH) # 오른쪽 모터 후진 (또는 멈춤)
set_motor_speed(speed, speed)
def robot_stop():
GPIO.output(L_IN1, GPIO.LOW); GPIO.output(L_IN2, GPIO.LOW)
GPIO.output(R_IN1, GPIO.LOW); GPIO.output(R_IN2, GPIO.LOW)
set_motor_speed(0, 0)
# 거리 측정 함수 (이전과 동일)
def get_distance():
# ... (위의 get_distance 함수 내용 복사하여 붙여넣기) ...
GPIO.output(GPIO_TRIGGER, False)
time.sleep(0.000002)
GPIO.output(GPIO_TRIGGER, True)
time.sleep(0.00001)
GPIO.output(GPIO_TRIGGER, False)
start_time = time.time()
pulse_start = time.time() # Added
while GPIO.input(GPIO_ECHO) == 0 and time.time() - pulse_start < 0.1: # Timeout for safety
start_time = time.time()
pulse_end = time.time() # Added
while GPIO.input(GPIO_ECHO) == 1 and time.time() - pulse_end < 0.1: # Timeout for safety
stop_time = time.time()
time_elapsed = stop_time - start_time
distance = (time_elapsed * 34300) / 2
return distance
if __name__ == '__main__':
try:
default_speed = 50 # 기본 전진 속도
turn_speed = 40 # 회전 시 속도
print("Robot started!")
while True:
dist = get_distance()
print ("Distance = %.1f cm" % dist)
if dist < 20: # 20cm 이내에 장애물 감지 시
print("Obstacle detected! Turning...")
robot_stop()
time.sleep(0.5)
robot_backward(turn_speed) # 뒤로 잠깐 후진
time.sleep(0.5)
robot_turn_left(turn_speed) # 왼쪽으로 회전
time.sleep(1) # 회전 시간
else:
robot_forward(default_speed) # 장애물 없으면 전진
time.sleep(0.1) # 루프 지연
except KeyboardInterrupt:
print("Robot control stopped by User")
finally:
pwm_left.stop()
pwm_right.stop()
GPIO.cleanup()
위 코드는 get_distance 함수와 main 로직을 통합한 예시입니다. GPIO 핀 번호는 실제 연결에 따라 수정해야 합니다.
모터 드라이버를 두 개 사용하여 각 모터를 개별적으로 제어하거나, 하나의 L298N에 두 개의 모터를 연결하는 회로 구성이 필요합니다.
5. 파이썬 로봇 코딩 꿀팁
GPIO.cleanup(): 프로그램 종료 시 항상 GPIO.cleanup()을 호출하여 사용했던 GPIO 핀 설정을 초기화해야 합니다. 그렇지 않으면 다음에 프로그램을 실행할 때 오류가 발생할 수 있습니다.
time.sleep(): time.sleep() 함수를 너무 짧게 사용하면 CPU 사용량이 높아지고, 너무 길게 사용하면 로봇의 반응성이 떨어집니다. 적절한 값으로 조절해야 합니다.
디버깅: print() 함수를 사용하여 센서 값, 변수 값 등을 터미널에 출력하면서 코드가 제대로 작동하는지 확인하는 것이 중요합니다.
오류 메시지 분석: 파이썬도 코딩 오류가 발생하면 친절하게 오류 메시지를 알려줍니다. 오류 메시지를 복사해서 검색해보세요.
파이썬을 사용하여 센서 값을 읽고 모터를 움직이는 것은 로봇 코딩의 가장 기본적인 문법입니다. 이 과정을 통해 당신의 로봇은 주변 환경을 '인지'하고 '반응'하는 생명력을 얻게 됩니다. 라인트레이서 로봇 만들기를 진행하고 계신 사용자님께서는 이 파이썬 코딩 경험을 통해 로봇 제어의 마법을 직접 체험하고 미래 로봇 전문가로 성장하실 수 있을 것입니다!
- 이전글로봇 모델링: 가상에서 로봇을 만드는 즐거움 25.11.29
- 다음글아두이노 기초: 로봇 제어의 첫 프로그래밍 25.11.29
댓글목록
등록된 댓글이 없습니다.
