公開日:2019/10/05
title.png

7th Season


#7-8 Pi ZeroWとArduinoのUSB⇔UART変換接続

 前回(「#7-7 Pi ZeroWの非同期シリアル通信」)、Pi ZeroWとArduinoの非同期シリアル通信を試していた時に、ふと思ったのですよ。

 「折角デバッグの済んでいるプログラムなのに、"Serial"インスタンスを置換しないとPi ZeroWと通信できないなんて、面倒だな」と。

 そう、Pi ZeroWには、USBホストになることが可能なUSB端子(実際にはUSB-OTG)が付いているでは無いですか!このUSBにArduinoを接続して、USB⇔UART変換で通信できないのかしら?そう思って調べてみたところ、「できる」みたいです。

Pi ZeroWのUSB

 Pi ZeroWのUSBは、USB-OTG(On The Go)と言う規格のインターフェイスで、つながる相手に合わせて、USBファンクションにもUSBホストにもなることができる仕様です。そのお陰で、接続ケーブルには、OTG対応のケーブルが必要でした(以下図、OTG変換アダプタ)。

ar72_otg.jpg

 と、言うことで、Pi ZeroWのUSB端子にArduinoを接続する、と言うことは、Pi ZeroWがUSBホストとなって、Arduinoとつながる、と言うことになります。USB-OTGの規格上は、全く問題なく、接続可能です。問題があるとすれば、Raspbianのデバイスドライバがどうなっているか?
 Windowsでもそうですが、新しく買って来たUSBデバイスの場合、デバイスドライバのインストールが必要なケースがありますよね?それと同じで、Pi ZeroWにArduinoをUSB接続した時、適切なドライバがRaspbianにインストールされていれば、良し。そうでなければ、接続はしたものの、認識してもらえず、何も操作できない状態に陥るでしょう。

 ネットで調べてみたところ、どうやら、Pi ZeroWのUSB端子にArduinoを接続すると、適切なドライバが機能して、通信できるようになるみたいです。ドライバの心配は要らないということです。

ArduinoをUSB接続する

 では、早速、Arduino UNOを接続してみます。まずは、OS(カーネル)のリングバッファ状態を表示させておきます。準備ができたら、Arduino UNOのUSBケーブルを、Pi ZeroWのUSB端子に、OTGアダプタを介して接続してください。

  実験サンプル:【 】内はshellウインドウでのコマンド入力
  【dmesg -w】 …… 実行後、ArduinoをPi ZeroWに接続
  usb 1-1: new full-speed USB device number 2 using dwc_otg
  usb 1-1: New USB device found,
  usb 1-1: Manufacturer: Arduino (www.arduino.cc)
  cdc_acm 1-1:1.0: ttyACM0: USB ACM device
  usbcore: registered new interface driver cdc_acm
  cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters
   …… 一部省略
  【CTRL-C】 …… dmesgを終了する

 こんな感じ(↑)です。「新しいUSBデバイスが見つかったよ。Arduinoだってさ。ttyACM0で登録したよ」って、言ってます。

※ttyACM0:Abstract Control Model……「抽象的な制御モデル」みたいですね。

  【ls -l /dev/ttyACM0】
  crw-rw---- 1 root dialout 166, 0 Sep 29 12:32 /dev/ttyACM0

  【stty -F /dev/ttyACM0】
  speed 9600 baud; line = 0;
  -brkint -imaxbel

 認識されたデバイスttyACM0は、前回のシリアルユニット(ttyS0)と同じでした。グループdialoutにリード/ライト権限が付加されていて、ユーザpiがdialoutに属しているので、ユーザpiからUSB⇔UART変換を制御して、Arduinoと通信することが可能です。

ArduinoとUSB⇔UART変換で通信する

 前回と同じですけど、今回はArduino UNOにDHT11の制御プログラム(meas_am2302.ino)を書き込んで、Pi ZeroWのUSBポートに接続します。

Pi ZeroW 接続 Arduino UNO 接続 DHT11
USB-OTG USB  
  5V VDD
GND GND
D2 SDA

 USBから電源がもらえて、レベルシフタ(L/S)も要らないので、とてもシンプルです。前回のネットリストと比べてみてください。

ar78_expr.jpg

 前回使ったawkのスクリプト(meas_am2302.awk)を少し変更する必要があります。以下、変更点周辺の抜粋です。

  完成スクリプト:meas_am2302.awk
  #! /usr/bin/awk -f
  BEGIN {
   :
   :
    # init
    FS=",";
    Serial="/dev/ttyACM0";
    system ("stty -F " Serial " 9600 -echo igncr -hup");
    PROCINFO[Serial, "READ_TIMEOUT"]=4000;

    # "who" command
    print "who" > Serial;
    getline < Serial;
    if ($0=="RDY")
    {
      print;
      print "who" > Serial;
      getline < Serial;
    }

    if (ERRNO=="")
      print;
    else
      print ERRNO;
   :
   :
  }


 青くしたところが、変更・追加箇所です。以下にまとめます。

 ちょっと、ArduinoにリセットをかけるDTR信号の動きが明確には、読み切れていないのですが、どうも、"RDY"を受信した時、直前に送っておいた【who】コマンドが無視されているみたいなので、再送信するように記述してあります。
 sttyコマンドに追加した-hupを削除すると、デバイス/dev/ttyACM0を開く(open)度に毎回Arduinoにリセットが掛かるようになります。その方が良いケース(毎回リセットしたいケース)もあるかもしれないので、使い分けてください。

※スクリプト(meas_am2302.awk)には、今回必要となったコードを追加してありますが、通信相手(変数Serialの設定値)は、前回のまま「/dev/serial0」としてありますので、ダウンロード後、そこだけ変更してください。

  実験サンプル:【 】内はshellウインドウでのコマンド入力
  【vi meas_am2302.awk】 …… Serialのデバイス名を変更する。
  Serial="/dev/ttyACM0";
    【ZZ】 …… セーブして終了

  【meas_am2302.awk】
  RDY …… Arduinoを接続して、初めの実行時だけ表示される。
  DHT11,1.02
  OK,30.0,59.0

  【meas_am2302.awk 3】
  DHT11,1.02
  OK,29.0,58.0
  OK,29.0,58.0
  OK,29.0,58.0
  OK,30.0,58.0

 USB⇔UART変換経由で、Pi ZeroWとArduino UNOが通信し、Arduinoが読み出したDHT11の気温・湿度データをPi ZeroWに取り込むことができました。

 前回(「#7-7 Pi ZeroWの非同期シリアル通信」)の様に、シリアルユニット同士を接続する場合と違って、レベルシフタ(L/S)も要らないし、USBから電源も取れるし、すごく楽チンです。以下、特徴をまとめておきます。

 個人的には、欠点を遥かに超越する利点がある、と感じています。皆様はいかがでしょうか?

その他のUSBデバイスは繋がるの?

 そもそも、キーボードやマウスなど(HID)の様な、デフォルトのデバイスドライバで事足りる物であれば、Pi ZeroWに接続するだけで使えたわけです。Arduinoも、ある意味、デフォルトデバイスドライバの中から、ttyACM0というデバイスドライバが選択されて、動作することができた、と考えることができます。

※ttyACM0のA.C.M.が、「USB Abstract Control Model (抽象的な制御モデル) driver」の略であろうことは、dmesgのメッセージから明らかです。何らかのデフォルトデバイスドライバだと考えられます。

 そこで、「明らかにデフォルトドライバでは動作できないでしょ?」と言う、特殊なものは除き、いくつか、手元に見つかったUSB接続デバイスをPi ZeroWに接続して、対応状況を調べてみようと思います。
 調査方法は、shellウインドウで、【dmesg -w】を実行しておいて、次々とUSBデバイスを挿してみるだけです。

  実験サンプル:【 】内はshellウインドウでのコマンド入力
  【dmesg -w】 …… 実行後、ArduinoをPi ZeroWに接続
   :
   …… USB機器を接続して、メッセージを確認する。
   :
  【CTRL-C】 …… すべての機器の確認が終わったら、dmesgを終了

 以下、手元のUSB機器で試してみた結果です。

USB⇔UART変換モジュール(FTDI)

 いつも使っている、USB⇔UART変換モジュール(FTDI、下図)をPi ZeroWに接続してみました。

ar41_ftdi.jpg

 「Product: FT232R USB UART」として認識され、デバイス/dev/ttyUSB0が登録されました。

  【ls -l /dev/ttyUSB0】
  crw-rw---- 1 root dialout 188, 0 Sep 29 11:22 /dev/ttyUSB0

 こちらも、/dev/ttyS0や/dev/ttyACM0と同様、グループdialoutに対してリード/ライト権がありますので、恐らく、普通にデバイスを開いて(openして)、アクセス可能でしょう。ttyS0が使えるのに、敢えてFTDIを使用する機会があるかどうかは疑問ですが……。

※FTDIはジャンパで信号レベルを3.3V/5Vから選べるので、L/S無しで非同期シリアル通信が可能と言う利点はあるかも、です。RTSやCTS、DTRも使用可能です。

 Arduino Pro Mini+L/SでttyS0(UART)とつなぐか、Arduino Pro Mini+FTDIでttyUSB0とつなぐか?どっちもどっち?な感じですね……。

Arduino Micro

 同じArduinoですが、UNO(ATmega328+ATmega16U2(USB⇔UART変換チップ))と異なり、ATmega32U4を搭載した、Arduino Micro(下図)は認識されるでしょうか?

ar21_micro.jpg

 Arduino MicroをPi ZeroWのUSBに挿入したところ、「Product: Arduino Leonardo」として認識され、/dev/ttyACM0が登録されました。

  【ls -l /dev/ttyACM0】
  crw-rw---- 1 root dialout 166, 0 Sep 29 11:25 /dev/ttyACM0

 UNOと同様に、USB⇔UART通信することができました。

 時に、Windowsの場合だと、新しく検出したUSB⇔UART変換デバイスには、COM1,2,3,…と、番号が振られ、基本的に、初めて検出された時に割り振られた番号を記憶しています。一度、COM2で認識されたUNOは、何度接続しても、COM2で接続され、例えば、UNOが接続されていない時にMicroを挿入したとしても、MicroにCOM2が割り当てられることはありません。
 例えばこの時、MicroにはCOM3が割り当てられ、以降、Microを検出すると、毎回COM3になります。

 しかし、Raspbianでは、違うことが解りました。今回のMicroも、UNOと同じttyACM0で登録されています。HUBなどを使って、複数台同時接続は試していないので、定かではありませんが、恐らく、毎回検出した順にttyACM0,1,2,…と、番号が振られるのでしょう。

STM32ボード

 ARM Cortex-M3を搭載した、STM32ボード(下図)では、どうでしょうか?

ar41_stm32.jpg

 同様に【dmesg -w】で監視しながらPi ZeroWのUSB端子に挿入したところ、「Product: Maple 003」として認識され、/dev/ttyACM0が登録されました。

  【ls -l /dev/ttyACM0】
  crw-rw---- 1 root dialout 166, 0 Sep 29 11:25 /dev/ttyACM0

 UNO、Microと同様です。USB⇔UART変換での通信も確認できました。

 Arduino系の、比較的有名なチップだったから、デバイスドライバが対応していたのか?はたまた、USB接続した時に、デバイスから送られてくる情報を使って、ttyACM0が適切だと判断され、登録に至ったのか?は、定かではありません。

 もし、前者だとすると、マイナーなUSB⇔UART変換チップを搭載したArduino互換機の中には、認識してもらえずに、制御不能なボードがあるかもしれないので、ご注意ください。手元のArduino系MCUボードは全て、ttyACM0で認識されることを確認できたので、筆者の環境では、困ることはなさそうです。

USB接続HDD

 最後に、USB接続のハードディスク(HDD)を試してみます。使用したのは、Windowsで使っている、Toshiba製の60Gバイト HDDで、フォーマットはNTFSです。
 Pi ZeroWのUSB-OTGコネクタに接続したところ、リムーバブルディスクとして認識され、デスクトップにアイコンが表示されました(下図)。

ar78_remov.png

 ただし、dmesgコマンドには、「ntfs: (device sda1): load_system_files(): $LogFile is not clean. Mounting read-only. Mount in Windows.」と、言うメッセージ(リードオンリでマウントしたよ)が出力されており、実際、ファイルへの書き込みはできませんでした。存在するファイルのリスト(lsコマンド)は取得でき、内容の参照は可能でした。ただし、日本語のファイル名は文字化けして読めませんでした。
 dmesgコマンドのログを解釈すると、Raspbianでリード/ライトするには、何らかのお作法が必要みたいですね。ちょっと、試しに接続してみただけ、ですので、深追いはしないことにします……。


 これで、Arduinoとの通信がとても簡単に確立できるようになりました。使い道のなくなったUARTユニットは何に使おう?個人的には、「シリアルコンソール」って言うのは、あまり魅力を感じないので、何か使い道ができた時の為にリザーブしておこうと思います。


btn_arduino.png

btn_prev.png btn_next.png

home