| 想要从Android手机中发送文字到Arduino开发板吗?请看下文的介绍! 
 所需的材料 ●    支持USB主机模式的Android手机(即支持OTG)。检查您的手机是否使用Play商店中的USB Host Diagnostics应用程序。 ●    Arduino Uno R3开发板。 ●    Arduino USB电缆 ●    USB OTG电缆 - 需要将其连接到Arduino的USB和智能手机的micro-USB端口。 ●    Android Studio - 您需要安装和设置。这很容易做到。 Android Studio通过预测和代码生成使应用程序开发更容易。您还可以按照本文在计算机上设置Android Studio。
 
 Android应用程序的主要组件 Android应用中有3个主要文件:
 ●    MainActivity.java 这是Java代码所在的位置。它控制着应用程序的运行方式。 ●    activity_main.xml中 这包含应用程序的布局,即组件或类似小部件的按钮、TextViews等。 ●    AndroidManifest.xml中 您可以在此处定义应用程序必须启动的时间、所需的权限以及需要访问的硬件。 
 还有许多其他文件,但它们都是在这三个文件的帮助下链接在一起的。 
 互动可以被描述为用户与电话交互的屏幕。互动包含按钮、文本字段、图像等小部件,这些小部件有助于传输信息。本教程将使用一个互动,即Main Activity,它将用户的输入发送到Arduino并显示收到的文本。 
 布局 我们将为USB应用程序和蓝牙应用程序使用相同的布局。这是一个简单的小工具,需要最少的小部件来测试设备之间的连接。 
  
 如您所见,它有一个EditText小部件,用于从用户获取输入,按钮以启动连接、传输数据、结束连接和清除TextView。收到的数据显示在TextView(按钮下方的空白部分)中。 
 这是XML的一部分。由于按钮的代码类似,我只截取了一小部分。 复制代码<RelativeLayout 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:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
    <EditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/editText"
        android:layout_alignParentTop="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true" />
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Begin"
        android:id="@+id/buttonStart"
        android:layout_below="@+id/editText"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:onClick="onClickStart"/>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/textView"
        android:layout_below="@+id/buttonSend"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignRight="@+id/editText"
        android:layout_alignEnd="@+id/editText"
        android:layout_alignParentBottom="true" />
