Posted at
ArduinoDay 11

ArduinoのATmega168/328Pでサンプリングに挑んだ場合の限界値

More than 3 years have passed since last update.

これはArduino DuemilanoveあるいはUNO R3をターゲットに、avr-gccを使って実験していたときに得られた結果の抜粋である。


やっていること/したいこと


  • 物理乱数生成のために、ノイズ源から0/1のビットを取り出し、シリアル変換してArduinoに載っているシリアル-USB変換チップに送っている

  • ノイズ源は少なくとも10MHzぐらいまでは十分帯域が伸びているので、できるだけ速くサンプリングしたい

  • できればAVRの中でちょっとしたフィルタリングもしたい

  • クロックは16MHzのままで実験(20MHzにしたら速くはなると思う)


  • register volatile を使ってCの変数は極力レジスタに割り当てた


結論


  • タイマー割り込みは使わずにタイマーカウントの完了を待って同期させたほうが速い(当然だが1

  • タイマー割り込みがあると250kHzぐらいが限界

  • タイマー割り込みを使わなければ400kHzぐらいまではなんとかいけそう


コードと回路図置き場

https://github.com/jj1bdx/avrhwrng



  • v1はTimer 0のタイマー割り込みを使っている


  • v2はTimer 0のタイマー割り込みを諦めて、タイマー0がカウント終了になった時のフラグ(OCF0A/TIFR0)を見て、終わっていたら次に進むという緩い同期をしている


  • rawtestはv2よりずっとコード量が少なく、何もしていないが、その分速い

バイナリや回路図もあるので興味のある方はどうぞ。


課題


  • v1はガチガチに同期させるので出力速度は一定しているが、遅い

  • v2は同期が緩いのと、中でノイズ源の入力によって出力回数が変化するvon Neumannテストをしていて出力速度が一定せずバラツキがある

  • rawtestは本当に何もしていないのと同期が緩いので速いが、これではAVRを使った意味がない

  • 一桁遅いレートならArduino UNO R3でもなんとかなるだろう

  • やっぱり割り込み使ったほうが安全なような気がする





  1. タイマー割り込みを処理する部分では、スタックへレジスタを退避復旧させなければならないため、その分時間がかかる。