TWELITEを使ってI2Cセンサーを無線化しよう

# はじめに

この記事は、[mohikanz #2 Advent Calendar 2018](https://adventar.org/calendars/3057)の12日目の記事です。

マイコンセンサーを無線化するにあたって、とても便利なTWELITEを使うための手順です。
ざっくり言うと、最初から設定されている標準アプリ（App_Twelite）を、無線タグアプリ （App_Tag）に変更する手順です。
ここで言うアプリとは、マイコンデバイスに搭載されているファームウェアのことを言います。

## 何が便利なの?

ラズパイなどでセンサーから値を取得している方はご存知かと思いますが、I2Cセンサーから値を取得するためには、それなりのロジックが必要です。
無線タグアプリを使うと、センサー固有の特別なロジックは不要で、値を取得することが可能です。
CSV形式など人が見やすい形にしたり、コンピュータが処理しやすい形式にしたり、とても便利なデバイスです。
また、有線ではなく、無線でやりとりが可能なので、センサーの置き場所問題も解決します。（電源問題はありますが）


公式サイトより

- 無線タグアプリ（App_Tag）は各種I2Cセンサー用のドライバを内蔵しており、接続するだけで動作させることができます。


# 作業環境

- MacBook Pro 2016モデル
- MacOS Mojave
- USBポートに変換するアダプタ
- TWELITE USBスティック高出力タイプ(RED)
- TWE-Lite-R
- MicroUSBケーブル
- ブレッドボード、ジャンパワイヤー

# 親機の設定

親機から設定します。
子機からやっても問題ありません。

## ファームウェアのダウンロード

ファームウェアは、以下のURLにあります。
事前にダウンロードしておいてください。

超簡単！標準アプリ（App_Twelite）ダウンロード
https://mono-wireless.com/jp/products/TWE-APPS/App_Twelite/download.html

無線タグアプリ （App_Tag）ダウンロード
https://mono-wireless.com/jp/products/TWE-APPS/App_Tag/download.html


## デバイスの確認

デバイスと接続確認を行います。

```shell-session
$ ls -1 /dev/cu.*
/dev/cu.Bluetooth-Incoming-Port
/dev/cu.MALS
/dev/cu.SOC
/dev/cu.usbserial-MW2HPG7R
/dev/cu.usbserial-MWS47KJ

$ screen /dev/cu.usbserial-MW2HPG7R 115200
```

インタラクティブモードは、+++　を入力します。

```shell-session
--- CONFIG/MONO WIRELESS TWELITE APP V1-08-1/SID=0x82012487/LID=0x00 ---
 a: set Application ID (0x67720102) 
 i: set Device ID (121=0x79) 
 c: set Channels (18) 
 x: set Tx Power (03) 
 t: set mode4 sleep dur (1000ms) 
 y: set mode7 sleep dur (10s) 
 f: set mode3 fps (32) 
 z: set PWM HZ (1000,1000,1000,1000) 
 o: set Option Bits (0x00000020) 
 b: set UART baud (38400) 
 p: set UART parity (N) 
---
 S: save Configuration
 R: reset to Defaults
```

終了は、CTRL+A -> K -> yです

```
[screen is terminating]
```

## ファームウェア更新準備

ファームウェアを適当なディレクトリに解凍し、依存するパッケージをインストールします。
すでにインストール済みであれば、作業不要です。

```shell-session
MWSDK$ brew install libusb
MWSDK$ pip3 install --upgrade pip
MWSDK$ pip3 install pyserial
MWSDK$ pip3 install pyftdi
```

私の環境

```shell_session
$ pip3 list
Package        Version   
-------------- ----------
beautifulsoup4 4.6.3     
bs4            0.0.1     
certifi        2018.10.15
chardet        3.0.4     
idna           2.7       
pip            10.0.1    
pyftdi         0.29.2    
pyserial       3.4       
pyusb          1.0.2     
requests       2.20.0    
setuptools     39.0.1    
urllib3        1.24 
```

## 親機のファームウェア更新

FTDIドライバを無効にします。
シリアル通信しているデバイスやアプリがあると、OSがハングアップする場合もあるので、作業するときは注意してください。

```shell-session
$ sudo kextunload -b com.apple.driver.AppleUSBFTDI
```

`/dev/`からデバイスが消えていることを確認します。

```shell-session
$ ls -1 /dev/cu.*
/dev/cu.Bluetooth-Incoming-Port
/dev/cu.MALS
/dev/cu.SOC
```

MONOSTICKのデバイスIDを確認します。
私は、TWE-Lite-Rも接続しているので、ファームウェアを導入するデバイスIDを確認します。
一旦デバイスを抜くなりして、間違えないようにしてください。

```shell-session
$ ./Tools/tweprog_py/tweterm.py -p ftdi:///?
Available interfaces:
  ftdi://ftdi:232:MW2HPG7R/1   (MONOSTICK)
  ftdi://ftdi:232:MWS47KJ/1    (TWE-Lite-R)

Please specify the USB device
```

確認できたら、ファームウェアを書き込みます。BlueとRedは、別ファームウェアなので気をつけます。
また、SDKに含まれているバージョンはv2.1.3ですが、v2.1.5が公開されているので、そちらを適用しました。
デバイスIDと書き込みたいファームウェアを再度確認し、コマンドを投入します。
書き込みが完了したら、ts出力(タイムスタンプ)がずらずらっと流れてくるので、Ctrl+Cを2回押して一旦終了します。

```shell-session
$ ./Tools/tweprog_py/tweterm.py -p ftdi://ftdi:232:MW2HPG7R/1 -F ./App_Tag_bin_2_1_5/App_Tag-Parent-RED-MONOSTICK.bin -b 115200

*** TWE Wrting firmware ... ./App_Tag_bin_2_1_5/App_Tag-Parent-RED-MONOSTICK.bin
MODEL: TWEModel.TWELiteRED
SER: 2012487
FILEINFO: 0f 03 000b
0%..10%..20%..30%..40%..50%..60%..70%..80%..90%..done - 10.52 kb/s
Entering minicom mode

*** App_Tag (Parent) 2.01-5 ***
* App ID:67726305 Long Addr:82012487 Short Addr 0487 LID 00
::ts=1
::ts=2
::ts=3
::ts=4
::ts=5
::ts=6
::ts=7
::ts=8
::ts=9
::ts=10
*** r:reset i:+++ A:ASCFMT B:BINFMT x:exit>::ts=11
[Exit]
Bye.
```

FTDIドライバを有効にします。

```shell-session
$　sudo kextload -b com.apple.driver.AppleUSBFTDI
```

USBシリアルデバイスが参照できることを確認します。

```shell-session
$ ls -1 /dev/cu.*
/dev/cu.Bluetooth-Incoming-Port
/dev/cu.MALS
/dev/cu.SOC
/dev/cu.usbserial-MW2HPG7R
/dev/cu.usbserial-MWS47KJ
```

## 親機の設定変更

::tsが出ている状態で```+++```を入力し、インタラクティブモードに入ります。

```
$ screen /dev/cu.usbserial-MW2HPG7R 115200
::ts=10
::ts=11
::ts=12
--- CONFIG/App_Tag V2-01-5/SID=0x82012487/LID=0x00 ---
 a: set Application ID (0x67726305) 
 c: set Channels (15) 
 x: set Tx Power (3) 
 b: set UART baud (38400) 
 B: set UART option (8N1) 
 k: set Enc Key (0xA5A5A5A5) 
 o: set Option Bits (0x00000001) 
---
 S: save Configuration
 R: reset to Defaults
```

データ処理の都合上、タイムスタンプ出力が不要でしたので、これを変更します。
オプションビットが、```0x00000001```になっているので、```0x00020000```に変更します。
他にも設定可能な値があり、公式サイトに記載があります。
処理のしやすい形に変更しましょう。

|ビット（１６進）|説明|
|:---------|:--------|
|　　0x00000001　|　初期値　|
| 0x00000020 | UART出力をセミコロン区切り形式で出力します。 |
| 0x00000040 | UART出力をカンマ区切り形式で出力します。 |
| 0x00000100 | UART出力を書式形式のアスキー文字で出力します。 |
| 0x00000300 | UART出力を書式形式のバイナリ系列で出力します。 |
| 0x00001000 | 暗号化通信を有効にします。（相手側の暗号化設定もしてください。） |
| 0x00020000 | 標準出力形式、セミコロン区切り形式、カンマ区切り形式時のタイムスタンプの出力を停止します。 |
| 0x00040000 | シリアルのボーレートやパリティの設定を反映させます。 |


### 設定後イメージ

```
--- CONFIG/App_Tag V2-01-5/SID=0x82012487/LID=0x00 ---
 a: set Application ID (0x67726305) 
 c: set Channels (15) 
 x: set Tx Power (3) 
 b: set UART baud (38400) 
 B: set UART option (8N1) 
 k: set Enc Key (0xA5A5A5A5) 
 o: set Option Bits (0x00020000)*
---
 S: save Configuration
 R: reset to Defaults

!INF FlashWrite Success
!INF RESET SYSTEM...
*** App_Tag (Parent) 2.01-5 ***
* App ID:67726305 Long Addr:82012487 Short Addr 0487 LID 00
```

### TWE-Lite-R で繋がっている親機設定

他にも親機がいるので、設定値を確認しました。
参考資料ですが。
同じApplication ID？だと、複数親機がいても受信できるみたいですね。

```
$screen /dev/tty.usbserial-MWS47KJ 115200

--- CONFIG/App_Tag V2-01-5/SID=0x8102e282/LID=0x00 ---
 a: set Application ID (0x67726305) 
 c: set Channels (15) 
 x: set Tx Power (3) 
 b: set UART baud (38400) 
 B: set UART option (8N1) 
 k: set Enc Key (0xA5A5A5A5) 
 o: set Option Bits (0x00020000) 
---
 S: save Configuration
 R: reset to Defaults
```

### 子機からのデータ受信

子機から受信したデータのイメージです。

```
::rc=80000000:lq=84:ct=34BC:ed=8102E338:id=1:ba=2960:a1=0921:a2=0508:te=2450
```

# 子機の設定

子機は、TWE-Lite-Rを使って書き込みを行います。


## 子機のファームウェア更新

FTDIドライバを無効にします。

```shell-session
$ sudo kextunload -b com.apple.driver.AppleUSBFTDI
```

`/dev/`からデバイスが消えていることを確認します。

```shell-session
$ ls -1 /dev/cu.*
/dev/cu.Bluetooth-Incoming-Port
/dev/cu.MALS
/dev/cu.SOC
```

TWE-Lite-RのデバイスIDを確認します。

```shell-session
$ ./Tools/tweprog_py/tweterm.py -p ftdi:///?
Available interfaces:
  ftdi://ftdi:232:MW2HPG7R/1   (MONOSTICK)
  ftdi://ftdi:232:MWS47KJ/1    (TWE-Lite-R)

Please specify the USB device
```

無線タグ子機アプリのバイナリを確認し、書き込みを行います。

```shell-session
$ ./Tools/tweprog_py/tweterm.py -p ftdi://ftdi:232:MWS47KJ/1 -F ./App_Tag_bin_2_1_5/App_Tag-EndDevice-BLUE.bin -b 115200
```

書き込みが完了したら、親機と同じようにCtrl+Cを2回押して抜けます。

FTDIドライバを有効にします。

```shell-session
$　sudo kextload -b com.apple.driver.AppleUSBFTDI
```

USBシリアルデバイスが参照できることを確認します。

```shell-session
$ ls -1 /dev/cu.*
/dev/cu.Bluetooth-Incoming-Port
/dev/cu.MALS
/dev/cu.SOC
/dev/cu.usbserial-MW2HPG7R
/dev/cu.usbserial-MWS47KJ
```

## 子機の設定変更

子機は間欠駆動しているので、親機のように+を3回入力してインタラクティブモードへの移行が出来ません。
インタラクティブモードに入るには、M2をGNDに接続し、電源を投入します。
ちょっと強引ですが、ブレッドボードに押し付ければ、うまく繋がります。

<img width="474" alt="スクリーンショット 2018-12-10 14.54.23.png" src="https://qiita-image-store.s3.amazonaws.com/0/150734/eb3f0464-f50c-7c51-ea7c-65a37e0cf972.png">

公式サイトに書いてあるので、その通りにやってみます。
接続しても、何も表示されないので、TWE-Lite-Rの「RSTボタン」を押します。
基盤の右端にありますので、押してみましょう。

公式サイトはこちらです。
https://mono-wireless.com/jp/products/TWE-APPS/App_Tag/interactive.html#enddevice


```shell-session
$ screen /dev/tty.usbserial-MWS47KJ 115200

--- CONFIG/App_Tag V2-01-5/SID=0x8102e338/LID=0x01/RC=9101/ST=0 ---
 a: set Application ID (0x67726305) 
 i: set Device ID (1=0x01) 
 c: set Channels (15) 
 x: set Tx Power (13) 
 b: set UART baud (38400) 
 B: set UART option (8N1) 
 k: set Enc Key (0xA5A5A5A5) 
 o: set Option Bits (0x00000001) 
 d: set Sleep Dur (120000) 
 w: set Sensor Wait Dur (30) 
 m: set Sensor Mode (0x32) 
 p: set Sensor Parameter (0) 
 P: set Sensor Parameter2 (  ) 
---
 S: save Configuration
 R: reset to Defaults
```

データは、120秒間隔で親機へ送信するようにしました。
あまり多いと電池の消耗も激しくなるので、状況に応じて使い分けてください。

```d: set Sleep Dur (120000) ```


以下のメッセージが表示される場合は、通常モードで起動しているので、おそらくM2とGNDがうまく接続されていません。回路を確認してください。

```shell-session
*** App_Tag (ED_Inp) 2.01-5 ***
* App ID:67726405 Long Addr:8102e338 Short Adr 0078 LID 01 Calib=9102

*** Entering Config Mode ***
>>> TxCmp Ng(tick=33,req=#0) <<<
!INF:OTA TIME OUT
!INF:OTA SKIPPED. START NORMALLY. 01
```

# ラズパイで動作確認

4つあるポートのどこでも良いので、親機を接続します。

```shell-session
$ ls -1 /dev/ttyUSB0
/dev/ttyUSB0
```

## cuコマンドで確認

MONOSTICKがRaspberry Piで認識できたら、cuコマンドを使ってシリアル通信を行ってみます。

```shell-session
$ sudo apt install cu

$ cu -s 115200 -l /dev/ttyUSB0
Connected.

::rc=80000000:lq=159:ct=004D:ed=8102E338:id=1:ba=2960:a1=0921:a2=0506:te=2700
```

~.(チルダ ピリオド)を入力するとプログラムが終了します。


## Pythonで確認

シリアル通信で定評のある？、Pythonを使います。
個人的にNode.jsでも良かったのですが、ラズパイだと色々ありまして、Pythonにしました。

シリアル通信に必要なモジュールをインストールします。

```
$ pip3 install pyserial
Collecting pyserial
  Downloading https://files.pythonhosted.org/packages/0d/e4/2a744dd9e3be04a0c0907414e2a01a7c88bb3915cbe3c8cc06e209f59c30/pyserial-3.4-py2.py3-none-any.whl (193kB)
    100% |████████████████████████████████| 194kB 1.2MB/s 
Installing collected packages: pyserial
Successfully installed pyserial-3.4
```

動作確認用のソースは、以下のサイトからお借りしました。

TWE-Lite DIPをRaspberry Pi上のToCoStickとPythonプログラム経由で通信しLチカ
https://www.skyarch.net/blog/?p=4941

```python:index.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import serial
import sys

argv = sys.argv
argc = len(argv)

def read_serial(s):
        while True:
                line = s.readline()
                print line.strip()

# USBデバイスの指定
if argc != 2:
        s = serial.Serial("/dev/ttyUSB0", 115200, timeout=130)
else :
        s = serial.Serial(argv[1], 115200, timeout=130)

while True:
        try:
                read_serial(s)
        except KeyboardInterrupt:
                break
        except:
                continue

s.close()
```

実行結果です。あとはご自由にどうぞ。
Python3で実行すると、エラーが出ますので、適切に修正してください。
(めちゃくちゃハマった...)

```
$ python index.py /dev/ttyUSB0
::rc=80000000:lq=147:ct=0061:ed=8102E338:id=1:ba=2960:a1=0926:a2=0511:te=2743
```

# 回路

回路図はここにありますので、参考に作成してください。
https://mono-wireless.com/jp/products/TWE-APPS/App_Tag/mode_ADT7410.html

そんなに部品もないので、簡単に作れます。
こんな感じで作ってみました。
もうちょっと小さく出来るんじゃない？回路が美しくない!
などなど、色々思うことはあります(汗)
親機は、この記事を書いたあとで、USBスティックの方に切り替えました。

子機
<img width="547" alt="スクリーンショット 2018-12-10 14.52.42.png" src="https://qiita-image-store.s3.amazonaws.com/0/150734/efa68383-3f6d-bada-dbaf-c216b3908766.png">

親機 (TWE-Lite-R)
<img width="984" alt="スクリーンショット 2018-12-10 14.52.04.png" src="https://qiita-image-store.s3.amazonaws.com/0/150734/16a4bb42-03d6-9004-c98b-21210672d123.png">


# 参考にさせていただいたサイト

TWELITEの無線タグアプリを試す
https://qiita.com/miminashi/items/453f7f3e31c8c009e486

TWE-Lite DIPをRaspberry Pi上のToCoStickとPythonプログラム経由で通信しLチカ
https://www.skyarch.net/blog/?p=4941