こんにちは、ENGかぴです。
Arduinoと人感センサーを組み合わせることで人体を感知して通知するシステムを作ることができます。人感センサーが感知したときにLEDを点灯/消灯させると同時にブザーを鳴らす人感モジュールを製作して動作確認を行いました。
人感センサーはSB612A(秋月電子)を使用しています。人体感知用に開発された集電センサーモジュールであり動作確認しやすいようにボート化されています。
Arduino UNO(以下Arduinoとする)を使って動作確認を行ったことを下記リンクにまとめています。
Arduinoで学べるマイコンのソフト開発と標準ライブラリの使い方
人感センサーの使い方
人感センサーはPIR(Passive Infrared Ray)と表現され周囲の赤外線の変化によって人間の接近を感知するセンサーです。
SB612Aの使い方
人感センサーの1ピンに電源を供給するためArduinoのDC5Vを接続し、3ピンをArduinoのGNDに接続します。人感センサーの2ピンから感知信号が出力されるためArduinoのDIに接続します。
電源はモジュール内にコンバータが内蔵されているためDC3.3VからDC12Vまで印加することができます。SB612Aの出力はCMOS出力またはオープンコレクタ出力を選択することができます。本記事ではCMOS出力をDIに接続しています。
ArduinoではDC3.3VをHIGHと認識できるためCMOSで受けても問題になりませんが、DC5VマイコンなどでVIHが3.3V以上になる場合はオープンコレクタ出力を利用することで感知信号を取得することができます。
回路図のオープンコレクタ出力使用時の接続例を赤文字で入れています。VOUTがHIGHになると接続先のDIはLOWになるため注意が必要です。
調整できる項目
SB612Aでは調整できる項目が3つあります。
- 感度調整(SENS)
- 調光(DARK_ADJ)
- 遅延時間調整(DELAY_TIME)
SB612A内部のセンサードライバBM612に入力する電圧を可変抵抗で分圧して調整します。
抵抗を表面から見た時反時計回りに回すと可変抵抗の抵抗が大きくなります。
感度調整(SENS)
BM612のSENSに入力する電圧(PIR信号を検出するための閾値)を調整します。1MΩと可変抵抗で分圧することで閾値が決まります。VSSは最小の閾値となりVDD/4が最大の閾値となります。SENSの値が大きいほどPIRの信号検出の感度が低くなります。
調光(DARK_ADJ)
BM612のOENに入力する電圧を調整します。OEN電圧がLOWからHIGHに立ち上がる際に0.4VDD(1.2V)より高い場合に検出してVOUTが有効になります。HIGHからLOWに立ち下がる場合0.2VDD(0.6V)よりも低い場合にVOUTが無効になります。
OENの調整は可変抵抗を高くすると分圧の関係から電圧が低くなるためVOUTが出力しにくくなります。抵抗を高くするほど明るい場所での感度が鈍くなります。
遅延時間調整(DELAY_TIME)
BM612のTIMEに入力する電圧を調整します。TIMEに入力される電圧が低いほど遅延時間が短くなりVOUTを出力する期間が短くなります。
遅延時間を10秒程度にしたい場合は可変抵抗を82kΩ程度に調整することで実現できます。データシートの正規化のグラフと表のレンジが異なっていますが表の値が正しそうです。
人感センサーモジュール
Arduinoに人感センサーSB612Aを組み込んでシステムを構成しました。人体を感知したときブザーとLEDで通知するモジュールです。
全体構成
人感センサーの出力をArduinoのDIで受けた後にブザーを鳴らしながらLEDを点灯/消灯させて人感センサーが感知したことを通知します。電源はArduinoの電源ジャックから電池で供給します。
LEDは感知の表示に使用しますが、電池の消費を抑えるためR2の抵抗で明るさを調整しました。手持ちのLEDは10kΩを使用しても暗さを感じませんでした。暗いと感じる場合は抵抗を小さくして明るさの調整を行います。
時間遅延は5秒程度になるように調整しています。R1の抵抗はブザーの音の大きさを抑える目的とブザーが短絡故障した場合の保護のため実装しています。(基本的にブザーはインピーダンスが高いことが多いので不要なこともあります。)
製作したモジュール
人感センサーモジュールを製作していますが箱の中にArduinoとブザーなどを収納し人感センサーと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);
void mainTimer(void);
void DiFilter(void);
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(void){
++cnt10ms;
}
/* Timer Management function add */
void mainTimer(void){
if( cnt10ms >= BASE_CNT ){
cnt10ms -=BASE_CNT; //10msごとにここに遷移する
if( timled > TIME_UP ){
timled--;
}
if( timdifilt > TIME_UP ){
timdifilt--;
}
}
}
/* DiFilter function add */
void DiFilter(void){
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;
}
}
MsTimer2.hは標準ライブラリでは実装されていません。ライブラリマネージャで追加する必要があります。
関連リンク
Arduinoのライブラリを使って動作確認を行ったことを下記リンクにまとめています。
Arduinoで学べるマイコンのソフト開発と標準ライブラリの使い方
Seeeduino XIAOで学べるソフト開発と標準ライブラリの使い方
ESP32-WROOM-32Eで学べるソフト開発と標準ライブラリの使い方
最後まで、読んでいただきありがとうございました。
厚紙で箱を作り適当な穴をあけただけの簡単な工作でしたが基板とセンサーがむき出しに設置されているよりかはましだと思いました。頑張った感は少しはありました。