Arduinoと人感センサーを組み込みブザーで通知する

組み込みエンジニア

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

Arduinoと人感センサーを組み合わせることで人体を検知して通知するシステムを作ることができます。人感センサーが人体を検出したときにLEDを点灯/消灯させ通知すると同時にブザーを鳴らす人感モジュールを製作して動作確認を行いました。

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

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

人感センサーの使い方

人感センサーはSB612A(秋月電子)を使用しています。人体検出用に開発された集電センサーモジュールであり動作確認しやすいようにボート化されています。人感センサーはPIR(Passive Infrared Ray)と表現され周囲の赤外線の変化によって人間の接近を検知するセンサーです。

SB612Aの使い方

引用:SB612Aのデータシート(Schematic Diagram)
引用:SB612Aのデータシート(Schematic Diagram)

SB612Aの使い方は簡単です。モジュールに供給する電源とSB612Aが検知した際に出力するDOをArduinoなどのマイコンのDIに入力します。

電源はモジュール内にコンバータが内蔵されているためDC3.3VからDC12Vまで印加することができます。また出力はCMOS出力及びオープンコレクタ出力のどちらかを選択できます。

Arduino UNOではDC3.3VをHIGHと認識できるためCMOSで受けても問題になりませんが、DC5VマイコンなどでVIHが3.3V以上となる場合はオープンコレクタ出力を利用することで検知信号を取得することができます。

回路図のオープンコレクタ出力使用時の接続例を赤文字で入れています。VOUTがHIGHになると接続先のDIはLOWになるため注意が必要です。

調整できる項目

人感センサーSB612A

SB612Aでは調整できる項目が3つあります。

  1. 感度調整(Sensitivity adjustment)
  2. 調光(Light adjustment)
  3. 遅延時間調整(Delay time adjustment)

SB612A内部のセンサードライバBM612に入力する電圧を可変抵抗で分圧して調整します。抵抗を表面から見た時反時計回りに回すと可変抵抗の抵抗が大きくなります。

感度調整

BM612のSENSに入力する電圧(PIR信号を検出するための閾値)を調整します。1MΩと可変抵抗で分圧することで閾値が決まります。VSSは最小の閾値となりVDD/4が最大の閾値となります。SENSの値が大きいほどPIRの信号検出の感度が低くなります。

調光

BM612のOENに入力する電圧を調整します。OEN電圧がLOWからHIGHに立ち上がる際に0.4VDD(1.2V)より高い場合に検出してVOUTが有効になります。HIGHからLOWに立ち下がる場合0.2VDD(0.6V)よりも低い場合にVOUTが無効になります。

OENの調整は可変抵抗を高くすると分圧の関係から電圧が低くなるためVOUTが出力しにくくなります。抵抗を高くするほど明るい場所での感度が鈍くなります。

遅延時間調整

BM612のTIMEに入力する電圧を調整します。TIMEに入力される電圧が低いほど遅延時間が短くなりVOUTを出力する期間が短くなります。

遅延時間を10秒程度にしたい場合は可変抵抗を82kΩ程度に調整することで実現できます。データシートの正規化のグラフと表のレンジが異なっていますが表の値が正しそうです。

グラフの方はレンジが3600sec時に0.25になっていますが、おそらく0.5の間違いだと思われます。

人感センサーモジュール

Arduino UNOに人感センサーSB612Aを組み込んでシステムを構成しました。人体を検知したとき検知したことを通知する機能を追加して人感センサーの動作を確認しています。

全体構成

人感センサーモジュールの全体構成
人感センサーモジュールの全体構成

人感センサーの出力をArduino UNOのDIで受けた後にブザーを鳴らしながらLEDを点灯/消灯させて人感センサーが検知したことを通知します。

時間遅延は5秒程度になるように調整しています。抵抗R1はブザーの音の大きさを抑える目的とブザーが短絡故障した場合の保護のため実装しています。(基本的にブザーはインピーダンスが高いことが多いので不要なこともあります。)

