ベース回路にブザーを接続して、一定時間経過したらブザーを鳴らす回路とプログラムを作成しました。もし購入されたブザーが、「圧電スピーカー」などの信号を発生させないと鳴らないブザーを買ってしまった場合、前回のプログラムではブザーが鳴りません。今回はスピーカー系のブザーを鳴らしてみます。
ブザーの種類
第25回でブザーの種類を説明しましたが、単純に電圧を加えるとブザーが鳴るものと、鳴らすための信号を発生させる必要があるブザーがあります。
今回は補足として、鳴らすための信号を発生させる必要があるブザーを鳴らしてみます。このようなブザーを鳴らすためには、回路の変更は必要なく、プログラムの変更だけで対応することができます。
もし間違って購入されてしまった場合でも大丈夫です。逆にこのような時こそ色々勉強するチャンスですよ。
ブザーを鳴らすためには
電圧を加えただけで鳴るブザーは、ブザー内部に発音するための回路があらかじめ入っています。では、このようなブザーは内部でどのような信号を発生させているのでしょうか。ブザーの種類によって異なりますが、例えば以下のような信号を発生させています。
この信号って結局電圧が変化しているだけで、この変化に合わせてブザーの振動板が振動して音が出ている、というわけです。スピーカーも振動板を振動させて音を発生させているので同じ原理ですよね。ということは、この振動を早くすれば高い音が出ますし、振動を遅くすれば低い音が出ます。
ではどのくらいの時間間隔でこの電圧を変化させればいいかというと発音させたい音程によります。人間の耳はだいたい20Hz〜20kHzまで聞き取れるそうですが、ブザーの音としては、だいたい1000Hzぐらいが良いのでは、と思います。今回は1000Hzでブザーを鳴らすことにしてみます。
では1000Hzで鳴らすには、この信号の時間間隔をどうすればいいのでしょうか。1000Hzとは、1秒間に1000回振動することになりますので、1回の振動は0.001秒、つまり1ミリ秒、ということになります。
というとで、この信号は以下のように0.5ミリ秒OFF、0.5ミリ秒ONを繰り返せばいいことになります。
この信号って発生させるのできそうですよね。ブザーは5番ピンのGP2に接続していますので、この信号は、
GP2=0;
0.5ミリ秒待つ
GP2=1;
0.5ミリ秒待つ
を繰り返せばよさそうです。あとは0.5ミリ秒の待ちですが、発光ダイオードを光らせる際に使用した関数は、__delay_ms()で、単位はミリ秒ですが、小数点は指定できません。かわりにもっと小さい単位、マイクロ秒で指定できる関数、__delay_us()がありますのでこれを使用します。(μはASCII文字にありませんので、μのかわりに u を使用しています)
0.5ミリ秒は500マイクロ秒ですので、引数には500を指定します。
つまりブザーを鳴らすには、
while(1){
GP2=0;
__delay_us(500);
GP2=1;
__delay_us(500);
}
とすればブザーが鳴ります。またこの数字を変えるとブザーの音程が変わりますが、あまり高い音程にする(周波数を高くする)と、振動板の振動が追いつかず音が割れたり鳴らなくなったりしますので、この辺りに注意しながら自分の好きな音程を探してみてください。
プログラム
前回のプログラムでは、時間がきたらGP2=1としてブザーを鳴らしていました。この部分を上のコードに置き換えればOKですが、上のコードは無限ループに入ります。前回のコードではGP2=1でブザーを鳴らした後に発光ダイオードを点灯させていましたので、この点灯のタイミングをブザーのコードの前にする必要があります。また、最後のwhile(1){}は必要ありませんので削除します。
以下にスピーカータイプのブザーを鳴らす場合のプログラムになります。
/*
* File: main.c
* Author: Tool Labs
* プログラム内容:
* 電源投入後は発光ダイオード(GP5)を点灯、ブザーはOFFにしておく。
* スイッチ(GP4)が押されたら、発光ダイオードを点滅させる。
* 一定時間経過したらブザー(GP2)を鳴らし、発光ダイオード(GP5)を点灯させる。
*/
// インクルードファイル
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
// PIC12F683コンフィグレーションビット設定
#pragma config FOSC = INTOSCIO // Oscillator Selection bits (INTOSCIO oscillator: I/O function on RA4/OSC2/CLKOUT pin, I/O function on RA5/OSC1/CLKIN)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON // Power-up Timer Enable bit (PWRT enabled)
#pragma config MCLRE = OFF // MCLR Pin Function Select bit (MCLR pin function is digital input, MCLR internally tied to VDD)
#pragma config CP = OFF // Code Protection bit (Program memory code protection is disabled)
#pragma config CPD = OFF // Data Code Protection bit (Data memory code protection is disabled)
#pragma config BOREN = ON // Brown Out Detect (BOR enabled)
#pragma config IESO = OFF // Internal External Switchover bit (Internal External Switchover mode is disabled)
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is disabled)
// クロック周波数指定
// (__delay_ms()関数が必要としているため)
#define _XTAL_FREQ 1000000
/*
* main()関数
*/
int main(int argc, char** argv) {
// PICマイコン初期化
OSCCON = 0x40; //クロック周波数を1MHzに設定
ANSEL = 0x00; //すべてのピンをデジタルモードに設定
TRISIO = 0x10; //GP4を入力ピン、それ以外を出力ピンに設定。ただしGP3ピンはもともと入力固定
// タイマー用の変数
unsigned char timer;
// ブザーのピン(GP2)を0にして、ブザーをOFFにする
GP2 = 0;
// LEDのピン(GP5)を1にして、LEDを点灯させる
GP5 = 1;
// スイッチ(GP4)がOFFの間、何もしないで待ち続ける
while(GP4 == 0){
}
// スイッチが押されたら、LEDの点滅を開始する
// まずはじめにLEDのピン(GP5)を0にして、LEDを消灯する
GP5 = 0;
// 1秒点滅を10回繰り返す。つまり10秒間点滅させる
for(timer=0; timer<10; timer++) {
// まず、消灯状態のまま950ミリ秒待つ
__delay_ms(950);
// 950ミリ秒経過したら、LEDのピンを1にして、LEDを点灯する
GP5 = 1;
// LED点灯状態で50ミリ秒待つ
__delay_ms(50);
// 50ミリ秒経ったら、LEDのピンを0にして、LEDを消灯する
GP5 = 0;
}
// LEDのピン(GP5)を1にして、LEDを点灯させる
GP5 = 1;
// ブザーのピン(GP2)に信号を加えて、ブザーをならす(1kHzの例)
while(1){
GP2=0;
__delay_us(500);
GP2=1;
__delay_us(500);
}
// ここには到達しない
return (EXIT_SUCCESS);
}