Edge ImpulseとArduino Nano 33 BLE Senseによる高精度ECGアナライザー
必要な部品と材料
| 部品 | 数量 |
|---|---|
| Arduino Nano 33 BLE Sense | 1 |
| SparkFun シングルリード心拍モニター - AD8232 | 1 |
| ElectroPeak 0.96インチ OLED 64x128 ディスプレイモジュール | 1 |
必要な工具と機器
- はんだごて(汎用)
- 鉛フリーはんだ
- ジャンパーワイヤキット 10本(5cm)
使用するアプリとオンラインサービス
- Edge Impulse Studio
- MATLAB
- Arduino IDE
- Microsoft Visual Studio 2017
このプロジェクトについて
突然の心臓発作と死亡率の増大 - 深刻化する懸念
過去10年間で、突発的な心臓発作による死亡が著しく増加しています。
特にインドのような発展途上国では、遺伝的要因や生活習慣に加え、地方部の医療リソース不足が心臓発作の死亡率を押し上げています。

テクノロジーによるこの地球規模課題への貢献
私はEdge Impulseを活用したTinyMLアプリケーションとして、ポケットに入るサイズのミニ診断ECGアナライザーデバイスを開発しました。これはクラウド接続なしで、心疾患を独立して診断できます。
現在市場にあるECGアナライザーとその特徴
- 従来のIoT医療機器:大量のECGデータをモバイル/サーバーに送信し、高性能プロセッサやモバイルアプリで解析
- PCベースのアプリケーション:ECGデバイスから信号を受信し、PC上でパターン解析
- すべてのECG解析デバイスは、インターネットまたは高性能コンピュータ/モバイルアプリに依存している
これらを以下の図にまとめます:

本プロジェクトのキーソリューション
- Edge Impulse搭載のECGアナライザーは、インターネット依存なしでECGデータを解析
- IoTデバイスと比較してレイテンシが最小
- 15KBのROMで動作するTinyMLモデルは、TinyML対応マイコンならどこでも動作可能
- ECGパターンを解析し、「正常」「心房細動」「一次房室ブロック(第一度房室ブロック)」の3クラスに分類
アーキテクチャ
ECGアナライザーは以下の要素で構成されます:
- AD8232によるECG取得
- 様々な心疾患のECGパターンシミュレーション
- 質の高いデータセットを生成する新規アプローチ
- モデルの訓練
- モデルのテスト精度評価と、デプロイ済みライブラリとアプリケーションコードの統合

ECG波形の基礎知識
技術的な作業に入る前に、ECG波形の基本を確認します。
ECG波形は5つの波(P、Q、R、S、T波)に分けられます。

心房細動

一次房室ブロック(第一度房室ブロック)

ECGアナライザーを作ろう
1. AD8232によるECG取得
以下の接続図に従って、ECGセンサーAD8232をArduino Nano 33 BLE Senseに接続します。
以下のコードを書き込み、Ctrl+Shift+Lでシリアルプロッタを開くと、グラフィカルなストリーミングデータが可視化されます。
void setup() {
// シリアル通信初期化:
Serial.begin(115200);
pinMode(2, INPUT); // リードオフ検出 LO+
pinMode(3, INPUT); // リードオフ検出 LO-
}
void loop() {
if((digitalRead(2) == 1) || (digitalRead(3) == 1)){
Serial.println('!');
} else {
// アナログ入力0の値を送信:
Serial.println(analogRead(A0));
}
// シリアルデータ飽和防止のため少し待機
delay(5);
}
1.1 ECG電極の配置
ECG電極は上図の通りRA(右腕)、LA(左腕)、LL(左脚)に配置し、ジャックをECGアナライザーのAD8232センサーに接続します。

2. MATLAB Signal Builderによる様々なECGパターンのシミュレーション
Step 2.1: 正常ECGデータをExcelに保存
まずシリアルモニタのデータをコピーし、以下のテンプレートでExcelファイルに保存します。ECG値は2列目の'Y'に、1列目はタイムシリーズで(* 0.005)つまり5ms刻みでインクリメントします。

Step 2.2: MATLAB Signal Builder
MATLABで新しいSimulinkモデルを作成します。

ワークスペースで'signal builder'と入力して選択し、'scope'も挿入してSignal Builderに接続します。スクリーンショットを参照してください。


保存したExcelデータを読み込むには、Signal Builderを開いて「ファイルからインポート」を選択します。

指定のオプションを選んでデータをインポートします。モデルは保存せずにインポートしてください(まだ手順が残っているため)。

2.3: Signal BuilderでのECGデータ可視化
60秒分のECGデータはSignal Builderで以下のように見えます。手動編集する場合は5秒分にズームし、ECG波形を「ドラッグ」して編集します。


ズーム後、マウスポインタをECG波形に近づけると、任意のポイントを選択してドラッグ編集できます。

2.4: Signal BuilderでP-R間隔データを編集(房室ブロック1度ケース)
P波を手動で下にドラッグし、R波より十分手前にシフトさせることで、P-R間隔が200msを超える状態を作ります。この操作をSignal Builderのデータ上で複数のタイムラインで繰り返します。

編集後、データを.matファイルとしてエクスポートします(Signal Builderにオプションあり)。保存後、以下の手順でデータを取り出します。

