Arduinoでシリアル通信のテストをしていたが、PC側の特定のソフトからだとArduinoと通信できない現象に悩まされた。
ArduinoのSerialライブラリは、hand shakeやparity等の指定もDTR/RTS等の操作も無いシンプルなものだ。デフォルトのライブラリが単純すぎるのかと思い、代替のSoftwareSerialやNewSoftSerialを使ってみたが全く結果は変わらなかった。またシリアル変換chipの相性などを疑ってみたが、これもよく分からなかった。そもそも有名なFTDIのchipに大きな問題が在る訳なかろうに。
Portmonで調べた結果、動作するソフトと動作しないソフトとでは通信パラメータ(IOCTL)が一部異なっていたが、結果から言うとDTRの制御に問題があることが分かった。
Diecimila以降のArduinoでは、DTR線を特殊な用途(=auto reset)に使っているのだ。
つまり、DuemilanoveではFT232RからのDTR線が、0.1uFのコンデンサを介してATmegaのRESET端子(pin1)に繋がっており、DTRをgroundに落とすことで、コンデンサの放充電によりpin1へのreset pulseを作り出し、auto resetがかかる仕組みになっているのだという。なお、回路図ではRTS線もR2を介してRESETに繋がっている様に見えるが、NMは"not mounted"の略で、ここは繋がっていない。DiecimilaではRTS/DTRともにNMの表記があるが、R2には何も実装されず(NM)、R3には0.1uFのコンデンサが実装されている、と本家に記載がある。
Note that R2 is not mounted and that R3 has been replaced by a 100 nano-farad capacitor.Arduinoとうまく通信できないソフトでは、DTR線を独自に制御してしているために、どうやら通信中にArduinoにリセットをかけてしまうらしかった。
基板に変更を加えずにAuto resetを無効にする
この問題は有名らしく、対策はすぐに見つかった。Hardwareに変更を加えても良いが、簡便なのは以下の方法。本家のAutomatic resetの解説に小さく書かれている。
You may also be able to disable the auto-reset by connecting a 110 ohm resistor from 5V to the reset line.(RESET端子と5Vの間に、110Ωの抵抗を追加する。)Playgroundにも解説があって、こちらでは120Ωが推奨されている。実際120Ωの抵抗は見つけにくいから、合成抵抗で110~124Ωにせよと。ピンソケットに刺せるので楽チンだ。
なおRESETと+5Vの間にはまた別に10kの抵抗があるので、これと並列合成で109~122Ω位の値になる。ATmegaのpinあたりの最大電流は40mAだが、109Ωだと5/109*1000=46mA位流れる計算になる。少し流れすぎな気もするが、DTRがgroundに落ちた時にresetがかからなくするためにはこれくらいの電流が必要なんだろう。
この方法を試したところ、無事問題のソフトからも通信できるようになった。
なお、この対策法はSerial変換がFT232Rだけの場合に有効らしく、同様のDTR結線があるUNOでは残念ながら動作しないようだ。(本家には出来ると書いてあり、auto resetは確かに無効に出来るのだが、通信ができない。)
また、auto resetを無効にすると、Playgroundに書いてあるように、programの自動uploadが出来なくなる。手動resetが必要。手順は、
- reset buttonを押したままにする。
- 基板上のTX/RX LEDから目をそらさずに、
- Arduino IDEのUploadボタンをclick。
- RX(?) LEDが光ったらすぐにreset buttonから手を離す。
また1.を省略し、TX LEDが光ってからすぐにreset buttonを押す方法でもuploadできた。慣れればそれほど面倒ではない。
0 件のコメント:
コメントを投稿