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

組み込みエンジニア
本記事はプロモーションが含まれています。

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

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

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

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

Arduino UNO(以下Arduinoとします。)を対象とします。Arduinoのライブラリを使用して動作確認したことをまとめています。

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

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

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

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

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

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

#define PIN_PULSE  6

void setup() {

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

Arduinoの標準ライブラリであるanalogWrite()関数を使用することでPWM波形が生成でき簡単にブザーを鳴らすことができます。引数1はPWM出力するピン番号、引数2には最大値255に対してパルスを切り替える値を指定します。最大値に対して指定した値がHIGHになる区間になります。

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

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

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

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

広告

PWM波形について

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

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

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

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

void ChngBuz(){

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

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

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

音程の変化を大きくしたい場合はキャリア周波数を変化させた方が良いでしょう。例えば6ピンを3ピンに置き換えると音程が低くなります。

スポンサーリンク

動作確認

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

Arduinoの3ピンはLEDの点灯用に使用し6ピンは電子ブザーを鳴らします。ブザーはインピーダンスが高いものを使用していれば抵抗は不要です。短絡故障したときにマイコンに負荷がかかるため実装した方が良い場合もありますが、今回は手持ちの抵抗を実装すると音が小さくなりすぎたため直接接続しています。

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

SWはPWM波形のデューティー比を変更するために実装しています。SWを押すとPWMのデューティー比が変更されブザーの音程が変更され「ピッ」と1秒間隔で鳴っていることが確認できました。LEDも1秒間隔で点灯/消灯しますがデューティー比が高くなるほど輝度が上がっていることが確認できました。

LEDの3ピンとブザーの6ピンを入れ替えるとブザーの音程が低くなるためキャリア周波数が変わっていることも確認できます。

ソースコード全体

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

#define PIN_PULSE1 6
#define PIN_PULSE2 3
#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;
uint32_t beforetimCnt = millis();
DIFILT_TYP difilt;
uint8_t duty;

void ChngBuz(void);
void DiFilter(void);
void mainTimer(void);

void setup() {

  pinMode(PIN_DI,INPUT_PULLUP);
  timdifilt = FILT_MIN;
  timbuzon = BUZ_ON;
  timbuzon2 = TIME_OFF;
}

void loop() {

  DiFilter();
  mainTimer();

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

  if( timbuzon == TIME_UP ){
    timbuzon = TIME_OFF;
    timbuzon2 = BUZ_OFF;
    analogWrite(PIN_PULSE1,0);
    analogWrite(PIN_PULSE2,0);
  }
  if( timbuzon2 == TIME_UP ){
    timbuzon2 = TIME_OFF;
    timbuzon = BUZ_ON;
    analogWrite(PIN_PULSE1,duty);
    analogWrite(PIN_PULSE2,duty);
  }
}

/* Timer Management function add */
void mainTimer(void){

  if ( millis() - beforetimCnt >= BASETIME ){
    beforetimCnt = millis();

    if( timdifilt > TIME_UP ){
      --timdifilt;
    }
    if( timbuzon > TIME_UP ){
      --timbuzon;
    }
    if( timbuzon2 > TIME_UP ){
      --timbuzon2;
    }
  }
}
/* 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で学べるソフト開発と標準ライブラリの使い方

PR:技術系の通信教育講座ならJTEX

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

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