USB/Arduinoインターフェース

コンセプト

  • ArduinoコネクタおよびホストインターフェースについてArduinoとの互換性をとる。
  • USBコネクタがジャックインされる(USBバスパワーが投入される)とUSBインターフェースが活性化される。

USBブリッジチップCP2104/2105

製品に採用したのはCP2104であるが、第一次試作の当初、入手上の問題から使用することになったCP2105での試行錯誤も合わせて記録しておく。(混ざって読みにくいですね。すみません。)

  • Silicon LabsのCP2104/2105*1を使用する。CP2104はJapanino*2で採用されている。これらは安く、外付け部品が少ない(バスクロック用クリスタルも不要!)。ただし、パッケージがあまりにも小さくて手はんだが難しい。
  • CP2104/2105は「独立した」3.3Vレギュレータを内蔵しているため、これを利用してArduinoコネクタの3V3端子に電源を供給 することができる。ただし電流は最大100mA。USBバスパワーでない場合(電池駆動の場合)でもレギュレータ入力端子に5Vを与えておけば3.3Vが 出力される。
  • I/O供給電圧は3.3V系であるため、VOHが5V系インターフェースに合わない場合があるかもしれない。その場合は外部でプルアップしろとデータシートには書いてある。また、VIHは5.8Vまで許容されているので5V系の出力をそのまま接続することができる。
  • CP2104/2105用の支援ソフトウェアがSilicon Labsから提供されている。
    • CP210x_VCP_Win_XP_S2K3_Vista_7.exe 仮想シリアルドライバ
    • CP210xSetIDs.exe チップ内蔵のID書き換えアプリ
    • CP210xPortConfig.exe ポート機能設定アプリ(これでLED制御ポートを設定する*3
  • CP2105はデフォルトではGPIOモードになっており、そのままではDTR信号を出せず「自動リセット」(下記)が使えない。上記のポート機能設定アプリでModemモードに設定し直す。(右図)

CP2104

CP2105

  • RTSを使って自動リセットができることが分かった(後述)ので、CP2105に関して配線を変更。GPIO.0_S(標準ポートのGPIO0)を送信LEDに、GPIO.1_Sを受信LEDに接続。しかしこのままではGPIOはただのホストから制御する汎用I/Oポートのままなので、CP210xが自働的にLEDを点灯できるように 上記のアプリCP210xPortConfig.exeを使って設定変更する。

CP2104

CP2105

  1. まず ポート機能設定アプリを起動する。
  2. CP210xをUSB接続。(あらかじめ接続してあった場合はいったん外して再度挿したほうがよい)
  3. リフレッシュボタンを押す(図の1)。
  4. CP2105の場合”Device Mode”は”GPIO Mode”のまま。変更しない。
  5. GPIO_O_SCIとGPIO_1_SCIの2行の設定を”Automatic by Device”および”Open-Drain”に変更(図の2)。このとき、設定順を逆にすると、”Open-Drain”が”Push-Pull”に変わってしまうので注意。
  6. “Set Configuration”ボタンを押す(図の3)。書き換え許可を求めるダイアログが出るがYESを選択。ウィンドウが一瞬ブリンクして書き変わる。

*1 シリアルポートの数が異なる。2104は1チャネル、2105は2チャネル内蔵。価格はほとんど違わない。当初2104のディーラー在庫がなかったため一次試作のみ2105を使うことに。量産では在庫が復活。

*2 学研の「大人の科学マガジンVol.27」に付録のArduino互換のマイコンボード。

*3CP2105についてはLED出力ポートがDTR信号とピンを共有しているため、LED制御ができないことが判明。その後の調査でDTRの代わりにRTS信号を使うことにして、LED出力ポートの不足は解決。

MACユーザはリセット時に注意

MAC用のドラ イバ(Silicon Labs製)で「自動リセット」がうまくかからない問題があるという書き込みを発見。Japaninoの設計元のSparkfunの開発者が肯定している。おそらくMACのドライバがDTRを期待通りにドライブしない仕様となっているのであろう。本家のArduino(Duemilanove)では FTDIのFT232RLを使用しており、こちらでは問題は起こっていない。 大人の科学の公式FAQでMacへの対処法が出ている。

 A10.「コンパイル後のスケッチのサイズ・・・」の文字が出たタイミングでJapaninoボード上の「RESET」ボタンを0.5~1秒ほど押してください。うまくいかない場合、再起動してからやり直してください。

一応これで対処できるようだ。

Arduino「自動リセット」についての解説

Arduino本家のHP、Duemilanoveの仕様説明にはこう書かれている。

自動(ソフトウェア)リセット

Arduino Duemilanoveは、(スケッチを)アップロードする前に物理的にリセットボタンを押さなくても済むように、ソフトウェアが動作しているコンピュータからリセットできるように設計されている。 FT232RLのハードウェアフロー制御信号の1つ(DTR)が0.1uFのコンデンサを介してATmega168/328に接続されている。 Arduino環境では、Arduinoソフトウェアは単純に「アップロードボタン」を押すだけでコードをアップロードできる機能を使っている。 ということは、ブートローダのタイムアウトをより短くできるし、 DTRを引き下げることでアップロードを開始するのにうまい仕組みにもなっている。 この仕組みは別の意味も含んでいる。DuemilanoveがMac OSXあるいはLinuxに接続されている場合は、 いつでもソフトウェアから(USB経由で)確立した接続がリセットされてしまうということだ。 リセット後の0.5秒くらいの間にDuemilanoveのブートローダが走る。 不正なデータ(新しいコードを除いたもの)を無視するようプログラムされているものの、 接続確立後ボードに送られた最初の数バイトの邪魔なデータを取り込んでしまう。 ボード上で動いているスケッチが最初の起動で初期設定やその他のデータを受信する場合、 接続確立の後とデータ送信の前に1秒間通信を待たせるようスケッチに作りこんであることを確認する必要がある。 Duemilanoveには自動リセットを無効にするパターンカット用の配線パターンがある。 この配線パターンの隣にあるハンダパッドは、ハンダを載せることでカットしたパターンを元に戻すことができる。 このパッドには”RESET-EN”という印刷がしてある。 また、110Ωの抵抗を5Vとリセット線の間に接続することで自動リセットを無効にすることもできる。

非常に低コストでできる頭のいい(しかしトリッキーな)方法ではあるが、回路設計の常識からは逸脱した乱暴な方法といえないだろうか。

Avrdudeでの自動リセットの扱い

ここで、Arduino開発環境の内部で使用されている書込みプログラム Avrdude のソースコードを眺めてみた。

avrdude.c:

static int arduino_open(PROGRAMMER * pgm, char * port)
{
   ...
    /* Clear DTR and RTS to unload the RESET capacitor (for example in Arduino) */
    serial_set_dtr_rts(&pgm->fd, 0);
    usleep(50*1000);
    /* Set DTR and RTS back to high */
    serial_set_dtr_rts(&pgm->fd, 1);
    usleep(50*1000);
    ...
}

ser_win32.c:

static int ser_set_dtr_rts(union filedescriptor *fd, int is_on)
{
     HANDLE hComPort=(HANDLE)fd->pfd;
     if (is_on) {
           EscapeCommFunction(hComPort, SETDTR);
           EscapeCommFunction(hComPort, SETRTS);
     } else {
           EscapeCommFunction(hComPort, CLRDTR);
           EscapeCommFunction(hComPort, CLRRTS);
     }
     return 0;
}

これを見るとDTRだけでなくRTSもトグルしている。すなわちどちらのピンでも自動リセットをかけることができるようである。 実験して確認したところ、RTSでもリセットをかけることができた。これでCP2105をGPIOモードのままModemモードに設定する必要がなくなる。 GPIO.0とGPIO.1はデフォルトの設定のままLEDドライブ用のピンとして使える。

Arduinoインターフェース

  • CPUに標準のATmega168/328と異なるATmega324を使用するため、兼用機能(PWMなど)が合わない部分がある。
  • ボード内ですでに利用しているピンもArduinoに合わせてコネクタに出す。
  • Arduino標準では”Power”コネクタの6番ピンは”VIN”であり、ここから5V電源が供給される場合がある。本製品では対応しないためこのピンは空きとする。

市販のシールドを買ってきた

安価でかつ追加部品なしですぐに使えそうな「タッチシールド(1,495円)」を買ってきた。メカ寸法はぴったり合ってた。基板レイアウトは問題なし。 Sparkfunの商品ページから回路図とサンプルコードを入手。 A4-A5ポートをI2C(=TWI)として使い、D2を割り込み入力にしているようだ。WOBとの対応は以下のとおり。

期待される機能 Arduinoピン名 ATmega168 WOB(ATmega324) H/W使用可
I2C(SDA) A4 PC4(SDA) PA4 OK
I2C(SCL) A5 PC5(SCL) PA5 OK
INT0 D2 PD2(INT0) PD2(RXD1) 衝突

残念、割り込み入力でネットワークレシーバ出力と衝突している。だが、ハードウェア的にはダンパー抵抗が入っているので衝突しても壊れることはない。加えてPB6によりレシーバ出力を禁止してやればよい。ネットワークとは排他的になるのはやむを得ない。 それよりもサンプルコードで内蔵TWIを使っているのが困る。ソフトウェアエミュレーション方式に書き換えた結果、見事動作。