(溜まったネタを時系列に こだわらず書いている。今回は今までの一連の稿の始まり かつメインとなる話で、このシリーズの最後となる。)
換気扇を間欠運転しているタイマー XY-WJ01にはシリアル(UART)ポートが付いているので、それを使って遠隔制御することができる。システムができた当初は必要ないと思って居たものの、(おもしろそうだから)できるものは試したいし、使っているうちに、例えば「ちょっと(30分くらい)強制的に換気したい」というような場合があり、PCから換気扇をonにできて自動で元に戻れば便利だと思ったので、やりたくなった。
PCとタイマーの繋ぎ方の検討
PCをタイマーのシリアルポートに繋ぐ方法を検討したら、Wi-Fiが良さそうだった。
- 無線: 線がなくて美しいが、技適の壁のために安価なものは使えない場合がある。
- Wi-Fi
- IP通信なので、仕組みとしては ちょっと大掛かりになってしまう。
- 親機はルーターが使えるので、1台で済む。
- Bluetooth
- シリアルポートプロファイルは手軽で良い。
- こういうのが欲しかった。
- 2台(1ペア)必要なのが面倒だし、少し高く付く。
- ただ、最初は片方はスマフォでも良い。
- 僕には馴染みがない。
- シリアルポートプロファイルは手軽で良い。
- その他
- TWILITEシリーズ
- おもしろいし簡単に使えそうなのだが、独自規格だったり3.3Vだったりして、(僕には)ちょっと面倒・使いにくいのが残念。
- もしUARTが5V(トレラント)だったら、買ったかも知れない。
- オリジナル製品のため安くはない(かと言って すごく高い訳でもない)し、開発機器(と言うほど大掛かりではない)が要る場合もある。
- ここら辺が独自規格・製品の難点だと思う。
- 2台(1ペア)必要なのが面倒だし、少し高く付く。
- おもしろいし簡単に使えそうなのだが、独自規格だったり3.3Vだったりして、(僕には)ちょっと面倒・使いにくいのが残念。
- TWILITEシリーズ
- Wi-Fi
- 有線(UART): 比較的安く、使うのは超簡単だが、コードが部屋を這うのが綺麗でない。
- タイマーはAC 100Vを扱うので、通信路(タイマー - PC)を絶縁することが必須。
ただ、以前も書いたように、単純にWi-Fi - シリアルができる安い製品(しかも、技適認証済み)は なく、ESP32シリーズを使うのが一番良さそうだった。が、繋いで電源を入れるだけでは駄目で、少なくとも何らかの設定をしなければ使えないのが面倒だし、機能が豊富過ぎて もったいない。
それで、手元にWi-Fi内蔵SDカード PQI Air Card II(以下、Air Card)が眠って居たので使えないか検討したものの、問題・課題が多いので却下した。はずなのだが、前の稿に書いたように ちょっと思い付いて試したら、とんでもなく面倒なことになってしまった。
実は その前に、Air Cardを試すのにも使うのでUSB-シリアルアダプタを買い、タイマーに繋いでコマンドが実行できるようにしていた。
PCとタイマーを繋ぎ、タイマーのコマンドを実行できるようになるまで
まず、PCに適当なシリアルポート(信号レベルはRS232(±12Vなど)でなくUART(0, 5Vなど))がないので、USB-シリアルアダプタ(以下、シリアルアダプタ)を買った。選ぶ時、仮にAir Cardが駄目でもタイマーに直接接続できるように、絶縁型にした。
なぜ絶縁型にしたかというと、仮にタイマーが扱うAC 100Vがシリアルに漏れた場合でもPCを損傷させないためである。絶縁型であれば、仮にAC 100Vがシリアルに漏れてもPCのUSBポートには入らないはずで、タイマーは壊れるものの、PCは安全だ。
シリアルアダプタは、秋月のFT234X+ADuM121N使用絶縁USBシリアル変換モジュールにした。約千円だった。他に必要な部品(3.3V電源レギュレータ(Air Cardの電源にしようと思ったが、結局使わなかった)やXHコネクタなど)も一緒に買った。
届いてから動作確認(Linuxでのデバイスの認識やループバック通信)をしたところ、ちゃんと動いた。
選ぶ時に少し迷ったのだが、アダプタのチップは実績・定評のあるFTDIのもので良かったと思う。当然ながら挿せば動くし、例えば、タイマーへの通信がうまく行かなくて(後述)、転送速度のズレを疑った(実際には問題なかった)時に簡単に微調整(例: ±10%)できたのは良かった。
それからシリアルアダプタをタイマーに接続できるように基板にXHコネクタを付け、タイマーに繋げてコマンドを試したところ、なぜか処理されず、全部"FAIL"になってしまった。
一番まともそうなマニュアル(買った製品には添付されていない)を出しているメーカーらしき会社(そもそもメーカー名が不明なので、単なる商社かも知れない)に問い合わせても、マニュアルの関連箇所のコピーしか来なかった。不良品(ソフトにバグがある)と考えて買った店に問い合わせたが、やっぱりマニュアルのコピー(文章は中国語)を提示するだけで、「物は ちゃんと送った。製品に問題はない」などと無責任極まりない対応だった。更に、製品に問題のない(動作している)証拠を求めたが出して来なかった。
仕方ないので一旦諦めることにして、あとで使う時に壊れにくくなるようにシリアルアダプタをケース(壊れた100円カードリーダーのものを加工した)に収めたり、タイマー基板の入出力の一括接続用のXHコネクタを付けて整理した。
が、その後いろいろ試したら解決できた。: タイマーのコマンドは「一発で」送らなくてはならないのだ。例えば、設定を取得するコマンド"read"をターミナルソフト(例: minicom)で手で"r", "e", "a", "d"と打ち込むのは駄目で、それぞれの文字が"FAIL"になる。
一方、プログラム(LinuxのechoコマンドでOK)で一回で"read"と送れば成功する。※ ターミナルソフトでも、(あらかじめクリップボードに入れておいた)"read"をペーストすれば成功する。(図: ローカルエコーoffのため、画面には送信文字列(コマンド)が出ていないが、"read", 改行, 改行, 改行, "read"を送っている。)
おそらく、文字の受信間隔が しきい値より長いと、コマンドの区切りとしているのだろう。
※このことに気付いたのは、転送速度が異なるためかと思って微調整の仕方を調べたら、速度設定のあとにechoで文字を送信する例があって、最初なので そのとおりに試したら動いたことだった。本当に速度が違うのかと思って、上下限を調べたら調整なしの速度(9600bps)でも動いて、速度でなく送信方法がポイントだったことが分かった。
ただ、使ってみて分かったが、想像通りクロックが余り正確でないようで、タイマーの継続時間が結構狂う。大体、設定の7%くらい(例: 10分で42秒)短くなる。この調子だと温度でも変わりそうだ。
これはマニュアルに書いてない*ので、「ちょっと普通に」試したら全部"FAIL"になってしまう。※
*もしかして、元々の中国語版のマニュアル(あるのか不明)を読めば、文章の本来の意味から分かるのかも知れないが、全くの無理筋だ。あるいは、(PS1に書いたことに関連するが、)発注元の仕様書には書いてあって そう実装したけど、(テキトーな誰かが作った)マニュアルには書かれなかったのかも知れない。
※メーカーらしき会社の掲示板に、別の製品だが、同じ問題で困った人が居た。それに対しても通り一遍の回答で、「一回で送る」という情報はなかった。だから、その会社も単に売っているだけなのかも知れない。なお、呆れたのか諦めたのか、質問者からの返信はなかった。
Linux(bash)でタイマー XY-WJ01にreadコマンド(設定の取得)を送り、応答を受信する例を以下に示す。
timer_tty="/dev/ttyUSB0"
stty -F $timer_tty 9600 pass8 -cstopb -echo
my_tty=`tty`
tmo_s=1
timer_cmd="read"
bash -c "echo -n $timer_cmd; read -t $tmo_s res; echo \$res > $my_tty" < $timer_tty > $timer_tty
→ 結果: P6,OP:0.0.1.0,CL:0.0.3.5,LP:----
※他のコマンド(例: "P7"(モード7に変更))を実行したい場合は、変数timer_cmdに設定すれば良い。また、タイマーが接続されていない時や電源offの時に待ち続けないようにするため、readにタイムアウト(変数tmo_s, 1秒)を指定している。
(4/4 14:02) sttyに指定する通信設定を修正した。*: 一番重要なのは -echo で、これでエコーバックを停めないと、タイマーから送信された文字列がタイマーに送り返されて、エラーになったり設定が変わってしまうことがある。: 後述の、off時間が0("CL:0000")になってしまう現象の原因は これでないかと推測している。
*実際には他にも指定しているが、上記のものだけで充分である。
また、bashで実行するコマンドのリダイレクトも修正した。: 当初は検索して見つかった例のまま、意味を良く考えずに使っていたが、stderr(fd= 2)をstdout(fd= 1)にリダイレクトすると、Linux側のコマンドのエラーがタイマーに送られてしまうので良くない。
上の例は長くて分かりにくいかも知れないが、肝は一番最後の行のechoとreadだけで、やっていることは以下である。
stty -F /dev/ttyUSB0 9600 pass8 -cstopb -echo
echo -n "read" > /dev/ttyUSB0
read -t 1 res < /dev/ttyUSB0
echo $res
細かいことを書くと、こちらの場合は、(可能性は低いものの、)echoでタイマーにコマンドを送ってからreadを実行するまでに来た応答を取得できない。
そして、細くて長い(15m)電話線(モジュラーコード)※を買い、(長さが確定していないので、)モジュラージャックを切らずに接続するためのアダプタを作り、PCから洗面所まで「仮敷設」し、(コマンドは上のように手で打つものの、)PCからタイマーを制御できるようになっている。
※シリアルアダプタの端子数は4個(電源, 送信, 受信, GND)で、丁度電話用のモジュラーコードの芯数に合うのと細いコードが手頃な値段で売っているので、そうした。なお、15mは基本的にはシリアル通信には長いが、転送速度が9600bpsと遅いので問題ないと考えた。
- USB-シリアルアダプタ(一番下)は すごく小さい(ケースに壊れたSDカードリーダー(上)を使えそうだと思った)。
- USB-シリアルアダプタにXHコネクタを付け、ループバックテストはOKだった。
- タイマーXY-WJ01とPCの通信を試したが、駄目だった。
- タイマーXY-WJ01にどんな文字を送っても”FAIL”しか返って来ない。
- USB-シリアルアダプタにケースを付けた。
- → ケースのスペーサー(基板上下の白い細長い棒)が絶縁を悪化させるかも知れないと思ったので、改良した。 (3/22 10:09)
- USB-シリアルアダプタにコードを繋いだところ。 (注: XHコネクタ(右)側のコードはダミー)
- タイマーとの接続をXHコネクタ(5ピン)にした。リレーのNC接点も出した(紫色)。
- ようやくタイマーXY-WJ01と通信できた。マニュアルが不十分だったせいで失敗していた。 (“read”, 改行, 改行, 改行, “read”を送っている。)
- タイマーと通信できたので、タイマーとシリアルアダプタを電話線に繋ぐアダプタを作った。モジュラージャックの分岐アダプタを分解して使った。
- タイマーに電話線を繋いだところ。
- 最新のシステム構成・接続図
タイマーの遠隔制御の機能と実装
タイマーの遠隔制御の使い方(ユースケース)を検討し、以下のような機能を実現しようと考え、概ね実装した。
なお、下の指定時間on/offしている間にPCが再起動したりスリープした場合にタイマーの状態が元に戻らない(例: onまたはoffになったまま)のは良くないので、そうならないような方式を考えた。
そのため、「連続on」や「連続off」の機能は作らない。連続on/offしたい場合は、例えば「24時間」のように充分長い時間を指定するようにする。
実際、無限にon/offしたいことは ないし、仮にそうするなら、手で換気扇のスイッチをonにしたり、タイマーの電源を切れば良い。
- (一時的に、)指定時間(T1)onする。
- タイマーのモードがP6(on, offの繰り返し)の場合、設定(同じ設定でも可)を書き込むとonになるので、現在の設定をそのまま書き込むことで、設定のon時間(Tonとする)のonにする。
- XY-LJ02と違い、XY-WJ01には即座にon/offするコマンドがないので、このようにする。
- 以下の処理でT1のonを行う。
- モードがP6でない場合、P6にする。 → 最大Tonのonになる。
- 設定の書き込み。 → 最大Tonのonになる。
- T1の端数(T1 mod Ton)と繰り返し中の短縮分(例: 20秒x繰り返し回数)のsleepをする。
- T1/Ton > 1の場合、以下をT1/Ton-1回繰り返す。
- Tonよりわずかに(例: 20秒)短いsleepをする。※
- 設定の書き込み。 → Tonのon
- 仮に上の処理中にPCが再起動したりスリープした場合、最後のonのあとは通常のタイマー動作(on, off)に戻る。
- タイマーのモードがP6(on, offの繰り返し)の場合、設定(同じ設定でも可)を書き込むとonになるので、現在の設定をそのまま書き込むことで、設定のon時間(Tonとする)のonにする。
- (一時的に、)指定時間(T2)offする。
- タイマーのモードがP6の場合、P7(off, onの繰り返し)に変更するとoffになるので、そうすることで設定のoff時間(Toffとする)のoffにする。
- 以下の処理でT2のoffを行う。
- モードがP7でない場合、P7にする。 → 最大Toffのoffになる。
- 設定の書き込み。 → 最大Toffのoffになる。
- T2の端数(T2 mod Toff)と繰り返し中の短縮分(例: 20秒x繰り返し回数)のsleepをする。
- T2/Toff > 1の場合、以下をT2/Toff-1回繰り返す。
- Toffよりわずかに短いsleepをする。※
- 設定の書き込み。 → Toffのoff
- 仮に上の処理中にPCが再起動したりスリープした場合、最後のoffのあとはP7のタイマー動作(off, on)になる。
- これはP6と位相が異なるだけで、on/offの周期・比率は同じである。
- 終了後にモードをP6に戻すのが望ましいが、そのままでも次回の制御時にモードを取得して適宜対応すれば良い。
- 動作パターン(設定)を変更する。
- 単純に、新しい設定をタイマーに書き込めば良い。
- 設定のプリセット的なもの(例: 強, 中, 弱)を作り、それをタイマーに設定するようにすれば操作が楽になる。
※タイマーが設定でon/offするより前に それらを継続することで、換気扇のon/off動作を途切れさせないためにそうしたが、実際に使ってみると、多少途切れても実害はなく、そこまで厳密にする必要はないことが分かったので、今は、処理を簡単にするため、スリープ時間はタイマーのon/off時間(TonまたはToff)にしている。
同様に、タイマーのon/off時間の整数倍でない時間で換気扇をon/offする必要性も薄い気がしたので、今は、指定されたon/off時間(T1またはT2)をタイマーのon/off時間(TonまたはToff)の整数倍に丸めている。 (4/16 7:29)
これから(= 気が向いたら)プログラムを作るところだが、大方出来た つもりになってしまって作るのが面倒なので、こうしてブログを書いたりしているw
↓
(3/22 16:43) その後、なぜか やる気が出たので、上の指定時間on/offするプログラムを作った。また、YAD(Yet Another Dialog)というプログラムで とっても簡単なGUIを作った。既に いくつか不満はあるが、使いながら改良して行きたい。
- YADで換気扇リモコンのGUIを作ってみた。
- 時間指定はメニューから選択または数値入力で指定する。
- 残り時間を示す簡易なプログレスバーも付けた。
- 暫定版アイコン※も付けた。
※UXWingのVentilation Fan Blower iconを使用した。
↓
(3/23 9:30) 更に、Xfceのパネル(Windowsのタスクバーに相当)に入れて※手軽に かつダイアログの場所を取らずに使えるようにした。この部分をクリックすると、上の設定ダイアログが出て、タイマーの設定周期とは関係なく、指定した時間だけ換気扇をon/offすることができる。
※Generic monitorというウィジェットを使った。なお、パネルの空き(場所)が少ないため、CPU温度のウィジェットは止めた。タイマー(パネルの"Timer"のウィジェットのこと。制御対象のタイマーではない)が無駄に場所を食っているのだが、直せないので仕方ない。
- 換気扇リモコンのウィジェットをXfceのパネルに入れた。: “Vent”とその下のバー
- リモコンで換気扇をonにしている場合: バーは残りのon時間を示す(減る)。
- 同、offにしている場合: バーはoff経過時間を示す(増える)。
- マウスオーバーで詳細・説明を出す。
(3/26 20:57) 換気扇の動作パターンも設定できるようにした。とりあえず、on/off時間を3種類(H= 強, M= 中(標準), L= 弱)から選べるようにした。On時間の割合は、H: 約40%, M: 約22%, L: 約13%としてみた。
- 換気の強さを設定できるようにした。: “Fan mode”
- 換気の強さの設定: H, M, Lから選ぶ。
- 現在の換気の強さをバー(Vの右)の高さで表示するようにした。
- 通常時 (H= 強)
- 換気扇on時 (M= 中)
- 換気扇on時 (H= 強)
- (3/27 14:10) 表示を改良し、見やすく、かつ、うるさくなくした。
- 通常時 (H= 強)
- 通常時 (M= 中)
- 換気扇on時 (H= 強)
- 換気扇on時 (M= 中)
- 換気扇on時 (L= 弱)
それから、当初は接続を無線(Wi-Fi)にしようと思って居たが、電話線は充分細くて目立たないし、タイマーのコマンドの機能は少なく※苦労して無線にするほどのものではないので(ただ、GPIO付きのWi-Fi基板なら、タイマーの状態が取れそうだ)、上述の遠隔制御機能ができたら電話線を正式(綺麗)に敷設して、終わりにしようと思っている。
※以下のような惜しいことがある。
- コマンドで設定の取得や変更はできるが、状態(例: 現在onなのかoffなのか)を取得できない。
- 例えば通信を絶縁I2C(あるいは、上述のようにWi-Fi)にし、その先にシリアル通信とGPIOの可能な基板を付ければできる気はしているが、そこまでする必要性はないし、やってもon/off程度しか分からない。単なる興味だw
- 同じシリーズのXY-LJ02(基板のみの製品)のように、即座にon/offするコマンドがあると便利だ。
- だから、WJ01のstart/stopコマンドはLJ02でon/offになったのかも知れない。
タイマーのUARTコマンド・動作で分かったこと (3/26 12:34追記)
- 現在と異なるモードを設定すると、(当然ながらそのモードになるが、)その時のリレーのon/offは そのモードの最初の状態になる(例: P6ならonになる)。また、時間のカウントはリセットされる。
- 現在と同じモードを再設定した場合、(パラメタを再設定した場合の動作とは異なり)リレーのon/offは そのモードの最初の状態になる。
- 時間のカウントの詳細は未確認だが、以下のような感じである。
- On/offの状態が現在と変わる場合は時間のカウントがリセットされる? (リセットされないこともある?)
- On/offが変わらない場合はカウントがリセットされない?
- 時間のカウントの詳細は未確認だが、以下のような感じである。
- 上の2つにより、XY-LJ02のように、即座にリレーをon/offすることもできる(ただし、on/offされている時間は設定による)。
- 例: P6にすればonになり、P7にすればoffになる。
- 複数のコマンドを , で区切って一括して送れる(要するにreadコマンドの出力と同じ形式)。
- 任意の順序・数(もちろん上限はある)のコマンドが送れる。
- ただし、モード(Px)を指定した場合にはLP以外は無効になる。
- UARTコマンドを実行すると、たまにタイマーの設定が壊れることがある。
- Off時間が0("CL:0000")になってしまう。
- この場合、タイマーが停まる。
- 壊れる契機は不明。
- コマンド実行後の待ち時間が短いため?
- そのため、コマンド実行後に設定を取得し、いずれかのパラメタが"0000"になった場合は壊れたと判断して元の設定を再設定するようにした。
- (4/4 14:20) 上に追記したように、この問題の原因はタイマーコマンドの送受信の仕方の問題だと推測している。
- 以下に、推測した問題発生の流れを示す。
- [コマンド実行プログラム] 起動する。 (起動時にタイマーのttyがopenされる)
- [コマンド実行プログラム] コマンドをタイマーのttyに書き込む。
- [Linux] コマンドをタイマーに送信する。
- [タイマー] 結果をLinuxに送信する。
- [Linux] 受信した結果をタイマーにエコーバックする。 (sttyに-echoを指定していない場合)
- [コマンド実行プログラム] タイマーのttyから結果を取得する。
- [コマンド実行プログラム] 終了する。 (→ タイマーのttyがcloseされる)
- [タイマー] エコーバックされた文字列をコマンドとして解釈して、結果をLinuxに送信する。 (→ コマンド実行プログラムが起動していないため、破棄される。)
- 上の5と6,7の順序が問題で、5の前に7まで実行されれば問題ないが、そうでない場合には、コマンド実行プログラムが終了するまで、受信した結果のエコーバックが行われる。→ 受信した結果の一部がタイマーに送信される。
- readコマンドを実行する場合、結果は"P6,OP:0.0.1.0,CL:0.0.3.5,LP:----"のような文字列であるが、仮に"CL:0"までしか送信されなかったとしたら、タイマーはCLを0に設定し、問題の現象が起こるのではないか。
- モードやパラメタの設定コマンド(例: P7)の場合、結果は"DOWN"(成功)か"FAIL"(失敗)で、どちらにしても失敗して"FAIL"が送られて来るだけなので、大きな問題はない。
- ただ、コマンド実行プログラムが終了するまで この繰り返しが終わらないので、好ましくない。
- 以下に、推測した問題発生の流れを示す。
- Off時間が0("CL:0000")になってしまう。
PS1. タイマーの謎と危うさ
以前使ったセンサ基板(YL-40)同様、物自体は ちゃんとしているのに、メーカー名を記載せず ちゃんとしたマニュアルなしで売るのは怪し過ぎるしアンバランスだ。売る店が何も分かっていないのもおかしい。
あくまでも想像だが、ちゃんとした会社の製造発注先が横流ししているのではないか。
流通は置いておくとしても、メーカー名もマニュアルもないものを ちゃんとしたシステムに使うのはリスクが高い。使う側が自分で検証・担保するスタンス(= 「何が起こっても知らないよ」)なのだろう。
だから、僕がAC 100Vをこのタイマーに直接入れず、外部のリレーで制御するようにしたのは正解だった。いくら基板をチェックしたって、本当に安全な作りかは分からないからだ。そんなものを信用するくらいなら、自分で回路や基板を作ったほうが ずっと安心できる。
以前調べたら、このタイマーを車(後付けで、エンジン起動後に何かのボタンを押したかのようにしているようだ)や医療機器(プロト?)に使っている例があったが、結構怖い。そこまで信用していいのかと思う。(だからC国では車両火災などが良く起こる??)
(3/23 14:26) 書いてから気付いたが、このタイマーのon/off時間設定の単位は0.01秒から1分が可能だが、on/offをリレーで制御するのに0.01秒(10ms)って果たして「あり」なのか、大いに疑問だ。そんなに短い間隔で使ったら、あっという間にリレーが壊れるだろう。リレーで音楽でも演奏するつもり??w 代わりに時間の単位を付ければ良かったのに。こういう基本的なところが杜撰なようだ。
PS2. AliExpress(以下Ali)の本体も店も最低、クソ以下なので、もう絶対に使いたくない。Aliのシステムは おかしいところが多いし(例: 設定しても通知メールが来ないことが多いし、来ても英語と日本語で内容が正反対だったりする)、店は無責任極まりない(C国人の悪いイメージどおり、自分に非がないことを証拠もなしに叫ぶだけだ)。レビューの点数が いい店を選んで上のありさまだったので、全く信用できない。
僕の中での店(特に電子部品・モジュール)の信頼性の順位は以下である。
秋月, ヨドバシ >> Amazon > Amazon(マーケットプレイス), 楽天 >>>>>>>>>> Ali
もしヨドバシにあれば一番楽で安そうだし、秋月にあれば(送料は少し高いものの)、店も物も信頼できるから良い。Aliを使うくらいなら、多少高くてもAmazon(マーケットプレイス)から買うほうが、(問題があった場合の)ストレスは1/100、時間は1/10だ。
もう少ししたら、Aliのアカウントを削除するつもりだ。最初から今ひとつ信用できなかったので、クレジットカードの情報を登録しなかったのは、正解だ。