ArduinoでFFT解析を用いて片持ち梁の固有振動数を求める

## 目的
今回はマイコンとフォトダイオードを用いて片持ち梁の固有振動数を測定します。以下で具体的な手法を説明していきます。

## 測定方法
　下図の様に、フォトダイオードの受光部の前に振動させている片持ち梁を近づけることで、フォトダイオードから出た光が通過と反射を繰り返すので、この反射光をフォトダイオードの受光部で検知し、その電圧変化をマイコンへの入力とします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3990611/3432883d-e280-785b-d4c5-4f60b98fd015.png)

そして、マイコン内でFFTを行うことで、フォトダイオードで検知した電圧の変化の周波数を測定することができ、この周期が片持ち梁の固有振動数となるので、片持ち梁の固有振動数を求めることができます。

　今回はパソコン内にArduino IDEというアプリケーションをダウンロードし、マイコンにFFTを行うコードをコンパイルしました。用意するものや、マイコンに書き込むコードについては以下の記事を参考にしました。

 参考： [ArduinoとMEMSマイクでFFT解析を試す](https://qiita.com/ricelectric/items/d5fcd6010e51612cd8cc)

## 用意するもの
|名称  |種類, 使い方  |数量  |画像  |
|---|---|---|---|
|Arduino IDEがダウンロードできるパソコン  |コードを書いたりFFTで得られたデータをグラフ化する  |1  |ー |
|Seeed Studio XIAO RP2040  |マイコンであり、FFTを行う  |1  |![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3990611/2883e3e2-d861-cd98-1b53-b3cad97d0766.png) |
|反射型フォトセンサー RPR-220  |フォトダイオードであり、光を検知する  |1  |![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3990611/90dbe4ce-4beb-de11-e651-33af8cb3d466.png) |
|電解コンデンサー 2.2μF 50V 105℃  |フォトダイオードで検知した信号のローパスフィルタとして用いる  |1  |![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3990611/95d90950-ec62-0b2a-b3c2-cf91626a5cc2.png) |
|炭素皮膜抵抗器 470Ω  |回路を組む際に用いる  |1  |![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3990611/618a538b-1d2f-812a-024d-2496c77fd5a5.png) |
|炭素皮膜抵抗器 220Ω  |回路を組む際に用いる  |1  |![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3990611/f3e4d2fd-0d50-fb2b-bc22-2c70e82ab5b2.png) |
|炭素皮膜抵抗器 10kΩ  |回路を組む際に用いる  |1  |![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3990611/1c59d022-adfa-d4f4-17e8-c5ad68236a43.png) |
|ジャンパワイヤ  |回路を組む際に用いる  |10程度、多いほうが安心  |![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3990611/f640f0e8-8efb-47a9-8d85-99219498724d.png) |
|充電＆転送ケーブル  |パソコンとマイコンを接続するために使う  |1  |![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3990611/e9ae3cb8-af09-30e2-dfd4-cd6b24eedc3d.png) |
|ブレッドボード  |回路を組む際に用いる、大きいもののほうが組みやすい  |1  |![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3990611/80a78075-10f7-b4a2-47fa-9e76e04fd729.png) |
|ピンヘッダー  |マイコンをブレッドボードに接続するために使う  |2、ピンの数が合計で14あればよい  |![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3990611/eee9568a-facc-863f-cdaa-361e83e0a44c.png) |
|アルミ製の定規  |固有周波数を測る梁として使う  |1  |![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3990611/31477bbe-11f6-e954-f415-3fcbffefa9b3.png) |

以上のものの他にピンヘッダーをマイコンに接続するためのニッパーやはんだ、はんだごてなどの準備も必要になります。また、回路に関わるパーツは秋月電子で購入し、ケーブルはダイソーで購入しました。
 　
  以下にマイコンとフォトダイオードの仕様が載っているサイトを示します。

[Seeed Studio XIAO RP2040（マイコン）の仕様](https://akizukidenshi.com/catalog/g/g117044/)
[反射型フォトセンサー RPR-220（フォトダイオード）の仕様](https://fscdn.rohm.com/jp/products/databook/datasheet/opto/optical_sensor/photosensor/rpr-220-j.pdf)

## Arduino IDE の準備
　今回は始めてArduino IDEを使ったので、インストールの手順から説明します。開発環境などは[FFTなどを参考にした記事](https://qiita.com/ricelectric/items/d5fcd6010e51612cd8cc)に合わせてあり、

- windous11（パソコン）
- Arduino IDE 2.3.3（Arduino IDEのバージョン）
- Raspberry Pi Pico/RP2040/RP2350 3.8.1（ボードマネージャでインストール）
- arduinoFFT 2.0.2（ライブラリマネージャからインストール）

としました。

　以下に具体的な手順を示します。まずはパソコンにArduino IDEをインストールします。Arduino IDEのインストールの仕方はこちらの記事の通りに進めれば問題ないと思われます。

参考：[Arduino IDE 2のインストール方法、初期設定、使い方](https://logikara.blog/arduino-ide2-inst/#mokuji_2)
 
こちらの記事のインストールと初期設定の部分の操作を行います。
続いて、ボード情報の追加を行います。ボードマネージャからRaspberry Pi Pico/RP2040/RP2350 の ver3.8.1をダウンロードすることでボード情報の追加が完了します。やり方はこちらの記事の通りに進めれば大丈夫だと思われます。

参考：[ラズパイPico/Pico2/PicoWのArduinoIDE2のインストール方法や使い方紹介](https://logikara.blog/raspi-pico-arduinoide/#mokuji_4-1)

続いて、arduinoFFT の ver2.0.2のインストールについてですが、Raspberry Pi Pico/RP2040/RP2350のインストールと似た手順でインストールすることができます。まずは左のタブのボードマネージャの下にあるライブラリマネージャーを開きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3990611/37876008-758b-1324-cd59-de304ffebcb5.png)

そして上の画像の「検索をフィルタ…」のところに「arduinoFFT」と打ち込みます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3990611/10b48628-dc8c-2038-517c-2efda3e4c3c4.png)

上の画像の様にインストールと出てくるので、バージョンを確認してインストールを押せば、arduinoFFT の ver2.0.2のインストールは完了です。

　以上でArduino IDE の準備は終わりとなります。

## 回路の組み方
　続いて、測定を行うための回路の組み方について説明します。以下に実際に組む回路の全体図を示します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3990611/1d46d8e4-3ddb-d189-018b-d49c8dffd60d.png)

上の画像について、ダイオードについては足の長いほうが下側となります。

続いてこの回路のつなぎ方を表す図を示します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3990611/206af609-bc4a-4ffa-a07e-ea17e3f424c3.png)


この回路図において、マイコンのVCC、GND、２ピンはSeeed Studio XIAO RP2040の背面に描いてある通りであり、フォトダイオードの①から④までの数字は[フォトダイオードの仕様書](https://fscdn.rohm.com/jp/products/databook/datasheet/opto/optical_sensor/photosensor/rpr-220-j.pdf)に載っているピンの番号と一致しています。

　上の画像ではフォトダイオード付近にジャンパワイヤがありますが、実際に測定する場合はワイヤが邪魔で測定しづらいです。そのため、なるべくフォトダイオード付近にほかの物のないような配線ができると良いと思います。以下に配線を片側にまとめた場合の回路を示します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3990611/cfb408e5-6967-8c13-5b8b-2bc7d8ac3de9.png)

## コードについて

まずは回路がちゃんとできているか確認するためのコードをマイコンに書き込んでいきます。以下にコードと参考にした記事を示します。

> 引用
>```
>//********************************************************************
>//* フォトリフレクタからの入力を表示するプログラム (Seeed XIAO RP2040 用)
>//********************************************************************
>
>int pin = A2; // アナログピンを設定
>
>void setup() {
>  Serial.begin(9600); // シリアル通信を初期化
>  while (!Serial) {
>    ; // シリアルポートが開くのを待つ (必要な場合)
>  }
>}
>
>void loop() {
>  int val;
>  val = analogRead(pin); // アナログA0ピンからセンサ値を読み>込み
>  Serial.println(val);  // シリアルモニターへ表示
>  delay(100);           // 100ms待つ
>}
>
>```
参考：[第15回 Arduinoでパーツやセンサを使ってみよう～フォトリフレクタ編](https://deviceplus.jp/arduino/entry015/)

こちらのコードをまずは Arduino IDE 内に書き込みます。

　続いて充電＆転送ケーブルを使ってパソコンとマイコンを接続します。その後、[Raspberry Pi Pico/RP2040/RP2350 をインストールする際に参考にした記事](https://logikara.blog/raspi-pico-arduinoide/#mokuji_4-1)のボードの選択の部分を参考にして Seeed Studio XIAO RP2040 を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3990611/81e3cd34-bea3-57e0-0fa7-2cad2013b9c8.png)

同様にこの記事を参考にシリアルポート選択をします。私の場合はCOM4でした。

これでコードをマイコンに書き込む準備ができたので、Arduino IDE の画面左上にある右矢印のマークを押します。するとマイコン内にコードが書き込まれます。

このままでは何も表示されないのでArduino IDE の画面上部にある「ツール」タブから「シリアルモニタ」を選択しシリアルモニタを出します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3990611/33061cff-28c5-e51e-ad0e-66a5c81cd292.png)

すると、シリアルモニタに数字が大量に表示されます。これがリアルタイムに、フォトダイオードで検知した光を電圧変換し、その信号の直流成分が除されたものとなります。

試しにアルミ製の定規を近づけたり遠ざけたりしてみると、近づけた瞬間や遠ざけた瞬間に数値が大きくなります。これはフォトダイオードに入る光の量が一時的に増減するからとなります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3990611/c678464b-934b-138e-aa2a-86b7aead127b.png)

このように動くことが確認できれば、次は実際にFFTを行っていきます。以下にコードと参考にした記事を示します。

```
#include <arduinoFFT.h>

#define MICROPHONE_PIN A2

const double samplingFrequency = 2048.0f; // 2.048kHz for 2Hz resolution
const int samples = 1024; // this value must always be a power of 2

double real[samples] = {0};
double imaginary[samples] = {0};

ArduinoFFT<double> fft = ArduinoFFT<double>(real, imaginary, samples, samplingFrequency);

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

  pinMode(MICROPHONE_PIN, INPUT);

  analogReadResolution(12); // 12 bits
  delay(1000);
}

void loop() {
  static const int samplingPeriod = floor(1000000.0f / samplingFrequency); // in microseconds

  for (int i = 0; i < samples; i++) {
    unsigned long time = micros();
    real[i] = analogRead(MICROPHONE_PIN);
    imaginary[i] = 0;

    while (micros() < (time + samplingPeriod)) {
      // do nothing
    }
  }

  fft.dcRemoval();
  fft.windowing(FFT_WIN_TYP_HAMMING, FFT_FORWARD);
  fft.compute(FFT_FORWARD);
  fft.complexToMagnitude(); // overwrite the first half of the integer data array

  for (int i = 0; i < samples / 2; i++) {
    if (i > 0) {
      Serial.print(",");
    }
    Serial.print(real[i]);
  }
  Serial.println();

  delay(1000);
}
```
参考：[ArduinoとMEMSマイクでFFT解析を試す](https://qiita.com/ricelectric/items/d5fcd6010e51612cd8cc)

元の記事からの変更点として、１行目の arduino FFT のaが小文字であること、3行目のピンの番号が2になっていること、5行目のサンプリング周波数が2048になっていることが挙げられます。
1行目を変更した理由としては、ここを変更しないと私の環境ではうまく動作しなかったからです。
2行目を変更した理由としては、回路が2番ピンに刺さっているためであり、回路のほうを0番ピンにさせば元の記事の様にしても大丈夫となります。
3行目を変更した理由としては、参考にした記事でも述べられているように
>周波数分解能 = サンプリング周波数 ÷ サンプル数

となっており、元のデータでは周波数分解能が 46.875Hz と少し大きめであったため、周波数分解能を 2Hz とするためにこの変更をしています。
このコードを書きこむと、前のコードよりも更新頻度は遅くなり、数字の数は多くなります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3990611/7f7afb5f-80d4-c252-8c39-d7dc9d859016.png)

この横並びの数字は先ほど書き込んだコードの6行目で指定したサンプル数の半分の数だけ存在し、今回のコードでは512個あります。この横1行分の数字をすべてコピーしグラフ化することで、視覚的に周波数を見ることができます。

今回はエクセル上でグラフ化を行いました。まずは0から2ずつ増えていき最終的に1022になるまで数を入れます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3990611/26a93bb5-db67-6343-cf07-14e5b916b920.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3990611/5daf5024-025f-5d57-c47e-ec8ff1308682.png)

その後、シリアルモニタ上からコピーした1行分の数値をメモ帳などにペーストします。こうすることで、エクセルにコピーしやすくなります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3990611/638afcc2-8cc2-a2cb-fdbf-53b76daedc4c.png)

