필자는 예전에 부저장치를 이용한 라즈베리파이로 구동 하는 '부저 피아노' 를 연습용 프로그래밍 개발로 내놓은 적이 있다. [바로가기]

당시 포스팅의 목적은 라즈베리파이의 유용성과 파이썬 프로그래밍의 유용성을 알리기 위함이 목적 이었다면 이번 포스팅은 파이썬 그 자체만의 유용성을 알리고자 하는 목적이 될 것이다.

이번 프로그래밍 가이드는 순수히 파이썬만 활용하고 gui 디스플레이 기반의 유명한 교육용 게임 제작 모듈인 'pygame' 을 적극적으로 활용할 것이다.

그리고 해당 모듈을 활용하기 위해서는 모듈을 다운받아 파일 시스템에 적용 시켜야 한다.

pygame 모듈을 활용하여 키눌림과 키올라감을 감지하는 이벤트 처리와 동시에 음악을 재생하는 모듈도 pygame으로 활용하기로 한다. 

리눅스 우분투라면 간단히

-- 터미널 텍스트 박스 (Terminal text box) --

<Drag와 복사가 가능합니다.>



user@user-test:~$ sudo apt-get install python-pygame


-> 로써 모듈을 바로 설치하여 프로그래밍 할 수 있다.




혹은 http://www.lfd.uci.edu/~gohlke/pythonlibs/#pygame 에 접속하여 자신의 시스템에 맞는 모듈을 직접 다운받아

-- 터미널 텍스트 박스 (Terminal text box) --

<Drag와 복사가 가능합니다.>


user@user-test:~$ sudo pip install <파일명.whl>


-> 로써 모듈을 설치 한다.




다음으로는 소리를 재생할 음악파일을 다운 받는다. 

음악소스 파일은 망태기님 블로그의 음원 http://blog.daum.net/_blog/BlogTypeView.do?blogid=0S5D7&articleno=854 을 그대로 활용한다.



-- 터미널 텍스트 박스 (Terminal text box) --

<Drag와 복사가 가능합니다.>

// 터미널에서 바로 파일명을 지정하여 다운받자.


user@user-test:~$ wget -O 1.mp3 https://t1.daumcdn.net/cfile/blog/186170454F44FE8911

user@user-test:~$ wget -O 2.mp3 https://t1.daumcdn.net/cfile/blog/156322454F44FE8A0F

user@user-test:~$ wget -O 3.mp3 https://t1.daumcdn.net/cfile/blog/1765AC454F44FE8B0C

user@user-test:~$ wget -O 4.mp3 https://t1.daumcdn.net/cfile/blog/116018454F44FE8C13

user@user-test:~$ wget -O 5.mp3 https://t1.daumcdn.net/cfile/blog/14605A454F44FE8D12

user@user-test:~$ wget -O 6.mp3 https://t1.daumcdn.net/cfile/blog/12586D454F44FE8E18

user@user-test:~$ wget -O 7.mp3 https://t1.daumcdn.net/cfile/blog/1658CC454F44FE8F1C

user@user-test:~$ wget -O 8.mp3 https://t1.daumcdn.net/cfile/blog/125876454F44FE901E



소스코드는 다음과 같다.

              Source_File name : py_piano.py           |           Type : python             |                        |           


# -*- coding:utf-8 -*-
import pygame, time

from pygame.locals import *
pygame.init()	#pygame 라이브러리를 로드 한다.

display_screen = pygame.display.set_mode((815, 85)) # 디스플레이 창 크기 설정

pygame.display.set_caption('MINI PYTHON PIANO')	# 디스플레이 이름

pygame.mouse.set_visible(1)	# 마우스 커서 활성화

white = (255, 255, 255)	# 색 지정

black = (0, 0, 0)

display_font = pygame.font.Font('/usr/share/fonts/truetype/nanum/NanumBarunGothic.ttf', 32) # 폰트 지정

