본문으로 바로가기
반응형

PWM

PWM(Pulse Width Modulation => 펄스 폭 변조)는 디지털 출력으로 아날로그 회로를 제어하는 기술이다.

일정한 주기 내에서 Duty 비를 변화시켜서 평균 전압을 제어하는 기술이다.

이때 모터나 센서가 on되는 시간을 duty라고 한다.
duty가 50이다 -> 전체에서 50퍼만 쓴다라는 뜻으로 해석할 수 있다.
(모터의 속도조절은 PWM의 기술을 사용한것이라고 한다)

엘레베이터로 예시를 들어보자.
엘레베이터를 타고 제일 꼭대기층에 간다고하면,
고속으로 가다가 해당층에 도달하면 천천히 줄어들면서 멈춘다.( -> 목표에 도달하면서 모터의 힘을 서서히 바꾸는 것)
이 기술의 원리가 PWM 기술을통해 duty를 점점 줄이면서 작동하는 원리라고 볼 수 있다.

 

직류에서는 0, 1 밖에 존재하지 않는데 어떻게 5V에서 2.5V의 힘을 줄 수 있을까?(어떻게 duty를 조절할 수 있을까?)

 

0을 보내는 신호일때 0V, 1을 보내는 신호일때는 5V의 전압을 준다고 가정해보자.

만약 어떤 기기가 1초에 5V의 힘을 낸다고 가정하면,

1초 동안 2.5V의 힘을 얻고싶을때는 1초 동안 5V의 힘을 내는 받는 기기를 0.5초 동안의 힘만 내면 된다.

따라서 대략적인 그래프로 표현했을때 0.5초 동안 받는 5V와 1초 동안 받는 2.5V의 면적(duty)이 같다고 볼 수 있다.

 

 

두 그래프의 면적이 같다고 볼 수 있다

 

 

이제 PWM의 원리를 적용하여 LED의 밝기를 조절해보자.

하얀색 LED의 + 극에 21번핀,

                   - 에 GND를 연결해서 해당 코드를 실행해보자.

 

1. PWM의 원리를 이용하여 LED의 밝기를 변화시키는 회로와 코드 작성

#-*-coding: utf-8-*-
# 파일이름 : ledPwm1.py

import RPi.GPIO as GPIO
import time

ledPin = 21

GPIO.setmode(GPIO.BCM)
GPIO.setup(ledPin, GPIO.OUT)

p = GPIO.PWM(ledPin, 255)

p.start(0)

try:
   while True:
      for i in range(20):
         p.ChangeDutyCycle(5*i)
         time.sleep(0.1)
      for i in reversed(range(20)):
         p.ChangeDutyCycle(5*i)
         time.sleep(0.1)

except KeyboardInterrupt:
   print()
   GPIO.cleanup()

하얀색 LED가 밝아졌다가 어두워지는 것을 확인할 수 있다

이러한 원리로 무드등 제어의 원리를 알 수 있다.

 

 

2. 밝기를 직접 입력하여 LED 밝기를 조절하는 코드 작성

#-*-coding: utf-8-*-
# 파일이름 : ledPwm.py

import RPi.GPIO as GPIO

ledPin = 21

GPIO.setmode(GPIO.BCM)
GPIO.setup(ledPin, GPIO.OUT)

p = GPIO.PWM(ledPin, 255)
p.start(0)

while True:
   d = input("Enter Brightness(0 to 100) : ")  # LED 밝기 입력
   duty = int(d)                               # 입력받은 값이 정수인지 확인

   if(duty == 100):
      p.stop()
      GPIO.cleanup()
      break
   else:
      p.ChangeDutyCycle(duty)

입력한 숫자에따라 LED의 밝기가 달라진다.

 

 

초음파 센서 제어

초음파 센서는 주파수를 보냈을때의 시간과 주파수를 보낸후 반사되어 돌아오는 시간의 차이를 측정해서 대략적인 거리를 알 수 있게하는 센서이다.

출처 : http://www.3demp.com/community/boardDetails.php?cbID=124

Trig핀에 10u/s의 트리거 신호를 주면 초음파를 발생시켜서 물체에 쏘고, 

Echo 핀에서 초음파가 돌아오는 시점의 시간을 측정하여 거리를 재는 원리이다.

 

 

라즈베리파이를 통해 초음파 센서를 제어해보자.

출처 : https://steemkr.com/arduino/@jhis21c/45kpa4

맨 왼쪽 VCC 자리에는 5V,

맨 오른쪽 GND 자리에는 그라운드,

