こんにちは、ENGかぴです。
ESP32-WROOM-32EのWire(SPI)を使用すると加速度センサー(ADXL345)のデータを取得することができます。加速度センサーのイベントを発生させイベント発生前後の様子をSDカードに履歴として保存する方法をまとめました。
ESP32-WROOM-32E開発ボード(秋月電子)を使用しArduino IDEで開発を行います。また、ADXL345モジュール(秋月電子)を使用しています。
SDカードモジュールはmicroSDカードスロットレベルシフタ付きブレークアウト基板キット:AE-microSD-LLCNV(秋月電子)を使用しています。
下記記事で動作確認したADXL345のフォールイベントのデータをSDカードに保存します。
ESP32-WROOM-32Eで加速度の変化をグラフ表示する
WiFi通信を使って最新のデータを表示してSDカードに保存した履歴データと一致するか確認を行います。
ESP32-WROOM-32Eで動作確認したことについてリンクをまとめています。
ESP32-WROOM-32Eで学べるソフト開発と標準ライブラリの使い方
SDカードに加速度のイベント履歴を保存
Arduino環境ではSDカードを操作する標準ライブラリが実装されています。SDカードモジュールの配線とライブラリの使用方法を説明します。
ESP32-WROOM-32EとSDカードモジュールの構成

ADXL345はWire(I2C)通信を使用します。Wireを使用する場合はプルアップ抵抗が必要ですがADXL345モジュールに実装されているため必要ありません。ADXL345のイベント発生をDIで検出するため17ピンをRISING(立ち上がり)として使用します。
SDカードモジュールの電源は5VなのでESP32-WROOM-32Eの5Vを供給しています。
SDカードの操作はSPI通信を使用します。ESP32-WROOM-32EはVSPIとHSPIがありますが、特に指定しない場合VSPIピンが有効になります。HSPIを使用する場合は下記記事に使用例をまとめていますので参考にしてください。
ESP32-WROOM-32EのSPIでBME280の情報を取得
PR:わからないを放置せず、あなたにあった最低限のスキルを身に着けるコツを教える テックジム 「書けるが先で、理解が後」を体験しよう!
ライブラリの準備と初期化
#include <SPI.h>
#include <SD.h>
File myfile; //SDカードの状態を格納
void setup() {
if(!SD.begin()){
//初期化失敗の処理
}
}
SDカードの操作はSPI通信を使用するためSD.hをインクルードする必要があります。SPI.hはSD.hないでインクルードされているためインクルードしなくても問題ありません。SPIのスレーブ選択のDOを指定する必要がありますがデフォルトで5ピンが指定されています。
SDカードのファイルに関する情報等を管理するにFile型のクラス変数を変数を宣言します。例ではmyfileの宣言しています。
SDライブラリのbegin()関数を使用してSDカードに関する情報を初期化します。引数にはSDカードを選択するためのスレーブセレクト(SS)のピン番号を指定します。指定しない場合はデフォルトの5ピンで初期化が行われます。
SDカードが挿入されていない場合など失敗した場合は戻り値がfalseになるので必要があれば失敗したときの処理を入れます。
PR:アクセンチュアの転職なら【コンサルアクシスコンサルティング】
データの書き込み(動作履歴の保存)
myfile = SD.open(filepath,FILE_WRITE);
if(myfile){
myfile.println(" ,x,y,z");
for(uint16_t i = 0; i< CHART_SZ; i++ ){
myfile.print(i);
myfile.print(",");
myfile.print(wave[0][i]);
myfile.print(",");
myfile.print(wave[1][i]);
myfile.print(",");
myfile.println(wave[2][i]);
}
myfile.close(); //ファイルを閉じる
}else{
Serial.println("SD-ERR");
}
open()関数でファイルを書き込みモードで開きます。open()関数の第1引数にはファイルのパスを指定し、第2引数に書き込みを示すFILE_WRITEを指定します。ファイルが開けたらprint()関数を使用してデータを書き込みます。
print()関数でデータの番号とX,Y,Z軸の加速度情報を書き込みます。データの間に”,”を入れているのはテキストデータをCSVファイルに変換したときにセルを分けるためです。書き込みデータの最後は改行コードを入れるためprintln()で書き込みを行います。
データを書き込んだ後はファイルを閉じるためclose()関数を使用します。
データの読み込み(参考)
本記事ではデータの読み込みは使用しませんが参考の為データの読み込みについてまとめています。
//ファイル名を指定して読み込む場合の例
String filepath = "sample.txt"; //SDカード内に保存するファイル名
if (SD.exists(filepath)) { //ファイルが存在するか
Serial.println("sample.txt exists.");
myfile = SD.open(filepath,FILE_READ); //ファイルを開く
if(myfile){ //ファイルが開けた場合
while(myfile.available()){
str ="";
str = myfile.readStringUntil('\n'); //読み込み
}
myfile.close(); //ファイルを閉じる
}
} else {
Serial.println("sample.txt doesn't exist.");
}
SDカードからデータを読み出す場合にファイルが存在しているかをexists()関数で確認します。引数には開くファイル名を含めたパスを指定します。
ファイルが存在するかを確認せずにopen()関数で読み込みを行っても読み込み失敗になるためexists()関数で確認してからファイルを開くかは好みになります。
ファイルが存在する場合はopen()関数でファイルを読み込み専用で開きます。第1引数にはファイルのパスを指定し、第2引数に読み込みを示すFILE_READを指定します。
ファイルのopenに成功するとFileオブジェクト(myfileで宣言した変数)に戻り値として状態が引き継がれるためmyfileを使ってデータの読み込みを行います。
Fileオブジェクトのavailable()関数を使って読み込むデータが存在するかを確認します。データが存在する場合は0より大きな値になるためRead()関数を使ってデータを読み込みます。例ではReadStringUntil()関数を使って改行コードが見つかるまでデータを読み込んでいます。
データを読み込んだ後はファイルを閉じるためclose()関数を使用します。
//ディレクトリのファイル名を表示
File root = SD.open("/");
File file = root.openNextFile();
while(file){
Serial.println(file.name());
file = root.openNextFile();
}
SDカード内のファイルを表示する例を示しています。open()関数に”/”を指定することで直下のディレクトリが開きます。openNextFile()でファイルを指定しながらname()関数でファイル名を取得しています。
while()で繰り返すことで存在するファイル名をすべて表示することができます。対象のファイルがない場合はfalseになるためwhile()から抜けます。
加速度データをグラフで表示する
ADXL345の加速度情報をWiFiでブラウザー上にグラフ表示する方法は下記記事にまとめています。本記事ではグラフ用のデータの準備のポイントのみを説明します。
ESP32-WROOM-32Eで加速度の変化をグラフ表示する
グラフ表示はChart.jsを使っています。Chart.jsを使ってブラウザー上にグラフ表示する方法を下記記事まとめています。
Chart.jsを使ってデータをブラウザー上でグラフ表示する
加速度データをグラフ表示するためのデータを準備します。グラフ表示する目安としてADXL345のイベントを使います。今回はFREE FALLがイベントを検出した前後250msの加速度情報を保存して表示します。

