风筝
发表于: 2018-8-16 16:00:00 | 显示全部楼层

想要从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应用程序和蓝牙应用程序使用相同的布局。这是一个简单的小工具,需要最少的小部件来测试设备之间的连接。

layout-2015-10-10-224027.png


如您所见,它有一个EditText小部件,用于从用户获取输入,按钮以启动连接、传输数据、结束连接和清除TextView。收到的数据显示在TextView(按钮下方的空白部分)中。


这是XML的一部分。由于按钮的代码类似,我只截取了一小部分。

  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

  2.     xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"

  3.     android:layout_height="match_parent"
  4.    
  5.     android:paddingLeft="@dimen/activity_horizontal_margin"

  6.     android:paddingRight="@dimen/activity_horizontal_margin"

  7.     android:paddingTop="@dimen/activity_vertical_margin"

  8.     android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

  9.     <EditText

  10.         android:layout_width="wrap_content"

  11.         android:layout_height="wrap_content"

  12.         android:id="@+id/editText"

  13.         android:layout_alignParentTop="true"

  14.         android:layout_alignParentRight="true"

  15.         android:layout_alignParentEnd="true"

  16.         android:layout_alignParentLeft="true"

  17.         android:layout_alignParentStart="true" />

  18.     <Button

  19.         android:layout_width="wrap_content"

  20.         android:layout_height="wrap_content"

  21.         android:text="Begin"

  22.         android:id="@+id/buttonStart"

  23.         android:layout_below="@+id/editText"

  24.         android:layout_alignParentLeft="true"

  25.         android:layout_alignParentStart="true"

  26.         android:onClick="onClickStart"/>

  27.     <TextView

  28.         android:layout_width="wrap_content"

  29.         android:layout_height="wrap_content"

  30.         android:id="@+id/textView"

  31.         android:layout_below="@+id/buttonSend"

  32.         android:layout_alignParentLeft="true"

  33.         android:layout_alignParentStart="true"

  34.         android:layout_alignRight="@+id/editText"

  35.         android:layout_alignEnd="@+id/editText"

  36.         android:layout_alignParentBottom="true" />

  37. </RelativeLayout>
复制代码

我在这里使用了RelativeLayout,这意味着每个小部件都是根据它周围的小部件进行排列的。可以使用Design Tab轻松地重新创建布局,您可以在其中将窗口小部件拖放到任何位置。单击按钮时,我们必须描述需要执行的操作。为此,使用OnClick方法。在按钮的XML中指定方法的名称。为此,请添加以下行:

  1. android:onClick="onClickMethod"
复制代码

现在将鼠标悬停在此行上,左侧会弹出一条警告,如下所示:

Screenshot_from_2015-10-10_23_17_04.png


单击“创建'OnClick ...”。这将自动为MainActivity.java中的onClick方法注入代码。您必须为每个按钮执行此操作。


USB串行库

在Android中设置串行连接是一件非常麻烦的事情,因为它需要你手动配置很多东西,所以我一直在寻找一些自动完成这一切的库。我测试了其中的一些,最后由Github用户felHR85定位于UsbSerial库。在我找到的所有相关库中,这是唯一一个仍在更新的库。它很容易设置和使用。要将此库添加到项目中,请从Github下载最新的JAR文件。将其移动到项目目录中的“libs”文件夹。然后,在Android Studio的文件浏览器中,右键单击JAR并选择“添加为库”。


程序流程

download_(1).png

这是我们将如何进行的简要概述。每个活动都有一个onCreate()方法,该方法是在创建活动时运行的。无论您想要在开始时运行什么代码都必须放在其中。请注意,从设备读取是异步的,这意味着它将继续在后台运行。这样做是为了尽快收到数据。


打开连接

首先,让我们为Begin按钮定义onClick方法。单击时,它应搜索所有连接的设备,然后检查Arduino的供应商ID是否与连接的设备的供应商ID相匹配。如果找到,则必须向用户请求许可。每个USB从设备都有一个供应商和产品ID,可用于识别应该使用哪些驱动程序。任何Arduino的供应商ID都是0x2341或9025。

  1. public void onClickStart(View view) {

  2.         HashMap usbDevices = usbManager.getDeviceList();
  3.         if (!usbDevices.isEmpty()) {
  4.             boolean keep = true;
  5.             for (Map.Entry entry : usbDevices.entrySet()) {
  6.                 device = entry.getValue();
  7.                 int deviceVID = device.getVendorId();
  8.                 if (deviceVID == 0x2341)//Arduino Vendor ID
  9.                 {
  10.                     PendingIntent pi = PendingIntent.getBroadcast(this, 0,
  11.                      new Intent(ACTION_USB_PERMISSION), 0);
  12.                     usbManager.requestPermission(device, pi);
  13.                     keep = false;
  14.                 } else {
  15.                     connection = null;
  16.                     device = null;
  17.                 }

  18.                 if (!keep)
  19.                     break;
  20.             }
  21.         }
  22.     }
复制代码

