##本記事について
Arduinoを USB/HIDデバイスとして活用する第六回②です。[第六回①はここ]
(https://qiita.com/pronechia/items/5054b9567454df6b9edd)。①で実現した制御結果をロギングするところを紹介します。
##第六回)「赤外線によるエアコンのON/OFFと結果のロギングとプロット②」
①で紹介した、赤外線によるエアコンのON/OFFと温度調整制御を行いながら、周期毎のセンサー値や制御結果をEEPROMにロギングします。
ロギングは、周期的に発生するデータ一式を繰り返し回数分保持し、実行後にデータを指定して時系列順に取り出すなどして利用します。個々のデータのことをチャンネル(ch)と呼びます。
実現方法として特筆すべきは、アプリとデータの独立性を高めデータの追加/変更を容易とするため、EEPROM上のデータを読み書きする仕組みとして、INFOという考え方を導入したことです。これは、さまざまなアプリに適用することができます。
データの発生頻度が高くなければ、より大量にデータを保存できる方法として、ファイルをSDカードに保存する方法もあります。が、今回はエアコンのON/OFF制御のロギングということで、1日程度、データを保管する仕組みとしてEEPROMを使って実現しました。
##機能概要
下図にあるように、初期化時に蓄積するデータにラベル名(ch名)を付与してEEPROMアドレスと紐付けをします。これをINFO情報と呼びます。データは個別データと周期データを格納することができます。個別データはアプリ間のデータ共有として利用します。周期データはロギング/ビューワーで利用します。
制御実行時には、ロガーにより、ch名を指定して(EEPROMのアドレスを指定することなく)EEPROMに書き込みます。制御実行後動かすビューアーでは、 ch名と周期を指定してデータを読み出すことができます。また、アクセスをサポートするライブラリーも用意しました。ライブラリーでは、INFO情報を使ってchを読み書きすることができます。
この仕組みを使えば、データの追加/変更が簡単にでき、複数のアプリが共通のINFOを介してEEPROM上のデータにアクセスすることもできます。
・データの追加/変更が簡単にでき、EEPROMの物理アドレスを気にすることなくアプリ実装ができる。
・今回はマイコン1つだが、マイコンが複数であってもEEPROMを共有する仕組みが実現できる。
・INFOの提供元としてSDカードがあれば、ファイル渡しもできる。
##info情報
//info 情報定義構造体
typedef struct _INFO {
char label[8]; //ch名
uint16_t address; //EEPROM保存時のアドレス
uint16_t len; //1,2,4byte
} INFO;
//個別データ
#define INFOMAX 5
int tableInfoCount = INFOMAX;
INFO tableInfo[INFOMAX];
//周期データ(ヘッダー)
#define HEADERMAX 20
INFO tableHeaderInfo[HEADERMAX];
//周期データ(データ)
#define LOGRMAX 8
INFO tableLogInfo[LOGRMAX];
//初期化にて、設定する情報の例
//BME280で取得した温度、湿度、気圧を共有する
#define MAPDT 0x0040
#define MAPDH 0x0042
#define MAPDP 0x0044
#define MAPDC 0x0046
#define MAPDY 0x0047
//周期データは、温度、湿度、制御値
#define MAPLOGK 0x0000
#define MAPLOGL 0x0002
#define MAPLOGC 0x0003
//個別データのchごとの情報
strcpy(tableInfo[0].label , "Dtemp");
tableInfo[0].address = MAPDT;
tableInfo[0].len = 2;
strcpy(tableInfo[1].label , "Dhum");
tableInfo[1].address = MAPDH;
tableInfo[1].len = 2;
strcpy(tableInfo[2].label , "Dpress");
tableInfo[2].address = MAPDP;
tableInfo[2].len = 2;
strcpy(tableInfo[3].label , "Dctl");
tableInfo[3].address = MAPDC;
tableInfo[3].len = 1;
strcpy(tableInfo[4].label , "Dyobi");
tableInfo[4].address = MAPDY;
tableInfo[4].len = 1;
tableInfoCount = 5;
//周期データのchごとの情報
strcpy(tableLogInfo[0].label , "LK");
tableLogInfo[0].address = MAPLOGK;
tableLogInfo[0].len = 2;
strcpy(tableLogInfo[1].label , "LL");
tableLogInfo[1].address = MAPLOGL;
tableLogInfo[1].len = 1;
strcpy(tableLogInfo[2].label , "LC"); //controll値 エアコン on/off
tableLogInfo[2].address = MAPLOGC;
tableLogInfo[2].len = 1; // int8_t とする
tableLogInfoCount = 4
//周期データの管理情報
tableLogRepeat[0] = 2048; //最大個数
tableLogRepeat[1] = 2048;
tableLogRepeat[2] = 2048;
tableLogStartAddr[0] = 0x4000; //先頭アドレス
tableLogStartAddr[1] = 0x8000;
tableLogStartAddr[2] = 0xc000;
INFO構造体が、ch名とEEPROM物理アドレスを変換する主要な情報となる。
この例では、個別データを5つ、周期データを4つ定義している。周期データの最大個数を2048 としている。これだけのことを初期化で行っておけば、実際のEEPROM読み書き時は、ch名でアクセスできる。
##提供されるライブラリ
//Logヘッダーを読む
bool sub_EEPROM512_ReadLogHeader(int8_t p_lognum, unsigned long* p_s, unsigned long* p_e, int16_t* p_c, int16_t* p_n)
//
//Logヘッダーを書く
void sub_EEPROM512_WriteLogHeader(char p_se)
ロギングされたデータを管理するため、ログヘッダーの読み書き関数を提供する。
//chデータを書く
int16_t p_t; //温度、 25.00度の場合は2500とする
char* p = (char*)&p_t;
sub_SetLogVal(gCount, "LK", p); //温度
//chデータを読む
char p[8];
int16_t* fp;
sub_GetLogVal(pCount, "LK", p);
fp = (int16_t*)(p);
周期データの読み書き関数を提供する。
##実行時のログ蓄積
・個別データ用の例
"Dtemp"というch名のデータを制御で書き、別アプリで読むイメージの図です。
・周期データ用の例
"LK"というch名の周期データをロガーで書き、ビューアーで読み出すイメージ図です。何番名のデータかを意味する、パラメータ=cがあることがわかります。
##ログ管理機能
3セットのログを保持できるようにした。ログヘッダには、開始、終了、実行周期、データ点数を保持している。3セットのログのうち、次回書き込む番号(つまりログを残す番号)、次回読み取る番号(つまりプロットする番号)を指定することができる。
LLISTの例) LPLOT 0 / LNEXT 2 を実行した後の状態
ログに関する命令は以下の3種類
・LLIST 一覧表示
・LNEXT n 次回使用するログの指定 (書込番号)
・LPLOT n PLOTログの指示 (読込番号)
使い方手順例)
1。LLIST でログの状況を確認する。次回のロギングはログ番号2を使うと決める
2。LNEXT 2 で書込番号を2に設定する
3。ロギング実行
4。ロギング終了後、LLISTでログが書き込まれたことを確認する(時間、点数など)
5。LPLOT 2 で読込番号を2に設定する
6。シリアルモニター画面に切り替えて、1を入力すると、1ページ目が描画される。
点数が500点以上であれば、2を入力して、2ページ目を描画する、、、
##まとめ
実装上の工夫として、アプリとデータの独立性を高めデータの追加/変更を容易とする、INFOという考え方を実現できました。開発中にEEPROMを違うサイズに取り替えることが発生しましたが、アドレス依存部分が局所的で簡単に対応することができました。アプリの仕様変更にも柔軟に対応できると考えます。また、各種アプリで利用するために、ライブラリーとして提供することも考えられます。
③では、ロギングしたデータを取り出してIDEのシリアルプロッターにプロットする仕組みを紹介します。