Android到Arduino Leonardo Communication - 通过OTG线缆发送和接收命令

时间:2015-06-17 17:37:26

标签: android arduino

美好的一天。

我正在尝试构建一个Android应用程序,我有一个Arduino Leonardo板,通过键盘写命令发送输出。到目前为止,我能够在我的Android设备上接收Arduino输出作为键盘输入。我有一个EditText文本,只接收所有Arduino输出,当输出序列结束时,我可以轻松地解析EditText值。

但是,我现在遇到的问题是将数据从Android发送到Arduino。我完成了我的研究,Android和Arduino之间的推荐/常用通信方式是通过蓝牙,Android将数据发送到带有蓝牙屏蔽的Arduino。这是一个可行的解决方案,但是,我们的资源有限。我还看到了涉及OTG Cable的stackoverflow问题,但这些问题正在与Arduino Uno进行通信。似乎这些解决方案对莱昂纳多不起作用。我也看过博客,其中评论部分的人会询问如何在Android和Arduino Leonardo之间实现基于有线的通信系统。

有人可以帮我解决从Arduino Leonardo向Android发送数据的问题吗?看起来Arduino板上的通信接口/协议是不同的。

另外,作为附注,除了键盘写入命令之外,是否可以使用不同的命令将数据从Arduino Leonardo发送到Android?

1 个答案:

答案 0 :(得分:1)

此示例显示如何通过USB OTG电缆将String从Android发送到Arduino Uni,在发送之前您必须了解

vendor-id="9025"
product-id="0067"
Arduino

查看了此示例

import java.util.HashMap;
import java.util.Iterator;

