1. はじめに
お仕事で 「人が居ない事を検知して下さい、カメラはダメよ!」とか言う
いつもの無茶振りで話は突然はじまった
むむむ?
人が居る事ぢゃなくって人が居ない事を検知?
なんだ?何に使うんだ?
って事で一旦なんとなく形になって来たのでというお話
2. PIRセンサを真面目に考える
部品箱に入っている PIRセンサを取り出して
適当に繋いでみると実に不安定....に見える
これでは評価も低くなるなぁ
# define PIN (26)
void setup() {
Serial.begin( 115200 );
pinMode(PIN, INPUT_PULLUP);
}
void loop() {
int val;
val = digitalRead(PIN);
Serial.printf("val=%d\n", val);
}
データシートを読んでみると何やら BLOCK_TIME と言うものがあり
この間は 反応をしないらしい
ははぁ それで不安定に見えるのか...
3. 改造?
WEBを検索しまくると
とか、ICの5PIN/6PIN直結の記事が目立つ
別にそれが良いとか悪いとかの話ではなくて
改造しちゃうと量産
に耐えられなくなってしまうので
ここはソフトでカバーしまくることにした
- 量産の掟風なものがあり 買ってきたものは
改造
してはいけない - っていうかだいたい内製してねとのお話
4. 仕組み
下記のように BLOCK TIME と呼ばれる部分は 仮想的にONを出力しセンサからの値を出力しないようにする
//
// +---+............
// | | BLOCK :
// | | TIME :
// --------+ +----------------------------
// Status ON OFF
//
//
// +---+............
// | | VirtualON :
// | | TIME :
// --------+ +----------------------------
// Status ON OFF
//
//
さらに ON/OFF の状態が変わった時点から n分間の傾向を算出してみる
これが 0であれば過去n分間 そこに人が居なかった事がわかる
+-+ +-+ +-+
| | | | | |
| | | | | |
-----+ +-----+ +------....--------+ +----
1回目 2回目 n回目
<-------------- 過去n分間 --------------->
5. 全ソース
# include "myPIR.h"
const uint16_t LEDPIN = (10);
const uint16_t PIRPIN = (26);
const uint32_t ONE_SEC_MSEC = (1 * 1000);
const uint32_t FIVE_SEC_MSEC = (5 * 1000);
const uint32_t ONE_MIN_MSEC = (60 * ONE_SEC_MSEC);
//========================
// 初期化
//========================
void setup(void)
{
Serial.begin( 115200 );
pinMode(LEDPIN, OUTPUT);
digitalWrite(LEDPIN, !LOW);
setupPIR(PIRPIN, FIVE_SEC_MSEC);
}
//========================
// LOOP
//========================
void loop(void)
{
int16_t val, cnt;
val = getPIR();
cnt = getAnyMinTrand(ONE_MIN_MSEC);
digitalWrite(LEDPIN, !val);
Serial.printf("val=%d cnt=%d\n", val, cnt);
delay(1);
}
//===============================================================> myPIR.h
// HC-SR501
// Author/date : @chrmLinux 2021/09/29
// Author/update : @chrmLinux 2021/09/29
// https://datasheetspdf.com/pdf-file/775434/ETC/HC-SR501/1
//
// +--------------------------+
// | . . . |
// | G O V |
// | N U C |
// | D T C |
// || Repeat |
// |. Single == == |
// +--------------------------+
// Sensitivity TimeDelay
// VR VR
// min <-> max min <-> max
//
// 1)1分くらい待たないと安定しない
// 2)OFF直後に BLOCK TIME がある
//
// +---+............
// | | BLOCK :
// | | TIME :
// --------+ +----------------------------
// Status ON OFF
//
//
// 3)ぢゃ、仮想的にONするって感じで
//
// +---+............
// | | VirtualON :
// | | TIME :
// --------+ +----------------------------
// Status ON OFF
//
//
const uint32_t BLOCK_TM = (5 * 1000);
static uint16_t _pirPin = 0;
static uint32_t _blockTime = 0L;
//========================
// BLOCKING TIME秒数 待つ
//========================
bool waitBlockTime()
{
static uint32_t tm = millis();
bool rtn = false;
if ((millis() - tm) > _blockTime) {
tm = millis();
rtn = true;
// Serial.printf("[wait]\n");
}
return rtn;
}
//========================
// PIR初期化
//========================
void setupPIR(uint16_t pin, uint32_t blocktime)
{
_pirPin = pin;
_blockTime = (blocktime < BLOCK_TM) ? BLOCK_TM : blocktime;
pinMode(_pirPin, INPUT_PULLUP);
}
//========================
// 設定したBlockTImeを得る
//========================
uint32_t getBlockTime(void)
{
return _blockTime;
}
//========================
// PIRから実際に値を得る
//========================
int16_t getRealPIR(void)
{
int16_t val = digitalRead(_pirPin);
return val;
}
//========================
// PIRから仮想の値を得る
//========================
int16_t getPIR(void)
{
static int16_t preVal = -1;
if (preVal == HIGH) {
if (!waitBlockTime()) {
return HIGH;
}
}
int16_t val = getRealPIR();
if (preVal != val) {
// Serial.printf("[getPIR] preVal:%d val:%d\n", preVal, val);
preVal = val;
}
return val;
}
//========================
// センサ検知からn分間の傾向
//========================
uint32_t getAnyMinTrand(uint32_t any_sec_msec)
{
static uint32_t tm = millis();
static uint32_t cnt = 0L;
static int16_t preVal = 0;
int16_t val;
if ((millis() - tm) > any_sec_msec) {
tm = millis();
cnt = 0L;
}
val = getPIR();
if (preVal != val) {
tm = millis();
preVal = val;
if (val == HIGH) {
cnt++;
}
}
return cnt;
}
//<=============================================================== myPIR.h
6. おわりに
何かと癖がある PIRセンサですが
うまい具合に使うと色々な可能性が見えてきました
さて、クライアントはこれを何に使うのでしょうか...
私には見当もつきません(コロナ対策かな?)
- この処理が皆さんに広がって中途半端な故障の多い
PIRセンサ
とか言われているこれが見直される事を祈ります