Raspberry Pi と TWELITE で格安無線通信

※「格安」とは個人の主観です。

諸般の事情から、大自然に囲まれた我が家の周辺にメッシュネットワークを構築しようとしています。
無線通信のモジュールとしては今回紹介する 2.4GHz 帯の他にも Lora などの LPWA が有力な選択肢となりますが、手始めに最も安価に、そして簡単にセットアップできそうな [Mono Wireless](https://mono-wireless.com/jp/index.html) 社の TWELITE を検証します。
※今回の記事は機器のセットアップと検証環境の作成がメインになります。

# 実験のために必用なもの
* Raspbery pi
 * OS：raspbian 9.3
 * 今回は手元にあった Raspbery pi 3 Model B を使いましたが、ZERO でもなんでも大丈夫だと思います。
* [MONOSTICK-モノスティック](http://akizukidenshi.com/catalog/g/gM-12120/)
 * 無線親機として Raspberry Pi に繋ぐ。3,980 円
 * なお、今回は高出力タイプの RED を使用しています。BLUE であれば 2,980 円。用途に応じて使い分けましょう。
* [TWELITE DIP RED](http://akizukidenshi.com/catalog/g/gK-12823/)
 * 無線子機、および中継器として使用。2,700 円
* [ケース内組込型アンテナ MW-A-P4208/TWE-AN-P4208](http://akizukidenshi.com/catalog/g/gP-07734/)
 * マッチ棒タイプのアンテナが主流のようですが、将来的にケース内組み込みを想定しているためこちらを購入。485 円
 * マッチ棒で良ければ、[既にアンテナ取り付け済みの TWELITE DIP](http://akizukidenshi.com/catalog/g/gM-12504/) も販売されています。
* お手持ちのブレッドボード
* お手持ちのジャンパワイヤ
* お手持ちの電池、電池ケース

さて、必要なものが揃ったらセットアップを進めます。
電子工作に不慣れな方(私です)でも、道具さえそろっていれば簡単です。

# MONOSTICK と Rapberry PI を接続して親機を設定
MONOSTICK は DIP に比べて 1,280 円高いですが、パソコンなどに USB で簡単に接続できるという魅力があります。

設定は MONOSTICK を起動中の Rapberry PI に USB 接続するだけで完了です。

### 認識されている？
MONOSTICK 内の LED が点灯するので認識されているかどうかはすぐに分かりますが、この後の作業で割り当てられたデバイス名も必要になるので Raspberry Pi のターミナルから確認します。
`ls /dev/ttyUSB?`
/dev/ttyUSBX が割り当てられているはずです。
※ X は連番で、他に何も USB 接続していない場合は 0 が割り当てられます。
# TWELITE DIP RED を使った子機の設定
ブレッドボード上で配線をして、子機として起動してみましょう。
TWELITE DIP に同封されているカードには L チカするための配線図が記載されていますが、子機として使用するだけであれば配線はもっとシンプルです。

1. まず、アンテナを TWELITE DIP に繋ぎます。アンテナの接続部を下図の赤丸で囲んだ個所にグッと押し込みました。
2. ブレッドボードに TWELITE DIP をセットします。
3. 使用する動作モードに応じて配線します。[公式ページ](https://mono-wireless.com/jp/products/TWE-APPS/App_Twelite/step2.html)に詳しく書いてありますが、今回は「間欠1秒モード」を使用したので、モード設定ビット（M3）を GND（電源のマイナス側）にジャンパワイヤで接続します。（下図、青丸で囲んだ個所）
![antena.jpg](https://qiita-image-store.s3.amazonaws.com/0/135861/2bd22ed0-2549-c65a-515e-b7662f2575c2.jpeg)
4. 電源の＋極を VCC に、－極を GND に接続します。

これで子機のセットアップも完了です。

# 受信確認
Raspberry Pi から MONOSTICK を読み出してみましょう。
公式ページには読み出し用の [Python スクリプト](https://mono-wireless.com/jp/products/TWE-APPS/App_Twelite/python_twelite/index.html)が用意されています。

このスクリプトを Raspberry Pi 上に保存し、実行します。
引数には先ほど調べた、Raspberry Pi に割り当てられたデバイス名を指定します。
`python twelite_read.py /dev/ttyUSB0`

以下のような出力が得られれば成功です。

```python:output
open serial port: /dev/ttyUSB0

:7C811501C0820218BF0000020002A8FD00000000000055D4
  command   = 0x81 (data arrival)
  src       = 0x7c
  src long  = 0x820218bf
  dst       = 0x00
  pktid     = 0x15
  prtcl ver = 0x01
  LQI       = 192 / -31.30 [dbm]
  time stmp = 0.031 [s]
  relay flg = 0
  volt      = 0680 [mV]
  DI1=0/0  DI2=0/0  DI3=0/0  DI4=0/0
  AD1=0004 AD2=0004 AD3=0004 AD4=0004 [mV]
```

もしうまく受信ができない場合は、アンテナの指向性に注意しながらアンテナや親機の位置を調整してみてください。[公式ページ](https://mono-wireless.com/jp/products/TWE-ANTENNAS/omni/index.html)にはそれぞれのアンテナの指向性も掲載されています。併せて[設置ガイド](https://mono-wireless.com/jp/products/TWE-ANTENNAS/design/range.html)もご参照ください。
なお、MONOSTICK にも指向性があるため、L 字型 USB コネクタで MONOSTICK を縦に設置するか、Raspberry Pi を立てて置くと受信感度が高くなります。 

# いざ、検証
ブレッドボードに設置した子機をタッパーに入れて屋外で実験しました。
200m くらいの距離で無事に送受信ができることが確認できたのですが、
### 思っていた以上に指向性がシビア

* 先の[設置ガイド](https://mono-wireless.com/jp/products/TWE-ANTENNAS/design/range.html)に詳しいですが、地面に置いた場合は著しく距離が狭まるので、設置方法には注意が必要です。
* 丁度良い高さに設置できたとしても、アンテナの向きや角度によっては受信できないケースもあります。100m を越えると、アンテナの向き、角度は非常に重要になります。
* 200m くらいではより難しくなり、子機をぶんぶん振り回しているとたまに受信に成功する、といった感じ。
 * 山肌に設置したので、親機との高低差があったことが原因かもしれません。
* 今さらですが、このくらいの距離であれば出力の劣る BLUE タイプでも十分だったかも。

### そして孤独を知る
うまく受信できているうちはまだ良いのですが、山を登って子機を設置して家に戻って MONOSTICK を確認、また山に戻って、、、という繰り返し作業は精神的にも肉体的にも辛いものがありました。

軽い実験だとたかを括っていましたが、やはり遠隔で親機の受信状況を確認できるようにする必要があります。
### そういう時はだいたい SpreadSheet でなんとかなる
外でも受信状況が確認できるように、先ほどの twelite_read.py に Google SpreadSheet の書き込み機能を追加しましょう。
Python で SpreadSheet への書き込みを行う方法は[この記事](https://qiita.com/AAkira/items/22719cbbd41b26dbd0d1)を参考に、使用する API は [gspread API Reference](http://gspread.readthedocs.io/en/latest/) を参考にしました。
Google Drive API の他、Google Sheets API も有効化してください。

```python:write_spreadsheet.py
import os
import gspread
from oauth2client.service_account import ServiceAccountCredentials
from datetime import datetime

def write_spreadsheet(line):
    scope = ["https://spreadsheets.google.com/feeds"]
    doc_id = "your spreadsheet id"
    path = os.path.expanduser("your json file path")

    credentials = ServiceAccountCredentials.from_json_keyfile_name(path, scope)
    client = gspread.authorize(credentials)
    gfile   = client.open_by_key(doc_id)
    worksheet  = gfile.sheet1
    
    write_line = [line,datetime.now().strftime("%Y/%m/%d %H:%M:%S")]
    worksheet.append_row(write_line)
```

この関数を先ほどの twelite_read.py 内のデータを受信した時の分岐で呼び出すようにします。
通信データとタイムスタンプが SpreadSheet にリアルタイムで書き込まれるので、スマホなどから受信状況が確認できます。
※実行時に urllib.py でエラーが出た場合、SpreadSheet のファイル名、シート名などに Unicode 文字が含まれていないかを確認してください。
※[無料利用時の制限](https://developers.google.com/apps-script/guides/services/quotas)として、50,000 / day までしか API を利用できません。間欠 1 秒モードで常に GAS を呼び出していると半日ほどでこの制限に達してしまうので、検証時のみの一時的な利用を推奨します。

これでぐっと検証がしやすくなりました。
今回はほとんど起動確認までで終わってしまったので、また時間のあるときに以下の検証を進めたいと思います。

* TWELITE DIP BLUE との比較
* アンテナごとの違いや感度
* 加速度センサー付き無線タグ、[TWELITE 2525A](https://mono-wireless.com/jp/products/TWE-Lite-2525A/)の動作確認