通过USB从Android控制继电器



我有这个USB中继,我想从Android手机进行控制。

(这里有一个类似的帖子,但它解释了如何从Linux外壳中进行。通过查看代码,我认为我可以解决它——显然不是。)

设备列表在lsusb:中

总线002设备011:ID 16c0:05df VOTI设备描述符:b长度18b描述符类型1bcdUSB 1.10b设备类0(在接口级别定义)b设备子类0b设备协议0b最大数据包大小0 8id供应商0x16c0 VOTIidProduct 0x05dfbcdedit设备1.00iManufacturer 1iProduct 2iSerial 0bNumConfigurations 1配置描述符:b长度9b描述符类型2wTotalLength 34bNum接口1b配置值1iConfiguration 0bmAttributes 0x80(总线供电)最大功率20mA接口描述符:b长度9b描述符类型4b接口编号0b替代设置0bNumEndpoints 1b接口Class 3人机接口设备bInterface Subclass 0无子类b接口协议0无i接口0HID设备描述符:b长度9b描述符类型33bcdHID 1.01bCountryCode 0不受支持bNumDescriptors 1b描述符类型34报告wDescriptor长度22报告描述符:**不可用**终结点描述符:b长度7b描述符类型5b端点地址0x81 EP 1 INbmAttributes 3传输类型中断同步类型无使用类型数据wMaxPacketSize 0x0008 1x 8字节b间隔20

我觉得奇怪的是,终点被定义为"EP IN"。在我看来,它应该是"EP OUT",因为方向应该是"主机->设备"。

无论如何,我使用安卓USB管理器创建一个连接,然后初始化基于中断的端点的USbRequest。Android权限以及所有这些都得到了处理,因此设备连接成功。

用于发送数据的代码段。它在一个单独的线程中运行,遵循Android指南:

UsbRequest request = new UsbRequest();
synchronized (mUsbLock) {
    if (mUsbConnection != null && mUsbEndPointIn != null) {
        if (!request.initialize(mUsbConnection, mUsbEndPointIn)) {
            Log.e(TAG, "Unable to initialize UsbRequest. Thread exits");
            return;
        } else {
            if (DEBUG) {
                Log.d(TAG, String.format("Usb request is initialized"));
            }
        }
    } else {
        Log.e(TAG, "Usb communication is not up and running. The worker thread should never be started.");
        return;
    }
}
mRunning.set(true);
while (mRunning.get()) {
    if (DEBUG) {
        Log.d(TAG, String.format("Waiting for data to be sent to end point"));
    }
    WorkPackage wp = mWorkQueue.take();
    // send the package.
    byte[] data = wp.getData();
    if (!request.queue(ByteBuffer.wrap(data), data.length)) {
        Log.e(TAG, "Unable to queue to send data on UsbRequest.");
        continue;
    } else {
        if (DEBUG) {
            Log.d(TAG, String.format("Usb request is queued on end point, ep=%s", printUsbEndpoint(mUsbEndPointIn)));
        }
    }
}

看起来一切都很好,没有发生错误,请求在终点排队,但之后什么也没发生。我没有收到任何关于请求已被处理的消息。

由于供应商不会发布on/off命令,我尝试了基于Linux帖子的变体(如上)。不过似乎没有一个奏效。供应商仅发布Windows二进制库。

发送8字节包(根据最大包):

public static byte[] SET_RELAY_ON = {(byte) 0xff, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00};
public static byte[] SET_RELAY_OFF = {(byte) 0xfd, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00};

感谢您的帮助。

所以,我想出了如何做到这一点。我会在这里写下解决方案,以防其他人遇到类似的问题。

我不得不窥探USB流量,以了解实际发送的内容。事实证明,定义的中断终点根本没有被使用。因此,与设备的通信不是基于中断的,而是使用端点0上的控制传输类型。

因此,使用Android USB API,这转化为:

打开设备(设备->主机方向):

int r = mUsbConnection.controlTransfer(0xa1, 0x01, 0x0300, 0x00, buffer, buffer.length, 500);

打开继电器"1"(主机->设备方向)。

byte[] buffer = {(byte) 0xff, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00};
int r = mUsbConnection.controlTransfer(0x21, 0x09, 0x0300, 0x00, buffer, buffer.length, 500);

注意,缓冲器中的第二个参数(0x01)是继电器编号(如果板上有>1个继电器)。我只有一个。

闭合继电器"1"(主机->设备方向):

byte[] buffer = {(byte) 0xfd, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00};
int r = mUsbConnection.controlTransfer(0x21, 0x09, 0x0300, 0x00, buffer, buffer.length, 500);

我在Github中找到了与此类似的项目(对于谁在寻找它)https://github.com/gigacycle/AndroidHidUsbRelayControl

我已经测试了这个代码,我可以确认它与USB中继板配合得很好。

最新更新