編集履歴一覧に戻る
s51517765のアイコン画像

s51517765 が 2020年03月05日12時41分41秒 に編集

初版

タイトルの変更

+

Arduinoで振り子の周期を測定する

タグの変更

+

Leafonyプレゼントキャンペーン

本文の変更

+

このような質問をいただきました。 ![キャプションを入力できます](https://camo.elchika.com/f87bc6866b43b74f0e0675d14b11d9140071b8e4/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f62336539306561662d376461642d343165332d386363662d6164313030626336316330652f39616461666430302d656333332d346238652d393537392d396263303432386164646634/) ただし、振り子のハードウェアがないので、フォトセンサ(CDS)を指で隠すという形でフィージビリティ的に実施しました。 実際の振り子の周期としては、真ん中で観測すれば2回遮られるごとに周期になります。 左右のどちらかであれば遮られるごとに周期になります。 今回は左右のどちらか、に相当する方法で実装しました。 # 実装の考え方 フォトセンサ(CDS)は今回使用したものは、光が遮られる(振り子が通過すると)と抵抗が高くなり出力がLOWになり、光が戻ると抵抗が小さくなり出力はHIGHになります。 ただし、回路の組み方によってはHIGH/LOWは反対にもなります。 CDSは明るさによって抵抗が変わります。5Vを基準抵抗(ここでは10kΩ)と分圧することで明るさを検知します。基準抵抗はCDSによって、感度が一番よくなる抵抗を選びます。 明るいときと暗いときでのAnalog出力の差がなるべく大きくなる抵抗値を選びます。 下のようなコードを書いて、CDSの出力感度を確認しました。 ```CDS感度設定 void setup() { // put your setup code here, to run once: pinMode(A3, INPUT); Serial.begin(9600); } void loop() { int read; read = analogRead(A3); Serial.println(read); delay(300); } ``` ![キャプションを入力できます](https://camo.elchika.com/d81fbf599275ddbb0366cd9c51d4971fd55dbe36/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f62336539306561662d376461642d343165332d386363662d6164313030626336316330652f38383832303938342d393563612d343931662d613635302d663835343962316635373333/) # 実装のポイント では実際に時間を図るコードです。 光が遮られていない状態から、光が遮られている状態に変化した時刻を記録します。時刻を記録する配列をunsigned long time_[10];で10個分で用意します。 LOW→HIGHの状態を10回記録します。 ``` while (true) { read = digitalRead(A3); if (read == 1 && readPre == 0) { //1つ前で遮られていなく、今回遮られている time_[count] = micros(); count++; } // Serial.println(String(count) + " " + String(readPre) + " " + String(read)); readPre = read; //今の状態を前の状態として保持します delay(1); if (count == 10) break; //10回で終了 } ``` 次に、結果出力部です。 隣り合った時刻の差分をとれば、一周期です。 さらに、この平均をとります。平均はave=0にに対してして、平均したいものをave += period;のように加算し、最後にave /= 9;のように回数で割ります。 ついでにばらつき(最大ー最小)/2も算出してみました。 最大・最小は、Arduinoの関数Max/Minで求めてもよいです。 測定はMicro Secondですが、結果出力は1000倍してMilli Secondに丸めています。 ``` Serial.println("Calculation!"); Serial.println("Raw result."); unsigned long max = 0; unsigned long min = 32767; unsigned long period; unsigned long ave = 0; for (int i = 1; i < 10; i++) { //2つ目 - 1つ目が最初 // Serial.println(time_[i]); period = (time_[i] - time_[i - 1]) / 1000; Serial.println(period) ; ave += period; if (period < min)min = period; if (period > max)max = period; } ave /= 9; //結果 Serial.println("Ave= " + String(ave)); Serial.println("delta= " + String((max - min) / 2)); ``` # 出力結果 ``` Waiting Start! Calculation! Raw result. 219 315 226 239 241 241 225 210 209 Ave= 236 delta= 53 ``` [https://github.com/s51517765/-Measure-pendulum-cycle-with-Arduino](https://github.com/s51517765/-Measure-pendulum-cycle-with-Arduino)