Arduinoの標準ライブラリでブザーを鳴らす方法

組み込みエンジニア

こんにちは、ENGかぴです。

Arduinoに標準搭載されているライブラリを使用してPWM波形を生成することでブザーを鳴らすことができます。電子ブザーをPWMのデューティ比を変更しながらブザーを鳴らす方法と音程の変化についてまとめています。Arduino UNOを対象としています。

今回は標準ライブラリであるanalogWrite()を使用する方法でブザーを鳴らしています。seeeduino XIAOを使ってキャリア周波数を変更ながらブザーを鳴らした結果を下記にまとめています。

seeeduino XIAOの標準ライブラリでブザーを鳴らす方法

Arduino UNOを使って動作確認を行ったことを下記リンクにまとめています。

Arduinoで学べるマイコンのソフト開発と標準ライブラリの使い方

ArduinoのPWMでブザーを鳴らす方法

電子ブザーは発振回路がついており極性があるものが多く電圧を加えるとブザーが鳴りますが、電流を流し続けると発熱などの問題があるためパルス波形を与えて電流が流れ続けないようにしながら電圧を加えることが推奨されます。

ブザーの構造でコイルが使われている場合、電圧の変化によって逆起電力が発生することがあるため注意が必要な場合もあります。マイコンで動作させられる程度のブザーであれば気にならない程度ですが、電源電圧がDC12V以上のものになると対策が必要になるケースがあります。

逆起電力はコイルによって-側の電圧が高くなるためマイナス側にダイオードのアノード(A)をつなぐようにしてブザーに並列に接続することで対策できます。

標準ライブラリを使用する

Arduinoの標準ライブラリであるanalogWrite()を使用することでPWM波形が生成でき簡単にブザーを鳴らすことができます。

#define PIN_PULSE  6

void setup() {

    analogWrite(PIN_PULSE,duty); //最大値255に対して値を入れて比率を決める
}

analogWrite(引数1, 引数2)において引数1にはピン番号、引数2には最大値255に対する波形の切り変え値を指定します。最大値に対して指定した値がHになる区間になります。

例えばデューティ比を50%にしたい場合は引数2に127を指定します。0にすると理論的にはPWM波形が生成されませんが、実際は僅かに誤差の範囲で出力されることがあります。最大値の255の場合についても同様で電圧出力が100%にならないことがあります。

Arduino UNOにおいてはピンによってキャリア周波数が変化します。その関係を以下の表にまとめています。今回は6ピンを使用しています。

対象ピンキャリア周波数
3・5・6・9・10・11ピン490Hz
5・6ピン980Hz
PWMのキャリア周波数の関係

analogWrite()を発行するとPWM波形が出力し続けるためブザーが鳴り続けます。ブザー音を長く聞いていると耳障りに感じることも多いのでブザーを止めたい場合は引数に0を入れて一時的に停止することができます。

PWM波形について

PWMのデューティー比の考え方のイメージ

analogWrite()で生成したPWM波形のキャリア周波数は一定となります。引数に設定した値によってデューティ比が高くなっていきます。

デューティ比が高くなるほどONの区間が長くなるため平均した電圧は高くなります。

電子ブザーは電圧を変化させると若干音程を変えることができるためデューティ比を変化させることで若干音程を変えることができます。

/* Buzzer change function add */
void ChngBuz(){

    switch(buzmode){
    case 0:
        duty = 0;
        break;
    case 1:
        duty = 60;
        break;
    case 2:
        duty = 120;
        break;
    }

    analogWrite(PIN_PULSE,duty);//デューティ比を可変しながら音程を変更
}

電子ブザーのコイルなどの負荷によってデューティ比を変化させても電圧が変化しにくくなり、音程の変化を大きく感じることができません。

音程の変化を大きくしたい場合はキャリア周波数を変化させた方が良いでしょう。

動作確認

Arduinoでブザーを鳴らす(PWM)
Arduinoでブザーを鳴らす(PWM)

Arduinoの6ピンを使って電子ブザーを鳴らします。ブザーはインピーダンスが高いものを使用していれば抵抗は不要です。

短絡故障したときにマイコンに負荷がかかるため実装した方が良い場合もありますが、今回は手持ちの抵抗を実装すると音が小さくなりすぎたため直接接続しています。