加速度情報を保管するバッファはリング構成にすることでxyzdata[]配列のサイズをオーバーしないようにデータを更新することができます。wpはxyzdata[]配列におけるデータの格納場所を示すポインタです。
FREE FALLイベントが発生すると250ms分の加速度情報を取得してからwave[]配列にイベント発生時の加速度情報を格納します。
adxl.getAcceleration(xyz); //XYZの加速度の取得
ax = xyz[0];
getdata.xyz[0][getdata.wp] = ax;
if(++getdata.wp >= CHART_SZ ){
getdata.wp = 0;
}
if( timEventWait > TIME_UP ){ //イベントが発生したらスタート
if( ++evescnt >= CHART_HALF_SZ ){ //イベント発生から250ms経過
int16_t rp;
uint16_t i;
rp = getdata.wp;
for( i = 0; i < CHART_SZ; i++){
wave[0][i] = getdata.xyz[0][rp];
if( ++rp >= CHART_SZ ){
rp = 0;
}
}
timEventWait = TIME_UP;
evescnt = 0;
}
}
getdata.xyz[]配列に格納している加速度情報を時系列でグラフで表示するために並び替えしながら格納します。例ではgetdata[]においてwpで現在の測定値を格納した後でwpを更新(wp+1)しているので更新後のwp(wp+1)の測定データが時系列でみた時getdata[]内の最古のデータになります。
最古のデータの位置をrpの初期値としてgetdata[]配列のサイズ分順に取得して格納することで時系列で整理したデータになります。
FREE FALLイベント発生直後からデータを取得するのではなくイベント発生以前のデータを含めて取得することでイベント発生の様子を確認することができます。
PR:スキマ時間で自己啓発!スマホで学べる人気のオンライン資格講座【スタディング】まずは気になる講座を無料で体験しよう!
動作確認
WiFi通信を使用して加速度センサーの情報をグラフで表示します。同時にフォールイベントが発生したタイミングのシリアルプロッタの様子と比較します。SDカードに保存している履歴のデータについてもデータが一致することを確認します。

スマホ(Android)のGoogle ChromeでIPアドレス「192.168.11.2」を入力しリクエストを送るとESP32-WROOM-32Eからスマホに返信しFREE FALLが発生した時のデータの様子を示すグラフ表示されました。
シリアルプロッタでのグラフ表示を行ってFREE FALL発生時のデータと一致するかを確かめました。

シリアルプロッタのグラフとスマホのグラフを比較すると波形の形がほぼ一致していることが分かりました。位置がずれているのはシリアルプロッタをスクリーンショットするタイミングによるものです。SDカードに履歴が保存されているかを確認しました。

SDカード内に履歴が2つ保存されていました。グラフ表示しているのは最新のイベントなので「logData-2.text」のデータを確認して上記2つのデータと一致するかを確認しました。テキストデータをCSVデータに変換してエクセルデータで保存してグラフ表示しました。

エクセルで表示したグラフを確認するとスマホで確認したグラフ及びシリアルプロッタで確認したデータのグラフと一致していることが分かりました。SDカードに履歴が保存されていることが確認できました。
ソースコード全体
ソースコードは記事作成時点において動作確認できていますが、使用しているライブラリの更新により動作が保証できなくなる可能性があります。また、ソースコードを使用したことによって生じた不利益などの一切の責任を負いかねます。参考資料としてお使いください。
リンクからZIPファイル形式のファイルをダウンロードし、任意の場所に展開していただくとテキストファイルが生成されます。
本ソースコードでグラフ表示するためにChart.jsライブラリをESP32 Sketch Data Uploadを使ってフラッシュ領域に書き込んでおく必要があります。
関連リンク
Arduinoのライブラリを使って動作確認を行ったことを下記リンクにまとめています。
Arduinoで学べるマイコンのソフト開発と標準ライブラリの使い方
Seeeduino XIAOで学べるソフト開発と標準ライブラリの使い方
ESP32-WROOM-32Eで学べるソフト開発と標準ライブラリの使い方
PR:
わからないを放置せず、あなたにあったスキルを身に着けるコツを教える テックジムPython入門講座の申込
最後まで、読んでいただきありがとうございました。
SDカードに履歴を保存できたことでブラウザ上でSDカードのファイルを選択してグラフ表示するなど応用例が広がりそうです。