さて準備ができたので、C#からLEDを点灯させたいと思います。
VBですがサンプルコードがあるのでそれを参考にできるのと、こちらに仕様があります。
がHIDについてあまり詳しくない私のような場合はPythonでの操作について書かれたこちらの記事の方がわかりやすかったです。
さて、VBのサンプルコードではhid.dll
などのAPIを直接実行しているので、C#からP/Invokeすれば同じことができるはずです。が、そんなコードを一から書きたくないと思って検索するとHidLibraryというライブラリがあるのを見つけました。なんと、.NET Standard対応までされています。
というわけでHidLibraryを使ってコードを書いていきます。今後複雑な操作をさせるために操作用のクラスUSBIO2Device
を作ることにします。
HidDevices.Enumerate
でVendorIdとProductIdを指定すると、指定した接続デバイスの一覧が返ってきます。VendorIdとProductIdの値は仕様書に書いてあります。SendAndReceive
メソッドでJ1側の端子とJ2側の端子に出力される値を指定しています。
using HidLibrary; using System; using System.Linq; namespace HIDLabs.AkiUSBIO2.Library { public class USBIO2Device : IDisposable { private const int VendorId = 0x1352; private const int ProductId = 0x121; public static HidDevice[] ListDevices() => HidDevices.Enumerate(VendorId, ProductId).ToArray(); public static USBIO2Device Connect(HidDevice device) => new USBIO2Device(device); public static USBIO2Device Connect(HidDevice device) { return new USBIO2Device(device); } public static USBIO2Device Connect() { var device = HidDevices.Enumerate(VendorId, ProductId).FirstOrDefault(); if (device == null) { throw new InvalidOperationException("Deviceが見つかりません"); } return new USBIO2Device(device); } bool disposed = false; readonly HidDevice device; private USBIO2Device(HidDevice device) { this.device = device; } public void Dispose() { // Dispose of unmanaged resources. Dispose(true); // Suppress finalization. GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (disposed) return; if (disposing) device.Dispose(); disposed = true; } public (byte j1, byte j2) SendAndReceive(byte j1, byte j2) { var sendData = new byte[64]; sendData[1] = 0x20; sendData[2] = 0x1; sendData[3] = j1; sendData[4] = 0x2; sendData[5] = j2; var res = device.Write(sendData); if (!res) throw new InvalidOperationException("送信に失敗しました"); var receiveData = device.Read(); if (receiveData.Status != HidDeviceData.ReadStatus.Success) throw new InvalidOperationException($"受信に失敗しました: {receiveData.Status}"); return (receiveData.Data[2], receiveData.Data[3]); } } }
J1の0番端子の出力をOFF、ON繰り返すコードがこのようになります。すべてONが0xFFで、n番端子をOFFにするためには0xFF XOR 2^(n+1)
の値を書き込めばよいです。なお、HidLibraryにはHIDに対するほかの操作ができるメソッドが用意されていますが、USB-IO2.0に実行すると対応していないというエラーがかえってきました。
using HIDLabs.AkiUSBIO2.Library; using System; using System.Threading.Tasks; namespace HIDLabs.AkiUSBIO2.ConsoleApp { class Program { static async Task Main(string[] args) { Console.WriteLine("Hello USB IO2.0!"); using var device = USBIO2Device.Connect(); for (int i = 0; i < 10; i++) { device.SendAndReceive(0xFF ^ 1, 0xFF); await Task.Delay(TimeSpan.FromMilliseconds(100)); device.SendAndReceive(0xFF, 0xFF); await Task.Delay(TimeSpan.FromMilliseconds(100)); } device.SendAndReceive(0, 0); } } }
こんな感じで実際に点滅します。(パラメーターがサンプルコードと違う気がしますが...)
— たなか 🍣🍖🐡🐳 (@tanaka_733) 2020年5月5日