メモ帳にペーストしたものを再度コピーし、エクセルの0を入力したセルの下にペーストし、Ctrlを押して「テキスト ファイル ウィザードを使用」を押し、1度目の選択肢は「次へ」、2度目の選択肢では左のほうの「コンマ」にチェックを入れて「完了」を押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3990611/59eea3b8-aaba-b15b-30af-b6c63628209c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3990611/98bbfed3-b255-8f66-292b-198754e5044f.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3990611/c1b8fbef-ec47-bfdd-2c94-1dd991ff8bc1.png)

これで数値の代入ができたのでグラフを作ることができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3990611/bdc8b83c-3568-d0cf-71ca-15fa2a47a83c.png)

この画像では測定を行っていないため周波数のピークは検出できていません。

## 固有振動数の測定
　今回固有振動数を測定する梁は、上で示した通りアルミ製の定規となります。アルミ製定規でなくても測定はできますが、フォトダイオードを用いて測定を行うため、表面の反射率が高いもののほうが測定しやすいと思われます。
 
　アルミ定規を振動させる方法ですが、定規を机の上からはみ出して置き、上から手で押さえて固定し、はみ出ているほうの先端を手でたわませて素早く手を離す、という手法をとっています。ビヨーンという音が鳴ります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3990611/8568d592-6695-6e9c-e653-8f09ea4873c7.png)