</RelativeLayout>
 我在这里使用了RelativeLayout,这意味着每个小部件都是根据它周围的小部件进行排列的。可以使用Design Tab轻松地重新创建布局,您可以在其中将窗口小部件拖放到任何位置。单击按钮时,我们必须描述需要执行的操作。为此,使用OnClick方法。在按钮的XML中指定方法的名称。为此,请添加以下行: 复制代码android:onClick="onClickMethod"
 现在将鼠标悬停在此行上,左侧会弹出一条警告,如下所示: 
  
 单击“创建'OnClick ...”。这将自动为MainActivity.java中的onClick方法注入代码。您必须为每个按钮执行此操作。 
 USB串行库 在Android中设置串行连接是一件非常麻烦的事情,因为它需要你手动配置很多东西,所以我一直在寻找一些自动完成这一切的库。我测试了其中的一些,最后由Github用户felHR85定位于UsbSerial库。在我找到的所有相关库中,这是唯一一个仍在更新的库。它很容易设置和使用。要将此库添加到项目中,请从Github下载最新的JAR文件。将其移动到项目目录中的“libs”文件夹。然后,在Android Studio的文件浏览器中,右键单击JAR并选择“添加为库”。 
 程序流程 
  这是我们将如何进行的简要概述。每个活动都有一个onCreate()方法,该方法是在创建活动时运行的。无论您想要在开始时运行什么代码都必须放在其中。请注意,从设备读取是异步的,这意味着它将继续在后台运行。这样做是为了尽快收到数据。 
 打开连接 首先,让我们为Begin按钮定义onClick方法。单击时,它应搜索所有连接的设备,然后检查Arduino的供应商ID是否与连接的设备的供应商ID相匹配。如果找到,则必须向用户请求许可。每个USB从设备都有一个供应商和产品ID,可用于识别应该使用哪些驱动程序。任何Arduino的供应商ID都是0x2341或9025。 复制代码public void onClickStart(View view) {
        HashMap usbDevices = usbManager.getDeviceList();
        if (!usbDevices.isEmpty()) {
            boolean keep = true;
            for (Map.Entry entry : usbDevices.entrySet()) {
                device = entry.getValue();
                int deviceVID = device.getVendorId();
                if (deviceVID == 0x2341)//Arduino Vendor ID
                {
                    PendingIntent pi = PendingIntent.getBroadcast(this, 0, 
                     new Intent(ACTION_USB_PERMISSION), 0);
                    usbManager.requestPermission(device, pi);
                    keep = false;
                } else {
                    connection = null;
                    device = null;
                }
                if (!keep)
                    break;
            }
        }
    }
 现在让我们定义BroadcastReceiver来接收广播以询问用户权限,并在连接设备时自动启动连接,并在断开连接时关闭连接。 复制代码private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { //Broadcast Receiver to automatically start and stop the Serial connection.
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(ACTION_USB_PERMISSION)) {
                boolean granted = 
                intent.getExtras().getBoolean(UsbManager.EXTRA_PERMISSION_GRANTED);
                if (granted) {
                    connection = usbManager.openDevice(device);
                    serialPort = UsbSerialDevice.createUsbSerialDevice(device, connection);
                    if (serialPort != null) {
                        if (serialPort.open()) { //Set Serial Connection Parameters.
                            setUiEnabled(true); //Enable Buttons in UI
                            serialPort.setBaudRate(9600);
                            serialPort.setDataBits(UsbSerialInterface.DATA_BITS_8);
                            serialPort.setStopBits(UsbSerialInterface.STOP_BITS_1);
                            serialPort.setParity(UsbSerialInterface.PARITY_NONE);
                            serialPort.setFlowControl(UsbSerialInterface.FLOW_CONTROL_OFF);
                            serialPort.read(mCallback); //
                            tvAppend(textView,"Serial Connection Opened!\n");
                        } else {
                            Log.d("SERIAL", "PORT NOT OPEN");
                        }
                    } else {
                        Log.d("SERIAL", "PORT IS NULL");
                    }
                } else {
                    Log.d("SERIAL", "PERM NOT GRANTED");
                }
            } else if (intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) {
                onClickStart(startButton);
            } else if (intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_DETACHED)) {
                onClickStop(stopButton);
            }
        };
    };
 如果满足第一个IF条件,并且用户已授予权限,则为其供应商ID与我们所需的供应商ID匹配的设备启动连接。 此外,如果收到设备附加或分离的广播,请手动调用onClick方法以启动和停止按钮。 使用设备作为连接作为参数定义SerialPort。 如果成功,请打开SerialPort并相应地设置参数。 对于Uno,默认参数为8个数据位,1个停止位,无奇偶校验位且流量控制为关闭。 波特率可以是300,600,1200,2400,4800,9600,14400,19200,28800,38400,57600或115200,但我们使用标准9600。 
 从设备接收数据 在上面的代码片段中,注意说明serialPort.read(mCallback)的行。 这里将Callback的引用传递给read函数,以便在检测到任何传入数据时自动触发。 复制代码UsbSerialInterface.UsbReadCallback mCallback = new UsbSerialInterface.UsbReadCallback() { 
     //Defining a Callback which triggers whenever data is read.
        @Override
        public void onReceivedData(byte[] arg0) {
            String data = null;
            try {
                data = new String(arg0, "UTF-8");
                data.concat("/n");
                tvAppend(textView, data);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
    };
 收到的数据将采用原始字节的形式。我们必须将其重新编码为可读格式,如UTF-8。然后使用名为tvAppend()的自定义方法将其附加到TextView。这样做是因为对UI的任何更改只能在UI线程上进行。由于此Callback将作为后台线程运行,因此它不会直接影响UI。 复制代码 private void tvAppend(TextView tv, CharSequence text) { final TextView ftv = tv; final CharSequence ftext = text; runOnUiThread(new Runnable() { @Override public void run() { ftv.append(ftext); } }); } 
 将数据发送到设备 与从设备读取数据相比,发送数据相对容易。这是一个简单的函数调用,需要将数据字节作为参数发送。这将在发送按钮的OnClick方法中定义。 复制代码serialPort.write(string.getBytes()); 
 关闭连接 要关闭连接,只需关闭SerialPort即可。 
 应用程序清单 在清单中,说明应用可能需要的额外权限。唯一需要的是允许将手机变为USB主机。将以下内容添加到清单: 复制代码<uses-feature android:name="android.hardware.usb.host" />
 通过向MainActivity添加IntentFilter,可以使应用程序自动启动。连接任何新设备时将触发此IntentFilter。可以通过在XML文件中提供供应商ID和/或产品ID来明确指定设备的类型。 复制代码<?xml version="1.0" encoding="utf-8"?> 
        <activity
            android:name=".MainActivity"
            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" />
        </activity>
 注意行“android:resource =”@ xml / device_filter“。这告诉编译器它可以在src / main / res / xml中名为device_filter的文件中找到设备属性,所以在src中创建一个名为”xml“的文件夹/ main / res并在其中加入以下内容: 复制代码<resources>
    <usb-device vendor-id="9025" />
    <!-- Vendor ID of Arduino -->
</resources>
 测试应用程序
 在智能手机上构建并运行应用程序。现在启动Arduino IDE并设置Arduino以简单地回显它在串行端口上收到的任何内容。这是一个非常简单的代码。 复制代码void setup()  
 {  
  Serial.begin(9600);  
 }  
 void loop()  
 {  
  char c;
  if(Serial.available())  
  {  
   c = Serial.read();  
   Serial.print(c);  
  }  
 }  
 现在使用OTG电缆将Arduino连接到microUSB端口。该应用必须自动启动。尝试发送一些文本,然后将‘返回相同的数据! 
  
 总结 本文主要展示了Arduino开发板如何与您的智能手机通讯。这用途是无穷无尽的!如果需要来自一些传感器的数据,并且如果智能手机上没有这些数据,则可以使用微控制器从该传感器读取数据,并将数据传输到手机。 |