概要
Raspberry Pi用キットのアクティブ・ブザー、パッシブ・ブザーの実験。
アクティブ・ブザー
単純接続
アクティブ・ブザーは振動源を内蔵していて、電流が流すだけで音が出る。まず、単純に3.3Vの電源に繋いでみた。
抵抗なしで直接GNDに繋ぐと、「ピュー」という音が鳴る。抵抗値が10Ωで音はかなり小さくなり、100Ωにするとかすかに聞こえるくらいの音になった。
回路図
ブザーを電源に直接GPIOに繋いでもRasberry Piで制御できるが、キットの回路図はPNP型のトランジスターを介して接続していた。GPIOから流れる電流をより少なくするためと思われる。
この回路の場合、GPIOをHIGHにすると音はならず、LOWにするとC-E間にも電流が流れて音が出る。音量は直接3.3Vに繋いだ時と同じ。
コード
以下のコードでは単純にGPIOのHIGH/LOWを切り替えて、一定間隔でブザーを鳴らす。周期を短くすると「ピュピュピュピュ・・・」と連続して鳴動する。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
import RPi.GPIO as GPIO import time # Define GPIO17 pin PIN = 17 # Setup GPIO mode and pin GPIO.setmode(GPIO.BCM) GPIO.setup(PIN, GPIO.OUT, initial=GPIO.HIGH) # Function to end def destroy(): GPIO.output(PIN, GPIO.HIGH) GPIO.cleanup() try: # Repeat buzzing while True: GPIO.output(PIN, GPIO.LOW) time.sleep(0.1) GPIO.output(PIN, GPIO.HIGH) time.sleep(0.1) # Quit when CTRL+C pressed except KeyboardInterrupt: destroy() |
パッシブ・ブザー
ソフトウェアによる音
パッシブブザーは入力の1パルスに対して1回だけクリック音が出る。アクティブ・ブザーと同じ回路図でブザーをパッシブブザーに取り換えて同じコードで実行すると”click, click, …”と単調な音が続く。
ここで入力をある周波数にすると、その周波数に対応した音程のビープ音になる。
以下のコードは440Hzの音を鳴らすもので、設定した周波数の周期で矩形パルスを発生させてAの音を出す。ソフトウェア制御なので、ときどき音が途切れたりする。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
import RPi.GPIO as GPIO import time # Define GPIO17 pin PIN = 17 # Setup GPIO mode and pin GPIO.setmode(GPIO.BCM) GPIO.setup(PIN, GPIO.OUT, initial=GPIO.HIGH) def tone(freq): cycle_time = 1 / freq / 2 while True: GPIO.output(PIN, GPIO.LOW) time.sleep(cycle_time) GPIO.output(PIN, GPIO.HIGH) time.sleep(cycle_time) # Function to end def destroy(): GPIO.output(PIN, GPIO.HIGH) GPIO.cleanup() try: # Make a tone tone(440) # Quit when CTRL+C pressed except KeyboardInterrupt: destroy() |
PWMによる音
上と同様のことを、ハードウェアのPWMで実装したのが下記のコード。
ハードウェアPWMのGPIO13にピンを変えて、周波数やデューティー・サイクルを指定してAの音を2秒間出している。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
import RPi.GPIO as GPIO import time # Define GPIO17 pin PWM_PIN = 13 # Setup GPIO mode and pin GPIO.setmode(GPIO.BCM) GPIO.setup(PWM_PIN, GPIO.OUT) FREQ = 440 PWM = GPIO.PWM(PWM_PIN, FREQ) # Make a tone PWM.start(50) time.sleep(2) # Ending process PWM.ChangeDutyCycle(0) GPIO.cleanup() |
音階
PWMを使ってスケールを鳴らしてみた。
辞書定数で各音階に対応する周波数をセットして、ある周波数の1音を鳴らすクラスを定義。Cのスケールで音階を鳴らしている。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
import RPi.GPIO as GPIO import time # Define GPIO17 pin PWM_PIN = 13 # Setup GPIO mode and pin GPIO.setmode(GPIO.BCM) GPIO.setup(PWM_PIN, GPIO.OUT) # Define tones and frequencies of scale TONES = { 'c4': 261.626, 'd4': 293.655, 'e4': 329.628, 'f4': 349.228, 'g4': 391.995, 'a4': 440.000, 'h4': 493.883, 'c5': 523.251, } # Class to beep a tone class Tone: # Initialize an instance by specifying PWM pin number def __init__(self, pwm_pin): self.pwm = GPIO.PWM(pwm_pin, 1) # Beep a tone by specifying frequency and duration def beep(self, freq, duration): self.pwm.ChangeFrequency(freq) self.pwm.ChangeDutyCycle(0.5) self.pwm.start(50) time.sleep(duration) def none(self, duration): self.pwm.ChangeDutyCycle(0) time.sleep(duration) # Destroy instance by cleaning up pins def destroy(self): self.pwm.ChangeDutyCycle(0) GPIO.cleanup() tone = Tone(PWM_PIN) tone.beep(TONES['c4'], 0.3) tone.none(0.3) tone.beep(TONES['d4'], 0.3) tone.beep(TONES['e4'], 0.3) tone.beep(TONES['f4'], 0.3) tone.beep(TONES['g4'], 0.3) tone.beep(TONES['a4'], 0.3) tone.beep(TONES['h4'], 0.3) tone.beep(TONES['c5'], 0.3) tone.none(0.3) tone.beep(TONES['h4'], 0.3) tone.beep(TONES['a4'], 0.3) tone.beep(TONES['g4'], 0.3) tone.beep(TONES['f4'], 0.3) tone.beep(TONES['e4'], 0.3) tone.beep(TONES['d4'], 0.3) tone.beep(TONES['c4'], 0.3) tone.destroy() |
音楽
改めて音符・給付を並べて音楽を演奏するクラスを定義。ついでにテンポも指定できるようにした。
このクラスを使って、D-durの音階を鳴らしている。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
import RPi.GPIO as GPIO import time # Define GPIO17 pin PWM_PIN = 13 # Setup GPIO mode and pin GPIO.setmode(GPIO.BCM) GPIO.setup(PWM_PIN, GPIO.OUT) # Define tones and frequencies of scale # Class to play music class Music: # Class constant of tones and frequencies TONES = { 'g3': 195.998, 'gis3': 207.652, 'a3': 220.000, 'ais3': 233.082, 'h3': 246.942, 'c4': 261.626, 'cis4': 277.183, 'd4': 293.655, 'dis4': 311.127, 'e4': 329.628, 'f4': 349.228, 'fis4': 369.994, 'g4': 391.995, 'gis4': 415.305, 'a4': 440.000, 'ais4': 466.164, 'h4': 493.883, 'c5': 523.251, 'cis5': 554.365, 'd5': 587.330, 'dis5': 622.254, 'e5': 659.255, 'f5': 698.456, 'fis5': 739.989, 'g5': 783.991, 'gis5': 830.609, } # Class constant of tempos TEMPOS = { 'Largo': 46, 'Adagio': 56, 'Andante': 72, 'Moderato': 96, 'Allegro': 132, 'Vivace': 160, 'Presto': 184, } # Initialize an instance by specifying PWM pin number def __init__(self, pwm_pin): self.pwm = GPIO.PWM(pwm_pin, 1) self.tempo = self.TEMPOS['Moderato'] def _beat_to_duration(self, beat): return 60 / self.tempo * 4 / beat # Beep a tone by specifying frequency and duration def _beep(self, freq, duration): self.pwm.ChangeFrequency(freq) self.pwm.ChangeDutyCycle(0.5) self.pwm.start(50) time.sleep(duration) # Set new tempo def set_tempo(self, tempo): self.tempo = tempo # Make a sound of note # beat: 1, 2, 4, 8, 16, 32: whole, half, quarter, eighth, sixteenth, thirty-second def note(self, beat, pitch): freq = self.TONES[pitch] duration = self._beat_to_duration(beat) self._beep(freq, duration) # Rest of beat length def rest(self, beat): duration = self._beat_to_duration(beat) self.pwm.ChangeDutyCycle(0) time.sleep(duration) # Destroy instance by cleaning up pins def destroy(self): self.pwm.ChangeDutyCycle(0) GPIO.cleanup() m = Music(PWM_PIN) m.set_tempo(Music.TEMPOS['Allegro']) m.note(4, 'd4') m.rest(4) m.note(4, 'e4') m.note(4, 'fis4') m.note(4, 'g4') m.note(4, 'a4') m.note(4, 'h4') m.note(4, 'cis5') m.note(4, 'd5') m.rest(4) m.note(4, 'cis5') m.note(4, 'h4') m.note(4, 'a4') m.note(4, 'g4') m.note(4, 'fis4') m.note(4, 'e4') m.note(2, 'd4') m.destroy() |