[1] GPIO
1. PWM
- 라즈베리파이에서 PWM 신호는 10bit로 컨트롤하며, 따라서 0~1023 의 값을 줄 수 있다.
- 하지만 RPi.GPIO 모듈은 소프트웨어적으로 PWM 신호를 Duty Cycle 값으로 제어할 수 있도록 구현되어 있다.
1) PWM 객체 생성
- 객체 = RPi.GPIO.PWM(핀번호, 주파수)
① 핀번호 : PWM 출력할 핀
② 주파수 : Hz 단위의 주파수로 0보다 큰 값을 입력
2) 소프트웨어 PWM 시작
- 객체.start(듀티비)
- 듀티비 : Duty Cycle % 단위로서의 0~100 사이 숫자 입력
3) Duty Cycle 변경
- 객체.ChangeDutyCycle(듀티비)
4) Frequency 변경
- 객체.ChangeFreqeuncy(주파수)
5) PWM+LED 예제1
pwm_led_test1.py
from RPi import GPIO
led_pin = 22
GPIO.setmode(GPIO.BCM)
GPIO.setup(led_pin, GPIO.OUT)
# 소프트웨어 PWM을 사용하기 위해 객체를 생성
# GPIO.PWM(핀번호, 주파수)
# 핀번호 : PWM을 출력할 핀,
# 주파수 : 0보다 큰 값
pwm = GPIO.PWM(led_pin, 1000)
pwm.start(50) # 소프트웨어 PWM 시작 - 파형을 출력 (매개변수에는 duty cycle 숫자로 0~100까지의 숫자 입력)
time.sleep(3)
pwm.ChangeDutyCycle(100)
try:
while True: # led로 나가는 출력파형이 유지될 수 있도록
pass
except KeyboardInterrupt:
pass
finally:
pwm.stop() # PWM 출력 중지
GPIO.cleanup()
6) PWM+LED 예제2
- LED 가 서서히 밝아졌다가 서서히 어두워지는 것을 반복
pwm_led_exam1.py
from RPi import GPIO
import time
led_pin = 22
GPIO.setmode(GPIO.BCM)
GPIO.setup(led_pin, GPIO.OUT)
pwm = GPIO.PWM(led_pin, 1000)
pwm.start(0)
try:
while True:
for i in range(101):
pwm.ChangeDutyCycle(i)
time.sleep(0.01)
for i in range(100, -1, -1):
pwm.ChangeDutyCycle(i)
time.sleep(0.01)
except KeyboardInterrupt:
pass
finally:
pwm.stop()
GPIO.cleanup()
7) PWM+Buzzer 예제1
- 아두이노에서는 내장 라이브러리의 tone 함수를 이용해 주파수를 조절했음
https://powerstone829.tistory.com/59?category=1014640
[Day42] 2022-03-29(화) 아두이노7 - 부저, 조도센서, PIR센서, 온습도센서, LCD1 - 김서연 강사님
[1] 부저(Piezo Buzzer) - <아두이노 마스터1 우노보드 기초 - 신동욱> p234~243 - 삐 소리를 출력 - 주파수 신호를 주면 음계를 표현할 수 있다. - 능동부저(전원만 연결해도 출력)와 수동부저(전원만
powerstone829.tistory.com
- 라즈베리파이에서는 PWM 객체의 주파수를 조절하여 음계를 표현
- 라즈베리파이 기본 전원이 3.3V이므로, 부저 소리가 작고 떨리는 듯한 소리가 나올 수 있음
- 아래 사이트에서 보면 트랜지스터를 이용해 5V와 연결하여 사용할 수도 있다고 나온다.
https://rasino.tistory.com/332
【라즈베리Pi#20】 피에조 부저 사용하기! with (파이썬 코드)
【라즈베리Pi#20】 피에조 부저 사용하기! with (파이썬 코드) RaspberryPi Buzzer control with Python ! 안녕하세요 라즈이노 IoT 입니다. 이번 시간에는 라즈베리 Pi에서 부저를 사용해 보는 실습을 진행합.
rasino.tistory.com
pwm_buzzer_test1.py
from RPi import GPIO
import time
buzzer_pin = 27
GPIO.setmode(GPIO.BCM)
GPIO.setup(buzzer_pin, GPIO.OUT)
pwm = GPIO.PWM(buzzer_pin, 262) # 4옥타브 도에 해당하는 주파수
pwm.start(50)
time.sleep(2)
pwm.ChangeDutyCycle(0)
pwm.stop()
GPIO.cleanup()
8) PWM+Buzzer 예제2
- 도,레 출력을 3번 반복
pwm_buzzer_tset2.py
from RPi import GPIO
import time
buzzer_pin = 27
GPIO.setmode(GPIO.BCM)
GPIO.setup(buzzer_pin, GPIO.OUT)
pwm = GPIO.PWM(buzzer_pin, 1)
pwm.start(50)
for i in range(0, 3):
pwm.ChangeFrequency(262)
time.sleep(0.5)
pwm.ChangeFrequency(294)
time.sleep(0.5)
pwm.ChangeDutyCycle(0)
pwm.stop()
GPIO.cleanup()
9) PWM+Buzzer 예제3
- 도레미파솔라시도 출력
pwm_buzzer_exam.py
from RPi import GPIO
import time
buzzer_pin = 27
note = [262, 294, 330, 349, 391, 440, 494, 523]
GPIO.setmode(GPIO.BCM)
GPIO.setup(buzzer_pin, GPIO.OUT)
pwm = GPIO.PWM(buzzer_pin, 1)
pwm.start(50)
for i in note:
pwm.ChangeFrequency(i)
time.sleep(0.5)
pwm.ChangeDutyCycle(0)
pwm.stop()
GPIO.cleanup()
10) PWM+Servo Motor 예제1
https://powerstone829.tistory.com/58?category=1014640
[Day41] 2022-03-28(월) 아두이노6 - RGB LED, 서보모터, 초음파센서 - 김서연 강사님
2022-03-28(월) 21:50 수정 - 초음파센서 사용법 수정 [1] RGB LED 제어 - <아두이노 마스터1 우노보드 기초 - 신동욱> p172~179 1. RGB LED 예제1 - R,G,B가 연결된 핀에 각각 PWM 신호로 0~255 값을 랜덤하..
powerstone829.tistory.com
① 주파수 : 50Hz
② 각도 별 듀티비
- 0도 : 2.5%
- 90도 : 7.5%
- 180도 : 12.5%
pwm_servo_test1.py
from RPi import GPIO
import time
servo_pin = 19
GPIO.setmode(GPIO.BCM)
GPIO.setup(servo_pin, GPIO.OUT)
pwm = GPIO.PWM(servo_pin, 50)
pwm.start(2.5) # 서보모터의 초기값을 0으로 설정
time.sleep(2)
pwm.ChangeDutyCycle(0)
pwm.stop()
GPIO.cleanup()
11) PWM+Servo Motor 예제2
- 0~180도까지 서서히 움직이고, 마지막에 다시 0도로 이동
pwm_servo_test2.py
from RPi import GPIO
import time
servo_pin = 19
GPIO.setmode(GPIO.BCM)
GPIO.setup(servo_pin, GPIO.OUT)
pwm = GPIO.PWM(servo_pin, 50)
pwm.start(2.5) # 서보모터의 초기값을 0으로 설정
for i in range(25, 126): # 0: 2.5, 90: 7.5, 180: 12.5
pwm.ChangeDutyCycle(i/10)
time.sleep(0.02)
pwm.ChangeDutyCycle(3)
time.sleep(2)
pwm.ChangeDutyCycle(0)
pwm.stop()
GPIO.cleanup()
12) PWM+Servo Motor 예제3
- 0~180~0도로 이동하는 것을 3번 반복
pwm_servo_exam1.py
from RPi import GPIO
import time
servo_pin = 19
GPIO.setmode(GPIO.BCM)
GPIO.setup(servo_pin, GPIO.OUT)
pwm = GPIO.PWM(servo_pin, 50)
pwm.start(2.5)
for j in range(3):
for i in range(25, 126):
pwm.ChangeDutyCycle(i/10)
time.sleep(0.02)
for i in range(125, 24, -1):
pwm.ChangeDutyCycle(i/10)
time.sleep(0.02)
pwm.ChangeDutyCycle(0)
pwm.stop()
GPIO.cleanup()
13) Servo Motor 임의의 각도로 컨트롤 하기
- 0, 90, 180도는 각각 듀티비가 2.5, 7.5, 12.5 로 정해져 있다.
- 그 외 각도를 구하기 위해서는 해당 각도의 듀티비를 구해야 한다.
- 선형보간법을 이용하여 식을 세운다.
https://ko.wikipedia.org/wiki/%EC%84%A0%ED%98%95_%EB%B3%B4%EA%B0%84%EB%B2%95
선형 보간법 - 위키백과, 우리 모두의 백과사전
선형 보간법(線型補間法, linear interpolation)은 끝점의 값이 주어졌을 때 그 사이에 위치한 값을 추정하기 위하여 직선 거리에 따라 선형적으로 계산하는 방법이다. 두 빨간색 점 사이에 있는 파랑
ko.wikipedia.org
- A(0, 2.5), B(180, 12.5) 두 점을 지나는 직선의 1차함수( duty=f(degree) )를 구하는 것과 같다.
=> duty = degree / 180 * (12.5-2.5) + 2.5
=> duty = degree / 180 * 10 + 2.5
def getDuty(degree):
duty = degree/180*10 + 2.5
return duty # duty값을 리턴
print(getDuty(0)) # 2.5~3
print(getDuty(90)) # 7.5
print(getDuty(180)) # 12.5
print(getDuty(45)) # ?
print(getDuty(120)) # ?
print(getDuty(100)) # ?
14) PWM 종합 예제
# 스위치 2개, 서보모터, LED, 부저
# 스위치1 : +10도씩 서보모터를 이동
# 스위치2 : -10도씩 서보모터를 이동
# 180도 되면 스위치1을 눌러도 180도 유지
# 0도가 되면 스위치2를 눌러도 0도 유지
# 0도와 180도가 되면 부저에서 소리가 출력
# 90도가 되면 led 불 켜지도록 작업
# duty를 구하고 설정하는 것은 함수로 처리
# 나머지도 함수로 처리할 수 있는 것들은 처리해보기
from RPi import GPIO
import time
servo_pin = 19
angle = 0
push_btn1 = 20
push_btn2 = 21
led_pin = 22
buzzer_pin = 26
GPIO.setmode(GPIO.BCM)
GPIO.setup(servo_pin, GPIO.OUT)
GPIO.setup(push_btn1, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(push_btn2, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(led_pin, GPIO.OUT)
GPIO.setup(buzzer_pin, GPIO.OUT)
servo = GPIO.PWM(servo_pin, 50)
servo.start(2.5)
buzzer = GPIO.PWM(buzzer_pin, 262)
buzzer.start(0)
def getDuty(degree):
duty = degree / 180 * 10 + 2.5
return duty
def buzzer_on():
buzzer.ChangeDutyCycle(50)
time.sleep(0.1)
buzzer.ChangeDutyCycle(0)
def check_90():
if angle == 90:
GPIO.output(led_pin, GPIO.HIGH)
else:
GPIO.output(led_pin, GPIO.LOW)
def btn_call1(channel):
global angle
if angle != 180:
angle += 10
servo.ChangeDutyCycle(getDuty(angle))
if angle == 180:
buzzer_on()
check_90()
def btn_call2(channel):
global angle
if angle != 0:
angle -= 10
servo.ChangeDutyCycle(getDuty(angle))
if angle == 0:
buzzer_on()
check_90()
GPIO.add_event_detect(push_btn1, GPIO.RISING, callback=btn_call1, bouncetime=200)
GPIO.add_event_detect(push_btn2, GPIO.RISING, callback=btn_call2, bouncetime=200)
try:
while True:
pass
except KeyboardInterrupt:
pass
finally:
servo.ChangeDutyCycle(2.5)
time.sleep(0.5)
servo.stop()
buzzer.stop()
GPIO.cleanup()
※ 작업 중 GPIO.add_event_detect 관련 이슈
- callback 함수 내에 sleep 으로 딜레이가 있는 경우의 문제
-> sleep이 bouncetime보다 긴 경우, 마치 디바운싱이 안되는 것처럼 callback 함수를 두 번 실행하는 현상 발생
-> 방법1: sleep 시간을 bouncetime보다 짧게 주는 방법
-> 방법2: callback 함수가 실행되는 동안은 event가 detect 되지 않도록 하는 방법
-> 방법1은 내가 원하는 만큼 sleep 시간이나 bouncetime 시간을 줄 수 없는 문제
-> 방법2는 callback 함수가 실행되는 동안에도 event를 detect 해야 하는 경우 문제 발생
-> 어떤 해결 방법이 있을지 찾아보고 고민해 보아야 할 것 같다.
- 끝 -
'프로젝트형 IoT 서비스 개발 4회차 > 3. 게이트웨이 디바이스 제어' 카테고리의 다른 글
[Day54] 2022-04-14(목) 라즈베리파이3 - MQTT1 - 김서연 강사님 (2) | 2022.04.14 |
---|---|
[Day54] 2022-04-14(목) 라즈베리파이 준비7 - Visual Studio Code - 김서연 강사님 (0) | 2022.04.14 |
[Day52] 2022-04-12(화) 라즈베리파이1 - GPIO1(PUSH버튼) - 김서연 강사님 (0) | 2022.04.12 |
[Day52] 2022-04-12(화) 라즈베리파이 준비6 - Camera 연결 - 김서연 강사님 (0) | 2022.04.12 |
[Day52] 2022-04-12(화) 라즈베리파이 준비5 - 한글 폰트 세팅 - 김서연 강사님 (0) | 2022.04.12 |