手順:.matファイルをダブルクリック → 1x1 Datasetをダブルクリック → Data:1の下に編集済みデータが見える → 新しいExcelファイルにコピペ。
Step 2.5: Excelデータを配列に変換
Excelデータを配列に変換する.mスクリプトを作成しました。
MATLABで実行前に、ExcelFilenameをローカルのファイル名に、ExcelSheetNameを対応するシート名に置き換えてください。
data = xlsread('ExcelFilename.xlsx', 'ExcelSheetName');
ECGExtract = (data(1:end, 1)); %% A列データ
fid = fopen('test.txt', 'wt'); % tフラグで\nを\r\nに自動変換(Windows)
fprintf(fid, '{');
FormatSpec = [repmat('%i ', 1, size(ECGExtract, 2)) ','];
fprintf(fid, FormatSpec, ECGExtract);
fprintf(fid, '}');
fclose(fid);
カレントディレクトリにテキストファイルが生成されます。

配列の内容をコピーし、ECGAnalyzer.cのコードにペーストして、心房細動と一次房室ブロックのシミュレーション用データとします。

3. 質の高いデータセットを生成する新規アプローチ
生のECGデータを見ると、短い時間窓(例:3秒)では正常ECGと各疾患のECGを区別するのは非常に困難です。

フィルタ済みECGデータだけで心房細動、正常、一次房室ブロックを学習させたところ、精度は23%未満でした。短い時間窓ではモデルが違いを捉えられないためです。時間窓を長くすると処理時間とピークRAM使用量が大幅に増加し、それでも精度は出ませんでした。
新規アプローチの背景:
医師や訓練された技術者がECGを読むとき、R-R間隔やP-R間隔の小箱の数を数え、グラフに書き込んだり記憶したりして計算します。

私はフィルタ済みECGデータから別の波形を生成しました。
新しい波形:
- R-R間隔
- P-R間隔


正常ECGデータの生成データセット:

デコードされたR-R間隔とP-R間隔のデータは、正常ECGでは常に100と50になります。
心房細動ECGデータの生成データセット:

前回のR-R間隔と今回のR-R間隔に偏差があると、R-R間隔データが1サイクルだけ-100にドロップします。
一次房室ブロックECGデータの生成データセット:

P-R間隔が200msを超えると、P-R間隔データが1サイクルだけ-50にドロップします。
このアプローチにより、モデル精度を90%以上に向上させました。
4. Edge Impulseでのモデル訓練
Edge ImpulseでML訓練を始める前に、シミュレーション用とリアルタイムECGセンサー読み取り用のパラメータをライブラリファイルで設定します。
Step 4.1: SIMULATION設定
- リアルタイムECGセンサーからデータ取得する場合:
SIMULATION = 0 - MATLABセッションでシミュレートした心房細動・一次房室ブロックデータを使う場合:
SIMULATION = 1

Step 4.2: シミュレーション用データバッファのコメントアウト切り替え

Step 4.3: データ取得
「Normal」「Atrial fibrillation」「First-Degree Heart Block」の3ラベルでECGデータを収集します。

https://docs.edgeimpulse.com/docs/arduino-nano-33-ble-sense

周波数を202Hzに設定:
$ edge-impulse-daemon --frequency 202
Step 4.4: インパルスの作成
「Create impulse」セクションで、ウィンドウサイズ3000ms、ウィンドウ増分2999ms、K-means異常検知を選択。

Step 4.5: スペクトル特徴量
フィルタタイプを「None」に設定。

Step 4.6: NN分類器
訓練サイクル40回、学習率0.005で設定。精度92.9%を達成。

異常検知にはP-R間隔RMSとR-R間隔RMSを選択。
5. モデルテスト精度と統合
モデルテスト精度は約97%でした。

5.1 デプロイ
デプロイ対象としてArduinoを選択。

ダウンロードしたEIデプロイファイルをArduinoライブラリに追加。

注意: GitHubリンクからECG_AnalyzerライブラリもArduinoライブラリに追加してください。これにより、私のECGデコードアルゴリズムコードをEI生成モデルと統合できます。
5.2 アプリケーションコードをEI生成コアコードに統合
アプリケーションコードをEIデプロイ済みのnano_ble33_sense_accelerometer_continuousにマージし、ECGAnalyzer.inoとして保存しました。
GitHubリンクから入手可能です。デバイスに書き込む際は、ECG_Analyzer.c内のSIMULATION = 0に設定してください。

ハードウェア接続
以下のフリッツィング図に従って接続してください:


組み立て:


完成品
最終製品とテストデータでの精度レベル!


クレジット
ECG参考資料:https://geekymedics.com/how-to-read-an-ecg/
スケッチ
GitHubリポジトリ
https://github.com/Manivannan-maker/ECGAnalyzer
ECGAnalyzer.zipを解凍して使用:
書き込み用コード: EI_Deployed_Library\examples\ECGAnalyzer\ECGAnalyzer.ino
シミュレーション設定用ライブラリ: ECGAnalyzer_lib\ecg_analyzer.c
MATLABスクリプトとSignal Builderモデル: Matlab_Simulation\Excel2Arrayconverter.m, Matlab_Simulation\signalbuilder.slx
回路図
図に従って接続してください ecgdefault_SjMMcgW8jY.fzz
製造プロセス
- ティアラの芸術と職人技:歴史、素材、現代デザイン
- 有刺鉄線:歴史、構造、現代の用途
- Walabot搭載トイレ衛生モニター:カメラ不要で清潔度と使用状況を検知
- reTerminalでハンズオン機械学習:Edge Impulse & ARM NNデモガイド
- 壊れたおもちゃトラックを Raspberry Pi 搭載 RC ビークルに変身させる
- MOSMusicプロジェクトキット: MOSFET、Arduinoで音楽同期照明制御
- 農業・養鶏向けプレミアム六角ワイヤーネット機械
- ワイヤーEDM完全ガイド:マスターワイヤーカッティング
- CNCワイヤーカット放電加工:定義、プロセス、応用
- 最新ワイヤ放電加工機(EDM):高精度・非接触加工の実力
- EDM(放電加工)完全ガイド:原理・種類・メリット・デメリット