왼쪽에서 두번째 Trig 자리에는 14번핀,

오른쪽에서 두번째 Echo 자리에는 4번 핀에 연결하고 밑의 코드를 실행해보자.

 

3. 초음파 센서 제어

#-*-coding: utf-8 -*-
# 파일이름 : ultrasonic01.py

import RPi.GPIO as GPIO
import time

triggerPin = 14
echoPin = 4

GPIO.setmode(GPIO.BCM)
GPIO.setup(triggerPin, GPIO.OUT)   # 트리거핀을 출력으로 사용
GPIO.setup(echoPin, GPIO.IN)       # 에코핀을 입력으로 사용

try:
    while True:
      #구형파 발생
      GPIO.output(triggerPin, GPIO.LOW)  # 10m/s 동안 초음파를 쏴야함
      time.sleep(0.00001)                # 기초단위가 1초라서 10us는 10의 마이너스 5승으로 처리
      GPIO.output(triggerPin, GPIO.HIGH)

      #시간측정
      while GPIO.input(echoPin) == 0:  # 펄스 발생(초음파 전송이 끝나는 시간을 start에 저장)
         start = time.time()
      while GPIO.input(echoPin) == 1:  # 펄스 돌아옴(초음파 수신이 완료될때까지의 시간을 stop에 저장)
         stop = time.time()

      rtTotime = stop - start   # 리턴 투 타임 = (end시간 - start시간)

      # 거리 = 시간 * 속력
      # 이때 소리의  속력은 340m/s인데 cm로 단위를 바꿔줘야함=> 34000 cm/s
      # 그리고 340m/s 는 왕복속도라서 편도로 봐야하니 나누기 2를 해줘야함
      distance = rtTotime * ( 34000 / 2 )
      print("distance : %.2f cm" %distance) # 거리를 출력
      time.sleep(1)  # 1초마다 받아옴

except KeyboardInterrupt:
   GPIO.cleanup()

초음파센서에 손이나 물건을 갖다대서 거리 수치 변화를 관찰해보자

 

 

4. 초음파센서와 부저센서를 이용한 후방감지센서 만들기

초음파센서를통해 물체와의 거리를 잴 수 있게 됬으니, 자동차의 후방센서를 구현해보자.

초음파센서에 물체와의 거리가 점점 좁혀지면 부저센서에서 더 빠르게 소리를 출력하는 원리를 구현해보자.

회로구성

 #-*-coding: utf-8 -*-

import RPi.GPIO as GPIO
import time

triggerPin = 14
echoPin = 4
pinPiezo = 21

GPIO.setmode(GPIO.BCM)
GPIO.setup(triggerPin, GPIO.OUT)    # 출력
GPIO.setup(echoPin, GPIO.IN)        # 입력
GPIO.setup(pinPiezo, GPIO.OUT)

Buzz = GPIO.PWM(pinPiezo, 440)      # 부저센서 초기화

try:
   while True:
      #구형파 발생
      GPIO.output(triggerPin, GPIO.LOW)  
      time.sleep(0.00001) 
      GPIO.output(triggerPin, GPIO.HIGH)

      #시간측정
      while GPIO.input(echoPin) == 0:  # 펄스 발생
         start = time.time()
      while GPIO.input(echoPin) == 1:  # 펄스 돌아옴
         stop = time.time()

      rtTotime = stop - start                   # 리턴 투 타임 = (end시간 - start시간)

      distance = rtTotime * (34000 / 2 )
      print("distance : %.2f cm" %distance)     # 거리 출력
      time.sleep(0.2)  

      if(distance <= 40 and distance > 25):     # 26 ~ 40 cm 일때
         Buzz.start(50)
         Buzz.ChangeFrequency(523)
         time.sleep(0.3)
         Buzz.stop()
         time.sleep(0.3)
      elif(distance <= 25 and distance > 10):   # 25 ~ 11 cm 일때
         Buzz.start(50)
         Buzz.ChangeFrequency(523)
         time.sleep(0.15)
         Buzz.stop()
         time.sleep(0.1)
      elif(distance <= 10):                     # 10cm 이하일때
         Buzz.start(99)
         Buzz.ChangeFrequency(523) 
         time.sleep(0.05)
         Buzz.stop()
         time.sleep(0.05)
      else:                                     # 그 외(겁나 멀때)
         Buzz.stop()
         time.sleep(0.5)

except KeyboardInterrupt:
   GPIO.cleanup()

영상을 확인해보면 거리에따라 부저센서가 울리는 빈도수 변화를 관찰할 수 있다.

 

반응형