Month12月 2013

マルツのUSB-UART変換モジュール

AVRのデバッグ用にUARTで使うPD0とPD1を残してありましたが、よく考えるとUARTをモニターできるものがArduino以外になかったので、近所のマルツでこのモジュールを\893-で買ってきました。(近所にマルツしかパーツ屋がないのは苦しいorz)

マルツの超小型USBシリアル変換モジュールの箱

本体
マルツの超小型USBシリアル変換モジュール

箱を開けると本当に小さい基板と連結用のソケットが入っていて、これをはんだづけするとブレッドボードなどに指して利用できるみたいです。上の写真ははんだづけしてあるものです。

チップはProlific社のPC2303SAでUSB1.1/2.0フルスピードに対応しているようで、USBmicroのBソケットが付いています。

このモジュールの仕様で、信号ラインは3.3Vであるとこに注意しないといけません。5V系だったのでとりあえず手元の1kΩの抵抗2つで分圧してから入力させました。これで十分みたいです。電源は5Vでいいみたいですが。

この基板、ほんとうに小さくてUSBケーブルを指すとすぐ動きやがるのでケースとついでに5V変換の基板もつくろうと思っています。

【AVR】_delay_ms()がうまく動かない?

AVRで工作していると、1秒待って欲しいって思うときにディレイ関数を使いたくなります。そのノリで使っていたら、100msと指定していたのに10秒以上待たされるという現象が起きました。なぜでしょう。

まずはじめに疑ったのは、クロック周波数です。_delay_ms()関数では指定された時間とクロック周波数から計算されたサイクル数、待つという実装がされています。つまり、クロック周波数が違えば指定した時間通りに動いてくれません。

というわけでクロック周波数を確認しました。筆者が今回使っていたAVRはATmega328Pです。内蔵RC発信器からの8MHzで動作させています。Hzで書くと8,000,000Hzになります。周波数の指定は、F_CPUで定義することでできます。この場合は、

[code lang=”cpp” highlight=”1″]
#define F_CPU 8000000UL

int main(void){
_delay_ms(100);

return 0;
}

[/code]

このように8,000,000Hzである、と宣言します。最後のULはunsigned Long型の定数であると指定するためのものです。8,000,000という値はintの範囲(-32768~32767)を超えているので、これがないと溢れてしまいます。
今回は正しく定義されていたので別の問題である、ということで考えうる他の原因を考えました。

次に疑ったのは、_delay_ms()関数が引数として取りうる値が制限されていることです。調べてみると過去のバージョンのことで当てはまりませんので割愛します。

最終的に考えたことは、_delay_ms()関数は使ってはいけないのではないかということです。つまり、_delay_ms()関数を使っても正確に測ることは不可能な場合があるということです。
それは割り込みを使った時です。

考えてみればわかるのですが、時間から求めた回数だけ「何もしない」を繰り返しているわけです。その間に割り込みが発生してしまえばおかしくなるのはすぐに分かります。

というわけで、原因が割り込みであるというところまでは確認をしていませんが、LEDのダイナミック・ドライブでタイマー割り込みを積極的に利用しているのでこれが原因であるということで間違いないと思います。どのよう解決するかはまたどこかで書こうと思います。