« FEZ Domino Tips (2) - .Net Micro Frameworkでms単位の時間計測を行う | トップページ | Arduino Ethernet Shieldのパワーオンリセット »

FEZ Domino Tips (3) - USB Host機能の使い方

FEZ Dominoの特徴の一つはUSB Host制御のライブラリが充実していることです。USB Hostとは、USBデバイス(キーボード、マウス、USBメモリーなど)への読み書きを行うPC相当の動作を行う機能です。

mbedでもLPC1768にUSB Host機能がありますが、ライブラリが十分にそろっていません。そのため、USB Host機能を使ってUSB機器を制御したい場合、Dominoは有力な選択肢になりそうです。今回、USB Host関連のサンプルコードをいくつか動かしてみたので結果を記載します。


USBデバイスの認識

以下は、USBデバイス挿抜時のイベントを検出するコードです。ビルドするためには、次のアセンブリが必要です。

  • GHIElectronics.NETMF.System
  • GHIElectronics.NETMF.USBHost
  • GHIElectronics.NETMF.Hardware →USBH_Device classの定義がここあるため
  • Microsoft.SPOT.Naitve
using System.Threading;
using GHIElectronics.NETMF.USBHost;
using Microsoft.SPOT;

namespace FezUsbHost
{
    public class Program
    {
        public static void Main()
        {
            // Subscribe to USBH events.
            USBHostController.DeviceConnectedEvent += OnDeviceConnected;
            USBHostController.DeviceDisconnectedEvent += OnDeviceDisconnected;

            // Sleep forever
            Thread.Sleep(Timeout.Infinite);
        }

        // USB DeviceConnectedEvent Handler
        static void OnDeviceConnected(USBH_Device device)
        {
            Debug.Print("Device connected...");
            Debug.Print("ID: " + device.ID + ", Interface: " + 
                device.INTERFACE_INDEX + ", Type: " + device.TYPE);
        }

        // USB DeviceDisconnectedEvent Handler
        static void OnDeviceDisconnected(USBH_Device device)
        {
            Debug.Print("Device disconnected...");
            Debug.Print("ID: " + device.ID + ", Interface: " + 
                device.INTERFACE_INDEX + ", Type: " + device.TYPE);
        }
    }
}

コードのポイントは以下です。

  • 20, 28行目がデバイス挿抜時のイベントハンドラーです
  • イベント発生時に上記のハンドラーを呼び出すための登録が、12, 13行目になります。"+="でイベントハンドラーを登録できるのはC#独自の書式で、Javaより簡潔で分かりやすいのではないかと思います

実行するとデバイスIDやタイプをDebugコンソールに出力します。USBマウス・キーボードは挿抜を検出したのですが、手持ちのUSBメモリー(4GB)は認識しませんでした。本来このコードで認識してくれないとダメなので、こちらは継続調査です。


UBSマウスの読み取り

デバイスの挿抜に加えて、マウスの移動・ボタン押下のイベントハンドラーを追加しています。

using System.Threading;
using Microsoft.SPOT;
using GHIElectronics.NETMF.USBHost;

namespace Test
{
    public class Program
    {
        static USBH_Mouse mouse;
        public static void Main()
        {
            // Subscribe to USBH event.
            USBHostController.DeviceConnectedEvent += OnDeviceConnected;

            // Sleep forever
            Thread.Sleep(Timeout.Infinite);
        }

        static void OnDeviceConnected(USBH_Device device)
        {
            if (device.TYPE == USBH_DeviceType.Mouse)
            {
                Debug.Print("Mouse Connected");
                mouse = new USBH_Mouse(device);
                mouse.MouseMove += OnMouseMove;
                mouse.MouseDown += OnMouseDown;
            }
        }

        static void OnMouseMove(USBH_Mouse sender, USBH_MouseEventArgs args)
        {
            Debug.Print("Absol(x, y) = (" + sender.Cursor.X + ", " + 
                sender.Cursor.Y + ")");
            Debug.Print("Delta(x, y) = (" + args.DeltaPosition.X + ", " + 
                args.DeltaPosition.Y + ")");
        }

