Arduinoを USB/HIDデバイス(仮想キーボード)として活用する(第六回）ロギングとプロット①

##本記事について
　Arduinoを USB/HIDデバイスとして活用する第六回です。[第五回はここ](https://qiita.com/pronechia/items/b9623c5b8ac65b95edbf)。前回の　赤外線によるエアコンの ON/OFFと温度調整制御を拡張して、結果をロギング＆プロット出力する事例を紹介します。
##第六回）「赤外線によるエアコンのON/OFFと結果のプロット①」
　Arduinoの USB/HID を使って文字列を出力しブラウザーと連携して、エアコンのON/OFFと温度調整制御をおこない、結果をロギング＆プロット出力します。ブラウザー／Arduino／エアコン の仕組みは第五回と同様ですが、冷房／暖房の制御が可能です。さらに Arduino で結果をEEPROMにロギングし、後でIDEのシリアルプロッタに出力します。
##機能概要
 はじめに、学習モードで動かします。学習モードでは、実際のリモコンデータを赤外線受信し Adafruit Trinket M0 内部の仮想EEPROMに保管します。このデータは制御モードで使用されます。
　SW押下で制御モードに遷移します。制御モードでは、ブラウザーと連携し温度等収集/HID出力/ブラウザーからの制御値をTone受信/受信データに従った赤外線出力　を行うことで、エアコンの電源ON/OFFを行います。この処理は20秒間隔で繰り返され、周期毎に測定値や制御値を外部EEPROMにロギングします。
　一度電源をOFFした後、プロットモードで動かします。IDEのシリアルプロッタを使ってロギングしたデータをPC上にプロットすることができます。①では制御実行について説明し、ロギングやプロットの仕組みについては、②、③で説明します。
##準備するもの
　PC (MacBook pro) ブラウザーは、Chrome
　Adafruit Trinket M0 + 関連部品
　開発環境は  MacOS版の Arduino IDE v1.8.15
　WebServer(ローカスPC上で動作） 
##全体の仕組み
 htmlをWebサーバーに置きます。WebサーバーはPC内部のローカルサーバーで構いません。PC上のブラウザーで指定ページが表示でき、Adafruit Trinket M0にはSW、BME280、EEPROM、IR送受信モジュールが接続されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592438/bce35e0a-6c36-68df-0dc8-e9550e236fb6.png)

WebServerは、MacBookのローカルにapacheを立てて確認しました。
##ハード構成
 Adafruit Trinket M0 周りのハード構成を示す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592438/ef9ed769-2494-7f64-2dbe-ca061224e7e6.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592438/18d01c2e-5218-7b8a-6a91-6533f4d6a84a.png)

##ソフトウエア
下図は、Adafruit Trinket M0プログラム構成を示します。
仮想EEPROMの内容保持（プログラムを焼き直すと仮想EEPROMは初期化される）のため、学習モードと制御モードは同一プログラムで実現します。PLOT出力するには、ロギング終了後、一旦電源をOFFする必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592438/d4944288-aac7-d632-5a61-25880c70d46f.png)
html
　制御の判定はhtml内（JavaScript）で行います。第五回は冷房のON/OFFを判定しましたが、第六回では冷房、暖房のON/OFFを実現しています。htmlファイルは冷房と暖房で別々ですが、少し手直しすることで、暖房と冷房のどちらでも対応できるようにすることができます。