ブザーを持続して鳴らしていると耳障りに感じたため100ms間鳴らした後900msはOFFするようにしています。

SWはブザーの音程を切り替えるために実装しています。ボタンを押したときのチャタリング防止対策をソフト内で行っています。

SWを押すことで若干音程が変更され「ピッ」と1秒間隔でブザーが鳴っていることが確認できました。

ソースコード全体

以下のソースコードはコンパイルして動作確認をしております。チェックはしておりますがコメントなど細かな部分で間違っている可能性があります。参考としてお使いいただければと思います。

#include <MsTimer2.h>

#define PIN_PULSE 6
#define PIN_DI 5
#define DI_FILT_MAX 4
#define FILT_MIN 1

#define TIME_UP 0
#define TIME_OFF -1
#define BASETIME 10
#define BUZ_ON 10
#define BUZ_OFF 90

struct DIFILT_TYP{
    uint8_t wp;
    uint8_t buf[DI_FILT_MAX];
    uint8_t di1;
};

bool btnflg1;
uint8_t buzmode;
int16_t timdifilt;
int16_t timbuzon;
int16_t timbuzon2;
int16_t cnt10ms;
DIFILT_TYP difilt;
uint8_t duty;

void ChngBuz();
void DiFilter();

void setup() {

    pinMode(PIN_DI,INPUT_PULLUP);
    MsTimer2::set(1,TimerCnt); //1msごとに関数へ遷移
    MsTimer2::start();
    timdifilt = FILT_MIN;
    timbuzon = BUZ_ON;
    timbuzon2 = TIME_OFF;
}

void loop() {

    DiFilter();

    if(difilt.di1 == 0){
        if(btnflg1){
            btnflg1 = false;
            ChngBuz();
        }
    }else{
        btnflg1 = true;
    }
    if( cnt10ms >= BASETIME ){
       cnt10ms -= BASETIME;

        if( timdifilt > TIME_UP ){
            --timdifilt;
        }
        if( timbuzon > TIME_UP ){
            --timbuzon;
        }
        if( timbuzon2 > TIME_UP ){
            --timbuzon2;
        }
    }
    if( timbuzon == TIME_UP ){
        timbuzon = BUZ_OFF;
        timbuzon2 = BUZ_OFF;
        analogWrite(PIN_PULSE,0);
    }
    if( timbuzon2 == TIME_UP ){
        timbuzon2 = BUZ_OFF;
        timbuzon = BUZ_ON;
        analogWrite(PIN_PULSE,duty);
    }
}

/* callback function add */
void TimerCnt(){
    ++cnt10ms;
}
/* DiFilter function add */
void DiFilter(){

    if( timdifilt == TIME_UP ){
        difilt.buf[difilt.wp] = digitalRead(PIN_DI);

        if( difilt.buf[0] == difilt.buf[1] &&
            difilt.buf[1] == difilt.buf[2] &&
            difilt.buf[2] == difilt.buf[3] ){ //4回一致を確認
            difilt.di1 = difilt.buf[0];
        }
        if( ++difilt.wp >= DI_FILT_MAX ){
            difilt.wp = 0;
        }
        timdifilt = FILT_MIN;
    }
}
/* Buzzer change function add */
void ChngBuz(){

    switch(buzmode){ //ボタンを押すとデューティを変更する
    case 0:
        duty = 0;
        break;
    case 1:
        duty = 60;
        break;
    case 2:
        duty = 120;
        break;
    case 3:
        duty = 180;
        break;
    case 4:
        duty = 240;
        break;                
    }

    if( ++buzmode >= 5 ){
          buzmode = 0;
      }
}

関連リンク

Arduinoのライブラリを使って動作確認を行ったことを下記リンクにまとめています。

Arduinoで学べるマイコンのソフト開発と標準ライブラリの使い方

Seeeduino XIAOで学べるソフト開発と標準ライブラリの使い方

ESP32-WROOM-32Eで学べるソフト開発と標準ライブラリの使い方

GEEKJOB-未経験からITエンジニアに【オンライン無料体験】

最後まで、読んでいただきありがとうございました。

タイトルとURLをコピーしました