text = (u"키보드 1~8까지 꾸욱 눌러 보세요. \n Esc키를 누르면 종료 됩니다.")	# 유니코드 인코딩으로 텍스트 설계

display_text = display_font.render(text, True, black, white)	# 설게한 텍스트를 랜더링 한다.

display_text_vis = display_text.get_rect()	# 디스플레이에 표시

display_text_vis.center = (340, 34)	# # 디스플레이에 표시되는 위치 설정

def mp(file):	# 소리 파일을 불러 오는 파일을 불러오는 함수
	pygame.mixer.music.load(file)
	
while True:

	display_screen.fill(white)	# 디스플레이의 배경색 지정
	
	display_screen.blit(display_text, display_text_vis)	# 디스플레이에 텍스트 표시
	
	pygame.display.update()	# 디스플레이를 계속 업데이트 한다.

	for event in pygame.event.get():	# 이벤트 시작
      
      
		if (event.type == KEYDOWN):	# 키를 눌렀을 경우 mp함수가 음악 파일을 불러오고 pygame모듈이 재생
			if (event.key == pygame.K_1):

				mp("1.mp3")
				pygame.mixer.music.play()
 
      
		if (event.type == KEYDOWN):
     			if (event.key == pygame.K_2):

				mp("2.mp3")
				pygame.mixer.music.play()
     
		if (event.type == KEYDOWN):
     			if (event.key == pygame.K_3):

				mp("3.mp3")
				pygame.mixer.music.play()
			
		if (event.type == KEYDOWN):
     			if (event.key == pygame.K_4):

				mp("4.mp3")
				pygame.mixer.music.play()
			
		if (event.type == KEYDOWN):
     			if (event.key == pygame.K_5):

				mp("5.mp3")
				pygame.mixer.music.play()
			
		if (event.type == KEYDOWN):
     			if (event.key == pygame.K_6):

				mp("6.mp3")
				pygame.mixer.music.play()
		if (event.type == KEYDOWN):
     			if (event.key == pygame.K_7):

				mp("7.mp3")
				pygame.mixer.music.play()
		if (event.type == KEYDOWN):
     			if (event.key == pygame.K_8):

				mp("8.mp3")
				pygame.mixer.music.play()
				
		if (event.type == KEYUP):	# 키가 올라갔을때(땠을 때) 재생을 중단 시킴


     			pygame.mixer.music.stop()
      
      
		if (event.type == KEYUP):	# esc 키를 누르고 땠을때 종료 실행
      			if (event.key == pygame.K_ESCAPE):

      				pygame.quit()
	
		if event.type == QUIT:	# 창을 종료 했을때 정상 종료 수행
			pygame.quit()




-- 터미널 텍스트 박스 (Terminal text box) --

<Drag와 복사가 가능합니다.>

// 코딩이 완료 되었다면 실행해 보자.


user@user-test:~$ python py_piano.py



키보드의 키 1~8(도레미파솔라시도) 를 눌러 보고 눌렀다 때 보면서 음의 길이도 조절이 되는지를 테스트해 보자.



도움이 되셨다면 '♡' 버튼을 꼭눌러 주시면 감사 하겠습니다.


그리고 글에 부족한 점이 있거나 틀린 점, 더 궁금한 부분이 있는 것 같다면 꼭 댓글로 알려 주시 감사 하겠습니다.

         






패시브 부저의 소리를 직접 제어하는 전자 피아노 처럼 만들수 있을까 하는 생각으로 한번 제작해 보았습니다.

부저 (buzzer)는 총 크게 두가지 나누어 집니다.

    패시브 부저 (passive buzzer) : 음의 출력 시간 대역폭을 이용하여 여러 음역대의 소리를 재생하는 것이 가능한 부저.

    액티브 부저 (active buzzer) : 음이 소리가 단일적으로 단조로우며 활용할수 있는 것은 출력의 크기 뿐 이다.