ソースコード、html は、[GitHub]
(https://github.com/pronechia/apl_usbhid_TrinketM0_06)から取り出すことができます。 各フォルダー内のすべてのファイルを同一フォルダに保存して、Arduino IDE でコンパイルしてください。

環境に合わせて、以下の内容を確認または修正してください
apl_usbhid_TrinketM0_06Mac.ino の先頭で宣言されています。
①BME280 I2Cアドレスの設定　（0x76 or 0x77 のどちらか）
//#define BME280DEVADDR 0x76
//#define BME280DEVADDR 0x77
②Webserverに合わせて、ＵＲＬを記述すること
//String g_url_string = "http'//192.168.xxx.xxx/xxxxxxxx.htm"; //内部WebServer用
String g_url_string = "http'//localhost/example0501.htm"; //localhost用
③ハード設定が間違いないか確認
//#define LED_PIN 13
//#define SW_PIN 1
//#define IR_IN 3
//#define IR_OUT 4
//#define TONE_PIN 3
④EEPROM I2Cアドレスの設定
lib_EEPROM512.ino の上部で宣言されています。
//#define I2CEEPROM512 0x56     //512kbit=64kByte
//#define I2CEEPROM512 0x57     //512kbit=64kByte

注意）
・ソースコードは、 Mac用とWindows用があります。IDE実行環境に合わせて使い分けてください。
・BME280のI2Cアドレス、EEPROMのI2Cアドレスが間違った場合はエラーとし処理を中断します。
・サンプルのHTMLファイルは、冷暖房別にhtmlフォルダにあります。
・IDEでコンパイルなど実行する場合、ツール／ボードの設定は、 Adafruit Trinket M0 です。

##実行

準備
・WebServerが使えて、PCと接続できていること。MacPCのapacheを立てることが簡単かと思います。
・ブラウザーは、Chromeが利用できること。
・MacPCの入力モードは、英数字である必要があります。日本語モードになっていないことを確認してください。

１。PCに Adafruit Trinket M0 をUSB接続、イヤフォンジャック接続する。電源ON後、概ね５秒程度でLEDが点灯し、入力待ちまたはSW押下待ちになります。

２。学習モードで動作確認
　赤外線の送受信が正しく行われているか動作確認します。
・ r コマンドでIDEの送信ボタンを押します。５秒以内に、赤外線受信機に向けてエアコンのリモコンの電源ON/OFFボタンを押してください。受信した結果がシリアルモニターに表示されます。電源ONとOFFの２種類のデータをテキストエディタ等に保存してください。エアコンがONの時にボタンを押すとOFF信号、エアコンがOFFの時がON信号です。
　注意）リモコンの仕様にもよりまずが、エアコン信号は数値が３００〜６００個並びます。数個の場合は受信エラーが考えられますので、再度、取り直してください。
・ sコマンド（rコマンドで受信した　s, で始まる文字列をそのままコピペ）で送信ボタンを押します。赤外線送信により実際のエアコンが動作することを確認してください。
画面イメージは、第五回を参照してください。

３。学習モードで信号を保管する
　リモコンの電源ON,OFF信号をM0に学習させます。p1 が電源ON、p2 が電源OFFです。まず p1コマンド用の文字列をエディタ等で編集します。rコマンドで受信した電源ON用の s, で始まる文字列の s, を p1, に変更してコピーしてください。
変更前の例）s,432,437,428,437,435,479,390,430,25318,3469,1735,430,1333,400,445,421,438,,,,,,
変更後の例）p1,432,437,428,437,435,479,390,430,25318,3469,1735,430,1333,400,445,421,438,,,,,,

p1 コマンド（上記でコピーした文字列をIDEにペーストして）でIDEの送信ボタンを押します。送った文字列が仮想EEPROMに保存されます。電源OFF信号を学習させる場合は p2 コマンドです。
　エアコンの前に移動して、LEDをエアコン受信窓に向けます。q1 コマンドでIDEの送信ボタンを押します。p1コマンドで保持した仮想EEPRONの値が赤外線送信されます。これにより実際のエアコンが動作することを確認してください。電源OFF信号を動作させる場合（p2 コマンドで保持した値）は q2 コマンドです。
　これで学習が終わりました。Adafruit Trinket M0　の電源をOFFしても学習内容は保持されます。ただ、プログラムを焼き直した場合は、学習内容がクリアーされるため、学習をやり直してください。

４。ログ管理機能の準備
　学習モードで動作中に、シリアルモニターからログ管理機能を動かし、次回使用するログ番号を設定する。
LLISTで現状確認。
LNEXT n で次回使用するログ番号=n を設定することができる。
LPLOT n で次回プロットするログ番号=n を設定することができる。
初めての場合は、LNEXT 0 コマンドと　LPLOT 0 コマンドを実行しておいてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592438/9d1626da-b207-0eea-d218-c60f58296739.png)

ログ管理機能の詳細は、次の記事②で説明します。

5。ブラウザーを開く
　ブラウザーchromeを開いて、カーソル（フォーカス）をブラウザーに当てておきます。制御モードで動き始めると、 USB/HID で文字列が入力されるための準備です。

6。制御モードで動かす
　SW押下で制御モードへ遷移します。学習モードで動かす必要がなければ、電源ON後、すぐにSW押下でかまいません。LEDが消灯して制御モードになります。遷移後、Adafruit Trinket M0 のUSB/HID から音量アップキーとURL文字列が出力されます。これでトップページが表示されます。　
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592438/7b89df24-b999-1f0d-e177-7f3329ba6115.png)
　トップページです。水色のフィールドはシステムが使用します。白色のフィールドは人が入力する項目です。