画像の様に机から10cmはみ出た状態で押さえています。
以上の操作によって振動した定規の横からフォトダイオードを近づけて周波数を測定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3990611/ed0f86cc-2c2a-bb72-1b57-661e2a07ea60.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3990611/da6aeb9a-e5ba-8c89-27ed-602fe4e42ab6.png)

今回は実験装置を素手などで固定しているため、再現性の高い測定を行うためには定規やフォトダイオードを固定するための治具を製作すると良いと思われます。

## 測定結果
　以上の手法で測定した結果を示します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3990611/26a6e7ea-0dc5-8273-baa9-825c58bff657.png)

上の画像の様に122Hzあたりでピークが検出されています。よってこの定規は、10cmで片持ち梁の状態のとき122Hzの固有振動数となるといえます。

## 結果の考察
　今回使用した梁の理論的な固有振動数を計算し、実際の測定値と比較してみたいと思います。
 ここで計算式は次の記事を参考にしました。

 参考：[梁の共振周波数と固定方法の関係【機械力学的解説】](https://machinal-explain-site.com/2022-03-06-%e5%85%b1%e6%8c%af%e5%91%a8%e6%b3%a2%e6%95%b0%e3%81%a8%e5%9b%ba%e5%ae%9a%e6%96%b9%e6%b3%95%e3%81%ae%e9%96%a2%e4%bf%82%ef%bd%9e%e6%a9%9f%e6%a2%b0%e5%8a%9b%e5%ad%a6%e7%9a%84%e8%a7%a3%e8%aa%ac/)

この記事の一端固定支持で λ1l=1.88 の式を参考にしています。また、アルミ製の定規の材料特性はアルミニウムのものを用いており、こちらのサイトのものを使っています。

参考：[アルミニウム材料の諸特性データベース](https://www.aluminum.or.jp/materialdb/3.html)

以上を踏まえて計算を行うコードを以下に示します。このコードはPythonで書いたため、Arduino IDE では動きません。

```
#bの値（定規の横幅 [m]）
b = 0.017

#hの値（定規の厚み [m])
h = 0.0015

#hの値（定規の長さ [m])
L = 0.1

#材料のヤング率 [Pa]
E = 7 * 10**10

#材料の密度 [kg/m3]
lo = 2700

I = (b * h**3) / 12 #断面二次モーメント
ramda = 1.88 / L
f = (ramda**2 / (2 * 3.141592)) * (((E*I)/(lo*b*h))**0.5)
print(f) #単位は [Hz]
```

以上の手法で計算した結果、124Hz という結果が得られた。
この値は、測定した122Hzとかなり近い値になっており、比較的高い精度で測定が行えたと思われる。

## まとめ
　今回はマイコンやフォトダイオードなどを用いて固有振動数を測定することができました。今回の実験装置は雑なところが多く、ちゃんとした装置をくみ上げることでより高精度な測定が行えると感じました。また、周波数分解能を上げることでより細かな値を知ることができると思います。これらの反省を活かし、次の測定などを行っていきたいと思います。