製作したモジュール

人感センサーモジュール(自作)
人感センサーモジュール(自作)

人感センサーモジュールを製作していますが箱の中にArduino UNOとブザーなどを収納し人感センサーとLEDを表に出して検知したことが分かるようにしています。

人感センサーモジュールを本棚の上や階段の途中に設置して通り過ぎた時ブザーが鳴りLEDが点灯/消灯していることが確認できました。

厚紙で箱を作り適当な穴をあけただけの簡単な工作でしたが基板とセンサーがむき出しに設置されているよりかはましだと思いました。頑張った感は少しはありました。

動作確認

シリアルモニタによる動作確認
シリアルモニタによる動作確認

シリアルモニタに人感センサーが検知した場合に文字を表示するようにしています。センサーに手をかざすと検知しブザーが鳴りLEDが点灯消灯することが確認できました。

調光の抵抗を高くしていくと部屋の照明を落とさないと人感センサーが反応しなくなることも確認できています。

LEDやブザーによる消費電流が増えてしまうため電池の消費を抑えるために短めの時間遅延にしていますがシステム構成によって最適な時間を検討することができるため応用範囲が広くなりそうです。

ソースコード全体

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

#include <MsTimer2.h>

#define TIME_UP 0
#define TIME_OFF -1
#define BASE_CNT 10 //10msがベースタイマとなる
#define FILT_MIN 1
#define DI_FILT_MAX 4
#define LED_ONOFF 20

#define PIN_PULSE 6
#define PIN_DI1 7
#define PIN_DO1 8

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

// application use
int8_t timdifilt = TIME_OFF;
int8_t timled = LED_ONOFF;
DIFILT_TYP difilt;
int8_t cnt10ms;
bool btnflg1;

/*** Local function prototypes */
void TimerCnt();
void mainTimer();
void DiFilter();

void setup() {
  
    pinMode(PIN_DI1,INPUT);
    pinMode(PIN_DO1,OUTPUT);
    Serial.begin(115200);

    MsTimer2::set(1,TimerCnt); //1msごとに関数へ遷移
    MsTimer2::start();
    timdifilt = FILT_MIN;

    for( uint8_t i=0; i < 10; i++ ){
      mainTimer();
      DiFilter();
      delay(10);
    }
}

void loop() {

    mainTimer();
    DiFilter();  

    if(difilt.di1 == 1){
        if(btnflg1){
            btnflg1 = false;
            Serial.println("Sensor->ok");
            analogWrite(PIN_PULSE,128); //ブザーを鳴らす
        }

        if( timled == TIME_UP ){
            timled = LED_ONOFF;

            if(digitalRead(PIN_DO1)){
                digitalWrite(PIN_DO1,LOW);
            }else{
                digitalWrite(PIN_DO1,HIGH);
            }
        }
    }else{
        btnflg1 = true;
        analogWrite(PIN_PULSE,0); //ブザーを止める
        digitalWrite(PIN_DO1,LOW);
    }
}
/* callback function add */
void TimerCnt(){
    ++cnt10ms;
}

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

    if( cnt10ms >= BASE_CNT ){
        cnt10ms -=BASE_CNT; //10msごとにここに遷移する

        if( timled > TIME_UP ){
            timled--;
        }

        if( timdifilt > TIME_UP ){
            timdifilt--;
        }
    }
}
/* DiFilter function add */
void DiFilter(){
    uint8_t i;
    bool	boo = true;

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

        for( i= 1; i < DI_FILT_MAX; i++ ){
            if( difilt.buf[i - 1] != difilt.buf[i] ){
                boo = false;
            }
        }
 
        if( boo ){
            difilt.di1 = difilt.buf[difilt.wp];
        }

        if( ++difilt.wp >= DI_FILT_MAX ){
            difilt.wp = 0;
        }

        timdifilt = FILT_MIN;
    }
}

関連リンク

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

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

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

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

TECH::CAMPプログラミング教養【無料体験会】

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

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