ボタン電池1個で数年持つ無線ドア開閉センサを作る

**本文中に記載されているファームウェアは2019年11月現在提供されておらず、また、現行ファームウェアとは互換性がないため、当時のファームウェアをお持ちの方のみ参照してください。参考のため、本文は残しておきます。**これからドア開閉をはじめてみたい方は、後続製品である、[OPEN-CLOSE SENSE PAL/開閉センサーパル](https://mono-wireless.com/jp/products/twelite-pal/sense/openclose-pal.html)を利用すると、配線等が不要となりますのでご検討ください。

関連記事:
- [無線通信機能付き小型センサ「OPEN-CLOSE SENSE PAL」を使ってみた](https://qiita.com/RyoOkaya/items/660ceb91d2b4e0378a8d) (@RyoOkaya さま)


安価で簡単に扱うことができる無線デバイス TWE-Lite DIP の超低消費電力機能を活かせる最新のファームウェアを使って、一度電池を入れたら数年は電池交換が要らないドアの開閉センサを作ってみましょう。無線を利用しているため、配線を気にすることなく好きな場所に好きなだけ設置ができます。製作してから1年以上経過していますが、特に問題なく動きつづけています。

## 全体構成
今回はシンプルにドア開閉センサの信号を受信機で受ける仕組みにしています。各ドアセンサは2分毎にドアの開閉状態や電池電圧を受信機に通知するほか、ドアが開いた瞬間または閉じた瞬間にも受信機にその状況を通知するように設定していきます。

TWE-Lite DIP は見通しの良いところなら 1km 程度電波が飛びますので、家の中であればおおよそ電波は届くと思いますが、必要に応じて中継器を追加することも可能です。
![0.jpg](https://qiita-image-store.s3.amazonaws.com/0/43450/b8dbb299-4d09-f0bf-b829-a6c29b758349.jpeg)

以下の説明は主に Windows 環境を想定していますが、Mac OS X や Linux についても適宜説明を追加しています。お好きな環境をご利用ください。

## TWE-Lite DIP の設定
### 準備するもの
- TWE-Lite DIP × 2個以上
http://akizukidenshi.com/catalog/g/gM-06760/
![6s.jpg](https://qiita-image-store.s3.amazonaws.com/0/43450/d0790b86-5220-0fff-ad0f-5861067a68d8.jpeg)
1つは受信機に、それ以外はセンサとして利用します。アンテナの色は特に性能や機能には影響はありません。  

より遠くと通信をしたい場合、壁などが多い場所で利用する場合には、より高性能なアンテナがつけられるタイプもあります。

TWE-Lite DIP-UFL
http://akizukidenshi.com/catalog/g/gM-07731/

TWE-Lite DIP-UFL 用アンテナ TWE-AN-099
http://akizukidenshi.com/catalog/g/gP-07733/


- TWE-Lite R × 1台
http://akizukidenshi.com/catalog/g/gM-08264/
![2s.jpg](https://qiita-image-store.s3.amazonaws.com/0/43450/f7c1a0a5-1fb5-b33c-8ea0-f239c2b6edd8.jpeg)
TWE-Lite DIP の書き換えにも受信機の一部としても利用します。

- ブレッドボード
http://akizukidenshi.com/catalog/g/gP-00315/
![1s.jpg](https://qiita-image-store.s3.amazonaws.com/0/43450/6b038371-7654-77e4-984e-95f67ff58bdd.jpeg)
ブレッドボードははんだごてがなくても簡単に動作が確認できるので、ちょっとした動作確認におすすめです。

- 線材
http://akizukidenshi.com/catalog/g/gP-00288/
![7s.jpg](https://qiita-image-store.s3.amazonaws.com/0/43450/60384259-7446-20ba-f920-57acdce7f1f1.jpeg)
ブレッドボード用のものを適宜。

- ボタン電池(CR2032)
http://akizukidenshi.com/catalog/g/gB-05694/
![4.jpg](https://qiita-image-store.s3.amazonaws.com/0/43450/7cf69b52-0aa0-f87e-7f49-aff2908744e7.jpeg)
コイン電池とも。CR2032は10年位は自然放電せずに利用できます。

- ボタン電池基板取付用ホルダー　ＣＲ２０３２用（小型タイプ）
http://akizukidenshi.com/catalog/g/gP-00706/
![5.jpg](https://qiita-image-store.s3.amazonaws.com/0/43450/20d2f78f-89ce-045a-28f4-7636b14ee2b4.jpeg)
こちらも適宜。

- 1MΩ～5MΩ位の抵抗 (センサあたり1本)
![8s.jpg](https://qiita-image-store.s3.amazonaws.com/0/43450/f1bc27ce-69c0-9f4b-1496-e972711c7271.jpeg)
入手性の良いものを適宜選んでください。今回は 2.2 MΩ (赤赤緑金) を利用しました。

- ケース入りリードスイッチ（磁石付セット）ＭＣ－１４ＡＧ
http://akizukidenshi.com/catalog/g/gP-04025/
![3s.jpg](https://qiita-image-store.s3.amazonaws.com/0/43450/f0e7ce98-8632-10c9-a25d-7f6f6092643e.jpeg)
磁石とリードスイッチのセットです。磁石がリードスイッチに近づくとリードスイッチがONになります。これを写真のような感じでドアに取り付けます。
![9s.jpg](https://qiita-image-store.s3.amazonaws.com/0/43450/ee440f72-0017-2100-8bfc-49280fb35ed5.jpeg)
ブレッドボードで動作確認ができたらユニバーサル基板などにしっかりと配線しなおしましょう。写真はユニバーサル基板上に配線した例です。ドア側についているのが磁石、基板側についているのがリードスイッチです。

### ドライバのインストール・書き込みソフトの導入
USBアダプター TWE-Lite R のドライバを http://mono-wireless.com/jp/products/TWE-Lite-R/index.html の手順に従ってダウンロード・インストールします。書き込み用ソフトウエアも上記Webサイトにありますので、合わせて入手しておきます。Windows用のGUIツールと、Windows, Linux, Mac OS X 用のコマンドラインツールがあります。

### ファームウェアの入手
http://mono-wireless.com/jp/products/Software_download/index.html にある、非公式バージョン ver 1.7.1 ソフトウェア(ソース含) をダウンロードします(旧バージョンの下のほう、1.6.5と1.3.10の間にあります)。これを TWE-Lite DIP に使うとスイッチの ON/OFF を超低消費電力で監視できる回路が抵抗1本で作れます。

この中の、
App_TweLite_1_7_1_unoff\App_TweLite\Master\Build\App_TweLite_Master_JN5164_1_7_1.bin

を上記の書き込みツールで書き込みます。

TWE-Lite R に TWE Lite DIP を写真のように接続し、書き込みを行ってください。

![23s.jpg](https://qiita-image-store.s3.amazonaws.com/0/43450/1c1d900e-d6eb-1654-e10a-e0d481326da9.jpeg)

### TWE-Lite DIP の設定変更
ファームウェアを書き込んだら、シリアルポートにアクセスできるツール(Windows の場合は TeraTerm http://sourceforge.jp/projects/ttssh2/ など)で TWE-Lite に接続します。シリアルポートの設定は、115200 bps, パリティ なし, データビット 8bit, ストップビット 1bit, フロー制御 なし です。設定したら、TWE-Lite R のリセットボタンを押すと、次のような画面が表示されます。

>!INF TOCOS TWELITE DIP APP V1-07-1, SID=0x81000831, LID=0x78
>!INF Default config (no save info)...
>!INF DIO --> 00000000000000010000

この画面がでたらキーボードの + キーをゆっくりめに3回押します。すると、設定画面に切り替わります。

>--- CONFIG/TOCOS TWELITE DIP APP V1-07-1/SID=0x81000831/LID=0x78 ---
> a: set Application ID (0x67720102)
> i: set Device ID (--)
> c: set Channels (18)
> x: set Tx Power (3)
> t: set mode4 sleep dur (1000ms)
> y: set mode7 sleep dur (10s)
> f: set mode3 fps (32)
> z: set PWM HZ (1000)
> o: set Option Bits    (0x00000000)
> O: set Option Bits #2 (0x00000000)
> b: set UART baud (38400)
> p: set UART parity (N)

なお設定項目の詳細は、http://mono-wireless.com/jp/products/TWE-Lite-DIP/TWE-Lite-DIP-step3-interactive.html にありますが、今回利用しているファームウェアには無い機能もありますので注意してください。

### センサ側の設定
センサ側の TWE-Lite の設定例です。各行の先頭の文字(大文字小文字に注意)を入力すると、その値が変更できます。

>--- CONFIG/TOCOS TWELITE DIP APP V1-07-1/SID=0x81000831/LID=0x78 ---
> a: set Application ID (0x7d56c47d)*
> i: set Device ID (3=0x03)*
> c: set Channels (18)
> x: set Tx Power (3)
> t: set mode4 sleep dur (1000ms)
> y: set mode7 sleep dur (120s)*
> f: set mode3 fps (32)
> z: set PWM HZ (1000)
> o: set Option Bits    (0x00000000)
> O: set Option Bits #2 (0x00000001)*
> b: set UART baud (38400)
> p: set UART parity (N)

上記の * がついている部分が変更した値です。

> a: set Application ID (0x7d56c47d)

Application ID の値の決め方は、http://mono-wireless.com/jp/products/TWE-Lite-DIP/TWE-Lite-DIP-step3-interactive.html の「アプリケーションIDの設定」に詳細が記載されていますが、 0x00010001 ～ 0x7FFFFFFE の中から適当に選んでおけばよいでしょう。自分で利用する TWE-Lite DIP にはすべて同じ Application ID を書き込みます。

> i: set Device ID (3=0x03)

Device ID には 1 ～ 100 の値を設定してください。センサ側のデバイスを区別するための番号になります。100台までならこの設定だけでそれぞれのセンサを区別することができます。
TWE-Lite DIP が電波を発信する時間は1回あたり数ミリ秒程度と短いため、100台同時に動作したとしてもほとんど電波が衝突することはありませんが、もし衝突してしまった場合は次の電波送信までデータが受け取れないことに注意してください。

> y: set mode7 sleep dur (120s)

の部分がセンサが定期的に目を覚ます設定です。ここでは120秒としました。10秒を設定しても単純計算では1年程度動作します。この値を長くすればするほど電池は長持ちしますが、電池が切れたことや電波のノイズなどでドアが開いたこと・閉じたことがうまく検出できなかった場合を考えると、あまり長くしすぎないほうが良いかもしれません。

> o: set Option Bits    (0x00000000)

特に変更する必要はありません。オプションビットの設定に「ADCを利用しない場合に設定すると配線を省略できます。」という項目がありますが、今回の省電力モード(間欠モード)では記載にある通り無効となり、必ずADCの値が読み込まれますので、ADCのプルアップ(アナログ入力ピン1～4(22～25番ピン)を+ 側に接続)を忘れないようにしてください。

> O: set Option Bits #2 (0x00000001)

がプルアップ無効化オプションの設定です。この設定が、今回ダウンロードしたファームウェアに特別に用意された設定値です。このオプションを利用しない場合、デジタル入力ピンは自動的に内部でプルアップされます。この場合、

- ドアが閉じたことは瞬時に判定することは可能だが、開いた瞬間はとらえられない
- センサのスイッチがON(ドアが閉じた状態)になると内部プルアップの抵抗分(数十kΩ)の電流が流れ続けてしまうので、電池がすぐなくなってしまう

という問題があります。今回はデジタル入力1ピンに1を設定することで内部プルアップを無効にし、上記の問題を解消します。

入力が終わったら S キーを押し、設定を保存します。

### 受信機側の設定
次に受信機側も設定します。下記の2行のみ変更します。

> a: set Application ID (0x7d56c47d)*
> i: set Device ID (121=0x79)*

Application ID はセンサ側と同じにしてください。Device ID には 121 を設定してください。この設定にすると、TWE-Lite DIP は親機(受信機) として利用できるようになります。
なお、Device ID に 122 を設定することで、中継器とすることも可能です。詳細は、http://mono-wireless.com/jp/products/TWE-Lite-DIP/TWE-Lite-DIP-step3-interactive.html を参照してください。

入力が終わったら S キーを押し、設定を保存します。

## 回路の製作
### センサ回路の製作
ブレッドボード上に回路を作ります。M1(13番ピン), M2(26番ピン), M3(27番ピン)を - 側に、アナログ入力ピン1～4(22～25番ピン)を+ 側に接続し、VCC(28番ピン) を + 側, GND(14番ピン) を - 側を配線します。デジタル入力1ピン(12番ピン)をプルアップするとドアが閉じた瞬間が、プルダウンするとドアが開いた瞬間が検出できます。

#### ドアが閉じた瞬間の検出
配線図を示します。デジタル入力1ピン(12番ピン)をプルアップしておき、リードスイッチがONになった時に当該ピンが 0V になるように配線します。

![pullups.jpg](https://qiita-image-store.s3.amazonaws.com/0/43450/c1d9a15a-19c5-7a02-d736-c05150f3b779.jpeg)
![pullup2s.jpg](https://qiita-image-store.s3.amazonaws.com/0/43450/f4f6fbe3-07a8-f84f-95a8-1bf70d67de33.jpeg)

#### ドアが開いた瞬間の検出
リードスイッチがONになったとき、デジタル入力1ピン(12番ピン)が 3V (電池電圧) になるように当該ピンをプルダウンします。プルアップの場合との違いは、赤丸の部分のみです。

![pulldowns.jpg](https://qiita-image-store.s3.amazonaws.com/0/43450/b370a061-2296-5abe-75e1-6e609b307a3e.jpeg)
![pulldown2s.jpg](https://qiita-image-store.s3.amazonaws.com/0/43450/c624d784-060e-b52d-ed4d-973a74ca7d31.jpeg)

### 受信機回路の製作
特に製作する作業はありません。TWE-Lite R に、受信機用に設定を行った TWE-Lite DIP を差し込み、PC等に接続すれば完了です。

![23s.jpg](https://qiita-image-store.s3.amazonaws.com/0/43450/1c1d900e-d6eb-1654-e10a-e0d481326da9.jpeg)

## 設置
それでは設置していきましょう。受信機はできるだけ見通しの良いところに設置してください。センサは適当なドアや障子などにつけていきましょう。
### 注意点
受信機とセンサのアンテナの向きが平行になるように設置しましょう。平行な時にもっとも電波が効率よく伝わります。
![22s.jpg](https://qiita-image-store.s3.amazonaws.com/0/43450/3a1b071a-9b49-7055-6233-c4a66b25bc91.jpeg)

## センサデータの受信
シリアルポートが読み取れるお好きなプログラミング言語で簡単にデータを取得することができます。データは下記のようなテキスト形式です。

>:018115011881000812008AA8000B5716000124FFFFFFFDEC
 
データフォーマットを下記に示します。アプリケーションでは、最低限、太字の部分を監視すればよいでしょう。

| 位置(十進) | 文字数 | 意味 |
|:-----------|------------:|:------------|
|+00 | 1 |必ず 「:」  |
|+01 | 2 |**送信元の論理デバイスID(今回の場合は1～100)**  |
|+03 | 2 |コマンド(0x81: IO状態の通知)  |
|+05 | 2 |パケット識別子 (アプリケーションIDより生成される)  |
|+07 | 2 |プロトコルバージョン (0x01 固定)  |
|+09 | 2 |LQI値、電波強度に応じた値で 0xFF が最大、0x00 が最小  |
|+11 | 8 |送信元の個体識別番号 |
|+19 | 2 |宛先の論理デバイスID |
|+21 | 4 |タイムスタンプ (秒64カウント) |
|+25 | 2 |中継フラグ(中継済みなら1) |
|+27 | 4 |**電源電圧[mV]** |
|+31 | 2 |未使用 |
|+33 | 2 |**DI(デジタル入力) の状態ビット。DI1(0x1) DI2(0x2) DI3(0x4) DI4(0x8)。1がOn(Lowレベル)。今回の場合は、ここが 00 か 01 かを確認すればよい**|
|+35 | 2 |DI の変更状態ビット。DI1(0x1) DI2(0x2) DI3(0x4) DI4(0x8)。1が変更対象。|
|+37 | 2 |AD1の変換値。0～2000[mV]のAD値を16で割った値を格納。|
|+39 | 2 |AD2の変換値。0～2000[mV]のAD値を16で割った値を格納。|
|+41 | 2 |AD3の変換値。0～2000[mV]のAD値を16で割った値を格納。|
|+43 | 2 |AD4の変換値。0～2000[mV]のAD値を16で割った値を格納。|
|+45 | 2 |AD1～AD4の補正値　（LSBから順に２ビットずつ補正値、LSB側が　AD1, MSB側が AD4）|
|+47| 2 |チェックサム|

### サンプルコード
Node.js 12.13.0 で記述する例です。serialport と socket.io は別途 npm install しておいてください。また、 ```COM15``` の部分は環境に合わせて修正してください。ブラウザから http://localhost:3000/index.html にアクセスするとセンサの内容を確認できます。下記の例では月毎にログを保存するようにしています。

```js:server.js
'use strict';

const SerialPort = require('serialport');
const parsers = SerialPort.parsers;
const parser = new parsers.Readline({
  delimiter: '\r\n'
});
const port = new SerialPort('COM15',{
  baudRate: 115200
});
port.pipe(parser);


var fs = require('fs');

var app = require('http').createServer(function(req, res) {
  res.writeHead(200, {'Content-Type': 'text/html'});
  res.end(fs.readFileSync('index.html'));  
}).listen(3000);

var io = require('socket.io').listen(app);

var toDoubleDigits = function(num) {
  num += "";
  if (num.length === 1) {
    num = "0" + num;
  }
 return num;
};

port.on('open', () => {
  console.log('port open');
});
parser.on('data', (data) => {
        console.log('data received: ' + data.toString() +"*");
        io.sockets.emit('msg', data.toString());
        var fs = require('fs');
        
        var date = new Date();
        var yyyy = date.getFullYear();
        var mm = toDoubleDigits(date.getMonth() + 1);
        var unixtime = parseInt(date/1000);
        fs.appendFile(yyyy + mm + '.txt',  unixtime + ',' + data + '\r\n', 'utf8', function (err) {
            if(err != null){
                console.log(err);
            }
        });
});
```

```html:index.html
<!DOCTYPE html>
<meta charset="UTF-8">
<head>
<title>TWE-Lite 読み取り</title>
<script src="/socket.io/socket.io.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script>
$(function() {
  var socket = io.connect();
  socket.on('msg', function(data) {
    var date = new Date();
    var sensorId = data.substr(1, 2);
    var sensorVoltage = data.substr(27, 4);
    var sensorValue = data.substr(33,2);
    
    var str = date.toString()
       + "センサ:" + sensorId + " (" + parseInt(sensorVoltage,16) + " mV) => " + sensorValue;
    
    $('div').prepend(str + '<br>');
  });
});
</script>
</head><body><div></div></body></html>
```

ブラウザでの表示例です。
>Fri Dec 05 2014 23:46:02 GMT+0900 (東京 (標準時))センサ:01 (2906 mV) => 00
>Fri Dec 05 2014 23:45:55 GMT+0900 (東京 (標準時))センサ:02 (2849 mV) => 00
>Fri Dec 05 2014 23:45:45 GMT+0900 (東京 (標準時))センサ:04 (3108 mV) => 01

明日は、cubic9com さんの 「家電を赤外線で操作するR2-D2を作った話」 です！