import android.support.v7.app.ActionBarActivity;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends ActionBarActivity {

 TextView textInfo;
 TextView textSearchedEndpoint;

 TextView textDeviceName;
 TextView textStatus;

 private static final int targetVendorID = 9025;  //Arduino Uno
 private static final int targetProductID = 67; //Arduino Uno, not 0067
 UsbDevice deviceFound = null;
 UsbInterface usbInterfaceFound = null;
 UsbEndpoint endpointIn = null;
 UsbEndpoint endpointOut = null;

 private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";
 PendingIntent mPermissionIntent;

 UsbInterface usbInterface;
 UsbDeviceConnection usbDeviceConnection;

 EditText textOut;
 Button buttonSend;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  textStatus = (TextView) findViewById(R.id.textstatus);

  textDeviceName = (TextView) findViewById(R.id.textdevicename);
  textInfo = (TextView) findViewById(R.id.info);
  textSearchedEndpoint = (TextView) findViewById(R.id.searchedendpoint);

  // register the broadcast receiver
  mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(
    ACTION_USB_PERMISSION), 0);
  IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
  registerReceiver(mUsbReceiver, filter);

  registerReceiver(mUsbDeviceReceiver, new IntentFilter(
    UsbManager.ACTION_USB_DEVICE_ATTACHED));
  registerReceiver(mUsbDeviceReceiver, new IntentFilter(
    UsbManager.ACTION_USB_DEVICE_DETACHED));

  connectUsb();

  textOut = (EditText)findViewById(R.id.textout);
  buttonSend = (Button)findViewById(R.id.send);
  buttonSend.setOnClickListener(buttonSendOnClickListener);
 }

 OnClickListener buttonSendOnClickListener =
  new OnClickListener(){

   @Override
   public void onClick(View v) {

    if(deviceFound != null){

     String tOut = textOut.getText().toString();
     byte[] bytesOut = tOut.getBytes(); //convert String to byte[]
     int usbResult = usbDeviceConnection.bulkTransfer(
      endpointOut, bytesOut, bytesOut.length, 0);

    }else{
     Toast.makeText(MainActivity.this, 
      "deviceFound == null", 
      Toast.LENGTH_LONG).show();
    }


   }};

 @Override
 protected void onDestroy() {
  releaseUsb();
  unregisterReceiver(mUsbReceiver);
  unregisterReceiver(mUsbDeviceReceiver);
  super.onDestroy();
 }

 private void connectUsb() {

  Toast.makeText(MainActivity.this, "connectUsb()", Toast.LENGTH_LONG)
    .show();
  textStatus.setText("connectUsb()");

  searchEndPoint();

  if (usbInterfaceFound != null) {
   setupUsbComm();
  }

 }

 private void releaseUsb() {

  Toast.makeText(MainActivity.this, "releaseUsb()", Toast.LENGTH_LONG)
    .show();
  textStatus.setText("releaseUsb()");

  if (usbDeviceConnection != null) {
   if (usbInterface != null) {
    usbDeviceConnection.releaseInterface(usbInterface);
    usbInterface = null;
   }
   usbDeviceConnection.close();
   usbDeviceConnection = null;
  }

  deviceFound = null;
  usbInterfaceFound = null;
  endpointIn = null;
  endpointOut = null;
 }

 private void searchEndPoint() {

  textInfo.setText("");
  textSearchedEndpoint.setText("");

  usbInterfaceFound = null;
  endpointOut = null;
  endpointIn = null;

  // Search device for targetVendorID and targetProductID
  if (deviceFound == null) {
   UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
   HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
   Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();

   while (deviceIterator.hasNext()) {
    UsbDevice device = deviceIterator.next();

    if (device.getVendorId() == targetVendorID) {
     if (device.getProductId() == targetProductID) {
      deviceFound = device;
     }
    }
   }
  }

  if (deviceFound == null) {
   Toast.makeText(MainActivity.this, "device not found",
     Toast.LENGTH_LONG).show();
   textStatus.setText("device not found");
  } else {
   String s = deviceFound.toString() + "\n" + "DeviceID: "
     + deviceFound.getDeviceId() + "\n" + "DeviceName: "
     + deviceFound.getDeviceName() + "\n" + "DeviceClass: "
     + deviceFound.getDeviceClass() + "\n" + "DeviceSubClass: "
     + deviceFound.getDeviceSubclass() + "\n" + "VendorID: "
     + deviceFound.getVendorId() + "\n" + "ProductID: "
     + deviceFound.getProductId() + "\n" + "InterfaceCount: "
     + deviceFound.getInterfaceCount();
   textInfo.setText(s);

   // Search for UsbInterface with Endpoint of USB_ENDPOINT_XFER_BULK,
   // and direction USB_DIR_OUT and USB_DIR_IN

   for (int i = 0; i < deviceFound.getInterfaceCount(); i++) {
    UsbInterface usbif = deviceFound.getInterface(i);

    UsbEndpoint tOut = null;
    UsbEndpoint tIn = null;

    int tEndpointCnt = usbif.getEndpointCount();
    if (tEndpointCnt >= 2) {
     for (int j = 0; j < tEndpointCnt; j++) {
      if (usbif.getEndpoint(j).getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
       if (usbif.getEndpoint(j).getDirection() == UsbConstants.USB_DIR_OUT) {
        tOut = usbif.getEndpoint(j);
       } else if (usbif.getEndpoint(j).getDirection() == UsbConstants.USB_DIR_IN) {
        tIn = usbif.getEndpoint(j);
       }
      }
     }

     if (tOut != null && tIn != null) {
      // This interface have both USB_DIR_OUT
      // and USB_DIR_IN of USB_ENDPOINT_XFER_BULK
      usbInterfaceFound = usbif;
      endpointOut = tOut;
      endpointIn = tIn;
     }
    }

   }

   if (usbInterfaceFound == null) {
    textSearchedEndpoint.setText("No suitable interface found!");
   } else {
    textSearchedEndpoint.setText("UsbInterface found: "
      + usbInterfaceFound.toString() + "\n\n"
      + "Endpoint OUT: " + endpointOut.toString() + "\n\n"
      + "Endpoint IN: " + endpointIn.toString());
   }
  }
 }

 private boolean setupUsbComm() {

  // for more info, search SET_LINE_CODING and
  // SET_CONTROL_LINE_STATE in the document:
  // "Universal Serial Bus Class Definitions for Communication Devices"

  final int RQSID_SET_LINE_CODING = 0x20;
  final int RQSID_SET_CONTROL_LINE_STATE = 0x22;

  boolean success = false;

  UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
  Boolean permitToRead = manager.hasPermission(deviceFound);

  if (permitToRead) {
   usbDeviceConnection = manager.openDevice(deviceFound);
   if (usbDeviceConnection != null) {
    usbDeviceConnection.claimInterface(usbInterfaceFound, true);

    int usbResult;
    usbResult = usbDeviceConnection.controlTransfer(0x21, // requestType
      RQSID_SET_CONTROL_LINE_STATE, // SET_CONTROL_LINE_STATE
      0, // value
      0, // index
      null, // buffer
      0, // length
      0); // timeout

    Toast.makeText(
      MainActivity.this,
      "controlTransfer(SET_CONTROL_LINE_STATE): " + usbResult,
      Toast.LENGTH_LONG).show();

    // baud rate = 9600
    // 8 data bit
    // 1 stop bit
    byte[] encodingSetting = new byte[] { (byte) 0x80, 0x25, 0x00,
      0x00, 0x00, 0x00, 0x08 };
    usbResult = usbDeviceConnection.controlTransfer(0x21, // requestType
      RQSID_SET_LINE_CODING, // SET_LINE_CODING
      0, // value
      0, // index
      encodingSetting, // buffer
      7, // length
      0); // timeout
    Toast.makeText(MainActivity.this,
      "controlTransfer(RQSID_SET_LINE_CODING): " + usbResult,
      Toast.LENGTH_LONG).show();

    /*
    byte[] bytesHello = new byte[] { (byte) 'H', 'e', 'l', 'l',
      'o', ' ', 'f', 'r', 'o', 'm', ' ', 'A', 'n', 'd', 'r',
      'o', 'i', 'd' };
    usbResult = usbDeviceConnection.bulkTransfer(endpointOut,
      bytesHello, bytesHello.length, 0);
    Toast.makeText(MainActivity.this, "bulkTransfer: " + usbResult,
      Toast.LENGTH_LONG).show();
    */
   }

  } else {
   manager.requestPermission(deviceFound, mPermissionIntent);
   Toast.makeText(MainActivity.this, "Permission: " + permitToRead,
     Toast.LENGTH_LONG).show();
   textStatus.setText("Permission: " + permitToRead);
  }

  return success;
 }

 private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {

  @Override
  public void onReceive(Context context, Intent intent) {
   String action = intent.getAction();
   if (ACTION_USB_PERMISSION.equals(action)) {

    Toast.makeText(MainActivity.this, "ACTION_USB_PERMISSION",
      Toast.LENGTH_LONG).show();
    textStatus.setText("ACTION_USB_PERMISSION");

    synchronized (this) {
     UsbDevice device = (UsbDevice) intent
       .getParcelableExtra(UsbManager.EXTRA_DEVICE);

     if (intent.getBooleanExtra(
       UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
      if (device != null) {
       connectUsb();
      }
     } else {
      Toast.makeText(MainActivity.this,
        "permission denied for device " + device,
        Toast.LENGTH_LONG).show();
      textStatus.setText("permission denied for device "
        + device);
     }
    }
   }
  }
 };

 private final BroadcastReceiver mUsbDeviceReceiver = new BroadcastReceiver() {

  @Override
  public void onReceive(Context context, Intent intent) {
   String action = intent.getAction();
   if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {

    deviceFound = (UsbDevice) intent
      .getParcelableExtra(UsbManager.EXTRA_DEVICE);
    Toast.makeText(
      MainActivity.this,
      "ACTION_USB_DEVICE_ATTACHED: \n"
        + deviceFound.toString(), Toast.LENGTH_LONG)
      .show();
    textStatus.setText("ACTION_USB_DEVICE_ATTACHED: \n"
      + deviceFound.toString());

    connectUsb();

   } else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {

    UsbDevice device = (UsbDevice) intent
      .getParcelableExtra(UsbManager.EXTRA_DEVICE);

    Toast.makeText(MainActivity.this,
      "ACTION_USB_DEVICE_DETACHED: \n" + device.toString(),
      Toast.LENGTH_LONG).show();
    textStatus.setText("ACTION_USB_DEVICE_DETACHED: \n"
      + device.toString());

    if (device != null) {
     if (device == deviceFound) {
      releaseUsb();
     }else{
      Toast.makeText(MainActivity.this, 
        "device == deviceFound, no call releaseUsb()\n" +
        device.toString() + "\n" +
        deviceFound.toString(), 
        Toast.LENGTH_LONG).show();
     }
    }else{
     Toast.makeText(MainActivity.this, 
      "device == null, no call releaseUsb()", Toast.LENGTH_LONG).show();
    }

    textInfo.setText("");
   }
  }

 };

}

创建/res/xml/device_filter.xml以指定vendor-id和product-id。

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- idVendor=2341, idProduct=0043 for Arduino Uno R3 -->
    <usb-device 
        vendor-id="9025" 
        product-id="0067" />
</resources>

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.androidusbhostarduinouno"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-feature android:name="android.hardware.usb.host" />

    <uses-sdk
        android:minSdkVersion="13"
        android:targetSdkVersion="21" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:configChanges="keyboard|orientation"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
            </intent-filter>
            <meta-data
                android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
                android:resource="@xml/device_filter" />
            <intent-filter>
                <action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
            </intent-filter>
        </activity>
    </application>

</manifest>

layout,/ stl /layout / activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.androidusbhostarduinouno.MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold" />

    <EditText
        android:id="@+id/textout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
    <Button
        android:id="@+id/send"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Send"/>

    <TextView
        android:id="@+id/textstatus"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/textdevicename"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textStyle="bold|italic" />

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical" >

            <TextView
                android:id="@+id/info"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />

            <TextView
                android:id="@+id/searchedendpoint"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textStyle="bold" />
        </LinearLayout>
    </ScrollView>

</LinearLayout>

我希望它会帮助你