해당 프로젝트는 이중 패시브 부저를 이용하여 컴퓨터의 키보드를 피아노 건반으로 사용하는 부저 피아노 시스템 입니다.

준비물 :

      PASSIVE_BUZZER X1
        TRANSISTOR X1
        LED X1
        1kΩ x1

       

라즈베리파이의 GPIO 시스템과 각 연결 상태는 이러합니다.

      5V -> PASSIVE_BUZZER_1 (+) -> LED_1 (+)

        GPIO_18 -> 1KΩ -> TRANSITOR1(2)
                TRNSISTOR_1(1) -> PASSIVE_BUZZER1 (-) -> LED_1 (-)


        GND -> TRNSISTOR_1(3)



실행 구조 :

    buano (bash)
        - pb1.py (python)


소스 코드 :


buano


#!/bin/bash

trap 'killall -9 python' 0
while [ : ]; do
clear
echo "
            << buano >>

This proram source is buzzer piano by rasberrypi on python module.

Maintainer : C O S M O S project. <cosmosproject15@gmail.com>
Homepage : http://cosmosproject2015.tistory.com
"
read -n 1 -p "input [keyboard]:" pia

    if [ "$pia" = "q" ]; then
        sed -i 's/number/250/g' pb1.py
        python pb1.py
        sed -i 's/250/number/g' pb1.py
    fi
    if [ "$pia" = "w" ]; then

        sed -i 's/number/340/g' pb1.py
        python pb1.py
        sed -i 's/340/number/g' pb1.py


    fi
    if [ "$pia" = "e" ]; then
        sed -i 's/number/420/g' pb1.py
        python pb1.py
        sed -i 's/420/number/g' pb1.py

    fi
    if [ "$pia" = "r" ]; then
        sed -i 's/number/500/g' pb1.py
        python pb1.py
        sed -i 's/500/number/g' pb1.py

    fi

    if [ "$pia" = "t" ]; then
        sed -i 's/number/580/g' pb1.py
        python pb1.py
        sed -i 's/580/number/g' pb1.py
    fi
    if [ "$pia" = "y" ]; then

        sed -i 's/number/640/g' pb1.py
        python pb1.py
        sed -i 's/640/number/g' pb1.py


    fi
    if [ "$pia" = "u" ]; then
        sed -i 's/number/710/g' pb1.py
        python pb1.py
        sed -i 's/710/number/g' pb1.py

    fi
    if [ "$pia" = "i" ]; then
        sed -i 's/number/780/g' pb1.py
        python pb1.py
        sed -i 's/780/number/g' pb1.py

    fi
    if [ "$pia" = "o" ]; then
        sed -i 's/number/850/g' pb1.py
        python pb1.py
        sed -i 's/850/number/g' pb1.py
    fi
    if [ "$pia" = "p" ]; then

        sed -i 's/number/930/g' pb1.py
        python pb1.py
        sed -i 's/930/number/g' pb1.py


    fi
    if [ "$pia" = "a" ]; then
        sed -i 's/number/1000/g' pb1.py
        python pb1.py
        sed -i 's/1000/number/g' pb1.py

    fi
    if [ "$pia" = "s" ]; then
        sed -i 's/number/1080/g' pb1.py
        python pb1.py
        sed -i 's/1080/number/g' pb1.py

    fi
    if [ "$pia" = "d" ]; then
        sed -i 's/number/1140/g' pb1.py
        python pb1.py
        sed -i 's/1140/number/g' pb1.py
    fi
    if [ "$pia" = "f" ]; then

        sed -i 's/number/1220/g' pb1.py
        python pb1.py
        sed -i 's/1220/number/g' pb1.py


    fi
    if [ "$pia" = "g" ]; then
        sed -i 's/number/1300/g' pb1.py
        python pb1.py
        sed -i 's/1300/number/g' pb1.py

    fi
    if [ "$pia" = "h" ]; then
        sed -i 's/number/1380/g' pb1.py
        python pb1.py
        sed -i 's/1380/number/g' pb1.py

    fi
    if [ "$pia" = "j" ]; then
        sed -i 's/number/1430/g' pb1.py
        python pb1.py
        sed -i 's/1430/number/g' pb1.py
    fi
    if [ "$pia" = "k" ]; then

        sed -i 's/number/1500/g' pb1.py
        python pb1.py
        sed -i 's/1500/number/g' pb1.py


    fi
    if [ "$pia" = "l" ]; then
        sed -i 's/number/1570/g' pb1.py
        python pb1.py
        sed -i 's/1570/number/g' pb1.py

    fi
    if [ "$pia" = "z" ]; then
        sed -i 's/number/1630/g' pb1.py
        python pb1.py
        sed -i 's/1630/number/g' pb1.py

    fi

    if [ "$pia" = "x" ]; then
        sed -i 's/number/1710/g' pb1.py
        python pb1.py
        sed -i 's/1710/number/g' pb1.py
    fi
    if [ "$pia" = "c" ]; then

        sed -i 's/number/1800/g' pb1.py
        python pb1.py
        sed -i 's/1800/number/g' pb1.py


    fi
    if [ "$pia" = "v" ]; then
        sed -i 's/number/1870/g' pb1.py
        python pb1.py
        sed -i 's/1870/number/g' pb1.py

    fi
    if [ "$pia" = "b" ]; then
        sed -i 's/number/1920/g' pb1.py
        python pb1.py
        sed -i 's/1920/number/g' pb1.py

    fi
    if [ "$pia" = "n" ]; then
        sed -i 's/number/2000/g' pb1.py
        python pb1.py
        sed -i 's/2000/number/g' pb1.py
    fi
    if [ "$pia" = "m" ]; then

        sed -i 's/number/2080/g' pb1.py
        python pb1.py
        sed -i 's/2080/number/g' pb1.py


    fi
    if [ "$pia" = "," ]; then
        sed -i 's/number/2140/g' pb1.py
        python pb1.py
        sed -i 's/2140/number/g' pb1.py

    fi
    if [ "$pia" = "." ]; then
        sed -i 's/number/2200/g' pb1.py
        python pb1.py
        sed -i 's/2200/number/g' pb1.py

    fi

