M5StackのSDカードでデータログの予備実験をしてみましたが失敗でした
※他のブログ記事見ても遅いですが、本家ESP32は速いですので、M5Stackの構造上の問題かと思います。
=>バッファにため込んで、大きなデータにしてから、一挙に書き込む方法もありますが、受信ログ処理だけでなく計算・表示・無線送信処理が入ってくると、ぎりぎりのタイミングになってます。そこに、ため込んだデータのSD書込み部分が入ってくるとその時に遅れが発生しますので、その他の処理が破綻してしまいデータ落ちます。データの欠落なしに、高速ログするには、絶対的な書き込み速度が速いマイコンでないとリアルタイム系のデータログは無理です。
※2022年3月追記=>M5StackでのSDカードログは、遅すぎてモノの動きの計測ログに使えない
ので代わりのマイコンに乗り換えました。年々時系列データの周期が速い現象で大量のデータをログするようになってきてます。そのため、SDカードログでは、M5Stackを断念して、Arm CPUのCorTex-M7搭載のTeensy4.1を採用しました。ArduinoIDEでArduinoのコードそのまま使えるので、違和感なくプログラム作れます。SDカード書き込み速度が5Mbit/sec以上でるので数kbyteのデータを1msec以内にログできます。更に、SDログと同時にリアルタイムデータとして周期の異なるセンサーの同期処理をして、スマホ、PCへBlueToothでデータ送信する機能など高速処理させないといけないので、600MHzクロックの超高速マイコンTeensy4.1でないと実現できなくなってきてます。
【RTK22】超高速マイコンCortex-M7搭載Teensy4.1いじる その1<SDcardWrite5MB/sec以上でる>
①M5StackのμSDカードで連続ログする(使えない)
休みなくデータを送り続けるのは厳しい使い方で、今までも
mbedでトライしてきたのですが、4msecは無理で、6~10msec周期でないとタイムスタンプが周期的にログできないことが判ってます。そこで、M5StackでのSD書き込みのライブラリを使って連続書き込み実験をしてみました。
ログデータ:dataNo,msec 6~10byte程度です。
周期:2msec,4msec、6msec,8msec,12msec,20msecの5水準
リファレンス:2msecでUSBシリアル(115200bps)でPCでTeratermログ
これらの条件で8000データ~32000データまで時系列グラフにプロット
結果1:2msecでもUSBシリアルだとタイムスタンプデータ遅延は発生しない。
結果2:SDカード書き込みでは、20msecでもタイムスタンプ遅延が発生していて
等周期での計測をSDカードへログすることはできないことが判った。
SD書き込みテスト用のプログラムを下記に備忘録しておきます。
シンプルで要領を得たよいサンプルプログラムを公開していだだいた方に感謝です。
上記サンプルプログラムはIMUの値をSD書き込みするようになっていますが、IMU部分をはずして、タイムスタンプを記録するプログラムに改造して実験しました。
このサンプルプログラムは、M5Stackの3個のボタンを上手に使ってあります。Aボタンで記録スタート、Bボタンで、記録ストップ。Cボタンで電源オフとなってます。SDカード記録で最後にf.closeしないといけないのですが、Bボタンでf.closeになるので、任意の長さでファイルを作れるのが便利です。
/ test Logger // 2019/12/22 #include <M5Stack.h>File f; bool fOK = false; int i = 0;void setup() { M5.begin();// Start SD card if (!SD.begin()) { M5.Lcd.println(“ERROR: SD CARD.”); while (1) ; }// Open log file f = SD.open(“/testLog.txt”, FILE_WRITE); if (!f) { M5.Lcd.println(“ERROR: OPEN FILE.”); while (1) ; }// Greeting Message M5.Lcd.println(“testLogger”);}void loop() { String dataString = “”;M5.update();if (fOK) { dataString += String(i++); dataString += String(“,”); dataString += String(millis());f.println(dataString); //Serial.println(dataString); }if (M5.BtnA.wasPressed()) { M5.Lcd.println(“Start>”); fOK = true; } if (M5.BtnB.wasPressed()) { M5.Lcd.println(“End”); fOK = false; } if (M5.BtnC.wasPressed()) { f.close(); M5.powerOFF(); } delay(20); } |
SDカードへの書き込みは1回あたり最低10msec程度はかかります。そのため1回に書き込むバイト数が多くなるに従い、転送速度は上がります。
例えば1回あたり100バイトだと5kB/s程度ですが、1KBだと70KB/s 、10KBだと450KB/sまで向上します。
2msecごとに10バイト書き込む場合、5kB/sの転送速度があればいいので、データをバッファに格納して、1KB程度たまれば書き込むようにすれば、2msec間隔でもログが可能だと思われます。
小林様ありがとうございます。SDカード書き込みの用途次第でバッファで補える場合もありますが、
私の使い方はログのデータ間の時間精度をリアルタイムにする場合遅延があるとその分データの同期がとれなくなるという使い方をした場合ということです。
GNSS用途なら、十分使えると思います。
現在は、タイムスタンプをデータに添付してM5STACKへ送っているので、SDが遅れてもログのデータ落ちがなくログしてますが、あとでデータ処理が面倒なのでM5Stackで各マイコンからのデータ受信時に、タイムスタンプをみながら、合わせて1つのデータセットにしてから、SDログとスマホ、PCへ転送することで、2重のログをすることにしてます。私の用途は、ロードバイクのパワーメーターなので、4か所からの数msec周期のデータ数百バイト常時入ってきて、それらの同期遅延が数msecにしないとパワー計算がずれてしまうので、精度的にも大変な用途です。無線自体の遅延とデータ落ちが問題で、結局ESP-NOWを採用して成功しました。Xbeeでは、無理でした。
あまり事例の無い用途なので、読者の皆様のご参考ならないかもしれませんが、自転車マニアの一部には、参考にしてもらってます。 以後もご指導宜しくお願いいたします。