7。Startコマンド
　トップページ表示後、続けてStartコマンドで確認音が出力されます。Adafruit Trinket M0 で音が受信できたということは、正しく画面が表示されて音量設定も問題ないと判断できます。これで、次に進むことができます。音が受信できない場合は、LEDが高速点滅しURL入力が繰り返されます。正しく音が拾えるように、音量やイヤホンジャックの接続などを確認してください。

8。20秒間隔で以下が繰り返され、エアコンON/OFFと温度調節制御を実行します。
・上りデータ送信処理の内容
　　　Dataコマンドで、Adafruit Trinket M0 で測定した室温をブラウザーに送ります。ブラウザー側では、室温を受け取ると同時に、現在時刻が表示されます。
　　・USB/HIDで　‘Data’ + Tab + Enterが入力される
　　・USB/HIDで　室温 + Tab + Enter　が入力される
　　・Browser側で現在時刻を求め表示される。
・下りデータ受信処理の内容
　　　Inquコマンドで、ブラウザーから、制御値を受け取ります。
　　・USB/HIDで　‘Inqu’ + Tab + Enterが入力される
　　・Browser側JavaScriptでエアコンON/OFFと温度調節制御が必要かどうか判断し、制御値を求める。
　　　 (制御値は、 3:時刻による電源ON 6:時刻による電源OFF 9:温度による電源ON 10:温度による電源OFF）
　　・USB/HIDで　‘1’ + Tab + Enterが入力されると、送信データ値にしたがって 音を出す。
　　 M0側で音を拾い、 ON/OFFを判定する
　　必要なビット数 (ここでは4回)繰り返しエアコンON/OFF制御値を把握します。M0で受信した値に応じて、必要であれば　学習モードで仮想EEPROMに保持した電源ON信号／電源OFF信号を赤外線出力します。実際にエアコンが動作することを確認してください。

　コマンドは２０秒間隔で繰り返されます。その間にブラウザー側でA/C ON時刻、A/C OFF時刻、設定温度　ON/OFF設定切替ボタン　を入力することができます。ON/OFF時刻の入力、設定温度の入力をしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592438/2941cbfc-d0ba-1b23-cf75-ea8463ef42a6.png)

9。ロギングを開始するために、SW押下する。
制御モードへ遷移した直後は、ロギングOFFです。SW押下でロギングが開始されます。ロギング実施中は、周期毎に　測定値と制御結果をロギングします。再度のSW押下するまでロギングが継続されます。
ロギングできる最大件数（４０９５件）を超えると、ロギング処理は実施されません。

10。SW押下してロギングを終了する。
　終了を忘れるとログを見ることができないので注意してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592438/485c7697-4c67-1d02-a546-3208e6100c36.png)

11。ログをプロットするために、一度　電源をOFFする

12。Arduino起動後、IDEのシリアルプロット画面を開く。
　　１　を入力して送信ボタン押下で、１ページ目をプロット出力します。１から５００までのデータがプロットされます。以下が、例です。

＜条件など＞
・7月の昼間、冷房で実施。
・周期：20sec で約7時間20分運転。ログ点数は約1300。
・開始時の室温は28度。
・設定温度は 27度。解除は26度。
・開始10分後から制御開始、制御終了後1時間程度ロギングは実施。
・室温の変化をプロット（青グラフ）した。
・制御値は、ON/OFFレベル（赤グラフ）で示す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592438/97ce5a2e-464b-bb22-759e-dcc6f03c5eb8.png)
平均して　7分冷房、8分停止を繰り返し、室温を　２６度〜２７度に保持していることがわかります。
２を入力して送信ボタン押下で　２ページ目（５０１から１０００までのデータ）をプロット出力します。３ページ目も同様。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592438/305e40d0-3591-60d4-f002-6142e0f0ff4f.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592438/f019fb20-3b0e-f033-2c40-08374f73dd6e.png)

##まとめ
　赤外線によるエアコンの ON/OFFと温度調整制御を実行し、結果をロギング＆プロット出力する事例を実現することができました。改善事項としては、IR学習データを保持する仮想EEPROMを使わずに、今回追加した外部のEEPROMを使うとプログラム焼き直しで毎回、IRデータを書き込む必要がなくなり使い勝手が良くなります。
　次の記事②では、アプリとデータ定義の独立性を高くする工夫をしたロギング（EEPROMにデータを残す）の仕組みを、③では、データを取り出してIDEのシリアルプロッターにプロットする仕組みを紹介します。