done

exit 0



pb1.py

import RPi.GPIO as GPIO  
import time              


class Buzzer(object):
 def __init__(self):
  GPIO.setmode(GPIO.BCM) 
  self.buzzer_pin = 18
  GPIO.setup(self.buzzer_pin, GPIO.IN)
  GPIO.setup(self.buzzer_pin, GPIO.OUT)


 def __del__(self):
  class_name = self.__class__.__name__

## Create the function 'buzz'

 def buzz(self,pitch, duration):  
 
  if(pitch==0):
   time.sleep(duration)
   return
  period = 1.0 / pitch    
  delay = period / 2    
  cycles = int(duration * pitch) 

## Set cycles for GPIO.output

  for i in range(cycles):   
   GPIO.output(self.buzzer_pin, True)  
   time.sleep(delay)  
   GPIO.output(self.buzzer_pin, False)   
   time.sleep(delay)   

 def play(self, tune):
  GPIO.setmode(GPIO.BCM)
  GPIO.setup(self.buzzer_pin, GPIO.OUT)
  x=0

## Set the pitch and duration.

  if(tune==1):
    pitches=[number]
    duration=0.1
    for p in pitches:
      self.buzz(p, duration) 
      time.sleep(duration *0.5)


  GPIO.setup(self.buzzer_pin, GPIO.IN)

## Play start

if __name__ == "__main__":
  buzzer = Buzzer()
  buzzer.play(int(1))
GPIO.cleanup()



실행 :


./buano



소스 다운로드 :


github : https://github.com/cosmosproject15/pi-buano



$ git clone https://github.com/cosmosproject15/pi-buano










   
 

+ Recent posts