Arduinoのtone関数の出力を計測してみた

最近電子工作界隈で人気のArduinoですが、お手軽に電子工作をできるというメリットがある反面、精度がイマイチというデメリットもあります。今回は、指定した周波数の矩形波を生成できるtone関数についてその精度を調べてみました。

そもそもの発端は、LEDを点滅させるのにtone関数を使おうと思い、2Hzの矩形波を出力しようとしてもLEDが点灯しっぱなしになってしまって思い通りにいかなかったことでした。久々にオシロスコープを引っぱりだしてきて調べてみると、2Hzを指定しているはずなのに随分と高い周波数(130Hz程度)の矩形波が出力されていました。これはどうしたもんかと思って色々調べてみると、どうも30Hz以下を指定しても狙いどおりの出力が得られないことがわかりました。

Experimental Setup

実験に用いた機器は以下のとおり。

オシロスコープで8番ピンの出力波形の周期を測定し、周波数を算出しました。また、測定の際には開発中のKondoLisp( http://github.com/hayamiz/kondo-lisp/ )を利用しました。

Experimental Result

tone関数の引数として指定した周波数(入力周波数)を横軸に、結果として得られた出力の周波数を縦軸にとったグラフが次のようになりました。

arduino-tone-char1

周波数が低い領域では実測値が異常な値を示していますが、それ以外では大体入力に対して10%程度の誤差の出力が得られていることがわかりました。10%の誤差というと決っして小さくはないので、Arduinoでtone関数を使ってそれなりに正確な波形を得ようとする際には、誤差を測定して補正することが必須になりそうです。

さて、何やら変な値を示している低い周波数帯に注目してみましょう。

arduino-tone-char2

引数として指定した周波数が低い領域では、上は2000Hzから、下は40Hzまで、変な値の振れ方をしています。この傾向は入力の周波数が31Hzになった途端にピタっと収まります。おそらくは、矩形波を生成するために内部でクロック数を数えているカウンタがオーバーフローするか何かしているんでしょう。実験に使ったArduino Duemilanoveは16MHzで動作しているので、30Hzの周期33msは533333クロックに相当します。16bit整数なら軽く溢れてしまいますね。この理屈だと、31Hzから大丈夫になることは説明できないのですが、まあ内部的に色々と事情があるのでしょう。気になる人は、Arduinoのtone関数の実装を読んでみるとよいと思います。

まとめ

  • Arduinoのtone関数は誤差が約10%ほどあるので、真面目な用途に使う際にはキャリブレーションを忘れずに
  • 低い周波数帯(30Hz以下)ではtone関数は使えないので注意しよう

30Hz以下で使えないことに関しては、そこまでできるようにしろとは求めないけれど、せめて有効な周波数の範囲をリファレンスに書いてほしいなあと思います。