Arduino の loop() 1周にかかる時間(分周)

はじめに

ふと知人と話をして気になったので調べてみました。

そもそもなんで知りたかったというと、Arduino をつかった波形を観測するという記事があって、この波形ってどれくらい正確なのか?という話をしたためです。実際に使っている記事はこちら。

で、調べてみました。

状況や使うメソッドに応じて変わる事が前提だとは思いますが、こんな回答が見つかりました。

質問

arduinoのloop()の周波数

loop()が回る周波数が知りたいです。
具体的には外部からsin波などの数値をリアルタイムで入力した時の分解能の限界を教えてほしいです。

https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q11157619371

回答

その前に。
ハードの限界を引き出そうと思うなら、arduino言語は全く適当でない、というのはいい?
「簡単に使えます」のために、arduino言語はいろいろと「無駄」をしているから。マイコンの性能をカリカリに使いたいのなら出来るだけ自分でやるようにしないと。
http://ameblo.jp/aretaumitohirunosunahama/entry-12014713486.html
あたりを見ると、
—-
これはArduinoの標準関数
analogRead()
の実行に約100usかかる
—-
のを、Arduinoおまかせにしないことで
—-
実測の結果、
19.048usごとに
A/D変換が実行されました。
—-
なんて話もある。これはArduinoとしてではあるけれど。さらに本気でやるのならAVR-studioだっけ、Arduinoから離れてAVRを自分で全部面倒みてやる、とかの必要もあるかも。

実際には、周期が重要なパラメータならばプログラムの実行時間に頼って周期を作るのは決してよい方法ではなくて、タイマーなどを叩いてしっかり「時間」を作りこんでやるのが普通。「数値をリアルタイムで入力」というのがADコンバータなのかそれともそれ以外の「数値」を入力する経路なのかもわからないけれど、例えばADコンバータなら変換に必要な時間(有効桁数によってちがったりするけれど)はカタログデータから求まるので、それに対して適切な余裕を持たせた周期タイマーでAD変換のトリガをかける、などの手法を取る。「数値」のソースが違ったとしてもまぁ大筋は同じ考え方になると思う。



それでもやっぱり”loop()が回る周波数を知りたい”のなら…
一番簡単には、オシロスコープを調達して、I/Oのどれかを毎周期トグル(OFF<->ON切換)して、その周期を測定すればいい。もちろんのこと、loop()の中身によって実行周期は変わるから、中身はそれなりに作りこんでやらないと測定にならない。

あるいは、loopを数万回繰り返す周期でLEDをトグルしてやれば、その数万分の1がloop()の周期ってことになる。
何もしないでループを回してみると、

void setup() {
pinMode(13,OUTPUT);
}

long n=0;
int s=1;
void loop() {
if(n++>1000000){
s=s^1;
n=0;
digitalWrite(13,s);
}
}
で大体2秒周期ぐらい(相当いいかげんだけど)だから、一周2μS、500KHzぐらいで回っていることになる。

https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q11157619371

ソースを整形してみます

void setup() {
  pinMode(13, OUTPUT);
}

long n = 0;
int s = 1;

void loop() {
  if(n++ > 1000000) {
    s = s ^ 1;
    n = 0;
    digitalWrite(13, s);
  }
}

上記コードでざっくり 500KHz だそうです。

回答者の方のリンク先には、「arduino にマイクを接続して、音階を判別する」ということをしています。(そんな発想思い浮かばなかった)

ADCSRA レジスタを触ることで、変換精度を犠牲にしつつ、変換の高速化を図っているようです。

まとめ

疑問が解けたような気がしますが、そもそもやりたかったことは正確な波形を観測することなので、黙ってオシロスコープ購入した方が良さそうな気がしてきました;(´◦ω◦`):