PIC16F1827に圧電スピーカー(PKM13EPYH4000-A0)をつないで鳴らす。
秋月で大昔に買ったのに完全に忘れてて、ふと部品箱から発見されたのでやってみた。
いろんな方法でLチカをやっているので、流用するのが楽だなと思い、PIC16F1827につなぐことにした。
動画である必要は全く無かった。
5kHzの矩形波で鳴らしている。
それを__delay_ms();で区切って、ピピッと鳴らす。
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 |
#define _XTAL_FREQ 8000000 void interrupt intr(void) { TMR2IF = 0; RA0 ^= 1; } main(){ OSCCONbits.IRCF = 0b1110; ANSELA = 0b00000000; ANSELB = 0b00000000; TRISA = 0b00000000; TRISB = 0b00000000; INTCONbits.GIE = 1; INTCONbits.PEIE = 1; PIE1bits.TMR2IE = 1; T2CONbits.T2OUTPS = 0b0000; T2CONbits.TMR2ON = 0b1; T2CONbits.T2CKPS = 0b00; TMR2 = 0x00; PR2 = 200; while(1){ T2CONbits.TMR2ON = 0; __delay_ms(250); T2CONbits.TMR2ON = 1; __delay_ms(50); T2CONbits.TMR2ON = 0; __delay_ms(50); T2CONbits.TMR2ON = 1; __delay_ms(50); } } |
何もタイマー割り込みまで使わなくてもお得意の__delayだけでいいじゃんという気はしたが、ピピッって鳴らすなら結局割り込みを使った方が楽だ。
しかも、もともと1秒間隔でLEDを点滅させるコードなので、それより周波数が高くなる分にはプログラムは削る一方となり、その意味でも楽だった。
データシートに3Vの場合の出力のグラフが載っているが、周波数によって出力に結構ばらつきがあるんだとわかる。
上の例では約5kHzで鳴らしているが、もう少し高くすると逆に音が小さくなる領域があるとかはおもしろい。
また、whileの中をこんな風に変えると
1 2 3 4 5 6 7 |
while(1){ unsigned int i; for(i=250;i>150;i=i-5){ PR2 = i; __delay_ms(10); } } |
どっかで聞いたことのあるような警告音っぽい音が鳴る。
6種類くらい作ってみた。
C言語のソースファイルとプロジェクト[BOOTH PIC16F1827_Sounder_TMR2]
回路は「もし、これからPICを始めるなら、まず何をそろえる?」のLEDの換わりに圧電サウンダを取り付けたもの。
いろいろ遊べそうな感じ。
(追記)
やっぱメロディーを鳴らしたくなったので、「むすんでひらいて」の先頭2小節のみを鳴らしてみた。
音の高さはPR2の値で変更し、長さは__delay_ms();でというやっつけ。
上のコードのPostscalerのままだと音が高すぎたので1:2に変更した。
PIC16F1827_Sounder_TMR2_musuhiraki (5853 ダウンロード )
青の欄が音の周波数で、5kHz前後の1オクターブを選んである。
その右がPR2の値の計算、8MHz÷4÷音の周波数÷2で求めてある。
この段階でPostscalerは1:1のつもりなので計算には入っておらず、÷2はLowとHighで1周期だから。
鳴らしてみたら高すぎたが、値を変更するのが面倒なのでPostscalerの値だけを変更した。
この方法だとオクターブの上げ下げが非常に簡単だ。