公開日:2024/05/25
title.png

30th Season


#30-4 USB⇔UART変換が足りない

 先日、USB⇔UART変換モジュールを使いたくて、手持ちのFTDIモジュール(下図)を探したのだけど見つかりません。「アレレ??」と思ったら、既に別な用途で使っていました。

ar41_ftdi.jpg

  「メガネ、メガネ👓、アレ?何処に置いたっけ?」
    と、頭の上に乗せていた、みたいな……?

 今回は、そんなお話です。

USB⇔UART変換機能

 本HPのプログラムは、シリアルモニタからコマンドを送信したり、デバッグ情報を受信したりする物が多いです。故に筆者の使い方では、USB⇔UART変換機能は、必須機能なのです。
 Arduino UNOやDUE等のマイコンボードでは、ボード上にUSB⇔UART変換チップが搭載されている(※)ため、FTDIの様な、外付けのモジュールが必要ありません。

※あるいは、マイコンボード上のMCUチップその物がUSBユニットを搭載している。

 しかし、MCUチップATmega328やATtiny2313、ATtiny85等を生(単体)で使う場合には、外付けのUSB⇔UART変換モジュールが必要になります(以下記事など)。

 これらのMCUを単体で使う場合、USB⇔UART変換モジュールが必要で、最低1個あれば充足するのですが、複数を組み合わせて同時に使おうとすると、その数だけUSB⇔UART変換モジュールも必要となります。

使用頻度が高い

 特に本HPでは、USB⇔UART変換モジュール(FTDI)の使用頻度は高く、なんやかんやと使っています。過去にも、たまに足りなくなって困る時があったのですが、さすがにUSB⇔UART変換モジュールを2個同時に使いたいケースは本当に稀なので、もう1個予備で買うか?と言うと、そこまでの必要を感じませんでした。

 仮に、追加で予備を購入しようとすると、USB⇔UART変換モジュールは400円前後で購入可能なのですが、最近は400円〜600円と送料が高額なので、肝心なUSB⇔UART変換モジュールよりも高くつきます。「何してんのよ?」って感じで、無駄です。

※これでは、送ってもらう送料が主体で、商品がおまけ、みたいだ……?!「送ってもらうために商品を選んでいる」感じ。

 でも、稀に2個同時に使いたい場合があるのも事実……、と、無限ループ……。

そうか、作ってしまおう

 本当に必要なら、予備として買ってしまうのも良い考えです。でも、稀にしか使う機会が無いのなら無駄なので、自分で作ってしまおうと考えました。

マイコンボードを使う

 ボード上にUSB⇔UART変換チップが載っているマイコンボード(手持ちの例では以下)が在れば、作ることができます。


 Arduinoでは通常、マイコンボード上のUSB⇔UART変換チップとのシリアル通信はSerialクラスライブラリで使用可能です。ボード上のMCUに、追加のUARTユニットが搭載されている場合、2個目のUARTはSerial1、3個目はSerial2等のクラスでサポートされています。
 なので、Serialクラス⇔Serial1クラス間をブリッジするソフトウェアを組んでコンパイル&書き込んでおけば、そのマイコンボードは、

  USB ⇔ Serialクラス ⇔ Serial1クラス

と、2段階のブリッジを経て、USB⇔UART変換モジュールとして機能するのです。

ソフトウェア設計

 ただただ、ひたすら、SerialクラスとSerial1クラス間で送受信データをブリッジするだけなので、プログラムの処理は以下の様に単純です。

 何と、まあ、簡単ですこと。具体的なコードも、以下の通りです。

  #define SERIALU Serial  // USB <=> Serial
  #define SERIALB Serial1  // Serial <=> UART to bridge
  #define SERIALU_BAUD 9600  // SERIALU baud rate
  #define SERIALB_BAUD 9600  // SERIALB baud rate

  void setup (void)
  {
    // serial
    SERIALU.begin (SERIALU_BAUD);
    SERIALB.begin (SERIALB_BAUD);
    while (!SERIALU || !SERIALB)
      ;
  }

  void loop (void)
  {
    // re-direct each other
    if (SERIALU.available ()>0)
      SERIALB.write (SERIALU.read ());
    if (SERIALB.available ()>0)
      SERIALU.write (SERIALB.read ());
  }


 シンプル(1^−^;)。
 2つのUART通信速度が異なる場合も、プログラムとしては動作可能ですが、遅い方のUART通信に律速されてスルーレートが落ちたり、場合によってはデータを取りこぼしたりする可能性がある事には、留意してください(∵バッファオーバフロウ)。

定格電圧

 3.3V定格のUSB⇔UART変換が必要な場合、候補となる手持ちのマイコンボードは:

 5V定格のUSB⇔UART変換が必要な場合、候補となる手持ちのマイコンボードはArduino UNO一択でした。
 ただ、UNOには、ハードウェアUARTユニットが1個しか搭載されておらず、その1個も、オンボードのUSB⇔UART変換チップ(ATmega16U2)との通信で使われているので、ブリッジ先に使えるUARTユニットがありません。

 止むを得ないので、UNOの場合には、拙作高速ソフトウェアシリアルライブラリ(HsswSerial)を使う事にしました。一般に、ソフトウェアシリアルは半二重通信なので、データを取りこぼす恐れがありますが、これは止む無しです。

プログラム

 以下に、完成したプログラムをリンクします。

  完成版プログラム:usb_uart.ino

 UNOとDUEで動作確認してあります。他のマイコンボードでも、少し修正すれば問題なく使えるはずです。

  修正が必要かもしれない箇所は:

 以下の様な#defineマクロ等を使って、マイコンボード毎に場合分け(#ifdef〜#endif)して使ってください。

 例えば、以下コードの様になります。

  #ifdef ARDUINO_AVR_UNO
  #define Serial1 SerialHssw  // HsswSerialクラスライブラリを使う
  #endif // ARDUINO_AVR_UNO

一応、実験しておく?

 ここでは、Arduino DUEと、普通のUSB⇔UART変換モジュール(FTDI等)を使って、相互の通信ができる事を確認しておきましょう。DUEに、こちらのプログラムをコンパイル&書き込んで、DUEとUSB⇔UART変換モジュールを以下接続表に従って接続してください。

Arduino DUE 接続 USB⇔UART変換
モジュール(FTDI等)
GND GND
D18(TXD0※) RXD
D19(RXD0※) TXD

※DUEのシルクでは、TXD1,RXD1の表示です。また、FTDIの電圧ジャンパは3.3V側に設定してください。


 以下、実験中の様子です。

a304_expr.jpg

 上の写真だと、DUEがUSB⇔UART変換モジュールとなって、外部のUART通信機器(上写真ではFTDI)とUART通信している様子です。


 Arduino IDEのシリアルモニタやTera Term等の通信ソフトウェアを使い、互いにデータを送信し合って、動作を確認して見てください。

 以上が確認できたら、OKです。


 ただのUSB⇔UART変換モジュールとして、マイコンボードを1個使ってしまうのは勿体ない気もしますが、USB⇔UART変換モジュールが足りない時の代用としては、使えます。時々しか必要にならない、予備のUSB⇔UART変換モジュールを購入するのは、お金の無駄ですし、こんな簡単なプログラムでUSB⇔UART変換モジュールの代用にできるなら、活用すべきでしょう?


btn_arduino.png

btn_prev.png btn_next.png

home