现在让我们定义BroadcastReceiver来接收广播以询问用户权限,并在连接设备时自动启动连接,并在断开连接时关闭连接。

  1. private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { //Broadcast Receiver to automatically start and stop the Serial connection.
  2.         @Override
  3.         public void onReceive(Context context, Intent intent) {
  4.             if (intent.getAction().equals(ACTION_USB_PERMISSION)) {
  5.                 boolean granted =
  6.                 intent.getExtras().getBoolean(UsbManager.EXTRA_PERMISSION_GRANTED);
  7.                 if (granted) {
  8.                     connection = usbManager.openDevice(device);
  9.                     serialPort = UsbSerialDevice.createUsbSerialDevice(device, connection);
  10.                     if (serialPort != null) {
  11.                         if (serialPort.open()) { //Set Serial Connection Parameters.
  12.                             setUiEnabled(true); //Enable Buttons in UI
  13.                             serialPort.setBaudRate(9600);
  14.                             serialPort.setDataBits(UsbSerialInterface.DATA_BITS_8);
  15.                             serialPort.setStopBits(UsbSerialInterface.STOP_BITS_1);
  16.                             serialPort.setParity(UsbSerialInterface.PARITY_NONE);
  17.                             serialPort.setFlowControl(UsbSerialInterface.FLOW_CONTROL_OFF);
  18.                             serialPort.read(mCallback); //
  19.                             tvAppend(textView,"Serial Connection Opened!\n");

  20.                         } else {
  21.                             Log.d("SERIAL", "PORT NOT OPEN");
  22.                         }
  23.                     } else {
  24.                         Log.d("SERIAL", "PORT IS NULL");
  25.                     }
  26.                 } else {
  27.                     Log.d("SERIAL", "PERM NOT GRANTED");
  28.                 }
  29.             } else if (intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) {
  30.                 onClickStart(startButton);
  31.             } else if (intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_DETACHED)) {
  32.                 onClickStop(stopButton);
  33.             }
  34.         };
  35.     };
复制代码

如果满足第一个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函数,以便在检测到任何传入数据时自动触发。

  1. UsbSerialInterface.UsbReadCallback mCallback = new UsbSerialInterface.UsbReadCallback() {
  2.      //Defining a Callback which triggers whenever data is read.
  3.         @Override
  4.         public void onReceivedData(byte[] arg0) {
  5.             String data = null;
  6.             try {
  7.                 data = new String(arg0, "UTF-8");
  8.                 data.concat("/n");
  9.                 tvAppend(textView, data);
  10.             } catch (UnsupportedEncodingException e) {
  11.                 e.printStackTrace();
  12.             }
  13.         }
  14.     };
复制代码

收到的数据将采用原始字节的形式。我们必须将其重新编码为可读格式,如UTF-8。然后使用名为tvAppend()的自定义方法将其附加到TextView。这样做是因为对UI的任何更改只能在UI线程上进行。由于此Callback将作为后台线程运行,因此它不会直接影响UI。

  1. 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方法中定义。

  1. serialPort.write(string.getBytes());
复制代码

关闭连接

要关闭连接,只需关闭SerialPort即可。

  1. serialPort.close();
复制代码

应用程序清单

在清单中,说明应用可能需要的额外权限。唯一需要的是允许将手机变为USB主机。将以下内容添加到清单:

  1. <uses-feature android:name="android.hardware.usb.host" />
复制代码

通过向MainActivity添加IntentFilter,可以使应用程序自动启动。连接任何新设备时将触发此IntentFilter。可以通过在XML文件中提供供应商ID和/或产品ID来明确指定设备的类型。

  1. <?xml version="1.0" encoding="utf-8"?>
  2.         <activity
  3.             android:name=".MainActivity"
  4.             android:label="@string/app_name" >
  5.             <intent-filter>
  6.                 <action android:name="android.intent.action.MAIN" />

  7.                 <category android:name="android.intent.category.LAUNCHER" />
  8.             </intent-filter>
  9.             <intent-filter>
  10.                 <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
  11.             </intent-filter>

  12.             <meta-data
  13.                 android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
  14.                 android:resource="@xml/device_filter" />
  15.         </activity>
复制代码

注意行“android:resource =”@ xml / device_filter“。这告诉编译器它可以在src / main / res / xml中名为device_filter的文件中找到设备属性,所以在src中创建一个名为”xml“的文件夹/ main / res并在其中加入以下内容:

  1. <resources>
  2.     <usb-device vendor-id="9025" />
  3.     <!-- Vendor ID of Arduino -->
  4. </resources>
复制代码

测试应用程序

在智能手机上构建并运行应用程序。现在启动Arduino IDE并设置Arduino以简单地回显它在串行端口上收到的任何内容。这是一个非常简单的代码。

  1. void setup()  
  2. {  
  3.   Serial.begin(9600);  
  4. }  
  5. void loop()  
  6. {  
  7.   char c;
  8.   if(Serial.available())  
  9.   {  
  10.    c = Serial.read();  
  11.    Serial.print(c);  
  12.   }  
  13. }  
复制代码

现在使用OTG电缆将Arduino连接到microUSB端口。该应用必须自动启动。尝试发送一些文本,然后将‘返回相同的数据!

Screenshot_2015-10-11-20-38-59.png


总结

本文主要展示了Arduino开发板如何与您的智能手机通讯。这用途是无穷无尽的!如果需要来自一些传感器的数据,并且如果智能手机上没有这些数据,则可以使用微控制器从该传感器读取数据,并将数据传输到手机。

跳转到指定楼层
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题 705 | 回复: 1492



手机版|

GMT+8, 2024-11-7 23:35 , Processed in 0.044357 second(s), 6 queries , Gzip On, MemCache On. Powered by Discuz! X3.5

YiBoard一板网 © 2015-2022 地址:河北省石家庄市长安区高营大街 ( 冀ICP备18020117号 )

快速回复 返回顶部 返回列表