        static void OnMouseDown(USBH_Mouse sender, USBH_MouseEventArgs args)
        {
            Debug.Print("Button down number: " + args.ChangedButton);
        }
    }
}
  • 25, 26行目でマウスイベントのハンドラーを登録しています
  • 30, 38行目がイベントハンドラーになります
  • 32行目はマウスの位置を絶対座標(0, 0)~(512, 512)で表示します
  • 34行目は移動量(差分)を表示します
  • 読み取りスケールをscale()メソッドで変更できるのですが、まだ使い方が分かっていません


FTDIチップとのUSBシリアル通信

最後が、FTDIのUSBシリアル変換チップとの接続です。以下は、ArduinoとFEZ DominoをUSBケーブルで接続し、USBシリアル変換(ArduinoのFT232RLチップ)を介して、Arduino - FEZ Domino間でシリアル通信を行うコードです(Arduino→ FEZ方向)。

このサンプルをビルドするためには、アセンブリ参照として、Microsoft.SPOT.Hardwareの追加が必要です。

using System.Threading;
using Microsoft.SPOT;
using GHIElectronics.NETMF.USBHost;

namespace FezFTDI


{
    public class Program
    {
        static USBH_SerialUSB serialUSB;
        static Thread serialUSBThread;      // Receive data from Arduino

        public static void Main()
        {
            // Subscribe to USBH event.
            USBHostController.DeviceConnectedEvent += DeviceConnectedEvent;
            // Sleep forever
            Thread.Sleep(Timeout.Infinite);
        }

        static void DeviceConnectedEvent(USBH_Device device)
        {
            Debug.Print("Device connected");
            switch (device.TYPE)
            {
                case USBH_DeviceType.Serial_FTDI: // FTDI connected
                    serialUSB = new USBH_SerialUSB(device, 9600, System.IO.Ports.Parity.None, 8,
                    System.IO.Ports.StopBits.One);
                    serialUSB.Open();
                    serialUSBThread = new Thread(SerialUSBThread);
                    serialUSBThread.Start();
                    break;
                case USBH_DeviceType.Unknown: // SiLabs but not recognized
                    // force SiLabs
                    USBH_Device silabs = new USBH_Device(device.ID, device.INTERFACE_INDEX,
                    USBH_DeviceType.Serial_SiLabs, device.VENDOR_ID, device.PRODUCT_ID,
                    device.PORT_NUMBER);
                    serialUSB = new USBH_SerialUSB(silabs, 9600, System.IO.Ports.Parity.None, 8,
                    System.IO.Ports.StopBits.One);
                    serialUSB.Open();
                    serialUSBThread = new Thread(SerialUSBThread);
                    serialUSBThread.Start();
                    break;
            }
        }

        static void SerialUSBThread()
        {
            // Print received data from Arduino
            byte [] data = new byte[8];
            char c;
            string receivedMsg = "";

            while (true)
            {
                if (serialUSB.Read(data, 0, 1) != 0)
                {
                    c = (char)data[0];
                    if (c >= 0x20)
                    {
                        receivedMsg += c.ToString();
                    }
                    else if (c == '\n')
                    {
                        Debug.Print(receivedMsg);
                        receivedMsg = "";
                    }
                }
            }
        }
    }
}
  • 27行目以降で、FTDIチップを認識した際の初期化処理を行っています
  • Arduino Nanoと接続して正常に受信ができることを確認しました。
  • 34行目以降は、Silicon LabのCP210Xに対応した処理なのですが、Japaninoをつなぐと39行目で例外が発生してしまいました


参考資料

« FEZ Domino Tips (2) - .Net Micro Frameworkでms単位の時間計測を行う | トップページ | Arduino Ethernet Shieldのパワーオンリセット »

dotNet MF」カテゴリの記事

コメント

この記事へのコメントは終了しました。

2018年10月
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31      
無料ブログはココログ