AE測定、長期間ロギングシステム構築 (その4) 信号検出実験編

OSC0101

前回までで、センサーから信号をとりだすアナログ部分と、AD変換を行うArduinoの事前検討が完了しました。ここでは、取り出した(AE)信号をAD変換して読み込む実験を行い、妥当な情報をロギングできそうかを検証していきます。
 ここで、前出の記事( AD変換部 事前検証編 )で、検討したリセット問題に関連して新たな課題を理解しました。avrdudeで、Flash readデータの吸出しを行う予定にしていましたが、avrdudeを実行するとリセットが発生することが分かりました。このため、avrdudeを利用するなら電解コンデンサーを追加してリセット発生を抑制する方法は使えないことが分かりました。リセットを発生させない運用ならロギング実装の中にデータを吸い出す実装が必要ということになります。どちらを選択するかが課題として残ります。その選択は信号検出実験の後に再検討することにしましょう。

やりかたは、まずは1ch、 そして最終ゴールを見据えて4ch分のデータ取得をやってみましょう。データは、とりあえずRAM上(変数)に保持して、データ転送し、シリアルプロッタで、プロットしてみます。 シリルプロッタでの結果が、オシロスコープで見た波形と一致するかを見てみましょう。そして、データ取得の閾値や周期などを検討してみようという方針です。

分圧回路の製作(手持ち部品から選抜)

前段のアンプは9V電源で、Max9Vの出力があります。Arduino Uni V3の耐圧といかアナログ信号入力の制限は0~5Vです。改めてオシロでアンプの出力をDCで確認すると、だいたい0~9Vの範囲で、振れていて、4.5Vあたりが中心電圧です。
オシロ 検出信号波形

osc_dc
osc_dc


時間もないので、手持ち部品から選抜して、できるだけ適した回路を作成してみます。
10kΩの半固定抵抗が4個あったので、これを使いまます。本番を想定して4回路分取る前提で、とりあえず1回路分を作成しました。

回路写真

Bunatu
分圧回路


これを使って、仮配線してみます。これで、システム全体の仮組み(仮SI)ができました。実験用のコードを動かして確認しましょう。プログラムは変数として使える2KBの範囲内で収まるようしました。要約すると、入力波形をAD変換しながら取得・蓄積して、閾値を超えたらPCに蓄積した波形をなげるというものです。

簡易オシロ Arduinoスケッチ(OSCsimulater.ino)

// --- 設定項目 ---
const int NUM_CHANS = 4;
const int BUFFER_SIZE = 1500; // バッファサイズ (1.5KB)
const int TRIGGER_CH = 0; // A0をトリガーに設定
const int THRESHOLD = 30; // 閾値 (8bit: 0-255) ※約2.5V
//const int PRE_TRIGGER_SAMPLES = 200; // トリガー前に何セット分表示するか
const int DISPLAY_POINTS = 50; // 画面に表示したい総行数
const int PRE_TRIGGER_SAMPLES = 5; // そのうちの20%(過去分)
const int POST_TRIGGER_SAMPLES = 50; // 残りの80%(未来分)

byte buffer[BUFFER_SIZE];
int head = 0; // 書き込み位置

void setup() {
Serial.begin(115200);

// ADCの高速化 (Prescaler 16 = 約1MHzのADCクロック)
// 分割比を16に設定することで、4chでも実用的な速度を確保します。
ADCSRA &= ~(bit(ADPS2) | bit(ADPS1) | bit(ADPS0));
ADCSRA |= bit(ADPS2);

Serial.println("System Ready. Waiting for trigger on A0...");
}

void loop() {
// --- 1. 定常サンプリング ---
int val = analogRead(A0 + (head % NUM_CHANS));
buffer[head] = (byte)(val >> 2);

// --- 2. トリガー判定 ---
if ((head % NUM_CHANS) == TRIGGER_CH && buffer[head] > THRESHOLD) {
captureAndSend(head);
// 送信が終わったら head をリセットして、次のトリガーに備える
head = 0;
// 少し待機(連続トリガーによるチャタリング防止)
delay(500);
}

head = (head + 1) % BUFFER_SIZE;
}

void captureAndSend(int tIndex) {
// 1. 未来分をサンプリング
for (int i = 0; i < (POST_TRIGGER_SAMPLES * NUM_CHANS); i++) {
head = (head + 1) % BUFFER_SIZE;
int v = analogRead(A0 + (head % NUM_CHANS));
buffer[head] = (byte)(v >> 2);
}

// 2. 画面を一度リセットするために「空のデータ」を少し送る
// これにより前の波形と新しい波形の間に隙間ができます
for (int i = 0; i < 50; i++) {
Serial.println("0,0,0,0");
}

// 3. 送信開始位置の計算
int startOffset = (tIndex - (PRE_TRIGGER_SAMPLES * NUM_CHANS) + BUFFER_SIZE * 2) % BUFFER_SIZE;
startOffset = (startOffset / NUM_CHANS) * NUM_CHANS;

// 4. データ送信
for (int i = 0; i < DISPLAY_POINTS; i++) {
for (int ch = 0; ch < NUM_CHANS; ch++) {
int idx = (startOffset + (i * NUM_CHANS) + ch) % BUFFER_SIZE;
Serial.print(buffer[idx]);
if (ch < NUM_CHANS - 1) Serial.print(",");
}
Serial.println();
// ここでdelayを入れると、波形が描画される「スピード」を調整できます
delayMicroseconds(500);
}
}

この仮の簡易オシロ スケッチで取得したシリアルプロットでの波形の観測動画です。 

AE仮配線観測

とりあえずこれで、Arduinoで波形を観測できそうなことを確認できました。A0チャンネルの1回路にだけ接続して他はフリー状態ですが、A0の影響を受けて波形を観測しており、他のチャンネルを接続したとき影響を受けないか確認が必要そうです。つぎは、ほぼ本番の接続状態で、複数チャンネルでの観測を試しましょう。


関連記事

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です